Skip to content

Commit 4bf4ba6

Browse files
committed
Add more setters for EcKdf.
Adds setters for the ANSI X9.63 KDFs (`EcKdf::sha1`, etc) and the NIST SP800-56A KDFs (`EcKdf::sha1_sp800`) to `EcKdf`. Fixes `EcKdf::sha256`. Fixes #281. Signed-off-by: Neal H. Walfield <[email protected]>
1 parent bf85b6f commit 4bf4ba6

File tree

2 files changed

+134
-11
lines changed

2 files changed

+134
-11
lines changed

cryptoki/src/mechanism/elliptic_curve.rs

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,45 @@ pub struct EcKdf<'a> {
8282
shared_data: Option<&'a [u8]>,
8383
}
8484

85-
impl EcKdf<'_> {
85+
macro_rules! ansi {
86+
{ $func_name: ident, $algo: ident, $algo_name: literal } => {
87+
#[doc = "The key derivation function based on "]
88+
#[doc = $algo_name]
89+
#[doc = " as defined in the ANSI X9.63 standard. The
90+
derived key is produced by concatenating hashes of
91+
the shared value followed by 00000001, 00000002,
92+
etc. until we find enough bytes to fill the
93+
`CKA_VALUE_LEN` of the derived key."]
94+
pub fn $func_name(shared_data: &'a [u8]) -> Self {
95+
Self {
96+
kdf_type: $algo,
97+
shared_data: Some(shared_data),
98+
}
99+
}
100+
}
101+
}
102+
103+
macro_rules! sp800 {
104+
{ $func_name: ident, $algo: ident, $algo_name: literal } => {
105+
#[doc = "The key derivation function based on "]
106+
#[doc = $algo_name]
107+
#[doc = " as defined in the [NIST SP800-56A standard, revision
108+
2](http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf),
109+
section 5.8.1.1. The derived key is produced by
110+
concatenating hashes of 00000001, 00000002,
111+
etc. followed by the shared value until we find
112+
enough bytes to fill the `CKA_VALUE_LEN` of the
113+
derived key."]
114+
pub fn $func_name(shared_data: &'a [u8]) -> Self {
115+
Self {
116+
kdf_type: $algo,
117+
shared_data: Some(shared_data),
118+
}
119+
}
120+
}
121+
}
122+
123+
impl<'a> EcKdf<'a> {
86124
/// The null transformation. The derived key value is produced by
87125
/// taking bytes from the left of the agreed value. The new key
88126
/// size is limited to the size of the agreed value.
@@ -93,16 +131,25 @@ impl EcKdf<'_> {
93131
}
94132
}
95133

96-
/// The key derivation function based on sha256 as defined in the ANSI X9.63 standard. The
97-
/// derived key is produced by concatenating hashes of the shared
98-
/// value followed by 00000001, 00000002, etc. until we find
99-
/// enough bytes to fill the `CKA_VALUE_LEN` of the derived key.
100-
pub fn sha256() -> Self {
101-
Self {
102-
kdf_type: CKD_SHA256_KDF,
103-
shared_data: None,
104-
}
105-
}
134+
ansi!(sha1, CKD_SHA1_KDF, "SHA1");
135+
ansi!(sha224, CKD_SHA224_KDF, "SHA224");
136+
ansi!(sha256, CKD_SHA256_KDF, "SHA256");
137+
ansi!(sha384, CKD_SHA384_KDF, "SHA384");
138+
ansi!(sha512, CKD_SHA512_KDF, "SHA512");
139+
ansi!(sha3_224, CKD_SHA3_224_KDF, "SHA3_224");
140+
ansi!(sha3_256, CKD_SHA3_256_KDF, "SHA3_256");
141+
ansi!(sha3_384, CKD_SHA3_384_KDF, "SHA3_384");
142+
ansi!(sha3_512, CKD_SHA3_512_KDF, "SHA3_512");
143+
144+
sp800!(sha1_sp800, CKD_SHA1_KDF_SP800, "SHA1");
145+
sp800!(sha224_sp800, CKD_SHA224_KDF_SP800, "SHA224");
146+
sp800!(sha256_sp800, CKD_SHA256_KDF_SP800, "SHA256");
147+
sp800!(sha384_sp800, CKD_SHA384_KDF_SP800, "SHA384");
148+
sp800!(sha512_sp800, CKD_SHA512_KDF_SP800, "SHA512");
149+
sp800!(sha3_224_sp800, CKD_SHA3_224_KDF_SP800, "SHA3_224");
150+
sp800!(sha3_256_sp800, CKD_SHA3_256_KDF_SP800, "SHA3_256");
151+
sp800!(sha3_384_sp800, CKD_SHA3_384_KDF_SP800, "SHA3_384");
152+
sp800!(sha3_512_sp800, CKD_SHA3_512_KDF_SP800, "SHA3_512");
106153

