1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11skey.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2670 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file implements the Symkey wrapper and the PKCS context 1.9 + * Interfaces. 1.10 + */ 1.11 + 1.12 +#include "seccomon.h" 1.13 +#include "secmod.h" 1.14 +#include "nssilock.h" 1.15 +#include "secmodi.h" 1.16 +#include "secmodti.h" 1.17 +#include "pkcs11.h" 1.18 +#include "pk11func.h" 1.19 +#include "secitem.h" 1.20 +#include "secoid.h" 1.21 +#include "secerr.h" 1.22 +#include "hasht.h" 1.23 + 1.24 +static void 1.25 +pk11_EnterKeyMonitor(PK11SymKey *symKey) { 1.26 + if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) 1.27 + PK11_EnterSlotMonitor(symKey->slot); 1.28 +} 1.29 + 1.30 +static void 1.31 +pk11_ExitKeyMonitor(PK11SymKey *symKey) { 1.32 + if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) 1.33 + PK11_ExitSlotMonitor(symKey->slot); 1.34 +} 1.35 + 1.36 +/* 1.37 + * pk11_getKeyFromList returns a symKey that has a session (if needSession 1.38 + * was specified), or explicitly does not have a session (if needSession 1.39 + * was not specified). 1.40 + */ 1.41 +static PK11SymKey * 1.42 +pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) { 1.43 + PK11SymKey *symKey = NULL; 1.44 + 1.45 + PZ_Lock(slot->freeListLock); 1.46 + /* own session list are symkeys with sessions that the symkey owns. 1.47 + * 'most' symkeys will own their own session. */ 1.48 + if (needSession) { 1.49 + if (slot->freeSymKeysWithSessionHead) { 1.50 + symKey = slot->freeSymKeysWithSessionHead; 1.51 + slot->freeSymKeysWithSessionHead = symKey->next; 1.52 + slot->keyCount--; 1.53 + } 1.54 + } 1.55 + /* if we don't need a symkey with its own session, or we couldn't find 1.56 + * one on the owner list, get one from the non-owner free list. */ 1.57 + if (!symKey) { 1.58 + if (slot->freeSymKeysHead) { 1.59 + symKey = slot->freeSymKeysHead; 1.60 + slot->freeSymKeysHead = symKey->next; 1.61 + slot->keyCount--; 1.62 + } 1.63 + } 1.64 + PZ_Unlock(slot->freeListLock); 1.65 + if (symKey) { 1.66 + symKey->next = NULL; 1.67 + if (!needSession) { 1.68 + return symKey; 1.69 + } 1.70 + /* if we are getting an owner key, make sure we have a valid session. 1.71 + * session could be invalid if the token has been removed or because 1.72 + * we got it from the non-owner free list */ 1.73 + if ((symKey->series != slot->series) || 1.74 + (symKey->session == CK_INVALID_SESSION)) { 1.75 + symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); 1.76 + } 1.77 + PORT_Assert(symKey->session != CK_INVALID_SESSION); 1.78 + if (symKey->session != CK_INVALID_SESSION) 1.79 + return symKey; 1.80 + PK11_FreeSymKey(symKey); 1.81 + /* if we are here, we need a session, but couldn't get one, it's 1.82 + * unlikely we pk11_GetNewSession will succeed if we call it a second 1.83 + * time. */ 1.84 + return NULL; 1.85 + } 1.86 + 1.87 + symKey = PORT_New(PK11SymKey); 1.88 + if (symKey == NULL) { 1.89 + return NULL; 1.90 + } 1.91 + 1.92 + symKey->next = NULL; 1.93 + if (needSession) { 1.94 + symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); 1.95 + PORT_Assert(symKey->session != CK_INVALID_SESSION); 1.96 + if (symKey->session == CK_INVALID_SESSION) { 1.97 + PK11_FreeSymKey(symKey); 1.98 + symKey = NULL; 1.99 + } 1.100 + } else { 1.101 + symKey->session = CK_INVALID_SESSION; 1.102 + } 1.103 + return symKey; 1.104 +} 1.105 + 1.106 +/* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */ 1.107 +void 1.108 +PK11_CleanKeyList(PK11SlotInfo *slot) 1.109 +{ 1.110 + PK11SymKey *symKey = NULL; 1.111 + 1.112 + while (slot->freeSymKeysWithSessionHead) { 1.113 + symKey = slot->freeSymKeysWithSessionHead; 1.114 + slot->freeSymKeysWithSessionHead = symKey->next; 1.115 + pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); 1.116 + PORT_Free(symKey); 1.117 + } 1.118 + while (slot->freeSymKeysHead) { 1.119 + symKey = slot->freeSymKeysHead; 1.120 + slot->freeSymKeysHead = symKey->next; 1.121 + pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); 1.122 + PORT_Free(symKey); 1.123 + } 1.124 + return; 1.125 +} 1.126 + 1.127 +/* 1.128 + * create a symetric key: 1.129 + * Slot is the slot to create the key in. 1.130 + * type is the mechanism type 1.131 + * owner is does this symKey structure own it's object handle (rare 1.132 + * that this is false). 1.133 + * needSession means the returned symKey will return with a valid session 1.134 + * allocated already. 1.135 + */ 1.136 +static PK11SymKey * 1.137 +pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.138 + PRBool owner, PRBool needSession, void *wincx) 1.139 +{ 1.140 + 1.141 + PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession); 1.142 + 1.143 + if (symKey == NULL) { 1.144 + return NULL; 1.145 + } 1.146 + /* if needSession was specified, make sure we have a valid session. 1.147 + * callers which specify needSession as false should do their own 1.148 + * check of the session before returning the symKey */ 1.149 + if (needSession && symKey->session == CK_INVALID_SESSION) { 1.150 + PK11_FreeSymKey(symKey); 1.151 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.152 + return NULL; 1.153 + } 1.154 + 1.155 + symKey->type = type; 1.156 + symKey->data.type = siBuffer; 1.157 + symKey->data.data = NULL; 1.158 + symKey->data.len = 0; 1.159 + symKey->owner = owner; 1.160 + symKey->objectID = CK_INVALID_HANDLE; 1.161 + symKey->slot = slot; 1.162 + symKey->series = slot->series; 1.163 + symKey->cx = wincx; 1.164 + symKey->size = 0; 1.165 + symKey->refCount = 1; 1.166 + symKey->origin = PK11_OriginNULL; 1.167 + symKey->parent = NULL; 1.168 + symKey->freeFunc = NULL; 1.169 + symKey->userData = NULL; 1.170 + PK11_ReferenceSlot(slot); 1.171 + return symKey; 1.172 +} 1.173 + 1.174 +/* 1.175 + * destroy a symetric key 1.176 + */ 1.177 +void 1.178 +PK11_FreeSymKey(PK11SymKey *symKey) 1.179 +{ 1.180 + PK11SlotInfo *slot; 1.181 + PRBool freeit = PR_TRUE; 1.182 + 1.183 + if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) { 1.184 + PK11SymKey *parent = symKey->parent; 1.185 + 1.186 + symKey->parent = NULL; 1.187 + if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { 1.188 + pk11_EnterKeyMonitor(symKey); 1.189 + (void) PK11_GETTAB(symKey->slot)-> 1.190 + C_DestroyObject(symKey->session, symKey->objectID); 1.191 + pk11_ExitKeyMonitor(symKey); 1.192 + } 1.193 + if (symKey->data.data) { 1.194 + PORT_Memset(symKey->data.data, 0, symKey->data.len); 1.195 + PORT_Free(symKey->data.data); 1.196 + } 1.197 + /* free any existing data */ 1.198 + if (symKey->userData && symKey->freeFunc) { 1.199 + (*symKey->freeFunc)(symKey->userData); 1.200 + } 1.201 + slot = symKey->slot; 1.202 + PZ_Lock(slot->freeListLock); 1.203 + if (slot->keyCount < slot->maxKeyCount) { 1.204 + /* 1.205 + * freeSymkeysWithSessionHead contain a list of reusable 1.206 + * SymKey structures with valid sessions. 1.207 + * sessionOwner must be true. 1.208 + * session must be valid. 1.209 + * freeSymKeysHead contain a list of SymKey structures without 1.210 + * valid session. 1.211 + * session must be CK_INVALID_SESSION. 1.212 + * though sessionOwner is false, callers should not depend on 1.213 + * this fact. 1.214 + */ 1.215 + if (symKey->sessionOwner) { 1.216 + PORT_Assert (symKey->session != CK_INVALID_SESSION); 1.217 + symKey->next = slot->freeSymKeysWithSessionHead; 1.218 + slot->freeSymKeysWithSessionHead = symKey; 1.219 + } else { 1.220 + symKey->session = CK_INVALID_SESSION; 1.221 + symKey->next = slot->freeSymKeysHead; 1.222 + slot->freeSymKeysHead = symKey; 1.223 + } 1.224 + slot->keyCount++; 1.225 + symKey->slot = NULL; 1.226 + freeit = PR_FALSE; 1.227 + } 1.228 + PZ_Unlock(slot->freeListLock); 1.229 + if (freeit) { 1.230 + pk11_CloseSession(symKey->slot, symKey->session, 1.231 + symKey->sessionOwner); 1.232 + PORT_Free(symKey); 1.233 + } 1.234 + PK11_FreeSlot(slot); 1.235 + 1.236 + if (parent) { 1.237 + PK11_FreeSymKey(parent); 1.238 + } 1.239 + } 1.240 +} 1.241 + 1.242 +PK11SymKey * 1.243 +PK11_ReferenceSymKey(PK11SymKey *symKey) 1.244 +{ 1.245 + PR_ATOMIC_INCREMENT(&symKey->refCount); 1.246 + return symKey; 1.247 +} 1.248 + 1.249 +/* 1.250 + * Accessors 1.251 + */ 1.252 +CK_MECHANISM_TYPE 1.253 +PK11_GetMechanism(PK11SymKey *symKey) 1.254 +{ 1.255 + return symKey->type; 1.256 +} 1.257 + 1.258 +/* 1.259 + * return the slot associated with a symetric key 1.260 + */ 1.261 +PK11SlotInfo * 1.262 +PK11_GetSlotFromKey(PK11SymKey *symKey) 1.263 +{ 1.264 + return PK11_ReferenceSlot(symKey->slot); 1.265 +} 1.266 + 1.267 +CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *symKey) 1.268 +{ 1.269 + return PK11_GetKeyType(symKey->type,symKey->size); 1.270 +} 1.271 + 1.272 +PK11SymKey * 1.273 +PK11_GetNextSymKey(PK11SymKey *symKey) 1.274 +{ 1.275 + return symKey ? symKey->next : NULL; 1.276 +} 1.277 + 1.278 +char * 1.279 +PK11_GetSymKeyNickname(PK11SymKey *symKey) 1.280 +{ 1.281 + return PK11_GetObjectNickname(symKey->slot,symKey->objectID); 1.282 +} 1.283 + 1.284 +SECStatus 1.285 +PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname) 1.286 +{ 1.287 + return PK11_SetObjectNickname(symKey->slot,symKey->objectID,nickname); 1.288 +} 1.289 + 1.290 +void * 1.291 +PK11_GetSymKeyUserData(PK11SymKey *symKey) 1.292 +{ 1.293 + return symKey->userData; 1.294 +} 1.295 + 1.296 +void 1.297 +PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData, 1.298 + PK11FreeDataFunc freeFunc) 1.299 +{ 1.300 + /* free any existing data */ 1.301 + if (symKey->userData && symKey->freeFunc) { 1.302 + (*symKey->freeFunc)(symKey->userData); 1.303 + } 1.304 + symKey->userData = userData; 1.305 + symKey->freeFunc = freeFunc; 1.306 + return; 1.307 +} 1.308 + 1.309 +/* 1.310 + * turn key handle into an appropriate key object 1.311 + */ 1.312 +PK11SymKey * 1.313 +PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, 1.314 + CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx) 1.315 +{ 1.316 + PK11SymKey *symKey; 1.317 + PRBool needSession = !(owner && parent); 1.318 + 1.319 + if (keyID == CK_INVALID_HANDLE) { 1.320 + return NULL; 1.321 + } 1.322 + 1.323 + symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx); 1.324 + if (symKey == NULL) { 1.325 + return NULL; 1.326 + } 1.327 + 1.328 + symKey->objectID = keyID; 1.329 + symKey->origin = origin; 1.330 + 1.331 + /* adopt the parent's session */ 1.332 + /* This is only used by SSL. What we really want here is a session 1.333 + * structure with a ref count so the session goes away only after all the 1.334 + * keys do. */ 1.335 + if (!needSession) { 1.336 + symKey->sessionOwner = PR_FALSE; 1.337 + symKey->session = parent->session; 1.338 + symKey->parent = PK11_ReferenceSymKey(parent); 1.339 + /* This is the only case where pk11_CreateSymKey does not explicitly 1.340 + * check symKey->session. We need to assert here to make sure. 1.341 + * the session isn't invalid. */ 1.342 + PORT_Assert(parent->session != CK_INVALID_SESSION); 1.343 + if (parent->session == CK_INVALID_SESSION) { 1.344 + PK11_FreeSymKey(symKey); 1.345 + PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 1.346 + return NULL; 1.347 + } 1.348 + } 1.349 + 1.350 + return symKey; 1.351 +} 1.352 + 1.353 +/* 1.354 + * turn key handle into an appropriate key object 1.355 + */ 1.356 +PK11SymKey * 1.357 +PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, 1.358 + int series, void *wincx) 1.359 +{ 1.360 + PK11SymKey *symKey = NULL; 1.361 + 1.362 + if (slot->series != series) return NULL; 1.363 + if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL; 1.364 + if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism; 1.365 + 1.366 + symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, 1.367 + slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx); 1.368 + return symKey; 1.369 +} 1.370 + 1.371 +/* 1.372 + * This function is not thread-safe because it sets wrapKey->sessionOwner 1.373 + * without using a lock or atomic routine. It can only be called when 1.374 + * only one thread has a reference to wrapKey. 1.375 + */ 1.376 +void 1.377 +PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey) 1.378 +{ 1.379 + /* save the handle and mechanism for the wrapping key */ 1.380 + /* mark the key and session as not owned by us to they don't get freed 1.381 + * when the key goes way... that lets us reuse the key later */ 1.382 + slot->refKeys[wrap] = wrapKey->objectID; 1.383 + wrapKey->owner = PR_FALSE; 1.384 + wrapKey->sessionOwner = PR_FALSE; 1.385 + slot->wrapMechanism = wrapKey->type; 1.386 +} 1.387 + 1.388 + 1.389 +/* 1.390 + * figure out if a key is still valid or if it is stale. 1.391 + */ 1.392 +PRBool 1.393 +PK11_VerifyKeyOK(PK11SymKey *key) { 1.394 + if (!PK11_IsPresent(key->slot)) { 1.395 + return PR_FALSE; 1.396 + } 1.397 + return (PRBool)(key->series == key->slot->series); 1.398 +} 1.399 + 1.400 +static PK11SymKey * 1.401 +pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.402 + PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate, 1.403 + unsigned int templateCount, SECItem *key, void *wincx) 1.404 +{ 1.405 + PK11SymKey * symKey; 1.406 + SECStatus rv; 1.407 + 1.408 + symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); 1.409 + if (symKey == NULL) { 1.410 + return NULL; 1.411 + } 1.412 + 1.413 + symKey->size = key->len; 1.414 + 1.415 + PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len); 1.416 + templateCount++; 1.417 + 1.418 + if (SECITEM_CopyItem(NULL,&symKey->data,key) != SECSuccess) { 1.419 + PK11_FreeSymKey(symKey); 1.420 + return NULL; 1.421 + } 1.422 + 1.423 + symKey->origin = origin; 1.424 + 1.425 + /* import the keys */ 1.426 + rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate, 1.427 + templateCount, isToken, &symKey->objectID); 1.428 + if ( rv != SECSuccess) { 1.429 + PK11_FreeSymKey(symKey); 1.430 + return NULL; 1.431 + } 1.432 + 1.433 + return symKey; 1.434 +} 1.435 + 1.436 +/* 1.437 + * turn key bits into an appropriate key object 1.438 + */ 1.439 +PK11SymKey * 1.440 +PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.441 + PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,void *wincx) 1.442 +{ 1.443 + PK11SymKey * symKey; 1.444 + unsigned int templateCount = 0; 1.445 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.446 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.447 + CK_BBOOL cktrue = CK_TRUE; /* sigh */ 1.448 + CK_ATTRIBUTE keyTemplate[5]; 1.449 + CK_ATTRIBUTE * attrs = keyTemplate; 1.450 + 1.451 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; 1.452 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; 1.453 + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; 1.454 + templateCount = attrs - keyTemplate; 1.455 + PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.456 + 1.457 + keyType = PK11_GetKeyType(type,key->len); 1.458 + symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE, 1.459 + keyTemplate, templateCount, key, wincx); 1.460 + return symKey; 1.461 +} 1.462 + 1.463 + 1.464 +/* 1.465 + * turn key bits into an appropriate key object 1.466 + */ 1.467 +PK11SymKey * 1.468 +PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.469 + PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, 1.470 + CK_FLAGS flags, PRBool isPerm, void *wincx) 1.471 +{ 1.472 + PK11SymKey * symKey; 1.473 + unsigned int templateCount = 0; 1.474 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.475 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.476 + CK_BBOOL cktrue = CK_TRUE; /* sigh */ 1.477 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.478 + CK_ATTRIBUTE * attrs = keyTemplate; 1.479 + 1.480 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; 1.481 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; 1.482 + if (isPerm) { 1.483 + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++; 1.484 + /* sigh some tokens think CKA_PRIVATE = false is a reasonable 1.485 + * default for secret keys */ 1.486 + PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++; 1.487 + } 1.488 + attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 1.489 + if ((operation != CKA_FLAGS_ONLY) && 1.490 + !pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) { 1.491 + PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); attrs++; 1.492 + } 1.493 + templateCount = attrs - keyTemplate; 1.494 + PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.495 + 1.496 + keyType = PK11_GetKeyType(type,key->len); 1.497 + symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm, 1.498 + keyTemplate, templateCount, key, wincx); 1.499 + if (symKey && isPerm) { 1.500 + symKey->owner = PR_FALSE; 1.501 + } 1.502 + return symKey; 1.503 +} 1.504 + 1.505 + 1.506 +PK11SymKey * 1.507 +PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, 1.508 + void *wincx) 1.509 +{ 1.510 + CK_ATTRIBUTE findTemp[4]; 1.511 + CK_ATTRIBUTE *attrs; 1.512 + CK_BBOOL ckTrue = CK_TRUE; 1.513 + CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; 1.514 + int tsize = 0; 1.515 + CK_OBJECT_HANDLE key_id; 1.516 + 1.517 + attrs = findTemp; 1.518 + PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; 1.519 + PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; 1.520 + if (keyID) { 1.521 + PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len); attrs++; 1.522 + } 1.523 + tsize = attrs - findTemp; 1.524 + PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); 1.525 + 1.526 + key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize); 1.527 + if (key_id == CK_INVALID_HANDLE) { 1.528 + return NULL; 1.529 + } 1.530 + return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, 1.531 + PR_FALSE, wincx); 1.532 +} 1.533 + 1.534 +PK11SymKey * 1.535 +PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) 1.536 +{ 1.537 + CK_ATTRIBUTE findTemp[4]; 1.538 + CK_ATTRIBUTE *attrs; 1.539 + CK_BBOOL ckTrue = CK_TRUE; 1.540 + CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; 1.541 + int tsize = 0; 1.542 + int objCount = 0; 1.543 + CK_OBJECT_HANDLE *key_ids; 1.544 + PK11SymKey *nextKey = NULL; 1.545 + PK11SymKey *topKey = NULL; 1.546 + int i,len; 1.547 + 1.548 + attrs = findTemp; 1.549 + PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; 1.550 + PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; 1.551 + if (nickname) { 1.552 + len = PORT_Strlen(nickname); 1.553 + PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; 1.554 + } 1.555 + tsize = attrs - findTemp; 1.556 + PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); 1.557 + 1.558 + key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount); 1.559 + if (key_ids == NULL) { 1.560 + return NULL; 1.561 + } 1.562 + 1.563 + for (i=0; i < objCount ; i++) { 1.564 + SECItem typeData; 1.565 + CK_KEY_TYPE type = CKK_GENERIC_SECRET; 1.566 + SECStatus rv = PK11_ReadAttribute(slot, key_ids[i], 1.567 + CKA_KEY_TYPE, NULL, &typeData); 1.568 + if (rv == SECSuccess) { 1.569 + if (typeData.len == sizeof(CK_KEY_TYPE)) { 1.570 + type = *(CK_KEY_TYPE *)typeData.data; 1.571 + } 1.572 + PORT_Free(typeData.data); 1.573 + } 1.574 + nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, 1.575 + PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx); 1.576 + if (nextKey) { 1.577 + nextKey->next = topKey; 1.578 + topKey = nextKey; 1.579 + } 1.580 + } 1.581 + PORT_Free(key_ids); 1.582 + return topKey; 1.583 +} 1.584 + 1.585 +void * 1.586 +PK11_GetWindow(PK11SymKey *key) 1.587 +{ 1.588 + return key->cx; 1.589 +} 1.590 + 1.591 + 1.592 +/* 1.593 + * extract a symetric key value. NOTE: if the key is sensitive, we will 1.594 + * not be able to do this operation. This function is used to move 1.595 + * keys from one token to another */ 1.596 +SECStatus 1.597 +PK11_ExtractKeyValue(PK11SymKey *symKey) 1.598 +{ 1.599 + SECStatus rv; 1.600 + 1.601 + if (symKey->data.data != NULL) { 1.602 + if (symKey->size == 0) { 1.603 + symKey->size = symKey->data.len; 1.604 + } 1.605 + return SECSuccess; 1.606 + } 1.607 + 1.608 + if (symKey->slot == NULL) { 1.609 + PORT_SetError( SEC_ERROR_INVALID_KEY ); 1.610 + return SECFailure; 1.611 + } 1.612 + 1.613 + rv = PK11_ReadAttribute(symKey->slot,symKey->objectID,CKA_VALUE,NULL, 1.614 + &symKey->data); 1.615 + if (rv == SECSuccess) { 1.616 + symKey->size = symKey->data.len; 1.617 + } 1.618 + return rv; 1.619 +} 1.620 + 1.621 +SECStatus 1.622 +PK11_DeleteTokenSymKey(PK11SymKey *symKey) 1.623 +{ 1.624 + if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) { 1.625 + return SECFailure; 1.626 + } 1.627 + PK11_DestroyTokenObject(symKey->slot,symKey->objectID); 1.628 + symKey->objectID = CK_INVALID_HANDLE; 1.629 + return SECSuccess; 1.630 +} 1.631 + 1.632 +SECItem * 1.633 +PK11_GetKeyData(PK11SymKey *symKey) 1.634 +{ 1.635 + return &symKey->data; 1.636 +} 1.637 + 1.638 +/* This symbol is exported for backward compatibility. */ 1.639 +SECItem * 1.640 +__PK11_GetKeyData(PK11SymKey *symKey) 1.641 +{ 1.642 + return PK11_GetKeyData(symKey); 1.643 +} 1.644 + 1.645 + 1.646 +/* 1.647 + * PKCS #11 key Types with predefined length 1.648 + */ 1.649 +unsigned int 1.650 +pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType) 1.651 +{ 1.652 + int length = 0; 1.653 + switch (keyType) { 1.654 + case CKK_DES: length = 8; break; 1.655 + case CKK_DES2: length = 16; break; 1.656 + case CKK_DES3: length = 24; break; 1.657 + case CKK_SKIPJACK: length = 10; break; 1.658 + case CKK_BATON: length = 20; break; 1.659 + case CKK_JUNIPER: length = 20; break; 1.660 + default: break; 1.661 + } 1.662 + return length; 1.663 +} 1.664 + 1.665 +/* return the keylength if possible. '0' if not */ 1.666 +unsigned int 1.667 +PK11_GetKeyLength(PK11SymKey *key) 1.668 +{ 1.669 + CK_KEY_TYPE keyType; 1.670 + 1.671 + if (key->size != 0) return key->size; 1.672 + 1.673 + /* First try to figure out the key length from its type */ 1.674 + keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE); 1.675 + key->size = pk11_GetPredefinedKeyLength(keyType); 1.676 + if ((keyType == CKK_GENERIC_SECRET) && 1.677 + (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) { 1.678 + key->size=48; 1.679 + } 1.680 + 1.681 + if( key->size != 0 ) return key->size; 1.682 + 1.683 + if (key->data.data == NULL) { 1.684 + PK11_ExtractKeyValue(key); 1.685 + } 1.686 + /* key is probably secret. Look up its length */ 1.687 + /* this is new PKCS #11 version 2.0 functionality. */ 1.688 + if (key->size == 0) { 1.689 + CK_ULONG keyLength; 1.690 + 1.691 + keyLength = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_VALUE_LEN); 1.692 + if (keyLength != CK_UNAVAILABLE_INFORMATION) { 1.693 + key->size = (unsigned int)keyLength; 1.694 + } 1.695 + } 1.696 + 1.697 + return key->size; 1.698 +} 1.699 + 1.700 +/* return the strength of a key. This is different from length in that 1.701 + * 1) it returns the size in bits, and 2) it returns only the secret portions 1.702 + * of the key minus any checksums or parity. 1.703 + */ 1.704 +unsigned int 1.705 +PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid) 1.706 +{ 1.707 + int size=0; 1.708 + CK_MECHANISM_TYPE mechanism= CKM_INVALID_MECHANISM; /* RC2 only */ 1.709 + SECItem *param = NULL; /* RC2 only */ 1.710 + CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */ 1.711 + unsigned int effectiveBits = 0; /* RC2 ONLY */ 1.712 + 1.713 + switch (PK11_GetKeyType(key->type,0)) { 1.714 + case CKK_CDMF: 1.715 + return 40; 1.716 + case CKK_DES: 1.717 + return 56; 1.718 + case CKK_DES3: 1.719 + case CKK_DES2: 1.720 + size = PK11_GetKeyLength(key); 1.721 + if (size == 16) { 1.722 + /* double des */ 1.723 + return 112; /* 16*7 */ 1.724 + } 1.725 + return 168; 1.726 + /* 1.727 + * RC2 has is different than other ciphers in that it allows the user 1.728 + * to deprecating keysize while still requiring all the bits for the 1.729 + * original key. The info 1.730 + * on what the effective key strength is in the parameter for the key. 1.731 + * In S/MIME this parameter is stored in the DER encoded algid. In Our 1.732 + * other uses of RC2, effectiveBits == keyBits, so this code functions 1.733 + * correctly without an algid. 1.734 + */ 1.735 + case CKK_RC2: 1.736 + /* if no algid was provided, fall through to default */ 1.737 + if (!algid) { 1.738 + break; 1.739 + } 1.740 + /* verify that the algid is for RC2 */ 1.741 + mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid)); 1.742 + if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) { 1.743 + break; 1.744 + } 1.745 + 1.746 + /* now get effective bits from the algorithm ID. */ 1.747 + param = PK11_ParamFromAlgid(algid); 1.748 + /* if we couldn't get memory just use key length */ 1.749 + if (param == NULL) { 1.750 + break; 1.751 + } 1.752 + 1.753 + rc2_params = (CK_RC2_CBC_PARAMS *) param->data; 1.754 + /* paranoia... shouldn't happen */ 1.755 + PORT_Assert(param->data != NULL); 1.756 + if (param->data == NULL) { 1.757 + SECITEM_FreeItem(param,PR_TRUE); 1.758 + break; 1.759 + } 1.760 + effectiveBits = (unsigned int)rc2_params->ulEffectiveBits; 1.761 + SECITEM_FreeItem(param,PR_TRUE); 1.762 + param = NULL; rc2_params=NULL; /* paranoia */ 1.763 + 1.764 + /* we have effective bits, is and allocated memory is free, now 1.765 + * we need to return the smaller of effective bits and keysize */ 1.766 + size = PK11_GetKeyLength(key); 1.767 + if ((unsigned int)size*8 > effectiveBits) { 1.768 + return effectiveBits; 1.769 + } 1.770 + 1.771 + return size*8; /* the actual key is smaller, the strength can't be 1.772 + * greater than the actual key size */ 1.773 + 1.774 + default: 1.775 + break; 1.776 + } 1.777 + return PK11_GetKeyLength(key) * 8; 1.778 +} 1.779 + 1.780 +/* 1.781 + * The next three utilities are to deal with the fact that a given operation 1.782 + * may be a multi-slot affair. This creates a new key object that is copied 1.783 + * into the new slot. 1.784 + */ 1.785 +PK11SymKey * 1.786 +pk11_CopyToSlotPerm(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 1.787 + CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, 1.788 + PRBool isPerm, PK11SymKey *symKey) 1.789 +{ 1.790 + SECStatus rv; 1.791 + PK11SymKey *newKey = NULL; 1.792 + 1.793 + /* Extract the raw key data if possible */ 1.794 + if (symKey->data.data == NULL) { 1.795 + rv = PK11_ExtractKeyValue(symKey); 1.796 + /* KEY is sensitive, we're try key exchanging it. */ 1.797 + if (rv != SECSuccess) { 1.798 + return pk11_KeyExchange(slot, type, operation, 1.799 + flags, isPerm, symKey); 1.800 + } 1.801 + } 1.802 + 1.803 + newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin, 1.804 + operation, &symKey->data, flags, isPerm, symKey->cx); 1.805 + if (newKey == NULL) { 1.806 + newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey); 1.807 + } 1.808 + return newKey; 1.809 +} 1.810 + 1.811 +PK11SymKey * 1.812 +pk11_CopyToSlot(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, 1.813 + CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey) 1.814 +{ 1.815 + return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey); 1.816 +} 1.817 + 1.818 +/* 1.819 + * Make sure the slot we are in is the correct slot for the operation 1.820 + * by verifying that it supports all of the specified mechanism types. 1.821 + */ 1.822 +PK11SymKey * 1.823 +pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type, 1.824 + int mechCount, CK_ATTRIBUTE_TYPE operation) 1.825 +{ 1.826 + PK11SlotInfo *slot = symKey->slot; 1.827 + PK11SymKey *newKey = NULL; 1.828 + PRBool needToCopy = PR_FALSE; 1.829 + int i; 1.830 + 1.831 + if (slot == NULL) { 1.832 + needToCopy = PR_TRUE; 1.833 + } else { 1.834 + i = 0; 1.835 + while ((i < mechCount) && (needToCopy == PR_FALSE)) { 1.836 + if (!PK11_DoesMechanism(slot,type[i])) { 1.837 + needToCopy = PR_TRUE; 1.838 + } 1.839 + i++; 1.840 + } 1.841 + } 1.842 + 1.843 + if (needToCopy == PR_TRUE) { 1.844 + slot = PK11_GetBestSlotMultiple(type,mechCount,symKey->cx); 1.845 + if (slot == NULL) { 1.846 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.847 + return NULL; 1.848 + } 1.849 + newKey = pk11_CopyToSlot(slot, type[0], operation, symKey); 1.850 + PK11_FreeSlot(slot); 1.851 + } 1.852 + return newKey; 1.853 +} 1.854 + 1.855 +/* 1.856 + * Make sure the slot we are in is the correct slot for the operation 1.857 + */ 1.858 +PK11SymKey * 1.859 +pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type, 1.860 + CK_ATTRIBUTE_TYPE operation) 1.861 +{ 1.862 + return pk11_ForceSlotMultiple(symKey, &type, 1, operation); 1.863 +} 1.864 + 1.865 +PK11SymKey * 1.866 +PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, 1.867 + CK_FLAGS flags, PRBool perm, PK11SymKey *symKey) 1.868 +{ 1.869 + if (symKey->slot == slot) { 1.870 + if (perm) { 1.871 + return PK11_ConvertSessionSymKeyToTokenSymKey(symKey,symKey->cx); 1.872 + } else { 1.873 + return PK11_ReferenceSymKey(symKey); 1.874 + } 1.875 + } 1.876 + 1.877 + return pk11_CopyToSlotPerm(slot, symKey->type, 1.878 + operation, flags, perm, symKey); 1.879 +} 1.880 + 1.881 +/* 1.882 + * Use the token to generate a key. 1.883 + * 1.884 + * keySize must be 'zero' for fixed key length algorithms. A nonzero 1.885 + * keySize causes the CKA_VALUE_LEN attribute to be added to the template 1.886 + * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN 1.887 + * attribute for keys with fixed length. The exception is DES2. If you 1.888 + * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN 1.889 + * parameter and use the key size to determine which underlying DES keygen 1.890 + * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). 1.891 + * 1.892 + * keyType must be -1 for most algorithms. Some PBE algorthims cannot 1.893 + * determine the correct key type from the mechanism or the parameters, 1.894 + * so key type must be specified. Other PKCS #11 mechanisms may do so in 1.895 + * the future. Currently there is no need to export this publically. 1.896 + * Keep it private until there is a need in case we need to expand the 1.897 + * keygen parameters again... 1.898 + * 1.899 + * CK_FLAGS flags: key operation flags 1.900 + * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags 1.901 + */ 1.902 +PK11SymKey * 1.903 +pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.904 + SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid, 1.905 + CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx) 1.906 +{ 1.907 + PK11SymKey *symKey; 1.908 + CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS]; 1.909 + CK_ATTRIBUTE *attrs = genTemplate; 1.910 + int count = sizeof(genTemplate)/sizeof(genTemplate[0]); 1.911 + CK_MECHANISM_TYPE keyGenType; 1.912 + CK_BBOOL cktrue = CK_TRUE; 1.913 + CK_BBOOL ckfalse = CK_FALSE; 1.914 + CK_ULONG ck_key_size; /* only used for variable-length keys */ 1.915 + 1.916 + if (pk11_BadAttrFlags(attrFlags)) { 1.917 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.918 + return NULL; 1.919 + } 1.920 + 1.921 + if ((keySize != 0) && (type != CKM_DES3_CBC) && 1.922 + (type !=CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) { 1.923 + ck_key_size = keySize; /* Convert to PK11 type */ 1.924 + 1.925 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size)); 1.926 + attrs++; 1.927 + } 1.928 + 1.929 + if (keyType != -1) { 1.930 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)); 1.931 + attrs++; 1.932 + } 1.933 + 1.934 + /* Include key id value if provided */ 1.935 + if (keyid) { 1.936 + PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; 1.937 + } 1.938 + 1.939 + attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); 1.940 + attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); 1.941 + 1.942 + count = attrs - genTemplate; 1.943 + PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); 1.944 + 1.945 + keyGenType = PK11_GetKeyGenWithSize(type, keySize); 1.946 + if (keyGenType == CKM_FAKE_RANDOM) { 1.947 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.948 + return NULL; 1.949 + } 1.950 + symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType, 1.951 + param, genTemplate, count, wincx); 1.952 + if (symKey != NULL) { 1.953 + symKey->size = keySize; 1.954 + } 1.955 + return symKey; 1.956 +} 1.957 + 1.958 +/* 1.959 + * Use the token to generate a key. - Public 1.960 + * 1.961 + * keySize must be 'zero' for fixed key length algorithms. A nonzero 1.962 + * keySize causes the CKA_VALUE_LEN attribute to be added to the template 1.963 + * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN 1.964 + * attribute for keys with fixed length. The exception is DES2. If you 1.965 + * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN 1.966 + * parameter and use the key size to determine which underlying DES keygen 1.967 + * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). 1.968 + * 1.969 + * CK_FLAGS flags: key operation flags 1.970 + * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags 1.971 + */ 1.972 +PK11SymKey * 1.973 +PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.974 + SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, 1.975 + PK11AttrFlags attrFlags, void *wincx) 1.976 +{ 1.977 + return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize, 1.978 + keyid, opFlags, attrFlags, wincx); 1.979 +} 1.980 + 1.981 +/* 1.982 + * Use the token to generate a key. keySize must be 'zero' for fixed key 1.983 + * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute 1.984 + * to be added to the template for the key. PKCS #11 modules fail if you 1.985 + * specify the CKA_VALUE_LEN attribute for keys with fixed length. 1.986 + * NOTE: this means to generate a DES2 key from this interface you must 1.987 + * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying 1.988 + * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work. 1.989 + */ 1.990 +PK11SymKey * 1.991 +PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, 1.992 + int keySize, SECItem *keyid, PRBool isToken, void *wincx) 1.993 +{ 1.994 + PK11SymKey *symKey; 1.995 + PRBool weird = PR_FALSE; /* hack for fortezza */ 1.996 + CK_FLAGS opFlags = CKF_SIGN; 1.997 + PK11AttrFlags attrFlags = 0; 1.998 + 1.999 + if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { 1.1000 + weird = PR_TRUE; 1.1001 + keySize = 0; 1.1002 + } 1.1003 + 1.1004 + opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; 1.1005 + 1.1006 + if (isToken) { 1.1007 + attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); 1.1008 + } 1.1009 + 1.1010 + symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, 1.1011 + -1, keySize, keyid, opFlags, attrFlags, wincx); 1.1012 + if (symKey && weird) { 1.1013 + PK11_SetFortezzaHack(symKey); 1.1014 + } 1.1015 + 1.1016 + return symKey; 1.1017 +} 1.1018 + 1.1019 +PK11SymKey * 1.1020 +PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, 1.1021 + int keySize, void *wincx) 1.1022 +{ 1.1023 + return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx); 1.1024 +} 1.1025 + 1.1026 +PK11SymKey * 1.1027 +PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1.1028 + CK_MECHANISM_TYPE keyGenType, 1.1029 + SECItem *param, CK_ATTRIBUTE * attrs, 1.1030 + unsigned int attrsCount, void *wincx) 1.1031 +{ 1.1032 + PK11SymKey *symKey; 1.1033 + CK_SESSION_HANDLE session; 1.1034 + CK_MECHANISM mechanism; 1.1035 + CK_RV crv; 1.1036 + PRBool isToken = CK_FALSE; 1.1037 + CK_ULONG keySize = 0; 1.1038 + unsigned i; 1.1039 + 1.1040 + /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into 1.1041 + isToken. */ 1.1042 + for (i = 0; i < attrsCount; ++i) { 1.1043 + switch (attrs[i].type) { 1.1044 + case CKA_VALUE_LEN: 1.1045 + if (attrs[i].pValue == NULL || 1.1046 + attrs[i].ulValueLen != sizeof(CK_ULONG)) { 1.1047 + PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); 1.1048 + return NULL; 1.1049 + } 1.1050 + keySize = * (CK_ULONG *) attrs[i].pValue; 1.1051 + break; 1.1052 + case CKA_TOKEN: 1.1053 + if (attrs[i].pValue == NULL || 1.1054 + attrs[i].ulValueLen != sizeof(CK_BBOOL)) { 1.1055 + PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); 1.1056 + return NULL; 1.1057 + } 1.1058 + isToken = (*(CK_BBOOL*)attrs[i].pValue) ? PR_TRUE : PR_FALSE; 1.1059 + break; 1.1060 + } 1.1061 + } 1.1062 + 1.1063 + /* find a slot to generate the key into */ 1.1064 + /* Only do slot management if this is not a token key */ 1.1065 + if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { 1.1066 + PK11SlotInfo *bestSlot = PK11_GetBestSlot(type,wincx); 1.1067 + if (bestSlot == NULL) { 1.1068 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1069 + return NULL; 1.1070 + } 1.1071 + symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); 1.1072 + PK11_FreeSlot(bestSlot); 1.1073 + } else { 1.1074 + symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); 1.1075 + } 1.1076 + if (symKey == NULL) return NULL; 1.1077 + 1.1078 + symKey->size = keySize; 1.1079 + symKey->origin = PK11_OriginGenerated; 1.1080 + 1.1081 + /* Set the parameters for the key gen if provided */ 1.1082 + mechanism.mechanism = keyGenType; 1.1083 + mechanism.pParameter = NULL; 1.1084 + mechanism.ulParameterLen = 0; 1.1085 + if (param) { 1.1086 + mechanism.pParameter = param->data; 1.1087 + mechanism.ulParameterLen = param->len; 1.1088 + } 1.1089 + 1.1090 + /* Get session and perform locking */ 1.1091 + if (isToken) { 1.1092 + PK11_Authenticate(symKey->slot,PR_TRUE,wincx); 1.1093 + /* Should always be original slot */ 1.1094 + session = PK11_GetRWSession(symKey->slot); 1.1095 + symKey->owner = PR_FALSE; 1.1096 + } else { 1.1097 + session = symKey->session; 1.1098 + if (session != CK_INVALID_SESSION) 1.1099 + pk11_EnterKeyMonitor(symKey); 1.1100 + } 1.1101 + if (session == CK_INVALID_SESSION) { 1.1102 + PK11_FreeSymKey(symKey); 1.1103 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.1104 + return NULL; 1.1105 + } 1.1106 + 1.1107 + crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, 1.1108 + &mechanism, attrs, attrsCount, &symKey->objectID); 1.1109 + 1.1110 + /* Release lock and session */ 1.1111 + if (isToken) { 1.1112 + PK11_RestoreROSession(symKey->slot, session); 1.1113 + } else { 1.1114 + pk11_ExitKeyMonitor(symKey); 1.1115 + } 1.1116 + 1.1117 + if (crv != CKR_OK) { 1.1118 + PK11_FreeSymKey(symKey); 1.1119 + PORT_SetError( PK11_MapError(crv) ); 1.1120 + return NULL; 1.1121 + } 1.1122 + 1.1123 + return symKey; 1.1124 +} 1.1125 + 1.1126 + 1.1127 +/* --- */ 1.1128 +PK11SymKey * 1.1129 +PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx) 1.1130 +{ 1.1131 + return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx); 1.1132 +} 1.1133 + 1.1134 +PK11SymKey* 1.1135 +PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) 1.1136 +{ 1.1137 + PK11SlotInfo* slot = symk->slot; 1.1138 + CK_ATTRIBUTE template[1]; 1.1139 + CK_ATTRIBUTE *attrs = template; 1.1140 + CK_BBOOL cktrue = CK_TRUE; 1.1141 + CK_RV crv; 1.1142 + CK_OBJECT_HANDLE newKeyID; 1.1143 + CK_SESSION_HANDLE rwsession; 1.1144 + 1.1145 + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; 1.1146 + 1.1147 + PK11_Authenticate(slot, PR_TRUE, wincx); 1.1148 + rwsession = PK11_GetRWSession(slot); 1.1149 + if (rwsession == CK_INVALID_SESSION) { 1.1150 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.1151 + return NULL; 1.1152 + } 1.1153 + crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID, 1.1154 + template, 1, &newKeyID); 1.1155 + PK11_RestoreROSession(slot, rwsession); 1.1156 + 1.1157 + if (crv != CKR_OK) { 1.1158 + PORT_SetError( PK11_MapError(crv) ); 1.1159 + return NULL; 1.1160 + } 1.1161 + 1.1162 + return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin, 1.1163 + symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/); 1.1164 +} 1.1165 + 1.1166 +/* 1.1167 + * This function does a straight public key wrap (which only RSA can do). 1.1168 + * Use PK11_PubGenKey and PK11_WrapSymKey to implement the FORTEZZA and 1.1169 + * Diffie-Hellman Ciphers. */ 1.1170 +SECStatus 1.1171 +PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey, 1.1172 + PK11SymKey *symKey, SECItem *wrappedKey) 1.1173 +{ 1.1174 + PK11SlotInfo *slot; 1.1175 + CK_ULONG len = wrappedKey->len; 1.1176 + PK11SymKey *newKey = NULL; 1.1177 + CK_OBJECT_HANDLE id; 1.1178 + CK_MECHANISM mechanism; 1.1179 + PRBool owner = PR_TRUE; 1.1180 + CK_SESSION_HANDLE session; 1.1181 + CK_RV crv; 1.1182 + 1.1183 + if (symKey == NULL) { 1.1184 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1185 + return SECFailure; 1.1186 + } 1.1187 + 1.1188 + /* if this slot doesn't support the mechanism, go to a slot that does */ 1.1189 + newKey = pk11_ForceSlot(symKey,type,CKA_ENCRYPT); 1.1190 + if (newKey != NULL) { 1.1191 + symKey = newKey; 1.1192 + } 1.1193 + 1.1194 + if (symKey->slot == NULL) { 1.1195 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1196 + return SECFailure; 1.1197 + } 1.1198 + 1.1199 + slot = symKey->slot; 1.1200 + mechanism.mechanism = pk11_mapWrapKeyType(pubKey->keyType); 1.1201 + mechanism.pParameter = NULL; 1.1202 + mechanism.ulParameterLen = 0; 1.1203 + 1.1204 + id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); 1.1205 + if (id == CK_INVALID_HANDLE) { 1.1206 + if (newKey) { 1.1207 + PK11_FreeSymKey(newKey); 1.1208 + } 1.1209 + return SECFailure; /* Error code has been set. */ 1.1210 + } 1.1211 + 1.1212 + session = pk11_GetNewSession(slot,&owner); 1.1213 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.1214 + crv = PK11_GETTAB(slot)->C_WrapKey(session,&mechanism, 1.1215 + id,symKey->objectID,wrappedKey->data,&len); 1.1216 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1217 + pk11_CloseSession(slot,session,owner); 1.1218 + if (newKey) { 1.1219 + PK11_FreeSymKey(newKey); 1.1220 + } 1.1221 + 1.1222 + if (crv != CKR_OK) { 1.1223 + PORT_SetError( PK11_MapError(crv) ); 1.1224 + return SECFailure; 1.1225 + } 1.1226 + wrappedKey->len = len; 1.1227 + return SECSuccess; 1.1228 +} 1.1229 + 1.1230 +/* 1.1231 + * this little function uses the Encrypt function to wrap a key, just in 1.1232 + * case we have problems with the wrap implementation for a token. 1.1233 + */ 1.1234 +static SECStatus 1.1235 +pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type, 1.1236 + SECItem *inKey, SECItem *outKey) 1.1237 +{ 1.1238 + PK11SlotInfo *slot; 1.1239 + CK_ULONG len; 1.1240 + SECItem *data; 1.1241 + CK_MECHANISM mech; 1.1242 + PRBool owner = PR_TRUE; 1.1243 + CK_SESSION_HANDLE session; 1.1244 + CK_RV crv; 1.1245 + 1.1246 + slot = wrappingKey->slot; 1.1247 + /* use NULL IV's for wrapping */ 1.1248 + mech.mechanism = type; 1.1249 + if (param) { 1.1250 + mech.pParameter = param->data; 1.1251 + mech.ulParameterLen = param->len; 1.1252 + } else { 1.1253 + mech.pParameter = NULL; 1.1254 + mech.ulParameterLen = 0; 1.1255 + } 1.1256 + session = pk11_GetNewSession(slot,&owner); 1.1257 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.1258 + crv = PK11_GETTAB(slot)->C_EncryptInit(session,&mech, 1.1259 + wrappingKey->objectID); 1.1260 + if (crv != CKR_OK) { 1.1261 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1262 + pk11_CloseSession(slot,session,owner); 1.1263 + PORT_SetError( PK11_MapError(crv) ); 1.1264 + return SECFailure; 1.1265 + } 1.1266 + 1.1267 + /* keys are almost always aligned, but if we get this far, 1.1268 + * we've gone above and beyond anyway... */ 1.1269 + data = PK11_BlockData(inKey,PK11_GetBlockSize(type,param)); 1.1270 + if (data == NULL) { 1.1271 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1272 + pk11_CloseSession(slot,session,owner); 1.1273 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1274 + return SECFailure; 1.1275 + } 1.1276 + len = outKey->len; 1.1277 + crv = PK11_GETTAB(slot)->C_Encrypt(session,data->data,data->len, 1.1278 + outKey->data, &len); 1.1279 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1280 + pk11_CloseSession(slot,session,owner); 1.1281 + SECITEM_FreeItem(data,PR_TRUE); 1.1282 + outKey->len = len; 1.1283 + if (crv != CKR_OK) { 1.1284 + PORT_SetError( PK11_MapError(crv) ); 1.1285 + return SECFailure; 1.1286 + } 1.1287 + return SECSuccess; 1.1288 +} 1.1289 + 1.1290 +/* 1.1291 + * This function does a symetric based wrap. 1.1292 + */ 1.1293 +SECStatus 1.1294 +PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param, 1.1295 + PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey) 1.1296 +{ 1.1297 + PK11SlotInfo *slot; 1.1298 + CK_ULONG len = wrappedKey->len; 1.1299 + PK11SymKey *newKey = NULL; 1.1300 + SECItem *param_save = NULL; 1.1301 + CK_MECHANISM mechanism; 1.1302 + PRBool owner = PR_TRUE; 1.1303 + CK_SESSION_HANDLE session; 1.1304 + CK_RV crv; 1.1305 + SECStatus rv; 1.1306 + 1.1307 + /* if this slot doesn't support the mechanism, go to a slot that does */ 1.1308 + /* Force symKey and wrappingKey into the same slot */ 1.1309 + if ((wrappingKey->slot == NULL) || (symKey->slot != wrappingKey->slot)) { 1.1310 + /* first try copying the wrapping Key to the symKey slot */ 1.1311 + if (symKey->slot && PK11_DoesMechanism(symKey->slot,type)) { 1.1312 + newKey = pk11_CopyToSlot(symKey->slot,type,CKA_WRAP,wrappingKey); 1.1313 + } 1.1314 + /* Nope, try it the other way */ 1.1315 + if (newKey == NULL) { 1.1316 + if (wrappingKey->slot) { 1.1317 + newKey = pk11_CopyToSlot(wrappingKey->slot, 1.1318 + symKey->type, CKA_ENCRYPT, symKey); 1.1319 + } 1.1320 + /* just not playing... one last thing, can we get symKey's data? 1.1321 + * If it's possible, we it should already be in the 1.1322 + * symKey->data.data pointer because pk11_CopyToSlot would have 1.1323 + * tried to put it there. */ 1.1324 + if (newKey == NULL) { 1.1325 + /* Can't get symKey's data: Game Over */ 1.1326 + if (symKey->data.data == NULL) { 1.1327 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1328 + return SECFailure; 1.1329 + } 1.1330 + if (param == NULL) { 1.1331 + param_save = param = PK11_ParamFromIV(type,NULL); 1.1332 + } 1.1333 + rv = pk11_HandWrap(wrappingKey, param, type, 1.1334 + &symKey->data,wrappedKey); 1.1335 + if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); 1.1336 + return rv; 1.1337 + } 1.1338 + /* we successfully moved the sym Key */ 1.1339 + symKey = newKey; 1.1340 + } else { 1.1341 + /* we successfully moved the wrapping Key */ 1.1342 + wrappingKey = newKey; 1.1343 + } 1.1344 + } 1.1345 + 1.1346 + /* at this point both keys are in the same token */ 1.1347 + slot = wrappingKey->slot; 1.1348 + mechanism.mechanism = type; 1.1349 + /* use NULL IV's for wrapping */ 1.1350 + if (param == NULL) { 1.1351 + param_save = param = PK11_ParamFromIV(type,NULL); 1.1352 + } 1.1353 + if (param) { 1.1354 + mechanism.pParameter = param->data; 1.1355 + mechanism.ulParameterLen = param->len; 1.1356 + } else { 1.1357 + mechanism.pParameter = NULL; 1.1358 + mechanism.ulParameterLen = 0; 1.1359 + } 1.1360 + 1.1361 + len = wrappedKey->len; 1.1362 + 1.1363 + session = pk11_GetNewSession(slot,&owner); 1.1364 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.1365 + crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism, 1.1366 + wrappingKey->objectID, symKey->objectID, 1.1367 + wrappedKey->data, &len); 1.1368 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1369 + pk11_CloseSession(slot,session,owner); 1.1370 + rv = SECSuccess; 1.1371 + if (crv != CKR_OK) { 1.1372 + /* can't wrap it? try hand wrapping it... */ 1.1373 + do { 1.1374 + if (symKey->data.data == NULL) { 1.1375 + rv = PK11_ExtractKeyValue(symKey); 1.1376 + if (rv != SECSuccess) break; 1.1377 + } 1.1378 + rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, 1.1379 + wrappedKey); 1.1380 + } while (PR_FALSE); 1.1381 + } else { 1.1382 + wrappedKey->len = len; 1.1383 + } 1.1384 + if (newKey) PK11_FreeSymKey(newKey); 1.1385 + if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); 1.1386 + return rv; 1.1387 +} 1.1388 + 1.1389 +/* 1.1390 + * This Generates a new key based on a symetricKey 1.1391 + */ 1.1392 +PK11SymKey * 1.1393 +PK11_Derive( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param, 1.1394 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.1395 + int keySize) 1.1396 +{ 1.1397 + return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1.1398 + keySize, NULL, 0, PR_FALSE); 1.1399 +} 1.1400 + 1.1401 + 1.1402 +PK11SymKey * 1.1403 +PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1.1404 + SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.1405 + int keySize, CK_FLAGS flags) 1.1406 +{ 1.1407 + CK_BBOOL ckTrue = CK_TRUE; 1.1408 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.1409 + unsigned int templateCount; 1.1410 + 1.1411 + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 1.1412 + return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1.1413 + keySize, keyTemplate, templateCount, PR_FALSE); 1.1414 +} 1.1415 + 1.1416 +PK11SymKey * 1.1417 +PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1.1418 + SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.1419 + int keySize, CK_FLAGS flags, PRBool isPerm) 1.1420 +{ 1.1421 + CK_BBOOL cktrue = CK_TRUE; 1.1422 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.1423 + CK_ATTRIBUTE *attrs; 1.1424 + unsigned int templateCount = 0; 1.1425 + 1.1426 + attrs = keyTemplate; 1.1427 + if (isPerm) { 1.1428 + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.1429 + } 1.1430 + templateCount = attrs - keyTemplate; 1.1431 + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 1.1432 + return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1.1433 + keySize, keyTemplate, templateCount, isPerm); 1.1434 +} 1.1435 + 1.1436 +PK11SymKey * 1.1437 +PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1.1438 + SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.1439 + int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, 1.1440 + PRBool isPerm) 1.1441 +{ 1.1442 + PK11SlotInfo * slot = baseKey->slot; 1.1443 + PK11SymKey * symKey; 1.1444 + PK11SymKey * newBaseKey = NULL; 1.1445 + CK_BBOOL cktrue = CK_TRUE; 1.1446 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.1447 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.1448 + CK_ULONG valueLen = 0; 1.1449 + CK_MECHANISM mechanism; 1.1450 + CK_RV crv; 1.1451 +#define MAX_ADD_ATTRS 4 1.1452 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; 1.1453 +#undef MAX_ADD_ATTRS 1.1454 + CK_ATTRIBUTE * attrs = keyTemplate; 1.1455 + CK_SESSION_HANDLE session; 1.1456 + unsigned int templateCount; 1.1457 + 1.1458 + if (numAttrs > MAX_TEMPL_ATTRS) { 1.1459 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.1460 + return NULL; 1.1461 + } 1.1462 + 1.1463 + /* first copy caller attributes in. */ 1.1464 + for (templateCount = 0; templateCount < numAttrs; ++templateCount) { 1.1465 + *attrs++ = *userAttr++; 1.1466 + } 1.1467 + 1.1468 + /* We only add the following attributes to the template if the caller 1.1469 + ** didn't already supply them. 1.1470 + */ 1.1471 + if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { 1.1472 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); 1.1473 + attrs++; 1.1474 + } 1.1475 + if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { 1.1476 + keyType = PK11_GetKeyType(target, keySize); 1.1477 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); 1.1478 + attrs++; 1.1479 + } 1.1480 + if (keySize > 0 && 1.1481 + !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { 1.1482 + valueLen = (CK_ULONG)keySize; 1.1483 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); 1.1484 + attrs++; 1.1485 + } 1.1486 + if ((operation != CKA_FLAGS_ONLY) && 1.1487 + !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { 1.1488 + PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); attrs++; 1.1489 + } 1.1490 + 1.1491 + templateCount = attrs - keyTemplate; 1.1492 + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.1493 + 1.1494 + /* move the key to a slot that can do the function */ 1.1495 + if (!PK11_DoesMechanism(slot,derive)) { 1.1496 + /* get a new base key & slot */ 1.1497 + PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx); 1.1498 + 1.1499 + if (newSlot == NULL) return NULL; 1.1500 + 1.1501 + newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE, 1.1502 + baseKey); 1.1503 + PK11_FreeSlot(newSlot); 1.1504 + if (newBaseKey == NULL) 1.1505 + return NULL; 1.1506 + baseKey = newBaseKey; 1.1507 + slot = baseKey->slot; 1.1508 + } 1.1509 + 1.1510 + 1.1511 + /* get our key Structure */ 1.1512 + symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx); 1.1513 + if (symKey == NULL) { 1.1514 + return NULL; 1.1515 + } 1.1516 + 1.1517 + symKey->size = keySize; 1.1518 + 1.1519 + mechanism.mechanism = derive; 1.1520 + if (param) { 1.1521 + mechanism.pParameter = param->data; 1.1522 + mechanism.ulParameterLen = param->len; 1.1523 + } else { 1.1524 + mechanism.pParameter = NULL; 1.1525 + mechanism.ulParameterLen = 0; 1.1526 + } 1.1527 + symKey->origin=PK11_OriginDerive; 1.1528 + 1.1529 + if (isPerm) { 1.1530 + session = PK11_GetRWSession(slot); 1.1531 + } else { 1.1532 + pk11_EnterKeyMonitor(symKey); 1.1533 + session = symKey->session; 1.1534 + } 1.1535 + if (session == CK_INVALID_SESSION) { 1.1536 + if (!isPerm) 1.1537 + pk11_ExitKeyMonitor(symKey); 1.1538 + crv = CKR_SESSION_HANDLE_INVALID; 1.1539 + } else { 1.1540 + crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, 1.1541 + baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); 1.1542 + if (isPerm) { 1.1543 + PK11_RestoreROSession(slot, session); 1.1544 + } else { 1.1545 + pk11_ExitKeyMonitor(symKey); 1.1546 + } 1.1547 + } 1.1548 + if (newBaseKey) 1.1549 + PK11_FreeSymKey(newBaseKey); 1.1550 + if (crv != CKR_OK) { 1.1551 + PK11_FreeSymKey(symKey); 1.1552 + return NULL; 1.1553 + } 1.1554 + return symKey; 1.1555 +} 1.1556 + 1.1557 +/* Create a new key by concatenating base and data 1.1558 + */ 1.1559 +static PK11SymKey *pk11_ConcatenateBaseAndData(PK11SymKey *base, 1.1560 + CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target, 1.1561 + CK_ATTRIBUTE_TYPE operation) 1.1562 +{ 1.1563 + CK_KEY_DERIVATION_STRING_DATA mechParams; 1.1564 + SECItem param; 1.1565 + 1.1566 + if (base == NULL) { 1.1567 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1568 + return NULL; 1.1569 + } 1.1570 + 1.1571 + mechParams.pData = data; 1.1572 + mechParams.ulLen = dataLen; 1.1573 + param.data = (unsigned char *)&mechParams; 1.1574 + param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); 1.1575 + 1.1576 + return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA, 1.1577 + ¶m, target, operation, 0); 1.1578 +} 1.1579 + 1.1580 +/* Create a new key by concatenating base and key 1.1581 + */ 1.1582 +static PK11SymKey *pk11_ConcatenateBaseAndKey(PK11SymKey *base, 1.1583 + PK11SymKey *key, CK_MECHANISM_TYPE target, 1.1584 + CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) 1.1585 +{ 1.1586 + SECItem param; 1.1587 + 1.1588 + if ((base == NULL) || (key == NULL)) { 1.1589 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1590 + return NULL; 1.1591 + } 1.1592 + 1.1593 + param.data = (unsigned char *)&(key->objectID); 1.1594 + param.len = sizeof(CK_OBJECT_HANDLE); 1.1595 + 1.1596 + return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY, 1.1597 + ¶m, target, operation, keySize); 1.1598 +} 1.1599 + 1.1600 +/* Create a new key whose value is the hash of tobehashed. 1.1601 + * type is the mechanism for the derived key. 1.1602 + */ 1.1603 +static PK11SymKey *pk11_HashKeyDerivation(PK11SymKey *toBeHashed, 1.1604 + CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target, 1.1605 + CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) 1.1606 +{ 1.1607 + return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySize); 1.1608 +} 1.1609 + 1.1610 +/* This function implements the ANSI X9.63 key derivation function 1.1611 + */ 1.1612 +static PK11SymKey *pk11_ANSIX963Derive(PK11SymKey *sharedSecret, 1.1613 + CK_EC_KDF_TYPE kdf, SECItem *sharedData, 1.1614 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.1615 + CK_ULONG keySize) 1.1616 +{ 1.1617 + CK_KEY_TYPE keyType; 1.1618 + CK_MECHANISM_TYPE hashMechanism, mechanismArray[4]; 1.1619 + CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen; 1.1620 + CK_ULONG SharedInfoLen; 1.1621 + CK_BYTE *buffer = NULL; 1.1622 + PK11SymKey *toBeHashed, *hashOutput; 1.1623 + PK11SymKey *newSharedSecret = NULL; 1.1624 + PK11SymKey *oldIntermediateResult, *intermediateResult = NULL; 1.1625 + 1.1626 + if (sharedSecret == NULL) { 1.1627 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1628 + return NULL; 1.1629 + } 1.1630 + 1.1631 + switch (kdf) { 1.1632 + case CKD_SHA1_KDF: 1.1633 + HashLen = SHA1_LENGTH; 1.1634 + hashMechanism = CKM_SHA1_KEY_DERIVATION; 1.1635 + break; 1.1636 + case CKD_SHA224_KDF: 1.1637 + HashLen = SHA224_LENGTH; 1.1638 + hashMechanism = CKM_SHA224_KEY_DERIVATION; 1.1639 + break; 1.1640 + case CKD_SHA256_KDF: 1.1641 + HashLen = SHA256_LENGTH; 1.1642 + hashMechanism = CKM_SHA256_KEY_DERIVATION; 1.1643 + break; 1.1644 + case CKD_SHA384_KDF: 1.1645 + HashLen = SHA384_LENGTH; 1.1646 + hashMechanism = CKM_SHA384_KEY_DERIVATION; 1.1647 + break; 1.1648 + case CKD_SHA512_KDF: 1.1649 + HashLen = SHA512_LENGTH; 1.1650 + hashMechanism = CKM_SHA512_KEY_DERIVATION; 1.1651 + break; 1.1652 + default: 1.1653 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1654 + return NULL; 1.1655 + } 1.1656 + 1.1657 + derivedKeySize = keySize; 1.1658 + if (derivedKeySize == 0) { 1.1659 + keyType = PK11_GetKeyType(target,keySize); 1.1660 + derivedKeySize = pk11_GetPredefinedKeyLength(keyType); 1.1661 + if (derivedKeySize == 0) { 1.1662 + derivedKeySize = HashLen; 1.1663 + } 1.1664 + } 1.1665 + 1.1666 + /* Check that key_len isn't too long. The maximum key length could be 1.1667 + * greatly increased if the code below did not limit the 4-byte counter 1.1668 + * to a maximum value of 255. */ 1.1669 + if (derivedKeySize > 254 * HashLen) { 1.1670 + PORT_SetError( SEC_ERROR_INVALID_ARGS ); 1.1671 + return NULL; 1.1672 + } 1.1673 + 1.1674 + maxCounter = derivedKeySize / HashLen; 1.1675 + if (derivedKeySize > maxCounter * HashLen) 1.1676 + maxCounter++; 1.1677 + 1.1678 + if ((sharedData == NULL) || (sharedData->data == NULL)) 1.1679 + SharedInfoLen = 0; 1.1680 + else 1.1681 + SharedInfoLen = sharedData->len; 1.1682 + 1.1683 + bufferLen = SharedInfoLen + 4; 1.1684 + 1.1685 + /* Populate buffer with Counter || sharedData 1.1686 + * where Counter is 0x00000001. */ 1.1687 + buffer = (unsigned char *)PORT_Alloc(bufferLen); 1.1688 + if (buffer == NULL) { 1.1689 + PORT_SetError(SEC_ERROR_NO_MEMORY); 1.1690 + return NULL; 1.1691 + } 1.1692 + 1.1693 + buffer[0] = 0; 1.1694 + buffer[1] = 0; 1.1695 + buffer[2] = 0; 1.1696 + buffer[3] = 1; 1.1697 + if (SharedInfoLen > 0) { 1.1698 + PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen); 1.1699 + } 1.1700 + 1.1701 + /* Look for a slot that supports the mechanisms needed 1.1702 + * to implement the ANSI X9.63 KDF as well as the 1.1703 + * target mechanism. 1.1704 + */ 1.1705 + mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA; 1.1706 + mechanismArray[1] = hashMechanism; 1.1707 + mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY; 1.1708 + mechanismArray[3] = target; 1.1709 + 1.1710 + newSharedSecret = pk11_ForceSlotMultiple(sharedSecret, 1.1711 + mechanismArray, 4, operation); 1.1712 + if (newSharedSecret != NULL) { 1.1713 + sharedSecret = newSharedSecret; 1.1714 + } 1.1715 + 1.1716 + for(counter=1; counter <= maxCounter; counter++) { 1.1717 + /* Concatenate shared_secret and buffer */ 1.1718 + toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer, 1.1719 + bufferLen, hashMechanism, operation); 1.1720 + if (toBeHashed == NULL) { 1.1721 + goto loser; 1.1722 + } 1.1723 + 1.1724 + /* Hash value */ 1.1725 + if (maxCounter == 1) { 1.1726 + /* In this case the length of the key to be derived is 1.1727 + * less than or equal to the length of the hash output. 1.1728 + * So, the output of the hash operation will be the 1.1729 + * dervied key. */ 1.1730 + hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, 1.1731 + target, operation, keySize); 1.1732 + } else { 1.1733 + /* In this case, the output of the hash operation will be 1.1734 + * concatenated with other data to create the derived key. */ 1.1735 + hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, 1.1736 + CKM_CONCATENATE_BASE_AND_KEY, operation, 0); 1.1737 + } 1.1738 + PK11_FreeSymKey(toBeHashed); 1.1739 + if (hashOutput == NULL) { 1.1740 + goto loser; 1.1741 + } 1.1742 + 1.1743 + /* Append result to intermediate result, if necessary */ 1.1744 + oldIntermediateResult = intermediateResult; 1.1745 + 1.1746 + if (oldIntermediateResult == NULL) { 1.1747 + intermediateResult = hashOutput; 1.1748 + } else { 1.1749 + if (counter == maxCounter) { 1.1750 + /* This is the final concatenation, and so the output 1.1751 + * will be the derived key. */ 1.1752 + intermediateResult = 1.1753 + pk11_ConcatenateBaseAndKey(oldIntermediateResult, 1.1754 + hashOutput, target, operation, keySize); 1.1755 + } else { 1.1756 + /* The output of this concatenation will be concatenated 1.1757 + * with other data to create the derived key. */ 1.1758 + intermediateResult = 1.1759 + pk11_ConcatenateBaseAndKey(oldIntermediateResult, 1.1760 + hashOutput, CKM_CONCATENATE_BASE_AND_KEY, 1.1761 + operation, 0); 1.1762 + } 1.1763 + 1.1764 + PK11_FreeSymKey(hashOutput); 1.1765 + PK11_FreeSymKey(oldIntermediateResult); 1.1766 + if (intermediateResult == NULL) { 1.1767 + goto loser; 1.1768 + } 1.1769 + } 1.1770 + 1.1771 + /* Increment counter (assumes maxCounter < 255) */ 1.1772 + buffer[3]++; 1.1773 + } 1.1774 + 1.1775 + PORT_ZFree(buffer, bufferLen); 1.1776 + if (newSharedSecret != NULL) 1.1777 + PK11_FreeSymKey(newSharedSecret); 1.1778 + return intermediateResult; 1.1779 + 1.1780 +loser: 1.1781 + if (buffer != NULL) 1.1782 + PORT_ZFree(buffer, bufferLen); 1.1783 + if (newSharedSecret != NULL) 1.1784 + PK11_FreeSymKey(newSharedSecret); 1.1785 + if (intermediateResult != NULL) 1.1786 + PK11_FreeSymKey(intermediateResult); 1.1787 + return NULL; 1.1788 +} 1.1789 + 1.1790 +/* 1.1791 + * This Generates a wrapping key based on a privateKey, publicKey, and two 1.1792 + * random numbers. For Mail usage RandomB should be NULL. In the Sender's 1.1793 + * case RandomA is generate, outherwize it is passed. 1.1794 + */ 1.1795 +static unsigned char *rb_email = NULL; 1.1796 + 1.1797 +PK11SymKey * 1.1798 +PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 1.1799 + PRBool isSender, SECItem *randomA, SECItem *randomB, 1.1800 + CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 1.1801 + CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx) 1.1802 +{ 1.1803 + PK11SlotInfo *slot = privKey->pkcs11Slot; 1.1804 + CK_MECHANISM mechanism; 1.1805 + PK11SymKey *symKey; 1.1806 + CK_RV crv; 1.1807 + 1.1808 + 1.1809 + if (rb_email == NULL) { 1.1810 + rb_email = PORT_ZAlloc(128); 1.1811 + if (rb_email == NULL) { 1.1812 + return NULL; 1.1813 + } 1.1814 + rb_email[127] = 1; 1.1815 + } 1.1816 + 1.1817 + /* get our key Structure */ 1.1818 + symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); 1.1819 + if (symKey == NULL) { 1.1820 + return NULL; 1.1821 + } 1.1822 + 1.1823 + symKey->origin = PK11_OriginDerive; 1.1824 + 1.1825 + switch (privKey->keyType) { 1.1826 + case rsaKey: 1.1827 + case nullKey: 1.1828 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1829 + break; 1.1830 + case dsaKey: 1.1831 + case keaKey: 1.1832 + case fortezzaKey: 1.1833 + { 1.1834 + CK_KEA_DERIVE_PARAMS param; 1.1835 + param.isSender = (CK_BBOOL) isSender; 1.1836 + param.ulRandomLen = randomA->len; 1.1837 + param.pRandomA = randomA->data; 1.1838 + param.pRandomB = rb_email; 1.1839 + if (randomB) 1.1840 + param.pRandomB = randomB->data; 1.1841 + if (pubKey->keyType == fortezzaKey) { 1.1842 + param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; 1.1843 + param.pPublicData = pubKey->u.fortezza.KEAKey.data; 1.1844 + } else { 1.1845 + /* assert type == keaKey */ 1.1846 + /* XXX change to match key key types */ 1.1847 + param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; 1.1848 + param.pPublicData = pubKey->u.fortezza.KEAKey.data; 1.1849 + } 1.1850 + 1.1851 + mechanism.mechanism = derive; 1.1852 + mechanism.pParameter = ¶m; 1.1853 + mechanism.ulParameterLen = sizeof(param); 1.1854 + 1.1855 + /* get a new symKey structure */ 1.1856 + pk11_EnterKeyMonitor(symKey); 1.1857 + crv=PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 1.1858 + privKey->pkcs11ID, NULL, 0, &symKey->objectID); 1.1859 + pk11_ExitKeyMonitor(symKey); 1.1860 + if (crv == CKR_OK) return symKey; 1.1861 + PORT_SetError( PK11_MapError(crv) ); 1.1862 + } 1.1863 + break; 1.1864 + case dhKey: 1.1865 + { 1.1866 + CK_BBOOL cktrue = CK_TRUE; 1.1867 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.1868 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.1869 + CK_ULONG key_size = 0; 1.1870 + CK_ATTRIBUTE keyTemplate[4]; 1.1871 + int templateCount; 1.1872 + CK_ATTRIBUTE *attrs = keyTemplate; 1.1873 + 1.1874 + if (pubKey->keyType != dhKey) { 1.1875 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1876 + break; 1.1877 + } 1.1878 + 1.1879 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 1.1880 + attrs++; 1.1881 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 1.1882 + attrs++; 1.1883 + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; 1.1884 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 1.1885 + attrs++; 1.1886 + templateCount = attrs - keyTemplate; 1.1887 + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.1888 + 1.1889 + keyType = PK11_GetKeyType(target,keySize); 1.1890 + key_size = keySize; 1.1891 + symKey->size = keySize; 1.1892 + if (key_size == 0) templateCount--; 1.1893 + 1.1894 + mechanism.mechanism = derive; 1.1895 + 1.1896 + /* we can undefine these when we define diffie-helman keys */ 1.1897 + 1.1898 + mechanism.pParameter = pubKey->u.dh.publicValue.data; 1.1899 + mechanism.ulParameterLen = pubKey->u.dh.publicValue.len; 1.1900 + 1.1901 + pk11_EnterKeyMonitor(symKey); 1.1902 + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 1.1903 + privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); 1.1904 + pk11_ExitKeyMonitor(symKey); 1.1905 + if (crv == CKR_OK) return symKey; 1.1906 + PORT_SetError( PK11_MapError(crv) ); 1.1907 + } 1.1908 + break; 1.1909 + case ecKey: 1.1910 + { 1.1911 + CK_BBOOL cktrue = CK_TRUE; 1.1912 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.1913 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.1914 + CK_ULONG key_size = 0; 1.1915 + CK_ATTRIBUTE keyTemplate[4]; 1.1916 + int templateCount; 1.1917 + CK_ATTRIBUTE *attrs = keyTemplate; 1.1918 + CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; 1.1919 + 1.1920 + if (pubKey->keyType != ecKey) { 1.1921 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1922 + break; 1.1923 + } 1.1924 + 1.1925 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 1.1926 + attrs++; 1.1927 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 1.1928 + attrs++; 1.1929 + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; 1.1930 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 1.1931 + attrs++; 1.1932 + templateCount = attrs - keyTemplate; 1.1933 + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.1934 + 1.1935 + keyType = PK11_GetKeyType(target,keySize); 1.1936 + key_size = keySize; 1.1937 + if (key_size == 0) { 1.1938 + if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { 1.1939 + templateCount --; 1.1940 + } else { 1.1941 + /* sigh, some tokens can't figure this out and require 1.1942 + * CKA_VALUE_LEN to be set */ 1.1943 + key_size = SHA1_LENGTH; 1.1944 + } 1.1945 + } 1.1946 + symKey->size = key_size; 1.1947 + 1.1948 + mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); 1.1949 + mechParams->kdf = CKD_SHA1_KDF; 1.1950 + mechParams->ulSharedDataLen = 0; 1.1951 + mechParams->pSharedData = NULL; 1.1952 + mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 1.1953 + mechParams->pPublicData = pubKey->u.ec.publicValue.data; 1.1954 + 1.1955 + mechanism.mechanism = derive; 1.1956 + mechanism.pParameter = mechParams; 1.1957 + mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); 1.1958 + 1.1959 + pk11_EnterKeyMonitor(symKey); 1.1960 + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 1.1961 + &mechanism, privKey->pkcs11ID, keyTemplate, 1.1962 + templateCount, &symKey->objectID); 1.1963 + pk11_ExitKeyMonitor(symKey); 1.1964 + 1.1965 + /* old PKCS #11 spec was ambiguous on what needed to be passed, 1.1966 + * try this again with and encoded public key */ 1.1967 + if (crv != CKR_OK) { 1.1968 + SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 1.1969 + &pubKey->u.ec.publicValue, 1.1970 + SEC_ASN1_GET(SEC_OctetStringTemplate)); 1.1971 + if (pubValue == NULL) { 1.1972 + PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 1.1973 + break; 1.1974 + } 1.1975 + mechParams->ulPublicDataLen = pubValue->len; 1.1976 + mechParams->pPublicData = pubValue->data; 1.1977 + 1.1978 + pk11_EnterKeyMonitor(symKey); 1.1979 + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 1.1980 + &mechanism, privKey->pkcs11ID, keyTemplate, 1.1981 + templateCount, &symKey->objectID); 1.1982 + pk11_ExitKeyMonitor(symKey); 1.1983 + 1.1984 + SECITEM_FreeItem(pubValue,PR_TRUE); 1.1985 + } 1.1986 + 1.1987 + PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 1.1988 + 1.1989 + if (crv == CKR_OK) return symKey; 1.1990 + PORT_SetError( PK11_MapError(crv) ); 1.1991 + } 1.1992 + } 1.1993 + 1.1994 + PK11_FreeSymKey(symKey); 1.1995 + return NULL; 1.1996 +} 1.1997 + 1.1998 +/* Returns the size of the public key, or 0 if there 1.1999 + * is an error. */ 1.2000 +static CK_ULONG 1.2001 +pk11_ECPubKeySize(SECItem *publicValue) 1.2002 +{ 1.2003 + if (publicValue->data[0] == 0x04) { 1.2004 + /* key encoded in uncompressed form */ 1.2005 + return((publicValue->len - 1)/2); 1.2006 + } else if ( (publicValue->data[0] == 0x02) || 1.2007 + (publicValue->data[0] == 0x03)) { 1.2008 + /* key encoded in compressed form */ 1.2009 + return(publicValue->len - 1); 1.2010 + } 1.2011 + /* key encoding not recognized */ 1.2012 + return(0); 1.2013 +} 1.2014 + 1.2015 +static PK11SymKey * 1.2016 +pk11_PubDeriveECKeyWithKDF( 1.2017 + SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 1.2018 + PRBool isSender, SECItem *randomA, SECItem *randomB, 1.2019 + CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 1.2020 + CK_ATTRIBUTE_TYPE operation, int keySize, 1.2021 + CK_ULONG kdf, SECItem *sharedData, void *wincx) 1.2022 +{ 1.2023 + PK11SlotInfo *slot = privKey->pkcs11Slot; 1.2024 + PK11SymKey *symKey; 1.2025 + PK11SymKey *SharedSecret; 1.2026 + CK_MECHANISM mechanism; 1.2027 + CK_RV crv; 1.2028 + CK_BBOOL cktrue = CK_TRUE; 1.2029 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.2030 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.2031 + CK_ULONG key_size = 0; 1.2032 + CK_ATTRIBUTE keyTemplate[4]; 1.2033 + int templateCount; 1.2034 + CK_ATTRIBUTE *attrs = keyTemplate; 1.2035 + CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; 1.2036 + 1.2037 + if (pubKey->keyType != ecKey) { 1.2038 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.2039 + return NULL; 1.2040 + } 1.2041 + if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) && 1.2042 + (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) && 1.2043 + (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) { 1.2044 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.2045 + return NULL; 1.2046 + } 1.2047 + 1.2048 + /* get our key Structure */ 1.2049 + symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); 1.2050 + if (symKey == NULL) { 1.2051 + return NULL; 1.2052 + } 1.2053 + 1.2054 + symKey->origin = PK11_OriginDerive; 1.2055 + 1.2056 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; 1.2057 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; 1.2058 + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; 1.2059 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; 1.2060 + templateCount = attrs - keyTemplate; 1.2061 + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.2062 + 1.2063 + keyType = PK11_GetKeyType(target,keySize); 1.2064 + key_size = keySize; 1.2065 + if (key_size == 0) { 1.2066 + if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { 1.2067 + templateCount --; 1.2068 + } else { 1.2069 + /* sigh, some tokens can't figure this out and require 1.2070 + * CKA_VALUE_LEN to be set */ 1.2071 + switch (kdf) { 1.2072 + case CKD_NULL: 1.2073 + key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); 1.2074 + if (key_size == 0) { 1.2075 + PK11_FreeSymKey(symKey); 1.2076 + return NULL; 1.2077 + } 1.2078 + break; 1.2079 + case CKD_SHA1_KDF: 1.2080 + key_size = SHA1_LENGTH; 1.2081 + break; 1.2082 + case CKD_SHA224_KDF: 1.2083 + key_size = SHA224_LENGTH; 1.2084 + break; 1.2085 + case CKD_SHA256_KDF: 1.2086 + key_size = SHA256_LENGTH; 1.2087 + break; 1.2088 + case CKD_SHA384_KDF: 1.2089 + key_size = SHA384_LENGTH; 1.2090 + break; 1.2091 + case CKD_SHA512_KDF: 1.2092 + key_size = SHA512_LENGTH; 1.2093 + break; 1.2094 + default: 1.2095 + PORT_Assert(!"Invalid CKD"); 1.2096 + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 1.2097 + return NULL; 1.2098 + } 1.2099 + } 1.2100 + } 1.2101 + symKey->size = key_size; 1.2102 + 1.2103 + mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); 1.2104 + if (!mechParams) { 1.2105 + PK11_FreeSymKey(symKey); 1.2106 + return NULL; 1.2107 + } 1.2108 + mechParams->kdf = kdf; 1.2109 + if (sharedData == NULL) { 1.2110 + mechParams->ulSharedDataLen = 0; 1.2111 + mechParams->pSharedData = NULL; 1.2112 + } else { 1.2113 + mechParams->ulSharedDataLen = sharedData->len; 1.2114 + mechParams->pSharedData = sharedData->data; 1.2115 + } 1.2116 + mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 1.2117 + mechParams->pPublicData = pubKey->u.ec.publicValue.data; 1.2118 + 1.2119 + mechanism.mechanism = derive; 1.2120 + mechanism.pParameter = mechParams; 1.2121 + mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); 1.2122 + 1.2123 + pk11_EnterKeyMonitor(symKey); 1.2124 + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 1.2125 + privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); 1.2126 + pk11_ExitKeyMonitor(symKey); 1.2127 + 1.2128 + /* old PKCS #11 spec was ambiguous on what needed to be passed, 1.2129 + * try this again with an encoded public key */ 1.2130 + if (crv != CKR_OK) { 1.2131 + SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 1.2132 + &pubKey->u.ec.publicValue, 1.2133 + SEC_ASN1_GET(SEC_OctetStringTemplate)); 1.2134 + if (pubValue == NULL) { 1.2135 + goto loser; 1.2136 + } 1.2137 + mechParams->ulPublicDataLen = pubValue->len; 1.2138 + mechParams->pPublicData = pubValue->data; 1.2139 + 1.2140 + pk11_EnterKeyMonitor(symKey); 1.2141 + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 1.2142 + &mechanism, privKey->pkcs11ID, keyTemplate, 1.2143 + templateCount, &symKey->objectID); 1.2144 + pk11_ExitKeyMonitor(symKey); 1.2145 + 1.2146 + if ((crv != CKR_OK) && (kdf != CKD_NULL)) { 1.2147 + /* Some PKCS #11 libraries cannot perform the key derivation 1.2148 + * function. So, try calling C_DeriveKey with CKD_NULL and then 1.2149 + * performing the KDF separately. 1.2150 + */ 1.2151 + CK_ULONG derivedKeySize = key_size; 1.2152 + 1.2153 + keyType = CKK_GENERIC_SECRET; 1.2154 + key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); 1.2155 + if (key_size == 0) { 1.2156 + SECITEM_FreeItem(pubValue,PR_TRUE); 1.2157 + goto loser; 1.2158 + } 1.2159 + SharedSecret = symKey; 1.2160 + SharedSecret->size = key_size; 1.2161 + 1.2162 + mechParams->kdf = CKD_NULL; 1.2163 + mechParams->ulSharedDataLen = 0; 1.2164 + mechParams->pSharedData = NULL; 1.2165 + mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 1.2166 + mechParams->pPublicData = pubKey->u.ec.publicValue.data; 1.2167 + 1.2168 + pk11_EnterKeyMonitor(SharedSecret); 1.2169 + crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, 1.2170 + &mechanism, privKey->pkcs11ID, keyTemplate, 1.2171 + templateCount, &SharedSecret->objectID); 1.2172 + pk11_ExitKeyMonitor(SharedSecret); 1.2173 + 1.2174 + if (crv != CKR_OK) { 1.2175 + /* old PKCS #11 spec was ambiguous on what needed to be passed, 1.2176 + * try this one final time with an encoded public key */ 1.2177 + mechParams->ulPublicDataLen = pubValue->len; 1.2178 + mechParams->pPublicData = pubValue->data; 1.2179 + 1.2180 + pk11_EnterKeyMonitor(SharedSecret); 1.2181 + crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, 1.2182 + &mechanism, privKey->pkcs11ID, keyTemplate, 1.2183 + templateCount, &SharedSecret->objectID); 1.2184 + pk11_ExitKeyMonitor(SharedSecret); 1.2185 + } 1.2186 + 1.2187 + /* Perform KDF. */ 1.2188 + if (crv == CKR_OK) { 1.2189 + symKey = pk11_ANSIX963Derive(SharedSecret, kdf, 1.2190 + sharedData, target, operation, 1.2191 + derivedKeySize); 1.2192 + PK11_FreeSymKey(SharedSecret); 1.2193 + if (symKey == NULL) { 1.2194 + SECITEM_FreeItem(pubValue,PR_TRUE); 1.2195 + PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 1.2196 + return NULL; 1.2197 + } 1.2198 + } 1.2199 + } 1.2200 + SECITEM_FreeItem(pubValue,PR_TRUE); 1.2201 + } 1.2202 + 1.2203 +loser: 1.2204 + PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 1.2205 + 1.2206 + if (crv != CKR_OK) { 1.2207 + PK11_FreeSymKey(symKey); 1.2208 + symKey = NULL; 1.2209 + PORT_SetError( PK11_MapError(crv) ); 1.2210 + } 1.2211 + return symKey; 1.2212 +} 1.2213 + 1.2214 +PK11SymKey * 1.2215 +PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 1.2216 + PRBool isSender, SECItem *randomA, SECItem *randomB, 1.2217 + CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 1.2218 + CK_ATTRIBUTE_TYPE operation, int keySize, 1.2219 + CK_ULONG kdf, SECItem *sharedData, void *wincx) 1.2220 +{ 1.2221 + 1.2222 + switch (privKey->keyType) { 1.2223 + case rsaKey: 1.2224 + case nullKey: 1.2225 + case dsaKey: 1.2226 + case keaKey: 1.2227 + case fortezzaKey: 1.2228 + case dhKey: 1.2229 + return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, 1.2230 + derive, target, operation, keySize, wincx); 1.2231 + case ecKey: 1.2232 + return pk11_PubDeriveECKeyWithKDF( privKey, pubKey, isSender, 1.2233 + randomA, randomB, derive, target, operation, keySize, 1.2234 + kdf, sharedData, wincx); 1.2235 + default: 1.2236 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.2237 + break; 1.2238 + } 1.2239 + 1.2240 + return NULL; 1.2241 +} 1.2242 + 1.2243 +/* 1.2244 + * this little function uses the Decrypt function to unwrap a key, just in 1.2245 + * case we are having problem with unwrap. NOTE: The key size may 1.2246 + * not be preserved properly for some algorithms! 1.2247 + */ 1.2248 +static PK11SymKey * 1.2249 +pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, 1.2250 + CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target, 1.2251 + CK_ATTRIBUTE *keyTemplate, unsigned int templateCount, 1.2252 + int key_size, void * wincx, CK_RV *crvp, PRBool isPerm) 1.2253 +{ 1.2254 + CK_ULONG len; 1.2255 + SECItem outKey; 1.2256 + PK11SymKey *symKey; 1.2257 + CK_RV crv; 1.2258 + PRBool owner = PR_TRUE; 1.2259 + CK_SESSION_HANDLE session; 1.2260 + 1.2261 + /* remove any VALUE_LEN parameters */ 1.2262 + if (keyTemplate[templateCount-1].type == CKA_VALUE_LEN) { 1.2263 + templateCount--; 1.2264 + } 1.2265 + 1.2266 + /* keys are almost always aligned, but if we get this far, 1.2267 + * we've gone above and beyond anyway... */ 1.2268 + outKey.data = (unsigned char*)PORT_Alloc(inKey->len); 1.2269 + if (outKey.data == NULL) { 1.2270 + PORT_SetError( SEC_ERROR_NO_MEMORY ); 1.2271 + if (crvp) *crvp = CKR_HOST_MEMORY; 1.2272 + return NULL; 1.2273 + } 1.2274 + len = inKey->len; 1.2275 + 1.2276 + /* use NULL IV's for wrapping */ 1.2277 + session = pk11_GetNewSession(slot,&owner); 1.2278 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.2279 + crv = PK11_GETTAB(slot)->C_DecryptInit(session,mech,wrappingKey); 1.2280 + if (crv != CKR_OK) { 1.2281 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.2282 + pk11_CloseSession(slot,session,owner); 1.2283 + PORT_Free(outKey.data); 1.2284 + PORT_SetError( PK11_MapError(crv) ); 1.2285 + if (crvp) *crvp =crv; 1.2286 + return NULL; 1.2287 + } 1.2288 + crv = PK11_GETTAB(slot)->C_Decrypt(session,inKey->data,inKey->len, 1.2289 + outKey.data, &len); 1.2290 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.2291 + pk11_CloseSession(slot,session,owner); 1.2292 + if (crv != CKR_OK) { 1.2293 + PORT_Free(outKey.data); 1.2294 + PORT_SetError( PK11_MapError(crv) ); 1.2295 + if (crvp) *crvp =crv; 1.2296 + return NULL; 1.2297 + } 1.2298 + 1.2299 + outKey.len = (key_size == 0) ? len : key_size; 1.2300 + outKey.type = siBuffer; 1.2301 + 1.2302 + if (PK11_DoesMechanism(slot,target)) { 1.2303 + symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, 1.2304 + isPerm, keyTemplate, 1.2305 + templateCount, &outKey, wincx); 1.2306 + } else { 1.2307 + slot = PK11_GetBestSlot(target,wincx); 1.2308 + if (slot == NULL) { 1.2309 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.2310 + PORT_Free(outKey.data); 1.2311 + if (crvp) *crvp = CKR_DEVICE_ERROR; 1.2312 + return NULL; 1.2313 + } 1.2314 + symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, 1.2315 + isPerm, keyTemplate, 1.2316 + templateCount, &outKey, wincx); 1.2317 + PK11_FreeSlot(slot); 1.2318 + } 1.2319 + PORT_Free(outKey.data); 1.2320 + 1.2321 + if (crvp) *crvp = symKey? CKR_OK : CKR_DEVICE_ERROR; 1.2322 + return symKey; 1.2323 +} 1.2324 + 1.2325 +/* 1.2326 + * The wrap/unwrap function is pretty much the same for private and 1.2327 + * public keys. It's just getting the Object ID and slot right. This is 1.2328 + * the combined unwrap function. 1.2329 + */ 1.2330 +static PK11SymKey * 1.2331 +pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, 1.2332 + CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey, 1.2333 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, 1.2334 + void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm) 1.2335 +{ 1.2336 + PK11SymKey * symKey; 1.2337 + SECItem * param_free = NULL; 1.2338 + CK_BBOOL cktrue = CK_TRUE; 1.2339 + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1.2340 + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1.2341 + CK_ULONG valueLen = 0; 1.2342 + CK_MECHANISM mechanism; 1.2343 + CK_SESSION_HANDLE rwsession; 1.2344 + CK_RV crv; 1.2345 + CK_MECHANISM_INFO mechanism_info; 1.2346 +#define MAX_ADD_ATTRS 4 1.2347 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; 1.2348 +#undef MAX_ADD_ATTRS 1.2349 + CK_ATTRIBUTE * attrs = keyTemplate; 1.2350 + unsigned int templateCount; 1.2351 + 1.2352 + if (numAttrs > MAX_TEMPL_ATTRS) { 1.2353 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.2354 + return NULL; 1.2355 + } 1.2356 + 1.2357 + /* first copy caller attributes in. */ 1.2358 + for (templateCount = 0; templateCount < numAttrs; ++templateCount) { 1.2359 + *attrs++ = *userAttr++; 1.2360 + } 1.2361 + 1.2362 + /* We only add the following attributes to the template if the caller 1.2363 + ** didn't already supply them. 1.2364 + */ 1.2365 + if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { 1.2366 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); 1.2367 + attrs++; 1.2368 + } 1.2369 + if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { 1.2370 + keyType = PK11_GetKeyType(target, keySize); 1.2371 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); 1.2372 + attrs++; 1.2373 + } 1.2374 + if ((operation != CKA_FLAGS_ONLY) && 1.2375 + !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { 1.2376 + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; 1.2377 + } 1.2378 + 1.2379 + /* 1.2380 + * must be last in case we need to use this template to import the key 1.2381 + */ 1.2382 + if (keySize > 0 && 1.2383 + !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { 1.2384 + valueLen = (CK_ULONG)keySize; 1.2385 + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); 1.2386 + attrs++; 1.2387 + } 1.2388 + 1.2389 + templateCount = attrs - keyTemplate; 1.2390 + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); 1.2391 + 1.2392 + 1.2393 + /* find out if we can do wrap directly. Because the RSA case if *very* 1.2394 + * common, cache the results for it. */ 1.2395 + if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) { 1.2396 + mechanism_info.flags = slot->RSAInfoFlags; 1.2397 + } else { 1.2398 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.2399 + crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,wrapType, 1.2400 + &mechanism_info); 1.2401 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.2402 + if (crv != CKR_OK) { 1.2403 + mechanism_info.flags = 0; 1.2404 + } 1.2405 + if (wrapType == CKM_RSA_PKCS) { 1.2406 + slot->RSAInfoFlags = mechanism_info.flags; 1.2407 + slot->hasRSAInfo = PR_TRUE; 1.2408 + } 1.2409 + } 1.2410 + 1.2411 + /* initialize the mechanism structure */ 1.2412 + mechanism.mechanism = wrapType; 1.2413 + /* use NULL IV's for wrapping */ 1.2414 + if (param == NULL) 1.2415 + param = param_free = PK11_ParamFromIV(wrapType,NULL); 1.2416 + if (param) { 1.2417 + mechanism.pParameter = param->data; 1.2418 + mechanism.ulParameterLen = param->len; 1.2419 + } else { 1.2420 + mechanism.pParameter = NULL; 1.2421 + mechanism.ulParameterLen = 0; 1.2422 + } 1.2423 + 1.2424 + if ((mechanism_info.flags & CKF_DECRYPT) 1.2425 + && !PK11_DoesMechanism(slot,target)) { 1.2426 + symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, 1.2427 + target, keyTemplate, templateCount, keySize, 1.2428 + wincx, &crv, isPerm); 1.2429 + if (symKey) { 1.2430 + if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); 1.2431 + return symKey; 1.2432 + } 1.2433 + /* 1.2434 + * if the RSA OP simply failed, don't try to unwrap again 1.2435 + * with this module. 1.2436 + */ 1.2437 + if (crv == CKR_DEVICE_ERROR){ 1.2438 + if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); 1.2439 + return NULL; 1.2440 + } 1.2441 + /* fall through, maybe they incorrectly set CKF_DECRYPT */ 1.2442 + } 1.2443 + 1.2444 + /* get our key Structure */ 1.2445 + symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx); 1.2446 + if (symKey == NULL) { 1.2447 + if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); 1.2448 + return NULL; 1.2449 + } 1.2450 + 1.2451 + symKey->size = keySize; 1.2452 + symKey->origin = PK11_OriginUnwrap; 1.2453 + 1.2454 + if (isPerm) { 1.2455 + rwsession = PK11_GetRWSession(slot); 1.2456 + } else { 1.2457 + pk11_EnterKeyMonitor(symKey); 1.2458 + rwsession = symKey->session; 1.2459 + } 1.2460 + PORT_Assert(rwsession != CK_INVALID_SESSION); 1.2461 + if (rwsession == CK_INVALID_SESSION) 1.2462 + crv = CKR_SESSION_HANDLE_INVALID; 1.2463 + else 1.2464 + crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey, 1.2465 + wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, 1.2466 + &symKey->objectID); 1.2467 + if (isPerm) { 1.2468 + if (rwsession != CK_INVALID_SESSION) 1.2469 + PK11_RestoreROSession(slot, rwsession); 1.2470 + } else { 1.2471 + pk11_ExitKeyMonitor(symKey); 1.2472 + } 1.2473 + if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); 1.2474 + if (crv != CKR_OK) { 1.2475 + PK11_FreeSymKey(symKey); 1.2476 + symKey = NULL; 1.2477 + if (crv != CKR_DEVICE_ERROR) { 1.2478 + /* try hand Unwrapping */ 1.2479 + symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, 1.2480 + target, keyTemplate, templateCount, 1.2481 + keySize, wincx, NULL, isPerm); 1.2482 + } 1.2483 + } 1.2484 + 1.2485 + return symKey; 1.2486 +} 1.2487 + 1.2488 +/* use a symetric key to unwrap another symetric key */ 1.2489 +PK11SymKey * 1.2490 +PK11_UnwrapSymKey( PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, 1.2491 + SECItem *param, SECItem *wrappedKey, 1.2492 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.2493 + int keySize) 1.2494 +{ 1.2495 + return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 1.2496 + wrapType, param, wrappedKey, target, operation, keySize, 1.2497 + wrappingKey->cx, NULL, 0, PR_FALSE); 1.2498 +} 1.2499 + 1.2500 +/* use a symetric key to unwrap another symetric key */ 1.2501 +PK11SymKey * 1.2502 +PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, 1.2503 + SECItem *param, SECItem *wrappedKey, 1.2504 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.2505 + int keySize, CK_FLAGS flags) 1.2506 +{ 1.2507 + CK_BBOOL ckTrue = CK_TRUE; 1.2508 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.2509 + unsigned int templateCount; 1.2510 + 1.2511 + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 1.2512 + return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 1.2513 + wrapType, param, wrappedKey, target, operation, keySize, 1.2514 + wrappingKey->cx, keyTemplate, templateCount, PR_FALSE); 1.2515 +} 1.2516 + 1.2517 +PK11SymKey * 1.2518 +PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, 1.2519 + CK_MECHANISM_TYPE wrapType, 1.2520 + SECItem *param, SECItem *wrappedKey, 1.2521 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1.2522 + int keySize, CK_FLAGS flags, PRBool isPerm) 1.2523 +{ 1.2524 + CK_BBOOL cktrue = CK_TRUE; 1.2525 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.2526 + CK_ATTRIBUTE *attrs; 1.2527 + unsigned int templateCount; 1.2528 + 1.2529 + attrs = keyTemplate; 1.2530 + if (isPerm) { 1.2531 + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.2532 + } 1.2533 + templateCount = attrs-keyTemplate; 1.2534 + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 1.2535 + 1.2536 + return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 1.2537 + wrapType, param, wrappedKey, target, operation, keySize, 1.2538 + wrappingKey->cx, keyTemplate, templateCount, isPerm); 1.2539 +} 1.2540 + 1.2541 + 1.2542 +/* unwrap a symetric key with a private key. */ 1.2543 +PK11SymKey * 1.2544 +PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, 1.2545 + CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) 1.2546 +{ 1.2547 + CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 1.2548 + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 1.2549 + 1.2550 + if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { 1.2551 + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); 1.2552 + } 1.2553 + 1.2554 + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, 1.2555 + wrapType, NULL, wrappedKey, target, operation, keySize, 1.2556 + wrappingKey->wincx, NULL, 0, PR_FALSE); 1.2557 +} 1.2558 + 1.2559 +/* unwrap a symetric key with a private key. */ 1.2560 +PK11SymKey * 1.2561 +PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, 1.2562 + SECItem *wrappedKey, CK_MECHANISM_TYPE target, 1.2563 + CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags) 1.2564 +{ 1.2565 + CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 1.2566 + CK_BBOOL ckTrue = CK_TRUE; 1.2567 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.2568 + unsigned int templateCount; 1.2569 + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 1.2570 + 1.2571 + templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 1.2572 + 1.2573 + if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { 1.2574 + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); 1.2575 + } 1.2576 + 1.2577 + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, 1.2578 + wrapType, NULL, wrappedKey, target, operation, keySize, 1.2579 + wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE); 1.2580 +} 1.2581 + 1.2582 +PK11SymKey * 1.2583 +PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, 1.2584 + SECItem *wrappedKey, CK_MECHANISM_TYPE target, 1.2585 + CK_ATTRIBUTE_TYPE operation, int keySize, 1.2586 + CK_FLAGS flags, PRBool isPerm) 1.2587 +{ 1.2588 + CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 1.2589 + CK_BBOOL cktrue = CK_TRUE; 1.2590 + CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1.2591 + CK_ATTRIBUTE *attrs; 1.2592 + unsigned int templateCount; 1.2593 + PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 1.2594 + 1.2595 + attrs = keyTemplate; 1.2596 + if (isPerm) { 1.2597 + PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; 1.2598 + } 1.2599 + templateCount = attrs-keyTemplate; 1.2600 + 1.2601 + templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 1.2602 + 1.2603 + if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { 1.2604 + PK11_HandlePasswordCheck(slot,wrappingKey->wincx); 1.2605 + } 1.2606 + 1.2607 + return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, 1.2608 + wrapType, NULL, wrappedKey, target, operation, keySize, 1.2609 + wrappingKey->wincx, keyTemplate, templateCount, isPerm); 1.2610 +} 1.2611 + 1.2612 +PK11SymKey* 1.2613 +PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech) 1.2614 +{ 1.2615 + CK_RV crv; 1.2616 + CK_ATTRIBUTE setTemplate; 1.2617 + CK_BBOOL ckTrue = CK_TRUE; 1.2618 + PK11SlotInfo *slot = originalKey->slot; 1.2619 + 1.2620 + /* first just try to set this key up for signing */ 1.2621 + PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue)); 1.2622 + pk11_EnterKeyMonitor(originalKey); 1.2623 + crv = PK11_GETTAB(slot)-> C_SetAttributeValue(originalKey->session, 1.2624 + originalKey->objectID, &setTemplate, 1); 1.2625 + pk11_ExitKeyMonitor(originalKey); 1.2626 + if (crv == CKR_OK) { 1.2627 + return PK11_ReferenceSymKey(originalKey); 1.2628 + } 1.2629 + 1.2630 + /* nope, doesn't like it, use the pk11 copy object command */ 1.2631 + return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey); 1.2632 +} 1.2633 + 1.2634 +void 1.2635 +PK11_SetFortezzaHack(PK11SymKey *symKey) { 1.2636 + symKey->origin = PK11_OriginFortezzaHack; 1.2637 +} 1.2638 + 1.2639 +/* 1.2640 + * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4 1.2641 + * working. This function simply gets a valid IV for the keys. 1.2642 + */ 1.2643 +SECStatus 1.2644 +PK11_GenerateFortezzaIV(PK11SymKey *symKey,unsigned char *iv,int len) 1.2645 +{ 1.2646 + CK_MECHANISM mech_info; 1.2647 + CK_ULONG count = 0; 1.2648 + CK_RV crv; 1.2649 + SECStatus rv = SECFailure; 1.2650 + 1.2651 + mech_info.mechanism = CKM_SKIPJACK_CBC64; 1.2652 + mech_info.pParameter = iv; 1.2653 + mech_info.ulParameterLen = len; 1.2654 + 1.2655 + /* generate the IV for fortezza */ 1.2656 + PK11_EnterSlotMonitor(symKey->slot); 1.2657 + crv=PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session, 1.2658 + &mech_info, symKey->objectID); 1.2659 + if (crv == CKR_OK) { 1.2660 + PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session, 1.2661 + NULL, &count); 1.2662 + rv = SECSuccess; 1.2663 + } 1.2664 + PK11_ExitSlotMonitor(symKey->slot); 1.2665 + return rv; 1.2666 +} 1.2667 + 1.2668 +CK_OBJECT_HANDLE 1.2669 +PK11_GetSymKeyHandle(PK11SymKey *symKey) 1.2670 +{ 1.2671 + return symKey->objectID; 1.2672 +} 1.2673 +