Skip to content

Fix [Dev] ML-KEM (with Archival) support for CRMFPopClient (and/or cli)#5364

Draft
jmagne wants to merge 1 commit into
dogtagpki:masterfrom
jmagne:crmf-pop-ml-kem
Draft

Fix [Dev] ML-KEM (with Archival) support for CRMFPopClient (and/or cli)#5364
jmagne wants to merge 1 commit into
dogtagpki:masterfrom
jmagne:crmf-pop-ml-kem

Conversation

@jmagne
Copy link
Copy Markdown
Contributor

@jmagne jmagne commented May 22, 2026

Add code in KRA to extract the ML-KEM session key if encapsulated.
Added a new user profile caMLKEMUserCert.cfg
Fixed UserKeyDefault.java to recognize ML-KEM, it already checks for ML-DSA.

Assisted-by: Claude Sonnet 4.5

Add code in KRA to extract the ML-KEM session key if encapsulated.
Added a new user profile caMLKEMUserCert.cfg
Fixed UserKeyDefault.java to recognize ML-KEM, it already checks for ML-DSA.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 48dd03bf-e11a-483a-9d2c-91382d964f06

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

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

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 introduces support for ML-KEM (Module-Lattice-Based Key-Encapsulation Mechanism) by adding a new certificate profile, implementing encapsulation and decapsulation logic in CryptoUtil, and updating the KRA to support ML-KEM transport keys. Feedback from the review highlights a critical need to use the returned token-resident key after calling importPublicKey to ensure correct encapsulation. Additionally, the reviewer suggested using more specific exceptions like NoSuchAlgorithmException, removing redundant log messages, and correcting minor whitespace issues.

Comment on lines +2363 to +2367
token.importPublicKey(wrappingKey, false);

// Do ML-KEM encapsulate to derive shared secret + ciphertext
logger.debug("CryptoUtil: Using ML-KEM encapsulation for key archival");
KEMEncapsulation keyResult = encapsulateMLKEM(wrappingKey, params.getPayloadEncryptionAlgorithm());
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The return value of token.importPublicKey(wrappingKey, false) is ignored. As noted in the comment on line 2360, ML-KEM requires the public key to be imported as a PKCS#11 object on the token for encapsulation. The importPublicKey method returns a PK11PubKey (as a PublicKey) which should be used in the subsequent encapsulateMLKEM call to ensure the operation uses the token-resident key. Additionally, there is a double space before params on line 2367.

Suggested change
token.importPublicKey(wrappingKey, false);
// Do ML-KEM encapsulate to derive shared secret + ciphertext
logger.debug("CryptoUtil: Using ML-KEM encapsulation for key archival");
KEMEncapsulation keyResult = encapsulateMLKEM(wrappingKey, params.getPayloadEncryptionAlgorithm());
PublicKey tokenKey = token.importPublicKey(wrappingKey, false);
// Do ML-KEM encapsulate to derive shared secret + ciphertext
logger.debug("CryptoUtil: Using ML-KEM encapsulation for key archival");
KEMEncapsulation keyResult = encapsulateMLKEM(tokenKey, params.getPayloadEncryptionAlgorithm());

sk = CryptoUtil.decapsulateMLKEM(wrappingKey,
encSymmKey,
params.getPayloadEncryptionAlgorithm());
logger.debug("TransportKeyUnit.unwrap: Using ML-KEM decapsulation");
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

This debug log message is identical to the one on line 434. It should be updated to indicate that the decapsulation step has completed successfully or removed to avoid redundancy.

Suggested change
logger.debug("TransportKeyUnit.unwrap: Using ML-KEM decapsulation");
logger.debug("TransportKeyUnit.unwrap: ML-KEM decapsulation successful");

byte[] kemCipherText = null;

if (wrappingAlg == null) {
throw new Exception("Unable to determine transport key algorithm");
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

Using a generic Exception is discouraged. Since this is a cryptographic operation where an algorithm cannot be determined, NoSuchAlgorithmException would be more appropriate and idiomatic.

Suggested change
throw new Exception("Unable to determine transport key algorithm");
throw new NoSuchAlgorithmException("Unable to determine transport key algorithm");

if (isAlgorithmMLKEM(wrappingAlg)) {
session_data = kemCipherText;
} else {
session_data = wrapUsingPublicKey(
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

There are unnecessary extra spaces before the method call.

Suggested change
session_data = wrapUsingPublicKey(
session_data = wrapUsingPublicKey(

@sonarqubecloud
Copy link
Copy Markdown

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.

1 participant