Skip to content

Commit 2b1cd44

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 0169642 commit 2b1cd44

File tree

2 files changed

+143
-11
lines changed

2 files changed

+143
-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: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,91 @@ fn derive_key() -> TestResult {
687687
Ok(())
688688
}
689689

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

0 commit comments

Comments
 (0)