Skip to content

Commit ebb9c67

Browse files
committed
refactor: derive Default for EddsaParams
1 parent 8d4fca9 commit ebb9c67

File tree

4 files changed

+205
-36
lines changed

4 files changed

+205
-36
lines changed

cryptoki/src/mechanism/eddsa.rs

Lines changed: 128 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! EdDSA mechanism types
22
33
use cryptoki_sys::*;
4-
use std::marker::PhantomData;
4+
use std::{convert::TryInto, ffi::c_void, marker::PhantomData, ptr::null_mut};
55

6-
/// EdDSA parameters.
6+
/// EdDSA signature schemes.
77
///
88
/// The EdDSA mechanism, denoted CKM_EDDSA, is a mechanism for
99
/// single-part and multipart signatures and verification for
@@ -13,6 +13,88 @@ use std::marker::PhantomData;
1313
/// For curves according to RFC 8032, this mechanism has an
1414
/// optional parameter, a CK_EDDSA_PARAMS structure.
1515
///
16+
/// | Signature Scheme | Mechanism Param | phFlag | Context Data |
17+
/// |------------------|-----------------|--------|--------------|
18+
/// | Ed25519 | Not Required | N/A | N/A |
19+
/// | Ed25519ctx | Required | False | Optional |
20+
/// | Ed25519ph | Required | True | Optional |
21+
/// | Ed448 | Required | False | Optional |
22+
/// | Ed448ph | Required | True | Optional |
23+
///
24+
/// The absence or presence of the parameter as well as its
25+
/// content is used to identify which signature scheme is to be
26+
/// used.
27+
#[derive(Debug, Clone, Copy)]
28+
pub enum EddsaSignatureScheme<'a> {
29+
/// Pure EdDSA mode where the scheme is implicitly defined
30+
/// by the curve.
31+
Pure,
32+
/// Ed25519 signature scheme without additional parameters.
33+
Ed25519,
34+
/// Ed25519 signature scheme with optional context-specific
35+
/// data.
36+
Ed25519ctx(&'a [u8]),
37+
/// Ed25519 signature scheme with pre-hashing and optional
38+
/// context-specific data.
39+
Ed25519ph(&'a [u8]),
40+
/// Ed448 signature scheme with optional context-specific data.
41+
Ed448(&'a [u8]),
42+
/// Ed448 signature scheme with pre-hashing and optional
43+
/// context-specific data.
44+
Ed448ph(&'a [u8]),
45+
}
46+
47+
impl EddsaSignatureScheme<'_> {
48+
/// Convert an `EddsaSignatureScheme` into the corresponding
49+
/// parameters.
50+
///
51+
/// This function prepares the appropriate parameters for
52+
/// the mechanism based on the signature scheme variant.
53+
///
54+
/// # Returns
55+
///
56+
/// A pointer the mechanism-specific parameters.
57+
///
58+
/// For `Pure` and `Ed25519`, this returns `null_mut()` as no
59+
/// additional parameters are required. For other schemes, a
60+
/// pointer to the an `CK_EDDSA_PARAMS` structure is returned.
61+
pub fn into_params(&self) -> *mut c_void {
62+
match self {
63+
EddsaSignatureScheme::Pure | EddsaSignatureScheme::Ed25519 => null_mut(),
64+
EddsaSignatureScheme::Ed448(context) | EddsaSignatureScheme::Ed25519ctx(context) => {
65+
&CK_EDDSA_PARAMS {
66+
phFlag: false.into(),
67+
pContextData: context.as_ptr() as *mut _,
68+
ulContextDataLen: context
69+
.len()
70+
.try_into()
71+
.expect("usize can not fit in CK_ULONG"),
72+
} as *const CK_EDDSA_PARAMS as *mut _
73+
}
74+
EddsaSignatureScheme::Ed448ph(context) | EddsaSignatureScheme::Ed25519ph(context) => {
75+
&CK_EDDSA_PARAMS {
76+
phFlag: true.into(),
77+
pContextData: context.as_ptr() as *mut _,
78+
ulContextDataLen: context
79+
.len()
80+
.try_into()
81+
.expect("usize can not fit in CK_ULONG"),
82+
} as *const CK_EDDSA_PARAMS as *mut _
83+
}
84+
}
85+
}
86+
}
87+
88+
/// EdDSA parameters.
89+
///
90+
/// The EdDSA mechanism, denoted CKM_EDDSA, is a mechanism for
91+
/// single-part and multipart signatures and verification for
92+
/// EdDSA. This mechanism implements the five EdDSA signature
93+
/// schemes defined in RFC 8032 and RFC 8410.
94+
///
95+
/// For curves according to RFC 8032, this mechanism has an
96+
/// optional parameter, a CK_EDDSA_PARAMS structure.
97+
///
1698
/// The absence or presence of the parameter as well as its
1799
/// content is used to identify which signature scheme is to be
18100
/// used.
@@ -29,7 +111,7 @@ use std::marker::PhantomData;
29111
#[derive(Copy, Debug, Clone)]
30112
#[repr(transparent)]
31113
pub struct EddsaParams<'a> {
32-
inner: CK_EDDSA_PARAMS,
114+
inner: Option<CK_EDDSA_PARAMS>,
33115
_marker: PhantomData<&'a [u8]>,
34116
}
35117

@@ -39,23 +121,55 @@ impl EddsaParams<'_> {
39121
/// # Arguments
40122
///
41123
/// * `params` - The CK_EDDSA_PARAMS structure.
42-
pub fn new(params: CK_EDDSA_PARAMS) -> Self {
124+
///
125+
/// # Returns
126+
///
127+
/// A new EddsaParams struct.
128+
pub fn new(scheme: EddsaSignatureScheme) -> Self {
129+
let params =
130+
match scheme {
131+
EddsaSignatureScheme::Pure | EddsaSignatureScheme::Ed25519 => None,
132+
EddsaSignatureScheme::Ed25519ctx(context)
133+
| EddsaSignatureScheme::Ed448(context) => Some({
134+
CK_EDDSA_PARAMS {
135+
phFlag: false.into(),
136+
pContextData: context.as_ptr() as *mut _,
137+
ulContextDataLen: context
138+
.len()
139+
.try_into()
140+
.expect("usize can not fit in CK_ULONG"),
141+
}
142+
}),
143+
EddsaSignatureScheme::Ed25519ph(context)
144+
| EddsaSignatureScheme::Ed448ph(context) => Some({
145+
CK_EDDSA_PARAMS {
146+
phFlag: true.into(),
147+
pContextData: context.as_ptr() as *mut _,
148+
ulContextDataLen: context
149+
.len()
150+
.try_into()
151+
.expect("usize can not fit in CK_ULONG"),
152+
}
153+
}),
154+
};
155+
43156
Self {
44157
inner: params,
45158
_marker: PhantomData,
46159
}
47160
}
48-
}
49161

50-
impl Default for EddsaParams<'_> {
51-
/// Provide a default instance of `EddsaParams`.
162+
/// Retrieve the inner `CK_EDDSA_PARAMS` struct, if present.
52163
///
53-
/// This initializes `EddsaParams` with the default value
54-
/// of the `CK_EDDSA_PARAMS` structure.
55-
fn default() -> Self {
56-
Self {
57-
inner: CK_EDDSA_PARAMS::default(),
58-
_marker: PhantomData,
59-
}
164+
/// This method provides a reference to the `CK_EDDSA_PARAMS`
165+
/// struct encapsulated within the `EddsaParams`, if the signature
166+
/// scheme requires additional parameters.
167+
///
168+
/// # Returns
169+
///
170+
/// `Some(&CK_EDDSA_PARAMS)` if the signature scheme has associated
171+
/// parameters, otherwise `None`.
172+
pub fn inner(&self) -> Option<&CK_EDDSA_PARAMS> {
173+
self.inner.as_ref()
60174
}
61175
}

cryptoki/src/mechanism/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,7 @@ pub enum Mechanism<'a> {
912912
/// such may not be understood by some backends. It is included
913913
/// here because some vendor implementations support it through
914914
/// the v2.40 interface.
915-
Eddsa(Option<eddsa::EddsaParams<'a>>),
915+
Eddsa(eddsa::EddsaParams<'a>),
916916

917917
// SHA-n
918918
/// SHA-1 mechanism
@@ -1079,12 +1079,13 @@ impl From<&Mechanism<'_>> for CK_MECHANISM {
10791079
| Mechanism::Sha512RsaPkcsPss(params) => make_mechanism(mechanism, params),
10801080
Mechanism::RsaPkcsOaep(params) => make_mechanism(mechanism, params),
10811081
Mechanism::Ecdh1Derive(params) => make_mechanism(mechanism, params),
1082-
Mechanism::Eddsa(params) => match params {
1083-
Some(params) => make_mechanism(mechanism, params),
1082+
Mechanism::Eddsa(params) => match params.inner() {
10841083
None => CK_MECHANISM {
10851084
mechanism,
1086-
..Default::default()
1085+
pParameter: null_mut(),
1086+
ulParameterLen: 0,
10871087
},
1088+
Some(params) => make_mechanism(mechanism, params),
10881089
},
10891090
Mechanism::HkdfDerive(params) | Mechanism::HkdfData(params) => {
10901091
make_mechanism(mechanism, params)

cryptoki/tests/basic.rs

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use common::init_pins;
77
use cryptoki::context::Function;
88
use cryptoki::error::{Error, RvError};
99
use cryptoki::mechanism::aead::GcmParams;
10-
use cryptoki::mechanism::eddsa::EddsaParams;
10+
use cryptoki::mechanism::eddsa::{EddsaParams, EddsaSignatureScheme};
1111
use cryptoki::mechanism::rsa::{PkcsMgfType, PkcsOaepParams, PkcsOaepSource};
1212
use cryptoki::mechanism::{Mechanism, MechanismType};
1313
use cryptoki::object::{
@@ -73,7 +73,7 @@ fn sign_verify() -> TestResult {
7373

7474
#[test]
7575
#[serial]
76-
fn sign_verify_ed25519() -> TestResult {
76+
fn sign_verify_eddsa() -> TestResult {
7777
let (pkcs11, slot) = init_pins();
7878

7979
let session = pkcs11.open_rw_session(slot)?;
@@ -100,9 +100,13 @@ fn sign_verify_ed25519() -> TestResult {
100100

101101
let data = [0xFF, 0x55, 0xDD];
102102

103-
let signature = session.sign(&Mechanism::Eddsa(None), private, &data)?;
103+
let scheme = EddsaSignatureScheme::Pure;
104104

105-
session.verify(&Mechanism::Eddsa(None), public, &data, &signature)?;
105+
let params = EddsaParams::new(scheme);
106+
107+
let signature = session.sign(&Mechanism::Eddsa(params), private, &data)?;
108+
109+
session.verify(&Mechanism::Eddsa(params), public, &data, &signature)?;
106110

107111
session.destroy_object(public)?;
108112
session.destroy_object(private)?;
@@ -112,7 +116,7 @@ fn sign_verify_ed25519() -> TestResult {
112116

113117
#[test]
114118
#[serial]
115-
fn sign_verify_ed25519_with_eddsa_params() -> TestResult {
119+
fn sign_verify_eddsa_with_ed25519_schemes() -> TestResult {
116120
let (pkcs11, slot) = init_pins();
117121

118122
let session = pkcs11.open_rw_session(slot)?;
@@ -139,18 +143,68 @@ fn sign_verify_ed25519_with_eddsa_params() -> TestResult {
139143

140144
let data = [0xFF, 0x55, 0xDD];
141145

142-
let signature = session.sign(
143-
&Mechanism::Eddsa(Some(EddsaParams::default())),
144-
private,
145-
&data,
146-
)?;
146+
let schemes = [
147+
EddsaSignatureScheme::Ed25519,
148+
EddsaSignatureScheme::Ed25519ctx(b"context"),
149+
EddsaSignatureScheme::Ed25519ph(&[]),
150+
EddsaSignatureScheme::Ed25519ph(b"context"),
151+
];
147152

148-
session.verify(
149-
&Mechanism::Eddsa(Some(EddsaParams::default())),
150-
public,
151-
&data,
152-
&signature,
153-
)?;
153+
for scheme in schemes {
154+
let params = EddsaParams::new(scheme);
155+
156+
let signature = session.sign(&Mechanism::Eddsa(params), private, &data)?;
157+
158+
session.verify(&Mechanism::Eddsa(params), public, &data, &signature)?;
159+
}
160+
161+
session.destroy_object(public)?;
162+
session.destroy_object(private)?;
163+
164+
Ok(())
165+
}
166+
167+
#[test]
168+
#[serial]
169+
fn sign_verify_eddsa_with_ed448_schemes() -> TestResult {
170+
let (pkcs11, slot) = init_pins();
171+
172+
let session = pkcs11.open_rw_session(slot)?;
173+
174+
session.login(UserType::User, Some(&AuthPin::new(USER_PIN.into())))?;
175+
176+
let mechanism = Mechanism::EccEdwardsKeyPairGen;
177+
178+
let pub_key_template = vec![
179+
Attribute::Token(true),
180+
Attribute::Private(false),
181+
Attribute::Verify(true),
182+
// Ed448 OID
183+
// See: https://github.com/opendnssec/SoftHSMv2/blob/ac70dc398b236e4522101930e790008936489e2d/src/lib/test/SignVerifyTests.cpp#L173
184+
Attribute::EcParams(vec![
185+
0x13, 0x0a, 0x65, 0x64, 0x77, 0x61, 0x72, 0x64, 0x73, 0x34, 0x34, 0x38,
186+
]),
187+
];
188+
189+
let priv_key_template = vec![Attribute::Token(true)];
190+
191+
let (public, private) =
192+
session.generate_key_pair(&mechanism, &pub_key_template, &priv_key_template)?;
193+
194+
let data = [0xFF, 0x55, 0xDD];
195+
196+
let schemes = [
197+
EddsaSignatureScheme::Ed448(b"context"),
198+
EddsaSignatureScheme::Ed448ph(b"context"),
199+
];
200+
201+
for scheme in schemes {
202+
let params = EddsaParams::new(scheme);
203+
204+
let signature = session.sign(&Mechanism::Eddsa(params), private, &data)?;
205+
206+
session.verify(&Mechanism::Eddsa(params), public, &data, &signature)?;
207+
}
154208

155209
session.destroy_object(public)?;
156210
session.destroy_object(private)?;

cryptoki/tests/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ use cryptoki::types::AuthPin;
77
use std::env;
88

99
// The default user pin
10-
pub static USER_PIN: &str = "fedcba";
10+
pub static USER_PIN: &str = "1234";
1111
// The default SO pin
12-
pub static SO_PIN: &str = "abcdef";
12+
pub static SO_PIN: &str = "1234";
1313

1414
pub fn get_pkcs11() -> Pkcs11 {
1515
Pkcs11::new(

0 commit comments

Comments
 (0)