| OLD | NEW |
| (Empty) |
| 1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
| 2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
| 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
| 4 /* | |
| 5 * This file implements the Symkey wrapper and the PKCS context | |
| 6 * Interfaces. | |
| 7 */ | |
| 8 | |
| 9 #include "seccomon.h" | |
| 10 #include "secmod.h" | |
| 11 #include "nssilock.h" | |
| 12 #include "secmodi.h" | |
| 13 #include "secmodti.h" | |
| 14 #include "pkcs11.h" | |
| 15 #include "pk11func.h" | |
| 16 #include "secitem.h" | |
| 17 #include "secoid.h" | |
| 18 #include "secerr.h" | |
| 19 #include "hasht.h" | |
| 20 | |
| 21 static void | |
| 22 pk11_EnterKeyMonitor(PK11SymKey *symKey) { | |
| 23 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) | |
| 24 PK11_EnterSlotMonitor(symKey->slot); | |
| 25 } | |
| 26 | |
| 27 static void | |
| 28 pk11_ExitKeyMonitor(PK11SymKey *symKey) { | |
| 29 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) | |
| 30 PK11_ExitSlotMonitor(symKey->slot); | |
| 31 } | |
| 32 | |
| 33 /* | |
| 34 * pk11_getKeyFromList returns a symKey that has a session (if needSession | |
| 35 * was specified), or explicitly does not have a session (if needSession | |
| 36 * was not specified). | |
| 37 */ | |
| 38 static PK11SymKey * | |
| 39 pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) { | |
| 40 PK11SymKey *symKey = NULL; | |
| 41 | |
| 42 PZ_Lock(slot->freeListLock); | |
| 43 /* own session list are symkeys with sessions that the symkey owns. | |
| 44 * 'most' symkeys will own their own session. */ | |
| 45 if (needSession) { | |
| 46 if (slot->freeSymKeysWithSessionHead) { | |
| 47 symKey = slot->freeSymKeysWithSessionHead; | |
| 48 slot->freeSymKeysWithSessionHead = symKey->next; | |
| 49 slot->keyCount--; | |
| 50 } | |
| 51 } | |
| 52 /* if we don't need a symkey with its own session, or we couldn't find | |
| 53 * one on the owner list, get one from the non-owner free list. */ | |
| 54 if (!symKey) { | |
| 55 if (slot->freeSymKeysHead) { | |
| 56 symKey = slot->freeSymKeysHead; | |
| 57 slot->freeSymKeysHead = symKey->next; | |
| 58 slot->keyCount--; | |
| 59 } | |
| 60 } | |
| 61 PZ_Unlock(slot->freeListLock); | |
| 62 if (symKey) { | |
| 63 symKey->next = NULL; | |
| 64 if (!needSession) { | |
| 65 return symKey; | |
| 66 } | |
| 67 /* if we are getting an owner key, make sure we have a valid session. | |
| 68 * session could be invalid if the token has been removed or because | |
| 69 * we got it from the non-owner free list */ | |
| 70 if ((symKey->series != slot->series) || | |
| 71 (symKey->session == CK_INVALID_SESSION)) { | |
| 72 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); | |
| 73 } | |
| 74 PORT_Assert(symKey->session != CK_INVALID_SESSION); | |
| 75 if (symKey->session != CK_INVALID_SESSION) | |
| 76 return symKey; | |
| 77 PK11_FreeSymKey(symKey); | |
| 78 /* if we are here, we need a session, but couldn't get one, it's | |
| 79 * unlikely we pk11_GetNewSession will succeed if we call it a second | |
| 80 * time. */ | |
| 81 return NULL; | |
| 82 } | |
| 83 | |
| 84 symKey = PORT_New(PK11SymKey); | |
| 85 if (symKey == NULL) { | |
| 86 return NULL; | |
| 87 } | |
| 88 | |
| 89 symKey->next = NULL; | |
| 90 if (needSession) { | |
| 91 symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner); | |
| 92 PORT_Assert(symKey->session != CK_INVALID_SESSION); | |
| 93 if (symKey->session == CK_INVALID_SESSION) { | |
| 94 PK11_FreeSymKey(symKey); | |
| 95 symKey = NULL; | |
| 96 } | |
| 97 } else { | |
| 98 symKey->session = CK_INVALID_SESSION; | |
| 99 } | |
| 100 return symKey; | |
| 101 } | |
| 102 | |
| 103 /* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */ | |
| 104 void | |
| 105 PK11_CleanKeyList(PK11SlotInfo *slot) | |
| 106 { | |
| 107 PK11SymKey *symKey = NULL; | |
| 108 | |
| 109 while (slot->freeSymKeysWithSessionHead) { | |
| 110 symKey = slot->freeSymKeysWithSessionHead; | |
| 111 slot->freeSymKeysWithSessionHead = symKey->next; | |
| 112 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); | |
| 113 PORT_Free(symKey); | |
| 114 } | |
| 115 while (slot->freeSymKeysHead) { | |
| 116 symKey = slot->freeSymKeysHead; | |
| 117 slot->freeSymKeysHead = symKey->next; | |
| 118 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); | |
| 119 PORT_Free(symKey); | |
| 120 } | |
| 121 return; | |
| 122 } | |
| 123 | |
| 124 /* | |
| 125 * create a symetric key: | |
| 126 * Slot is the slot to create the key in. | |
| 127 * type is the mechanism type | |
| 128 * owner is does this symKey structure own it's object handle (rare | |
| 129 * that this is false). | |
| 130 * needSession means the returned symKey will return with a valid session | |
| 131 * allocated already. | |
| 132 */ | |
| 133 static PK11SymKey * | |
| 134 pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 135 PRBool owner, PRBool needSession, void *wincx) | |
| 136 { | |
| 137 | |
| 138 PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession); | |
| 139 | |
| 140 if (symKey == NULL) { | |
| 141 return NULL; | |
| 142 } | |
| 143 /* if needSession was specified, make sure we have a valid session. | |
| 144 * callers which specify needSession as false should do their own | |
| 145 * check of the session before returning the symKey */ | |
| 146 if (needSession && symKey->session == CK_INVALID_SESSION) { | |
| 147 PK11_FreeSymKey(symKey); | |
| 148 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 149 return NULL; | |
| 150 } | |
| 151 | |
| 152 symKey->type = type; | |
| 153 symKey->data.type = siBuffer; | |
| 154 symKey->data.data = NULL; | |
| 155 symKey->data.len = 0; | |
| 156 symKey->owner = owner; | |
| 157 symKey->objectID = CK_INVALID_HANDLE; | |
| 158 symKey->slot = slot; | |
| 159 symKey->series = slot->series; | |
| 160 symKey->cx = wincx; | |
| 161 symKey->size = 0; | |
| 162 symKey->refCount = 1; | |
| 163 symKey->origin = PK11_OriginNULL; | |
| 164 symKey->parent = NULL; | |
| 165 symKey->freeFunc = NULL; | |
| 166 symKey->userData = NULL; | |
| 167 PK11_ReferenceSlot(slot); | |
| 168 return symKey; | |
| 169 } | |
| 170 | |
| 171 /* | |
| 172 * destroy a symetric key | |
| 173 */ | |
| 174 void | |
| 175 PK11_FreeSymKey(PK11SymKey *symKey) | |
| 176 { | |
| 177 PK11SlotInfo *slot; | |
| 178 PRBool freeit = PR_TRUE; | |
| 179 | |
| 180 if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) { | |
| 181 PK11SymKey *parent = symKey->parent; | |
| 182 | |
| 183 symKey->parent = NULL; | |
| 184 if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { | |
| 185 pk11_EnterKeyMonitor(symKey); | |
| 186 (void) PK11_GETTAB(symKey->slot)-> | |
| 187 C_DestroyObject(symKey->session, symKey->objectID); | |
| 188 pk11_ExitKeyMonitor(symKey); | |
| 189 } | |
| 190 if (symKey->data.data) { | |
| 191 PORT_Memset(symKey->data.data, 0, symKey->data.len); | |
| 192 PORT_Free(symKey->data.data); | |
| 193 } | |
| 194 /* free any existing data */ | |
| 195 if (symKey->userData && symKey->freeFunc) { | |
| 196 (*symKey->freeFunc)(symKey->userData); | |
| 197 } | |
| 198 slot = symKey->slot; | |
| 199 PZ_Lock(slot->freeListLock); | |
| 200 if (slot->keyCount < slot->maxKeyCount) { | |
| 201 /* | |
| 202 * freeSymkeysWithSessionHead contain a list of reusable | |
| 203 * SymKey structures with valid sessions. | |
| 204 * sessionOwner must be true. | |
| 205 * session must be valid. | |
| 206 * freeSymKeysHead contain a list of SymKey structures without | |
| 207 * valid session. | |
| 208 * session must be CK_INVALID_SESSION. | |
| 209 * though sessionOwner is false, callers should not depend on | |
| 210 * this fact. | |
| 211 */ | |
| 212 if (symKey->sessionOwner) { | |
| 213 PORT_Assert (symKey->session != CK_INVALID_SESSION); | |
| 214 symKey->next = slot->freeSymKeysWithSessionHead; | |
| 215 slot->freeSymKeysWithSessionHead = symKey; | |
| 216 } else { | |
| 217 symKey->session = CK_INVALID_SESSION; | |
| 218 symKey->next = slot->freeSymKeysHead; | |
| 219 slot->freeSymKeysHead = symKey; | |
| 220 } | |
| 221 slot->keyCount++; | |
| 222 symKey->slot = NULL; | |
| 223 freeit = PR_FALSE; | |
| 224 } | |
| 225 PZ_Unlock(slot->freeListLock); | |
| 226 if (freeit) { | |
| 227 pk11_CloseSession(symKey->slot, symKey->session, | |
| 228 symKey->sessionOwner); | |
| 229 PORT_Free(symKey); | |
| 230 } | |
| 231 PK11_FreeSlot(slot); | |
| 232 | |
| 233 if (parent) { | |
| 234 PK11_FreeSymKey(parent); | |
| 235 } | |
| 236 } | |
| 237 } | |
| 238 | |
| 239 PK11SymKey * | |
| 240 PK11_ReferenceSymKey(PK11SymKey *symKey) | |
| 241 { | |
| 242 PR_ATOMIC_INCREMENT(&symKey->refCount); | |
| 243 return symKey; | |
| 244 } | |
| 245 | |
| 246 /* | |
| 247 * Accessors | |
| 248 */ | |
| 249 CK_MECHANISM_TYPE | |
| 250 PK11_GetMechanism(PK11SymKey *symKey) | |
| 251 { | |
| 252 return symKey->type; | |
| 253 } | |
| 254 | |
| 255 /* | |
| 256 * return the slot associated with a symetric key | |
| 257 */ | |
| 258 PK11SlotInfo * | |
| 259 PK11_GetSlotFromKey(PK11SymKey *symKey) | |
| 260 { | |
| 261 return PK11_ReferenceSlot(symKey->slot); | |
| 262 } | |
| 263 | |
| 264 CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *symKey) | |
| 265 { | |
| 266 return PK11_GetKeyType(symKey->type,symKey->size); | |
| 267 } | |
| 268 | |
| 269 PK11SymKey * | |
| 270 PK11_GetNextSymKey(PK11SymKey *symKey) | |
| 271 { | |
| 272 return symKey ? symKey->next : NULL; | |
| 273 } | |
| 274 | |
| 275 char * | |
| 276 PK11_GetSymKeyNickname(PK11SymKey *symKey) | |
| 277 { | |
| 278 return PK11_GetObjectNickname(symKey->slot,symKey->objectID); | |
| 279 } | |
| 280 | |
| 281 SECStatus | |
| 282 PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname) | |
| 283 { | |
| 284 return PK11_SetObjectNickname(symKey->slot,symKey->objectID,nickname); | |
| 285 } | |
| 286 | |
| 287 void * | |
| 288 PK11_GetSymKeyUserData(PK11SymKey *symKey) | |
| 289 { | |
| 290 return symKey->userData; | |
| 291 } | |
| 292 | |
| 293 void | |
| 294 PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData, | |
| 295 PK11FreeDataFunc freeFunc) | |
| 296 { | |
| 297 /* free any existing data */ | |
| 298 if (symKey->userData && symKey->freeFunc) { | |
| 299 (*symKey->freeFunc)(symKey->userData); | |
| 300 } | |
| 301 symKey->userData = userData; | |
| 302 symKey->freeFunc = freeFunc; | |
| 303 return; | |
| 304 } | |
| 305 | |
| 306 /* | |
| 307 * turn key handle into an appropriate key object | |
| 308 */ | |
| 309 PK11SymKey * | |
| 310 PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, | |
| 311 CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx) | |
| 312 { | |
| 313 PK11SymKey *symKey; | |
| 314 PRBool needSession = !(owner && parent); | |
| 315 | |
| 316 if (keyID == CK_INVALID_HANDLE) { | |
| 317 return NULL; | |
| 318 } | |
| 319 | |
| 320 symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx); | |
| 321 if (symKey == NULL) { | |
| 322 return NULL; | |
| 323 } | |
| 324 | |
| 325 symKey->objectID = keyID; | |
| 326 symKey->origin = origin; | |
| 327 | |
| 328 /* adopt the parent's session */ | |
| 329 /* This is only used by SSL. What we really want here is a session | |
| 330 * structure with a ref count so the session goes away only after all the | |
| 331 * keys do. */ | |
| 332 if (!needSession) { | |
| 333 symKey->sessionOwner = PR_FALSE; | |
| 334 symKey->session = parent->session; | |
| 335 symKey->parent = PK11_ReferenceSymKey(parent); | |
| 336 /* This is the only case where pk11_CreateSymKey does not explicitly | |
| 337 * check symKey->session. We need to assert here to make sure. | |
| 338 * the session isn't invalid. */ | |
| 339 PORT_Assert(parent->session != CK_INVALID_SESSION); | |
| 340 if (parent->session == CK_INVALID_SESSION) { | |
| 341 PK11_FreeSymKey(symKey); | |
| 342 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); | |
| 343 return NULL; | |
| 344 } | |
| 345 } | |
| 346 | |
| 347 return symKey; | |
| 348 } | |
| 349 | |
| 350 /* | |
| 351 * turn key handle into an appropriate key object | |
| 352 */ | |
| 353 PK11SymKey * | |
| 354 PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, | |
| 355 int series, void *wincx) | |
| 356 { | |
| 357 PK11SymKey *symKey = NULL; | |
| 358 | |
| 359 if (slot->series != series) return NULL; | |
| 360 if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL; | |
| 361 if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism; | |
| 362 | |
| 363 symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, | |
| 364 slot->wrapMechanism, slot->refKeys[wrap], PR_FALSE, wincx); | |
| 365 return symKey; | |
| 366 } | |
| 367 | |
| 368 /* | |
| 369 * This function is not thread-safe because it sets wrapKey->sessionOwner | |
| 370 * without using a lock or atomic routine. It can only be called when | |
| 371 * only one thread has a reference to wrapKey. | |
| 372 */ | |
| 373 void | |
| 374 PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey) | |
| 375 { | |
| 376 /* save the handle and mechanism for the wrapping key */ | |
| 377 /* mark the key and session as not owned by us to they don't get freed | |
| 378 * when the key goes way... that lets us reuse the key later */ | |
| 379 slot->refKeys[wrap] = wrapKey->objectID; | |
| 380 wrapKey->owner = PR_FALSE; | |
| 381 wrapKey->sessionOwner = PR_FALSE; | |
| 382 slot->wrapMechanism = wrapKey->type; | |
| 383 } | |
| 384 | |
| 385 | |
| 386 /* | |
| 387 * figure out if a key is still valid or if it is stale. | |
| 388 */ | |
| 389 PRBool | |
| 390 PK11_VerifyKeyOK(PK11SymKey *key) { | |
| 391 if (!PK11_IsPresent(key->slot)) { | |
| 392 return PR_FALSE; | |
| 393 } | |
| 394 return (PRBool)(key->series == key->slot->series); | |
| 395 } | |
| 396 | |
| 397 static PK11SymKey * | |
| 398 pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 399 PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate, | |
| 400 unsigned int templateCount, SECItem *key, void *wincx) | |
| 401 { | |
| 402 PK11SymKey * symKey; | |
| 403 SECStatus rv; | |
| 404 | |
| 405 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); | |
| 406 if (symKey == NULL) { | |
| 407 return NULL; | |
| 408 } | |
| 409 | |
| 410 symKey->size = key->len; | |
| 411 | |
| 412 PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len); | |
| 413 templateCount++; | |
| 414 | |
| 415 if (SECITEM_CopyItem(NULL,&symKey->data,key) != SECSuccess) { | |
| 416 PK11_FreeSymKey(symKey); | |
| 417 return NULL; | |
| 418 } | |
| 419 | |
| 420 symKey->origin = origin; | |
| 421 | |
| 422 /* import the keys */ | |
| 423 rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate, | |
| 424 templateCount, isToken, &symKey->objectID); | |
| 425 if ( rv != SECSuccess) { | |
| 426 PK11_FreeSymKey(symKey); | |
| 427 return NULL; | |
| 428 } | |
| 429 | |
| 430 return symKey; | |
| 431 } | |
| 432 | |
| 433 /* | |
| 434 * turn key bits into an appropriate key object | |
| 435 */ | |
| 436 PK11SymKey * | |
| 437 PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 438 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,void *wincx) | |
| 439 { | |
| 440 PK11SymKey * symKey; | |
| 441 unsigned int templateCount = 0; | |
| 442 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 443 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 444 CK_BBOOL cktrue = CK_TRUE; /* sigh */ | |
| 445 CK_ATTRIBUTE keyTemplate[5]; | |
| 446 CK_ATTRIBUTE * attrs = keyTemplate; | |
| 447 | |
| 448 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; | |
| 449 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; | |
| 450 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; | |
| 451 templateCount = attrs - keyTemplate; | |
| 452 PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 453 | |
| 454 keyType = PK11_GetKeyType(type,key->len); | |
| 455 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE, | |
| 456 keyTemplate, templateCount, key, wincx); | |
| 457 return symKey; | |
| 458 } | |
| 459 | |
| 460 | |
| 461 /* | |
| 462 * turn key bits into an appropriate key object | |
| 463 */ | |
| 464 PK11SymKey * | |
| 465 PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 466 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, | |
| 467 CK_FLAGS flags, PRBool isPerm, void *wincx) | |
| 468 { | |
| 469 PK11SymKey * symKey; | |
| 470 unsigned int templateCount = 0; | |
| 471 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 472 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 473 CK_BBOOL cktrue = CK_TRUE; /* sigh */ | |
| 474 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 475 CK_ATTRIBUTE * attrs = keyTemplate; | |
| 476 | |
| 477 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; | |
| 478 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; | |
| 479 if (isPerm) { | |
| 480 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++; | |
| 481 /* sigh some tokens think CKA_PRIVATE = false is a reasonable | |
| 482 * default for secret keys */ | |
| 483 PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue) ); attrs++; | |
| 484 } | |
| 485 attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); | |
| 486 if ((operation != CKA_FLAGS_ONLY) && | |
| 487 !pk11_FindAttrInTemplate(keyTemplate, attrs-keyTemplate, operation)) { | |
| 488 PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); attrs++; | |
| 489 } | |
| 490 templateCount = attrs - keyTemplate; | |
| 491 PR_ASSERT(templateCount+1 <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 492 | |
| 493 keyType = PK11_GetKeyType(type,key->len); | |
| 494 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm, | |
| 495 keyTemplate, templateCount, key, wincx); | |
| 496 if (symKey && isPerm) { | |
| 497 symKey->owner = PR_FALSE; | |
| 498 } | |
| 499 return symKey; | |
| 500 } | |
| 501 | |
| 502 | |
| 503 PK11SymKey * | |
| 504 PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, | |
| 505 void *wincx) | |
| 506 { | |
| 507 CK_ATTRIBUTE findTemp[4]; | |
| 508 CK_ATTRIBUTE *attrs; | |
| 509 CK_BBOOL ckTrue = CK_TRUE; | |
| 510 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; | |
| 511 int tsize = 0; | |
| 512 CK_OBJECT_HANDLE key_id; | |
| 513 | |
| 514 attrs = findTemp; | |
| 515 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; | |
| 516 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; | |
| 517 if (keyID) { | |
| 518 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len); attrs++; | |
| 519 } | |
| 520 tsize = attrs - findTemp; | |
| 521 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); | |
| 522 | |
| 523 key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize); | |
| 524 if (key_id == CK_INVALID_HANDLE) { | |
| 525 return NULL; | |
| 526 } | |
| 527 return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, | |
| 528 PR_FALSE, wincx); | |
| 529 } | |
| 530 | |
| 531 PK11SymKey * | |
| 532 PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) | |
| 533 { | |
| 534 CK_ATTRIBUTE findTemp[4]; | |
| 535 CK_ATTRIBUTE *attrs; | |
| 536 CK_BBOOL ckTrue = CK_TRUE; | |
| 537 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; | |
| 538 int tsize = 0; | |
| 539 int objCount = 0; | |
| 540 CK_OBJECT_HANDLE *key_ids; | |
| 541 PK11SymKey *nextKey = NULL; | |
| 542 PK11SymKey *topKey = NULL; | |
| 543 int i,len; | |
| 544 | |
| 545 attrs = findTemp; | |
| 546 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); attrs++; | |
| 547 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); attrs++; | |
| 548 if (nickname) { | |
| 549 len = PORT_Strlen(nickname); | |
| 550 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); attrs++; | |
| 551 } | |
| 552 tsize = attrs - findTemp; | |
| 553 PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); | |
| 554 | |
| 555 key_ids = pk11_FindObjectsByTemplate(slot,findTemp,tsize,&objCount); | |
| 556 if (key_ids == NULL) { | |
| 557 return NULL; | |
| 558 } | |
| 559 | |
| 560 for (i=0; i < objCount ; i++) { | |
| 561 SECItem typeData; | |
| 562 CK_KEY_TYPE type = CKK_GENERIC_SECRET; | |
| 563 SECStatus rv = PK11_ReadAttribute(slot, key_ids[i], | |
| 564 CKA_KEY_TYPE, NULL, &typeData); | |
| 565 if (rv == SECSuccess) { | |
| 566 if (typeData.len == sizeof(CK_KEY_TYPE)) { | |
| 567 type = *(CK_KEY_TYPE *)typeData.data; | |
| 568 } | |
| 569 PORT_Free(typeData.data); | |
| 570 } | |
| 571 nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, | |
| 572 PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx); | |
| 573 if (nextKey) { | |
| 574 nextKey->next = topKey; | |
| 575 topKey = nextKey; | |
| 576 } | |
| 577 } | |
| 578 PORT_Free(key_ids); | |
| 579 return topKey; | |
| 580 } | |
| 581 | |
| 582 void * | |
| 583 PK11_GetWindow(PK11SymKey *key) | |
| 584 { | |
| 585 return key->cx; | |
| 586 } | |
| 587 | |
| 588 | |
| 589 /* | |
| 590 * extract a symetric key value. NOTE: if the key is sensitive, we will | |
| 591 * not be able to do this operation. This function is used to move | |
| 592 * keys from one token to another */ | |
| 593 SECStatus | |
| 594 PK11_ExtractKeyValue(PK11SymKey *symKey) | |
| 595 { | |
| 596 SECStatus rv; | |
| 597 | |
| 598 if (symKey->data.data != NULL) { | |
| 599 if (symKey->size == 0) { | |
| 600 symKey->size = symKey->data.len; | |
| 601 } | |
| 602 return SECSuccess; | |
| 603 } | |
| 604 | |
| 605 if (symKey->slot == NULL) { | |
| 606 PORT_SetError( SEC_ERROR_INVALID_KEY ); | |
| 607 return SECFailure; | |
| 608 } | |
| 609 | |
| 610 rv = PK11_ReadAttribute(symKey->slot,symKey->objectID,CKA_VALUE,NULL, | |
| 611 &symKey->data); | |
| 612 if (rv == SECSuccess) { | |
| 613 symKey->size = symKey->data.len; | |
| 614 } | |
| 615 return rv; | |
| 616 } | |
| 617 | |
| 618 SECStatus | |
| 619 PK11_DeleteTokenSymKey(PK11SymKey *symKey) | |
| 620 { | |
| 621 if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) { | |
| 622 return SECFailure; | |
| 623 } | |
| 624 PK11_DestroyTokenObject(symKey->slot,symKey->objectID); | |
| 625 symKey->objectID = CK_INVALID_HANDLE; | |
| 626 return SECSuccess; | |
| 627 } | |
| 628 | |
| 629 SECItem * | |
| 630 PK11_GetKeyData(PK11SymKey *symKey) | |
| 631 { | |
| 632 return &symKey->data; | |
| 633 } | |
| 634 | |
| 635 /* This symbol is exported for backward compatibility. */ | |
| 636 SECItem * | |
| 637 __PK11_GetKeyData(PK11SymKey *symKey) | |
| 638 { | |
| 639 return PK11_GetKeyData(symKey); | |
| 640 } | |
| 641 | |
| 642 | |
| 643 /* | |
| 644 * PKCS #11 key Types with predefined length | |
| 645 */ | |
| 646 unsigned int | |
| 647 pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType) | |
| 648 { | |
| 649 int length = 0; | |
| 650 switch (keyType) { | |
| 651 case CKK_DES: length = 8; break; | |
| 652 case CKK_DES2: length = 16; break; | |
| 653 case CKK_DES3: length = 24; break; | |
| 654 case CKK_SKIPJACK: length = 10; break; | |
| 655 case CKK_BATON: length = 20; break; | |
| 656 case CKK_JUNIPER: length = 20; break; | |
| 657 default: break; | |
| 658 } | |
| 659 return length; | |
| 660 } | |
| 661 | |
| 662 /* return the keylength if possible. '0' if not */ | |
| 663 unsigned int | |
| 664 PK11_GetKeyLength(PK11SymKey *key) | |
| 665 { | |
| 666 CK_KEY_TYPE keyType; | |
| 667 | |
| 668 if (key->size != 0) return key->size; | |
| 669 | |
| 670 /* First try to figure out the key length from its type */ | |
| 671 keyType = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_KEY_TYPE); | |
| 672 key->size = pk11_GetPredefinedKeyLength(keyType); | |
| 673 if ((keyType == CKK_GENERIC_SECRET) && | |
| 674 (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) { | |
| 675 key->size=48; | |
| 676 } | |
| 677 | |
| 678 if( key->size != 0 ) return key->size; | |
| 679 | |
| 680 if (key->data.data == NULL) { | |
| 681 PK11_ExtractKeyValue(key); | |
| 682 } | |
| 683 /* key is probably secret. Look up its length */ | |
| 684 /* this is new PKCS #11 version 2.0 functionality. */ | |
| 685 if (key->size == 0) { | |
| 686 CK_ULONG keyLength; | |
| 687 | |
| 688 keyLength = PK11_ReadULongAttribute(key->slot,key->objectID,CKA_VALUE_LE
N); | |
| 689 if (keyLength != CK_UNAVAILABLE_INFORMATION) { | |
| 690 key->size = (unsigned int)keyLength; | |
| 691 } | |
| 692 } | |
| 693 | |
| 694 return key->size; | |
| 695 } | |
| 696 | |
| 697 /* return the strength of a key. This is different from length in that | |
| 698 * 1) it returns the size in bits, and 2) it returns only the secret portions | |
| 699 * of the key minus any checksums or parity. | |
| 700 */ | |
| 701 unsigned int | |
| 702 PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid) | |
| 703 { | |
| 704 int size=0; | |
| 705 CK_MECHANISM_TYPE mechanism= CKM_INVALID_MECHANISM; /* RC2 only */ | |
| 706 SECItem *param = NULL; /* RC2 only */ | |
| 707 CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */ | |
| 708 unsigned int effectiveBits = 0; /* RC2 ONLY */ | |
| 709 | |
| 710 switch (PK11_GetKeyType(key->type,0)) { | |
| 711 case CKK_CDMF: | |
| 712 return 40; | |
| 713 case CKK_DES: | |
| 714 return 56; | |
| 715 case CKK_DES3: | |
| 716 case CKK_DES2: | |
| 717 size = PK11_GetKeyLength(key); | |
| 718 if (size == 16) { | |
| 719 /* double des */ | |
| 720 return 112; /* 16*7 */ | |
| 721 } | |
| 722 return 168; | |
| 723 /* | |
| 724 * RC2 has is different than other ciphers in that it allows the user | |
| 725 * to deprecating keysize while still requiring all the bits for the | |
| 726 * original key. The info | |
| 727 * on what the effective key strength is in the parameter for the key. | |
| 728 * In S/MIME this parameter is stored in the DER encoded algid. In Our | |
| 729 * other uses of RC2, effectiveBits == keyBits, so this code functions | |
| 730 * correctly without an algid. | |
| 731 */ | |
| 732 case CKK_RC2: | |
| 733 /* if no algid was provided, fall through to default */ | |
| 734 if (!algid) { | |
| 735 break; | |
| 736 } | |
| 737 /* verify that the algid is for RC2 */ | |
| 738 mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid)); | |
| 739 if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) { | |
| 740 break; | |
| 741 } | |
| 742 | |
| 743 /* now get effective bits from the algorithm ID. */ | |
| 744 param = PK11_ParamFromAlgid(algid); | |
| 745 /* if we couldn't get memory just use key length */ | |
| 746 if (param == NULL) { | |
| 747 break; | |
| 748 } | |
| 749 | |
| 750 rc2_params = (CK_RC2_CBC_PARAMS *) param->data; | |
| 751 /* paranoia... shouldn't happen */ | |
| 752 PORT_Assert(param->data != NULL); | |
| 753 if (param->data == NULL) { | |
| 754 SECITEM_FreeItem(param,PR_TRUE); | |
| 755 break; | |
| 756 } | |
| 757 effectiveBits = (unsigned int)rc2_params->ulEffectiveBits; | |
| 758 SECITEM_FreeItem(param,PR_TRUE); | |
| 759 param = NULL; rc2_params=NULL; /* paranoia */ | |
| 760 | |
| 761 /* we have effective bits, is and allocated memory is free, now | |
| 762 * we need to return the smaller of effective bits and keysize */ | |
| 763 size = PK11_GetKeyLength(key); | |
| 764 if ((unsigned int)size*8 > effectiveBits) { | |
| 765 return effectiveBits; | |
| 766 } | |
| 767 | |
| 768 return size*8; /* the actual key is smaller, the strength can't be | |
| 769 * greater than the actual key size */ | |
| 770 | |
| 771 default: | |
| 772 break; | |
| 773 } | |
| 774 return PK11_GetKeyLength(key) * 8; | |
| 775 } | |
| 776 | |
| 777 /* | |
| 778 * The next three utilities are to deal with the fact that a given operation | |
| 779 * may be a multi-slot affair. This creates a new key object that is copied | |
| 780 * into the new slot. | |
| 781 */ | |
| 782 PK11SymKey * | |
| 783 pk11_CopyToSlotPerm(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, | |
| 784 CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, | |
| 785 PRBool isPerm, PK11SymKey *symKey) | |
| 786 { | |
| 787 SECStatus rv; | |
| 788 PK11SymKey *newKey = NULL; | |
| 789 | |
| 790 /* Extract the raw key data if possible */ | |
| 791 if (symKey->data.data == NULL) { | |
| 792 rv = PK11_ExtractKeyValue(symKey); | |
| 793 /* KEY is sensitive, we're try key exchanging it. */ | |
| 794 if (rv != SECSuccess) { | |
| 795 return pk11_KeyExchange(slot, type, operation, | |
| 796 flags, isPerm, symKey); | |
| 797 } | |
| 798 } | |
| 799 | |
| 800 newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin, | |
| 801 operation, &symKey->data, flags, isPerm, symKey->cx); | |
| 802 if (newKey == NULL) { | |
| 803 newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey); | |
| 804 } | |
| 805 return newKey; | |
| 806 } | |
| 807 | |
| 808 PK11SymKey * | |
| 809 pk11_CopyToSlot(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, | |
| 810 CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey) | |
| 811 { | |
| 812 return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey); | |
| 813 } | |
| 814 | |
| 815 /* | |
| 816 * Make sure the slot we are in is the correct slot for the operation | |
| 817 * by verifying that it supports all of the specified mechanism types. | |
| 818 */ | |
| 819 PK11SymKey * | |
| 820 pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type, | |
| 821 int mechCount, CK_ATTRIBUTE_TYPE operation) | |
| 822 { | |
| 823 PK11SlotInfo *slot = symKey->slot; | |
| 824 PK11SymKey *newKey = NULL; | |
| 825 PRBool needToCopy = PR_FALSE; | |
| 826 int i; | |
| 827 | |
| 828 if (slot == NULL) { | |
| 829 needToCopy = PR_TRUE; | |
| 830 } else { | |
| 831 i = 0; | |
| 832 while ((i < mechCount) && (needToCopy == PR_FALSE)) { | |
| 833 if (!PK11_DoesMechanism(slot,type[i])) { | |
| 834 needToCopy = PR_TRUE; | |
| 835 } | |
| 836 i++; | |
| 837 } | |
| 838 } | |
| 839 | |
| 840 if (needToCopy == PR_TRUE) { | |
| 841 slot = PK11_GetBestSlotMultiple(type,mechCount,symKey->cx); | |
| 842 if (slot == NULL) { | |
| 843 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 844 return NULL; | |
| 845 } | |
| 846 newKey = pk11_CopyToSlot(slot, type[0], operation, symKey); | |
| 847 PK11_FreeSlot(slot); | |
| 848 } | |
| 849 return newKey; | |
| 850 } | |
| 851 | |
| 852 /* | |
| 853 * Make sure the slot we are in is the correct slot for the operation | |
| 854 */ | |
| 855 PK11SymKey * | |
| 856 pk11_ForceSlot(PK11SymKey *symKey,CK_MECHANISM_TYPE type, | |
| 857 CK_ATTRIBUTE_TYPE operation) | |
| 858 { | |
| 859 return pk11_ForceSlotMultiple(symKey, &type, 1, operation); | |
| 860 } | |
| 861 | |
| 862 PK11SymKey * | |
| 863 PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, | |
| 864 CK_FLAGS flags, PRBool perm, PK11SymKey *symKey) | |
| 865 { | |
| 866 if (symKey->slot == slot) { | |
| 867 if (perm) { | |
| 868 return PK11_ConvertSessionSymKeyToTokenSymKey(symKey,symKey->cx); | |
| 869 } else { | |
| 870 return PK11_ReferenceSymKey(symKey); | |
| 871 } | |
| 872 } | |
| 873 | |
| 874 return pk11_CopyToSlotPerm(slot, symKey->type, | |
| 875 operation, flags, perm, symKey); | |
| 876 } | |
| 877 | |
| 878 /* | |
| 879 * Use the token to generate a key. | |
| 880 * | |
| 881 * keySize must be 'zero' for fixed key length algorithms. A nonzero | |
| 882 * keySize causes the CKA_VALUE_LEN attribute to be added to the template | |
| 883 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN | |
| 884 * attribute for keys with fixed length. The exception is DES2. If you | |
| 885 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN | |
| 886 * parameter and use the key size to determine which underlying DES keygen | |
| 887 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). | |
| 888 * | |
| 889 * keyType must be -1 for most algorithms. Some PBE algorthims cannot | |
| 890 * determine the correct key type from the mechanism or the parameters, | |
| 891 * so key type must be specified. Other PKCS #11 mechanisms may do so in | |
| 892 * the future. Currently there is no need to export this publically. | |
| 893 * Keep it private until there is a need in case we need to expand the | |
| 894 * keygen parameters again... | |
| 895 * | |
| 896 * CK_FLAGS flags: key operation flags | |
| 897 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags | |
| 898 */ | |
| 899 PK11SymKey * | |
| 900 pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 901 SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid, | |
| 902 CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx) | |
| 903 { | |
| 904 PK11SymKey *symKey; | |
| 905 CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS]; | |
| 906 CK_ATTRIBUTE *attrs = genTemplate; | |
| 907 int count = sizeof(genTemplate)/sizeof(genTemplate[0]); | |
| 908 CK_MECHANISM_TYPE keyGenType; | |
| 909 CK_BBOOL cktrue = CK_TRUE; | |
| 910 CK_BBOOL ckfalse = CK_FALSE; | |
| 911 CK_ULONG ck_key_size; /* only used for variable-length keys */ | |
| 912 | |
| 913 if (pk11_BadAttrFlags(attrFlags)) { | |
| 914 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 915 return NULL; | |
| 916 } | |
| 917 | |
| 918 if ((keySize != 0) && (type != CKM_DES3_CBC) && | |
| 919 (type !=CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) { | |
| 920 ck_key_size = keySize; /* Convert to PK11 type */ | |
| 921 | |
| 922 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size)); | |
| 923 attrs++; | |
| 924 } | |
| 925 | |
| 926 if (keyType != -1) { | |
| 927 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)); | |
| 928 attrs++; | |
| 929 } | |
| 930 | |
| 931 /* Include key id value if provided */ | |
| 932 if (keyid) { | |
| 933 PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); attrs++; | |
| 934 } | |
| 935 | |
| 936 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); | |
| 937 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); | |
| 938 | |
| 939 count = attrs - genTemplate; | |
| 940 PR_ASSERT(count <= sizeof(genTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 941 | |
| 942 keyGenType = PK11_GetKeyGenWithSize(type, keySize); | |
| 943 if (keyGenType == CKM_FAKE_RANDOM) { | |
| 944 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 945 return NULL; | |
| 946 } | |
| 947 symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType, | |
| 948 param, genTemplate, count, wincx); | |
| 949 if (symKey != NULL) { | |
| 950 symKey->size = keySize; | |
| 951 } | |
| 952 return symKey; | |
| 953 } | |
| 954 | |
| 955 /* | |
| 956 * Use the token to generate a key. - Public | |
| 957 * | |
| 958 * keySize must be 'zero' for fixed key length algorithms. A nonzero | |
| 959 * keySize causes the CKA_VALUE_LEN attribute to be added to the template | |
| 960 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN | |
| 961 * attribute for keys with fixed length. The exception is DES2. If you | |
| 962 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN | |
| 963 * parameter and use the key size to determine which underlying DES keygen | |
| 964 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). | |
| 965 * | |
| 966 * CK_FLAGS flags: key operation flags | |
| 967 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags | |
| 968 */ | |
| 969 PK11SymKey * | |
| 970 PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 971 SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, | |
| 972 PK11AttrFlags attrFlags, void *wincx) | |
| 973 { | |
| 974 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize, | |
| 975 keyid, opFlags, attrFlags, wincx); | |
| 976 } | |
| 977 | |
| 978 /* | |
| 979 * Use the token to generate a key. keySize must be 'zero' for fixed key | |
| 980 * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute | |
| 981 * to be added to the template for the key. PKCS #11 modules fail if you | |
| 982 * specify the CKA_VALUE_LEN attribute for keys with fixed length. | |
| 983 * NOTE: this means to generate a DES2 key from this interface you must | |
| 984 * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying | |
| 985 * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work. | |
| 986 */ | |
| 987 PK11SymKey * | |
| 988 PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, | |
| 989 int keySize, SECItem *keyid, PRBool isToken, void *wincx) | |
| 990 { | |
| 991 PK11SymKey *symKey; | |
| 992 PRBool weird = PR_FALSE; /* hack for fortezza */ | |
| 993 CK_FLAGS opFlags = CKF_SIGN; | |
| 994 PK11AttrFlags attrFlags = 0; | |
| 995 | |
| 996 if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { | |
| 997 weird = PR_TRUE; | |
| 998 keySize = 0; | |
| 999 } | |
| 1000 | |
| 1001 opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; | |
| 1002 | |
| 1003 if (isToken) { | |
| 1004 attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); | |
| 1005 } | |
| 1006 | |
| 1007 symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, | |
| 1008 -1, keySize, keyid, opFlags, attrFlags, wincx); | |
| 1009 if (symKey && weird) { | |
| 1010 PK11_SetFortezzaHack(symKey); | |
| 1011 } | |
| 1012 | |
| 1013 return symKey; | |
| 1014 } | |
| 1015 | |
| 1016 PK11SymKey * | |
| 1017 PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, | |
| 1018 int keySize, void *wincx) | |
| 1019 { | |
| 1020 return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx); | |
| 1021 } | |
| 1022 | |
| 1023 PK11SymKey * | |
| 1024 PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, | |
| 1025 CK_MECHANISM_TYPE keyGenType, | |
| 1026 SECItem *param, CK_ATTRIBUTE * attrs, | |
| 1027 unsigned int attrsCount, void *wincx) | |
| 1028 { | |
| 1029 PK11SymKey *symKey; | |
| 1030 CK_SESSION_HANDLE session; | |
| 1031 CK_MECHANISM mechanism; | |
| 1032 CK_RV crv; | |
| 1033 PRBool isToken = CK_FALSE; | |
| 1034 CK_ULONG keySize = 0; | |
| 1035 unsigned i; | |
| 1036 | |
| 1037 /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into | |
| 1038 isToken. */ | |
| 1039 for (i = 0; i < attrsCount; ++i) { | |
| 1040 switch (attrs[i].type) { | |
| 1041 case CKA_VALUE_LEN: | |
| 1042 if (attrs[i].pValue == NULL || | |
| 1043 attrs[i].ulValueLen != sizeof(CK_ULONG)) { | |
| 1044 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); | |
| 1045 return NULL; | |
| 1046 } | |
| 1047 keySize = * (CK_ULONG *) attrs[i].pValue; | |
| 1048 break; | |
| 1049 case CKA_TOKEN: | |
| 1050 if (attrs[i].pValue == NULL || | |
| 1051 attrs[i].ulValueLen != sizeof(CK_BBOOL)) { | |
| 1052 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); | |
| 1053 return NULL; | |
| 1054 } | |
| 1055 isToken = (*(CK_BBOOL*)attrs[i].pValue) ? PR_TRUE : PR_FALSE; | |
| 1056 break; | |
| 1057 } | |
| 1058 } | |
| 1059 | |
| 1060 /* find a slot to generate the key into */ | |
| 1061 /* Only do slot management if this is not a token key */ | |
| 1062 if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot,type))) { | |
| 1063 PK11SlotInfo *bestSlot = PK11_GetBestSlot(type,wincx); | |
| 1064 if (bestSlot == NULL) { | |
| 1065 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 1066 return NULL; | |
| 1067 } | |
| 1068 symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); | |
| 1069 PK11_FreeSlot(bestSlot); | |
| 1070 } else { | |
| 1071 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); | |
| 1072 } | |
| 1073 if (symKey == NULL) return NULL; | |
| 1074 | |
| 1075 symKey->size = keySize; | |
| 1076 symKey->origin = PK11_OriginGenerated; | |
| 1077 | |
| 1078 /* Set the parameters for the key gen if provided */ | |
| 1079 mechanism.mechanism = keyGenType; | |
| 1080 mechanism.pParameter = NULL; | |
| 1081 mechanism.ulParameterLen = 0; | |
| 1082 if (param) { | |
| 1083 mechanism.pParameter = param->data; | |
| 1084 mechanism.ulParameterLen = param->len; | |
| 1085 } | |
| 1086 | |
| 1087 /* Get session and perform locking */ | |
| 1088 if (isToken) { | |
| 1089 PK11_Authenticate(symKey->slot,PR_TRUE,wincx); | |
| 1090 /* Should always be original slot */ | |
| 1091 session = PK11_GetRWSession(symKey->slot); | |
| 1092 symKey->owner = PR_FALSE; | |
| 1093 } else { | |
| 1094 session = symKey->session; | |
| 1095 if (session != CK_INVALID_SESSION) | |
| 1096 pk11_EnterKeyMonitor(symKey); | |
| 1097 } | |
| 1098 if (session == CK_INVALID_SESSION) { | |
| 1099 PK11_FreeSymKey(symKey); | |
| 1100 PORT_SetError(SEC_ERROR_BAD_DATA); | |
| 1101 return NULL; | |
| 1102 } | |
| 1103 | |
| 1104 crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, | |
| 1105 &mechanism, attrs, attrsCount, &symKey->objectID); | |
| 1106 | |
| 1107 /* Release lock and session */ | |
| 1108 if (isToken) { | |
| 1109 PK11_RestoreROSession(symKey->slot, session); | |
| 1110 } else { | |
| 1111 pk11_ExitKeyMonitor(symKey); | |
| 1112 } | |
| 1113 | |
| 1114 if (crv != CKR_OK) { | |
| 1115 PK11_FreeSymKey(symKey); | |
| 1116 PORT_SetError( PK11_MapError(crv) ); | |
| 1117 return NULL; | |
| 1118 } | |
| 1119 | |
| 1120 return symKey; | |
| 1121 } | |
| 1122 | |
| 1123 | |
| 1124 /* --- */ | |
| 1125 PK11SymKey * | |
| 1126 PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx) | |
| 1127 { | |
| 1128 return PK11_TokenKeyGen(slot, CKM_DES3_CBC, 0, 0, keyid, PR_TRUE, cx); | |
| 1129 } | |
| 1130 | |
| 1131 PK11SymKey* | |
| 1132 PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) | |
| 1133 { | |
| 1134 PK11SlotInfo* slot = symk->slot; | |
| 1135 CK_ATTRIBUTE template[1]; | |
| 1136 CK_ATTRIBUTE *attrs = template; | |
| 1137 CK_BBOOL cktrue = CK_TRUE; | |
| 1138 CK_RV crv; | |
| 1139 CK_OBJECT_HANDLE newKeyID; | |
| 1140 CK_SESSION_HANDLE rwsession; | |
| 1141 | |
| 1142 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); attrs++; | |
| 1143 | |
| 1144 PK11_Authenticate(slot, PR_TRUE, wincx); | |
| 1145 rwsession = PK11_GetRWSession(slot); | |
| 1146 if (rwsession == CK_INVALID_SESSION) { | |
| 1147 PORT_SetError(SEC_ERROR_BAD_DATA); | |
| 1148 return NULL; | |
| 1149 } | |
| 1150 crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID, | |
| 1151 template, 1, &newKeyID); | |
| 1152 PK11_RestoreROSession(slot, rwsession); | |
| 1153 | |
| 1154 if (crv != CKR_OK) { | |
| 1155 PORT_SetError( PK11_MapError(crv) ); | |
| 1156 return NULL; | |
| 1157 } | |
| 1158 | |
| 1159 return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin, | |
| 1160 symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/); | |
| 1161 } | |
| 1162 | |
| 1163 /* | |
| 1164 * This function does a straight public key wrap (which only RSA can do). | |
| 1165 * Use PK11_PubGenKey and PK11_WrapSymKey to implement the FORTEZZA and | |
| 1166 * Diffie-Hellman Ciphers. */ | |
| 1167 SECStatus | |
| 1168 PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey, | |
| 1169 PK11SymKey *symKey, SECItem *wrappedKey) | |
| 1170 { | |
| 1171 PK11SlotInfo *slot; | |
| 1172 CK_ULONG len = wrappedKey->len; | |
| 1173 PK11SymKey *newKey = NULL; | |
| 1174 CK_OBJECT_HANDLE id; | |
| 1175 CK_MECHANISM mechanism; | |
| 1176 PRBool owner = PR_TRUE; | |
| 1177 CK_SESSION_HANDLE session; | |
| 1178 CK_RV crv; | |
| 1179 | |
| 1180 if (symKey == NULL) { | |
| 1181 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1182 return SECFailure; | |
| 1183 } | |
| 1184 | |
| 1185 /* if this slot doesn't support the mechanism, go to a slot that does */ | |
| 1186 newKey = pk11_ForceSlot(symKey,type,CKA_ENCRYPT); | |
| 1187 if (newKey != NULL) { | |
| 1188 symKey = newKey; | |
| 1189 } | |
| 1190 | |
| 1191 if (symKey->slot == NULL) { | |
| 1192 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 1193 return SECFailure; | |
| 1194 } | |
| 1195 | |
| 1196 slot = symKey->slot; | |
| 1197 mechanism.mechanism = pk11_mapWrapKeyType(pubKey->keyType); | |
| 1198 mechanism.pParameter = NULL; | |
| 1199 mechanism.ulParameterLen = 0; | |
| 1200 | |
| 1201 id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); | |
| 1202 if (id == CK_INVALID_HANDLE) { | |
| 1203 if (newKey) { | |
| 1204 PK11_FreeSymKey(newKey); | |
| 1205 } | |
| 1206 return SECFailure; /* Error code has been set. */ | |
| 1207 } | |
| 1208 | |
| 1209 session = pk11_GetNewSession(slot,&owner); | |
| 1210 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); | |
| 1211 crv = PK11_GETTAB(slot)->C_WrapKey(session,&mechanism, | |
| 1212 id,symKey->objectID,wrappedKey->data,&len); | |
| 1213 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 1214 pk11_CloseSession(slot,session,owner); | |
| 1215 if (newKey) { | |
| 1216 PK11_FreeSymKey(newKey); | |
| 1217 } | |
| 1218 | |
| 1219 if (crv != CKR_OK) { | |
| 1220 PORT_SetError( PK11_MapError(crv) ); | |
| 1221 return SECFailure; | |
| 1222 } | |
| 1223 wrappedKey->len = len; | |
| 1224 return SECSuccess; | |
| 1225 } | |
| 1226 | |
| 1227 /* | |
| 1228 * this little function uses the Encrypt function to wrap a key, just in | |
| 1229 * case we have problems with the wrap implementation for a token. | |
| 1230 */ | |
| 1231 static SECStatus | |
| 1232 pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type, | |
| 1233 SECItem *inKey, SECItem *outKey) | |
| 1234 { | |
| 1235 PK11SlotInfo *slot; | |
| 1236 CK_ULONG len; | |
| 1237 SECItem *data; | |
| 1238 CK_MECHANISM mech; | |
| 1239 PRBool owner = PR_TRUE; | |
| 1240 CK_SESSION_HANDLE session; | |
| 1241 CK_RV crv; | |
| 1242 | |
| 1243 slot = wrappingKey->slot; | |
| 1244 /* use NULL IV's for wrapping */ | |
| 1245 mech.mechanism = type; | |
| 1246 if (param) { | |
| 1247 mech.pParameter = param->data; | |
| 1248 mech.ulParameterLen = param->len; | |
| 1249 } else { | |
| 1250 mech.pParameter = NULL; | |
| 1251 mech.ulParameterLen = 0; | |
| 1252 } | |
| 1253 session = pk11_GetNewSession(slot,&owner); | |
| 1254 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); | |
| 1255 crv = PK11_GETTAB(slot)->C_EncryptInit(session,&mech, | |
| 1256 wrappingKey->objectID); | |
| 1257 if (crv != CKR_OK) { | |
| 1258 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 1259 pk11_CloseSession(slot,session,owner); | |
| 1260 PORT_SetError( PK11_MapError(crv) ); | |
| 1261 return SECFailure; | |
| 1262 } | |
| 1263 | |
| 1264 /* keys are almost always aligned, but if we get this far, | |
| 1265 * we've gone above and beyond anyway... */ | |
| 1266 data = PK11_BlockData(inKey,PK11_GetBlockSize(type,param)); | |
| 1267 if (data == NULL) { | |
| 1268 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 1269 pk11_CloseSession(slot,session,owner); | |
| 1270 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1271 return SECFailure; | |
| 1272 } | |
| 1273 len = outKey->len; | |
| 1274 crv = PK11_GETTAB(slot)->C_Encrypt(session,data->data,data->len, | |
| 1275 outKey->data, &len); | |
| 1276 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 1277 pk11_CloseSession(slot,session,owner); | |
| 1278 SECITEM_FreeItem(data,PR_TRUE); | |
| 1279 outKey->len = len; | |
| 1280 if (crv != CKR_OK) { | |
| 1281 PORT_SetError( PK11_MapError(crv) ); | |
| 1282 return SECFailure; | |
| 1283 } | |
| 1284 return SECSuccess; | |
| 1285 } | |
| 1286 | |
| 1287 /* | |
| 1288 * This function does a symetric based wrap. | |
| 1289 */ | |
| 1290 SECStatus | |
| 1291 PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param, | |
| 1292 PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey) | |
| 1293 { | |
| 1294 PK11SlotInfo *slot; | |
| 1295 CK_ULONG len = wrappedKey->len; | |
| 1296 PK11SymKey *newKey = NULL; | |
| 1297 SECItem *param_save = NULL; | |
| 1298 CK_MECHANISM mechanism; | |
| 1299 PRBool owner = PR_TRUE; | |
| 1300 CK_SESSION_HANDLE session; | |
| 1301 CK_RV crv; | |
| 1302 SECStatus rv; | |
| 1303 | |
| 1304 /* if this slot doesn't support the mechanism, go to a slot that does */ | |
| 1305 /* Force symKey and wrappingKey into the same slot */ | |
| 1306 if ((wrappingKey->slot == NULL) || (symKey->slot != wrappingKey->slot)) { | |
| 1307 /* first try copying the wrapping Key to the symKey slot */ | |
| 1308 if (symKey->slot && PK11_DoesMechanism(symKey->slot,type)) { | |
| 1309 newKey = pk11_CopyToSlot(symKey->slot,type,CKA_WRAP,wrappingKey); | |
| 1310 } | |
| 1311 /* Nope, try it the other way */ | |
| 1312 if (newKey == NULL) { | |
| 1313 if (wrappingKey->slot) { | |
| 1314 newKey = pk11_CopyToSlot(wrappingKey->slot, | |
| 1315 symKey->type, CKA_ENCRYPT, symKey); | |
| 1316 } | |
| 1317 /* just not playing... one last thing, can we get symKey's data? | |
| 1318 * If it's possible, we it should already be in the | |
| 1319 * symKey->data.data pointer because pk11_CopyToSlot would have | |
| 1320 * tried to put it there. */ | |
| 1321 if (newKey == NULL) { | |
| 1322 /* Can't get symKey's data: Game Over */ | |
| 1323 if (symKey->data.data == NULL) { | |
| 1324 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 1325 return SECFailure; | |
| 1326 } | |
| 1327 if (param == NULL) { | |
| 1328 param_save = param = PK11_ParamFromIV(type,NULL); | |
| 1329 } | |
| 1330 rv = pk11_HandWrap(wrappingKey, param, type, | |
| 1331 &symKey->data,wrappedKey); | |
| 1332 if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); | |
| 1333 return rv; | |
| 1334 } | |
| 1335 /* we successfully moved the sym Key */ | |
| 1336 symKey = newKey; | |
| 1337 } else { | |
| 1338 /* we successfully moved the wrapping Key */ | |
| 1339 wrappingKey = newKey; | |
| 1340 } | |
| 1341 } | |
| 1342 | |
| 1343 /* at this point both keys are in the same token */ | |
| 1344 slot = wrappingKey->slot; | |
| 1345 mechanism.mechanism = type; | |
| 1346 /* use NULL IV's for wrapping */ | |
| 1347 if (param == NULL) { | |
| 1348 param_save = param = PK11_ParamFromIV(type,NULL); | |
| 1349 } | |
| 1350 if (param) { | |
| 1351 mechanism.pParameter = param->data; | |
| 1352 mechanism.ulParameterLen = param->len; | |
| 1353 } else { | |
| 1354 mechanism.pParameter = NULL; | |
| 1355 mechanism.ulParameterLen = 0; | |
| 1356 } | |
| 1357 | |
| 1358 len = wrappedKey->len; | |
| 1359 | |
| 1360 session = pk11_GetNewSession(slot,&owner); | |
| 1361 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); | |
| 1362 crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism, | |
| 1363 wrappingKey->objectID, symKey->objectID, | |
| 1364 wrappedKey->data, &len); | |
| 1365 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 1366 pk11_CloseSession(slot,session,owner); | |
| 1367 rv = SECSuccess; | |
| 1368 if (crv != CKR_OK) { | |
| 1369 /* can't wrap it? try hand wrapping it... */ | |
| 1370 do { | |
| 1371 if (symKey->data.data == NULL) { | |
| 1372 rv = PK11_ExtractKeyValue(symKey); | |
| 1373 if (rv != SECSuccess) break; | |
| 1374 } | |
| 1375 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, | |
| 1376 wrappedKey); | |
| 1377 } while (PR_FALSE); | |
| 1378 } else { | |
| 1379 wrappedKey->len = len; | |
| 1380 } | |
| 1381 if (newKey) PK11_FreeSymKey(newKey); | |
| 1382 if (param_save) SECITEM_FreeItem(param_save,PR_TRUE); | |
| 1383 return rv; | |
| 1384 } | |
| 1385 | |
| 1386 /* | |
| 1387 * This Generates a new key based on a symetricKey | |
| 1388 */ | |
| 1389 PK11SymKey * | |
| 1390 PK11_Derive( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param, | |
| 1391 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 1392 int keySize) | |
| 1393 { | |
| 1394 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, | |
| 1395 keySize, NULL, 0, PR_FALSE); | |
| 1396 } | |
| 1397 | |
| 1398 | |
| 1399 PK11SymKey * | |
| 1400 PK11_DeriveWithFlags( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, | |
| 1401 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 1402 int keySize, CK_FLAGS flags) | |
| 1403 { | |
| 1404 CK_BBOOL ckTrue = CK_TRUE; | |
| 1405 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 1406 unsigned int templateCount; | |
| 1407 | |
| 1408 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); | |
| 1409 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, | |
| 1410 keySize, keyTemplate, templateCount, PR_FALSE); | |
| 1411 } | |
| 1412 | |
| 1413 PK11SymKey * | |
| 1414 PK11_DeriveWithFlagsPerm( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, | |
| 1415 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 1416 int keySize, CK_FLAGS flags, PRBool isPerm) | |
| 1417 { | |
| 1418 CK_BBOOL cktrue = CK_TRUE; | |
| 1419 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 1420 CK_ATTRIBUTE *attrs; | |
| 1421 unsigned int templateCount = 0; | |
| 1422 | |
| 1423 attrs = keyTemplate; | |
| 1424 if (isPerm) { | |
| 1425 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; | |
| 1426 } | |
| 1427 templateCount = attrs - keyTemplate; | |
| 1428 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); | |
| 1429 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, | |
| 1430 keySize, keyTemplate, templateCount, isPerm); | |
| 1431 } | |
| 1432 | |
| 1433 PK11SymKey * | |
| 1434 PK11_DeriveWithTemplate( PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, | |
| 1435 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 1436 int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, | |
| 1437 PRBool isPerm) | |
| 1438 { | |
| 1439 PK11SlotInfo * slot = baseKey->slot; | |
| 1440 PK11SymKey * symKey; | |
| 1441 PK11SymKey * newBaseKey = NULL; | |
| 1442 CK_BBOOL cktrue = CK_TRUE; | |
| 1443 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 1444 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 1445 CK_ULONG valueLen = 0; | |
| 1446 CK_MECHANISM mechanism; | |
| 1447 CK_RV crv; | |
| 1448 #define MAX_ADD_ATTRS 4 | |
| 1449 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; | |
| 1450 #undef MAX_ADD_ATTRS | |
| 1451 CK_ATTRIBUTE * attrs = keyTemplate; | |
| 1452 CK_SESSION_HANDLE session; | |
| 1453 unsigned int templateCount; | |
| 1454 | |
| 1455 if (numAttrs > MAX_TEMPL_ATTRS) { | |
| 1456 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1457 return NULL; | |
| 1458 } | |
| 1459 | |
| 1460 /* first copy caller attributes in. */ | |
| 1461 for (templateCount = 0; templateCount < numAttrs; ++templateCount) { | |
| 1462 *attrs++ = *userAttr++; | |
| 1463 } | |
| 1464 | |
| 1465 /* We only add the following attributes to the template if the caller | |
| 1466 ** didn't already supply them. | |
| 1467 */ | |
| 1468 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { | |
| 1469 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); | |
| 1470 attrs++; | |
| 1471 } | |
| 1472 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { | |
| 1473 keyType = PK11_GetKeyType(target, keySize); | |
| 1474 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); | |
| 1475 attrs++; | |
| 1476 } | |
| 1477 if (keySize > 0 && | |
| 1478 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { | |
| 1479 valueLen = (CK_ULONG)keySize; | |
| 1480 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); | |
| 1481 attrs++; | |
| 1482 } | |
| 1483 if ((operation != CKA_FLAGS_ONLY) && | |
| 1484 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { | |
| 1485 PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); attrs++; | |
| 1486 } | |
| 1487 | |
| 1488 templateCount = attrs - keyTemplate; | |
| 1489 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 1490 | |
| 1491 /* move the key to a slot that can do the function */ | |
| 1492 if (!PK11_DoesMechanism(slot,derive)) { | |
| 1493 /* get a new base key & slot */ | |
| 1494 PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx); | |
| 1495 | |
| 1496 if (newSlot == NULL) return NULL; | |
| 1497 | |
| 1498 newBaseKey = pk11_CopyToSlot (newSlot, derive, CKA_DERIVE, | |
| 1499 baseKey); | |
| 1500 PK11_FreeSlot(newSlot); | |
| 1501 if (newBaseKey == NULL) | |
| 1502 return NULL; | |
| 1503 baseKey = newBaseKey; | |
| 1504 slot = baseKey->slot; | |
| 1505 } | |
| 1506 | |
| 1507 | |
| 1508 /* get our key Structure */ | |
| 1509 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx); | |
| 1510 if (symKey == NULL) { | |
| 1511 return NULL; | |
| 1512 } | |
| 1513 | |
| 1514 symKey->size = keySize; | |
| 1515 | |
| 1516 mechanism.mechanism = derive; | |
| 1517 if (param) { | |
| 1518 mechanism.pParameter = param->data; | |
| 1519 mechanism.ulParameterLen = param->len; | |
| 1520 } else { | |
| 1521 mechanism.pParameter = NULL; | |
| 1522 mechanism.ulParameterLen = 0; | |
| 1523 } | |
| 1524 symKey->origin=PK11_OriginDerive; | |
| 1525 | |
| 1526 if (isPerm) { | |
| 1527 session = PK11_GetRWSession(slot); | |
| 1528 } else { | |
| 1529 pk11_EnterKeyMonitor(symKey); | |
| 1530 session = symKey->session; | |
| 1531 } | |
| 1532 if (session == CK_INVALID_SESSION) { | |
| 1533 if (!isPerm) | |
| 1534 pk11_ExitKeyMonitor(symKey); | |
| 1535 crv = CKR_SESSION_HANDLE_INVALID; | |
| 1536 } else { | |
| 1537 crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, | |
| 1538 baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); | |
| 1539 if (isPerm) { | |
| 1540 PK11_RestoreROSession(slot, session); | |
| 1541 } else { | |
| 1542 pk11_ExitKeyMonitor(symKey); | |
| 1543 } | |
| 1544 } | |
| 1545 if (newBaseKey) | |
| 1546 PK11_FreeSymKey(newBaseKey); | |
| 1547 if (crv != CKR_OK) { | |
| 1548 PK11_FreeSymKey(symKey); | |
| 1549 return NULL; | |
| 1550 } | |
| 1551 return symKey; | |
| 1552 } | |
| 1553 | |
| 1554 /* Create a new key by concatenating base and data | |
| 1555 */ | |
| 1556 static PK11SymKey *pk11_ConcatenateBaseAndData(PK11SymKey *base, | |
| 1557 CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target, | |
| 1558 CK_ATTRIBUTE_TYPE operation) | |
| 1559 { | |
| 1560 CK_KEY_DERIVATION_STRING_DATA mechParams; | |
| 1561 SECItem param; | |
| 1562 | |
| 1563 if (base == NULL) { | |
| 1564 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1565 return NULL; | |
| 1566 } | |
| 1567 | |
| 1568 mechParams.pData = data; | |
| 1569 mechParams.ulLen = dataLen; | |
| 1570 param.data = (unsigned char *)&mechParams; | |
| 1571 param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); | |
| 1572 | |
| 1573 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA, | |
| 1574 ¶m, target, operation, 0); | |
| 1575 } | |
| 1576 | |
| 1577 /* Create a new key by concatenating base and key | |
| 1578 */ | |
| 1579 static PK11SymKey *pk11_ConcatenateBaseAndKey(PK11SymKey *base, | |
| 1580 PK11SymKey *key, CK_MECHANISM_TYPE target, | |
| 1581 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) | |
| 1582 { | |
| 1583 SECItem param; | |
| 1584 | |
| 1585 if ((base == NULL) || (key == NULL)) { | |
| 1586 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1587 return NULL; | |
| 1588 } | |
| 1589 | |
| 1590 param.data = (unsigned char *)&(key->objectID); | |
| 1591 param.len = sizeof(CK_OBJECT_HANDLE); | |
| 1592 | |
| 1593 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY, | |
| 1594 ¶m, target, operation, keySize); | |
| 1595 } | |
| 1596 | |
| 1597 /* Create a new key whose value is the hash of tobehashed. | |
| 1598 * type is the mechanism for the derived key. | |
| 1599 */ | |
| 1600 static PK11SymKey *pk11_HashKeyDerivation(PK11SymKey *toBeHashed, | |
| 1601 CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target, | |
| 1602 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) | |
| 1603 { | |
| 1604 return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySi
ze); | |
| 1605 } | |
| 1606 | |
| 1607 /* This function implements the ANSI X9.63 key derivation function | |
| 1608 */ | |
| 1609 static PK11SymKey *pk11_ANSIX963Derive(PK11SymKey *sharedSecret, | |
| 1610 CK_EC_KDF_TYPE kdf, SECItem *sharedData, | |
| 1611 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 1612 CK_ULONG keySize) | |
| 1613 { | |
| 1614 CK_KEY_TYPE keyType; | |
| 1615 CK_MECHANISM_TYPE hashMechanism, mechanismArray[4]; | |
| 1616 CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen; | |
| 1617 CK_ULONG SharedInfoLen; | |
| 1618 CK_BYTE *buffer = NULL; | |
| 1619 PK11SymKey *toBeHashed, *hashOutput; | |
| 1620 PK11SymKey *newSharedSecret = NULL; | |
| 1621 PK11SymKey *oldIntermediateResult, *intermediateResult = NULL; | |
| 1622 | |
| 1623 if (sharedSecret == NULL) { | |
| 1624 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1625 return NULL; | |
| 1626 } | |
| 1627 | |
| 1628 switch (kdf) { | |
| 1629 case CKD_SHA1_KDF: | |
| 1630 HashLen = SHA1_LENGTH; | |
| 1631 hashMechanism = CKM_SHA1_KEY_DERIVATION; | |
| 1632 break; | |
| 1633 case CKD_SHA224_KDF: | |
| 1634 HashLen = SHA224_LENGTH; | |
| 1635 hashMechanism = CKM_SHA224_KEY_DERIVATION; | |
| 1636 break; | |
| 1637 case CKD_SHA256_KDF: | |
| 1638 HashLen = SHA256_LENGTH; | |
| 1639 hashMechanism = CKM_SHA256_KEY_DERIVATION; | |
| 1640 break; | |
| 1641 case CKD_SHA384_KDF: | |
| 1642 HashLen = SHA384_LENGTH; | |
| 1643 hashMechanism = CKM_SHA384_KEY_DERIVATION; | |
| 1644 break; | |
| 1645 case CKD_SHA512_KDF: | |
| 1646 HashLen = SHA512_LENGTH; | |
| 1647 hashMechanism = CKM_SHA512_KEY_DERIVATION; | |
| 1648 break; | |
| 1649 default: | |
| 1650 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1651 return NULL; | |
| 1652 } | |
| 1653 | |
| 1654 derivedKeySize = keySize; | |
| 1655 if (derivedKeySize == 0) { | |
| 1656 keyType = PK11_GetKeyType(target,keySize); | |
| 1657 derivedKeySize = pk11_GetPredefinedKeyLength(keyType); | |
| 1658 if (derivedKeySize == 0) { | |
| 1659 derivedKeySize = HashLen; | |
| 1660 } | |
| 1661 } | |
| 1662 | |
| 1663 /* Check that key_len isn't too long. The maximum key length could be | |
| 1664 * greatly increased if the code below did not limit the 4-byte counter | |
| 1665 * to a maximum value of 255. */ | |
| 1666 if (derivedKeySize > 254 * HashLen) { | |
| 1667 PORT_SetError( SEC_ERROR_INVALID_ARGS ); | |
| 1668 return NULL; | |
| 1669 } | |
| 1670 | |
| 1671 maxCounter = derivedKeySize / HashLen; | |
| 1672 if (derivedKeySize > maxCounter * HashLen) | |
| 1673 maxCounter++; | |
| 1674 | |
| 1675 if ((sharedData == NULL) || (sharedData->data == NULL)) | |
| 1676 SharedInfoLen = 0; | |
| 1677 else | |
| 1678 SharedInfoLen = sharedData->len; | |
| 1679 | |
| 1680 bufferLen = SharedInfoLen + 4; | |
| 1681 | |
| 1682 /* Populate buffer with Counter || sharedData | |
| 1683 * where Counter is 0x00000001. */ | |
| 1684 buffer = (unsigned char *)PORT_Alloc(bufferLen); | |
| 1685 if (buffer == NULL) { | |
| 1686 PORT_SetError(SEC_ERROR_NO_MEMORY); | |
| 1687 return NULL; | |
| 1688 } | |
| 1689 | |
| 1690 buffer[0] = 0; | |
| 1691 buffer[1] = 0; | |
| 1692 buffer[2] = 0; | |
| 1693 buffer[3] = 1; | |
| 1694 if (SharedInfoLen > 0) { | |
| 1695 PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen); | |
| 1696 } | |
| 1697 | |
| 1698 /* Look for a slot that supports the mechanisms needed | |
| 1699 * to implement the ANSI X9.63 KDF as well as the | |
| 1700 * target mechanism. | |
| 1701 */ | |
| 1702 mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA; | |
| 1703 mechanismArray[1] = hashMechanism; | |
| 1704 mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY; | |
| 1705 mechanismArray[3] = target; | |
| 1706 | |
| 1707 newSharedSecret = pk11_ForceSlotMultiple(sharedSecret, | |
| 1708 mechanismArray, 4, operation); | |
| 1709 if (newSharedSecret != NULL) { | |
| 1710 sharedSecret = newSharedSecret; | |
| 1711 } | |
| 1712 | |
| 1713 for(counter=1; counter <= maxCounter; counter++) { | |
| 1714 /* Concatenate shared_secret and buffer */ | |
| 1715 toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer, | |
| 1716 bufferLen, hashMechanism, operation); | |
| 1717 if (toBeHashed == NULL) { | |
| 1718 goto loser; | |
| 1719 } | |
| 1720 | |
| 1721 /* Hash value */ | |
| 1722 if (maxCounter == 1) { | |
| 1723 /* In this case the length of the key to be derived is | |
| 1724 * less than or equal to the length of the hash output. | |
| 1725 * So, the output of the hash operation will be the | |
| 1726 * dervied key. */ | |
| 1727 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, | |
| 1728 target, operation, keySize); | |
| 1729 } else { | |
| 1730 /* In this case, the output of the hash operation will be | |
| 1731 * concatenated with other data to create the derived key. */ | |
| 1732 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, | |
| 1733 CKM_CONCATENATE_BASE_AND_KEY, operation, 0); | |
| 1734 } | |
| 1735 PK11_FreeSymKey(toBeHashed); | |
| 1736 if (hashOutput == NULL) { | |
| 1737 goto loser; | |
| 1738 } | |
| 1739 | |
| 1740 /* Append result to intermediate result, if necessary */ | |
| 1741 oldIntermediateResult = intermediateResult; | |
| 1742 | |
| 1743 if (oldIntermediateResult == NULL) { | |
| 1744 intermediateResult = hashOutput; | |
| 1745 } else { | |
| 1746 if (counter == maxCounter) { | |
| 1747 /* This is the final concatenation, and so the output | |
| 1748 * will be the derived key. */ | |
| 1749 intermediateResult = | |
| 1750 pk11_ConcatenateBaseAndKey(oldIntermediateResult, | |
| 1751 hashOutput, target, operation, keySize); | |
| 1752 } else { | |
| 1753 /* The output of this concatenation will be concatenated | |
| 1754 * with other data to create the derived key. */ | |
| 1755 intermediateResult = | |
| 1756 pk11_ConcatenateBaseAndKey(oldIntermediateResult, | |
| 1757 hashOutput, CKM_CONCATENATE_BASE_AND_KEY, | |
| 1758 operation, 0); | |
| 1759 } | |
| 1760 | |
| 1761 PK11_FreeSymKey(hashOutput); | |
| 1762 PK11_FreeSymKey(oldIntermediateResult); | |
| 1763 if (intermediateResult == NULL) { | |
| 1764 goto loser; | |
| 1765 } | |
| 1766 } | |
| 1767 | |
| 1768 /* Increment counter (assumes maxCounter < 255) */ | |
| 1769 buffer[3]++; | |
| 1770 } | |
| 1771 | |
| 1772 PORT_ZFree(buffer, bufferLen); | |
| 1773 if (newSharedSecret != NULL) | |
| 1774 PK11_FreeSymKey(newSharedSecret); | |
| 1775 return intermediateResult; | |
| 1776 | |
| 1777 loser: | |
| 1778 if (buffer != NULL) | |
| 1779 PORT_ZFree(buffer, bufferLen); | |
| 1780 if (newSharedSecret != NULL) | |
| 1781 PK11_FreeSymKey(newSharedSecret); | |
| 1782 if (intermediateResult != NULL) | |
| 1783 PK11_FreeSymKey(intermediateResult); | |
| 1784 return NULL; | |
| 1785 } | |
| 1786 | |
| 1787 /* | |
| 1788 * This Generates a wrapping key based on a privateKey, publicKey, and two | |
| 1789 * random numbers. For Mail usage RandomB should be NULL. In the Sender's | |
| 1790 * case RandomA is generate, outherwize it is passed. | |
| 1791 */ | |
| 1792 static unsigned char *rb_email = NULL; | |
| 1793 | |
| 1794 PK11SymKey * | |
| 1795 PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, | |
| 1796 PRBool isSender, SECItem *randomA, SECItem *randomB, | |
| 1797 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, | |
| 1798 CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx) | |
| 1799 { | |
| 1800 PK11SlotInfo *slot = privKey->pkcs11Slot; | |
| 1801 CK_MECHANISM mechanism; | |
| 1802 PK11SymKey *symKey; | |
| 1803 CK_RV crv; | |
| 1804 | |
| 1805 | |
| 1806 if (rb_email == NULL) { | |
| 1807 rb_email = PORT_ZAlloc(128); | |
| 1808 if (rb_email == NULL) { | |
| 1809 return NULL; | |
| 1810 } | |
| 1811 rb_email[127] = 1; | |
| 1812 } | |
| 1813 | |
| 1814 /* get our key Structure */ | |
| 1815 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); | |
| 1816 if (symKey == NULL) { | |
| 1817 return NULL; | |
| 1818 } | |
| 1819 | |
| 1820 symKey->origin = PK11_OriginDerive; | |
| 1821 | |
| 1822 switch (privKey->keyType) { | |
| 1823 case rsaKey: | |
| 1824 case rsaPssKey: | |
| 1825 case rsaOaepKey: | |
| 1826 case nullKey: | |
| 1827 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 1828 break; | |
| 1829 case dsaKey: | |
| 1830 case keaKey: | |
| 1831 case fortezzaKey: | |
| 1832 { | |
| 1833 CK_KEA_DERIVE_PARAMS param; | |
| 1834 param.isSender = (CK_BBOOL) isSender; | |
| 1835 param.ulRandomLen = randomA->len; | |
| 1836 param.pRandomA = randomA->data; | |
| 1837 param.pRandomB = rb_email; | |
| 1838 if (randomB) | |
| 1839 param.pRandomB = randomB->data; | |
| 1840 if (pubKey->keyType == fortezzaKey) { | |
| 1841 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; | |
| 1842 param.pPublicData = pubKey->u.fortezza.KEAKey.data; | |
| 1843 } else { | |
| 1844 /* assert type == keaKey */ | |
| 1845 /* XXX change to match key key types */ | |
| 1846 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; | |
| 1847 param.pPublicData = pubKey->u.fortezza.KEAKey.data; | |
| 1848 } | |
| 1849 | |
| 1850 mechanism.mechanism = derive; | |
| 1851 mechanism.pParameter = ¶m; | |
| 1852 mechanism.ulParameterLen = sizeof(param); | |
| 1853 | |
| 1854 /* get a new symKey structure */ | |
| 1855 pk11_EnterKeyMonitor(symKey); | |
| 1856 crv=PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, | |
| 1857 privKey->pkcs11ID, NULL, 0, &symKey->objectID); | |
| 1858 pk11_ExitKeyMonitor(symKey); | |
| 1859 if (crv == CKR_OK) return symKey; | |
| 1860 PORT_SetError( PK11_MapError(crv) ); | |
| 1861 } | |
| 1862 break; | |
| 1863 case dhKey: | |
| 1864 { | |
| 1865 CK_BBOOL cktrue = CK_TRUE; | |
| 1866 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 1867 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 1868 CK_ULONG key_size = 0; | |
| 1869 CK_ATTRIBUTE keyTemplate[4]; | |
| 1870 int templateCount; | |
| 1871 CK_ATTRIBUTE *attrs = keyTemplate; | |
| 1872 | |
| 1873 if (pubKey->keyType != dhKey) { | |
| 1874 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 1875 break; | |
| 1876 } | |
| 1877 | |
| 1878 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); | |
| 1879 attrs++; | |
| 1880 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); | |
| 1881 attrs++; | |
| 1882 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; | |
| 1883 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); | |
| 1884 attrs++; | |
| 1885 templateCount = attrs - keyTemplate; | |
| 1886 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE))
; | |
| 1887 | |
| 1888 keyType = PK11_GetKeyType(target,keySize); | |
| 1889 key_size = keySize; | |
| 1890 symKey->size = keySize; | |
| 1891 if (key_size == 0) templateCount--; | |
| 1892 | |
| 1893 mechanism.mechanism = derive; | |
| 1894 | |
| 1895 /* we can undefine these when we define diffie-helman keys */ | |
| 1896 | |
| 1897 mechanism.pParameter = pubKey->u.dh.publicValue.data; | |
| 1898 mechanism.ulParameterLen = pubKey->u.dh.publicValue.len; | |
| 1899 | |
| 1900 pk11_EnterKeyMonitor(symKey); | |
| 1901 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, | |
| 1902 privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); | |
| 1903 pk11_ExitKeyMonitor(symKey); | |
| 1904 if (crv == CKR_OK) return symKey; | |
| 1905 PORT_SetError( PK11_MapError(crv) ); | |
| 1906 } | |
| 1907 break; | |
| 1908 case ecKey: | |
| 1909 { | |
| 1910 CK_BBOOL cktrue = CK_TRUE; | |
| 1911 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 1912 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 1913 CK_ULONG key_size = 0; | |
| 1914 CK_ATTRIBUTE keyTemplate[4]; | |
| 1915 int templateCount; | |
| 1916 CK_ATTRIBUTE *attrs = keyTemplate; | |
| 1917 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; | |
| 1918 | |
| 1919 if (pubKey->keyType != ecKey) { | |
| 1920 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 1921 break; | |
| 1922 } | |
| 1923 | |
| 1924 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); | |
| 1925 attrs++; | |
| 1926 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); | |
| 1927 attrs++; | |
| 1928 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; | |
| 1929 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); | |
| 1930 attrs++; | |
| 1931 templateCount = attrs - keyTemplate; | |
| 1932 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE))
; | |
| 1933 | |
| 1934 keyType = PK11_GetKeyType(target,keySize); | |
| 1935 key_size = keySize; | |
| 1936 if (key_size == 0) { | |
| 1937 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { | |
| 1938 templateCount --; | |
| 1939 } else { | |
| 1940 /* sigh, some tokens can't figure this out and require | |
| 1941 * CKA_VALUE_LEN to be set */ | |
| 1942 key_size = SHA1_LENGTH; | |
| 1943 } | |
| 1944 } | |
| 1945 symKey->size = key_size; | |
| 1946 | |
| 1947 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); | |
| 1948 mechParams->kdf = CKD_SHA1_KDF; | |
| 1949 mechParams->ulSharedDataLen = 0; | |
| 1950 mechParams->pSharedData = NULL; | |
| 1951 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; | |
| 1952 mechParams->pPublicData = pubKey->u.ec.publicValue.data; | |
| 1953 | |
| 1954 mechanism.mechanism = derive; | |
| 1955 mechanism.pParameter = mechParams; | |
| 1956 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); | |
| 1957 | |
| 1958 pk11_EnterKeyMonitor(symKey); | |
| 1959 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, | |
| 1960 &mechanism, privKey->pkcs11ID, keyTemplate, | |
| 1961 templateCount, &symKey->objectID); | |
| 1962 pk11_ExitKeyMonitor(symKey); | |
| 1963 | |
| 1964 /* old PKCS #11 spec was ambiguous on what needed to be passed, | |
| 1965 * try this again with and encoded public key */ | |
| 1966 if (crv != CKR_OK) { | |
| 1967 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, | |
| 1968 &pubKey->u.ec.publicValue, | |
| 1969 SEC_ASN1_GET(SEC_OctetStringTemplate)); | |
| 1970 if (pubValue == NULL) { | |
| 1971 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); | |
| 1972 break; | |
| 1973 } | |
| 1974 mechParams->ulPublicDataLen = pubValue->len; | |
| 1975 mechParams->pPublicData = pubValue->data; | |
| 1976 | |
| 1977 pk11_EnterKeyMonitor(symKey); | |
| 1978 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, | |
| 1979 &mechanism, privKey->pkcs11ID, keyTemplate, | |
| 1980 templateCount, &symKey->objectID); | |
| 1981 pk11_ExitKeyMonitor(symKey); | |
| 1982 | |
| 1983 SECITEM_FreeItem(pubValue,PR_TRUE); | |
| 1984 } | |
| 1985 | |
| 1986 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); | |
| 1987 | |
| 1988 if (crv == CKR_OK) return symKey; | |
| 1989 PORT_SetError( PK11_MapError(crv) ); | |
| 1990 } | |
| 1991 } | |
| 1992 | |
| 1993 PK11_FreeSymKey(symKey); | |
| 1994 return NULL; | |
| 1995 } | |
| 1996 | |
| 1997 /* Returns the size of the public key, or 0 if there | |
| 1998 * is an error. */ | |
| 1999 static CK_ULONG | |
| 2000 pk11_ECPubKeySize(SECItem *publicValue) | |
| 2001 { | |
| 2002 if (publicValue->data[0] == 0x04) { | |
| 2003 /* key encoded in uncompressed form */ | |
| 2004 return((publicValue->len - 1)/2); | |
| 2005 } else if ( (publicValue->data[0] == 0x02) || | |
| 2006 (publicValue->data[0] == 0x03)) { | |
| 2007 /* key encoded in compressed form */ | |
| 2008 return(publicValue->len - 1); | |
| 2009 } | |
| 2010 /* key encoding not recognized */ | |
| 2011 return(0); | |
| 2012 } | |
| 2013 | |
| 2014 static PK11SymKey * | |
| 2015 pk11_PubDeriveECKeyWithKDF( | |
| 2016 SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, | |
| 2017 PRBool isSender, SECItem *randomA, SECItem *randomB, | |
| 2018 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, | |
| 2019 CK_ATTRIBUTE_TYPE operation, int keySize, | |
| 2020 CK_ULONG kdf, SECItem *sharedData, void *wincx) | |
| 2021 { | |
| 2022 PK11SlotInfo *slot = privKey->pkcs11Slot; | |
| 2023 PK11SymKey *symKey; | |
| 2024 PK11SymKey *SharedSecret; | |
| 2025 CK_MECHANISM mechanism; | |
| 2026 CK_RV crv; | |
| 2027 CK_BBOOL cktrue = CK_TRUE; | |
| 2028 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 2029 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 2030 CK_ULONG key_size = 0; | |
| 2031 CK_ATTRIBUTE keyTemplate[4]; | |
| 2032 int templateCount; | |
| 2033 CK_ATTRIBUTE *attrs = keyTemplate; | |
| 2034 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; | |
| 2035 | |
| 2036 if (pubKey->keyType != ecKey) { | |
| 2037 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 2038 return NULL; | |
| 2039 } | |
| 2040 if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) && | |
| 2041 (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) && | |
| 2042 (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) { | |
| 2043 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 2044 return NULL; | |
| 2045 } | |
| 2046 | |
| 2047 /* get our key Structure */ | |
| 2048 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); | |
| 2049 if (symKey == NULL) { | |
| 2050 return NULL; | |
| 2051 } | |
| 2052 | |
| 2053 symKey->origin = PK11_OriginDerive; | |
| 2054 | |
| 2055 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; | |
| 2056 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; | |
| 2057 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; | |
| 2058 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); attrs++; | |
| 2059 templateCount = attrs - keyTemplate; | |
| 2060 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 2061 | |
| 2062 keyType = PK11_GetKeyType(target,keySize); | |
| 2063 key_size = keySize; | |
| 2064 if (key_size == 0) { | |
| 2065 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { | |
| 2066 templateCount --; | |
| 2067 } else { | |
| 2068 /* sigh, some tokens can't figure this out and require | |
| 2069 * CKA_VALUE_LEN to be set */ | |
| 2070 switch (kdf) { | |
| 2071 case CKD_NULL: | |
| 2072 key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); | |
| 2073 if (key_size == 0) { | |
| 2074 PK11_FreeSymKey(symKey); | |
| 2075 return NULL; | |
| 2076 } | |
| 2077 break; | |
| 2078 case CKD_SHA1_KDF: | |
| 2079 key_size = SHA1_LENGTH; | |
| 2080 break; | |
| 2081 case CKD_SHA224_KDF: | |
| 2082 key_size = SHA224_LENGTH; | |
| 2083 break; | |
| 2084 case CKD_SHA256_KDF: | |
| 2085 key_size = SHA256_LENGTH; | |
| 2086 break; | |
| 2087 case CKD_SHA384_KDF: | |
| 2088 key_size = SHA384_LENGTH; | |
| 2089 break; | |
| 2090 case CKD_SHA512_KDF: | |
| 2091 key_size = SHA512_LENGTH; | |
| 2092 break; | |
| 2093 default: | |
| 2094 PORT_Assert(!"Invalid CKD"); | |
| 2095 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); | |
| 2096 return NULL; | |
| 2097 } | |
| 2098 } | |
| 2099 } | |
| 2100 symKey->size = key_size; | |
| 2101 | |
| 2102 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); | |
| 2103 if (!mechParams) { | |
| 2104 PK11_FreeSymKey(symKey); | |
| 2105 return NULL; | |
| 2106 } | |
| 2107 mechParams->kdf = kdf; | |
| 2108 if (sharedData == NULL) { | |
| 2109 mechParams->ulSharedDataLen = 0; | |
| 2110 mechParams->pSharedData = NULL; | |
| 2111 } else { | |
| 2112 mechParams->ulSharedDataLen = sharedData->len; | |
| 2113 mechParams->pSharedData = sharedData->data; | |
| 2114 } | |
| 2115 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; | |
| 2116 mechParams->pPublicData = pubKey->u.ec.publicValue.data; | |
| 2117 | |
| 2118 mechanism.mechanism = derive; | |
| 2119 mechanism.pParameter = mechParams; | |
| 2120 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); | |
| 2121 | |
| 2122 pk11_EnterKeyMonitor(symKey); | |
| 2123 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, | |
| 2124 privKey->pkcs11ID, keyTemplate, templateCount, &symKey->objectID); | |
| 2125 pk11_ExitKeyMonitor(symKey); | |
| 2126 | |
| 2127 /* old PKCS #11 spec was ambiguous on what needed to be passed, | |
| 2128 * try this again with an encoded public key */ | |
| 2129 if (crv != CKR_OK) { | |
| 2130 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, | |
| 2131 &pubKey->u.ec.publicValue, | |
| 2132 SEC_ASN1_GET(SEC_OctetStringTemplate)); | |
| 2133 if (pubValue == NULL) { | |
| 2134 goto loser; | |
| 2135 } | |
| 2136 mechParams->ulPublicDataLen = pubValue->len; | |
| 2137 mechParams->pPublicData = pubValue->data; | |
| 2138 | |
| 2139 pk11_EnterKeyMonitor(symKey); | |
| 2140 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, | |
| 2141 &mechanism, privKey->pkcs11ID, keyTemplate, | |
| 2142 templateCount, &symKey->objectID); | |
| 2143 pk11_ExitKeyMonitor(symKey); | |
| 2144 | |
| 2145 if ((crv != CKR_OK) && (kdf != CKD_NULL)) { | |
| 2146 /* Some PKCS #11 libraries cannot perform the key derivation | |
| 2147 * function. So, try calling C_DeriveKey with CKD_NULL and then | |
| 2148 * performing the KDF separately. | |
| 2149 */ | |
| 2150 CK_ULONG derivedKeySize = key_size; | |
| 2151 | |
| 2152 keyType = CKK_GENERIC_SECRET; | |
| 2153 key_size = pk11_ECPubKeySize(&pubKey->u.ec.publicValue); | |
| 2154 if (key_size == 0) { | |
| 2155 SECITEM_FreeItem(pubValue,PR_TRUE); | |
| 2156 goto loser; | |
| 2157 } | |
| 2158 SharedSecret = symKey; | |
| 2159 SharedSecret->size = key_size; | |
| 2160 | |
| 2161 mechParams->kdf = CKD_NULL; | |
| 2162 mechParams->ulSharedDataLen = 0; | |
| 2163 mechParams->pSharedData = NULL; | |
| 2164 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; | |
| 2165 mechParams->pPublicData = pubKey->u.ec.publicValue.data; | |
| 2166 | |
| 2167 pk11_EnterKeyMonitor(SharedSecret); | |
| 2168 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, | |
| 2169 &mechanism, privKey->pkcs11ID, keyTemplate, | |
| 2170 templateCount, &SharedSecret->objectID); | |
| 2171 pk11_ExitKeyMonitor(SharedSecret); | |
| 2172 | |
| 2173 if (crv != CKR_OK) { | |
| 2174 /* old PKCS #11 spec was ambiguous on what needed to be passed, | |
| 2175 * try this one final time with an encoded public key */ | |
| 2176 mechParams->ulPublicDataLen = pubValue->len; | |
| 2177 mechParams->pPublicData = pubValue->data; | |
| 2178 | |
| 2179 pk11_EnterKeyMonitor(SharedSecret); | |
| 2180 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, | |
| 2181 &mechanism, privKey->pkcs11ID, keyTemplate, | |
| 2182 templateCount, &SharedSecret->objectID); | |
| 2183 pk11_ExitKeyMonitor(SharedSecret); | |
| 2184 } | |
| 2185 | |
| 2186 /* Perform KDF. */ | |
| 2187 if (crv == CKR_OK) { | |
| 2188 symKey = pk11_ANSIX963Derive(SharedSecret, kdf, | |
| 2189 sharedData, target, operation, | |
| 2190 derivedKeySize); | |
| 2191 PK11_FreeSymKey(SharedSecret); | |
| 2192 if (symKey == NULL) { | |
| 2193 SECITEM_FreeItem(pubValue,PR_TRUE); | |
| 2194 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); | |
| 2195 return NULL; | |
| 2196 } | |
| 2197 } | |
| 2198 } | |
| 2199 SECITEM_FreeItem(pubValue,PR_TRUE); | |
| 2200 } | |
| 2201 | |
| 2202 loser: | |
| 2203 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); | |
| 2204 | |
| 2205 if (crv != CKR_OK) { | |
| 2206 PK11_FreeSymKey(symKey); | |
| 2207 symKey = NULL; | |
| 2208 PORT_SetError( PK11_MapError(crv) ); | |
| 2209 } | |
| 2210 return symKey; | |
| 2211 } | |
| 2212 | |
| 2213 PK11SymKey * | |
| 2214 PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, | |
| 2215 PRBool isSender, SECItem *randomA, SECItem *randomB, | |
| 2216 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, | |
| 2217 CK_ATTRIBUTE_TYPE operation, int keySize, | |
| 2218 CK_ULONG kdf, SECItem *sharedData, void *wincx) | |
| 2219 { | |
| 2220 | |
| 2221 switch (privKey->keyType) { | |
| 2222 case rsaKey: | |
| 2223 case nullKey: | |
| 2224 case dsaKey: | |
| 2225 case keaKey: | |
| 2226 case fortezzaKey: | |
| 2227 case dhKey: | |
| 2228 return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, | |
| 2229 derive, target, operation, keySize, wincx); | |
| 2230 case ecKey: | |
| 2231 return pk11_PubDeriveECKeyWithKDF( privKey, pubKey, isSender, | |
| 2232 randomA, randomB, derive, target, operation, keySize, | |
| 2233 kdf, sharedData, wincx); | |
| 2234 default: | |
| 2235 PORT_SetError(SEC_ERROR_BAD_KEY); | |
| 2236 break; | |
| 2237 } | |
| 2238 | |
| 2239 return NULL; | |
| 2240 } | |
| 2241 | |
| 2242 /* | |
| 2243 * this little function uses the Decrypt function to unwrap a key, just in | |
| 2244 * case we are having problem with unwrap. NOTE: The key size may | |
| 2245 * not be preserved properly for some algorithms! | |
| 2246 */ | |
| 2247 static PK11SymKey * | |
| 2248 pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, | |
| 2249 CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target, | |
| 2250 CK_ATTRIBUTE *keyTemplate, unsigned int templateCount, | |
| 2251 int key_size, void * wincx, CK_RV *crvp, PRBool isPerm) | |
| 2252 { | |
| 2253 CK_ULONG len; | |
| 2254 SECItem outKey; | |
| 2255 PK11SymKey *symKey; | |
| 2256 CK_RV crv; | |
| 2257 PRBool owner = PR_TRUE; | |
| 2258 CK_SESSION_HANDLE session; | |
| 2259 | |
| 2260 /* remove any VALUE_LEN parameters */ | |
| 2261 if (keyTemplate[templateCount-1].type == CKA_VALUE_LEN) { | |
| 2262 templateCount--; | |
| 2263 } | |
| 2264 | |
| 2265 /* keys are almost always aligned, but if we get this far, | |
| 2266 * we've gone above and beyond anyway... */ | |
| 2267 outKey.data = (unsigned char*)PORT_Alloc(inKey->len); | |
| 2268 if (outKey.data == NULL) { | |
| 2269 PORT_SetError( SEC_ERROR_NO_MEMORY ); | |
| 2270 if (crvp) *crvp = CKR_HOST_MEMORY; | |
| 2271 return NULL; | |
| 2272 } | |
| 2273 len = inKey->len; | |
| 2274 | |
| 2275 /* use NULL IV's for wrapping */ | |
| 2276 session = pk11_GetNewSession(slot,&owner); | |
| 2277 if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); | |
| 2278 crv = PK11_GETTAB(slot)->C_DecryptInit(session,mech,wrappingKey); | |
| 2279 if (crv != CKR_OK) { | |
| 2280 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 2281 pk11_CloseSession(slot,session,owner); | |
| 2282 PORT_Free(outKey.data); | |
| 2283 PORT_SetError( PK11_MapError(crv) ); | |
| 2284 if (crvp) *crvp =crv; | |
| 2285 return NULL; | |
| 2286 } | |
| 2287 crv = PK11_GETTAB(slot)->C_Decrypt(session,inKey->data,inKey->len, | |
| 2288 outKey.data, &len); | |
| 2289 if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); | |
| 2290 pk11_CloseSession(slot,session,owner); | |
| 2291 if (crv != CKR_OK) { | |
| 2292 PORT_Free(outKey.data); | |
| 2293 PORT_SetError( PK11_MapError(crv) ); | |
| 2294 if (crvp) *crvp =crv; | |
| 2295 return NULL; | |
| 2296 } | |
| 2297 | |
| 2298 outKey.len = (key_size == 0) ? len : key_size; | |
| 2299 outKey.type = siBuffer; | |
| 2300 | |
| 2301 if (PK11_DoesMechanism(slot,target)) { | |
| 2302 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, | |
| 2303 isPerm, keyTemplate, | |
| 2304 templateCount, &outKey, wincx); | |
| 2305 } else { | |
| 2306 slot = PK11_GetBestSlot(target,wincx); | |
| 2307 if (slot == NULL) { | |
| 2308 PORT_SetError( SEC_ERROR_NO_MODULE ); | |
| 2309 PORT_Free(outKey.data); | |
| 2310 if (crvp) *crvp = CKR_DEVICE_ERROR; | |
| 2311 return NULL; | |
| 2312 } | |
| 2313 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, | |
| 2314 isPerm, keyTemplate, | |
| 2315 templateCount, &outKey, wincx); | |
| 2316 PK11_FreeSlot(slot); | |
| 2317 } | |
| 2318 PORT_Free(outKey.data); | |
| 2319 | |
| 2320 if (crvp) *crvp = symKey? CKR_OK : CKR_DEVICE_ERROR; | |
| 2321 return symKey; | |
| 2322 } | |
| 2323 | |
| 2324 /* | |
| 2325 * The wrap/unwrap function is pretty much the same for private and | |
| 2326 * public keys. It's just getting the Object ID and slot right. This is | |
| 2327 * the combined unwrap function. | |
| 2328 */ | |
| 2329 static PK11SymKey * | |
| 2330 pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, | |
| 2331 CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey, | |
| 2332 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, | |
| 2333 void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm) | |
| 2334 { | |
| 2335 PK11SymKey * symKey; | |
| 2336 SECItem * param_free = NULL; | |
| 2337 CK_BBOOL cktrue = CK_TRUE; | |
| 2338 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; | |
| 2339 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; | |
| 2340 CK_ULONG valueLen = 0; | |
| 2341 CK_MECHANISM mechanism; | |
| 2342 CK_SESSION_HANDLE rwsession; | |
| 2343 CK_RV crv; | |
| 2344 CK_MECHANISM_INFO mechanism_info; | |
| 2345 #define MAX_ADD_ATTRS 4 | |
| 2346 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; | |
| 2347 #undef MAX_ADD_ATTRS | |
| 2348 CK_ATTRIBUTE * attrs = keyTemplate; | |
| 2349 unsigned int templateCount; | |
| 2350 | |
| 2351 if (numAttrs > MAX_TEMPL_ATTRS) { | |
| 2352 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 2353 return NULL; | |
| 2354 } | |
| 2355 | |
| 2356 /* first copy caller attributes in. */ | |
| 2357 for (templateCount = 0; templateCount < numAttrs; ++templateCount) { | |
| 2358 *attrs++ = *userAttr++; | |
| 2359 } | |
| 2360 | |
| 2361 /* We only add the following attributes to the template if the caller | |
| 2362 ** didn't already supply them. | |
| 2363 */ | |
| 2364 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { | |
| 2365 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); | |
| 2366 attrs++; | |
| 2367 } | |
| 2368 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { | |
| 2369 keyType = PK11_GetKeyType(target, keySize); | |
| 2370 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType ); | |
| 2371 attrs++; | |
| 2372 } | |
| 2373 if ((operation != CKA_FLAGS_ONLY) && | |
| 2374 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { | |
| 2375 PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; | |
| 2376 } | |
| 2377 | |
| 2378 /* | |
| 2379 * must be last in case we need to use this template to import the key | |
| 2380 */ | |
| 2381 if (keySize > 0 && | |
| 2382 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { | |
| 2383 valueLen = (CK_ULONG)keySize; | |
| 2384 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); | |
| 2385 attrs++; | |
| 2386 } | |
| 2387 | |
| 2388 templateCount = attrs - keyTemplate; | |
| 2389 PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); | |
| 2390 | |
| 2391 | |
| 2392 /* find out if we can do wrap directly. Because the RSA case if *very* | |
| 2393 * common, cache the results for it. */ | |
| 2394 if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) { | |
| 2395 mechanism_info.flags = slot->RSAInfoFlags; | |
| 2396 } else { | |
| 2397 if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); | |
| 2398 crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,wrapType, | |
| 2399 &mechanism_info); | |
| 2400 if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); | |
| 2401 if (crv != CKR_OK) { | |
| 2402 mechanism_info.flags = 0; | |
| 2403 } | |
| 2404 if (wrapType == CKM_RSA_PKCS) { | |
| 2405 slot->RSAInfoFlags = mechanism_info.flags; | |
| 2406 slot->hasRSAInfo = PR_TRUE; | |
| 2407 } | |
| 2408 } | |
| 2409 | |
| 2410 /* initialize the mechanism structure */ | |
| 2411 mechanism.mechanism = wrapType; | |
| 2412 /* use NULL IV's for wrapping */ | |
| 2413 if (param == NULL) | |
| 2414 param = param_free = PK11_ParamFromIV(wrapType,NULL); | |
| 2415 if (param) { | |
| 2416 mechanism.pParameter = param->data; | |
| 2417 mechanism.ulParameterLen = param->len; | |
| 2418 } else { | |
| 2419 mechanism.pParameter = NULL; | |
| 2420 mechanism.ulParameterLen = 0; | |
| 2421 } | |
| 2422 | |
| 2423 if ((mechanism_info.flags & CKF_DECRYPT) | |
| 2424 && !PK11_DoesMechanism(slot,target)) { | |
| 2425 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, | |
| 2426 target, keyTemplate, templateCount, keySize, | |
| 2427 wincx, &crv, isPerm); | |
| 2428 if (symKey) { | |
| 2429 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); | |
| 2430 return symKey; | |
| 2431 } | |
| 2432 /* | |
| 2433 * if the RSA OP simply failed, don't try to unwrap again | |
| 2434 * with this module. | |
| 2435 */ | |
| 2436 if (crv == CKR_DEVICE_ERROR){ | |
| 2437 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); | |
| 2438 return NULL; | |
| 2439 } | |
| 2440 /* fall through, maybe they incorrectly set CKF_DECRYPT */ | |
| 2441 } | |
| 2442 | |
| 2443 /* get our key Structure */ | |
| 2444 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx); | |
| 2445 if (symKey == NULL) { | |
| 2446 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); | |
| 2447 return NULL; | |
| 2448 } | |
| 2449 | |
| 2450 symKey->size = keySize; | |
| 2451 symKey->origin = PK11_OriginUnwrap; | |
| 2452 | |
| 2453 if (isPerm) { | |
| 2454 rwsession = PK11_GetRWSession(slot); | |
| 2455 } else { | |
| 2456 pk11_EnterKeyMonitor(symKey); | |
| 2457 rwsession = symKey->session; | |
| 2458 } | |
| 2459 PORT_Assert(rwsession != CK_INVALID_SESSION); | |
| 2460 if (rwsession == CK_INVALID_SESSION) | |
| 2461 crv = CKR_SESSION_HANDLE_INVALID; | |
| 2462 else | |
| 2463 crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession,&mechanism,wrappingKey, | |
| 2464 wrappedKey->data, wrappedKey->len, keyTemplate, templateCount, | |
| 2465 &symKey->objectID); | |
| 2466 if (isPerm) { | |
| 2467 if (rwsession != CK_INVALID_SESSION) | |
| 2468 PK11_RestoreROSession(slot, rwsession); | |
| 2469 } else { | |
| 2470 pk11_ExitKeyMonitor(symKey); | |
| 2471 } | |
| 2472 if (param_free) SECITEM_FreeItem(param_free,PR_TRUE); | |
| 2473 if (crv != CKR_OK) { | |
| 2474 PK11_FreeSymKey(symKey); | |
| 2475 symKey = NULL; | |
| 2476 if (crv != CKR_DEVICE_ERROR) { | |
| 2477 /* try hand Unwrapping */ | |
| 2478 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, | |
| 2479 target, keyTemplate, templateCount, | |
| 2480 keySize, wincx, NULL, isPerm); | |
| 2481 } | |
| 2482 } | |
| 2483 | |
| 2484 return symKey; | |
| 2485 } | |
| 2486 | |
| 2487 /* use a symetric key to unwrap another symetric key */ | |
| 2488 PK11SymKey * | |
| 2489 PK11_UnwrapSymKey( PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, | |
| 2490 SECItem *param, SECItem *wrappedKey, | |
| 2491 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 2492 int keySize) | |
| 2493 { | |
| 2494 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, | |
| 2495 wrapType, param, wrappedKey, target, operation, keySize, | |
| 2496 wrappingKey->cx, NULL, 0, PR_FALSE); | |
| 2497 } | |
| 2498 | |
| 2499 /* use a symetric key to unwrap another symetric key */ | |
| 2500 PK11SymKey * | |
| 2501 PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, | |
| 2502 SECItem *param, SECItem *wrappedKey, | |
| 2503 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 2504 int keySize, CK_FLAGS flags) | |
| 2505 { | |
| 2506 CK_BBOOL ckTrue = CK_TRUE; | |
| 2507 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 2508 unsigned int templateCount; | |
| 2509 | |
| 2510 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); | |
| 2511 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, | |
| 2512 wrapType, param, wrappedKey, target, operation, keySize, | |
| 2513 wrappingKey->cx, keyTemplate, templateCount, PR_FALSE); | |
| 2514 } | |
| 2515 | |
| 2516 PK11SymKey * | |
| 2517 PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, | |
| 2518 CK_MECHANISM_TYPE wrapType, | |
| 2519 SECItem *param, SECItem *wrappedKey, | |
| 2520 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, | |
| 2521 int keySize, CK_FLAGS flags, PRBool isPerm) | |
| 2522 { | |
| 2523 CK_BBOOL cktrue = CK_TRUE; | |
| 2524 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 2525 CK_ATTRIBUTE *attrs; | |
| 2526 unsigned int templateCount; | |
| 2527 | |
| 2528 attrs = keyTemplate; | |
| 2529 if (isPerm) { | |
| 2530 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; | |
| 2531 } | |
| 2532 templateCount = attrs-keyTemplate; | |
| 2533 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); | |
| 2534 | |
| 2535 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, | |
| 2536 wrapType, param, wrappedKey, target, operation, keySize, | |
| 2537 wrappingKey->cx, keyTemplate, templateCount, isPerm); | |
| 2538 } | |
| 2539 | |
| 2540 | |
| 2541 /* unwrap a symetric key with a private key. */ | |
| 2542 PK11SymKey * | |
| 2543 PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, | |
| 2544 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) | |
| 2545 { | |
| 2546 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); | |
| 2547 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; | |
| 2548 | |
| 2549 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { | |
| 2550 PK11_HandlePasswordCheck(slot,wrappingKey->wincx); | |
| 2551 } | |
| 2552 | |
| 2553 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, | |
| 2554 wrapType, NULL, wrappedKey, target, operation, keySize, | |
| 2555 wrappingKey->wincx, NULL, 0, PR_FALSE); | |
| 2556 } | |
| 2557 | |
| 2558 /* unwrap a symetric key with a private key. */ | |
| 2559 PK11SymKey * | |
| 2560 PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, | |
| 2561 SECItem *wrappedKey, CK_MECHANISM_TYPE target, | |
| 2562 CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags) | |
| 2563 { | |
| 2564 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); | |
| 2565 CK_BBOOL ckTrue = CK_TRUE; | |
| 2566 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 2567 unsigned int templateCount; | |
| 2568 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; | |
| 2569 | |
| 2570 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); | |
| 2571 | |
| 2572 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { | |
| 2573 PK11_HandlePasswordCheck(slot,wrappingKey->wincx); | |
| 2574 } | |
| 2575 | |
| 2576 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, | |
| 2577 wrapType, NULL, wrappedKey, target, operation, keySize, | |
| 2578 wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE); | |
| 2579 } | |
| 2580 | |
| 2581 PK11SymKey * | |
| 2582 PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, | |
| 2583 SECItem *wrappedKey, CK_MECHANISM_TYPE target, | |
| 2584 CK_ATTRIBUTE_TYPE operation, int keySize, | |
| 2585 CK_FLAGS flags, PRBool isPerm) | |
| 2586 { | |
| 2587 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); | |
| 2588 CK_BBOOL cktrue = CK_TRUE; | |
| 2589 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; | |
| 2590 CK_ATTRIBUTE *attrs; | |
| 2591 unsigned int templateCount; | |
| 2592 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; | |
| 2593 | |
| 2594 attrs = keyTemplate; | |
| 2595 if (isPerm) { | |
| 2596 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); attrs++; | |
| 2597 } | |
| 2598 templateCount = attrs-keyTemplate; | |
| 2599 | |
| 2600 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); | |
| 2601 | |
| 2602 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey,CKA_PRIVATE)) { | |
| 2603 PK11_HandlePasswordCheck(slot,wrappingKey->wincx); | |
| 2604 } | |
| 2605 | |
| 2606 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, | |
| 2607 wrapType, NULL, wrappedKey, target, operation, keySize, | |
| 2608 wrappingKey->wincx, keyTemplate, templateCount, isPerm); | |
| 2609 } | |
| 2610 | |
| 2611 PK11SymKey* | |
| 2612 PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech) | |
| 2613 { | |
| 2614 CK_RV crv; | |
| 2615 CK_ATTRIBUTE setTemplate; | |
| 2616 CK_BBOOL ckTrue = CK_TRUE; | |
| 2617 PK11SlotInfo *slot = originalKey->slot; | |
| 2618 | |
| 2619 /* first just try to set this key up for signing */ | |
| 2620 PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue)); | |
| 2621 pk11_EnterKeyMonitor(originalKey); | |
| 2622 crv = PK11_GETTAB(slot)-> C_SetAttributeValue(originalKey->session, | |
| 2623 originalKey->objectID, &setTemplate, 1); | |
| 2624 pk11_ExitKeyMonitor(originalKey); | |
| 2625 if (crv == CKR_OK) { | |
| 2626 return PK11_ReferenceSymKey(originalKey); | |
| 2627 } | |
| 2628 | |
| 2629 /* nope, doesn't like it, use the pk11 copy object command */ | |
| 2630 return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey); | |
| 2631 } | |
| 2632 | |
| 2633 void | |
| 2634 PK11_SetFortezzaHack(PK11SymKey *symKey) { | |
| 2635 symKey->origin = PK11_OriginFortezzaHack; | |
| 2636 } | |
| 2637 | |
| 2638 /* | |
| 2639 * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4 | |
| 2640 * working. This function simply gets a valid IV for the keys. | |
| 2641 */ | |
| 2642 SECStatus | |
| 2643 PK11_GenerateFortezzaIV(PK11SymKey *symKey,unsigned char *iv,int len) | |
| 2644 { | |
| 2645 CK_MECHANISM mech_info; | |
| 2646 CK_ULONG count = 0; | |
| 2647 CK_RV crv; | |
| 2648 SECStatus rv = SECFailure; | |
| 2649 | |
| 2650 mech_info.mechanism = CKM_SKIPJACK_CBC64; | |
| 2651 mech_info.pParameter = iv; | |
| 2652 mech_info.ulParameterLen = len; | |
| 2653 | |
| 2654 /* generate the IV for fortezza */ | |
| 2655 PK11_EnterSlotMonitor(symKey->slot); | |
| 2656 crv=PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session, | |
| 2657 &mech_info, symKey->objectID); | |
| 2658 if (crv == CKR_OK) { | |
| 2659 PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session, | |
| 2660 NULL, &count); | |
| 2661 rv = SECSuccess; | |
| 2662 } | |
| 2663 PK11_ExitSlotMonitor(symKey->slot); | |
| 2664 return rv; | |
| 2665 } | |
| 2666 | |
| 2667 CK_OBJECT_HANDLE | |
| 2668 PK11_GetSymKeyHandle(PK11SymKey *symKey) | |
| 2669 { | |
| 2670 return symKey->objectID; | |
| 2671 } | |
| 2672 | |
| OLD | NEW |