From 3bf8f5cbb98934b6ab3cfb9eead5c46ee12053eb Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 5 Aug 2021 12:31:13 +0200 Subject: [PATCH 1/7] Add generation of symmetric keys (DES3) Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/functions/key_management.rs | 23 +++++++++++++++++++++++ cryptoki/src/types/mechanism/mod.rs | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/cryptoki/src/functions/key_management.rs b/cryptoki/src/functions/key_management.rs index 1c3b816b..01ef09f3 100644 --- a/cryptoki/src/functions/key_management.rs +++ b/cryptoki/src/functions/key_management.rs @@ -12,6 +12,29 @@ use cryptoki_sys::{CK_ATTRIBUTE, CK_MECHANISM, CK_MECHANISM_PTR}; use std::convert::TryInto; impl<'a> Session<'a> { + /// Generate a secret key + pub fn generate_key( + &self, + mechanism: &Mechanism, + template: &[Attribute], + ) -> Result { + let mut mechanism: CK_MECHANISM = mechanism.into(); + let mut template: Vec = template.iter().map(|attr| attr.into()).collect(); + let mut handle = 0; + unsafe { + Rv::from(get_pkcs11!(self.client(), C_GenerateKey)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + template.as_mut_ptr(), + template.len().try_into()?, + &mut handle, + )) + .into_result()?; + } + + Ok(ObjectHandle::new(handle)) + } + /// Generate a public/private key pair pub fn generate_key_pair( &self, diff --git a/cryptoki/src/types/mechanism/mod.rs b/cryptoki/src/types/mechanism/mod.rs index c2f481b7..534c7100 100644 --- a/cryptoki/src/types/mechanism/mod.rs +++ b/cryptoki/src/types/mechanism/mod.rs @@ -43,6 +43,12 @@ impl MechanismType { val: CKM_RSA_PKCS_OAEP, }; + // DES + /// DES3 + pub const DES3_KEY_GEN: MechanismType = MechanismType { + val: CKM_DES3_KEY_GEN, + }; + // ECC /// EC key pair generation mechanism pub const ECC_KEY_PAIR_GEN: MechanismType = MechanismType { @@ -117,6 +123,7 @@ impl TryFrom for MechanismType { CKM_SHA256 => Ok(MechanismType::SHA256), CKM_SHA384 => Ok(MechanismType::SHA384), CKM_SHA512 => Ok(MechanismType::SHA512), + CKM_DES3_KEY_GEN => Ok(MechanismType::DES3_KEY_GEN), CKM_EC_KEY_PAIR_GEN => Ok(MechanismType::ECC_KEY_PAIR_GEN), CKM_EC_EDWARDS_KEY_PAIR_GEN => Ok(MechanismType::ECC_EDWARDS_KEY_PAIR_GEN), CKM_EC_MONTGOMERY_KEY_PAIR_GEN => Ok(MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN), @@ -150,6 +157,10 @@ pub enum Mechanism { /// defined in PKCS #1 RsaPkcsOaep(rsa::PkcsOaepParams), + // DES + /// DES3 + Des3KeyGen, + // ECC /// EC key pair generation EccKeyPairGen, @@ -190,6 +201,8 @@ impl Mechanism { Mechanism::RsaPkcsPss(_) => MechanismType::RSA_PKCS_PSS, Mechanism::RsaPkcsOaep(_) => MechanismType::RSA_PKCS_OAEP, + Mechanism::Des3KeyGen => MechanismType::DES3_KEY_GEN, + Mechanism::EccKeyPairGen => MechanismType::ECC_KEY_PAIR_GEN, Mechanism::EccEdwardsKeyPairGen => MechanismType::ECC_EDWARDS_KEY_PAIR_GEN, Mechanism::EccMontgomeryKeyPairGen => MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN, @@ -240,6 +253,7 @@ impl From<&Mechanism> for CK_MECHANISM { | Mechanism::Sha256 | Mechanism::Sha384 | Mechanism::Sha512 + | Mechanism::Des3KeyGen | Mechanism::EccKeyPairGen | Mechanism::EccEdwardsKeyPairGen | Mechanism::EccMontgomeryKeyPairGen From d32a1077198e6e0c2b54cdf4410752696d5b180d Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Thu, 5 Aug 2021 12:41:57 +0200 Subject: [PATCH 2/7] Add key wrapping function Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/functions/key_management.rs | 37 +++++++++++++++++ cryptoki/tests/basic.rs | 53 ++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/cryptoki/src/functions/key_management.rs b/cryptoki/src/functions/key_management.rs index 01ef09f3..55005801 100644 --- a/cryptoki/src/functions/key_management.rs +++ b/cryptoki/src/functions/key_management.rs @@ -93,4 +93,41 @@ impl<'a> Session<'a> { Ok(ObjectHandle::new(handle)) } + + /// Wrap key + pub fn wrap_key( + &self, + mechanism: &Mechanism, + wrapping_key: ObjectHandle, + key: ObjectHandle, + ) -> Result> { + let mut mechanism: CK_MECHANISM = mechanism.into(); + unsafe { + let mut wrapped_key_len = 0; + + Rv::from(get_pkcs11!(self.client(), C_WrapKey)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + wrapping_key.handle(), + key.handle(), + std::ptr::null_mut(), + &mut wrapped_key_len, + )) + .into_result()?; + + let mut wrapped_key = vec![0; wrapped_key_len.try_into()?]; + + Rv::from(get_pkcs11!(self.client(), C_WrapKey)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + wrapping_key.handle(), + key.handle(), + wrapped_key.as_mut_ptr(), + &mut wrapped_key_len, + )) + .into_result()?; + + Ok(wrapped_key) + } + } } diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index fce0040f..fe932cbb 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -291,6 +291,59 @@ fn get_token_info() { assert_eq!("SoftHSM project", info.get_manufacturer_id()); } +#[test] +#[serial] +fn wrap_key() { + let (pkcs11, slot) = init_pins(); + // set flags + let mut flags = Flags::new(); + let _ = flags.set_rw_session(true).set_serial_session(true); + + // open a session + let session = pkcs11.open_session_no_callback(slot, flags).unwrap(); + + // log in the session + session.login(UserType::User).unwrap(); + + let key_to_be_wrapped_template = vec![ + Attribute::Token(true.into()), + // the key needs to be extractable to be suitable for being wrapped + Attribute::Extractable(true.into()), + ]; + + // generate a secret key that will be wrapped + let key_to_be_wrapped = session + .generate_key(&Mechanism::Des3KeyGen, &key_to_be_wrapped_template) + .unwrap(); + + // pub key template + let pub_key_template = vec![ + Attribute::Token(true.into()), + Attribute::Private(true.into()), + Attribute::PublicExponent(vec![0x01, 0x00, 0x01]), + Attribute::ModulusBits(1024.into()), + // key needs to have "wrap" attribute to wrap other keys + Attribute::Wrap(true.into()), + ]; + + // priv key template + let priv_key_template = vec![Attribute::Token(true.into())]; + + let wrapping_key = session + .generate_key_pair( + &Mechanism::RsaPkcsKeyPairGen, + &pub_key_template, + &priv_key_template, + ) + .unwrap() + .0; + + let wrapped_key = session + .wrap_key(&Mechanism::RsaPkcs, wrapping_key, key_to_be_wrapped) + .unwrap(); + assert_eq!(wrapped_key.len(), 128); +} + #[test] #[serial] fn login_feast() { From 4b432c2f6c6d857f5908a2937b3b822dc91cea05 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Mon, 9 Aug 2021 10:09:16 +0200 Subject: [PATCH 3/7] Add function to unwrap previously wrapped keys Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/functions/key_management.rs | 28 ++++++++++++++++++++++++ cryptoki/tests/basic.rs | 21 ++++++++++++++---- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/cryptoki/src/functions/key_management.rs b/cryptoki/src/functions/key_management.rs index 55005801..38febaf0 100644 --- a/cryptoki/src/functions/key_management.rs +++ b/cryptoki/src/functions/key_management.rs @@ -130,4 +130,32 @@ impl<'a> Session<'a> { Ok(wrapped_key) } } + + /// Unwrap previously wrapped key + pub fn unwrap_key( + &self, + mechanism: &Mechanism, + unwrapping_key: ObjectHandle, + wrapped_key: &[u8], + template: &[Attribute], + ) -> Result { + let mut mechanism: CK_MECHANISM = mechanism.into(); + let mut template: Vec = template.iter().map(|attr| attr.into()).collect(); + let mut handle = 0; + unsafe { + Rv::from(get_pkcs11!(self.client(), C_UnwrapKey)( + self.handle(), + &mut mechanism as CK_MECHANISM_PTR, + unwrapping_key.handle(), + wrapped_key.as_ptr() as *mut u8, + wrapped_key.len().try_into()?, + template.as_mut_ptr(), + template.len().try_into()?, + &mut handle, + )) + .into_result()?; + } + + Ok(ObjectHandle::new(handle)) + } } diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index fe932cbb..de0f1df6 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -293,7 +293,7 @@ fn get_token_info() { #[test] #[serial] -fn wrap_key() { +fn wrap_and_unwrap_key() { let (pkcs11, slot) = init_pins(); // set flags let mut flags = Flags::new(); @@ -329,19 +329,32 @@ fn wrap_key() { // priv key template let priv_key_template = vec![Attribute::Token(true.into())]; - let wrapping_key = session + let (wrapping_key, unwrapping_key) = session .generate_key_pair( &Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &priv_key_template, ) - .unwrap() - .0; + .unwrap(); let wrapped_key = session .wrap_key(&Mechanism::RsaPkcs, wrapping_key, key_to_be_wrapped) .unwrap(); assert_eq!(wrapped_key.len(), 128); + + session + .unwrap_key( + &Mechanism::RsaPkcs, + unwrapping_key, + &wrapped_key, + &[ + Attribute::Token(true.into()), + Attribute::Private(true.into()), + Attribute::Class(ObjectClass::SECRET_KEY), + Attribute::KeyType(KeyType::GENERIC_SECRET), + ], + ) + .unwrap(); } #[test] From 2c054b01ac7f250fe7c614c8158425015efe9f8b Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Mon, 9 Aug 2021 10:42:15 +0200 Subject: [PATCH 4/7] Add DES3 ECB mechanism Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/types/mechanism/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cryptoki/src/types/mechanism/mod.rs b/cryptoki/src/types/mechanism/mod.rs index 534c7100..9f09b6c9 100644 --- a/cryptoki/src/types/mechanism/mod.rs +++ b/cryptoki/src/types/mechanism/mod.rs @@ -48,6 +48,8 @@ impl MechanismType { pub const DES3_KEY_GEN: MechanismType = MechanismType { val: CKM_DES3_KEY_GEN, }; + /// DES3 CBC + pub const DES3_ECB: MechanismType = MechanismType { val: CKM_DES3_ECB }; // ECC /// EC key pair generation mechanism @@ -124,6 +126,7 @@ impl TryFrom for MechanismType { CKM_SHA384 => Ok(MechanismType::SHA384), CKM_SHA512 => Ok(MechanismType::SHA512), CKM_DES3_KEY_GEN => Ok(MechanismType::DES3_KEY_GEN), + CKM_DES3_ECB => Ok(MechanismType::DES3_ECB), CKM_EC_KEY_PAIR_GEN => Ok(MechanismType::ECC_KEY_PAIR_GEN), CKM_EC_EDWARDS_KEY_PAIR_GEN => Ok(MechanismType::ECC_EDWARDS_KEY_PAIR_GEN), CKM_EC_MONTGOMERY_KEY_PAIR_GEN => Ok(MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN), @@ -160,6 +163,8 @@ pub enum Mechanism { // DES /// DES3 Des3KeyGen, + /// DES3 ECB + Des3Ecb, // ECC /// EC key pair generation @@ -202,6 +207,7 @@ impl Mechanism { Mechanism::RsaPkcsOaep(_) => MechanismType::RSA_PKCS_OAEP, Mechanism::Des3KeyGen => MechanismType::DES3_KEY_GEN, + Mechanism::Des3Ecb => MechanismType::DES3_ECB, Mechanism::EccKeyPairGen => MechanismType::ECC_KEY_PAIR_GEN, Mechanism::EccEdwardsKeyPairGen => MechanismType::ECC_EDWARDS_KEY_PAIR_GEN, @@ -254,6 +260,7 @@ impl From<&Mechanism> for CK_MECHANISM { | Mechanism::Sha384 | Mechanism::Sha512 | Mechanism::Des3KeyGen + | Mechanism::Des3Ecb | Mechanism::EccKeyPairGen | Mechanism::EccEdwardsKeyPairGen | Mechanism::EccMontgomeryKeyPairGen From 7c4f6d127d6008576cd6fada8487235722d551ce Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Mon, 9 Aug 2021 10:42:33 +0200 Subject: [PATCH 5/7] Add DES3 key type Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/types/object.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cryptoki/src/types/object.rs b/cryptoki/src/types/object.rs index 21e3602e..00d0dc41 100644 --- a/cryptoki/src/types/object.rs +++ b/cryptoki/src/types/object.rs @@ -530,6 +530,8 @@ impl KeyType { pub const GENERIC_SECRET: KeyType = KeyType { val: CKK_GENERIC_SECRET, }; + /// DES3 secret + pub const DES3: KeyType = KeyType { val: CKK_DES3 }; } impl Deref for KeyType { @@ -556,6 +558,7 @@ impl TryFrom for KeyType { CKK_EC_EDWARDS => Ok(KeyType::EC_EDWARDS), CKK_EC_MONTGOMERY => Ok(KeyType::EC_MONTGOMERY), CKK_GENERIC_SECRET => Ok(KeyType::GENERIC_SECRET), + CKK_DES3 => Ok(KeyType::DES3), other => { error!("Key type {} is not supported.", other); Err(Error::NotSupported) From 7088dec5abf8ede8d02f702edf3d46b379bf2107 Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Mon, 9 Aug 2021 10:43:26 +0200 Subject: [PATCH 6/7] Add test to see if unwrapped DES3 key works Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/tests/basic.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index de0f1df6..cb62b687 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -309,6 +309,7 @@ fn wrap_and_unwrap_key() { Attribute::Token(true.into()), // the key needs to be extractable to be suitable for being wrapped Attribute::Extractable(true.into()), + Attribute::Encrypt(true.into()), ]; // generate a secret key that will be wrapped @@ -316,6 +317,16 @@ fn wrap_and_unwrap_key() { .generate_key(&Mechanism::Des3KeyGen, &key_to_be_wrapped_template) .unwrap(); + // Des3Ecb input length must be a multiple of 8 + // see: PKCS#11 spec Table 10-10, DES-ECB Key And Data Length Constraints + let encrypted_with_original = session + .encrypt( + &Mechanism::Des3Ecb, + key_to_be_wrapped, + &[1, 2, 3, 4, 5, 6, 7, 8], + ) + .unwrap(); + // pub key template let pub_key_template = vec![ Attribute::Token(true.into()), @@ -342,7 +353,7 @@ fn wrap_and_unwrap_key() { .unwrap(); assert_eq!(wrapped_key.len(), 128); - session + let unwrapped_key = session .unwrap_key( &Mechanism::RsaPkcs, unwrapping_key, @@ -350,11 +361,21 @@ fn wrap_and_unwrap_key() { &[ Attribute::Token(true.into()), Attribute::Private(true.into()), + Attribute::Encrypt(true.into()), Attribute::Class(ObjectClass::SECRET_KEY), - Attribute::KeyType(KeyType::GENERIC_SECRET), + Attribute::KeyType(KeyType::DES3), ], ) .unwrap(); + + let encrypted_with_unwrapped = session + .encrypt( + &Mechanism::Des3Ecb, + unwrapped_key, + &[1, 2, 3, 4, 5, 6, 7, 8], + ) + .unwrap(); + assert_eq!(encrypted_with_original, encrypted_with_unwrapped); } #[test] From be8a9214e8292446012d55059ced0af685390ade Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Tue, 17 Aug 2021 10:36:18 +0200 Subject: [PATCH 7/7] Add note about DES3 being deprecated Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/types/mechanism/mod.rs | 4 +++- cryptoki/src/types/object.rs | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cryptoki/src/types/mechanism/mod.rs b/cryptoki/src/types/mechanism/mod.rs index 9f09b6c9..24627d18 100644 --- a/cryptoki/src/types/mechanism/mod.rs +++ b/cryptoki/src/types/mechanism/mod.rs @@ -45,10 +45,12 @@ impl MechanismType { // DES /// DES3 + /// Note that DES3 is deprecated. See https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf section 2, p. 6. pub const DES3_KEY_GEN: MechanismType = MechanismType { val: CKM_DES3_KEY_GEN, }; - /// DES3 CBC + /// DES3 ECB + /// Note that DES3 is deprecated. See https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf section 2, p. 6. pub const DES3_ECB: MechanismType = MechanismType { val: CKM_DES3_ECB }; // ECC diff --git a/cryptoki/src/types/object.rs b/cryptoki/src/types/object.rs index 00d0dc41..15b73ef7 100644 --- a/cryptoki/src/types/object.rs +++ b/cryptoki/src/types/object.rs @@ -531,6 +531,7 @@ impl KeyType { val: CKK_GENERIC_SECRET, }; /// DES3 secret + /// Note that DES3 is deprecated. See https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf section 2, p. 6. pub const DES3: KeyType = KeyType { val: CKK_DES3 }; }