diff --git a/.github/actions/ci_script/action.yml b/.github/actions/ci_script/action.yml index 679471bf..88bb7297 100644 --- a/.github/actions/ci_script/action.yml +++ b/.github/actions/ci_script/action.yml @@ -30,7 +30,7 @@ runs: - name: Test script env: - PKCS11_SOFTHSM2_MODULE: /usr/lib/softhsm/libsofthsm2.so + TEST_PKCS11_MODULE: /usr/lib/softhsm/libsofthsm2.so SOFTHSM2_CONF: /tmp/softhsm2.conf run: ./ci.sh shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5e2e4a56..3448729d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,24 @@ jobs: - name: "Installs SoftHSM and execute tests" uses: ./.github/actions/ci_script + tests-kryoptic: + name: Run tests against Kryoptic + runs-on: ubuntu-latest + container: fedora:rawhide + steps: + - name: Install dependencies + run: dnf -y install git cargo clang-devel kryoptic + - uses: actions/checkout@v2 + - name: Test script + env: + KRYOPTIC_CONF: /tmp/kryoptic.sql + TEST_PKCS11_MODULE: /usr/lib64/pkcs11/libkryoptic_pkcs11.so + run: | + RUST_BACKTRACE=1 cargo build && + RUST_BACKTRACE=1 cargo build --all-features && + RUST_BACKTRACE=1 cargo test + + build-msrv: name: MSRV - Execute CI script runs-on: ubuntu-latest diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b6da54e9..64c5187d 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -62,7 +62,7 @@ jobs: - name: Test script env: - PKCS11_SOFTHSM2_MODULE: /usr/lib/softhsm/libsofthsm2.so + TEST_PKCS11_MODULE: /usr/lib/softhsm/libsofthsm2.so SOFTHSM2_CONF: /tmp/softhsm2.conf run: | rm Cargo.lock diff --git a/cryptoki-sys/build.rs b/cryptoki-sys/build.rs index 49148552..582a4b31 100644 --- a/cryptoki-sys/build.rs +++ b/cryptoki-sys/build.rs @@ -91,8 +91,12 @@ mod generate { .dynamic_library_name("Pkcs11") // The PKCS11 library works in a slightly different way to most shared libraries. We have // to call `C_GetFunctionList`, which returns a list of pointers to the _actual_ library - // functions. This is the only function we need to create a binding for. + // functions (in PKCS #11 before 3.0). The PKCS #11 3.0 introduces the new functions + // `C_GetInterface` and `C_GetInterfaceList` to request the hew functions from 3.0 API. + // These are the only function we need to create a binding for. .allowlist_function("C_GetFunctionList") + .allowlist_function("C_GetInterfaceList") + .allowlist_function("C_GetInterface") // This is needed because no types will be generated if `allowlist_function` is used. // Unsure if this is a bug. .allowlist_type("*") diff --git a/cryptoki/README.md b/cryptoki/README.md index 0e1c136d..77f998d5 100644 --- a/cryptoki/README.md +++ b/cryptoki/README.md @@ -22,7 +22,7 @@ You can follow the installation steps directly in the repository's README but he sudo apt install libsofthsm2 mkdir /tmp/tokens echo "directories.tokendir = /tmp/tokens" > /tmp/softhsm2.conf -export PKCS11_SOFTHSM2_MODULE="/usr/lib/softhsm/libsofthsm2.so" +export TEST_PKCS11_MODULE="/usr/lib/softhsm/libsofthsm2.so" export SOFTHSM2_CONF="/tmp/softhsm2.conf" cargo run --example generate_key_pair ``` @@ -43,7 +43,7 @@ use std::env; // initialize a new Pkcs11 object using the module from the env variable let pkcs11 = Pkcs11::new( - env::var("PKCS11_SOFTHSM2_MODULE") + env::var("TEST_PKCS11_MODULE") .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), )?; diff --git a/cryptoki/examples/generate_key_pair.rs b/cryptoki/examples/generate_key_pair.rs index 6c0b785e..87d9bf49 100644 --- a/cryptoki/examples/generate_key_pair.rs +++ b/cryptoki/examples/generate_key_pair.rs @@ -15,7 +15,7 @@ pub static SO_PIN: &str = "abcdef"; fn main() -> testresult::TestResult { // initialize a new Pkcs11 object using the module from the env variable let pkcs11 = Pkcs11::new( - env::var("PKCS11_SOFTHSM2_MODULE") + env::var("TEST_PKCS11_MODULE") .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), )?; diff --git a/cryptoki/src/context/general_purpose.rs b/cryptoki/src/context/general_purpose.rs index a4114371..918f85ad 100644 --- a/cryptoki/src/context/general_purpose.rs +++ b/cryptoki/src/context/general_purpose.rs @@ -44,6 +44,17 @@ macro_rules! check_fn { }}; } +macro_rules! check_30_fn { + ($pkcs11:expr, $func_name:ident) => {{ + let func = paste! { $pkcs11 + .impl_ + .function_list_30 + .map(|f| f.[]) + }; + func.is_some() + }}; +} + #[allow(missing_docs)] #[derive(Debug, Copy, Clone)] /// Enumeration of all functions defined by the PKCS11 spec @@ -116,6 +127,31 @@ pub enum Function { GetFunctionStatus, CancelFunction, WaitForSlotEvent, + /* PKCS #11 3.0 */ + GetInterfaceList, + GetInterface, + LoginUser, + SessionCancel, + MessageEncryptInit, + EncryptMessage, + EncryptMessageBegin, + EncryptMessageNext, + MessageEncryptFinal, + MessageDecryptInit, + DecryptMessage, + DecryptMessageBegin, + DecryptMessageNext, + MessageDecryptFinal, + MessageSignInit, + SignMessage, + SignMessageBegin, + SignMessageNext, + MessageSignFinal, + MessageVerifyInit, + VerifyMessage, + VerifyMessageBegin, + VerifyMessageNext, + MessageVerifyFinal, } impl Display for Function { @@ -195,5 +231,30 @@ pub(super) fn is_fn_supported(ctx: &Pkcs11, function: Function) -> bool { Function::GetFunctionStatus => check_fn!(ctx, GetFunctionStatus), Function::CancelFunction => check_fn!(ctx, CancelFunction), Function::WaitForSlotEvent => check_fn!(ctx, WaitForSlotEvent), + /* PKCS #11 3.0 */ + Function::GetInterfaceList => check_30_fn!(ctx, GetInterfaceList), + Function::GetInterface => check_30_fn!(ctx, GetInterface), + Function::LoginUser => check_30_fn!(ctx, LoginUser), + Function::SessionCancel => check_30_fn!(ctx, SessionCancel), + Function::MessageEncryptInit => check_30_fn!(ctx, MessageEncryptInit), + Function::EncryptMessage => check_30_fn!(ctx, EncryptMessage), + Function::EncryptMessageBegin => check_30_fn!(ctx, EncryptMessageBegin), + Function::EncryptMessageNext => check_30_fn!(ctx, EncryptMessageNext), + Function::MessageEncryptFinal => check_30_fn!(ctx, MessageEncryptFinal), + Function::MessageDecryptInit => check_30_fn!(ctx, MessageDecryptInit), + Function::DecryptMessage => check_30_fn!(ctx, DecryptMessage), + Function::DecryptMessageBegin => check_30_fn!(ctx, DecryptMessageBegin), + Function::DecryptMessageNext => check_30_fn!(ctx, DecryptMessageNext), + Function::MessageDecryptFinal => check_30_fn!(ctx, MessageDecryptFinal), + Function::MessageSignInit => check_30_fn!(ctx, MessageSignInit), + Function::SignMessage => check_30_fn!(ctx, SignMessage), + Function::SignMessageBegin => check_30_fn!(ctx, SignMessageBegin), + Function::SignMessageNext => check_30_fn!(ctx, SignMessageNext), + Function::MessageSignFinal => check_30_fn!(ctx, MessageSignFinal), + Function::MessageVerifyInit => check_30_fn!(ctx, MessageVerifyInit), + Function::VerifyMessage => check_30_fn!(ctx, VerifyMessage), + Function::VerifyMessageBegin => check_30_fn!(ctx, VerifyMessageBegin), + Function::VerifyMessageNext => check_30_fn!(ctx, VerifyMessageNext), + Function::MessageVerifyFinal => check_30_fn!(ctx, MessageVerifyFinal), } } diff --git a/cryptoki/src/context/mod.rs b/cryptoki/src/context/mod.rs index 60f4681a..9527c364 100644 --- a/cryptoki/src/context/mod.rs +++ b/cryptoki/src/context/mod.rs @@ -44,12 +44,14 @@ pub(crate) struct Pkcs11Impl { // valid. _pkcs11_lib: cryptoki_sys::Pkcs11, pub(crate) function_list: cryptoki_sys::CK_FUNCTION_LIST, + pub(crate) function_list_30: Option, } impl fmt::Debug for Pkcs11Impl { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Pkcs11Impl") .field("function_list", &self.function_list) + .field("function_list_30", &self.function_list_30) .finish() } } @@ -111,6 +113,40 @@ impl Pkcs11 { } unsafe fn _new(pkcs11_lib: cryptoki_sys::Pkcs11) -> Result { + /* First try the 3.0 API to get default interface. It might have some more functions than + * the 2.4 API */ + let mut interface = mem::MaybeUninit::uninit(); + if pkcs11_lib.C_GetInterface.is_ok() { + Rv::from(pkcs11_lib.C_GetInterface( + ptr::null_mut(), + ptr::null_mut(), + interface.as_mut_ptr(), + 0, + )) + .into_result(Function::GetInterface)?; + if !interface.as_ptr().is_null() { + let ifce_ptr: *mut cryptoki_sys::CK_INTERFACE = *interface.as_ptr(); + let ifce: cryptoki_sys::CK_INTERFACE = *ifce_ptr; + + let list_ptr: *mut cryptoki_sys::CK_FUNCTION_LIST = + ifce.pFunctionList as *mut cryptoki_sys::CK_FUNCTION_LIST; + let list: cryptoki_sys::CK_FUNCTION_LIST = *list_ptr; + if list.version.major >= 3 { + let list30_ptr: *mut cryptoki_sys::CK_FUNCTION_LIST_3_0 = + ifce.pFunctionList as *mut cryptoki_sys::CK_FUNCTION_LIST_3_0; + return Ok(Pkcs11 { + impl_: Arc::new(Pkcs11Impl { + _pkcs11_lib: pkcs11_lib, + function_list: *list_ptr, /* the function list aliases */ + function_list_30: Some(*list30_ptr), + }), + initialized: Arc::new(RwLock::new(false)), + }); + } + /* fall back to the 2.* API */ + } + } + let mut list = mem::MaybeUninit::uninit(); Rv::from(pkcs11_lib.C_GetFunctionList(list.as_mut_ptr())) @@ -122,6 +158,7 @@ impl Pkcs11 { impl_: Arc::new(Pkcs11Impl { _pkcs11_lib: pkcs11_lib, function_list: *list_ptr, + function_list_30: None, }), initialized: Arc::new(RwLock::new(false)), }) diff --git a/cryptoki/src/context/session_management.rs b/cryptoki/src/context/session_management.rs index ee393039..382c45da 100644 --- a/cryptoki/src/context/session_management.rs +++ b/cryptoki/src/context/session_management.rs @@ -50,7 +50,7 @@ impl Pkcs11 { /// use cryptoki::context::Pkcs11; /// /// let mut client = Pkcs11::new( - /// std::env::var("PKCS11_SOFTHSM2_MODULE") + /// std::env::var("TEST_PKCS11_MODULE") /// .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), /// )?; /// client.initialize(cryptoki::context::CInitializeArgs::OsThreads)?; diff --git a/cryptoki/src/object.rs b/cryptoki/src/object.rs index abdefd0a..9f159236 100644 --- a/cryptoki/src/object.rs +++ b/cryptoki/src/object.rs @@ -1378,6 +1378,8 @@ pub enum AttributeInfo { Sensitive, /// The attribute is available to get from the object and has the specified size in bytes. Available(usize), + /// The attribute is not available. + Unavailable, } #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/cryptoki/src/session/object_management.rs b/cryptoki/src/session/object_management.rs index 4c676ded..77de95d4 100644 --- a/cryptoki/src/session/object_management.rs +++ b/cryptoki/src/session/object_management.rs @@ -39,7 +39,7 @@ const MAX_OBJECT_COUNT: NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(10) /// /// # fn main() -> testresult::TestResult { /// # let pkcs11 = Pkcs11::new( -/// # env::var("PKCS11_SOFTHSM2_MODULE") +/// # env::var("TEST_PKCS11_MODULE") /// # .unwrap_or_else(|_| "/usr/local/lib/libsofthsm2.so".to_string()), /// # )?; /// # @@ -282,7 +282,7 @@ impl Session { /// # use cryptoki::object::{Attribute, AttributeType, CertificateType, ObjectClass, ObjectHandle}; /// # /// # let mut client = Pkcs11::new( - /// # std::env::var("PKCS11_SOFTHSM2_MODULE") + /// # std::env::var("TEST_PKCS11_MODULE") /// # .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), /// # )?; /// # client.initialize(cryptoki::context::CInitializeArgs::OsThreads)?; @@ -401,7 +401,7 @@ impl Session { /// use std::env; /// /// let mut pkcs11 = Pkcs11::new( - /// env::var("PKCS11_SOFTHSM2_MODULE") + /// env::var("TEST_PKCS11_MODULE") /// .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), /// ) /// .unwrap(); @@ -454,7 +454,11 @@ impl Session { )) } { Rv::Ok => { - results.push(AttributeInfo::Available(template[0].ulValueLen.try_into()?)) + if template[0].ulValueLen == CK_UNAVAILABLE_INFORMATION { + results.push(AttributeInfo::Unavailable) + } else { + results.push(AttributeInfo::Available(template[0].ulValueLen.try_into()?)) + } } Rv::Error(RvError::AttributeSensitive) => results.push(AttributeInfo::Sensitive), Rv::Error(RvError::AttributeTypeInvalid) => { diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index c32b14c7..6aa7b31a 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 mod common; -use crate::common::{get_pkcs11, SO_PIN, USER_PIN}; +use crate::common::{get_pkcs11, is_softhsm, SO_PIN, USER_PIN}; use common::init_pins; use cryptoki::context::Function; use cryptoki::error::{Error, RvError}; @@ -46,10 +46,11 @@ fn sign_verify() -> TestResult { Attribute::Private(false), Attribute::PublicExponent(public_exponent), Attribute::ModulusBits(modulus_bits.into()), + Attribute::Verify(true), ]; // priv key template - let priv_key_template = vec![Attribute::Token(true)]; + let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)]; // generate a key pair let (public, private) = @@ -93,7 +94,7 @@ fn sign_verify_eddsa() -> TestResult { ]), ]; - let priv_key_template = vec![Attribute::Token(true)]; + let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)]; let (public, private) = session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?; @@ -136,7 +137,7 @@ fn sign_verify_eddsa_with_ed25519_schemes() -> TestResult { ]), ]; - let priv_key_template = vec![Attribute::Token(true)]; + let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)]; let (public, private) = session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?; @@ -186,7 +187,7 @@ fn sign_verify_eddsa_with_ed448_schemes() -> TestResult { ]), ]; - let priv_key_template = vec![Attribute::Token(true)]; + let priv_key_template = vec![Attribute::Token(true), Attribute::Sign(true)]; let (public, private) = session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?; @@ -267,6 +268,11 @@ fn encrypt_decrypt() -> TestResult { #[test] #[serial] fn derive_key() -> TestResult { + /* FIXME: This is now broken in Kryoptic: https://github.com/latchset/kryoptic/issues/184 */ + if !is_softhsm() { + /* return Ignore(); */ + return Ok(()); + } let (pkcs11, slot) = init_pins(); // open a session @@ -410,7 +416,7 @@ fn import_export() -> TestResult { fn get_token_info() -> TestResult { let (pkcs11, slot) = init_pins(); let info = pkcs11.get_token_info(slot)?; - assert_eq!("SoftHSM project", info.manufacturer_id()); + assert_ne!("", info.manufacturer_id()); Ok(()) } @@ -436,12 +442,13 @@ fn session_find_objects() -> testresult::TestResult { Attribute::Token(true), Attribute::Encrypt(true), Attribute::Label(format!("key_{}", i).as_bytes().to_vec()), + Attribute::ValueLen(32.into()), Attribute::Id("12345678".as_bytes().to_vec()), // reusing the same CKA_ID ]; // generate a secret key let _key = session - .generate_key(&Mechanism::Des3KeyGen, &key_template) + .generate_key(&Mechanism::AesKeyGen, &key_template) .unwrap(); }); @@ -450,7 +457,7 @@ fn session_find_objects() -> testresult::TestResult { Attribute::Token(true), Attribute::Id("12345678".as_bytes().to_vec()), Attribute::Class(ObjectClass::SECRET_KEY), - Attribute::KeyType(KeyType::DES3), + Attribute::KeyType(KeyType::AES), ]; let mut found_keys = session.find_objects(&key_search_template)?; @@ -485,12 +492,13 @@ fn session_objecthandle_iterator() -> testresult::TestResult { let key_template = vec![ Attribute::Token(true), Attribute::Encrypt(true), + Attribute::ValueLen(32.into()), Attribute::Label(format!("key_{}", i).as_bytes().to_vec()), Attribute::Id("12345678".as_bytes().to_vec()), // reusing the same CKA_ID ]; // generate a secret key - session.generate_key(&Mechanism::Des3KeyGen, &key_template)?; + session.generate_key(&Mechanism::AesKeyGen, &key_template)?; } // retrieve these keys using this template @@ -498,7 +506,7 @@ fn session_objecthandle_iterator() -> testresult::TestResult { Attribute::Token(true), Attribute::Id("12345678".as_bytes().to_vec()), Attribute::Class(ObjectClass::SECRET_KEY), - Attribute::KeyType(KeyType::DES3), + Attribute::KeyType(KeyType::AES), ]; // test iter_objects_with_cache_size() @@ -563,6 +571,12 @@ fn session_objecthandle_iterator() -> testresult::TestResult { #[test] #[serial] fn wrap_and_unwrap_key() { + /* FIXME: This is now broken in Kryoptic: https://github.com/latchset/kryoptic/issues/184 */ + if !is_softhsm() { + /* return Ignore(); */ + return; + } + let (pkcs11, slot) = init_pins(); // open a session let session = pkcs11.open_rw_session(slot).unwrap(); @@ -574,6 +588,7 @@ fn wrap_and_unwrap_key() { let key_to_be_wrapped_template = vec![ Attribute::Token(true), + Attribute::ValueLen(32.into()), // the key needs to be extractable to be suitable for being wrapped Attribute::Extractable(true), Attribute::Encrypt(true), @@ -581,16 +596,15 @@ fn wrap_and_unwrap_key() { // generate a secret key that will be wrapped let key_to_be_wrapped = session - .generate_key(&Mechanism::Des3KeyGen, &key_to_be_wrapped_template) + .generate_key(&Mechanism::AesKeyGen, &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 + // AesEcb input length must be a multiple of 16 let encrypted_with_original = session .encrypt( - &Mechanism::Des3Ecb, + &Mechanism::AesEcb, key_to_be_wrapped, - &[1, 2, 3, 4, 5, 6, 7, 8], + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], ) .unwrap(); @@ -630,16 +644,16 @@ fn wrap_and_unwrap_key() { Attribute::Private(true), Attribute::Encrypt(true), Attribute::Class(ObjectClass::SECRET_KEY), - Attribute::KeyType(KeyType::DES3), + Attribute::KeyType(KeyType::AES), ], ) .unwrap(); let encrypted_with_unwrapped = session .encrypt( - &Mechanism::Des3Ecb, + &Mechanism::AesEcb, unwrapped_key, - &[1, 2, 3, 4, 5, 6, 7, 8], + &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], ) .unwrap(); assert_eq!(encrypted_with_original, encrypted_with_unwrapped); @@ -695,9 +709,14 @@ fn get_info_test() -> TestResult { let (pkcs11, _) = init_pins(); let info = pkcs11.get_library_info()?; - assert_eq!(info.cryptoki_version().major(), 2); - assert_eq!(info.cryptoki_version().minor(), 40); - assert_eq!(info.manufacturer_id(), String::from("SoftHSM")); + assert_ne!("", info.manufacturer_id()); + if is_softhsm() { + assert_eq!(info.cryptoki_version().major(), 2); + assert_eq!(info.cryptoki_version().minor(), 40); + } else { + assert_eq!(info.cryptoki_version().major(), 3); + assert_eq!(info.cryptoki_version().minor(), 0); + } Ok(()) } @@ -709,7 +728,7 @@ fn get_slot_info_test() -> TestResult { assert!(slot_info.token_present()); assert!(!slot_info.hardware_slot()); assert!(!slot_info.removable_device()); - assert_eq!(slot_info.manufacturer_id(), String::from("SoftHSM project")); + assert_ne!("", slot_info.manufacturer_id()); Ok(()) } @@ -928,6 +947,18 @@ fn is_fn_supported_test() { pkcs11.is_fn_supported(Function::DigestFinal), "C_DigestFinal function reports as not supported" ); + if is_softhsm() { + // the SoftHSM does not have PKCS#11 3.0 API so this function is not present + assert!( + !pkcs11.is_fn_supported(Function::MessageEncryptInit), + "C_MessageEncryptInit function reports supported for SoftHSM" + ); + } else { + assert!( + pkcs11.is_fn_supported(Function::MessageEncryptInit), + "C_MessageEncryptInit function reports as not supported" + ); + } } #[test] @@ -988,6 +1019,11 @@ fn test_clone_initialize() { #[test] #[serial] fn aes_key_attributes_test() -> TestResult { + /* FIXME: This is now broken in Kryoptic: https://github.com/latchset/kryoptic/issues/182 */ + if !is_softhsm() { + /* return Ignore(); */ + return Ok(()); + } let (pkcs11, slot) = init_pins(); // open a session @@ -1283,9 +1319,13 @@ fn gcm_param_graceful_failure() -> TestResult { #[test] #[serial] -// Currently empty AAD crashes SoftHSM, see: https://github.com/opendnssec/SoftHSMv2/issues/605 -#[ignore] fn aes_gcm_no_aad() -> TestResult { + // Currently empty AAD crashes SoftHSM, see: https://github.com/opendnssec/SoftHSMv2/issues/605 + if is_softhsm() { + /* return Ignore(); */ + return Ok(()); + } + // Encrypt two blocks of zeros with AES-128-GCM let key = vec![0; 16]; let mut iv = [0; 12]; @@ -1353,9 +1393,16 @@ fn rsa_pkcs_oaep_empty() -> TestResult { let session = pkcs11.open_rw_session(slot)?; session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?; - let pub_key_template = [Attribute::ModulusBits(2048.into())]; - let (pubkey, privkey) = - session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?; + let pub_key_template = [ + Attribute::ModulusBits(2048.into()), + Attribute::Encrypt(true), + ]; + let priv_key_template = [Attribute::Decrypt(true)]; + let (pubkey, privkey) = session.generate_key_pair( + &Mechanism::RsaPkcsKeyPairGen, + &pub_key_template, + &priv_key_template, + )?; let oaep = PkcsOaepParams::new( MechanismType::SHA1, PkcsMgfType::MGF1_SHA1, @@ -1374,15 +1421,27 @@ fn rsa_pkcs_oaep_empty() -> TestResult { #[test] #[serial] -#[ignore] // it's not clear why the test with data specified fails fn rsa_pkcs_oaep_with_data() -> TestResult { + /* SoftHSM does not support additional OAEP Source */ + if is_softhsm() { + /* return Ignore(); */ + return Ok(()); + } + let (pkcs11, slot) = init_pins(); let session = pkcs11.open_rw_session(slot)?; session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?; - let pub_key_template = [Attribute::ModulusBits(2048.into())]; - let (pubkey, privkey) = - session.generate_key_pair(&Mechanism::RsaPkcsKeyPairGen, &pub_key_template, &[])?; + let pub_key_template = [ + Attribute::ModulusBits(2048.into()), + Attribute::Encrypt(true), + ]; + let priv_key_template = vec![Attribute::Decrypt(true)]; + let (pubkey, privkey) = session.generate_key_pair( + &Mechanism::RsaPkcsKeyPairGen, + &pub_key_template, + &priv_key_template, + )?; let oaep = PkcsOaepParams::new( MechanismType::SHA1, PkcsMgfType::MGF1_SHA1, @@ -1401,11 +1460,16 @@ fn rsa_pkcs_oaep_with_data() -> TestResult { #[test] #[serial] fn get_slot_event() -> TestResult { - // Not implemented in SoftHSMv2 - // https://github.com/opendnssec/SoftHSMv2/issues/370 let (pkcs11, _slot) = init_pins(); - let event = pkcs11.get_slot_event()?; - assert_eq!(None, event); + if is_softhsm() { + // Not implemented in SoftHSMv2 + // https://github.com/opendnssec/SoftHSMv2/issues/370 + let event = pkcs11.get_slot_event()?; + assert_eq!(None, event); + } else { + // Not implemented in Kryoptic + pkcs11.get_slot_event().unwrap_err(); + } Ok(()) } @@ -1523,6 +1587,7 @@ fn sign_verify_sha1_hmac() -> TestResult { Attribute::Private(true), Attribute::Sensitive(true), Attribute::Sign(true), + Attribute::Verify(true), Attribute::KeyType(KeyType::GENERIC_SECRET), Attribute::Class(ObjectClass::SECRET_KEY), Attribute::ValueLen(256.into()), @@ -1552,6 +1617,7 @@ fn sign_verify_sha224_hmac() -> TestResult { Attribute::Private(true), Attribute::Sensitive(true), Attribute::Sign(true), + Attribute::Verify(true), Attribute::KeyType(KeyType::GENERIC_SECRET), Attribute::Class(ObjectClass::SECRET_KEY), Attribute::ValueLen(256.into()), @@ -1581,6 +1647,7 @@ fn sign_verify_sha256_hmac() -> TestResult { Attribute::Private(true), Attribute::Sensitive(true), Attribute::Sign(true), + Attribute::Verify(true), Attribute::KeyType(KeyType::GENERIC_SECRET), Attribute::Class(ObjectClass::SECRET_KEY), Attribute::ValueLen(256.into()), @@ -1610,6 +1677,7 @@ fn sign_verify_sha384_hmac() -> TestResult { Attribute::Private(true), Attribute::Sensitive(true), Attribute::Sign(true), + Attribute::Verify(true), Attribute::KeyType(KeyType::GENERIC_SECRET), Attribute::Class(ObjectClass::SECRET_KEY), Attribute::ValueLen(256.into()), @@ -1639,6 +1707,7 @@ fn sign_verify_sha512_hmac() -> TestResult { Attribute::Private(true), Attribute::Sensitive(true), Attribute::Sign(true), + Attribute::Verify(true), Attribute::KeyType(KeyType::GENERIC_SECRET), Attribute::Class(ObjectClass::SECRET_KEY), Attribute::ValueLen(256.into()), diff --git a/cryptoki/tests/common.rs b/cryptoki/tests/common.rs index 95e4202d..65be5c60 100644 --- a/cryptoki/tests/common.rs +++ b/cryptoki/tests/common.rs @@ -11,12 +11,17 @@ pub static USER_PIN: &str = "fedcba"; // The default SO pin pub static SO_PIN: &str = "abcdef"; +fn get_pkcs11_path() -> String { + env::var("TEST_PKCS11_MODULE") + .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()) +} + +pub fn is_softhsm() -> bool { + get_pkcs11_path().contains("softhsm") +} + pub fn get_pkcs11() -> Pkcs11 { - Pkcs11::new( - env::var("PKCS11_SOFTHSM2_MODULE") - .unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string()), - ) - .unwrap() + Pkcs11::new(get_pkcs11_path()).unwrap() } pub fn init_pins() -> (Pkcs11, Slot) {