use crate::pkcs11::vendor::*;
use crate::tests::*;
use itertools::Itertools;
use serial_test::parallel;
#[cfg(feature = "sp800_108")]
#[test]
#[parallel]
fn test_sp800_kdf() {
let mut testtokn = TestToken::initialized("test_sp800_kdf", None);
let session = testtokn.get_session(true);
testtokn.login();
let handle = ret_or_panic!(generate_key(
session,
CKM_GENERIC_SECRET_KEY_GEN,
std::ptr::null_mut(),
0,
&[(CKA_KEY_TYPE, CKK_GENERIC_SECRET), (CKA_VALUE_LEN, 16),],
&[],
&[(CKA_DERIVE, true),],
));
let derive_template = make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_AES),
(CKA_VALUE_LEN, 16),
],
&[],
&[(CKA_ENCRYPT, true), (CKA_DECRYPT, true)],
);
let mut counter_format = CK_SP800_108_COUNTER_FORMAT {
bLittleEndian: 0,
ulWidthInBits: 8,
};
let mut data_params = [CK_PRF_DATA_PARAM {
type_: CK_SP800_108_ITERATION_VARIABLE,
pValue: &mut counter_format as *mut _ as CK_VOID_PTR,
ulValueLen: sizeof!(CK_SP800_108_COUNTER_FORMAT),
}];
let mut params = CK_SP800_108_KDF_PARAMS {
prfType: CKM_SHA3_384_HMAC,
ulNumberOfDataParams: data_params.len() as CK_ULONG,
pDataParams: data_params.as_mut_ptr(),
ulAdditionalDerivedKeys: 0,
pAdditionalDerivedKeys: std::ptr::null_mut(),
};
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_SP800_108_COUNTER_KDF,
pParameter: &mut params as *mut _ as CK_VOID_PTR,
ulParameterLen: sizeof!(CK_SP800_108_KDF_PARAMS),
};
let mut handle3 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut handle3,
);
assert_eq!(ret, CKR_OK);
let mut handle4 = CK_INVALID_HANDLE;
let mut handle5 = CK_UNAVAILABLE_INFORMATION;
let mut handle6 = CK_UNAVAILABLE_INFORMATION;
let mut addl_keys = [
CK_DERIVED_KEY {
pTemplate: derive_template.as_ptr() as *mut _,
ulAttributeCount: derive_template.len() as CK_ULONG,
phKey: &mut handle5,
},
CK_DERIVED_KEY {
pTemplate: derive_template.as_ptr() as *mut _,
ulAttributeCount: derive_template.len() as CK_ULONG,
phKey: &mut handle6,
},
];
params.ulAdditionalDerivedKeys = 2;
params.pAdditionalDerivedKeys = addl_keys.as_mut_ptr();
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_SP800_108_COUNTER_KDF,
pParameter: &mut params as *mut _ as CK_VOID_PTR,
ulParameterLen: sizeof!(CK_SP800_108_KDF_PARAMS),
};
let ret = fn_derive_key(
session,
&mut derive_mech,
handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut handle4,
);
assert_eq!(ret, CKR_OK);
let mut val: CK_ULONG = 0;
let attrtmpl = make_ptrs_template(&[(
CKA_VALUE_LEN,
void_ptr!(&mut val),
CK_ULONG_SIZE,
)]);
let ret = fn_get_attribute_value(
session,
handle3,
attrtmpl.as_ptr() as *mut _,
attrtmpl.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(val, 16);
val = 0;
let ret = fn_get_attribute_value(
session,
handle4,
attrtmpl.as_ptr() as *mut _,
attrtmpl.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(val, 16);
val = 0;
let ret = fn_get_attribute_value(
session,
handle5,
attrtmpl.as_ptr() as *mut _,
attrtmpl.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(val, 16);
val = 0;
let ret = fn_get_attribute_value(
session,
handle6,
attrtmpl.as_ptr() as *mut _,
attrtmpl.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(val, 16);
let derive_template = make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
(CKA_VALUE_LEN, 1234),
],
&[],
&[(CKA_DERIVE, true)],
);
let mut counter_format = CK_SP800_108_COUNTER_FORMAT {
bLittleEndian: 0,
ulWidthInBits: 32,
};
let mut data_params = [
CK_PRF_DATA_PARAM {
type_: CK_SP800_108_ITERATION_VARIABLE,
pValue: std::ptr::null_mut(),
ulValueLen: 0,
},
CK_PRF_DATA_PARAM {
type_: CK_SP800_108_COUNTER,
pValue: &mut counter_format as *mut _ as CK_VOID_PTR,
ulValueLen: sizeof!(CK_SP800_108_COUNTER_FORMAT),
},
];
#[cfg(feature = "fips")]
let mut iv = [123u8; 32];
#[cfg(not(feature = "fips"))]
let mut iv = [1u8; 5];
let mut params = CK_SP800_108_FEEDBACK_KDF_PARAMS {
prfType: CKM_SHA256_HMAC,
ulNumberOfDataParams: data_params.len() as CK_ULONG,
pDataParams: data_params.as_mut_ptr(),
ulIVLen: iv.len() as CK_ULONG,
pIV: iv.as_mut_ptr(),
ulAdditionalDerivedKeys: 0,
pAdditionalDerivedKeys: std::ptr::null_mut(),
};
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_SP800_108_FEEDBACK_KDF,
pParameter: &mut params as *mut _ as CK_VOID_PTR,
ulParameterLen: sizeof!(CK_SP800_108_FEEDBACK_KDF_PARAMS),
};
let mut handle7 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut handle7,
);
assert_eq!(ret, CKR_OK);
}
#[cfg(feature = "aes")]
#[test]
#[parallel]
fn test_aes_enc_kdf() {
let mut testtokn = TestToken::initialized("test_aes_enc_kdf", None);
let session = testtokn.get_session(true);
testtokn.login();
let aeskey = ret_or_panic!(generate_key(
session,
CKM_AES_KEY_GEN,
std::ptr::null_mut(),
0,
&[(CKA_KEY_TYPE, CKK_AES), (CKA_VALUE_LEN, 32),],
&[],
&[(CKA_DERIVE, true)],
));
let derive_template = make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_AES),
(CKA_VALUE_LEN, 16),
],
&[],
&[(CKA_DERIVE, true)],
);
let data = "derive keys data";
let mut derive_params = CK_KEY_DERIVATION_STRING_DATA {
pData: data.as_ptr() as CK_BYTE_PTR,
ulLen: data.len() as CK_ULONG,
};
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_AES_ECB_ENCRYPT_DATA,
pParameter: &mut derive_params as *mut _ as CK_VOID_PTR,
ulParameterLen: sizeof!(CK_KEY_DERIVATION_STRING_DATA),
};
let mut aeskey2 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
aeskey,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut aeskey2,
);
assert_eq!(ret, CKR_OK);
let mut derive_params = CK_AES_CBC_ENCRYPT_DATA_PARAMS {
iv: [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
pData: data.as_ptr() as CK_BYTE_PTR,
length: data.len() as CK_ULONG,
};
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_AES_CBC_ENCRYPT_DATA,
pParameter: &mut derive_params as *mut _ as CK_VOID_PTR,
ulParameterLen: sizeof!(CK_AES_CBC_ENCRYPT_DATA_PARAMS),
};
let mut aeskey3 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
aeskey2,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut aeskey3,
);
assert_eq!(ret, CKR_OK);
}
#[cfg(feature = "hash")]
#[test]
#[parallel]
fn test_hash_kdf() {
let mut testtokn = TestToken::initialized("test_hash_kdf", None);
let session = testtokn.get_session(true);
testtokn.login();
for kopt in [
(CKM_GENERIC_SECRET_KEY_GEN, CKK_GENERIC_SECRET, 16),
(CKM_AES_KEY_GEN, CKK_AES, 32),
] {
let key_handle = ret_or_panic!(generate_key(
session,
kopt.0,
std::ptr::null_mut(),
0,
&[(CKA_KEY_TYPE, kopt.1), (CKA_VALUE_LEN, kopt.2),],
&[],
&[(CKA_DERIVE, true),],
));
for hopt in [
#[cfg(not(feature = "no_sha1"))]
(CKM_SHA1_KEY_DERIVATION, 20),
(CKM_SHA224_KEY_DERIVATION, 28),
(CKM_SHA256_KEY_DERIVATION, 32),
(CKM_SHA384_KEY_DERIVATION, 48),
(CKM_SHA512_KEY_DERIVATION, 64),
(CKM_SHA3_224_KEY_DERIVATION, 28),
(CKM_SHA3_256_KEY_DERIVATION, 32),
(CKM_SHA3_384_KEY_DERIVATION, 48),
(CKM_SHA3_512_KEY_DERIVATION, 64),
] {
let derive_template = make_attr_template(
&[(CKA_CLASS, CKO_SECRET_KEY)],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut derive_mech = CK_MECHANISM {
mechanism: hopt.0,
pParameter: std::ptr::null_mut(),
ulParameterLen: 0,
};
let mut hashkey1 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey1,
);
assert_eq!(ret, CKR_OK);
let mut extract_template = [CK_ATTRIBUTE {
type_: CKA_VALUE,
pValue: std::ptr::null_mut(),
ulValueLen: 0,
}];
let ret = fn_get_attribute_value(
session,
hashkey1,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(extract_template[0].ulValueLen, hopt.1);
let derive_template = make_attr_template(
&[(CKA_CLASS, CKO_SECRET_KEY), (CKA_VALUE_LEN, hopt.1 + 10)],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut hashkey2 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey2,
);
assert_eq!(ret, CKR_TEMPLATE_INCONSISTENT);
let derive_template = make_attr_template(
&[(CKA_CLASS, CKO_SECRET_KEY), (CKA_VALUE_LEN, hopt.1 - 10)],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut hashkey2 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey2,
);
assert_eq!(ret, CKR_OK);
extract_template[0].ulValueLen = 0;
let ret = fn_get_attribute_value(
session,
hashkey2,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(extract_template[0].ulValueLen, hopt.1 - 10);
let derive_template = make_attr_template(
&[(CKA_CLASS, CKO_SECRET_KEY), (CKA_KEY_TYPE, CKK_AES)],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut hashkey3 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey3,
);
assert_eq!(ret, CKR_OK);
extract_template[0].ulValueLen = 0;
let len = match hopt.0 {
CKM_SHA1_KEY_DERIVATION => 16,
CKM_SHA224_KEY_DERIVATION | CKM_SHA3_224_KEY_DERIVATION => 24,
_ => 32,
};
let ret = fn_get_attribute_value(
session,
hashkey3,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(extract_template[0].ulValueLen, len);
}
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_SHA256_KEY_DERIVATION,
pParameter: std::ptr::null_mut(),
ulParameterLen: 0,
};
let derive_template = make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_AES),
(CKA_VALUE_LEN, 42),
],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut hashkey4 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey4,
);
assert_eq!(ret, CKR_TEMPLATE_INCONSISTENT);
let derive_template = make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_AES),
(CKA_VALUE_LEN, 32),
],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
);
let mut hashkey4 = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_ptr() as *mut _,
derive_template.len() as CK_ULONG,
&mut hashkey4,
);
assert_eq!(ret, CKR_OK);
let mut extract_template =
make_ptrs_template(&[(CKA_VALUE, std::ptr::null_mut(), 0)]);
let ret = fn_get_attribute_value(
session,
hashkey4,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(extract_template[0].ulValueLen, 32);
}
testtokn.finalize();
}
#[cfg(feature = "hkdf")]
#[test]
#[parallel]
fn test_hkdf() {
let mut testtokn = TestToken::initialized("test_hkdf", None);
let session = testtokn.get_session(true);
testtokn.login();
let derive_hash = CKM_SHA256;
for kopt in [
(CKM_GENERIC_SECRET_KEY_GEN, CKK_GENERIC_SECRET, 12),
(CKM_GENERIC_SECRET_KEY_GEN, CKK_GENERIC_SECRET, 32),
(CKM_HKDF_KEY_GEN, CKK_HKDF, 32),
] {
let key_handle = ret_or_panic!(generate_key(
session,
kopt.0,
std::ptr::null_mut(),
0,
&[(CKA_KEY_TYPE, kopt.1), (CKA_VALUE_LEN, kopt.2),],
&[],
&[(CKA_DERIVE, true),],
));
let salt_handle = ret_or_panic!(generate_key(
session,
kopt.0,
std::ptr::null_mut(),
0,
&[(CKA_KEY_TYPE, kopt.1), (CKA_VALUE_LEN, kopt.2),],
&[],
&[(CKA_DERIVE, true),],
));
let salt_data = "SALT";
let info_data = "INFO";
let derive_type = [CKM_HKDF_DERIVE, CKM_HKDF_DATA].into_iter();
let derive_mode =
[(true, true), (true, false), (false, true)].into_iter();
let derive_salt_type =
[CKF_HKDF_SALT_NULL, CKF_HKDF_SALT_DATA, CKF_HKDF_SALT_KEY]
.into_iter();
let derive_use_info = [true, false].into_iter();
for (((mech, mode), salt_type), use_info) in derive_type
.cartesian_product(derive_mode)
.cartesian_product(derive_salt_type)
.cartesian_product(derive_use_info)
{
if mech == CKM_HKDF_DATA
&& (mode.0 == false || salt_type == CKF_HKDF_SALT_NULL)
{
continue;
}
let (obj_class, mut derive_template) = match mech {
CKM_HKDF_DERIVE => (
CKO_SECRET_KEY,
make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
),
),
CKM_HKDF_DATA => (
CKO_DATA,
make_attr_template(
&[(CKA_CLASS, CKO_DATA), (CKA_VALUE_LEN, 32)],
&[],
&[],
),
),
_ => panic!("Bad test data"),
};
let hkdf_params = CK_HKDF_PARAMS {
bExtract: if mode.0 { CK_TRUE } else { CK_FALSE },
bExpand: if mode.1 { CK_TRUE } else { CK_FALSE },
prfHashMechanism: derive_hash,
ulSaltType: salt_type,
pSalt: match salt_type {
CKF_HKDF_SALT_NULL => std::ptr::null_mut(),
CKF_HKDF_SALT_DATA => byte_ptr!(salt_data.as_ptr()),
CKF_HKDF_SALT_KEY => std::ptr::null_mut(),
_ => panic!("Bad test data"),
},
ulSaltLen: match salt_type {
CKF_HKDF_SALT_NULL => 0,
CKF_HKDF_SALT_DATA => salt_data.len() as CK_ULONG,
CKF_HKDF_SALT_KEY => 0,
_ => panic!("Bad test data"),
},
hSaltKey: salt_handle,
pInfo: match use_info {
true => byte_ptr!(info_data.as_ptr()),
false => std::ptr::null_mut(),
},
ulInfoLen: match use_info {
true => info_data.len() as CK_ULONG,
false => 0,
},
};
let mut derive_mech = CK_MECHANISM {
mechanism: mech,
pParameter: void_ptr!(&hkdf_params),
ulParameterLen: sizeof!(CK_HKDF_PARAMS),
};
let mut drv_handle = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_mut_ptr(),
derive_template.len() as CK_ULONG,
&mut drv_handle,
);
assert_eq!(ret, CKR_OK);
let mut class: CK_ULONG = CK_UNAVAILABLE_INFORMATION;
let mut extract_template = make_ptrs_template(&[
(CKA_CLASS, void_ptr!(&mut class), CK_ULONG_SIZE),
(CKA_VALUE, std::ptr::null_mut(), 0),
]);
let ret = fn_get_attribute_value(
session,
drv_handle,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(class, obj_class);
assert_eq!(extract_template[1].ulValueLen, 32);
#[cfg(feature = "fips")]
{
let mut flags: CK_FLAGS = 0;
let ret = fn_get_session_validation_flags(
session,
CKS_LAST_VALIDATION_OK,
&mut flags,
);
assert_eq!(ret, CKR_OK);
if kopt.2 < 14 {
assert_eq!(flags, 0);
} else {
assert_eq!(flags, crate::fips::indicators::KRF_FIPS);
}
}
}
}
let hash = CKM_SHA256;
let ikm = [0x0b; 22];
let len = 1200;
let okm = hex::decode(
"8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d\
2d9d201395faa4b61a96c8b2fb61057244b36c6ddd287f634795e7d80d5fe2\
6bfc36def6dc129c29271a0eb7ab14bd2ca88259f8a3a92ac2ec0e3e4fa046\
a4b90b137ce44a2105152c2db1480a0ac2e999db47e000833856093a641da0\
82a94429eccf5143b1780234baacfa9d89b850473f2c678f7caa96b00efdac\
e2d71fd42412465308f2374960b6c3c35d3eaaea0b8f7e595fa9cc5db25a91\
bc0120bad6223b25e378f514686eedfc9f102e045868e64ab02f1c021868b4\
e6686e295a10a94524e8730d79b4d3f890c387763a19a248577e9aad8e23ba\
2bacfc9230fb144a7730d3ceaf799d1de1032951dc1fddea17f96981fbf6b0\
5e4878df782b497f60c3eb4cff0c249d8c1bbeabca6e66c71cc79314f2bfc7\
58dd41c9872cbb461e17cff0002a9fdee546953f98dde7d4aa828a68f4ccd9\
50d371d1eb3839219bfdb9ef911d3602d78bd2f6a970a6c437763c81821e13\
1325fa77fc8963a021b87caa8e35ad2a37f2237a2143c1966817e4da9912a2\
013cd7239c5fad2e4599f9ce20bcd8cd0ff1516f9f2496ecce94ccd82cde5c\
9ef120bbaf640d6292d6916d40d99d9d4657dd2fdf2d4e5a5bbb27446ed58a\
3d637d0811c555273b0fd3699161acb58205fe6cfd45245249a7ecfc4c3d06\
68de270e6962d1d19fffa4b8df099cd4022cb0df18ffcffff5b046f0fc082e\
d16f99b416b7bbd4982ad0afc8b1dc332a8058729065538dbe9422b795a887\
af9c5d50ee85a60871be14c7f2d1111f197378d99065fb89a0f57b73427927\
98963f00910e5fad47a64477f41c07ac6058e01932502eb6faa88a6cc21e11\
5b8e3ddfae8fdcaab60d13d808f3206b4e9da8bd4ae1108b2a01d256a02c91\
31ea0f6203c8c6e55ec7ae16bb19cf3239490085713679e7c304ce254e2897\
c0fd3bc97263a562fe161dcf6d21e841eb2266aa1cfaaaf6fc094111ad4b2e\
4d8e05b50854ae5de83d81842c689a55b1be7d575ac50e81d7708c262c1f70\
452884c7714abef03b88b85a41e895a0e7529b8d631e5e77583175c80e86e4\
5802763eaba0471d11fc885b34fa4b5309a9fe49a5215d4aa21041c53a30a1\
e97250f6445ce537bb3efb1fa17f141db69c7d97ab48cb34c33bef0ded5d4c\
320fe554a0faea353a5579cb08f072565bbd49d167186f39a298a553f320bb\
89eaee54151b08deef49b7b630af62b4d7be1f4965a53c67e7d3e34a6d8263\
ee86f44dfbe019cbe8e3bd4ed0cda06985127ff8d1794e6321891a950f329a\
ca2b36b16f8a2bb910b1206a5c238ef079df12ecb0f0f7e3e4f8a64bfd23b5\
7e9d286a1c8d2e9290d9a4f1d20ec100aac7dc90783cb2ecfd69d71a91dcc3\
913494ebf7a7a00d1051102d7f268e761855b985c2599350f15ee0d4093244\
113185bc7031d2431ccd9391fcd58a85e068458b644ed265b3f103852a2d7b\
bf0d2c1d7c02e30ff1ec552f09bc60e36393391cec05926009520af12d9638\
7cc55b9553e79da8b2eb9303ecf15bb289530c3d65c4cc5a68f8ece60a3752\
2fe3d0e6ba4ddfb560a45717456cf91c5dc5b8117da68bc49968ec1e35852b\
bc54e554fb839b35f6c3b5c09530855d8691fc0f126f67346f949bd813a6db\
44c513d1e61b8c8789eb9e823d1a38862dca1c5331da",
)
.expect("Failed to decode hex value");
let key_handle = ret_or_panic!(import_object(
session,
CKO_SECRET_KEY,
&[(CKA_KEY_TYPE, CKK_GENERIC_SECRET)],
&[(CKA_VALUE, ikm.as_slice())],
&[(CKA_DERIVE, true)],
));
let mut derive_template = make_attr_template(
&[(CKA_CLASS, CKO_DATA), (CKA_VALUE_LEN, len)],
&[],
&[],
);
let hkdf_params = CK_HKDF_PARAMS {
bExtract: CK_TRUE,
bExpand: CK_TRUE,
prfHashMechanism: hash,
ulSaltType: CKF_HKDF_SALT_NULL,
pSalt: std::ptr::null_mut(),
ulSaltLen: 0,
hSaltKey: CK_INVALID_HANDLE,
pInfo: std::ptr::null_mut(),
ulInfoLen: 0,
};
let mut derive_mech = CK_MECHANISM {
mechanism: CKM_HKDF_DATA,
pParameter: void_ptr!(&hkdf_params),
ulParameterLen: sizeof!(CK_HKDF_PARAMS),
};
let mut drv_handle = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
key_handle,
derive_template.as_mut_ptr(),
derive_template.len() as CK_ULONG,
&mut drv_handle,
);
assert_eq!(ret, CKR_OK);
let mut result = vec![0u8; len as usize];
let mut extract_template = make_ptrs_template(&[(
CKA_VALUE,
void_ptr!(result.as_mut_ptr()),
len as usize,
)]);
let ret = fn_get_attribute_value(
session,
drv_handle,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(extract_template[0].ulValueLen, len);
assert_eq!(result, okm);
testtokn.finalize();
}
#[cfg(feature = "pbkdf2")]
#[cfg(not(feature = "no_sha1"))]
#[test]
#[parallel]
fn test_pbkdf2() {
let mut testtokn = TestToken::initialized("test_pbkdf2", None);
let session = testtokn.get_session(false);
testtokn.login();
for test in [
#[cfg(not(feature = "fips"))]
#[cfg(feature = "slow")]
(
"password",
"salt",
1,
hex::decode("0c60c80f961f0e71f3a9b524af6012062fe037a6").unwrap(),
),
#[cfg(not(feature = "fips"))]
#[cfg(feature = "slow")]
(
"password",
"salt",
2,
hex::decode("ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957").unwrap(),
),
#[cfg(not(feature = "fips"))]
#[cfg(feature = "slow")]
(
"password",
"salt",
4096,
hex::decode("4b007901b765489abead49d926f721d065a429c1").unwrap(),
),
#[cfg(feature = "slow")]
(
"password",
"salt",
16777216,
hex::decode("eefe3d61cd4da4e4e9945b3d6ba2158c2634e984").unwrap(),
),
(
"passwordPASSWORDpassword",
"saltSALTsaltSALTsaltSALTsaltSALTsalt",
4096,
hex::decode("3d2eec4fe41c849b80c8d83662c0e44a8b291a964cf2f07038")
.unwrap(),
),
#[cfg(not(feature = "fips"))]
(
"pass\0word",
"sa\0lt",
4096,
hex::decode("56fa6aa75548099dcc37d7f03425e0c3").unwrap(),
),
#[cfg(not(feature = "fips"))]
(
"",
"salt",
1024,
hex::decode("372bd05001b6ca2a4668e7f4f219204b").unwrap(),
),
] {
let params = CK_PKCS5_PBKD2_PARAMS2 {
saltSource: CKZ_DATA_SPECIFIED,
pSaltSourceData: void_ptr!(test.1.as_ptr()),
ulSaltSourceDataLen: test.1.len() as CK_ULONG,
iterations: test.2,
prf: CKP_PKCS5_PBKD2_HMAC_SHA1,
pPrfData: std::ptr::null_mut(),
ulPrfDataLen: 0,
pPassword: test.0.as_ptr() as *const _ as *mut _,
ulPasswordLen: test.0.len() as CK_ULONG,
};
let handle = ret_or_panic!(generate_key(
session,
CKM_PKCS5_PBKD2,
void_ptr!(¶ms),
sizeof!(CK_PKCS5_PBKD2_PARAMS2),
&[
(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
(CKA_VALUE_LEN, test.3.len() as CK_ULONG),
],
&[],
&[
(CKA_WRAP, true),
(CKA_UNWRAP, true),
(CKA_SENSITIVE, false),
(CKA_EXTRACTABLE, true),
],
));
let mut result = vec![0u8; test.3.len()];
let mut extract_template = make_ptrs_template(&[(
CKA_VALUE,
void_ptr!(result.as_mut_ptr()),
result.len(),
)]);
let ret = fn_get_attribute_value(
session,
handle,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(result, test.3);
}
testtokn.finalize();
}
#[cfg(feature = "sshkdf")]
#[test]
#[parallel]
fn test_sshkdf() {
let mut testtokn = TestToken::initialized("test_sshkdf", None);
let session = testtokn.get_session(false);
testtokn.login();
for test in [
#[cfg(not(any(feature = "fips", feature = "no_sha1")))]
(
CKM_SHA_1,
hex::decode(
"000001001eb033aab0830ccd612bb4167300fadd3e74ebc7a51941\
e374319e84b537452e20c7404ef71f7cb2fbbc86a0b3de6a5481da\
9451f71286001558ed2e3ba184553f143aad3a1c7a97b095cbb645\
d78202fe9a826b131eeb229f54895abdf108350596cbd9e37d2a7a\
18c9efeebb360637d0e1c3ba0d2636d2a84a28451fcb3ae91aa155\
ffa69127889244a02df18491d6fc7b4c440d385f7dcab120d7c620\
f62a750f032131e8cee361ad9f03e315634f1da4c62e97af50f992\
0f847ed0fbef05b0888993bb5029101ae4d384c03fde132c7b3b61\
ebccf44fa32c24af984ec29e615d39cce25809178bc18475584566\
e4901924493710971fca33dce88f64c25e",
)
.unwrap(),
hex::decode("82c692ef009ae5874044048bfbdef7438118ca1b").unwrap(),
hex::decode("82c692ef009ae5874044048bfbdef7438118ca1b").unwrap(),
hex::decode("0f529afc2f2e1c67636822c1b456a798").unwrap(),
hex::decode("03b5596d748eef4122e356d10bc85ead").unwrap(),
hex::decode(
"1588f52090daeb6e88e3665e98f5cce933f0fae328a2befbe808ad\
c37bf62b34",
)
.unwrap(),
hex::decode(
"5b6a435e02777bed749c10790e24d3e5bdff63161c4e2baf334279\
33ffa831ff",
)
.unwrap(),
hex::decode("31bde53364f3445b0de695849b2a96a42ceaf4f3").unwrap(),
hex::decode("f39da5279ba483a705e83d837bb97044690ed9bc").unwrap(),
),
(
CKM_SHA256,
hex::decode(
"000001004b3c931dbc90f471d53c81439b16a1f2b5cae0f327261d\
398101d433e1a6eef9d5de7ab6ac4bf24ddbb1329e1cb785a436fb\
597f4c7f7fdb087d921ccf8695473a6db93bef4fbc6ebfb6622d49\
c17d818b691f07bf268496a88e75199524a43cb597dc839f5e799a\
d16f28262ce1b3a2d9874e10af76cee054bad55fb0d0062397caf6\
64a6e4d74cdde081904e137c43d5a061259829dd71bc0b1c80e489\
c7c67a43bcd35744a2a19f9d953832aba1a4d12900e84f6cb06327\
1e0ecbd7c99494809604570817af51774741738ea80b4ce4cc326e\
eae3caa959e40528b341aa80cde04acea11bded12be73f7820d0e5\
670234f0661d8e3e6b3e82b9fd3411a6da",
)
.unwrap(),
hex::decode(
"0eae56989310f527883af6e2b01943e7cd741f6a483bf60415c05b\
3387c05eaf",
)
.unwrap(),
hex::decode(
"0eae56989310f527883af6e2b01943e7cd741f6a483bf60415c05b\
3387c05eaf",
)
.unwrap(),
hex::decode("28f2016a5d81305e8b03dcc7886e344c").unwrap(),
hex::decode("36e3705af889ccc5a9e84170f44b5322").unwrap(),
hex::decode(
"f2ecd739f4423ae5e08639a8465be3a8c33e3bf109da95c3fc73ca\
306156a79f",
)
.unwrap(),
hex::decode(
"f3d2fc5bf516fc18c656a7fdc1e2e32cc61b2980f8226c8513f894\
c31e38ed5f",
)
.unwrap(),
hex::decode(
"3fec8dd099f8b61da4eb6058e17aca7a89e10b6e403e83901d29d0\
0aaf435b64",
)
.unwrap(),
hex::decode(
"cde71f736c0e31e81707b3679b5be187c8056965a08fc2f5d82f94\
5cbec975bd",
)
.unwrap(),
),
(
CKM_SHA384,
hex::decode(
"0000010100d4af17edd4baccef26d37991a62e124a78dc0a3136ce\
8adb0fbbfa8ca9e41fdb589b24f78e953801c05a405353dd7ef12f\
ad6872ef0b6a8a094453bf8600aed0355836f97ca6692a2523f000\
6e51de272acb05e57645e69654bc00fa8aec453381a6d0177649d7\
c191c9456579a02d25201b3307113cb89c00d7f797cdad28c91f41\
6edc2e63d2f9647ab3e47c959357930f01721f992ef332081bf5e3\
8ae3a75e24212d079fd1280d5979962c5414a90bc2e99454b1549c\
f1b403c03a3b0857bd32efd4b41c7deeca452f11256bac9fdb8dce\
eef6492ad804a80de67d916a57ec2a00ce6115d2bcc4bd8fa7f466\
44088b9370597efacd0d6c937690d6248172",
)
.unwrap(),
hex::decode(
"c05cd92556dc72044c4969ccf09d1c7551fd725cdc42f16a15e69e\
c9d89d75a366c9268277fee763a38d95543aa3652e",
)
.unwrap(),
hex::decode(
"c05cd92556dc72044c4969ccf09d1c7551fd725cdc42f16a15e69e\
c9d89d75a366c9268277fee763a38d95543aa3652e",
)
.unwrap(),
hex::decode("f727aecee81f151d552d4c6b165bef3b").unwrap(),
hex::decode("f4c72877550b4a24487d377d50739b63").unwrap(),
hex::decode(
"cc4e387b44068ca27da3646f5d2595d5a8b80732992bbe2336097c\
af6c64cbbb",
)
.unwrap(),
hex::decode(
"a586ca518c54812f57c10a6d0e7499489490d5de062e424e9a9c41\
ffd367981a",
)
.unwrap(),
hex::decode(
"0d587549efd9fdf1fcbc4ff56620f9a2b9138db9873c537d2b5071\
eae7799f3649d769ae6300752972a891d36c4addf2",
)
.unwrap(),
hex::decode(
"35dd32a9425db34efd622e6516296b4652f4cffdcff8fb61b61df0\
54144672e21bb0e43da674493360269fcc1d96fa85",
)
.unwrap(),
),
(
CKM_SHA512,
hex::decode(
"0000010100b5ec7df0e63b61d9e676f055d467ea76ac2a4f9242a17\
982f614dcf3e2a41e5270de58c0ed508d16bad51eef5ae1ff6c4428\
0ff983d441664e23681c5ba883a53841136e8e40d8027022a86cde2\
2790a8714db49183ce6af7c53044d8218a2a7b5778bae1e9fdeccef\
1780cf0005495818bf6300a95d9653a079f70f55117c369f4250ec3\
397be371eff7e5d066a5396ddb184ebe0ad8b81db2d462396769260\
2e8960bd3eb560b1b348771abe94921ba9e802caef648937133cc12\
9028954b0316d4996a92b65c1e65317ab1a2989027bef3e80c69d02\
bfd0e765af9ec1060ca49549d181b45d670eb66f872030dba6a017d\
4f8c61f68f733ee3b92302ad640",
)
.unwrap(),
hex::decode(
"d77e95d23d1fcdac73d3aa1907b952aba5f842b8755e1bc99268d1\
74f2515187523e1572857c5b2c144929fe47b859b13323aaec1f73\
b5dac7ee72cd0e29e337",
)
.unwrap(),
hex::decode(
"d77e95d23d1fcdac73d3aa1907b952aba5f842b8755e1bc99268d1\
74f2515187523e1572857c5b2c144929fe47b859b13323aaec1f73\
b5dac7ee72cd0e29e337",
)
.unwrap(),
hex::decode("bd59bb5679b272a6e93c1d0267b868b9").unwrap(),
hex::decode("c99c79493d4ccef62f08a21d19b3294c").unwrap(),
hex::decode(
"c76f1ff0a3933433c3869444f8dafa0bc672b62f4d4ab79c645c3b\
aa7ea557d4",
)
.unwrap(),
hex::decode(
"23c39f34b3c80b37915f0be671cb3a91c3483288097694d4218647\
323a2dcb47",
)
.unwrap(),
hex::decode(
"4bd4bd7d0e84ccf31444b3ad1cb92490138342b8748af1ad525c0f\
124db13e995bb98f47468b2378e668a938970054f017e610ced872\
4a81319140fbc6b96898",
)
.unwrap(),
hex::decode(
"3ac38453d0243a62e87b74d1b9ca0b992012f09d3e0924fe1a1e9f\
d1e1752ae9d5776ee7e66670203bb1ad5af1a0e7ff7a9fcc348185\
8416500afa448d23f101",
)
.unwrap(),
),
] {
let handle = ret_or_panic!(import_object(
session,
CKO_SECRET_KEY,
&[(CKA_KEY_TYPE, CKK_GENERIC_SECRET)],
&[(CKA_VALUE, test.1.as_slice())],
&[(CKA_DERIVE, true)],
));
for kt in [
(b"A", test.4),
(b"B", test.5),
(b"C", test.6),
(b"D", test.7),
(b"E", test.8),
(b"F", test.9),
] {
let sshkdf_params = KR_SSHKDF_PARAMS {
prfHashMechanism: test.0,
derivedKeyType: kt.0[0],
pExchangeHash: byte_ptr!(test.2.as_ptr()),
ulExchangeHashLen: test.2.len() as CK_ULONG,
pSessionId: byte_ptr!(test.3.as_ptr()),
ulSessionIdLen: test.3.len() as CK_ULONG,
};
let mut derive_template = match kt.0 {
b"A" | b"B" => make_attr_template(
&[
(CKA_CLASS, CKO_DATA),
(CKA_VALUE_LEN, kt.1.len() as CK_ULONG),
],
&[],
&[],
),
b"C" | b"D" | b"E" | b"F" => make_attr_template(
&[
(CKA_CLASS, CKO_SECRET_KEY),
(CKA_KEY_TYPE, CKK_GENERIC_SECRET),
(CKA_VALUE_LEN, kt.1.len() as CK_ULONG),
],
&[],
&[(CKA_SENSITIVE, false), (CKA_EXTRACTABLE, true)],
),
_ => panic!("What?"),
};
let mut derive_mech = CK_MECHANISM {
mechanism: KRM_SSHKDF_DERIVE,
pParameter: void_ptr!(&sshkdf_params),
ulParameterLen: sizeof!(KR_SSHKDF_PARAMS),
};
let mut drv_handle = CK_INVALID_HANDLE;
let ret = fn_derive_key(
session,
&mut derive_mech,
handle,
derive_template.as_mut_ptr(),
derive_template.len() as CK_ULONG,
&mut drv_handle,
);
assert_eq!(ret, CKR_OK);
let mut result = vec![0u8; kt.1.len()];
let mut extract_template = make_ptrs_template(&[(
CKA_VALUE,
void_ptr!(result.as_mut_ptr()),
kt.1.len(),
)]);
let ret = fn_get_attribute_value(
session,
drv_handle,
extract_template.as_mut_ptr(),
extract_template.len() as CK_ULONG,
);
assert_eq!(ret, CKR_OK);
assert_eq!(result, kt.1);
}
}
testtokn.finalize();
}