1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ckfw/dbm/db.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1032 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "ckdbm.h" 1.9 + 1.10 +#define PREFIX_METADATA "0000" 1.11 +#define PREFIX_OBJECT "0001" 1.12 +#define PREFIX_INDEX "0002" 1.13 + 1.14 +static CK_VERSION nss_dbm_db_format_version = { 1, 0 }; 1.15 +struct handle { 1.16 + char prefix[4]; 1.17 + CK_ULONG id; 1.18 +}; 1.19 + 1.20 +NSS_IMPLEMENT nss_dbm_db_t * 1.21 +nss_dbm_db_open 1.22 +( 1.23 + NSSArena *arena, 1.24 + NSSCKFWInstance *fwInstance, 1.25 + char *filename, 1.26 + int flags, 1.27 + CK_RV *pError 1.28 +) 1.29 +{ 1.30 + nss_dbm_db_t *rv; 1.31 + CK_VERSION db_version; 1.32 + 1.33 + rv = nss_ZNEW(arena, nss_dbm_db_t); 1.34 + if( (nss_dbm_db_t *)NULL == rv ) { 1.35 + *pError = CKR_HOST_MEMORY; 1.36 + return (nss_dbm_db_t *)NULL; 1.37 + } 1.38 + 1.39 + rv->db = dbopen(filename, flags, 0600, DB_HASH, (const void *)NULL); 1.40 + if( (DB *)NULL == rv->db ) { 1.41 + *pError = CKR_TOKEN_NOT_PRESENT; 1.42 + return (nss_dbm_db_t *)NULL; 1.43 + } 1.44 + 1.45 + rv->crustylock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError); 1.46 + if( (NSSCKFWMutex *)NULL == rv->crustylock ) { 1.47 + return (nss_dbm_db_t *)NULL; 1.48 + } 1.49 + 1.50 + db_version = nss_dbm_db_get_format_version(rv); 1.51 + if( db_version.major != nss_dbm_db_format_version.major ) { 1.52 + nss_dbm_db_close(rv); 1.53 + *pError = CKR_TOKEN_NOT_RECOGNIZED; 1.54 + return (nss_dbm_db_t *)NULL; 1.55 + } 1.56 + 1.57 + return rv; 1.58 +} 1.59 + 1.60 +NSS_IMPLEMENT void 1.61 +nss_dbm_db_close 1.62 +( 1.63 + nss_dbm_db_t *db 1.64 +) 1.65 +{ 1.66 + if( (NSSCKFWMutex *)NULL != db->crustylock ) { 1.67 + (void)NSSCKFWMutex_Destroy(db->crustylock); 1.68 + } 1.69 + 1.70 + if( (DB *)NULL != db->db ) { 1.71 + (void)db->db->close(db->db); 1.72 + } 1.73 + 1.74 + nss_ZFreeIf(db); 1.75 +} 1.76 + 1.77 +NSS_IMPLEMENT CK_VERSION 1.78 +nss_dbm_db_get_format_version 1.79 +( 1.80 + nss_dbm_db_t *db 1.81 +) 1.82 +{ 1.83 + CK_VERSION rv; 1.84 + DBT k, v; 1.85 + int dbrv; 1.86 + char buffer[64]; 1.87 + 1.88 + rv.major = rv.minor = 0; 1.89 + 1.90 + k.data = PREFIX_METADATA "FormatVersion"; 1.91 + k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); 1.92 + (void)memset(&v, 0, sizeof(v)); 1.93 + 1.94 + /* Locked region */ 1.95 + { 1.96 + if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) { 1.97 + return rv; 1.98 + } 1.99 + 1.100 + dbrv = db->db->get(db->db, &k, &v, 0); 1.101 + if( dbrv == 0 ) { 1.102 + CK_ULONG major = 0, minor = 0; 1.103 + (void)PR_sscanf(v.data, "%ld.%ld", &major, &minor); 1.104 + rv.major = major; 1.105 + rv.minor = minor; 1.106 + } else if( dbrv > 0 ) { 1.107 + (void)PR_snprintf(buffer, sizeof(buffer), "%ld.%ld", nss_dbm_db_format_version.major, 1.108 + nss_dbm_db_format_version.minor); 1.109 + v.data = buffer; 1.110 + v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL); 1.111 + dbrv = db->db->put(db->db, &k, &v, 0); 1.112 + (void)db->db->sync(db->db, 0); 1.113 + rv = nss_dbm_db_format_version; 1.114 + } else { 1.115 + /* No error return.. */ 1.116 + ; 1.117 + } 1.118 + 1.119 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.120 + } 1.121 + 1.122 + return rv; 1.123 +} 1.124 + 1.125 +NSS_IMPLEMENT CK_RV 1.126 +nss_dbm_db_set_label 1.127 +( 1.128 + nss_dbm_db_t *db, 1.129 + NSSUTF8 *label 1.130 +) 1.131 +{ 1.132 + CK_RV rv; 1.133 + DBT k, v; 1.134 + int dbrv; 1.135 + 1.136 + k.data = PREFIX_METADATA "Label"; 1.137 + k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); 1.138 + v.data = label; 1.139 + v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL); 1.140 + 1.141 + /* Locked region */ 1.142 + { 1.143 + if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) { 1.144 + return rv; 1.145 + } 1.146 + 1.147 + dbrv = db->db->put(db->db, &k, &v, 0); 1.148 + if( 0 != dbrv ) { 1.149 + rv = CKR_DEVICE_ERROR; 1.150 + } 1.151 + 1.152 + dbrv = db->db->sync(db->db, 0); 1.153 + if( 0 != dbrv ) { 1.154 + rv = CKR_DEVICE_ERROR; 1.155 + } 1.156 + 1.157 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.158 + } 1.159 + 1.160 + return rv; 1.161 +} 1.162 + 1.163 +NSS_IMPLEMENT NSSUTF8 * 1.164 +nss_dbm_db_get_label 1.165 +( 1.166 + nss_dbm_db_t *db, 1.167 + NSSArena *arena, 1.168 + CK_RV *pError 1.169 +) 1.170 +{ 1.171 + NSSUTF8 *rv = (NSSUTF8 *)NULL; 1.172 + DBT k, v; 1.173 + int dbrv; 1.174 + 1.175 + k.data = PREFIX_METADATA "Label"; 1.176 + k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); 1.177 + 1.178 + /* Locked region */ 1.179 + { 1.180 + if( CKR_OK != NSSCKFWMutex_Lock(db->crustylock) ) { 1.181 + return rv; 1.182 + } 1.183 + 1.184 + dbrv = db->db->get(db->db, &k, &v, 0); 1.185 + if( 0 == dbrv ) { 1.186 + rv = nssUTF8_Duplicate((NSSUTF8 *)v.data, arena); 1.187 + if( (NSSUTF8 *)NULL == rv ) { 1.188 + *pError = CKR_HOST_MEMORY; 1.189 + } 1.190 + } else if( dbrv > 0 ) { 1.191 + /* Just return null */ 1.192 + ; 1.193 + } else { 1.194 + *pError = CKR_DEVICE_ERROR; 1.195 + ; 1.196 + } 1.197 + 1.198 + 1.199 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.200 + } 1.201 + 1.202 + return rv; 1.203 +} 1.204 + 1.205 +NSS_IMPLEMENT CK_RV 1.206 +nss_dbm_db_delete_object 1.207 +( 1.208 + nss_dbm_dbt_t *dbt 1.209 +) 1.210 +{ 1.211 + CK_RV rv; 1.212 + int dbrv; 1.213 + 1.214 + /* Locked region */ 1.215 + { 1.216 + rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.217 + if( CKR_OK != rv ) { 1.218 + return rv; 1.219 + } 1.220 + 1.221 + dbrv = dbt->my_db->db->del(dbt->my_db->db, &dbt->dbt, 0); 1.222 + if( 0 != dbrv ) { 1.223 + rv = CKR_DEVICE_ERROR; 1.224 + goto done; 1.225 + } 1.226 + 1.227 + dbrv = dbt->my_db->db->sync(dbt->my_db->db, 0); 1.228 + if( 0 != dbrv ) { 1.229 + rv = CKR_DEVICE_ERROR; 1.230 + goto done; 1.231 + } 1.232 + 1.233 + done: 1.234 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.235 + } 1.236 + 1.237 + return rv; 1.238 +} 1.239 + 1.240 +static CK_ULONG 1.241 +nss_dbm_db_new_handle 1.242 +( 1.243 + nss_dbm_db_t *db, 1.244 + DBT *dbt, /* pre-allocated */ 1.245 + CK_RV *pError 1.246 +) 1.247 +{ 1.248 + CK_ULONG rv; 1.249 + DBT k, v; 1.250 + CK_ULONG align = 0, id, myid; 1.251 + struct handle *hp; 1.252 + 1.253 + if( sizeof(struct handle) != dbt->size ) { 1.254 + return EINVAL; 1.255 + } 1.256 + 1.257 + /* Locked region */ 1.258 + { 1.259 + *pError = NSSCKFWMutex_Lock(db->crustylock); 1.260 + if( CKR_OK != *pError ) { 1.261 + return EINVAL; 1.262 + } 1.263 + 1.264 + k.data = PREFIX_METADATA "LastID"; 1.265 + k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); 1.266 + (void)memset(&v, 0, sizeof(v)); 1.267 + 1.268 + rv = db->db->get(db->db, &k, &v, 0); 1.269 + if( 0 == rv ) { 1.270 + (void)memcpy(&align, v.data, sizeof(CK_ULONG)); 1.271 + id = ntohl(align); 1.272 + } else if( rv > 0 ) { 1.273 + id = 0; 1.274 + } else { 1.275 + goto done; 1.276 + } 1.277 + 1.278 + myid = id; 1.279 + id++; 1.280 + align = htonl(id); 1.281 + v.data = &align; 1.282 + v.size = sizeof(CK_ULONG); 1.283 + 1.284 + rv = db->db->put(db->db, &k, &v, 0); 1.285 + if( 0 != rv ) { 1.286 + goto done; 1.287 + } 1.288 + 1.289 + rv = db->db->sync(db->db, 0); 1.290 + if( 0 != rv ) { 1.291 + goto done; 1.292 + } 1.293 + 1.294 + done: 1.295 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.296 + } 1.297 + 1.298 + if( 0 != rv ) { 1.299 + return rv; 1.300 + } 1.301 + 1.302 + hp = (struct handle *)dbt->data; 1.303 + (void)memcpy(&hp->prefix[0], PREFIX_OBJECT, 4); 1.304 + hp->id = myid; 1.305 + 1.306 + return 0; 1.307 +} 1.308 + 1.309 +/* 1.310 + * This attribute-type-dependent swapping should probably 1.311 + * be in the Framework, because it'll be a concern of just 1.312 + * about every Module. Of course any Framework implementation 1.313 + * will have to be augmentable or overridable by a Module. 1.314 + */ 1.315 + 1.316 +enum swap_type { type_byte, type_short, type_long, type_opaque }; 1.317 + 1.318 +static enum swap_type 1.319 +nss_dbm_db_swap_type 1.320 +( 1.321 + CK_ATTRIBUTE_TYPE type 1.322 +) 1.323 +{ 1.324 + switch( type ) { 1.325 + case CKA_CLASS: return type_long; 1.326 + case CKA_TOKEN: return type_byte; 1.327 + case CKA_PRIVATE: return type_byte; 1.328 + case CKA_LABEL: return type_opaque; 1.329 + case CKA_APPLICATION: return type_opaque; 1.330 + case CKA_VALUE: return type_opaque; 1.331 + case CKA_CERTIFICATE_TYPE: return type_long; 1.332 + case CKA_ISSUER: return type_opaque; 1.333 + case CKA_SERIAL_NUMBER: return type_opaque; 1.334 + case CKA_KEY_TYPE: return type_long; 1.335 + case CKA_SUBJECT: return type_opaque; 1.336 + case CKA_ID: return type_opaque; 1.337 + case CKA_SENSITIVE: return type_byte; 1.338 + case CKA_ENCRYPT: return type_byte; 1.339 + case CKA_DECRYPT: return type_byte; 1.340 + case CKA_WRAP: return type_byte; 1.341 + case CKA_UNWRAP: return type_byte; 1.342 + case CKA_SIGN: return type_byte; 1.343 + case CKA_SIGN_RECOVER: return type_byte; 1.344 + case CKA_VERIFY: return type_byte; 1.345 + case CKA_VERIFY_RECOVER: return type_byte; 1.346 + case CKA_DERIVE: return type_byte; 1.347 + case CKA_START_DATE: return type_opaque; 1.348 + case CKA_END_DATE: return type_opaque; 1.349 + case CKA_MODULUS: return type_opaque; 1.350 + case CKA_MODULUS_BITS: return type_long; 1.351 + case CKA_PUBLIC_EXPONENT: return type_opaque; 1.352 + case CKA_PRIVATE_EXPONENT: return type_opaque; 1.353 + case CKA_PRIME_1: return type_opaque; 1.354 + case CKA_PRIME_2: return type_opaque; 1.355 + case CKA_EXPONENT_1: return type_opaque; 1.356 + case CKA_EXPONENT_2: return type_opaque; 1.357 + case CKA_COEFFICIENT: return type_opaque; 1.358 + case CKA_PRIME: return type_opaque; 1.359 + case CKA_SUBPRIME: return type_opaque; 1.360 + case CKA_BASE: return type_opaque; 1.361 + case CKA_VALUE_BITS: return type_long; 1.362 + case CKA_VALUE_LEN: return type_long; 1.363 + case CKA_EXTRACTABLE: return type_byte; 1.364 + case CKA_LOCAL: return type_byte; 1.365 + case CKA_NEVER_EXTRACTABLE: return type_byte; 1.366 + case CKA_ALWAYS_SENSITIVE: return type_byte; 1.367 + case CKA_MODIFIABLE: return type_byte; 1.368 + case CKA_NETSCAPE_URL: return type_opaque; 1.369 + case CKA_NETSCAPE_EMAIL: return type_opaque; 1.370 + case CKA_NETSCAPE_SMIME_INFO: return type_opaque; 1.371 + case CKA_NETSCAPE_SMIME_TIMESTAMP: return type_opaque; 1.372 + case CKA_NETSCAPE_PKCS8_SALT: return type_opaque; 1.373 + case CKA_NETSCAPE_PASSWORD_CHECK: return type_opaque; 1.374 + case CKA_NETSCAPE_EXPIRES: return type_opaque; 1.375 + case CKA_TRUST_DIGITAL_SIGNATURE: return type_long; 1.376 + case CKA_TRUST_NON_REPUDIATION: return type_long; 1.377 + case CKA_TRUST_KEY_ENCIPHERMENT: return type_long; 1.378 + case CKA_TRUST_DATA_ENCIPHERMENT: return type_long; 1.379 + case CKA_TRUST_KEY_AGREEMENT: return type_long; 1.380 + case CKA_TRUST_KEY_CERT_SIGN: return type_long; 1.381 + case CKA_TRUST_CRL_SIGN: return type_long; 1.382 + case CKA_TRUST_SERVER_AUTH: return type_long; 1.383 + case CKA_TRUST_CLIENT_AUTH: return type_long; 1.384 + case CKA_TRUST_CODE_SIGNING: return type_long; 1.385 + case CKA_TRUST_EMAIL_PROTECTION: return type_long; 1.386 + case CKA_TRUST_IPSEC_END_SYSTEM: return type_long; 1.387 + case CKA_TRUST_IPSEC_TUNNEL: return type_long; 1.388 + case CKA_TRUST_IPSEC_USER: return type_long; 1.389 + case CKA_TRUST_TIME_STAMPING: return type_long; 1.390 + case CKA_NETSCAPE_DB: return type_opaque; 1.391 + case CKA_NETSCAPE_TRUST: return type_opaque; 1.392 + default: return type_opaque; 1.393 + } 1.394 +} 1.395 + 1.396 +static void 1.397 +nss_dbm_db_swap_copy 1.398 +( 1.399 + CK_ATTRIBUTE_TYPE type, 1.400 + void *dest, 1.401 + void *src, 1.402 + CK_ULONG len 1.403 +) 1.404 +{ 1.405 + switch( nss_dbm_db_swap_type(type) ) { 1.406 + case type_byte: 1.407 + case type_opaque: 1.408 + (void)memcpy(dest, src, len); 1.409 + break; 1.410 + case type_short: 1.411 + { 1.412 + CK_USHORT s, d; 1.413 + (void)memcpy(&s, src, sizeof(CK_USHORT)); 1.414 + d = htons(s); 1.415 + (void)memcpy(dest, &d, sizeof(CK_USHORT)); 1.416 + break; 1.417 + } 1.418 + case type_long: 1.419 + { 1.420 + CK_ULONG s, d; 1.421 + (void)memcpy(&s, src, sizeof(CK_ULONG)); 1.422 + d = htonl(s); 1.423 + (void)memcpy(dest, &d, sizeof(CK_ULONG)); 1.424 + break; 1.425 + } 1.426 + } 1.427 +} 1.428 + 1.429 +static CK_RV 1.430 +nss_dbm_db_wrap_object 1.431 +( 1.432 + NSSArena *arena, 1.433 + CK_ATTRIBUTE_PTR pTemplate, 1.434 + CK_ULONG ulAttributeCount, 1.435 + DBT *object 1.436 +) 1.437 +{ 1.438 + CK_ULONG object_size; 1.439 + CK_ULONG i; 1.440 + CK_ULONG *pulData; 1.441 + char *pcData; 1.442 + CK_ULONG offset; 1.443 + 1.444 + object_size = (1 + ulAttributeCount*3) * sizeof(CK_ULONG); 1.445 + offset = object_size; 1.446 + for( i = 0; i < ulAttributeCount; i++ ) { 1.447 + object_size += pTemplate[i].ulValueLen; 1.448 + } 1.449 + 1.450 + object->size = object_size; 1.451 + object->data = nss_ZAlloc(arena, object_size); 1.452 + if( (void *)NULL == object->data ) { 1.453 + return CKR_HOST_MEMORY; 1.454 + } 1.455 + 1.456 + pulData = (CK_ULONG *)object->data; 1.457 + pcData = (char *)object->data; 1.458 + 1.459 + pulData[0] = htonl(ulAttributeCount); 1.460 + for( i = 0; i < ulAttributeCount; i++ ) { 1.461 + CK_ULONG len = pTemplate[i].ulValueLen; 1.462 + pulData[1 + i*3] = htonl(pTemplate[i].type); 1.463 + pulData[2 + i*3] = htonl(len); 1.464 + pulData[3 + i*3] = htonl(offset); 1.465 + nss_dbm_db_swap_copy(pTemplate[i].type, &pcData[offset], pTemplate[i].pValue, len); 1.466 + offset += len; 1.467 + } 1.468 + 1.469 + return CKR_OK; 1.470 +} 1.471 + 1.472 +static CK_RV 1.473 +nss_dbm_db_unwrap_object 1.474 +( 1.475 + NSSArena *arena, 1.476 + DBT *object, 1.477 + CK_ATTRIBUTE_PTR *ppTemplate, 1.478 + CK_ULONG *pulAttributeCount 1.479 +) 1.480 +{ 1.481 + CK_ULONG *pulData; 1.482 + char *pcData; 1.483 + CK_ULONG n, i; 1.484 + CK_ATTRIBUTE_PTR pTemplate; 1.485 + 1.486 + pulData = (CK_ULONG *)object->data; 1.487 + pcData = (char *)object->data; 1.488 + 1.489 + n = ntohl(pulData[0]); 1.490 + *pulAttributeCount = n; 1.491 + pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n); 1.492 + if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) { 1.493 + return CKR_HOST_MEMORY; 1.494 + } 1.495 + 1.496 + for( i = 0; i < n; i++ ) { 1.497 + CK_ULONG len; 1.498 + CK_ULONG offset; 1.499 + void *p; 1.500 + 1.501 + pTemplate[i].type = ntohl(pulData[1 + i*3]); 1.502 + len = ntohl(pulData[2 + i*3]); 1.503 + offset = ntohl(pulData[3 + i*3]); 1.504 + 1.505 + p = nss_ZAlloc(arena, len); 1.506 + if( (void *)NULL == p ) { 1.507 + return CKR_HOST_MEMORY; 1.508 + } 1.509 + 1.510 + nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len); 1.511 + pTemplate[i].ulValueLen = len; 1.512 + pTemplate[i].pValue = p; 1.513 + } 1.514 + 1.515 + *ppTemplate = pTemplate; 1.516 + return CKR_OK; 1.517 +} 1.518 + 1.519 + 1.520 +NSS_IMPLEMENT nss_dbm_dbt_t * 1.521 +nss_dbm_db_create_object 1.522 +( 1.523 + NSSArena *arena, 1.524 + nss_dbm_db_t *db, 1.525 + CK_ATTRIBUTE_PTR pTemplate, 1.526 + CK_ULONG ulAttributeCount, 1.527 + CK_RV *pError, 1.528 + CK_ULONG *pdbrv 1.529 +) 1.530 +{ 1.531 + NSSArena *tmparena = (NSSArena *)NULL; 1.532 + nss_dbm_dbt_t *rv = (nss_dbm_dbt_t *)NULL; 1.533 + DBT object; 1.534 + 1.535 + rv = nss_ZNEW(arena, nss_dbm_dbt_t); 1.536 + if( (nss_dbm_dbt_t *)NULL == rv ) { 1.537 + *pError = CKR_HOST_MEMORY; 1.538 + return (nss_dbm_dbt_t *)NULL; 1.539 + } 1.540 + 1.541 + rv->my_db = db; 1.542 + rv->dbt.size = sizeof(struct handle); 1.543 + rv->dbt.data = nss_ZAlloc(arena, rv->dbt.size); 1.544 + if( (void *)NULL == rv->dbt.data ) { 1.545 + *pError = CKR_HOST_MEMORY; 1.546 + return (nss_dbm_dbt_t *)NULL; 1.547 + } 1.548 + 1.549 + *pdbrv = nss_dbm_db_new_handle(db, &rv->dbt, pError); 1.550 + if( 0 != *pdbrv ) { 1.551 + return (nss_dbm_dbt_t *)NULL; 1.552 + } 1.553 + 1.554 + tmparena = NSSArena_Create(); 1.555 + if( (NSSArena *)NULL == tmparena ) { 1.556 + *pError = CKR_HOST_MEMORY; 1.557 + return (nss_dbm_dbt_t *)NULL; 1.558 + } 1.559 + 1.560 + *pError = nss_dbm_db_wrap_object(tmparena, pTemplate, ulAttributeCount, &object); 1.561 + if( CKR_OK != *pError ) { 1.562 + return (nss_dbm_dbt_t *)NULL; 1.563 + } 1.564 + 1.565 + /* Locked region */ 1.566 + { 1.567 + *pError = NSSCKFWMutex_Lock(db->crustylock); 1.568 + if( CKR_OK != *pError ) { 1.569 + goto loser; 1.570 + } 1.571 + 1.572 + *pdbrv = db->db->put(db->db, &rv->dbt, &object, 0); 1.573 + if( 0 != *pdbrv ) { 1.574 + *pError = CKR_DEVICE_ERROR; 1.575 + } 1.576 + 1.577 + (void)db->db->sync(db->db, 0); 1.578 + 1.579 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.580 + } 1.581 + 1.582 + loser: 1.583 + if( (NSSArena *)NULL != tmparena ) { 1.584 + (void)NSSArena_Destroy(tmparena); 1.585 + } 1.586 + 1.587 + return rv; 1.588 +} 1.589 + 1.590 + 1.591 +NSS_IMPLEMENT CK_RV 1.592 +nss_dbm_db_find_objects 1.593 +( 1.594 + nss_dbm_find_t *find, 1.595 + nss_dbm_db_t *db, 1.596 + CK_ATTRIBUTE_PTR pTemplate, 1.597 + CK_ULONG ulAttributeCount, 1.598 + CK_ULONG *pdbrv 1.599 +) 1.600 +{ 1.601 + CK_RV rv = CKR_OK; 1.602 + 1.603 + if( (nss_dbm_db_t *)NULL != db ) { 1.604 + DBT k, v; 1.605 + 1.606 + rv = NSSCKFWMutex_Lock(db->crustylock); 1.607 + if( CKR_OK != rv ) { 1.608 + return rv; 1.609 + } 1.610 + 1.611 + *pdbrv = db->db->seq(db->db, &k, &v, R_FIRST); 1.612 + while( 0 == *pdbrv ) { 1.613 + CK_ULONG i, j; 1.614 + NSSArena *tmparena = (NSSArena *)NULL; 1.615 + CK_ULONG ulac; 1.616 + CK_ATTRIBUTE_PTR pt; 1.617 + 1.618 + if( (k.size < 4) || (0 != memcmp(k.data, PREFIX_OBJECT, 4)) ) { 1.619 + goto nomatch; 1.620 + } 1.621 + 1.622 + tmparena = NSSArena_Create(); 1.623 + 1.624 + rv = nss_dbm_db_unwrap_object(tmparena, &v, &pt, &ulac); 1.625 + if( CKR_OK != rv ) { 1.626 + goto loser; 1.627 + } 1.628 + 1.629 + for( i = 0; i < ulAttributeCount; i++ ) { 1.630 + for( j = 0; j < ulac; j++ ) { 1.631 + if( pTemplate[i].type == pt[j].type ) { 1.632 + if( pTemplate[i].ulValueLen != pt[j].ulValueLen ) { 1.633 + goto nomatch; 1.634 + } 1.635 + if( 0 != memcmp(pTemplate[i].pValue, pt[j].pValue, pt[j].ulValueLen) ) { 1.636 + goto nomatch; 1.637 + } 1.638 + break; 1.639 + } 1.640 + } 1.641 + if( j == ulac ) { 1.642 + goto nomatch; 1.643 + } 1.644 + } 1.645 + 1.646 + /* entire template matches */ 1.647 + { 1.648 + struct nss_dbm_dbt_node *node; 1.649 + 1.650 + node = nss_ZNEW(find->arena, struct nss_dbm_dbt_node); 1.651 + if( (struct nss_dbm_dbt_node *)NULL == node ) { 1.652 + rv = CKR_HOST_MEMORY; 1.653 + goto loser; 1.654 + } 1.655 + 1.656 + node->dbt = nss_ZNEW(find->arena, nss_dbm_dbt_t); 1.657 + if( (nss_dbm_dbt_t *)NULL == node->dbt ) { 1.658 + rv = CKR_HOST_MEMORY; 1.659 + goto loser; 1.660 + } 1.661 + 1.662 + node->dbt->dbt.size = k.size; 1.663 + node->dbt->dbt.data = nss_ZAlloc(find->arena, k.size); 1.664 + if( (void *)NULL == node->dbt->dbt.data ) { 1.665 + rv = CKR_HOST_MEMORY; 1.666 + goto loser; 1.667 + } 1.668 + 1.669 + (void)memcpy(node->dbt->dbt.data, k.data, k.size); 1.670 + 1.671 + node->dbt->my_db = db; 1.672 + 1.673 + node->next = find->found; 1.674 + find->found = node; 1.675 + } 1.676 + 1.677 + nomatch: 1.678 + if( (NSSArena *)NULL != tmparena ) { 1.679 + (void)NSSArena_Destroy(tmparena); 1.680 + } 1.681 + *pdbrv = db->db->seq(db->db, &k, &v, R_NEXT); 1.682 + } 1.683 + 1.684 + if( *pdbrv < 0 ) { 1.685 + rv = CKR_DEVICE_ERROR; 1.686 + goto loser; 1.687 + } 1.688 + 1.689 + rv = CKR_OK; 1.690 + 1.691 + loser: 1.692 + (void)NSSCKFWMutex_Unlock(db->crustylock); 1.693 + } 1.694 + 1.695 + return rv; 1.696 +} 1.697 + 1.698 +NSS_IMPLEMENT CK_BBOOL 1.699 +nss_dbm_db_object_still_exists 1.700 +( 1.701 + nss_dbm_dbt_t *dbt 1.702 +) 1.703 +{ 1.704 + CK_BBOOL rv; 1.705 + CK_RV ckrv; 1.706 + int dbrv; 1.707 + DBT object; 1.708 + 1.709 + ckrv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.710 + if( CKR_OK != ckrv ) { 1.711 + return CK_FALSE; 1.712 + } 1.713 + 1.714 + dbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.715 + if( 0 == dbrv ) { 1.716 + rv = CK_TRUE; 1.717 + } else { 1.718 + rv = CK_FALSE; 1.719 + } 1.720 + 1.721 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.722 + 1.723 + return rv; 1.724 +} 1.725 + 1.726 +NSS_IMPLEMENT CK_ULONG 1.727 +nss_dbm_db_get_object_attribute_count 1.728 +( 1.729 + nss_dbm_dbt_t *dbt, 1.730 + CK_RV *pError, 1.731 + CK_ULONG *pdbrv 1.732 +) 1.733 +{ 1.734 + CK_ULONG rv = 0; 1.735 + DBT object; 1.736 + CK_ULONG *pulData; 1.737 + 1.738 + /* Locked region */ 1.739 + { 1.740 + *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.741 + if( CKR_OK != *pError ) { 1.742 + return rv; 1.743 + } 1.744 + 1.745 + *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.746 + if( 0 == *pdbrv ) { 1.747 + ; 1.748 + } else if( *pdbrv > 0 ) { 1.749 + *pError = CKR_OBJECT_HANDLE_INVALID; 1.750 + goto done; 1.751 + } else { 1.752 + *pError = CKR_DEVICE_ERROR; 1.753 + goto done; 1.754 + } 1.755 + 1.756 + pulData = (CK_ULONG *)object.data; 1.757 + rv = ntohl(pulData[0]); 1.758 + 1.759 + done: 1.760 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.761 + } 1.762 + 1.763 + return rv; 1.764 +} 1.765 + 1.766 +NSS_IMPLEMENT CK_RV 1.767 +nss_dbm_db_get_object_attribute_types 1.768 +( 1.769 + nss_dbm_dbt_t *dbt, 1.770 + CK_ATTRIBUTE_TYPE_PTR typeArray, 1.771 + CK_ULONG ulCount, 1.772 + CK_ULONG *pdbrv 1.773 +) 1.774 +{ 1.775 + CK_RV rv = CKR_OK; 1.776 + DBT object; 1.777 + CK_ULONG *pulData; 1.778 + CK_ULONG n, i; 1.779 + 1.780 + /* Locked region */ 1.781 + { 1.782 + rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.783 + if( CKR_OK != rv ) { 1.784 + return rv; 1.785 + } 1.786 + 1.787 + *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.788 + if( 0 == *pdbrv ) { 1.789 + ; 1.790 + } else if( *pdbrv > 0 ) { 1.791 + rv = CKR_OBJECT_HANDLE_INVALID; 1.792 + goto done; 1.793 + } else { 1.794 + rv = CKR_DEVICE_ERROR; 1.795 + goto done; 1.796 + } 1.797 + 1.798 + pulData = (CK_ULONG *)object.data; 1.799 + n = ntohl(pulData[0]); 1.800 + 1.801 + if( ulCount < n ) { 1.802 + rv = CKR_BUFFER_TOO_SMALL; 1.803 + goto done; 1.804 + } 1.805 + 1.806 + for( i = 0; i < n; i++ ) { 1.807 + typeArray[i] = ntohl(pulData[1 + i*3]); 1.808 + } 1.809 + 1.810 + done: 1.811 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.812 + } 1.813 + 1.814 + return rv; 1.815 +} 1.816 + 1.817 +NSS_IMPLEMENT CK_ULONG 1.818 +nss_dbm_db_get_object_attribute_size 1.819 +( 1.820 + nss_dbm_dbt_t *dbt, 1.821 + CK_ATTRIBUTE_TYPE type, 1.822 + CK_RV *pError, 1.823 + CK_ULONG *pdbrv 1.824 +) 1.825 +{ 1.826 + CK_ULONG rv = 0; 1.827 + DBT object; 1.828 + CK_ULONG *pulData; 1.829 + CK_ULONG n, i; 1.830 + 1.831 + /* Locked region */ 1.832 + { 1.833 + *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.834 + if( CKR_OK != *pError ) { 1.835 + return rv; 1.836 + } 1.837 + 1.838 + *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.839 + if( 0 == *pdbrv ) { 1.840 + ; 1.841 + } else if( *pdbrv > 0 ) { 1.842 + *pError = CKR_OBJECT_HANDLE_INVALID; 1.843 + goto done; 1.844 + } else { 1.845 + *pError = CKR_DEVICE_ERROR; 1.846 + goto done; 1.847 + } 1.848 + 1.849 + pulData = (CK_ULONG *)object.data; 1.850 + n = ntohl(pulData[0]); 1.851 + 1.852 + for( i = 0; i < n; i++ ) { 1.853 + if( type == ntohl(pulData[1 + i*3]) ) { 1.854 + rv = ntohl(pulData[2 + i*3]); 1.855 + } 1.856 + } 1.857 + 1.858 + if( i == n ) { 1.859 + *pError = CKR_ATTRIBUTE_TYPE_INVALID; 1.860 + goto done; 1.861 + } 1.862 + 1.863 + done: 1.864 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.865 + } 1.866 + 1.867 + return rv; 1.868 +} 1.869 + 1.870 +NSS_IMPLEMENT NSSItem * 1.871 +nss_dbm_db_get_object_attribute 1.872 +( 1.873 + nss_dbm_dbt_t *dbt, 1.874 + NSSArena *arena, 1.875 + CK_ATTRIBUTE_TYPE type, 1.876 + CK_RV *pError, 1.877 + CK_ULONG *pdbrv 1.878 +) 1.879 +{ 1.880 + NSSItem *rv = (NSSItem *)NULL; 1.881 + DBT object; 1.882 + CK_ULONG i; 1.883 + NSSArena *tmp = NSSArena_Create(); 1.884 + CK_ATTRIBUTE_PTR pTemplate; 1.885 + CK_ULONG ulAttributeCount; 1.886 + 1.887 + /* Locked region */ 1.888 + { 1.889 + *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.890 + if( CKR_OK != *pError ) { 1.891 + goto loser; 1.892 + } 1.893 + 1.894 + *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.895 + if( 0 == *pdbrv ) { 1.896 + ; 1.897 + } else if( *pdbrv > 0 ) { 1.898 + *pError = CKR_OBJECT_HANDLE_INVALID; 1.899 + goto done; 1.900 + } else { 1.901 + *pError = CKR_DEVICE_ERROR; 1.902 + goto done; 1.903 + } 1.904 + 1.905 + *pError = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount); 1.906 + if( CKR_OK != *pError ) { 1.907 + goto done; 1.908 + } 1.909 + 1.910 + for( i = 0; i < ulAttributeCount; i++ ) { 1.911 + if( type == pTemplate[i].type ) { 1.912 + rv = nss_ZNEW(arena, NSSItem); 1.913 + if( (NSSItem *)NULL == rv ) { 1.914 + *pError = CKR_HOST_MEMORY; 1.915 + goto done; 1.916 + } 1.917 + rv->size = pTemplate[i].ulValueLen; 1.918 + rv->data = nss_ZAlloc(arena, rv->size); 1.919 + if( (void *)NULL == rv->data ) { 1.920 + *pError = CKR_HOST_MEMORY; 1.921 + goto done; 1.922 + } 1.923 + (void)memcpy(rv->data, pTemplate[i].pValue, rv->size); 1.924 + break; 1.925 + } 1.926 + } 1.927 + if( ulAttributeCount == i ) { 1.928 + *pError = CKR_ATTRIBUTE_TYPE_INVALID; 1.929 + goto done; 1.930 + } 1.931 + 1.932 + done: 1.933 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.934 + } 1.935 + 1.936 + loser: 1.937 + if( (NSSArena *)NULL != tmp ) { 1.938 + NSSArena_Destroy(tmp); 1.939 + } 1.940 + 1.941 + return rv; 1.942 +} 1.943 + 1.944 +NSS_IMPLEMENT CK_RV 1.945 +nss_dbm_db_set_object_attribute 1.946 +( 1.947 + nss_dbm_dbt_t *dbt, 1.948 + CK_ATTRIBUTE_TYPE type, 1.949 + NSSItem *value, 1.950 + CK_ULONG *pdbrv 1.951 +) 1.952 +{ 1.953 + CK_RV rv = CKR_OK; 1.954 + DBT object; 1.955 + CK_ULONG i; 1.956 + NSSArena *tmp = NSSArena_Create(); 1.957 + CK_ATTRIBUTE_PTR pTemplate; 1.958 + CK_ULONG ulAttributeCount; 1.959 + 1.960 + /* Locked region */ 1.961 + { 1.962 + rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); 1.963 + if( CKR_OK != rv ) { 1.964 + goto loser; 1.965 + } 1.966 + 1.967 + *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); 1.968 + if( 0 == *pdbrv ) { 1.969 + ; 1.970 + } else if( *pdbrv > 0 ) { 1.971 + rv = CKR_OBJECT_HANDLE_INVALID; 1.972 + goto done; 1.973 + } else { 1.974 + rv = CKR_DEVICE_ERROR; 1.975 + goto done; 1.976 + } 1.977 + 1.978 + rv = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount); 1.979 + if( CKR_OK != rv ) { 1.980 + goto done; 1.981 + } 1.982 + 1.983 + for( i = 0; i < ulAttributeCount; i++ ) { 1.984 + if( type == pTemplate[i].type ) { 1.985 + /* Replacing an existing attribute */ 1.986 + pTemplate[i].ulValueLen = value->size; 1.987 + pTemplate[i].pValue = value->data; 1.988 + break; 1.989 + } 1.990 + } 1.991 + 1.992 + if( i == ulAttributeCount ) { 1.993 + /* Adding a new attribute */ 1.994 + CK_ATTRIBUTE_PTR npt = nss_ZNEWARRAY(tmp, CK_ATTRIBUTE, ulAttributeCount+1); 1.995 + if( (CK_ATTRIBUTE_PTR)NULL == npt ) { 1.996 + rv = CKR_DEVICE_ERROR; 1.997 + goto done; 1.998 + } 1.999 + 1.1000 + for( i = 0; i < ulAttributeCount; i++ ) { 1.1001 + npt[i] = pTemplate[i]; 1.1002 + } 1.1003 + 1.1004 + npt[ulAttributeCount].type = type; 1.1005 + npt[ulAttributeCount].ulValueLen = value->size; 1.1006 + npt[ulAttributeCount].pValue = value->data; 1.1007 + 1.1008 + pTemplate = npt; 1.1009 + ulAttributeCount++; 1.1010 + } 1.1011 + 1.1012 + rv = nss_dbm_db_wrap_object(tmp, pTemplate, ulAttributeCount, &object); 1.1013 + if( CKR_OK != rv ) { 1.1014 + goto done; 1.1015 + } 1.1016 + 1.1017 + *pdbrv = dbt->my_db->db->put(dbt->my_db->db, &dbt->dbt, &object, 0); 1.1018 + if( 0 != *pdbrv ) { 1.1019 + rv = CKR_DEVICE_ERROR; 1.1020 + goto done; 1.1021 + } 1.1022 + 1.1023 + (void)dbt->my_db->db->sync(dbt->my_db->db, 0); 1.1024 + 1.1025 + done: 1.1026 + (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); 1.1027 + } 1.1028 + 1.1029 + loser: 1.1030 + if( (NSSArena *)NULL != tmp ) { 1.1031 + NSSArena_Destroy(tmp); 1.1032 + } 1.1033 + 1.1034 + return rv; 1.1035 +}