pk11skey.c (117390B)
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 <stddef.h> 10 #include <limits.h> 11 12 #include "seccomon.h" 13 #include "secmod.h" 14 #include "nssilock.h" 15 #include "secmodi.h" 16 #include "secmodti.h" 17 #include "pkcs11.h" 18 #include "pk11func.h" 19 #include "secitem.h" 20 #include "secoid.h" 21 #include "secerr.h" 22 #include "hasht.h" 23 24 static ECPointEncoding pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey); 25 26 static void 27 pk11_EnterKeyMonitor(PK11SymKey *symKey) 28 { 29 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) 30 PK11_EnterSlotMonitor(symKey->slot); 31 } 32 33 static void 34 pk11_ExitKeyMonitor(PK11SymKey *symKey) 35 { 36 if (!symKey->sessionOwner || !(symKey->slot->isThreadSafe)) 37 PK11_ExitSlotMonitor(symKey->slot); 38 } 39 40 /* 41 * pk11_getKeyFromList returns a symKey that has a session (if needSession 42 * was specified), or explicitly does not have a session (if needSession 43 * was not specified). 44 */ 45 static PK11SymKey * 46 pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) 47 { 48 PK11SymKey *symKey = NULL; 49 50 PZ_Lock(slot->freeListLock); 51 /* own session list are symkeys with sessions that the symkey owns. 52 * 'most' symkeys will own their own session. */ 53 if (needSession) { 54 if (slot->freeSymKeysWithSessionHead) { 55 symKey = slot->freeSymKeysWithSessionHead; 56 slot->freeSymKeysWithSessionHead = symKey->next; 57 slot->keyCount--; 58 } 59 } 60 /* if we don't need a symkey with its own session, or we couldn't find 61 * one on the owner list, get one from the non-owner free list. */ 62 if (!symKey) { 63 if (slot->freeSymKeysHead) { 64 symKey = slot->freeSymKeysHead; 65 slot->freeSymKeysHead = symKey->next; 66 slot->keyCount--; 67 } 68 } 69 PZ_Unlock(slot->freeListLock); 70 if (symKey) { 71 symKey->next = NULL; 72 if (!needSession) { 73 return symKey; 74 } 75 /* if we are getting an owner key, make sure we have a valid session. 76 * session could be invalid if the token has been removed or because 77 * we got it from the non-owner free list */ 78 if ((symKey->series != slot->series) || 79 (symKey->session == CK_INVALID_HANDLE)) { 80 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); 81 } 82 PORT_Assert(symKey->session != CK_INVALID_HANDLE); 83 if (symKey->session != CK_INVALID_HANDLE) 84 return symKey; 85 PK11_FreeSymKey(symKey); 86 /* if we are here, we need a session, but couldn't get one, it's 87 * unlikely we pk11_GetNewSession will succeed if we call it a second 88 * time. */ 89 return NULL; 90 } 91 92 symKey = PORT_New(PK11SymKey); 93 if (symKey == NULL) { 94 return NULL; 95 } 96 97 symKey->next = NULL; 98 if (needSession) { 99 symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner); 100 PORT_Assert(symKey->session != CK_INVALID_HANDLE); 101 if (symKey->session == CK_INVALID_HANDLE) { 102 PK11_FreeSymKey(symKey); 103 symKey = NULL; 104 } 105 } else { 106 symKey->session = CK_INVALID_HANDLE; 107 } 108 return symKey; 109 } 110 111 /* Caller MUST hold slot->freeListLock (or ref count == 0?) !! */ 112 void 113 PK11_CleanKeyList(PK11SlotInfo *slot) 114 { 115 PK11SymKey *symKey = NULL; 116 117 while (slot->freeSymKeysWithSessionHead) { 118 symKey = slot->freeSymKeysWithSessionHead; 119 slot->freeSymKeysWithSessionHead = symKey->next; 120 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); 121 PORT_Free(symKey); 122 } 123 while (slot->freeSymKeysHead) { 124 symKey = slot->freeSymKeysHead; 125 slot->freeSymKeysHead = symKey->next; 126 pk11_CloseSession(slot, symKey->session, symKey->sessionOwner); 127 PORT_Free(symKey); 128 } 129 return; 130 } 131 132 /* 133 * create a symetric key: 134 * Slot is the slot to create the key in. 135 * type is the mechanism type 136 * owner is does this symKey structure own it's object handle (rare 137 * that this is false). 138 * needSession means the returned symKey will return with a valid session 139 * allocated already. 140 */ 141 static PK11SymKey * 142 pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 143 PRBool owner, PRBool needSession, void *wincx) 144 { 145 146 PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession); 147 148 if (symKey == NULL) { 149 return NULL; 150 } 151 /* if needSession was specified, make sure we have a valid session. 152 * callers which specify needSession as false should do their own 153 * check of the session before returning the symKey */ 154 if (needSession && symKey->session == CK_INVALID_HANDLE) { 155 PK11_FreeSymKey(symKey); 156 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 157 return NULL; 158 } 159 160 symKey->type = type; 161 symKey->data.type = siBuffer; 162 symKey->data.data = NULL; 163 symKey->data.len = 0; 164 symKey->owner = owner; 165 symKey->objectID = CK_INVALID_HANDLE; 166 symKey->slot = slot; 167 symKey->series = slot->series; 168 symKey->cx = wincx; 169 symKey->size = 0; 170 symKey->refCount = 1; 171 symKey->origin = PK11_OriginNULL; 172 symKey->parent = NULL; 173 symKey->freeFunc = NULL; 174 symKey->userData = NULL; 175 PK11_ReferenceSlot(slot); 176 return symKey; 177 } 178 179 /* 180 * destroy a symetric key 181 */ 182 void 183 PK11_FreeSymKey(PK11SymKey *symKey) 184 { 185 PK11SlotInfo *slot; 186 PRBool freeit = PR_TRUE; 187 188 if (!symKey) { 189 return; 190 } 191 192 if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) { 193 PK11SymKey *parent = symKey->parent; 194 195 symKey->parent = NULL; 196 if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { 197 pk11_EnterKeyMonitor(symKey); 198 (void)PK11_GETTAB(symKey->slot)->C_DestroyObject(symKey->session, symKey->objectID); 199 pk11_ExitKeyMonitor(symKey); 200 } 201 if (symKey->data.data) { 202 PORT_Memset(symKey->data.data, 0, symKey->data.len); 203 PORT_Free(symKey->data.data); 204 } 205 /* free any existing data */ 206 if (symKey->userData && symKey->freeFunc) { 207 (*symKey->freeFunc)(symKey->userData); 208 } 209 slot = symKey->slot; 210 PZ_Lock(slot->freeListLock); 211 if (slot->keyCount < slot->maxKeyCount) { 212 /* 213 * freeSymkeysWithSessionHead contain a list of reusable 214 * SymKey structures with valid sessions. 215 * sessionOwner must be true. 216 * session must be valid. 217 * freeSymKeysHead contain a list of SymKey structures without 218 * valid session. 219 * session must be CK_INVALID_HANDLE. 220 * though sessionOwner is false, callers should not depend on 221 * this fact. 222 */ 223 if (symKey->sessionOwner) { 224 PORT_Assert(symKey->session != CK_INVALID_HANDLE); 225 symKey->next = slot->freeSymKeysWithSessionHead; 226 slot->freeSymKeysWithSessionHead = symKey; 227 } else { 228 symKey->session = CK_INVALID_HANDLE; 229 symKey->next = slot->freeSymKeysHead; 230 slot->freeSymKeysHead = symKey; 231 } 232 slot->keyCount++; 233 symKey->slot = NULL; 234 freeit = PR_FALSE; 235 } 236 PZ_Unlock(slot->freeListLock); 237 if (freeit) { 238 pk11_CloseSession(symKey->slot, symKey->session, 239 symKey->sessionOwner); 240 PORT_Free(symKey); 241 } 242 PK11_FreeSlot(slot); 243 244 if (parent) { 245 PK11_FreeSymKey(parent); 246 } 247 } 248 } 249 250 PK11SymKey * 251 PK11_ReferenceSymKey(PK11SymKey *symKey) 252 { 253 PR_ATOMIC_INCREMENT(&symKey->refCount); 254 return symKey; 255 } 256 257 /* 258 * Accessors 259 */ 260 CK_MECHANISM_TYPE 261 PK11_GetMechanism(PK11SymKey *symKey) 262 { 263 return symKey->type; 264 } 265 266 /* 267 * return the slot associated with a symetric key 268 */ 269 PK11SlotInfo * 270 PK11_GetSlotFromKey(PK11SymKey *symKey) 271 { 272 return PK11_ReferenceSlot(symKey->slot); 273 } 274 275 CK_KEY_TYPE 276 PK11_GetSymKeyType(PK11SymKey *symKey) 277 { 278 return PK11_GetKeyType(symKey->type, symKey->size); 279 } 280 281 PK11SymKey * 282 PK11_GetNextSymKey(PK11SymKey *symKey) 283 { 284 return symKey ? symKey->next : NULL; 285 } 286 287 char * 288 PK11_GetSymKeyNickname(PK11SymKey *symKey) 289 { 290 return PK11_GetObjectNickname(symKey->slot, symKey->objectID); 291 } 292 293 SECStatus 294 PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname) 295 { 296 return PK11_SetObjectNickname(symKey->slot, symKey->objectID, nickname); 297 } 298 299 void * 300 PK11_GetSymKeyUserData(PK11SymKey *symKey) 301 { 302 return symKey->userData; 303 } 304 305 void 306 PK11_SetSymKeyUserData(PK11SymKey *symKey, void *userData, 307 PK11FreeDataFunc freeFunc) 308 { 309 /* free any existing data */ 310 if (symKey->userData && symKey->freeFunc) { 311 (*symKey->freeFunc)(symKey->userData); 312 } 313 symKey->userData = userData; 314 symKey->freeFunc = freeFunc; 315 return; 316 } 317 318 /* 319 * turn key handle into an appropriate key object 320 */ 321 PK11SymKey * 322 PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, 323 CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID, PRBool owner, void *wincx) 324 { 325 PK11SymKey *symKey; 326 PRBool needSession = !(owner && parent); 327 328 if (keyID == CK_INVALID_HANDLE) { 329 return NULL; 330 } 331 332 symKey = pk11_CreateSymKey(slot, type, owner, needSession, wincx); 333 if (symKey == NULL) { 334 return NULL; 335 } 336 337 symKey->objectID = keyID; 338 symKey->origin = origin; 339 340 /* adopt the parent's session */ 341 /* This is only used by SSL. What we really want here is a session 342 * structure with a ref count so the session goes away only after all the 343 * keys do. */ 344 if (!needSession) { 345 symKey->sessionOwner = PR_FALSE; 346 symKey->session = parent->session; 347 symKey->parent = PK11_ReferenceSymKey(parent); 348 /* This is the only case where pk11_CreateSymKey does not explicitly 349 * check symKey->session. We need to assert here to make sure. 350 * the session isn't invalid. */ 351 PORT_Assert(parent->session != CK_INVALID_HANDLE); 352 if (parent->session == CK_INVALID_HANDLE) { 353 PK11_FreeSymKey(symKey); 354 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 355 return NULL; 356 } 357 } 358 359 return symKey; 360 } 361 362 /* 363 * Restore a symmetric wrapping key that was saved using PK11_SetWrapKey. 364 * 365 * This function is provided for ABI compatibility; see PK11_SetWrapKey below. 366 */ 367 PK11SymKey * 368 PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, 369 int series, void *wincx) 370 { 371 PK11SymKey *symKey = NULL; 372 CK_OBJECT_HANDLE keyHandle; 373 374 PK11_EnterSlotMonitor(slot); 375 if (slot->series != series || 376 slot->refKeys[wrap] == CK_INVALID_HANDLE) { 377 PK11_ExitSlotMonitor(slot); 378 return NULL; 379 } 380 381 if (type == CKM_INVALID_MECHANISM) { 382 type = slot->wrapMechanism; 383 } 384 385 keyHandle = slot->refKeys[wrap]; 386 PK11_ExitSlotMonitor(slot); 387 symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, 388 slot->wrapMechanism, keyHandle, PR_FALSE, wincx); 389 return symKey; 390 } 391 392 /* 393 * This function sets an attribute on the current slot with a wrapping key. The 394 * data saved is ephemeral; it needs to be run every time the program is 395 * invoked. 396 * 397 * Since NSS 3.45, this function is marginally more thread safe. It uses the 398 * slot lock (if present) and fails silently if a value is already set. Use 399 * PK11_GetWrapKey() after calling this function to get the current wrapping key 400 * in case there was an update on another thread. 401 * 402 * Either way, using this function is inadvisable. It's provided for ABI 403 * compatibility only. 404 */ 405 void 406 PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey) 407 { 408 PK11_EnterSlotMonitor(slot); 409 if (wrap >= 0) { 410 size_t uwrap = (size_t)wrap; 411 if (uwrap < PR_ARRAY_SIZE(slot->refKeys) && 412 slot->refKeys[uwrap] == CK_INVALID_HANDLE) { 413 /* save the handle and mechanism for the wrapping key */ 414 /* mark the key and session as not owned by us so they don't get 415 * freed when the key goes way... that lets us reuse the key 416 * later */ 417 slot->refKeys[uwrap] = wrapKey->objectID; 418 wrapKey->owner = PR_FALSE; 419 wrapKey->sessionOwner = PR_FALSE; 420 slot->wrapMechanism = wrapKey->type; 421 } 422 } 423 PK11_ExitSlotMonitor(slot); 424 } 425 426 /* 427 * figure out if a key is still valid or if it is stale. 428 */ 429 PRBool 430 PK11_VerifyKeyOK(PK11SymKey *key) 431 { 432 if (!PK11_IsPresent(key->slot)) { 433 return PR_FALSE; 434 } 435 return (PRBool)(key->series == key->slot->series); 436 } 437 438 static PK11SymKey * 439 pk11_ImportSymKeyWithTempl(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 440 PK11Origin origin, PRBool isToken, CK_ATTRIBUTE *keyTemplate, 441 unsigned int templateCount, SECItem *key, void *wincx) 442 { 443 PK11SymKey *symKey; 444 SECStatus rv; 445 446 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); 447 if (symKey == NULL) { 448 return NULL; 449 } 450 451 symKey->size = key->len; 452 453 PK11_SETATTRS(&keyTemplate[templateCount], CKA_VALUE, key->data, key->len); 454 templateCount++; 455 456 if (SECITEM_CopyItem(NULL, &symKey->data, key) != SECSuccess) { 457 PK11_FreeSymKey(symKey); 458 return NULL; 459 } 460 461 symKey->origin = origin; 462 463 /* import the keys */ 464 rv = PK11_CreateNewObject(slot, symKey->session, keyTemplate, 465 templateCount, isToken, &symKey->objectID); 466 if (rv != SECSuccess) { 467 PK11_FreeSymKey(symKey); 468 return NULL; 469 } 470 471 return symKey; 472 } 473 474 /* 475 * turn key bits into an appropriate key object 476 */ 477 PK11SymKey * 478 PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 479 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx) 480 { 481 PK11SymKey *symKey; 482 unsigned int templateCount = 0; 483 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 484 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 485 CK_BBOOL cktrue = CK_TRUE; /* sigh */ 486 CK_ATTRIBUTE keyTemplate[5]; 487 CK_ATTRIBUTE *attrs = keyTemplate; 488 489 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 490 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 491 * it as a real attribute */ 492 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 493 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 494 * etc. Strip out the real attribute here */ 495 operation &= ~CKA_NSS_MESSAGE_MASK; 496 } 497 498 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 499 attrs++; 500 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 501 attrs++; 502 PK11_SETATTRS(attrs, operation, &cktrue, 1); 503 attrs++; 504 templateCount = attrs - keyTemplate; 505 PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 506 507 keyType = PK11_GetKeyType(type, key->len); 508 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, PR_FALSE, 509 keyTemplate, templateCount, key, wincx); 510 return symKey; 511 } 512 /* Import a PKCS #11 data object and return it as a key. This key is 513 * only useful in a limited number of mechanisms, such as HKDF. */ 514 PK11SymKey * 515 PK11_ImportDataKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, PK11Origin origin, 516 CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx) 517 { 518 CK_OBJECT_CLASS ckoData = CKO_DATA; 519 CK_ATTRIBUTE template[2] = { { CKA_CLASS, (CK_BYTE_PTR)&ckoData, sizeof(ckoData) }, 520 { CKA_VALUE, (CK_BYTE_PTR)key->data, key->len } }; 521 CK_OBJECT_HANDLE handle; 522 PK11GenericObject *genObject; 523 524 genObject = PK11_CreateGenericObject(slot, template, PR_ARRAY_SIZE(template), PR_FALSE); 525 if (genObject == NULL) { 526 return NULL; 527 } 528 handle = PK11_GetObjectHandle(PK11_TypeGeneric, genObject, NULL); 529 /* A note about ownership of the PKCS #11 handle: 530 * PK11_CreateGenericObject() will not destroy the object it creates 531 * on Free, For that you want PK11_CreateManagedGenericObject(). 532 * Below we import the handle into the symKey structure. We pass 533 * PR_TRUE as the owner so that the symKey will destroy the object 534 * once it's freed. This is why it's safe to destroy genObject now. */ 535 PK11_DestroyGenericObject(genObject); 536 if (handle == CK_INVALID_HANDLE) { 537 return NULL; 538 } 539 return PK11_SymKeyFromHandle(slot, NULL, origin, type, handle, PR_TRUE, wincx); 540 } 541 542 /* turn key bits into an appropriate key object */ 543 PK11SymKey * 544 PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 545 PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, 546 CK_FLAGS flags, PRBool isPerm, void *wincx) 547 { 548 PK11SymKey *symKey; 549 unsigned int templateCount = 0; 550 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 551 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 552 CK_BBOOL cktrue = CK_TRUE; /* sigh */ 553 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 554 CK_ATTRIBUTE *attrs = keyTemplate; 555 556 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 557 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 558 * it as a real attribute */ 559 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 560 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 561 * etc. Strip out the real attribute here */ 562 operation &= ~CKA_NSS_MESSAGE_MASK; 563 } 564 565 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 566 attrs++; 567 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 568 attrs++; 569 if (isPerm) { 570 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); 571 attrs++; 572 /* sigh some tokens think CKA_PRIVATE = false is a reasonable 573 * default for secret keys */ 574 PK11_SETATTRS(attrs, CKA_PRIVATE, &cktrue, sizeof(cktrue)); 575 attrs++; 576 } 577 attrs += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 578 if ((operation != CKA_FLAGS_ONLY) && 579 !pk11_FindAttrInTemplate(keyTemplate, attrs - keyTemplate, operation)) { 580 PK11_SETATTRS(attrs, operation, &cktrue, sizeof(cktrue)); 581 attrs++; 582 } 583 templateCount = attrs - keyTemplate; 584 PR_ASSERT(templateCount + 1 <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 585 586 keyType = PK11_GetKeyType(type, key->len); 587 symKey = pk11_ImportSymKeyWithTempl(slot, type, origin, isPerm, 588 keyTemplate, templateCount, key, wincx); 589 if (symKey && isPerm) { 590 symKey->owner = PR_FALSE; 591 } 592 return symKey; 593 } 594 595 PK11SymKey * 596 PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, 597 void *wincx) 598 { 599 CK_ATTRIBUTE findTemp[5]; 600 CK_ATTRIBUTE *attrs; 601 CK_BBOOL ckTrue = CK_TRUE; 602 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; 603 size_t tsize = 0; 604 CK_OBJECT_HANDLE key_id; 605 CK_KEY_TYPE keyType = PK11_GetKeyType(type, 0); 606 607 attrs = findTemp; 608 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); 609 attrs++; 610 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); 611 attrs++; 612 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 613 attrs++; 614 if (keyID) { 615 PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len); 616 attrs++; 617 } 618 tsize = attrs - findTemp; 619 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)); 620 621 key_id = pk11_FindObjectByTemplate(slot, findTemp, tsize); 622 if (key_id == CK_INVALID_HANDLE) { 623 return NULL; 624 } 625 return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, 626 PR_FALSE, wincx); 627 } 628 629 PK11SymKey * 630 PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname, void *wincx) 631 { 632 CK_ATTRIBUTE findTemp[4]; 633 CK_ATTRIBUTE *attrs; 634 CK_BBOOL ckTrue = CK_TRUE; 635 CK_OBJECT_CLASS keyclass = CKO_SECRET_KEY; 636 int tsize = 0; 637 int objCount = 0; 638 CK_OBJECT_HANDLE *key_ids; 639 PK11SymKey *nextKey = NULL; 640 PK11SymKey *topKey = NULL; 641 int i, len; 642 643 attrs = findTemp; 644 PK11_SETATTRS(attrs, CKA_CLASS, &keyclass, sizeof(keyclass)); 645 attrs++; 646 PK11_SETATTRS(attrs, CKA_TOKEN, &ckTrue, sizeof(ckTrue)); 647 attrs++; 648 if (nickname) { 649 len = PORT_Strlen(nickname); 650 PK11_SETATTRS(attrs, CKA_LABEL, nickname, len); 651 attrs++; 652 } 653 tsize = attrs - findTemp; 654 PORT_Assert(tsize <= sizeof(findTemp) / sizeof(CK_ATTRIBUTE)); 655 656 key_ids = pk11_FindObjectsByTemplate(slot, findTemp, tsize, &objCount); 657 if (key_ids == NULL) { 658 return NULL; 659 } 660 661 for (i = 0; i < objCount; i++) { 662 SECItem typeData; 663 CK_KEY_TYPE type = CKK_GENERIC_SECRET; 664 SECStatus rv = PK11_ReadAttribute(slot, key_ids[i], 665 CKA_KEY_TYPE, NULL, &typeData); 666 if (rv == SECSuccess) { 667 if (typeData.len == sizeof(CK_KEY_TYPE)) { 668 type = *(CK_KEY_TYPE *)typeData.data; 669 } 670 PORT_Free(typeData.data); 671 } 672 nextKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, 673 PK11_GetKeyMechanism(type), key_ids[i], PR_FALSE, wincx); 674 if (nextKey) { 675 nextKey->next = topKey; 676 topKey = nextKey; 677 } 678 } 679 PORT_Free(key_ids); 680 return topKey; 681 } 682 683 void * 684 PK11_GetWindow(PK11SymKey *key) 685 { 686 return key->cx; 687 } 688 689 /* 690 * extract a symmetric key value. NOTE: if the key is sensitive, we will 691 * not be able to do this operation. This function is used to move 692 * keys from one token to another */ 693 SECStatus 694 PK11_ExtractKeyValue(PK11SymKey *symKey) 695 { 696 SECStatus rv; 697 698 if (symKey == NULL) { 699 PORT_SetError(SEC_ERROR_INVALID_ARGS); 700 return SECFailure; 701 } 702 703 if (symKey->data.data != NULL) { 704 if (symKey->size == 0) { 705 symKey->size = symKey->data.len; 706 } 707 return SECSuccess; 708 } 709 710 if (symKey->slot == NULL) { 711 PORT_SetError(SEC_ERROR_INVALID_KEY); 712 return SECFailure; 713 } 714 715 rv = PK11_ReadAttribute(symKey->slot, symKey->objectID, CKA_VALUE, NULL, 716 &symKey->data); 717 if (rv == SECSuccess) { 718 symKey->size = symKey->data.len; 719 } 720 return rv; 721 } 722 723 SECStatus 724 PK11_DeleteTokenSymKey(PK11SymKey *symKey) 725 { 726 if (!PK11_IsPermObject(symKey->slot, symKey->objectID)) { 727 return SECFailure; 728 } 729 PK11_DestroyTokenObject(symKey->slot, symKey->objectID); 730 symKey->objectID = CK_INVALID_HANDLE; 731 return SECSuccess; 732 } 733 734 SECItem * 735 PK11_GetKeyData(PK11SymKey *symKey) 736 { 737 return &symKey->data; 738 } 739 740 /* This symbol is exported for backward compatibility. */ 741 SECItem * 742 __PK11_GetKeyData(PK11SymKey *symKey) 743 { 744 return PK11_GetKeyData(symKey); 745 } 746 747 /* 748 * PKCS #11 key Types with predefined length 749 */ 750 unsigned int 751 pk11_GetPredefinedKeyLength(CK_KEY_TYPE keyType) 752 { 753 int length = 0; 754 switch (keyType) { 755 case CKK_DES: 756 length = 8; 757 break; 758 case CKK_DES2: 759 length = 16; 760 break; 761 case CKK_DES3: 762 length = 24; 763 break; 764 case CKK_SKIPJACK: 765 length = 10; 766 break; 767 case CKK_BATON: 768 length = 20; 769 break; 770 case CKK_JUNIPER: 771 length = 20; 772 break; 773 default: 774 break; 775 } 776 return length; 777 } 778 779 /* return the keylength if possible. '0' if not */ 780 unsigned int 781 PK11_GetKeyLength(PK11SymKey *key) 782 { 783 CK_KEY_TYPE keyType; 784 785 if (key->size != 0) 786 return key->size; 787 788 /* First try to figure out the key length from its type */ 789 keyType = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_KEY_TYPE); 790 key->size = pk11_GetPredefinedKeyLength(keyType); 791 if ((keyType == CKK_GENERIC_SECRET) && 792 (key->type == CKM_SSL3_PRE_MASTER_KEY_GEN)) { 793 key->size = 48; 794 } 795 796 if (key->size != 0) 797 return key->size; 798 799 if (key->data.data == NULL) { 800 PK11_ExtractKeyValue(key); 801 } 802 /* key is probably secret. Look up its length */ 803 /* this is new PKCS #11 version 2.0 functionality. */ 804 if (key->size == 0) { 805 CK_ULONG keyLength; 806 807 keyLength = PK11_ReadULongAttribute(key->slot, key->objectID, CKA_VALUE_LEN); 808 if (keyLength != CK_UNAVAILABLE_INFORMATION) { 809 key->size = (unsigned int)keyLength; 810 } 811 } 812 813 return key->size; 814 } 815 816 /* return the strength of a key. This is different from length in that 817 * 1) it returns the size in bits, and 2) it returns only the secret portions 818 * of the key minus any checksums or parity. 819 */ 820 unsigned int 821 PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid) 822 { 823 int size = 0; 824 CK_MECHANISM_TYPE mechanism = CKM_INVALID_MECHANISM; /* RC2 only */ 825 SECItem *param = NULL; /* RC2 only */ 826 CK_RC2_CBC_PARAMS *rc2_params = NULL; /* RC2 ONLY */ 827 unsigned int effectiveBits = 0; /* RC2 ONLY */ 828 829 switch (PK11_GetKeyType(key->type, 0)) { 830 case CKK_CDMF: 831 return 40; 832 case CKK_DES: 833 return 56; 834 case CKK_DES3: 835 case CKK_DES2: 836 size = PK11_GetKeyLength(key); 837 if (size == 16) { 838 /* double des */ 839 return 112; /* 16*7 */ 840 } 841 return 168; 842 /* 843 * RC2 has is different than other ciphers in that it allows the user 844 * to deprecating keysize while still requiring all the bits for the 845 * original key. The info 846 * on what the effective key strength is in the parameter for the key. 847 * In S/MIME this parameter is stored in the DER encoded algid. In Our 848 * other uses of RC2, effectiveBits == keyBits, so this code functions 849 * correctly without an algid. 850 */ 851 case CKK_RC2: 852 /* if no algid was provided, fall through to default */ 853 if (!algid) { 854 break; 855 } 856 /* verify that the algid is for RC2 */ 857 mechanism = PK11_AlgtagToMechanism(SECOID_GetAlgorithmTag(algid)); 858 if ((mechanism != CKM_RC2_CBC) && (mechanism != CKM_RC2_ECB)) { 859 break; 860 } 861 862 /* now get effective bits from the algorithm ID. */ 863 param = PK11_ParamFromAlgid(algid); 864 /* if we couldn't get memory just use key length */ 865 if (param == NULL) { 866 break; 867 } 868 869 rc2_params = (CK_RC2_CBC_PARAMS *)param->data; 870 /* paranoia... shouldn't happen */ 871 PORT_Assert(param->data != NULL); 872 if (param->data == NULL) { 873 SECITEM_FreeItem(param, PR_TRUE); 874 break; 875 } 876 effectiveBits = (unsigned int)rc2_params->ulEffectiveBits; 877 SECITEM_FreeItem(param, PR_TRUE); 878 param = NULL; 879 rc2_params = NULL; /* paranoia */ 880 881 /* we have effective bits, is and allocated memory is free, now 882 * we need to return the smaller of effective bits and keysize */ 883 size = PK11_GetKeyLength(key); 884 if ((unsigned int)size * 8 > effectiveBits) { 885 return effectiveBits; 886 } 887 888 return size * 8; /* the actual key is smaller, the strength can't be 889 * greater than the actual key size */ 890 891 default: 892 break; 893 } 894 return PK11_GetKeyLength(key) * 8; 895 } 896 897 /* 898 * The next three utilities are to deal with the fact that a given operation 899 * may be a multi-slot affair. This creates a new key object that is copied 900 * into the new slot. 901 */ 902 PK11SymKey * 903 pk11_CopyToSlotPerm(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 904 CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, 905 PRBool isPerm, PK11SymKey *symKey) 906 { 907 SECStatus rv; 908 PK11SymKey *newKey = NULL; 909 910 /* Extract the raw key data if possible */ 911 if (symKey->data.data == NULL) { 912 rv = PK11_ExtractKeyValue(symKey); 913 /* KEY is sensitive, we're try key exchanging it. */ 914 if (rv != SECSuccess) { 915 return pk11_KeyExchange(slot, type, operation, 916 flags, isPerm, symKey); 917 } 918 } 919 920 newKey = PK11_ImportSymKeyWithFlags(slot, type, symKey->origin, 921 operation, &symKey->data, flags, isPerm, symKey->cx); 922 if (newKey == NULL) { 923 newKey = pk11_KeyExchange(slot, type, operation, flags, isPerm, symKey); 924 } 925 return newKey; 926 } 927 928 PK11SymKey * 929 pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 930 CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey) 931 { 932 return pk11_CopyToSlotPerm(slot, type, operation, 0, PR_FALSE, symKey); 933 } 934 935 /* 936 * Make sure the slot we are in is the correct slot for the operation 937 * by verifying that it supports all of the specified mechanism types. 938 */ 939 PK11SymKey * 940 pk11_ForceSlotMultiple(PK11SymKey *symKey, CK_MECHANISM_TYPE *type, 941 int mechCount, CK_ATTRIBUTE_TYPE operation) 942 { 943 PK11SlotInfo *slot = symKey->slot; 944 PK11SymKey *newKey = NULL; 945 PRBool needToCopy = PR_FALSE; 946 int i; 947 948 if (slot == NULL) { 949 needToCopy = PR_TRUE; 950 } else { 951 i = 0; 952 while ((i < mechCount) && (needToCopy == PR_FALSE)) { 953 if (!PK11_DoesMechanism(slot, type[i])) { 954 needToCopy = PR_TRUE; 955 } 956 i++; 957 } 958 } 959 960 if (needToCopy == PR_TRUE) { 961 slot = PK11_GetBestSlotMultiple(type, mechCount, symKey->cx); 962 if (slot == NULL) { 963 PORT_SetError(SEC_ERROR_NO_MODULE); 964 return NULL; 965 } 966 newKey = pk11_CopyToSlot(slot, type[0], operation, symKey); 967 PK11_FreeSlot(slot); 968 } 969 return newKey; 970 } 971 972 /* 973 * Make sure the slot we are in is the correct slot for the operation 974 */ 975 PK11SymKey * 976 pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type, 977 CK_ATTRIBUTE_TYPE operation) 978 { 979 return pk11_ForceSlotMultiple(symKey, &type, 1, operation); 980 } 981 982 PK11SymKey * 983 PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation, 984 CK_FLAGS flags, PRBool perm, PK11SymKey *symKey) 985 { 986 if (symKey->slot == slot) { 987 if (perm) { 988 return PK11_ConvertSessionSymKeyToTokenSymKey(symKey, symKey->cx); 989 } else { 990 return PK11_ReferenceSymKey(symKey); 991 } 992 } 993 994 return pk11_CopyToSlotPerm(slot, symKey->type, 995 operation, flags, perm, symKey); 996 } 997 998 /* 999 * Use the token to generate a key. 1000 * 1001 * keySize must be 'zero' for fixed key length algorithms. A nonzero 1002 * keySize causes the CKA_VALUE_LEN attribute to be added to the template 1003 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN 1004 * attribute for keys with fixed length. The exception is DES2. If you 1005 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN 1006 * parameter and use the key size to determine which underlying DES keygen 1007 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). 1008 * 1009 * keyType must be -1 for most algorithms. Some PBE algorthims cannot 1010 * determine the correct key type from the mechanism or the parameters, 1011 * so key type must be specified. Other PKCS #11 mechanisms may do so in 1012 * the future. Currently there is no need to export this publically. 1013 * Keep it private until there is a need in case we need to expand the 1014 * keygen parameters again... 1015 * 1016 * CK_FLAGS flags: key operation flags 1017 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags 1018 */ 1019 PK11SymKey * 1020 pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1021 SECItem *param, CK_KEY_TYPE keyType, int keySize, SECItem *keyid, 1022 CK_FLAGS opFlags, PK11AttrFlags attrFlags, void *wincx) 1023 { 1024 PK11SymKey *symKey; 1025 CK_ATTRIBUTE genTemplate[MAX_TEMPL_ATTRS]; 1026 CK_ATTRIBUTE *attrs = genTemplate; 1027 int count = sizeof(genTemplate) / sizeof(genTemplate[0]); 1028 CK_MECHANISM_TYPE keyGenType; 1029 CK_BBOOL cktrue = CK_TRUE; 1030 CK_BBOOL ckfalse = CK_FALSE; 1031 CK_ULONG ck_key_size; /* only used for variable-length keys */ 1032 1033 if (pk11_BadAttrFlags(attrFlags)) { 1034 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1035 return NULL; 1036 } 1037 1038 if ((keySize != 0) && (type != CKM_DES3_CBC) && 1039 (type != CKM_DES3_CBC_PAD) && (type != CKM_DES3_ECB)) { 1040 ck_key_size = keySize; /* Convert to PK11 type */ 1041 1042 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &ck_key_size, sizeof(ck_key_size)); 1043 attrs++; 1044 } 1045 1046 if (keyType != -1) { 1047 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(CK_KEY_TYPE)); 1048 attrs++; 1049 } 1050 1051 /* Include key id value if provided */ 1052 if (keyid) { 1053 PK11_SETATTRS(attrs, CKA_ID, keyid->data, keyid->len); 1054 attrs++; 1055 } 1056 1057 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); 1058 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); 1059 1060 count = attrs - genTemplate; 1061 PR_ASSERT(count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE)); 1062 1063 keyGenType = PK11_GetKeyGenWithSize(type, keySize); 1064 if (keyGenType == CKM_FAKE_RANDOM) { 1065 PORT_SetError(SEC_ERROR_NO_MODULE); 1066 return NULL; 1067 } 1068 symKey = PK11_KeyGenWithTemplate(slot, type, keyGenType, 1069 param, genTemplate, count, wincx); 1070 if (symKey != NULL) { 1071 symKey->size = keySize; 1072 } 1073 return symKey; 1074 } 1075 1076 /* 1077 * Use the token to generate a key. - Public 1078 * 1079 * keySize must be 'zero' for fixed key length algorithms. A nonzero 1080 * keySize causes the CKA_VALUE_LEN attribute to be added to the template 1081 * for the key. Most PKCS #11 modules fail if you specify the CKA_VALUE_LEN 1082 * attribute for keys with fixed length. The exception is DES2. If you 1083 * select a CKM_DES3_CBC mechanism, this code will not add the CKA_VALUE_LEN 1084 * parameter and use the key size to determine which underlying DES keygen 1085 * function to use (CKM_DES2_KEY_GEN or CKM_DES3_KEY_GEN). 1086 * 1087 * CK_FLAGS flags: key operation flags 1088 * PK11AttrFlags attrFlags: PK11_ATTR_XXX key attribute flags 1089 */ 1090 PK11SymKey * 1091 PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1092 SECItem *param, int keySize, SECItem *keyid, CK_FLAGS opFlags, 1093 PK11AttrFlags attrFlags, void *wincx) 1094 { 1095 return pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, -1, keySize, 1096 keyid, opFlags, attrFlags, wincx); 1097 } 1098 1099 /* 1100 * Use the token to generate a key. keySize must be 'zero' for fixed key 1101 * length algorithms. A nonzero keySize causes the CKA_VALUE_LEN attribute 1102 * to be added to the template for the key. PKCS #11 modules fail if you 1103 * specify the CKA_VALUE_LEN attribute for keys with fixed length. 1104 * NOTE: this means to generate a DES2 key from this interface you must 1105 * specify CKM_DES2_KEY_GEN as the mechanism directly; specifying 1106 * CKM_DES3_CBC as the mechanism and 16 as keySize currently doesn't work. 1107 */ 1108 PK11SymKey * 1109 PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, 1110 int keySize, SECItem *keyid, PRBool isToken, void *wincx) 1111 { 1112 PK11SymKey *symKey; 1113 PRBool weird = PR_FALSE; /* hack for fortezza */ 1114 CK_FLAGS opFlags = CKF_SIGN; 1115 PK11AttrFlags attrFlags = 0; 1116 1117 if ((keySize == -1) && (type == CKM_SKIPJACK_CBC64)) { 1118 weird = PR_TRUE; 1119 keySize = 0; 1120 } 1121 1122 opFlags |= weird ? CKF_DECRYPT : CKF_ENCRYPT; 1123 1124 if (isToken) { 1125 attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); 1126 } 1127 1128 symKey = pk11_TokenKeyGenWithFlagsAndKeyType(slot, type, param, 1129 -1, keySize, keyid, opFlags, attrFlags, wincx); 1130 if (symKey && weird) { 1131 PK11_SetFortezzaHack(symKey); 1132 } 1133 1134 return symKey; 1135 } 1136 1137 PK11SymKey * 1138 PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *param, 1139 int keySize, void *wincx) 1140 { 1141 return PK11_TokenKeyGen(slot, type, param, keySize, 0, PR_FALSE, wincx); 1142 } 1143 1144 PK11SymKey * 1145 PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 1146 CK_MECHANISM_TYPE keyGenType, 1147 SECItem *param, CK_ATTRIBUTE *attrs, 1148 unsigned int attrsCount, void *wincx) 1149 { 1150 PK11SymKey *symKey; 1151 CK_SESSION_HANDLE session; 1152 CK_MECHANISM mechanism; 1153 CK_RV crv; 1154 PRBool isToken = CK_FALSE; 1155 CK_ULONG keySize = 0; 1156 unsigned i; 1157 1158 /* Extract the template's CKA_VALUE_LEN into keySize and CKA_TOKEN into 1159 isToken. */ 1160 for (i = 0; i < attrsCount; ++i) { 1161 switch (attrs[i].type) { 1162 case CKA_VALUE_LEN: 1163 if (attrs[i].pValue == NULL || 1164 attrs[i].ulValueLen != sizeof(CK_ULONG)) { 1165 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); 1166 return NULL; 1167 } 1168 keySize = *(CK_ULONG *)attrs[i].pValue; 1169 break; 1170 case CKA_TOKEN: 1171 if (attrs[i].pValue == NULL || 1172 attrs[i].ulValueLen != sizeof(CK_BBOOL)) { 1173 PORT_SetError(PK11_MapError(CKR_TEMPLATE_INCONSISTENT)); 1174 return NULL; 1175 } 1176 isToken = (*(CK_BBOOL *)attrs[i].pValue) ? PR_TRUE : PR_FALSE; 1177 break; 1178 } 1179 } 1180 1181 /* find a slot to generate the key into */ 1182 /* Only do slot management if this is not a token key */ 1183 if (!isToken && (slot == NULL || !PK11_DoesMechanism(slot, type))) { 1184 PK11SlotInfo *bestSlot = PK11_GetBestSlot(type, wincx); 1185 if (bestSlot == NULL) { 1186 PORT_SetError(SEC_ERROR_NO_MODULE); 1187 return NULL; 1188 } 1189 symKey = pk11_CreateSymKey(bestSlot, type, !isToken, PR_TRUE, wincx); 1190 PK11_FreeSlot(bestSlot); 1191 } else { 1192 symKey = pk11_CreateSymKey(slot, type, !isToken, PR_TRUE, wincx); 1193 } 1194 if (symKey == NULL) 1195 return NULL; 1196 1197 symKey->size = keySize; 1198 symKey->origin = PK11_OriginGenerated; 1199 1200 /* Set the parameters for the key gen if provided */ 1201 mechanism.mechanism = keyGenType; 1202 mechanism.pParameter = NULL; 1203 mechanism.ulParameterLen = 0; 1204 if (param) { 1205 mechanism.pParameter = param->data; 1206 mechanism.ulParameterLen = param->len; 1207 } 1208 1209 /* Get session and perform locking */ 1210 if (isToken) { 1211 PK11_Authenticate(symKey->slot, PR_TRUE, wincx); 1212 /* Should always be original slot */ 1213 session = PK11_GetRWSession(symKey->slot); 1214 symKey->owner = PR_FALSE; 1215 } else { 1216 session = symKey->session; 1217 if (session != CK_INVALID_HANDLE) 1218 pk11_EnterKeyMonitor(symKey); 1219 } 1220 if (session == CK_INVALID_HANDLE) { 1221 PK11_FreeSymKey(symKey); 1222 PORT_SetError(SEC_ERROR_BAD_DATA); 1223 return NULL; 1224 } 1225 1226 crv = PK11_GETTAB(symKey->slot)->C_GenerateKey(session, &mechanism, attrs, attrsCount, &symKey->objectID); 1227 1228 /* Release lock and session */ 1229 if (isToken) { 1230 PK11_RestoreROSession(symKey->slot, session); 1231 } else { 1232 pk11_ExitKeyMonitor(symKey); 1233 } 1234 1235 if (crv != CKR_OK) { 1236 PK11_FreeSymKey(symKey); 1237 PORT_SetError(PK11_MapError(crv)); 1238 return NULL; 1239 } 1240 1241 return symKey; 1242 } 1243 1244 PK11SymKey * 1245 PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk, void *wincx) 1246 { 1247 PK11SlotInfo *slot = symk->slot; 1248 CK_ATTRIBUTE template[1]; 1249 CK_ATTRIBUTE *attrs = template; 1250 CK_BBOOL cktrue = CK_TRUE; 1251 CK_RV crv; 1252 CK_OBJECT_HANDLE newKeyID; 1253 CK_SESSION_HANDLE rwsession; 1254 1255 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(cktrue)); 1256 attrs++; 1257 1258 PK11_Authenticate(slot, PR_TRUE, wincx); 1259 rwsession = PK11_GetRWSession(slot); 1260 if (rwsession == CK_INVALID_HANDLE) { 1261 PORT_SetError(SEC_ERROR_BAD_DATA); 1262 return NULL; 1263 } 1264 crv = PK11_GETTAB(slot)->C_CopyObject(rwsession, symk->objectID, 1265 template, 1, &newKeyID); 1266 PK11_RestoreROSession(slot, rwsession); 1267 1268 if (crv != CKR_OK) { 1269 PORT_SetError(PK11_MapError(crv)); 1270 return NULL; 1271 } 1272 1273 return PK11_SymKeyFromHandle(slot, NULL /*parent*/, symk->origin, 1274 symk->type, newKeyID, PR_FALSE /*owner*/, NULL /*wincx*/); 1275 } 1276 1277 /* This function does a straight public key wrap with the CKM_RSA_PKCS 1278 * mechanism. */ 1279 SECStatus 1280 PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey, 1281 PK11SymKey *symKey, SECItem *wrappedKey) 1282 { 1283 CK_MECHANISM_TYPE inferred = pk11_mapWrapKeyType(pubKey->keyType); 1284 return PK11_PubWrapSymKeyWithMechanism(pubKey, inferred, NULL, symKey, 1285 wrappedKey); 1286 } 1287 1288 /* This function wraps a symmetric key with a public key, such as with the 1289 * CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP mechanisms. */ 1290 SECStatus 1291 PK11_PubWrapSymKeyWithMechanism(SECKEYPublicKey *pubKey, 1292 CK_MECHANISM_TYPE mechType, SECItem *param, 1293 PK11SymKey *symKey, SECItem *wrappedKey) 1294 { 1295 PK11SlotInfo *slot; 1296 CK_ULONG len = wrappedKey->len; 1297 PK11SymKey *newKey = NULL; 1298 CK_OBJECT_HANDLE id; 1299 CK_MECHANISM mechanism; 1300 PRBool owner = PR_TRUE; 1301 CK_SESSION_HANDLE session; 1302 CK_RV crv; 1303 1304 if (symKey == NULL) { 1305 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1306 return SECFailure; 1307 } 1308 1309 /* if this slot doesn't support the mechanism, go to a slot that does */ 1310 newKey = pk11_ForceSlot(symKey, mechType, CKA_ENCRYPT); 1311 if (newKey != NULL) { 1312 symKey = newKey; 1313 } 1314 1315 if (symKey->slot == NULL) { 1316 PORT_SetError(SEC_ERROR_NO_MODULE); 1317 return SECFailure; 1318 } 1319 1320 slot = symKey->slot; 1321 1322 mechanism.mechanism = mechType; 1323 if (param == NULL) { 1324 mechanism.pParameter = NULL; 1325 mechanism.ulParameterLen = 0; 1326 } else { 1327 mechanism.pParameter = param->data; 1328 mechanism.ulParameterLen = param->len; 1329 } 1330 1331 id = PK11_ImportPublicKey(slot, pubKey, PR_FALSE); 1332 if (id == CK_INVALID_HANDLE) { 1333 if (newKey) { 1334 PK11_FreeSymKey(newKey); 1335 } 1336 return SECFailure; /* Error code has been set. */ 1337 } 1338 1339 session = pk11_GetNewSession(slot, &owner); 1340 if (!owner || !(slot->isThreadSafe)) 1341 PK11_EnterSlotMonitor(slot); 1342 crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism, 1343 id, symKey->objectID, wrappedKey->data, &len); 1344 if (!owner || !(slot->isThreadSafe)) 1345 PK11_ExitSlotMonitor(slot); 1346 pk11_CloseSession(slot, session, owner); 1347 if (newKey) { 1348 PK11_FreeSymKey(newKey); 1349 } 1350 1351 if (crv != CKR_OK) { 1352 PORT_SetError(PK11_MapError(crv)); 1353 return SECFailure; 1354 } 1355 wrappedKey->len = len; 1356 return SECSuccess; 1357 } 1358 1359 /* 1360 * this little function uses the Encrypt function to wrap a key, just in 1361 * case we have problems with the wrap implementation for a token. 1362 */ 1363 static SECStatus 1364 pk11_HandWrap(PK11SymKey *wrappingKey, SECItem *param, CK_MECHANISM_TYPE type, 1365 SECItem *inKey, SECItem *outKey) 1366 { 1367 PK11SlotInfo *slot; 1368 CK_ULONG len; 1369 SECItem *data; 1370 CK_MECHANISM mech; 1371 PRBool owner = PR_TRUE; 1372 CK_SESSION_HANDLE session; 1373 CK_RV crv; 1374 1375 slot = wrappingKey->slot; 1376 /* use NULL IV's for wrapping */ 1377 mech.mechanism = type; 1378 if (param) { 1379 mech.pParameter = param->data; 1380 mech.ulParameterLen = param->len; 1381 } else { 1382 mech.pParameter = NULL; 1383 mech.ulParameterLen = 0; 1384 } 1385 session = pk11_GetNewSession(slot, &owner); 1386 if (!owner || !(slot->isThreadSafe)) 1387 PK11_EnterSlotMonitor(slot); 1388 crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech, 1389 wrappingKey->objectID); 1390 if (crv != CKR_OK) { 1391 if (!owner || !(slot->isThreadSafe)) 1392 PK11_ExitSlotMonitor(slot); 1393 pk11_CloseSession(slot, session, owner); 1394 PORT_SetError(PK11_MapError(crv)); 1395 return SECFailure; 1396 } 1397 1398 /* keys are almost always aligned, but if we get this far, 1399 * we've gone above and beyond anyway... */ 1400 data = PK11_BlockData(inKey, PK11_GetBlockSize(type, param)); 1401 if (data == NULL) { 1402 if (!owner || !(slot->isThreadSafe)) 1403 PK11_ExitSlotMonitor(slot); 1404 pk11_CloseSession(slot, session, owner); 1405 PORT_SetError(SEC_ERROR_NO_MEMORY); 1406 return SECFailure; 1407 } 1408 len = outKey->len; 1409 crv = PK11_GETTAB(slot)->C_Encrypt(session, data->data, data->len, 1410 outKey->data, &len); 1411 if (!owner || !(slot->isThreadSafe)) 1412 PK11_ExitSlotMonitor(slot); 1413 pk11_CloseSession(slot, session, owner); 1414 SECITEM_FreeItem(data, PR_TRUE); 1415 outKey->len = len; 1416 if (crv != CKR_OK) { 1417 PORT_SetError(PK11_MapError(crv)); 1418 return SECFailure; 1419 } 1420 return SECSuccess; 1421 } 1422 1423 /* 1424 * helper function which moves two keys into a new slot based on the 1425 * desired mechanism. 1426 */ 1427 static SECStatus 1428 pk11_moveTwoKeys(CK_MECHANISM_TYPE mech, 1429 CK_ATTRIBUTE_TYPE preferedOperation, 1430 CK_ATTRIBUTE_TYPE movingOperation, 1431 PK11SymKey *preferedKey, PK11SymKey *movingKey, 1432 PK11SymKey **newPreferedKey, PK11SymKey **newMovingKey) 1433 { 1434 PK11SlotInfo *newSlot; 1435 *newMovingKey = NULL; 1436 *newPreferedKey = NULL; 1437 1438 newSlot = PK11_GetBestSlot(mech, preferedKey->cx); 1439 if (newSlot == NULL) { 1440 return SECFailure; 1441 } 1442 *newMovingKey = pk11_CopyToSlot(newSlot, movingKey->type, 1443 movingOperation, movingKey); 1444 if (*newMovingKey == NULL) { 1445 goto loser; 1446 } 1447 *newPreferedKey = pk11_CopyToSlot(newSlot, preferedKey->type, 1448 preferedOperation, preferedKey); 1449 if (*newPreferedKey == NULL) { 1450 goto loser; 1451 } 1452 1453 PK11_FreeSlot(newSlot); 1454 return SECSuccess; 1455 loser: 1456 PK11_FreeSlot(newSlot); 1457 PK11_FreeSymKey(*newMovingKey); 1458 PK11_FreeSymKey(*newPreferedKey); 1459 *newMovingKey = NULL; 1460 *newPreferedKey = NULL; 1461 return SECFailure; 1462 } 1463 1464 /* 1465 * To do joint operations, we often need two keys in the same slot. 1466 * Usually the PKCS #11 wrappers handle this correctly (like for PK11_WrapKey), 1467 * but sometimes the wrappers don't know about mechanism specific keys in 1468 * the Mechanism params. This function makes sure the two keys are in the 1469 * same slot by copying one or both of the keys into a common slot. This 1470 * functions makes sure the slot can handle the target mechanism. If the copy 1471 * is warranted, this function will prefer to move the movingKey first, then 1472 * the preferedKey. If the keys are moved, the new keys are returned in 1473 * newMovingKey and/or newPreferedKey. The application is responsible 1474 * for freeing those keys once the operation is complete. 1475 */ 1476 SECStatus 1477 PK11_SymKeysToSameSlot(CK_MECHANISM_TYPE mech, 1478 CK_ATTRIBUTE_TYPE preferedOperation, 1479 CK_ATTRIBUTE_TYPE movingOperation, 1480 PK11SymKey *preferedKey, PK11SymKey *movingKey, 1481 PK11SymKey **newPreferedKey, PK11SymKey **newMovingKey) 1482 { 1483 /* usually don't return new keys */ 1484 *newMovingKey = NULL; 1485 *newPreferedKey = NULL; 1486 if (movingKey->slot == preferedKey->slot) { 1487 1488 /* this should be the most common case */ 1489 if ((preferedKey->slot != NULL) && 1490 PK11_DoesMechanism(preferedKey->slot, mech)) { 1491 return SECSuccess; 1492 } 1493 1494 /* we are in the same slot, but it doesn't do the operation, 1495 * move both keys to an appropriate target slot */ 1496 return pk11_moveTwoKeys(mech, preferedOperation, movingOperation, 1497 preferedKey, movingKey, 1498 newPreferedKey, newMovingKey); 1499 } 1500 1501 /* keys are in different slot, try moving the moving key to the prefered 1502 * key's slot */ 1503 if ((preferedKey->slot != NULL) && 1504 PK11_DoesMechanism(preferedKey->slot, mech)) { 1505 *newMovingKey = pk11_CopyToSlot(preferedKey->slot, movingKey->type, 1506 movingOperation, movingKey); 1507 if (*newMovingKey != NULL) { 1508 return SECSuccess; 1509 } 1510 } 1511 /* couldn't moving the moving key to the prefered slot, try moving 1512 * the prefered key */ 1513 if ((movingKey->slot != NULL) && 1514 PK11_DoesMechanism(movingKey->slot, mech)) { 1515 *newPreferedKey = pk11_CopyToSlot(movingKey->slot, preferedKey->type, 1516 preferedOperation, preferedKey); 1517 if (*newPreferedKey != NULL) { 1518 return SECSuccess; 1519 } 1520 } 1521 /* Neither succeeded, but that could be that they were not in slots that 1522 * supported the operation, try moving both keys into a common slot that 1523 * can do the operation. */ 1524 return pk11_moveTwoKeys(mech, preferedOperation, movingOperation, 1525 preferedKey, movingKey, 1526 newPreferedKey, newMovingKey); 1527 } 1528 1529 /* 1530 * This function does a symetric based wrap. 1531 */ 1532 SECStatus 1533 PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *param, 1534 PK11SymKey *wrappingKey, PK11SymKey *symKey, 1535 SECItem *wrappedKey) 1536 { 1537 PK11SlotInfo *slot; 1538 CK_ULONG len = wrappedKey->len; 1539 PK11SymKey *newSymKey = NULL; 1540 PK11SymKey *newWrappingKey = NULL; 1541 SECItem *param_save = NULL; 1542 CK_MECHANISM mechanism; 1543 PRBool owner = PR_TRUE; 1544 CK_SESSION_HANDLE session; 1545 CK_RV crv; 1546 SECStatus rv; 1547 1548 /* force the keys into same slot */ 1549 rv = PK11_SymKeysToSameSlot(type, CKA_ENCRYPT, CKA_WRAP, 1550 symKey, wrappingKey, 1551 &newSymKey, &newWrappingKey); 1552 if (rv != SECSuccess) { 1553 /* Couldn't move the keys as desired, try to hand unwrap if possible */ 1554 if (symKey->data.data == NULL) { 1555 rv = PK11_ExtractKeyValue(symKey); 1556 if (rv != SECSuccess) { 1557 PORT_SetError(SEC_ERROR_NO_MODULE); 1558 return SECFailure; 1559 } 1560 } 1561 if (param == NULL) { 1562 param_save = param = PK11_ParamFromIV(type, NULL); 1563 } 1564 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, wrappedKey); 1565 if (param_save) 1566 SECITEM_FreeItem(param_save, PR_TRUE); 1567 return rv; 1568 } 1569 if (newSymKey) { 1570 symKey = newSymKey; 1571 } 1572 if (newWrappingKey) { 1573 wrappingKey = newWrappingKey; 1574 } 1575 1576 /* at this point both keys are in the same token */ 1577 slot = wrappingKey->slot; 1578 mechanism.mechanism = type; 1579 /* use NULL IV's for wrapping */ 1580 if (param == NULL) { 1581 param_save = param = PK11_ParamFromIV(type, NULL); 1582 } 1583 if (param) { 1584 mechanism.pParameter = param->data; 1585 mechanism.ulParameterLen = param->len; 1586 } else { 1587 mechanism.pParameter = NULL; 1588 mechanism.ulParameterLen = 0; 1589 } 1590 1591 len = wrappedKey->len; 1592 1593 session = pk11_GetNewSession(slot, &owner); 1594 if (!owner || !(slot->isThreadSafe)) 1595 PK11_EnterSlotMonitor(slot); 1596 crv = PK11_GETTAB(slot)->C_WrapKey(session, &mechanism, 1597 wrappingKey->objectID, symKey->objectID, 1598 wrappedKey->data, &len); 1599 if (!owner || !(slot->isThreadSafe)) 1600 PK11_ExitSlotMonitor(slot); 1601 pk11_CloseSession(slot, session, owner); 1602 rv = SECSuccess; 1603 if (crv != CKR_OK) { 1604 /* can't wrap it? try hand wrapping it... */ 1605 do { 1606 if (symKey->data.data == NULL) { 1607 rv = PK11_ExtractKeyValue(symKey); 1608 if (rv != SECSuccess) 1609 break; 1610 } 1611 rv = pk11_HandWrap(wrappingKey, param, type, &symKey->data, 1612 wrappedKey); 1613 } while (PR_FALSE); 1614 } else { 1615 wrappedKey->len = len; 1616 } 1617 PK11_FreeSymKey(newSymKey); 1618 PK11_FreeSymKey(newWrappingKey); 1619 if (param_save) 1620 SECITEM_FreeItem(param_save, PR_TRUE); 1621 return rv; 1622 } 1623 1624 /* 1625 * This Generates a new key based on a symetricKey 1626 */ 1627 PK11SymKey * 1628 PK11_Derive(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, SECItem *param, 1629 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1630 int keySize) 1631 { 1632 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1633 keySize, NULL, 0, PR_FALSE); 1634 } 1635 1636 PK11SymKey * 1637 PK11_DeriveWithFlags(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1638 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1639 int keySize, CK_FLAGS flags) 1640 { 1641 CK_BBOOL ckTrue = CK_TRUE; 1642 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1643 unsigned int templateCount; 1644 1645 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 1646 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1647 keySize, keyTemplate, templateCount, PR_FALSE); 1648 } 1649 1650 PK11SymKey * 1651 PK11_DeriveWithFlagsPerm(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1652 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1653 int keySize, CK_FLAGS flags, PRBool isPerm) 1654 { 1655 CK_BBOOL cktrue = CK_TRUE; 1656 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 1657 CK_ATTRIBUTE *attrs; 1658 unsigned int templateCount = 0; 1659 1660 attrs = keyTemplate; 1661 if (isPerm) { 1662 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); 1663 attrs++; 1664 } 1665 templateCount = attrs - keyTemplate; 1666 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 1667 return PK11_DeriveWithTemplate(baseKey, derive, param, target, operation, 1668 keySize, keyTemplate, templateCount, isPerm); 1669 } 1670 1671 PK11SymKey * 1672 PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive, 1673 SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1674 int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, 1675 PRBool isPerm) 1676 { 1677 PK11SlotInfo *slot = baseKey->slot; 1678 PK11SymKey *symKey; 1679 PK11SymKey *newBaseKey = NULL; 1680 CK_BBOOL cktrue = CK_TRUE; 1681 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 1682 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 1683 CK_ULONG valueLen = 0; 1684 CK_MECHANISM mechanism; 1685 CK_RV crv; 1686 #define MAX_ADD_ATTRS 4 1687 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; 1688 #undef MAX_ADD_ATTRS 1689 CK_ATTRIBUTE *attrs = keyTemplate; 1690 CK_SESSION_HANDLE session; 1691 unsigned int templateCount; 1692 1693 if (numAttrs > MAX_TEMPL_ATTRS) { 1694 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1695 return NULL; 1696 } 1697 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 1698 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 1699 * it as a real attribute */ 1700 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 1701 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 1702 * etc. Strip out the real attribute here */ 1703 operation &= ~CKA_NSS_MESSAGE_MASK; 1704 } 1705 1706 /* first copy caller attributes in. */ 1707 for (templateCount = 0; templateCount < numAttrs; ++templateCount) { 1708 *attrs++ = *userAttr++; 1709 } 1710 1711 /* We only add the following attributes to the template if the caller 1712 ** didn't already supply them. 1713 */ 1714 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { 1715 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); 1716 attrs++; 1717 } 1718 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { 1719 keyType = PK11_GetKeyType(target, keySize); 1720 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType); 1721 attrs++; 1722 } 1723 if (keySize > 0 && 1724 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { 1725 valueLen = (CK_ULONG)keySize; 1726 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); 1727 attrs++; 1728 } 1729 if ((operation != CKA_FLAGS_ONLY) && 1730 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { 1731 PK11_SETATTRS(attrs, operation, &cktrue, sizeof cktrue); 1732 attrs++; 1733 } 1734 1735 templateCount = attrs - keyTemplate; 1736 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 1737 1738 /* move the key to a slot that can do the function */ 1739 if (!PK11_DoesMechanism(slot, derive)) { 1740 /* get a new base key & slot */ 1741 PK11SlotInfo *newSlot = PK11_GetBestSlot(derive, baseKey->cx); 1742 1743 if (newSlot == NULL) 1744 return NULL; 1745 1746 newBaseKey = pk11_CopyToSlot(newSlot, derive, CKA_DERIVE, 1747 baseKey); 1748 PK11_FreeSlot(newSlot); 1749 if (newBaseKey == NULL) 1750 return NULL; 1751 baseKey = newBaseKey; 1752 slot = baseKey->slot; 1753 } 1754 1755 /* get our key Structure */ 1756 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, baseKey->cx); 1757 if (symKey == NULL) { 1758 return NULL; 1759 } 1760 1761 symKey->size = keySize; 1762 1763 mechanism.mechanism = derive; 1764 if (param) { 1765 mechanism.pParameter = param->data; 1766 mechanism.ulParameterLen = param->len; 1767 } else { 1768 mechanism.pParameter = NULL; 1769 mechanism.ulParameterLen = 0; 1770 } 1771 symKey->origin = PK11_OriginDerive; 1772 1773 if (isPerm) { 1774 session = PK11_GetRWSession(slot); 1775 } else { 1776 pk11_EnterKeyMonitor(symKey); 1777 session = symKey->session; 1778 } 1779 if (session == CK_INVALID_HANDLE) { 1780 if (!isPerm) 1781 pk11_ExitKeyMonitor(symKey); 1782 crv = CKR_SESSION_HANDLE_INVALID; 1783 } else { 1784 crv = PK11_GETTAB(slot)->C_DeriveKey(session, &mechanism, 1785 baseKey->objectID, keyTemplate, templateCount, &symKey->objectID); 1786 if (isPerm) { 1787 PK11_RestoreROSession(slot, session); 1788 } else { 1789 pk11_ExitKeyMonitor(symKey); 1790 } 1791 } 1792 if (newBaseKey) 1793 PK11_FreeSymKey(newBaseKey); 1794 if (crv != CKR_OK) { 1795 PK11_FreeSymKey(symKey); 1796 PORT_SetError(PK11_MapError(crv)); 1797 return NULL; 1798 } 1799 return symKey; 1800 } 1801 1802 /* Create a new key by concatenating base and data 1803 */ 1804 static PK11SymKey * 1805 pk11_ConcatenateBaseAndData(PK11SymKey *base, 1806 CK_BYTE *data, CK_ULONG dataLen, CK_MECHANISM_TYPE target, 1807 CK_ATTRIBUTE_TYPE operation) 1808 { 1809 CK_KEY_DERIVATION_STRING_DATA mechParams; 1810 SECItem param; 1811 1812 if (base == NULL) { 1813 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1814 return NULL; 1815 } 1816 1817 mechParams.pData = data; 1818 mechParams.ulLen = dataLen; 1819 param.data = (unsigned char *)&mechParams; 1820 param.len = sizeof(CK_KEY_DERIVATION_STRING_DATA); 1821 1822 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_DATA, 1823 ¶m, target, operation, 0); 1824 } 1825 1826 /* Create a new key by concatenating base and key 1827 */ 1828 static PK11SymKey * 1829 pk11_ConcatenateBaseAndKey(PK11SymKey *base, 1830 PK11SymKey *key, CK_MECHANISM_TYPE target, 1831 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) 1832 { 1833 SECItem param; 1834 1835 if ((base == NULL) || (key == NULL)) { 1836 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1837 return NULL; 1838 } 1839 1840 param.data = (unsigned char *)&(key->objectID); 1841 param.len = sizeof(CK_OBJECT_HANDLE); 1842 1843 return PK11_Derive(base, CKM_CONCATENATE_BASE_AND_KEY, 1844 ¶m, target, operation, keySize); 1845 } 1846 1847 PK11SymKey * 1848 PK11_ConcatSymKeys(PK11SymKey *left, PK11SymKey *right, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation) 1849 { 1850 PK11SymKey *out = NULL; 1851 PK11SymKey *copyOfLeft = NULL; 1852 PK11SymKey *copyOfRight = NULL; 1853 1854 if ((left == NULL) || (right == NULL)) { 1855 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1856 return NULL; 1857 } 1858 1859 SECStatus rv = PK11_SymKeysToSameSlot(CKM_CONCATENATE_BASE_AND_KEY, 1860 CKA_DERIVE, CKA_DERIVE, left, right, 1861 ©OfLeft, ©OfRight); 1862 if (rv != SECSuccess) { 1863 /* error code already set */ 1864 return NULL; 1865 } 1866 1867 out = pk11_ConcatenateBaseAndKey(copyOfLeft ? copyOfLeft : left, copyOfRight ? copyOfRight : right, target, operation, 0); 1868 PK11_FreeSymKey(copyOfLeft); 1869 PK11_FreeSymKey(copyOfRight); 1870 return out; 1871 } 1872 1873 /* Create a new key whose value is the hash of tobehashed. 1874 * type is the mechanism for the derived key. 1875 */ 1876 static PK11SymKey * 1877 pk11_HashKeyDerivation(PK11SymKey *toBeHashed, 1878 CK_MECHANISM_TYPE hashMechanism, CK_MECHANISM_TYPE target, 1879 CK_ATTRIBUTE_TYPE operation, CK_ULONG keySize) 1880 { 1881 return PK11_Derive(toBeHashed, hashMechanism, NULL, target, operation, keySize); 1882 } 1883 1884 /* This function implements the ANSI X9.63 key derivation function 1885 */ 1886 static PK11SymKey * 1887 pk11_ANSIX963Derive(PK11SymKey *sharedSecret, 1888 CK_EC_KDF_TYPE kdf, SECItem *sharedData, 1889 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 1890 CK_ULONG keySize) 1891 { 1892 CK_KEY_TYPE keyType; 1893 CK_MECHANISM_TYPE hashMechanism, mechanismArray[4]; 1894 CK_ULONG derivedKeySize, HashLen, counter, maxCounter, bufferLen; 1895 CK_ULONG SharedInfoLen; 1896 CK_BYTE *buffer = NULL; 1897 PK11SymKey *toBeHashed, *hashOutput; 1898 PK11SymKey *newSharedSecret = NULL; 1899 PK11SymKey *oldIntermediateResult, *intermediateResult = NULL; 1900 1901 if (sharedSecret == NULL) { 1902 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1903 return NULL; 1904 } 1905 1906 switch (kdf) { 1907 case CKD_SHA1_KDF: 1908 HashLen = SHA1_LENGTH; 1909 hashMechanism = CKM_SHA1_KEY_DERIVATION; 1910 break; 1911 case CKD_SHA224_KDF: 1912 HashLen = SHA224_LENGTH; 1913 hashMechanism = CKM_SHA224_KEY_DERIVATION; 1914 break; 1915 case CKD_SHA256_KDF: 1916 HashLen = SHA256_LENGTH; 1917 hashMechanism = CKM_SHA256_KEY_DERIVATION; 1918 break; 1919 case CKD_SHA384_KDF: 1920 HashLen = SHA384_LENGTH; 1921 hashMechanism = CKM_SHA384_KEY_DERIVATION; 1922 break; 1923 case CKD_SHA512_KDF: 1924 HashLen = SHA512_LENGTH; 1925 hashMechanism = CKM_SHA512_KEY_DERIVATION; 1926 break; 1927 default: 1928 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1929 return NULL; 1930 } 1931 1932 derivedKeySize = keySize; 1933 if (derivedKeySize == 0) { 1934 keyType = PK11_GetKeyType(target, keySize); 1935 derivedKeySize = pk11_GetPredefinedKeyLength(keyType); 1936 if (derivedKeySize == 0) { 1937 derivedKeySize = HashLen; 1938 } 1939 } 1940 1941 /* Check that key_len isn't too long. The maximum key length could be 1942 * greatly increased if the code below did not limit the 4-byte counter 1943 * to a maximum value of 255. */ 1944 if (derivedKeySize > 254 * HashLen) { 1945 PORT_SetError(SEC_ERROR_INVALID_ARGS); 1946 return NULL; 1947 } 1948 1949 maxCounter = derivedKeySize / HashLen; 1950 if (derivedKeySize > maxCounter * HashLen) 1951 maxCounter++; 1952 1953 if ((sharedData == NULL) || (sharedData->data == NULL)) 1954 SharedInfoLen = 0; 1955 else 1956 SharedInfoLen = sharedData->len; 1957 1958 bufferLen = SharedInfoLen + 4; 1959 1960 /* Populate buffer with Counter || sharedData 1961 * where Counter is 0x00000001. */ 1962 buffer = (unsigned char *)PORT_Alloc(bufferLen); 1963 if (buffer == NULL) { 1964 PORT_SetError(SEC_ERROR_NO_MEMORY); 1965 return NULL; 1966 } 1967 1968 buffer[0] = 0; 1969 buffer[1] = 0; 1970 buffer[2] = 0; 1971 buffer[3] = 1; 1972 if (SharedInfoLen > 0) { 1973 PORT_Memcpy(&buffer[4], sharedData->data, SharedInfoLen); 1974 } 1975 1976 /* Look for a slot that supports the mechanisms needed 1977 * to implement the ANSI X9.63 KDF as well as the 1978 * target mechanism. 1979 */ 1980 mechanismArray[0] = CKM_CONCATENATE_BASE_AND_DATA; 1981 mechanismArray[1] = hashMechanism; 1982 mechanismArray[2] = CKM_CONCATENATE_BASE_AND_KEY; 1983 mechanismArray[3] = target; 1984 1985 newSharedSecret = pk11_ForceSlotMultiple(sharedSecret, 1986 mechanismArray, 4, operation); 1987 if (newSharedSecret != NULL) { 1988 sharedSecret = newSharedSecret; 1989 } 1990 1991 for (counter = 1; counter <= maxCounter; counter++) { 1992 /* Concatenate shared_secret and buffer */ 1993 toBeHashed = pk11_ConcatenateBaseAndData(sharedSecret, buffer, 1994 bufferLen, hashMechanism, operation); 1995 if (toBeHashed == NULL) { 1996 goto loser; 1997 } 1998 1999 /* Hash value */ 2000 if (maxCounter == 1) { 2001 /* In this case the length of the key to be derived is 2002 * less than or equal to the length of the hash output. 2003 * So, the output of the hash operation will be the 2004 * dervied key. */ 2005 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, 2006 target, operation, keySize); 2007 } else { 2008 /* In this case, the output of the hash operation will be 2009 * concatenated with other data to create the derived key. */ 2010 hashOutput = pk11_HashKeyDerivation(toBeHashed, hashMechanism, 2011 CKM_CONCATENATE_BASE_AND_KEY, operation, 0); 2012 } 2013 PK11_FreeSymKey(toBeHashed); 2014 if (hashOutput == NULL) { 2015 goto loser; 2016 } 2017 2018 /* Append result to intermediate result, if necessary */ 2019 oldIntermediateResult = intermediateResult; 2020 2021 if (oldIntermediateResult == NULL) { 2022 intermediateResult = hashOutput; 2023 } else { 2024 if (counter == maxCounter) { 2025 /* This is the final concatenation, and so the output 2026 * will be the derived key. */ 2027 intermediateResult = 2028 pk11_ConcatenateBaseAndKey(oldIntermediateResult, 2029 hashOutput, target, operation, keySize); 2030 } else { 2031 /* The output of this concatenation will be concatenated 2032 * with other data to create the derived key. */ 2033 intermediateResult = 2034 pk11_ConcatenateBaseAndKey(oldIntermediateResult, 2035 hashOutput, CKM_CONCATENATE_BASE_AND_KEY, 2036 operation, 0); 2037 } 2038 2039 PK11_FreeSymKey(hashOutput); 2040 PK11_FreeSymKey(oldIntermediateResult); 2041 if (intermediateResult == NULL) { 2042 goto loser; 2043 } 2044 } 2045 2046 /* Increment counter (assumes maxCounter < 255) */ 2047 buffer[3]++; 2048 } 2049 2050 PORT_ZFree(buffer, bufferLen); 2051 if (newSharedSecret != NULL) 2052 PK11_FreeSymKey(newSharedSecret); 2053 return intermediateResult; 2054 2055 loser: 2056 PORT_ZFree(buffer, bufferLen); 2057 if (newSharedSecret != NULL) 2058 PK11_FreeSymKey(newSharedSecret); 2059 if (intermediateResult != NULL) 2060 PK11_FreeSymKey(intermediateResult); 2061 return NULL; 2062 } 2063 2064 /* 2065 * This regenerate a public key from a private key. This function is currently 2066 * NSS private. If we want to make it public, we need to add and optional 2067 * template or at least flags (a.la. PK11_DeriveWithFlags). 2068 */ 2069 CK_OBJECT_HANDLE 2070 PK11_DerivePubKeyFromPrivKey(SECKEYPrivateKey *privKey) 2071 { 2072 PK11SlotInfo *slot = privKey->pkcs11Slot; 2073 CK_MECHANISM mechanism; 2074 CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE; 2075 CK_RV crv; 2076 2077 mechanism.mechanism = CKM_NSS_PUB_FROM_PRIV; 2078 mechanism.pParameter = NULL; 2079 mechanism.ulParameterLen = 0; 2080 2081 PK11_EnterSlotMonitor(slot); 2082 crv = PK11_GETTAB(slot)->C_DeriveKey(slot->session, &mechanism, 2083 privKey->pkcs11ID, NULL, 0, 2084 &objectID); 2085 PK11_ExitSlotMonitor(slot); 2086 if (crv != CKR_OK) { 2087 PORT_SetError(PK11_MapError(crv)); 2088 return CK_INVALID_HANDLE; 2089 } 2090 return objectID; 2091 } 2092 2093 /* 2094 * This Generates a wrapping key based on a privateKey, publicKey, and two 2095 * random numbers. For Mail usage RandomB should be NULL. In the Sender's 2096 * case RandomA is generate, otherwise it is passed. 2097 */ 2098 PK11SymKey * 2099 PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 2100 PRBool isSender, SECItem *randomA, SECItem *randomB, 2101 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 2102 CK_ATTRIBUTE_TYPE operation, int keySize, void *wincx) 2103 { 2104 PK11SlotInfo *slot = privKey->pkcs11Slot; 2105 CK_MECHANISM mechanism; 2106 PK11SymKey *symKey; 2107 CK_RV crv; 2108 2109 /* get our key Structure */ 2110 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); 2111 if (symKey == NULL) { 2112 return NULL; 2113 } 2114 2115 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 2116 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 2117 * it as a real attribute */ 2118 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 2119 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 2120 * etc. Strip out the real attribute here */ 2121 operation &= ~CKA_NSS_MESSAGE_MASK; 2122 } 2123 2124 symKey->origin = PK11_OriginDerive; 2125 2126 switch (privKey->keyType) { 2127 case keaKey: 2128 case fortezzaKey: { 2129 static unsigned char rb_email[128] = { 0 }; 2130 CK_KEA_DERIVE_PARAMS param; 2131 param.isSender = (CK_BBOOL)isSender; 2132 param.ulRandomLen = randomA->len; 2133 param.pRandomA = randomA->data; 2134 param.pRandomB = rb_email; 2135 param.pRandomB[127] = 1; 2136 if (randomB) 2137 param.pRandomB = randomB->data; 2138 if (pubKey->keyType == fortezzaKey) { 2139 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; 2140 param.pPublicData = pubKey->u.fortezza.KEAKey.data; 2141 } else { 2142 /* assert type == keaKey */ 2143 /* XXX change to match key key types */ 2144 param.ulPublicDataLen = pubKey->u.fortezza.KEAKey.len; 2145 param.pPublicData = pubKey->u.fortezza.KEAKey.data; 2146 } 2147 2148 mechanism.mechanism = derive; 2149 mechanism.pParameter = ¶m; 2150 mechanism.ulParameterLen = sizeof(param); 2151 2152 /* get a new symKey structure */ 2153 pk11_EnterKeyMonitor(symKey); 2154 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 2155 privKey->pkcs11ID, NULL, 0, 2156 &symKey->objectID); 2157 pk11_ExitKeyMonitor(symKey); 2158 if (crv == CKR_OK) 2159 return symKey; 2160 PORT_SetError(PK11_MapError(crv)); 2161 } break; 2162 case dhKey: { 2163 CK_BBOOL cktrue = CK_TRUE; 2164 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 2165 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 2166 CK_ULONG key_size = 0; 2167 CK_ATTRIBUTE keyTemplate[4]; 2168 int templateCount; 2169 CK_ATTRIBUTE *attrs = keyTemplate; 2170 2171 if (pubKey->keyType != dhKey) { 2172 PORT_SetError(SEC_ERROR_BAD_KEY); 2173 break; 2174 } 2175 2176 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 2177 attrs++; 2178 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 2179 attrs++; 2180 PK11_SETATTRS(attrs, operation, &cktrue, 1); 2181 attrs++; 2182 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 2183 attrs++; 2184 templateCount = attrs - keyTemplate; 2185 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 2186 2187 keyType = PK11_GetKeyType(target, keySize); 2188 key_size = keySize; 2189 symKey->size = keySize; 2190 if (key_size == 0) 2191 templateCount--; 2192 2193 mechanism.mechanism = derive; 2194 2195 /* we can undefine these when we define diffie-helman keys */ 2196 2197 mechanism.pParameter = pubKey->u.dh.publicValue.data; 2198 mechanism.ulParameterLen = pubKey->u.dh.publicValue.len; 2199 2200 pk11_EnterKeyMonitor(symKey); 2201 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 2202 privKey->pkcs11ID, keyTemplate, 2203 templateCount, &symKey->objectID); 2204 pk11_ExitKeyMonitor(symKey); 2205 if (crv == CKR_OK) 2206 return symKey; 2207 PORT_SetError(PK11_MapError(crv)); 2208 } break; 2209 case ecKey: { 2210 CK_BBOOL cktrue = CK_TRUE; 2211 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 2212 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 2213 CK_ULONG key_size = 0; 2214 CK_ATTRIBUTE keyTemplate[4]; 2215 int templateCount; 2216 CK_ATTRIBUTE *attrs = keyTemplate; 2217 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; 2218 2219 if (pubKey->keyType != ecKey) { 2220 PORT_SetError(SEC_ERROR_BAD_KEY); 2221 break; 2222 } 2223 2224 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 2225 attrs++; 2226 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 2227 attrs++; 2228 PK11_SETATTRS(attrs, operation, &cktrue, 1); 2229 attrs++; 2230 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 2231 attrs++; 2232 templateCount = attrs - keyTemplate; 2233 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 2234 2235 keyType = PK11_GetKeyType(target, keySize); 2236 key_size = keySize; 2237 if (key_size == 0) { 2238 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { 2239 templateCount--; 2240 } else { 2241 /* sigh, some tokens can't figure this out and require 2242 * CKA_VALUE_LEN to be set */ 2243 key_size = SHA1_LENGTH; 2244 } 2245 } 2246 symKey->size = key_size; 2247 2248 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); 2249 mechParams->kdf = CKD_SHA1_KDF; 2250 mechParams->ulSharedDataLen = 0; 2251 mechParams->pSharedData = NULL; 2252 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 2253 mechParams->pPublicData = pubKey->u.ec.publicValue.data; 2254 2255 mechanism.mechanism = derive; 2256 mechanism.pParameter = mechParams; 2257 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); 2258 2259 pk11_EnterKeyMonitor(symKey); 2260 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 2261 &mechanism, privKey->pkcs11ID, keyTemplate, 2262 templateCount, &symKey->objectID); 2263 pk11_ExitKeyMonitor(symKey); 2264 2265 /* old PKCS #11 spec was ambiguous on what needed to be passed, 2266 * try this again with and encoded public key */ 2267 if (crv != CKR_OK && pk11_ECGetPubkeyEncoding(pubKey) != ECPoint_XOnly) { 2268 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 2269 &pubKey->u.ec.publicValue, 2270 SEC_ASN1_GET(SEC_OctetStringTemplate)); 2271 if (pubValue == NULL) { 2272 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 2273 break; 2274 } 2275 mechParams->ulPublicDataLen = pubValue->len; 2276 mechParams->pPublicData = pubValue->data; 2277 2278 pk11_EnterKeyMonitor(symKey); 2279 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 2280 &mechanism, privKey->pkcs11ID, keyTemplate, 2281 templateCount, &symKey->objectID); 2282 pk11_ExitKeyMonitor(symKey); 2283 2284 SECITEM_FreeItem(pubValue, PR_TRUE); 2285 } 2286 2287 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 2288 2289 if (crv == CKR_OK) 2290 return symKey; 2291 PORT_SetError(PK11_MapError(crv)); 2292 } 2293 /* most keys are not KEA keys, so assume they are bad if they 2294 * are not handled explicitly */ 2295 default: 2296 PORT_SetError(SEC_ERROR_BAD_KEY); 2297 break; 2298 } 2299 2300 PK11_FreeSymKey(symKey); 2301 return NULL; 2302 } 2303 2304 /* Test for curves that are known to use a special encoding. 2305 * Extend this function when additional curves are added. */ 2306 static ECPointEncoding 2307 pk11_ECGetPubkeyEncoding(const SECKEYPublicKey *pubKey) 2308 { 2309 SECItem oid; 2310 SECStatus rv; 2311 PORTCheapArenaPool tmpArena; 2312 ECPointEncoding encoding = ECPoint_Undefined; 2313 2314 PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE); 2315 2316 /* decode the OID tag */ 2317 rv = SEC_QuickDERDecodeItem(&tmpArena.arena, &oid, 2318 SEC_ASN1_GET(SEC_ObjectIDTemplate), 2319 &pubKey->u.ec.DEREncodedParams); 2320 if (rv == SECSuccess) { 2321 SECOidTag tag = SECOID_FindOIDTag(&oid); 2322 switch (tag) { 2323 case SEC_OID_X25519: 2324 case SEC_OID_CURVE25519: 2325 encoding = ECPoint_XOnly; 2326 break; 2327 case SEC_OID_SECG_EC_SECP256R1: 2328 case SEC_OID_SECG_EC_SECP384R1: 2329 case SEC_OID_SECG_EC_SECP521R1: 2330 default: 2331 /* unknown curve, default to uncompressed */ 2332 encoding = ECPoint_Uncompressed; 2333 } 2334 } 2335 PORT_DestroyCheapArena(&tmpArena); 2336 return encoding; 2337 } 2338 2339 /* Returns the size of the public key, or 0 if there 2340 * is an error. */ 2341 static CK_ULONG 2342 pk11_ECPubKeySize(SECKEYPublicKey *pubKey) 2343 { 2344 SECItem *publicValue = &pubKey->u.ec.publicValue; 2345 2346 ECPointEncoding encoding = pk11_ECGetPubkeyEncoding(pubKey); 2347 if (encoding == ECPoint_XOnly) { 2348 return publicValue->len; 2349 } 2350 if (encoding == ECPoint_Uncompressed) { 2351 /* key encoded in uncompressed form */ 2352 return ((publicValue->len - 1) / 2); 2353 } 2354 /* key encoding not recognized */ 2355 return 0; 2356 } 2357 2358 static PK11SymKey * 2359 pk11_PubDeriveECKeyWithKDF( 2360 SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 2361 PRBool isSender, SECItem *randomA, SECItem *randomB, 2362 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 2363 CK_ATTRIBUTE_TYPE operation, int keySize, 2364 CK_ULONG kdf, SECItem *sharedData, void *wincx) 2365 { 2366 PK11SlotInfo *slot = privKey->pkcs11Slot; 2367 PK11SymKey *symKey; 2368 PK11SymKey *SharedSecret; 2369 CK_MECHANISM mechanism; 2370 CK_RV crv; 2371 CK_BBOOL cktrue = CK_TRUE; 2372 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 2373 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 2374 CK_ULONG key_size = 0; 2375 CK_ATTRIBUTE keyTemplate[4]; 2376 int templateCount; 2377 CK_ATTRIBUTE *attrs = keyTemplate; 2378 CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; 2379 2380 if (pubKey->keyType != ecKey && pubKey->keyType != ecMontKey) { 2381 PORT_SetError(SEC_ERROR_BAD_KEY); 2382 return NULL; 2383 } 2384 if ((kdf != CKD_NULL) && (kdf != CKD_SHA1_KDF) && 2385 (kdf != CKD_SHA224_KDF) && (kdf != CKD_SHA256_KDF) && 2386 (kdf != CKD_SHA384_KDF) && (kdf != CKD_SHA512_KDF)) { 2387 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 2388 return NULL; 2389 } 2390 2391 /* get our key Structure */ 2392 symKey = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, wincx); 2393 if (symKey == NULL) { 2394 return NULL; 2395 } 2396 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 2397 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 2398 * it as a real attribute */ 2399 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 2400 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 2401 * etc. Strip out the real attribute here */ 2402 operation &= ~CKA_NSS_MESSAGE_MASK; 2403 } 2404 2405 symKey->origin = PK11_OriginDerive; 2406 2407 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 2408 attrs++; 2409 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 2410 attrs++; 2411 PK11_SETATTRS(attrs, operation, &cktrue, 1); 2412 attrs++; 2413 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); 2414 attrs++; 2415 templateCount = attrs - keyTemplate; 2416 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 2417 2418 keyType = PK11_GetKeyType(target, keySize); 2419 key_size = keySize; 2420 if (key_size == 0) { 2421 if ((key_size = pk11_GetPredefinedKeyLength(keyType))) { 2422 templateCount--; 2423 } else { 2424 /* sigh, some tokens can't figure this out and require 2425 * CKA_VALUE_LEN to be set */ 2426 switch (kdf) { 2427 case CKD_NULL: 2428 key_size = pk11_ECPubKeySize(pubKey); 2429 if (key_size == 0) { 2430 PK11_FreeSymKey(symKey); 2431 return NULL; 2432 } 2433 break; 2434 case CKD_SHA1_KDF: 2435 key_size = SHA1_LENGTH; 2436 break; 2437 case CKD_SHA224_KDF: 2438 key_size = SHA224_LENGTH; 2439 break; 2440 case CKD_SHA256_KDF: 2441 key_size = SHA256_LENGTH; 2442 break; 2443 case CKD_SHA384_KDF: 2444 key_size = SHA384_LENGTH; 2445 break; 2446 case CKD_SHA512_KDF: 2447 key_size = SHA512_LENGTH; 2448 break; 2449 default: 2450 PORT_AssertNotReached("Invalid CKD"); 2451 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 2452 PK11_FreeSymKey(symKey); 2453 return NULL; 2454 } 2455 } 2456 } 2457 symKey->size = key_size; 2458 2459 mechParams = PORT_ZNew(CK_ECDH1_DERIVE_PARAMS); 2460 if (!mechParams) { 2461 PK11_FreeSymKey(symKey); 2462 return NULL; 2463 } 2464 mechParams->kdf = kdf; 2465 if (sharedData == NULL) { 2466 mechParams->ulSharedDataLen = 0; 2467 mechParams->pSharedData = NULL; 2468 } else { 2469 mechParams->ulSharedDataLen = sharedData->len; 2470 mechParams->pSharedData = sharedData->data; 2471 } 2472 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 2473 mechParams->pPublicData = pubKey->u.ec.publicValue.data; 2474 2475 mechanism.mechanism = derive; 2476 mechanism.pParameter = mechParams; 2477 mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); 2478 2479 pk11_EnterKeyMonitor(symKey); 2480 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, &mechanism, 2481 privKey->pkcs11ID, keyTemplate, 2482 templateCount, &symKey->objectID); 2483 pk11_ExitKeyMonitor(symKey); 2484 2485 /* old PKCS #11 spec was ambiguous on what needed to be passed, 2486 * try this again with an encoded public key */ 2487 if (crv != CKR_OK) { 2488 /* For curves that only use X as public value and no encoding we don't 2489 * have to try again. (Currently only Curve25519) */ 2490 if (pk11_ECGetPubkeyEncoding(pubKey) == ECPoint_XOnly) { 2491 goto loser; 2492 } 2493 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 2494 &pubKey->u.ec.publicValue, 2495 SEC_ASN1_GET(SEC_OctetStringTemplate)); 2496 if (pubValue == NULL) { 2497 goto loser; 2498 } 2499 mechParams->ulPublicDataLen = pubValue->len; 2500 mechParams->pPublicData = pubValue->data; 2501 2502 pk11_EnterKeyMonitor(symKey); 2503 crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, 2504 &mechanism, privKey->pkcs11ID, keyTemplate, 2505 templateCount, &symKey->objectID); 2506 pk11_ExitKeyMonitor(symKey); 2507 2508 if ((crv != CKR_OK) && (kdf != CKD_NULL)) { 2509 /* Some PKCS #11 libraries cannot perform the key derivation 2510 * function. So, try calling C_DeriveKey with CKD_NULL and then 2511 * performing the KDF separately. 2512 */ 2513 CK_ULONG derivedKeySize = key_size; 2514 2515 keyType = CKK_GENERIC_SECRET; 2516 key_size = pk11_ECPubKeySize(pubKey); 2517 if (key_size == 0) { 2518 SECITEM_FreeItem(pubValue, PR_TRUE); 2519 goto loser; 2520 } 2521 SharedSecret = symKey; 2522 SharedSecret->size = key_size; 2523 2524 mechParams->kdf = CKD_NULL; 2525 mechParams->ulSharedDataLen = 0; 2526 mechParams->pSharedData = NULL; 2527 mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; 2528 mechParams->pPublicData = pubKey->u.ec.publicValue.data; 2529 2530 pk11_EnterKeyMonitor(SharedSecret); 2531 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, 2532 &mechanism, privKey->pkcs11ID, keyTemplate, 2533 templateCount, &SharedSecret->objectID); 2534 pk11_ExitKeyMonitor(SharedSecret); 2535 2536 if (crv != CKR_OK) { 2537 /* old PKCS #11 spec was ambiguous on what needed to be passed, 2538 * try this one final time with an encoded public key */ 2539 mechParams->ulPublicDataLen = pubValue->len; 2540 mechParams->pPublicData = pubValue->data; 2541 2542 pk11_EnterKeyMonitor(SharedSecret); 2543 crv = PK11_GETTAB(slot)->C_DeriveKey(SharedSecret->session, 2544 &mechanism, privKey->pkcs11ID, keyTemplate, 2545 templateCount, &SharedSecret->objectID); 2546 pk11_ExitKeyMonitor(SharedSecret); 2547 } 2548 2549 /* Perform KDF. */ 2550 if (crv == CKR_OK) { 2551 symKey = pk11_ANSIX963Derive(SharedSecret, kdf, 2552 sharedData, target, operation, 2553 derivedKeySize); 2554 PK11_FreeSymKey(SharedSecret); 2555 if (symKey == NULL) { 2556 SECITEM_FreeItem(pubValue, PR_TRUE); 2557 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 2558 return NULL; 2559 } 2560 } 2561 } 2562 SECITEM_FreeItem(pubValue, PR_TRUE); 2563 } 2564 2565 loser: 2566 PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); 2567 2568 if (crv != CKR_OK) { 2569 PK11_FreeSymKey(symKey); 2570 symKey = NULL; 2571 PORT_SetError(PK11_MapError(crv)); 2572 } 2573 return symKey; 2574 } 2575 2576 PK11SymKey * 2577 PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, 2578 PRBool isSender, SECItem *randomA, SECItem *randomB, 2579 CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, 2580 CK_ATTRIBUTE_TYPE operation, int keySize, 2581 CK_ULONG kdf, SECItem *sharedData, void *wincx) 2582 { 2583 2584 switch (privKey->keyType) { 2585 case keaKey: 2586 case fortezzaKey: 2587 case dhKey: 2588 return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, 2589 derive, target, operation, keySize, wincx); 2590 case ecKey: 2591 case ecMontKey: 2592 return pk11_PubDeriveECKeyWithKDF(privKey, pubKey, isSender, 2593 randomA, randomB, derive, target, 2594 operation, keySize, 2595 kdf, sharedData, wincx); 2596 default: 2597 PORT_SetError(SEC_ERROR_BAD_KEY); 2598 break; 2599 } 2600 2601 return NULL; 2602 } 2603 2604 /* 2605 * this little function uses the Decrypt function to unwrap a key, just in 2606 * case we are having problem with unwrap. NOTE: The key size may 2607 * not be preserved properly for some algorithms! 2608 */ 2609 static PK11SymKey * 2610 pk11_HandUnwrap(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, 2611 CK_MECHANISM *mech, SECItem *inKey, CK_MECHANISM_TYPE target, 2612 CK_ATTRIBUTE *keyTemplate, unsigned int templateCount, 2613 int key_size, void *wincx, CK_RV *crvp, PRBool isPerm) 2614 { 2615 CK_ULONG len; 2616 SECItem outKey; 2617 PK11SymKey *symKey; 2618 CK_RV crv; 2619 PRBool owner = PR_TRUE; 2620 CK_SESSION_HANDLE session; 2621 2622 /* remove any VALUE_LEN parameters */ 2623 if (keyTemplate[templateCount - 1].type == CKA_VALUE_LEN) { 2624 templateCount--; 2625 } 2626 2627 /* keys are almost always aligned, but if we get this far, 2628 * we've gone above and beyond anyway... */ 2629 outKey.data = (unsigned char *)PORT_Alloc(inKey->len); 2630 if (outKey.data == NULL) { 2631 PORT_SetError(SEC_ERROR_NO_MEMORY); 2632 if (crvp) 2633 *crvp = CKR_HOST_MEMORY; 2634 return NULL; 2635 } 2636 len = inKey->len; 2637 2638 /* use NULL IV's for wrapping */ 2639 session = pk11_GetNewSession(slot, &owner); 2640 if (!owner || !(slot->isThreadSafe)) 2641 PK11_EnterSlotMonitor(slot); 2642 crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, wrappingKey); 2643 if (crv != CKR_OK) { 2644 if (!owner || !(slot->isThreadSafe)) 2645 PK11_ExitSlotMonitor(slot); 2646 pk11_CloseSession(slot, session, owner); 2647 PORT_Free(outKey.data); 2648 PORT_SetError(PK11_MapError(crv)); 2649 if (crvp) 2650 *crvp = crv; 2651 return NULL; 2652 } 2653 crv = PK11_GETTAB(slot)->C_Decrypt(session, inKey->data, inKey->len, 2654 outKey.data, &len); 2655 if (!owner || !(slot->isThreadSafe)) 2656 PK11_ExitSlotMonitor(slot); 2657 pk11_CloseSession(slot, session, owner); 2658 if (crv != CKR_OK) { 2659 PORT_Free(outKey.data); 2660 PORT_SetError(PK11_MapError(crv)); 2661 if (crvp) 2662 *crvp = crv; 2663 return NULL; 2664 } 2665 2666 outKey.len = (key_size == 0) ? len : key_size; 2667 outKey.type = siBuffer; 2668 2669 if (PK11_DoesMechanism(slot, target)) { 2670 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, 2671 isPerm, keyTemplate, 2672 templateCount, &outKey, wincx); 2673 } else { 2674 slot = PK11_GetBestSlot(target, wincx); 2675 if (slot == NULL) { 2676 PORT_SetError(SEC_ERROR_NO_MODULE); 2677 PORT_Free(outKey.data); 2678 if (crvp) 2679 *crvp = CKR_DEVICE_ERROR; 2680 return NULL; 2681 } 2682 symKey = pk11_ImportSymKeyWithTempl(slot, target, PK11_OriginUnwrap, 2683 isPerm, keyTemplate, 2684 templateCount, &outKey, wincx); 2685 PK11_FreeSlot(slot); 2686 } 2687 PORT_Free(outKey.data); 2688 2689 if (crvp) 2690 *crvp = symKey ? CKR_OK : CKR_DEVICE_ERROR; 2691 return symKey; 2692 } 2693 2694 /* 2695 * The wrap/unwrap function is pretty much the same for private and 2696 * public keys. It's just getting the Object ID and slot right. This is 2697 * the combined unwrap function. 2698 */ 2699 static PK11SymKey * 2700 pk11_AnyUnwrapKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE wrappingKey, 2701 CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey, 2702 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize, 2703 void *wincx, CK_ATTRIBUTE *userAttr, unsigned int numAttrs, PRBool isPerm) 2704 { 2705 PK11SymKey *symKey; 2706 SECItem *param_free = NULL; 2707 CK_BBOOL cktrue = CK_TRUE; 2708 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 2709 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 2710 CK_ULONG valueLen = 0; 2711 CK_MECHANISM mechanism; 2712 CK_SESSION_HANDLE rwsession; 2713 CK_RV crv; 2714 CK_MECHANISM_INFO mechanism_info; 2715 #define MAX_ADD_ATTRS 4 2716 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS + MAX_ADD_ATTRS]; 2717 #undef MAX_ADD_ATTRS 2718 CK_ATTRIBUTE *attrs = keyTemplate; 2719 unsigned int templateCount; 2720 2721 if (numAttrs > MAX_TEMPL_ATTRS) { 2722 PORT_SetError(SEC_ERROR_INVALID_ARGS); 2723 return NULL; 2724 } 2725 /* CKA_NSS_MESSAGE is a fake operation to distinguish between 2726 * Normal Encrypt/Decrypt and MessageEncrypt/Decrypt. Don't try to set 2727 * it as a real attribute */ 2728 if ((operation & CKA_NSS_MESSAGE_MASK) == CKA_NSS_MESSAGE) { 2729 /* Message is or'd with a real Attribute (CKA_ENCRYPT, CKA_DECRYPT), 2730 * etc. Strip out the real attribute here */ 2731 operation &= ~CKA_NSS_MESSAGE_MASK; 2732 } 2733 2734 /* first copy caller attributes in. */ 2735 for (templateCount = 0; templateCount < numAttrs; ++templateCount) { 2736 *attrs++ = *userAttr++; 2737 } 2738 2739 /* We only add the following attributes to the template if the caller 2740 ** didn't already supply them. 2741 */ 2742 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_CLASS)) { 2743 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof keyClass); 2744 attrs++; 2745 } 2746 if (!pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_KEY_TYPE)) { 2747 keyType = PK11_GetKeyType(target, keySize); 2748 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof keyType); 2749 attrs++; 2750 } 2751 if ((operation != CKA_FLAGS_ONLY) && 2752 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, operation)) { 2753 PK11_SETATTRS(attrs, operation, &cktrue, 1); 2754 attrs++; 2755 } 2756 2757 /* 2758 * must be last in case we need to use this template to import the key 2759 */ 2760 if (keySize > 0 && 2761 !pk11_FindAttrInTemplate(keyTemplate, numAttrs, CKA_VALUE_LEN)) { 2762 valueLen = (CK_ULONG)keySize; 2763 PK11_SETATTRS(attrs, CKA_VALUE_LEN, &valueLen, sizeof valueLen); 2764 attrs++; 2765 } 2766 2767 templateCount = attrs - keyTemplate; 2768 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 2769 2770 /* find out if we can do wrap directly. Because the RSA case if *very* 2771 * common, cache the results for it. */ 2772 if ((wrapType == CKM_RSA_PKCS) && (slot->hasRSAInfo)) { 2773 mechanism_info.flags = slot->RSAInfoFlags; 2774 } else { 2775 if (!slot->isThreadSafe) 2776 PK11_EnterSlotMonitor(slot); 2777 crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID, wrapType, 2778 &mechanism_info); 2779 if (!slot->isThreadSafe) 2780 PK11_ExitSlotMonitor(slot); 2781 if (crv != CKR_OK) { 2782 mechanism_info.flags = 0; 2783 } 2784 if (wrapType == CKM_RSA_PKCS) { 2785 slot->RSAInfoFlags = mechanism_info.flags; 2786 slot->hasRSAInfo = PR_TRUE; 2787 } 2788 } 2789 2790 /* initialize the mechanism structure */ 2791 mechanism.mechanism = wrapType; 2792 /* use NULL IV's for wrapping */ 2793 if (param == NULL) 2794 param = param_free = PK11_ParamFromIV(wrapType, NULL); 2795 if (param) { 2796 mechanism.pParameter = param->data; 2797 mechanism.ulParameterLen = param->len; 2798 } else { 2799 mechanism.pParameter = NULL; 2800 mechanism.ulParameterLen = 0; 2801 } 2802 2803 if ((mechanism_info.flags & CKF_DECRYPT) && !PK11_DoesMechanism(slot, target)) { 2804 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, 2805 target, keyTemplate, templateCount, keySize, 2806 wincx, &crv, isPerm); 2807 if (symKey) { 2808 if (param_free) 2809 SECITEM_FreeItem(param_free, PR_TRUE); 2810 return symKey; 2811 } 2812 /* 2813 * if the RSA OP simply failed, don't try to unwrap again 2814 * with this module. 2815 */ 2816 if (crv == CKR_DEVICE_ERROR) { 2817 if (param_free) 2818 SECITEM_FreeItem(param_free, PR_TRUE); 2819 return NULL; 2820 } 2821 /* fall through, maybe they incorrectly set CKF_DECRYPT */ 2822 } 2823 2824 /* get our key Structure */ 2825 symKey = pk11_CreateSymKey(slot, target, !isPerm, PR_TRUE, wincx); 2826 if (symKey == NULL) { 2827 if (param_free) 2828 SECITEM_FreeItem(param_free, PR_TRUE); 2829 return NULL; 2830 } 2831 2832 symKey->size = keySize; 2833 symKey->origin = PK11_OriginUnwrap; 2834 2835 if (isPerm) { 2836 rwsession = PK11_GetRWSession(slot); 2837 } else { 2838 pk11_EnterKeyMonitor(symKey); 2839 rwsession = symKey->session; 2840 } 2841 PORT_Assert(rwsession != CK_INVALID_HANDLE); 2842 if (rwsession == CK_INVALID_HANDLE) 2843 crv = CKR_SESSION_HANDLE_INVALID; 2844 else 2845 crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, wrappingKey, 2846 wrappedKey->data, wrappedKey->len, 2847 keyTemplate, templateCount, 2848 &symKey->objectID); 2849 if (isPerm) { 2850 if (rwsession != CK_INVALID_HANDLE) 2851 PK11_RestoreROSession(slot, rwsession); 2852 } else { 2853 pk11_ExitKeyMonitor(symKey); 2854 } 2855 if (param_free) 2856 SECITEM_FreeItem(param_free, PR_TRUE); 2857 if (crv != CKR_OK) { 2858 PK11_FreeSymKey(symKey); 2859 symKey = NULL; 2860 if (crv != CKR_DEVICE_ERROR) { 2861 /* try hand Unwrapping */ 2862 symKey = pk11_HandUnwrap(slot, wrappingKey, &mechanism, wrappedKey, 2863 target, keyTemplate, templateCount, 2864 keySize, wincx, NULL, isPerm); 2865 } 2866 } 2867 2868 return symKey; 2869 } 2870 2871 /* use a symetric key to unwrap another symetric key */ 2872 PK11SymKey * 2873 PK11_UnwrapSymKey(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, 2874 SECItem *param, SECItem *wrappedKey, 2875 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 2876 int keySize) 2877 { 2878 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 2879 wrapType, param, wrappedKey, target, operation, keySize, 2880 wrappingKey->cx, NULL, 0, PR_FALSE); 2881 } 2882 2883 /* use a symetric key to unwrap another symetric key */ 2884 PK11SymKey * 2885 PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType, 2886 SECItem *param, SECItem *wrappedKey, 2887 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 2888 int keySize, CK_FLAGS flags) 2889 { 2890 CK_BBOOL ckTrue = CK_TRUE; 2891 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 2892 unsigned int templateCount; 2893 2894 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 2895 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 2896 wrapType, param, wrappedKey, target, operation, keySize, 2897 wrappingKey->cx, keyTemplate, templateCount, PR_FALSE); 2898 } 2899 2900 PK11SymKey * 2901 PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey, 2902 CK_MECHANISM_TYPE wrapType, 2903 SECItem *param, SECItem *wrappedKey, 2904 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, 2905 int keySize, CK_FLAGS flags, PRBool isPerm) 2906 { 2907 CK_BBOOL cktrue = CK_TRUE; 2908 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 2909 CK_ATTRIBUTE *attrs; 2910 unsigned int templateCount; 2911 2912 attrs = keyTemplate; 2913 if (isPerm) { 2914 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); 2915 attrs++; 2916 } 2917 templateCount = attrs - keyTemplate; 2918 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 2919 2920 return pk11_AnyUnwrapKey(wrappingKey->slot, wrappingKey->objectID, 2921 wrapType, param, wrappedKey, target, operation, keySize, 2922 wrappingKey->cx, keyTemplate, templateCount, isPerm); 2923 } 2924 2925 /* unwrap a symmetric key with a private key. Only supports CKM_RSA_PKCS. */ 2926 PK11SymKey * 2927 PK11_PubUnwrapSymKey(SECKEYPrivateKey *wrappingKey, SECItem *wrappedKey, 2928 CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize) 2929 { 2930 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 2931 2932 return PK11_PubUnwrapSymKeyWithMechanism(wrappingKey, wrapType, NULL, 2933 wrappedKey, target, operation, 2934 keySize); 2935 } 2936 2937 /* unwrap a symmetric key with a private key with the given parameters. */ 2938 PK11SymKey * 2939 PK11_PubUnwrapSymKeyWithMechanism(SECKEYPrivateKey *wrappingKey, 2940 CK_MECHANISM_TYPE mechType, SECItem *param, 2941 SECItem *wrappedKey, CK_MECHANISM_TYPE target, 2942 CK_ATTRIBUTE_TYPE operation, int keySize) 2943 { 2944 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 2945 2946 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) { 2947 PK11_HandlePasswordCheck(slot, wrappingKey->wincx); 2948 } 2949 2950 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, mechType, param, 2951 wrappedKey, target, operation, keySize, 2952 wrappingKey->wincx, NULL, 0, PR_FALSE); 2953 } 2954 2955 /* unwrap a symetric key with a private key. */ 2956 PK11SymKey * 2957 PK11_PubUnwrapSymKeyWithFlags(SECKEYPrivateKey *wrappingKey, 2958 SECItem *wrappedKey, CK_MECHANISM_TYPE target, 2959 CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags) 2960 { 2961 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 2962 CK_BBOOL ckTrue = CK_TRUE; 2963 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 2964 unsigned int templateCount; 2965 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 2966 2967 templateCount = pk11_OpFlagsToAttributes(flags, keyTemplate, &ckTrue); 2968 2969 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) { 2970 PK11_HandlePasswordCheck(slot, wrappingKey->wincx); 2971 } 2972 2973 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, 2974 wrapType, NULL, wrappedKey, target, operation, keySize, 2975 wrappingKey->wincx, keyTemplate, templateCount, PR_FALSE); 2976 } 2977 2978 PK11SymKey * 2979 PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey, 2980 SECItem *wrappedKey, CK_MECHANISM_TYPE target, 2981 CK_ATTRIBUTE_TYPE operation, int keySize, 2982 CK_FLAGS flags, PRBool isPerm) 2983 { 2984 CK_MECHANISM_TYPE wrapType = pk11_mapWrapKeyType(wrappingKey->keyType); 2985 CK_BBOOL cktrue = CK_TRUE; 2986 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 2987 CK_ATTRIBUTE *attrs; 2988 unsigned int templateCount; 2989 PK11SlotInfo *slot = wrappingKey->pkcs11Slot; 2990 2991 attrs = keyTemplate; 2992 if (isPerm) { 2993 PK11_SETATTRS(attrs, CKA_TOKEN, &cktrue, sizeof(CK_BBOOL)); 2994 attrs++; 2995 } 2996 templateCount = attrs - keyTemplate; 2997 2998 templateCount += pk11_OpFlagsToAttributes(flags, attrs, &cktrue); 2999 3000 if (SECKEY_HAS_ATTRIBUTE_SET(wrappingKey, CKA_PRIVATE)) { 3001 PK11_HandlePasswordCheck(slot, wrappingKey->wincx); 3002 } 3003 3004 return pk11_AnyUnwrapKey(slot, wrappingKey->pkcs11ID, 3005 wrapType, NULL, wrappedKey, target, operation, keySize, 3006 wrappingKey->wincx, keyTemplate, templateCount, isPerm); 3007 } 3008 3009 PK11SymKey * 3010 PK11_CopySymKeyForSigning(PK11SymKey *originalKey, CK_MECHANISM_TYPE mech) 3011 { 3012 CK_RV crv; 3013 CK_ATTRIBUTE setTemplate; 3014 CK_BBOOL ckTrue = CK_TRUE; 3015 PK11SlotInfo *slot = originalKey->slot; 3016 3017 /* first just try to set this key up for signing */ 3018 PK11_SETATTRS(&setTemplate, CKA_SIGN, &ckTrue, sizeof(ckTrue)); 3019 pk11_EnterKeyMonitor(originalKey); 3020 crv = PK11_GETTAB(slot)->C_SetAttributeValue(originalKey->session, 3021 originalKey->objectID, &setTemplate, 1); 3022 pk11_ExitKeyMonitor(originalKey); 3023 if (crv == CKR_OK) { 3024 return PK11_ReferenceSymKey(originalKey); 3025 } 3026 3027 /* nope, doesn't like it, use the pk11 copy object command */ 3028 return pk11_CopyToSlot(slot, mech, CKA_SIGN, originalKey); 3029 } 3030 3031 void 3032 PK11_SetFortezzaHack(PK11SymKey *symKey) 3033 { 3034 symKey->origin = PK11_OriginFortezzaHack; 3035 } 3036 3037 /* 3038 * This is required to allow FORTEZZA_NULL and FORTEZZA_RC4 3039 * working. This function simply gets a valid IV for the keys. 3040 */ 3041 SECStatus 3042 PK11_GenerateFortezzaIV(PK11SymKey *symKey, unsigned char *iv, int len) 3043 { 3044 CK_MECHANISM mech_info; 3045 CK_ULONG count = 0; 3046 CK_RV crv; 3047 SECStatus rv = SECFailure; 3048 3049 mech_info.mechanism = CKM_SKIPJACK_CBC64; 3050 mech_info.pParameter = iv; 3051 mech_info.ulParameterLen = len; 3052 3053 /* generate the IV for fortezza */ 3054 PK11_EnterSlotMonitor(symKey->slot); 3055 crv = PK11_GETTAB(symKey->slot)->C_EncryptInit(symKey->slot->session, &mech_info, symKey->objectID); 3056 if (crv == CKR_OK) { 3057 PK11_GETTAB(symKey->slot)->C_EncryptFinal(symKey->slot->session, NULL, &count); 3058 rv = SECSuccess; 3059 } 3060 PK11_ExitSlotMonitor(symKey->slot); 3061 return rv; 3062 } 3063 3064 CK_OBJECT_HANDLE 3065 PK11_GetSymKeyHandle(PK11SymKey *symKey) 3066 { 3067 return symKey->objectID; 3068 } 3069 3070 SECStatus 3071 PK11_Encapsulate(SECKEYPublicKey *pubKey, CK_MECHANISM_TYPE target, 3072 PK11AttrFlags attrFlags, CK_FLAGS opFlags, 3073 PK11SymKey **outKey, SECItem **outCiphertext) 3074 { 3075 PORT_Assert(pubKey); 3076 PORT_Assert(outKey); 3077 PORT_Assert(outCiphertext); 3078 3079 PK11SlotInfo *slot = pubKey->pkcs11Slot; 3080 3081 PK11SymKey *sharedSecret = NULL; 3082 SECItem *ciphertext = NULL; 3083 3084 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 3085 unsigned int templateCount; 3086 3087 CK_ATTRIBUTE *attrs; 3088 CK_BBOOL cktrue = CK_TRUE; 3089 CK_BBOOL ckfalse = CK_FALSE; 3090 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 3091 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 3092 CK_MECHANISM_TYPE kemType = pk11_mapKemKeyType(pubKey->keyType); 3093 CK_MECHANISM mech = { kemType, NULL, 0 }; 3094 CK_ULONG ciphertextLen = 0; 3095 CK_RV crv; 3096 3097 /* set up the target key template */ 3098 attrs = keyTemplate; 3099 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 3100 attrs++; 3101 3102 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 3103 attrs++; 3104 3105 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); 3106 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); 3107 3108 templateCount = attrs - keyTemplate; 3109 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 3110 3111 *outKey = NULL; 3112 *outCiphertext = NULL; 3113 3114 /* create a struxture for the target key */ 3115 sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL); 3116 if (sharedSecret == NULL) { 3117 PORT_SetError(SEC_ERROR_NO_MEMORY); 3118 return SECFailure; 3119 } 3120 sharedSecret->origin = PK11_OriginDerive; 3121 3122 /* this path is KEM mechanism agnostic */ 3123 if (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE) >= 0) { 3124 pk11_EnterKeyMonitor(sharedSecret); 3125 /* get the length the normal PKCS #11 way. This works no matter 3126 * what the KEM is and we don't have to try to guess the KEM length 3127 * from the key */ 3128 crv = PK11_GETTAB(slot)->C_EncapsulateKey(sharedSecret->session, 3129 &mech, 3130 pubKey->pkcs11ID, 3131 keyTemplate, 3132 templateCount, 3133 NULL, 3134 &ciphertextLen, 3135 &sharedSecret->objectID); 3136 pk11_ExitKeyMonitor(sharedSecret); 3137 if ((crv != CKR_OK) && (crv != CKR_BUFFER_TOO_SMALL) && 3138 (crv != CKR_KEY_SIZE_RANGE)) { 3139 goto loser; 3140 } 3141 ciphertext = SECITEM_AllocItem(NULL, NULL, ciphertextLen); 3142 if (ciphertext == NULL) { 3143 crv = CKR_HOST_MEMORY; 3144 goto loser; 3145 } 3146 pk11_EnterKeyMonitor(sharedSecret); 3147 /* Now do the encapsulate */ 3148 /* NOTE: the PKCS #11 order of the parameters is different from 3149 * the vendor interface */ 3150 crv = PK11_GETTAB(slot)->C_EncapsulateKey(sharedSecret->session, 3151 &mech, 3152 pubKey->pkcs11ID, 3153 keyTemplate, 3154 templateCount, 3155 ciphertext->data, 3156 &ciphertextLen, 3157 &sharedSecret->objectID); 3158 pk11_ExitKeyMonitor(sharedSecret); 3159 if (crv != CKR_OK) { 3160 goto loser; 3161 } 3162 ciphertext->len = ciphertextLen; 3163 } else { 3164 /* use the old NSS private interface */ 3165 CK_INTERFACE_PTR KEMInterface = NULL; 3166 CK_UTF8CHAR_PTR KEMInterfaceName = 3167 (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface"; 3168 CK_VERSION KEMInterfaceVersion = { 1, 0 }; 3169 CK_NSS_KEM_FUNCTIONS *KEMInterfaceFunctions = NULL; 3170 CK_NSS_KEM_PARAMETER_SET_TYPE kemParameterSet; 3171 3172 crv = PK11_GETTAB(slot)->C_GetInterface(KEMInterfaceName, 3173 &KEMInterfaceVersion, 3174 &KEMInterface, 0); 3175 if (crv != CKR_OK) { 3176 goto loser; 3177 } 3178 KEMInterfaceFunctions = (CK_NSS_KEM_FUNCTIONS *)(KEMInterface->pFunctionList); 3179 3180 /* the old API expected the parameter set as a parameter, the 3181 * pkcs11 v3.2 gets it from the key */ 3182 kemParameterSet = PK11_ReadULongAttribute(slot, 3183 pubKey->pkcs11ID, 3184 CKA_NSS_PARAMETER_SET); 3185 if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) { 3186 kemParameterSet = PK11_ReadULongAttribute(slot, 3187 pubKey->pkcs11ID, 3188 CKA_PARAMETER_SET); 3189 if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) { 3190 crv = CKR_PUBLIC_KEY_INVALID; 3191 goto loser; 3192 } 3193 } 3194 /* The old interface only ever supported KYBER768 and MLKEM768 3195 * SOME versions of RHEL has MLKEM1024 support, if we want to 3196 * make sure this works with those versions of softoken (without their 3197 * NSS) we should check the kemParamSet and set the mech to 3198 * CKM_NSS_ML_KEM if the key isn't KYBER and the cipher test to 3199 * MLKEM104_CIPHERTEXT_BYTES if the kemParmset is MLKEM1024 */ 3200 mech.mechanism = CKM_NSS_KYBER; 3201 mech.pParameter = (CK_VOID_PTR)&kemParameterSet; 3202 mech.ulParameterLen = sizeof(kemParameterSet); 3203 ciphertextLen = KYBER768_CIPHERTEXT_BYTES; 3204 3205 ciphertext = SECITEM_AllocItem(NULL, NULL, ciphertextLen); 3206 if (ciphertext == NULL) { 3207 crv = CKR_HOST_MEMORY; 3208 goto loser; 3209 } 3210 3211 pk11_EnterKeyMonitor(sharedSecret); 3212 crv = KEMInterfaceFunctions->C_Encapsulate(sharedSecret->session, 3213 &mech, 3214 pubKey->pkcs11ID, 3215 keyTemplate, 3216 templateCount, 3217 &sharedSecret->objectID, 3218 ciphertext->data, 3219 &ciphertextLen); 3220 pk11_ExitKeyMonitor(sharedSecret); 3221 if (crv != CKR_OK) { 3222 goto loser; 3223 } 3224 3225 PORT_Assert(ciphertextLen == ciphertext->len); 3226 } 3227 3228 *outKey = sharedSecret; 3229 *outCiphertext = ciphertext; 3230 3231 return SECSuccess; 3232 3233 loser: 3234 PK11_FreeSymKey(sharedSecret); 3235 SECITEM_FreeItem(ciphertext, PR_TRUE); 3236 PORT_SetError(PK11_MapError(crv)); 3237 return SECFailure; 3238 } 3239 3240 SECStatus 3241 PK11_Decapsulate(SECKEYPrivateKey *privKey, const SECItem *ciphertext, 3242 CK_MECHANISM_TYPE target, PK11AttrFlags attrFlags, 3243 CK_FLAGS opFlags, PK11SymKey **outKey) 3244 { 3245 PORT_Assert(privKey); 3246 PORT_Assert(ciphertext); 3247 PORT_Assert(outKey); 3248 3249 PK11SlotInfo *slot = privKey->pkcs11Slot; 3250 3251 PK11SymKey *sharedSecret; 3252 3253 CK_ATTRIBUTE keyTemplate[MAX_TEMPL_ATTRS]; 3254 unsigned int templateCount; 3255 3256 CK_ATTRIBUTE *attrs; 3257 CK_BBOOL cktrue = CK_TRUE; 3258 CK_BBOOL ckfalse = CK_FALSE; 3259 CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; 3260 CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; 3261 CK_MECHANISM_TYPE kemType = pk11_mapKemKeyType(privKey->keyType); 3262 CK_MECHANISM mech = { kemType, NULL, 0 }; 3263 3264 CK_RV crv; 3265 3266 *outKey = NULL; 3267 sharedSecret = pk11_CreateSymKey(slot, target, PR_TRUE, PR_TRUE, NULL); 3268 if (sharedSecret == NULL) { 3269 PORT_SetError(SEC_ERROR_NO_MEMORY); 3270 return SECFailure; 3271 } 3272 sharedSecret->origin = PK11_OriginUnwrap; 3273 3274 attrs = keyTemplate; 3275 PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); 3276 attrs++; 3277 3278 PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); 3279 attrs++; 3280 3281 attrs += pk11_AttrFlagsToAttributes(attrFlags, attrs, &cktrue, &ckfalse); 3282 attrs += pk11_OpFlagsToAttributes(opFlags, attrs, &cktrue); 3283 3284 templateCount = attrs - keyTemplate; 3285 PR_ASSERT(templateCount <= sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)); 3286 3287 if (PK11_CheckPKCS11Version(slot, 3, 2, PR_TRUE) >= 0) { 3288 pk11_EnterKeyMonitor(sharedSecret); 3289 crv = PK11_GETTAB(slot)->C_DecapsulateKey(sharedSecret->session, 3290 &mech, 3291 privKey->pkcs11ID, 3292 keyTemplate, 3293 templateCount, 3294 ciphertext->data, 3295 ciphertext->len, 3296 &sharedSecret->objectID); 3297 pk11_ExitKeyMonitor(sharedSecret); 3298 if (crv != CKR_OK) { 3299 goto loser; 3300 } 3301 } else { 3302 CK_INTERFACE_PTR KEMInterface = NULL; 3303 CK_UTF8CHAR_PTR KEMInterfaceName = 3304 (CK_UTF8CHAR_PTR) "Vendor NSS KEM Interface"; 3305 CK_VERSION KEMInterfaceVersion = { 1, 0 }; 3306 CK_NSS_KEM_FUNCTIONS *KEMInterfaceFunctions = NULL; 3307 3308 crv = PK11_GETTAB(slot)->C_GetInterface(KEMInterfaceName, 3309 &KEMInterfaceVersion, 3310 &KEMInterface, 0); 3311 if (crv != CKR_OK) { 3312 PORT_SetError(PK11_MapError(crv)); 3313 goto loser; 3314 } 3315 KEMInterfaceFunctions = 3316 (CK_NSS_KEM_FUNCTIONS *)(KEMInterface->pFunctionList); 3317 3318 /* the old API expected the parameter set as a parameter, the 3319 * pkcs11 v3.2 gets it from the key */ 3320 CK_ULONG kemParameterSet = PK11_ReadULongAttribute(slot, 3321 privKey->pkcs11ID, 3322 CKA_NSS_PARAMETER_SET); 3323 if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) { 3324 kemParameterSet = PK11_ReadULongAttribute(slot, 3325 privKey->pkcs11ID, 3326 CKA_PARAMETER_SET); 3327 if (kemParameterSet == CK_UNAVAILABLE_INFORMATION) { 3328 crv = CKR_KEY_HANDLE_INVALID; 3329 goto loser; 3330 } 3331 } 3332 /* The old interface only ever supported KYBER768 and MLKEM768 3333 * SOME versions of RHEL has MLKEM1024 support, if we want to 3334 * make sure this works with those versions of softoken (without their 3335 * NSS) we should check the kemParamSet and set the mech to 3336 * CKM_NSS_ML_KEM if the key isn't KYBER and the cipher test to 3337 * MLKEM104_CIPHERTEXT_BYTES if the kemParmset is MLKEM1024 */ 3338 mech.mechanism = CKM_NSS_KYBER; 3339 mech.pParameter = (CK_VOID_PTR)&kemParameterSet; 3340 mech.ulParameterLen = sizeof(kemParameterSet); 3341 3342 pk11_EnterKeyMonitor(sharedSecret); 3343 crv = KEMInterfaceFunctions->C_Decapsulate(sharedSecret->session, 3344 &mech, 3345 privKey->pkcs11ID, 3346 ciphertext->data, 3347 ciphertext->len, 3348 keyTemplate, 3349 templateCount, 3350 &sharedSecret->objectID); 3351 pk11_ExitKeyMonitor(sharedSecret); 3352 if (crv != CKR_OK) { 3353 goto loser; 3354 } 3355 } 3356 3357 *outKey = sharedSecret; 3358 return SECSuccess; 3359 3360 loser: 3361 PK11_FreeSymKey(sharedSecret); 3362 return SECFailure; 3363 }