Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27175)
(cherry picked from commit 60f2a714002365256dba1c55bb4dd46802ea14d6)
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26765)
- Also added a provider "validate" method that wraps the PCT test.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26656)
- Moved the codec code out of `ml_kem.c` into its own file in
the provider tree. Will be easier to share some code with
ML-DSA, and possible to use PROV_CTX, to do config lookups
directly in the functions doing the work.
- Update and fixes of the EVP_PKEY-ML-KEM(8) documentation, which
had accumulated some stale/inaccurate material, and needed new
text for the "prefer_seed" parameter.
- Test the "prefer_seed=no" behaviour.
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/26569)
- On import, if a seed is provided, the keys are regenerated.
- The seed is exported as a separate "seed" parameter, when available.
The "ml-kem.retain_seed" parameter is also exported, when false.
- The seed is optionally dropped after key generation.
* When the "ml-kem.retain_seed" keygen parameter is set to zero.
* When the "ml-kem.retain_seed" keygen parameter is not set to 1,
and the "ml-kem.retain_seed" provider config property is set
explictly false.
- The exported private key parameter "priv" is always the FIPS 203 |dk|.
- Private key decoding from PKCS#8 produces a transient "seed-only" form
of the key, in which "retain_seed" is set to false when the
"ml-kem.retain_seed" provider config property is set explictly false.
The full key is generated during "load" and the seed is retained
or not as specified.
- Import honours the "ml-kem.retain_seed" parameter when specified, or
otherwise honours the provider's "ml-kem.retain_seed" property.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26512)
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26456)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26341)
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26341)
Also avoid a file name conflict when adding ML-KEM to the FIPS provider.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Hugo Landau <hlandau@devever.net>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26338)
- When used as KEMs in TLS the ECDHE algorithms are NOT subjected to
HPKE Extract/Expand key derivation. Instead the TLS HKDF is used
as usual.
- Consequently these KEMs are just the usual ECDHE key exchange
operations, be it with the encap ECDH private key unavoidably
ephemeral.
- A new "MLX" KEM provider is added that supports four hybrids of EC/ECX
DH with ML-KEM:
* ML-KEM-768 + X25519
* ML-KEM-1024 + X448
* P-256 + ML-KEM-768
* P-384 + ML-KEM-1024
- Support listing of implemented TLS groups.
The SSL_CTX_get0_implemented_groups() function and new
`openssl list -tls-groups` and `openssl list -all-tls-groups`
commands make it possible to determine which groups are
implemented by the SSL library for a particular TLS version
or range of versions matching an SSL_CTX.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26220)
Loosely based on similar code in BoringSSL.
Added the valgrind macros necessary to mark secret inputs as uninitialised on
entry to the ML-KEM keygen, encap and decap functions. The inputs and outputs
are then untagged before control returns to the caller, where, at least in the
case of tests and protocols that check whether the derived keys succeeded in
decoding a key-confirmation message, there will at some point be a branch based
on the *content* of the compute shared secret.
When a build is configured with `-DOPENSSL_CONSTANT_TIME_VALIDATION`, and
various tests that use ML-KEM are run under:
$ valgrind --tool=memcheck --error-exitcode=1 --exit-on-first-error=yes cmd [args]
any internal secret-data-dependent branches added by a mis-optimising
compiler, or inadvertently introduced into the source code would cause
the tests to fail, exposing the side channel.
Since the side-channels are liable to depend on the compiler and
selected optimisation flags, tests would need to cover a few combinations.
* clang vs. gcc
* debug builds
* default builds
* -O2
* -O3 -fno-vectorise (a problem with clang in "clangover")
* -Os (was a problem with clang in "clangover")
...
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26270)
* Core ML_KEM constants in new <openssl/ml_kem.h>
* Renamed variant ordinals to ML_KEM_<bits>_VARIANT, freeing
up the unadorned ML_KEM_<bits> names.
* Fewer/cleaner macros in <crypto/ml_kem.h>
* Fewer/cleaner macros for setting up the ML_KEM_VINFO table.
* Made (d, z) be separate inputs to the now single key generation
function. Both or neither have to be NULL. This supports potential
future callers that store them in a different order, or in separate
buffers.
- Random values are chosen when both are NULL, we never return the
generated seeds, rather we may, when/if (d, z) private key support
is added, store these in the expanded key, and make them available
for import/export.
* No need for a stand-by keygen encoded public key buffer when the
caller does not provide one (will ask for it later if needed).
New `hash_h_pubkey` function can compute the public hash from
the expanded form in constant space (384 bytes for 12-bit encoded
scalar).
* Simplified code in `scalar_mult`.
* New `scalar_mult_add` adds the product to an existing scalar.
Used in new `matrix_mult_transpose_add` replacing `matrix_mult_transpose`.
* Unrolled loop in `encode_12`.
* Folded decompression and inverse NTT into vecode_decode, the three
were always used together.
* Folded inverse NTT into former `matrix_mult` as `matrix_mult_intt`,
always used together.
* New gencbd_vector_ntt combines CBD vector generation with inverse NTT
in one pass.
* All this makes for more readable code in `decrypt_cpa` and especially
`genkey()`, which no longer requires caller-allocated variant-specific
temporary storage (just a single EVP_MD_CTX is still needed).
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26236)
This introduces support for ML-KEM-512 and ML-KEM-1024 using the same
underlying implementation parameterised by a few macros for the
associated types and constants.
KAT tests are added for ML-KEM 512 and 1024, to complement the previous
tests for ML-KEM-768.
MLKEM{512,768,1024} TLS "group" codepoints are updated to match the
final IANA assigments and to make the additional KEMs known to the TLS
layer.
The pure-QC MLKEMs are not in the default list of supported groups, and
need to be explicitly enabled by the application. Future work will
introduce support for hybrids, and for more fine-grained policy of
which keyshares a client should send by default, and when a server
should request (HRR) a new mutually-supported group that was not
sent.
Tests for ML-KEM key exchange added to sslapitest to make sure that our
TLS client MLKEM{512,768,1024} implementations interoperate with our TLS
server, and that MLKEM* are not negotiated in TLS 1.2.
Tests also added to excercise non-derandomised ML-KEM APIs, both
directly (bypassing the provider layer), and through the generic EVP KEM
API (exercising the provider). These make sure that RNG input is used
correctly (KAT tests bypass the RNG by specifying seeds).
The API interface to the provider takes an "const ML_KEM_VINFO" pointer,
(obtained from ossl_ml_kem_get_vinfo()). This checks input and output
buffer sizes before passing control to internal code that assumes
correctly sized (for each variant) buffers.
The original BoringSSL API was refactored to eliminate the opaque
public/private key structure wrappers, since these structures are an
internal detail between libcrypto and the provider, they are not part of
the public (EVP) API.
New "clangover" counter-measures added, refined with much appreciated
input from David Benjamin (Chromium).
The internal steps of "encrypt_cpa" were reordered to reduce the
working-set size of the algorithm, now needs space for just two
temporary "vectors" rather than three. The "decap" function now process
the decrypted message in one call, rather than three separate calls to
scalar_decode_1, scalar_decompress and scalar_add.
Some loops were unrolled, improving performance of en/decapsulate
(pre-expanded vectors and matrix) by around 5%.
To handle, however unlikely, the SHA3 primitives not behaving like
"pure" functions and failing, the implementation of `decap` was modifed:
- To use the KDF to compute the Fujisaki-Okamoto (FO) failure secret
first thing, and if that fails, bail out returning an error, a shared
secret is still returned at random from the RNG, but it is OK for the
caller to not use it.
- If any of the subsequently used hash primitives fail, use the computed
FO failure secret (OK, despite no longer constant-time) and return
success (otherwise the RNG would replace the result).
- We quite reasonably assume that chosen-ciphertext attacks (of the
correct length) cannot cause hash functions to fail in a manner the
depends on the private key content.
Support for ML-KEM-512 required adding a centered binomial distribution
helper function to deal with η_1 == 3 in just that variant.
Some additional comments were added to highlight how the code relates to
the ML-KEM specification in FIPS 203.
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/26172)