Skip to content

Commit 62f9b18

Browse files
authored
Merge pull request #310 from jacobprudhomme/simple-derivation-mechanisms
Feat: Add mechanisms for simple key derivations
2 parents 3ac2766 + 098d6d1 commit 62f9b18

File tree

4 files changed

+402
-14
lines changed

4 files changed

+402
-14
lines changed

cryptoki/src/mechanism/misc.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2025 Contributors to the Parsec project.
2+
// SPDX-License-Identifier: Apache-2.0
3+
//! Miscellaneous mechanisms:
4+
//! - Simple key derivation mechanisms
5+
//! See: <https://docs.oasis-open.org/pkcs11/pkcs11-spec/v3.1/os/pkcs11-spec-v3.1-os.html#_Toc111203697>
6+
7+
use std::marker::PhantomData;
8+
9+
use cryptoki_sys::*;
10+
11+
/// A parameter used as input for one of the simple key derivation mechanisms
12+
/// that takes a bytestring as input (CKM_CONCATENATE_BASE_AND_DATA,
13+
/// CKM_CONCATENATE_DATA_AND_BASE, CKM_XOR_BASE_AND_DATA).
14+
#[derive(Debug, Clone, Copy)]
15+
#[repr(transparent)]
16+
pub struct KeyDerivationStringData<'a> {
17+
inner: CK_KEY_DERIVATION_STRING_DATA,
18+
/// Marker type to ensure we don't outlive the data
19+
_marker: PhantomData<&'a [u8]>,
20+
}
21+
22+
impl<'a> KeyDerivationStringData<'a> {
23+
/// Construct parameter for simple key derivation mechanisms that take a
24+
/// bytestring as one of their inputs.
25+
///
26+
/// # Arguments
27+
///
28+
/// * `data` - The bytestring to use as input to the key derivation method.
29+
pub fn new(data: &'a [u8]) -> Self {
30+
Self {
31+
inner: CK_KEY_DERIVATION_STRING_DATA {
32+
pData: data.as_ptr() as *mut _,
33+
ulLen: data
34+
.len()
35+
.try_into()
36+
.expect("length of data does not fit in CK_ULONG"),
37+
},
38+
_marker: PhantomData,
39+
}
40+
}
41+
}
42+
43+
/// A parameter indicating the index of the bit in the the base key from which
44+
/// to extract the derived key.
45+
#[derive(Debug, Clone, Copy)]
46+
#[repr(transparent)]
47+
pub struct ExtractParams(CK_EXTRACT_PARAMS);
48+
49+
impl ExtractParams {
50+
/// Construct parameter from index of bit from which to extract the derived
51+
/// key from the base key.
52+
///
53+
/// # Arguments
54+
///
55+
/// * `index` - The bit index from which to extract the derived key from the base key.
56+
pub fn new(index: usize) -> Self {
57+
Self(
58+
index
59+
.try_into()
60+
.expect("given usize value does not fit into CK_ULONG"),
61+
)
62+
}
63+
}

cryptoki/src/mechanism/mod.rs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub mod elliptic_curve;
1010
pub mod hkdf;
1111
pub mod kbkdf;
1212
mod mechanism_info;
13+
pub mod misc;
1314
pub mod rsa;
1415
pub mod vendor_defined;
1516

@@ -24,7 +25,9 @@ use std::ptr::null_mut;
2425
use vendor_defined::VendorDefinedMechanism;
2526

2627
use crate::error::Error;
28+
use crate::mechanism::misc::{ExtractParams, KeyDerivationStringData};
2729
use crate::mechanism::rsa::PkcsOaepParams;
30+
use crate::object::ObjectHandle;
2831
pub use mechanism_info::MechanismInfo;
2932

3033
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
@@ -342,6 +345,28 @@ impl MechanismType {
342345
val: CKM_SP800_108_DOUBLE_PIPELINE_KDF,
343346
};
344347

348+
// Other simple key derivation mechanisms
349+
/// Concatenation of a base key and another key
350+
pub const CONCATENATE_BASE_AND_KEY: MechanismType = MechanismType {
351+
val: CKM_CONCATENATE_BASE_AND_KEY,
352+
};
353+
/// Concatenation of a base key and data (i.e. data appended)
354+
pub const CONCATENATE_BASE_AND_DATA: MechanismType = MechanismType {
355+
val: CKM_CONCATENATE_BASE_AND_DATA,
356+
};
357+
/// Concatenation of data and a base key (i.e. data prepended)
358+
pub const CONCATENATE_DATA_AND_BASE: MechanismType = MechanismType {
359+
val: CKM_CONCATENATE_DATA_AND_BASE,
360+
};
361+
/// XOR-ing of a base key and data
362+
pub const XOR_BASE_AND_DATA: MechanismType = MechanismType {
363+
val: CKM_XOR_BASE_AND_DATA,
364+
};
365+
/// Extraction of a key from bits of another key
366+
pub const EXTRACT_KEY_FROM_KEY: MechanismType = MechanismType {
367+
val: CKM_EXTRACT_KEY_FROM_KEY,
368+
};
369+
345370
// ML-KEM
346371
/// ML-KEM key pair generation mechanism
347372
pub const ML_KEM_KEY_PAIR_GEN: MechanismType = MechanismType {
@@ -963,6 +988,11 @@ impl TryFrom<CK_MECHANISM_TYPE> for MechanismType {
963988
CKM_SP800_108_COUNTER_KDF => Ok(MechanismType::SP800_108_COUNTER_KDF),
964989
CKM_SP800_108_FEEDBACK_KDF => Ok(MechanismType::SP800_108_FEEDBACK_KDF),
965990
CKM_SP800_108_DOUBLE_PIPELINE_KDF => Ok(MechanismType::SP800_108_DOUBLE_PIPELINE_KDF),
991+
CKM_CONCATENATE_BASE_AND_KEY => Ok(MechanismType::CONCATENATE_BASE_AND_KEY),
992+
CKM_CONCATENATE_BASE_AND_DATA => Ok(MechanismType::CONCATENATE_BASE_AND_DATA),
993+
CKM_CONCATENATE_DATA_AND_BASE => Ok(MechanismType::CONCATENATE_DATA_AND_BASE),
994+
CKM_XOR_BASE_AND_DATA => Ok(MechanismType::XOR_BASE_AND_DATA),
995+
CKM_EXTRACT_KEY_FROM_KEY => Ok(MechanismType::EXTRACT_KEY_FROM_KEY),
966996
CKM_ML_KEM_KEY_PAIR_GEN => Ok(MechanismType::ML_KEM_KEY_PAIR_GEN),
967997
CKM_ML_KEM => Ok(MechanismType::ML_KEM),
968998
CKM_ML_DSA_KEY_PAIR_GEN => Ok(MechanismType::ML_DSA_KEY_PAIR_GEN),
@@ -1219,6 +1249,18 @@ pub enum Mechanism<'a> {
12191249
/// NIST SP 800-108 KDF (aka KBKDF) mechanism in double pipeline-mode
12201250
KbkdfDoublePipeline(kbkdf::KbkdfParams<'a>),
12211251

1252+
// Other simple key derivation mechanisms
1253+
/// Concatenation of a base key and another key
1254+
ConcatenateBaseAndKey(ObjectHandle),
1255+
/// Concatenation of a base key and data (i.e. data appended)
1256+
ConcatenateBaseAndData(KeyDerivationStringData<'a>),
1257+
/// Concatenation of data and a base key (i.e. data prepended)
1258+
ConcatenateDataAndBase(KeyDerivationStringData<'a>),
1259+
/// XOR-ing of a base key and data
1260+
XorBaseAndData(KeyDerivationStringData<'a>),
1261+
/// Extraction of a key from bits of another key
1262+
ExtractKeyFromKey(ExtractParams),
1263+
12221264
// ML-KEM
12231265
/// ML-KEM key pair generation mechanism
12241266
MlKemKeyPairGen,
@@ -1366,6 +1408,12 @@ impl Mechanism<'_> {
13661408
Mechanism::KbkdfFeedback(_) => MechanismType::SP800_108_FEEDBACK_KDF,
13671409
Mechanism::KbkdfDoublePipeline(_) => MechanismType::SP800_108_DOUBLE_PIPELINE_KDF,
13681410

1411+
Mechanism::ConcatenateBaseAndKey(_) => MechanismType::CONCATENATE_BASE_AND_KEY,
1412+
Mechanism::ConcatenateBaseAndData(_) => MechanismType::CONCATENATE_BASE_AND_DATA,
1413+
Mechanism::ConcatenateDataAndBase(_) => MechanismType::CONCATENATE_DATA_AND_BASE,
1414+
Mechanism::XorBaseAndData(_) => MechanismType::XOR_BASE_AND_DATA,
1415+
Mechanism::ExtractKeyFromKey(_) => MechanismType::EXTRACT_KEY_FROM_KEY,
1416+
13691417
Mechanism::MlKemKeyPairGen => MechanismType::ML_KEM_KEY_PAIR_GEN,
13701418
Mechanism::MlKem => MechanismType::ML_KEM,
13711419

@@ -1417,20 +1465,8 @@ impl From<&Mechanism<'_>> for CK_MECHANISM {
14171465
| Mechanism::Des3Cbc(params)
14181466
| Mechanism::DesCbcPad(params)
14191467
| Mechanism::Des3CbcPad(params) => make_mechanism(mechanism, params),
1420-
Mechanism::AesGcm(params) => CK_MECHANISM {
1421-
mechanism,
1422-
pParameter: params as *const _ as *mut c_void,
1423-
ulParameterLen: size_of::<CK_GCM_PARAMS>()
1424-
.try_into()
1425-
.expect("usize can not fit in CK_ULONG"),
1426-
},
1427-
Mechanism::AesGcmMessage(params) => CK_MECHANISM {
1428-
mechanism,
1429-
pParameter: params as *const _ as *mut c_void,
1430-
ulParameterLen: size_of::<CK_GCM_MESSAGE_PARAMS>()
1431-
.try_into()
1432-
.expect("usize can not fit in CK_ULONG"),
1433-
},
1468+
Mechanism::AesGcm(params) => make_mechanism(mechanism, params),
1469+
Mechanism::AesGcmMessage(params) => make_mechanism(mechanism, params),
14341470
Mechanism::RsaPkcsPss(params)
14351471
| Mechanism::Sha1RsaPkcsPss(params)
14361472
| Mechanism::Sha256RsaPkcsPss(params)
@@ -1453,6 +1489,11 @@ impl From<&Mechanism<'_>> for CK_MECHANISM {
14531489
make_mechanism(mechanism, params.inner())
14541490
}
14551491
Mechanism::KbkdfFeedback(params) => make_mechanism(mechanism, params.inner()),
1492+
Mechanism::ConcatenateBaseAndKey(params) => make_mechanism(mechanism, params),
1493+
Mechanism::ConcatenateBaseAndData(params)
1494+
| Mechanism::ConcatenateDataAndBase(params)
1495+
| Mechanism::XorBaseAndData(params) => make_mechanism(mechanism, params),
1496+
Mechanism::ExtractKeyFromKey(params) => make_mechanism(mechanism, params),
14561497
Mechanism::HashMlDsa(params) => make_mechanism(mechanism, params),
14571498
Mechanism::MlDsa(params)
14581499
| Mechanism::HashMlDsaSha224(params)

cryptoki/src/object.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,7 @@ impl TryFrom<CK_ATTRIBUTE> for Attribute {
10191019
}
10201020

10211021
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1022+
#[repr(transparent)]
10221023
/// Token specific identifier for an object
10231024
pub struct ObjectHandle {
10241025
handle: CK_OBJECT_HANDLE,

0 commit comments

Comments
 (0)