sftkpwd.c (46623B)
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 * The following code handles the storage of PKCS 11 modules used by the 6 * NSS. For the rest of NSS, only one kind of database handle exists: 7 * 8 * SFTKDBHandle 9 * 10 * There is one SFTKDBHandle for the each key database and one for each cert 11 * database. These databases are opened as associated pairs, one pair per 12 * slot. SFTKDBHandles are reference counted objects. 13 * 14 * Each SFTKDBHandle points to a low level database handle (SDB). This handle 15 * represents the underlying physical database. These objects are not 16 * reference counted, an are 'owned' by their respective SFTKDBHandles. 17 * 18 * 19 */ 20 #include "sftkdb.h" 21 #include "sftkdbti.h" 22 #include "pkcs11t.h" 23 #include "pkcs11i.h" 24 #include "sdb.h" 25 #include "prprf.h" 26 #include "secasn1.h" 27 #include "pratom.h" 28 #include "blapi.h" 29 #include "secoid.h" 30 #include "lowpbe.h" 31 #include "secdert.h" 32 #include "prsystem.h" 33 #include "lgglue.h" 34 #include "secerr.h" 35 #include "softoken.h" 36 37 static const int NSS_MP_PBE_ITERATION_COUNT = 10000; 38 39 static int 40 getPBEIterationCount(void) 41 { 42 int c = NSS_MP_PBE_ITERATION_COUNT; 43 44 char *val = getenv("NSS_MIN_MP_PBE_ITERATION_COUNT"); 45 if (val && *val) { 46 int minimum = atoi(val); 47 if (c < minimum) { 48 c = minimum; 49 } 50 } 51 52 val = getenv("NSS_MAX_MP_PBE_ITERATION_COUNT"); 53 if (val && *val) { 54 int maximum = atoi(val); 55 if (c > maximum) { 56 c = maximum; 57 } 58 } 59 /* never let c be less than one, no matter what the environment 60 * variable is set to */ 61 if (c < 1) { 62 c = 1; 63 } 64 return c; 65 } 66 67 PRBool 68 sftk_isLegacyIterationCountAllowed(void) 69 { 70 static const char *legacyCountEnvVar = 71 "NSS_ALLOW_LEGACY_DBM_ITERATION_COUNT"; 72 char *iterEnv = getenv(legacyCountEnvVar); 73 return (iterEnv && strcmp("0", iterEnv) != 0); 74 } 75 76 /****************************************************************** 77 * 78 * Key DB password handling functions 79 * 80 * These functions manage the key db password (set, reset, initialize, use). 81 * 82 * The key is managed on 'this side' of the database. All private data is 83 * encrypted before it is sent to the database itself. Besides PBE's, the 84 * database management code can also mix in various fixed keys so the data 85 * in the database is no longer considered 'plain text'. 86 */ 87 88 /* take string password and turn it into a key. The key is dependent 89 * on a global salt entry acquired from the database. This salted 90 * value will be based to a pkcs5 pbe function before it is used 91 * in an actual encryption */ 92 static SECStatus 93 sftkdb_passwordToKey(SFTKDBHandle *keydb, SECItem *salt, 94 const char *pw, SECItem *key) 95 { 96 HASH_HashType hType; 97 const SECHashObject *hashObj; 98 void *ctx = NULL; 99 SECStatus rv = SECFailure; 100 101 hType = salt->len == SHA384_LENGTH ? HASH_AlgSHA384 : HASH_AlgSHA1; 102 hashObj = HASH_GetRawHashObject(hType); 103 104 if (!pw) { 105 PORT_SetError(SEC_ERROR_INVALID_ARGS); 106 return SECFailure; 107 } 108 109 key->data = PORT_Alloc(hashObj->length); 110 if (key->data == NULL) { 111 goto loser; 112 } 113 key->len = hashObj->length; 114 115 ctx = hashObj->create(); 116 if (ctx == NULL) { 117 goto loser; 118 } 119 hashObj->begin(ctx); 120 if (salt && salt->data) { 121 hashObj->update(ctx, salt->data, salt->len); 122 } 123 hashObj->update(ctx, (unsigned char *)pw, PORT_Strlen(pw)); 124 hashObj->end(ctx, key->data, &key->len, key->len); 125 rv = SECSuccess; 126 127 loser: 128 if (ctx) { 129 hashObj->destroy(ctx, PR_TRUE); 130 } 131 if (rv != SECSuccess) { 132 if (key->data != NULL) { 133 PORT_ZFree(key->data, key->len); 134 } 135 key->data = NULL; 136 } 137 return rv; 138 } 139 140 /* 141 * Cipher text stored in the database contains 3 elements: 142 * 1) an identifier describing the encryption algorithm. 143 * 2) an entry specific salt value. 144 * 3) the encrypted value. 145 * 146 * The following data structure represents the encrypted data in a decoded 147 * (but still encrypted) form. 148 */ 149 typedef struct sftkCipherValueStr sftkCipherValue; 150 struct sftkCipherValueStr { 151 PLArenaPool *arena; 152 SECOidTag alg; 153 NSSPKCS5PBEParameter *param; 154 SECItem salt; 155 SECItem value; 156 }; 157 158 #define SFTK_CIPHERTEXT_VERSION 3 159 160 struct SFTKDBEncryptedDataInfoStr { 161 SECAlgorithmID algorithm; 162 SECItem encryptedData; 163 }; 164 typedef struct SFTKDBEncryptedDataInfoStr SFTKDBEncryptedDataInfo; 165 166 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) 167 168 const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = { 169 { SEC_ASN1_SEQUENCE, 170 0, NULL, sizeof(SFTKDBEncryptedDataInfo) }, 171 { SEC_ASN1_INLINE | SEC_ASN1_XTRN, 172 offsetof(SFTKDBEncryptedDataInfo, algorithm), 173 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, 174 { SEC_ASN1_OCTET_STRING, 175 offsetof(SFTKDBEncryptedDataInfo, encryptedData) }, 176 { 0 } 177 }; 178 179 /* 180 * This parses the cipherText into cipher value. NOTE: cipherValue will point 181 * to data in cipherText, if cipherText is freed, cipherValue will be invalid. 182 */ 183 static SECStatus 184 sftkdb_decodeCipherText(const SECItem *cipherText, sftkCipherValue *cipherValue) 185 { 186 PLArenaPool *arena = NULL; 187 SFTKDBEncryptedDataInfo edi; 188 SECStatus rv; 189 190 PORT_Assert(cipherValue); 191 cipherValue->arena = NULL; 192 cipherValue->param = NULL; 193 194 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 195 if (arena == NULL) { 196 return SECFailure; 197 } 198 199 rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate, 200 cipherText); 201 if (rv != SECSuccess) { 202 goto loser; 203 } 204 cipherValue->alg = SECOID_GetAlgorithmTag(&edi.algorithm); 205 cipherValue->param = nsspkcs5_AlgidToParam(&edi.algorithm); 206 if (cipherValue->param == NULL) { 207 goto loser; 208 } 209 cipherValue->value = edi.encryptedData; 210 cipherValue->arena = arena; 211 212 return SECSuccess; 213 loser: 214 if (cipherValue->param) { 215 nsspkcs5_DestroyPBEParameter(cipherValue->param); 216 cipherValue->param = NULL; 217 } 218 if (arena) { 219 PORT_FreeArena(arena, PR_FALSE); 220 } 221 return SECFailure; 222 } 223 224 /* 225 * unlike decode, Encode actually allocates a SECItem the caller must free 226 * The caller can pass an optional arena to to indicate where to place 227 * the resultant cipherText. 228 */ 229 static SECStatus 230 sftkdb_encodeCipherText(PLArenaPool *arena, sftkCipherValue *cipherValue, 231 SECItem **cipherText) 232 { 233 SFTKDBEncryptedDataInfo edi; 234 SECAlgorithmID *algid; 235 SECStatus rv; 236 PLArenaPool *localArena = NULL; 237 238 localArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 239 if (localArena == NULL) { 240 return SECFailure; 241 } 242 243 algid = nsspkcs5_CreateAlgorithmID(localArena, cipherValue->alg, 244 cipherValue->param); 245 if (algid == NULL) { 246 rv = SECFailure; 247 goto loser; 248 } 249 rv = SECOID_CopyAlgorithmID(localArena, &edi.algorithm, algid); 250 SECOID_DestroyAlgorithmID(algid, PR_TRUE); 251 if (rv != SECSuccess) { 252 goto loser; 253 } 254 edi.encryptedData = cipherValue->value; 255 256 *cipherText = SEC_ASN1EncodeItem(arena, NULL, &edi, 257 sftkdb_EncryptedDataInfoTemplate); 258 if (*cipherText == NULL) { 259 rv = SECFailure; 260 } 261 262 loser: 263 if (localArena) { 264 PORT_FreeArena(localArena, PR_TRUE); 265 } 266 267 return rv; 268 } 269 270 /* 271 * Use our key to decode a cipherText block from the database. 272 * 273 * plain text is allocated by nsspkcs5_CipherData and must be freed 274 * with SECITEM_FreeItem by the caller. 275 */ 276 SECStatus 277 sftkdb_DecryptAttribute(SFTKDBHandle *handle, SECItem *passKey, 278 CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type, 279 SECItem *cipherText, SECItem **plain) 280 { 281 SECStatus rv; 282 sftkCipherValue cipherValue; 283 284 /* First get the cipher type */ 285 *plain = NULL; 286 rv = sftkdb_decodeCipherText(cipherText, &cipherValue); 287 if (rv != SECSuccess) { 288 goto loser; 289 } 290 291 *plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value, 292 PR_FALSE, NULL); 293 if (*plain == NULL) { 294 rv = SECFailure; 295 goto loser; 296 } 297 298 /* If we are using aes 256, we need to check authentication as well.*/ 299 if ((type != CKT_INVALID_TYPE) && 300 (cipherValue.alg == SEC_OID_PKCS5_PBES2) && 301 (cipherValue.param->encAlg == SEC_OID_AES_256_CBC)) { 302 SECItem signature; 303 unsigned char signData[SDB_MAX_META_DATA_LEN]; 304 CK_RV crv; 305 306 /* if we get here from the old legacy db, there is clearly an 307 * error, don't return the plaintext */ 308 if (handle == NULL) { 309 rv = SECFailure; 310 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); 311 goto loser; 312 } 313 314 signature.data = signData; 315 signature.len = sizeof(signData); 316 rv = SECFailure; 317 /* sign sftkdb_GetAttriibuteSignature returns a crv, not an rv */ 318 crv = sftkdb_GetAttributeSignature(handle, handle, id, type, 319 &signature); 320 if (crv == CKR_OK) { 321 rv = sftkdb_VerifyAttribute(handle, passKey, CK_INVALID_HANDLE, 322 type, *plain, &signature); 323 } 324 if (rv != SECSuccess) { 325 /* handle bug 1720226 where old versions of NSS misfiled the signature 326 * attribute on password update */ 327 id |= SFTK_KEYDB_TYPE | SFTK_TOKEN_TYPE; 328 signature.len = sizeof(signData); 329 crv = sftkdb_GetAttributeSignature(handle, handle, id, type, 330 &signature); 331 if (crv != CKR_OK) { 332 rv = SECFailure; 333 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 334 goto loser; 335 } 336 rv = sftkdb_VerifyAttribute(handle, passKey, CK_INVALID_HANDLE, 337 type, *plain, &signature); 338 } 339 } 340 341 loser: 342 if (cipherValue.param) { 343 nsspkcs5_DestroyPBEParameter(cipherValue.param); 344 } 345 if (cipherValue.arena) { 346 PORT_FreeArena(cipherValue.arena, PR_FALSE); 347 } 348 /* Item decrypted, but failed integrity, clear it out */ 349 if (*plain && rv != SECSuccess) { 350 SECITEM_ZfreeItem(*plain, PR_TRUE); 351 *plain = NULL; 352 } 353 return rv; 354 } 355 356 /* If the database can't store the integrity check, it's a non-FIPS database 357 * and we use the old encryption scheme for it */ 358 static PRBool 359 sftkdb_useLegacyEncryption(SFTKDBHandle *handle, SDB *db) 360 { 361 if ((handle == NULL) || (db == NULL)) { 362 /* this is the case where the legacy db is calling back to us to 363 * encrypt or decrypt attributes inside the lower level db code. 364 * This is because the legacy db stored keys as pkcs #8 encrypted 365 * blobs rather than individual encrypted attributes */ 366 return PR_TRUE; 367 } 368 /* currently, only the legacy db can't store meta data, but if we 369 * add a new db that also can't store meta data, then it to wouldn't 370 * be able to do the integrity checks. In both cases use the old encryption 371 * algorithms. */ 372 if ((db->sdb_flags & SDB_HAS_META) == 0) { 373 return PR_TRUE; 374 } 375 return PR_FALSE; 376 } 377 378 /* 379 * encrypt a block. This function returned the encrypted ciphertext which 380 * the caller must free. If the caller provides an arena, cipherText will 381 * be allocated out of that arena. This also generated the per entry 382 * salt automatically. 383 */ 384 SECStatus 385 sftkdb_EncryptAttribute(PLArenaPool *arena, SFTKDBHandle *handle, SDB *db, 386 SECItem *passKey, int iterationCount, 387 CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type, 388 SECItem *plainText, SECItem **cipherText) 389 { 390 SECStatus rv; 391 sftkCipherValue cipherValue; 392 SECItem *cipher = NULL; 393 NSSPKCS5PBEParameter *param = NULL; 394 unsigned char saltData[HASH_LENGTH_MAX]; 395 SECItem *signature = NULL; 396 HASH_HashType hashType = HASH_AlgNULL; 397 398 if (sftkdb_useLegacyEncryption(handle, db)) { 399 cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; 400 cipherValue.salt.len = SHA1_LENGTH; 401 hashType = HASH_AlgSHA1; 402 } else { 403 cipherValue.alg = SEC_OID_AES_256_CBC; 404 cipherValue.salt.len = SHA256_LENGTH; 405 hashType = HASH_AlgSHA256; 406 } 407 cipherValue.salt.data = saltData; 408 RNG_GenerateGlobalRandomBytes(saltData, cipherValue.salt.len); 409 410 param = nsspkcs5_NewParam(cipherValue.alg, hashType, &cipherValue.salt, 411 iterationCount); 412 if (param == NULL) { 413 rv = SECFailure; 414 goto loser; 415 } 416 cipher = nsspkcs5_CipherData(param, passKey, plainText, PR_TRUE, NULL); 417 if (cipher == NULL) { 418 rv = SECFailure; 419 goto loser; 420 } 421 cipherValue.value = *cipher; 422 cipherValue.param = param; 423 424 rv = sftkdb_encodeCipherText(arena, &cipherValue, cipherText); 425 if (rv != SECSuccess) { 426 goto loser; 427 } 428 429 /* If we are using aes 256, we need to add authentication as well */ 430 if ((type != CKT_INVALID_TYPE) && 431 (cipherValue.param->encAlg == SEC_OID_AES_256_CBC)) { 432 rv = sftkdb_SignAttribute(arena, handle, db, passKey, iterationCount, 433 CK_INVALID_HANDLE, type, plainText, 434 &signature); 435 if (rv != SECSuccess) { 436 goto loser; 437 } 438 rv = sftkdb_PutAttributeSignature(handle, db, id, type, 439 signature); 440 if (rv != SECSuccess) { 441 goto loser; 442 } 443 } 444 445 loser: 446 if ((arena == NULL) && signature) { 447 SECITEM_ZfreeItem(signature, PR_TRUE); 448 } 449 if (cipher) { 450 SECITEM_FreeItem(cipher, PR_TRUE); 451 } 452 if (param) { 453 nsspkcs5_DestroyPBEParameter(param); 454 } 455 return rv; 456 } 457 458 /* 459 * use the password and the pbe parameters to generate an HMAC for the 460 * given plain text data. This is used by sftkdb_VerifyAttribute and 461 * sftkdb_SignAttribute. Signature is returned in signData. The caller 462 * must preallocate the space in the secitem. 463 */ 464 static SECStatus 465 sftkdb_pbehash(SECOidTag sigOid, SECItem *passKey, 466 NSSPKCS5PBEParameter *param, 467 CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType, 468 SECItem *plainText, SECItem *signData) 469 { 470 SECStatus rv = SECFailure; 471 SECItem *key = NULL; 472 HMACContext *hashCx = NULL; 473 HASH_HashType hashType = HASH_AlgNULL; 474 const SECHashObject *hashObj; 475 unsigned char addressData[SDB_ULONG_SIZE]; 476 hashType = HASH_FromHMACOid(param->encAlg); 477 if (hashType == HASH_AlgNULL) { 478 PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); 479 return SECFailure; 480 } 481 482 hashObj = HASH_GetRawHashObject(hashType); 483 if (hashObj == NULL) { 484 goto loser; 485 } 486 487 key = nsspkcs5_ComputeKeyAndIV(param, passKey, NULL, PR_FALSE); 488 if (!key) { 489 goto loser; 490 } 491 492 hashCx = HMAC_Create(hashObj, key->data, key->len, PR_TRUE); 493 if (!hashCx) { 494 goto loser; 495 } 496 HMAC_Begin(hashCx); 497 /* Tie this value to a particular object. This is most important for 498 * the trust attributes, where and attacker could copy a value for 499 * 'validCA' from another cert in the database */ 500 sftk_ULong2SDBULong(addressData, objectID); 501 HMAC_Update(hashCx, addressData, SDB_ULONG_SIZE); 502 sftk_ULong2SDBULong(addressData, attrType); 503 HMAC_Update(hashCx, addressData, SDB_ULONG_SIZE); 504 505 HMAC_Update(hashCx, plainText->data, plainText->len); 506 rv = HMAC_Finish(hashCx, signData->data, &signData->len, signData->len); 507 508 loser: 509 if (hashCx) { 510 HMAC_Destroy(hashCx, PR_TRUE); 511 } 512 if (key) { 513 SECITEM_ZfreeItem(key, PR_TRUE); 514 } 515 return rv; 516 } 517 518 /* 519 * Use our key to verify a signText block from the database matches 520 * the plainText from the database. The signText is a PKCS 5 v2 pbe. 521 * plainText is the plainText of the attribute. 522 */ 523 SECStatus 524 sftkdb_VerifyAttribute(SFTKDBHandle *handle, 525 SECItem *passKey, CK_OBJECT_HANDLE objectID, 526 CK_ATTRIBUTE_TYPE attrType, 527 SECItem *plainText, SECItem *signText) 528 { 529 SECStatus rv; 530 sftkCipherValue signValue; 531 SECItem signature; 532 unsigned char signData[HASH_LENGTH_MAX]; 533 534 /* First get the cipher type */ 535 rv = sftkdb_decodeCipherText(signText, &signValue); 536 if (rv != SECSuccess) { 537 goto loser; 538 } 539 signature.data = signData; 540 signature.len = sizeof(signData); 541 542 rv = sftkdb_pbehash(signValue.alg, passKey, signValue.param, 543 objectID, attrType, plainText, &signature); 544 if (rv != SECSuccess) { 545 goto loser; 546 } 547 if (SECITEM_CompareItem(&signValue.value, &signature) != 0) { 548 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 549 rv = SECFailure; 550 } 551 552 loser: 553 PORT_Memset(signData, 0, sizeof signData); 554 if (signValue.param) { 555 nsspkcs5_DestroyPBEParameter(signValue.param); 556 } 557 if (signValue.arena) { 558 PORT_FreeArena(signValue.arena, PR_TRUE); 559 } 560 return rv; 561 } 562 563 /* 564 * Use our key to create a signText block the plain text of an 565 * attribute. The signText is a PKCS 5 v2 pbe. 566 */ 567 SECStatus 568 sftkdb_SignAttribute(PLArenaPool *arena, SFTKDBHandle *keyDB, SDB *db, 569 SECItem *passKey, int iterationCount, 570 CK_OBJECT_HANDLE objectID, 571 CK_ATTRIBUTE_TYPE attrType, 572 SECItem *plainText, SECItem **signature) 573 { 574 SECStatus rv; 575 sftkCipherValue signValue; 576 NSSPKCS5PBEParameter *param = NULL; 577 unsigned char saltData[HASH_LENGTH_MAX]; 578 unsigned char signData[HASH_LENGTH_MAX]; 579 SECOidTag hmacAlg = SEC_OID_HMAC_SHA256; /* hash for authentication */ 580 SECOidTag prfAlg = SEC_OID_HMAC_SHA256; /* hash for pb key generation */ 581 HASH_HashType prfType; 582 unsigned int hmacLength; 583 unsigned int prfLength; 584 585 /* this code allows us to fetch the lengths and hashes on the fly 586 * by simply changing the OID above */ 587 prfType = HASH_FromHMACOid(prfAlg); 588 PORT_Assert(prfType != HASH_AlgNULL); 589 prfLength = HASH_GetRawHashObject(prfType)->length; 590 PORT_Assert(prfLength <= HASH_LENGTH_MAX); 591 592 hmacLength = HASH_GetRawHashObject(HASH_FromHMACOid(hmacAlg))->length; 593 PORT_Assert(hmacLength <= HASH_LENGTH_MAX); 594 595 /* initialize our CipherValue structure */ 596 signValue.alg = SEC_OID_PKCS5_PBMAC1; 597 signValue.salt.len = prfLength; 598 signValue.salt.data = saltData; 599 signValue.value.data = signData; 600 signValue.value.len = hmacLength; 601 RNG_GenerateGlobalRandomBytes(saltData, prfLength); 602 603 /* initialize our pkcs5 parameter */ 604 param = nsspkcs5_NewParam(signValue.alg, HASH_AlgSHA1, &signValue.salt, 605 iterationCount); 606 if (param == NULL) { 607 rv = SECFailure; 608 goto loser; 609 } 610 param->keyID = pbeBitGenIntegrityKey; 611 /* set the PKCS 5 v2 parameters, not extractable from the 612 * data passed into nsspkcs5_NewParam */ 613 param->encAlg = hmacAlg; 614 param->hashType = prfType; 615 param->keyLen = hmacLength; 616 rv = SECOID_SetAlgorithmID(param->poolp, ¶m->prfAlg, prfAlg, NULL); 617 if (rv != SECSuccess) { 618 goto loser; 619 } 620 621 /* calculate the mac */ 622 rv = sftkdb_pbehash(signValue.alg, passKey, param, objectID, attrType, 623 plainText, &signValue.value); 624 if (rv != SECSuccess) { 625 goto loser; 626 } 627 signValue.param = param; 628 629 /* write it out */ 630 rv = sftkdb_encodeCipherText(arena, &signValue, signature); 631 if (rv != SECSuccess) { 632 goto loser; 633 } 634 635 loser: 636 PORT_Memset(signData, 0, sizeof signData); 637 if (param) { 638 nsspkcs5_DestroyPBEParameter(param); 639 } 640 return rv; 641 } 642 643 /* 644 * safely swith the passed in key for the one caches in the keydb handle 645 * 646 * A key attached to the handle tells us the the token is logged in. 647 * We can used the key attached to the handle in sftkdb_EncryptAttribute 648 * and sftkdb_DecryptAttribute calls. 649 */ 650 static void 651 sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey, int iterationCount) 652 { 653 unsigned char *data; 654 int len; 655 656 if (keydb->passwordLock == NULL) { 657 PORT_Assert(keydb->type != SFTK_KEYDB_TYPE); 658 return; 659 } 660 661 /* an atomic pointer set would be nice */ 662 SKIP_AFTER_FORK(PZ_Lock(keydb->passwordLock)); 663 data = keydb->passwordKey.data; 664 len = keydb->passwordKey.len; 665 keydb->passwordKey.data = passKey->data; 666 keydb->passwordKey.len = passKey->len; 667 keydb->defaultIterationCount = iterationCount; 668 passKey->data = data; 669 passKey->len = len; 670 SKIP_AFTER_FORK(PZ_Unlock(keydb->passwordLock)); 671 } 672 673 /* 674 * returns true if we are in a middle of a merge style update. 675 */ 676 PRBool 677 sftkdb_InUpdateMerge(SFTKDBHandle *keydb) 678 { 679 return keydb->updateID ? PR_TRUE : PR_FALSE; 680 } 681 682 /* 683 * returns true if we are looking for the password for the user's old source 684 * database as part of a merge style update. 685 */ 686 PRBool 687 sftkdb_NeedUpdateDBPassword(SFTKDBHandle *keydb) 688 { 689 if (!sftkdb_InUpdateMerge(keydb)) { 690 return PR_FALSE; 691 } 692 if (keydb->updateDBIsInit && !keydb->updatePasswordKey) { 693 return PR_TRUE; 694 } 695 return PR_FALSE; 696 } 697 698 /* 699 * fetch an update password key from a handle. 700 */ 701 SECItem * 702 sftkdb_GetUpdatePasswordKey(SFTKDBHandle *handle) 703 { 704 SECItem *key = NULL; 705 706 /* if we're a cert db, fetch it from our peer key db */ 707 if (handle->type == SFTK_CERTDB_TYPE) { 708 handle = handle->peerDB; 709 } 710 711 /* don't have one */ 712 if (!handle) { 713 return NULL; 714 } 715 716 PZ_Lock(handle->passwordLock); 717 if (handle->updatePasswordKey) { 718 key = SECITEM_DupItem(handle->updatePasswordKey); 719 } 720 PZ_Unlock(handle->passwordLock); 721 722 return key; 723 } 724 725 /* 726 * free the update password key from a handle. 727 */ 728 void 729 sftkdb_FreeUpdatePasswordKey(SFTKDBHandle *handle) 730 { 731 SECItem *key = NULL; 732 733 /* don't have one */ 734 if (!handle) { 735 return; 736 } 737 738 /* if we're a cert db, we don't have one */ 739 if (handle->type == SFTK_CERTDB_TYPE) { 740 return; 741 } 742 743 PZ_Lock(handle->passwordLock); 744 if (handle->updatePasswordKey) { 745 key = handle->updatePasswordKey; 746 handle->updatePasswordKey = NULL; 747 } 748 PZ_Unlock(handle->passwordLock); 749 750 if (key) { 751 SECITEM_ZfreeItem(key, PR_TRUE); 752 } 753 754 return; 755 } 756 757 /* 758 * what password db we use depends heavily on the update state machine 759 * 760 * 1) no update db, return the normal database. 761 * 2) update db and no merge return the update db. 762 * 3) update db and in merge: 763 * return the update db if we need the update db's password, 764 * otherwise return our normal datbase. 765 */ 766 static SDB * 767 sftk_getPWSDB(SFTKDBHandle *keydb) 768 { 769 if (!keydb->update) { 770 return keydb->db; 771 } 772 if (!sftkdb_InUpdateMerge(keydb)) { 773 return keydb->update; 774 } 775 if (sftkdb_NeedUpdateDBPassword(keydb)) { 776 return keydb->update; 777 } 778 return keydb->db; 779 } 780 781 /* 782 * return success if we have a valid password entry. 783 * This is will show up outside of PKCS #11 as CKF_USER_PIN_INIT 784 * in the token flags. 785 */ 786 SECStatus 787 sftkdb_HasPasswordSet(SFTKDBHandle *keydb) 788 { 789 SECItem salt, value; 790 unsigned char saltData[SDB_MAX_META_DATA_LEN]; 791 unsigned char valueData[SDB_MAX_META_DATA_LEN]; 792 CK_RV crv; 793 SDB *db; 794 795 if (keydb == NULL) { 796 return SECFailure; 797 } 798 799 db = sftk_getPWSDB(keydb); 800 if (db == NULL) { 801 return SECFailure; 802 } 803 804 salt.data = saltData; 805 salt.len = sizeof(saltData); 806 value.data = valueData; 807 value.len = sizeof(valueData); 808 crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value); 809 810 /* If no password is set, we can update right away */ 811 if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update && crv != CKR_OK) { 812 /* update the peer certdb if it exists */ 813 if (keydb->peerDB) { 814 sftkdb_Update(keydb->peerDB, NULL); 815 } 816 sftkdb_Update(keydb, NULL); 817 } 818 return (crv == CKR_OK) ? SECSuccess : SECFailure; 819 } 820 821 /* pull out the common final part of checking a password */ 822 SECStatus 823 sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, 824 const char *pw, SECItem *value, 825 PRBool *tokenRemoved); 826 827 /* 828 * check to see if we have the NULL password set. 829 * We special case the NULL password so that if you have no password set, you 830 * don't do thousands of hash rounds. This allows us to startup and get 831 * webpages without slowdown in normal mode. 832 */ 833 SECStatus 834 sftkdb_CheckPasswordNull(SFTKDBHandle *keydb, PRBool *tokenRemoved) 835 { 836 /* just like sftkdb_CheckPassowd, we get the salt and value, and 837 * create a dbkey */ 838 SECStatus rv; 839 SECItem salt, value; 840 unsigned char saltData[SDB_MAX_META_DATA_LEN]; 841 unsigned char valueData[SDB_MAX_META_DATA_LEN]; 842 SECItem key; 843 SDB *db; 844 CK_RV crv; 845 sftkCipherValue cipherValue; 846 847 cipherValue.param = NULL; 848 cipherValue.arena = NULL; 849 850 if (keydb == NULL) { 851 return SECFailure; 852 } 853 854 db = sftk_getPWSDB(keydb); 855 if (db == NULL) { 856 return SECFailure; 857 } 858 859 key.data = NULL; 860 key.len = 0; 861 862 /* get the entry from the database */ 863 salt.data = saltData; 864 salt.len = sizeof(saltData); 865 value.data = valueData; 866 value.len = sizeof(valueData); 867 crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value); 868 if (crv != CKR_OK) { 869 rv = SECFailure; 870 goto done; 871 } 872 873 /* get our intermediate key based on the entry salt value */ 874 rv = sftkdb_passwordToKey(keydb, &salt, "", &key); 875 if (rv != SECSuccess) { 876 goto done; 877 } 878 879 /* First get the cipher type */ 880 rv = sftkdb_decodeCipherText(&value, &cipherValue); 881 if (rv != SECSuccess) { 882 goto done; 883 } 884 885 if (cipherValue.param->iter != 1) { 886 rv = SECFailure; 887 goto done; 888 } 889 890 rv = sftkdb_finishPasswordCheck(keydb, &key, "", &value, tokenRemoved); 891 892 done: 893 if (key.data) { 894 PORT_ZFree(key.data, key.len); 895 } 896 if (cipherValue.param) { 897 nsspkcs5_DestroyPBEParameter(cipherValue.param); 898 } 899 if (cipherValue.arena) { 900 PORT_FreeArena(cipherValue.arena, PR_FALSE); 901 } 902 return rv; 903 } 904 905 #define SFTK_PW_CHECK_STRING "password-check" 906 #define SFTK_PW_CHECK_LEN 14 907 908 /* 909 * check if the supplied password is valid 910 */ 911 SECStatus 912 sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved) 913 { 914 SECStatus rv; 915 SECItem salt, value; 916 unsigned char saltData[SDB_MAX_META_DATA_LEN]; 917 unsigned char valueData[SDB_MAX_META_DATA_LEN]; 918 SECItem key; 919 SDB *db; 920 CK_RV crv; 921 922 if (keydb == NULL) { 923 return SECFailure; 924 } 925 926 db = sftk_getPWSDB(keydb); 927 if (db == NULL) { 928 return SECFailure; 929 } 930 931 key.data = NULL; 932 key.len = 0; 933 934 if (pw == NULL) 935 pw = ""; 936 937 /* get the entry from the database */ 938 salt.data = saltData; 939 salt.len = sizeof(saltData); 940 value.data = valueData; 941 value.len = sizeof(valueData); 942 crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value); 943 if (crv != CKR_OK) { 944 rv = SECFailure; 945 goto done; 946 } 947 948 /* get our intermediate key based on the entry salt value */ 949 rv = sftkdb_passwordToKey(keydb, &salt, pw, &key); 950 if (rv != SECSuccess) { 951 goto done; 952 } 953 954 rv = sftkdb_finishPasswordCheck(keydb, &key, pw, &value, tokenRemoved); 955 956 done: 957 if (key.data) { 958 PORT_ZFree(key.data, key.len); 959 } 960 return rv; 961 } 962 963 /* we need to pass iterationCount in case we are updating a new database 964 * and from an old one. */ 965 SECStatus 966 sftkdb_finishPasswordCheck(SFTKDBHandle *keydb, SECItem *key, const char *pw, 967 SECItem *value, PRBool *tokenRemoved) 968 { 969 SECItem *result = NULL; 970 SECStatus rv; 971 int iterationCount = getPBEIterationCount(); 972 973 if (*pw == 0) { 974 iterationCount = 1; 975 } else if (keydb->usesLegacyStorage && !sftk_isLegacyIterationCountAllowed()) { 976 iterationCount = 1; 977 } 978 979 /* decrypt the entry value */ 980 rv = sftkdb_DecryptAttribute(keydb, key, CK_INVALID_HANDLE, 981 CKT_INVALID_TYPE, value, &result); 982 if (rv != SECSuccess) { 983 goto done; 984 } 985 986 /* if it's what we expect, update our key in the database handle and 987 * return Success */ 988 if ((result->len == SFTK_PW_CHECK_LEN) && 989 PORT_Memcmp(result->data, SFTK_PW_CHECK_STRING, SFTK_PW_CHECK_LEN) == 0) { 990 /* 991 * We have a password, now lets handle any potential update cases.. 992 * 993 * First, the normal case: no update. In this case we only need the 994 * the password for our only DB, which we now have, we switch 995 * the keys and fall through. 996 * Second regular (non-merge) update: The target DB does not yet have 997 * a password initialized, we now have the password for the source DB, 998 * so we can switch the keys and simply update the target database. 999 * Merge update case: This one is trickier. 1000 * 1) If we need the source DB password, then we just got it here. 1001 * We need to save that password, 1002 * then we need to check to see if we need or have the target 1003 * database password. 1004 * If we have it (it's the same as the source), or don't need 1005 * it (it's not set or is ""), we can start the update now. 1006 * If we don't have it, we need the application to get it from 1007 * the user. Clear our sessions out to simulate a token 1008 * removal. C_GetTokenInfo will change the token description 1009 * and the token will still appear to be logged out. 1010 * 2) If we already have the source DB password, this password is 1011 * for the target database. We can now move forward with the 1012 * update, as we now have both required passwords. 1013 * 1014 */ 1015 PZ_Lock(keydb->passwordLock); 1016 if (sftkdb_NeedUpdateDBPassword(keydb)) { 1017 /* Squirrel this special key away. 1018 * This has the side effect of turning sftkdb_NeedLegacyPW off, 1019 * as well as changing which database is returned from 1020 * SFTK_GET_PW_DB (thus effecting both sftkdb_CheckPassword() 1021 * and sftkdb_HasPasswordSet()) */ 1022 keydb->updatePasswordKey = SECITEM_DupItem(key); 1023 PZ_Unlock(keydb->passwordLock); 1024 if (keydb->updatePasswordKey == NULL) { 1025 /* PORT_Error set by SECITEM_DupItem */ 1026 rv = SECFailure; 1027 goto done; 1028 } 1029 1030 /* Simulate a token removal -- we need to do this any 1031 * any case at this point so the token name is correct. */ 1032 *tokenRemoved = PR_TRUE; 1033 1034 /* 1035 * OK, we got the update DB password, see if we need a password 1036 * for the target... 1037 */ 1038 if (sftkdb_HasPasswordSet(keydb) == SECSuccess) { 1039 /* We have a password, do we know what the password is? 1040 * check 1) for the password the user supplied for the 1041 * update DB, 1042 * and 2) for the null password. 1043 * 1044 * RECURSION NOTE: we are calling ourselves here. This means 1045 * any updates, switchKeys, etc will have been completed 1046 * if these functions return successfully, in those cases 1047 * just exit returning Success. We don't recurse infinitely 1048 * because we are making this call from a NeedUpdateDBPassword 1049 * block and we've already set that update password at this 1050 * point. */ 1051 rv = sftkdb_CheckPassword(keydb, pw, tokenRemoved); 1052 if (rv == SECSuccess) { 1053 /* source and target databases have the same password, we 1054 * are good to go */ 1055 goto done; 1056 } 1057 sftkdb_CheckPasswordNull(keydb, tokenRemoved); 1058 1059 /* 1060 * Important 'NULL' code here. At this point either we 1061 * succeeded in logging in with "" or we didn't. 1062 * 1063 * If we did succeed at login, our machine state will be set 1064 * to logged in appropriately. The application will find that 1065 * it's logged in as soon as it opens a new session. We have 1066 * also completed the update. Life is good. 1067 * 1068 * If we did not succeed, well the user still successfully 1069 * logged into the update database, since we faked the token 1070 * removal it's just like the user logged into his smart card 1071 * then removed it. the actual login work, so we report that 1072 * success back to the user, but we won't actually be 1073 * logged in. The application will find this out when it 1074 * checks it's login state, thus triggering another password 1075 * prompt so we can get the real target DB password. 1076 * 1077 * summary, we exit from here with SECSuccess no matter what. 1078 */ 1079 rv = SECSuccess; 1080 goto done; 1081 } else { 1082 /* there is no password, just fall through to update. 1083 * update will write the source DB's password record 1084 * into the target DB just like it would in a non-merge 1085 * update case. */ 1086 } 1087 } else { 1088 PZ_Unlock(keydb->passwordLock); 1089 } 1090 /* load the keys, so the keydb can parse it's key set */ 1091 sftkdb_switchKeys(keydb, key, iterationCount); 1092 1093 /* we need to update, do it now */ 1094 if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update) { 1095 /* update the peer certdb if it exists */ 1096 if (keydb->peerDB) { 1097 sftkdb_Update(keydb->peerDB, key); 1098 } 1099 sftkdb_Update(keydb, key); 1100 } 1101 } else { 1102 rv = SECFailure; 1103 /*PORT_SetError( bad password); */ 1104 } 1105 1106 done: 1107 if (result) { 1108 SECITEM_ZfreeItem(result, PR_TRUE); 1109 } 1110 return rv; 1111 } 1112 1113 /* 1114 * return Success if the there is a cached password key. 1115 */ 1116 SECStatus 1117 sftkdb_PWCached(SFTKDBHandle *keydb) 1118 { 1119 SECStatus rv; 1120 PZ_Lock(keydb->passwordLock); 1121 rv = keydb->passwordKey.data ? SECSuccess : SECFailure; 1122 PZ_Unlock(keydb->passwordLock); 1123 return rv; 1124 } 1125 1126 static CK_RV 1127 sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle, 1128 CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount) 1129 { 1130 SFTKDBHandle *keyHandle = handle; 1131 SDB *keyTarget = NULL; 1132 if (handle->type != SFTK_KEYDB_TYPE) { 1133 keyHandle = handle->peerDB; 1134 } 1135 if (keyHandle == NULL) { 1136 return CKR_OK; 1137 } 1138 // Old DBs don't have metadata, so we can return early here. 1139 keyTarget = SFTK_GET_SDB(keyHandle); 1140 if ((keyTarget->sdb_flags & SDB_HAS_META) == 0) { 1141 return CKR_OK; 1142 } 1143 1144 id &= SFTK_OBJ_ID_MASK; 1145 1146 CK_ATTRIBUTE_TYPE authAttrTypes[] = { 1147 CKA_MODULUS, 1148 CKA_PUBLIC_EXPONENT, 1149 CKA_NSS_CERT_SHA1_HASH, 1150 CKA_NSS_CERT_MD5_HASH, 1151 CKA_NAME_HASH_ALGORITHM, 1152 CKA_HASH_OF_CERTIFICATE, 1153 CKA_PKCS_TRUST_SERVER_AUTH, 1154 CKA_PKCS_TRUST_CLIENT_AUTH, 1155 CKA_PKCS_TRUST_EMAIL_PROTECTION, 1156 CKA_PKCS_TRUST_CODE_SIGNING, 1157 CKA_NSS_TRUST_SERVER_AUTH, 1158 CKA_NSS_TRUST_CLIENT_AUTH, 1159 CKA_NSS_TRUST_EMAIL_PROTECTION, 1160 CKA_NSS_TRUST_CODE_SIGNING, 1161 CKA_NSS_TRUST_STEP_UP_APPROVED, 1162 CKA_NSS_OVERRIDE_EXTENSIONS, 1163 }; 1164 const CK_ULONG authAttrTypeCount = sizeof(authAttrTypes) / sizeof(authAttrTypes[0]); 1165 1166 // We don't know what attributes this object has, so we update them one at a 1167 // time. 1168 unsigned int i; 1169 for (i = 0; i < authAttrTypeCount; i++) { 1170 CK_ATTRIBUTE authAttr = { authAttrTypes[i], NULL, 0 }; 1171 CK_RV rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1); 1172 if (rv != CKR_OK) { 1173 continue; 1174 } 1175 if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) { 1176 continue; 1177 } 1178 authAttr.pValue = PORT_ArenaAlloc(arena, authAttr.ulValueLen); 1179 if (authAttr.pValue == NULL) { 1180 return CKR_HOST_MEMORY; 1181 } 1182 rv = sftkdb_GetAttributeValue(handle, id, &authAttr, 1); 1183 if (rv != CKR_OK) { 1184 return rv; 1185 } 1186 if ((authAttr.ulValueLen == -1) || (authAttr.ulValueLen == 0)) { 1187 return CKR_GENERAL_ERROR; 1188 } 1189 // GetAttributeValue just verified the old macs, so it is safe to write 1190 // them out now. 1191 if (authAttr.ulValueLen == sizeof(CK_ULONG) && 1192 sftkdb_isULONGAttribute(authAttr.type)) { 1193 CK_ULONG value = *(CK_ULONG *)authAttr.pValue; 1194 sftk_ULong2SDBULong(authAttr.pValue, value); 1195 authAttr.ulValueLen = SDB_ULONG_SIZE; 1196 } 1197 SECItem *signText; 1198 SECItem plainText; 1199 plainText.data = authAttr.pValue; 1200 plainText.len = authAttr.ulValueLen; 1201 if (sftkdb_SignAttribute(arena, handle, keyTarget, newKey, 1202 iterationCount, id, authAttr.type, 1203 &plainText, &signText) != SECSuccess) { 1204 return CKR_GENERAL_ERROR; 1205 } 1206 if (sftkdb_PutAttributeSignature(handle, keyTarget, id, authAttr.type, 1207 signText) != SECSuccess) { 1208 return CKR_GENERAL_ERROR; 1209 } 1210 } 1211 1212 return CKR_OK; 1213 } 1214 1215 static CK_RV 1216 sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb, 1217 CK_OBJECT_HANDLE id, SECItem *newKey, int iterationCount) 1218 { 1219 CK_ATTRIBUTE_TYPE privAttrTypes[] = { 1220 CKA_VALUE, 1221 CKA_SEED, 1222 CKA_PRIVATE_EXPONENT, 1223 CKA_PRIME_1, 1224 CKA_PRIME_2, 1225 CKA_EXPONENT_1, 1226 CKA_EXPONENT_2, 1227 CKA_COEFFICIENT, 1228 }; 1229 const CK_ULONG privAttrCount = sizeof(privAttrTypes) / sizeof(privAttrTypes[0]); 1230 1231 // We don't know what attributes this object has, so we update them one at a 1232 // time. 1233 unsigned int i; 1234 for (i = 0; i < privAttrCount; i++) { 1235 // Read the old attribute in the clear. 1236 CK_OBJECT_HANDLE sdbId = id & SFTK_OBJ_ID_MASK; 1237 CK_ATTRIBUTE privAttr = { privAttrTypes[i], NULL, 0 }; 1238 CK_RV crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1); 1239 if (crv != CKR_OK) { 1240 continue; 1241 } 1242 if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) { 1243 continue; 1244 } 1245 privAttr.pValue = PORT_ArenaAlloc(arena, privAttr.ulValueLen); 1246 if (privAttr.pValue == NULL) { 1247 return CKR_HOST_MEMORY; 1248 } 1249 crv = sftkdb_GetAttributeValue(keydb, id, &privAttr, 1); 1250 if (crv != CKR_OK) { 1251 return crv; 1252 } 1253 if ((privAttr.ulValueLen == -1) || (privAttr.ulValueLen == 0)) { 1254 return CKR_GENERAL_ERROR; 1255 } 1256 SECItem plainText; 1257 SECItem *result; 1258 plainText.data = privAttr.pValue; 1259 plainText.len = privAttr.ulValueLen; 1260 if (sftkdb_EncryptAttribute(arena, keydb, keydb->db, newKey, 1261 iterationCount, sdbId, privAttr.type, 1262 &plainText, &result) != SECSuccess) { 1263 return CKR_GENERAL_ERROR; 1264 } 1265 privAttr.pValue = result->data; 1266 privAttr.ulValueLen = result->len; 1267 // Clear sensitive data. 1268 PORT_Memset(plainText.data, 0, plainText.len); 1269 1270 // Write the newly encrypted attributes out directly. 1271 keydb->newKey = newKey; 1272 keydb->newDefaultIterationCount = iterationCount; 1273 crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, sdbId, &privAttr, 1); 1274 keydb->newKey = NULL; 1275 if (crv != CKR_OK) { 1276 return crv; 1277 } 1278 } 1279 1280 return CKR_OK; 1281 } 1282 1283 static CK_RV 1284 sftk_convertAttributes(SFTKDBHandle *handle, CK_OBJECT_HANDLE id, 1285 SECItem *newKey, int iterationCount) 1286 { 1287 CK_RV crv = CKR_OK; 1288 PLArenaPool *arena = NULL; 1289 1290 /* get a new arena to simplify cleanup */ 1291 arena = PORT_NewArena(1024); 1292 if (!arena) { 1293 return CKR_HOST_MEMORY; 1294 } 1295 1296 /* 1297 * first handle the MACS 1298 */ 1299 crv = sftk_updateMacs(arena, handle, id, newKey, iterationCount); 1300 if (crv != CKR_OK) { 1301 goto loser; 1302 } 1303 1304 if (handle->type == SFTK_KEYDB_TYPE) { 1305 crv = sftk_updateEncrypted(arena, handle, id, newKey, 1306 iterationCount); 1307 if (crv != CKR_OK) { 1308 goto loser; 1309 } 1310 } 1311 1312 /* free up our mess */ 1313 PORT_FreeArena(arena, PR_TRUE); 1314 return CKR_OK; 1315 1316 loser: 1317 /* there may be unencrypted data, clear it out down */ 1318 PORT_FreeArena(arena, PR_TRUE); 1319 return crv; 1320 } 1321 1322 /* 1323 * must be called with the old key active. 1324 */ 1325 CK_RV 1326 sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template, 1327 CK_ULONG count, SECItem *newKey, int iterationCount) 1328 { 1329 SDBFind *find = NULL; 1330 CK_ULONG idCount = SFTK_MAX_IDS; 1331 CK_OBJECT_HANDLE ids[SFTK_MAX_IDS]; 1332 CK_RV crv, crv2; 1333 unsigned int i; 1334 1335 crv = sftkdb_FindObjectsInit(handle, template, count, &find); 1336 1337 if (crv != CKR_OK) { 1338 return crv; 1339 } 1340 while ((crv == CKR_OK) && (idCount == SFTK_MAX_IDS)) { 1341 crv = sftkdb_FindObjects(handle, find, ids, SFTK_MAX_IDS, &idCount); 1342 for (i = 0; (crv == CKR_OK) && (i < idCount); i++) { 1343 crv = sftk_convertAttributes(handle, ids[i], newKey, 1344 iterationCount); 1345 } 1346 } 1347 crv2 = sftkdb_FindObjectsFinal(handle, find); 1348 if (crv == CKR_OK) 1349 crv = crv2; 1350 1351 return crv; 1352 } 1353 1354 /* 1355 * change the database password. 1356 */ 1357 SECStatus 1358 sftkdb_ChangePassword(SFTKDBHandle *keydb, 1359 char *oldPin, char *newPin, PRBool *tokenRemoved) 1360 { 1361 SECStatus rv = SECSuccess; 1362 SECItem plainText; 1363 SECItem newKey; 1364 SECItem *result = NULL; 1365 SECItem salt, value; 1366 SFTKDBHandle *certdb; 1367 unsigned char saltData[SDB_MAX_META_DATA_LEN]; 1368 unsigned char valueData[SDB_MAX_META_DATA_LEN]; 1369 int iterationCount = getPBEIterationCount(); 1370 int preferred_salt_length; 1371 CK_RV crv; 1372 SDB *db; 1373 1374 if (keydb == NULL) { 1375 return SECFailure; 1376 } 1377 1378 db = SFTK_GET_SDB(keydb); 1379 if (db == NULL) { 1380 return SECFailure; 1381 } 1382 1383 newKey.data = NULL; 1384 1385 /* make sure we have a valid old pin */ 1386 crv = (*keydb->db->sdb_Begin)(keydb->db); 1387 if (crv != CKR_OK) { 1388 rv = SECFailure; 1389 goto loser; 1390 } 1391 salt.data = saltData; 1392 salt.len = sizeof(saltData); 1393 value.data = valueData; 1394 value.len = sizeof(valueData); 1395 crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value); 1396 if (crv == CKR_OK) { 1397 rv = sftkdb_CheckPassword(keydb, oldPin, tokenRemoved); 1398 if (rv == SECFailure) { 1399 goto loser; 1400 } 1401 } else { 1402 salt.len = 0; 1403 } 1404 1405 preferred_salt_length = SHA384_LENGTH; 1406 1407 /* Prefer SHA-1 if the password is NULL */ 1408 if (!newPin || *newPin == 0) { 1409 preferred_salt_length = SHA1_LENGTH; 1410 } 1411 1412 if (salt.len != preferred_salt_length) { 1413 salt.len = preferred_salt_length; 1414 RNG_GenerateGlobalRandomBytes(salt.data, salt.len); 1415 } 1416 1417 if (newPin && *newPin == 0) { 1418 iterationCount = 1; 1419 } else if (keydb->usesLegacyStorage && !sftk_isLegacyIterationCountAllowed()) { 1420 iterationCount = 1; 1421 } 1422 1423 rv = sftkdb_passwordToKey(keydb, &salt, newPin, &newKey); 1424 if (rv != SECSuccess) { 1425 goto loser; 1426 } 1427 1428 /* 1429 * convert encrypted entries here. 1430 */ 1431 crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey, iterationCount); 1432 if (crv != CKR_OK) { 1433 rv = SECFailure; 1434 goto loser; 1435 } 1436 /* fix up certdb macs */ 1437 certdb = keydb->peerDB; 1438 if (certdb) { 1439 CK_ATTRIBUTE objectType = { CKA_CLASS, 0, sizeof(CK_OBJECT_CLASS) }; 1440 CK_OBJECT_CLASS myClass = CKO_NSS_TRUST; 1441 1442 objectType.pValue = &myClass; 1443 crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey, 1444 iterationCount); 1445 if (crv != CKR_OK) { 1446 rv = SECFailure; 1447 goto loser; 1448 } 1449 myClass = CKO_PUBLIC_KEY; 1450 crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey, 1451 iterationCount); 1452 if (crv != CKR_OK) { 1453 rv = SECFailure; 1454 goto loser; 1455 } 1456 1457 myClass = CKO_TRUST; 1458 crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey, 1459 iterationCount); 1460 if (crv != CKR_OK) { 1461 rv = SECFailure; 1462 goto loser; 1463 } 1464 } 1465 1466 plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING; 1467 plainText.len = SFTK_PW_CHECK_LEN; 1468 1469 rv = sftkdb_EncryptAttribute(NULL, keydb, keydb->db, &newKey, 1470 iterationCount, CK_INVALID_HANDLE, 1471 CKT_INVALID_TYPE, &plainText, &result); 1472 if (rv != SECSuccess) { 1473 goto loser; 1474 } 1475 value.data = result->data; 1476 value.len = result->len; 1477 crv = (*keydb->db->sdb_PutMetaData)(keydb->db, "password", &salt, &value); 1478 if (crv != CKR_OK) { 1479 rv = SECFailure; 1480 goto loser; 1481 } 1482 crv = (*keydb->db->sdb_Commit)(keydb->db); 1483 if (crv != CKR_OK) { 1484 rv = SECFailure; 1485 goto loser; 1486 } 1487 1488 keydb->newKey = NULL; 1489 1490 sftkdb_switchKeys(keydb, &newKey, iterationCount); 1491 1492 loser: 1493 if (newKey.data) { 1494 PORT_ZFree(newKey.data, newKey.len); 1495 } 1496 if (result) { 1497 SECITEM_FreeItem(result, PR_TRUE); 1498 } 1499 if (rv != SECSuccess) { 1500 (*keydb->db->sdb_Abort)(keydb->db); 1501 } 1502 1503 return rv; 1504 } 1505 1506 /* 1507 * lose our cached password 1508 */ 1509 SECStatus 1510 sftkdb_ClearPassword(SFTKDBHandle *keydb) 1511 { 1512 SECItem oldKey; 1513 oldKey.data = NULL; 1514 oldKey.len = 0; 1515 sftkdb_switchKeys(keydb, &oldKey, 1); 1516 if (oldKey.data) { 1517 PORT_ZFree(oldKey.data, oldKey.len); 1518 } 1519 return SECSuccess; 1520 }