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