Skip to content

Commit 92382a3

Browse files
authored
Merge pull request #292 from nwalfield/eckdf
Add more setters for EcKdf.
2 parents bf85b6f + fb1efbc commit 92382a3

File tree

3 files changed

+158
-12
lines changed

3 files changed

+158
-12
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: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
mod common;
44

5-
use crate::common::{get_pkcs11, is_softhsm, SO_PIN, USER_PIN};
5+
use crate::common::{get_firmware_version, get_pkcs11, is_kryoptic, is_softhsm, SO_PIN, USER_PIN};
66
use common::init_pins;
77
use cryptoki::context::Function;
88
use cryptoki::error::{Error, RvError};
@@ -687,6 +687,94 @@ 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+
if is_kryoptic() {
702+
let (major, minor) = get_firmware_version(&pkcs11, slot);
703+
// Kryoptic added support for sha256_sp800 in version 1.3.
704+
if !(major > 1 || minor >= 3) {
705+
eprintln!(
706+
"Skipping test: Kryoptic is too old (need 1.3, got {}.{})",
707+
major, minor
708+
);
709+
return Ok(());
710+
}
711+
}
712+
713+
// open a session
714+
let session = pkcs11.open_rw_session(slot)?;
715+
716+
// log in the session
717+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
718+
719+
// sha256_sp800
720+
let key = hex::decode("F00670C5F139E7E6C2511EA04FF507AFBBE237CE3C71A89CA59A1C5CF8856562")
721+
.expect("valid hex");
722+
let ephemeral_key =
723+
hex::decode("533B3F09E53B3DEED661A13F7A7D9694AB71CE156C728E00DEE87A1EE3A14C4A")
724+
.expect("valid hex");
725+
let kdf_param = hex::decode("0A2B0601040197550105011203010807416E6F6E796D6F75732053656E646572202020205633A4C5AE4305BC0FE2ABB699A8EE54632790A0").expect("valid hex");
726+
let derivation = hex::decode("AF8CE51D0139A6D60831A9BABAB20186").expect("valid hex");
727+
728+
let template = [
729+
Attribute::Class(ObjectClass::PRIVATE_KEY),
730+
Attribute::KeyType(KeyType::EC_MONTGOMERY),
731+
Attribute::EcParams(vec![
732+
0x13, 0x0a, 0x63, 0x75, 0x72, 0x76, 0x65, 0x32, 0x35, 0x35, 0x31, 0x39,
733+
]),
734+
Attribute::Value(key),
735+
Attribute::Id(b"foo".to_vec()),
736+
Attribute::Label(b"bar".to_vec()),
737+
Attribute::Sensitive(true),
738+
Attribute::Token(true),
739+
Attribute::Derive(true),
740+
];
741+
742+
let private = session.create_object(&template)?;
743+
744+
let kdf = EcKdf::sha256_sp800(&kdf_param);
745+
746+
let params = Ecdh1DeriveParams::new(kdf, &ephemeral_key);
747+
748+
let shared_secret = session.derive_key(
749+
&Mechanism::Ecdh1Derive(params),
750+
private,
751+
&[
752+
Attribute::Class(ObjectClass::SECRET_KEY),
753+
Attribute::KeyType(KeyType::GENERIC_SECRET),
754+
Attribute::ValueLen(Ulong::new(derivation.len().try_into().unwrap())),
755+
Attribute::Sensitive(false),
756+
Attribute::Extractable(true),
757+
Attribute::Token(false),
758+
],
759+
)?;
760+
761+
let value_attribute = session
762+
.get_attributes(shared_secret, &[AttributeType::Value])?
763+
.remove(0);
764+
let value = if let Attribute::Value(value) = value_attribute {
765+
value
766+
} else {
767+
panic!("Expected value attribute.");
768+
};
769+
770+
assert_eq!(value, derivation);
771+
772+
// delete keys
773+
session.destroy_object(private)?;
774+
775+
Ok(())
776+
}
777+
690778
#[test]
691779
#[serial]
692780
fn import_export() -> TestResult {

cryptoki/tests/common.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ pub fn is_softhsm() -> bool {
2020
get_pkcs11_path().contains("softhsm")
2121
}
2222

23+
pub fn is_kryoptic() -> bool {
24+
get_pkcs11_path().contains("kryoptic")
25+
}
26+
2327
pub fn get_pkcs11() -> Pkcs11 {
2428
Pkcs11::new(get_pkcs11_path()).unwrap()
2529
}
@@ -46,3 +50,10 @@ pub fn init_pins() -> (Pkcs11, Slot) {
4650

4751
(pkcs11, slot)
4852
}
53+
54+
pub fn get_firmware_version(pkcs11: &Pkcs11, slot: Slot) -> (u8, u8) {
55+
let info = pkcs11.get_slot_info(slot).unwrap();
56+
57+
let v = info.firmware_version();
58+
(v.major(), v.minor())
59+
}

0 commit comments

Comments
 (0)