Skip to content

Conversation

jakemas
Copy link
Collaborator

@jakemas jakemas commented Sep 24, 2025

Issues:

N/A - ML-KEM support.

Description of changes:

mlkem-native provides pk and sk check functions crypto_kem_check_pk and crypto_kem_check_sk that are namespaced to ml_kem_{512/768/1024}_check_{pk/sk}. This PR hooks them up to EVP_PKEY_check and EVP_PKEY_public_check so we can call them on PKEY of typeKEM.

This PR also implements a Pairwise Consistency Test (PCT) between the provided public and secret key -- this means the the functionKEM_check_key enforces pub key is present when secret key is present, this is intended behaviour -- we need both to be able to check consistency, otherwise the function serves little functionality.

Call-outs:

Due to the way the MLKEM multi-level build is compiled, we can't call mlkem{512/768/1024}_check_sk directly, so have to have those little wrapper functions in crypto/fipsmodule/ml_kem/ml_kem.c, as with other functions in that file.

Testing:

KEM tests are modified to:

EXPECT_TRUE(EVP_PKEY_check(kem_key_ctx.get()));
EXPECT_TRUE(EVP_PKEY_public_check((kem_key_ctx.get())));

Also added test suite KEMCheckKeyNegativeTests for testing KEM_check_key via. EVP_PKEY_check and EVP_PKEY_public_check. These checks include:

  • Valid Key Baseline - Verifies both EVP_PKEY_check and EVP_PKEY_public_check pass on a properly generated KEM keypair.
  • Corrupted Public Key - Tests that validation fails when public key bytes are corrupted while secret key remains valid.
  • Corrupted Secret Key - Tests that validation fails when secret key hash is corrupted while public key remains valid.
  • Mismatched Keypair - Tests Pairwise Consistency Test (PCT) failure detection when public and secret keys are from different keypairs.
  • Public Key Only Valid - Tests that validation passes when only public key material is provided.
  • Public Key Only Corrupted - Tests that validation fails when only corrupted public key material is provided.
  • Secret Key Only - Tests that validation fails when only secret key is provided without required public key.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

@codecov-commenter
Copy link

codecov-commenter commented Sep 24, 2025

Codecov Report

❌ Patch coverage is 83.91960% with 32 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.96%. Comparing base (0f99f4e) to head (416f603).

Files with missing lines Patch % Lines
crypto/fipsmodule/ml_kem/ml_kem.c 79.41% 21 Missing ⚠️
crypto/fipsmodule/kem/kem.c 83.33% 9 Missing ⚠️
crypto/evp_extra/evp_extra_test.cc 94.87% 0 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2709      +/-   ##
==========================================
+ Coverage   78.95%   78.96%   +0.01%     
==========================================
  Files         671      671              
  Lines      114801   114998     +197     
  Branches    16153    16179      +26     
==========================================
+ Hits        90643    90811     +168     
- Misses      23372    23399      +27     
- Partials      786      788       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines 322 to 326
// Check that at least the public key exists
if (key->public_key == NULL) {
OPENSSL_PUT_ERROR(EVP, EVP_R_NO_KEY_SET);
return 0;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

NP: It's currently possible (although I wish it weren't) for the secret_key to be set but not the public_key. For those, this would always return an error.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently intended behaviour, my idea is to merge the PRs first that ensure we can populate both. Then we fail this check if pub_key isn't set when secrect_key is? How does that sound?

Copy link
Collaborator Author

@jakemas jakemas Oct 7, 2025

Choose a reason for hiding this comment

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

Once caveat is that EVP_PKEY_public_check also calls the same function e.g. EC_KEY_check_key that just handles it. See here. Little bit strange, but if we follow the pattern, we'd have to make KEM_CHECK ok with pub only. Or we could implement two functions, the second KEM_CHECK_PUBLIC_KEY and call the it from EVP_PKEY_public_check: drafted that idea out here 0616873, but I don't think I like the anti-pattern. Looking at EC check for inspo, I will implement similar to how they do it, If only public key: validates public key only, if secret key is present: requires public key and validates public key, secret key, and PCT.

Copy link
Collaborator Author

@jakemas jakemas Oct 7, 2025

Choose a reason for hiding this comment

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

I've landed on f30bfd4 that preserves functionality with other EVP_PKEY_public_check/EVP_PKEY_check functions. As documented, it

// KEM_check_key: validates the key based on available key material
// - If only public key: validates public key only
// - If secret key is present: requires public key and validates public key, secret key, and PCT

I added negative testing for a bunch of cases, including the one you mention:

  // ---- 7. Test with secret key only (no public key) ----
  // Create EVP_PKEY with only secret key (no public key)

@dkostic dkostic self-requested a review October 6, 2025 22:46
@justsmth justsmth requested a review from hanno-becker October 7, 2025 13:51
@jakemas
Copy link
Collaborator Author

jakemas commented Oct 7, 2025

Upstream work discussed with Hanno on exposing the check_{sk/pk} functions pq-code-package/mlkem-native#1216. We may perhaps need to do an import/update of mlkem-native before this can merge.

@jakemas jakemas marked this pull request as ready for review October 7, 2025 19:09
@jakemas jakemas requested a review from a team as a code owner October 7, 2025 19:09
@jakemas jakemas marked this pull request as draft October 7, 2025 19:10
@jakemas jakemas marked this pull request as ready for review October 7, 2025 21:05
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.

3 participants