From 657d64cec38709a767c31958e2bd7b0ed2d3aa3b Mon Sep 17 00:00:00 2001 From: Wiktor Kwapisiewicz Date: Mon, 8 May 2023 10:43:17 +0200 Subject: [PATCH] Add EdDSA mechanism Co-authored-by: legounix Signed-off-by: Wiktor Kwapisiewicz --- cryptoki/src/mechanism/mod.rs | 18 ++++++++++++++++ cryptoki/tests/basic.rs | 39 +++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/cryptoki/src/mechanism/mod.rs b/cryptoki/src/mechanism/mod.rs index f00d0ef4..ab8af4bb 100644 --- a/cryptoki/src/mechanism/mod.rs +++ b/cryptoki/src/mechanism/mod.rs @@ -152,6 +152,13 @@ impl MechanismType { val: CKM_EC_MONTGOMERY_KEY_PAIR_GEN, }; + /// EDDSA mechanism + /// + /// Note: EdDSA is not part of the PKCS#11 v2.40 standard and as + /// such may not be understood by the backend. It is included here + /// because some vendor implementations support it through the + /// v2.40 interface. + pub const EDDSA: MechanismType = MechanismType { val: CKM_EDDSA }; /// ECDH key derivation mechanism pub const ECDH1_DERIVE: MechanismType = MechanismType { val: CKM_ECDH1_DERIVE, @@ -587,6 +594,7 @@ impl MechanismType { CKM_EC_MONTGOMERY_KEY_PAIR_GEN => { String::from(stringify!(CKM_EC_MONTGOMERY_KEY_PAIR_GEN)) } + CKM_EDDSA => String::from(stringify!(CKM_EDDSA)), _ => format!("unknown {mech:08x}"), } } @@ -631,6 +639,7 @@ impl TryFrom for MechanismType { 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), + CKM_EDDSA => Ok(MechanismType::EDDSA), CKM_ECDH1_DERIVE => Ok(MechanismType::ECDH1_DERIVE), CKM_ECDSA => Ok(MechanismType::ECDSA), CKM_SHA256_RSA_PKCS => Ok(MechanismType::SHA256_RSA_PKCS), @@ -761,6 +770,13 @@ pub enum Mechanism<'a> { EcdsaSha384, /// ECDSA with SHA-512 mechanism EcdsaSha512, + /// EDDSA mechanism + /// + /// Note: EdDSA is not part of the PKCS#11 v2.40 standard and as + /// such may not be understood by the backend. It is included here + /// because some vendor implementations support it through the + /// v2.40 interface. + Eddsa, // SHA-n /// SHA-1 mechanism @@ -827,6 +843,7 @@ impl Mechanism<'_> { Mechanism::EccKeyPairGen => MechanismType::ECC_KEY_PAIR_GEN, Mechanism::EccEdwardsKeyPairGen => MechanismType::ECC_EDWARDS_KEY_PAIR_GEN, Mechanism::EccMontgomeryKeyPairGen => MechanismType::ECC_MONTGOMERY_KEY_PAIR_GEN, + Mechanism::Eddsa => MechanismType::EDDSA, Mechanism::Ecdh1Derive(_) => MechanismType::ECDH1_DERIVE, Mechanism::Ecdsa => MechanismType::ECDSA, Mechanism::EcdsaSha1 => MechanismType::ECDSA_SHA1, @@ -895,6 +912,7 @@ impl From<&Mechanism<'_>> for CK_MECHANISM { | Mechanism::EccKeyPairGen | Mechanism::EccEdwardsKeyPairGen | Mechanism::EccMontgomeryKeyPairGen + | Mechanism::Eddsa | Mechanism::Ecdsa | Mechanism::EcdsaSha1 | Mechanism::EcdsaSha224 diff --git a/cryptoki/tests/basic.rs b/cryptoki/tests/basic.rs index 89789e88..e0340636 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -63,6 +63,45 @@ fn sign_verify() -> TestResult { Ok(()) } +#[test] +#[serial] +fn sign_verify_ed25519() -> TestResult { + let (pkcs11, slot) = init_pins(); + + let session = pkcs11.open_rw_session(slot)?; + + session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?; + + let mechanism = Mechanism::EccEdwardsKeyPairGen; + + let pub_key_template = vec![ + Attribute::Token(true), + Attribute::Private(false), + Attribute::Verify(true), + // Ed25519 OID + // See: https://github.com/opendnssec/SoftHSMv2/blob/ac70dc398b236e4522101930e790008936489e2d/src/lib/test/SignVerifyTests.cpp#L173 + Attribute::EcParams(vec![ + 0x13, 0x0c, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x32, 0x35, 0x35, 0x31, 0x39, + ]), + ]; + + let priv_key_template = vec![Attribute::Token(true)]; + + let (public, private) = + session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?; + + let data = [0xFF, 0x55, 0xDD]; + + let signature = session.sign(&Mechanism::Eddsa, private, &data)?; + + session.verify(&Mechanism::Eddsa, public, &data, &signature)?; + + session.destroy_object(public)?; + session.destroy_object(private)?; + + Ok(()) +} + #[test] #[serial] fn encrypt_decrypt() -> TestResult {