| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #include "ckdbm.h" |
| |
| #define PREFIX_METADATA "0000" |
| #define PREFIX_OBJECT "0001" |
| #define PREFIX_INDEX "0002" |
| |
| static CK_VERSION nss_dbm_db_format_version = { 1, 0 }; |
| struct handle { |
| char prefix[4]; |
| CK_ULONG id; |
| }; |
| |
| NSS_IMPLEMENT nss_dbm_db_t * |
| nss_dbm_db_open( |
| NSSArena *arena, |
| NSSCKFWInstance *fwInstance, |
| char *filename, |
| int flags, |
| CK_RV *pError) |
| { |
| nss_dbm_db_t *rv; |
| CK_VERSION db_version; |
| |
| rv = nss_ZNEW(arena, nss_dbm_db_t); |
| if ((nss_dbm_db_t *)NULL == rv) { |
| *pError = CKR_HOST_MEMORY; |
| return (nss_dbm_db_t *)NULL; |
| } |
| |
| rv->db = dbopen(filename, flags, 0600, DB_HASH, (const void *)NULL); |
| if ((DB *)NULL == rv->db) { |
| *pError = CKR_TOKEN_NOT_PRESENT; |
| return (nss_dbm_db_t *)NULL; |
| } |
| |
| rv->crustylock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError); |
| if ((NSSCKFWMutex *)NULL == rv->crustylock) { |
| return (nss_dbm_db_t *)NULL; |
| } |
| |
| db_version = nss_dbm_db_get_format_version(rv); |
| if (db_version.major != nss_dbm_db_format_version.major) { |
| nss_dbm_db_close(rv); |
| *pError = CKR_TOKEN_NOT_RECOGNIZED; |
| return (nss_dbm_db_t *)NULL; |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT void |
| nss_dbm_db_close( |
| nss_dbm_db_t *db) |
| { |
| if ((NSSCKFWMutex *)NULL != db->crustylock) { |
| (void)NSSCKFWMutex_Destroy(db->crustylock); |
| } |
| |
| if ((DB *)NULL != db->db) { |
| (void)db->db->close(db->db); |
| } |
| |
| nss_ZFreeIf(db); |
| } |
| |
| NSS_IMPLEMENT CK_VERSION |
| nss_dbm_db_get_format_version( |
| nss_dbm_db_t *db) |
| { |
| CK_VERSION rv; |
| DBT k, v; |
| int dbrv; |
| char buffer[64]; |
| |
| rv.major = rv.minor = 0; |
| |
| k.data = PREFIX_METADATA "FormatVersion"; |
| k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); |
| (void)memset(&v, 0, sizeof(v)); |
| |
| /* Locked region */ |
| { |
| if (CKR_OK != NSSCKFWMutex_Lock(db->crustylock)) { |
| return rv; |
| } |
| |
| dbrv = db->db->get(db->db, &k, &v, 0); |
| if (dbrv == 0) { |
| CK_ULONG major = 0, minor = 0; |
| (void)PR_sscanf(v.data, "%ld.%ld", &major, &minor); |
| rv.major = major; |
| rv.minor = minor; |
| } else if (dbrv > 0) { |
| (void)PR_snprintf(buffer, sizeof(buffer), "%ld.%ld", nss_dbm_db_format_version.major, |
| nss_dbm_db_format_version.minor); |
| v.data = buffer; |
| v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL); |
| dbrv = db->db->put(db->db, &k, &v, 0); |
| (void)db->db->sync(db->db, 0); |
| rv = nss_dbm_db_format_version; |
| } else { |
| /* No error return.. */ |
| ; |
| } |
| |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nss_dbm_db_set_label( |
| nss_dbm_db_t *db, |
| NSSUTF8 *label) |
| { |
| CK_RV rv; |
| DBT k, v; |
| int dbrv; |
| |
| k.data = PREFIX_METADATA "Label"; |
| k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); |
| v.data = label; |
| v.size = nssUTF8_Size((NSSUTF8 *)v.data, (PRStatus *)NULL); |
| |
| /* Locked region */ |
| { |
| rv = NSSCKFWMutex_Lock(db->crustylock); |
| if (CKR_OK != rv) { |
| return rv; |
| } |
| |
| dbrv = db->db->put(db->db, &k, &v, 0); |
| if (0 != dbrv) { |
| rv = CKR_DEVICE_ERROR; |
| } |
| |
| dbrv = db->db->sync(db->db, 0); |
| if (0 != dbrv) { |
| rv = CKR_DEVICE_ERROR; |
| } |
| |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT NSSUTF8 * |
| nss_dbm_db_get_label( |
| nss_dbm_db_t *db, |
| NSSArena *arena, |
| CK_RV *pError) |
| { |
| NSSUTF8 *rv = (NSSUTF8 *)NULL; |
| DBT k, v; |
| int dbrv; |
| |
| k.data = PREFIX_METADATA "Label"; |
| k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); |
| |
| /* Locked region */ |
| { |
| if (CKR_OK != NSSCKFWMutex_Lock(db->crustylock)) { |
| return rv; |
| } |
| |
| dbrv = db->db->get(db->db, &k, &v, 0); |
| if (0 == dbrv) { |
| rv = nssUTF8_Duplicate((NSSUTF8 *)v.data, arena); |
| if ((NSSUTF8 *)NULL == rv) { |
| *pError = CKR_HOST_MEMORY; |
| } |
| } else if (dbrv > 0) { |
| /* Just return null */ |
| ; |
| } else { |
| *pError = CKR_DEVICE_ERROR; |
| ; |
| } |
| |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nss_dbm_db_delete_object( |
| nss_dbm_dbt_t *dbt) |
| { |
| CK_RV rv; |
| int dbrv; |
| |
| /* Locked region */ |
| { |
| rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != rv) { |
| return rv; |
| } |
| |
| dbrv = dbt->my_db->db->del(dbt->my_db->db, &dbt->dbt, 0); |
| if (0 != dbrv) { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| dbrv = dbt->my_db->db->sync(dbt->my_db->db, 0); |
| if (0 != dbrv) { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| static CK_ULONG |
| nss_dbm_db_new_handle( |
| nss_dbm_db_t *db, |
| DBT *dbt, /* pre-allocated */ |
| CK_RV *pError) |
| { |
| CK_ULONG rv; |
| DBT k, v; |
| CK_ULONG align = 0, id, myid; |
| struct handle *hp; |
| |
| if (sizeof(struct handle) != dbt->size) { |
| return EINVAL; |
| } |
| |
| /* Locked region */ |
| { |
| *pError = NSSCKFWMutex_Lock(db->crustylock); |
| if (CKR_OK != *pError) { |
| return EINVAL; |
| } |
| |
| k.data = PREFIX_METADATA "LastID"; |
| k.size = nssUTF8_Size((NSSUTF8 *)k.data, (PRStatus *)NULL); |
| (void)memset(&v, 0, sizeof(v)); |
| |
| rv = db->db->get(db->db, &k, &v, 0); |
| if (0 == rv) { |
| (void)memcpy(&align, v.data, sizeof(CK_ULONG)); |
| id = ntohl(align); |
| } else if (rv > 0) { |
| id = 0; |
| } else { |
| goto done; |
| } |
| |
| myid = id; |
| id++; |
| align = htonl(id); |
| v.data = &align; |
| v.size = sizeof(CK_ULONG); |
| |
| rv = db->db->put(db->db, &k, &v, 0); |
| if (0 != rv) { |
| goto done; |
| } |
| |
| rv = db->db->sync(db->db, 0); |
| if (0 != rv) { |
| goto done; |
| } |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| if (0 != rv) { |
| return rv; |
| } |
| |
| hp = (struct handle *)dbt->data; |
| (void)memcpy(&hp->prefix[0], PREFIX_OBJECT, 4); |
| hp->id = myid; |
| |
| return 0; |
| } |
| |
| /* |
| * This attribute-type-dependent swapping should probably |
| * be in the Framework, because it'll be a concern of just |
| * about every Module. Of course any Framework implementation |
| * will have to be augmentable or overridable by a Module. |
| */ |
| |
| enum swap_type { type_byte, |
| type_short, |
| type_long, |
| type_opaque }; |
| |
| static enum swap_type |
| nss_dbm_db_swap_type( |
| CK_ATTRIBUTE_TYPE type) |
| { |
| switch (type) { |
| case CKA_CLASS: |
| return type_long; |
| case CKA_TOKEN: |
| return type_byte; |
| case CKA_PRIVATE: |
| return type_byte; |
| case CKA_LABEL: |
| return type_opaque; |
| case CKA_APPLICATION: |
| return type_opaque; |
| case CKA_VALUE: |
| return type_opaque; |
| case CKA_CERTIFICATE_TYPE: |
| return type_long; |
| case CKA_ISSUER: |
| return type_opaque; |
| case CKA_SERIAL_NUMBER: |
| return type_opaque; |
| case CKA_KEY_TYPE: |
| return type_long; |
| case CKA_SUBJECT: |
| return type_opaque; |
| case CKA_ID: |
| return type_opaque; |
| case CKA_SENSITIVE: |
| return type_byte; |
| case CKA_ENCRYPT: |
| return type_byte; |
| case CKA_DECRYPT: |
| return type_byte; |
| case CKA_WRAP: |
| return type_byte; |
| case CKA_UNWRAP: |
| return type_byte; |
| case CKA_SIGN: |
| return type_byte; |
| case CKA_SIGN_RECOVER: |
| return type_byte; |
| case CKA_VERIFY: |
| return type_byte; |
| case CKA_VERIFY_RECOVER: |
| return type_byte; |
| case CKA_DERIVE: |
| return type_byte; |
| case CKA_START_DATE: |
| return type_opaque; |
| case CKA_END_DATE: |
| return type_opaque; |
| case CKA_MODULUS: |
| return type_opaque; |
| case CKA_MODULUS_BITS: |
| return type_long; |
| case CKA_PUBLIC_EXPONENT: |
| return type_opaque; |
| case CKA_PRIVATE_EXPONENT: |
| return type_opaque; |
| case CKA_PRIME_1: |
| return type_opaque; |
| case CKA_PRIME_2: |
| return type_opaque; |
| case CKA_EXPONENT_1: |
| return type_opaque; |
| case CKA_EXPONENT_2: |
| return type_opaque; |
| case CKA_COEFFICIENT: |
| return type_opaque; |
| case CKA_PRIME: |
| return type_opaque; |
| case CKA_SUBPRIME: |
| return type_opaque; |
| case CKA_BASE: |
| return type_opaque; |
| case CKA_VALUE_BITS: |
| return type_long; |
| case CKA_VALUE_LEN: |
| return type_long; |
| case CKA_EXTRACTABLE: |
| return type_byte; |
| case CKA_LOCAL: |
| return type_byte; |
| case CKA_NEVER_EXTRACTABLE: |
| return type_byte; |
| case CKA_ALWAYS_SENSITIVE: |
| return type_byte; |
| case CKA_MODIFIABLE: |
| return type_byte; |
| case CKA_NETSCAPE_URL: |
| return type_opaque; |
| case CKA_NETSCAPE_EMAIL: |
| return type_opaque; |
| case CKA_NETSCAPE_SMIME_INFO: |
| return type_opaque; |
| case CKA_NETSCAPE_SMIME_TIMESTAMP: |
| return type_opaque; |
| case CKA_NETSCAPE_PKCS8_SALT: |
| return type_opaque; |
| case CKA_NETSCAPE_PASSWORD_CHECK: |
| return type_opaque; |
| case CKA_NETSCAPE_EXPIRES: |
| return type_opaque; |
| case CKA_TRUST_DIGITAL_SIGNATURE: |
| return type_long; |
| case CKA_TRUST_NON_REPUDIATION: |
| return type_long; |
| case CKA_TRUST_KEY_ENCIPHERMENT: |
| return type_long; |
| case CKA_TRUST_DATA_ENCIPHERMENT: |
| return type_long; |
| case CKA_TRUST_KEY_AGREEMENT: |
| return type_long; |
| case CKA_TRUST_KEY_CERT_SIGN: |
| return type_long; |
| case CKA_TRUST_CRL_SIGN: |
| return type_long; |
| case CKA_TRUST_SERVER_AUTH: |
| return type_long; |
| case CKA_TRUST_CLIENT_AUTH: |
| return type_long; |
| case CKA_TRUST_CODE_SIGNING: |
| return type_long; |
| case CKA_TRUST_EMAIL_PROTECTION: |
| return type_long; |
| case CKA_TRUST_IPSEC_END_SYSTEM: |
| return type_long; |
| case CKA_TRUST_IPSEC_TUNNEL: |
| return type_long; |
| case CKA_TRUST_IPSEC_USER: |
| return type_long; |
| case CKA_TRUST_TIME_STAMPING: |
| return type_long; |
| case CKA_NETSCAPE_DB: |
| return type_opaque; |
| case CKA_NETSCAPE_TRUST: |
| return type_opaque; |
| default: |
| return type_opaque; |
| } |
| } |
| |
| static void |
| nss_dbm_db_swap_copy( |
| CK_ATTRIBUTE_TYPE type, |
| void *dest, |
| void *src, |
| CK_ULONG len) |
| { |
| switch (nss_dbm_db_swap_type(type)) { |
| case type_byte: |
| case type_opaque: |
| (void)memcpy(dest, src, len); |
| break; |
| case type_short: { |
| CK_USHORT s, d; |
| (void)memcpy(&s, src, sizeof(CK_USHORT)); |
| d = htons(s); |
| (void)memcpy(dest, &d, sizeof(CK_USHORT)); |
| break; |
| } |
| case type_long: { |
| CK_ULONG s, d; |
| (void)memcpy(&s, src, sizeof(CK_ULONG)); |
| d = htonl(s); |
| (void)memcpy(dest, &d, sizeof(CK_ULONG)); |
| break; |
| } |
| } |
| } |
| |
| static CK_RV |
| nss_dbm_db_wrap_object( |
| NSSArena *arena, |
| CK_ATTRIBUTE_PTR pTemplate, |
| CK_ULONG ulAttributeCount, |
| DBT *object) |
| { |
| CK_ULONG object_size; |
| CK_ULONG i; |
| CK_ULONG *pulData; |
| char *pcData; |
| CK_ULONG offset; |
| |
| object_size = (1 + ulAttributeCount * 3) * sizeof(CK_ULONG); |
| offset = object_size; |
| for (i = 0; i < ulAttributeCount; i++) { |
| object_size += pTemplate[i].ulValueLen; |
| } |
| |
| object->size = object_size; |
| object->data = nss_ZAlloc(arena, object_size); |
| if ((void *)NULL == object->data) { |
| return CKR_HOST_MEMORY; |
| } |
| |
| pulData = (CK_ULONG *)object->data; |
| pcData = (char *)object->data; |
| |
| pulData[0] = htonl(ulAttributeCount); |
| for (i = 0; i < ulAttributeCount; i++) { |
| CK_ULONG len = pTemplate[i].ulValueLen; |
| pulData[1 + i * 3] = htonl(pTemplate[i].type); |
| pulData[2 + i * 3] = htonl(len); |
| pulData[3 + i * 3] = htonl(offset); |
| nss_dbm_db_swap_copy(pTemplate[i].type, &pcData[offset], pTemplate[i].pValue, len); |
| offset += len; |
| } |
| |
| return CKR_OK; |
| } |
| |
| static CK_RV |
| nss_dbm_db_unwrap_object( |
| NSSArena *arena, |
| DBT *object, |
| CK_ATTRIBUTE_PTR *ppTemplate, |
| CK_ULONG *pulAttributeCount) |
| { |
| CK_ULONG *pulData; |
| char *pcData; |
| CK_ULONG n, i; |
| CK_ATTRIBUTE_PTR pTemplate; |
| |
| pulData = (CK_ULONG *)object->data; |
| pcData = (char *)object->data; |
| |
| n = ntohl(pulData[0]); |
| *pulAttributeCount = n; |
| pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n); |
| if ((CK_ATTRIBUTE_PTR)NULL == pTemplate) { |
| return CKR_HOST_MEMORY; |
| } |
| |
| for (i = 0; i < n; i++) { |
| CK_ULONG len; |
| CK_ULONG offset; |
| void *p; |
| |
| pTemplate[i].type = ntohl(pulData[1 + i * 3]); |
| len = ntohl(pulData[2 + i * 3]); |
| offset = ntohl(pulData[3 + i * 3]); |
| |
| p = nss_ZAlloc(arena, len); |
| if ((void *)NULL == p) { |
| return CKR_HOST_MEMORY; |
| } |
| |
| nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len); |
| pTemplate[i].ulValueLen = len; |
| pTemplate[i].pValue = p; |
| } |
| |
| *ppTemplate = pTemplate; |
| return CKR_OK; |
| } |
| |
| NSS_IMPLEMENT nss_dbm_dbt_t * |
| nss_dbm_db_create_object( |
| NSSArena *arena, |
| nss_dbm_db_t *db, |
| CK_ATTRIBUTE_PTR pTemplate, |
| CK_ULONG ulAttributeCount, |
| CK_RV *pError, |
| CK_ULONG *pdbrv) |
| { |
| NSSArena *tmparena = (NSSArena *)NULL; |
| nss_dbm_dbt_t *rv = (nss_dbm_dbt_t *)NULL; |
| DBT object; |
| |
| rv = nss_ZNEW(arena, nss_dbm_dbt_t); |
| if ((nss_dbm_dbt_t *)NULL == rv) { |
| *pError = CKR_HOST_MEMORY; |
| return (nss_dbm_dbt_t *)NULL; |
| } |
| |
| rv->my_db = db; |
| rv->dbt.size = sizeof(struct handle); |
| rv->dbt.data = nss_ZAlloc(arena, rv->dbt.size); |
| if ((void *)NULL == rv->dbt.data) { |
| *pError = CKR_HOST_MEMORY; |
| return (nss_dbm_dbt_t *)NULL; |
| } |
| |
| *pdbrv = nss_dbm_db_new_handle(db, &rv->dbt, pError); |
| if (0 != *pdbrv) { |
| return (nss_dbm_dbt_t *)NULL; |
| } |
| |
| tmparena = NSSArena_Create(); |
| if ((NSSArena *)NULL == tmparena) { |
| *pError = CKR_HOST_MEMORY; |
| return (nss_dbm_dbt_t *)NULL; |
| } |
| |
| *pError = nss_dbm_db_wrap_object(tmparena, pTemplate, ulAttributeCount, &object); |
| if (CKR_OK != *pError) { |
| return (nss_dbm_dbt_t *)NULL; |
| } |
| |
| /* Locked region */ |
| { |
| *pError = NSSCKFWMutex_Lock(db->crustylock); |
| if (CKR_OK != *pError) { |
| goto loser; |
| } |
| |
| *pdbrv = db->db->put(db->db, &rv->dbt, &object, 0); |
| if (0 != *pdbrv) { |
| *pError = CKR_DEVICE_ERROR; |
| } |
| |
| (void)db->db->sync(db->db, 0); |
| |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| loser: |
| if ((NSSArena *)NULL != tmparena) { |
| (void)NSSArena_Destroy(tmparena); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nss_dbm_db_find_objects( |
| nss_dbm_find_t *find, |
| nss_dbm_db_t *db, |
| CK_ATTRIBUTE_PTR pTemplate, |
| CK_ULONG ulAttributeCount, |
| CK_ULONG *pdbrv) |
| { |
| CK_RV rv = CKR_OK; |
| |
| if ((nss_dbm_db_t *)NULL != db) { |
| DBT k, v; |
| |
| rv = NSSCKFWMutex_Lock(db->crustylock); |
| if (CKR_OK != rv) { |
| return rv; |
| } |
| |
| *pdbrv = db->db->seq(db->db, &k, &v, R_FIRST); |
| while (0 == *pdbrv) { |
| CK_ULONG i, j; |
| NSSArena *tmparena = (NSSArena *)NULL; |
| CK_ULONG ulac; |
| CK_ATTRIBUTE_PTR pt; |
| |
| if ((k.size < 4) || (0 != memcmp(k.data, PREFIX_OBJECT, 4))) { |
| goto nomatch; |
| } |
| |
| tmparena = NSSArena_Create(); |
| |
| rv = nss_dbm_db_unwrap_object(tmparena, &v, &pt, &ulac); |
| if (CKR_OK != rv) { |
| goto loser; |
| } |
| |
| for (i = 0; i < ulAttributeCount; i++) { |
| for (j = 0; j < ulac; j++) { |
| if (pTemplate[i].type == |
| pt[j].type) { |
| if (pTemplate[i].ulValueLen != |
| pt[j].ulValueLen) { |
| goto nomatch; |
| } |
| if (0 != |
| memcmp(pTemplate[i].pValue, pt[j].pValue, pt[j].ulValueLen)) { |
| goto nomatch; |
| } |
| break; |
| } |
| } |
| if (j == ulac) { |
| goto nomatch; |
| } |
| } |
| |
| /* entire template matches */ |
| { |
| struct nss_dbm_dbt_node *node; |
| |
| node = nss_ZNEW(find->arena, struct nss_dbm_dbt_node); |
| if ((struct nss_dbm_dbt_node *)NULL == node) { |
| rv = |
| CKR_HOST_MEMORY; |
| goto loser; |
| } |
| |
| node->dbt = nss_ZNEW(find->arena, nss_dbm_dbt_t); |
| if ((nss_dbm_dbt_t *)NULL == node->dbt) { |
| rv = |
| CKR_HOST_MEMORY; |
| goto loser; |
| } |
| |
| node->dbt->dbt.size = k.size; |
| node->dbt->dbt.data = nss_ZAlloc(find->arena, k.size); |
| if ((void *)NULL == node->dbt->dbt.data) { |
| rv = |
| CKR_HOST_MEMORY; |
| goto loser; |
| } |
| |
| (void)memcpy(node->dbt->dbt.data, k.data, k.size); |
| |
| node->dbt->my_db = db; |
| |
| node->next = find->found; |
| find->found = node; |
| } |
| |
| nomatch: |
| if ((NSSArena *)NULL != tmparena) { |
| (void)NSSArena_Destroy(tmparena); |
| } |
| *pdbrv = db->db->seq(db->db, &k, &v, R_NEXT); |
| } |
| |
| if (*pdbrv < 0) { |
| rv = CKR_DEVICE_ERROR; |
| goto loser; |
| } |
| |
| rv = CKR_OK; |
| |
| loser: |
| (void)NSSCKFWMutex_Unlock(db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_BBOOL |
| nss_dbm_db_object_still_exists( |
| nss_dbm_dbt_t *dbt) |
| { |
| CK_BBOOL rv; |
| CK_RV ckrv; |
| int dbrv; |
| DBT object; |
| |
| ckrv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != ckrv) { |
| return CK_FALSE; |
| } |
| |
| dbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == dbrv) { |
| rv = CK_TRUE; |
| } else { |
| rv = CK_FALSE; |
| } |
| |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_ULONG |
| nss_dbm_db_get_object_attribute_count( |
| nss_dbm_dbt_t *dbt, |
| CK_RV *pError, |
| CK_ULONG *pdbrv) |
| { |
| CK_ULONG rv = 0; |
| DBT object; |
| CK_ULONG *pulData; |
| |
| /* Locked region */ |
| { |
| *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != *pError) { |
| return rv; |
| } |
| |
| *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == *pdbrv) { |
| ; |
| } else if (*pdbrv > 0) { |
| *pError = CKR_OBJECT_HANDLE_INVALID; |
| goto done; |
| } else { |
| *pError = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| pulData = (CK_ULONG *)object.data; |
| rv = ntohl(pulData[0]); |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nss_dbm_db_get_object_attribute_types( |
| nss_dbm_dbt_t *dbt, |
| CK_ATTRIBUTE_TYPE_PTR typeArray, |
| CK_ULONG ulCount, |
| CK_ULONG *pdbrv) |
| { |
| CK_RV rv = CKR_OK; |
| DBT object; |
| CK_ULONG *pulData; |
| CK_ULONG n, i; |
| |
| /* Locked region */ |
| { |
| rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != rv) { |
| return rv; |
| } |
| |
| *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == *pdbrv) { |
| ; |
| } else if (*pdbrv > 0) { |
| rv = CKR_OBJECT_HANDLE_INVALID; |
| goto done; |
| } else { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| pulData = (CK_ULONG *)object.data; |
| n = ntohl(pulData[0]); |
| |
| if (ulCount < n) { |
| rv = CKR_BUFFER_TOO_SMALL; |
| goto done; |
| } |
| |
| for (i = 0; i < n; i++) { |
| typeArray[i] = ntohl(pulData[1 + i * 3]); |
| } |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_ULONG |
| nss_dbm_db_get_object_attribute_size( |
| nss_dbm_dbt_t *dbt, |
| CK_ATTRIBUTE_TYPE type, |
| CK_RV *pError, |
| CK_ULONG *pdbrv) |
| { |
| CK_ULONG rv = 0; |
| DBT object; |
| CK_ULONG *pulData; |
| CK_ULONG n, i; |
| |
| /* Locked region */ |
| { |
| *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != *pError) { |
| return rv; |
| } |
| |
| *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == *pdbrv) { |
| ; |
| } else if (*pdbrv > 0) { |
| *pError = CKR_OBJECT_HANDLE_INVALID; |
| goto done; |
| } else { |
| *pError = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| pulData = (CK_ULONG *)object.data; |
| n = ntohl(pulData[0]); |
| |
| for (i = 0; i < n; i++) { |
| if (type == ntohl(pulData[1 + i * 3])) { |
| rv = ntohl(pulData[2 + i * 3]); |
| } |
| } |
| |
| if (i == n) { |
| *pError = CKR_ATTRIBUTE_TYPE_INVALID; |
| goto done; |
| } |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT NSSItem * |
| nss_dbm_db_get_object_attribute( |
| nss_dbm_dbt_t *dbt, |
| NSSArena *arena, |
| CK_ATTRIBUTE_TYPE type, |
| CK_RV *pError, |
| CK_ULONG *pdbrv) |
| { |
| NSSItem *rv = (NSSItem *)NULL; |
| DBT object; |
| CK_ULONG i; |
| NSSArena *tmp = NSSArena_Create(); |
| CK_ATTRIBUTE_PTR pTemplate; |
| CK_ULONG ulAttributeCount; |
| |
| /* Locked region */ |
| { |
| *pError = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != *pError) { |
| goto loser; |
| } |
| |
| *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == *pdbrv) { |
| ; |
| } else if (*pdbrv > 0) { |
| *pError = CKR_OBJECT_HANDLE_INVALID; |
| goto done; |
| } else { |
| *pError = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| *pError = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount); |
| if (CKR_OK != *pError) { |
| goto done; |
| } |
| |
| for (i = 0; i < ulAttributeCount; i++) { |
| if (type == pTemplate[i].type) { |
| rv = nss_ZNEW(arena, NSSItem); |
| if ((NSSItem *)NULL == rv) { |
| *pError = |
| CKR_HOST_MEMORY; |
| goto done; |
| } |
| rv->size = pTemplate[i].ulValueLen; |
| rv->data = nss_ZAlloc(arena, rv->size); |
| if ((void *)NULL == rv->data) { |
| *pError = |
| CKR_HOST_MEMORY; |
| goto done; |
| } |
| (void)memcpy(rv->data, pTemplate[i].pValue, rv->size); |
| break; |
| } |
| } |
| if (ulAttributeCount == i) { |
| *pError = CKR_ATTRIBUTE_TYPE_INVALID; |
| goto done; |
| } |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| loser: |
| if ((NSSArena *)NULL != tmp) { |
| NSSArena_Destroy(tmp); |
| } |
| |
| return rv; |
| } |
| |
| NSS_IMPLEMENT CK_RV |
| nss_dbm_db_set_object_attribute( |
| nss_dbm_dbt_t *dbt, |
| CK_ATTRIBUTE_TYPE type, |
| NSSItem *value, |
| CK_ULONG *pdbrv) |
| { |
| CK_RV rv = CKR_OK; |
| DBT object; |
| CK_ULONG i; |
| NSSArena *tmp = NSSArena_Create(); |
| CK_ATTRIBUTE_PTR pTemplate; |
| CK_ULONG ulAttributeCount; |
| |
| /* Locked region */ |
| { |
| rv = NSSCKFWMutex_Lock(dbt->my_db->crustylock); |
| if (CKR_OK != rv) { |
| goto loser; |
| } |
| |
| *pdbrv = dbt->my_db->db->get(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 == *pdbrv) { |
| ; |
| } else if (*pdbrv > 0) { |
| rv = CKR_OBJECT_HANDLE_INVALID; |
| goto done; |
| } else { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| rv = nss_dbm_db_unwrap_object(tmp, &object, &pTemplate, &ulAttributeCount); |
| if (CKR_OK != rv) { |
| goto done; |
| } |
| |
| for (i = 0; i < ulAttributeCount; i++) { |
| if (type == pTemplate[i].type) { |
| /* Replacing an existing attribute */ |
| pTemplate[i].ulValueLen = value->size; |
| pTemplate[i].pValue = value->data; |
| break; |
| } |
| } |
| |
| if (i == ulAttributeCount) { |
| /* Adding a new attribute */ |
| CK_ATTRIBUTE_PTR npt = nss_ZNEWARRAY(tmp, CK_ATTRIBUTE, ulAttributeCount + 1); |
| if ((CK_ATTRIBUTE_PTR)NULL == npt) { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| for (i = 0; i < ulAttributeCount; i++) { |
| npt[i] = pTemplate[i]; |
| } |
| |
| npt[ulAttributeCount].type = type; |
| npt[ulAttributeCount].ulValueLen = value->size; |
| npt[ulAttributeCount].pValue = value->data; |
| |
| pTemplate = npt; |
| ulAttributeCount++; |
| } |
| |
| rv = nss_dbm_db_wrap_object(tmp, pTemplate, ulAttributeCount, &object); |
| if (CKR_OK != rv) { |
| goto done; |
| } |
| |
| *pdbrv = dbt->my_db->db->put(dbt->my_db->db, &dbt->dbt, &object, 0); |
| if (0 != *pdbrv) { |
| rv = CKR_DEVICE_ERROR; |
| goto done; |
| } |
| |
| (void)dbt->my_db->db->sync(dbt->my_db->db, 0); |
| |
| done: |
| (void)NSSCKFWMutex_Unlock(dbt->my_db->crustylock); |
| } |
| |
| loser: |
| if ((NSSArena *)NULL != tmp) { |
| NSSArena_Destroy(tmp); |
| } |
| |
| return rv; |
| } |