107154
// The intention here is to be able to support other methods with
108155
// shared data, without it being a breaking change, by just adding

cryptoki/tests/basic.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,82 @@ fn derive_key() -> TestResult {
687687
Ok(())
688688
}
689689

690+
#[test]
691+
#[serial]
692+
fn derive_key_sp800() -> TestResult {
693+
if is_softhsm() {
694+
return Ok(());
695+
}
696+
697+
use cryptoki::mechanism::elliptic_curve::*;
698+
699+
let (pkcs11, slot) = init_pins();
700+
701+
// open a session
702+
let session = pkcs11.open_rw_session(slot)?;
703+
704+
// log in the session
705+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
706+
707+
// sha256_sp800
708+
let key = hex::decode("F00670C5F139E7E6C2511EA04FF507AFBBE237CE3C71A89CA59A1C5CF8856562")
709+
.expect("valid hex");
710+
let ephemeral_key =
711+
hex::decode("533B3F09E53B3DEED661A13F7A7D9694AB71CE156C728E00DEE87A1EE3A14C4A")
712+
.expect("valid hex");
713+
let kdf_param = hex::decode("0A2B0601040197550105011203010807416E6F6E796D6F75732053656E646572202020205633A4C5AE4305BC0FE2ABB699A8EE54632790A0").expect("valid hex");
714+
let derivation = hex::decode("AF8CE51D0139A6D60831A9BABAB20186").expect("valid hex");
715+
716+
let template = [
717+
Attribute::Class(ObjectClass::PRIVATE_KEY),
718+
Attribute::KeyType(KeyType::EC_MONTGOMERY),
719+
Attribute::EcParams(vec![
720+
0x13, 0x0a, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39,
721+
]),
722+
Attribute::Value(key),
723+
Attribute::Id(b"foo".to_vec()),
724+
Attribute::Label(b"bar".to_vec()),
725+
Attribute::Sensitive(true),
726+
Attribute::Token(true),
727+
Attribute::Derive(true),
728+
];
729+
730+
let private = session.create_object(&template)?;
731+
732+
let kdf = EcKdf::sha256_sp800(&kdf_param);
733+
734+
let params = Ecdh1DeriveParams::new(kdf, &ephemeral_key);
735+
736+
let shared_secret = session.derive_key(
737+
&Mechanism::Ecdh1Derive(params),
738+
private,
739+
&[
740+
Attribute::Class(ObjectClass::SECRET_KEY),
741+
Attribute::KeyType(KeyType::GENERIC_SECRET),
742+
Attribute::ValueLen(Ulong::new(derivation.len() as u64).try_into().unwrap()),
743+
Attribute::Sensitive(false),
744+
Attribute::Extractable(true),
745+
Attribute::Token(false),
746+
],
747+
)?;
748+
749+
let value_attribute = session
750+
.get_attributes(shared_secret, &[AttributeType::Value])?
751+
.remove(0);
752+
let value = if let Attribute::Value(value) = value_attribute {
753+
value
754+
} else {
755+
panic!("Expected value attribute.");
756+
};
757+
758+
assert_eq!(value, derivation);
759+
760+
// delete keys
761+
session.destroy_object(private)?;
762+
763+
Ok(())
764+
}
765+
690766
#[test]
691767
#[serial]
692768
fn import_export() -> TestResult {

0 commit comments

Comments
 (0)