- 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.
800 lines
29 KiB
Diff
800 lines
29 KiB
Diff
# 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 = ¶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
|
|
@@ -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,
|
|
¶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);
|
|
@@ -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.
|