Make hybrid MLKEM work with our FIPS provider (3.0.7)

Resolves: RHEL-95239
This commit is contained in:
Dmitry Belyavskiy 2025-06-03 17:30:09 +02:00
parent 36bf905365
commit ea4218d43c
2 changed files with 307 additions and 0 deletions

View File

@ -0,0 +1,302 @@
From 26ad3b905a6d4b1fa50b304f21f67aa0d35265e9 Mon Sep 17 00:00:00 2001
From: Dmitry Belyavskiy <beldmit@gmail.com>
Date: Fri, 30 May 2025 16:17:37 +0200
Subject: [PATCH 58/58] Allow hybrid MLKEM in FIPS mode
---
crypto/ml_kem/ml_kem.c | 11 ++--
include/crypto/ml_kem.h | 2 +
providers/defltprov.c | 8 +--
providers/implementations/kem/mlx_kem.c | 33 +++++++++-
providers/implementations/keymgmt/mlx_kmgmt.c | 61 ++++++++++++++++++-
5 files changed, 103 insertions(+), 12 deletions(-)
diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c
index ec75233435..8d0cc1a82c 100644
--- a/crypto/ml_kem/ml_kem.c
+++ b/crypto/ml_kem/ml_kem.c
@@ -1581,6 +1581,7 @@ ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties,
{
const ML_KEM_VINFO *vinfo = ossl_ml_kem_get_vinfo(evp_type);
ML_KEM_KEY *key;
+ char *adjusted_propq = NULL;
if (vinfo == NULL)
return NULL;
@@ -1588,15 +1589,17 @@ ML_KEM_KEY *ossl_ml_kem_key_new(OSSL_LIB_CTX *libctx, const char *properties,
if ((key = OPENSSL_malloc(sizeof(*key))) == NULL)
return NULL;
+ adjusted_propq = get_adjusted_propq(properties);
key->vinfo = vinfo;
key->libctx = libctx;
key->prov_flags = ML_KEM_KEY_PROV_FLAGS_DEFAULT;
- key->shake128_md = EVP_MD_fetch(libctx, "SHAKE128", properties);
- key->shake256_md = EVP_MD_fetch(libctx, "SHAKE256", properties);
- key->sha3_256_md = EVP_MD_fetch(libctx, "SHA3-256", properties);
- key->sha3_512_md = EVP_MD_fetch(libctx, "SHA3-512", properties);
+ key->shake128_md = EVP_MD_fetch(libctx, "SHAKE128", adjusted_propq ? adjusted_propq : properties);
+ key->shake256_md = EVP_MD_fetch(libctx, "SHAKE256", adjusted_propq ? adjusted_propq : properties);
+ key->sha3_256_md = EVP_MD_fetch(libctx, "SHA3-256", adjusted_propq ? adjusted_propq : properties);
+ key->sha3_512_md = EVP_MD_fetch(libctx, "SHA3-512", adjusted_propq ? adjusted_propq : properties);
key->d = key->z = key->rho = key->pkhash = key->encoded_dk = NULL;
key->s = key->m = key->t = NULL;
+ OPENSSL_free(adjusted_propq);
if (key->shake128_md != NULL
&& key->shake256_md != NULL
diff --git a/include/crypto/ml_kem.h b/include/crypto/ml_kem.h
index 67d55697e9..ab1aaae8ac 100644
--- a/include/crypto/ml_kem.h
+++ b/include/crypto/ml_kem.h
@@ -278,4 +278,6 @@ int ossl_ml_kem_decap(uint8_t *shared_secret, size_t slen,
__owur
int ossl_ml_kem_pubkey_cmp(const ML_KEM_KEY *key1, const ML_KEM_KEY *key2);
+char *get_adjusted_propq(const char *propq);
+
#endif /* OPENSSL_HEADER_ML_KEM_H */
diff --git a/providers/defltprov.c b/providers/defltprov.c
index eee2178b41..0dba017f3f 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -517,8 +517,8 @@ static const OSSL_ALGORITHM deflt_asym_kem[] = {
{ "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 },
+ { "SecP256r1MLKEM768", "provider=default,fips=yes", ossl_mlx_kem_asym_kem_functions },
+ { "SecP384r1MLKEM1024", "provider=default,fips=yes", ossl_mlx_kem_asym_kem_functions },
# endif
#endif
{ NULL, NULL, NULL }
@@ -597,9 +597,9 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
PROV_DESCS_X448MLKEM1024 },
# endif
# if !defined(OPENSSL_NO_EC)
- { PROV_NAMES_SecP256r1MLKEM768, "provider=default", ossl_mlx_p256_kem_kmgmt_functions,
+ { PROV_NAMES_SecP256r1MLKEM768, "provider=default,fips=yes", ossl_mlx_p256_kem_kmgmt_functions,
PROV_DESCS_SecP256r1MLKEM768 },
- { PROV_NAMES_SecP384r1MLKEM1024, "provider=default", ossl_mlx_p384_kem_kmgmt_functions,
+ { PROV_NAMES_SecP384r1MLKEM1024, "provider=default,fips=yes", ossl_mlx_p384_kem_kmgmt_functions,
PROV_DESCS_SecP384r1MLKEM1024 },
# endif
#endif
diff --git a/providers/implementations/kem/mlx_kem.c b/providers/implementations/kem/mlx_kem.c
index 197c345d85..08fbf99a76 100644
--- a/providers/implementations/kem/mlx_kem.c
+++ b/providers/implementations/kem/mlx_kem.c
@@ -19,6 +19,7 @@
#include "prov/mlx_kem.h"
#include "prov/provider_ctx.h"
#include "prov/providercommon.h"
+#include <string.h>
static OSSL_FUNC_kem_newctx_fn mlx_kem_newctx;
static OSSL_FUNC_kem_freectx_fn mlx_kem_freectx;
@@ -103,6 +104,28 @@ mlx_kem_set_ctx_params(void *vctx, const OSSL_PARAM params[])
return 1;
}
+char *get_adjusted_propq(const char *propq)
+{
+ char *adjusted_propq = NULL;
+ const char *nofips = "-fips";
+ size_t len = propq ? strlen(propq) + 1 + strlen(nofips) + 1 :
+ strlen(nofips) + 1;
+ char *ptr = NULL;
+
+ adjusted_propq = OPENSSL_zalloc(len);
+ if (adjusted_propq != NULL) {
+ ptr = adjusted_propq;
+ if (propq && strlen(propq) > 0) {
+ memcpy(ptr, propq, strlen(propq));
+ ptr += strlen(propq);
+ *ptr = ',';
+ ptr++;
+ }
+ memcpy(ptr, nofips, strlen(nofips));
+ }
+ return adjusted_propq;
+}
+
static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
unsigned char *shsec, size_t *slen)
{
@@ -115,6 +138,7 @@ static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
uint8_t *sbuf;
int ml_kem_slot = key->xinfo->ml_kem_slot;
int ret = 0;
+ char *adjusted_propq = NULL;
if (!mlx_kem_have_pubkey(key)) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
@@ -167,7 +191,8 @@ static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
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);
+ adjusted_propq = get_adjusted_propq(key->propq);
+ ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->mkey, adjusted_propq ? adjusted_propq : key->propq);
if (ctx == NULL
|| EVP_PKEY_encapsulate_init(ctx, NULL) <= 0
|| EVP_PKEY_encapsulate(ctx, cbuf, &encap_clen, sbuf, &encap_slen) <= 0)
@@ -237,6 +262,7 @@ static int mlx_kem_encapsulate(void *vctx, unsigned char *ctext, size_t *clen,
end:
EVP_PKEY_free(xkey);
EVP_PKEY_CTX_free(ctx);
+ OPENSSL_free(adjusted_propq);
return ret;
}
@@ -252,6 +278,7 @@ static int mlx_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen,
size_t decap_clen = key->minfo->ctext_bytes + key->xinfo->pubkey_bytes;
int ml_kem_slot = key->xinfo->ml_kem_slot;
int ret = 0;
+ char *adjusted_propq = NULL;
if (!mlx_kem_have_prvkey(key)) {
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_KEY);
@@ -287,7 +314,8 @@ static int mlx_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen,
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);
+ adjusted_propq = get_adjusted_propq(key->propq);
+ ctx = EVP_PKEY_CTX_new_from_pkey(key->libctx, key->mkey, adjusted_propq ? adjusted_propq : key->propq);
if (ctx == NULL
|| EVP_PKEY_decapsulate_init(ctx, NULL) <= 0
|| EVP_PKEY_decapsulate(ctx, sbuf, &decap_slen, cbuf, decap_clen) <= 0)
@@ -325,6 +353,7 @@ static int mlx_kem_decapsulate(void *vctx, uint8_t *shsec, size_t *slen,
end:
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(xkey);
+ OPENSSL_free(adjusted_propq);
return ret;
}
diff --git a/providers/implementations/keymgmt/mlx_kmgmt.c b/providers/implementations/keymgmt/mlx_kmgmt.c
index bea8783276..aeef0c8f84 100644
--- a/providers/implementations/keymgmt/mlx_kmgmt.c
+++ b/providers/implementations/keymgmt/mlx_kmgmt.c
@@ -156,6 +156,52 @@ typedef struct export_cb_arg_st {
size_t prvlen;
} EXPORT_CB_ARG;
+#ifndef FIPS_MODULE
+# include <openssl/bn.h>
+# include <openssl/ec.h>
+static size_t decompress_pub_key(void *pub, size_t compressed_len, size_t decompressed_len)
+{
+ EC_GROUP *group = NULL;
+ EC_POINT *point = NULL;
+ BN_CTX *ctx = NULL;
+ size_t len = compressed_len;
+ int group_nid = NID_undef;
+
+ switch (len) {
+ case 33:
+ group_nid = NID_X9_62_prime256v1;
+ break;
+ case 49:
+ group_nid = NID_secp384r1;
+ break;
+ default:
+ return len;
+ break;
+ }
+
+ ctx = BN_CTX_new();
+ group = EC_GROUP_new_by_curve_name(group_nid);
+ if (ctx == NULL || group == NULL)
+ goto err;
+
+ point = EC_POINT_new(group);
+ if (point == NULL)
+ goto err;
+
+ if (!EC_POINT_oct2point(group, point, pub, len, ctx))
+ goto err;
+
+ len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, pub, decompressed_len, ctx);
+
+err:
+ EC_POINT_free(point);
+ EC_GROUP_free(group);
+ BN_CTX_free(ctx);
+
+ return len;
+}
+#endif
+
/* Copy any exported key material into its storage slot */
static int export_sub_cb(const OSSL_PARAM *params, void *varg)
{
@@ -176,6 +222,10 @@ static int export_sub_cb(const OSSL_PARAM *params, void *varg)
if (OSSL_PARAM_get_octet_string(p, &pub, sub_arg->publen, &len) != 1)
return 0;
+#ifndef FIPS_MODULE
+ if (len < sub_arg->publen)
+ len = decompress_pub_key(pub, len, sub_arg->publen);
+#endif
if (len != sub_arg->publen) {
ERR_raise_data(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR,
"Unexpected %s public key length %lu != %lu",
@@ -344,12 +394,14 @@ load_slot(OSSL_LIB_CTX *libctx, const char *propq, const char *pname,
void *val;
int ml_kem_slot = key->xinfo->ml_kem_slot;
int ret = 0;
+ char *adjusted_propq = NULL;
if (slot == ml_kem_slot) {
alg = key->minfo->algorithm_name;
ppkey = &key->mkey;
off = slot * xbytes;
len = mbytes;
+ adjusted_propq = get_adjusted_propq(propq);
} else {
alg = key->xinfo->algorithm_name;
group = (char *) key->xinfo->group_name;
@@ -359,7 +411,8 @@ load_slot(OSSL_LIB_CTX *libctx, const char *propq, const char *pname,
}
val = (void *)(in + off);
- if ((ctx = EVP_PKEY_CTX_new_from_name(libctx, alg, propq)) == NULL
+ if ((ctx = EVP_PKEY_CTX_new_from_name(libctx, alg,
+ adjusted_propq ? adjusted_propq : propq)) == NULL
|| EVP_PKEY_fromdata_init(ctx) <= 0)
goto err;
parr[0] = OSSL_PARAM_construct_octet_string(pname, val, len);
@@ -370,6 +423,7 @@ load_slot(OSSL_LIB_CTX *libctx, const char *propq, const char *pname,
ret = 1;
err:
+ OPENSSL_free(adjusted_propq);
EVP_PKEY_CTX_free(ctx);
return ret;
}
@@ -688,6 +742,7 @@ static void *mlx_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)
PROV_ML_KEM_GEN_CTX *gctx = vgctx;
MLX_KEY *key;
char *propq;
+ char *adjusted_propq = NULL;
if (gctx == NULL
|| (gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) ==
@@ -704,8 +759,10 @@ static void *mlx_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)
return key;
/* For now, using the same "propq" for all components */
- key->mkey = EVP_PKEY_Q_keygen(key->libctx, key->propq,
+ adjusted_propq = get_adjusted_propq(propq);
+ key->mkey = EVP_PKEY_Q_keygen(key->libctx, adjusted_propq ? adjusted_propq : key->propq,
key->minfo->algorithm_name);
+ OPENSSL_free(adjusted_propq);
key->xkey = EVP_PKEY_Q_keygen(key->libctx, key->propq,
key->xinfo->algorithm_name,
key->xinfo->group_name);
--
2.49.0

View File

@ -96,6 +96,9 @@ Patch0054: 0054-crypto-disable-OSSL_PARAM_REAL-on-UEFI.patch
Patch0055: 0055-hashfunc-add-stddef.h-include.patch Patch0055: 0055-hashfunc-add-stddef.h-include.patch
Patch0056: 0056-rio-add-RIO_POLL_METHOD_NONE.patch Patch0056: 0056-rio-add-RIO_POLL_METHOD_NONE.patch
Patch0057: 0057-apps-x509.c-Fix-the-addreject-option-adding-trust-in.patch Patch0057: 0057-apps-x509.c-Fix-the-addreject-option-adding-trust-in.patch
%if ( %{defined rhel} && (! %{defined centos}) )
Patch0058: 0058-Allow-hybrid-MLKEM-in-FIPS-mode.patch
%endif
#The patches that are different for RHEL9 and 10 start here #The patches that are different for RHEL9 and 10 start here
Patch0100: 0100-RHEL9-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch Patch0100: 0100-RHEL9-Allow-SHA1-in-seclevel-2-if-rh-allow-sha1-signatures.patch
@ -435,6 +438,8 @@ ln -s /etc/crypto-policies/back-ends/openssl_fips.config $RPM_BUILD_ROOT%{_sysco
* Mon Jun 02 2025 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.5.0-4 * Mon Jun 02 2025 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.5.0-4
- Compact patches for better maintainability - Compact patches for better maintainability
Related: RHEL-80854 Related: RHEL-80854
- Make hybrid MLKEM work with our FIPS provider (3.0.7)
Resolves: RHEL-95239
* Thu May 22 2025 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.5.0-3 * Thu May 22 2025 Dmitry Belyavskiy <dbelyavs@redhat.com> - 1:3.5.0-3
- Fix regressions caused by rebase to OpenSSL 3.5 - Fix regressions caused by rebase to OpenSSL 3.5