db.c (26773B)
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 * 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 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 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 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 * 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 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 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 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 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 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 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 * 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 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 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 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 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 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 * 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 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 }