Skip to content

Add PKCS#11 3.2 bindings + plug them into the cryptoki#264

Merged
wiktor-k merged 15 commits into
parallaxsecond:mainfrom
Jakuje:pkcs11-3.2
Jul 25, 2025
Merged

Add PKCS#11 3.2 bindings + plug them into the cryptoki#264
wiktor-k merged 15 commits into
parallaxsecond:mainfrom
Jakuje:pkcs11-3.2

Conversation

@Jakuje

@Jakuje Jakuje commented Apr 25, 2025

Copy link
Copy Markdown
Collaborator

The PKCS#11 3.2 headers are available and considered final:

https://github.com/latchset/pkcs11-headers/tree/main/public-domain/3.2

This pulls the new headers, regenerates bindings and adjusts the initialization so they can be used.

I took also the chance to update bindgen to 0.71.1 once we generate new binding version

@Jakuje

Jakuje commented Apr 25, 2025

Copy link
Copy Markdown
Collaborator Author

Oh, lovely! The CI does not like the generated binding as it is too complex.

error: very complex type used. Consider factoring parts into `type` definitions
    --> /home/runner/work/rust-cryptoki/rust-cryptoki/cryptoki-sys/src/bindings/x86_64-unknown-linux-gnu.rs:6801:35
     |
6801 |       pub C_UnwrapKeyAuthenticated: Result<
     |  ___________________________________^
6802 | |         unsafe extern "C" fn(
6803 | |             arg1: CK_SESSION_HANDLE,
6804 | |             arg2: *mut CK_MECHANISM,
...    |
6814 | |         ::libloading::Error,
6815 | |     >,
     | |_____^
     |

Who would say it for a function with 10 arguments:

    pub C_UnwrapKeyAuthenticated: Result<
        unsafe extern "C" fn(
            arg1: CK_SESSION_HANDLE,
            arg2: *mut CK_MECHANISM,
            arg3: CK_OBJECT_HANDLE,
            arg4: *mut CK_BYTE,
            arg5: CK_ULONG,
            arg6: *mut CK_ATTRIBUTE,
            arg7: CK_ULONG,
            arg8: *mut CK_BYTE,
            arg9: CK_ULONG,
            arg10: *mut CK_OBJECT_HANDLE,
        ) -> CK_RV,
        ::libloading::Error,
    >,  

Is this something we should fix in the generated bindings or open an issue for the bindgen? Not sure if this is a new issue with the new bindgen, but more likely the issue of the new PKCS#11 API having that insane number of arguments ....

@wiktor-k

Copy link
Copy Markdown
Collaborator

Hmm fortunately this is just a clippy issue. I guess suppressing it somewhere would be an okayish workaround. (maybe in lib.rs of -sys?)

I'd still report it to bindgen. This may improve their code generation or at least make them consider adding the lint suppression in the generated code.

@Jakuje

Jakuje commented Apr 30, 2025

Copy link
Copy Markdown
Collaborator Author

Thanks for the pointer! I see the lib.rs has already some more warnings ignored. I am not sure if there is some way how to improve the code generation to avoid this. I can think of using some temporary named type for the function, but I think it just moves the problem one more function argument away.

I think this is inherent issue of the PKCS#11 specification, introducing this complex functions.

@wiktor-k

Copy link
Copy Markdown
Collaborator

I am not sure if there is some way how to improve the code generation to avoid this.

FWIW I didn't mean that. Slapping the lint suppression there is sufficient enough for me.

@Jakuje

Jakuje commented May 5, 2025

Copy link
Copy Markdown
Collaborator Author

Kryoptic tests now fail as there are few bugs in the last release that were already fixed in main. I think this is already good for first reviews, but I would probably wait for the pkcs11 3.2 to get released officially and I will likely implement also the SLH-DSA (they look quite simple and similar to the ML-DSA, but I do not have an implementation to test against yet).

@Jakuje
Jakuje marked this pull request as ready for review May 5, 2025 17:02
@hug-dev

hug-dev commented May 12, 2025

Copy link
Copy Markdown
Member

Feel free to ping us when you want us to review this again!

@Jakuje

Jakuje commented Jun 19, 2025

Copy link
Copy Markdown
Collaborator Author

I think this should be ready for reviews! Rebased and updated links to the final headers.

@teythoon

Copy link
Copy Markdown

I found a small issue. When I ask for an AttributeType::MlDsaParameterSet, the token returns an Attribute::ParameterSet.

I think the patch introduces AttributeType::MlDsaParameterSet as an alias for AttributeType::ParameterSet. Both MlDsaParameterSet and ParameterSet map to CKA_PARAMETER_SET, and therefore the distinction is lost, and the response will be a ParameterSet.

@Jakuje

Jakuje commented Jun 25, 2025

Copy link
Copy Markdown
Collaborator Author

I found a small issue. When I ask for an AttributeType::MlDsaParameterSet, the token returns an Attribute::ParameterSet.

I think the patch introduces AttributeType::MlDsaParameterSet as an alias for AttributeType::ParameterSet. Both MlDsaParameterSet and ParameterSet map to CKA_PARAMETER_SET, and therefore the distinction is lost, and the response will be a ParameterSet.

Yeah, I was aware of this issue, but I am not sure how this could be easily handled given that this attribute has different values for different key types. Any thoughts?

I think it would require some logic in the GetAttributeValue mapping the type to the correct aliased "subtype" based on the key type, but I really did not look into that yet.

@teythoon

Copy link
Copy Markdown

I think the aliasing is most surprising. The Rust model is a refinement of the interface model, i.e. it is more expressive. I think that is a mistake at this point. It is also surprising for people coming from the PKCS#11 spec.

Instead, I think we should offer explicit conversion functions from ParameterSetType (doesn't exist yet, and should hold a u64, and that is what Attribute::ParameterSet should use) to MlDsaParameterSet.

wiktor-k
wiktor-k previously approved these changes Jul 7, 2025

@wiktor-k wiktor-k left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looks good 👌 Thanks for attaching tests for various combinations of the new API.

Comment thread cryptoki/src/context/general_purpose.rs
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment on lines +117 to +126
let (p_context, ul_context_len) = match context {
Some(c) => (
c.as_ptr() as *mut _,
c.len().try_into().expect("usize can not fit in CK_ULONG"),
),
None => (null_mut(), 0),
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
let (p_context, ul_context_len) = match context {
Some(c) => (
c.as_ptr() as *mut _,
c.len().try_into().expect("usize can not fit in CK_ULONG"),
),
None => (null_mut(), 0),
};
let (p_context, ul_context_len) = if let Some(c) = context {
(c.as_ptr() as *mut _,
c.len().try_into().expect("usize can not fit in CK_ULONG")),
} else {
(null_mut(), 0),
};
};

I tend to avoid matches which then destructure into Some/None as I think if let is more readable... but it's not a blocker :)

.unwrap_or_else(|_| "/usr/local/lib/softhsm/libsofthsm2.so".to_string())
}

#[allow(dead_code)]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is that still needed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

warning: function `is_softhsm` is never used
  --> cryptoki/tests/common/mod.rs:19:8
   |
19 | pub fn is_softhsm() -> bool {
   |        ^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: `cryptoki` (test "ml_kem") generated 1 warning
warning: `cryptoki` (test "ml_dsa") generated 1 warning (1 duplicate)

I did some restructure of the tests and this reports failure for the two now (mlkem and mldsa) as they do not use this public function.

I think the whole test structure can be improved as now it builds separate test binaries, which is not very effective.

So as a after-thought I think we should really have one test binary and source code split to separate files, probably something similar as we have in kryoptic (but that lives under src/tests, which I understand is not a standard place to push tests according to rust.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

which is not very effective.

Oh yeah, this is definitely an annoying aspect of cargo test and part of the reason why in other projects we're instead using cargo nextest run instead of bare cargo test.

@Jakuje
Jakuje force-pushed the pkcs11-3.2 branch 4 times, most recently from 38fc896 to 31b8bdc Compare July 8, 2025 10:23
hug-dev
hug-dev previously approved these changes Jul 8, 2025

@hug-dev hug-dev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you for pushing for this!

Comment thread cryptoki/src/context/mod.rs
@Jakuje

Jakuje commented Jul 8, 2025

Copy link
Copy Markdown
Collaborator Author

I still want to resolve the ParameterSetType issue reported by @teythoon, but I needed some clarification what exactly he had in mind. I agree that the current solution is wrong, but I was not able to make better one working so far :)

@Jakuje

Jakuje commented Jul 8, 2025

Copy link
Copy Markdown
Collaborator Author

@teythoon I did rehash the ParameterSetType a bit in the last commit. Is it something you had in your mind or is there something missing that you would add or change?

@teythoon

teythoon commented Jul 9, 2025

Copy link
Copy Markdown

Yes, that was what I had in mind.

But, I remember Simo suggesting to keep the aliases, always make sure to request the key type as well, and when wrapping the response in Rust types, convert the generic parameter set response to a specific one based on the reported key type. If that is feasible to implement, that'd be most convenient for the downstream users.

@Jakuje

Jakuje commented Jul 11, 2025

Copy link
Copy Markdown
Collaborator Author

But, I remember Simo suggesting to keep the aliases, always make sure to request the key type as well, and when wrapping the response in Rust types, convert the generic parameter set response to a specific one based on the reported key type. If that is feasible to implement, that'd be most convenient for the downstream users.

I guess I will have to think about that a bit more (and will probably not get back to that before I will get back from holiday). It will either have to be some ad-hoc change in the C_GetAttribute to do both of the pulling of the key type and converting the parameter set to the key-specific one. Or some new more generic logic to do this. But as far as I know the ParameterSet of the three new PQC algorithms is the only one so the ad-hoc solution might be enough.

Jakuje added 4 commits July 23, 2025 11:12
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
this requires the new version of proc-macro2

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
@Jakuje

Jakuje commented Jul 23, 2025

Copy link
Copy Markdown
Collaborator Author

@teythoon I though about implementing the aliases, but though it would be more confusing now. With the .into() conversion, the inner types are just one step away. If we decide to do this later, it can be done though.

@hug-dev @wiktor-k I think this is ready for final reviews.

wiktor-k
wiktor-k previously approved these changes Jul 23, 2025

@wiktor-k wiktor-k left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM 👍 a couple of nits/questions.

Comment thread cryptoki/src/mechanism/mechanism_info.rs
Comment thread cryptoki/src/mechanism/mechanism_info.rs
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/mechanism/mldsa.rs Outdated
Comment thread cryptoki/src/session/encapsulation.rs Outdated
Jakuje added 11 commits July 23, 2025 13:25
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
One of the new functions in PKCS#11 3.2 have 10(!) arguments, which goes
over the threshold of what clippy considers reasonable. But given that
we need to be compatible with this API, there is no other reasonable way
to tackle this than to ignore the warning/error.

error: very complex type used. Consider factoring parts into `type` definitions
    --> /home/runner/work/rust-cryptoki/rust-cryptoki/cryptoki-sys/src/bindings/x86_64-unknown-linux-gnu.rs:6801:35
     |
6801 |       pub C_UnwrapKeyAuthenticated: Result<
     |  ___________________________________^
6802 | |         unsafe extern "C" fn(
6803 | |             arg1: CK_SESSION_HANDLE,
6804 | |             arg2: *mut CK_MECHANISM,
...    |
6814 | |         ::libloading::Error,
6815 | |     >,
     | |_____^
     |

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
... which is no longer basic after having 2000+ lines

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
This is needed for multiplart ML-DSA signature verifications

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
Signed-off-by: Jakub Jelen <jjelen@redhat.com>
All these operations follow Section 5.2 semantics, which allow the size
query to return larger buffer and adjust the returned length to the real
length during the operation.

Previously, the `resize()` was used, but it was discussed several times
that it can not extend the buffer (unless the pkcs11 module misbehaves)
so changing all the places to `truncate()` instead.

Signed-off-by: Jakub Jelen <jjelen@redhat.com>
@Jakuje

Jakuje commented Jul 23, 2025

Copy link
Copy Markdown
Collaborator Author

Applied all the suggestions. Thanks for prompt review @wiktor-k !

@hug-dev hug-dev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!!

@wiktor-k
wiktor-k enabled auto-merge July 25, 2025 12:40
@wiktor-k
wiktor-k merged commit 5201f0a into parallaxsecond:main Jul 25, 2025
43 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