You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add ASN.1 decoding for ML-KEM private keys as seeds (#2707)
### Issues:
Resolves #N/A
Addresses #aws/aws-lc-rs#799
### Description of changes:
This PR adds support for the parsing of ML-KEM private keys encoded in
the ASN.1 seed format, as described in
https://datatracker.ietf.org/doc/draft-ietf-lamps-kyber-certificates/.
As such, 64 byte ASN.1 encoded private keys, such as this example
ml-kem-512 private key from the IETF draft can now be parsed in aws-lc
using `EVP_parse_private_key`:
```
-----BEGIN PRIVATE KEY-----
MFQCAQAwCwYJYIZIAWUDBAQBBEKAQAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZ
GhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8=
-----END PRIVATE KEY-----
```
The `EVP_PKEY` produced will have **both** the full private and public
ML-KEM key expanded material within.
This very much follows a similar PR for ML-DSA
#2157.
While there are a few ways to tackle the issue of getting the public key
when the private is provided, for example making use of the
`OneAsymmetricKey` structure as in
https://datatracker.ietf.org/doc/html/draft-ietf-lamps-kyber-certificates-11#section-6.
However as PKCS8 v2 isn't well supported, I feel encoding
`OneAsymmetricKey` won't be easy for those wanting to bring key material
into aws-lc/-rs. Python Cryptography doesn't support it today, for
example. OpenSSL encodes keys by default using the `BOTH` approach (seed
and expanded material), so importing from OpenSSL produced private seeds
will now be possible, and populate both pub and priv keys.
#### Background
The IETF draft standard defines three private key formats for ML-KEM
certificates:
1. __seed [0] OCTET STRING__ - 64-byte deterministic seed (added in this
PR)
2. __expandedKey OCTET STRING__ - Full private key material
(#2624)
3. __both SEQUENCE {seed, expandedKey}__ - Both formats together (future
work)
Previously, AWS-LC only supported the expandedKey format. This PR adds
support for the more compact seed format, which uses deterministic key
generation from a 64-byte seed.
How does this help aws/aws-lc-rs#799?
When the private key is provided as a seed, both the expanded private
and secret key are populated within the EVP_PKEY structure, allowing,
for the first time, a fully populated key on import.
### Call-outs:
__Core Implementation:__
- __`crypto/evp_extra/p_kem_asn1.c`__: Enhanced `kem_priv_decode()` to
detect and parse seed format using ASN.1 context-specific tag `[0]`
(stubbed out BOTH format)
- __`crypto/fipsmodule/kem/kem.c`__: Added
`KEM_KEY_set_raw_keypair_from_seed()` function to generate keypairs from
seeds using deterministic ML-KEM functions
- __`crypto/fipsmodule/kem/internal.h`__: Added function declaration for
seed-based key generation
FIPS Questions:
Are we allowed to expose this functionality as part of the FIPS module?
Yes, see https://csrc.nist.gov/projects/post-quantum-cryptography/faqs
Question 1:
>Are cryptographic modules implementing FIPS 203 or FIPS 204 allowed to
use seeds as the default key format instead of expanded keys? For
example, in FIPS 203, can a cryptographic module store a 64-byte seed
(d, z) instead of the output (dk, ek) of Algorithm 19 (ML-KEM.KeyGen),
and compute (dk, ek) as needed via (dk, ek) <--
ML-KEM.KeyGen_internal(d, z)?
>
> **Response**:
For both FIPS 203 and FIPS 204, a KeyGen seed is considered an
acceptable alternative format for a key-pair, or for the private (i.e.,
decapsulation or signing) key. In particular, generating the seed in one
cryptographic module and then importing or exporting it into another
cryptographic module is allowed. The internal key generation functions
ML-KEM.KeyGen_Internal(d, z) and ML-DSA.KeyGen_internal(ξ) can be
accessed for this purpose.
### Testing:
- __`crypto/evp_extra/p_kem_test.cc`__: Added comprehensive
`ParsePrivateKeySeed` test using IETF standard test vectors
- Added test vectors for ML-KEM-512, ML-KEM-768, and ML-KEM-1024 seed
formats from Appendix C of the draft standard
- Tests verify that seed-generated keypairs match expected public keys
from the standard
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.
---------
Co-authored-by: Sean McGrail <[email protected]>
Co-authored-by: Justin W Smith <[email protected]>
0 commit comments