Index: mozilla/security/nss/lib/pk11wrap/pk11skey.c |
=================================================================== |
--- mozilla/security/nss/lib/pk11wrap/pk11skey.c (revision 191424) |
+++ mozilla/security/nss/lib/pk11wrap/pk11skey.c (working copy) |
@@ -1,2668 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* |
- * This file implements the Symkey wrapper and the PKCS context |
- * Interfaces. |
- */ |
- |
-#include "seccomon.h" |
-#include "secmod.h" |
-#include "nssilock.h" |
-#include "secmodi.h" |
-#include "secmodti.h" |
-#include "pkcs11.h" |
-#include "pk11func.h" |
-#include "secitem.h" |
-#include "secoid.h" |
-#include "secerr.h" |
-#include "hasht.h" |
- |
-static void |
-pk11_EnterKeyMonitor(PK11SymKey *symKey) { |
- if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) |
- PK11_EnterSlotMonitor(symKey->slot); |
-} |
- |
-static void |
-pk11_ExitKeyMonitor(PK11SymKey *symKey) { |
- if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) |
- PK11_ExitSlotMonitor(symKey->slot); |
-} |
- |
-/* |
- * pk11_getKeyFromList returns a symKey that has a session (if needSession |
- * was specified), or explicitly does not have a session (if needSession |
- * was not specified). |
- */ |
-static PK11SymKey * |
-pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) { |
- PK11SymKey *symKey = NULL; |
- |
- PZ_Lock(slot->freeListLock); |
- /* own session list are symkeys with sessions that the symkey owns. |
- * 'most' symkeys will own their own session. */ |
- if (needSession) { |
- if (slot->freeSymKeysWithSessionHead) { |
- symKey = slot->freeSymKeysWithSessionHead; |
- slot->freeSymKeysWithSessionHead = symKey->next; |
- slot->keyCount--; |
- } |
- } |
- /* if we don't need a symkey with its own session, or we couldn't find |
- * one on the owner list, get one from the non-owner free list. */ |
- if (!symKey) { |
- if (slot->freeSymKeysHead) { |
- symKey = slot->freeSymKeysHead; |
- slot->freeSymKeysHead = symKey->next; |
- slot->keyCount--; |
- } |
- } |
- PZ_Unlock(slot->freeListLock); |
- if (symKey) { |
- symKey->next = NULL; |
- if (!needSession) { |
- return symKey; |
- } |
- /* if we are getting an owner key, make sure we have a valid session. |
- * session could be invalid if the token has been removed or because |
- * we got it from the non-owner free list */ |
- if ((symKey->series != slot->series) || |
- (symKey->session == CK_INVALID_SESSION)) { |
- symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); |
- } |
- PORT_Assert(symKey->session != CK_INVALID_SESSION); |
- if (symKey->session != CK_INVALID_SESSION) |
- return symKey; |
- PK11_FreeSymKey(symKey); |
- /* if we are here, we need a session, but couldn't get one, it's |
- * unlikely we pk11_GetNewSession will succeed if we call it a second |
- * time. */ |
- return NULL; |
- } |
- |
- symKey = PORT_New(PK11SymKey); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->next = NULL; |
- if (needSession) { |
- symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); |
- PORT_Assert(symKey->session != CK_INVALID_SESSION); |
- if (symKey->session == CK_INVALID_SESSION) { |
- PK11_FreeSymKey(symKey); |
- symKey = NULL; |
- } |
- } else { |
- symKey->session = CK_INVALID_SESSION; |
- } |
- return symKey; |
-} |
- |
-/* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */ |
-void |
-PK11_CleanKeyList(PK11SlotInfo *slot) |
-{ |
- PK11SymKey *symKey = NULL; |
- |
- while (slot->freeSymKeysWithSessionHead) { |
- symKey = slot->freeSymKeysWithSessionHead; |
- slot->freeSymKeysWithSessionHead = symKey->next; |
- pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); |
- PORT_Free(symKey); |
- } |
- while (slot->freeSymKeysHead) { |
- symKey = slot->freeSymKeysHead; |
- slot->freeSymKeysHead = symKey->next; |
- pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); |
- PORT_Free(symKey); |
- } |
- return; |
-} |
- |
-/* |
- * create a symetric key: |
- * Slot is the slot to create the key in. |
- * type is the mechanism type |
- * owner is does this symKey structure own it's object handle (rare |
- * that this is false). |
- * needSession means the returned symKey will return with a valid session |
- * allocated already. |
- */ |
-static PK11SymKey * |
-pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, |
- PRBool owner, PRBool needSession, void *wincx) |
-{ |
- |
- PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession); |
- |
- if (symKey == NULL) { |
- return NULL; |
- } |
- /* if needSession was specified, make sure we have a valid session. |
- * callers which specify needSession as false should do their own |
- * check of the session before returning the symKey */ |
- if (needSession && symKey->session == CK_INVALID_SESSION) { |
- PK11_FreeSymKey(symKey); |
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
- return NULL; |
- } |
- |
- symKey->type = type; |
- symKey->data.type = siBuffer; |
- symKey->data.data = NULL; |
- symKey->data.len = 0; |
- symKey->owner = owner; |
- symKey->objectID = CK_INVALID_HANDLE; |
- symKey->slot = slot; |
- symKey->series = slot->series; |
- symKey->cx = wincx; |
- symKey->size = 0; |
- symKey->refCount = 1; |
- symKey->origin = PK11_OriginNULL; |
- symKey->parent = NULL; |
- symKey->freeFunc = NULL; |
- symKey->userData = NULL; |
- PK11_ReferenceSlot(slot); |
- return symKey; |
-} |
- |
-/* |
- * destroy a symetric key |
- */ |
-void |
-PK11_FreeSymKey(PK11SymKey *symKey) |
-{ |
- PK11SlotInfo *slot; |
- PRBool freeit = PR_TRUE; |
- |
- if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) { |
- PK11SymKey *parent = symKey->parent; |
- |
- symKey->parent = NULL; |
- if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { |
- pk11_EnterKeyMonitor(symKey); |
- (void) PK11_GETTAB(symKey->slot)-> |
- C_DestroyObject(symKey->session, symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- } |
- if (symKey->data.data) { |
- PORT_Memset(symKey->data.data, 0, symKey->data.len); |
- PORT_Free(symKey->data.data); |
- } |
- /* free any existing data */ |
- if (symKey->userData && symKey->freeFunc) { |
- (*symKey->freeFunc)(symKey->userData); |
- } |
- slot = symKey->slot; |
- PZ_Lock(slot->freeListLock); |
- if (slot->keyCount < slot->maxKeyCount) { |
- /* |
- * freeSymkeysWithSessionHead contain a list of reusable |
- * SymKey structures with valid sessions. |
- * sessionOwner must be true. |
- * session must be valid. |
- * freeSymKeysHead contain a list of SymKey structures without |
- * valid session. |
- * session must be CK_INVALID_SESSION. |
- * though sessionOwner is false, callers should not depend on |
- * this fact. |
- */ |
- if (symKey->sessionOwner) { |
- PORT_Assert (symKey->session != CK_INVALID_SESSION); |
- symKey->next = slot->freeSymKeysWithSessionHead; |
- slot->freeSymKeysWithSessionHead = symKey; |
- } else { |
- symKey->session = CK_INVALID_SESSION; |
- symKey->next = slot->freeSymKeysHead; |
- slot->freeSymKeysHead = symKey; |
- } |
- slot->keyCount++; |
- symKey->slot = NULL; |
- freeit = PR_FALSE; |
- } |
- PZ_Unlock(slot->freeListLock); |
- if (freeit) { |
- pk11_CloseSession(symKey->slot, symKey->session, |
- symKey->sessionOwner); |
- PORT_Free(symKey); |
- } |
- PK11_FreeSlot(slot); |
- |
- if (parent) { |
- PK11_FreeSymKey(parent); |
- } |
- } |
-} |
- |
-PK11SymKey * |
-PK11_ReferenceSymKey(PK11SymKey *symKey) |
-{ |
- PR_ATOMIC_INCREMENT(&symKey->refCount); |
- return symKey; |
-} |
- |
-/* |
- * Accessors |
- */ |
-CK_MECHANISM_TYPE |
-PK11_GetMechanism(PK11SymKey *symKey) |
-{ |
- return symKey->type; |
-} |
- |
-/* |
- * return the slot associated with a symetric key |
- */ |
-PK11SlotInfo * |
-PK11_GetSlotFromKey(PK11SymKey *symKey) |
-{ |
- return PK11_ReferenceSlot(symKey->slot); |
-} |
- |
-CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *symKey) |
-{ |
- return PK11_GetKeyType(symKey->type,symKey->size); |
-} |
- |
-PK11SymKey * |
-PK11_GetNextSymKey(PK11SymKey *symKey) |
-{ |
- return symKey ? symKey->next : NULL; |
-} |
- |
-char * |
-PK11_GetSymKeyNickname(PK11SymKey *symKey) |
-{ |
- return PK11_GetObjectNickname(symKey->slot,symKey->objectID); |
-} |
- |
-SECStatus |
-PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname) |
-{ |
- return PK11_SetObjectNickname(symKey->slot,symKey->objectID,nickname); |
-} |
- |
-void * |
-PK11_GetSymKeyUserData(PK11SymKey *symKey) |
-{ |
- return symKey->userData; |
-} |
- |
-void |
-PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData, |
- PK11FreeDataFunc freeFunc) |
-{ |
- /* free any existing data */ |
- if (symKey->userData && symKey->freeFunc) { |
- (*symKey->freeFunc)(symKey->userData); |
- } |
- symKey->userData = userData; |
- symKey->freeFunc = freeFunc; |
- return; |
-} |
- |
-/* |
- * turn key handle into an appropriate key object |
- */ |
-PK11SymKey * |
-PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, |
- CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx) |
-{ |
- PK11SymKey *symKey; |
- PRBool needSession = !(owner && parent); |
- |
- if (keyID == CK_INVALID_HANDLE) { |
- return NULL; |
- } |
- |
- symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->objectID = keyID; |
- symKey->origin = origin; |
- |
- /* adopt the parent's session */ |
- /* This is only used by SSL. What we really want here is a session |
- * structure with a ref count so the session goes away only after all the |
- * keys do. */ |
- if (!needSession) { |
- symKey->sessionOwner = PR_FALSE; |
- symKey->session = parent->session; |
- symKey->parent = PK11_ReferenceSymKey(parent); |
- /* This is the only case where pk11_CreateSymKey does not explicitly |
- * check symKey->session. We need to assert here to make sure. |
- * the session isn't invalid. */ |
- PORT_Assert(parent->session != CK_INVALID_SESSION); |
- if (parent->session == CK_INVALID_SESSION) { |
- PK11_FreeSymKey(symKey); |
- PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
- return NULL; |
- } |
- } |
- |
- return symKey; |
-} |
- |
-/* |
- * turn key handle into an appropriate key object |
- */ |
-PK11SymKey * |
-PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, |
- int series, void *wincx) |
-{ |
- PK11SymKey *symKey = NULL; |
- |
- if (slot->series != series) return NULL; |
- if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL; |
- if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism; |
- |
- symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, |
- slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx); |
- 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. |
- */ |
-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; |
-} |
- |
- |
-/* |
- * figure out if a key is still valid or if it is stale. |
- */ |
-PRBool |
-PK11_VerifyKeyOK(PK11SymKey *key) { |
- if (!PK11_IsPresent(key->slot)) { |
- 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) |
-{ |
- PK11SymKey * symKey; |
- SECStatus rv; |
- |
- symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->size = key->len; |
- |
- PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len); |
- templateCount++; |
- |
- if (SECITEM_CopyItem(NULL,&symKey->data,key) != SECSuccess) { |
- PK11_FreeSymKey(symKey); |
- return NULL; |
- } |
- |
- symKey->origin = origin; |
- |
- /* import the keys */ |
- rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate, |
- templateCount, isToken, &symKey->objectID); |
- if ( rv != SECSuccess) { |
- PK11_FreeSymKey(symKey); |
- return NULL; |
- } |
- |
- return symKey; |
-} |
- |
-/* |
- * 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) |
-{ |
- PK11SymKey * symKey; |
- unsigned int templateCount = 0; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_BBOOL cktrue = CK_TRUE; /* sigh */ |
- CK_ATTRIBUTE keyTemplate[5]; |
- CK_ATTRIBUTE * attrs = keyTemplate; |
- |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); 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); |
- return symKey; |
-} |
- |
- |
-/* |
- * turn key bits into an appropriate key object |
- */ |
-PK11SymKey * |
-PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, |
- PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, |
- CK_FLAGS flags, PRBool isPerm, void *wincx) |
-{ |
- PK11SymKey * symKey; |
- unsigned int templateCount = 0; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_BBOOL cktrue = CK_TRUE; /* sigh */ |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- CK_ATTRIBUTE * attrs = keyTemplate; |
- |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; |
- if (isPerm) { |
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++; |
- /* sigh some tokens think CKA_PRIVATE = false is a reasonable |
- * default for secret keys */ |
- PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++; |
- } |
- attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); |
- if ((operation != CKA_FLAGS_ONLY) && |
- !pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) { |
- 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); |
- if (symKey && isPerm) { |
- symKey->owner = PR_FALSE; |
- } |
- return symKey; |
-} |
- |
- |
-PK11SymKey * |
-PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, |
- void *wincx) |
-{ |
- CK_ATTRIBUTE findTemp[4]; |
- CK_ATTRIBUTE *attrs; |
- CK_BBOOL ckTrue = CK_TRUE; |
- CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; |
- int tsize = 0; |
- CK_OBJECT_HANDLE key_id; |
- |
- attrs = findTemp; |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; |
- PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; |
- if (keyID) { |
- PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len); attrs++; |
- } |
- tsize = attrs - findTemp; |
- PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); |
- |
- key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize); |
- if (key_id == CK_INVALID_HANDLE) { |
- return NULL; |
- } |
- return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, |
- PR_FALSE, wincx); |
-} |
- |
-PK11SymKey * |
-PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) |
-{ |
- CK_ATTRIBUTE findTemp[4]; |
- CK_ATTRIBUTE *attrs; |
- CK_BBOOL ckTrue = CK_TRUE; |
- CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; |
- int tsize = 0; |
- int objCount = 0; |
- CK_OBJECT_HANDLE *key_ids; |
- PK11SymKey *nextKey = NULL; |
- PK11SymKey *topKey = NULL; |
- int i,len; |
- |
- attrs = findTemp; |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; |
- PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; |
- if (nickname) { |
- len = PORT_Strlen(nickname); |
- PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; |
- } |
- tsize = attrs - findTemp; |
- PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); |
- |
- key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount); |
- if (key_ids == NULL) { |
- return NULL; |
- } |
- |
- for (i=0; i < objCount ; i++) { |
- SECItem typeData; |
- CK_KEY_TYPE type = CKK_GENERIC_SECRET; |
- SECStatus rv = PK11_ReadAttribute(slot, key_ids[i], |
- CKA_KEY_TYPE, NULL, &typeData); |
- if (rv == SECSuccess) { |
- if (typeData.len == sizeof(CK_KEY_TYPE)) { |
- type = *(CK_KEY_TYPE *)typeData.data; |
- } |
- PORT_Free(typeData.data); |
- } |
- nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, |
- PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx); |
- if (nextKey) { |
- nextKey->next = topKey; |
- topKey = nextKey; |
- } |
- } |
- PORT_Free(key_ids); |
- return topKey; |
-} |
- |
-void * |
-PK11_GetWindow(PK11SymKey *key) |
-{ |
- return key->cx; |
-} |
- |
- |
-/* |
- * extract a symetric 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 |
-PK11_ExtractKeyValue(PK11SymKey *symKey) |
-{ |
- SECStatus rv; |
- |
- if (symKey->data.data != NULL) { |
- if (symKey->size == 0) { |
- symKey->size = symKey->data.len; |
- } |
- return SECSuccess; |
- } |
- |
- if (symKey->slot == NULL) { |
- PORT_SetError( SEC_ERROR_INVALID_KEY ); |
- return SECFailure; |
- } |
- |
- rv = PK11_ReadAttribute(symKey->slot,symKey->objectID,CKA_VALUE,NULL, |
- &symKey->data); |
- if (rv == SECSuccess) { |
- symKey->size = symKey->data.len; |
- } |
- return rv; |
-} |
- |
-SECStatus |
-PK11_DeleteTokenSymKey(PK11SymKey *symKey) |
-{ |
- if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) { |
- return SECFailure; |
- } |
- PK11_DestroyTokenObject(symKey->slot,symKey->objectID); |
- symKey->objectID = CK_INVALID_HANDLE; |
- return SECSuccess; |
-} |
- |
-SECItem * |
-PK11_GetKeyData(PK11SymKey *symKey) |
-{ |
- return &symKey->data; |
-} |
- |
-/* This symbol is exported for backward compatibility. */ |
-SECItem * |
-__PK11_GetKeyData(PK11SymKey *symKey) |
-{ |
- return PK11_GetKeyData(symKey); |
-} |
- |
- |
-/* |
- * PKCS #11 key Types with predefined length |
- */ |
-unsigned int |
-pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType) |
-{ |
- int length = 0; |
- switch (keyType) { |
- case CKK_DES: length = 8; break; |
- case CKK_DES2: length = 16; break; |
- case CKK_DES3: length = 24; break; |
- case CKK_SKIPJACK: length = 10; break; |
- case CKK_BATON: length = 20; break; |
- case CKK_JUNIPER: length = 20; break; |
- default: break; |
- } |
- return length; |
-} |
- |
-/* return the keylength if possible. '0' if not */ |
-unsigned int |
-PK11_GetKeyLength(PK11SymKey *key) |
-{ |
- CK_KEY_TYPE keyType; |
- |
- if (key->size != 0) return key->size; |
- |
- /* First try to figure out the key length from its type */ |
- keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE); |
- key->size = pk11_GetPredefinedKeyLength(keyType); |
- if ((keyType == CKK_GENERIC_SECRET) && |
- (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) { |
- key->size=48; |
- } |
- |
- if( key->size != 0 ) return key->size; |
- |
- if (key->data.data == NULL) { |
- PK11_ExtractKeyValue(key); |
- } |
- /* key is probably secret. Look up its length */ |
- /* this is new PKCS #11 version 2.0 functionality. */ |
- if (key->size == 0) { |
- CK_ULONG keyLength; |
- |
- keyLength = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_VALUE_LEN); |
- if (keyLength != CK_UNAVAILABLE_INFORMATION) { |
- key->size = (unsigned int)keyLength; |
- } |
- } |
- |
- return key->size; |
-} |
- |
-/* return the strength of a key. This is different from length in that |
- * 1) it returns the size in bits, and 2) it returns only the secret portions |
- * of the key minus any checksums or parity. |
- */ |
-unsigned int |
-PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid) |
-{ |
- int size=0; |
- CK_MECHANISM_TYPE mechanism= CKM_INVALID_MECHANISM; /* RC2 only */ |
- SECItem *param = NULL; /* RC2 only */ |
- CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */ |
- unsigned int effectiveBits = 0; /* RC2 ONLY */ |
- |
- switch (PK11_GetKeyType(key->type,0)) { |
- case CKK_CDMF: |
- return 40; |
- case CKK_DES: |
- return 56; |
- case CKK_DES3: |
- case CKK_DES2: |
- size = PK11_GetKeyLength(key); |
- if (size == 16) { |
- /* double des */ |
- return 112; /* 16*7 */ |
- } |
- return 168; |
- /* |
- * RC2 has is different than other ciphers in that it allows the user |
- * to deprecating keysize while still requiring all the bits for the |
- * original key. The info |
- * on what the effective key strength is in the parameter for the key. |
- * In S/MIME this parameter is stored in the DER encoded algid. In Our |
- * other uses of RC2, effectiveBits == keyBits, so this code functions |
- * correctly without an algid. |
- */ |
- case CKK_RC2: |
- /* if no algid was provided, fall through to default */ |
- if (!algid) { |
- break; |
- } |
- /* verify that the algid is for RC2 */ |
- mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid)); |
- if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) { |
- break; |
- } |
- |
- /* now get effective bits from the algorithm ID. */ |
- param = PK11_ParamFromAlgid(algid); |
- /* if we couldn't get memory just use key length */ |
- if (param == NULL) { |
- break; |
- } |
- |
- rc2_params = (CK_RC2_CBC_PARAMS *) param->data; |
- /* paranoia... shouldn't happen */ |
- PORT_Assert(param->data != NULL); |
- if (param->data == NULL) { |
- SECITEM_FreeItem(param,PR_TRUE); |
- break; |
- } |
- effectiveBits = (unsigned int)rc2_params->ulEffectiveBits; |
- SECITEM_FreeItem(param,PR_TRUE); |
- param = NULL; rc2_params=NULL; /* paranoia */ |
- |
- /* we have effective bits, is and allocated memory is free, now |
- * we need to return the smaller of effective bits and keysize */ |
- size = PK11_GetKeyLength(key); |
- if ((unsigned int)size*8 > effectiveBits) { |
- return effectiveBits; |
- } |
- |
- return size*8; /* the actual key is smaller, the strength can't be |
- * greater than the actual key size */ |
- |
- default: |
- break; |
- } |
- return PK11_GetKeyLength(key) * 8; |
-} |
- |
-/* |
- * The next three utilities are to deal with the fact that a given operation |
- * may be a multi-slot affair. This creates a new key object that is copied |
- * into the new slot. |
- */ |
-PK11SymKey * |
-pk11_CopyToSlotPerm(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, |
- CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, |
- PRBool isPerm, PK11SymKey *symKey) |
-{ |
- SECStatus rv; |
- PK11SymKey *newKey = NULL; |
- |
- /* Extract the raw key data if possible */ |
- if (symKey->data.data == NULL) { |
- rv = PK11_ExtractKeyValue(symKey); |
- /* KEY is sensitive, we're try key exchanging it. */ |
- if (rv != SECSuccess) { |
- return pk11_KeyExchange(slot, type, operation, |
- flags, isPerm, symKey); |
- } |
- } |
- |
- newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin, |
- operation, &symKey->data, flags, isPerm, symKey->cx); |
- if (newKey == NULL) { |
- newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey); |
- } |
- return newKey; |
-} |
- |
-PK11SymKey * |
-pk11_CopyToSlot(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, |
- CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey) |
-{ |
- return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey); |
-} |
- |
-/* |
- * Make sure the slot we are in is the correct slot for the operation |
- * by verifying that it supports all of the specified mechanism types. |
- */ |
-PK11SymKey * |
-pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type, |
- int mechCount, CK_ATTRIBUTE_TYPE operation) |
-{ |
- PK11SlotInfo *slot = symKey->slot; |
- PK11SymKey *newKey = NULL; |
- PRBool needToCopy = PR_FALSE; |
- int i; |
- |
- if (slot == NULL) { |
- needToCopy = PR_TRUE; |
- } else { |
- i = 0; |
- while ((i < mechCount) && (needToCopy == PR_FALSE)) { |
- if (!PK11_DoesMechanism(slot,type[i])) { |
- needToCopy = PR_TRUE; |
- } |
- i++; |
- } |
- } |
- |
- if (needToCopy == PR_TRUE) { |
- slot = PK11_GetBestSlotMultiple(type,mechCount,symKey->cx); |
- if (slot == NULL) { |
- PORT_SetError( SEC_ERROR_NO_MODULE ); |
- return NULL; |
- } |
- newKey = pk11_CopyToSlot(slot, type[0], operation, symKey); |
- PK11_FreeSlot(slot); |
- } |
- return newKey; |
-} |
- |
-/* |
- * Make sure the slot we are in is the correct slot for the operation |
- */ |
-PK11SymKey * |
-pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type, |
- CK_ATTRIBUTE_TYPE operation) |
-{ |
- return pk11_ForceSlotMultiple(symKey, &type, 1, operation); |
-} |
- |
-PK11SymKey * |
-PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, |
- CK_FLAGS flags, PRBool perm, PK11SymKey *symKey) |
-{ |
- if (symKey->slot == slot) { |
- if (perm) { |
- return PK11_ConvertSessionSymKeyToTokenSymKey(symKey,symKey->cx); |
- } else { |
- return PK11_ReferenceSymKey(symKey); |
- } |
- } |
- |
- return pk11_CopyToSlotPerm(slot, symKey->type, |
- operation, flags, perm, symKey); |
-} |
- |
-/* |
- * Use the token to generate a key. |
- * |
- * keySize must be 'zero' for fixed key length algorithms. A nonzero |
- * keySize causes the CKA_VALUE_LEN attribute to be added to the template |
- * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN |
- * attribute for keys with fixed length. The exception is DES2. If you |
- * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN |
- * parameter and use the key size to determine which underlying DES keygen |
- * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). |
- * |
- * keyType must be -1 for most algorithms. Some PBE algorthims cannot |
- * determine the correct key type from the mechanism or the parameters, |
- * so key type must be specified. Other PKCS #11 mechanisms may do so in |
- * the future. Currently there is no need to export this publically. |
- * Keep it private until there is a need in case we need to expand the |
- * keygen parameters again... |
- * |
- * CK_FLAGS flags: key operation flags |
- * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags |
- */ |
-PK11SymKey * |
-pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, |
- SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid, |
- CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx) |
-{ |
- PK11SymKey *symKey; |
- CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS]; |
- CK_ATTRIBUTE *attrs = genTemplate; |
- int count = sizeof(genTemplate)/sizeof(genTemplate[0]); |
- CK_MECHANISM_TYPE keyGenType; |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_BBOOL ckfalse = CK_FALSE; |
- CK_ULONG ck_key_size; /* only used for variable-length keys */ |
- |
- if (pk11_BadAttrFlags(attrFlags)) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- if ((keySize != 0) && (type != CKM_DES3_CBC) && |
- (type !=CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) { |
- ck_key_size = keySize; /* Convert to PK11 type */ |
- |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size)); |
- attrs++; |
- } |
- |
- if (keyType != -1) { |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)); |
- attrs++; |
- } |
- |
- /* Include key id value if provided */ |
- if (keyid) { |
- PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; |
- } |
- |
- attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); |
- attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); |
- |
- count = attrs - genTemplate; |
- PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- keyGenType = PK11_GetKeyGenWithSize(type, keySize); |
- if (keyGenType == CKM_FAKE_RANDOM) { |
- PORT_SetError( SEC_ERROR_NO_MODULE ); |
- return NULL; |
- } |
- symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType, |
- param, genTemplate, count, wincx); |
- if (symKey != NULL) { |
- symKey->size = keySize; |
- } |
- return symKey; |
-} |
- |
-/* |
- * Use the token to generate a key. - Public |
- * |
- * keySize must be 'zero' for fixed key length algorithms. A nonzero |
- * keySize causes the CKA_VALUE_LEN attribute to be added to the template |
- * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN |
- * attribute for keys with fixed length. The exception is DES2. If you |
- * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN |
- * parameter and use the key size to determine which underlying DES keygen |
- * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). |
- * |
- * CK_FLAGS flags: key operation flags |
- * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags |
- */ |
-PK11SymKey * |
-PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, |
- SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, |
- PK11AttrFlags attrFlags, void *wincx) |
-{ |
- return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize, |
- keyid, opFlags, attrFlags, wincx); |
-} |
- |
-/* |
- * Use the token to generate a key. keySize must be 'zero' for fixed key |
- * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute |
- * to be added to the template for the key. PKCS #11 modules fail if you |
- * specify the CKA_VALUE_LEN attribute for keys with fixed length. |
- * NOTE: this means to generate a DES2 key from this interface you must |
- * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying |
- * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work. |
- */ |
-PK11SymKey * |
-PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, |
- int keySize, SECItem *keyid, PRBool isToken, void *wincx) |
-{ |
- PK11SymKey *symKey; |
- PRBool weird = PR_FALSE; /* hack for fortezza */ |
- CK_FLAGS opFlags = CKF_SIGN; |
- PK11AttrFlags attrFlags = 0; |
- |
- if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { |
- weird = PR_TRUE; |
- keySize = 0; |
- } |
- |
- opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; |
- |
- if (isToken) { |
- attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); |
- } |
- |
- symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, |
- -1, keySize, keyid, opFlags, attrFlags, wincx); |
- if (symKey && weird) { |
- PK11_SetFortezzaHack(symKey); |
- } |
- |
- return symKey; |
-} |
- |
-PK11SymKey * |
-PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, |
- int keySize, void *wincx) |
-{ |
- 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) |
-{ |
- return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx); |
-} |
- |
-PK11SymKey* |
-PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) |
-{ |
- PK11SlotInfo* slot = symk->slot; |
- CK_ATTRIBUTE template[1]; |
- CK_ATTRIBUTE *attrs = template; |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_RV crv; |
- CK_OBJECT_HANDLE newKeyID; |
- CK_SESSION_HANDLE rwsession; |
- |
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; |
- |
- PK11_Authenticate(slot, PR_TRUE, wincx); |
- rwsession = PK11_GetRWSession(slot); |
- if (rwsession == CK_INVALID_SESSION) { |
- PORT_SetError(SEC_ERROR_BAD_DATA); |
- return NULL; |
- } |
- crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID, |
- template, 1, &newKeyID); |
- PK11_RestoreROSession(slot, rwsession); |
- |
- if (crv != CKR_OK) { |
- PORT_SetError( PK11_MapError(crv) ); |
- return NULL; |
- } |
- |
- return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin, |
- symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/); |
-} |
- |
-/* |
- * This function does a straight public key wrap (which only RSA can do). |
- * Use PK11_PubGenKey and PK11_WrapSymKey to implement the FORTEZZA and |
- * Diffie-Hellman Ciphers. */ |
-SECStatus |
-PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey, |
- PK11SymKey *symKey, SECItem *wrappedKey) |
-{ |
- PK11SlotInfo *slot; |
- CK_ULONG len = wrappedKey->len; |
- PK11SymKey *newKey = NULL; |
- CK_OBJECT_HANDLE id; |
- CK_MECHANISM mechanism; |
- PRBool owner = PR_TRUE; |
- CK_SESSION_HANDLE session; |
- CK_RV crv; |
- |
- if (symKey == NULL) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return SECFailure; |
- } |
- |
- /* if this slot doesn't support the mechanism, go to a slot that does */ |
- newKey = pk11_ForceSlot(symKey,type,CKA_ENCRYPT); |
- if (newKey != NULL) { |
- symKey = newKey; |
- } |
- |
- if (symKey->slot == NULL) { |
- PORT_SetError( SEC_ERROR_NO_MODULE ); |
- return SECFailure; |
- } |
- |
- slot = symKey->slot; |
- mechanism.mechanism = pk11_mapWrapKeyType(pubKey->keyType); |
- mechanism.pParameter = NULL; |
- mechanism.ulParameterLen = 0; |
- |
- id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); |
- if (id == CK_INVALID_HANDLE) { |
- if (newKey) { |
- PK11_FreeSymKey(newKey); |
- } |
- return SECFailure; /* Error code has been set. */ |
- } |
- |
- session = pk11_GetNewSession(slot,&owner); |
- if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); |
- crv = PK11_GETTAB(slot)->C_WrapKey(session,&mechanism, |
- id,symKey->objectID,wrappedKey->data,&len); |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- if (newKey) { |
- PK11_FreeSymKey(newKey); |
- } |
- |
- if (crv != CKR_OK) { |
- PORT_SetError( PK11_MapError(crv) ); |
- return SECFailure; |
- } |
- wrappedKey->len = len; |
- return SECSuccess; |
-} |
- |
-/* |
- * this little function uses the Encrypt function to wrap a key, just in |
- * case we have problems with the wrap implementation for a token. |
- */ |
-static SECStatus |
-pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type, |
- SECItem *inKey, SECItem *outKey) |
-{ |
- PK11SlotInfo *slot; |
- CK_ULONG len; |
- SECItem *data; |
- CK_MECHANISM mech; |
- PRBool owner = PR_TRUE; |
- CK_SESSION_HANDLE session; |
- CK_RV crv; |
- |
- slot = wrappingKey->slot; |
- /* use NULL IV's for wrapping */ |
- mech.mechanism = type; |
- if (param) { |
- mech.pParameter = param->data; |
- mech.ulParameterLen = param->len; |
- } else { |
- mech.pParameter = NULL; |
- mech.ulParameterLen = 0; |
- } |
- session = pk11_GetNewSession(slot,&owner); |
- if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); |
- crv = PK11_GETTAB(slot)->C_EncryptInit(session,&mech, |
- wrappingKey->objectID); |
- if (crv != CKR_OK) { |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- PORT_SetError( PK11_MapError(crv) ); |
- return SECFailure; |
- } |
- |
- /* keys are almost always aligned, but if we get this far, |
- * we've gone above and beyond anyway... */ |
- data = PK11_BlockData(inKey,PK11_GetBlockSize(type,param)); |
- if (data == NULL) { |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return SECFailure; |
- } |
- len = outKey->len; |
- crv = PK11_GETTAB(slot)->C_Encrypt(session,data->data,data->len, |
- outKey->data, &len); |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- SECITEM_FreeItem(data,PR_TRUE); |
- outKey->len = len; |
- if (crv != CKR_OK) { |
- PORT_SetError( PK11_MapError(crv) ); |
- return SECFailure; |
- } |
- return SECSuccess; |
-} |
- |
-/* |
- * This function does a symetric based wrap. |
- */ |
-SECStatus |
-PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param, |
- PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey) |
-{ |
- PK11SlotInfo *slot; |
- CK_ULONG len = wrappedKey->len; |
- PK11SymKey *newKey = NULL; |
- SECItem *param_save = NULL; |
- CK_MECHANISM mechanism; |
- PRBool owner = PR_TRUE; |
- CK_SESSION_HANDLE session; |
- CK_RV crv; |
- SECStatus rv; |
- |
- /* if this slot doesn't support the mechanism, go to a slot that does */ |
- /* Force symKey and wrappingKey into the same slot */ |
- if ((wrappingKey->slot == NULL) || (symKey->slot != wrappingKey->slot)) { |
- /* first try copying the wrapping Key to the symKey slot */ |
- if (symKey->slot && PK11_DoesMechanism(symKey->slot,type)) { |
- newKey = pk11_CopyToSlot(symKey->slot,type,CKA_WRAP,wrappingKey); |
- } |
- /* Nope, try it the other way */ |
- if (newKey == NULL) { |
- if (wrappingKey->slot) { |
- newKey = pk11_CopyToSlot(wrappingKey->slot, |
- symKey->type, CKA_ENCRYPT, symKey); |
- } |
- /* just not playing... one last thing, can we get symKey's data? |
- * If it's possible, we it should already be in the |
- * symKey->data.data pointer because pk11_CopyToSlot would have |
- * tried to put it there. */ |
- if (newKey == NULL) { |
- /* Can't get symKey's data: Game Over */ |
- if (symKey->data.data == NULL) { |
- PORT_SetError( SEC_ERROR_NO_MODULE ); |
- return SECFailure; |
- } |
- if (param == NULL) { |
- param_save = param = PK11_ParamFromIV(type,NULL); |
- } |
- rv = pk11_HandWrap(wrappingKey, param, type, |
- &symKey->data,wrappedKey); |
- if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); |
- return rv; |
- } |
- /* we successfully moved the sym Key */ |
- symKey = newKey; |
- } else { |
- /* we successfully moved the wrapping Key */ |
- wrappingKey = newKey; |
- } |
- } |
- |
- /* at this point both keys are in the same token */ |
- slot = wrappingKey->slot; |
- mechanism.mechanism = type; |
- /* use NULL IV's for wrapping */ |
- if (param == NULL) { |
- param_save = param = PK11_ParamFromIV(type,NULL); |
- } |
- if (param) { |
- mechanism.pParameter = param->data; |
- mechanism.ulParameterLen = param->len; |
- } else { |
- mechanism.pParameter = NULL; |
- mechanism.ulParameterLen = 0; |
- } |
- |
- len = wrappedKey->len; |
- |
- session = pk11_GetNewSession(slot,&owner); |
- if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); |
- crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism, |
- wrappingKey->objectID, symKey->objectID, |
- wrappedKey->data, &len); |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- rv = SECSuccess; |
- if (crv != CKR_OK) { |
- /* can't wrap it? try hand wrapping it... */ |
- do { |
- if (symKey->data.data == NULL) { |
- rv = PK11_ExtractKeyValue(symKey); |
- if (rv != SECSuccess) break; |
- } |
- rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, |
- wrappedKey); |
- } while (PR_FALSE); |
- } else { |
- wrappedKey->len = len; |
- } |
- if (newKey) PK11_FreeSymKey(newKey); |
- if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); |
- return rv; |
-} |
- |
-/* |
- * This Generates a new key based on a symetricKey |
- */ |
-PK11SymKey * |
-PK11_Derive( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize) |
-{ |
- return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, |
- keySize, NULL, 0, PR_FALSE); |
-} |
- |
- |
-PK11SymKey * |
-PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, |
- SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize, CK_FLAGS flags) |
-{ |
- CK_BBOOL ckTrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- unsigned int templateCount; |
- |
- templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); |
- return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, |
- keySize, keyTemplate, templateCount, PR_FALSE); |
-} |
- |
-PK11SymKey * |
-PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, |
- SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize, CK_FLAGS flags, PRBool isPerm) |
-{ |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- CK_ATTRIBUTE *attrs; |
- unsigned int templateCount = 0; |
- |
- attrs = keyTemplate; |
- if (isPerm) { |
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; |
- } |
- templateCount = attrs - keyTemplate; |
- templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); |
- return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, |
- keySize, keyTemplate, templateCount, isPerm); |
-} |
- |
-PK11SymKey * |
-PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, |
- SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, |
- PRBool isPerm) |
-{ |
- PK11SlotInfo * slot = baseKey->slot; |
- PK11SymKey * symKey; |
- PK11SymKey * newBaseKey = NULL; |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_ULONG valueLen = 0; |
- CK_MECHANISM mechanism; |
- CK_RV crv; |
-#define MAX_ADD_ATTRS 4 |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; |
-#undef MAX_ADD_ATTRS |
- CK_ATTRIBUTE * attrs = keyTemplate; |
- CK_SESSION_HANDLE session; |
- unsigned int templateCount; |
- |
- if (numAttrs > MAX_TEMPL_ATTRS) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- /* first copy caller attributes in. */ |
- for (templateCount = 0; templateCount < numAttrs; ++templateCount) { |
- *attrs++ = *userAttr++; |
- } |
- |
- /* We only add the following attributes to the template if the caller |
- ** didn't already supply them. |
- */ |
- if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); |
- attrs++; |
- } |
- if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { |
- keyType = PK11_GetKeyType(target, keySize); |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); |
- attrs++; |
- } |
- if (keySize > 0 && |
- !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { |
- valueLen = (CK_ULONG)keySize; |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); |
- attrs++; |
- } |
- if ((operation != CKA_FLAGS_ONLY) && |
- !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { |
- PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); attrs++; |
- } |
- |
- templateCount = attrs - keyTemplate; |
- PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- /* move the key to a slot that can do the function */ |
- if (!PK11_DoesMechanism(slot,derive)) { |
- /* get a new base key & slot */ |
- PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx); |
- |
- if (newSlot == NULL) return NULL; |
- |
- newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE, |
- baseKey); |
- PK11_FreeSlot(newSlot); |
- if (newBaseKey == NULL) |
- return NULL; |
- baseKey = newBaseKey; |
- slot = baseKey->slot; |
- } |
- |
- |
- /* get our key Structure */ |
- symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->size = keySize; |
- |
- mechanism.mechanism = derive; |
- if (param) { |
- mechanism.pParameter = param->data; |
- mechanism.ulParameterLen = param->len; |
- } else { |
- mechanism.pParameter = NULL; |
- mechanism.ulParameterLen = 0; |
- } |
- symKey->origin=PK11_OriginDerive; |
- |
- if (isPerm) { |
- session = PK11_GetRWSession(slot); |
- } else { |
- pk11_EnterKeyMonitor(symKey); |
- session = symKey->session; |
- } |
- if (session == CK_INVALID_SESSION) { |
- if (!isPerm) |
- pk11_ExitKeyMonitor(symKey); |
- crv = CKR_SESSION_HANDLE_INVALID; |
- } else { |
- crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, |
- baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); |
- if (isPerm) { |
- PK11_RestoreROSession(slot, session); |
- } else { |
- pk11_ExitKeyMonitor(symKey); |
- } |
- } |
- if (newBaseKey) |
- PK11_FreeSymKey(newBaseKey); |
- if (crv != CKR_OK) { |
- PK11_FreeSymKey(symKey); |
- return NULL; |
- } |
- return symKey; |
-} |
- |
-/* Create a new key by concatenating base and data |
- */ |
-static PK11SymKey *pk11_ConcatenateBaseAndData(PK11SymKey *base, |
- CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation) |
-{ |
- CK_KEY_DERIVATION_STRING_DATA mechParams; |
- SECItem param; |
- |
- if (base == NULL) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- mechParams.pData = data; |
- mechParams.ulLen = dataLen; |
- param.data = (unsigned char *)&mechParams; |
- param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); |
- |
- return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA, |
- ¶m, target, operation, 0); |
-} |
- |
-/* Create a new key by concatenating base and key |
- */ |
-static PK11SymKey *pk11_ConcatenateBaseAndKey(PK11SymKey *base, |
- PK11SymKey *key, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) |
-{ |
- SECItem param; |
- |
- if ((base == NULL) || (key == NULL)) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- param.data = (unsigned char *)&(key->objectID); |
- param.len = sizeof(CK_OBJECT_HANDLE); |
- |
- return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY, |
- ¶m, target, operation, keySize); |
-} |
- |
-/* Create a new key whose value is the hash of tobehashed. |
- * type is the mechanism for the derived key. |
- */ |
-static PK11SymKey *pk11_HashKeyDerivation(PK11SymKey *toBeHashed, |
- CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) |
-{ |
- return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySize); |
-} |
- |
-/* This function implements the ANSI X9.63 key derivation function |
- */ |
-static PK11SymKey *pk11_ANSIX963Derive(PK11SymKey *sharedSecret, |
- CK_EC_KDF_TYPE kdf, SECItem *sharedData, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- CK_ULONG keySize) |
-{ |
- CK_KEY_TYPE keyType; |
- CK_MECHANISM_TYPE hashMechanism, mechanismArray[4]; |
- CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen; |
- CK_ULONG SharedInfoLen; |
- CK_BYTE *buffer = NULL; |
- PK11SymKey *toBeHashed, *hashOutput; |
- PK11SymKey *newSharedSecret = NULL; |
- PK11SymKey *oldIntermediateResult, *intermediateResult = NULL; |
- |
- if (sharedSecret == NULL) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- switch (kdf) { |
- case CKD_SHA1_KDF: |
- HashLen = SHA1_LENGTH; |
- hashMechanism = CKM_SHA1_KEY_DERIVATION; |
- break; |
- case CKD_SHA224_KDF: |
- HashLen = SHA224_LENGTH; |
- hashMechanism = CKM_SHA224_KEY_DERIVATION; |
- break; |
- case CKD_SHA256_KDF: |
- HashLen = SHA256_LENGTH; |
- hashMechanism = CKM_SHA256_KEY_DERIVATION; |
- break; |
- case CKD_SHA384_KDF: |
- HashLen = SHA384_LENGTH; |
- hashMechanism = CKM_SHA384_KEY_DERIVATION; |
- break; |
- case CKD_SHA512_KDF: |
- HashLen = SHA512_LENGTH; |
- hashMechanism = CKM_SHA512_KEY_DERIVATION; |
- break; |
- default: |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- derivedKeySize = keySize; |
- if (derivedKeySize == 0) { |
- keyType = PK11_GetKeyType(target,keySize); |
- derivedKeySize = pk11_GetPredefinedKeyLength(keyType); |
- if (derivedKeySize == 0) { |
- derivedKeySize = HashLen; |
- } |
- } |
- |
- /* Check that key_len isn't too long. The maximum key length could be |
- * greatly increased if the code below did not limit the 4-byte counter |
- * to a maximum value of 255. */ |
- if (derivedKeySize > 254 * HashLen) { |
- PORT_SetError( SEC_ERROR_INVALID_ARGS ); |
- return NULL; |
- } |
- |
- maxCounter = derivedKeySize / HashLen; |
- if (derivedKeySize > maxCounter * HashLen) |
- maxCounter++; |
- |
- if ((sharedData == NULL) || (sharedData->data == NULL)) |
- SharedInfoLen = 0; |
- else |
- SharedInfoLen = sharedData->len; |
- |
- bufferLen = SharedInfoLen + 4; |
- |
- /* Populate buffer with Counter || sharedData |
- * where Counter is 0x00000001. */ |
- buffer = (unsigned char *)PORT_Alloc(bufferLen); |
- if (buffer == NULL) { |
- PORT_SetError(SEC_ERROR_NO_MEMORY); |
- return NULL; |
- } |
- |
- buffer[0] = 0; |
- buffer[1] = 0; |
- buffer[2] = 0; |
- buffer[3] = 1; |
- if (SharedInfoLen > 0) { |
- PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen); |
- } |
- |
- /* Look for a slot that supports the mechanisms needed |
- * to implement the ANSI X9.63 KDF as well as the |
- * target mechanism. |
- */ |
- mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA; |
- mechanismArray[1] = hashMechanism; |
- mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY; |
- mechanismArray[3] = target; |
- |
- newSharedSecret = pk11_ForceSlotMultiple(sharedSecret, |
- mechanismArray, 4, operation); |
- if (newSharedSecret != NULL) { |
- sharedSecret = newSharedSecret; |
- } |
- |
- for(counter=1; counter <= maxCounter; counter++) { |
- /* Concatenate shared_secret and buffer */ |
- toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer, |
- bufferLen, hashMechanism, operation); |
- if (toBeHashed == NULL) { |
- goto loser; |
- } |
- |
- /* Hash value */ |
- if (maxCounter == 1) { |
- /* In this case the length of the key to be derived is |
- * less than or equal to the length of the hash output. |
- * So, the output of the hash operation will be the |
- * dervied key. */ |
- hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, |
- target, operation, keySize); |
- } else { |
- /* In this case, the output of the hash operation will be |
- * concatenated with other data to create the derived key. */ |
- hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, |
- CKM_CONCATENATE_BASE_AND_KEY, operation, 0); |
- } |
- PK11_FreeSymKey(toBeHashed); |
- if (hashOutput == NULL) { |
- goto loser; |
- } |
- |
- /* Append result to intermediate result, if necessary */ |
- oldIntermediateResult = intermediateResult; |
- |
- if (oldIntermediateResult == NULL) { |
- intermediateResult = hashOutput; |
- } else { |
- if (counter == maxCounter) { |
- /* This is the final concatenation, and so the output |
- * will be the derived key. */ |
- intermediateResult = |
- pk11_ConcatenateBaseAndKey(oldIntermediateResult, |
- hashOutput, target, operation, keySize); |
- } else { |
- /* The output of this concatenation will be concatenated |
- * with other data to create the derived key. */ |
- intermediateResult = |
- pk11_ConcatenateBaseAndKey(oldIntermediateResult, |
- hashOutput, CKM_CONCATENATE_BASE_AND_KEY, |
- operation, 0); |
- } |
- |
- PK11_FreeSymKey(hashOutput); |
- PK11_FreeSymKey(oldIntermediateResult); |
- if (intermediateResult == NULL) { |
- goto loser; |
- } |
- } |
- |
- /* Increment counter (assumes maxCounter < 255) */ |
- buffer[3]++; |
- } |
- |
- PORT_ZFree(buffer, bufferLen); |
- if (newSharedSecret != NULL) |
- PK11_FreeSymKey(newSharedSecret); |
- return intermediateResult; |
- |
-loser: |
- if (buffer != NULL) |
- PORT_ZFree(buffer, bufferLen); |
- if (newSharedSecret != NULL) |
- PK11_FreeSymKey(newSharedSecret); |
- if (intermediateResult != NULL) |
- PK11_FreeSymKey(intermediateResult); |
- return NULL; |
-} |
- |
-/* |
- * 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. |
- */ |
-static unsigned char *rb_email = NULL; |
- |
-PK11SymKey * |
-PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, |
- PRBool isSender, SECItem *randomA, SECItem *randomB, |
- CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx) |
-{ |
- PK11SlotInfo *slot = privKey->pkcs11Slot; |
- CK_MECHANISM mechanism; |
- PK11SymKey *symKey; |
- CK_RV crv; |
- |
- |
- if (rb_email == NULL) { |
- rb_email = PORT_ZAlloc(128); |
- if (rb_email == NULL) { |
- return NULL; |
- } |
- rb_email[127] = 1; |
- } |
- |
- /* get our key Structure */ |
- symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->origin = PK11_OriginDerive; |
- |
- switch (privKey->keyType) { |
- case rsaKey: |
- case nullKey: |
- PORT_SetError(SEC_ERROR_BAD_KEY); |
- break; |
- case dsaKey: |
- case keaKey: |
- case fortezzaKey: |
- { |
- CK_KEA_DERIVE_PARAMS param; |
- param.isSender = (CK_BBOOL) isSender; |
- param.ulRandomLen = randomA->len; |
- param.pRandomA = randomA->data; |
- param.pRandomB = rb_email; |
- if (randomB) |
- param.pRandomB = randomB->data; |
- if (pubKey->keyType == fortezzaKey) { |
- param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; |
- param.pPublicData = pubKey->u.fortezza.KEAKey.data; |
- } else { |
- /* assert type == keaKey */ |
- /* XXX change to match key key types */ |
- param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; |
- param.pPublicData = pubKey->u.fortezza.KEAKey.data; |
- } |
- |
- mechanism.mechanism = derive; |
- mechanism.pParameter = ¶m; |
- mechanism.ulParameterLen = sizeof(param); |
- |
- /* get a new symKey structure */ |
- pk11_EnterKeyMonitor(symKey); |
- crv=PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, |
- privKey->pkcs11ID, NULL, 0, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- if (crv == CKR_OK) return symKey; |
- PORT_SetError( PK11_MapError(crv) ); |
- } |
- break; |
- case dhKey: |
- { |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_ULONG key_size = 0; |
- CK_ATTRIBUTE keyTemplate[4]; |
- int templateCount; |
- CK_ATTRIBUTE *attrs = keyTemplate; |
- |
- if (pubKey->keyType != dhKey) { |
- PORT_SetError(SEC_ERROR_BAD_KEY); |
- break; |
- } |
- |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); |
- attrs++; |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
- attrs++; |
- PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); |
- attrs++; |
- templateCount = attrs - keyTemplate; |
- PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- keyType = PK11_GetKeyType(target,keySize); |
- key_size = keySize; |
- symKey->size = keySize; |
- if (key_size == 0) templateCount--; |
- |
- mechanism.mechanism = derive; |
- |
- /* we can undefine these when we define diffie-helman keys */ |
- |
- mechanism.pParameter = pubKey->u.dh.publicValue.data; |
- mechanism.ulParameterLen = pubKey->u.dh.publicValue.len; |
- |
- pk11_EnterKeyMonitor(symKey); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, |
- privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- if (crv == CKR_OK) return symKey; |
- PORT_SetError( PK11_MapError(crv) ); |
- } |
- break; |
- case ecKey: |
- { |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_ULONG key_size = 0; |
- CK_ATTRIBUTE keyTemplate[4]; |
- int templateCount; |
- CK_ATTRIBUTE *attrs = keyTemplate; |
- CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; |
- |
- if (pubKey->keyType != ecKey) { |
- PORT_SetError(SEC_ERROR_BAD_KEY); |
- break; |
- } |
- |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); |
- attrs++; |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); |
- attrs++; |
- PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); |
- attrs++; |
- templateCount = attrs - keyTemplate; |
- PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- keyType = PK11_GetKeyType(target,keySize); |
- key_size = keySize; |
- if (key_size == 0) { |
- if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { |
- templateCount --; |
- } else { |
- /* sigh, some tokens can't figure this out and require |
- * CKA_VALUE_LEN to be set */ |
- key_size = SHA1_LENGTH; |
- } |
- } |
- symKey->size = key_size; |
- |
- mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); |
- mechParams->kdf = CKD_SHA1_KDF; |
- mechParams->ulSharedDataLen = 0; |
- mechParams->pSharedData = NULL; |
- mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; |
- mechParams->pPublicData = pubKey->u.ec.publicValue.data; |
- |
- mechanism.mechanism = derive; |
- mechanism.pParameter = mechParams; |
- mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); |
- |
- pk11_EnterKeyMonitor(symKey); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, |
- &mechanism, privKey->pkcs11ID, keyTemplate, |
- templateCount, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- |
- /* old PKCS #11 spec was ambiguous on what needed to be passed, |
- * try this again with and encoded public key */ |
- if (crv != CKR_OK) { |
- SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
- &pubKey->u.ec.publicValue, |
- SEC_ASN1_GET(SEC_OctetStringTemplate)); |
- if (pubValue == NULL) { |
- PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); |
- break; |
- } |
- mechParams->ulPublicDataLen = pubValue->len; |
- mechParams->pPublicData = pubValue->data; |
- |
- pk11_EnterKeyMonitor(symKey); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, |
- &mechanism, privKey->pkcs11ID, keyTemplate, |
- templateCount, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- |
- SECITEM_FreeItem(pubValue,PR_TRUE); |
- } |
- |
- PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); |
- |
- if (crv == CKR_OK) return symKey; |
- PORT_SetError( PK11_MapError(crv) ); |
- } |
- } |
- |
- PK11_FreeSymKey(symKey); |
- return NULL; |
-} |
- |
-/* Returns the size of the public key, or 0 if there |
- * is an error. */ |
-static CK_ULONG |
-pk11_ECPubKeySize(SECItem *publicValue) |
-{ |
- if (publicValue->data[0] == 0x04) { |
- /* key encoded in uncompressed form */ |
- return((publicValue->len - 1)/2); |
- } else if ( (publicValue->data[0] == 0x02) || |
- (publicValue->data[0] == 0x03)) { |
- /* key encoded in compressed form */ |
- return(publicValue->len - 1); |
- } |
- /* key encoding not recognized */ |
- return(0); |
-} |
- |
-static PK11SymKey * |
-pk11_PubDeriveECKeyWithKDF( |
- SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, |
- PRBool isSender, SECItem *randomA, SECItem *randomB, |
- CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, int keySize, |
- CK_ULONG kdf, SECItem *sharedData, void *wincx) |
-{ |
- PK11SlotInfo *slot = privKey->pkcs11Slot; |
- PK11SymKey *symKey; |
- PK11SymKey *SharedSecret; |
- CK_MECHANISM mechanism; |
- CK_RV crv; |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_ULONG key_size = 0; |
- CK_ATTRIBUTE keyTemplate[4]; |
- int templateCount; |
- CK_ATTRIBUTE *attrs = keyTemplate; |
- CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; |
- |
- if (pubKey->keyType != ecKey) { |
- PORT_SetError(SEC_ERROR_BAD_KEY); |
- return NULL; |
- } |
- if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) && |
- (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) && |
- (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) { |
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
- return NULL; |
- } |
- |
- /* get our key Structure */ |
- symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); |
- if (symKey == NULL) { |
- return NULL; |
- } |
- |
- symKey->origin = PK11_OriginDerive; |
- |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; |
- PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; |
- templateCount = attrs - keyTemplate; |
- PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- keyType = PK11_GetKeyType(target,keySize); |
- key_size = keySize; |
- if (key_size == 0) { |
- if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { |
- templateCount --; |
- } else { |
- /* sigh, some tokens can't figure this out and require |
- * CKA_VALUE_LEN to be set */ |
- switch (kdf) { |
- case CKD_NULL: |
- key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); |
- if (key_size == 0) { |
- PK11_FreeSymKey(symKey); |
- return NULL; |
- } |
- break; |
- case CKD_SHA1_KDF: |
- key_size = SHA1_LENGTH; |
- break; |
- case CKD_SHA224_KDF: |
- key_size = SHA224_LENGTH; |
- break; |
- case CKD_SHA256_KDF: |
- key_size = SHA256_LENGTH; |
- break; |
- case CKD_SHA384_KDF: |
- key_size = SHA384_LENGTH; |
- break; |
- case CKD_SHA512_KDF: |
- key_size = SHA512_LENGTH; |
- break; |
- default: |
- PORT_Assert(!"Invalid CKD"); |
- PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); |
- return NULL; |
- } |
- } |
- } |
- symKey->size = key_size; |
- |
- mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); |
- if (!mechParams) { |
- PK11_FreeSymKey(symKey); |
- return NULL; |
- } |
- mechParams->kdf = kdf; |
- if (sharedData == NULL) { |
- mechParams->ulSharedDataLen = 0; |
- mechParams->pSharedData = NULL; |
- } else { |
- mechParams->ulSharedDataLen = sharedData->len; |
- mechParams->pSharedData = sharedData->data; |
- } |
- mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; |
- mechParams->pPublicData = pubKey->u.ec.publicValue.data; |
- |
- mechanism.mechanism = derive; |
- mechanism.pParameter = mechParams; |
- mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); |
- |
- pk11_EnterKeyMonitor(symKey); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, |
- privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- |
- /* old PKCS #11 spec was ambiguous on what needed to be passed, |
- * try this again with an encoded public key */ |
- if (crv != CKR_OK) { |
- SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, |
- &pubKey->u.ec.publicValue, |
- SEC_ASN1_GET(SEC_OctetStringTemplate)); |
- if (pubValue == NULL) { |
- goto loser; |
- } |
- mechParams->ulPublicDataLen = pubValue->len; |
- mechParams->pPublicData = pubValue->data; |
- |
- pk11_EnterKeyMonitor(symKey); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, |
- &mechanism, privKey->pkcs11ID, keyTemplate, |
- templateCount, &symKey->objectID); |
- pk11_ExitKeyMonitor(symKey); |
- |
- if ((crv != CKR_OK) && (kdf != CKD_NULL)) { |
- /* Some PKCS #11 libraries cannot perform the key derivation |
- * function. So, try calling C_DeriveKey with CKD_NULL and then |
- * performing the KDF separately. |
- */ |
- CK_ULONG derivedKeySize = key_size; |
- |
- keyType = CKK_GENERIC_SECRET; |
- key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); |
- if (key_size == 0) { |
- SECITEM_FreeItem(pubValue,PR_TRUE); |
- goto loser; |
- } |
- SharedSecret = symKey; |
- SharedSecret->size = key_size; |
- |
- mechParams->kdf = CKD_NULL; |
- mechParams->ulSharedDataLen = 0; |
- mechParams->pSharedData = NULL; |
- mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; |
- mechParams->pPublicData = pubKey->u.ec.publicValue.data; |
- |
- pk11_EnterKeyMonitor(SharedSecret); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, |
- &mechanism, privKey->pkcs11ID, keyTemplate, |
- templateCount, &SharedSecret->objectID); |
- pk11_ExitKeyMonitor(SharedSecret); |
- |
- if (crv != CKR_OK) { |
- /* old PKCS #11 spec was ambiguous on what needed to be passed, |
- * try this one final time with an encoded public key */ |
- mechParams->ulPublicDataLen = pubValue->len; |
- mechParams->pPublicData = pubValue->data; |
- |
- pk11_EnterKeyMonitor(SharedSecret); |
- crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, |
- &mechanism, privKey->pkcs11ID, keyTemplate, |
- templateCount, &SharedSecret->objectID); |
- pk11_ExitKeyMonitor(SharedSecret); |
- } |
- |
- /* Perform KDF. */ |
- if (crv == CKR_OK) { |
- symKey = pk11_ANSIX963Derive(SharedSecret, kdf, |
- sharedData, target, operation, |
- derivedKeySize); |
- PK11_FreeSymKey(SharedSecret); |
- if (symKey == NULL) { |
- SECITEM_FreeItem(pubValue,PR_TRUE); |
- PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); |
- return NULL; |
- } |
- } |
- } |
- SECITEM_FreeItem(pubValue,PR_TRUE); |
- } |
- |
-loser: |
- PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); |
- |
- if (crv != CKR_OK) { |
- PK11_FreeSymKey(symKey); |
- symKey = NULL; |
- PORT_SetError( PK11_MapError(crv) ); |
- } |
- return symKey; |
-} |
- |
-PK11SymKey * |
-PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, |
- PRBool isSender, SECItem *randomA, SECItem *randomB, |
- CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, int keySize, |
- CK_ULONG kdf, SECItem *sharedData, void *wincx) |
-{ |
- |
- switch (privKey->keyType) { |
- case rsaKey: |
- case nullKey: |
- case dsaKey: |
- case keaKey: |
- case fortezzaKey: |
- case dhKey: |
- return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, |
- derive, target, operation, keySize, wincx); |
- case ecKey: |
- return pk11_PubDeriveECKeyWithKDF( privKey, pubKey, isSender, |
- randomA, randomB, derive, target, operation, keySize, |
- kdf, sharedData, wincx); |
- default: break; |
- } |
- |
- return NULL; |
-} |
- |
-/* |
- * this little function uses the Decrypt function to unwrap a key, just in |
- * case we are having problem with unwrap. NOTE: The key size may |
- * not be preserved properly for some algorithms! |
- */ |
-static PK11SymKey * |
-pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, |
- CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE *keyTemplate, unsigned int templateCount, |
- int key_size, void * wincx, CK_RV *crvp, PRBool isPerm) |
-{ |
- CK_ULONG len; |
- SECItem outKey; |
- PK11SymKey *symKey; |
- CK_RV crv; |
- PRBool owner = PR_TRUE; |
- CK_SESSION_HANDLE session; |
- |
- /* remove any VALUE_LEN parameters */ |
- if (keyTemplate[templateCount-1].type == CKA_VALUE_LEN) { |
- templateCount--; |
- } |
- |
- /* keys are almost always aligned, but if we get this far, |
- * we've gone above and beyond anyway... */ |
- outKey.data = (unsigned char*)PORT_Alloc(inKey->len); |
- if (outKey.data == NULL) { |
- PORT_SetError( SEC_ERROR_NO_MEMORY ); |
- if (crvp) *crvp = CKR_HOST_MEMORY; |
- return NULL; |
- } |
- len = inKey->len; |
- |
- /* use NULL IV's for wrapping */ |
- session = pk11_GetNewSession(slot,&owner); |
- if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); |
- crv = PK11_GETTAB(slot)->C_DecryptInit(session,mech,wrappingKey); |
- if (crv != CKR_OK) { |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- PORT_Free(outKey.data); |
- PORT_SetError( PK11_MapError(crv) ); |
- if (crvp) *crvp =crv; |
- return NULL; |
- } |
- crv = PK11_GETTAB(slot)->C_Decrypt(session,inKey->data,inKey->len, |
- outKey.data, &len); |
- if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); |
- pk11_CloseSession(slot,session,owner); |
- if (crv != CKR_OK) { |
- PORT_Free(outKey.data); |
- PORT_SetError( PK11_MapError(crv) ); |
- if (crvp) *crvp =crv; |
- return NULL; |
- } |
- |
- 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); |
- } 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); |
- PK11_FreeSlot(slot); |
- } |
- PORT_Free(outKey.data); |
- |
- if (crvp) *crvp = symKey? CKR_OK : CKR_DEVICE_ERROR; |
- return symKey; |
-} |
- |
-/* |
- * The wrap/unwrap function is pretty much the same for private and |
- * public keys. It's just getting the Object ID and slot right. This is |
- * the combined unwrap function. |
- */ |
-static PK11SymKey * |
-pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, |
- CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, |
- void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm) |
-{ |
- PK11SymKey * symKey; |
- SECItem * param_free = NULL; |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; |
- CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; |
- CK_ULONG valueLen = 0; |
- CK_MECHANISM mechanism; |
- CK_SESSION_HANDLE rwsession; |
- CK_RV crv; |
- CK_MECHANISM_INFO mechanism_info; |
-#define MAX_ADD_ATTRS 4 |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; |
-#undef MAX_ADD_ATTRS |
- CK_ATTRIBUTE * attrs = keyTemplate; |
- unsigned int templateCount; |
- |
- if (numAttrs > MAX_TEMPL_ATTRS) { |
- PORT_SetError(SEC_ERROR_INVALID_ARGS); |
- return NULL; |
- } |
- |
- /* first copy caller attributes in. */ |
- for (templateCount = 0; templateCount < numAttrs; ++templateCount) { |
- *attrs++ = *userAttr++; |
- } |
- |
- /* We only add the following attributes to the template if the caller |
- ** didn't already supply them. |
- */ |
- if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { |
- PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); |
- attrs++; |
- } |
- if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { |
- keyType = PK11_GetKeyType(target, keySize); |
- PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); |
- attrs++; |
- } |
- if ((operation != CKA_FLAGS_ONLY) && |
- !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { |
- PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; |
- } |
- |
- /* |
- * must be last in case we need to use this template to import the key |
- */ |
- if (keySize > 0 && |
- !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { |
- valueLen = (CK_ULONG)keySize; |
- PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); |
- attrs++; |
- } |
- |
- templateCount = attrs - keyTemplate; |
- PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); |
- |
- |
- /* find out if we can do wrap directly. Because the RSA case if *very* |
- * common, cache the results for it. */ |
- if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) { |
- mechanism_info.flags = slot->RSAInfoFlags; |
- } else { |
- if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); |
- crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,wrapType, |
- &mechanism_info); |
- if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); |
- if (crv != CKR_OK) { |
- mechanism_info.flags = 0; |
- } |
- if (wrapType == CKM_RSA_PKCS) { |
- slot->RSAInfoFlags = mechanism_info.flags; |
- slot->hasRSAInfo = PR_TRUE; |
- } |
- } |
- |
- /* initialize the mechanism structure */ |
- mechanism.mechanism = wrapType; |
- /* use NULL IV's for wrapping */ |
- if (param == NULL) |
- param = param_free = PK11_ParamFromIV(wrapType,NULL); |
- if (param) { |
- mechanism.pParameter = param->data; |
- mechanism.ulParameterLen = param->len; |
- } else { |
- mechanism.pParameter = NULL; |
- mechanism.ulParameterLen = 0; |
- } |
- |
- if ((mechanism_info.flags & CKF_DECRYPT) |
- && !PK11_DoesMechanism(slot,target)) { |
- symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, |
- target, keyTemplate, templateCount, keySize, |
- wincx, &crv, isPerm); |
- if (symKey) { |
- if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); |
- return symKey; |
- } |
- /* |
- * if the RSA OP simply failed, don't try to unwrap again |
- * with this module. |
- */ |
- if (crv == CKR_DEVICE_ERROR){ |
- if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); |
- return NULL; |
- } |
- /* fall through, maybe they incorrectly set CKF_DECRYPT */ |
- } |
- |
- /* get our key Structure */ |
- symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx); |
- if (symKey == NULL) { |
- if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); |
- return NULL; |
- } |
- |
- symKey->size = keySize; |
- symKey->origin = PK11_OriginUnwrap; |
- |
- if (isPerm) { |
- rwsession = PK11_GetRWSession(slot); |
- } else { |
- pk11_EnterKeyMonitor(symKey); |
- rwsession = symKey->session; |
- } |
- PORT_Assert(rwsession != CK_INVALID_SESSION); |
- if (rwsession == CK_INVALID_SESSION) |
- crv = CKR_SESSION_HANDLE_INVALID; |
- else |
- crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey, |
- wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, |
- &symKey->objectID); |
- if (isPerm) { |
- if (rwsession != CK_INVALID_SESSION) |
- PK11_RestoreROSession(slot, rwsession); |
- } else { |
- pk11_ExitKeyMonitor(symKey); |
- } |
- if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); |
- if (crv != CKR_OK) { |
- PK11_FreeSymKey(symKey); |
- symKey = NULL; |
- if (crv != CKR_DEVICE_ERROR) { |
- /* try hand Unwrapping */ |
- symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, |
- target, keyTemplate, templateCount, |
- keySize, wincx, NULL, isPerm); |
- } |
- } |
- |
- return symKey; |
-} |
- |
-/* use a symetric key to unwrap another symetric key */ |
-PK11SymKey * |
-PK11_UnwrapSymKey( PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, |
- SECItem *param, SECItem *wrappedKey, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize) |
-{ |
- return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, |
- wrapType, param, wrappedKey, target, operation, keySize, |
- wrappingKey->cx, NULL, 0, PR_FALSE); |
-} |
- |
-/* use a symetric key to unwrap another symetric key */ |
-PK11SymKey * |
-PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, |
- SECItem *param, SECItem *wrappedKey, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize, CK_FLAGS flags) |
-{ |
- CK_BBOOL ckTrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- unsigned int templateCount; |
- |
- templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); |
- return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, |
- wrapType, param, wrappedKey, target, operation, keySize, |
- wrappingKey->cx, keyTemplate, templateCount, PR_FALSE); |
-} |
- |
-PK11SymKey * |
-PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, |
- CK_MECHANISM_TYPE wrapType, |
- SECItem *param, SECItem *wrappedKey, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, |
- int keySize, CK_FLAGS flags, PRBool isPerm) |
-{ |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- CK_ATTRIBUTE *attrs; |
- unsigned int templateCount; |
- |
- attrs = keyTemplate; |
- if (isPerm) { |
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; |
- } |
- templateCount = attrs-keyTemplate; |
- templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); |
- |
- return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, |
- wrapType, param, wrappedKey, target, operation, keySize, |
- wrappingKey->cx, keyTemplate, templateCount, isPerm); |
-} |
- |
- |
-/* unwrap a symetric key with a private key. */ |
-PK11SymKey * |
-PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, |
- CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) |
-{ |
- CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); |
- PK11SlotInfo *slot = wrappingKey->pkcs11Slot; |
- |
- if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { |
- PK11_HandlePasswordCheck(slot,wrappingKey->wincx); |
- } |
- |
- return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, |
- wrapType, NULL, wrappedKey, target, operation, keySize, |
- wrappingKey->wincx, NULL, 0, PR_FALSE); |
-} |
- |
-/* unwrap a symetric key with a private key. */ |
-PK11SymKey * |
-PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, |
- SECItem *wrappedKey, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags) |
-{ |
- CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); |
- CK_BBOOL ckTrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- unsigned int templateCount; |
- PK11SlotInfo *slot = wrappingKey->pkcs11Slot; |
- |
- templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); |
- |
- if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { |
- PK11_HandlePasswordCheck(slot,wrappingKey->wincx); |
- } |
- |
- return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, |
- wrapType, NULL, wrappedKey, target, operation, keySize, |
- wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE); |
-} |
- |
-PK11SymKey * |
-PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, |
- SECItem *wrappedKey, CK_MECHANISM_TYPE target, |
- CK_ATTRIBUTE_TYPE operation, int keySize, |
- CK_FLAGS flags, PRBool isPerm) |
-{ |
- CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); |
- CK_BBOOL cktrue = CK_TRUE; |
- CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; |
- CK_ATTRIBUTE *attrs; |
- unsigned int templateCount; |
- PK11SlotInfo *slot = wrappingKey->pkcs11Slot; |
- |
- attrs = keyTemplate; |
- if (isPerm) { |
- PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; |
- } |
- templateCount = attrs-keyTemplate; |
- |
- templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); |
- |
- if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { |
- PK11_HandlePasswordCheck(slot,wrappingKey->wincx); |
- } |
- |
- return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, |
- wrapType, NULL, wrappedKey, target, operation, keySize, |
- wrappingKey->wincx, keyTemplate, templateCount, isPerm); |
-} |
- |
-PK11SymKey* |
-PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech) |
-{ |
- CK_RV crv; |
- CK_ATTRIBUTE setTemplate; |
- CK_BBOOL ckTrue = CK_TRUE; |
- PK11SlotInfo *slot = originalKey->slot; |
- |
- /* first just try to set this key up for signing */ |
- PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue)); |
- pk11_EnterKeyMonitor(originalKey); |
- crv = PK11_GETTAB(slot)-> C_SetAttributeValue(originalKey->session, |
- originalKey->objectID, &setTemplate, 1); |
- pk11_ExitKeyMonitor(originalKey); |
- if (crv == CKR_OK) { |
- return PK11_ReferenceSymKey(originalKey); |
- } |
- |
- /* nope, doesn't like it, use the pk11 copy object command */ |
- return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey); |
-} |
- |
-void |
-PK11_SetFortezzaHack(PK11SymKey *symKey) { |
- symKey->origin = PK11_OriginFortezzaHack; |
-} |
- |
-/* |
- * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4 |
- * working. This function simply gets a valid IV for the keys. |
- */ |
-SECStatus |
-PK11_GenerateFortezzaIV(PK11SymKey *symKey,unsigned char *iv,int len) |
-{ |
- CK_MECHANISM mech_info; |
- CK_ULONG count = 0; |
- CK_RV crv; |
- SECStatus rv = SECFailure; |
- |
- mech_info.mechanism = CKM_SKIPJACK_CBC64; |
- mech_info.pParameter = iv; |
- mech_info.ulParameterLen = len; |
- |
- /* generate the IV for fortezza */ |
- PK11_EnterSlotMonitor(symKey->slot); |
- crv=PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session, |
- &mech_info, symKey->objectID); |
- if (crv == CKR_OK) { |
- PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session, |
- NULL, &count); |
- rv = SECSuccess; |
- } |
- PK11_ExitSlotMonitor(symKey->slot); |
- return rv; |
-} |
- |
-CK_OBJECT_HANDLE |
-PK11_GetSymKeyHandle(PK11SymKey *symKey) |
-{ |
- return symKey->objectID; |
-} |
- |