Initial ML-KEM documentation
Reviewed-by: Viktor Dukhovni <viktor@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/26037)
This commit is contained in:
parent
42436eb53e
commit
78df1c1f61
8 changed files with 330 additions and 3 deletions
|
@ -4619,6 +4619,10 @@ DEPEND[html/man7/EVP_KEM-EC.html]=man7/EVP_KEM-EC.pod
|
|||
GENERATE[html/man7/EVP_KEM-EC.html]=man7/EVP_KEM-EC.pod
|
||||
DEPEND[man/man7/EVP_KEM-EC.7]=man7/EVP_KEM-EC.pod
|
||||
GENERATE[man/man7/EVP_KEM-EC.7]=man7/EVP_KEM-EC.pod
|
||||
DEPEND[html/man7/EVP_KEM-ML-KEM.html]=man7/EVP_KEM-ML-KEM.pod
|
||||
GENERATE[html/man7/EVP_KEM-ML-KEM.html]=man7/EVP_KEM-ML-KEM.pod
|
||||
DEPEND[man/man7/EVP_KEM-ML-KEM.7]=man7/EVP_KEM-ML-KEM.pod
|
||||
GENERATE[man/man7/EVP_KEM-ML-KEM.7]=man7/EVP_KEM-ML-KEM.pod
|
||||
DEPEND[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
|
||||
GENERATE[html/man7/EVP_KEM-RSA.html]=man7/EVP_KEM-RSA.pod
|
||||
DEPEND[man/man7/EVP_KEM-RSA.7]=man7/EVP_KEM-RSA.pod
|
||||
|
@ -4755,6 +4759,10 @@ DEPEND[html/man7/EVP_PKEY-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod
|
|||
GENERATE[html/man7/EVP_PKEY-ML-DSA.html]=man7/EVP_PKEY-ML-DSA.pod
|
||||
DEPEND[man/man7/EVP_PKEY-ML-DSA.7]=man7/EVP_PKEY-ML-DSA.pod
|
||||
GENERATE[man/man7/EVP_PKEY-ML-DSA.7]=man7/EVP_PKEY-ML-DSA.pod
|
||||
DEPEND[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod
|
||||
GENERATE[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod
|
||||
DEPEND[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.pod
|
||||
GENERATE[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.pod
|
||||
DEPEND[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
|
||||
GENERATE[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
|
||||
DEPEND[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
|
||||
|
@ -5121,6 +5129,7 @@ html/man7/EVP_KDF-X942-ASN1.html \
|
|||
html/man7/EVP_KDF-X942-CONCAT.html \
|
||||
html/man7/EVP_KDF-X963.html \
|
||||
html/man7/EVP_KEM-EC.html \
|
||||
html/man7/EVP_KEM-ML-KEM.html \
|
||||
html/man7/EVP_KEM-RSA.html \
|
||||
html/man7/EVP_KEM-X25519.html \
|
||||
html/man7/EVP_KEYEXCH-DH.html \
|
||||
|
@ -5155,6 +5164,7 @@ html/man7/EVP_PKEY-EC.html \
|
|||
html/man7/EVP_PKEY-FFC.html \
|
||||
html/man7/EVP_PKEY-HMAC.html \
|
||||
html/man7/EVP_PKEY-ML-DSA.html \
|
||||
html/man7/EVP_PKEY-ML-KEM.html \
|
||||
html/man7/EVP_PKEY-RSA.html \
|
||||
html/man7/EVP_PKEY-SM2.html \
|
||||
html/man7/EVP_PKEY-X25519.html \
|
||||
|
@ -5270,6 +5280,7 @@ man/man7/EVP_KDF-X942-ASN1.7 \
|
|||
man/man7/EVP_KDF-X942-CONCAT.7 \
|
||||
man/man7/EVP_KDF-X963.7 \
|
||||
man/man7/EVP_KEM-EC.7 \
|
||||
man/man7/EVP_KEM-ML-KEM.7 \
|
||||
man/man7/EVP_KEM-RSA.7 \
|
||||
man/man7/EVP_KEM-X25519.7 \
|
||||
man/man7/EVP_KEYEXCH-DH.7 \
|
||||
|
@ -5304,6 +5315,7 @@ man/man7/EVP_PKEY-EC.7 \
|
|||
man/man7/EVP_PKEY-FFC.7 \
|
||||
man/man7/EVP_PKEY-HMAC.7 \
|
||||
man/man7/EVP_PKEY-ML-DSA.7 \
|
||||
man/man7/EVP_PKEY-ML-KEM.7 \
|
||||
man/man7/EVP_PKEY-RSA.7 \
|
||||
man/man7/EVP_PKEY-SM2.7 \
|
||||
man/man7/EVP_PKEY-X25519.7 \
|
||||
|
|
122
doc/designs/ML-KEM.md
Normal file
122
doc/designs/ML-KEM.md
Normal file
|
@ -0,0 +1,122 @@
|
|||
ML-KEM Design
|
||||
=============
|
||||
|
||||
This document covers OpenSSL specific ML-KEM implementation details.
|
||||
[FIPS 203](https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.203.pdf)
|
||||
clearly states most of the requirements of ML-KEM and has comprehensive
|
||||
pseudo code for all its algorithms.
|
||||
|
||||
ML-KEM Parameters & Functions
|
||||
-----------------------------
|
||||
|
||||
There are 3 different parameter sets in FIPS 203 (see Section 8).
|
||||
There are constants related to these, as well as there being a group of
|
||||
functions associated with each set.
|
||||
|
||||
To support these variants, OpenSSL will have 3 different key managers and 3
|
||||
corresponding KEM function sets. The names used are of the form "ML-KEM-768".
|
||||
|
||||
The key problem implementing the different variants lies in the significant
|
||||
differences in (dimensions of) vectors and matrics required. For this reason,
|
||||
[boringssl](https://boringssl.googlesource.com/boringssl/+/HEAD/crypto/mlkem)
|
||||
chose to use C++ templates to represent the different parameter sets.
|
||||
As C++ cannot be used in OpenSSL, (object) code duplication by way of use
|
||||
of macros to minimize source code duplication is used. Note that C++ templates are also specialised at compile time to the specific types at which they are instantiated, so there's not in fact much difference in the resulting code size. Templates are in this regard just a cleaner, more expressive "macro" system.
|
||||
|
||||
ML-KEM makes extensive use of SHA3 primitives, SHA3-256, SHA3-512, SHAKE256 and SHAKE128.
|
||||
To improve ML-KEM execution performance the EVP handles for these are pre-fetched during ML-KEM
|
||||
key initialisation and stored in an ossl_ml_kem_ctx object.
|
||||
These are then used in key generation, encapsulation and decapsulation.
|
||||
The context is also duplicated (EVP_MD handles uprefed) when the ML-KEM key is duplicated.
|
||||
|
||||
This ossl_ml_kem_ctx is then passed to all functions.
|
||||
As already noted, it is presently allocated on a per-key basis in the providers'
|
||||
ML-KEM key context, but if there's some way to do this just once during provider
|
||||
initialisation, or once per thread, ... performance might noticeably improve.
|
||||
|
||||
ML-KEM keys
|
||||
-----------
|
||||
|
||||
As expected, ML-KEM has both public and private keys.
|
||||
Since the public key is exchanged between the two parties as part of key
|
||||
agreement, the encoding (wire-form) of the public key is clearly defined and
|
||||
there are unambiguous choices for its encoding and decoding functions.
|
||||
|
||||
It may be noted that the wire-form public key is "compressed".
|
||||
Instead of the bulky "A" ("m" in the code) matrix, which represents the majority
|
||||
of the storage required for ML-KEM public and private keys, the wire-form public
|
||||
key, holds a 32-byte seed from which one can regenerate the matrix.
|
||||
The full matrix is in memory in the internal form (needed for computations) of
|
||||
the public key (which in our implementation is simply a reference into the internal
|
||||
form of the private key when both are known).
|
||||
It is possible to save space and compute the matrix elements just-in-time, as-needed,
|
||||
which would not have a performance impact on the encapsulation step (typically server)
|
||||
where each matrix element is used exactly once!
|
||||
|
||||
However, the same matrix is used both during key generation and decapsulation and
|
||||
computing it twice would have a noticeable performance impact (typically on the client).
|
||||
If we wanted to do just-in-time matrix computation for decapsulation, we'd need to have
|
||||
a different memory layout for public keys when only the public key is known, and to change
|
||||
the algorithm code to generate matrix elements on demand during encapsulation. This can
|
||||
be considered later, if it is determined that the space savings (9*512 bytes in memory for
|
||||
ML-KEM-768, for the full matrix, instead of 512 bytes for a just-in-time element) this could
|
||||
be considered later, but the server will generally destroy the client public key soon after the
|
||||
shared secret is computed, so these don't stay in memory long, so briefly saving ~2KB may
|
||||
not to be of much benefit).
|
||||
|
||||
The private key format is somewhat ad hoc, though (to be able to fully describe the algorithms)
|
||||
FIPS 203 documents a format that is commonly referred to as the "extended"
|
||||
format and also exportable/importable via encoding functions in well-defined
|
||||
sizes. The IETF voices interest in using the "seed-based" format (the (d,z) seed
|
||||
pair from which the key is generated and can be recovered). This is supported by the
|
||||
FIPS 203 internal deterministic key generation functions, which are "testing only".
|
||||
We naturally use this for running the Known Answer Tests, but our private key encoding
|
||||
format is the full expanded key, not the 64 byte (d,z) seed pair.
|
||||
|
||||
The design therefore caters to both options: The default key generation and
|
||||
KEM encapsulation/decapsulation functions operate on/with "extended keys".
|
||||
It is also possible to use the "seed-based" format by way of providing
|
||||
specific OSSL_PARAMs made available for that purpose -- but again, as per
|
||||
NIST guidance, only for testing. If the seed version is retrieved from a
|
||||
normal key generation operation, it shall be subject to the same level of
|
||||
protection given to private key material.
|
||||
|
||||
Key generation API
|
||||
------------------
|
||||
|
||||
Keys can therefore be generated as "usual" by way of the EVP functions
|
||||
EVP_PKEY_generate() and EVP_PKEY_Q_keygen().
|
||||
|
||||
An explicit seed can be specified by setting the OSSL_PARAM value
|
||||
"OSSL_PKEY_PARAM_ML_KEM_SEED" to a 64-byte octet-string before key generation.
|
||||
The octet-string value must be the concatenation of the B<d> and B<z> strings in that
|
||||
order.
|
||||
|
||||
KEM API
|
||||
-------
|
||||
|
||||
ML-KEM is meant to be a simple replacement for existing KEM algorithms.
|
||||
Therefore, simple use should be
|
||||
|
||||
EVP_PKEY_encapsulate_init(), EVP_PKEY_encapsulate(),
|
||||
EVP_PKEY_decapsulate_init(), EVP_PKEY_decapsulate().
|
||||
|
||||
For the encapsulation operation, a test-only option exists to avoid the
|
||||
otherwise mandatory use of a random number generator for passing in a
|
||||
known "entropy" by way of the OSSL_PARAM "OSSL_KEM_PARAM_IKME".
|
||||
|
||||
Buffers
|
||||
-------
|
||||
|
||||
There are many functions passing buffers of sizes dependent on algorithm
|
||||
(version). It therefore is required to properly check/allocate buffers of
|
||||
suitable sizes as defined in the core "mlkem.h" header file. These size
|
||||
checks are performed within the provider logic. The core crypto APIs for
|
||||
any ML-KEM algorithm are not to be exposed and called by external users.
|
||||
|
||||
Constant Time Considerations
|
||||
----------------------------
|
||||
|
||||
The usual constant time methods are used in the implementation. All possible
|
||||
error conditions that can be detected are passed up the call stack to provide
|
||||
the usual OK/NOK status for all required functions.
|
|
@ -93,7 +93,8 @@ Decapsulate data using RSA:
|
|||
|
||||
L<EVP_PKEY_CTX_new_from_pkey(3)>,
|
||||
L<EVP_PKEY_encapsulate(3)>,
|
||||
L<EVP_KEM-RSA(7)>, L<EVP_KEM-X25519(7)>, L<EVP_KEM-EC(7)>
|
||||
L<EVP_KEM-RSA(7)>, L<EVP_KEM-X25519(7)>, L<EVP_KEM-EC(7)>,
|
||||
L<EVP_KEM-ML-KEM-512(7)>, L<EVP_KEM-ML-KEM-768(7)>, L<EVP_KEM-ML-KEM-1024(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
|
@ -102,7 +102,8 @@ Encapsulate an RSASVE key (for RSA keys).
|
|||
|
||||
L<EVP_PKEY_CTX_new_from_pkey(3)>,
|
||||
L<EVP_PKEY_decapsulate(3)>,
|
||||
L<EVP_KEM-RSA(7)>, L<EVP_KEM-X25519(7)>, L<EVP_KEM-EC(7)>
|
||||
L<EVP_KEM-RSA(7)>, L<EVP_KEM-X25519(7)>, L<EVP_KEM-EC(7)>,
|
||||
L<EVP_KEM-ML-KEM-512(7)>, L<EVP_KEM-ML-KEM-768(7)>, L<EVP_KEM-ML-KEM-1024(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
65
doc/man7/EVP_KEM-ML-KEM.pod
Normal file
65
doc/man7/EVP_KEM-ML-KEM.pod
Normal file
|
@ -0,0 +1,65 @@
|
|||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
EVP_KEM-ML-KEM-512,EVP_KEM-ML-KEM-768,EVP_KEM-ML-KEM-1024,EVP_KEM-ML-KEM
|
||||
- EVP_KEM ML-KEM keytype and algorithm support
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<ML-KEM> keytypes and parameters are described in L<EVP_PKEY-ML-KEM(7)>.
|
||||
See L<EVP_PKEY_encapsulate(3)> and L<EVP_PKEY_decapsulate(3)> for more info
|
||||
regarding the basic KEM operations.
|
||||
|
||||
=head2 ML-KEM KEM parameters
|
||||
|
||||
=over 4
|
||||
|
||||
=item "ikme" (B<OSSL_KEM_PARAM_IKME>)<UTF8 string>
|
||||
|
||||
The OpenSSL ML-KEM encapsulation mechanism can only be modified by
|
||||
setting randomness during encapsulation facilitating testing as per
|
||||
FIPS 203, section 6.2, algorithm 17.
|
||||
|
||||
This parameter is not to be set for other purposes than testing.
|
||||
This parameter is disabled for use in the FIPS provider (TODO(ML-KEM)).
|
||||
|
||||
When this parameter is not set, encapsulation proceeds as per FIPS 203,
|
||||
section 7.2
|
||||
|
||||
This parameter is only settable.
|
||||
|
||||
=back
|
||||
|
||||
This can be set when using EVP_PKEY_encapsulate_init().
|
||||
|
||||
=head1 CONFORMING TO
|
||||
|
||||
=over 4
|
||||
|
||||
=item FIPS203
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<EVP_PKEY_encapsulate(3)>,
|
||||
L<EVP_PKEY_decapsulate(3)>
|
||||
L<EVP_KEYMGMT(3)>,
|
||||
L<EVP_PKEY(3)>,
|
||||
L<provider-keymgmt(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
This functionality was added in OpenSSL 3.5.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
113
doc/man7/EVP_PKEY-ML-KEM.pod
Normal file
113
doc/man7/EVP_PKEY-ML-KEM.pod
Normal file
|
@ -0,0 +1,113 @@
|
|||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
EVP_PKEY-ML-KEM-512,
|
||||
EVP_PKEY-ML-KEM-768,
|
||||
EVP_PKEY-ML-KEM-1024,
|
||||
EVP_KEYMGMT-ML-KEM-512,
|
||||
EVP_KEYMGMT-ML-KEM-768,
|
||||
EVP_KEYMGMT-ML-KEM-1024,
|
||||
EVP_PKEY-ML-KEM
|
||||
- ML-KEM keytype and algorithm support
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The B<ML-KEM-512>, B<ML-KEM-768>, and B<ML-KEM-1024> keytypes are implemented in
|
||||
OpenSSL's default provider.
|
||||
|
||||
=for comment (TODO(ML-KEM): Add FIPS support).
|
||||
|
||||
=head2 Keygen Parameters
|
||||
|
||||
By default, no parameters are required for generating a key pair.
|
||||
|
||||
=over 4
|
||||
|
||||
=item "seed" (B<OSSL_PKEY_PARAM_ML_KEM_SEED>) <octet string>
|
||||
|
||||
ML-KEM internally requires the generation of a keypair using a random value (seed).
|
||||
This optional parameter can be used to set the value prior to key pair generation.
|
||||
According to FIPS 203, section 3.3, this parameter should only be used for
|
||||
test purposes and be treated with the same care as private key material.
|
||||
The length of the seed is 64 bytes.
|
||||
|
||||
This parameter is only settable.
|
||||
|
||||
See L<provider-keymgmt(7)/Common Information Parameters> for further information.
|
||||
|
||||
=back
|
||||
|
||||
Use EVP_PKEY_CTX_set_params() after calling EVP_PKEY_keygen_init().
|
||||
|
||||
=head2 Common parameters
|
||||
|
||||
In addition to the common parameters that all keytypes should support (see
|
||||
L<provider-keymgmt(7)/Common parameters>), the implementation of these keytypes
|
||||
support the following.
|
||||
|
||||
=over 4
|
||||
|
||||
=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
|
||||
|
||||
The public key value.
|
||||
|
||||
This parameter is used when importing or exporting the public key value with the
|
||||
EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
|
||||
|
||||
=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
|
||||
|
||||
The private key value.
|
||||
|
||||
This parameter is used when importing or exporting the public key value with the
|
||||
EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
|
||||
|
||||
=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
|
||||
|
||||
Used for getting and setting the encoding of a public key. Public keys are
|
||||
expected be encoded in a format as defined by FIPS 203.
|
||||
|
||||
This parameter is gettable and settable.
|
||||
|
||||
=back
|
||||
|
||||
=head1 CONFORMING TO
|
||||
|
||||
=over 4
|
||||
|
||||
=item FIPS 203
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
An B<EVP_PKEY> context can be obtained by calling:
|
||||
|
||||
EVP_PKEY_CTX *pctx =
|
||||
EVP_PKEY_CTX_new_from_name(NULL, "ML-KEM-768", NULL);
|
||||
|
||||
An B<ML-KEM-768> key can be generated like this:
|
||||
|
||||
pkey = EVP_PKEY_Q_keygen(NULL, NULL, "ML-KEM-768");
|
||||
|
||||
Equivalent calls are possible for B<ML-KEM-512> and B<ML-KEM-1024>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<EVP_KEYMGMT(3)>, L<EVP_PKEY(3)>, L<provider-keymgmt(7)>,
|
||||
L<EVP_KEM-ML-KEM(7)>
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
This functionality was added in OpenSSL 3.5.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License 2.0 (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
L<https://www.openssl.org/source/license.html>.
|
||||
|
||||
=cut
|
|
@ -229,6 +229,12 @@ The OpenSSL default provider supports these operations and algorithms:
|
|||
|
||||
=item EC, see L<EVP_KEM-EC(7)>
|
||||
|
||||
=item ML-KEM-512, see L<EVP_KEM-ML-KEM-512(7)>
|
||||
|
||||
=item ML-KEM-768, see L<EVP_KEM-ML-KEM-768(7)>
|
||||
|
||||
=item ML-KEM-1024, see L<EVP_KEM-ML-KEM-1024(7)>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Asymmetric Key Management
|
||||
|
@ -277,6 +283,12 @@ The OpenSSL default provider supports these operations and algorithms:
|
|||
|
||||
=item ML-DSA-87, see L<EVP_KEYMGMT-ML-DSA(7)>
|
||||
|
||||
=item ML-KEM-512, see L<EVP_KEYMGMT-ML-KEM-512(7)>
|
||||
|
||||
=item ML-KEM-768, see L<EVP_KEYMGMT-ML-KEM-768(7)>
|
||||
|
||||
=item ML-KEM-1024, see L<EVP_KEYMGMT-ML-KEM-1024(7)>
|
||||
|
||||
=back
|
||||
|
||||
=head2 Random Number Generation
|
||||
|
|
|
@ -502,7 +502,8 @@ L<EVP_PKEY_get_security_bits(3)>,
|
|||
L<provider(7)>,
|
||||
L<EVP_PKEY-X25519(7)>, L<EVP_PKEY-X448(7)>, L<EVP_PKEY-ED25519(7)>,
|
||||
L<EVP_PKEY-ED448(7)>, L<EVP_PKEY-EC(7)>, L<EVP_PKEY-RSA(7)>,
|
||||
L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-ML-DSA(7)>
|
||||
L<EVP_PKEY-DSA(7)>, L<EVP_PKEY-DH(7)>, L<EVP_PKEY-ML-DSA(7)>,
|
||||
L<EVP_PKEY-ML-KEM(7)>.
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue