nss/nss-3.124-fix-pub-key-import-encapsulate.patch
2026-08-19 19:37:08 -04:00

218 lines
8.3 KiB
Diff

# HG changeset patch
# User Robert Relyea <rrelyea@redhat.com>
# Date 1781029720 25200
# Tue Jun 09 11:28:40 2026 -0700
# Branch NSS_3_124_BRANCH
# Node ID 1e0565f958c9e9ce4713a19eeee3541286133fb6
# Parent d9ba1487c7c6821154edd972c88cecba1d458503
nss-3.124-fix-pub-key-import-encapsulate.patch
diff --git a/lib/pk11wrap/pk11skey.c b/lib/pk11wrap/pk11skey.c
--- a/lib/pk11wrap/pk11skey.c
+++ b/lib/pk11wrap/pk11skey.c
@@ -3124,33 +3124,54 @@ SECStatus
PK11_Encapsulate(SECKEYPublicKey *pubKey, CK_MECHANISM_TYPE target,
PK11AttrFlags attrFlags, CK_FLAGS opFlags,
PK11SymKey **outKey, SECItem **outCiphertext)
{
PORT_Assert(pubKey);
PORT_Assert(outKey);
PORT_Assert(outCiphertext);
- PK11SlotInfo *slot = pubKey->pkcs11Slot;
PK11SymKey *sharedSecret = NULL;
SECItem *ciphertext = NULL;
CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS];
unsigned int templateCount;
+
CK_ATTRIBUTE *attrs;
CK_BBOOL cktrue = CK_TRUE;
CK_BBOOL ckfalse = CK_FALSE;
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
CK_MECHANISM_TYPE kemType = pk11_mapKemKeyType(pubKey->keyType);
CK_MECHANISM mech = { kemType, NULL, 0 };
CK_ULONG ciphertextLen = 0;
- CK_RV crv;
+ CK_RV crv = CKR_OK;
+
+ PK11SlotInfo *slot = pubKey->pkcs11Slot;
+
+ if (slot == NULL) {
+ CK_MECHANISM_TYPE mechs[] = { kemType, target};
+ CK_ULONG mech_count = PR_ARRAY_SIZE(mechs);
+ slot = PK11_GetBestSlotMultiple(mechs, mech_count, NULL /*sigh*/);
+ } else {
+ /* should we check if the slot can do target and kemtype
+ * here and move the public key if it can't? */
+ slot = PK11_ReferenceSlot(slot);
+ }
+ if (slot == NULL) {
+ goto loser; /* error already set */
+ }
+
+ CK_OBJECT_HANDLE id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE);
+
+ if (id == CK_INVALID_HANDLE) {
+ goto loser; /* error already set */
+ }
/* set up the target key template */
attrs = keyTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
attrs++;
PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
attrs++;
@@ -3162,30 +3183,30 @@ PK11_Encapsulate(SECKEYPublicKey *pubKey
PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE));
*outKey = NULL;
*outCiphertext = NULL;
/* create a struxture for the target key */
sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL);
if (sharedSecret == NULL) {
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- return SECFailure;
+ crv = CKR_HOST_MEMORY;
+ goto loser;
}
sharedSecret->origin = PK11_OriginDerive;
/* this path is KEM mechanism agnostic */
if (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE) >= 0) {
pk11_EnterKeyMonitor(sharedSecret);
/* get the length the normal PKCS #11 way. This works no matter
* what the KEM is and we don't have to try to guess the KEM length
* from the key */
crv = PK11_GETTAB(slot)->C_EncapsulateKey(sharedSecret->session,
&mech,
- pubKey->pkcs11ID,
+ id,
keyTemplate,
templateCount,
NULL,
&ciphertextLen,
&sharedSecret->objectID);
pk11_ExitKeyMonitor(sharedSecret);
if ((crv != CKR_OK) && (crv != CKR_BUFFER_TOO_SMALL) &&
(crv != CKR_KEY_SIZE_RANGE)) {
@@ -3197,17 +3218,17 @@ PK11_Encapsulate(SECKEYPublicKey *pubKey
goto loser;
}
pk11_EnterKeyMonitor(sharedSecret);
/* Now do the encapsulate */
/* NOTE: the PKCS #11 order of the parameters is different from
* the vendor interface */
crv = PK11_GETTAB(slot)->C_EncapsulateKey(sharedSecret->session,
&mech,
- pubKey->pkcs11ID,
+ id,
keyTemplate,
templateCount,
ciphertext->data,
&ciphertextLen,
&sharedSecret->objectID);
pk11_ExitKeyMonitor(sharedSecret);
if (crv != CKR_OK) {
goto loser;
@@ -3228,21 +3249,21 @@ PK11_Encapsulate(SECKEYPublicKey *pubKey
if (crv != CKR_OK) {
goto loser;
}
KEMInterfaceFunctions = (CK_NSS_KEM_FUNCTIONS *)(KEMInterface->pFunctionList);
/* the old API expected the parameter set as a parameter, the
* pkcs11 v3.2 gets it from the key */
kemParameterSet = PK11_ReadULongAttribute(slot,
- pubKey->pkcs11ID,
+ id,
CKA_NSS_PARAMETER_SET);
if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) {
kemParameterSet = PK11_ReadULongAttribute(slot,
- pubKey->pkcs11ID,
+ id,
CKA_PARAMETER_SET);
if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) {
crv = CKR_PUBLIC_KEY_INVALID;
goto loser;
}
}
/* The old interface only ever supported KYBER768 and MLKEM768
* SOME versions of RHEL has MLKEM1024 support, if we want to
@@ -3259,39 +3280,48 @@ PK11_Encapsulate(SECKEYPublicKey *pubKey
if (ciphertext == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
pk11_EnterKeyMonitor(sharedSecret);
crv = KEMInterfaceFunctions->C_Encapsulate(sharedSecret->session,
&mech,
- pubKey->pkcs11ID,
+ id,
keyTemplate,
templateCount,
&sharedSecret->objectID,
ciphertext->data,
&ciphertextLen);
pk11_ExitKeyMonitor(sharedSecret);
if (crv != CKR_OK) {
goto loser;
}
PORT_Assert(ciphertextLen == ciphertext->len);
}
+ PK11_FreeSlot(slot);
+
*outKey = sharedSecret;
*outCiphertext = ciphertext;
return SECSuccess;
loser:
- PK11_FreeSymKey(sharedSecret);
+ if (slot) {
+ PK11_FreeSlot(slot);
+ }
+ if (sharedSecret) {
+ PK11_FreeSymKey(sharedSecret);
+ }
SECITEM_FreeItem(ciphertext, PR_TRUE);
- PORT_SetError(PK11_MapError(crv));
+ if (crv != CKR_OK) {
+ PORT_SetError(PK11_MapError(crv));
+ }
return SECFailure;
}
SECStatus
PK11_Decapsulate(SECKEYPrivateKey *privKey, const SECItem *ciphertext,
CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags,
CK_FLAGS opFlags, PK11SymKey **outKey)
{
@@ -3312,17 +3342,17 @@ PK11_Decapsulate(SECKEYPrivateKey *privK
CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
CK_MECHANISM_TYPE kemType = pk11_mapKemKeyType(privKey->keyType);
CK_MECHANISM mech = { kemType, NULL, 0 };
CK_RV crv;
*outKey = NULL;
- sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL);
+ sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, privKey->wincx);
if (sharedSecret == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return SECFailure;
}
sharedSecret->origin = PK11_OriginUnwrap;
attrs = keyTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));