Skip to content

Add leancrypto backend#456

Open
smuellerDD wants to merge 5 commits into
latchset:mainfrom
smuellerDD:leancrypto
Open

Add leancrypto backend#456
smuellerDD wants to merge 5 commits into
latchset:mainfrom
smuellerDD:leancrypto

Conversation

@smuellerDD

Copy link
Copy Markdown

Description

This PR intends to add the leancrypto as backend implementing the cryptographic algorithms used by kryoptic. Leancrypto is intended as a library that focuses on PQC support and does not contain classic algorithms (except Curve25519/448 intended for hybrid algorithms) as outlined in https://leancrypto.org. Furthermore, it is intended to be versatile to be used in various different execution environments (user space, kernel space, EFI, ...) and therefore is intended as a library that provides the needs for large numbers of different use cases.

For now, this PR is a WIP and intends to ask and clarify several questions before or while adding more algorithm support:

  1. The feature handling of fips/non-fips/leancrypto leads to an awkward selection between the native, OpenSSL and leancrypto backends. Note, leancrypto also offers a FIPS compliant support. Do you have any idea or suggestions on how to make the feature selection simpler?
  2. The leancrypto backend currently uses map_err as error conversion between leancrypto and kryoptic. I have seen the specific error handling in the OpenSSL code base - what is the preferred error handling mechanism?

The current PR provides PBKDF2 to discuss the questions and the approach. As part of the PR, I added PBKDF2 SHA2 test vectors as leancrypto does not offer SHA-1.

To test the code, perform the following steps:

  1. clone leancrypto from https://github.com/smuellerDD/leancrypto
  2. compile and install the HEAD: meson setup build && meson compile -C build && sudo meson install -C build && sudo ldconfig
  3. symlink the leancrypto code repository into the root directory of kryoptic
  4. build/test kryoptic: cargo test -F leancrypto

Checklist

  • Test suite updated
    - [ ] Rustdoc string were added or updated
  • CHANGELOG and/or other documentation added or updated
  • This is not a code change

Reviewer's checklist:

  • Any issues marked for closing are fully addressed
  • There is a test suite reasonably covering new functionality or modifications
  • This feature/change has adequate documentation added
  • A changelog entry is added if the change is significant
  • Code conform to coding style that today cannot yet be enforced via the check style test
  • Commits have short titles and sensible text
  • Doc string are properly updated

Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Stephan Mueller <smueller@chronox.de>

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request integrates the leancrypto library as an optional backend for PBKDF2 key derivation, adding the leancrypto-sys dependency and introducing a new leancrypto module. It maps PKCS#11 mechanism types to leancrypto digest algorithms and implements pbkdf2_derive using the new backend. Additionally, new tests are added to verify PBKDF2 functionality with SHA-2. Feedback includes correcting a copy-paste error in the PBKDF2 derivation error message and using checked conversions (try_from) instead of truncating casts (as) when converting usize to CK_ULONG in the test suite to prevent potential silent data loss.

Comment thread src/leancrypto/pbkdf2.rs
iter_count,
&mut dkm,
)
.map_err(|e| Error::other_error(format!("leancrypto encrypt: {e}")))?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The error message refers to 'leancrypto encrypt', but this function performs PBKDF2 key derivation. This copy-paste error can be misleading during debugging. It should be updated to reflect the actual operation.

Suggested change
.map_err(|e| Error::other_error(format!("leancrypto encrypt: {e}")))?;
.map_err(|e| Error::other_error(format!("leancrypto pbkdf2 derive: {e}")))?;

Comment thread src/tests/kdfs.rs
Comment thread src/tests/kdfs.rs
Comment thread src/tests/kdfs.rs
Signed-off-by: Stephan Mueller <smueller@chronox.de>
The DRBG support allows the configuration of "HMAC DRBG SHA256" and
"HMAC DRBG SHA512". Yet, both are diverted into using the leancrypto
"seeded DRNG" which is a DRNG properly seeded by leancrypto during
initialization and during runtime.

Signed-off-by: Stephan Mueller <smueller@chronox.de>
@smuellerDD

Copy link
Copy Markdown
Author

I have added the DRBG backend. During the addition, I am yet slightly unsure about the naming: The naming required by kryoptic is "HMAC DRBG SHA256" or SHA512. Yet, kryoptic requires effectively the availability of a fully seeded DRBG where the actual type does not really matter. Therefore, the current leancrypto backend uses the "seeded DRNG" logic found in leancrypto which is guaranteed to provide a fully seeded and reseeded DRNG instance. Yet, its type cannot really be configured from the outside as it is initialized as one of the first parts in leancrypto. The default DRBG type used in leancrypto is an XDRBG 256 (i.e. an implementation which is expected to be added to the next revision of SP800-90A). At compile-time of leancrypto, this type can be changed, including to a HMAC-DRBG.

Is this approach considered appropriate?

Signed-off-by: Stephan Mueller <smueller@chronox.de>

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

What's the cause of the tests failure?

Comment thread src/leancrypto/kbkdf.rs
use leancrypto_sys::lcr_hash::lcr_hash_digestsize_mapping;
use leancrypto_sys::lcr_kbkdf::{lcr_kbkdf_ctr, lcr_kbkdf_fb};

#[cfg(feature = "fips")]

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.

It's odd that you add fips features here when the module is never included if the feature is enabled

Comment thread src/tests/kdf_vectors.rs
&mut dk_handle,
);
if ret != CKR_OK {
/*

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.

if this only happens with leancrypto I would rather guard this test with the feature.
Otherwise it will also ignore failures it shouldn't for other backends

Comment thread src/tests/kdfs.rs
derive_template.len() as CK_ULONG,
&mut handle3,
);
/* Ignore when a backend does not support CMAC KDF */

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.

as above, put a leancrypto feature guard around this

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ack

Comment thread src/tests/kdfs.rs
Comment thread src/tests/kdfs.rs
Comment thread src/tests/kdfs.rs
@simo5

simo5 commented Jun 1, 2026

Copy link
Copy Markdown
Member

I have added the DRBG backend. During the addition, I am yet slightly unsure about the naming: The naming required by kryoptic is "HMAC DRBG SHA256" or SHA512. Yet, kryoptic requires effectively the availability of a fully seeded DRBG where the actual type does not really matter. Therefore, the current leancrypto backend uses the "seeded DRNG" logic found in leancrypto which is guaranteed to provide a fully seeded and reseeded DRNG instance. Yet, its type cannot really be configured from the outside as it is initialized as one of the first parts in leancrypto. The default DRBG type used in leancrypto is an XDRBG 256 (i.e. an implementation which is expected to be added to the next revision of SP800-90A). At compile-time of leancrypto, this type can be changed, including to a HMAC-DRBG.

Is this approach considered appropriate?

Yes,
IIRC PKCS#11 does not specify what the RNG should be, only that one exists, so any implementation that provides a reasonable RNG will be fine.

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.

2 participants