summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--security/nss/lib/nss/nss.def1
-rw-r--r--security/nss/lib/pk11wrap/pk11pub.h13
-rw-r--r--security/nss/lib/pk11wrap/pk11skey.c179
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)