comparison nss/lib/softoken/legacydb/keydb.c @ 3:150b72113545

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