Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / ckfw / dbm / db.c
blob1ad75c6291c32f49e0a5ffeec96b8182661bf1af
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #ifdef DEBUG
38 static const char CVS_ID[] = "@(#) $RCSfile: db.c,v $ $Revision: 1.6 $ $Date: 2006/03/02 22:48:54 $";
39 #endif /* DEBUG */
41 #include "ckdbm.h"
43 #define PREFIX_METADATA "0000"
44 #define PREFIX_OBJECT "0001"
45 #define PREFIX_INDEX "0002"
47 static CK_VERSION nss_dbm_db_format_version = { 1, 0 };
48 struct handle {
49 char prefix[4];
50 CK_ULONG id;
53 NSS_IMPLEMENT nss_dbm_db_t *
54 nss_dbm_db_open
56 NSSArena *arena,
57 NSSCKFWInstance *fwInstance,
58 char *filename,
59 int flags,
60 CK_RV *pError
63 nss_dbm_db_t *rv;
64 CK_VERSION db_version;
66 rv = nss_ZNEW(arena, nss_dbm_db_t);
67 if( (nss_dbm_db_t *)NULL == rv ) {
68 *pError = CKR_HOST_MEMORY;
69 return (nss_dbm_db_t *)NULL;
72 rv->db = dbopen(filename, flags, 0600, DB_HASH, (const void *)NULL);
73 if( (DB *)NULL == rv->db ) {
74 *pError = CKR_TOKEN_NOT_PRESENT;
75 return (nss_dbm_db_t *)NULL;
78 rv->crustylock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError);
79 if( (NSSCKFWMutex *)NULL == rv->crustylock ) {
80 return (nss_dbm_db_t *)NULL;
83 db_version = nss_dbm_db_get_format_version(rv);
84 if( db_version.major != nss_dbm_db_format_version.major ) {
85 nss_dbm_db_close(rv);
86 *pError = CKR_TOKEN_NOT_RECOGNIZED;
87 return (nss_dbm_db_t *)NULL;
90 return rv;
93 NSS_IMPLEMENT void
94 nss_dbm_db_close
96 nss_dbm_db_t *db
99 if( (NSSCKFWMutex *)NULL != db->crustylock ) {
100 (void)NSSCKFWMutex_Destroy(db->crustylock);
103 if( (DB *)NULL != db->db ) {
104 (void)db->db->close(db->db);
107 nss_ZFreeIf(db);
110 NSS_IMPLEMENT CK_VERSION
111 nss_dbm_db_get_format_version
113 nss_dbm_db_t *db
116 CK_VERSION rv;
117 DBT k, v;
118 int dbrv;
119 char buffer[64];
121 rv.major = rv.minor = 0;
123 k.data = PREFIX_METADATA "FormatVersion";
124 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
125 (void)memset(&v, 0, sizeof(v));
127 /* Locked region */
129 if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
130 return rv;
133 dbrv = db->db->get(db->db, &k, &v, 0);
134 if( dbrv == 0 ) {
135 CK_ULONG major = 0, minor = 0;
136 (void)PR_sscanf(v.data, "%ld.%ld", &major, &minor);
137 rv.major = major;
138 rv.minor = minor;
139 } else if( dbrv > 0 ) {
140 (void)PR_snprintf(buffer, sizeof(buffer), "%ld.%ld", nss_dbm_db_format_version.major,
141 nss_dbm_db_format_version.minor);
142 v.data = buffer;
143 v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
144 dbrv = db->db->put(db->db, &k, &v, 0);
145 (void)db->db->sync(db->db, 0);
146 rv = nss_dbm_db_format_version;
147 } else {
148 /* No error return.. */
152 (void)NSSCKFWMutex_Unlock(db->crustylock);
155 return rv;
158 NSS_IMPLEMENT CK_RV
159 nss_dbm_db_set_label
161 nss_dbm_db_t *db,
162 NSSUTF8 *label
165 CK_RV rv;
166 DBT k, v;
167 int dbrv;
169 k.data = PREFIX_METADATA "Label";
170 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
171 v.data = label;
172 v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL);
174 /* Locked region */
176 if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
177 return rv;
180 dbrv = db->db->put(db->db, &k, &v, 0);
181 if( 0 != dbrv ) {
182 rv = CKR_DEVICE_ERROR;
185 dbrv = db->db->sync(db->db, 0);
186 if( 0 != dbrv ) {
187 rv = CKR_DEVICE_ERROR;
190 (void)NSSCKFWMutex_Unlock(db->crustylock);
193 return rv;
196 NSS_IMPLEMENT NSSUTF8 *
197 nss_dbm_db_get_label
199 nss_dbm_db_t *db,
200 NSSArena *arena,
201 CK_RV *pError
204 NSSUTF8 *rv = (NSSUTF8 *)NULL;
205 DBT k, v;
206 int dbrv;
208 k.data = PREFIX_METADATA "Label";
209 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
211 /* Locked region */
213 if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) {
214 return rv;
217 dbrv = db->db->get(db->db, &k, &v, 0);
218 if( 0 == dbrv ) {
219 rv = nssUTF8_Duplicate((NSSUTF8 *)v.data, arena);
220 if( (NSSUTF8 *)NULL == rv ) {
221 *pError = CKR_HOST_MEMORY;
223 } else if( dbrv > 0 ) {
224 /* Just return null */
226 } else {
227 *pError = CKR_DEVICE_ERROR;
232 (void)NSSCKFWMutex_Unlock(db->crustylock);
235 return rv;
238 NSS_IMPLEMENT CK_RV
239 nss_dbm_db_delete_object
241 nss_dbm_dbt_t *dbt
244 CK_RV rv;
245 int dbrv;
247 /* Locked region */
249 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
250 if( CKR_OK != rv ) {
251 return rv;
254 dbrv = dbt->my_db->db->del(dbt->my_db->db, &dbt->dbt, 0);
255 if( 0 != dbrv ) {
256 rv = CKR_DEVICE_ERROR;
257 goto done;
260 dbrv = dbt->my_db->db->sync(dbt->my_db->db, 0);
261 if( 0 != dbrv ) {
262 rv = CKR_DEVICE_ERROR;
263 goto done;
266 done:
267 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
270 return rv;
273 static CK_ULONG
274 nss_dbm_db_new_handle
276 nss_dbm_db_t *db,
277 DBT *dbt, /* pre-allocated */
278 CK_RV *pError
281 CK_ULONG rv;
282 DBT k, v;
283 CK_ULONG align = 0, id, myid;
284 struct handle *hp;
286 if( sizeof(struct handle) != dbt->size ) {
287 return EINVAL;
290 /* Locked region */
292 *pError = NSSCKFWMutex_Lock(db->crustylock);
293 if( CKR_OK != *pError ) {
294 return EINVAL;
297 k.data = PREFIX_METADATA "LastID";
298 k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL);
299 (void)memset(&v, 0, sizeof(v));
301 rv = db->db->get(db->db, &k, &v, 0);
302 if( 0 == rv ) {
303 (void)memcpy(&align, v.data, sizeof(CK_ULONG));
304 id = ntohl(align);
305 } else if( rv > 0 ) {
306 id = 0;
307 } else {
308 goto done;
311 myid = id;
312 id++;
313 align = htonl(id);
314 v.data = &align;
315 v.size = sizeof(CK_ULONG);
317 rv = db->db->put(db->db, &k, &v, 0);
318 if( 0 != rv ) {
319 goto done;
322 rv = db->db->sync(db->db, 0);
323 if( 0 != rv ) {
324 goto done;
327 done:
328 (void)NSSCKFWMutex_Unlock(db->crustylock);
331 if( 0 != rv ) {
332 return rv;
335 hp = (struct handle *)dbt->data;
336 (void)memcpy(&hp->prefix[0], PREFIX_OBJECT, 4);
337 hp->id = myid;
339 return 0;
343 * This attribute-type-dependent swapping should probably
344 * be in the Framework, because it'll be a concern of just
345 * about every Module. Of course any Framework implementation
346 * will have to be augmentable or overridable by a Module.
349 enum swap_type { type_byte, type_short, type_long, type_opaque };
351 static enum swap_type
352 nss_dbm_db_swap_type
354 CK_ATTRIBUTE_TYPE type
357 switch( type ) {
358 case CKA_CLASS: return type_long;
359 case CKA_TOKEN: return type_byte;
360 case CKA_PRIVATE: return type_byte;
361 case CKA_LABEL: return type_opaque;
362 case CKA_APPLICATION: return type_opaque;
363 case CKA_VALUE: return type_opaque;
364 case CKA_CERTIFICATE_TYPE: return type_long;
365 case CKA_ISSUER: return type_opaque;
366 case CKA_SERIAL_NUMBER: return type_opaque;
367 case CKA_KEY_TYPE: return type_long;
368 case CKA_SUBJECT: return type_opaque;
369 case CKA_ID: return type_opaque;
370 case CKA_SENSITIVE: return type_byte;
371 case CKA_ENCRYPT: return type_byte;
372 case CKA_DECRYPT: return type_byte;
373 case CKA_WRAP: return type_byte;
374 case CKA_UNWRAP: return type_byte;
375 case CKA_SIGN: return type_byte;
376 case CKA_SIGN_RECOVER: return type_byte;
377 case CKA_VERIFY: return type_byte;
378 case CKA_VERIFY_RECOVER: return type_byte;
379 case CKA_DERIVE: return type_byte;
380 case CKA_START_DATE: return type_opaque;
381 case CKA_END_DATE: return type_opaque;
382 case CKA_MODULUS: return type_opaque;
383 case CKA_MODULUS_BITS: return type_long;
384 case CKA_PUBLIC_EXPONENT: return type_opaque;
385 case CKA_PRIVATE_EXPONENT: return type_opaque;
386 case CKA_PRIME_1: return type_opaque;
387 case CKA_PRIME_2: return type_opaque;
388 case CKA_EXPONENT_1: return type_opaque;
389 case CKA_EXPONENT_2: return type_opaque;
390 case CKA_COEFFICIENT: return type_opaque;
391 case CKA_PRIME: return type_opaque;
392 case CKA_SUBPRIME: return type_opaque;
393 case CKA_BASE: return type_opaque;
394 case CKA_VALUE_BITS: return type_long;
395 case CKA_VALUE_LEN: return type_long;
396 case CKA_EXTRACTABLE: return type_byte;
397 case CKA_LOCAL: return type_byte;
398 case CKA_NEVER_EXTRACTABLE: return type_byte;
399 case CKA_ALWAYS_SENSITIVE: return type_byte;
400 case CKA_MODIFIABLE: return type_byte;
401 case CKA_NETSCAPE_URL: return type_opaque;
402 case CKA_NETSCAPE_EMAIL: return type_opaque;
403 case CKA_NETSCAPE_SMIME_INFO: return type_opaque;
404 case CKA_NETSCAPE_SMIME_TIMESTAMP: return type_opaque;
405 case CKA_NETSCAPE_PKCS8_SALT: return type_opaque;
406 case CKA_NETSCAPE_PASSWORD_CHECK: return type_opaque;
407 case CKA_NETSCAPE_EXPIRES: return type_opaque;
408 case CKA_TRUST_DIGITAL_SIGNATURE: return type_long;
409 case CKA_TRUST_NON_REPUDIATION: return type_long;
410 case CKA_TRUST_KEY_ENCIPHERMENT: return type_long;
411 case CKA_TRUST_DATA_ENCIPHERMENT: return type_long;
412 case CKA_TRUST_KEY_AGREEMENT: return type_long;
413 case CKA_TRUST_KEY_CERT_SIGN: return type_long;
414 case CKA_TRUST_CRL_SIGN: return type_long;
415 case CKA_TRUST_SERVER_AUTH: return type_long;
416 case CKA_TRUST_CLIENT_AUTH: return type_long;
417 case CKA_TRUST_CODE_SIGNING: return type_long;
418 case CKA_TRUST_EMAIL_PROTECTION: return type_long;
419 case CKA_TRUST_IPSEC_END_SYSTEM: return type_long;
420 case CKA_TRUST_IPSEC_TUNNEL: return type_long;
421 case CKA_TRUST_IPSEC_USER: return type_long;
422 case CKA_TRUST_TIME_STAMPING: return type_long;
423 case CKA_NETSCAPE_DB: return type_opaque;
424 case CKA_NETSCAPE_TRUST: return type_opaque;
425 default: return type_opaque;
429 static void
430 nss_dbm_db_swap_copy
432 CK_ATTRIBUTE_TYPE type,
433 void *dest,
434 void *src,
435 CK_ULONG len
438 switch( nss_dbm_db_swap_type(type) ) {
439 case type_byte:
440 case type_opaque:
441 (void)memcpy(dest, src, len);
442 break;
443 case type_short:
445 CK_USHORT s, d;
446 (void)memcpy(&s, src, sizeof(CK_USHORT));
447 d = htons(s);
448 (void)memcpy(dest, &d, sizeof(CK_USHORT));
449 break;
451 case type_long:
453 CK_ULONG s, d;
454 (void)memcpy(&s, src, sizeof(CK_ULONG));
455 d = htonl(s);
456 (void)memcpy(dest, &d, sizeof(CK_ULONG));
457 break;
462 static CK_RV
463 nss_dbm_db_wrap_object
465 NSSArena *arena,
466 CK_ATTRIBUTE_PTR pTemplate,
467 CK_ULONG ulAttributeCount,
468 DBT *object
471 CK_ULONG object_size;
472 CK_ULONG i;
473 CK_ULONG *pulData;
474 char *pcData;
475 CK_ULONG offset;
477 object_size = (1 + ulAttributeCount*3) * sizeof(CK_ULONG);
478 offset = object_size;
479 for( i = 0; i < ulAttributeCount; i++ ) {
480 object_size += pTemplate[i].ulValueLen;
483 object->size = object_size;
484 object->data = nss_ZAlloc(arena, object_size);
485 if( (void *)NULL == object->data ) {
486 return CKR_HOST_MEMORY;
489 pulData = (CK_ULONG *)object->data;
490 pcData = (char *)object->data;
492 pulData[0] = htonl(ulAttributeCount);
493 for( i = 0; i < ulAttributeCount; i++ ) {
494 CK_ULONG len = pTemplate[i].ulValueLen;
495 pulData[1 + i*3] = htonl(pTemplate[i].type);
496 pulData[2 + i*3] = htonl(len);
497 pulData[3 + i*3] = htonl(offset);
498 nss_dbm_db_swap_copy(pTemplate[i].type, &pcData[offset], pTemplate[i].pValue, len);
499 offset += len;
502 return CKR_OK;
505 static CK_RV
506 nss_dbm_db_unwrap_object
508 NSSArena *arena,
509 DBT *object,
510 CK_ATTRIBUTE_PTR *ppTemplate,
511 CK_ULONG *pulAttributeCount
514 CK_ULONG *pulData;
515 char *pcData;
516 CK_ULONG n, i;
517 CK_ATTRIBUTE_PTR pTemplate;
519 pulData = (CK_ULONG *)object->data;
520 pcData = (char *)object->data;
522 n = ntohl(pulData[0]);
523 *pulAttributeCount = n;
524 pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n);
525 if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
526 return CKR_HOST_MEMORY;
529 for( i = 0; i < n; i++ ) {
530 CK_ULONG len;
531 CK_ULONG offset;
532 void *p;
534 pTemplate[i].type = ntohl(pulData[1 + i*3]);
535 len = ntohl(pulData[2 + i*3]);
536 offset = ntohl(pulData[3 + i*3]);
538 p = nss_ZAlloc(arena, len);
539 if( (void *)NULL == p ) {
540 return CKR_HOST_MEMORY;
543 nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len);
544 pTemplate[i].ulValueLen = len;
545 pTemplate[i].pValue = p;
548 *ppTemplate = pTemplate;
549 return CKR_OK;
553 NSS_IMPLEMENT nss_dbm_dbt_t *
554 nss_dbm_db_create_object
556 NSSArena *arena,
557 nss_dbm_db_t *db,
558 CK_ATTRIBUTE_PTR pTemplate,
559 CK_ULONG ulAttributeCount,
560 CK_RV *pError,
561 CK_ULONG *pdbrv
564 NSSArena *tmparena = (NSSArena *)NULL;
565 nss_dbm_dbt_t *rv = (nss_dbm_dbt_t *)NULL;
566 DBT object;
568 rv = nss_ZNEW(arena, nss_dbm_dbt_t);
569 if( (nss_dbm_dbt_t *)NULL == rv ) {
570 *pError = CKR_HOST_MEMORY;
571 return (nss_dbm_dbt_t *)NULL;
574 rv->my_db = db;
575 rv->dbt.size = sizeof(struct handle);
576 rv->dbt.data = nss_ZAlloc(arena, rv->dbt.size);
577 if( (void *)NULL == rv->dbt.data ) {
578 *pError = CKR_HOST_MEMORY;
579 return (nss_dbm_dbt_t *)NULL;
582 *pdbrv = nss_dbm_db_new_handle(db, &rv->dbt, pError);
583 if( 0 != *pdbrv ) {
584 return (nss_dbm_dbt_t *)NULL;
587 tmparena = NSSArena_Create();
588 if( (NSSArena *)NULL == tmparena ) {
589 *pError = CKR_HOST_MEMORY;
590 return (nss_dbm_dbt_t *)NULL;
593 *pError = nss_dbm_db_wrap_object(tmparena, pTemplate, ulAttributeCount, &object);
594 if( CKR_OK != *pError ) {
595 return (nss_dbm_dbt_t *)NULL;
598 /* Locked region */
600 *pError = NSSCKFWMutex_Lock(db->crustylock);
601 if( CKR_OK != *pError ) {
602 goto loser;
605 *pdbrv = db->db->put(db->db, &rv->dbt, &object, 0);
606 if( 0 != *pdbrv ) {
607 *pError = CKR_DEVICE_ERROR;
610 (void)db->db->sync(db->db, 0);
612 (void)NSSCKFWMutex_Unlock(db->crustylock);
615 loser:
616 if( (NSSArena *)NULL != tmparena ) {
617 (void)NSSArena_Destroy(tmparena);
620 return rv;
624 NSS_IMPLEMENT CK_RV
625 nss_dbm_db_find_objects
627 nss_dbm_find_t *find,
628 nss_dbm_db_t *db,
629 CK_ATTRIBUTE_PTR pTemplate,
630 CK_ULONG ulAttributeCount,
631 CK_ULONG *pdbrv
634 CK_RV rv = CKR_OK;
636 if( (nss_dbm_db_t *)NULL != db ) {
637 DBT k, v;
639 rv = NSSCKFWMutex_Lock(db->crustylock);
640 if( CKR_OK != rv ) {
641 return rv;
644 *pdbrv = db->db->seq(db->db, &k, &v, R_FIRST);
645 while( 0 == *pdbrv ) {
646 CK_ULONG i, j;
647 NSSArena *tmparena = (NSSArena *)NULL;
648 CK_ULONG ulac;
649 CK_ATTRIBUTE_PTR pt;
651 if( (k.size < 4) || (0 != memcmp(k.data, PREFIX_OBJECT, 4)) ) {
652 goto nomatch;
655 tmparena = NSSArena_Create();
657 rv = nss_dbm_db_unwrap_object(tmparena, &v, &pt, &ulac);
658 if( CKR_OK != rv ) {
659 goto loser;
662 for( i = 0; i < ulAttributeCount; i++ ) {
663 for( j = 0; j < ulac; j++ ) {
664 if( pTemplate[i].type == pt[j].type ) {
665 if( pTemplate[i].ulValueLen != pt[j].ulValueLen ) {
666 goto nomatch;
668 if( 0 != memcmp(pTemplate[i].pValue, pt[j].pValue, pt[j].ulValueLen) ) {
669 goto nomatch;
671 break;
674 if( j == ulac ) {
675 goto nomatch;
679 /* entire template matches */
681 struct nss_dbm_dbt_node *node;
683 node = nss_ZNEW(find->arena, struct nss_dbm_dbt_node);
684 if( (struct nss_dbm_dbt_node *)NULL == node ) {
685 rv = CKR_HOST_MEMORY;
686 goto loser;
689 node->dbt = nss_ZNEW(find->arena, nss_dbm_dbt_t);
690 if( (nss_dbm_dbt_t *)NULL == node->dbt ) {
691 rv = CKR_HOST_MEMORY;
692 goto loser;
695 node->dbt->dbt.size = k.size;
696 node->dbt->dbt.data = nss_ZAlloc(find->arena, k.size);
697 if( (void *)NULL == node->dbt->dbt.data ) {
698 rv = CKR_HOST_MEMORY;
699 goto loser;
702 (void)memcpy(node->dbt->dbt.data, k.data, k.size);
704 node->dbt->my_db = db;
706 node->next = find->found;
707 find->found = node;
710 nomatch:
711 if( (NSSArena *)NULL != tmparena ) {
712 (void)NSSArena_Destroy(tmparena);
714 *pdbrv = db->db->seq(db->db, &k, &v, R_NEXT);
717 if( *pdbrv < 0 ) {
718 rv = CKR_DEVICE_ERROR;
719 goto loser;
722 rv = CKR_OK;
724 loser:
725 (void)NSSCKFWMutex_Unlock(db->crustylock);
728 return rv;
731 NSS_IMPLEMENT CK_BBOOL
732 nss_dbm_db_object_still_exists
734 nss_dbm_dbt_t *dbt
737 CK_BBOOL rv;
738 CK_RV ckrv;
739 int dbrv;
740 DBT object;
742 ckrv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
743 if( CKR_OK != ckrv ) {
744 return CK_FALSE;
747 dbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
748 if( 0 == dbrv ) {
749 rv = CK_TRUE;
750 } else {
751 rv = CK_FALSE;
754 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
756 return rv;
759 NSS_IMPLEMENT CK_ULONG
760 nss_dbm_db_get_object_attribute_count
762 nss_dbm_dbt_t *dbt,
763 CK_RV *pError,
764 CK_ULONG *pdbrv
767 CK_ULONG rv = 0;
768 DBT object;
769 CK_ULONG *pulData;
771 /* Locked region */
773 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
774 if( CKR_OK != *pError ) {
775 return rv;
778 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
779 if( 0 == *pdbrv ) {
781 } else if( *pdbrv > 0 ) {
782 *pError = CKR_OBJECT_HANDLE_INVALID;
783 goto done;
784 } else {
785 *pError = CKR_DEVICE_ERROR;
786 goto done;
789 pulData = (CK_ULONG *)object.data;
790 rv = ntohl(pulData[0]);
792 done:
793 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
796 return rv;
799 NSS_IMPLEMENT CK_RV
800 nss_dbm_db_get_object_attribute_types
802 nss_dbm_dbt_t *dbt,
803 CK_ATTRIBUTE_TYPE_PTR typeArray,
804 CK_ULONG ulCount,
805 CK_ULONG *pdbrv
808 CK_RV rv = CKR_OK;
809 DBT object;
810 CK_ULONG *pulData;
811 CK_ULONG n, i;
813 /* Locked region */
815 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
816 if( CKR_OK != rv ) {
817 return rv;
820 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
821 if( 0 == *pdbrv ) {
823 } else if( *pdbrv > 0 ) {
824 rv = CKR_OBJECT_HANDLE_INVALID;
825 goto done;
826 } else {
827 rv = CKR_DEVICE_ERROR;
828 goto done;
831 pulData = (CK_ULONG *)object.data;
832 n = ntohl(pulData[0]);
834 if( ulCount < n ) {
835 rv = CKR_BUFFER_TOO_SMALL;
836 goto done;
839 for( i = 0; i < n; i++ ) {
840 typeArray[i] = ntohl(pulData[1 + i*3]);
843 done:
844 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
847 return rv;
850 NSS_IMPLEMENT CK_ULONG
851 nss_dbm_db_get_object_attribute_size
853 nss_dbm_dbt_t *dbt,
854 CK_ATTRIBUTE_TYPE type,
855 CK_RV *pError,
856 CK_ULONG *pdbrv
859 CK_ULONG rv = 0;
860 DBT object;
861 CK_ULONG *pulData;
862 CK_ULONG n, i;
864 /* Locked region */
866 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
867 if( CKR_OK != *pError ) {
868 return rv;
871 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
872 if( 0 == *pdbrv ) {
874 } else if( *pdbrv > 0 ) {
875 *pError = CKR_OBJECT_HANDLE_INVALID;
876 goto done;
877 } else {
878 *pError = CKR_DEVICE_ERROR;
879 goto done;
882 pulData = (CK_ULONG *)object.data;
883 n = ntohl(pulData[0]);
885 for( i = 0; i < n; i++ ) {
886 if( type == ntohl(pulData[1 + i*3]) ) {
887 rv = ntohl(pulData[2 + i*3]);
891 if( i == n ) {
892 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
893 goto done;
896 done:
897 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
900 return rv;
903 NSS_IMPLEMENT NSSItem *
904 nss_dbm_db_get_object_attribute
906 nss_dbm_dbt_t *dbt,
907 NSSArena *arena,
908 CK_ATTRIBUTE_TYPE type,
909 CK_RV *pError,
910 CK_ULONG *pdbrv
913 NSSItem *rv = (NSSItem *)NULL;
914 DBT object;
915 CK_ULONG i;
916 NSSArena *tmp = NSSArena_Create();
917 CK_ATTRIBUTE_PTR pTemplate;
918 CK_ULONG ulAttributeCount;
920 /* Locked region */
922 *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
923 if( CKR_OK != *pError ) {
924 goto loser;
927 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
928 if( 0 == *pdbrv ) {
930 } else if( *pdbrv > 0 ) {
931 *pError = CKR_OBJECT_HANDLE_INVALID;
932 goto done;
933 } else {
934 *pError = CKR_DEVICE_ERROR;
935 goto done;
938 *pError = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
939 if( CKR_OK != *pError ) {
940 goto done;
943 for( i = 0; i < ulAttributeCount; i++ ) {
944 if( type == pTemplate[i].type ) {
945 rv = nss_ZNEW(arena, NSSItem);
946 if( (NSSItem *)NULL == rv ) {
947 *pError = CKR_HOST_MEMORY;
948 goto done;
950 rv->size = pTemplate[i].ulValueLen;
951 rv->data = nss_ZAlloc(arena, rv->size);
952 if( (void *)NULL == rv->data ) {
953 *pError = CKR_HOST_MEMORY;
954 goto done;
956 (void)memcpy(rv->data, pTemplate[i].pValue, rv->size);
957 break;
960 if( ulAttributeCount == i ) {
961 *pError = CKR_ATTRIBUTE_TYPE_INVALID;
962 goto done;
965 done:
966 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
969 loser:
970 if( (NSSArena *)NULL != tmp ) {
971 NSSArena_Destroy(tmp);
974 return rv;
977 NSS_IMPLEMENT CK_RV
978 nss_dbm_db_set_object_attribute
980 nss_dbm_dbt_t *dbt,
981 CK_ATTRIBUTE_TYPE type,
982 NSSItem *value,
983 CK_ULONG *pdbrv
986 CK_RV rv = CKR_OK;
987 DBT object;
988 CK_ULONG i;
989 NSSArena *tmp = NSSArena_Create();
990 CK_ATTRIBUTE_PTR pTemplate;
991 CK_ULONG ulAttributeCount;
993 /* Locked region */
995 rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock);
996 if( CKR_OK != rv ) {
997 goto loser;
1000 *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0);
1001 if( 0 == *pdbrv ) {
1003 } else if( *pdbrv > 0 ) {
1004 rv = CKR_OBJECT_HANDLE_INVALID;
1005 goto done;
1006 } else {
1007 rv = CKR_DEVICE_ERROR;
1008 goto done;
1011 rv = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount);
1012 if( CKR_OK != rv ) {
1013 goto done;
1016 for( i = 0; i < ulAttributeCount; i++ ) {
1017 if( type == pTemplate[i].type ) {
1018 /* Replacing an existing attribute */
1019 pTemplate[i].ulValueLen = value->size;
1020 pTemplate[i].pValue = value->data;
1021 break;
1025 if( i == ulAttributeCount ) {
1026 /* Adding a new attribute */
1027 CK_ATTRIBUTE_PTR npt = nss_ZNEWARRAY(tmp, CK_ATTRIBUTE, ulAttributeCount+1);
1028 if( (CK_ATTRIBUTE_PTR)NULL == npt ) {
1029 rv = CKR_DEVICE_ERROR;
1030 goto done;
1033 for( i = 0; i < ulAttributeCount; i++ ) {
1034 npt[i] = pTemplate[i];
1037 npt[ulAttributeCount].type = type;
1038 npt[ulAttributeCount].ulValueLen = value->size;
1039 npt[ulAttributeCount].pValue = value->data;
1041 pTemplate = npt;
1042 ulAttributeCount++;
1045 rv = nss_dbm_db_wrap_object(tmp, pTemplate, ulAttributeCount, &object);
1046 if( CKR_OK != rv ) {
1047 goto done;
1050 *pdbrv = dbt->my_db->db->put(dbt->my_db->db, &dbt->dbt, &object, 0);
1051 if( 0 != *pdbrv ) {
1052 rv = CKR_DEVICE_ERROR;
1053 goto done;
1056 (void)dbt->my_db->db->sync(dbt->my_db->db, 0);
1058 done:
1059 (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock);
1062 loser:
1063 if( (NSSArena *)NULL != tmp ) {
1064 NSSArena_Destroy(tmp);
1067 return rv;