security/nss/lib/ckfw/dbm/db.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial