rust-cryptoki icon indicating copy to clipboard operation
rust-cryptoki copied to clipboard

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

Open Jakuje opened this issue 7 months ago • 1 comments

The PKCS#11 3.2 headers are available (pre-release though, but final version should be out in coming weeks):

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

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

So far opened only as a draft as the specs is not published yet, but planning to add some more functions using kryoptic, that will verify the whole process works.

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

Jakuje avatar Apr 25 '25 13:04 Jakuje

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 ....

Jakuje avatar Apr 25 '25 14:04 Jakuje

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.

wiktor-k avatar Apr 29 '25 19:04 wiktor-k

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.

Jakuje avatar Apr 30 '25 07:04 Jakuje

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.

wiktor-k avatar Apr 30 '25 09:04 wiktor-k

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 avatar May 05 '25 17:05 Jakuje

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

hug-dev avatar May 12 '25 08:05 hug-dev

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

Jakuje avatar Jun 19 '25 07:06 Jakuje

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.

teythoon avatar Jun 25 '25 14:06 teythoon

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.

Jakuje avatar Jun 25 '25 14:06 Jakuje

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.

teythoon avatar Jun 26 '25 11:06 teythoon

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 avatar Jul 08 '25 12:07 Jakuje

@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?

Jakuje avatar Jul 08 '25 20:07 Jakuje

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.

teythoon avatar Jul 09 '25 11:07 teythoon

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 avatar Jul 11 '25 17:07 Jakuje

@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.

Jakuje avatar Jul 23 '25 09:07 Jakuje

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

Jakuje avatar Jul 23 '25 11:07 Jakuje