Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: revise EdDSA mechanism to support optional params #244

Merged
merged 1 commit into from
Feb 10, 2025

Conversation

mcaneris
Copy link
Contributor

This revises the Mechanism::Eddsa struct to receive a EddsaParams struct as an optional argument in line with the PKCS#11 3.0 specification.

According to RFC 8032, CKM_EDDSA 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. The following table enumerates the five signature schemes defined in RFC 8032 and all supported permutations of the mechanism parameter and its content.

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

The binding for CK_EDDSA_PARAMS is already present under the cryptoki-sys crate. However, there is no way currently to pass these params to the Mechanism::Eddsa struct.

As the specification places significance on the absence of the parameters (resulting in curve selection), I elected to pass EddsaParams as an Option to Mechanism::Eddsa. Added and modified tests pass for Ed25519 signing with no parameters, as well as default CK_EDDSA_PARAMS.

I think the capability to pass these params is necessary to use the various curves allowed under the mechanism according to the specification.

Copy link
Collaborator

@wiktor-k wiktor-k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks very nice 👌

cryptoki/src/mechanism/eddsa.rs Outdated Show resolved Hide resolved
let data = [0xFF, 0x55, 0xDD];

let signature = session.sign(
&Mechanism::Eddsa(Some(EddsaParams::default())),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does SoftHSM support any other parameters than the defaults? If so it'd be good to test it.

/// 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<eddsa::EddsaParams<'a>>),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... here None and Some(Default::default()) is exactly the same state... I wonder if it's too ugly to require Default::default() (remove the Option)... @hug-dev ?

Copy link
Contributor Author

@mcaneris mcaneris Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the passing of an Option made the code more ugly, but I think the None case is not same as the Default case.

In the Default case, although CK_EDDSA_PARAMS is a nullish struct (phFlag is false, pContextData is null, and pContextDataLen is 0), params passed to Eddsa mechanism is no longer null (in other words, pParameter is not null, and ulParameterLen is no longer 0).

Reading the specification, I understand that for selection of the Ed25519 curve, pParameter must be null, and ulParameterLen must be 0.

That said, I'm open to suggestions for a more elegant solution, I agree the Option made it ugly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the passing of an Option made the code more ugly, but I think the None case is not same as the Default case.

I don't mind None that much but just for the sake of my understanding I'd like to get bottom to the None non-equal to Default. I think one thing that tripped me is the manual conversion from CK_MECHANISM below. 👇

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replied in my other comment on a way to fix this, with an enum 🤓!

/// 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<eddsa::EddsaParams<'a>>),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree the passing of an Option made the code more ugly, but I think the None case is not same as the Default case.

I don't mind None that much but just for the sake of my understanding I'd like to get bottom to the None non-equal to Default. I think one thing that tripped me is the manual conversion from CK_MECHANISM below. 👇

Some(params) => make_mechanism(mechanism, params),
None => CK_MECHANISM {
mechanism,
..Default::default()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Continued:

This line made me suspicious. Maybe it's just me but I think this would be more readable (basically the same code as for Mechanism::HkdfKeyGen):

Suggested change
..Default::default()
pParameter: null_mut(),
ulParameterLen: 0,

I wonder if this is just me, though, and yeah, I'm aware that this makes the code longer 😅

Copy link
Member

@hug-dev hug-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!! Really appreciate the effort in the description you added and the comments too, made it easy to review!

Added a suggestion on types, would also appreciate @ionut-arm eyes to make sure all of this is correct :)

cryptoki/src/mechanism/eddsa.rs Show resolved Hide resolved
/// 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<eddsa::EddsaParams<'a>>),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replied in my other comment on a way to fix this, with an enum 🤓!

This revises the `Mechanism::Eddsa` struct to receive a `EddsaParams` struct as an optional argument.

Signed-off-by: Mete Can Eriş <can.eris@feyn.dev>
@mcaneris mcaneris reopened this Feb 10, 2025
Copy link
Member

@hug-dev hug-dev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for keeping with it through the reviews 💪 !

@wiktor-k wiktor-k enabled auto-merge February 10, 2025 21:01
Copy link
Collaborator

@wiktor-k wiktor-k left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really good 👌 I had a couple of nits but then decided they're not that important 😅

Thanks! 🙏

@wiktor-k wiktor-k merged commit ff533d8 into parallaxsecond:main Feb 10, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants