Resolves: RHEL-127696

- Fix regression in private key lifecycle
This commit is contained in:
Robert Relyea 2026-01-20 13:58:51 -08:00
parent ee702100d1
commit e57288c6ae
2 changed files with 160 additions and 28 deletions

View File

@ -2,32 +2,42 @@
# User Robert Relyea <rrelyea@redhat.com>
# 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);

View File

@ -1,6 +1,6 @@
%global nss_version 3.112.0
%global nspr_version 4.36.0
%global baserelease 6
%global baserelease 7
%global nss_release %baserelease
# NOTE: To avoid NVR clashes of nspr* packages:
# use "%%global nspr_release %%[%%baserelease+n]" to handle offsets when
@ -1204,6 +1204,9 @@ update-crypto-policies &> /dev/null || :
%changelog
* Fri Jan 16 2026 Bob Relyea <rrelyea@redhat.com> - 3.112.0-7
- fix gregression in -5 bug fix
* Fri Jan 9 2026 Bob Relyea <rrelyea@redhat.com> - 3.112.0-6
- fix a null in ml-dsa pkcs12 decode
- fix return code in ml-kem pct