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