Skip to content

Commit

Permalink
Merge pull request #38 from wiktor-k/add-wrap
Browse files Browse the repository at this point in the history
Add secret key generation and key wrapping functions
  • Loading branch information
ionut-arm authored Sep 3, 2021
2 parents 10b35c3 + be8a921 commit 5194254
Show file tree
Hide file tree
Showing 4 changed files with 202 additions and 0 deletions.
88 changes: 88 additions & 0 deletions cryptoki/src/functions/key_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ObjectHandle> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut template: Vec<CK_ATTRIBUTE> = 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,
Expand Down Expand Up @@ -70,4 +93,69 @@ impl<'a> Session<'a> {

Ok(ObjectHandle::new(handle))
}

/// Wrap key
pub fn wrap_key(
&self,
mechanism: &Mechanism,
wrapping_key: ObjectHandle,
key: ObjectHandle,
) -> Result<Vec<u8>> {
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)
}
}

/// Unwrap previously wrapped key
pub fn unwrap_key(
&self,
mechanism: &Mechanism,
unwrapping_key: ObjectHandle,
wrapped_key: &[u8],
template: &[Attribute],
) -> Result<ObjectHandle> {
let mut mechanism: CK_MECHANISM = mechanism.into();
let mut template: Vec<CK_ATTRIBUTE> = 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))
}
}
23 changes: 23 additions & 0 deletions cryptoki/src/types/mechanism/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ impl MechanismType {
val: CKM_RSA_PKCS_OAEP,
};

// 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 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
/// EC key pair generation mechanism
pub const ECC_KEY_PAIR_GEN: MechanismType = MechanismType {
Expand Down Expand Up @@ -117,6 +127,8 @@ impl TryFrom<CK_MECHANISM_TYPE> 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_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),
Expand Down Expand Up @@ -150,6 +162,12 @@ pub enum Mechanism {
/// defined in PKCS #1
RsaPkcsOaep(rsa::PkcsOaepParams),

// DES
/// DES3
Des3KeyGen,
/// DES3 ECB
Des3Ecb,

// ECC
/// EC key pair generation
EccKeyPairGen,
Expand Down Expand Up @@ -190,6 +208,9 @@ impl Mechanism {
Mechanism::RsaPkcsPss(_) => MechanismType::RSA_PKCS_PSS,
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,
Mechanism::EccMontgomeryKeyPairGen => MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN,
Expand Down Expand Up @@ -240,6 +261,8 @@ impl From<&Mechanism> for CK_MECHANISM {
| Mechanism::Sha256
| Mechanism::Sha384
| Mechanism::Sha512
| Mechanism::Des3KeyGen
| Mechanism::Des3Ecb
| Mechanism::EccKeyPairGen
| Mechanism::EccEdwardsKeyPairGen
| Mechanism::EccMontgomeryKeyPairGen
Expand Down
4 changes: 4 additions & 0 deletions cryptoki/src/types/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ impl KeyType {
pub const GENERIC_SECRET: KeyType = 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 };
}

impl Deref for KeyType {
Expand All @@ -556,6 +559,7 @@ impl TryFrom<CK_KEY_TYPE> 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)
Expand Down
87 changes: 87 additions & 0 deletions cryptoki/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,93 @@ fn get_token_info() {
assert_eq!("SoftHSM project", info.get_manufacturer_id());
}

#[test]
#[serial]
fn wrap_and_unwrap_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()),
Attribute::Encrypt(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();

// 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()),
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, unwrapping_key) = session
.generate_key_pair(
&Mechanism::RsaPkcsKeyPairGen,
&pub_key_template,
&priv_key_template,
)
.unwrap();

let wrapped_key = session
.wrap_key(&Mechanism::RsaPkcs, wrapping_key, key_to_be_wrapped)
.unwrap();
assert_eq!(wrapped_key.len(), 128);

let unwrapped_key = session
.unwrap_key(
&Mechanism::RsaPkcs,
unwrapping_key,
&wrapped_key,
&[
Attribute::Token(true.into()),
Attribute::Private(true.into()),
Attribute::Encrypt(true.into()),
Attribute::Class(ObjectClass::SECRET_KEY),
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]
#[serial]
fn login_feast() {
Expand Down

0 comments on commit 5194254

Please sign in to comment.