PageRenderTime 59ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/security/nss/lib/softoken/legacydb/keydb.c

http://github.com/zpao/v8monkey
C | 2272 lines | 1657 code | 370 blank | 245 comment | 415 complexity | 09025043ef2509d9863423aad34b7427 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-3.0, AGPL-1.0, LGPL-2.1, BSD-3-Clause, GPL-2.0, JSON, Apache-2.0, 0BSD
  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-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  23. *
  24. * Alternatively, the contents of this file may be used under the terms of
  25. * either the GNU General Public License Version 2 or later (the "GPL"), or
  26. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. * in which case the provisions of the GPL or the LGPL are applicable instead
  28. * of those above. If you wish to allow use of your version of this file only
  29. * under the terms of either the GPL or the LGPL, and not to allow others to
  30. * use your version of this file under the terms of the MPL, indicate your
  31. * decision by deleting the provisions above and replace them with the notice
  32. * and other provisions required by the GPL or the LGPL. If you do not delete
  33. * the provisions above, a recipient may use your version of this file under
  34. * the terms of any one of the MPL, the GPL or the LGPL.
  35. *
  36. * ***** END LICENSE BLOCK ***** */
  37. /* $Id: keydb.c,v 1.12 2010/07/20 01:26:04 wtc%google.com Exp $ */
  38. #include "lowkeyi.h"
  39. #include "secasn1.h"
  40. #include "secder.h"
  41. #include "secoid.h"
  42. #include "blapi.h"
  43. #include "secitem.h"
  44. #include "pcert.h"
  45. #include "mcom_db.h"
  46. #include "secerr.h"
  47. #include "keydbi.h"
  48. #include "lgdb.h"
  49. /*
  50. * Record keys for keydb
  51. */
  52. #define SALT_STRING "global-salt"
  53. #define VERSION_STRING "Version"
  54. #define KEYDB_PW_CHECK_STRING "password-check"
  55. #define KEYDB_PW_CHECK_LEN 14
  56. #define KEYDB_FAKE_PW_CHECK_STRING "fake-password-check"
  57. #define KEYDB_FAKE_PW_CHECK_LEN 19
  58. /* Size of the global salt for key database */
  59. #define SALT_LENGTH 16
  60. SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
  61. const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[] = {
  62. { SEC_ASN1_SEQUENCE,
  63. 0, NULL, sizeof(NSSLOWKEYEncryptedPrivateKeyInfo) },
  64. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  65. offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,algorithm),
  66. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  67. { SEC_ASN1_OCTET_STRING,
  68. offsetof(NSSLOWKEYEncryptedPrivateKeyInfo,encryptedData) },
  69. { 0 }
  70. };
  71. const SEC_ASN1Template nsslowkey_PointerToEncryptedPrivateKeyInfoTemplate[] = {
  72. { SEC_ASN1_POINTER, 0, nsslowkey_EncryptedPrivateKeyInfoTemplate }
  73. };
  74. /* ====== Default key databse encryption algorithm ====== */
  75. static void
  76. sec_destroy_dbkey(NSSLOWKEYDBKey *dbkey)
  77. {
  78. if ( dbkey && dbkey->arena ) {
  79. PORT_FreeArena(dbkey->arena, PR_FALSE);
  80. }
  81. }
  82. static void
  83. free_dbt(DBT *dbt)
  84. {
  85. if ( dbt ) {
  86. PORT_Free(dbt->data);
  87. PORT_Free(dbt);
  88. }
  89. return;
  90. }
  91. static int keydb_Get(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
  92. unsigned int flags);
  93. static int keydb_Put(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
  94. unsigned int flags);
  95. static int keydb_Sync(NSSLOWKEYDBHandle *db, unsigned int flags);
  96. static int keydb_Del(NSSLOWKEYDBHandle *db, DBT *key, unsigned int flags);
  97. static int keydb_Seq(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
  98. unsigned int flags);
  99. static void keydb_Close(NSSLOWKEYDBHandle *db);
  100. /*
  101. * format of key database entries for version 3 of database:
  102. * byte offset field
  103. * ----------- -----
  104. * 0 version
  105. * 1 salt-len
  106. * 2 nn-len
  107. * 3.. salt-data
  108. * ... nickname
  109. * ... encrypted-key-data
  110. */
  111. static DBT *
  112. encode_dbkey(NSSLOWKEYDBKey *dbkey,unsigned char version)
  113. {
  114. DBT *bufitem = NULL;
  115. unsigned char *buf;
  116. int nnlen;
  117. char *nn;
  118. bufitem = (DBT *)PORT_ZAlloc(sizeof(DBT));
  119. if ( bufitem == NULL ) {
  120. goto loser;
  121. }
  122. if ( dbkey->nickname ) {
  123. nn = dbkey->nickname;
  124. nnlen = PORT_Strlen(nn) + 1;
  125. } else {
  126. nn = "";
  127. nnlen = 1;
  128. }
  129. /* compute the length of the record */
  130. /* 1 + 1 + 1 == version number header + salt length + nn len */
  131. bufitem->size = dbkey->salt.len + nnlen + dbkey->derPK.len + 1 + 1 + 1;
  132. bufitem->data = (void *)PORT_ZAlloc(bufitem->size);
  133. if ( bufitem->data == NULL ) {
  134. goto loser;
  135. }
  136. buf = (unsigned char *)bufitem->data;
  137. /* set version number */
  138. buf[0] = version;
  139. /* set length of salt */
  140. PORT_Assert(dbkey->salt.len < 256);
  141. buf[1] = dbkey->salt.len;
  142. /* set length of nickname */
  143. PORT_Assert(nnlen < 256);
  144. buf[2] = nnlen;
  145. /* copy salt */
  146. PORT_Memcpy(&buf[3], dbkey->salt.data, dbkey->salt.len);
  147. /* copy nickname */
  148. PORT_Memcpy(&buf[3 + dbkey->salt.len], nn, nnlen);
  149. /* copy encrypted key */
  150. PORT_Memcpy(&buf[3 + dbkey->salt.len + nnlen], dbkey->derPK.data,
  151. dbkey->derPK.len);
  152. return(bufitem);
  153. loser:
  154. if ( bufitem ) {
  155. free_dbt(bufitem);
  156. }
  157. return(NULL);
  158. }
  159. static NSSLOWKEYDBKey *
  160. decode_dbkey(DBT *bufitem, int expectedVersion)
  161. {
  162. NSSLOWKEYDBKey *dbkey;
  163. PLArenaPool *arena = NULL;
  164. unsigned char *buf;
  165. int version;
  166. int keyoff;
  167. int nnlen;
  168. int saltoff;
  169. buf = (unsigned char *)bufitem->data;
  170. version = buf[0];
  171. if ( version != expectedVersion ) {
  172. goto loser;
  173. }
  174. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  175. if ( arena == NULL ) {
  176. goto loser;
  177. }
  178. dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
  179. if ( dbkey == NULL ) {
  180. goto loser;
  181. }
  182. dbkey->arena = arena;
  183. dbkey->salt.data = NULL;
  184. dbkey->derPK.data = NULL;
  185. dbkey->salt.len = buf[1];
  186. dbkey->salt.data = (unsigned char *)PORT_ArenaZAlloc(arena, dbkey->salt.len);
  187. if ( dbkey->salt.data == NULL ) {
  188. goto loser;
  189. }
  190. saltoff = 2;
  191. keyoff = 2 + dbkey->salt.len;
  192. if ( expectedVersion >= 3 ) {
  193. nnlen = buf[2];
  194. if ( nnlen ) {
  195. dbkey->nickname = (char *)PORT_ArenaZAlloc(arena, nnlen + 1);
  196. if ( dbkey->nickname ) {
  197. PORT_Memcpy(dbkey->nickname, &buf[keyoff+1], nnlen);
  198. }
  199. }
  200. keyoff += ( nnlen + 1 );
  201. saltoff = 3;
  202. }
  203. PORT_Memcpy(dbkey->salt.data, &buf[saltoff], dbkey->salt.len);
  204. dbkey->derPK.len = bufitem->size - keyoff;
  205. dbkey->derPK.data = (unsigned char *)PORT_ArenaZAlloc(arena,dbkey->derPK.len);
  206. if ( dbkey->derPK.data == NULL ) {
  207. goto loser;
  208. }
  209. PORT_Memcpy(dbkey->derPK.data, &buf[keyoff], dbkey->derPK.len);
  210. return(dbkey);
  211. loser:
  212. if ( arena ) {
  213. PORT_FreeArena(arena, PR_FALSE);
  214. }
  215. return(NULL);
  216. }
  217. static NSSLOWKEYDBKey *
  218. get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index)
  219. {
  220. NSSLOWKEYDBKey *dbkey;
  221. DBT entry;
  222. int ret;
  223. /* get it from the database */
  224. ret = keydb_Get(handle, index, &entry, 0);
  225. if ( ret ) {
  226. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  227. return NULL;
  228. }
  229. /* set up dbkey struct */
  230. dbkey = decode_dbkey(&entry, handle->version);
  231. return(dbkey);
  232. }
  233. static SECStatus
  234. put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool update)
  235. {
  236. DBT *keydata = NULL;
  237. int status;
  238. keydata = encode_dbkey(dbkey, handle->version);
  239. if ( keydata == NULL ) {
  240. goto loser;
  241. }
  242. /* put it in the database */
  243. if ( update ) {
  244. status = keydb_Put(handle, index, keydata, 0);
  245. } else {
  246. status = keydb_Put(handle, index, keydata, R_NOOVERWRITE);
  247. }
  248. if ( status ) {
  249. goto loser;
  250. }
  251. /* sync the database */
  252. status = keydb_Sync(handle, 0);
  253. if ( status ) {
  254. goto loser;
  255. }
  256. free_dbt(keydata);
  257. return(SECSuccess);
  258. loser:
  259. if ( keydata ) {
  260. free_dbt(keydata);
  261. }
  262. return(SECFailure);
  263. }
  264. SECStatus
  265. nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
  266. SECStatus (* keyfunc)(DBT *k, DBT *d, void *pdata),
  267. void *udata )
  268. {
  269. DBT data;
  270. DBT key;
  271. SECStatus status;
  272. int ret;
  273. if (handle == NULL) {
  274. return(SECFailure);
  275. }
  276. ret = keydb_Seq(handle, &key, &data, R_FIRST);
  277. if ( ret ) {
  278. return(SECFailure);
  279. }
  280. do {
  281. /* skip version record */
  282. if ( data.size > 1 ) {
  283. if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) {
  284. if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) {
  285. continue;
  286. }
  287. }
  288. /* skip password check */
  289. if ( key.size == KEYDB_PW_CHECK_LEN ) {
  290. if ( PORT_Memcmp(key.data, KEYDB_PW_CHECK_STRING,
  291. KEYDB_PW_CHECK_LEN) == 0 ) {
  292. continue;
  293. }
  294. }
  295. status = (* keyfunc)(&key, &data, udata);
  296. if (status != SECSuccess) {
  297. return(status);
  298. }
  299. }
  300. } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 );
  301. return(SECSuccess);
  302. }
  303. #ifdef notdef
  304. typedef struct keyNode {
  305. struct keyNode *next;
  306. DBT key;
  307. } keyNode;
  308. typedef struct {
  309. PLArenaPool *arena;
  310. keyNode *head;
  311. } keyList;
  312. static SECStatus
  313. sec_add_key_to_list(DBT *key, DBT *data, void *arg)
  314. {
  315. keyList *keylist;
  316. keyNode *node;
  317. void *keydata;
  318. keylist = (keyList *)arg;
  319. /* allocate the node struct */
  320. node = (keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(keyNode));
  321. if ( node == NULL ) {
  322. return(SECFailure);
  323. }
  324. /* allocate room for key data */
  325. keydata = PORT_ArenaZAlloc(keylist->arena, key->size);
  326. if ( keydata == NULL ) {
  327. return(SECFailure);
  328. }
  329. /* link node into list */
  330. node->next = keylist->head;
  331. keylist->head = node;
  332. /* copy key into node */
  333. PORT_Memcpy(keydata, key->data, key->size);
  334. node->key.size = key->size;
  335. node->key.data = keydata;
  336. return(SECSuccess);
  337. }
  338. #endif
  339. static SECItem *
  340. decodeKeyDBGlobalSalt(DBT *saltData)
  341. {
  342. SECItem *saltitem;
  343. saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  344. if ( saltitem == NULL ) {
  345. return(NULL);
  346. }
  347. saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size);
  348. if ( saltitem->data == NULL ) {
  349. PORT_Free(saltitem);
  350. return(NULL);
  351. }
  352. saltitem->len = saltData->size;
  353. PORT_Memcpy(saltitem->data, saltData->data, saltitem->len);
  354. return(saltitem);
  355. }
  356. static SECItem *
  357. GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
  358. {
  359. DBT saltKey;
  360. DBT saltData;
  361. int ret;
  362. saltKey.data = SALT_STRING;
  363. saltKey.size = sizeof(SALT_STRING) - 1;
  364. ret = keydb_Get(handle, &saltKey, &saltData, 0);
  365. if ( ret ) {
  366. return(NULL);
  367. }
  368. return(decodeKeyDBGlobalSalt(&saltData));
  369. }
  370. static SECStatus
  371. StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle, SECItem *salt)
  372. {
  373. DBT saltKey;
  374. DBT saltData;
  375. int status;
  376. saltKey.data = SALT_STRING;
  377. saltKey.size = sizeof(SALT_STRING) - 1;
  378. saltData.data = (void *)salt->data;
  379. saltData.size = salt->len;
  380. /* put global salt into the database now */
  381. status = keydb_Put(handle, &saltKey, &saltData, 0);
  382. if ( status ) {
  383. return(SECFailure);
  384. }
  385. return(SECSuccess);
  386. }
  387. static SECStatus
  388. makeGlobalVersion(NSSLOWKEYDBHandle *handle)
  389. {
  390. unsigned char version;
  391. DBT versionData;
  392. DBT versionKey;
  393. int status;
  394. version = NSSLOWKEY_DB_FILE_VERSION;
  395. versionData.data = &version;
  396. versionData.size = 1;
  397. versionKey.data = VERSION_STRING;
  398. versionKey.size = sizeof(VERSION_STRING)-1;
  399. /* put version string into the database now */
  400. status = keydb_Put(handle, &versionKey, &versionData, 0);
  401. if ( status ) {
  402. return(SECFailure);
  403. }
  404. handle->version = version;
  405. return(SECSuccess);
  406. }
  407. static SECStatus
  408. makeGlobalSalt(NSSLOWKEYDBHandle *handle)
  409. {
  410. DBT saltKey;
  411. DBT saltData;
  412. unsigned char saltbuf[16];
  413. int status;
  414. saltKey.data = SALT_STRING;
  415. saltKey.size = sizeof(SALT_STRING) - 1;
  416. saltData.data = (void *)saltbuf;
  417. saltData.size = sizeof(saltbuf);
  418. RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf));
  419. /* put global salt into the database now */
  420. status = keydb_Put(handle, &saltKey, &saltData, 0);
  421. if ( status ) {
  422. return(SECFailure);
  423. }
  424. return(SECSuccess);
  425. }
  426. static SECStatus
  427. encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,
  428. SECItem *encCheck);
  429. static unsigned char
  430. nsslowkey_version(NSSLOWKEYDBHandle *handle)
  431. {
  432. DBT versionKey;
  433. DBT versionData;
  434. int ret;
  435. versionKey.data = VERSION_STRING;
  436. versionKey.size = sizeof(VERSION_STRING)-1;
  437. if (handle->db == NULL) {
  438. return 255;
  439. }
  440. /* lookup version string in database */
  441. ret = keydb_Get( handle, &versionKey, &versionData, 0 );
  442. /* error accessing the database */
  443. if ( ret < 0 ) {
  444. return 255;
  445. }
  446. if ( ret >= 1 ) {
  447. return 0;
  448. }
  449. return *( (unsigned char *)versionData.data);
  450. }
  451. static PRBool
  452. seckey_HasAServerKey(NSSLOWKEYDBHandle *handle)
  453. {
  454. DBT key;
  455. DBT data;
  456. int ret;
  457. PRBool found = PR_FALSE;
  458. ret = keydb_Seq(handle, &key, &data, R_FIRST);
  459. if ( ret ) {
  460. return PR_FALSE;
  461. }
  462. do {
  463. /* skip version record */
  464. if ( data.size > 1 ) {
  465. /* skip salt */
  466. if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) {
  467. if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) {
  468. continue;
  469. }
  470. }
  471. /* skip pw check entry */
  472. if ( key.size == KEYDB_PW_CHECK_LEN ) {
  473. if ( PORT_Memcmp(key.data, KEYDB_PW_CHECK_STRING,
  474. KEYDB_PW_CHECK_LEN) == 0 ) {
  475. continue;
  476. }
  477. }
  478. /* keys stored by nickname will have 0 as the last byte of the
  479. * db key. Other keys must be stored by modulus. We will not
  480. * update those because they are left over from a keygen that
  481. * never resulted in a cert.
  482. */
  483. if ( ((unsigned char *)key.data)[key.size-1] != 0 ) {
  484. continue;
  485. }
  486. if (PORT_Strcmp(key.data,"Server-Key") == 0) {
  487. found = PR_TRUE;
  488. break;
  489. }
  490. }
  491. } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 );
  492. return found;
  493. }
  494. /* forward declare local create function */
  495. static NSSLOWKEYDBHandle * nsslowkey_NewHandle(DB *dbHandle);
  496. /*
  497. * currently updates key database from v2 to v3
  498. */
  499. static SECStatus
  500. nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
  501. {
  502. SECStatus rv;
  503. DBT checkKey;
  504. DBT checkData;
  505. DBT saltKey;
  506. DBT saltData;
  507. DBT key;
  508. DBT data;
  509. unsigned char version;
  510. NSSLOWKEYDBKey *dbkey = NULL;
  511. NSSLOWKEYDBHandle *update = NULL;
  512. SECItem *oldSalt = NULL;
  513. int ret;
  514. SECItem checkitem;
  515. if ( handle->updatedb == NULL ) {
  516. return SECSuccess;
  517. }
  518. /* create a full DB Handle for our update so we
  519. * can use the correct locks for the db primatives */
  520. update = nsslowkey_NewHandle(handle->updatedb);
  521. if ( update == NULL) {
  522. return SECSuccess;
  523. }
  524. /* update has now inherited the database handle */
  525. handle->updatedb = NULL;
  526. /*
  527. * check the version record
  528. */
  529. version = nsslowkey_version(update);
  530. if (version != 2) {
  531. goto done;
  532. }
  533. saltKey.data = SALT_STRING;
  534. saltKey.size = sizeof(SALT_STRING) - 1;
  535. ret = keydb_Get(update, &saltKey, &saltData, 0);
  536. if ( ret ) {
  537. /* no salt in old db, so it is corrupted */
  538. goto done;
  539. }
  540. oldSalt = decodeKeyDBGlobalSalt(&saltData);
  541. if ( oldSalt == NULL ) {
  542. /* bad salt in old db, so it is corrupted */
  543. goto done;
  544. }
  545. /*
  546. * look for a pw check entry
  547. */
  548. checkKey.data = KEYDB_PW_CHECK_STRING;
  549. checkKey.size = KEYDB_PW_CHECK_LEN;
  550. ret = keydb_Get(update, &checkKey, &checkData, 0 );
  551. if (ret) {
  552. /*
  553. * if we have a key, but no KEYDB_PW_CHECK_STRING, then this must
  554. * be an old server database, and it does have a password associated
  555. * with it. Put a fake entry in so we can identify this db when we do
  556. * get the password for it.
  557. */
  558. if (seckey_HasAServerKey(update)) {
  559. DBT fcheckKey;
  560. DBT fcheckData;
  561. /*
  562. * include a fake string
  563. */
  564. fcheckKey.data = KEYDB_FAKE_PW_CHECK_STRING;
  565. fcheckKey.size = KEYDB_FAKE_PW_CHECK_LEN;
  566. fcheckData.data = "1";
  567. fcheckData.size = 1;
  568. /* put global salt into the new database now */
  569. ret = keydb_Put( handle, &saltKey, &saltData, 0);
  570. if ( ret ) {
  571. goto done;
  572. }
  573. ret = keydb_Put( handle, &fcheckKey, &fcheckData, 0);
  574. if ( ret ) {
  575. goto done;
  576. }
  577. } else {
  578. goto done;
  579. }
  580. } else {
  581. /* put global salt into the new database now */
  582. ret = keydb_Put( handle, &saltKey, &saltData, 0);
  583. if ( ret ) {
  584. goto done;
  585. }
  586. dbkey = decode_dbkey(&checkData, 2);
  587. if ( dbkey == NULL ) {
  588. goto done;
  589. }
  590. checkitem = dbkey->derPK;
  591. dbkey->derPK.data = NULL;
  592. /* format the new pw check entry */
  593. rv = encodePWCheckEntry(NULL, &dbkey->derPK, SEC_OID_RC4, &checkitem);
  594. if ( rv != SECSuccess ) {
  595. goto done;
  596. }
  597. rv = put_dbkey(handle, &checkKey, dbkey, PR_TRUE);
  598. if ( rv != SECSuccess ) {
  599. goto done;
  600. }
  601. /* free the dbkey */
  602. sec_destroy_dbkey(dbkey);
  603. dbkey = NULL;
  604. }
  605. /* now traverse the database */
  606. ret = keydb_Seq(update, &key, &data, R_FIRST);
  607. if ( ret ) {
  608. goto done;
  609. }
  610. do {
  611. /* skip version record */
  612. if ( data.size > 1 ) {
  613. /* skip salt */
  614. if ( key.size == ( sizeof(SALT_STRING) - 1 ) ) {
  615. if ( PORT_Memcmp(key.data, SALT_STRING, key.size) == 0 ) {
  616. continue;
  617. }
  618. }
  619. /* skip pw check entry */
  620. if ( key.size == checkKey.size ) {
  621. if ( PORT_Memcmp(key.data, checkKey.data, key.size) == 0 ) {
  622. continue;
  623. }
  624. }
  625. /* keys stored by nickname will have 0 as the last byte of the
  626. * db key. Other keys must be stored by modulus. We will not
  627. * update those because they are left over from a keygen that
  628. * never resulted in a cert.
  629. */
  630. if ( ((unsigned char *)key.data)[key.size-1] != 0 ) {
  631. continue;
  632. }
  633. dbkey = decode_dbkey(&data, 2);
  634. if ( dbkey == NULL ) {
  635. continue;
  636. }
  637. /* This puts the key into the new database with the same
  638. * index (nickname) that it had before. The second pass
  639. * of the update will have the password. It will decrypt
  640. * and re-encrypt the entries using a new algorithm.
  641. */
  642. dbkey->nickname = (char *)key.data;
  643. rv = put_dbkey(handle, &key, dbkey, PR_FALSE);
  644. dbkey->nickname = NULL;
  645. sec_destroy_dbkey(dbkey);
  646. }
  647. } while ( keydb_Seq(update, &key, &data, R_NEXT) == 0 );
  648. dbkey = NULL;
  649. done:
  650. /* sync the database */
  651. ret = keydb_Sync(handle, 0);
  652. nsslowkey_CloseKeyDB(update);
  653. if ( oldSalt ) {
  654. SECITEM_FreeItem(oldSalt, PR_TRUE);
  655. }
  656. if ( dbkey ) {
  657. sec_destroy_dbkey(dbkey);
  658. }
  659. return(SECSuccess);
  660. }
  661. static SECStatus
  662. openNewDB(const char *appName, const char *prefix, const char *dbname,
  663. NSSLOWKEYDBHandle *handle, NSSLOWKEYDBNameFunc namecb, void *cbarg)
  664. {
  665. SECStatus rv = SECFailure;
  666. int status = RDB_FAIL;
  667. char *updname = NULL;
  668. DB *updatedb = NULL;
  669. PRBool updated = PR_FALSE;
  670. int ret;
  671. if (appName) {
  672. handle->db = rdbopen( appName, prefix, "key", NO_CREATE, &status);
  673. } else {
  674. handle->db = dbopen( dbname, NO_CREATE, 0600, DB_HASH, 0 );
  675. }
  676. /* if create fails then we lose */
  677. if ( handle->db == NULL ) {
  678. return (status == RDB_RETRY) ? SECWouldBlock: SECFailure;
  679. }
  680. /* force a transactional read, which will verify that one and only one
  681. * process attempts the update. */
  682. if (nsslowkey_version(handle) == NSSLOWKEY_DB_FILE_VERSION) {
  683. /* someone else has already updated the database for us */
  684. db_InitComplete(handle->db);
  685. return SECSuccess;
  686. }
  687. /*
  688. * if we are creating a multiaccess database, see if there is a
  689. * local database we can update from.
  690. */
  691. if (appName) {
  692. NSSLOWKEYDBHandle *updateHandle;
  693. updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 );
  694. if (!updatedb) {
  695. goto noupdate;
  696. }
  697. /* nsslowkey_version needs a full handle because it calls
  698. * the kdb_Get() function, which needs to lock.
  699. */
  700. updateHandle = nsslowkey_NewHandle(updatedb);
  701. if (!updateHandle) {
  702. updatedb->close(updatedb);
  703. goto noupdate;
  704. }
  705. handle->version = nsslowkey_version(updateHandle);
  706. if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
  707. nsslowkey_CloseKeyDB(updateHandle);
  708. goto noupdate;
  709. }
  710. /* copy the new DB from the old one */
  711. db_Copy(handle->db, updatedb);
  712. nsslowkey_CloseKeyDB(updateHandle);
  713. db_InitComplete(handle->db);
  714. return SECSuccess;
  715. }
  716. noupdate:
  717. /* update the version number */
  718. rv = makeGlobalVersion(handle);
  719. if ( rv != SECSuccess ) {
  720. goto loser;
  721. }
  722. /*
  723. * try to update from v2 db
  724. */
  725. updname = (*namecb)(cbarg, 2);
  726. if ( updname != NULL ) {
  727. handle->updatedb = dbopen( updname, NO_RDONLY, 0600, DB_HASH, 0 );
  728. PORT_Free( updname );
  729. if ( handle->updatedb ) {
  730. /*
  731. * Try to update the db using a null password. If the db
  732. * doesn't have a password, then this will work. If it does
  733. * have a password, then this will fail and we will do the
  734. * update later
  735. */
  736. rv = nsslowkey_UpdateKeyDBPass1(handle);
  737. if ( rv == SECSuccess ) {
  738. updated = PR_TRUE;
  739. }
  740. }
  741. }
  742. /* we are using the old salt if we updated from an old db */
  743. if ( ! updated ) {
  744. rv = makeGlobalSalt(handle);
  745. if ( rv != SECSuccess ) {
  746. goto loser;
  747. }
  748. }
  749. /* sync the database */
  750. ret = keydb_Sync(handle, 0);
  751. if ( ret ) {
  752. rv = SECFailure;
  753. goto loser;
  754. }
  755. rv = SECSuccess;
  756. loser:
  757. db_InitComplete(handle->db);
  758. return rv;
  759. }
  760. static DB *
  761. openOldDB(const char *appName, const char *prefix, const char *dbname,
  762. PRBool openflags) {
  763. DB *db = NULL;
  764. if (appName) {
  765. db = rdbopen( appName, prefix, "key", openflags, NULL);
  766. } else {
  767. db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
  768. }
  769. return db;
  770. }
  771. /* check for correct version number */
  772. static PRBool
  773. verifyVersion(NSSLOWKEYDBHandle *handle)
  774. {
  775. int version = nsslowkey_version(handle);
  776. handle->version = version;
  777. if (version != NSSLOWKEY_DB_FILE_VERSION ) {
  778. if (handle->db) {
  779. keydb_Close(handle);
  780. handle->db = NULL;
  781. }
  782. }
  783. return handle->db != NULL;
  784. }
  785. static NSSLOWKEYDBHandle *
  786. nsslowkey_NewHandle(DB *dbHandle)
  787. {
  788. NSSLOWKEYDBHandle *handle;
  789. handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle));
  790. if (handle == NULL) {
  791. PORT_SetError (SEC_ERROR_NO_MEMORY);
  792. return NULL;
  793. }
  794. handle->appname = NULL;
  795. handle->dbname = NULL;
  796. handle->global_salt = NULL;
  797. handle->updatedb = NULL;
  798. handle->db = dbHandle;
  799. handle->ref = 1;
  800. handle->lock = PZ_NewLock(nssILockKeyDB);
  801. return handle;
  802. }
  803. NSSLOWKEYDBHandle *
  804. nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
  805. NSSLOWKEYDBNameFunc namecb, void *cbarg)
  806. {
  807. NSSLOWKEYDBHandle *handle = NULL;
  808. SECStatus rv;
  809. int openflags;
  810. char *dbname = NULL;
  811. handle = nsslowkey_NewHandle(NULL);
  812. openflags = readOnly ? NO_RDONLY : NO_RDWR;
  813. dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION);
  814. if ( dbname == NULL ) {
  815. goto loser;
  816. }
  817. handle->appname = appName ? PORT_Strdup(appName) : NULL ;
  818. handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) :
  819. (prefix ? PORT_Strdup(prefix) : NULL);
  820. handle->readOnly = readOnly;
  821. handle->db = openOldDB(appName, prefix, dbname, openflags);
  822. if (handle->db) {
  823. verifyVersion(handle);
  824. if (handle->version == 255) {
  825. goto loser;
  826. }
  827. }
  828. /* if first open fails, try to create a new DB */
  829. if ( handle->db == NULL ) {
  830. if ( readOnly ) {
  831. goto loser;
  832. }
  833. rv = openNewDB(appName, prefix, dbname, handle, namecb, cbarg);
  834. /* two processes started to initialize the database at the same time.
  835. * The multiprocess code blocked the second one, then had it retry to
  836. * see if it can just open the database normally */
  837. if (rv == SECWouldBlock) {
  838. handle->db = openOldDB(appName,prefix,dbname, openflags);
  839. verifyVersion(handle);
  840. if (handle->db == NULL) {
  841. goto loser;
  842. }
  843. } else if (rv != SECSuccess) {
  844. goto loser;
  845. }
  846. }
  847. handle->global_salt = GetKeyDBGlobalSalt(handle);
  848. if ( dbname )
  849. PORT_Free( dbname );
  850. return handle;
  851. loser:
  852. if ( dbname )
  853. PORT_Free( dbname );
  854. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  855. nsslowkey_CloseKeyDB(handle);
  856. return NULL;
  857. }
  858. /*
  859. * Close the database
  860. */
  861. void
  862. nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle)
  863. {
  864. if (handle != NULL) {
  865. if (handle->db != NULL) {
  866. keydb_Close(handle);
  867. }
  868. if (handle->updatedb) {
  869. handle->updatedb->close(handle->updatedb);
  870. }
  871. if (handle->dbname) PORT_Free(handle->dbname);
  872. if (handle->appname) PORT_Free(handle->appname);
  873. if (handle->global_salt) {
  874. SECITEM_FreeItem(handle->global_salt,PR_TRUE);
  875. }
  876. if (handle->lock != NULL) {
  877. SKIP_AFTER_FORK(PZ_DestroyLock(handle->lock));
  878. }
  879. PORT_Free(handle);
  880. }
  881. }
  882. /* Get the key database version */
  883. int
  884. nsslowkey_GetKeyDBVersion(NSSLOWKEYDBHandle *handle)
  885. {
  886. PORT_Assert(handle != NULL);
  887. return handle->version;
  888. }
  889. /*
  890. * Delete a private key that was stored in the database
  891. */
  892. SECStatus
  893. nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, const SECItem *pubkey)
  894. {
  895. DBT namekey;
  896. int ret;
  897. if (handle == NULL) {
  898. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  899. return(SECFailure);
  900. }
  901. /* set up db key and data */
  902. namekey.data = pubkey->data;
  903. namekey.size = pubkey->len;
  904. /* delete it from the database */
  905. ret = keydb_Del(handle, &namekey, 0);
  906. if ( ret ) {
  907. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  908. return(SECFailure);
  909. }
  910. /* sync the database */
  911. ret = keydb_Sync(handle, 0);
  912. if ( ret ) {
  913. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  914. return(SECFailure);
  915. }
  916. return(SECSuccess);
  917. }
  918. /*
  919. * Store a key in the database, indexed by its public key modulus.(value!)
  920. */
  921. SECStatus
  922. nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle,
  923. NSSLOWKEYPrivateKey *privkey,
  924. SECItem *pubKeyData,
  925. char *nickname,
  926. SDB *sdb)
  927. {
  928. return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData,
  929. nickname, sdb, PR_FALSE);
  930. }
  931. SECStatus
  932. nsslowkey_UpdateNickname(NSSLOWKEYDBHandle *handle,
  933. NSSLOWKEYPrivateKey *privkey,
  934. SECItem *pubKeyData,
  935. char *nickname,
  936. SDB *sdb)
  937. {
  938. return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData,
  939. nickname, sdb, PR_TRUE);
  940. }
  941. /* see if the symetric CKA_ID already Exists.
  942. */
  943. PRBool
  944. nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id)
  945. {
  946. DBT namekey;
  947. DBT dummy;
  948. int status;
  949. namekey.data = (char *)id->data;
  950. namekey.size = id->len;
  951. status = keydb_Get(handle, &namekey, &dummy, 0);
  952. if ( status ) {
  953. return PR_FALSE;
  954. }
  955. return PR_TRUE;
  956. }
  957. /* see if the public key for this cert is in the database filed
  958. * by modulus
  959. */
  960. PRBool
  961. nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert)
  962. {
  963. NSSLOWKEYPublicKey *pubkey = NULL;
  964. DBT namekey;
  965. DBT dummy;
  966. int status;
  967. /* get cert's public key */
  968. pubkey = nsslowcert_ExtractPublicKey(cert);
  969. if ( pubkey == NULL ) {
  970. return PR_FALSE;
  971. }
  972. /* TNH - make key from NSSLOWKEYPublicKey */
  973. switch (pubkey->keyType) {
  974. case NSSLOWKEYRSAKey:
  975. namekey.data = pubkey->u.rsa.modulus.data;
  976. namekey.size = pubkey->u.rsa.modulus.len;
  977. break;
  978. case NSSLOWKEYDSAKey:
  979. namekey.data = pubkey->u.dsa.publicValue.data;
  980. namekey.size = pubkey->u.dsa.publicValue.len;
  981. break;
  982. case NSSLOWKEYDHKey:
  983. namekey.data = pubkey->u.dh.publicValue.data;
  984. namekey.size = pubkey->u.dh.publicValue.len;
  985. break;
  986. #ifdef NSS_ENABLE_ECC
  987. case NSSLOWKEYECKey:
  988. namekey.data = pubkey->u.ec.publicValue.data;
  989. namekey.size = pubkey->u.ec.publicValue.len;
  990. break;
  991. #endif /* NSS_ENABLE_ECC */
  992. default:
  993. /* XXX We don't do Fortezza or DH yet. */
  994. return PR_FALSE;
  995. }
  996. if (handle->version != 3) {
  997. unsigned char buf[SHA1_LENGTH];
  998. SHA1_HashBuf(buf,namekey.data,namekey.size);
  999. /* NOTE: don't use pubkey after this! it's now thrashed */
  1000. PORT_Memcpy(namekey.data,buf,sizeof(buf));
  1001. namekey.size = sizeof(buf);
  1002. }
  1003. status = keydb_Get(handle, &namekey, &dummy, 0);
  1004. /* some databases have the key stored as a signed value */
  1005. if (status) {
  1006. unsigned char *buf = (unsigned char *)PORT_Alloc(namekey.size+1);
  1007. if (buf) {
  1008. PORT_Memcpy(&buf[1], namekey.data, namekey.size);
  1009. buf[0] = 0;
  1010. namekey.data = buf;
  1011. namekey.size ++;
  1012. status = keydb_Get(handle, &namekey, &dummy, 0);
  1013. PORT_Free(buf);
  1014. }
  1015. }
  1016. lg_nsslowkey_DestroyPublicKey(pubkey);
  1017. if ( status ) {
  1018. return PR_FALSE;
  1019. }
  1020. return PR_TRUE;
  1021. }
  1022. typedef struct NSSLowPasswordDataParamStr {
  1023. SECItem salt;
  1024. SECItem iter;
  1025. } NSSLowPasswordDataParam;
  1026. static const SEC_ASN1Template NSSLOWPasswordParamTemplate[] =
  1027. {
  1028. {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLowPasswordDataParam) },
  1029. {SEC_ASN1_OCTET_STRING, offsetof(NSSLowPasswordDataParam, salt) },
  1030. {SEC_ASN1_INTEGER, offsetof(NSSLowPasswordDataParam, iter) },
  1031. {0}
  1032. };
  1033. struct LGEncryptedDataInfoStr {
  1034. SECAlgorithmID algorithm;
  1035. SECItem encryptedData;
  1036. };
  1037. typedef struct LGEncryptedDataInfoStr LGEncryptedDataInfo;
  1038. const SEC_ASN1Template lg_EncryptedDataInfoTemplate[] = {
  1039. { SEC_ASN1_SEQUENCE,
  1040. 0, NULL, sizeof(LGEncryptedDataInfo) },
  1041. { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
  1042. offsetof(LGEncryptedDataInfo,algorithm),
  1043. SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
  1044. { SEC_ASN1_OCTET_STRING,
  1045. offsetof(LGEncryptedDataInfo,encryptedData) },
  1046. { 0 }
  1047. };
  1048. static SECItem *
  1049. nsslowkey_EncodePW(SECOidTag alg, const SECItem *salt, SECItem *data)
  1050. {
  1051. NSSLowPasswordDataParam param;
  1052. LGEncryptedDataInfo edi;
  1053. PLArenaPool *arena;
  1054. unsigned char one = 1;
  1055. SECItem *epw = NULL;
  1056. SECItem *encParam;
  1057. SECStatus rv;
  1058. param.salt = *salt;
  1059. param.iter.type = siBuffer; /* encode as signed integer */
  1060. param.iter.data = &one;
  1061. param.iter.len = 1;
  1062. edi.encryptedData = *data;
  1063. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1064. if (arena == NULL) {
  1065. return NULL;
  1066. }
  1067. encParam = SEC_ASN1EncodeItem(arena, NULL, &param,
  1068. NSSLOWPasswordParamTemplate);
  1069. if (encParam == NULL) {
  1070. goto loser;
  1071. }
  1072. rv = SECOID_SetAlgorithmID(arena, &edi.algorithm, alg, encParam);
  1073. if (rv != SECSuccess) {
  1074. goto loser;
  1075. }
  1076. epw = SEC_ASN1EncodeItem(NULL, NULL, &edi, lg_EncryptedDataInfoTemplate);
  1077. loser:
  1078. PORT_FreeArena(arena, PR_FALSE);
  1079. return epw;
  1080. }
  1081. static SECItem *
  1082. nsslowkey_DecodePW(const SECItem *derData, SECOidTag *alg, SECItem *salt)
  1083. {
  1084. NSSLowPasswordDataParam param;
  1085. LGEncryptedDataInfo edi;
  1086. PLArenaPool *arena;
  1087. SECItem *pwe = NULL;
  1088. SECStatus rv;
  1089. salt->data = NULL;
  1090. param.iter.type = siBuffer; /* decode as signed integer */
  1091. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1092. if (arena == NULL) {
  1093. return NULL;
  1094. }
  1095. rv = SEC_QuickDERDecodeItem(arena, &edi, lg_EncryptedDataInfoTemplate,
  1096. derData);
  1097. if (rv != SECSuccess) {
  1098. goto loser;
  1099. }
  1100. *alg = SECOID_GetAlgorithmTag(&edi.algorithm);
  1101. rv = SEC_QuickDERDecodeItem(arena, &param, NSSLOWPasswordParamTemplate,
  1102. &edi.algorithm.parameters);
  1103. if (rv != SECSuccess) {
  1104. goto loser;
  1105. }
  1106. rv = SECITEM_CopyItem(NULL, salt, &param.salt);
  1107. if (rv != SECSuccess) {
  1108. goto loser;
  1109. }
  1110. pwe = SECITEM_DupItem(&edi.encryptedData);
  1111. loser:
  1112. if (!pwe && salt->data) {
  1113. PORT_Free(salt->data);
  1114. salt->data = NULL;
  1115. }
  1116. PORT_FreeArena(arena, PR_FALSE);
  1117. return pwe;
  1118. }
  1119. /*
  1120. * check to see if the user has a password
  1121. */
  1122. static SECStatus
  1123. nsslowkey_GetPWCheckEntry(NSSLOWKEYDBHandle *handle,NSSLOWKEYPasswordEntry *entry)
  1124. {
  1125. DBT checkkey; /*, checkdata; */
  1126. NSSLOWKEYDBKey *dbkey = NULL;
  1127. SECItem *global_salt = NULL;
  1128. SECItem *item = NULL;
  1129. SECItem entryData, oid;
  1130. SECItem none = { siBuffer, NULL, 0 };
  1131. SECStatus rv = SECFailure;
  1132. SECOidTag algorithm;
  1133. if (handle == NULL) {
  1134. /* PORT_SetError */
  1135. return(SECFailure);
  1136. }
  1137. global_salt = GetKeyDBGlobalSalt(handle);
  1138. if (!global_salt) {
  1139. global_salt = &none;
  1140. }
  1141. if (global_salt->len > sizeof(entry->data)) {
  1142. /* PORT_SetError */
  1143. goto loser;
  1144. }
  1145. PORT_Memcpy(entry->data, global_salt->data, global_salt->len);
  1146. entry->salt.data = entry->data;
  1147. entry->salt.len = global_salt->len;
  1148. entry->value.data = &entry->data[entry->salt.len];
  1149. checkkey.data = KEYDB_PW_CHECK_STRING;
  1150. checkkey.size = KEYDB_PW_CHECK_LEN;
  1151. dbkey = get_dbkey(handle, &checkkey);
  1152. if (dbkey == NULL) {
  1153. /* handle 'FAKE' check here */
  1154. goto loser;
  1155. }
  1156. oid.len = dbkey->derPK.data[0];
  1157. oid.data = &dbkey->derPK.data[1];
  1158. if (dbkey->derPK.len < (KEYDB_PW_CHECK_LEN + 1 +oid.len)) {
  1159. goto loser;
  1160. }
  1161. algorithm = SECOID_FindOIDTag(&oid);
  1162. entryData.type = siBuffer;
  1163. entryData.len = dbkey->derPK.len - (oid.len+1);
  1164. entryData.data = &dbkey->derPK.data[oid.len+1];
  1165. item = nsslowkey_EncodePW(algorithm, &dbkey->salt, &entryData);
  1166. if (!item || (item->len + entry->salt.len) > sizeof(entry->data)) {
  1167. goto loser;
  1168. }
  1169. PORT_Memcpy(entry->value.data, item->data, item->len);
  1170. entry->value.len = item->len;
  1171. rv = SECSuccess;
  1172. loser:
  1173. if (item) {
  1174. SECITEM_FreeItem(item, PR_TRUE);
  1175. }
  1176. if (dbkey) {
  1177. sec_destroy_dbkey(dbkey);
  1178. }
  1179. if (global_salt != &none) {
  1180. SECITEM_FreeItem(global_salt,PR_TRUE);
  1181. }
  1182. return rv;
  1183. }
  1184. /*
  1185. * check to see if the user has a password
  1186. */
  1187. static SECStatus
  1188. nsslowkey_PutPWCheckEntry(NSSLOWKEYDBHandle *handle,NSSLOWKEYPasswordEntry *entry)
  1189. {
  1190. DBT checkkey;
  1191. NSSLOWKEYDBKey *dbkey = NULL;
  1192. SECItem *item = NULL;
  1193. SECItem salt;
  1194. SECOidTag algid;
  1195. SECStatus rv = SECFailure;
  1196. PLArenaPool *arena;
  1197. int ret;
  1198. if (handle == NULL) {
  1199. /* PORT_SetError */
  1200. return(SECFailure);
  1201. }
  1202. checkkey.data = KEYDB_PW_CHECK_STRING;
  1203. checkkey.size = KEYDB_PW_CHECK_LEN;
  1204. salt.data = NULL;
  1205. arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1206. if (arena == NULL) {
  1207. return SECFailure;
  1208. }
  1209. item = nsslowkey_DecodePW(&entry->value, &algid, &salt);
  1210. if (item == NULL) {
  1211. goto loser;
  1212. }
  1213. dbkey = PORT_ArenaZNew(arena, NSSLOWKEYDBKey);
  1214. if (dbkey == NULL) {
  1215. goto loser;
  1216. }
  1217. dbkey->arena = arena;
  1218. rv = SECITEM_CopyItem(arena, &dbkey->salt, &salt);
  1219. if (rv != SECSuccess) {
  1220. goto loser;
  1221. }
  1222. rv = encodePWCheckEntry(arena, &dbkey->derPK, algid, item);
  1223. if (rv != SECSuccess) {
  1224. goto loser;
  1225. }
  1226. rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE);
  1227. if (rv != SECSuccess) {
  1228. goto loser;
  1229. }
  1230. if (handle->global_salt) {
  1231. SECITEM_FreeItem(handle->global_salt, PR_TRUE);
  1232. handle->global_salt = NULL;
  1233. }
  1234. rv = StoreKeyDBGlobalSalt(handle, &entry->salt);
  1235. if (rv != SECSuccess) {
  1236. goto loser;
  1237. }
  1238. ret = keydb_Sync(handle, 0);
  1239. if ( ret ) {
  1240. rv = SECFailure;
  1241. goto loser;
  1242. }
  1243. handle->global_salt = GetKeyDBGlobalSalt(handle);
  1244. loser:
  1245. if (item) {
  1246. SECITEM_FreeItem(item, PR_TRUE);
  1247. }
  1248. if (arena) {
  1249. PORT_FreeArena(arena, PR_TRUE);
  1250. }
  1251. if (salt.data) {
  1252. PORT_Free(salt.data);
  1253. }
  1254. return rv;
  1255. }
  1256. #ifdef EC_DEBUG
  1257. #define SEC_PRINT(str1, str2, num, sitem) \
  1258. printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
  1259. str1, str2, num, sitem->len); \
  1260. for (i = 0; i < sitem->len; i++) { \
  1261. printf("%02x:", sitem->data[i]); \
  1262. } \
  1263. printf("\n")
  1264. #else
  1265. #define SEC_PRINT(a, b, c, d)
  1266. #endif /* EC_DEBUG */
  1267. SECStatus
  1268. seckey_encrypt_private_key( PLArenaPool *permarena, NSSLOWKEYPrivateKey *pk,
  1269. SDB *sdbpw, SECItem *result)
  1270. {
  1271. NSSLOWKEYPrivateKeyInfo *pki = NULL;
  1272. SECStatus rv = SECFailure;
  1273. PLArenaPool *temparena = NULL;
  1274. SECItem *der_item = NULL;
  1275. SECItem *cipherText = NULL;
  1276. SECItem *dummy = NULL;
  1277. #ifdef NSS_ENABLE_ECC
  1278. SECItem *fordebug = NULL;
  1279. int savelen;
  1280. #endif
  1281. temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  1282. if(temparena == NULL)
  1283. goto loser;
  1284. /* allocate structures */
  1285. pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
  1286. sizeof(NSSLOWKEYPrivateKeyInfo));
  1287. der_item = (SECItem *)PORT_ArenaZAlloc(temparena, sizeof(SECItem));
  1288. if((pki == NULL) || (der_item == NULL))
  1289. goto loser;
  1290. /* setup private key info */
  1291. dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version),
  1292. NSSLOWKEY_PRIVATE_KEY_INFO_VERSION);
  1293. if(dummy == NULL)
  1294. goto loser;
  1295. /* Encode the key, and set the algorithm (with params) */
  1296. switch (pk->keyType) {
  1297. case NSSLOWKEYRSAKey:
  1298. lg_prepare_low_rsa_priv_key_for_asn1(pk);
  1299. dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
  1300. lg_nsslowkey_RSAPrivateKeyTemplate);
  1301. if (dummy == NULL) {
  1302. rv = SECFailure;
  1303. goto loser;
  1304. }
  1305. rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),
  1306. SEC_OID_PKCS1_RSA_ENCRYPTION, 0);
  1307. if (rv == SECFailure) {
  1308. goto loser;
  1309. }
  1310. break;
  1311. case NSSLOWKEYDSAKey:
  1312. lg_prepare_low_dsa_priv_key_for_asn1(pk);
  1313. dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
  1314. lg_nsslowkey_DSAPrivateKeyTemplate);
  1315. if (dummy == NULL) {
  1316. rv = SECFailure;
  1317. goto loser;
  1318. }
  1319. lg_prepare_low_pqg_params_for_asn1(&pk->u.dsa.params);
  1320. dummy = SEC_ASN1EncodeItem(temparena, NULL, &pk->u.dsa.params,
  1321. lg_nsslowkey_PQGParamsTemplate);
  1322. if (dummy == NULL) {
  1323. rv = SECFailure;
  1324. goto loser;
  1325. }
  1326. rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),
  1327. SEC_OID_ANSIX9_DSA_SIGNATURE, dummy);
  1328. if (rv == SECFailure) {
  1329. goto loser;
  1330. }
  1331. break;
  1332. case NSSLOWKEYDHKey:
  1333. lg_prepare_low_dh_priv_key_for_asn1(pk);
  1334. dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
  1335. lg_nsslowkey_DHPrivateKeyTemplate);
  1336. if (dummy == NULL) {
  1337. rv = SECFailure;
  1338. goto loser;
  1339. }
  1340. rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),
  1341. SEC_OID_X942_DIFFIE_HELMAN_KEY, dummy);
  1342. if (rv == SECFailure) {
  1343. goto loser;
  1344. }
  1345. break;
  1346. #ifdef NSS_ENABLE_ECC
  1347. case NSSLOWKEYECKey:
  1348. lg_prepare_low_ec_priv_key_for_asn1(pk);
  1349. /* Public value is encoded as a bit string so adjust length
  1350. * to be in bits before ASN encoding and readjust
  1351. * immediately after.
  1352. *
  1353. * Since the SECG specification recommends not including the
  1354. * parameters as part of ECPrivateKey, we zero out the curveOID
  1355. * length before encoding and restore it later.
  1356. */
  1357. pk->u.ec.publicValue.len <<= 3;
  1358. savelen = pk->u.ec.ecParams.curveOID.len;
  1359. pk->u.ec.ecParams.curveOID.len = 0;
  1360. dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk,
  1361. lg_nsslowkey_ECPrivateKeyTemplate);
  1362. pk->u.ec.ecParams.curveOID.len = savelen;
  1363. pk->u.ec.publicValue.len >>= 3;
  1364. if (dummy == NULL) {
  1365. rv = SECFailure;
  1366. goto loser;
  1367. }
  1368. dummy = &pk->u.ec.ecParams.DEREncoding;
  1369. /* At this point dummy should contain the encoded params */
  1370. rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm),
  1371. SEC_OID_ANSIX962_EC_PUBLIC_KEY, dummy);
  1372. if (rv == SECFailure) {
  1373. goto loser;
  1374. }
  1375. fordebug = &(pki->privateKey);
  1376. SEC_PRINT("seckey_encrypt_private_key()", "PrivateKey",
  1377. pk->keyType, fordebug);
  1378. break;
  1379. #endif /* NSS_ENABLE_ECC */
  1380. default:
  1381. /* We don't support DH or Fortezza private keys yet */
  1382. PORT_Assert(PR_FALSE);
  1383. break;
  1384. }
  1385. /* setup encrypted private key info */
  1386. dummy = SEC_ASN1EncodeItem(temparena, der_item, pki,
  1387. lg_nsslowkey_PrivateKeyInfoTemplate);
  1388. SEC_PRINT("seckey_encrypt_private_key()", "PrivateKeyInfo",
  1389. pk->keyType, der_item);
  1390. if(dummy == NULL) {
  1391. rv = SECFailure;
  1392. goto loser;
  1393. }
  1394. rv = lg_util_encrypt(temparena, sdbpw, dummy, &cipherText);
  1395. if (rv != SECSuccess) {
  1396. goto loser;
  1397. }
  1398. rv = SECITEM_CopyItem ( permarena, result, cipherText);
  1399. loser:
  1400. if(temparena != NULL)
  1401. PORT_FreeArena(temparena, PR_TRUE);
  1402. return rv;
  1403. }
  1404. static SECStatus
  1405. seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SDB *sdbpw,
  1406. NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update)
  1407. {
  1408. NSSLOWKEYDBKey *dbkey = NULL;
  1409. PLArenaPool *arena = NULL;
  1410. SECStatus rv = SECFailure;
  1411. if((keydb == NULL) || (index == NULL) || (sdbpw == NULL) ||
  1412. (pk == NULL))
  1413. return SECFailure;
  1414. arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  1415. if(arena == NULL)
  1416. return SECFailure;
  1417. dbkey = (NSSLOWKEYDBKey *)PORT_ArenaZAlloc(arena, sizeof(NSSLOWKEYDBKey));
  1418. if(dbkey == NULL)
  1419. goto loser;
  1420. dbkey->arena = arena;
  1421. dbkey->nickname = nickname;
  1422. rv = seckey_encrypt_private_key(arena, pk, sdbpw, &dbkey->derPK);
  1423. if(rv != SECSuccess)
  1424. goto loser;
  1425. rv = put_dbkey(keydb, index, dbkey, update);
  1426. /* let success fall through */
  1427. loser:
  1428. if(arena != NULL)
  1429. PORT_FreeArena(arena, PR_TRUE);
  1430. return rv;
  1431. }
  1432. /*
  1433. * Store a key in the database, indexed by its public key modulus.
  1434. * Note that the nickname is optional. It was only used by keyutil.
  1435. */
  1436. SECStatus
  1437. nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle,
  1438. NSSLOWKEYPrivateKey *privkey,
  1439. SECItem *pubKeyData,
  1440. char *nickname,
  1441. SDB *sdbpw,
  1442. PRBool update)
  1443. {
  1444. DBT namekey;
  1445. SECStatus rv;
  1446. if (handle == NULL) {
  1447. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  1448. return(SECFailure);
  1449. }
  1450. /* set up db key and data */
  1451. namekey.data = pubKeyData->data;
  1452. namekey.size = pubKeyData->len;
  1453. /* encrypt the private key */
  1454. rv = seckey_put_private_key(handle, &namekey, sdbpw, privkey, nickname,
  1455. update);
  1456. return(rv);
  1457. }
  1458. static NSSLOWKEYPrivateKey *
  1459. seckey_decrypt_private_key(SECItem*epki,
  1460. SDB *sdbpw)
  1461. {
  1462. NSSLOWKEYPrivateKey *pk = NULL;
  1463. NSSLOWKEYPrivateKeyInfo *pki = NULL;
  1464. SECStatus rv = SECFailure;
  1465. PLArenaPool *temparena = NULL, *permarena = NULL;
  1466. SECItem *dest = NULL;
  1467. #ifdef NSS_ENABLE_ECC
  1468. SECItem *fordebug = NULL;
  1469. #endif
  1470. if((epki == NULL) || (sdbpw == NULL))
  1471. goto loser;
  1472. temparena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  1473. permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  1474. if((temparena == NULL) || (permarena == NULL))
  1475. goto loser;
  1476. /* allocate temporary items */
  1477. pki = (NSSLOWKEYPrivateKeyInfo *)PORT_ArenaZAlloc(temparena,
  1478. sizeof(NSSLOWKEYPrivateKeyInfo));
  1479. /* allocate permanent arena items */
  1480. pk = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(permarena,
  1481. sizeof(NSSLOWKEYPrivateKey));
  1482. if((pk == NULL) || (pki == NULL))
  1483. goto loser;
  1484. pk->arena = permarena;
  1485. rv = lg_util_decrypt(sdbpw, epki, &dest);
  1486. if (rv != SECSuccess) {
  1487. goto loser;
  1488. }
  1489. if(dest != NULL)
  1490. {
  1491. SECItem newPrivateKey;
  1492. SECItem newAlgParms;
  1493. SEC_PRINT("seckey_decrypt_private_key()", "PrivateKeyInfo", -1,
  1494. dest);
  1495. rv = SEC_QuickDERDecodeItem(temparena, pki,
  1496. lg_nsslowkey_PrivateKeyInfoTemplate, dest);
  1497. if(rv == SECSuccess)
  1498. {
  1499. switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
  1500. case SEC_OID_X500_RSA_ENCRYPTION:
  1501. case SEC_OID_PKCS1_RSA_ENCRYPTION:
  1502. pk->keyType = NSSLOWKEYRSAKey;
  1503. lg_prepare_low_rsa_priv_key_for_asn1(pk);
  1504. if (SECSuccess != SECITEM_CopyItem(permarena, &newPrivateKey,
  1505. &pki->privateKey) ) break;
  1506. rv = SEC_QuickDERDecodeItem(permarena, pk,
  1507. lg_nsslowkey_RSAPrivateKeyTemplate,
  1508. &newPrivateKey);
  1509. break;
  1510. case SEC_OID_ANSIX9_DSA_SIGNATURE:
  1511. pk->keyType = NSSLOWKEYDSAKey;
  1512. lg_prepare_low_dsa_priv_key_for_asn1(pk);
  1513. if (SECSuccess != SECITEM_CopyItem(permarena, &newPrivateKey,
  1514. &pki->privateKey) ) break;
  1515. rv = SEC_QuickDERDecodeItem(permarena, pk,
  1516. lg_nsslowkey_DSAPrivateKeyTemplate,
  1517. &newPrivateKey);
  1518. if (rv != SECSuccess)
  1519. goto loser;
  1520. lg_prepare_low_pqg_params_for_asn1(&pk->u.dsa.params);
  1521. if (SECSuccess != SECITEM_CopyItem(permarena, &newAlgParms,
  1522. &pki->algorithm.parameters) ) break;
  1523. rv = SEC_QuickDERDecodeItem(permarena, &pk->u.dsa.params,
  1524. lg_nsslowkey_PQGParamsTemplate,
  1525. &newAlgParms);
  1526. break;
  1527. case SEC_OID_X942_DIFFIE_HELMAN_KEY:
  1528. pk->keyType = NSSLOWKEYDHKey;
  1529. lg_prepare_low_dh_priv_key_for_asn1(pk);
  1530. if (SECSuccess != SECITEM_CopyItem(permarena, &newPrivateKey,
  1531. &pki->privateKey) ) break;
  1532. rv = SEC_QuickDERDecodeItem(permarena, pk,
  1533. lg_nsslowkey_DHPrivateKeyTemplate,
  1534. &newPrivateKey);
  1535. break;
  1536. #ifdef NSS_ENABLE_ECC
  1537. case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
  1538. pk->keyType = NSSLOWKEYECKey;
  1539. lg_prepare_low_ec_priv_key_for_asn1(pk);
  1540. fordebug = &pki->privateKey;
  1541. SEC_PRINT("seckey_decrypt_private_key()", "PrivateKey",
  1542. pk->keyType, fordebug);
  1543. if (SECSuccess != SECITEM_CopyItem(permarena, &newPrivateKey,
  1544. &pki->privateKey) ) break;
  1545. rv = SEC_QuickDERDecodeItem(permarena, pk,
  1546. lg_nsslowkey_ECPrivateKeyTemplate,
  1547. &newPrivateKey);
  1548. if (rv != SECSuccess)
  1549. goto loser;
  1550. lg_prepare_low_ecparams_for_asn1(&pk->u.ec.ecParams);
  1551. rv = SECITEM_CopyItem(permarena,
  1552. &pk->u.ec.ecParams.DEREncoding,
  1553. &pki->algorithm.parameters);
  1554. if (rv != SECSuccess)
  1555. goto loser;
  1556. /* Fill out the rest of EC params */
  1557. rv = LGEC_FillParams(permarena, &pk->u.ec.ecParams.DEREncoding,
  1558. &pk->u.ec.ecParams);
  1559. if (rv != SECSuccess)
  1560. goto loser;
  1561. if (pk->u.ec.publicValue.len != 0) {
  1562. pk->u.ec.publicValue.len >>= 3;
  1563. }
  1564. break;
  1565. #endif /* NSS_ENABLE_ECC */
  1566. default:
  1567. rv = SECFailure;
  1568. break;
  1569. }
  1570. }
  1571. else if(PORT_GetError() == SEC_ERROR_BAD_DER)
  1572. {
  1573. PORT_SetError(SEC_ERROR_BAD_PASSWORD);
  1574. goto loser;
  1575. }
  1576. }
  1577. /* let success fall through */
  1578. loser:
  1579. if(temparena != NULL)
  1580. PORT_FreeArena(temparena, PR_TRUE);
  1581. if(dest != NULL)
  1582. SECITEM_ZfreeItem(dest, PR_TRUE);
  1583. if(rv != SECSuccess)
  1584. {
  1585. if(permarena != NULL)
  1586. PORT_FreeArena(permarena, PR_TRUE);
  1587. pk = NULL;
  1588. }
  1589. return pk;
  1590. }
  1591. static NSSLOWKEYPrivateKey *
  1592. seckey_decode_encrypted_private_key(NSSLOWKEYDBKey *dbkey, SDB *sdbpw)
  1593. {
  1594. if( ( dbkey == NULL ) || ( sdbpw == NULL ) ) {
  1595. return NULL;
  1596. }
  1597. return seckey_decrypt_private_key(&(dbkey->derPK), sdbpw);
  1598. }
  1599. static NSSLOWKEYPrivateKey *
  1600. seckey_get_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, char **nickname,
  1601. SDB *sdbpw)
  1602. {
  1603. NSSLOWKEYDBKey *dbkey = NULL;
  1604. NSSLOWKEYPrivateKey *pk = NULL;
  1605. if( ( keydb == NULL ) || ( index == NULL ) || ( sdbpw == NULL ) ) {
  1606. return NULL;
  1607. }
  1608. dbkey = get_dbkey(keydb, index);
  1609. if(dbkey == NULL) {
  1610. goto loser;
  1611. }
  1612. if ( nickname ) {
  1613. if ( dbkey->nickname && ( dbkey->nickname[0] != 0 ) ) {
  1614. *nickname = PORT_Strdup(dbkey->nickname);
  1615. } else {
  1616. *nickname = NULL;
  1617. }
  1618. }
  1619. pk = seckey_decode_encrypted_private_key(dbkey, sdbpw);
  1620. /* let success fall through */
  1621. loser:
  1622. if ( dbkey != NULL ) {
  1623. sec_destroy_dbkey(dbkey);
  1624. }
  1625. return pk;
  1626. }
  1627. /*
  1628. * Find a key in the database, indexed by its public key modulus
  1629. * This is used to find keys that have been stored before their
  1630. * certificate arrives. Once the certificate arrives the key
  1631. * is looked up by the public modulus in the certificate, and the
  1632. * re-stored by its nickname.
  1633. */
  1634. NSSLOWKEYPrivateKey *
  1635. nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus,
  1636. SDB *sdbpw)
  1637. {
  1638. DBT namekey;
  1639. NSSLOWKEYPrivateKey *pk = NULL;
  1640. if (handle == NULL) {
  1641. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  1642. return NULL;
  1643. }
  1644. /* set up db key */
  1645. namekey.data = modulus->data;
  1646. namekey.size = modulus->len;
  1647. pk = seckey_get_private_key(handle, &namekey, NULL, sdbpw);
  1648. /* no need to free dbkey, since its on the stack, and the data it
  1649. * points to is owned by the database
  1650. */
  1651. return(pk);
  1652. }
  1653. char *
  1654. nsslowkey_FindKeyNicknameByPublicKey(NSSLOWKEYDBHandle *handle,
  1655. SECItem *modulus, SDB *sdbpw)
  1656. {
  1657. DBT namekey;
  1658. NSSLOWKEYPrivateKey *pk = NULL;
  1659. char *nickname = NULL;
  1660. if (handle == NULL) {
  1661. PORT_SetError(SEC_ERROR_BAD_DATABASE);
  1662. return NULL;
  1663. }
  1664. /* set up db key */
  1665. namekey.data = modulus->data;
  1666. namekey.size = modulus->len;
  1667. pk = seckey_get_private_key(handle, &namekey, &nickname, sdbpw);
  1668. if (pk) {
  1669. lg_nsslowkey_DestroyPrivateKey(pk);
  1670. }
  1671. /* no need to free dbkey, since its on the stack, and the data it
  1672. * points to is owned by the database
  1673. */
  1674. return(nickname);
  1675. }
  1676. /* ===== ENCODING ROUTINES ===== */
  1677. static SECStatus
  1678. encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,
  1679. SECItem *encCheck)
  1680. {
  1681. SECOidData *oidData;
  1682. SECStatus rv;
  1683. oidData = SECOID_FindOIDByTag(alg);
  1684. if ( oidData == NULL ) {
  1685. rv = SECFailure;
  1686. goto loser;
  1687. }
  1688. entry->len = 1 + oidData->oid.len + encCheck->len;
  1689. if ( arena ) {
  1690. entry->data = (unsigned char *)PORT_ArenaAlloc(arena, entry->len);
  1691. } else {
  1692. entry->data = (unsigned char *)PORT_Alloc(entry->len);
  1693. }
  1694. if ( entry->data == NULL ) {
  1695. goto loser;
  1696. }
  1697. /* first length of oid */
  1698. entry->data[0] = (unsigned char)oidData->oid.len;
  1699. /* next oid itself */
  1700. PORT_Memcpy(&entry->data[1], oidData->oid.data, oidData->oid.len);
  1701. /* finally the encrypted check string */
  1702. PORT_Memcpy(&entry->data[1+oidData->oid.len], encCheck->data,
  1703. encCheck->len);
  1704. return(SECSuccess);
  1705. loser:
  1706. return(SECFailure);
  1707. }
  1708. #define MAX_DB_SIZE 0xffff
  1709. /*
  1710. * Clear out all the keys in the existing database
  1711. */
  1712. static SECStatus
  1713. nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
  1714. {
  1715. SECStatus rv;
  1716. int ret;
  1717. int errors = 0;
  1718. if ( handle->db == NULL ) {
  1719. return(SECSuccess);
  1720. }
  1721. if (handle->readOnly) {
  1722. /* set an error code */
  1723. return SECFailure;
  1724. }
  1725. if (handle->appname == NULL && handle->dbname == NULL) {
  1726. return SECFailure;
  1727. }
  1728. keydb_Close(handle);
  1729. if (handle->appname) {
  1730. handle->db=
  1731. rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL);
  1732. } else {
  1733. handle->db = dbopen( handle->dbname, NO_CREATE, 0600, DB_HASH, 0 );
  1734. }
  1735. if (handle->db == NULL) {
  1736. /* set an error code */
  1737. return SECFailure;
  1738. }
  1739. rv = makeGlobalVersion(handle);
  1740. if ( rv != SECSuccess ) {
  1741. errors++;
  1742. goto done;
  1743. }
  1744. if (handle->global_salt) {
  1745. rv = StoreKeyDBGlobalSalt(handle, handle->global_salt);
  1746. } else {
  1747. rv = makeGlobalSalt(handle);
  1748. if ( rv == SECSuccess ) {
  1749. handle->global_salt = GetKeyDBGlobalSalt(handle);
  1750. }
  1751. }
  1752. if ( rv != SECSuccess ) {
  1753. errors++;
  1754. }
  1755. done:
  1756. /* sync the database */
  1757. ret = keydb_Sync(handle, 0);
  1758. db_InitComplete(handle->db);
  1759. return (errors == 0 ? SECSuccess : SECFailure);
  1760. }
  1761. static int
  1762. keydb_Get(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
  1763. {
  1764. PRStatus prstat;
  1765. int ret;
  1766. PRLock *kdbLock = kdb->lock;
  1767. DB *db = kdb->db;
  1768. PORT_Assert(kdbLock != NULL);
  1769. PZ_Lock(kdbLock);
  1770. ret = (* db->get)(db, key, data, flags);
  1771. prstat = PZ_Unlock(kdbLock);
  1772. return(ret);
  1773. }
  1774. static int
  1775. keydb_Put(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
  1776. {
  1777. PRStatus prstat;
  1778. int ret = 0;
  1779. PRLock *kdbLock = kdb->lock;
  1780. DB *db = kdb->db;
  1781. PORT_Assert(kdbLock != NULL);
  1782. PZ_Lock(kdbLock);
  1783. ret = (* db->put)(db, key, data, flags);
  1784. prstat = PZ_Unlock(kdbLock);
  1785. return(ret);
  1786. }
  1787. static int
  1788. keydb_Sync(NSSLOWKEYDBHandle *kdb, unsigned int flags)
  1789. {
  1790. PRStatus prstat;
  1791. int ret;
  1792. PRLock *kdbLock = kdb->lock;
  1793. DB *db = kdb->db;
  1794. PORT_Assert(kdbLock != NULL);
  1795. PZ_Lock(kdbLock);
  1796. ret = (* db->sync)(db, flags);
  1797. prstat = PZ_Unlock(kdbLock);
  1798. return(ret);
  1799. }
  1800. static int
  1801. keydb_Del(NSSLOWKEYDBHandle *kdb, DBT *key, unsigned int flags)
  1802. {
  1803. PRStatus prstat;
  1804. int ret;
  1805. PRLock *kdbLock = kdb->lock;
  1806. DB *db = kdb->db;
  1807. PORT_Assert(kdbLock != NULL);
  1808. PZ_Lock(kdbLock);
  1809. ret = (* db->del)(db, key, flags);
  1810. prstat = PZ_Unlock(kdbLock);
  1811. return(ret);
  1812. }
  1813. static int
  1814. keydb_Seq(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
  1815. {
  1816. PRStatus prstat;
  1817. int ret;
  1818. PRLock *kdbLock = kdb->lock;
  1819. DB *db = kdb->db;
  1820. PORT_Assert(kdbLock != NULL);
  1821. PZ_Lock(kdbLock);
  1822. ret = (* db->seq)(db, key, data, flags);
  1823. prstat = PZ_Unlock(kdbLock);
  1824. return(ret);
  1825. }
  1826. static void
  1827. keydb_Close(NSSLOWKEYDBHandle *kdb)
  1828. {
  1829. PRStatus prstat;
  1830. PRLock *kdbLock = kdb->lock;
  1831. DB *db = kdb->db;
  1832. PORT_Assert(kdbLock != NULL);
  1833. SKIP_AFTER_FORK(PZ_Lock(kdbLock));
  1834. (* db->close)(db);
  1835. SKIP_AFTER_FORK(prstat = PZ_Unlock(kdbLock));
  1836. return;
  1837. }
  1838. /*
  1839. * SDB Entry Points for the Key DB
  1840. */
  1841. CK_RV
  1842. lg_GetMetaData(SDB *sdb, const char *id, SECItem *item1, SECItem *item2)
  1843. {
  1844. NSSLOWKEYDBHandle *keydb;
  1845. NSSLOWKEYPasswordEntry entry;
  1846. SECStatus rv;
  1847. keydb = lg_getKeyDB(sdb);
  1848. if (keydb == NULL) {
  1849. return CKR_TOKEN_WRITE_PROTECTED;
  1850. }
  1851. if (PORT_Strcmp(id,"password") != 0) {
  1852. /* shouldn't happen */
  1853. return CKR_GENERAL_ERROR; /* no extra data stored */
  1854. }
  1855. rv = nsslowkey_GetPWCheckEntry(keydb, &entry);
  1856. if (rv != SECSuccess) {
  1857. return CKR_GENERAL_ERROR;
  1858. }
  1859. item1->len = entry.salt.len;
  1860. PORT_Memcpy(item1->data, entry.salt.data, item1->len);
  1861. item2->len = entry.value.len;
  1862. PORT_Memcpy(item2->data, entry.value.data, item2->len);
  1863. return CKR_OK;
  1864. }
  1865. CK_RV
  1866. lg_PutMetaData(SDB *sdb, const char *id,
  1867. const SECItem *item1, const SECItem *item2)
  1868. {
  1869. NSSLOWKEYDBHandle *keydb;
  1870. NSSLOWKEYPasswordEntry entry;
  1871. SECStatus rv;
  1872. keydb = lg_getKeyDB(sdb);
  1873. if (keydb == NULL) {
  1874. return CKR_TOKEN_WRITE_PROTECTED;
  1875. }
  1876. if (PORT_Strcmp(id,"password") != 0) {
  1877. /* shouldn't happen */
  1878. return CKR_GENERAL_ERROR; /* no extra data stored */
  1879. }
  1880. entry.salt = *item1;
  1881. entry.value = *item2;
  1882. rv = nsslowkey_PutPWCheckEntry(keydb, &entry);
  1883. if (rv != SECSuccess) {
  1884. return CKR_GENERAL_ERROR;
  1885. }
  1886. return CKR_OK;
  1887. }
  1888. CK_RV
  1889. lg_Reset(SDB *sdb)
  1890. {
  1891. NSSLOWKEYDBHandle *keydb;
  1892. SECStatus rv;
  1893. keydb = lg_getKeyDB(sdb);
  1894. if (keydb == NULL) {
  1895. return CKR_TOKEN_WRITE_PROTECTED;
  1896. }
  1897. rv = nsslowkey_ResetKeyDB(keydb);
  1898. if (rv != SECSuccess) {
  1899. return CKR_GENERAL_ERROR;
  1900. }
  1901. return CKR_OK;
  1902. }