diff options
-rw-r--r-- | security/nss/lib/nss/nss.def | 1 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11pub.h | 13 | ||||
-rw-r--r-- | security/nss/lib/pk11wrap/pk11skey.c | 179 |
3 files changed, 124 insertions, 69 deletions
diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index d08e7cd12..6c4495d58 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -1008,6 +1008,7 @@ CERT_GetConstrainedCertificateNames; CERT_FindCertByNicknameOrEmailAddrForUsage; PK11_DeriveWithTemplate; PK11_FindCertsFromEmailAddress; +PK11_KeyGenWithTemplate; SECMOD_RestartModules; ;+ local: ;+ *; diff --git a/security/nss/lib/pk11wrap/pk11pub.h b/security/nss/lib/pk11wrap/pk11pub.h index a47b73750..2813e370b 100644 --- a/security/nss/lib/pk11wrap/pk11pub.h +++ b/security/nss/lib/pk11wrap/pk11pub.h @@ -334,6 +334,19 @@ PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx); +/* Generates a key using the exact template supplied by the caller. The other + * PK11_[Token]KeyGen mechanisms should be used instead of this one whenever + * they work because they include/exclude the CKA_VALUE_LEN template value + * based on the mechanism type as required by many tokens. + * + * keyGenType should be PK11_GetKeyGenWithSize(type, <key size>) or it should + * be equal to type if PK11_GetKeyGenWithSize cannot be used (e.g. because + * pk11wrap does not know about the mechanisms). + */ +PK11SymKey *PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, + CK_MECHANISM_TYPE keyGenType, + SECItem *param, CK_ATTRIBUTE * attrs, + unsigned int attrsCount, void *wincx); PK11SymKey * PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx); PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey); diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 27c05067a..ae72f52e7 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -915,7 +915,7 @@ pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE *attrs = genTemplate; int count = sizeof(genTemplate)/sizeof(genTemplate[0]); CK_SESSION_HANDLE session; - CK_MECHANISM mechanism; + CK_MECHANISM_TYPE keyGenType; CK_RV crv; CK_BBOOL cktrue = CK_TRUE; CK_BBOOL ckfalse = CK_FALSE; @@ -951,76 +951,16 @@ pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, count = attrs - genTemplate; PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); - /* Initialize the Key Gen Mechanism */ - mechanism.mechanism = PK11_GetKeyGenWithSize(type, keySize); - if (mechanism.mechanism == CKM_FAKE_RANDOM) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return NULL; - } - - /* find a slot to generate the key into */ - /* Only do slot management if this is not a token key */ - if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { - PK11SlotInfo *bestSlot; - - bestSlot = PK11_GetBestSlot(type,wincx); - if (bestSlot == NULL) { - PORT_SetError( SEC_ERROR_NO_MODULE ); - return NULL; - } - - symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); - - PK11_FreeSlot(bestSlot); - } else { - symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); - } - if (symKey == NULL) return NULL; - - symKey->size = keySize; - symKey->origin = PK11_OriginGenerated; - - /* Set the parameters for the key gen if provided */ - mechanism.pParameter = NULL; - mechanism.ulParameterLen = 0; - if (param) { - mechanism.pParameter = param->data; - mechanism.ulParameterLen = param->len; - } - - /* Get session and perform locking */ - if (isToken) { - PK11_Authenticate(symKey->slot,PR_TRUE,wincx); - /* Should always be original slot */ - session = PK11_GetRWSession(symKey->slot); - symKey->owner = PR_FALSE; - } else { - session = symKey->session; - if (session != CK_INVALID_SESSION) - pk11_EnterKeyMonitor(symKey); - } - if (session == CK_INVALID_SESSION) { - PK11_FreeSymKey(symKey); - PORT_SetError(SEC_ERROR_BAD_DATA); - return NULL; - } - - crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, - &mechanism, genTemplate, count, &symKey->objectID); - - /* Release lock and session */ - if (isToken) { - PK11_RestoreROSession(symKey->slot, session); - } else { - pk11_ExitKeyMonitor(symKey); + keyGenType = PK11_GetKeyGenWithSize(type, keySize); + if (keyGenType == CKM_FAKE_RANDOM) { + PORT_SetError( SEC_ERROR_NO_MODULE ); + return NULL; } - - if (crv != CKR_OK) { - PK11_FreeSymKey(symKey); - PORT_SetError( PK11_MapError(crv) ); - return NULL; + symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType, + param, genTemplate, count, wincx); + if (symKey != NULL) { + symKey->size = keySize; } - return symKey; } @@ -1092,6 +1032,107 @@ PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx); } +PK11SymKey * +PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, + CK_MECHANISM_TYPE keyGenType, + SECItem *param, CK_ATTRIBUTE * attrs, + unsigned int attrsCount, void *wincx) +{ + PK11SymKey *symKey; + CK_SESSION_HANDLE session; + CK_MECHANISM mechanism; + CK_RV crv; + PRBool isToken = CK_FALSE; + CK_ULONG keySize = 0; + unsigned i; + + /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into + isToken. */ + for (i = 0; i < attrsCount; ++i) { + switch (attrs[i].type) { + case CKA_VALUE_LEN: + if (attrs[i].pValue == NULL || + attrs[i].ulValueLen != sizeof(CK_ULONG)) { + PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); + return NULL; + } + keySize = * (CK_ULONG *) attrs[i].pValue; + break; + case CKA_TOKEN: + if (attrs[i].pValue == NULL || + attrs[i].ulValueLen != sizeof(CK_BBOOL)) { + PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); + return NULL; + } + isToken = (*(CK_BBOOL*)attrs[i].pValue) ? PR_TRUE : PR_FALSE; + break; + } + } + + /* find a slot to generate the key into */ + /* Only do slot management if this is not a token key */ + if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { + PK11SlotInfo *bestSlot = PK11_GetBestSlot(type,wincx); + if (bestSlot == NULL) { + PORT_SetError( SEC_ERROR_NO_MODULE ); + return NULL; + } + symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); + PK11_FreeSlot(bestSlot); + } else { + symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); + } + if (symKey == NULL) return NULL; + + symKey->size = keySize; + symKey->origin = PK11_OriginGenerated; + + /* Set the parameters for the key gen if provided */ + mechanism.mechanism = keyGenType; + mechanism.pParameter = NULL; + mechanism.ulParameterLen = 0; + if (param) { + mechanism.pParameter = param->data; + mechanism.ulParameterLen = param->len; + } + + /* Get session and perform locking */ + if (isToken) { + PK11_Authenticate(symKey->slot,PR_TRUE,wincx); + /* Should always be original slot */ + session = PK11_GetRWSession(symKey->slot); + symKey->owner = PR_FALSE; + } else { + session = symKey->session; + if (session != CK_INVALID_SESSION) + pk11_EnterKeyMonitor(symKey); + } + if (session == CK_INVALID_SESSION) { + PK11_FreeSymKey(symKey); + PORT_SetError(SEC_ERROR_BAD_DATA); + return NULL; + } + + crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, + &mechanism, attrs, attrsCount, &symKey->objectID); + + /* Release lock and session */ + if (isToken) { + PK11_RestoreROSession(symKey->slot, session); + } else { + pk11_ExitKeyMonitor(symKey); + } + + if (crv != CKR_OK) { + PK11_FreeSymKey(symKey); + PORT_SetError( PK11_MapError(crv) ); + return NULL; + } + + return symKey; +} + + /* --- */ PK11SymKey * PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx) |