From 23b99ddc44979fb107bdbc0488109d160265a4b8 Mon Sep 17 00:00:00 2001 From: Robert Relyea Date: Tue, 20 Jan 2026 13:50:25 -0800 Subject: [PATCH] Resolves: RHEL-127691 - Fix regression in private key lifecycle - fix a null in ml-dsa pkcs12 decode - fix return code in ml-kem pct --- nss-3.112-pkcs12-ml-dsa-crash-fix.patch | 202 ++++++++++++++++++++++++ nss-3.112-update-fixes.patch | 183 +++++++++++++++++---- nss.spec | 10 +- 3 files changed, 367 insertions(+), 28 deletions(-) create mode 100644 nss-3.112-pkcs12-ml-dsa-crash-fix.patch diff --git a/nss-3.112-pkcs12-ml-dsa-crash-fix.patch b/nss-3.112-pkcs12-ml-dsa-crash-fix.patch new file mode 100644 index 0000000..038dbc8 --- /dev/null +++ b/nss-3.112-pkcs12-ml-dsa-crash-fix.patch @@ -0,0 +1,202 @@ +# HG changeset patch +# User Robert Relyea +# Date 1767992040 28800 +# Fri Jan 09 12:54:00 2026 -0800 +# Branch RHEL10 +# Node ID 15f1129c29c037cce7913eb62c0eca06b5aa51d1 +# Parent 4bfb87c6e863957fc933e6dd5af8eae8a5cd0469 +nss-3.112-pkcs12-ml-dsa-crash-fix.patch + +diff --git a/gtests/pk11_gtest/pk11_der_private_key_import_unittest.cc b/gtests/pk11_gtest/pk11_der_private_key_import_unittest.cc +--- a/gtests/pk11_gtest/pk11_der_private_key_import_unittest.cc ++++ b/gtests/pk11_gtest/pk11_der_private_key_import_unittest.cc +@@ -7,16 +7,17 @@ + #include + #include + #include "nss.h" + #include "pk11pub.h" + #include "secutil.h" + + #include "gtest/gtest.h" + #include "nss_scoped_ptrs.h" ++#define SEC_OID_ML_DSA_44 SEC_OID_PRIVATE_3 + + namespace nss_test { + + const std::vector kValidP256Key = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, + 0xc9, 0xaf, 0xa9, 0xd8, 0x45, 0xba, 0x75, 0x16, 0x6b, 0x5c, 0x21, 0x57, +@@ -133,16 +134,69 @@ class DERPrivateKeyImportTest : public : + // no cert. This is expected, so clear it. + if (PORT_GetError() == SSL_ERROR_NO_CERTIFICATE) { + PORT_SetError(0); + } + } + + return rv == SECSuccess; + } ++ ++ SECStatus BuildPrivateKeyInfoAndImportIt(SECOidTag algTag) { ++ ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); ++ EXPECT_TRUE(slot); ++ if (!slot) { ++ return SECFailure; ++ } ++ ++ ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); ++ EXPECT_TRUE(arena); ++ if (!arena) { ++ return SECFailure; ++ } ++ ++ SECKEYPrivateKeyInfo* pki = (SECKEYPrivateKeyInfo*)PORT_ArenaZAlloc( ++ arena.get(), sizeof(SECKEYPrivateKeyInfo)); ++ EXPECT_TRUE(pki); ++ if (!pki) { ++ return SECFailure; ++ } ++ ++ pki->version.data = (unsigned char*)PORT_ArenaAlloc(arena.get(), 1); ++ EXPECT_TRUE(pki->version.data); ++ if (!pki->version.data) { ++ return SECFailure; ++ } ++ ++ pki->version.data[0] = 0x00; ++ pki->version.len = 1; ++ ++ EXPECT_EQ( ++ SECOID_SetAlgorithmID(arena.get(), &pki->algorithm, algTag, nullptr), ++ SECSuccess); ++ ++ // Empty private key ++ pki->privateKey.data = (unsigned char*)PORT_ArenaAlloc(arena.get(), 1); ++ EXPECT_TRUE(pki->privateKey.data); ++ if (!pki->privateKey.data) { ++ return SECFailure; ++ } ++ pki->privateKey.len = 0; ++ ++ SECKEYPrivateKey* privk = nullptr; ++ PORT_SetError(0); ++ SECStatus rv = PK11_ImportPrivateKeyInfoAndReturnKey( ++ slot.get(), pki, nullptr, nullptr, PR_FALSE, PR_FALSE, KU_ALL, &privk, ++ nullptr); ++ ++ if (privk) { ++ SECKEY_DestroyPrivateKey(privk); ++ } ++ return rv; ++ } + }; + + TEST_F(DERPrivateKeyImportTest, ImportPrivateRSAKey) { + EXPECT_TRUE(ParsePrivateKey(kValidRSAKey, true)); + EXPECT_FALSE(PORT_GetError()) << PORT_GetError(); + } + + TEST_F(DERPrivateKeyImportTest, ImportEcdsaKey) { +@@ -155,9 +209,15 @@ TEST_F(DERPrivateKeyImportTest, ImportIn + EXPECT_EQ(PORT_GetError(), SEC_ERROR_BAD_DER) << PORT_GetError(); + } + + TEST_F(DERPrivateKeyImportTest, ImportZeroLengthPrivateKey) { + EXPECT_FALSE(ParsePrivateKey(kInvalidZeroLengthKey, false)); + EXPECT_EQ(PORT_GetError(), SEC_ERROR_BAD_KEY) << PORT_GetError(); + } + ++TEST_F(DERPrivateKeyImportTest, ++ ImportZeroLengthMLDSAPrivateKey) { ++ EXPECT_EQ(BuildPrivateKeyInfoAndImportIt(SEC_OID_ML_DSA_44), SECFailure); ++ EXPECT_EQ(PORT_GetError(), SEC_ERROR_BAD_KEY); ++} ++ + } // namespace nss_test +diff --git a/lib/pk11wrap/pk11pk12.c b/lib/pk11wrap/pk11pk12.c +--- a/lib/pk11wrap/pk11pk12.c ++++ b/lib/pk11wrap/pk11pk12.c +@@ -323,17 +323,17 @@ PK11_ImportDERPrivateKeyInfoAndReturnKey + derPKI); + if (rv != SECSuccess) { + /* If SEC_ASN1DecodeItem fails, we cannot assume anything about the + * validity of the data in pki. The best we can do is free the arena + * and return. */ + PORT_FreeArena(temparena, PR_TRUE); + return rv; + } +- if (pki->privateKey.data == NULL) { ++ if (pki->privateKey.data == NULL || pki->privateKey.len == 0) { + /* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey + * is a zero-length octet string, free the arena and return a failure + * to avoid trying to zero the corresponding SECItem in + * SECKEY_DestroyPrivateKeyInfo(). */ + PORT_FreeArena(temparena, PR_TRUE); + PORT_SetError(SEC_ERROR_BAD_KEY); + return SECFailure; + } +@@ -753,16 +753,20 @@ PK11_ImportPrivateKeyInfoAndReturnKey(PK + keyTemplate = SECKEY_ECPrivateKeyExportTemplate; + paramTemplate = NULL; + paramDest = NULL; + lpk->keyType = ecKey; + break; + case SEC_OID_ML_DSA_44: + case SEC_OID_ML_DSA_65: + case SEC_OID_ML_DSA_87: ++ if (pki->privateKey.data == NULL || pki->privateKey.len == 0) { ++ PORT_SetError(SEC_ERROR_BAD_KEY); ++ goto loser; ++ } + /* choice */ + switch (pki->privateKey.data[0]) { + case SEC_ASN1_CONTEXT_SPECIFIC|0: + keyTemplate = SECKEY_MLDSAPrivateKeySeedExportTemplate; + break; + case SEC_ASN1_OCTET_STRING: + keyTemplate = SECKEY_MLDSAPrivateKeyKeyExportTemplate; + break; +diff --git a/lib/softoken/pkcs11c.c b/lib/softoken/pkcs11c.c +--- a/lib/softoken/pkcs11c.c ++++ b/lib/softoken/pkcs11c.c +@@ -5815,17 +5815,17 @@ sftk_PairwiseConsistencyCheck(CK_SESSION + } + crv = NSC_Decapsulate(hSession, &mech, privateKey->handle, + cipher_text, cipher_text_length, &template, 1, + &key2); + if (crv != CKR_OK) { + goto kem_done; + } + if (!sftk_compareKeysEqual(hSession, key1, key2)) { +- crv = CKR_DEVICE_ERROR; ++ crv = CKR_GENERAL_ERROR; + goto kem_done; + } + kem_done: + /* PORT_Free already checks for NULL */ + PORT_Free(cipher_text); + if (key1 != CK_INVALID_HANDLE) { + NSC_DestroyObject(hSession, key1); + } +@@ -7105,16 +7105,20 @@ sftk_unwrapPrivateKey(SFTKObject *key, S + paramSet = CKP_ML_DSA_44; + goto mldsa_next; + case SEC_OID_ML_DSA_65: + paramSet = CKP_ML_DSA_65; + goto mldsa_next; + case SEC_OID_ML_DSA_87: + paramSet = CKP_ML_DSA_87; + mldsa_next: ++ if (pki->privateKey.data == NULL || pki->privateKey.len == 0) { ++ PORT_SetError(SEC_ERROR_BAD_KEY); ++ goto loser; ++ } + switch (pki->privateKey.data[0]) { + case SEC_ASN1_CONTEXT_SPECIFIC|0: + keyTemplate = nsslowkey_PQSeedTemplate; + break; + case SEC_ASN1_OCTET_STRING: + keyTemplate = nsslowkey_PQPrivateKeyTemplate; + break; + case SEC_ASN1_CONSTRUCTED|SEC_ASN1_SEQUENCE: diff --git a/nss-3.112-update-fixes.patch b/nss-3.112-update-fixes.patch index 46f1e55..6c4508a 100644 --- a/nss-3.112-update-fixes.patch +++ b/nss-3.112-update-fixes.patch @@ -2,32 +2,42 @@ # User Robert Relyea # Date 1762542092 28800 # Fri Nov 07 11:01:32 2025 -0800 -# Branch RHEL10 -# Node ID 6949dbcd6631ec0db3f53b3cf8957fac3a80da25 -# Parent 3e2ea63bf062fef47334b69723db7eac95daaa2a +# Branch RHEL_8 +# Node ID 5b6833262609c6a2567d234a645be532bde27ef7 +# Parent 04ad729ed140ac94ab37d012dd2fec6c575bba2b 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; +@@ -243,16 +243,27 @@ struct SECKEYPrivateKeyStr { 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; ++#define SECKEYPRIVATEKEY_IS_TEMP_FLAG 0x01 ++#define SECKEYPRIVATEKEY_IS_OWNED_FLAG 0x02 ++#define SECKEYPRIVATEKEY_IS_TEMP(key) \ ++ ((PRBool)((key)->pkcs11IsTemp&SECKEYPRIVATEKEY_IS_TEMP_FLAG)==SECKEYPRIVATEKEY_IS_TEMP_FLAG) ++#define SECKEYPRIVATEKEY_IS_OWNED(key) \ ++ ((PRBool)((key)->pkcs11IsTemp&SECKEYPRIVATEKEY_IS_OWNED_FLAG)==SECKEYPRIVATEKEY_IS_OWNED_FLAG) ++#define SECKEYPRIVATEKEY_SET_TEMP(key,isTemp) (key)->pkcs11IsTemp = ((key)->pkcs11IsTemp & ~SECKEYPRIVATEKEY_IS_TEMP_FLAG) | \ ++ ((isTemp) ? SECKEYPRIVATEKEY_IS_TEMP_FLAG : 0) ++#define SECKEYPRIVATEKEY_SET_OWNED(key,isOwned) (key)->pkcs11IsTemp = ((key)->pkcs11IsTemp & ~SECKEYPRIVATEKEY_IS_OWNED_FLAG) | \ ++ ((isOwned) ? SECKEYPRIVATEKEY_IS_OWNED_FLAG : 0) ++ typedef struct { PRCList links; SECKEYPrivateKey *key; } SECKEYPrivateKeyListNode; + typedef struct { + PRCList list; + PLArenaPool *arena; diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c --- a/lib/cryptohi/seckey.c +++ b/lib/cryptohi/seckey.c @@ -41,7 +51,7 @@ diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c if (privk) { if (privk->pkcs11Slot) { - if (privk->pkcs11IsTemp) { -+ if (privk->pkcs11IsOwner) { ++ if (SECKEYPRIVATEKEY_IS_OWNED(privk)) { PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID); } PK11_FreeSlot(privk->pkcs11Slot); @@ -50,16 +60,33 @@ diff --git a/lib/cryptohi/seckey.c b/lib/cryptohi/seckey.c PORT_FreeArena(privk->arena, PR_TRUE); } } -@@ -1429,16 +1429,17 @@ SECKEY_CopyPrivateKey(const SECKEYPrivat +@@ -1418,27 +1418,31 @@ SECKEY_CopyPrivateKey(const SECKEYPrivat + copyk = (SECKEYPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYPrivateKey)); + if (copyk) { + copyk->arena = arena; + copyk->keyType = privk->keyType; + + /* copy the PKCS #11 parameters */ + copyk->pkcs11Slot = PK11_ReferenceSlot(privk->pkcs11Slot); + /* if the key we're referencing was a temparary key we have just +- * created, that we want to go away when we're through, we need ++ * it may go away when we're through, we need + * to make a copy of it */ +- if (privk->pkcs11IsTemp) { ++ copyk->pkcs11IsTemp = privk->pkcs11IsTemp; ++ if (SECKEYPRIVATEKEY_IS_TEMP(privk)) { copyk->pkcs11ID = PK11_CopyKey(privk->pkcs11Slot, privk->pkcs11ID); if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; ++ /* since we made a copy, we own that copy (even if we ++ * didn't own the original */ ++ SECKEYPRIVATEKEY_SET_OWNED(copyk, PR_TRUE); } else { copyk->pkcs11ID = privk->pkcs11ID; ++ SECKEYPRIVATEKEY_SET_OWNED(copyk, PR_FALSE); } - copyk->pkcs11IsTemp = privk->pkcs11IsTemp; -+ copyk->pkcs11IsOwner = privk->pkcs11IsOwner; +- copyk->pkcs11IsTemp = privk->pkcs11IsTemp; copyk->wincx = privk->wincx; copyk->staticflags = privk->staticflags; return copyk; @@ -118,7 +145,7 @@ diff --git a/lib/freebl/leancrypto/lc_sha3.h b/lib/freebl/leancrypto/lc_sha3.h 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 +@@ -1002,34 +1002,39 @@ PK11_ExtractPublicKey(PK11SlotInfo *slot return pubKey; } @@ -143,7 +170,24 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c 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 + if (keyType == nullKey) { + return NULL; + } + } ++ /* we can never own a perm key, make sure we don't set owner */ ++ if (!isTemp) { ++ isOwner = PR_FALSE; ++ } + + /* if the key is private, make sure we are authenticated to the + * token before we try to use it */ + isPrivate = (PRBool)PK11_HasAttributeSet(slot, privID, CKA_PRIVATE, PR_FALSE); + if (isPrivate) { + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv != SECSuccess) { + return NULL; +@@ -1047,17 +1052,19 @@ PK11_MakePrivKey(PK11SlotInfo *slot, Key + PORT_FreeArena(arena, PR_FALSE); return NULL; } @@ -151,8 +195,10 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c privKey->keyType = keyType; privKey->pkcs11Slot = PK11_ReferenceSlot(slot); privKey->pkcs11ID = privID; - privKey->pkcs11IsTemp = isTemp; -+ privKey->pkcs11IsOwner = isOwner; +- privKey->pkcs11IsTemp = isTemp; ++ privKey->pkcs11IsTemp = 0; ++ SECKEYPRIVATEKEY_SET_TEMP(privKey, isTemp); ++ SECKEYPRIVATEKEY_SET_OWNED(privKey, isOwner); privKey->wincx = wincx; return privKey; @@ -161,7 +207,7 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c PK11SlotInfo * PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key) { -@@ -2635,17 +2637,17 @@ PK11_CopyTokenPrivKeyToSessionPrivKey(PK +@@ -2635,17 +2642,17 @@ PK11_CopyTokenPrivKeyToSessionPrivKey(PK 1, &newKeyID); PK11_ExitSlotMonitor(destSlot); @@ -180,7 +226,7 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c { PK11SlotInfo *slot = privk->pkcs11Slot; CK_ATTRIBUTE template[1]; -@@ -2668,17 +2670,17 @@ PK11_ConvertSessionPrivKeyToTokenPrivKey +@@ -2668,17 +2675,17 @@ PK11_ConvertSessionPrivKeyToTokenPrivKey template, 1, &newKeyID); PK11_RestoreROSession(slot, rwsession); @@ -199,7 +245,7 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c * this function also frees the privKey structure. */ SECStatus -@@ -2731,17 +2733,17 @@ pk11_DoKeys(PK11SlotInfo *slot, CK_OBJEC +@@ -2731,17 +2738,17 @@ pk11_DoKeys(PK11SlotInfo *slot, CK_OBJEC { SECStatus rv = SECSuccess; SECKEYPrivateKey *privKey; @@ -218,7 +264,7 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c if (keycb->callback) { rv = (*keycb->callback)(privKey, keycb->callbackArg); } -@@ -2823,17 +2825,17 @@ PK11_FindKeyByKeyID(PK11SlotInfo *slot, +@@ -2823,17 +2830,17 @@ PK11_FindKeyByKeyID(PK11SlotInfo *slot, { CK_OBJECT_HANDLE keyHandle; SECKEYPrivateKey *privKey; @@ -237,7 +283,7 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c * 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 +@@ -3011,15 +3018,15 @@ PK11_ListPrivKeysInSlot(PK11SlotInfo *sl keys = SECKEY_NewPrivateKeyList(); if (keys == NULL) { PORT_Free(key_ids); @@ -254,6 +300,89 @@ diff --git a/lib/pk11wrap/pk11akey.c b/lib/pk11wrap/pk11akey.c PORT_Free(key_ids); return keys; } +diff --git a/lib/pk11wrap/pk11cert.c b/lib/pk11wrap/pk11cert.c +--- a/lib/pk11wrap/pk11cert.c ++++ b/lib/pk11wrap/pk11cert.c +@@ -1313,17 +1313,18 @@ PK11_FindPrivateKeyFromCert(PK11SlotInfo + if (rv != SECSuccess) { + return NULL; + } + keyh = PK11_MatchItem(slot, certh, CKO_PRIVATE_KEY); + } + if (keyh == CK_INVALID_HANDLE) { + return NULL; + } +- return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); ++ ++ return PK11_MakePrivKey(slot, nullKey, PR_FALSE, keyh, wincx); + } + + /* + * import a cert for a private key we have already generated. Set the label + * on both to be the nickname. This is for the Key Gen, orphaned key case. + */ + PK11SlotInfo * + PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, +@@ -2085,17 +2086,17 @@ PK11_FindKeyByAnyCert(CERTCertificate *c + SEC_ERROR_TOKEN_NOT_LOGGED_IN == err)) { + /* authenticate and try again */ + rv = PK11_Authenticate(slot, PR_TRUE, wincx); + if (rv == SECSuccess) { + keyHandle = PK11_MatchItem(slot, certHandle, CKO_PRIVATE_KEY); + } + } + if (keyHandle != CK_INVALID_HANDLE) { +- privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); ++ privKey = PK11_MakePrivKey(slot, nullKey, PR_FALSE, keyHandle, wincx); + } + if (slot) { + PK11_FreeSlot(slot); + } + return privKey; + } + + CK_OBJECT_HANDLE +@@ -2492,17 +2493,17 @@ PK11_FindKeyByDERCert(PK11SlotInfo *slot + return NULL; + } + + keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); + if (keyHandle == CK_INVALID_HANDLE) { + return NULL; + } + +- return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); ++ return PK11_MakePrivKey(slot, nullKey, PR_FALSE, keyHandle, wincx); + } + + SECStatus + PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, + char *nickname, + PRBool addCertUsage, void *wincx) + { + CK_OBJECT_HANDLE keyHandle; +diff --git a/lib/pk11wrap/pk11kea.c b/lib/pk11wrap/pk11kea.c +--- a/lib/pk11wrap/pk11kea.c ++++ b/lib/pk11wrap/pk11kea.c +@@ -86,17 +86,17 @@ pk11_KeyExchange(PK11SlotInfo *slot, CK_ + goto rsa_failed; + } + rsaParams.keySizeInBits = 1024; + rsaParams.pe = 0x10001; + privKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, + &rsaParams, &pubKey, PR_FALSE, PR_TRUE, symKey->cx); + } else { + /* if keys exist, build SECKEY data structures for them */ +- privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, privKeyHandle, ++ privKey = PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyHandle, + symKey->cx); + if (privKey != NULL) { + pubKey = PK11_ExtractPublicKey(slot, rsaKey, pubKeyHandle); + if (pubKey && pubKey->pkcs11Slot) { + PK11_FreeSlot(pubKey->pkcs11Slot); + pubKey->pkcs11Slot = NULL; + pubKey->pkcs11ID = CK_INVALID_HANDLE; + } diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c --- a/lib/pk11wrap/pk11skey.c +++ b/lib/pk11wrap/pk11skey.c @@ -423,7 +552,7 @@ diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c 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 +@@ -1031,36 +1031,40 @@ sftk_handleCrlObject(SFTKSession *sessio /* * check the consistancy and initialize a Public Key Object @@ -468,7 +597,7 @@ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c return crv; } crv = sftk_ConstrainAttribute(object, CKA_PRIME, -@@ -1073,92 +1077,73 @@ sftk_handlePublicKeyObject(SFTKSession * +@@ -1071,92 +1075,73 @@ sftk_handlePublicKeyObject(SFTKSession * crv = sftk_ConstrainAttribute(object, CKA_BASE, 2, DSA_MAX_P_BITS, 0); if (crv != CKR_OK) { return crv; @@ -562,7 +691,7 @@ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c /* make sure the required fields exist */ crv = sftk_defaultAttribute(object, CKA_SUBJECT, NULL, 0); -@@ -1226,21 +1211,21 @@ sftk_verifyRSAPrivateKey(SFTKObject *obj +@@ -1224,21 +1209,21 @@ sftk_verifyRSAPrivateKey(SFTKObject *obj /* * check the consistancy and initialize a Private Key Object @@ -588,7 +717,7 @@ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c 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 +@@ -1300,71 +1285,74 @@ sftk_handlePrivateKeyObject(SFTKSession crv = sftk_forceAttribute(object, CKA_NSS_DB, sftk_item_expand(&mod)); if (mod.data) @@ -673,7 +802,7 @@ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c #endif case CKK_NSS_ML_KEM: case CKK_ML_KEM: -@@ -1376,17 +1364,16 @@ sftk_handlePrivateKeyObject(SFTKSession +@@ -1374,17 +1362,16 @@ sftk_handlePrivateKeyObject(SFTKSession if (!sftk_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } @@ -691,7 +820,7 @@ diff --git a/lib/softoken/pkcs11.c b/lib/softoken/pkcs11.c return CKR_TEMPLATE_INCOMPLETE; } /* make sure we have a CKA_PARAMETER_SET */ -@@ -1454,17 +1441,16 @@ sftk_handlePrivateKeyObject(SFTKSession +@@ -1452,17 +1439,16 @@ sftk_handlePrivateKeyObject(SFTKSession } } sftk_DeleteAttributeType(object, CKA_NSS_SEED_OK); diff --git a/nss.spec b/nss.spec index 8dcd8d9..3a62202 100644 --- a/nss.spec +++ b/nss.spec @@ -63,7 +63,7 @@ print(string.sub(hash, 0, 16)) Summary: Network Security Services Name: nss Version: %{nss_version} -Release: 5%{?dist} +Release: 7%{?dist} License: MPLv2.0 URL: http://www.mozilla.org/projects/security/pki/nss/ Requires: nspr >= %{nspr_version}%{nspr_release} @@ -198,6 +198,7 @@ Patch88: nss-3.112-fix-get-interface.patch Patch89: nss-3.112-update-fixes.patch Patch90: nss-3.112-mlkem-fips-update.patch Patch91: nss-3.112-partial-pub-key-validate.patch +Patch92: nss-3.112-pkcs12-ml-dsa-crash-fix.patch %description Network Security Services (NSS) is a set of libraries designed to @@ -1000,6 +1001,13 @@ update-crypto-policies --no-reload &> /dev/null || : %changelog +* Fri Jan 16 2026 Bob Relyea - 3.112.0-7 +- fix regression in -5 bug fix + +* Fri Jan 9 2026 Bob Relyea - 3.112.0-6 +- fix a null in ml-dsa pkcs12 decode +- fix return code in ml-kem pct + * Tue Nov 11 2025 Bob Relyea - 3.112.0-5 - fips update - Fix indicators for the new post-quantum algorithms