Resolves: RHEL-131347

- fips update
-   Fix indicators for the new post-quantum algorithms
-   Fix the ML-KEM Self-tests
-   Fix the ML-KEM zeroizaiton
-   Add partial public validation before OAEP
- bug fixes
-   add CKA_SEED to private attributes so they are updated on password change.
-   mark CKA_PARAMETER_SET as CK_ULONG when storing into the database
-   fix unrefrence read in leancrypto.
This commit is contained in:
Robert Relyea 2025-11-26 10:54:36 -08:00
parent 5ae6003f38
commit d23185094d
5 changed files with 3022 additions and 18 deletions

View File

@ -69,6 +69,7 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] = {
#define CKF_ECW (CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP)
#define CKF_WRP (CKF_WRAP | CKF_UNWRAP)
#define CKF_KEK (CKF_WRAP | CKF_UNWRAP)
#define CKF_KEM (CKF_ENCAPSULATE | CKF_DECAPSULATE )
#define CKF_KEA CKF_DERIVE
#define CKF_KDF CKF_DERIVE
#define CKF_HSH CKF_DIGEST
@ -116,11 +117,12 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] = {
{ CKM_ECDSA_SHA384, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
{ CKM_ECDSA_SHA512, { EC_FB_KEY, CKF_SGN }, EC_FB_STEP, SFTKFIPSECC },
/* only allowed keys are implented for ML_DSA */
{ CKM_ML_DSA_KEY_PAIR_GEN, { CK_ALL_KEY, CKF_SGN }, CK_ALL_STEP, SFTKFIPSNone },
{ CKM_ML_DSA_KEY_PAIR_GEN, { CK_ALL_KEY, CKF_KPG }, CK_ALL_STEP, SFTKFIPSNone },
{ CKM_ML_DSA, { CK_ALL_KEY, CKF_SGN }, CK_ALL_STEP, SFTKFIPSNone },
/* only allowed keys are implented for ML_KEM */
{ CKM_ML_KEM_KEY_PAIR_GEN, { CK_ALL_KEY, CKF_SGN }, CK_ALL_STEP, SFTKFIPSMLKEM },
{ CKM_ML_KEM, { CK_ALL_KEY, CKF_SGN }, CK_ALL_STEP, SFTKFIPSMLKEM },
{ CKM_ML_KEM_KEY_PAIR_GEN, { CK_ALL_KEY, CKF_KPG }, CK_ALL_STEP, SFTKFIPSMLKEM },
{ CKM_ML_KEM, { CK_ALL_KEY, CKF_KEM }, CK_ALL_STEP, SFTKFIPSMLKEM },
/* ------------------------- RC2 Operations --------------------------- */
/* ------------------------- AES Operations --------------------------- */
{ CKM_AES_KEY_GEN, { AES_FB_KEY, CKF_GEN }, AES_FB_STEP, SFTKFIPSNone },
@ -185,7 +187,7 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] = {
* to set the FIPS indicators on these (sigh) */
/* NOTE: CKM_NSS_ML_KEM_KEY_GEN and the KYBER equivalent does not do
* pairwise consistency checks on key gen, so are not FIPS */
{ CKM_NSS_ML_KEM, { CK_ALL_KEY, CKF_SGN }, CK_ALL_STEP, SFTKFIPSNone },
{ CKM_NSS_ML_KEM, { CK_ALL_KEY, CKF_KEM }, CK_ALL_STEP, SFTKFIPSMLKEM },
{ CKM_NSS_AES_KEY_WRAP, { AES_FB_KEY, CKF_ECW }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_NSS_AES_KEY_WRAP_PAD, { AES_FB_KEY, CKF_ECW }, AES_FB_STEP, SFTKFIPSNone },
{ CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256, { 384, 384, CKF_DERIVE }, 1, SFTKFIPSTlsKeyCheck },
@ -206,6 +208,5 @@ SFTKFIPSAlgorithmList sftk_fips_mechs[] = {
* resulting key will also be FIPS and the resulting operations will be
* FIPS approved. */
{ CKM_CONCATENATE_BASE_AND_KEY, { 112, CK_MAX, CKF_DERIVE }, 1, SFTKFIPSNone },
{ CKM_CONCATENATE_BASE_AND_DATA, { 112, CK_MAX, CKF_DERIVE }, 1, SFTKFIPSNone },
};
const int SFTK_NUMBER_FIPS_ALGORITHMS = PR_ARRAY_SIZE(sftk_fips_mechs);

View File

@ -0,0 +1,685 @@
# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1761684967 25200
# Tue Oct 28 13:56:07 2025 -0700
# Branch RHEL10
# Node ID 418f1657f74f96af94aa91b1fcf39d7c4740b3fa
# Parent a2ec761c754f728b669dc32ea94e260362b43b5b
nss-3.112-mlkem-fips-update.patch
diff --git a/lib/freebl/fipsfreebl.c b/lib/freebl/fipsfreebl.c
--- a/lib/freebl/fipsfreebl.c
+++ b/lib/freebl/fipsfreebl.c
@@ -1797,29 +1797,34 @@ loser:
static SECStatus
freebl_ML_KEM_Test(KyberParams param_set,
const unsigned char *seed, size_t seed_len,
const unsigned char *enc_seed, size_t enc_seed_len,
const unsigned char *pub_key, size_t pub_key_len,
const unsigned char *priv_key, size_t priv_key_len,
const unsigned char *cipher_text, size_t cipher_text_len,
- const unsigned char *key, size_t key_len)
+ const unsigned char *key, size_t key_len,
+ const unsigned char *rej_key, size_t rej_key_len)
{
SECStatus rv;
unsigned char cipher_text_buf[MAX_ML_KEM_CIPHER_LENGTH];
+ unsigned char zero_text_buf[MAX_ML_KEM_CIPHER_LENGTH] = { 0 };
unsigned char priv_key_buf[MAX_ML_KEM_PRIVATE_KEY_LENGTH];
unsigned char pub_key_buf[MAX_ML_KEM_PUBLIC_KEY_LENGTH];
unsigned char key_buf[KYBER_SHARED_SECRET_BYTES];
unsigned char key2_buf[KYBER_SHARED_SECRET_BYTES];
+ unsigned char key3_buf[KYBER_SHARED_SECRET_BYTES];
SECItem ct_item = { siBuffer, cipher_text_buf, cipher_text_len };
+ SECItem zt_item = { siBuffer, zero_text_buf, cipher_text_len };
SECItem priv_key_item = { siBuffer, priv_key_buf, priv_key_len };
SECItem pub_key_item = { siBuffer, pub_key_buf, pub_key_len };
SECItem key_item = { siBuffer, key_buf, sizeof(key_buf) };
SECItem key2_item = { siBuffer, key2_buf, sizeof(key2_buf) };
+ SECItem key3_item = { siBuffer, key3_buf, sizeof(key3_buf) };
SECItem seed_item = { siBuffer, (unsigned char *)seed, seed_len };
SECItem eseed_item = { siBuffer, (unsigned char *)enc_seed, enc_seed_len };
PORT_Assert(pub_key_len <= sizeof(pub_key_buf));
PORT_Assert(priv_key_len <= sizeof(priv_key_buf));
PORT_Assert(cipher_text_len <= sizeof(cipher_text_buf));
rv = Kyber_NewKey(param_set, &seed_item, &priv_key_item, &pub_key_item);
@@ -1828,43 +1833,53 @@ freebl_ML_KEM_Test(KyberParams param_set
return rv;
}
if ((priv_key_item.len != priv_key_len) ||
(pub_key_item.len != pub_key_len) ||
(PORT_Memcmp(priv_key_item.data, priv_key, priv_key_len) != 0) ||
(PORT_Memcmp(pub_key_item.data, pub_key, pub_key_len) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return rv;
+ return SECFailure;
}
rv = Kyber_Encapsulate(param_set, &eseed_item, &pub_key_item,
&ct_item, &key_item);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return rv;
}
if ((ct_item.len != cipher_text_len) ||
(key_item.len != key_len) ||
(PORT_Memcmp(ct_item.data, cipher_text, cipher_text_len) != 0) ||
(PORT_Memcmp(key_item.data, key, key_len) != 0)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return rv;
+ return SECFailure;
}
rv = Kyber_Decapsulate(param_set, &priv_key_item, &ct_item, &key2_item);
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return rv;
}
if (SECITEM_CompareItem(&key2_item, &key_item) != 0) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ rv = Kyber_Decapsulate(param_set, &priv_key_item, &zt_item, &key3_item);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return rv;
}
+ if ((key3_item.len != rej_key_len) ||
+ (PORT_Memcmp(key3_item.data, rej_key, rej_key_len) != 0)) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
return SECSuccess;
}
static SECStatus
freebl_fips_ML_KEM_PowerUpSelfTest()
{
SECStatus rv;
@@ -1881,27 +1896,29 @@ freebl_fips_ML_KEM_PowerUpSelfTest()
PORT_Assert(sizeof (ml_kem1024_key) == KYBER_SHARED_SECRET_BYTES);
rv = freebl_ML_KEM_Test(params_ml_kem768_test_mode,
ml_kem_key_seed, KYBER_KEYPAIR_COIN_BYTES,
ml_kem_enc_seed, KYBER_SHARED_SECRET_BYTES,
ml_kem768_pub_key, KYBER768_PUBLIC_KEY_BYTES,
ml_kem768_priv_key, KYBER768_PRIVATE_KEY_BYTES,
ml_kem768_cipher_text, KYBER768_CIPHERTEXT_BYTES,
- ml_kem768_key, KYBER_SHARED_SECRET_BYTES);
+ ml_kem768_key, KYBER_SHARED_SECRET_BYTES,
+ ml_kem768_rej_key, KYBER_SHARED_SECRET_BYTES);
if (rv != SECSuccess) {
return SECFailure;
}
rv = freebl_ML_KEM_Test(params_ml_kem1024_test_mode,
ml_kem_key_seed, KYBER_KEYPAIR_COIN_BYTES,
ml_kem_enc_seed, KYBER_SHARED_SECRET_BYTES,
ml_kem1024_pub_key, MLKEM1024_PUBLIC_KEY_BYTES,
ml_kem1024_priv_key, MLKEM1024_PRIVATE_KEY_BYTES,
ml_kem1024_cipher_text, MLKEM1024_CIPHERTEXT_BYTES,
- ml_kem1024_key, KYBER_SHARED_SECRET_BYTES);
+ ml_kem1024_key, KYBER_SHARED_SECRET_BYTES,
+ ml_kem1024_rej_key, KYBER_SHARED_SECRET_BYTES);
if (rv != SECSuccess) {
return SECFailure;
}
return SECSuccess;
}
#ifdef NSS_ENABLE_ML_DSA
diff --git a/lib/freebl/kyber.c b/lib/freebl/kyber.c
--- a/lib/freebl/kyber.c
+++ b/lib/freebl/kyber.c
@@ -4,16 +4,17 @@
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include <stdbool.h>
#include "blapi.h"
+#include "blapii.h"
#include "secerr.h"
#include "secitem.h"
#include "kyber-pqcrystals-ref.h"
#include "kyber.h"
#include "verified/internal/libcrux_core.h"
#include "verified/libcrux_mlkem768_portable.h"
#include "verified/libcrux_mlkem768.h"
@@ -198,29 +199,39 @@ Kyber_NewKey(KyberParams params, const S
}
coins = randbuf;
}
NSS_CLASSIFY(coins, KYBER_KEYPAIR_COIN_BYTES);
if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
libcrux_ml_kem_mlkem768_MlKem768KeyPair keys = libcrux_ml_kem_mlkem768_portable_generate_key_pair(coins);
memcpy(pubkey->data, keys.pk.value, KYBER768_PUBLIC_KEY_BYTES);
memcpy(privkey->data, keys.sk.value, KYBER768_PRIVATE_KEY_BYTES);
+ PORT_SafeZero(&keys, sizeof(keys));
} else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
libcrux_ml_kem_mlkem1024_MlKem1024KeyPair keys = libcrux_ml_kem_mlkem1024_portable_generate_key_pair(coins);
memcpy(pubkey->data, keys.pk.value, MLKEM1024_PUBLIC_KEY_BYTES);
memcpy(privkey->data, keys.sk.value, MLKEM1024_PRIVATE_KEY_BYTES);
+ PORT_SafeZero(&keys, sizeof(keys));
#ifndef NSS_DISABLE_KYBER
} else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
pqcrystals_kyber768_ref_keypair_derand(pubkey->data, privkey->data, coins);
#endif
} else {
/* unreachable */
+ if (coins == randbuf) {
+ PORT_SafeZero(randbuf, sizeof(randbuf));
+ }
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
+ /* manual max stack count 68000 */
+ BLAPI_CLEAR_STACK(70000);
+ if (coins == randbuf) {
+ PORT_SafeZero(randbuf, sizeof(randbuf));
+ }
NSS_DECLASSIFY(pubkey->data, pubkey->len);
return SECSuccess;
}
SECStatus
Kyber_Encapsulate(KyberParams params, const SECItem *enc_seed, const SECItem *pubkey, SECItem *ciphertext, SECItem *secret)
{
if (!valid_params(params)) {
@@ -239,103 +250,133 @@ Kyber_Encapsulate(KyberParams params, co
coins = enc_seed->data;
} else {
if (RNG_GenerateGlobalRandomBytes(randbuf, sizeof randbuf) != SECSuccess) {
PORT_SetError(SEC_ERROR_NEED_RANDOM);
return SECFailure;
}
coins = randbuf;
}
+ SECStatus rv = SECSuccess;
NSS_CLASSIFY(coins, KYBER_ENC_COIN_BYTES);
if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
/* shouldn't this just use the typedef im libcrux_mlkem768.h? */
libcrux_ml_kem_types_MlKemPublicKey_15 pk_value;
memcpy(pk_value.value, pubkey->data, KYBER768_PUBLIC_KEY_BYTES);
bool valid_pk = libcrux_ml_kem_mlkem768_portable_validate_public_key(&pk_value);
if (!valid_pk) {
+ PORT_SafeZero(&pk_value, sizeof(pk_value));
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
}
tuple_3c encap = libcrux_ml_kem_mlkem768_portable_encapsulate(&pk_value, coins);
memcpy(ciphertext->data, encap.fst.value, KYBER768_CIPHERTEXT_BYTES);
memcpy(secret->data, encap.snd, KYBER_SHARED_SECRET_BYTES);
+ PORT_SafeZero(&pk_value, sizeof(pk_value));
+ PORT_SafeZero(&encap, sizeof(encap));
} else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
/* shouldn't this just use the typedef im libcrux_mlkem1024.h? */
libcrux_ml_kem_types_MlKemPublicKey_1f pk_value;
memcpy(pk_value.value, pubkey->data, MLKEM1024_PUBLIC_KEY_BYTES);
bool valid_pk = libcrux_ml_kem_mlkem1024_portable_validate_public_key(&pk_value);
if (!valid_pk) {
+ PORT_SafeZero(&pk_value, sizeof(pk_value));
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
}
tuple_21 encap = libcrux_ml_kem_mlkem1024_portable_encapsulate(&pk_value, coins);
memcpy(ciphertext->data, encap.fst.value, MLKEM1024_CIPHERTEXT_BYTES);
memcpy(secret->data, encap.snd, KYBER_SHARED_SECRET_BYTES);
+ PORT_SafeZero(&pk_value, sizeof(pk_value));
+ PORT_SafeZero(&encap, sizeof(encap));
#ifndef NSS_DISABLE_KYBER
} else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
pqcrystals_kyber768_ref_enc_derand(ciphertext->data, secret->data, pubkey->data, coins);
#endif
} else {
/* unreachable */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
}
+loser:
+ if (coins == randbuf) {
+ PORT_SafeZero(randbuf, sizeof(randbuf));
+ }
+ /* manual max stack count 6700 */
+ BLAPI_CLEAR_STACK(10000);
- return SECSuccess;
+ return rv;
}
SECStatus
Kyber_Decapsulate(KyberParams params, const SECItem *privkey, const SECItem *ciphertext, SECItem *secret)
{
if (!valid_params(params)) {
PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
return SECFailure;
}
if (!(valid_privkey(params, privkey) && valid_ciphertext(params, ciphertext) && valid_secret(params, secret))) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ SECStatus rv = SECSuccess;
if (params == params_ml_kem768 || params == params_ml_kem768_test_mode) {
libcrux_ml_kem_types_MlKemPrivateKey_55 private_key;
memcpy(private_key.value, privkey->data, KYBER768_PRIVATE_KEY_BYTES);
libcrux_ml_kem_mlkem768_MlKem768Ciphertext cipher_text;
memcpy(cipher_text.value, ciphertext->data, KYBER768_CIPHERTEXT_BYTES);
bool valid = libcrux_ml_kem_mlkem768_portable_validate_private_key(&private_key, &cipher_text);
if (!valid) {
+ PORT_SafeZero(&private_key, sizeof(private_key));
+ PORT_SafeZero(&cipher_text, sizeof(cipher_text));
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
}
libcrux_ml_kem_mlkem768_portable_decapsulate(&private_key, &cipher_text, secret->data);
+ PORT_SafeZero(&private_key, sizeof(private_key));
+ PORT_SafeZero(&cipher_text, sizeof(cipher_text));
} else if (params == params_ml_kem1024 || params == params_ml_kem1024_test_mode) {
libcrux_ml_kem_types_MlKemPrivateKey_95 private_key;
memcpy(private_key.value, privkey->data, MLKEM1024_PRIVATE_KEY_BYTES);
libcrux_ml_kem_mlkem1024_MlKem1024Ciphertext cipher_text;
memcpy(cipher_text.value, ciphertext->data, MLKEM1024_CIPHERTEXT_BYTES);
bool valid = libcrux_ml_kem_mlkem1024_portable_validate_private_key(&private_key, &cipher_text);
if (!valid) {
+ PORT_SafeZero(&private_key, sizeof(private_key));
+ PORT_SafeZero(&cipher_text, sizeof(cipher_text));
PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ rv = SECFailure;
+ goto loser;
}
libcrux_ml_kem_mlkem1024_portable_decapsulate(&private_key, &cipher_text, secret->data);
+ PORT_SafeZero(&private_key, sizeof(private_key));
+ PORT_SafeZero(&cipher_text, sizeof(cipher_text));
#ifndef NSS_DISABLE_KYBER
} else if (params == params_kyber768_round3 || params == params_kyber768_round3_test_mode) {
pqcrystals_kyber768_ref_dec(secret->data, ciphertext->data, privkey->data);
#endif
} else {
// unreachable
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
+loser:
+ /* manual max stack count 8200 */
+ BLAPI_CLEAR_STACK(10000);
- return SECSuccess;
+ return rv;
}
diff --git a/lib/freebl/ml_kem_fips_vectors.h b/lib/freebl/ml_kem_fips_vectors.h
--- a/lib/freebl/ml_kem_fips_vectors.h
+++ b/lib/freebl/ml_kem_fips_vectors.h
@@ -415,16 +415,21 @@
0xd6, 0x18, 0xf6, 0x5a, 0x70, 0x0b, 0x41, 0xf0, 0x17, 0x08, 0x67, 0x98,
0x2f, 0x5a, 0x68, 0xc7, 0x5c, 0x65, 0x15, 0x0e,
};
static const unsigned char ml_kem768_key[] = {
0x42, 0xf5, 0x58, 0xb0, 0xbc, 0x5d, 0x70, 0x0a, 0x91, 0x1b, 0x0f, 0xc6,
0x7f, 0x62, 0x37, 0x6f, 0x7a, 0xee, 0x46, 0x67, 0xf1, 0x96, 0x9e, 0x03,
0xf1, 0x8b, 0xdf, 0xdf, 0x3c, 0x59, 0xfb, 0xdc,
};
+ static const unsigned char ml_kem768_rej_key[] = {
+ 0x6b, 0x24, 0x6e, 0xb1, 0x8b, 0x55, 0x3a, 0xb4, 0xcc, 0x4a, 0x57, 0x04,
+ 0x4d, 0x8d, 0x15, 0x34, 0xa8, 0x85, 0xd1, 0xd3, 0x42, 0x14, 0xc9, 0x87,
+ 0x78, 0x96, 0x19, 0xcb, 0x73, 0xe6, 0x12, 0x9a,
+ };
static const unsigned char ml_kem1024_pub_key[] = {
0x4b, 0x94, 0xc2, 0x94, 0x50, 0x11, 0x11, 0x91, 0x82, 0x3b, 0x35, 0x14,
0xc9, 0xac, 0x1e, 0xa3, 0xd9, 0x82, 0x5c, 0xcb, 0x86, 0x39, 0x3a, 0x2d,
0xfb, 0x04, 0x65, 0x4f, 0xa2, 0x19, 0x2d, 0x37, 0xbf, 0xad, 0x1c, 0x49,
0x7c, 0x65, 0x02, 0xee, 0xe5, 0xca, 0x80, 0xa7, 0x3b, 0xfc, 0xe0, 0xba,
0xf5, 0xa5, 0x4a, 0x88, 0x58, 0x5a, 0x40, 0x13, 0x97, 0xa3, 0xd2, 0x32,
0xf4, 0x26, 0xa7, 0xaf, 0xb0, 0x82, 0xbc, 0x21, 0xa4, 0x43, 0x17, 0x09,
0x0e, 0xaa, 0xc7, 0x59, 0x2c, 0x2e, 0xa8, 0x8a, 0x65, 0x3c, 0x44, 0x91,
@@ -952,8 +957,13 @@
0x3b, 0xaf, 0x03, 0xad, 0xf1, 0xab, 0x8f, 0x86, 0xea, 0x46, 0x28, 0xf8,
0x53, 0x80, 0xee, 0x89, 0x53, 0xd4, 0xa1, 0xad,
};
static const unsigned char ml_kem1024_key[] = {
0x73, 0x8a, 0x88, 0xcd, 0x9a, 0x25, 0x86, 0x1e, 0x9a, 0x37, 0xc6, 0x5a,
0x67, 0xec, 0x1b, 0x39, 0xf0, 0x69, 0xae, 0xd9, 0x64, 0x6e, 0xde, 0x89,
0x41, 0x0a, 0xce, 0x47, 0xa9, 0x6a, 0x9b, 0x57,
};
+ static const unsigned char ml_kem1024_rej_key[] = {
+ 0x6a, 0x58, 0xe1, 0xc5, 0x96, 0x86, 0xc9, 0xfc, 0x32, 0x2e, 0xc2, 0x6b,
+ 0x6e, 0xa0, 0xd5, 0x27, 0x22, 0x67, 0x29, 0x2c, 0xe9, 0xa4, 0x0f, 0x12,
+ 0x75, 0x13, 0x96, 0xbc, 0x53, 0x22, 0x72, 0x46,
+ };
diff --git a/lib/softoken/kem.c b/lib/softoken/kem.c
--- a/lib/softoken/kem.c
+++ b/lib/softoken/kem.c
@@ -198,16 +198,18 @@ NSC_EncapsulateKey(CK_SESSION_HANDLE hSe
SFTKAttribute *encapsulationKey = NULL;
CK_RV crv;
SFTKFreeStatus status;
CK_ULONG paramSet = 0; /* use a generic U_LONG so we can handle
* different param set types based on the
* Mechanism value */
KyberParams kyberParams;
+ CK_OBJECT_CLASS ckclass = CKO_SECRET_KEY;
+ CK_KEY_TYPE ckkeyType = CKK_GENERIC_SECRET;
CHECK_FORK();
if (!pMechanism || !phKey || !pulCiphertextLen) {
return CKR_ARGUMENTS_BAD;
}
if (!sftk_kem_ValidateMechanism(pMechanism)) {
@@ -232,16 +234,25 @@ NSC_EncapsulateKey(CK_SESSION_HANDLE hSe
}
for (unsigned long int i = 0; i < ulAttributeCount; i++) {
crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
if (crv != CKR_OK) {
goto cleanup;
}
}
+ crv = sftk_defaultAttribute(key, CKA_CLASS, &ckclass, sizeof(ckclass));
+ if (crv != CKR_OK) {
+ goto cleanup;
+ }
+ crv = sftk_defaultAttribute(key, CKA_KEY_TYPE, &ckkeyType, sizeof(ckkeyType));
+ if (crv != CKR_OK) {
+ goto cleanup;
+ }
+
encapsulationKeyObject = sftk_ObjectFromHandle(hPublicKey, session);
if (encapsulationKeyObject == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
goto cleanup;
}
encapsulationKey = sftk_FindAttribute(encapsulationKeyObject, CKA_VALUE);
if (encapsulationKey == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
@@ -264,17 +275,17 @@ NSC_EncapsulateKey(CK_SESSION_HANDLE hSe
SECItem pubKey = { siBuffer, encapsulationKey->attrib.pValue, encapsulationKey->attrib.ulValueLen };
/* The length of secretBuf can be increased if we ever support other KEMs
* by changing the define at the top of this file */
uint8_t secretBuf[MAX_KEM_SHARED_SECRET_BYTES] = { 0 };
SECItem secret = { siBuffer, secretBuf, sizeof secretBuf };
key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_ENCAPSULATE,
- key, 0);
+ encapsulationKeyObject, 0);
key->source = SFTK_SOURCE_KEA;
switch (pMechanism->mechanism) {
#ifndef NSS_DISABLE_KYBER
case CKM_NSS_KYBER:
#endif
case CKM_NSS_ML_KEM:
case CKM_ML_KEM:
PORT_Assert(secret.len >= KYBER_SHARED_SECRET_BYTES);
@@ -347,16 +358,18 @@ NSC_DecapsulateKey(CK_SESSION_HANDLE hSe
SFTKAttribute *decapsulationKey = NULL;
CK_ULONG paramSet = 0; /* use a generic U_LONG so we can handle
* different param set types based on the
* Mechanism value */
CK_RV crv;
SFTKFreeStatus status;
KyberParams kyberParams;
+ CK_OBJECT_CLASS ckclass = CKO_SECRET_KEY;
+ CK_KEY_TYPE ckkeyType = CKK_GENERIC_SECRET;
CHECK_FORK();
if (!pMechanism || !pCiphertext || !pTemplate || !phKey) {
return CKR_ARGUMENTS_BAD;
}
if (!sftk_kem_ValidateMechanism(pMechanism)) {
@@ -381,16 +394,25 @@ NSC_DecapsulateKey(CK_SESSION_HANDLE hSe
}
for (unsigned long int i = 0; i < ulAttributeCount; i++) {
crv = sftk_AddAttributeType(key, sftk_attr_expand(&pTemplate[i]));
if (crv != CKR_OK) {
goto cleanup;
}
}
+ crv = sftk_defaultAttribute(key, CKA_CLASS, &ckclass, sizeof(ckclass));
+ if (crv != CKR_OK) {
+ goto cleanup;
+ }
+ crv = sftk_defaultAttribute(key, CKA_KEY_TYPE, &ckkeyType, sizeof(ckkeyType));
+ if (crv != CKR_OK) {
+ goto cleanup;
+ }
+
decapsulationKeyObject = sftk_ObjectFromHandle(hPrivateKey, session);
if (decapsulationKeyObject == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
goto cleanup;
}
decapsulationKey = sftk_FindAttribute(decapsulationKeyObject, CKA_VALUE);
if (decapsulationKey == NULL) {
crv = CKR_KEY_HANDLE_INVALID;
@@ -412,17 +434,17 @@ NSC_DecapsulateKey(CK_SESSION_HANDLE hSe
decapsulationKey->attrib.ulValueLen };
SECItem ciphertext = { siBuffer, pCiphertext, ulCiphertextLen };
/* The length of secretBuf can be increased if we ever support other KEMs
* by changing the define at the top of this file */
uint8_t secretBuf[MAX_KEM_SHARED_SECRET_BYTES] = { 0 };
SECItem secret = { siBuffer, secretBuf, sizeof secretBuf };
key->isFIPS = sftk_operationIsFIPS(slot, pMechanism, CKA_DECAPSULATE,
- key, 0);
+ decapsulationKeyObject, 0);
key->source = SFTK_SOURCE_KEA;
switch (pMechanism->mechanism) {
#ifndef NSS_DISABLE_KYBER
case CKM_NSS_KYBER:
#endif
case CKM_NSS_ML_KEM:
case CKM_ML_KEM:
diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -5236,17 +5236,17 @@ sftk_compareKeysEqual(CK_SESSION_HANDLE
SFTKObject *key1obj = NULL;
SFTKObject *key2obj = NULL;
SFTKAttribute *att1 = NULL;
SFTKAttribute *att2 = NULL;
/* fetch the pkcs11 objects from the handles */
session = sftk_SessionFromHandle(hSession);
if (session == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
+ return PR_FALSE;
}
key1obj = sftk_ObjectFromHandle(key1, session);
key2obj = sftk_ObjectFromHandle(key2, session);
sftk_FreeSession(session);
if ((key1obj == NULL) || (key2obj == NULL)) {
goto loser;
}
@@ -5268,17 +5268,17 @@ sftk_compareKeysEqual(CK_SESSION_HANDLE
goto loser;
}
result = PR_TRUE;
loser:
if (key1obj) {
sftk_FreeObject(key1obj);
}
if (key2obj) {
- sftk_FreeObject(key1obj);
+ sftk_FreeObject(key2obj);
}
if (att1) {
sftk_FreeAttribute(att1);
}
if (att2) {
sftk_FreeAttribute(att2);
}
return result;
@@ -5758,24 +5758,24 @@ sftk_PairwiseConsistencyCheck(CK_SESSION
SECITEM_ZfreeItem(&prime, PR_FALSE);
}
/* clean up before we return */
sftk_FreeAttribute(pubAttribute);
if (crv != CKR_OK) {
return crv;
}
}
- isKEM = sftk_isTrue(privateKey, CKA_ENCAPSULATE);
+ isKEM = sftk_isTrue(privateKey, CKA_DECAPSULATE);
if (isKEM) {
unsigned char *cipher_text = NULL;
CK_ULONG cipher_text_length = 0;
CK_OBJECT_HANDLE key1 = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE key2 = CK_INVALID_HANDLE;
CK_KEY_TYPE genType = CKO_SECRET_KEY;
- CK_ATTRIBUTE template = { CKA_KEY_TYPE, NULL, 0 };
+ CK_ATTRIBUTE template = { CKA_CLASS, NULL, 0 };
template.pValue = &genType;
template.ulValueLen = sizeof(genType);
crv = CKR_OK;
switch (keyType) {
case CKK_ML_KEM:
cipher_text_length = MAX_ML_KEM_CIPHER_LENGTH;
mech.mechanism = CKM_ML_KEM;
@@ -7905,16 +7905,17 @@ sftk_DeriveEncrypt(SFTKCipher encrypt, v
return crv;
}
crv = sftk_forceAttribute(key, CKA_VALUE, tmpdata, keySize);
PORT_Memset(tmpdata, 0, sizeof tmpdata);
return crv;
}
+
CK_RV
sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_SESSION_HANDLE hSession,
SFTKObject *sourceKey, const unsigned char *sourceKeyBytes,
int sourceKeyLen, SFTKObject *key, unsigned char *outKeyBytes,
int keySize, PRBool canBeData, PRBool isFIPS)
{
SFTKSession *session;
SFTKAttribute *saltKey_att = NULL;
@@ -7958,16 +7959,21 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
}
/* sourceKey is NULL if we are called from the POST, skip the
* sensitiveCheck */
if (sourceKey != NULL) {
crv = sftk_DeriveSensitiveCheck(sourceKey, key, canBeData);
if (crv != CKR_OK)
return crv;
+ /* if the source key is data, clear the FIPS flag
+ * and only get the FIPS state from the salt */
+ if (sourceKey->objclass == CKO_DATA) {
+ key->isFIPS = PR_FALSE;
+ }
}
/* HKDF-Extract(salt, base key value) */
if (params->bExtract) {
CK_BYTE *salt;
CK_ULONG saltLen;
HMACContext *hmac;
unsigned int bufLen;
@@ -7988,16 +7994,17 @@ sftk_HKDF(CK_HKDF_PARAMS_PTR params, CK_
break;
case CKF_HKDF_SALT_KEY:
/* lookup key */
session = sftk_SessionFromHandle(hSession);
if (session == NULL) {
return CKR_SESSION_HANDLE_INVALID;
}
+
saltKey = sftk_ObjectFromHandle(params->hSaltKey, session);
sftk_FreeSession(session);
if (saltKey == NULL) {
return CKR_KEY_HANDLE_INVALID;
}
/* if the base key is not fips, but the salt key is, the
* resulting key can be fips */
if (isFIPS && (key->isFIPS == 0) && (saltKey->isFIPS == 1)) {
@@ -9190,17 +9197,23 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
PORT_Memcpy(buf, att->attrib.pValue, att->attrib.ulValueLen);
PORT_Memcpy(buf + att->attrib.ulValueLen,
att2->attrib.pValue, att2->attrib.ulValueLen);
crv = sftk_forceAttribute(key, CKA_VALUE, buf, keySize);
PORT_ZFree(buf, tmpKeySize);
/* preserve the source of the original base key */
- /* key->source = sourceKey->source; */
+ key->source = sourceKey->source;
+
+ /* make sure this is fully fips approved, and mark it
+ * unapproved if not */
+ if (key->isFIPS) {
+ key->isFIPS = paramKey->isFIPS;
+ }
sftk_FreeAttribute(att2);
sftk_FreeObject(paramKey);
break;
}
case CKM_CONCATENATE_BASE_AND_DATA:
crv = sftk_DeriveSensitiveCheck(sourceKey, key, PR_FALSE);
if (crv != CKR_OK)
diff --git a/lib/softoken/pkcs11u.c b/lib/softoken/pkcs11u.c
--- a/lib/softoken/pkcs11u.c
+++ b/lib/softoken/pkcs11u.c
@@ -2285,16 +2285,22 @@ sftk_AttributeToFlags(CK_ATTRIBUTE_TYPE
flags = CKF_VERIFY;
break;
case CKA_VERIFY_RECOVER:
flags = CKF_VERIFY_RECOVER;
break;
case CKA_DERIVE:
flags = CKF_DERIVE;
break;
+ case CKA_ENCAPSULATE:
+ flags = CKF_ENCAPSULATE;
+ break;
+ case CKA_DECAPSULATE:
+ flags = CKF_DECAPSULATE;
+ break;
/* fake attribute to select digesting */
case CKA_DIGEST:
flags = CKF_DIGEST;
break;
/* fake attribute to select key gen */
case CKA_NSS_GENERATE:
flags = CKF_GENERATE;
break;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,799 @@
# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1762542092 28800
# Fri Nov 07 11:01:32 2025 -0800
# Branch RHEL10
# Node ID 6949dbcd6631ec0db3f53b3cf8957fac3a80da25
# Parent 3e2ea63bf062fef47334b69723db7eac95daaa2a
nss-3.112-update-fixes.patch
diff --git a/lib/cryptohi/keythi.h b/lib/cryptohi/keythi.h
--- a/lib/cryptohi/keythi.h
+++ b/lib/cryptohi/keythi.h
@@ -240,16 +240,17 @@ typedef struct SECKEYPublicKeyStr SECKEY
struct SECKEYPrivateKeyStr {
PLArenaPool *arena;
KeyType keyType;
PK11SlotInfo *pkcs11Slot; /* pkcs11 slot this key lives in */
CK_OBJECT_HANDLE pkcs11ID; /* ID of pkcs11 object */
PRBool pkcs11IsTemp; /* temp pkcs11 object, delete it when done */
void *wincx; /* context for errors and pw prompts */
PRUint32 staticflags; /* bit flag of cached PKCS#11 attributes */
+ PRBool pkcs11IsOwner; /* the pkcs11ID is owned by this SECKEY */
};
typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
typedef struct {
PRCList links;
SECKEYPrivateKey *key;
} SECKEYPrivateKeyListNode;
diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c
--- a/lib/cryptohi/seckey.c
+++ b/lib/cryptohi/seckey.c
@@ -416,17 +416,17 @@ SECKEY_CreateEDPrivateKey(SECKEYECParams
return (privk);
}
void
SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
{
if (privk) {
if (privk->pkcs11Slot) {
- if (privk->pkcs11IsTemp) {
+ if (privk->pkcs11IsOwner) {
PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID);
}
PK11_FreeSlot(privk->pkcs11Slot);
}
if (privk->arena) {
PORT_FreeArena(privk->arena, PR_TRUE);
}
}
@@ -1429,16 +1429,17 @@ SECKEY_CopyPrivateKey(const SECKEYPrivat
copyk->pkcs11ID =
PK11_CopyKey(privk->pkcs11Slot, privk->pkcs11ID);
if (copyk->pkcs11ID == CK_INVALID_HANDLE)
goto fail;
} else {
copyk->pkcs11ID = privk->pkcs11ID;
}
copyk->pkcs11IsTemp = privk->pkcs11IsTemp;
+ copyk->pkcs11IsOwner = privk->pkcs11IsOwner;
copyk->wincx = privk->wincx;
copyk->staticflags = privk->staticflags;
return copyk;
} else {
PORT_SetError(SEC_ERROR_NO_MEMORY);
}
fail:
diff --git a/lib/cryptohi/secvfy.c b/lib/cryptohi/secvfy.c
--- a/lib/cryptohi/secvfy.c
+++ b/lib/cryptohi/secvfy.c
@@ -436,17 +436,17 @@ sec_DecodeSigAlg(const SECKEYPublicKey *
const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg,
CK_MECHANISM_TYPE *mechp, SECItem *mechparamsp)
{
unsigned int len;
PLArenaPool *arena;
SECStatus rv;
SECItem oid;
SECOidTag encalg;
- PRBool comboRequired = PR_TRUE;
+ PRBool comboRequired = PR_FALSE;
char *evp;
PR_ASSERT(hashalg != NULL);
PR_ASSERT(encalgp != NULL);
PR_ASSERT(mechp != NULL);
/* Get the expected combined mechanism from the signature OID
* We'll override it in the table below if necessary */
*mechp = PK11_AlgtagToMechanism(sigAlg);
diff --git a/lib/freebl/leancrypto/lc_sha3.h b/lib/freebl/leancrypto/lc_sha3.h
--- a/lib/freebl/leancrypto/lc_sha3.h
+++ b/lib/freebl/leancrypto/lc_sha3.h
@@ -20,17 +20,20 @@
struct lc_hash_ctx _##name ; \
_##name.hash= type_; \
_##name.buf= NULL; \
_##name.stream = false; \
_##name.u.ctx_ptr = NULL; \
struct lc_hash_ctx *name= &_##name;
#define LC_HASH_SET_CTX(name, type_) \
- name->hash= type_;
+ name->hash= type_; \
+ name->stream = true; \
+ name->u.ctx_ptr = NULL; \
+ name->buf = NULL;
#define LC_SHAKE_256_CTX(name) \
LC_HASH_SET_CTX(name, lc_shake256);
typedef enum {
lc_shake128,
lc_shake256,
} sha3Type;
diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c
--- a/lib/pk11wrap/pk11akey.c
+++ b/lib/pk11wrap/pk11akey.c
@@ -1002,22 +1002,23 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot
return pubKey;
}
/*
* Build a Private Key structure from raw PKCS #11 information.
*/
SECKEYPrivateKey *
PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
- PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx)
+ PRBool isOwner, CK_OBJECT_HANDLE privID, void *wincx)
{
PLArenaPool *arena;
SECKEYPrivateKey *privKey;
PRBool isPrivate;
SECStatus rv;
+ PRBool isTemp = isOwner;
/* don't know? look it up */
if (keyType == nullKey) {
CK_KEY_TYPE pk11Type = CKK_RSA;
pk11Type = PK11_ReadULongAttribute(slot, privID, CKA_KEY_TYPE);
isTemp = (PRBool)!PK11_HasAttributeSet(slot, privID, CKA_TOKEN, PR_FALSE);
keyType = pk11_GetKeyTypeFromPKCS11KeyType(pk11Type);
@@ -1048,16 +1049,17 @@ PK11_MakePrivKey(PK11SlotInfo *slot, Key
return NULL;
}
privKey->arena = arena;
privKey->keyType = keyType;
privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
privKey->pkcs11ID = privID;
privKey->pkcs11IsTemp = isTemp;
+ privKey->pkcs11IsOwner = isOwner;
privKey->wincx = wincx;
return privKey;
}
PK11SlotInfo *
PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
{
@@ -2635,17 +2637,17 @@ PK11_CopyTokenPrivKeyToSessionPrivKey(PK
1, &newKeyID);
PK11_ExitSlotMonitor(destSlot);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return NULL;
}
- return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isTemp*/,
+ return PK11_MakePrivKey(destSlot, privKey->keyType, PR_TRUE /*isOwner*/,
newKeyID, privKey->wincx);
}
SECKEYPrivateKey *
PK11_ConvertSessionPrivKeyToTokenPrivKey(SECKEYPrivateKey *privk, void *wincx)
{
PK11SlotInfo *slot = privk->pkcs11Slot;
CK_ATTRIBUTE template[1];
@@ -2668,17 +2670,17 @@ PK11_ConvertSessionPrivKeyToTokenPrivKey
template, 1, &newKeyID);
PK11_RestoreROSession(slot, rwsession);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return NULL;
}
- return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isTemp*/,
+ return PK11_MakePrivKey(slot, nullKey /*KeyType*/, PR_FALSE /*isOwner*/,
newKeyID, NULL /*wincx*/);
}
/*
* destroy a private key if there are no matching certs.
* this function also frees the privKey structure.
*/
SECStatus
@@ -2731,17 +2733,17 @@ pk11_DoKeys(PK11SlotInfo *slot, CK_OBJEC
{
SECStatus rv = SECSuccess;
SECKEYPrivateKey *privKey;
pk11KeyCallback *keycb = (pk11KeyCallback *)arg;
if (!arg) {
return SECFailure;
}
- privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, keycb->wincx);
+ privKey = PK11_MakePrivKey(slot, nullKey, PR_FALSE, keyHandle, keycb->wincx);
if (privKey == NULL) {
return SECFailure;
}
if (keycb->callback) {
rv = (*keycb->callback)(privKey, keycb->callbackArg);
}
@@ -2823,17 +2825,17 @@ PK11_FindKeyByKeyID(PK11SlotInfo *slot,
{
CK_OBJECT_HANDLE keyHandle;
SECKEYPrivateKey *privKey;
keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
if (keyHandle == CK_INVALID_HANDLE) {
return NULL;
}
- privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
+ privKey = PK11_MakePrivKey(slot, nullKey, PR_FALSE, keyHandle, wincx);
return privKey;
}
/*
* Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
* from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
* smart cards happy.
*/
@@ -3011,15 +3013,15 @@ PK11_ListPrivKeysInSlot(PK11SlotInfo *sl
keys = SECKEY_NewPrivateKeyList();
if (keys == NULL) {
PORT_Free(key_ids);
return NULL;
}
for (i = 0; i < objCount; i++) {
SECKEYPrivateKey *privKey =
- PK11_MakePrivKey(slot, nullKey, PR_TRUE, key_ids[i], wincx);
+ PK11_MakePrivKey(slot, nullKey, PR_FALSE, key_ids[i], wincx);
SECKEY_AddPrivateKeyToListTail(keys, privKey);
}
PORT_Free(key_ids);
return keys;
}
diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c
--- a/lib/pk11wrap/pk11skey.c
+++ b/lib/pk11wrap/pk11skey.c
@@ -433,17 +433,17 @@ PK11_VerifyKeyOK(PK11SymKey *key)
return PR_FALSE;
}
return (PRBool)(key->series == key->slot->series);
}
static PK11SymKey *
pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate,
- unsigned int templateCount, SECItem *key, void *wincx)
+ unsigned int templateCount, SECItem *key, PRBool force, void *wincx)
{
PK11SymKey *symKey;
SECStatus rv;
symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx);
if (symKey == NULL) {
return NULL;
}
@@ -458,22 +458,71 @@ pk11_ImportSymKeyWithTempl(PK11SlotInfo
return NULL;
}
symKey->origin = origin;
/* import the keys */
rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate,
templateCount, isToken, &symKey->objectID);
- if (rv != SECSuccess) {
+ if (rv == SECSuccess) {
+ return symKey;
+ }
+ /* we failed to create the key, if force isn't set, we just fail now */
+ if (!force) {
+ PK11_FreeSymKey(symKey);
+ return NULL;
+ }
+ /* if force is set, we are simulating an unwrap, probably from another token, we
+ * are probably here because we are trying to import into a FIPS token. Normally
+ * we would want this to fail, but the application got here because they are using
+ * unwrap, which is the correct way to do this, so try to import the key into
+ * the FIPS token my hand */
+ /* first generate a seed key */
+ PK11SymKey *seedKey = PK11_KeyGen(slot, CKM_SHA256_HMAC, NULL, 256, wincx);
+
+ if (seedKey == NULL) {
PK11_FreeSymKey(symKey);
return NULL;
}
- return symKey;
+ /* now append our key data to the seed key and truncate the seed key */
+ CK_KEY_DERIVATION_STRING_DATA params = { 0 };
+ CK_MECHANISM mechanism = { 0, NULL, 0 };
+ params.pData = key->data;
+ params.ulLen = key->len;
+ mechanism.mechanism = CKM_CONCATENATE_DATA_AND_BASE;
+ mechanism.pParameter = &params;
+ mechanism.ulParameterLen = sizeof(params);
+
+ /* derive removed the CKA_VALUE_LEN before it called us, but now we need
+ * it back. We know there is space in the template because derive leaves
+ * space for the CKA_VALUE_LEN attribute. Any other callers that set force
+ * should also make sure there is space for the CKA_VALUE_LEN */
+ CK_ULONG valueLen; /* Don't define this in the 'if' statement, because it
+ * would go out of scope before we use it */
+ if (!pk11_FindAttrInTemplate(keyTemplate, templateCount, CKA_VALUE_LEN)) {
+ valueLen = (CK_ULONG)key->len;
+ keyTemplate[templateCount].type = CKA_VALUE_LEN;
+ keyTemplate[templateCount].pValue = (void *)&valueLen;
+ keyTemplate[templateCount].ulValueLen = sizeof(valueLen);
+ templateCount++;
+ }
+
+ CK_RV crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism,
+ seedKey->objectID, keyTemplate,
+ templateCount,
+ &symKey->objectID);
+ PK11_FreeSymKey(seedKey);
+ if (crv == CKR_OK) {
+ return symKey;
+ }
+
+ PK11_FreeSymKey(symKey);
+ return NULL;
}
/*
* turn key bits into an appropriate key object
*/
PK11SymKey *
PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx)
@@ -501,17 +550,17 @@ PK11_ImportSymKey(PK11SlotInfo *slot, CK
attrs++;
PK11_SETATTRS(attrs, operation, &cktrue, 1);
attrs++;
templateCount = attrs - keyTemplate;
PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
keyType = PK11_GetKeyType(type, key->len);
symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE,
- keyTemplate, templateCount, key, wincx);
+ keyTemplate, templateCount, key, PR_FALSE, wincx);
return symKey;
}
/* Import a PKCS #11 data object and return it as a key. This key is
* only useful in a limited number of mechanisms, such as HKDF. */
PK11SymKey *
PK11_ImportDataKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin,
CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx)
{
@@ -580,17 +629,17 @@ PK11_ImportSymKeyWithFlags(PK11SlotInfo
PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue));
attrs++;
}
templateCount = attrs - keyTemplate;
PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
keyType = PK11_GetKeyType(type, key->len);
symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm,
- keyTemplate, templateCount, key, wincx);
+ keyTemplate, templateCount, key, PR_FALSE, wincx);
if (symKey && isPerm) {
symKey->owner = PR_FALSE;
}
return symKey;
}
PK11SymKey *
PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID,
@@ -2670,29 +2719,29 @@ pk11_HandUnwrap(PK11SlotInfo *slot, CK_O
}
outKey.len = (key_size == 0) ? len : key_size;
outKey.type = siBuffer;
if (PK11_DoesMechanism(slot, target)) {
symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
isPerm, keyTemplate,
- templateCount, &outKey, wincx);
+ templateCount, &outKey, PR_TRUE, wincx);
} else {
slot = PK11_GetBestSlot(target, wincx);
if (slot == NULL) {
PORT_SetError(SEC_ERROR_NO_MODULE);
PORT_Free(outKey.data);
if (crvp)
*crvp = CKR_DEVICE_ERROR;
return NULL;
}
symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap,
isPerm, keyTemplate,
- templateCount, &outKey, wincx);
+ templateCount, &outKey, PR_TRUE, wincx);
PK11_FreeSlot(slot);
}
PORT_Free(outKey.data);
if (crvp)
*crvp = symKey ? CKR_OK : CKR_DEVICE_ERROR;
return symKey;
}
diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -1033,36 +1033,40 @@ sftk_handleCrlObject(SFTKSession *sessio
/*
* check the consistancy and initialize a Public Key Object
*/
static CK_RV
sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
CK_KEY_TYPE key_type)
{
- CK_BBOOL encrypt = CK_TRUE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL wrap = CK_TRUE;
+ CK_BBOOL encrypt = CK_FALSE;
+ CK_BBOOL recover = CK_FALSE;
+ CK_BBOOL wrap = CK_FALSE;
CK_BBOOL derive = CK_FALSE;
- CK_BBOOL verify = CK_TRUE;
+ CK_BBOOL verify = CK_FALSE;
CK_BBOOL encapsulate = CK_FALSE;
CK_ULONG paramSet = 0;
CK_RV crv;
switch (key_type) {
case CKK_RSA:
crv = sftk_ConstrainAttribute(object, CKA_MODULUS,
RSA_MIN_MODULUS_BITS, 0, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_PUBLIC_EXPONENT, 2, 0, 0);
if (crv != CKR_OK) {
return crv;
}
+ encrypt = CK_TRUE;
+ recover = CK_TRUE;
+ wrap = CK_TRUE;
+ verify = CK_TRUE;
break;
case CKK_DSA:
crv = sftk_ConstrainAttribute(object, CKA_SUBPRIME,
DSA_MIN_Q_BITS, DSA_MAX_Q_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_PRIME,
@@ -1073,92 +1077,73 @@ sftk_handlePublicKeyObject(SFTKSession *
crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DSA_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
+ verify = CK_TRUE;
break;
case CKK_DH:
crv = sftk_ConstrainAttribute(object, CKA_PRIME,
DH_MIN_P_BITS, DH_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DH_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
crv = sftk_ConstrainAttribute(object, CKA_VALUE, 2, DH_MAX_P_BITS, 0);
if (crv != CKR_OK) {
return crv;
}
- verify = CK_FALSE;
derive = CK_TRUE;
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
break;
case CKK_EC_MONTGOMERY:
case CKK_EC_EDWARDS:
case CKK_EC:
if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) {
return CKR_TEMPLATE_INCOMPLETE;
}
if (!sftk_hasAttribute(object, CKA_EC_POINT)) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE; /* CK_TRUE for ECDH */
verify = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
break;
#ifndef NSS_DISABLE_KYBER
case CKK_NSS_KYBER:
#endif
case CKK_NSS_ML_KEM:
case CKK_ML_KEM:
if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) {
return CKR_TEMPLATE_INCOMPLETE;
}
}
- derive = CK_FALSE;
- verify = CK_FALSE;
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
encapsulate = CK_TRUE;
break;
#ifdef NSS_ENABLE_ML_DSA
case CKK_ML_DSA:
if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
return CKR_TEMPLATE_INCOMPLETE;
}
crv = sftk_GetULongAttribute (object, CKA_PARAMETER_SET,
&paramSet);
if (crv != CKR_OK) {
return crv;
}
if (sftk_MLDSAGetSigLen(paramSet) == 0) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
- derive = CK_FALSE;
verify = CK_TRUE;
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
- encapsulate = CK_FALSE;
break;
#endif
default:
return CKR_ATTRIBUTE_VALUE_INVALID;
}
/* make sure the required fields exist */
crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0);
@@ -1226,21 +1211,21 @@ sftk_verifyRSAPrivateKey(SFTKObject *obj
/*
* check the consistancy and initialize a Private Key Object
*/
static CK_RV
sftk_handlePrivateKeyObject(SFTKSession *session, SFTKObject *object, CK_KEY_TYPE key_type)
{
CK_BBOOL cktrue = CK_TRUE;
- CK_BBOOL encrypt = CK_TRUE;
+ CK_BBOOL encrypt = CK_FALSE;
CK_BBOOL sign = CK_FALSE;
- CK_BBOOL recover = CK_TRUE;
- CK_BBOOL wrap = CK_TRUE;
- CK_BBOOL derive = CK_TRUE;
+ CK_BBOOL recover = CK_FALSE;
+ CK_BBOOL wrap = CK_FALSE;
+ CK_BBOOL derive = CK_FALSE;
CK_BBOOL decapsulate = CK_FALSE;
CK_BBOOL ckfalse = CK_FALSE;
PRBool createObjectInfo = PR_TRUE;
PRBool fillPrivateKey = PR_FALSE;
CK_ULONG paramSet = 0;
int missing_rsa_mod_component = 0;
int missing_rsa_exp_component = 0;
int missing_rsa_crt_component = 0;
@@ -1302,71 +1287,74 @@ sftk_handlePrivateKeyObject(SFTKSession
crv = sftk_forceAttribute(object, CKA_NSS_DB,
sftk_item_expand(&mod));
if (mod.data)
SECITEM_ZfreeItem(&mod, PR_FALSE);
if (crv != CKR_OK)
return crv;
sign = CK_TRUE;
- derive = CK_FALSE;
+ wrap = CK_TRUE;
+ encrypt = CK_TRUE;
break;
case CKK_DSA:
if (!sftk_hasAttribute(object, CKA_SUBPRIME)) {
return CKR_TEMPLATE_INCOMPLETE;
}
+ if (!sftk_hasAttribute(object, CKA_PRIME)) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if (!sftk_hasAttribute(object, CKA_BASE)) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ if (!sftk_hasAttribute(object, CKA_VALUE)) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
sign = CK_TRUE;
- derive = CK_FALSE;
- /* fall through */
+ break;
case CKK_DH:
if (!sftk_hasAttribute(object, CKA_PRIME)) {
return CKR_TEMPLATE_INCOMPLETE;
}
if (!sftk_hasAttribute(object, CKA_BASE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
if (!sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* allow subprime to be set after the fact */
crv = sftk_defaultAttribute(object, CKA_SUBPRIME, NULL, 0);
if (crv != CKR_OK) {
return crv;
}
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
+ derive = CK_TRUE;
break;
case CKK_EC:
case CKK_EC_EDWARDS:
case CKK_EC_MONTGOMERY:
if (!sftk_hasAttribute(object, CKA_EC_PARAMS)) {
return CKR_TEMPLATE_INCOMPLETE;
}
if (!sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* for ECDSA and EDDSA. Change if the structure of any of them is modified. */
derive = (key_type == CKK_EC_EDWARDS) ? CK_FALSE : CK_TRUE; /* CK_TRUE for ECDH */
sign = (key_type == CKK_EC_MONTGOMERY) ? CK_FALSE : CK_TRUE; /* for ECDSA and EDDSA */
- encrypt = CK_FALSE;
- recover = CK_FALSE;
- wrap = CK_FALSE;
break;
case CKK_NSS_JPAKE_ROUND1:
if (!sftk_hasAttribute(object, CKA_PRIME) ||
!sftk_hasAttribute(object, CKA_SUBPRIME) ||
!sftk_hasAttribute(object, CKA_BASE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* fall through */
case CKK_NSS_JPAKE_ROUND2:
/* CKA_NSS_JPAKE_SIGNERID and CKA_NSS_JPAKE_PEERID are checked in
the J-PAKE code. */
- encrypt = sign = recover = wrap = CK_FALSE;
derive = CK_TRUE;
createObjectInfo = PR_FALSE;
break;
#ifndef NSS_DISABLE_KYBER
case CKK_NSS_KYBER:
#endif
case CKK_NSS_ML_KEM:
case CKK_ML_KEM:
@@ -1376,17 +1364,16 @@ sftk_handlePrivateKeyObject(SFTKSession
if (!sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
if (!sftk_hasAttribute(object, CKA_PARAMETER_SET)) {
if (!sftk_hasAttribute(object, CKA_NSS_PARAMETER_SET)) {
return CKR_TEMPLATE_INCOMPLETE;
}
}
- encrypt = sign = recover = wrap = CK_FALSE;
decapsulate = CK_TRUE;
break;
#ifdef NSS_ENABLE_ML_DSA
case CKK_ML_DSA:
if (!sftk_hasAttribute(object, CKA_KEY_TYPE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
/* make sure we have a CKA_PARAMETER_SET */
@@ -1454,17 +1441,16 @@ sftk_handlePrivateKeyObject(SFTKSession
}
}
sftk_DeleteAttributeType(object, CKA_NSS_SEED_OK);
/* if we got this far, we should have a CKA_VALUE, either but
* one given to us, or by it being generated above */
if (!sftk_hasAttribute(object, CKA_VALUE)) {
return CKR_TEMPLATE_INCOMPLETE;
}
- encrypt = decapsulate = recover = wrap = CK_FALSE;
sign = CK_TRUE;
break;
#endif
default:
return CKR_ATTRIBUTE_VALUE_INVALID;
}
crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0);
if (crv != CKR_OK)
diff --git a/lib/softoken/sftkdb.c b/lib/softoken/sftkdb.c
--- a/lib/softoken/sftkdb.c
+++ b/lib/softoken/sftkdb.c
@@ -54,16 +54,17 @@ sftkdb_isULONGAttribute(CK_ATTRIBUTE_TYP
case CKA_KEY_GEN_MECHANISM:
case CKA_KEY_TYPE:
case CKA_MECHANISM_TYPE:
case CKA_MODULUS_BITS:
case CKA_PRIME_BITS:
case CKA_SUBPRIME_BITS:
case CKA_VALUE_BITS:
case CKA_VALUE_LEN:
+ case CKA_PARAMETER_SET:
case CKA_TRUST_DIGITAL_SIGNATURE:
case CKA_TRUST_NON_REPUDIATION:
case CKA_TRUST_KEY_ENCIPHERMENT:
case CKA_TRUST_DATA_ENCIPHERMENT:
case CKA_TRUST_KEY_AGREEMENT:
case CKA_TRUST_KEY_CERT_SIGN:
case CKA_TRUST_CRL_SIGN:
@@ -386,17 +387,25 @@ sftkdb_fixupTemplateOut(CK_ATTRIBUTE *te
CK_ULONG value;
value = sftk_SDBULong2ULong(ntemplate[i].pValue);
if (length < sizeof(CK_ULONG)) {
template[i].ulValueLen = -1;
crv = CKR_BUFFER_TOO_SMALL;
continue;
}
- PORT_Memcpy(template[i].pValue, &value, sizeof(CK_ULONG));
+ /* handle the case where the CKA_PARAMETER_SET was
+ * incorrectly encoded */
+ if ((value > 0xff) &&
+ (template[i].type == CKA_PARAMETER_SET)) {
+ PORT_Memcpy(template[i].pValue, ntemplate[i].pValue,
+ ntemplate[i].ulValueLen);
+ } else {
+ PORT_Memcpy(template[i].pValue, &value, sizeof(CK_ULONG));
+ }
}
template[i].ulValueLen = sizeof(CK_ULONG);
}
}
/* if no data was retrieved, no need to process encrypted or signed
* attributes */
if ((template[i].pValue == NULL) || (template[i].ulValueLen == -1)) {
@@ -1580,16 +1589,18 @@ sftkdb_DestroyObject(SFTKDBHandle *handl
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PRIME_2);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_EXPONENT_1);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_EXPONENT_2);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_COEFFICIENT);
+ (void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
+ CKA_SEED);
} else {
keydb = SFTK_GET_SDB(handle->peerDB);
}
/* now destroy any authenticated attributes that may exist */
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_MODULUS);
(void)sftkdb_DestroyAttributeSignature(handle, keydb, objectID,
CKA_PUBLIC_EXPONENT);
diff --git a/lib/softoken/sftkpwd.c b/lib/softoken/sftkpwd.c
--- a/lib/softoken/sftkpwd.c
+++ b/lib/softoken/sftkpwd.c
@@ -1205,16 +1205,17 @@ sftk_updateEncrypted(PLArenaPool *arena,
CK_ATTRIBUTE_TYPE privAttrTypes[] = {
CKA_VALUE,
CKA_PRIVATE_EXPONENT,
CKA_PRIME_1,
CKA_PRIME_2,
CKA_EXPONENT_1,
CKA_EXPONENT_2,
CKA_COEFFICIENT,
+ CKA_SEED,
};
const CK_ULONG privAttrCount = sizeof(privAttrTypes) / sizeof(privAttrTypes[0]);
// We don't know what attributes this object has, so we update them one at a
// time.
unsigned int i;
for (i = 0; i < privAttrCount; i++) {
// Read the old attribute in the clear.

View File

@ -3,7 +3,7 @@
# NOTE: To avoid NVR clashes of nspr* packages:
# - reset %%{nspr_release} to 1, when updating %%{nspr_version}
# - increment %%{nspr_version}, when updating the NSS part only
%global baserelease 4
%global baserelease 5
%global nss_release %baserelease
# use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when
# release number between nss and nspr are different.
@ -168,19 +168,22 @@ Patch53: nss-3.101-skip-ocsp-if-not-connected.patch
Patch74: nss-3.90-dh-test-update.patch
Patch75: nss-3.90-ppc_no_init.patch
# https://bugzilla.mozilla.org/show_bug.cgi?id=676100
Patch85: nss-3.101-fix-cms-abi-break.patch
Patch88: nss-3.101-fix-shlibsign-fips.patch
Patch78: nss-3.101-fix-cms-abi-break.patch
Patch79: nss-3.101-fix-shlibsign-fips.patch
# Post Quantum specific
Patch90: nss-3.112-disable-dsa.patch
Patch91: nss-3.112-replace-xyber-with-mlkem-256.patch
Patch92: nss-3.112-add-sec384r1-mlkem-1024.patch
Patch93: nss-3.112-add-ml-dsa-base.patch
Patch94: nss-3.112-add-ml-dsa-gtests.patch
Patch95: nss-3.112-add-ml-dsa-ssl-support.patch
Patch96: nss-3.112-fips-and-fixes-el10.patch
Patch97: nss-3.112-big-endian-compression-fix.patch
Patch98: nss-3.112-fix-get-interface.patch
Patch80: nss-3.112-disable-dsa.patch
Patch81: nss-3.112-replace-xyber-with-mlkem-256.patch
Patch82: nss-3.112-add-sec384r1-mlkem-1024.patch
Patch83: nss-3.112-add-ml-dsa-base.patch
Patch84: nss-3.112-add-ml-dsa-gtests.patch
Patch85: nss-3.112-add-ml-dsa-ssl-support.patch
Patch86: nss-3.112-fips-and-fixes-el10.patch
Patch87: nss-3.112-big-endian-compression-fix.patch
Patch88: nss-3.112-fix-get-interface.patch
Patch89: nss-3.112-mlkem-fips-update.patch
Patch90: nss-3.112-update-fixes.patch
Patch91: nss-3.112-partial-pub-key-validate.patch
# NSS reverse patches
Patch300: nss-3.79-distrusted-certs.patch
@ -728,6 +731,10 @@ rm -rf \
$RPM_BUILD_ROOT/%{_datadir}/aclocal/nspr.m4 \
$RPM_BUILD_ROOT/%{_includedir}/nspr4/md
#cp win.h to old name for compatibility
cp $RPM_BUILD_ROOT/%{_includedir}/nspr4/prwin.h \
$RPM_BUILD_ROOT/%{_includedir}/nspr4/prwin16.h
for f in nspr-config; do
install -c -m 644 ${f}.1 $RPM_BUILD_ROOT%{_mandir}/man1/${f}.1
done
@ -1164,11 +1171,22 @@ fi
%changelog
* Mon Nov 3 2025 Bob Relyea <rrelyea@redhat.com> - 3.112.0-5
- fips update
- Fix indicators for the new post-quantum algorithms
- Fix the ML-KEM Self-tests
- Fix the ML-KEM zeroizaiton
- Add partial public validation before OAEP
- bug fixes
- add CKA_SEED to private attributes so they are updated on password change.
- mark CKA_PARAMETER_SET as CK_ULONG when storing into the database
- fix unrefrence read in leancrypto.
* Thu Aug 7 2025 Bob Relyea <rrelyea@redhat.com> - 3.112.0-4
- fix interface issue when pulling 3.0 pkcs#11 interfaces explicitly
* Fri Aug 1 2025 Bob Relyea <rrelyea@redhat.com> - 3.112.0-3
- restore CONCATENATE functions accidentally remvoed in the last patch
- restore CONCATENATE functions accidentally removed in the last patch
- fix big endian issue in tstclnt and selfserv in certificate compression
* Wed Jul 30 2025 Bob Relyea <rrelyea@redhat.com> - 3.112.0-2