/security/nss/lib/softoken/sftkpwd.c

http://github.com/zpao/v8monkey · C · 1309 lines · 852 code · 146 blank · 311 comment · 223 complexity · 15f61d591c97af3a2408162757da1b0f MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2007
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. *
  23. * Alternatively, the contents of this file may be used under the terms of
  24. * either the GNU General Public License Version 2 or later (the "GPL"), or
  25. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  26. * in which case the provisions of the GPL or the LGPL are applicable instead
  27. * of those above. If you wish to allow use of your version of this file only
  28. * under the terms of either the GPL or the LGPL, and not to allow others to
  29. * use your version of this file under the terms of the MPL, indicate your
  30. * decision by deleting the provisions above and replace them with the notice
  31. * and other provisions required by the GPL or the LGPL. If you do not delete
  32. * the provisions above, a recipient may use your version of this file under
  33. * the terms of any one of the MPL, the GPL or the LGPL.
  34. *
  35. * ***** END LICENSE BLOCK ***** */
  36. /*
  37. * The following code handles the storage of PKCS 11 modules used by the
  38. * NSS. For the rest of NSS, only one kind of database handle exists:
  39. *
  40. * SFTKDBHandle
  41. *
  42. * There is one SFTKDBHandle for the each key database and one for each cert
  43. * database. These databases are opened as associated pairs, one pair per
  44. * slot. SFTKDBHandles are reference counted objects.
  45. *
  46. * Each SFTKDBHandle points to a low level database handle (SDB). This handle
  47. * represents the underlying physical database. These objects are not
  48. * reference counted, an are 'owned' by their respective SFTKDBHandles.
  49. *
  50. *
  51. */
  52. #include "sftkdb.h"
  53. #include "sftkdbti.h"
  54. #include "pkcs11t.h"
  55. #include "pkcs11i.h"
  56. #include "sdb.h"
  57. #include "prprf.h"
  58. #include "secmodt.h"
  59. #include "sftkpars.h"
  60. #include "pratom.h"
  61. #include "blapi.h"
  62. #include "secoid.h"
  63. #include "sechash.h"
  64. #include "lowpbe.h"
  65. #include "secdert.h"
  66. #include "prsystem.h"
  67. #include "lgglue.h"
  68. #include "secerr.h"
  69. #include "softoken.h"
  70. /******************************************************************
  71. *
  72. * Key DB password handling functions
  73. *
  74. * These functions manage the key db password (set, reset, initialize, use).
  75. *
  76. * The key is managed on 'this side' of the database. All private data is
  77. * encrypted before it is sent to the database itself. Besides PBE's, the
  78. * database management code can also mix in various fixed keys so the data
  79. * in the database is no longer considered 'plain text'.
  80. */
  81. /* take string password and turn it into a key. The key is dependent
  82. * on a global salt entry acquired from the database. This salted
  83. * value will be based to a pkcs5 pbe function before it is used
  84. * in an actual encryption */
  85. static SECStatus
  86. sftkdb_passwordToKey(SFTKDBHandle *keydb, SECItem *salt,
  87. const char *pw, SECItem *key)
  88. {
  89. SHA1Context *cx = NULL;
  90. SECStatus rv = SECFailure;
  91. key->data = PORT_Alloc(SHA1_LENGTH);
  92. if (key->data == NULL) {
  93. goto loser;
  94. }
  95. key->len = SHA1_LENGTH;
  96. cx = SHA1_NewContext();
  97. if ( cx == NULL) {
  98. goto loser;
  99. }
  100. SHA1_Begin(cx);
  101. if (salt && salt->data ) {
  102. SHA1_Update(cx, salt->data, salt->len);
  103. }
  104. SHA1_Update(cx, (unsigned char *)pw, PORT_Strlen(pw));
  105. SHA1_End(cx, key->data, &key->len, key->len);
  106. rv = SECSuccess;
  107. loser:
  108. if (cx) {
  109. SHA1_DestroyContext(cx, PR_TRUE);
  110. }
  111. if (rv != SECSuccess) {
  112. if (key->data != NULL) {
  113. PORT_ZFree(key->data,key->len);
  114. }
  115. key->data = NULL;
  116. }
  117. return rv;
  118. }
  119. /*
  120. * Cipher text stored in the database contains 3 elements:
  121. * 1) an identifier describing the encryption algorithm.
  122. * 2) an entry specific salt value.
  123. * 3) the encrypted value.
  124. *
  125. * The following data structure represents the encrypted data in a decoded
  126. * (but still encrypted) form.
  127. */
  128. typedef struct sftkCipherValueStr sftkCipherValue;
  129. struct sftkCipherValueStr {
  130. PLArenaPool *arena;
  131. SECOidTag alg;
  132. NSSPKCS5PBEParameter *param;
  133. SECItem salt;
  134. SECItem value;
  135. };
  136. #define SFTK_CIPHERTEXT_VERSION 3
  137. struct SFTKDBEncryptedDataInfoStr {
  138. SECAlgorithmID algorithm;
  139. SECItem encryptedData;
  140. };
  141. typedef struct SFTKDBEncryptedDataInfoStr SFTKDBEncryptedDataInfo;
  142. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  143. const SEC_ASN1Template sftkdb_EncryptedDataInfoTemplate[] = {
  144. { SEC_ASN1_SEQUENCE,
  145. 0, NULL, sizeof(SFTKDBEncryptedDataInfo) },
  146. { SEC_ASN1_INLINE | SEC_ASN1_XTRN ,
  147. offsetof(SFTKDBEncryptedDataInfo,algorithm),
  148. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  149. { SEC_ASN1_OCTET_STRING,
  150. offsetof(SFTKDBEncryptedDataInfo,encryptedData) },
  151. { 0 }
  152. };
  153. /*
  154. * This parses the cipherText into cipher value. NOTE: cipherValue will point
  155. * to data in cipherText, if cipherText is freed, cipherValue will be invalid.
  156. */
  157. static SECStatus
  158. sftkdb_decodeCipherText(SECItem *cipherText, sftkCipherValue *cipherValue)
  159. {
  160. PLArenaPool *arena = NULL;
  161. SFTKDBEncryptedDataInfo edi;
  162. SECStatus rv;
  163. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  164. if (arena == NULL) {
  165. return SECFailure;
  166. }
  167. cipherValue->arena = NULL;
  168. cipherValue->param = NULL;
  169. rv = SEC_QuickDERDecodeItem(arena, &edi, sftkdb_EncryptedDataInfoTemplate,
  170. cipherText);
  171. if (rv != SECSuccess) {
  172. goto loser;
  173. }
  174. cipherValue->alg = SECOID_GetAlgorithmTag(&edi.algorithm);
  175. cipherValue->param = nsspkcs5_AlgidToParam(&edi.algorithm);
  176. if (cipherValue->param == NULL) {
  177. goto loser;
  178. }
  179. cipherValue->value = edi.encryptedData;
  180. cipherValue->arena = arena;
  181. return SECSuccess;
  182. loser:
  183. if (cipherValue->param) {
  184. nsspkcs5_DestroyPBEParameter(cipherValue->param);
  185. cipherValue->param = NULL;
  186. }
  187. if (arena) {
  188. PORT_FreeArena(arena,PR_FALSE);
  189. }
  190. return SECFailure;
  191. }
  192. /*
  193. * unlike decode, Encode actually allocates a SECItem the caller must free
  194. * The caller can pass an optional arena to to indicate where to place
  195. * the resultant cipherText.
  196. */
  197. static SECStatus
  198. sftkdb_encodeCipherText(PLArenaPool *arena, sftkCipherValue *cipherValue,
  199. SECItem **cipherText)
  200. {
  201. SFTKDBEncryptedDataInfo edi;
  202. SECAlgorithmID *algid;
  203. SECStatus rv;
  204. PLArenaPool *localArena = NULL;
  205. localArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  206. if (localArena == NULL) {
  207. return SECFailure;
  208. }
  209. algid = nsspkcs5_CreateAlgorithmID(localArena, cipherValue->alg,
  210. cipherValue->param);
  211. if (algid == NULL) {
  212. rv = SECFailure;
  213. goto loser;
  214. }
  215. rv = SECOID_CopyAlgorithmID(localArena, &edi.algorithm, algid);
  216. SECOID_DestroyAlgorithmID(algid, PR_TRUE);
  217. if (rv != SECSuccess) {
  218. goto loser;
  219. }
  220. edi.encryptedData = cipherValue->value;
  221. *cipherText = SEC_ASN1EncodeItem(arena, NULL, &edi,
  222. sftkdb_EncryptedDataInfoTemplate);
  223. if (*cipherText == NULL) {
  224. rv = SECFailure;
  225. }
  226. loser:
  227. if (localArena) {
  228. PORT_FreeArena(localArena,PR_FALSE);
  229. }
  230. return rv;
  231. }
  232. /*
  233. * Use our key to decode a cipherText block from the database.
  234. *
  235. * plain text is allocated by nsspkcs5_CipherData and must be freed
  236. * with SECITEM_FreeItem by the caller.
  237. */
  238. SECStatus
  239. sftkdb_DecryptAttribute(SECItem *passKey, SECItem *cipherText, SECItem **plain)
  240. {
  241. SECStatus rv;
  242. sftkCipherValue cipherValue;
  243. /* First get the cipher type */
  244. rv = sftkdb_decodeCipherText(cipherText, &cipherValue);
  245. if (rv != SECSuccess) {
  246. goto loser;
  247. }
  248. *plain = nsspkcs5_CipherData(cipherValue.param, passKey, &cipherValue.value,
  249. PR_FALSE, NULL);
  250. if (*plain == NULL) {
  251. rv = SECFailure;
  252. goto loser;
  253. }
  254. loser:
  255. if (cipherValue.param) {
  256. nsspkcs5_DestroyPBEParameter(cipherValue.param);
  257. }
  258. if (cipherValue.arena) {
  259. PORT_FreeArena(cipherValue.arena,PR_FALSE);
  260. }
  261. return rv;
  262. }
  263. /*
  264. * encrypt a block. This function returned the encrypted ciphertext which
  265. * the caller must free. If the caller provides an arena, cipherText will
  266. * be allocated out of that arena. This also generated the per entry
  267. * salt automatically.
  268. */
  269. SECStatus
  270. sftkdb_EncryptAttribute(PLArenaPool *arena, SECItem *passKey,
  271. SECItem *plainText, SECItem **cipherText)
  272. {
  273. SECStatus rv;
  274. sftkCipherValue cipherValue;
  275. SECItem *cipher = NULL;
  276. NSSPKCS5PBEParameter *param = NULL;
  277. unsigned char saltData[HASH_LENGTH_MAX];
  278. cipherValue.alg = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
  279. cipherValue.salt.len = SHA1_LENGTH;
  280. cipherValue.salt.data = saltData;
  281. RNG_GenerateGlobalRandomBytes(saltData,cipherValue.salt.len);
  282. param = nsspkcs5_NewParam(cipherValue.alg, &cipherValue.salt, 1);
  283. if (param == NULL) {
  284. rv = SECFailure;
  285. goto loser;
  286. }
  287. cipher = nsspkcs5_CipherData(param, passKey, plainText, PR_TRUE, NULL);
  288. if (cipher == NULL) {
  289. rv = SECFailure;
  290. goto loser;
  291. }
  292. cipherValue.value = *cipher;
  293. cipherValue.param = param;
  294. rv = sftkdb_encodeCipherText(arena, &cipherValue, cipherText);
  295. if (rv != SECSuccess) {
  296. goto loser;
  297. }
  298. loser:
  299. if (cipher) {
  300. SECITEM_FreeItem(cipher, PR_TRUE);
  301. }
  302. if (param) {
  303. nsspkcs5_DestroyPBEParameter(param);
  304. }
  305. return rv;
  306. }
  307. /*
  308. * use the password and the pbe parameters to generate an HMAC for the
  309. * given plain text data. This is used by sftkdb_VerifyAttribute and
  310. * sftkdb_SignAttribute. Signature is returned in signData. The caller
  311. * must preallocate the space in the secitem.
  312. */
  313. static SECStatus
  314. sftkdb_pbehash(SECOidTag sigOid, SECItem *passKey,
  315. NSSPKCS5PBEParameter *param,
  316. CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType,
  317. SECItem *plainText, SECItem *signData)
  318. {
  319. SECStatus rv = SECFailure;
  320. SECItem *key = NULL;
  321. HMACContext *hashCx = NULL;
  322. HASH_HashType hashType = HASH_AlgNULL;
  323. const SECHashObject *hashObj;
  324. unsigned char addressData[SDB_ULONG_SIZE];
  325. hashType = HASH_FromHMACOid(param->encAlg);
  326. if (hashType == HASH_AlgNULL) {
  327. PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
  328. return SECFailure;
  329. }
  330. hashObj = HASH_GetRawHashObject(hashType);
  331. if (hashObj == NULL) {
  332. goto loser;
  333. }
  334. key = nsspkcs5_ComputeKeyAndIV(param, passKey, NULL, PR_FALSE);
  335. if (!key) {
  336. goto loser;
  337. }
  338. hashCx = HMAC_Create(hashObj, key->data, key->len, PR_TRUE);
  339. if (!hashCx) {
  340. goto loser;
  341. }
  342. HMAC_Begin(hashCx);
  343. /* Tie this value to a particular object. This is most important for
  344. * the trust attributes, where and attacker could copy a value for
  345. * 'validCA' from another cert in the database */
  346. sftk_ULong2SDBULong(addressData, objectID);
  347. HMAC_Update(hashCx, addressData, SDB_ULONG_SIZE);
  348. sftk_ULong2SDBULong(addressData, attrType);
  349. HMAC_Update(hashCx, addressData, SDB_ULONG_SIZE);
  350. HMAC_Update(hashCx, plainText->data, plainText->len);
  351. rv = HMAC_Finish(hashCx, signData->data, &signData->len, signData->len);
  352. loser:
  353. if (hashCx) {
  354. HMAC_Destroy(hashCx, PR_TRUE);
  355. }
  356. if (key) {
  357. SECITEM_FreeItem(key,PR_TRUE);
  358. }
  359. return rv;
  360. }
  361. /*
  362. * Use our key to verify a signText block from the database matches
  363. * the plainText from the database. The signText is a PKCS 5 v2 pbe.
  364. * plainText is the plainText of the attribute.
  365. */
  366. SECStatus
  367. sftkdb_VerifyAttribute(SECItem *passKey, CK_OBJECT_HANDLE objectID,
  368. CK_ATTRIBUTE_TYPE attrType,
  369. SECItem *plainText, SECItem *signText)
  370. {
  371. SECStatus rv;
  372. sftkCipherValue signValue;
  373. SECItem signature;
  374. unsigned char signData[HASH_LENGTH_MAX];
  375. /* First get the cipher type */
  376. rv = sftkdb_decodeCipherText(signText, &signValue);
  377. if (rv != SECSuccess) {
  378. goto loser;
  379. }
  380. signature.data = signData;
  381. signature.len = sizeof(signData);
  382. rv = sftkdb_pbehash(signValue.alg, passKey, signValue.param,
  383. objectID, attrType, plainText, &signature);
  384. if (rv != SECSuccess) {
  385. goto loser;
  386. }
  387. if (SECITEM_CompareItem(&signValue.value,&signature) != 0) {
  388. PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
  389. rv = SECFailure;
  390. }
  391. loser:
  392. if (signValue.param) {
  393. nsspkcs5_DestroyPBEParameter(signValue.param);
  394. }
  395. if (signValue.arena) {
  396. PORT_FreeArena(signValue.arena,PR_FALSE);
  397. }
  398. return rv;
  399. }
  400. /*
  401. * Use our key to create a signText block the plain text of an
  402. * attribute. The signText is a PKCS 5 v2 pbe.
  403. */
  404. SECStatus
  405. sftkdb_SignAttribute(PLArenaPool *arena, SECItem *passKey,
  406. CK_OBJECT_HANDLE objectID, CK_ATTRIBUTE_TYPE attrType,
  407. SECItem *plainText, SECItem **signature)
  408. {
  409. SECStatus rv;
  410. sftkCipherValue signValue;
  411. NSSPKCS5PBEParameter *param = NULL;
  412. unsigned char saltData[HASH_LENGTH_MAX];
  413. unsigned char signData[HASH_LENGTH_MAX];
  414. SECOidTag hmacAlg = SEC_OID_HMAC_SHA256; /* hash for authentication */
  415. SECOidTag prfAlg = SEC_OID_HMAC_SHA256; /* hash for pb key generation */
  416. HASH_HashType prfType;
  417. unsigned int hmacLength;
  418. unsigned int prfLength;
  419. /* this code allows us to fetch the lengths and hashes on the fly
  420. * by simply changing the OID above */
  421. prfType = HASH_FromHMACOid(prfAlg);
  422. PORT_Assert(prfType != HASH_AlgNULL);
  423. prfLength = HASH_GetRawHashObject(prfType)->length;
  424. PORT_Assert(prfLength <= HASH_LENGTH_MAX);
  425. hmacLength = HASH_GetRawHashObject(HASH_FromHMACOid(hmacAlg))->length;
  426. PORT_Assert(hmacLength <= HASH_LENGTH_MAX);
  427. /* initialize our CipherValue structure */
  428. signValue.alg = SEC_OID_PKCS5_PBMAC1;
  429. signValue.salt.len = prfLength;
  430. signValue.salt.data = saltData;
  431. signValue.value.data = signData;
  432. signValue.value.len = hmacLength;
  433. RNG_GenerateGlobalRandomBytes(saltData,prfLength);
  434. /* initialize our pkcs5 parameter */
  435. param = nsspkcs5_NewParam(signValue.alg, &signValue.salt, 1);
  436. if (param == NULL) {
  437. rv = SECFailure;
  438. goto loser;
  439. }
  440. param->keyID = pbeBitGenIntegrityKey;
  441. /* set the PKCS 5 v2 parameters, not extractable from the
  442. * data passed into nsspkcs5_NewParam */
  443. param->encAlg = hmacAlg;
  444. param->hashType = prfType;
  445. param->keyLen = hmacLength;
  446. rv = SECOID_SetAlgorithmID(param->poolp, &param->prfAlg, prfAlg, NULL);
  447. if (rv != SECSuccess) {
  448. goto loser;
  449. }
  450. /* calculate the mac */
  451. rv = sftkdb_pbehash(signValue.alg, passKey, param, objectID, attrType,
  452. plainText, &signValue.value);
  453. if (rv != SECSuccess) {
  454. goto loser;
  455. }
  456. signValue.param = param;
  457. /* write it out */
  458. rv = sftkdb_encodeCipherText(arena, &signValue, signature);
  459. if (rv != SECSuccess) {
  460. goto loser;
  461. }
  462. loser:
  463. if (param) {
  464. nsspkcs5_DestroyPBEParameter(param);
  465. }
  466. return rv;
  467. }
  468. /*
  469. * safely swith the passed in key for the one caches in the keydb handle
  470. *
  471. * A key attached to the handle tells us the the token is logged in.
  472. * We can used the key attached to the handle in sftkdb_EncryptAttribute
  473. * and sftkdb_DecryptAttribute calls.
  474. */
  475. static void
  476. sftkdb_switchKeys(SFTKDBHandle *keydb, SECItem *passKey)
  477. {
  478. unsigned char *data;
  479. int len;
  480. if (keydb->passwordLock == NULL) {
  481. PORT_Assert(keydb->type != SFTK_KEYDB_TYPE);
  482. return;
  483. }
  484. /* an atomic pointer set would be nice */
  485. SKIP_AFTER_FORK(PZ_Lock(keydb->passwordLock));
  486. data = keydb->passwordKey.data;
  487. len = keydb->passwordKey.len;
  488. keydb->passwordKey.data = passKey->data;
  489. keydb->passwordKey.len = passKey->len;
  490. passKey->data = data;
  491. passKey->len = len;
  492. SKIP_AFTER_FORK(PZ_Unlock(keydb->passwordLock));
  493. }
  494. /*
  495. * returns true if we are in a middle of a merge style update.
  496. */
  497. PRBool
  498. sftkdb_InUpdateMerge(SFTKDBHandle *keydb)
  499. {
  500. return keydb->updateID ? PR_TRUE : PR_FALSE;
  501. }
  502. /*
  503. * returns true if we are looking for the password for the user's old source
  504. * database as part of a merge style update.
  505. */
  506. PRBool
  507. sftkdb_NeedUpdateDBPassword(SFTKDBHandle *keydb)
  508. {
  509. if (!sftkdb_InUpdateMerge(keydb)) {
  510. return PR_FALSE;
  511. }
  512. if (keydb->updateDBIsInit && !keydb->updatePasswordKey) {
  513. return PR_TRUE;
  514. }
  515. return PR_FALSE;
  516. }
  517. /*
  518. * fetch an update password key from a handle.
  519. */
  520. SECItem *
  521. sftkdb_GetUpdatePasswordKey(SFTKDBHandle *handle)
  522. {
  523. SECItem *key = NULL;
  524. /* if we're a cert db, fetch it from our peer key db */
  525. if (handle->type == SFTK_CERTDB_TYPE) {
  526. handle = handle->peerDB;
  527. }
  528. /* don't have one */
  529. if (!handle) {
  530. return NULL;
  531. }
  532. PZ_Lock(handle->passwordLock);
  533. if (handle->updatePasswordKey) {
  534. key = SECITEM_DupItem(handle->updatePasswordKey);
  535. }
  536. PZ_Unlock(handle->passwordLock);
  537. return key;
  538. }
  539. /*
  540. * free the update password key from a handle.
  541. */
  542. void
  543. sftkdb_FreeUpdatePasswordKey(SFTKDBHandle *handle)
  544. {
  545. SECItem *key = NULL;
  546. /* don't have one */
  547. if (!handle) {
  548. return;
  549. }
  550. /* if we're a cert db, we don't have one */
  551. if (handle->type == SFTK_CERTDB_TYPE) {
  552. return;
  553. }
  554. PZ_Lock(handle->passwordLock);
  555. if (handle->updatePasswordKey) {
  556. key = handle->updatePasswordKey;
  557. handle->updatePasswordKey = NULL;
  558. }
  559. PZ_Unlock(handle->passwordLock);
  560. if (key) {
  561. SECITEM_ZfreeItem(key, PR_TRUE);
  562. }
  563. return;
  564. }
  565. /*
  566. * what password db we use depends heavily on the update state machine
  567. *
  568. * 1) no update db, return the normal database.
  569. * 2) update db and no merge return the update db.
  570. * 3) update db and in merge:
  571. * return the update db if we need the update db's password,
  572. * otherwise return our normal datbase.
  573. */
  574. static SDB *
  575. sftk_getPWSDB(SFTKDBHandle *keydb)
  576. {
  577. if (!keydb->update) {
  578. return keydb->db;
  579. }
  580. if (!sftkdb_InUpdateMerge(keydb)) {
  581. return keydb->update;
  582. }
  583. if (sftkdb_NeedUpdateDBPassword(keydb)) {
  584. return keydb->update;
  585. }
  586. return keydb->db;
  587. }
  588. /*
  589. * return success if we have a valid password entry.
  590. * This is will show up outside of PKCS #11 as CKF_USER_PIN_INIT
  591. * in the token flags.
  592. */
  593. SECStatus
  594. sftkdb_HasPasswordSet(SFTKDBHandle *keydb)
  595. {
  596. SECItem salt, value;
  597. unsigned char saltData[SDB_MAX_META_DATA_LEN];
  598. unsigned char valueData[SDB_MAX_META_DATA_LEN];
  599. CK_RV crv;
  600. SDB *db;
  601. if (keydb == NULL) {
  602. return SECFailure;
  603. }
  604. db = sftk_getPWSDB(keydb);
  605. if (db == NULL) {
  606. return SECFailure;
  607. }
  608. salt.data = saltData;
  609. salt.len = sizeof(saltData);
  610. value.data = valueData;
  611. value.len = sizeof(valueData);
  612. crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
  613. /* If no password is set, we can update right away */
  614. if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update
  615. && crv != CKR_OK) {
  616. /* update the peer certdb if it exists */
  617. if (keydb->peerDB) {
  618. sftkdb_Update(keydb->peerDB, NULL);
  619. }
  620. sftkdb_Update(keydb, NULL);
  621. }
  622. return (crv == CKR_OK) ? SECSuccess : SECFailure;
  623. }
  624. #define SFTK_PW_CHECK_STRING "password-check"
  625. #define SFTK_PW_CHECK_LEN 14
  626. /*
  627. * check if the supplied password is valid
  628. */
  629. SECStatus
  630. sftkdb_CheckPassword(SFTKDBHandle *keydb, const char *pw, PRBool *tokenRemoved)
  631. {
  632. SECStatus rv;
  633. SECItem salt, value;
  634. unsigned char saltData[SDB_MAX_META_DATA_LEN];
  635. unsigned char valueData[SDB_MAX_META_DATA_LEN];
  636. SECItem key;
  637. SECItem *result = NULL;
  638. SDB *db;
  639. CK_RV crv;
  640. if (keydb == NULL) {
  641. return SECFailure;
  642. }
  643. db = sftk_getPWSDB(keydb);
  644. if (db == NULL) {
  645. return SECFailure;
  646. }
  647. key.data = NULL;
  648. key.len = 0;
  649. if (pw == NULL) pw="";
  650. /* get the entry from the database */
  651. salt.data = saltData;
  652. salt.len = sizeof(saltData);
  653. value.data = valueData;
  654. value.len = sizeof(valueData);
  655. crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
  656. if (crv != CKR_OK) {
  657. rv = SECFailure;
  658. goto done;
  659. }
  660. /* get our intermediate key based on the entry salt value */
  661. rv = sftkdb_passwordToKey(keydb, &salt, pw, &key);
  662. if (rv != SECSuccess) {
  663. goto done;
  664. }
  665. /* decrypt the entry value */
  666. rv = sftkdb_DecryptAttribute(&key, &value, &result);
  667. if (rv != SECSuccess) {
  668. goto done;
  669. }
  670. /* if it's what we expect, update our key in the database handle and
  671. * return Success */
  672. if ((result->len == SFTK_PW_CHECK_LEN) &&
  673. PORT_Memcmp(result->data, SFTK_PW_CHECK_STRING, SFTK_PW_CHECK_LEN) == 0){
  674. /*
  675. * We have a password, now lets handle any potential update cases..
  676. *
  677. * First, the normal case: no update. In this case we only need the
  678. * the password for our only DB, which we now have, we switch
  679. * the keys and fall through.
  680. * Second regular (non-merge) update: The target DB does not yet have
  681. * a password initialized, we now have the password for the source DB,
  682. * so we can switch the keys and simply update the target database.
  683. * Merge update case: This one is trickier.
  684. * 1) If we need the source DB password, then we just got it here.
  685. * We need to save that password,
  686. * then we need to check to see if we need or have the target
  687. * database password.
  688. * If we have it (it's the same as the source), or don't need
  689. * it (it's not set or is ""), we can start the update now.
  690. * If we don't have it, we need the application to get it from
  691. * the user. Clear our sessions out to simulate a token
  692. * removal. C_GetTokenInfo will change the token description
  693. * and the token will still appear to be logged out.
  694. * 2) If we already have the source DB password, this password is
  695. * for the target database. We can now move forward with the
  696. * update, as we now have both required passwords.
  697. *
  698. */
  699. PZ_Lock(keydb->passwordLock);
  700. if (sftkdb_NeedUpdateDBPassword(keydb)) {
  701. /* Squirrel this special key away.
  702. * This has the side effect of turning sftkdb_NeedLegacyPW off,
  703. * as well as changing which database is returned from
  704. * SFTK_GET_PW_DB (thus effecting both sftkdb_CheckPassword()
  705. * and sftkdb_HasPasswordSet()) */
  706. keydb->updatePasswordKey = SECITEM_DupItem(&key);
  707. PZ_Unlock(keydb->passwordLock);
  708. if (keydb->updatePasswordKey == NULL) {
  709. /* PORT_Error set by SECITEM_DupItem */
  710. rv = SECFailure;
  711. goto done;
  712. }
  713. /* Simulate a token removal -- we need to do this any
  714. * any case at this point so the token name is correct. */
  715. *tokenRemoved = PR_TRUE;
  716. /*
  717. * OK, we got the update DB password, see if we need a password
  718. * for the target...
  719. */
  720. if (sftkdb_HasPasswordSet(keydb) == SECSuccess) {
  721. /* We have a password, do we know what the password is?
  722. * check 1) for the password the user supplied for the
  723. * update DB,
  724. * and 2) for the null password.
  725. *
  726. * RECURSION NOTE: we are calling ourselves here. This means
  727. * any updates, switchKeys, etc will have been completed
  728. * if these functions return successfully, in those cases
  729. * just exit returning Success. We don't recurse infinitely
  730. * because we are making this call from a NeedUpdateDBPassword
  731. * block and we've already set that update password at this
  732. * point. */
  733. rv = sftkdb_CheckPassword(keydb, pw, tokenRemoved);
  734. if (rv == SECSuccess) {
  735. /* source and target databases have the same password, we
  736. * are good to go */
  737. goto done;
  738. }
  739. sftkdb_CheckPassword(keydb, "", tokenRemoved);
  740. /*
  741. * Important 'NULL' code here. At this point either we
  742. * succeeded in logging in with "" or we didn't.
  743. *
  744. * If we did succeed at login, our machine state will be set
  745. * to logged in appropriately. The application will find that
  746. * it's logged in as soon as it opens a new session. We have
  747. * also completed the update. Life is good.
  748. *
  749. * If we did not succeed, well the user still successfully
  750. * logged into the update database, since we faked the token
  751. * removal it's just like the user logged into his smart card
  752. * then removed it. the actual login work, so we report that
  753. * success back to the user, but we won't actually be
  754. * logged in. The application will find this out when it
  755. * checks it's login state, thus triggering another password
  756. * prompt so we can get the real target DB password.
  757. *
  758. * summary, we exit from here with SECSuccess no matter what.
  759. */
  760. rv = SECSuccess;
  761. goto done;
  762. } else {
  763. /* there is no password, just fall through to update.
  764. * update will write the source DB's password record
  765. * into the target DB just like it would in a non-merge
  766. * update case. */
  767. }
  768. } else {
  769. PZ_Unlock(keydb->passwordLock);
  770. }
  771. /* load the keys, so the keydb can parse it's key set */
  772. sftkdb_switchKeys(keydb, &key);
  773. /* we need to update, do it now */
  774. if (((keydb->db->sdb_flags & SDB_RDONLY) == 0) && keydb->update) {
  775. /* update the peer certdb if it exists */
  776. if (keydb->peerDB) {
  777. sftkdb_Update(keydb->peerDB, &key);
  778. }
  779. sftkdb_Update(keydb, &key);
  780. }
  781. } else {
  782. rv = SECFailure;
  783. /*PORT_SetError( bad password); */
  784. }
  785. done:
  786. if (key.data) {
  787. PORT_ZFree(key.data,key.len);
  788. }
  789. if (result) {
  790. SECITEM_FreeItem(result,PR_TRUE);
  791. }
  792. return rv;
  793. }
  794. /*
  795. * return Success if the there is a cached password key.
  796. */
  797. SECStatus
  798. sftkdb_PWCached(SFTKDBHandle *keydb)
  799. {
  800. return keydb->passwordKey.data ? SECSuccess : SECFailure;
  801. }
  802. static CK_RV
  803. sftk_updateMacs(PLArenaPool *arena, SFTKDBHandle *handle,
  804. CK_OBJECT_HANDLE id, SECItem *newKey)
  805. {
  806. CK_RV crv = CKR_OK;
  807. CK_RV crv2;
  808. CK_ATTRIBUTE authAttrs[] = {
  809. {CKA_MODULUS, NULL, 0},
  810. {CKA_PUBLIC_EXPONENT, NULL, 0},
  811. {CKA_CERT_SHA1_HASH, NULL, 0},
  812. {CKA_CERT_MD5_HASH, NULL, 0},
  813. {CKA_TRUST_SERVER_AUTH, NULL, 0},
  814. {CKA_TRUST_CLIENT_AUTH, NULL, 0},
  815. {CKA_TRUST_EMAIL_PROTECTION, NULL, 0},
  816. {CKA_TRUST_CODE_SIGNING, NULL, 0},
  817. {CKA_TRUST_STEP_UP_APPROVED, NULL, 0},
  818. {CKA_NSS_OVERRIDE_EXTENSIONS, NULL, 0},
  819. };
  820. CK_ULONG authAttrCount = sizeof(authAttrs)/sizeof(CK_ATTRIBUTE);
  821. int i, count;
  822. SFTKDBHandle *keyHandle = handle;
  823. SDB *keyTarget = NULL;
  824. id &= SFTK_OBJ_ID_MASK;
  825. if (handle->type != SFTK_KEYDB_TYPE) {
  826. keyHandle = handle->peerDB;
  827. }
  828. if (keyHandle == NULL) {
  829. return CKR_OK;
  830. }
  831. /* old DB's don't have meta data, finished with MACs */
  832. keyTarget = SFTK_GET_SDB(keyHandle);
  833. if ((keyTarget->sdb_flags &SDB_HAS_META) == 0) {
  834. return CKR_OK;
  835. }
  836. /*
  837. * STEP 1: find the MACed attributes of this object
  838. */
  839. crv2 = sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
  840. count = 0;
  841. /* allocate space for the attributes */
  842. for (i=0; i < authAttrCount; i++) {
  843. if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)){
  844. continue;
  845. }
  846. count++;
  847. authAttrs[i].pValue = PORT_ArenaAlloc(arena,authAttrs[i].ulValueLen);
  848. if (authAttrs[i].pValue == NULL) {
  849. crv = CKR_HOST_MEMORY;
  850. break;
  851. }
  852. }
  853. /* if count was zero, none were found, finished with MACs */
  854. if (count == 0) {
  855. return CKR_OK;
  856. }
  857. crv = sftkdb_GetAttributeValue(handle, id, authAttrs, authAttrCount);
  858. /* ignore error code, we expect some possible errors */
  859. /* GetAttributeValue just verified the old macs, safe to write
  860. * them out then... */
  861. for (i=0; i < authAttrCount; i++) {
  862. SECItem *signText;
  863. SECItem plainText;
  864. SECStatus rv;
  865. if ((authAttrs[i].ulValueLen == -1) || (authAttrs[i].ulValueLen == 0)){
  866. continue;
  867. }
  868. plainText.data = authAttrs[i].pValue;
  869. plainText.len = authAttrs[i].ulValueLen;
  870. rv = sftkdb_SignAttribute(arena, newKey, id,
  871. authAttrs[i].type, &plainText, &signText);
  872. if (rv != SECSuccess) {
  873. return CKR_GENERAL_ERROR;
  874. }
  875. rv = sftkdb_PutAttributeSignature(handle, keyTarget, id,
  876. authAttrs[i].type, signText);
  877. if (rv != SECSuccess) {
  878. return CKR_GENERAL_ERROR;
  879. }
  880. }
  881. return CKR_OK;
  882. }
  883. static CK_RV
  884. sftk_updateEncrypted(PLArenaPool *arena, SFTKDBHandle *keydb,
  885. CK_OBJECT_HANDLE id, SECItem *newKey)
  886. {
  887. CK_RV crv = CKR_OK;
  888. CK_RV crv2;
  889. CK_ATTRIBUTE *first, *last;
  890. CK_ATTRIBUTE privAttrs[] = {
  891. {CKA_VALUE, NULL, 0},
  892. {CKA_PRIVATE_EXPONENT, NULL, 0},
  893. {CKA_PRIME_1, NULL, 0},
  894. {CKA_PRIME_2, NULL, 0},
  895. {CKA_EXPONENT_1, NULL, 0},
  896. {CKA_EXPONENT_2, NULL, 0},
  897. {CKA_COEFFICIENT, NULL, 0} };
  898. CK_ULONG privAttrCount = sizeof(privAttrs)/sizeof(CK_ATTRIBUTE);
  899. int i, count;
  900. /*
  901. * STEP 1. Read the old attributes in the clear.
  902. */
  903. /* Get the attribute sizes.
  904. * ignore the error code, we will have unknown attributes here */
  905. crv2 = sftkdb_GetAttributeValue(keydb, id, privAttrs, privAttrCount);
  906. /*
  907. * find the valid block of attributes and fill allocate space for
  908. * their data */
  909. first = last = NULL;
  910. for (i=0; i < privAttrCount; i++) {
  911. /* find the block of attributes that are appropriate for this
  912. * objects. There should only be once contiguous block, if not
  913. * there's an error.
  914. *
  915. * find the first and last good entry.
  916. */
  917. if ((privAttrs[i].ulValueLen == -1) || (privAttrs[i].ulValueLen == 0)){
  918. if (!first) continue;
  919. if (!last) {
  920. /* previous entry was last good entry */
  921. last= &privAttrs[i-1];
  922. }
  923. continue;
  924. }
  925. if (!first) {
  926. first = &privAttrs[i];
  927. }
  928. if (last) {
  929. /* OOPS, we've found another good entry beyond the end of the
  930. * last good entry, we need to fail here. */
  931. crv = CKR_GENERAL_ERROR;
  932. break;
  933. }
  934. privAttrs[i].pValue = PORT_ArenaAlloc(arena,privAttrs[i].ulValueLen);
  935. if (privAttrs[i].pValue == NULL) {
  936. crv = CKR_HOST_MEMORY;
  937. break;
  938. }
  939. }
  940. if (first == NULL) {
  941. /* no valid entries found, return error based on crv2 */
  942. return crv2;
  943. }
  944. if (last == NULL) {
  945. last = &privAttrs[privAttrCount-1];
  946. }
  947. if (crv != CKR_OK) {
  948. return crv;
  949. }
  950. /* read the attributes */
  951. count = (last-first)+1;
  952. crv = sftkdb_GetAttributeValue(keydb, id, first, count);
  953. if (crv != CKR_OK) {
  954. return crv;
  955. }
  956. /*
  957. * STEP 2: read the encrypt the attributes with the new key.
  958. */
  959. for (i=0; i < count; i++) {
  960. SECItem plainText;
  961. SECItem *result;
  962. SECStatus rv;
  963. plainText.data = first[i].pValue;
  964. plainText.len = first[i].ulValueLen;
  965. rv = sftkdb_EncryptAttribute(arena, newKey, &plainText, &result);
  966. if (rv != SECSuccess) {
  967. return CKR_GENERAL_ERROR;
  968. }
  969. first[i].pValue = result->data;
  970. first[i].ulValueLen = result->len;
  971. /* clear our sensitive data out */
  972. PORT_Memset(plainText.data, 0, plainText.len);
  973. }
  974. /*
  975. * STEP 3: write the newly encrypted attributes out directly
  976. */
  977. id &= SFTK_OBJ_ID_MASK;
  978. keydb->newKey = newKey;
  979. crv = (*keydb->db->sdb_SetAttributeValue)(keydb->db, id, first, count);
  980. keydb->newKey = NULL;
  981. return crv;
  982. }
  983. static CK_RV
  984. sftk_convertAttributes(SFTKDBHandle *handle,
  985. CK_OBJECT_HANDLE id, SECItem *newKey)
  986. {
  987. CK_RV crv = CKR_OK;
  988. PLArenaPool *arena = NULL;
  989. /* get a new arena to simplify cleanup */
  990. arena = PORT_NewArena(1024);
  991. if (!arena) {
  992. return CKR_HOST_MEMORY;
  993. }
  994. /*
  995. * first handle the MACS
  996. */
  997. crv = sftk_updateMacs(arena, handle, id, newKey);
  998. if (crv != CKR_OK) {
  999. goto loser;
  1000. }
  1001. if (handle->type == SFTK_KEYDB_TYPE) {
  1002. crv = sftk_updateEncrypted(arena, handle, id, newKey);
  1003. if (crv != CKR_OK) {
  1004. goto loser;
  1005. }
  1006. }
  1007. /* free up our mess */
  1008. /* NOTE: at this point we know we've cleared out any unencrypted data */
  1009. PORT_FreeArena(arena, PR_FALSE);
  1010. return CKR_OK;
  1011. loser:
  1012. /* there may be unencrypted data, clear it out down */
  1013. PORT_FreeArena(arena, PR_TRUE);
  1014. return crv;
  1015. }
  1016. /*
  1017. * must be called with the old key active.
  1018. */
  1019. CK_RV
  1020. sftkdb_convertObjects(SFTKDBHandle *handle, CK_ATTRIBUTE *template,
  1021. CK_ULONG count, SECItem *newKey)
  1022. {
  1023. SDBFind *find = NULL;
  1024. CK_ULONG idCount = SFTK_MAX_IDS;
  1025. CK_OBJECT_HANDLE ids[SFTK_MAX_IDS];
  1026. CK_RV crv, crv2;
  1027. int i;
  1028. crv = sftkdb_FindObjectsInit(handle, template, count, &find);
  1029. if (crv != CKR_OK) {
  1030. return crv;
  1031. }
  1032. while ((crv == CKR_OK) && (idCount == SFTK_MAX_IDS)) {
  1033. crv = sftkdb_FindObjects(handle, find, ids, SFTK_MAX_IDS, &idCount);
  1034. for (i=0; (crv == CKR_OK) && (i < idCount); i++) {
  1035. crv = sftk_convertAttributes(handle, ids[i], newKey);
  1036. }
  1037. }
  1038. crv2 = sftkdb_FindObjectsFinal(handle, find);
  1039. if (crv == CKR_OK) crv = crv2;
  1040. return crv;
  1041. }
  1042. /*
  1043. * change the database password.
  1044. */
  1045. SECStatus
  1046. sftkdb_ChangePassword(SFTKDBHandle *keydb,
  1047. char *oldPin, char *newPin, PRBool *tokenRemoved)
  1048. {
  1049. SECStatus rv = SECSuccess;
  1050. SECItem plainText;
  1051. SECItem newKey;
  1052. SECItem *result = NULL;
  1053. SECItem salt, value;
  1054. SFTKDBHandle *certdb;
  1055. unsigned char saltData[SDB_MAX_META_DATA_LEN];
  1056. unsigned char valueData[SDB_MAX_META_DATA_LEN];
  1057. CK_RV crv;
  1058. SDB *db;
  1059. if (keydb == NULL) {
  1060. return SECFailure;
  1061. }
  1062. db = SFTK_GET_SDB(keydb);
  1063. if (db == NULL) {
  1064. return SECFailure;
  1065. }
  1066. newKey.data = NULL;
  1067. /* make sure we have a valid old pin */
  1068. crv = (*keydb->db->sdb_Begin)(keydb->db);
  1069. if (crv != CKR_OK) {
  1070. rv = SECFailure;
  1071. goto loser;
  1072. }
  1073. salt.data = saltData;
  1074. salt.len = sizeof(saltData);
  1075. value.data = valueData;
  1076. value.len = sizeof(valueData);
  1077. crv = (*db->sdb_GetMetaData)(db, "password", &salt, &value);
  1078. if (crv == CKR_OK) {
  1079. rv = sftkdb_CheckPassword(keydb, oldPin, tokenRemoved);
  1080. if (rv == SECFailure) {
  1081. goto loser;
  1082. }
  1083. } else {
  1084. salt.len = SHA1_LENGTH;
  1085. RNG_GenerateGlobalRandomBytes(salt.data,salt.len);
  1086. }
  1087. rv = sftkdb_passwordToKey(keydb, &salt, newPin, &newKey);
  1088. if (rv != SECSuccess) {
  1089. goto loser;
  1090. }
  1091. /*
  1092. * convert encrypted entries here.
  1093. */
  1094. crv = sftkdb_convertObjects(keydb, NULL, 0, &newKey);
  1095. if (crv != CKR_OK) {
  1096. rv = SECFailure;
  1097. goto loser;
  1098. }
  1099. /* fix up certdb macs */
  1100. certdb = keydb->peerDB;
  1101. if (certdb) {
  1102. CK_ATTRIBUTE objectType = { CKA_CLASS, 0, sizeof(CK_OBJECT_CLASS) };
  1103. CK_OBJECT_CLASS myClass = CKO_NETSCAPE_TRUST;
  1104. objectType.pValue = &myClass;
  1105. crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey);
  1106. if (crv != CKR_OK) {
  1107. rv = SECFailure;
  1108. goto loser;
  1109. }
  1110. myClass = CKO_PUBLIC_KEY;
  1111. crv = sftkdb_convertObjects(certdb, &objectType, 1, &newKey);
  1112. if (crv != CKR_OK) {
  1113. rv = SECFailure;
  1114. goto loser;
  1115. }
  1116. }
  1117. plainText.data = (unsigned char *)SFTK_PW_CHECK_STRING;
  1118. plainText.len = SFTK_PW_CHECK_LEN;
  1119. rv = sftkdb_EncryptAttribute(NULL, &newKey, &plainText, &result);
  1120. if (rv != SECSuccess) {
  1121. goto loser;
  1122. }
  1123. value.data = result->data;
  1124. value.len = result->len;
  1125. crv = (*keydb->db->sdb_PutMetaData)(keydb->db, "password", &salt, &value);
  1126. if (crv != CKR_OK) {
  1127. rv = SECFailure;
  1128. goto loser;
  1129. }
  1130. crv = (*keydb->db->sdb_Commit)(keydb->db);
  1131. if (crv != CKR_OK) {
  1132. rv = SECFailure;
  1133. goto loser;
  1134. }
  1135. keydb->newKey = NULL;
  1136. sftkdb_switchKeys(keydb, &newKey);
  1137. loser:
  1138. if (newKey.data) {
  1139. PORT_ZFree(newKey.data,newKey.len);
  1140. }
  1141. if (result) {
  1142. SECITEM_FreeItem(result, PR_FALSE);
  1143. }
  1144. if (rv != SECSuccess) {
  1145. (*keydb->db->sdb_Abort)(keydb->db);
  1146. }
  1147. return rv;
  1148. }
  1149. /*
  1150. * lose our cached password
  1151. */
  1152. SECStatus
  1153. sftkdb_ClearPassword(SFTKDBHandle *keydb)
  1154. {
  1155. SECItem oldKey;
  1156. oldKey.data = NULL;
  1157. oldKey.len = 0;
  1158. sftkdb_switchKeys(keydb, &oldKey);
  1159. if (oldKey.data) {
  1160. PORT_ZFree(oldKey.data, oldKey.len);
  1161. }
  1162. return SECSuccess;
  1163. }