From 8d4fca9924eb0e26976af419ef63d945cc63e3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mete=20Can=20Eri=C5=9F?= Date: Sat, 18 Jan 2025 14:19:12 +0300 Subject: [PATCH 1/2] feat: revise EdDSA mechanism to support optional params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This revises the `Mechanism::Eddsa` struct to receive a `EddsaParams` struct as an optional argument. Signed-off-by: Mete Can Eriş --- cryptoki/src/mechanism/eddsa.rs | 61 +++++++++++++++++++++++++++++++++ cryptoki/src/mechanism/mod.rs | 24 +++++++++---- cryptoki/tests/basic.rs | 53 ++++++++++++++++++++++++++-- 3 files changed, 130 insertions(+), 8 deletions(-) create mode 100644 cryptoki/src/mechanism/eddsa.rs diff --git a/cryptoki/src/mechanism/eddsa.rs b/cryptoki/src/mechanism/eddsa.rs new file mode 100644 index 00000000..acdd3bda --- /dev/null +++ b/cryptoki/src/mechanism/eddsa.rs @@ -0,0 +1,61 @@ +//! EdDSA mechanism types + +use cryptoki_sys::*; +use std::marker::PhantomData; + +/// EdDSA parameters. +/// +/// The EdDSA mechanism, denoted CKM_EDDSA, is a mechanism for +/// single-part and multipart signatures and verification for +/// EdDSA. This mechanism implements the five EdDSA signature +/// schemes defined in RFC 8032 and RFC 8410. +/// +/// For curves according to RFC 8032, this mechanism has an +/// optional parameter, a CK_EDDSA_PARAMS structure. +/// +/// The absence or presence of the parameter as well as its +/// content is used to identify which signature scheme is to be +/// used. +/// +/// | Signature Scheme | Mechanism Param | phFlag | Context Data | +/// |------------------|-----------------|--------|--------------| +/// | Ed25519 | Not Required | N/A | N/A | +/// | Ed25519ctx | Required | False | Optional | +/// | Ed25519ph | Required | True | Optional | +/// | Ed448 | Required | False | Optional | +/// | Ed448ph | Required | True | Optional | +/// +/// This structure wraps a `CK_EDDSA_PARAMS` structure. +#[derive(Copy, Debug, Clone)] +#[repr(transparent)] +pub struct EddsaParams<'a> { + inner: CK_EDDSA_PARAMS, + _marker: PhantomData<&'a [u8]>, +} + +impl EddsaParams<'_> { + /// Construct EdDSA parameters. + /// + /// # Arguments + /// + /// * `params` - The CK_EDDSA_PARAMS structure. + pub fn new(params: CK_EDDSA_PARAMS) -> Self { + Self { + inner: params, + _marker: PhantomData, + } + } +} + +impl Default for EddsaParams<'_> { + /// Provide a default instance of `EddsaParams`. + /// + /// This initializes `EddsaParams` with the default value + /// of the `CK_EDDSA_PARAMS` structure. + fn default() -> Self { + Self { + inner: CK_EDDSA_PARAMS::default(), + _marker: PhantomData, + } + } +} diff --git a/cryptoki/src/mechanism/mod.rs b/cryptoki/src/mechanism/mod.rs index 52a78528..77a0ab33 100644 --- a/cryptoki/src/mechanism/mod.rs +++ b/cryptoki/src/mechanism/mod.rs @@ -3,6 +3,7 @@ //! Data types for mechanisms pub mod aead; +pub mod eddsa; pub mod ekdf; pub mod elliptic_curve; pub mod hkdf; @@ -902,11 +903,16 @@ pub enum Mechanism<'a> { EcdsaSha512, /// EDDSA mechanism /// + /// This mechanism has an optional parameter, a CK_EDDSA_PARAMS + /// structure. The absence or presence of the parameter as well + /// as its content is used to identify which signature scheme + /// is to be used. + /// /// 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, + /// such may not be understood by some backends. It is included + /// here because some vendor implementations support it through + /// the v2.40 interface. + Eddsa(Option>), // SHA-n /// SHA-1 mechanism @@ -1001,7 +1007,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::Eddsa(_) => MechanismType::EDDSA, Mechanism::Ecdh1Derive(_) => MechanismType::ECDH1_DERIVE, Mechanism::Ecdsa => MechanismType::ECDSA, Mechanism::EcdsaSha1 => MechanismType::ECDSA_SHA1, @@ -1073,6 +1079,13 @@ impl From<&Mechanism<'_>> for CK_MECHANISM { | Mechanism::Sha512RsaPkcsPss(params) => make_mechanism(mechanism, params), Mechanism::RsaPkcsOaep(params) => make_mechanism(mechanism, params), Mechanism::Ecdh1Derive(params) => make_mechanism(mechanism, params), + Mechanism::Eddsa(params) => match params { + Some(params) => make_mechanism(mechanism, params), + None => CK_MECHANISM { + mechanism, + ..Default::default() + }, + }, Mechanism::HkdfDerive(params) | Mechanism::HkdfData(params) => { make_mechanism(mechanism, params) } @@ -1098,7 +1111,6 @@ 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 1e3b32f8..059f9515 100644 --- a/cryptoki/tests/basic.rs +++ b/cryptoki/tests/basic.rs @@ -7,6 +7,7 @@ use common::init_pins; use cryptoki::context::Function; use cryptoki::error::{Error, RvError}; use cryptoki::mechanism::aead::GcmParams; +use cryptoki::mechanism::eddsa::EddsaParams; use cryptoki::mechanism::rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource}; use cryptoki::mechanism::{Mechanism, MechanismType}; use cryptoki::object::{ @@ -99,9 +100,57 @@ fn sign_verify_ed25519() -> TestResult { let data = [0xFF, 0x55, 0xDD]; - let signature = session.sign(&Mechanism::Eddsa, private, &data)?; + let signature = session.sign(&Mechanism::Eddsa(None), private, &data)?; - session.verify(&Mechanism::Eddsa, public, &data, &signature)?; + session.verify(&Mechanism::Eddsa(None), public, &data, &signature)?; + + session.destroy_object(public)?; + session.destroy_object(private)?; + + Ok(()) +} + +#[test] +#[serial] +fn sign_verify_ed25519_with_eddsa_params() -> 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(Some(EddsaParams::default())), + private, + &data, + )?; + + session.verify( + &Mechanism::Eddsa(Some(EddsaParams::default())), + public, + &data, + &signature, + )?; session.destroy_object(public)?; session.destroy_object(private)?; From 282cbdf1c2249cdc8efa18ff7ea8e2e335e67a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mete=20Can=20Eri=C5=9F?= Date: Mon, 20 Jan 2025 12:08:45 +0300 Subject: [PATCH 2/2] refactor: derive Default for EddsaParams --- cryptoki/src/mechanism/eddsa.rs | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/cryptoki/src/mechanism/eddsa.rs b/cryptoki/src/mechanism/eddsa.rs index acdd3bda..0d982b1a 100644 --- a/cryptoki/src/mechanism/eddsa.rs +++ b/cryptoki/src/mechanism/eddsa.rs @@ -26,7 +26,7 @@ use std::marker::PhantomData; /// | Ed448ph | Required | True | Optional | /// /// This structure wraps a `CK_EDDSA_PARAMS` structure. -#[derive(Copy, Debug, Clone)] +#[derive(Copy, Debug, Clone, Default)] #[repr(transparent)] pub struct EddsaParams<'a> { inner: CK_EDDSA_PARAMS, @@ -46,16 +46,3 @@ impl EddsaParams<'_> { } } } - -impl Default for EddsaParams<'_> { - /// Provide a default instance of `EddsaParams`. - /// - /// This initializes `EddsaParams` with the default value - /// of the `CK_EDDSA_PARAMS` structure. - fn default() -> Self { - Self { - inner: CK_EDDSA_PARAMS::default(), - _marker: PhantomData, - } - } -}