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 "ckdbm.h"
6
7 #define PREFIX_METADATA "0000"
8 #define PREFIX_OBJECT "0001"
9 #define PREFIX_INDEX "0002"
10
11 static CK_VERSION nss_dbm_db_format_version = { 1, 0 };
12 struct handle {
13 char prefix[4];
14 CK_ULONG id;
15 };
16
17 NSS_IMPLEMENT nss_dbm_db_t *
nss_dbm_db_open(NSSArena * arena,NSSCKFWInstance * fwInstance,char * filename,int flags,CK_RV * pError)18 nss_dbm_db_open(
19 NSSArena *arena,
20 NSSCKFWInstance *fwInstance,
21 char *filename,
22 int flags,
23 CK_RV *pError)
24 {
25 nss_dbm_db_t *rv;
26 CK_VERSION db_version;
27
28 rv = nss_ZNEW(arena, nss_dbm_db_t);
29 if ((nss_dbm_db_t *)NULL == rv) {
30 *pError = CKR_HOST_MEMORY;
31 return (nss_dbm_db_t *)NULL;
32 }
33
34 rv->db = dbopen(filename, flags, 0600, DB_HASH, (const void *)NULL);
35 if ((DB *)NULL == rv->db) {
36 *pError = CKR_TOKEN_NOT_PRESENT;
37 return (nss_dbm_db_t *)NULL;
38 }
39
40 rv->crustylock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError);
41 if ((NSSCKFWMutex *)NULL == rv->crustylock) {
42 return (nss_dbm_db_t *)NULL;
43 }
44
45 db_version = nss_dbm_db_get_format_version(rv);
46 if (db_version.major != nss_dbm_db_format_version.major) {
47 nss_dbm_db_close(rv);
48 *pError = CKR_TOKEN_NOT_RECOGNIZED;
49 return (nss_dbm_db_t *)NULL;
50 }
51
52 return rv;
53 }
54
55 NSS_IMPLEMENT void
nss_dbm_db_close(nss_dbm_db_t * db)56 nss_dbm_db_close(
57 nss_dbm_db_t *db)
58 {
59 if ((NSSCKFWMutex *)NULL != db->crustylock) {
60 (void)NSSCKFWMutex_Destroy(db->crustylock);
61 }
62
63 if ((DB *)NULL != db->db) {
64 (void)db->db->close(db->db);
65 }
66
67 nss_ZFreeIf(db);
68 }
69
70 NSS_IMPLEMENT CK_VERSION
nss_dbm_db_get_format_version(nss_dbm_db_t * db)71 nss_dbm_db_get_format_version(
72 nss_dbm_db_t *db)
73 {
74 CK_VERSION rv;
75 DBT k, v;
76 int dbrv;
77 char buffer[64];
78
79 rv.major = rv.minor = 0;
80
81 k.data = PREFIX_METADATA "FormatVersion";
82 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
83 (void)memset(&v, 0, sizeof(v));
84
85 /* Locked region */
86 {
87 if (CKR_OK != NSSCKFWMutex_Lock(db->crustylock)) {
88 return rv;
89 }
90
91 dbrv = db->db->get(db->db, &k, &v, 0);
92 if (dbrv == 0) {
93 CK_ULONG major = 0, minor = 0;
94 (void)PR_sscanf(v.data, "%ld.%ld", &major, &minor);
95 rv.major = major;
96 rv.minor = minor;
97 } else if (dbrv > 0) {
98 (void)PR_snprintf(buffer, sizeof(buffer), "%ld.%ld", nss_dbm_db_format_version.major,
99 nss_dbm_db_format_version.minor);
100 v.data = buffer;
101 v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
102 dbrv = db->db->put(db->db, &k, &v, 0);
103 (void)db->db->sync(db->db, 0);
104 rv = nss_dbm_db_format_version;
105 } else {
106 /* No error return.. */
107 ;
108 }
109
110 (void)NSSCKFWMutex_Unlock(db->crustylock);
111 }
112
113 return rv;
114 }
115
116 NSS_IMPLEMENT CK_RV
nss_dbm_db_set_label(nss_dbm_db_t * db,NSSUTF8 * label)117 nss_dbm_db_set_label(
118 nss_dbm_db_t *db,
119 NSSUTF8 *label)
120 {
121 CK_RV rv;
122 DBT k, v;
123 int dbrv;
124
125 k.data = PREFIX_METADATA "Label";
126 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
127 v.data = label;
128 v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
129
130 /* Locked region */
131 {
132 rv = NSSCKFWMutex_Lock(db->crustylock);
133 if (CKR_OK != rv) {
134 return rv;
135 }
136
137 dbrv = db->db->put(db->db, &k, &v, 0);
138 if (0 != dbrv) {
139 rv = CKR_DEVICE_ERROR;
140 }
141
142 dbrv = db->db->sync(db->db, 0);
143 if (0 != dbrv) {
144 rv = CKR_DEVICE_ERROR;
145 }
146
147 (void)NSSCKFWMutex_Unlock(db->crustylock);
148 }
149
150 return rv;
151 }
152
153 NSS_IMPLEMENT NSSUTF8 *
nss_dbm_db_get_label(nss_dbm_db_t * db,NSSArena * arena,CK_RV * pError)154 nss_dbm_db_get_label(
155 nss_dbm_db_t *db,
156 NSSArena *arena,
157 CK_RV *pError)
158 {
159 NSSUTF8 *rv = (NSSUTF8 *)NULL;
160 DBT k, v;
161 int dbrv;
162
163 k.data = PREFIX_METADATA "Label";
164 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
165
166 /* Locked region */
167 {
168 if (CKR_OK != NSSCKFWMutex_Lock(db->crustylock)) {
169 return rv;
170 }
171
172 dbrv = db->db->get(db->db, &k, &v, 0);
173 if (0 == dbrv) {
174 rv = nssUTF8_Duplicate((NSSUTF8 *)v.data, arena);
175 if ((NSSUTF8 *)NULL == rv) {
176 *pError = CKR_HOST_MEMORY;
177 }
178 } else if (dbrv > 0) {
179 /* Just return null */
180 ;
181 } else {
182 *pError = CKR_DEVICE_ERROR;
183 ;
184 }
185
186 (void)NSSCKFWMutex_Unlock(db->crustylock);
187 }
188
189 return rv;
190 }
191
192 NSS_IMPLEMENT CK_RV
nss_dbm_db_delete_object(nss_dbm_dbt_t * dbt)193 nss_dbm_db_delete_object(
194 nss_dbm_dbt_t *dbt)
195 {
196 CK_RV rv;
197 int dbrv;
198
199 /* Locked region */
200 {
201 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
202 if (CKR_OK != rv) {
203 return rv;
204 }
205
206 dbrv = dbt->my_db->db->del(dbt->my_db->db, &dbt->dbt, 0);
207 if (0 != dbrv) {
208 rv = CKR_DEVICE_ERROR;
209 goto done;
210 }
211
212 dbrv = dbt->my_db->db->sync(dbt->my_db->db, 0);
213 if (0 != dbrv) {
214 rv = CKR_DEVICE_ERROR;
215 goto done;
216 }
217
218 done:
219 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
220 }
221
222 return rv;
223 }
224
225 static CK_ULONG
nss_dbm_db_new_handle(nss_dbm_db_t * db,DBT * dbt,CK_RV * pError)226 nss_dbm_db_new_handle(
227 nss_dbm_db_t *db,
228 DBT *dbt, /* pre-allocated */
229 CK_RV *pError)
230 {
231 CK_ULONG rv;
232 DBT k, v;
233 CK_ULONG align = 0, id, myid;
234 struct handle *hp;
235
236 if (sizeof(struct handle) != dbt->size) {
237 return EINVAL;
238 }
239
240 /* Locked region */
241 {
242 *pError = NSSCKFWMutex_Lock(db->crustylock);
243 if (CKR_OK != *pError) {
244 return EINVAL;
245 }
246
247 k.data = PREFIX_METADATA "LastID";
248 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
249 (void)memset(&v, 0, sizeof(v));
250
251 rv = db->db->get(db->db, &k, &v, 0);
252 if (0 == rv) {
253 (void)memcpy(&align, v.data, sizeof(CK_ULONG));
254 id = ntohl(align);
255 } else if (rv > 0) {
256 id = 0;
257 } else {
258 goto done;
259 }
260
261 myid = id;
262 id++;
263 align = htonl(id);
264 v.data = &align;
265 v.size = sizeof(CK_ULONG);
266
267 rv = db->db->put(db->db, &k, &v, 0);
268 if (0 != rv) {
269 goto done;
270 }
271
272 rv = db->db->sync(db->db, 0);
273 if (0 != rv) {
274 goto done;
275 }
276
277 done:
278 (void)NSSCKFWMutex_Unlock(db->crustylock);
279 }
280
281 if (0 != rv) {
282 return rv;
283 }
284
285 hp = (struct handle *)dbt->data;
286 (void)memcpy(&hp->prefix[0], PREFIX_OBJECT, 4);
287 hp->id = myid;
288
289 return 0;
290 }
291
292 /*
293 * This attribute-type-dependent swapping should probably
294 * be in the Framework, because it'll be a concern of just
295 * about every Module. Of course any Framework implementation
296 * will have to be augmentable or overridable by a Module.
297 */
298
299 enum swap_type { type_byte,
300 type_short,
301 type_long,
302 type_opaque };
303
304 static enum swap_type
nss_dbm_db_swap_type(CK_ATTRIBUTE_TYPE type)305 nss_dbm_db_swap_type(
306 CK_ATTRIBUTE_TYPE type)
307 {
308 switch (type) {
309 case CKA_CLASS:
310 return type_long;
311 case CKA_TOKEN:
312 return type_byte;
313 case CKA_PRIVATE:
314 return type_byte;
315 case CKA_LABEL:
316 return type_opaque;
317 case CKA_APPLICATION:
318 return type_opaque;
319 case CKA_VALUE:
320 return type_opaque;
321 case CKA_CERTIFICATE_TYPE:
322 return type_long;
323 case CKA_ISSUER:
324 return type_opaque;
325 case CKA_SERIAL_NUMBER:
326 return type_opaque;
327 case CKA_KEY_TYPE:
328 return type_long;
329 case CKA_SUBJECT:
330 return type_opaque;
331 case CKA_ID:
332 return type_opaque;
333 case CKA_SENSITIVE:
334 return type_byte;
335 case CKA_ENCRYPT:
336 return type_byte;
337 case CKA_DECRYPT:
338 return type_byte;
339 case CKA_WRAP:
340 return type_byte;
341 case CKA_UNWRAP:
342 return type_byte;
343 case CKA_SIGN:
344 return type_byte;
345 case CKA_SIGN_RECOVER:
346 return type_byte;
347 case CKA_VERIFY:
348 return type_byte;
349 case CKA_VERIFY_RECOVER:
350 return type_byte;
351 case CKA_DERIVE:
352 return type_byte;
353 case CKA_START_DATE:
354 return type_opaque;
355 case CKA_END_DATE:
356 return type_opaque;
357 case CKA_MODULUS:
358 return type_opaque;
359 case CKA_MODULUS_BITS:
360 return type_long;
361 case CKA_PUBLIC_EXPONENT:
362 return type_opaque;
363 case CKA_PRIVATE_EXPONENT:
364 return type_opaque;
365 case CKA_PRIME_1:
366 return type_opaque;
367 case CKA_PRIME_2:
368 return type_opaque;
369 case CKA_EXPONENT_1:
370 return type_opaque;
371 case CKA_EXPONENT_2:
372 return type_opaque;
373 case CKA_COEFFICIENT:
374 return type_opaque;
375 case CKA_PRIME:
376 return type_opaque;
377 case CKA_SUBPRIME:
378 return type_opaque;
379 case CKA_BASE:
380 return type_opaque;
381 case CKA_VALUE_BITS:
382 return type_long;
383 case CKA_VALUE_LEN:
384 return type_long;
385 case CKA_EXTRACTABLE:
386 return type_byte;
387 case CKA_LOCAL:
388 return type_byte;
389 case CKA_NEVER_EXTRACTABLE:
390 return type_byte;
391 case CKA_ALWAYS_SENSITIVE:
392 return type_byte;
393 case CKA_MODIFIABLE:
394 return type_byte;
395 case CKA_NSS_URL:
396 return type_opaque;
397 case CKA_NSS_EMAIL:
398 return type_opaque;
399 case CKA_NSS_SMIME_INFO:
400 return type_opaque;
401 case CKA_NSS_SMIME_TIMESTAMP:
402 return type_opaque;
403 case CKA_NSS_PKCS8_SALT:
404 return type_opaque;
405 case CKA_NSS_PASSWORD_CHECK:
406 return type_opaque;
407 case CKA_NSS_EXPIRES:
408 return type_opaque;
409 case CKA_TRUST_DIGITAL_SIGNATURE:
410 return type_long;
411 case CKA_TRUST_NON_REPUDIATION:
412 return type_long;
413 case CKA_TRUST_KEY_ENCIPHERMENT:
414 return type_long;
415 case CKA_TRUST_DATA_ENCIPHERMENT:
416 return type_long;
417 case CKA_TRUST_KEY_AGREEMENT:
418 return type_long;
419 case CKA_TRUST_KEY_CERT_SIGN:
420 return type_long;
421 case CKA_TRUST_CRL_SIGN:
422 return type_long;
423 case CKA_TRUST_SERVER_AUTH:
424 return type_long;
425 case CKA_TRUST_CLIENT_AUTH:
426 return type_long;
427 case CKA_TRUST_CODE_SIGNING:
428 return type_long;
429 case CKA_TRUST_EMAIL_PROTECTION:
430 return type_long;
431 case CKA_TRUST_IPSEC_END_SYSTEM:
432 return type_long;
433 case CKA_TRUST_IPSEC_TUNNEL:
434 return type_long;
435 case CKA_TRUST_IPSEC_USER:
436 return type_long;
437 case CKA_TRUST_TIME_STAMPING:
438 return type_long;
439 case CKA_NSS_DB:
440 return type_opaque;
441 case CKA_NSS_TRUST:
442 return type_opaque;
443 default:
444 return type_opaque;
445 }
446 }
447
448 static void
nss_dbm_db_swap_copy(CK_ATTRIBUTE_TYPE type,void * dest,void * src,CK_ULONG len)449 nss_dbm_db_swap_copy(
450 CK_ATTRIBUTE_TYPE type,
451 void *dest,
452 void *src,
453 CK_ULONG len)
454 {
455 switch (nss_dbm_db_swap_type(type)) {
456 case type_byte:
457 case type_opaque:
458 (void)memcpy(dest, src, len);
459 break;
460 case type_short: {
461 CK_USHORT s, d;
462 (void)memcpy(&s, src, sizeof(CK_USHORT));
463 d = htons(s);
464 (void)memcpy(dest, &d, sizeof(CK_USHORT));
465 break;
466 }
467 case type_long: {
468 CK_ULONG s, d;
469 (void)memcpy(&s, src, sizeof(CK_ULONG));
470 d = htonl(s);
471 (void)memcpy(dest, &d, sizeof(CK_ULONG));
472 break;
473 }
474 }
475 }
476
477 static CK_RV
nss_dbm_db_wrap_object(NSSArena * arena,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,DBT * object)478 nss_dbm_db_wrap_object(
479 NSSArena *arena,
480 CK_ATTRIBUTE_PTR pTemplate,
481 CK_ULONG ulAttributeCount,
482 DBT *object)
483 {
484 CK_ULONG object_size;
485 CK_ULONG i;
486 CK_ULONG *pulData;
487 char *pcData;
488 CK_ULONG offset;
489
490 object_size = (1 + ulAttributeCount * 3) * sizeof(CK_ULONG);
491 offset = object_size;
492 for (i = 0; i < ulAttributeCount; i++) {
493 object_size += pTemplate[i].ulValueLen;
494 }
495
496 object->size = object_size;
497 object->data = nss_ZAlloc(arena, object_size);
498 if ((void *)NULL == object->data) {
499 return CKR_HOST_MEMORY;
500 }
501
502 pulData = (CK_ULONG *)object->data;
503 pcData = (char *)object->data;
504
505 pulData[0] = htonl(ulAttributeCount);
506 for (i = 0; i < ulAttributeCount; i++) {
507 CK_ULONG len = pTemplate[i].ulValueLen;
508 pulData[1 + i * 3] = htonl(pTemplate[i].type);
509 pulData[2 + i * 3] = htonl(len);
510 pulData[3 + i * 3] = htonl(offset);
511 nss_dbm_db_swap_copy(pTemplate[i].type, &pcData[offset], pTemplate[i].pValue, len);
512 offset += len;
513 }
514
515 return CKR_OK;
516 }
517
518 static CK_RV
nss_dbm_db_unwrap_object(NSSArena * arena,DBT * object,CK_ATTRIBUTE_PTR * ppTemplate,CK_ULONG * pulAttributeCount)519 nss_dbm_db_unwrap_object(
520 NSSArena *arena,
521 DBT *object,
522 CK_ATTRIBUTE_PTR *ppTemplate,
523 CK_ULONG *pulAttributeCount)
524 {
525 CK_ULONG *pulData;
526 char *pcData;
527 CK_ULONG n, i;
528 CK_ATTRIBUTE_PTR pTemplate;
529
530 pulData = (CK_ULONG *)object->data;
531 pcData = (char *)object->data;
532
533 n = ntohl(pulData[0]);
534 *pulAttributeCount = n;
535 pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n);
536 if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) {
537 return CKR_HOST_MEMORY;
538 }
539
540 for (i = 0; i < n; i++) {
541 CK_ULONG len;
542 CK_ULONG offset;
543 void *p;
544
545 pTemplate[i].type = ntohl(pulData[1 + i * 3]);
546 len = ntohl(pulData[2 + i * 3]);
547 offset = ntohl(pulData[3 + i * 3]);
548
549 p = nss_ZAlloc(arena, len);
550 if ((void *)NULL == p) {
551 return CKR_HOST_MEMORY;
552 }
553
554 nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len);
555 pTemplate[i].ulValueLen = len;
556 pTemplate[i].pValue = p;
557 }
558
559 *ppTemplate = pTemplate;
560 return CKR_OK;
561 }
562
563 NSS_IMPLEMENT nss_dbm_dbt_t *
nss_dbm_db_create_object(NSSArena * arena,nss_dbm_db_t * db,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_RV * pError,CK_ULONG * pdbrv)564 nss_dbm_db_create_object(
565 NSSArena *arena,
566 nss_dbm_db_t *db,
567 CK_ATTRIBUTE_PTR pTemplate,
568 CK_ULONG ulAttributeCount,
569 CK_RV *pError,
570 CK_ULONG *pdbrv)
571 {
572 NSSArena *tmparena = (NSSArena *)NULL;
573 nss_dbm_dbt_t *rv = (nss_dbm_dbt_t *)NULL;
574 DBT object;
575
576 rv = nss_ZNEW(arena, nss_dbm_dbt_t);
577 if ((nss_dbm_dbt_t *)NULL == rv) {
578 *pError = CKR_HOST_MEMORY;
579 return (nss_dbm_dbt_t *)NULL;
580 }
581
582 rv->my_db = db;
583 rv->dbt.size = sizeof(struct handle);
584 rv->dbt.data = nss_ZAlloc(arena, rv->dbt.size);
585 if ((void *)NULL == rv->dbt.data) {
586 *pError = CKR_HOST_MEMORY;
587 return (nss_dbm_dbt_t *)NULL;
588 }
589
590 *pdbrv = nss_dbm_db_new_handle(db, &rv->dbt, pError);
591 if (0 != *pdbrv) {
592 return (nss_dbm_dbt_t *)NULL;
593 }
594
595 tmparena = NSSArena_Create();
596 if ((NSSArena *)NULL == tmparena) {
597 *pError = CKR_HOST_MEMORY;
598 return (nss_dbm_dbt_t *)NULL;
599 }
600
601 *pError = nss_dbm_db_wrap_object(tmparena, pTemplate, ulAttributeCount, &object);
602 if (CKR_OK != *pError) {
603 return (nss_dbm_dbt_t *)NULL;
604 }
605
606 /* Locked region */
607 {
608 *pError = NSSCKFWMutex_Lock(db->crustylock);
609 if (CKR_OK != *pError) {
610 goto loser;
611 }
612
613 *pdbrv = db->db->put(db->db, &rv->dbt, &object, 0);
614 if (0 != *pdbrv) {
615 *pError = CKR_DEVICE_ERROR;
616 }
617
618 (void)db->db->sync(db->db, 0);
619
620 (void)NSSCKFWMutex_Unlock(db->crustylock);
621 }
622
623 loser:
624 if ((NSSArena *)NULL != tmparena) {
625 (void)NSSArena_Destroy(tmparena);
626 }
627
628 return rv;
629 }
630
631 NSS_IMPLEMENT CK_RV
nss_dbm_db_find_objects(nss_dbm_find_t * find,nss_dbm_db_t * db,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulAttributeCount,CK_ULONG * pdbrv)632 nss_dbm_db_find_objects(
633 nss_dbm_find_t *find,
634 nss_dbm_db_t *db,
635 CK_ATTRIBUTE_PTR pTemplate,
636 CK_ULONG ulAttributeCount,
637 CK_ULONG *pdbrv)
638 {
639 CK_RV rv = CKR_OK;
640
641 if ((nss_dbm_db_t *)NULL != db) {
642 DBT k, v;
643
644 rv = NSSCKFWMutex_Lock(db->crustylock);
645 if (CKR_OK != rv) {
646 return rv;
647 }
648
649 *pdbrv = db->db->seq(db->db, &k, &v, R_FIRST);
650 while (0 == *pdbrv) {
651 CK_ULONG i, j;
652 NSSArena *tmparena = (NSSArena *)NULL;
653 CK_ULONG ulac;
654 CK_ATTRIBUTE_PTR pt;
655
656 if ((k.size < 4) || (0 != memcmp(k.data, PREFIX_OBJECT, 4))) {
657 goto nomatch;
658 }
659
660 tmparena = NSSArena_Create();
661
662 rv = nss_dbm_db_unwrap_object(tmparena, &v, &pt, &ulac);
663 if (CKR_OK != rv) {
664 goto loser;
665 }
666
667 for (i = 0; i < ulAttributeCount; i++) {
668 for (j = 0; j < ulac; j++) {
669 if (pTemplate[i].type ==
670 pt[j].type) {
671 if (pTemplate[i].ulValueLen !=
672 pt[j].ulValueLen) {
673 goto nomatch;
674 }
675 if (0 !=
676 memcmp(pTemplate[i].pValue, pt[j].pValue, pt[j].ulValueLen)) {
677 goto nomatch;
678 }
679 break;
680 }
681 }
682 if (j == ulac) {
683 goto nomatch;
684 }
685 }
686
687 /* entire template matches */
688 {
689 struct nss_dbm_dbt_node *node;
690
691 node = nss_ZNEW(find->arena, struct nss_dbm_dbt_node);
692 if ((struct nss_dbm_dbt_node *)NULL == node) {
693 rv =
694 CKR_HOST_MEMORY;
695 goto loser;
696 }
697
698 node->dbt = nss_ZNEW(find->arena, nss_dbm_dbt_t);
699 if ((nss_dbm_dbt_t *)NULL == node->dbt) {
700 rv =
701 CKR_HOST_MEMORY;
702 goto loser;
703 }
704
705 node->dbt->dbt.size = k.size;
706 node->dbt->dbt.data = nss_ZAlloc(find->arena, k.size);
707 if ((void *)NULL == node->dbt->dbt.data) {
708 rv =
709 CKR_HOST_MEMORY;
710 goto loser;
711 }
712
713 (void)memcpy(node->dbt->dbt.data, k.data, k.size);
714
715 node->dbt->my_db = db;
716
717 node->next = find->found;
718 find->found = node;
719 }
720
721 nomatch:
722 if ((NSSArena *)NULL != tmparena) {
723 (void)NSSArena_Destroy(tmparena);
724 }
725 *pdbrv = db->db->seq(db->db, &k, &v, R_NEXT);
726 }
727
728 if (*pdbrv < 0) {
729 rv = CKR_DEVICE_ERROR;
730 goto loser;
731 }
732
733 rv = CKR_OK;
734
735 loser:
736 (void)NSSCKFWMutex_Unlock(db->crustylock);
737 }
738
739 return rv;
740 }
741
742 NSS_IMPLEMENT CK_BBOOL
nss_dbm_db_object_still_exists(nss_dbm_dbt_t * dbt)743 nss_dbm_db_object_still_exists(
744 nss_dbm_dbt_t *dbt)
745 {
746 CK_BBOOL rv;
747 CK_RV ckrv;
748 int dbrv;
749 DBT object;
750
751 ckrv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
752 if (CKR_OK != ckrv) {
753 return CK_FALSE;
754 }
755
756 dbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
757 if (0 == dbrv) {
758 rv = CK_TRUE;
759 } else {
760 rv = CK_FALSE;
761 }
762
763 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
764
765 return rv;
766 }
767
768 NSS_IMPLEMENT CK_ULONG
nss_dbm_db_get_object_attribute_count(nss_dbm_dbt_t * dbt,CK_RV * pError,CK_ULONG * pdbrv)769 nss_dbm_db_get_object_attribute_count(
770 nss_dbm_dbt_t *dbt,
771 CK_RV *pError,
772 CK_ULONG *pdbrv)
773 {
774 CK_ULONG rv = 0;
775 DBT object;
776 CK_ULONG *pulData;
777
778 /* Locked region */
779 {
780 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
781 if (CKR_OK != *pError) {
782 return rv;
783 }
784
785 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
786 if (0 == *pdbrv) {
787 ;
788 } else if (*pdbrv > 0) {
789 *pError = CKR_OBJECT_HANDLE_INVALID;
790 goto done;
791 } else {
792 *pError = CKR_DEVICE_ERROR;
793 goto done;
794 }
795
796 pulData = (CK_ULONG *)object.data;
797 rv = ntohl(pulData[0]);
798
799 done:
800 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
801 }
802
803 return rv;
804 }
805
806 NSS_IMPLEMENT CK_RV
nss_dbm_db_get_object_attribute_types(nss_dbm_dbt_t * dbt,CK_ATTRIBUTE_TYPE_PTR typeArray,CK_ULONG ulCount,CK_ULONG * pdbrv)807 nss_dbm_db_get_object_attribute_types(
808 nss_dbm_dbt_t *dbt,
809 CK_ATTRIBUTE_TYPE_PTR typeArray,
810 CK_ULONG ulCount,
811 CK_ULONG *pdbrv)
812 {
813 CK_RV rv = CKR_OK;
814 DBT object;
815 CK_ULONG *pulData;
816 CK_ULONG n, i;
817
818 /* Locked region */
819 {
820 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
821 if (CKR_OK != rv) {
822 return rv;
823 }
824
825 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
826 if (0 == *pdbrv) {
827 ;
828 } else if (*pdbrv > 0) {
829 rv = CKR_OBJECT_HANDLE_INVALID;
830 goto done;
831 } else {
832 rv = CKR_DEVICE_ERROR;
833 goto done;
834 }
835
836 pulData = (CK_ULONG *)object.data;
837 n = ntohl(pulData[0]);
838
839 if (ulCount < n) {
840 rv = CKR_BUFFER_TOO_SMALL;
841 goto done;
842 }
843
844 for (i = 0; i < n; i++) {
845 typeArray[i] = ntohl(pulData[1 + i * 3]);
846 }
847
848 done:
849 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
850 }
851
852 return rv;
853 }
854
855 NSS_IMPLEMENT CK_ULONG
nss_dbm_db_get_object_attribute_size(nss_dbm_dbt_t * dbt,CK_ATTRIBUTE_TYPE type,CK_RV * pError,CK_ULONG * pdbrv)856 nss_dbm_db_get_object_attribute_size(
857 nss_dbm_dbt_t *dbt,
858 CK_ATTRIBUTE_TYPE type,
859 CK_RV *pError,
860 CK_ULONG *pdbrv)
861 {
862 CK_ULONG rv = 0;
863 DBT object;
864 CK_ULONG *pulData;
865 CK_ULONG n, i;
866
867 /* Locked region */
868 {
869 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
870 if (CKR_OK != *pError) {
871 return rv;
872 }
873
874 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
875 if (0 == *pdbrv) {
876 ;
877 } else if (*pdbrv > 0) {
878 *pError = CKR_OBJECT_HANDLE_INVALID;
879 goto done;
880 } else {
881 *pError = CKR_DEVICE_ERROR;
882 goto done;
883 }
884
885 pulData = (CK_ULONG *)object.data;
886 n = ntohl(pulData[0]);
887
888 for (i = 0; i < n; i++) {
889 if (type == ntohl(pulData[1 + i * 3])) {
890 rv = ntohl(pulData[2 + i * 3]);
891 }
892 }
893
894 if (i == n) {
895 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
896 goto done;
897 }
898
899 done:
900 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
901 }
902
903 return rv;
904 }
905
906 NSS_IMPLEMENT NSSItem *
nss_dbm_db_get_object_attribute(nss_dbm_dbt_t * dbt,NSSArena * arena,CK_ATTRIBUTE_TYPE type,CK_RV * pError,CK_ULONG * pdbrv)907 nss_dbm_db_get_object_attribute(
908 nss_dbm_dbt_t *dbt,
909 NSSArena *arena,
910 CK_ATTRIBUTE_TYPE type,
911 CK_RV *pError,
912 CK_ULONG *pdbrv)
913 {
914 NSSItem *rv = (NSSItem *)NULL;
915 DBT object;
916 CK_ULONG i;
917 NSSArena *tmp = NSSArena_Create();
918 CK_ATTRIBUTE_PTR pTemplate;
919 CK_ULONG ulAttributeCount;
920
921 /* Locked region */
922 {
923 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
924 if (CKR_OK != *pError) {
925 goto loser;
926 }
927
928 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
929 if (0 == *pdbrv) {
930 ;
931 } else if (*pdbrv > 0) {
932 *pError = CKR_OBJECT_HANDLE_INVALID;
933 goto done;
934 } else {
935 *pError = CKR_DEVICE_ERROR;
936 goto done;
937 }
938
939 *pError = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
940 if (CKR_OK != *pError) {
941 goto done;
942 }
943
944 for (i = 0; i < ulAttributeCount; i++) {
945 if (type == pTemplate[i].type) {
946 rv = nss_ZNEW(arena, NSSItem);
947 if ((NSSItem *)NULL == rv) {
948 *pError =
949 CKR_HOST_MEMORY;
950 goto done;
951 }
952 rv->size = pTemplate[i].ulValueLen;
953 rv->data = nss_ZAlloc(arena, rv->size);
954 if ((void *)NULL == rv->data) {
955 *pError =
956 CKR_HOST_MEMORY;
957 goto done;
958 }
959 (void)memcpy(rv->data, pTemplate[i].pValue, rv->size);
960 break;
961 }
962 }
963 if (ulAttributeCount == i) {
964 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
965 goto done;
966 }
967
968 done:
969 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
970 }
971
972 loser:
973 if ((NSSArena *)NULL != tmp) {
974 NSSArena_Destroy(tmp);
975 }
976
977 return rv;
978 }
979
980 NSS_IMPLEMENT CK_RV
nss_dbm_db_set_object_attribute(nss_dbm_dbt_t * dbt,CK_ATTRIBUTE_TYPE type,NSSItem * value,CK_ULONG * pdbrv)981 nss_dbm_db_set_object_attribute(
982 nss_dbm_dbt_t *dbt,
983 CK_ATTRIBUTE_TYPE type,
984 NSSItem *value,
985 CK_ULONG *pdbrv)
986 {
987 CK_RV rv = CKR_OK;
988 DBT object;
989 CK_ULONG i;
990 NSSArena *tmp = NSSArena_Create();
991 CK_ATTRIBUTE_PTR pTemplate;
992 CK_ULONG ulAttributeCount;
993
994 /* Locked region */
995 {
996 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
997 if (CKR_OK != rv) {
998 goto loser;
999 }
1000
1001 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
1002 if (0 == *pdbrv) {
1003 ;
1004 } else if (*pdbrv > 0) {
1005 rv = CKR_OBJECT_HANDLE_INVALID;
1006 goto done;
1007 } else {
1008 rv = CKR_DEVICE_ERROR;
1009 goto done;
1010 }
1011
1012 rv = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
1013 if (CKR_OK != rv) {
1014 goto done;
1015 }
1016
1017 for (i = 0; i < ulAttributeCount; i++) {
1018 if (type == pTemplate[i].type) {
1019 /* Replacing an existing attribute */
1020 pTemplate[i].ulValueLen = value->size;
1021 pTemplate[i].pValue = value->data;
1022 break;
1023 }
1024 }
1025
1026 if (i == ulAttributeCount) {
1027 /* Adding a new attribute */
1028 CK_ATTRIBUTE_PTR npt = nss_ZNEWARRAY(tmp, CK_ATTRIBUTE, ulAttributeCount + 1);
1029 if ((CK_ATTRIBUTE_PTR)NULL == npt) {
1030 rv = CKR_DEVICE_ERROR;
1031 goto done;
1032 }
1033
1034 for (i = 0; i < ulAttributeCount; i++) {
1035 npt[i] = pTemplate[i];
1036 }
1037
1038 npt[ulAttributeCount].type = type;
1039 npt[ulAttributeCount].ulValueLen = value->size;
1040 npt[ulAttributeCount].pValue = value->data;
1041
1042 pTemplate = npt;
1043 ulAttributeCount++;
1044 }
1045
1046 rv = nss_dbm_db_wrap_object(tmp, pTemplate, ulAttributeCount, &object);
1047 if (CKR_OK != rv) {
1048 goto done;
1049 }
1050
1051 *pdbrv = dbt->my_db->db->put(dbt->my_db->db, &dbt->dbt, &object, 0);
1052 if (0 != *pdbrv) {
1053 rv = CKR_DEVICE_ERROR;
1054 goto done;
1055 }
1056
1057 (void)dbt->my_db->db->sync(dbt->my_db->db, 0);
1058
1059 done:
1060 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
1061 }
1062
1063 loser:
1064 if ((NSSArena *)NULL != tmp) {
1065 NSSArena_Destroy(tmp);
1066 }
1067
1068 return rv;
1069 }
1070