mirror of
https://github.com/openssl/openssl.git
synced 2025-03-31 20:10:45 +08:00
ML-KEM hybrids for TLS
- 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)
This commit is contained in:
parent
95d764a044
commit
4b1c73d2dd
@ -12,6 +12,7 @@ Groups
|
||||
|
||||
* OpenSSL Software Services, Inc.
|
||||
* OpenSSL Software Foundation, Inc.
|
||||
* Google LLC
|
||||
|
||||
Individuals
|
||||
-----------
|
||||
|
93
apps/list.c
93
apps/list.c
@ -23,6 +23,8 @@
|
||||
#include <openssl/store.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/safestack.h>
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/tls1.h>
|
||||
#include "apps.h"
|
||||
#include "app_params.h"
|
||||
@ -776,6 +778,42 @@ static int list_tls_sigalg_caps(OSSL_PROVIDER *provider, void *cbdata)
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
|
||||
static void list_tls_groups(int version, int all)
|
||||
{
|
||||
SSL_CTX *ctx = NULL;
|
||||
STACK_OF(OPENSSL_CSTRING) *groups;
|
||||
size_t i, num;
|
||||
|
||||
if ((groups = sk_OPENSSL_CSTRING_new_null()) == NULL) {
|
||||
BIO_printf(bio_err, "ERROR: Memory allocation\n");
|
||||
return;
|
||||
}
|
||||
if ((ctx = SSL_CTX_new(TLS_method())) == NULL) {
|
||||
BIO_printf(bio_err, "ERROR: Memory allocation\n");
|
||||
goto err;
|
||||
}
|
||||
if (!SSL_CTX_set_min_proto_version(ctx, version)
|
||||
|| !SSL_CTX_set_max_proto_version(ctx, version)) {
|
||||
BIO_printf(bio_err, "ERROR: setting TLS protocol version\n");
|
||||
goto err;
|
||||
}
|
||||
if (!SSL_CTX_get0_implemented_groups(ctx, all, groups)) {
|
||||
BIO_printf(bio_err, "ERROR: getting implemented TLS group list\n");
|
||||
goto err;
|
||||
}
|
||||
num = sk_OPENSSL_CSTRING_num(groups);
|
||||
for (i = 0; i < num; ++i) {
|
||||
BIO_printf(bio_out, "%s%c", sk_OPENSSL_CSTRING_value(groups, i),
|
||||
(i < num - 1) ? ':' : '\n');
|
||||
}
|
||||
err:
|
||||
SSL_CTX_free(ctx);
|
||||
sk_OPENSSL_CSTRING_free(groups);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void list_tls_signatures(void)
|
||||
{
|
||||
int tls_sigalg_listed = 0;
|
||||
@ -1515,6 +1553,15 @@ typedef enum HELPLIST_CHOICE {
|
||||
OPT_TLS_SIGNATURE_ALGORITHMS, OPT_ASYM_CIPHER_ALGORITHMS,
|
||||
OPT_STORE_LOADERS, OPT_PROVIDER_INFO, OPT_OBJECTS,
|
||||
OPT_SELECT_NAME,
|
||||
#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
|
||||
OPT_ALL_TLS_GROUPS, OPT_TLS_GROUPS,
|
||||
# if !defined(OPENSSL_NO_TLS1_2)
|
||||
OPT_TLS1_2,
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_TLS1_3)
|
||||
OPT_TLS1_3,
|
||||
# endif
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
OPT_ENGINES,
|
||||
#endif
|
||||
@ -1572,6 +1619,20 @@ const OPTIONS list_options[] = {
|
||||
"List of public key methods"},
|
||||
{"store-loaders", OPT_STORE_LOADERS, '-',
|
||||
"List of store loaders"},
|
||||
#if !defined(OPENSSL_NO_TLS1_2) || !defined(OPENSSL_NO_TLS1_3)
|
||||
{"tls-groups", OPT_TLS_GROUPS, '-',
|
||||
"List implemented TLS key exchange 'groups'" },
|
||||
{"all-tls-groups", OPT_ALL_TLS_GROUPS, '-',
|
||||
"List implemented TLS key exchange 'groups' and all aliases" },
|
||||
# ifndef OPENSSL_NO_TLS1_2
|
||||
{"tls1_2", OPT_TLS1_2, '-',
|
||||
"When listing 'groups', list those compatible with TLS1.2"},
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_TLS1_3
|
||||
{"tls1_3", OPT_TLS1_3, '-',
|
||||
"When listing 'groups', list those compatible with TLS1.3"},
|
||||
# endif
|
||||
#endif
|
||||
{"providers", OPT_PROVIDER_INFO, '-',
|
||||
"List of provider information"},
|
||||
#ifndef OPENSSL_NO_DEPRECATED_3_0
|
||||
@ -1594,6 +1655,14 @@ int list_main(int argc, char **argv)
|
||||
HELPLIST_CHOICE o;
|
||||
int one = 0, done = 0;
|
||||
int print_newline = 0;
|
||||
#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
|
||||
int all_tls_groups = 0;
|
||||
# if !defined(OPENSSL_NO_TLS1_3)
|
||||
unsigned int tls_version = TLS1_3_VERSION;
|
||||
# else
|
||||
unsigned int tls_version = TLS1_2_VERSION;
|
||||
# endif
|
||||
#endif
|
||||
struct {
|
||||
unsigned int commands:1;
|
||||
unsigned int all_algorithms:1;
|
||||
@ -1612,6 +1681,7 @@ int list_main(int argc, char **argv)
|
||||
unsigned int tls_signature_algorithms:1;
|
||||
unsigned int keyexchange_algorithms:1;
|
||||
unsigned int kem_algorithms:1;
|
||||
unsigned int tls_groups:1;
|
||||
unsigned int asym_cipher_algorithms:1;
|
||||
unsigned int pk_algorithms:1;
|
||||
unsigned int pk_method:1;
|
||||
@ -1692,6 +1762,25 @@ opthelp:
|
||||
case OPT_KEM_ALGORITHMS:
|
||||
todo.kem_algorithms = 1;
|
||||
break;
|
||||
#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
|
||||
case OPT_TLS_GROUPS:
|
||||
todo.tls_groups = 1;
|
||||
break;
|
||||
case OPT_ALL_TLS_GROUPS:
|
||||
all_tls_groups = 1;
|
||||
todo.tls_groups = 1;
|
||||
break;
|
||||
# if !defined(OPENSSL_NO_TLS1_2)
|
||||
case OPT_TLS1_2:
|
||||
tls_version = TLS1_2_VERSION;
|
||||
break;
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_TLS1_3)
|
||||
case OPT_TLS1_3:
|
||||
tls_version = TLS1_3_VERSION;
|
||||
break;
|
||||
# endif
|
||||
#endif
|
||||
case OPT_ASYM_CIPHER_ALGORITHMS:
|
||||
todo.asym_cipher_algorithms = 1;
|
||||
break;
|
||||
@ -1811,6 +1900,10 @@ opthelp:
|
||||
MAYBE_ADD_NL(list_keyexchanges());
|
||||
if (todo.kem_algorithms)
|
||||
MAYBE_ADD_NL(list_kems());
|
||||
#if !defined(OPENSSL_NO_TLS1_3) || !defined(OPENSSL_NO_TLS1_2)
|
||||
if (todo.tls_groups)
|
||||
MAYBE_ADD_NL(list_tls_groups(tls_version, all_tls_groups));
|
||||
#endif
|
||||
if (todo.pk_algorithms)
|
||||
MAYBE_ADD_NL(list_pkey());
|
||||
if (todo.pk_method)
|
||||
|
@ -1141,6 +1141,8 @@ PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
|
||||
PROV_R_NO_INSTANCE_ALLOWED:242:no instance allowed
|
||||
PROV_R_NO_KEY_SET:114:no key set
|
||||
PROV_R_NO_PARAMETERS_SET:177:no parameters set
|
||||
PROV_R_NULL_LENGTH_POINTER:247:null length pointer
|
||||
PROV_R_NULL_OUTPUT_BUFFER:245:null output buffer
|
||||
PROV_R_ONESHOT_CALL_OUT_OF_ORDER:239:oneshot call out of order
|
||||
PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE:178:\
|
||||
operation not supported for this keytype
|
||||
@ -1176,9 +1178,11 @@ PROV_R_UNSUPPORTED_CEK_ALG:145:unsupported cek alg
|
||||
PROV_R_UNSUPPORTED_KEY_SIZE:153:unsupported key size
|
||||
PROV_R_UNSUPPORTED_MAC_TYPE:137:unsupported mac type
|
||||
PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS:152:unsupported number of rounds
|
||||
PROV_R_UNSUPPORTED_SELECTION:248:unsupported selection
|
||||
PROV_R_UPDATE_CALL_OUT_OF_ORDER:240:update call out of order
|
||||
PROV_R_URI_AUTHORITY_UNSUPPORTED:223:uri authority unsupported
|
||||
PROV_R_VALUE_ERROR:138:value error
|
||||
PROV_R_WRONG_CIPHERTEXT_SIZE:246:wrong ciphertext size
|
||||
PROV_R_WRONG_FINAL_BLOCK_LENGTH:107:wrong final block length
|
||||
PROV_R_WRONG_OUTPUT_BUFFER_SIZE:139:wrong output buffer size
|
||||
PROV_R_XOF_DIGESTS_NOT_ALLOWED:183:xof digests not allowed
|
||||
|
@ -7,8 +7,6 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2024, Google Inc. */
|
||||
|
||||
#include <internal/common.h>
|
||||
#include <internal/constant_time.h>
|
||||
#include <internal/sha3.h>
|
||||
|
@ -32,6 +32,10 @@ B<openssl list>
|
||||
[B<-key-managers>]
|
||||
[B<-key-exchange-algorithms>]
|
||||
[B<-kem-algorithms>]
|
||||
[B<-tls-groups>]
|
||||
[B<-all-tls-groups>]
|
||||
[B<-tls1_2>]
|
||||
[B<-tls1_3>]
|
||||
[B<-signature-algorithms>]
|
||||
[B<-tls-signature-algorithms>]
|
||||
[B<-asymcipher-algorithms>]
|
||||
@ -191,6 +195,29 @@ Display a list of key exchange algorithms.
|
||||
|
||||
Display a list of key encapsulation algorithms.
|
||||
|
||||
=item B<-tls-groups>
|
||||
|
||||
Display a list of the IANA names of all available (implemented) TLS groups.
|
||||
By default the listed groups are those compatible with TLS 1.3.
|
||||
|
||||
=item B<-all-tls-groups>
|
||||
|
||||
Display a list of the names of all available (implemented) TLS groups,
|
||||
including any aliases.
|
||||
Some groups are known under multiple names, for example, B<secp256r1> is also
|
||||
known as B<P-256>.
|
||||
By default the listed groups are those compatible with TLS 1.3.
|
||||
|
||||
=item B<-tls1_2>
|
||||
|
||||
When listing TLS groups, list those compatible with TLS 1.2
|
||||
|
||||
=item B<-tls1_3>
|
||||
|
||||
When listing TLS groups, output those compatible with TLS 1.3.
|
||||
TLS 1.3 is the current default protocol version, but the default version is
|
||||
subject to change, so best to specify the version explicitly.
|
||||
|
||||
=item B<-signature-algorithms>
|
||||
|
||||
Display a list of signature algorithms.
|
||||
|
@ -669,11 +669,14 @@ For example strings, see L<SSL_CTX_set1_sigalgs(3)>
|
||||
Specifies the list of supported curves to be sent by the client. The curve is
|
||||
ultimately selected by the server.
|
||||
|
||||
The list of all supported groups includes named EC parameters as well as X25519
|
||||
and X448 or FFDHE groups, and may also include groups implemented in 3rd-party
|
||||
providers. For a list of named EC parameters, use:
|
||||
The list of available groups includes various built-in named EC curves, as well
|
||||
as X25519 and X448, FFDHE groups, and any additional groups implemented in the
|
||||
default or 3rd-party providers.
|
||||
The commands below list the available groups for TLS 1.2 and TLS 1.3,
|
||||
respectively:
|
||||
|
||||
$ openssl ecparam -list_curves
|
||||
$ openssl list -tls1_2 -tls-groups
|
||||
$ openssl list -tls1_3 -tls-groups
|
||||
|
||||
=item B<-cipher> I<cipherlist>
|
||||
|
||||
|
@ -675,11 +675,14 @@ Signature algorithms to support for client certificate authentication
|
||||
|
||||
Specifies the elliptic curve to use. NOTE: this is single curve, not a list.
|
||||
|
||||
The list of all supported groups includes named EC parameters as well as X25519
|
||||
and X448 or FFDHE groups, and may also include groups implemented in 3rd-party
|
||||
providers. For a list of named EC parameters, use:
|
||||
The list of available groups includes various built-in named EC curves, as well
|
||||
as X25519 and X448, FFDHE groups, and any additional groups implemented in the
|
||||
default or 3rd-party providers.
|
||||
The commands below list the available groups for TLS 1.2 and TLS 1.3,
|
||||
respectively.
|
||||
|
||||
$ openssl ecparam -list_curves
|
||||
$ openssl list -tls1_2 -tls-groups
|
||||
$ openssl list -tls1_3 -tls-groups
|
||||
|
||||
=item B<-cipher> I<val>
|
||||
|
||||
|
@ -155,13 +155,36 @@ group to use. This setting affects groups used for signatures (in TLSv1.2
|
||||
and earlier) and key exchange.
|
||||
|
||||
In its simplest form the I<groups> argument is a colon separated list of
|
||||
groups. Each group can be either the B<NIST> name (e.g. B<P-256>), some other
|
||||
commonly used name where applicable (e.g. B<X25519>, B<ffdhe2048>) or an
|
||||
OpenSSL OID name (e.g. B<prime256v1>). Group names are case sensitive. The list
|
||||
should be in order of preference with the most preferred group first.
|
||||
groups. The preferred names are those listed in the IANA
|
||||
L<TLS Supported Groups|https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8>
|
||||
registry.
|
||||
|
||||
For some groups, OpenSSL supports additional aliases.
|
||||
Such an alias could be a B<NIST> name (e.g. B<P-256>), an OpenSSL OID name
|
||||
(e.g. B<prime256v1>), or some other commonly used name.
|
||||
Group names are case sensitive.
|
||||
The list should be in order of preference with the most preferred group first.
|
||||
|
||||
The first group listed will also be used for the B<key_share> sent by a client
|
||||
in a TLSv1.3 B<ClientHello>.
|
||||
|
||||
The commands below list the IANA names for TLS 1.2 and TLS 1.3,
|
||||
respectively:
|
||||
|
||||
$ openssl list -tls1_2 -tls-groups
|
||||
$ openssl list -tls1_3 -tls-groups
|
||||
|
||||
The recommended groups (in order of decreasing performance) for TLS 1.3 are presently:
|
||||
|
||||
B<x25519>,
|
||||
B<secp256r1>,
|
||||
B<x448>,
|
||||
and
|
||||
B<secp384r1>.
|
||||
|
||||
The stronger security margins of the last two, come at a significant
|
||||
performance penalty.
|
||||
|
||||
An enriched alternative syntax, that enables clients to send multiple keyshares
|
||||
and allows servers to prioritise some groups over others, is described in
|
||||
L<SSL_CTX_set1_groups_list(3)>.
|
||||
@ -169,28 +192,6 @@ Since TLS 1.2 has neither keyshares nor a hello retry mechanism, with TLS 1.2
|
||||
the enriched syntax is ultimately equivalent to just a simple ordered list of
|
||||
groups, as with the simple form above.
|
||||
|
||||
The supported groups for B<TLSv1.3> include:
|
||||
B<secp256r1>,
|
||||
B<secp384r1>,
|
||||
B<secp521r1>,
|
||||
B<x25519>,
|
||||
B<x448>,
|
||||
B<brainpoolP256r1tls13>,
|
||||
B<brainpoolP384r1tls13>,
|
||||
B<brainpoolP512r1tls13>,
|
||||
B<ffdhe2048>,
|
||||
B<ffdhe3072>,
|
||||
B<ffdhe4096>,
|
||||
B<ffdhe6144>,
|
||||
B<ffdhe8192>
|
||||
B<MLKEM512>,
|
||||
B<MLKEM768>,
|
||||
and
|
||||
B<MLKEM1024>.
|
||||
|
||||
Additional providers may make available further algorithms via the
|
||||
TLS-GROUP capability. See L<provider-base(7)>.
|
||||
|
||||
=item B<-curves> I<groups>
|
||||
|
||||
This is a synonym for the B<-groups> command.
|
||||
@ -450,30 +451,28 @@ signatures (in TLSv1.2 and earlier) and key exchange. The first group listed
|
||||
will also be used for the B<key_share> sent by a client in a TLSv1.3
|
||||
B<ClientHello>.
|
||||
|
||||
The B<value> argument is a colon separated list of groups. The group can be
|
||||
either the B<NIST> name (e.g. B<P-256>), some other commonly used name where
|
||||
applicable (e.g. B<X25519>, B<ffdhe2048>) or an OpenSSL OID name
|
||||
(e.g. B<prime256v1>). Group names are case sensitive. The list should be in
|
||||
order of preference with the most preferred group first.
|
||||
The B<groups> argument is a colon separated list of groups. The preferred
|
||||
names are those listed in the IANA
|
||||
L<TLS Supported Groups|https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8>
|
||||
registry.
|
||||
For some groups, OpenSSL supports additional aliases.
|
||||
Such an alias could be a B<NIST> name (e.g. B<P-256>), an OpenSSL OID name
|
||||
(e.g. B<prime256v1>), or some other commonly used name.
|
||||
Group names are case sensitive.
|
||||
The list should be in order of preference with the most preferred group first.
|
||||
|
||||
The supported groups for B<TLSv1.3> include:
|
||||
B<secp256r1>,
|
||||
B<secp384r1>,
|
||||
B<secp521r1>,
|
||||
B<x25519>,
|
||||
B<x448>,
|
||||
B<brainpoolP256r1tls13>,
|
||||
B<brainpoolP384r1tls13>,
|
||||
B<brainpoolP512r1tls13>,
|
||||
B<ffdhe2048>,
|
||||
B<ffdhe3072>,
|
||||
B<ffdhe4096>,
|
||||
B<ffdhe6144>,
|
||||
B<ffdhe8192>
|
||||
B<MLKEM512>,
|
||||
B<MLKEM768>,
|
||||
and
|
||||
B<MLKEM1024>.
|
||||
The commands below list the available groups for TLS 1.2 and TLS 1.3,
|
||||
respectively:
|
||||
|
||||
$ openssl list -tls1_2 -tls-groups
|
||||
$ openssl list -tls1_3 -tls-groups
|
||||
|
||||
An enriched alternative syntax, that enables clients to send multiple keyshares
|
||||
and allows servers to prioritise some groups over others, is described in
|
||||
L<SSL_CTX_set1_groups_list(3)>.
|
||||
Since TLS 1.2 has neither keyshares nor a hello retry mechanism, with TLS 1.2
|
||||
the enriched syntax is ultimately equivalent to just a simple ordered list of
|
||||
groups, as with the simple form above.
|
||||
|
||||
=item B<Curves>
|
||||
|
||||
@ -853,7 +852,21 @@ added in OpenSSL 3.2.
|
||||
|
||||
B<PreferNoDHEKEX> was added in OpenSSL 3.3.
|
||||
|
||||
Support for B<ML-KEM> was added in OpenSSL 3.5.
|
||||
OpenSSL 3.5 introduces support for post-quantum (PQ) TLS key exchange via the
|
||||
B<MLKEM512>, B<MLKEM768> and B<MLKEM1024> TLS groups.
|
||||
These are based on the underlying B<ML-KEM-512>, B<ML-KEM-768> and
|
||||
B<ML-KEM-1024> algorithms from FIPS 203.
|
||||
|
||||
OpenSSL 3.5 also introduces support for three I<hybrid> ECDH PQ key exchange
|
||||
TLS I<groups>: B<X25519MLKEM768>, B<SecP256r1MLKEM768> and
|
||||
B<SecP384r1MLKEM1024>.
|
||||
They offer CPU performance comparable to the associated ECDH group, though at
|
||||
the cost of significantly larger key exchange messages.
|
||||
The third group, B<SecP384r1MLKEM1024> is substantially more CPU-intensive,
|
||||
largely as a result of the high CPU cost of ECDH for the underlying B<P-384>
|
||||
group.
|
||||
Also its key exchange messages at close to 1700 bytes are larger than the
|
||||
roughly 1200 bytes for the first two groups.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
|
@ -6,7 +6,7 @@ SSL_CTX_set1_groups, SSL_CTX_set1_groups_list, SSL_set1_groups,
|
||||
SSL_set1_groups_list, SSL_get1_groups, SSL_get0_iana_groups,
|
||||
SSL_get_shared_group, SSL_get_negotiated_group, SSL_CTX_set1_curves,
|
||||
SSL_CTX_set1_curves_list, SSL_set1_curves, SSL_set1_curves_list,
|
||||
SSL_get1_curves, SSL_get_shared_curve
|
||||
SSL_get1_curves, SSL_get_shared_curve, SSL_CTX_get0_implemented_groups
|
||||
- EC supported curve functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
@ -33,6 +33,9 @@ SSL_get1_curves, SSL_get_shared_curve
|
||||
int SSL_get1_curves(SSL *ssl, int *curves);
|
||||
int SSL_get_shared_curve(SSL *s, int n);
|
||||
|
||||
int SSL_CTX_get0_implemented_groups(SSL_CTX *ctx, int all,
|
||||
STACK_OF(OPENSSL_CSTRING) *names);
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
For all of the functions below that set the supported groups there must be at
|
||||
@ -85,24 +88,11 @@ SSL_CTX_set1_groups_list() sets the supported groups for B<ctx> to
|
||||
string I<list>. In contrast to SSL_CTX_set1_groups(), the names of the
|
||||
groups, rather than their NIDs, are used.
|
||||
|
||||
The supported groups for B<TLSv1.3> include:
|
||||
B<P-256>,
|
||||
B<P-384>,
|
||||
B<P-521>,
|
||||
B<X25519>,
|
||||
B<X448>,
|
||||
B<ffdhe2048>,
|
||||
B<ffdhe3072>,
|
||||
B<ffdhe4096>,
|
||||
B<ffdhe6144>
|
||||
B<ffdhe8192>,
|
||||
B<MLKEM512>,
|
||||
B<MLKEM768>,
|
||||
B<MLKEM1024>,
|
||||
B<brainpoolP256r1tls13>,
|
||||
B<brainpoolP384r1tls13>, and
|
||||
B<brainpoolP512r1tls13>.
|
||||
Support for other groups may be added by external providers.
|
||||
The commands below list the available groups for TLS 1.2 and TLS 1.3,
|
||||
respectively:
|
||||
|
||||
$ openssl list -tls1_2 -tls-groups
|
||||
$ openssl list -tls1_3 -tls-groups
|
||||
|
||||
Each group can be either the B<NIST> name (e.g. B<P-256>), some other commonly
|
||||
used name where applicable (e.g. B<X25519>, B<ffdhe2048>) or an OpenSSL OID name
|
||||
@ -226,6 +216,19 @@ current, non-resumption, connection). This can be called by either client or
|
||||
server. If the NID for the shared group is unknown then the value is set to the
|
||||
bitwise OR of TLSEXT_nid_unknown (0x1000000) and the id of the group.
|
||||
|
||||
SSL_CTX_get0_implemented_groups() populates a stack with the names of TLS
|
||||
groups that are compatible with the TLS version of the B<ctx> argument.
|
||||
The returned names are references to internal constants and must not be
|
||||
modified or freed. When B<all> is nonzero, the returned list includes not
|
||||
only the preferred IANA names of the groups, but also any associated aliases.
|
||||
If the SSL_CTX is version-flexible, the groups will be those compatible
|
||||
with any configured minimum and maximum protocol versions.
|
||||
The B<names> stack should be allocated by the caller and be empty, the
|
||||
matching group names are appended to the provided stack.
|
||||
The B<-tls-groups> and B<-all-tls-groups> options of the
|
||||
L<openssl list|openssl-list(1)> command output these lists for either
|
||||
TLS 1.2 or TLS 1.3 (by default).
|
||||
|
||||
All these functions are implemented as macros.
|
||||
|
||||
The curve functions are synonyms for the equivalently named group functions and
|
||||
@ -242,8 +245,9 @@ consider using the SSL_CONF interface instead of manually parsing options.
|
||||
|
||||
=head1 RETURN VALUES
|
||||
|
||||
SSL_CTX_set1_groups(), SSL_CTX_set1_groups_list(), SSL_set1_groups() and
|
||||
SSL_set1_groups_list(), return 1 for success and 0 for failure.
|
||||
SSL_CTX_set1_groups(), SSL_CTX_set1_groups_list(), SSL_set1_groups(),
|
||||
SSL_set1_groups_list(), and SSL_CTX_get0_implemented_groups() return 1 for
|
||||
success and 0 for failure.
|
||||
|
||||
SSL_get1_groups() returns the number of groups, which may be zero.
|
||||
|
||||
@ -275,6 +279,8 @@ SSL_set1_groups_list() was added in OpenSSL 3.3.
|
||||
|
||||
Support for B<ML-KEM> was added in OpenSSL 3.5.
|
||||
|
||||
B<SSL_CTX_get0_implemented_groups> was first implemented in OpenSSL 3.5.
|
||||
|
||||
Earlier versions of this document described the list as a preference order.
|
||||
However, OpenSSL's behavior as a TLS 1.3 server is to consider I<all>
|
||||
supported groups as comparable in security.
|
||||
|
@ -365,7 +365,7 @@ categories. See L<OSSL_trace_enabled(3)>.
|
||||
L<EVP_PKEY_public_check(3)> and L<EVP_PKEY_param_check(3)> now work for
|
||||
more key types. This includes RSA, DSA, ED25519, X25519, ED448 and X448.
|
||||
Previously (in 1.1.1) they would return -2. For key types that do not have
|
||||
parameters then L<EVP_PKEY_param_check(3)> will always return 1.
|
||||
parameters L<EVP_PKEY_param_check(3)> will always return 1.
|
||||
|
||||
=head3 Other notable deprecations and changes
|
||||
|
||||
|
@ -7,8 +7,6 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2024, Google Inc. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_ML_KEM_H
|
||||
# define OPENSSL_HEADER_ML_KEM_H
|
||||
# pragma once
|
||||
|
@ -59,5 +59,8 @@
|
||||
# define OSSL_TLS_GROUP_ID_mlkem512 0x0200
|
||||
# define OSSL_TLS_GROUP_ID_mlkem768 0x0201
|
||||
# define OSSL_TLS_GROUP_ID_mlkem1024 0x0202
|
||||
# define OSSL_TLS_GROUP_ID_SecP256r1MLKEM768 0x11EB
|
||||
# define OSSL_TLS_GROUP_ID_X25519MLKEM768 0x11EC
|
||||
# define OSSL_TLS_GROUP_ID_SecP384r1MLKEM1024 0x11ED
|
||||
|
||||
#endif
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2025 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
|
||||
@ -119,6 +119,8 @@
|
||||
# define PROV_R_NO_INSTANCE_ALLOWED 242
|
||||
# define PROV_R_NO_KEY_SET 114
|
||||
# define PROV_R_NO_PARAMETERS_SET 177
|
||||
# define PROV_R_NULL_LENGTH_POINTER 247
|
||||
# define PROV_R_NULL_OUTPUT_BUFFER 245
|
||||
# define PROV_R_ONESHOT_CALL_OUT_OF_ORDER 239
|
||||
# define PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 178
|
||||
# define PROV_R_OUTPUT_BUFFER_TOO_SMALL 106
|
||||
@ -150,9 +152,11 @@
|
||||
# define PROV_R_UNSUPPORTED_KEY_SIZE 153
|
||||
# define PROV_R_UNSUPPORTED_MAC_TYPE 137
|
||||
# define PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS 152
|
||||
# define PROV_R_UNSUPPORTED_SELECTION 248
|
||||
# define PROV_R_UPDATE_CALL_OUT_OF_ORDER 240
|
||||
# define PROV_R_URI_AUTHORITY_UNSUPPORTED 223
|
||||
# define PROV_R_VALUE_ERROR 138
|
||||
# define PROV_R_WRONG_CIPHERTEXT_SIZE 246
|
||||
# define PROV_R_WRONG_FINAL_BLOCK_LENGTH 107
|
||||
# define PROV_R_WRONG_OUTPUT_BUFFER_SIZE 139
|
||||
# define PROV_R_XOF_DIGESTS_NOT_ALLOWED 183
|
||||
|
@ -1336,6 +1336,7 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
||||
# define SSL_CTRL_SET_RETRY_VERIFY 136
|
||||
# define SSL_CTRL_GET_VERIFY_CERT_STORE 137
|
||||
# define SSL_CTRL_GET_CHAIN_CERT_STORE 138
|
||||
# define SSL_CTRL_GET0_IMPLEMENTED_GROUPS 139
|
||||
# define SSL_CERT_SET_FIRST 1
|
||||
# define SSL_CERT_SET_NEXT 2
|
||||
# define SSL_CERT_SET_SERVER 3
|
||||
@ -1444,6 +1445,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
|
||||
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(int *)(glist))
|
||||
# define SSL_CTX_set1_groups_list(ctx, s) \
|
||||
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
|
||||
# define SSL_CTX_get0_implemented_groups(ctx, all, out) \
|
||||
SSL_CTX_ctrl(ctx,SSL_CTRL_GET0_IMPLEMENTED_GROUPS, all, \
|
||||
(STACK_OF(OPENSSL_CSTRING) *)(out))
|
||||
# define SSL_set1_groups(s, glist, glistlen) \
|
||||
SSL_ctrl(s,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
|
||||
# define SSL_set1_groups_list(s, str) \
|
||||
|
@ -36,76 +36,62 @@ typedef struct tls_group_constants_st {
|
||||
int is_kem; /* Indicates utility as KEM */
|
||||
} TLS_GROUP_CONSTANTS;
|
||||
|
||||
/*
|
||||
* The indices of entries in this table must be independent of which TLS groups
|
||||
* we do or not support. It just lists basic facts about the groups, and is
|
||||
* used by (numeric slot number) reference in the "param_group_list" below.
|
||||
* Therefore, there must be no #ifdefs in this table, the index of each entry
|
||||
* must be independent of compile-time options.
|
||||
*
|
||||
* For the FFDHE groups, the security bit values are as given by
|
||||
* BN_security_bits(). For the ML-KEM hybrids these are the ML-KEM security
|
||||
* bits.
|
||||
*/
|
||||
static const TLS_GROUP_CONSTANTS group_list[] = {
|
||||
{ OSSL_TLS_GROUP_ID_sect163k1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect163r1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect163r2, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect193r1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect193r2, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect233k1, 112, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect233r1, 112, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect239k1, 112, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect283k1, 128, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect283r1, 128, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect409k1, 192, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect409r1, 192, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect571k1, 256, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_sect571r1, 256, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp160k1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp160r1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp160r2, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp192k1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp224k1, 112, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp256k1, 128, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP256r1, 128, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP384r1, 192, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP512r1, 256, TLS1_VERSION, TLS1_2_VERSION,
|
||||
DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_x25519, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_x448, 224, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP256r1_tls13, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP384r1_tls13, 192, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_brainpoolP512r1_tls13, 256, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* Security bit values as given by BN_security_bits() */
|
||||
{ OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
{ OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
#ifndef OPENSSL_NO_ML_KEM
|
||||
{ OSSL_TLS_GROUP_ID_mlkem512, ML_KEM_512_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
{ OSSL_TLS_GROUP_ID_mlkem768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
{ OSSL_TLS_GROUP_ID_mlkem1024, ML_KEM_1024_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
#endif
|
||||
/* 0 */ { OSSL_TLS_GROUP_ID_sect163k1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 1 */ { OSSL_TLS_GROUP_ID_sect163r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 2 */ { OSSL_TLS_GROUP_ID_sect163r2, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 3 */ { OSSL_TLS_GROUP_ID_sect193r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 4 */ { OSSL_TLS_GROUP_ID_sect193r2, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 5 */ { OSSL_TLS_GROUP_ID_sect233k1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 6 */ { OSSL_TLS_GROUP_ID_sect233r1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 7 */ { OSSL_TLS_GROUP_ID_sect239k1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 8 */ { OSSL_TLS_GROUP_ID_sect283k1, 128, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 9 */ { OSSL_TLS_GROUP_ID_sect283r1, 128, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 10 */ { OSSL_TLS_GROUP_ID_sect409k1, 192, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 11 */ { OSSL_TLS_GROUP_ID_sect409r1, 192, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 12 */ { OSSL_TLS_GROUP_ID_sect571k1, 256, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 13 */ { OSSL_TLS_GROUP_ID_sect571r1, 256, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 14 */ { OSSL_TLS_GROUP_ID_secp160k1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 15 */ { OSSL_TLS_GROUP_ID_secp160r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 16 */ { OSSL_TLS_GROUP_ID_secp160r2, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 17 */ { OSSL_TLS_GROUP_ID_secp192k1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 18 */ { OSSL_TLS_GROUP_ID_secp192r1, 80, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 19 */ { OSSL_TLS_GROUP_ID_secp224k1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 20 */ { OSSL_TLS_GROUP_ID_secp224r1, 112, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 21 */ { OSSL_TLS_GROUP_ID_secp256k1, 128, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 22 */ { OSSL_TLS_GROUP_ID_secp256r1, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
/* 23 */ { OSSL_TLS_GROUP_ID_secp384r1, 192, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
/* 24 */ { OSSL_TLS_GROUP_ID_secp521r1, 256, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
/* 25 */ { OSSL_TLS_GROUP_ID_brainpoolP256r1, 128, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 26 */ { OSSL_TLS_GROUP_ID_brainpoolP384r1, 192, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 27 */ { OSSL_TLS_GROUP_ID_brainpoolP512r1, 256, TLS1_VERSION, TLS1_2_VERSION, DTLS1_VERSION, DTLS1_2_VERSION, 0 },
|
||||
/* 28 */ { OSSL_TLS_GROUP_ID_x25519, 128, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
/* 29 */ { OSSL_TLS_GROUP_ID_x448, 224, TLS1_VERSION, 0, DTLS1_VERSION, 0, 0 },
|
||||
/* 30 */ { OSSL_TLS_GROUP_ID_brainpoolP256r1_tls13, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 31 */ { OSSL_TLS_GROUP_ID_brainpoolP384r1_tls13, 192, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 32 */ { OSSL_TLS_GROUP_ID_brainpoolP512r1_tls13, 256, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 33 */ { OSSL_TLS_GROUP_ID_ffdhe2048, 112, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 34 */ { OSSL_TLS_GROUP_ID_ffdhe3072, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 35 */ { OSSL_TLS_GROUP_ID_ffdhe4096, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 36 */ { OSSL_TLS_GROUP_ID_ffdhe6144, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 37 */ { OSSL_TLS_GROUP_ID_ffdhe8192, 192, TLS1_3_VERSION, 0, -1, -1, 0 },
|
||||
/* 38 */ { OSSL_TLS_GROUP_ID_mlkem512, ML_KEM_512_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
/* 39 */ { OSSL_TLS_GROUP_ID_mlkem768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
/* 40 */ { OSSL_TLS_GROUP_ID_mlkem1024, ML_KEM_1024_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
/* 41 */ { OSSL_TLS_GROUP_ID_X25519MLKEM768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
/* 42 */ { OSSL_TLS_GROUP_ID_SecP256r1MLKEM768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
/* 43 */ { OSSL_TLS_GROUP_ID_SecP384r1MLKEM1024, ML_KEM_1024_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
|
||||
};
|
||||
|
||||
#define TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx) \
|
||||
@ -136,6 +122,18 @@ static const TLS_GROUP_CONSTANTS group_list[] = {
|
||||
OSSL_PARAM_END \
|
||||
}
|
||||
|
||||
/*-
|
||||
* - The 4th field of each entry is an index into "group_list" above.
|
||||
*
|
||||
* - The 3rd field is the key management algorithm name.
|
||||
|
||||
* - The 2nd field is the GROUP_NAME used with the provider, needed for
|
||||
* providers that implement a family of related algorithms, but required
|
||||
* non-null even when the provider implements just one.
|
||||
*
|
||||
* - The 1st field is the TLS group name used in SSL_CTX_set_group_list(),
|
||||
* aliases repeat everything but the first field.
|
||||
*/
|
||||
static const OSSL_PARAM param_group_list[][11] = {
|
||||
# ifndef OPENSSL_NO_EC
|
||||
# ifndef OPENSSL_NO_EC2M
|
||||
@ -219,9 +217,16 @@ static const OSSL_PARAM param_group_list[][11] = {
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_ML_KEM) && !defined(FIPS_MODULE)
|
||||
/* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 */
|
||||
TLS_GROUP_ENTRY("MLKEM512", "MLKEM512", "ML-KEM-512", 38),
|
||||
TLS_GROUP_ENTRY("MLKEM768", "MLKEM768", "ML-KEM-768", 39),
|
||||
TLS_GROUP_ENTRY("MLKEM1024", "MLKEM1024", "ML-KEM-1024", 40),
|
||||
TLS_GROUP_ENTRY("MLKEM512", "", "ML-KEM-512", 38),
|
||||
TLS_GROUP_ENTRY("MLKEM768", "", "ML-KEM-768", 39),
|
||||
TLS_GROUP_ENTRY("MLKEM1024", "", "ML-KEM-1024", 40),
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_ML_KEM) && !defined(OPENSSL_NO_EC)
|
||||
# if !defined(OPENSSL_NO_ECX)
|
||||
TLS_GROUP_ENTRY("X25519MLKEM768", "", "X25519MLKEM768", 41),
|
||||
# endif
|
||||
TLS_GROUP_ENTRY("SecP256r1MLKEM768", "", "SecP256r1MLKEM768", 42),
|
||||
TLS_GROUP_ENTRY("SecP384r1MLKEM1024", "", "SecP384r1MLKEM1024", 43),
|
||||
# endif
|
||||
};
|
||||
#endif /* !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_ML_KEM) */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 2020-2025 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
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Generated by util/mkerr.pl DO NOT EDIT
|
||||
* Copyright 1995-2024 The OpenSSL Project Authors. All Rights Reserved.
|
||||
* Copyright 1995-2025 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
|
||||
@ -166,6 +166,10 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
"no instance allowed"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_KEY_SET), "no key set"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NO_PARAMETERS_SET), "no parameters set"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NULL_LENGTH_POINTER),
|
||||
"null length pointer"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NULL_OUTPUT_BUFFER),
|
||||
"null output buffer"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ONESHOT_CALL_OUT_OF_ORDER),
|
||||
"oneshot call out of order"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE),
|
||||
@ -223,11 +227,15 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
|
||||
"unsupported mac type"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_NUMBER_OF_ROUNDS),
|
||||
"unsupported number of rounds"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UNSUPPORTED_SELECTION),
|
||||
"unsupported selection"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_UPDATE_CALL_OUT_OF_ORDER),
|
||||
"update call out of order"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_URI_AUTHORITY_UNSUPPORTED),
|
||||
"uri authority unsupported"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_VALUE_ERROR), "value error"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_CIPHERTEXT_SIZE),
|
||||
"wrong ciphertext size"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_FINAL_BLOCK_LENGTH),
|
||||
"wrong final block length"},
|
||||
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_WRONG_OUTPUT_BUFFER_SIZE),
|
||||
|
@ -486,6 +486,14 @@ static const OSSL_ALGORITHM deflt_asym_kem[] = {
|
||||
{ PROV_NAMES_ML_KEM_512, "provider=default", ossl_ml_kem_asym_kem_functions },
|
||||
{ PROV_NAMES_ML_KEM_768, "provider=default", ossl_ml_kem_asym_kem_functions },
|
||||
{ PROV_NAMES_ML_KEM_1024, "provider=default", ossl_ml_kem_asym_kem_functions },
|
||||
# if !defined(OPENSSL_NO_ECX)
|
||||
{ "X25519MLKEM768", "provider=default", ossl_mlx_kem_asym_kem_functions },
|
||||
{ "X448MLKEM1024", "provider=default", ossl_mlx_kem_asym_kem_functions },
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_EC)
|
||||
{ "SecP256r1MLKEM768", "provider=default", ossl_mlx_kem_asym_kem_functions },
|
||||
{ "SecP384r1MLKEM1024", "provider=default", ossl_mlx_kem_asym_kem_functions },
|
||||
# endif
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
@ -556,6 +564,18 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
|
||||
PROV_DESCS_ML_KEM_768 },
|
||||
{ PROV_NAMES_ML_KEM_1024, "provider=default", ossl_ml_kem_1024_keymgmt_functions,
|
||||
PROV_DESCS_ML_KEM_1024 },
|
||||
# if !defined(OPENSSL_NO_ECX)
|
||||
{ PROV_NAMES_X25519MLKEM768, "provider=default", ossl_mlx_x25519_kem_kmgmt_functions,
|
||||
PROV_DESCS_X25519MLKEM768 },
|
||||
{ PROV_NAMES_X448MLKEM1024, "provider=default", ossl_mlx_x448_kem_kmgmt_functions,
|
||||
PROV_DESCS_X448MLKEM1024 },
|
||||
# endif
|
||||
# if !defined(OPENSSL_NO_EC)
|
||||
{ PROV_NAMES_SecP256r1MLKEM768, "provider=default", ossl_mlx_p256_kem_kmgmt_functions,
|
||||
PROV_DESCS_SecP256r1MLKEM768 },
|
||||
{ PROV_NAMES_SecP384r1MLKEM1024, "provider=default", ossl_mlx_p384_kem_kmgmt_functions,
|
||||
PROV_DESCS_SecP384r1MLKEM1024 },
|
||||
# endif
|
||||
#endif
|
||||
{ NULL, NULL, NULL }
|
||||
};
|
||||
|
@ -308,18 +308,20 @@ extern const OSSL_DISPATCH ossl_dhx_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_dsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_rsa_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_rsapss_keymgmt_functions[];
|
||||
#ifndef OPENSSL_NO_ECX
|
||||
extern const OSSL_DISPATCH ossl_kdf_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_mac_legacy_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[];
|
||||
#ifndef OPENSSL_NO_EC
|
||||
extern const OSSL_DISPATCH ossl_ec_keymgmt_functions[];
|
||||
# ifndef OPENSSL_NO_ECX
|
||||
extern const OSSL_DISPATCH ossl_x25519_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_x448_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ed25519_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ed448_keymgmt_functions[];
|
||||
#endif
|
||||
extern const OSSL_DISPATCH ossl_ec_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_kdf_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_mac_legacy_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_cmac_legacy_keymgmt_functions[];
|
||||
#ifndef OPENSSL_NO_SM2
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_SM2
|
||||
extern const OSSL_DISPATCH ossl_sm2_keymgmt_functions[];
|
||||
# endif
|
||||
#endif
|
||||
extern const OSSL_DISPATCH ossl_ml_dsa_44_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ml_dsa_65_keymgmt_functions[];
|
||||
@ -328,13 +330,25 @@ extern const OSSL_DISPATCH ossl_ml_dsa_87_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ml_kem_512_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ml_kem_768_keymgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ml_kem_1024_keymgmt_functions[];
|
||||
# ifndef OPENSSL_NO_EC
|
||||
# ifndef OPENSSL_NO_ECX
|
||||
extern const OSSL_DISPATCH ossl_mlx_x25519_kem_kmgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_mlx_x448_kem_kmgmt_functions[];
|
||||
# endif
|
||||
extern const OSSL_DISPATCH ossl_mlx_p256_kem_kmgmt_functions[];
|
||||
extern const OSSL_DISPATCH ossl_mlx_p384_kem_kmgmt_functions[];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Key Exchange */
|
||||
extern const OSSL_DISPATCH ossl_dh_keyexch_functions[];
|
||||
#ifndef OPENSSL_NO_EC
|
||||
extern const OSSL_DISPATCH ossl_ecdh_keyexch_functions[];
|
||||
# ifndef OPENSSL_NO_ECX
|
||||
extern const OSSL_DISPATCH ossl_x25519_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ossl_x448_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ecdh_keyexch_functions[];
|
||||
# endif
|
||||
#endif
|
||||
extern const OSSL_DISPATCH ossl_kdf_tls1_prf_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ossl_kdf_hkdf_keyexch_functions[];
|
||||
extern const OSSL_DISPATCH ossl_kdf_scrypt_keyexch_functions[];
|
||||
@ -403,9 +417,18 @@ extern const OSSL_DISPATCH ossl_sm2_asym_cipher_functions[];
|
||||
|
||||
/* Asym Key encapsulation */
|
||||
extern const OSSL_DISPATCH ossl_rsa_asym_kem_functions[];
|
||||
extern const OSSL_DISPATCH ossl_ecx_asym_kem_functions[];
|
||||
#ifndef OPENSSL_NO_EC
|
||||
extern const OSSL_DISPATCH ossl_ec_asym_kem_functions[];
|
||||
# ifndef OPENSSL_NO_ECX
|
||||
extern const OSSL_DISPATCH ossl_ecx_asym_kem_functions[];
|
||||
# endif
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_ML_KEM
|
||||
extern const OSSL_DISPATCH ossl_ml_kem_asym_kem_functions[];
|
||||
# ifndef OPENSSL_NO_EC
|
||||
extern const OSSL_DISPATCH ossl_mlx_kem_asym_kem_functions[];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Encoders */
|
||||
extern const OSSL_DISPATCH ossl_rsa_to_PKCS1_der_encoder_functions[];
|
||||
|
38
providers/implementations/include/prov/mlx_kem.h
Normal file
38
providers/implementations/include/prov/mlx_kem.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef OSSL_MLX_KEM_H
|
||||
# define OSSL_MLX_KEM_H
|
||||
# pragma once
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/ml_kem.h>
|
||||
#include <crypto/ml_kem.h>
|
||||
#include <crypto/ecx.h>
|
||||
|
||||
typedef struct ecdh_vinfo_st {
|
||||
const char *algorithm_name;
|
||||
const char *group_name;
|
||||
size_t pubkey_bytes;
|
||||
size_t prvkey_bytes;
|
||||
size_t shsec_bytes;
|
||||
int ml_kem_slot;
|
||||
int ml_kem_variant;
|
||||
} ECDH_VINFO;
|
||||
|
||||
typedef struct mlx_key_st {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
char *propq;
|
||||
const ML_KEM_VINFO *minfo;
|
||||
const ECDH_VINFO *xinfo;
|
||||
EVP_PKEY *mkey;
|
||||
EVP_PKEY *xkey;
|
||||
unsigned int state;
|
||||
} MLX_KEY;
|
||||
|
||||
#define MLX_HAVE_NOKEYS 0
|
||||
#define MLX_HAVE_PUBKEY 1
|
||||
#define MLX_HAVE_PRVKEY 2
|
||||
|
||||
/* Both key parts have whatever the ML-KEM component has */
|
||||
#define mlx_kem_have_pubkey(key) ((key)->state > 0)
|
||||
#define mlx_kem_have_prvkey(key) ((key)->state > 1)
|
||||
|
||||
#endif
|
@ -396,3 +396,11 @@
|
||||
#define PROV_DESCS_ML_KEM_768 "OpenSSL ML-KEM-768 implementation"
|
||||
#define PROV_NAMES_ML_KEM_1024 "ML-KEM-1024"
|
||||
#define PROV_DESCS_ML_KEM_1024 "OpenSSL ML-KEM-1024 implementation"
|
||||
#define PROV_NAMES_X25519MLKEM768 "X25519MLKEM768"
|
||||
#define PROV_DESCS_X25519MLKEM768 "X25519+ML-KEM-768 TLS hybrid implementation"
|
||||
#define PROV_NAMES_X448MLKEM1024 "X448MLKEM1024"
|
||||
#define PROV_DESCS_X448MLKEM1024 "X448+ML-KEM-1024 TLS hybrid implementation"
|
||||
#define PROV_NAMES_SecP256r1MLKEM768 "SecP256r1MLKEM768"
|
||||
#define PROV_DESCS_SecP256r1MLKEM768 "P-256+ML-KEM-768 TLS hybrid implementation"
|
||||
#define PROV_NAMES_SecP384r1MLKEM1024 "SecP384r1MLKEM1024"
|
||||
#define PROV_DESCS_SecP384r1MLKEM1024 "P-384+ML-KEM-1024 TLS hybrid implementation"
|
||||
|
@ -5,6 +5,7 @@ $RSA_KEM_GOAL=../../libdefault.a ../../libfips.a
|
||||
$EC_KEM_GOAL=../../libdefault.a
|
||||
$TEMPLATE_KEM_GOAL=../../libtemplate.a
|
||||
$ML_KEM_GOAL=../../libdefault.a
|
||||
$TLS_ML_KEM_HYBRID_GOAL=../../libdefault.a
|
||||
|
||||
SOURCE[$RSA_KEM_GOAL]=rsa_kem.c
|
||||
|
||||
@ -15,7 +16,11 @@ IF[{- !$disabled{ec} -}]
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
SOURCE[$TEMPLATE_KEM_GOAL]=template_kem.c
|
||||
IF[{- !$disabled{'ml-kem'} -}]
|
||||
SOURCE[$ML_KEM_GOAL] = ml_kem.c
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$TLS_ML_KEM_HYBRID_GOAL]=mlx_kem.c
|
||||
ENDIF
|
||||
SOURCE[$ML_KEM_GOAL] = ml_kem.c
|
||||
ENDIF
|
||||
|
||||
SOURCE[$TEMPLATE_KEM_GOAL]=template_kem.c
|
||||
|
@ -176,9 +176,10 @@ static int ml_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* For now tolerate newly-deprecated NULL length pointers. */
|
||||
if (clen == NULL) {
|
||||
clen = &encap_clen;
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER,
|
||||
"null ciphertext input/output length pointer");
|
||||
goto end;
|
||||
} else if (*clen < encap_clen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"ciphertext buffer too small");
|
||||
@ -188,7 +189,9 @@ static int ml_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
|
||||
}
|
||||
|
||||
if (slen == NULL) {
|
||||
slen = &encap_slen;
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER,
|
||||
"null shared secret input/output length pointer");
|
||||
goto end;
|
||||
} else if (*slen < encap_slen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"shared-secret buffer too small");
|
||||
@ -252,16 +255,14 @@ static int ml_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen,
|
||||
return ossl_ml_kem_decap(shsec, decap_slen, ctext, clen, key);
|
||||
}
|
||||
|
||||
typedef void (*func_ptr_t)(void);
|
||||
|
||||
const OSSL_DISPATCH ossl_ml_kem_asym_kem_functions[] = {
|
||||
{ OSSL_FUNC_KEM_NEWCTX, (func_ptr_t) ml_kem_newctx },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE_INIT, (func_ptr_t) ml_kem_encapsulate_init },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE, (func_ptr_t) ml_kem_encapsulate },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE_INIT, (func_ptr_t) ml_kem_decapsulate_init },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE, (func_ptr_t) ml_kem_decapsulate },
|
||||
{ OSSL_FUNC_KEM_FREECTX, (func_ptr_t) ml_kem_freectx },
|
||||
{ OSSL_FUNC_KEM_SET_CTX_PARAMS, (func_ptr_t) ml_kem_set_ctx_params },
|
||||
{ OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (func_ptr_t) ml_kem_settable_ctx_params },
|
||||
{ OSSL_FUNC_KEM_NEWCTX, (OSSL_FUNC) ml_kem_newctx },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE_INIT, (OSSL_FUNC) ml_kem_encapsulate_init },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE, (OSSL_FUNC) ml_kem_encapsulate },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE_INIT, (OSSL_FUNC) ml_kem_decapsulate_init },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE, (OSSL_FUNC) ml_kem_decapsulate },
|
||||
{ OSSL_FUNC_KEM_FREECTX, (OSSL_FUNC) ml_kem_freectx },
|
||||
{ OSSL_FUNC_KEM_SET_CTX_PARAMS, (OSSL_FUNC) ml_kem_set_ctx_params },
|
||||
{ OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (OSSL_FUNC) ml_kem_settable_ctx_params },
|
||||
OSSL_DISPATCH_END
|
||||
};
|
||||
|
341
providers/implementations/kem/mlx_kem.c
Normal file
341
providers/implementations/kem/mlx_kem.c
Normal file
@ -0,0 +1,341 @@
|
||||
/*
|
||||
* 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
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_dispatch.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/proverr.h>
|
||||
#include <openssl/rand.h>
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/mlx_kem.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/providercommon.h"
|
||||
|
||||
static OSSL_FUNC_kem_newctx_fn mlx_kem_newctx;
|
||||
static OSSL_FUNC_kem_freectx_fn mlx_kem_freectx;
|
||||
static OSSL_FUNC_kem_encapsulate_init_fn mlx_kem_encapsulate_init;
|
||||
static OSSL_FUNC_kem_encapsulate_fn mlx_kem_encapsulate;
|
||||
static OSSL_FUNC_kem_decapsulate_init_fn mlx_kem_decapsulate_init;
|
||||
static OSSL_FUNC_kem_decapsulate_fn mlx_kem_decapsulate;
|
||||
static OSSL_FUNC_kem_set_ctx_params_fn mlx_kem_set_ctx_params;
|
||||
static OSSL_FUNC_kem_settable_ctx_params_fn mlx_kem_settable_ctx_params;
|
||||
|
||||
typedef struct {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
MLX_KEY *key;
|
||||
int op;
|
||||
} PROV_MLX_KEM_CTX;
|
||||
|
||||
static void *mlx_kem_newctx(void *provctx)
|
||||
{
|
||||
PROV_MLX_KEM_CTX *ctx;
|
||||
|
||||
if ((ctx = OPENSSL_malloc(sizeof(*ctx))) == NULL)
|
||||
return NULL;
|
||||
|
||||
ctx->libctx = PROV_LIBCTX_OF(provctx);
|
||||
ctx->key = NULL;
|
||||
ctx->op = 0;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
static void mlx_kem_freectx(void *vctx)
|
||||
{
|
||||
OPENSSL_free(vctx);
|
||||
}
|
||||
|
||||
static int mlx_kem_init(void *vctx, int op, void *key,
|
||||
ossl_unused const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_MLX_KEM_CTX *ctx = vctx;
|
||||
|
||||
if (!ossl_prov_is_running())
|
||||
return 0;
|
||||
ctx->key = key;
|
||||
ctx->op = op;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx_kem_encapsulate_init(void *vctx, void *vkey, const OSSL_PARAM params[])
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
|
||||
if (!mlx_kem_have_pubkey(key)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
return mlx_kem_init(vctx, EVP_PKEY_OP_ENCAPSULATE, key, params);
|
||||
}
|
||||
|
||||
static int
|
||||
mlx_kem_decapsulate_init(void *vctx, void *vkey, const OSSL_PARAM params[])
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
|
||||
if (!mlx_kem_have_prvkey(key)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
return mlx_kem_init(vctx, EVP_PKEY_OP_DECAPSULATE, key, params);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *mlx_kem_settable_ctx_params(ossl_unused void *vctx,
|
||||
ossl_unused void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM params[] = { OSSL_PARAM_END };
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
static int
|
||||
mlx_kem_set_ctx_params(void *vctx, const OSSL_PARAM params[])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
|
||||
unsigned char *shsec, size_t *slen)
|
||||
{
|
||||
MLX_KEY *key = ((PROV_MLX_KEM_CTX *) vctx)->key;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *xkey = NULL;
|
||||
size_t encap_clen;
|
||||
size_t encap_slen;
|
||||
uint8_t *cbuf;
|
||||
uint8_t *sbuf;
|
||||
int ml_kem_slot = key->xinfo->ml_kem_slot;
|
||||
int ret = 0;
|
||||
|
||||
if (!mlx_kem_have_pubkey(key)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
goto end;
|
||||
}
|
||||
encap_clen = key->minfo->ctext_bytes + key->xinfo->pubkey_bytes;
|
||||
encap_slen = ML_KEM_SHARED_SECRET_BYTES + key->xinfo->shsec_bytes;
|
||||
|
||||
if (ctext == NULL) {
|
||||
if (clen == NULL && slen == NULL)
|
||||
return 0;
|
||||
if (clen != NULL)
|
||||
*clen = encap_clen;
|
||||
if (slen != NULL)
|
||||
*slen = encap_slen;
|
||||
return 1;
|
||||
}
|
||||
if (shsec == NULL) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NULL_OUTPUT_BUFFER,
|
||||
"null shared-secret output buffer");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (clen == NULL) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER,
|
||||
"null ciphertext input/output length pointer");
|
||||
return 0;
|
||||
} else if (*clen < encap_clen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"ciphertext buffer too small");
|
||||
return 0;
|
||||
} else {
|
||||
*clen = encap_clen;
|
||||
}
|
||||
|
||||
if (slen == NULL) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_NULL_LENGTH_POINTER,
|
||||
"null shared secret input/output length pointer");
|
||||
return 0;
|
||||
} else if (*slen < encap_slen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"shared-secret buffer too small");
|
||||
return 0;
|
||||
} else {
|
||||
*slen = encap_slen;
|
||||
}
|
||||
|
||||
/* ML-KEM encapsulation */
|
||||
encap_clen = key->minfo->ctext_bytes;
|
||||
encap_slen = ML_KEM_SHARED_SECRET_BYTES;
|
||||
cbuf = ctext + ml_kem_slot * key->xinfo->pubkey_bytes;
|
||||
sbuf = shsec + ml_kem_slot * key->xinfo->shsec_bytes;
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->mkey, key->propq);
|
||||
if (ctx == NULL
|
||||
|| EVP_PKEY_encapsulate_init(ctx, NULL) <= 0
|
||||
|| EVP_PKEY_encapsulate(ctx, cbuf, &encap_clen, sbuf, &encap_slen) <= 0)
|
||||
goto end;
|
||||
if (encap_clen != key->minfo->ctext_bytes) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s ciphertext output size: %lu",
|
||||
key->minfo->algorithm_name, (unsigned long) encap_clen);
|
||||
goto end;
|
||||
}
|
||||
if (encap_slen != ML_KEM_SHARED_SECRET_BYTES) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s shared secret output size: %lu",
|
||||
key->minfo->algorithm_name, (unsigned long) encap_slen);
|
||||
goto end;
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
/*-
|
||||
* ECDHE encapsulation
|
||||
*
|
||||
* Generate own ephemeral private key and add its public key to ctext.
|
||||
*
|
||||
* Note, we could support a settable parameter that sets an extant ECDH
|
||||
* keypair as the keys to use in encap, making it possible to reuse the
|
||||
* same (TLS client) ECDHE keypair for both the classical EC keyshare and a
|
||||
* corresponding ECDHE + ML-KEM keypair. But the TLS layer would then need
|
||||
* know that this is a hybrid, and that it can partly reuse the same keys
|
||||
* as another group for which a keyshare will be sent. Deferred until we
|
||||
* support generating multiple keyshares, there's a workable keyshare
|
||||
* prediction specification, and the optimisation is justified.
|
||||
*/
|
||||
cbuf = ctext + (1 - ml_kem_slot) * key->minfo->ctext_bytes;
|
||||
encap_clen = key->xinfo->pubkey_bytes;
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->xkey, key->propq);
|
||||
if (ctx == NULL
|
||||
|| EVP_PKEY_keygen_init(ctx) <= 0
|
||||
|| EVP_PKEY_keygen(ctx, &xkey) <= 0
|
||||
|| EVP_PKEY_get_octet_string_param(xkey, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
||||
cbuf, encap_clen, &encap_clen) <= 0)
|
||||
goto end;
|
||||
if (encap_clen != key->xinfo->pubkey_bytes) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s public key output size: %lu",
|
||||
key->xinfo->algorithm_name, (unsigned long) encap_clen);
|
||||
goto end;
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
/* Derive the ECDH shared secret */
|
||||
encap_slen = key->xinfo->shsec_bytes;
|
||||
sbuf = shsec + (1 - ml_kem_slot) * ML_KEM_SHARED_SECRET_BYTES;
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, xkey, key->propq);
|
||||
if (ctx == NULL
|
||||
|| EVP_PKEY_derive_init(ctx) <= 0
|
||||
|| EVP_PKEY_derive_set_peer(ctx, key->xkey) <= 0
|
||||
|| EVP_PKEY_derive(ctx, sbuf, &encap_slen) <= 0)
|
||||
goto end;
|
||||
if (encap_slen != key->xinfo->shsec_bytes) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s shared secret output size: %lu",
|
||||
key->xinfo->algorithm_name, (unsigned long) encap_slen);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
EVP_PKEY_free(xkey);
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mlx_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen,
|
||||
const uint8_t *ctext, size_t clen)
|
||||
{
|
||||
MLX_KEY *key = ((PROV_MLX_KEM_CTX *) vctx)->key;
|
||||
EVP_PKEY_CTX *ctx = NULL;
|
||||
EVP_PKEY *xkey = NULL;
|
||||
const uint8_t *cbuf;
|
||||
uint8_t *sbuf;
|
||||
size_t decap_slen = ML_KEM_SHARED_SECRET_BYTES + key->xinfo->shsec_bytes;
|
||||
size_t decap_clen = key->minfo->ctext_bytes + key->xinfo->pubkey_bytes;
|
||||
int ml_kem_slot = key->xinfo->ml_kem_slot;
|
||||
int ret = 0;
|
||||
|
||||
if (!mlx_kem_have_prvkey(key)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shsec == NULL) {
|
||||
if (slen == NULL)
|
||||
return 0;
|
||||
*slen = decap_slen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For now tolerate newly-deprecated NULL length pointers. */
|
||||
if (slen == NULL) {
|
||||
slen = &decap_slen;
|
||||
} else if (*slen < decap_slen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"shared-secret buffer too small");
|
||||
return 0;
|
||||
} else {
|
||||
*slen = decap_slen;
|
||||
}
|
||||
if (clen != decap_clen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_WRONG_CIPHERTEXT_SIZE,
|
||||
"wrong decapsulation input ciphertext size: %lu",
|
||||
(unsigned long) clen);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ML-KEM decapsulation */
|
||||
decap_clen = key->minfo->ctext_bytes;
|
||||
decap_slen = ML_KEM_SHARED_SECRET_BYTES;
|
||||
cbuf = ctext + ml_kem_slot * key->xinfo->pubkey_bytes;
|
||||
sbuf = shsec + ml_kem_slot * key->xinfo->shsec_bytes;
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->mkey, key->propq);
|
||||
if (ctx == NULL
|
||||
|| EVP_PKEY_decapsulate_init(ctx, NULL) <= 0
|
||||
|| EVP_PKEY_decapsulate(ctx, sbuf, &decap_slen, cbuf, decap_clen) <= 0)
|
||||
goto end;
|
||||
if (decap_slen != ML_KEM_SHARED_SECRET_BYTES) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s shared secret output size: %lu",
|
||||
key->minfo->algorithm_name, (unsigned long) decap_slen);
|
||||
goto end;
|
||||
}
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
|
||||
/* ECDH decapsulation */
|
||||
decap_clen = key->xinfo->pubkey_bytes;
|
||||
decap_slen = key->xinfo->shsec_bytes;
|
||||
cbuf = ctext + (1 - ml_kem_slot) * key->minfo->ctext_bytes;
|
||||
sbuf = shsec + (1 - ml_kem_slot) * ML_KEM_SHARED_SECRET_BYTES;
|
||||
ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->xkey, key->propq);
|
||||
if (ctx == NULL
|
||||
|| (xkey = EVP_PKEY_new()) == NULL
|
||||
|| EVP_PKEY_copy_parameters(xkey, key->xkey) <= 0
|
||||
|| EVP_PKEY_set1_encoded_public_key(xkey, cbuf, decap_clen) <= 0
|
||||
|| EVP_PKEY_derive_init(ctx) <= 0
|
||||
|| EVP_PKEY_derive_set_peer(ctx, xkey) <= 0
|
||||
|| EVP_PKEY_derive(ctx, sbuf, &decap_slen) <= 0)
|
||||
goto end;
|
||||
if (decap_slen != key->xinfo->shsec_bytes) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"unexpected %s shared secret output size: %lu",
|
||||
key->xinfo->algorithm_name, (unsigned long) decap_slen);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
EVP_PKEY_free(xkey);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const OSSL_DISPATCH ossl_mlx_kem_asym_kem_functions[] = {
|
||||
{ OSSL_FUNC_KEM_NEWCTX, (OSSL_FUNC) mlx_kem_newctx },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE_INIT, (OSSL_FUNC) mlx_kem_encapsulate_init },
|
||||
{ OSSL_FUNC_KEM_ENCAPSULATE, (OSSL_FUNC) mlx_kem_encapsulate },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE_INIT, (OSSL_FUNC) mlx_kem_decapsulate_init },
|
||||
{ OSSL_FUNC_KEM_DECAPSULATE, (OSSL_FUNC) mlx_kem_decapsulate },
|
||||
{ OSSL_FUNC_KEM_FREECTX, (OSSL_FUNC) mlx_kem_freectx },
|
||||
{ OSSL_FUNC_KEM_SET_CTX_PARAMS, (OSSL_FUNC) mlx_kem_set_ctx_params },
|
||||
{ OSSL_FUNC_KEM_SETTABLE_CTX_PARAMS, (OSSL_FUNC) mlx_kem_settable_ctx_params },
|
||||
OSSL_DISPATCH_END
|
||||
};
|
@ -11,6 +11,7 @@ $RSA_GOAL=../../libdefault.a ../../libfips.a
|
||||
$TEMPLATE_GOAL=../../libtemplate.a
|
||||
$ML_DSA_GOAL=../../libdefault.a ../../libfips.a
|
||||
$ML_KEM_GOAL=../../libdefault.a
|
||||
$TLS_ML_KEM_HYBRID_GOAL=../../libdefault.a
|
||||
|
||||
IF[{- !$disabled{dh} -}]
|
||||
SOURCE[$DH_GOAL]=dh_kmgmt.c
|
||||
@ -39,6 +40,13 @@ IF[{- !$disabled{ec} -}]
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{'ml-kem'} -}]
|
||||
IF[{- !$disabled{ec} -}]
|
||||
SOURCE[$TLS_ML_KEM_HYBRID_GOAL]=mlx_kmgmt.c
|
||||
ENDIF
|
||||
SOURCE[$ML_KEM_GOAL]=ml_kem_kmgmt.c
|
||||
ENDIF
|
||||
|
||||
SOURCE[$RSA_GOAL]=rsa_kmgmt.c
|
||||
|
||||
SOURCE[$KDF_GOAL]=kdf_legacy_kmgmt.c
|
||||
@ -50,7 +58,3 @@ SOURCE[$TEMPLATE_GOAL]=template_kmgmt.c
|
||||
IF[{- !$disabled{'ml-dsa'} -}]
|
||||
SOURCE[$ML_DSA_GOAL]=ml_dsa_kmgmt.c
|
||||
ENDIF
|
||||
|
||||
IF[{- !$disabled{'ml-kem'} -}]
|
||||
SOURCE[$ML_KEM_GOAL]=ml_kem_kmgmt.c
|
||||
ENDIF
|
||||
|
@ -44,6 +44,9 @@ static OSSL_FUNC_keymgmt_import_types_fn ml_kem_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_export_types_fn ml_kem_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_dup_fn ml_kem_dup;
|
||||
|
||||
static const int minimal_selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
|
||||
| OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
||||
|
||||
typedef struct ml_kem_gen_ctx_st {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
char *propq;
|
||||
@ -401,9 +404,6 @@ static int ml_kem_gen_set_params(void *vgctx, const OSSL_PARAM params[])
|
||||
static void *ml_kem_gen_init(void *provctx, int selection,
|
||||
const OSSL_PARAM params[], int variant)
|
||||
{
|
||||
static const int minimal =
|
||||
OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
|
||||
| OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
||||
PROV_ML_KEM_GEN_CTX *gctx = NULL;
|
||||
|
||||
/*
|
||||
@ -411,7 +411,7 @@ static void *ml_kem_gen_init(void *provctx, int selection,
|
||||
* appropriate.
|
||||
*/
|
||||
if (!ossl_prov_is_running()
|
||||
|| (selection & minimal) == 0
|
||||
|| (selection & minimal_selection) == 0
|
||||
|| (gctx = OPENSSL_zalloc(sizeof(*gctx))) == NULL)
|
||||
return NULL;
|
||||
|
||||
@ -489,8 +489,6 @@ static void *ml_kem_dup(const void *vkey, int selection)
|
||||
return ossl_ml_kem_key_dup(key, selection);
|
||||
}
|
||||
|
||||
typedef void (*func_ptr_t)(void);
|
||||
|
||||
#define DECLARE_VARIANT(bits) \
|
||||
static void *ml_kem_##bits##_new(void *provctx) \
|
||||
{ \
|
||||
@ -503,24 +501,24 @@ typedef void (*func_ptr_t)(void);
|
||||
return ml_kem_gen_init(provctx, selection, params, ML_KEM_##bits##_VARIANT); \
|
||||
} \
|
||||
const OSSL_DISPATCH ossl_ml_kem_##bits##_keymgmt_functions[] = { \
|
||||
{ OSSL_FUNC_KEYMGMT_NEW, (func_ptr_t) ml_kem_##bits##_new }, \
|
||||
{ OSSL_FUNC_KEYMGMT_FREE, (func_ptr_t) ossl_ml_kem_key_free }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (func_ptr_t) ml_kem_get_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (func_ptr_t) ml_kem_gettable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (func_ptr_t) ml_kem_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (func_ptr_t) ml_kem_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (func_ptr_t) ml_kem_has }, \
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (func_ptr_t) ml_kem_match }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (func_ptr_t) ml_kem_##bits##_gen_init }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (func_ptr_t) ml_kem_gen_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (func_ptr_t) ml_kem_gen_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN, (func_ptr_t) ml_kem_gen }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (func_ptr_t) ml_kem_gen_cleanup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_DUP, (func_ptr_t) ml_kem_dup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (func_ptr_t) ml_kem_import }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (func_ptr_t) ml_kem_imexport_types }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (func_ptr_t) ml_kem_export }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (func_ptr_t) ml_kem_imexport_types }, \
|
||||
{ OSSL_FUNC_KEYMGMT_NEW, (OSSL_FUNC) ml_kem_##bits##_new }, \
|
||||
{ OSSL_FUNC_KEYMGMT_FREE, (OSSL_FUNC) ossl_ml_kem_key_free }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (OSSL_FUNC) ml_kem_get_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (OSSL_FUNC) ml_kem_gettable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (OSSL_FUNC) ml_kem_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (OSSL_FUNC) ml_kem_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (OSSL_FUNC) ml_kem_has }, \
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (OSSL_FUNC) ml_kem_match }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (OSSL_FUNC) ml_kem_##bits##_gen_init }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (OSSL_FUNC) ml_kem_gen_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (OSSL_FUNC) ml_kem_gen_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN, (OSSL_FUNC) ml_kem_gen }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (OSSL_FUNC) ml_kem_gen_cleanup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_DUP, (OSSL_FUNC) ml_kem_dup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (OSSL_FUNC) ml_kem_import }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (OSSL_FUNC) ml_kem_imexport_types }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (OSSL_FUNC) ml_kem_export }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (OSSL_FUNC) ml_kem_imexport_types }, \
|
||||
OSSL_DISPATCH_END \
|
||||
}
|
||||
DECLARE_VARIANT(512);
|
||||
|
804
providers/implementations/keymgmt/mlx_kmgmt.c
Normal file
804
providers/implementations/keymgmt/mlx_kmgmt.c
Normal file
@ -0,0 +1,804 @@
|
||||
/*
|
||||
* 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
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <openssl/core_dispatch.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/param_build.h>
|
||||
#include <openssl/params.h>
|
||||
#include <openssl/proverr.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/self_test.h>
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/param_build_set.h"
|
||||
#include "prov/implementations.h"
|
||||
#include "prov/mlx_kem.h"
|
||||
#include "prov/provider_ctx.h"
|
||||
#include "prov/providercommon.h"
|
||||
#include "prov/securitycheck.h"
|
||||
|
||||
static OSSL_FUNC_keymgmt_gen_fn mlx_kem_gen;
|
||||
static OSSL_FUNC_keymgmt_gen_cleanup_fn mlx_kem_gen_cleanup;
|
||||
static OSSL_FUNC_keymgmt_gen_set_params_fn mlx_kem_gen_set_params;
|
||||
static OSSL_FUNC_keymgmt_gen_settable_params_fn mlx_kem_gen_settable_params;
|
||||
static OSSL_FUNC_keymgmt_get_params_fn mlx_kem_get_params;
|
||||
static OSSL_FUNC_keymgmt_gettable_params_fn mlx_kem_gettable_params;
|
||||
static OSSL_FUNC_keymgmt_set_params_fn mlx_kem_set_params;
|
||||
static OSSL_FUNC_keymgmt_settable_params_fn mlx_kem_settable_params;
|
||||
static OSSL_FUNC_keymgmt_has_fn mlx_kem_has;
|
||||
static OSSL_FUNC_keymgmt_match_fn mlx_kem_match;
|
||||
static OSSL_FUNC_keymgmt_import_fn mlx_kem_import;
|
||||
static OSSL_FUNC_keymgmt_export_fn mlx_kem_export;
|
||||
static OSSL_FUNC_keymgmt_import_types_fn mlx_kem_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_export_types_fn mlx_kem_imexport_types;
|
||||
static OSSL_FUNC_keymgmt_dup_fn mlx_kem_dup;
|
||||
|
||||
static const int minimal_selection = OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
|
||||
| OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
||||
|
||||
/* Must match DECLARE_DISPATCH invocations at the end of the file */
|
||||
static const ECDH_VINFO hybrid_vtable[] = {
|
||||
{ "EC", "P-256", 65, 32, 32, 1, ML_KEM_768_VARIANT },
|
||||
{ "EC", "P-384", 97, 48, 48, 1, ML_KEM_1024_VARIANT },
|
||||
#if !defined(OPENSSL_NO_ECX)
|
||||
{ "X25519", NULL, 32, 32, 32, 0, ML_KEM_768_VARIANT },
|
||||
{ "X448", NULL, 56, 56, 56, 0, ML_KEM_1024_VARIANT },
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct mlx_kem_gen_ctx_st {
|
||||
OSSL_LIB_CTX *libctx;
|
||||
char *propq;
|
||||
int selection;
|
||||
unsigned int variant;
|
||||
} PROV_ML_KEM_GEN_CTX;
|
||||
|
||||
static void mlx_kem_key_free(void *vkey)
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
|
||||
if (key == NULL)
|
||||
return;
|
||||
OPENSSL_free(key->propq);
|
||||
EVP_PKEY_free(key->mkey);
|
||||
EVP_PKEY_free(key->xkey);
|
||||
OPENSSL_free(key);
|
||||
}
|
||||
|
||||
/* Takes ownership of propq */
|
||||
static void *
|
||||
mlx_kem_key_new(unsigned int v, OSSL_LIB_CTX *libctx, char *propq)
|
||||
{
|
||||
MLX_KEY *key = NULL;
|
||||
unsigned int ml_kem_variant;
|
||||
|
||||
if (!ossl_prov_is_running()
|
||||
|| v >= OSSL_NELEM(hybrid_vtable)
|
||||
|| (key = OPENSSL_malloc(sizeof(*key))) == NULL)
|
||||
goto err;
|
||||
|
||||
ml_kem_variant = hybrid_vtable[v].ml_kem_variant;
|
||||
key->libctx = libctx;
|
||||
key->minfo = ossl_ml_kem_get_vinfo(ml_kem_variant);
|
||||
key->xinfo = &hybrid_vtable[v];
|
||||
key->xkey = key->mkey = NULL;
|
||||
key->state = MLX_HAVE_NOKEYS;
|
||||
key->propq = propq;
|
||||
return key;
|
||||
|
||||
err:
|
||||
OPENSSL_free(propq);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static int mlx_kem_has(const void *vkey, int selection)
|
||||
{
|
||||
const MLX_KEY *key = vkey;
|
||||
|
||||
/* A NULL key MUST fail to have anything */
|
||||
if (!ossl_prov_is_running() || key == NULL)
|
||||
return 0;
|
||||
|
||||
switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) {
|
||||
case 0:
|
||||
return 1;
|
||||
case OSSL_KEYMGMT_SELECT_PUBLIC_KEY:
|
||||
return mlx_kem_have_pubkey(key);
|
||||
default:
|
||||
return mlx_kem_have_prvkey(key);
|
||||
}
|
||||
}
|
||||
|
||||
static int mlx_kem_match(const void *vkey1, const void *vkey2, int selection)
|
||||
{
|
||||
const MLX_KEY *key1 = vkey1;
|
||||
const MLX_KEY *key2 = vkey2;
|
||||
int have_pub1 = mlx_kem_have_pubkey(key1);
|
||||
int have_pub2 = mlx_kem_have_pubkey(key2);
|
||||
|
||||
if (!ossl_prov_is_running())
|
||||
return 0;
|
||||
|
||||
/* Compare domain parameters */
|
||||
if (key1->xinfo != key2->xinfo)
|
||||
return 0;
|
||||
|
||||
if (!(selection & OSSL_KEYMGMT_SELECT_KEYPAIR))
|
||||
return 1;
|
||||
|
||||
if (have_pub1 ^ have_pub2)
|
||||
return 0;
|
||||
|
||||
/* As in other providers, equal when both have no key material. */
|
||||
if (!have_pub1)
|
||||
return 1;
|
||||
|
||||
return EVP_PKEY_eq(key1->mkey, key2->mkey)
|
||||
&& EVP_PKEY_eq(key1->xkey, key2->xkey);
|
||||
}
|
||||
|
||||
typedef struct export_cb_arg_st {
|
||||
const char *algorithm_name;
|
||||
uint8_t *pubenc;
|
||||
uint8_t *prvenc;
|
||||
int pubcount;
|
||||
int prvcount;
|
||||
size_t puboff;
|
||||
size_t prvoff;
|
||||
size_t publen;
|
||||
size_t prvlen;
|
||||
} EXPORT_CB_ARG;
|
||||
|
||||
/* Copy any exported key material into its storage slot */
|
||||
static int export_sub_cb(const OSSL_PARAM *params, void *varg)
|
||||
{
|
||||
EXPORT_CB_ARG *sub_arg = varg;
|
||||
const OSSL_PARAM *p = NULL;
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* The caller will decide whether anything essential is missing, but, if
|
||||
* some key material was returned, it should have the right (parameter)
|
||||
* data type and length.
|
||||
*/
|
||||
if (ossl_param_is_empty(params))
|
||||
return 1;
|
||||
if (sub_arg->pubenc != NULL
|
||||
&& (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY)) != NULL) {
|
||||
void *pub = sub_arg->pubenc + sub_arg->puboff;
|
||||
|
||||
if (OSSL_PARAM_get_octet_string(p, &pub, sub_arg->publen, &len) != 1)
|
||||
return 0;
|
||||
if (len != sub_arg->publen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"Unexpected %s public key length %lu != %lu",
|
||||
sub_arg->algorithm_name, (unsigned long) len,
|
||||
sub_arg->publen);
|
||||
return 0;
|
||||
}
|
||||
++sub_arg->pubcount;
|
||||
}
|
||||
if (sub_arg->prvenc != NULL
|
||||
&& (p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY)) != NULL) {
|
||||
void *prv = sub_arg->prvenc + sub_arg->prvoff;
|
||||
|
||||
if (OSSL_PARAM_get_octet_string(p, &prv, sub_arg->prvlen, &len) != 1)
|
||||
return 0;
|
||||
if (len != sub_arg->prvlen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
|
||||
"Unexpected %s private key length %lu != %lu",
|
||||
sub_arg->algorithm_name, (unsigned long) len,
|
||||
(unsigned long) sub_arg->publen);
|
||||
return 0;
|
||||
}
|
||||
++sub_arg->prvcount;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
export_sub(EXPORT_CB_ARG *sub_arg, int selection, MLX_KEY *key)
|
||||
{
|
||||
int slot;
|
||||
|
||||
/*
|
||||
* The caller is responsible for initialising only the pubenc and prvenc
|
||||
* pointer fields, the rest are set here or in the callback.
|
||||
*/
|
||||
sub_arg->pubcount = 0;
|
||||
sub_arg->prvcount = 0;
|
||||
|
||||
for (slot = 0; slot < 2; ++slot) {
|
||||
int ml_kem_slot = key->xinfo->ml_kem_slot;
|
||||
EVP_PKEY *pkey;
|
||||
|
||||
/* Export the parts of each component into its storage slot */
|
||||
if (slot == ml_kem_slot) {
|
||||
pkey = key->mkey;
|
||||
sub_arg->algorithm_name = key->minfo->algorithm_name;
|
||||
sub_arg->puboff = slot * key->xinfo->pubkey_bytes;
|
||||
sub_arg->prvoff = slot * key->xinfo->prvkey_bytes;
|
||||
sub_arg->publen = key->minfo->pubkey_bytes;
|
||||
sub_arg->prvlen = key->minfo->prvkey_bytes;
|
||||
} else {
|
||||
pkey = key->xkey;
|
||||
sub_arg->algorithm_name = key->xinfo->algorithm_name;
|
||||
sub_arg->puboff = (1 - ml_kem_slot) * key->minfo->pubkey_bytes;
|
||||
sub_arg->prvoff = (1 - ml_kem_slot) * key->minfo->prvkey_bytes;
|
||||
sub_arg->publen = key->xinfo->pubkey_bytes;
|
||||
sub_arg->prvlen = key->xinfo->prvkey_bytes;
|
||||
}
|
||||
if (!EVP_PKEY_export(pkey, selection, export_sub_cb, (void *)sub_arg))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mlx_kem_export(void *vkey, int selection, OSSL_CALLBACK *param_cb,
|
||||
void *cbarg)
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
OSSL_PARAM_BLD *tmpl = NULL;
|
||||
OSSL_PARAM *params = NULL;
|
||||
size_t publen;
|
||||
size_t prvlen;
|
||||
int ret = 0;
|
||||
EXPORT_CB_ARG sub_arg;
|
||||
|
||||
if (!ossl_prov_is_running() || key == NULL)
|
||||
return 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
/* Fail when no key material has yet been provided */
|
||||
if (!mlx_kem_have_pubkey(key)) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
publen = key->minfo->pubkey_bytes + key->xinfo->pubkey_bytes;
|
||||
prvlen = key->minfo->prvkey_bytes + key->xinfo->prvkey_bytes;
|
||||
memset(&sub_arg, 0, sizeof(sub_arg));
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
|
||||
sub_arg.pubenc = OPENSSL_malloc(publen);
|
||||
if (sub_arg.pubenc == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (mlx_kem_have_prvkey(key)
|
||||
&& (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
|
||||
/*
|
||||
* Allocated on the secure heap if configured, this is detected in
|
||||
* ossl_param_build_set_octet_string(), which will then also use the
|
||||
* secure heap.
|
||||
*/
|
||||
sub_arg.prvenc = OPENSSL_secure_zalloc(prvlen);
|
||||
if (sub_arg.prvenc == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
tmpl = OSSL_PARAM_BLD_new();
|
||||
if (tmpl == NULL)
|
||||
goto err;
|
||||
|
||||
/* Extract sub-component key material */
|
||||
if (!export_sub(&sub_arg, selection, key))
|
||||
goto err;
|
||||
|
||||
if (sub_arg.pubenc != NULL && sub_arg.pubcount == 2
|
||||
&& !ossl_param_build_set_octet_string(
|
||||
tmpl, NULL, OSSL_PKEY_PARAM_PUB_KEY, sub_arg.pubenc, publen))
|
||||
goto err;
|
||||
|
||||
if (sub_arg.prvenc != NULL && sub_arg.prvcount == 2
|
||||
&& !ossl_param_build_set_octet_string(
|
||||
tmpl, NULL, OSSL_PKEY_PARAM_PRIV_KEY, sub_arg.prvenc, prvlen))
|
||||
goto err;
|
||||
|
||||
params = OSSL_PARAM_BLD_to_param(tmpl);
|
||||
if (params == NULL)
|
||||
goto err;
|
||||
|
||||
ret = param_cb(params, cbarg);
|
||||
OSSL_PARAM_free(params);
|
||||
|
||||
err:
|
||||
OSSL_PARAM_BLD_free(tmpl);
|
||||
OPENSSL_secure_clear_free(sub_arg.prvenc, prvlen);
|
||||
OPENSSL_free(sub_arg.pubenc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *mlx_kem_imexport_types(int selection)
|
||||
{
|
||||
static const OSSL_PARAM key_types[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
|
||||
return key_types;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
load_slot(OSSL_LIB_CTX *libctx, const char *propq, const char *pname,
|
||||
int selection, MLX_KEY *key, int slot, const uint8_t *in,
|
||||
int mbytes, int xbytes)
|
||||
{
|
||||
EVP_PKEY_CTX *ctx;
|
||||
EVP_PKEY **ppkey;
|
||||
OSSL_PARAM parr[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
|
||||
const char *alg;
|
||||
char *group = NULL;
|
||||
size_t off, len;
|
||||
void *val;
|
||||
int ml_kem_slot = key->xinfo->ml_kem_slot;
|
||||
int ret = 0;
|
||||
|
||||
if (slot == ml_kem_slot) {
|
||||
alg = key->minfo->algorithm_name;
|
||||
ppkey = &key->mkey;
|
||||
off = slot * xbytes;
|
||||
len = mbytes;
|
||||
} else {
|
||||
alg = key->xinfo->algorithm_name;
|
||||
group = (char *) key->xinfo->group_name;
|
||||
ppkey = &key->xkey;
|
||||
off = (1 - ml_kem_slot) * mbytes;
|
||||
len = xbytes;
|
||||
}
|
||||
val = (void *)(in + off);
|
||||
|
||||
if ((ctx = EVP_PKEY_CTX_new_from_name(libctx, alg, propq)) == NULL
|
||||
|| EVP_PKEY_fromdata_init(ctx) <= 0)
|
||||
goto err;
|
||||
parr[0] = OSSL_PARAM_construct_octet_string(pname, val, len);
|
||||
if (group != NULL)
|
||||
parr[1] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
|
||||
group, 0);
|
||||
if (EVP_PKEY_fromdata(ctx, ppkey, selection, parr) > 0)
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
load_keys(MLX_KEY *key,
|
||||
const uint8_t *pubenc, size_t publen,
|
||||
const uint8_t *prvenc, size_t prvlen)
|
||||
{
|
||||
int slot;
|
||||
|
||||
for (slot = 0; slot < 2; ++slot) {
|
||||
if (prvlen) {
|
||||
/* Ignore public keys when private provided */
|
||||
if (!load_slot(key->libctx, key->propq, OSSL_PKEY_PARAM_PRIV_KEY,
|
||||
minimal_selection, key, slot, prvenc,
|
||||
key->minfo->prvkey_bytes, key->xinfo->prvkey_bytes))
|
||||
goto err;
|
||||
} else if (publen) {
|
||||
/* Absent private key data, import public keys */
|
||||
if (!load_slot(key->libctx, key->propq, OSSL_PKEY_PARAM_PUB_KEY,
|
||||
minimal_selection, key, slot, pubenc,
|
||||
key->minfo->pubkey_bytes, key->xinfo->pubkey_bytes))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
key->state = prvlen ? MLX_HAVE_PRVKEY : MLX_HAVE_PUBKEY;
|
||||
return 1;
|
||||
|
||||
err:
|
||||
EVP_PKEY_free(key->mkey);
|
||||
EVP_PKEY_free(key->xkey);
|
||||
key->xkey = key->mkey = NULL;
|
||||
key->state = MLX_HAVE_NOKEYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx_kem_key_fromdata(MLX_KEY *key,
|
||||
const OSSL_PARAM params[],
|
||||
int include_private)
|
||||
{
|
||||
const OSSL_PARAM *param_prv_key = NULL, *param_pub_key;
|
||||
const void *pubenc = NULL, *prvenc = NULL;
|
||||
size_t pubkey_bytes, prvkey_bytes;
|
||||
size_t publen = 0, prvlen = 0;
|
||||
|
||||
/* Invalid attempt to mutate a key, what is the right error to report? */
|
||||
if (key == NULL || mlx_kem_have_pubkey(key))
|
||||
return 0;
|
||||
pubkey_bytes = key->minfo->pubkey_bytes + key->xinfo->pubkey_bytes;
|
||||
prvkey_bytes = key->minfo->prvkey_bytes + key->xinfo->prvkey_bytes;
|
||||
|
||||
/* What does the caller want to set? */
|
||||
param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
|
||||
if (param_pub_key != NULL &&
|
||||
OSSL_PARAM_get_octet_string_ptr(param_pub_key, &pubenc, &publen) != 1)
|
||||
return 0;
|
||||
if (include_private)
|
||||
param_prv_key = OSSL_PARAM_locate_const(params,
|
||||
OSSL_PKEY_PARAM_PRIV_KEY);
|
||||
if (param_prv_key != NULL &&
|
||||
OSSL_PARAM_get_octet_string_ptr(param_prv_key, &prvenc, &prvlen) != 1)
|
||||
return 0;
|
||||
|
||||
/* The caller MUST specify at least one of the public or private keys. */
|
||||
if (publen == 0 && prvlen == 0) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a pubkey is provided, its length MUST be correct, if a private key
|
||||
* is also provided, the public key will be otherwise ignored. We could
|
||||
* look for a matching encoded block, but unclear this is useful.
|
||||
*/
|
||||
if (publen != 0 && publen != pubkey_bytes) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if (prvlen != 0 && prvlen != prvkey_bytes) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return load_keys(key, pubenc, publen, prvenc, prvlen);
|
||||
}
|
||||
|
||||
static int mlx_kem_import(void *vkey, int selection, const OSSL_PARAM params[])
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
int include_private;
|
||||
|
||||
if (!ossl_prov_is_running() || key == NULL)
|
||||
return 0;
|
||||
|
||||
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return 0;
|
||||
|
||||
include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
|
||||
return mlx_kem_key_fromdata(key, params, include_private);
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *mlx_kem_gettable_params(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM arr[] = {
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
|
||||
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/*
|
||||
* It is assumed the key is guaranteed non-NULL here, and is from this provider
|
||||
*/
|
||||
static int mlx_kem_get_params(void *vkey, OSSL_PARAM params[])
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
OSSL_PARAM *p, *pub, *prv = NULL;
|
||||
EXPORT_CB_ARG sub_arg;
|
||||
int selection;
|
||||
size_t publen = key->minfo->pubkey_bytes + key->xinfo->pubkey_bytes;
|
||||
size_t prvlen = key->minfo->prvkey_bytes + key->xinfo->prvkey_bytes;
|
||||
|
||||
/* The reported "bit" count is those of the ML-KEM key */
|
||||
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS);
|
||||
if (p != NULL)
|
||||
if (!OSSL_PARAM_set_int(p, key->minfo->bits))
|
||||
return 0;
|
||||
|
||||
/* The reported security bits are those of the ML-KEM key */
|
||||
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS);
|
||||
if (p != NULL)
|
||||
if (!OSSL_PARAM_set_int(p, key->minfo->secbits))
|
||||
return 0;
|
||||
|
||||
/* The ciphertext sizes are additive */
|
||||
p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE);
|
||||
if (p != NULL)
|
||||
if (!OSSL_PARAM_set_int(p, key->minfo->ctext_bytes + key->xinfo->pubkey_bytes))
|
||||
return 0;
|
||||
|
||||
if (!mlx_kem_have_pubkey(key))
|
||||
return 1;
|
||||
|
||||
memset(&sub_arg, 0, sizeof(sub_arg));
|
||||
pub = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
|
||||
if (pub != NULL) {
|
||||
if (pub->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
pub->return_size = publen;
|
||||
if (pub->data == NULL) {
|
||||
pub = NULL;
|
||||
} else if (pub->data_size < publen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"public key output buffer too short: %lu < %lu",
|
||||
(unsigned long) pub->data_size,
|
||||
(unsigned long) publen);
|
||||
return 0;
|
||||
} else {
|
||||
sub_arg.pubenc = pub->data;
|
||||
}
|
||||
}
|
||||
if (mlx_kem_have_prvkey(key)) {
|
||||
prv = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
|
||||
if (prv != NULL) {
|
||||
if (prv->data_type != OSSL_PARAM_OCTET_STRING)
|
||||
return 0;
|
||||
prv->return_size = prvlen;
|
||||
if (prv->data == NULL) {
|
||||
prv = NULL;
|
||||
} else if (prv->data_size < prvlen) {
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL,
|
||||
"private key output buffer too short: %lu < %lu",
|
||||
(unsigned long) prv->data_size,
|
||||
(unsigned long) prvlen);
|
||||
return 0;
|
||||
} else {
|
||||
sub_arg.prvenc = prv->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pub == NULL && prv == NULL)
|
||||
return 1;
|
||||
|
||||
selection = prv == NULL ? 0 : OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
||||
selection |= pub == NULL ? 0 : OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
||||
if (key->xinfo->group_name != NULL)
|
||||
selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
|
||||
|
||||
/* Extract sub-component key material */
|
||||
if (!export_sub(&sub_arg, selection, key))
|
||||
return 0;
|
||||
|
||||
if ((pub != NULL && sub_arg.pubcount != 2)
|
||||
|| (prv != NULL && sub_arg.prvcount != 2))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *mlx_kem_settable_params(void *provctx)
|
||||
{
|
||||
static const OSSL_PARAM arr[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
static int mlx_kem_set_params(void *vkey, const OSSL_PARAM params[])
|
||||
{
|
||||
MLX_KEY *key = vkey;
|
||||
const OSSL_PARAM *p;
|
||||
const void *pubenc = NULL;
|
||||
size_t publen = 0;
|
||||
|
||||
if (ossl_param_is_empty(params))
|
||||
return 1;
|
||||
|
||||
/* Only one settable parameter is supported */
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
|
||||
if (p == NULL)
|
||||
return 1;
|
||||
|
||||
/* Key mutation is reportedly generally not allowed */
|
||||
if (mlx_kem_have_pubkey(key)) {
|
||||
ERR_raise_data(ERR_LIB_PROV,
|
||||
PROV_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE,
|
||||
"keys cannot be mutated");
|
||||
return 0;
|
||||
}
|
||||
/* An unlikely failure mode is the parameter having some unexpected type */
|
||||
if (!OSSL_PARAM_get_octet_string_ptr(p, &pubenc, &publen))
|
||||
return 0;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
|
||||
if (p != NULL) {
|
||||
OPENSSL_free(key->propq);
|
||||
key->propq = NULL;
|
||||
if (!OSSL_PARAM_get_utf8_string(p, &key->propq, 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (publen != key->minfo->pubkey_bytes + key->xinfo->pubkey_bytes) {
|
||||
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return load_keys(key, pubenc, publen, NULL, 0);
|
||||
}
|
||||
|
||||
static int mlx_kem_gen_set_params(void *vgctx, const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_ML_KEM_GEN_CTX *gctx = vgctx;
|
||||
const OSSL_PARAM *p;
|
||||
|
||||
if (gctx == NULL)
|
||||
return 0;
|
||||
if (ossl_param_is_empty(params))
|
||||
return 1;
|
||||
|
||||
p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
|
||||
if (p != NULL) {
|
||||
if (p->data_type != OSSL_PARAM_UTF8_STRING)
|
||||
return 0;
|
||||
OPENSSL_free(gctx->propq);
|
||||
if ((gctx->propq = OPENSSL_strdup(p->data)) == NULL)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *mlx_kem_gen_init(int v, OSSL_LIB_CTX *libctx, int selection,
|
||||
const OSSL_PARAM params[])
|
||||
{
|
||||
PROV_ML_KEM_GEN_CTX *gctx = NULL;
|
||||
|
||||
/*
|
||||
* We can only generate private keys, check that the selection is
|
||||
* appropriate.
|
||||
*/
|
||||
if (!ossl_prov_is_running()
|
||||
|| (selection & minimal_selection) == 0
|
||||
|| (gctx = OPENSSL_zalloc(sizeof(*gctx))) == NULL)
|
||||
return NULL;
|
||||
|
||||
gctx->variant = v;
|
||||
gctx->libctx = libctx;
|
||||
gctx->selection = selection;
|
||||
if (mlx_kem_gen_set_params(gctx, params))
|
||||
return gctx;
|
||||
|
||||
mlx_kem_gen_cleanup(gctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const OSSL_PARAM *mlx_kem_gen_settable_params(ossl_unused void *vgctx,
|
||||
ossl_unused void *provctx)
|
||||
{
|
||||
static OSSL_PARAM settable[] = {
|
||||
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
|
||||
OSSL_PARAM_END
|
||||
};
|
||||
|
||||
return settable;
|
||||
}
|
||||
|
||||
static void *mlx_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)
|
||||
{
|
||||
PROV_ML_KEM_GEN_CTX *gctx = vgctx;
|
||||
MLX_KEY *key;
|
||||
char *propq = gctx->propq;
|
||||
|
||||
if (gctx == NULL
|
||||
|| (gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) ==
|
||||
OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
|
||||
return NULL;
|
||||
|
||||
/* Lose ownership of propq */
|
||||
gctx->propq = NULL;
|
||||
if ((key = mlx_kem_key_new(gctx->variant, gctx->libctx, propq)) == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
|
||||
return key;
|
||||
|
||||
/* For now, using the same "propq" for all components */
|
||||
key->mkey = EVP_PKEY_Q_keygen(key->libctx, key->propq,
|
||||
key->minfo->algorithm_name);
|
||||
key->xkey = EVP_PKEY_Q_keygen(key->libctx, key->propq,
|
||||
key->xinfo->algorithm_name,
|
||||
key->xinfo->group_name);
|
||||
if (key->mkey != NULL && key->xkey != NULL) {
|
||||
key->state = MLX_HAVE_PRVKEY;
|
||||
return key;
|
||||
}
|
||||
|
||||
mlx_kem_key_free(key);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void mlx_kem_gen_cleanup(void *vgctx)
|
||||
{
|
||||
PROV_ML_KEM_GEN_CTX *gctx = vgctx;
|
||||
|
||||
if (gctx == NULL)
|
||||
return;
|
||||
OPENSSL_free(gctx->propq);
|
||||
OPENSSL_free(gctx);
|
||||
}
|
||||
|
||||
static void *mlx_kem_dup(const void *vkey, int selection)
|
||||
{
|
||||
const MLX_KEY *key = vkey;
|
||||
MLX_KEY *ret;
|
||||
|
||||
if (!ossl_prov_is_running()
|
||||
|| (ret = OPENSSL_memdup(key, sizeof(*ret))) == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) {
|
||||
case 0:
|
||||
ret->xkey = ret->mkey = NULL;
|
||||
return ret;
|
||||
case OSSL_KEYMGMT_SELECT_KEYPAIR:
|
||||
ret->mkey = EVP_PKEY_dup(key->mkey);
|
||||
ret->xkey = EVP_PKEY_dup(key->xkey);
|
||||
if (ret->xkey != NULL && ret->mkey != NULL)
|
||||
return ret;
|
||||
break;
|
||||
default:
|
||||
ERR_raise_data(ERR_LIB_PROV, PROV_R_UNSUPPORTED_SELECTION,
|
||||
"duplication of partial key material not supported");
|
||||
break;
|
||||
}
|
||||
|
||||
mlx_kem_key_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define DECLARE_DISPATCH(name, variant) \
|
||||
static OSSL_FUNC_keymgmt_new_fn mlx_##name##_kem_new; \
|
||||
static void *mlx_##name##_kem_new(void *provctx) \
|
||||
{ \
|
||||
OSSL_LIB_CTX *libctx; \
|
||||
\
|
||||
libctx = provctx == NULL ? NULL : PROV_LIBCTX_OF(provctx); \
|
||||
return mlx_kem_key_new(variant, libctx, NULL); \
|
||||
} \
|
||||
static OSSL_FUNC_keymgmt_gen_init_fn mlx_##name##_kem_gen_init; \
|
||||
static void *mlx_##name##_kem_gen_init(void *provctx, int selection, \
|
||||
const OSSL_PARAM params[]) \
|
||||
{ \
|
||||
OSSL_LIB_CTX *libctx; \
|
||||
\
|
||||
libctx = provctx == NULL ? NULL : PROV_LIBCTX_OF(provctx); \
|
||||
return mlx_kem_gen_init(variant, libctx, selection, params); \
|
||||
} \
|
||||
const OSSL_DISPATCH ossl_mlx_##name##_kem_kmgmt_functions[] = { \
|
||||
{ OSSL_FUNC_KEYMGMT_NEW, (OSSL_FUNC) mlx_##name##_kem_new }, \
|
||||
{ OSSL_FUNC_KEYMGMT_FREE, (OSSL_FUNC) mlx_kem_key_free }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GET_PARAMS, (OSSL_FUNC) mlx_kem_get_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (OSSL_FUNC) mlx_kem_gettable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SET_PARAMS, (OSSL_FUNC) mlx_kem_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (OSSL_FUNC) mlx_kem_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_HAS, (OSSL_FUNC) mlx_kem_has }, \
|
||||
{ OSSL_FUNC_KEYMGMT_MATCH, (OSSL_FUNC) mlx_kem_match }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_INIT, (OSSL_FUNC) mlx_##name##_kem_gen_init }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (OSSL_FUNC) mlx_kem_gen_set_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, (OSSL_FUNC) mlx_kem_gen_settable_params }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN, (OSSL_FUNC) mlx_kem_gen }, \
|
||||
{ OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (OSSL_FUNC) mlx_kem_gen_cleanup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_DUP, (OSSL_FUNC) mlx_kem_dup }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT, (OSSL_FUNC) mlx_kem_import }, \
|
||||
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (OSSL_FUNC) mlx_kem_imexport_types }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT, (OSSL_FUNC) mlx_kem_export }, \
|
||||
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (OSSL_FUNC) mlx_kem_imexport_types }, \
|
||||
OSSL_DISPATCH_END \
|
||||
}
|
||||
/* See |hybrid_vtable| above */
|
||||
DECLARE_DISPATCH(p256, 0);
|
||||
DECLARE_DISPATCH(p384, 1);
|
||||
#if !defined(OPENSSL_NO_ECX)
|
||||
DECLARE_DISPATCH(x25519, 2);
|
||||
DECLARE_DISPATCH(x448, 3);
|
||||
#endif
|
@ -4079,6 +4079,12 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
||||
&ctx->ext.tuples_len,
|
||||
parg);
|
||||
|
||||
case SSL_CTRL_GET0_IMPLEMENTED_GROUPS:
|
||||
return tls1_get0_implemented_groups(ctx->min_proto_version,
|
||||
ctx->max_proto_version,
|
||||
ctx->group_list,
|
||||
ctx->group_list_len, larg, parg);
|
||||
|
||||
case SSL_CTRL_SET_SIGALGS:
|
||||
return tls1_set_sigalgs(ctx->cert, parg, larg, 0);
|
||||
|
||||
|
@ -2839,6 +2839,11 @@ __owur int tls1_group_id2nid(uint16_t group_id, int include_unknown);
|
||||
__owur uint16_t tls1_nid2group_id(int nid);
|
||||
__owur int tls1_check_group_id(SSL_CONNECTION *s, uint16_t group_id,
|
||||
int check_own_curves);
|
||||
__owur int tls1_get0_implemented_groups(int min_proto_version,
|
||||
int max_proto_version,
|
||||
TLS_GROUP_INFO *grps,
|
||||
size_t num, long all,
|
||||
STACK_OF(OPENSSL_CSTRING) *out);
|
||||
__owur uint16_t tls1_shared_group(SSL_CONNECTION *s, int nmatch);
|
||||
__owur int tls1_set_groups(uint16_t **grpext, size_t *grpextlen,
|
||||
uint16_t **ksext, size_t *ksextlen,
|
||||
|
75
ssl/t1_lib.c
75
ssl/t1_lib.c
@ -977,6 +977,81 @@ static int tls1_in_list(uint16_t id, const uint16_t *list, size_t listlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
TLS_GROUP_INFO *grp;
|
||||
size_t ix;
|
||||
} TLS_GROUP_IX;
|
||||
|
||||
DEFINE_STACK_OF(TLS_GROUP_IX)
|
||||
|
||||
static void free_wrapper(TLS_GROUP_IX *a)
|
||||
{
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
static int tls_group_ix_cmp(const TLS_GROUP_IX *const *a,
|
||||
const TLS_GROUP_IX *const *b)
|
||||
{
|
||||
int idcmpab = (*a)->grp->group_id < (*b)->grp->group_id;
|
||||
int idcmpba = (*b)->grp->group_id < (*a)->grp->group_id;
|
||||
int ixcmpab = (*a)->ix < (*b)->ix;
|
||||
int ixcmpba = (*b)->ix < (*a)->ix;
|
||||
|
||||
/* Ascending by group id */
|
||||
if (idcmpab != idcmpba)
|
||||
return (idcmpba - idcmpab);
|
||||
/* Ascending by original appearance index */
|
||||
return ixcmpba - ixcmpab;
|
||||
}
|
||||
|
||||
int tls1_get0_implemented_groups(int min_proto_version, int max_proto_version,
|
||||
TLS_GROUP_INFO *grps, size_t num, long all,
|
||||
STACK_OF(OPENSSL_CSTRING) *out)
|
||||
{
|
||||
STACK_OF(TLS_GROUP_IX) *collect = NULL;
|
||||
TLS_GROUP_IX *gix;
|
||||
uint16_t id = 0;
|
||||
int ret = 0;
|
||||
size_t ix;
|
||||
|
||||
if ((collect = sk_TLS_GROUP_IX_new(tls_group_ix_cmp)) == NULL)
|
||||
return 0;
|
||||
|
||||
if (grps == NULL || out == NULL)
|
||||
return 0;
|
||||
for (ix = 0; ix < num; ++ix, ++grps) {
|
||||
if (grps->mintls > 0 && max_proto_version > 0
|
||||
&& grps->mintls > max_proto_version)
|
||||
continue;
|
||||
if (grps->maxtls > 0 && min_proto_version > 0
|
||||
&& grps->maxtls < min_proto_version)
|
||||
continue;
|
||||
|
||||
if ((gix = OPENSSL_malloc(sizeof(*gix))) == NULL)
|
||||
goto end;
|
||||
gix->grp = grps;
|
||||
gix->ix = ix;
|
||||
if (sk_TLS_GROUP_IX_push(collect, gix) <= 0)
|
||||
goto end;
|
||||
}
|
||||
|
||||
sk_TLS_GROUP_IX_sort(collect);
|
||||
num = sk_TLS_GROUP_IX_num(collect);
|
||||
for (ix = 0; ix < num; ++ix) {
|
||||
gix = sk_TLS_GROUP_IX_value(collect, ix);
|
||||
if (!all && gix->grp->group_id == id)
|
||||
continue;
|
||||
id = gix->grp->group_id;
|
||||
if (sk_OPENSSL_CSTRING_push(out, gix->grp->tlsname) <= 0)
|
||||
goto end;
|
||||
}
|
||||
return 1;
|
||||
|
||||
end:
|
||||
sk_TLS_GROUP_IX_pop_free(collect, free_wrapper);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*-
|
||||
* For nmatch >= 0, return the id of the |nmatch|th shared group or 0
|
||||
* if there is no match.
|
||||
|
@ -4938,9 +4938,12 @@ static int test_ciphersuite_change(void)
|
||||
* Test 13 = Test MLKEM512
|
||||
* Test 14 = Test MLKEM768
|
||||
* Test 15 = Test MLKEM1024
|
||||
* Test 16 = Test all ML-KEM with TLSv1.2 client and server
|
||||
* Test 17 = Test all FFDHE with TLSv1.2 client and server
|
||||
* Test 18 = Test all ECDHE with TLSv1.2 client and server
|
||||
* Test 16 = Test X25519MLKEM768
|
||||
* Test 17 = Test SecP256r1MLKEM768
|
||||
* Test 18 = Test SecP384r1MLKEM1024
|
||||
* Test 19 = Test all ML-KEM with TLSv1.2 client and server
|
||||
* Test 20 = Test all FFDHE with TLSv1.2 client and server
|
||||
* Test 21 = Test all ECDHE with TLSv1.2 client and server
|
||||
*/
|
||||
# ifndef OPENSSL_NO_EC
|
||||
static int ecdhe_kexch_groups[] = {NID_X9_62_prime256v1, NID_secp384r1,
|
||||
@ -4970,7 +4973,7 @@ static int test_key_exchange(int idx)
|
||||
switch (idx) {
|
||||
# ifndef OPENSSL_NO_EC
|
||||
# ifndef OPENSSL_NO_TLS1_2
|
||||
case 18:
|
||||
case 21:
|
||||
max_version = TLS1_2_VERSION;
|
||||
# endif
|
||||
/* Fall through */
|
||||
@ -5008,7 +5011,7 @@ static int test_key_exchange(int idx)
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_DH
|
||||
# ifndef OPENSSL_NO_TLS1_2
|
||||
case 17:
|
||||
case 20:
|
||||
max_version = TLS1_2_VERSION;
|
||||
kexch_name0 = "ffdhe2048";
|
||||
# endif
|
||||
@ -5041,7 +5044,7 @@ static int test_key_exchange(int idx)
|
||||
# endif
|
||||
# ifndef OPENSSL_NO_ML_KEM
|
||||
# if !defined(OPENSSL_NO_TLS1_2)
|
||||
case 16:
|
||||
case 19:
|
||||
max_version = TLS1_2_VERSION;
|
||||
# if !defined(OPENSSL_NO_EC)
|
||||
/* Set at least one EC group so the handshake completes */
|
||||
@ -5083,6 +5086,25 @@ static int test_key_exchange(int idx)
|
||||
kexch_name0 = "MLKEM1024";
|
||||
kexch_names = kexch_name0;
|
||||
break;
|
||||
# ifndef OPENSSL_NO_EC
|
||||
# ifndef OPENSSL_NO_ECX
|
||||
case 16:
|
||||
kexch_groups = NULL;
|
||||
kexch_name0 = "X25519MLKEM768";
|
||||
kexch_names = kexch_name0;
|
||||
break;
|
||||
# endif
|
||||
case 17:
|
||||
kexch_groups = NULL;
|
||||
kexch_name0 = "SecP256r1MLKEM768";
|
||||
kexch_names = kexch_name0;
|
||||
break;
|
||||
case 18:
|
||||
kexch_groups = NULL;
|
||||
kexch_name0 = "SecP384r1MLKEM1024";
|
||||
kexch_names = kexch_name0;
|
||||
break;
|
||||
# endif
|
||||
# endif
|
||||
default:
|
||||
/* We're skipping this test */
|
||||
@ -5090,7 +5112,7 @@ static int test_key_exchange(int idx)
|
||||
}
|
||||
|
||||
/* ML-KEM not yet supported in the FIPS module */
|
||||
if (is_fips && idx >= 12 && idx <= 16) {
|
||||
if (is_fips && idx >= 12 && idx <= 19) {
|
||||
testresult = 1;
|
||||
goto end;
|
||||
};
|
||||
@ -5144,13 +5166,14 @@ static int test_key_exchange(int idx)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* If Handshake succeeds the negotiated kexch alg should be the first one in
|
||||
* configured, except in the case of FFDHE and ML-KEM groups (idx == 17, 18),
|
||||
* which are TLSv1.3 only so we expect no shared group to exist.
|
||||
* If the handshake succeeds the negotiated kexch alg should be the first
|
||||
* one in configured, except in the case of "all" FFDHE and "all" ML-KEM
|
||||
* groups (idx == 19, 20), which are TLSv1.3 only so we expect no shared
|
||||
* group to exist.
|
||||
*/
|
||||
shared_group0 = SSL_get_shared_group(serverssl, 0);
|
||||
switch (idx) {
|
||||
case 16:
|
||||
case 19:
|
||||
# if !defined(OPENSSL_NO_EC)
|
||||
/* MLKEM + TLS 1.2 and no DH => "secp526r1" */
|
||||
if (!TEST_int_eq(shared_group0, NID_X9_62_prime256v1))
|
||||
@ -5158,7 +5181,7 @@ static int test_key_exchange(int idx)
|
||||
break;
|
||||
# endif
|
||||
/* Fall through */
|
||||
case 17:
|
||||
case 20:
|
||||
if (!TEST_int_eq(shared_group0, 0))
|
||||
goto end;
|
||||
break;
|
||||
@ -12961,7 +12984,7 @@ int setup_tests(void)
|
||||
#endif /* OSSL_NO_USABLE_TLS1_3 */
|
||||
# ifndef OPENSSL_NO_TLS1_2
|
||||
/* Test with both TLSv1.3 and 1.2 versions */
|
||||
ADD_ALL_TESTS(test_key_exchange, 18);
|
||||
ADD_ALL_TESTS(test_key_exchange, 21);
|
||||
# if !defined(OPENSSL_NO_EC) && !defined(OPENSSL_NO_DH)
|
||||
ADD_ALL_TESTS(test_negotiated_group,
|
||||
4 * (OSSL_NELEM(ecdhe_kexch_groups)
|
||||
@ -12969,7 +12992,7 @@ int setup_tests(void)
|
||||
# endif
|
||||
# else
|
||||
/* Test with only TLSv1.3 versions */
|
||||
ADD_ALL_TESTS(test_key_exchange, 15);
|
||||
ADD_ALL_TESTS(test_key_exchange, 18);
|
||||
# endif
|
||||
ADD_ALL_TESTS(test_custom_exts, 6);
|
||||
ADD_TEST(test_stateless);
|
||||
|
@ -542,6 +542,7 @@ SSL_CTX_disable_ct define
|
||||
SSL_CTX_generate_session_ticket_fn define
|
||||
SSL_CTX_get0_chain_certs define
|
||||
SSL_CTX_get0_chain_cert_store define
|
||||
SSL_CTX_get0_implemented_groups define
|
||||
SSL_CTX_get0_verify_cert_store define
|
||||
SSL_CTX_get_default_read_ahead define
|
||||
SSL_CTX_get_extra_chain_certs define
|
||||
|
Loading…
x
Reference in New Issue
Block a user