Make hybrid MLKEM work with our FIPS provider (3.0.7)
Resolves: RHEL-95239
This commit is contained in:
parent
36bf905365
commit
ea4218d43c
302
0058-Allow-hybrid-MLKEM-in-FIPS-mode.patch
Normal file
302
0058-Allow-hybrid-MLKEM-in-FIPS-mode.patch
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user