diff options
Diffstat (limited to 'security/nss/lib/pk11wrap/pk11skey.c')
-rw-r--r-- | security/nss/lib/pk11wrap/pk11skey.c | 87 |
1 files changed, 71 insertions, 16 deletions
diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index cf2a40a2f..ad4166017 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -357,7 +357,9 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, } /* - * turn key handle into an appropriate key object + * Restore a symmetric wrapping key that was saved using PK11_SetWrapKey. + * + * This function is provided for ABI compatibility; see PK11_SetWrapKey below. */ PK11SymKey * PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, @@ -365,33 +367,51 @@ PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, { PK11SymKey *symKey = NULL; - if (slot->series != series) - return NULL; - if (slot->refKeys[wrap] == CK_INVALID_HANDLE) + PK11_EnterSlotMonitor(slot); + if (slot->series != series || + slot->refKeys[wrap] == CK_INVALID_HANDLE) { + PK11_ExitSlotMonitor(slot); return NULL; - if (type == CKM_INVALID_MECHANISM) + } + + if (type == CKM_INVALID_MECHANISM) { type = slot->wrapMechanism; + } symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx); + PK11_ExitSlotMonitor(slot); return symKey; } /* - * This function is not thread-safe because it sets wrapKey->sessionOwner - * without using a lock or atomic routine. It can only be called when - * only one thread has a reference to wrapKey. + * This function sets an attribute on the current slot with a wrapping key. The + * data saved is ephemeral; it needs to be run every time the program is + * invoked. + * + * Since NSS 3.45, this function is marginally more thread safe. It uses the + * slot lock (if present) and fails silently if a value is already set. Use + * PK11_GetWrapKey() after calling this function to get the current wrapping key + * in case there was an update on another thread. + * + * Either way, using this function is inadvisable. It's provided for ABI + * compatibility only. */ void PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey) { - /* save the handle and mechanism for the wrapping key */ - /* mark the key and session as not owned by us to they don't get freed - * when the key goes way... that lets us reuse the key later */ - slot->refKeys[wrap] = wrapKey->objectID; - wrapKey->owner = PR_FALSE; - wrapKey->sessionOwner = PR_FALSE; - slot->wrapMechanism = wrapKey->type; + PK11_EnterSlotMonitor(slot); + if (wrap < PR_ARRAY_SIZE(slot->refKeys) && + slot->refKeys[wrap] == CK_INVALID_HANDLE) { + /* save the handle and mechanism for the wrapping key */ + /* mark the key and session as not owned by us so they don't get freed + * when the key goes way... that lets us reuse the key later */ + slot->refKeys[wrap] = wrapKey->objectID; + wrapKey->owner = PR_FALSE; + wrapKey->sessionOwner = PR_FALSE; + slot->wrapMechanism = wrapKey->type; + } + PK11_ExitSlotMonitor(slot); } /* @@ -610,7 +630,7 @@ PK11_GetWindow(PK11SymKey *key) } /* - * extract a symetric key value. NOTE: if the key is sensitive, we will + * extract a symmetric key value. NOTE: if the key is sensitive, we will * not be able to do this operation. This function is used to move * keys from one token to another */ SECStatus @@ -618,6 +638,11 @@ PK11_ExtractKeyValue(PK11SymKey *symKey) { SECStatus rv; + if (symKey == NULL) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + if (symKey->data.data != NULL) { if (symKey->size == 0) { symKey->size = symKey->data.len; @@ -1598,6 +1623,7 @@ PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, PK11_FreeSymKey(newBaseKey); if (crv != CKR_OK) { PK11_FreeSymKey(symKey); + PORT_SetError(PK11_MapError(crv)); return NULL; } return symKey; @@ -1840,6 +1866,35 @@ loser: } /* + * This regenerate a public key from a private key. This function is currently + * NSS private. If we want to make it public, we need to add and optional + * template or at least flags (a.la. PK11_DeriveWithFlags). + */ +CK_OBJECT_HANDLE +PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey) +{ + PK11SlotInfo *slot = privKey->pkcs11Slot; + CK_MECHANISM mechanism; + CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE; + CK_RV crv; + + mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV; + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + + PK11_EnterSlotMonitor(slot); + crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism, + privKey->pkcs11ID, NULL, 0, + &objectID); + PK11_ExitSlotMonitor(slot); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError(crv)); + return CK_INVALID_HANDLE; + } + return objectID; +} + +/* * This Generates a wrapping key based on a privateKey, publicKey, and two * random numbers. For Mail usage RandomB should be NULL. In the Sender's * case RandomA is generate, outherwize it is passed. |