929 lines
34 KiB
Diff
929 lines
34 KiB
Diff
# HG changeset patch
|
|
# User Robert Relyea <rrelyea@redhat.com>
|
|
# Date 1762542092 28800
|
|
# Fri Nov 07 11:01:32 2025 -0800
|
|
# 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
|
|
@@ -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 */
|
|
};
|
|
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
|
|
@@ -416,17 +416,17 @@ SECKEY_CreateEDPrivateKey(SECKEYECParams
|
|
return (privk);
|
|
}
|
|
|
|
void
|
|
SECKEY_DestroyPrivateKey(SECKEYPrivateKey *privk)
|
|
{
|
|
if (privk) {
|
|
if (privk->pkcs11Slot) {
|
|
- if (privk->pkcs11IsTemp) {
|
|
+ if (SECKEYPRIVATEKEY_IS_OWNED(privk)) {
|
|
PK11_DestroyObject(privk->pkcs11Slot, privk->pkcs11ID);
|
|
}
|
|
PK11_FreeSlot(privk->pkcs11Slot);
|
|
}
|
|
if (privk->arena) {
|
|
PORT_FreeArena(privk->arena, PR_TRUE);
|
|
}
|
|
}
|
|
@@ -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->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,34 +1002,39 @@ 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);
|
|
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;
|
|
}
|
|
|
|
privKey->arena = arena;
|
|
privKey->keyType = keyType;
|
|
privKey->pkcs11Slot = PK11_ReferenceSlot(slot);
|
|
privKey->pkcs11ID = privID;
|
|
- privKey->pkcs11IsTemp = isTemp;
|
|
+ privKey->pkcs11IsTemp = 0;
|
|
+ SECKEYPRIVATEKEY_SET_TEMP(privKey, isTemp);
|
|
+ SECKEYPRIVATEKEY_SET_OWNED(privKey, isOwner);
|
|
privKey->wincx = wincx;
|
|
|
|
return privKey;
|
|
}
|
|
|
|
PK11SlotInfo *
|
|
PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key)
|
|
{
|
|
@@ -2635,17 +2642,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 +2675,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 +2738,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 +2830,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 +3018,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/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
|
|
@@ -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 = ¶ms;
|
|
+ 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
|
|
@@ -1031,36 +1031,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,
|
|
@@ -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;
|
|
}
|
|
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,
|
|
¶mSet);
|
|
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);
|
|
@@ -1224,21 +1209,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;
|
|
@@ -1300,71 +1285,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:
|
|
@@ -1374,17 +1362,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 */
|
|
@@ -1452,17 +1439,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.
|