diff options
Diffstat (limited to 'security/nss/lib/ckfw/dbm')
-rw-r--r-- | security/nss/lib/ckfw/dbm/Makefile | 9 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/anchor.c | 17 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/ckdbm.h | 210 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/config.mk | 8 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/db.c | 1069 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/find.c | 126 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/instance.c | 147 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/manifest.mn | 25 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/object.c | 155 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/session.c | 255 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/slot.c | 165 | ||||
-rw-r--r-- | security/nss/lib/ckfw/dbm/token.c | 260 |
12 files changed, 2446 insertions, 0 deletions
diff --git a/security/nss/lib/ckfw/dbm/Makefile b/security/nss/lib/ckfw/dbm/Makefile new file mode 100644 index 000000000..07ae9676a --- /dev/null +++ b/security/nss/lib/ckfw/dbm/Makefile @@ -0,0 +1,9 @@ +# +# 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 manifest.mn +include config.mk +include $(CORE_DEPTH)/coreconf/config.mk +include $(CORE_DEPTH)/coreconf/rules.mk diff --git a/security/nss/lib/ckfw/dbm/anchor.c b/security/nss/lib/ckfw/dbm/anchor.c new file mode 100644 index 000000000..c904d25ae --- /dev/null +++ b/security/nss/lib/ckfw/dbm/anchor.c @@ -0,0 +1,17 @@ +/* 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/. */ + +/* + * dbm/anchor.c + * + * This file "anchors" the actual cryptoki entry points in this module's + * shared library, which is required for dynamic loading. See the + * comments in nssck.api for more information. + */ + +#include "ckdbm.h" + +#define MODULE_NAME dbm +#define INSTANCE_NAME (NSSCKMDInstance *)&nss_dbm_mdInstance +#include "nssck.api" diff --git a/security/nss/lib/ckfw/dbm/ckdbm.h b/security/nss/lib/ckfw/dbm/ckdbm.h new file mode 100644 index 000000000..8c2607cb3 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/ckdbm.h @@ -0,0 +1,210 @@ +/* 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/. */ + +#ifndef CKDBM_H +#define CKDBM_H + +#include "nssckmdt.h" +#include "nssckfw.h" + +/* + * I'm including this for access to the arena functions. + * Looks like we should publish that API. + */ +#ifndef BASE_H +#include "base.h" +#endif /* BASE_H */ + +/* + * This is where the Netscape extensions live, at least for now. + */ +#ifndef CKT_H +#include "ckt.h" +#endif /* CKT_H */ + +#include "mcom_db.h" + +NSS_EXTERN_DATA NSSCKMDInstance nss_dbm_mdInstance; + +typedef struct nss_dbm_db_struct nss_dbm_db_t; +struct nss_dbm_db_struct { + DB *db; + NSSCKFWMutex *crustylock; +}; + +typedef struct nss_dbm_dbt_struct nss_dbm_dbt_t; +struct nss_dbm_dbt_struct { + DBT dbt; + nss_dbm_db_t *my_db; +}; + +typedef struct nss_dbm_instance_struct nss_dbm_instance_t; +struct nss_dbm_instance_struct { + NSSArena *arena; + CK_ULONG nSlots; + char **filenames; + int *flags; /* e.g. O_RDONLY, O_RDWR */ +}; + +typedef struct nss_dbm_slot_struct nss_dbm_slot_t; +struct nss_dbm_slot_struct { + nss_dbm_instance_t *instance; + char *filename; + int flags; + nss_dbm_db_t *token_db; +}; + +typedef struct nss_dbm_token_struct nss_dbm_token_t; +struct nss_dbm_token_struct { + NSSArena *arena; + nss_dbm_slot_t *slot; + nss_dbm_db_t *session_db; + NSSUTF8 *label; +}; + +struct nss_dbm_dbt_node { + struct nss_dbm_dbt_node *next; + nss_dbm_dbt_t *dbt; +}; + +typedef struct nss_dbm_session_struct nss_dbm_session_t; +struct nss_dbm_session_struct { + NSSArena *arena; + nss_dbm_token_t *token; + CK_ULONG deviceError; + struct nss_dbm_dbt_node *session_objects; + NSSCKFWMutex *list_lock; +}; + +typedef struct nss_dbm_object_struct nss_dbm_object_t; +struct nss_dbm_object_struct { + NSSArena *arena; /* token or session */ + nss_dbm_dbt_t *handle; +}; + +typedef struct nss_dbm_find_struct nss_dbm_find_t; +struct nss_dbm_find_struct { + NSSArena *arena; + struct nss_dbm_dbt_node *found; + NSSCKFWMutex *list_lock; +}; + +NSS_EXTERN NSSCKMDSlot * +nss_dbm_mdSlot_factory( + nss_dbm_instance_t *instance, + char *filename, + int flags, + CK_RV *pError); + +NSS_EXTERN NSSCKMDToken * +nss_dbm_mdToken_factory( + nss_dbm_slot_t *slot, + CK_RV *pError); + +NSS_EXTERN NSSCKMDSession * +nss_dbm_mdSession_factory( + nss_dbm_token_t *token, + NSSCKFWSession *fwSession, + NSSCKFWInstance *fwInstance, + CK_BBOOL rw, + CK_RV *pError); + +NSS_EXTERN NSSCKMDObject * +nss_dbm_mdObject_factory( + nss_dbm_object_t *object, + CK_RV *pError); + +NSS_EXTERN NSSCKMDFindObjects * +nss_dbm_mdFindObjects_factory( + nss_dbm_find_t *find, + CK_RV *pError); + +NSS_EXTERN nss_dbm_db_t * +nss_dbm_db_open( + NSSArena *arena, + NSSCKFWInstance *fwInstance, + char *filename, + int flags, + CK_RV *pError); + +NSS_EXTERN void +nss_dbm_db_close( + nss_dbm_db_t *db); + +NSS_EXTERN CK_VERSION +nss_dbm_db_get_format_version( + nss_dbm_db_t *db); + +NSS_EXTERN CK_RV +nss_dbm_db_set_label( + nss_dbm_db_t *db, + NSSUTF8 *label); + +NSS_EXTERN NSSUTF8 * +nss_dbm_db_get_label( + nss_dbm_db_t *db, + NSSArena *arena, + CK_RV *pError); + +NSS_EXTERN CK_RV +nss_dbm_db_delete_object( + nss_dbm_dbt_t *dbt); + +NSS_EXTERN 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); + +NSS_EXTERN 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); + +NSS_EXTERN CK_BBOOL +nss_dbm_db_object_still_exists( + nss_dbm_dbt_t *dbt); + +NSS_EXTERN CK_ULONG +nss_dbm_db_get_object_attribute_count( + nss_dbm_dbt_t *dbt, + CK_RV *pError, + CK_ULONG *pdbrv); + +NSS_EXTERN 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); + +NSS_EXTERN CK_ULONG +nss_dbm_db_get_object_attribute_size( + nss_dbm_dbt_t *dbt, + CK_ATTRIBUTE_TYPE type, + CK_RV *pError, + CK_ULONG *pdbrv); + +NSS_EXTERN NSSItem * +nss_dbm_db_get_object_attribute( + nss_dbm_dbt_t *dbt, + NSSArena *arena, + CK_ATTRIBUTE_TYPE type, + CK_RV *pError, + CK_ULONG *pdbrv); + +NSS_EXTERN CK_RV +nss_dbm_db_set_object_attribute( + nss_dbm_dbt_t *dbt, + CK_ATTRIBUTE_TYPE type, + NSSItem *value, + CK_ULONG *pdbrv); + +#endif /* CKDBM_H */ diff --git a/security/nss/lib/ckfw/dbm/config.mk b/security/nss/lib/ckfw/dbm/config.mk new file mode 100644 index 000000000..a1991e5f4 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/config.mk @@ -0,0 +1,8 @@ +# +# 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/. + +ifdef BUILD_IDG +DEFINES += -DNSSDEBUG +endif diff --git a/security/nss/lib/ckfw/dbm/db.c b/security/nss/lib/ckfw/dbm/db.c new file mode 100644 index 000000000..bbf2b9510 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/db.c @@ -0,0 +1,1069 @@ +/* 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; +} diff --git a/security/nss/lib/ckfw/dbm/find.c b/security/nss/lib/ckfw/dbm/find.c new file mode 100644 index 000000000..8a03855c3 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/find.c @@ -0,0 +1,126 @@ +/* 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" + +static void +nss_dbm_mdFindObjects_Final( + NSSCKMDFindObjects *mdFindObjects, + NSSCKFWFindObjects *fwFindObjects, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_find_t *find = (nss_dbm_find_t *)mdFindObjects->etc; + + /* Locks might have system resources associated */ + (void)NSSCKFWMutex_Destroy(find->list_lock); + (void)NSSArena_Destroy(find->arena); +} + +static NSSCKMDObject * +nss_dbm_mdFindObjects_Next( + NSSCKMDFindObjects *mdFindObjects, + NSSCKFWFindObjects *fwFindObjects, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSArena *arena, + CK_RV *pError) +{ + nss_dbm_find_t *find = (nss_dbm_find_t *)mdFindObjects->etc; + struct nss_dbm_dbt_node *node; + nss_dbm_object_t *object; + NSSCKMDObject *rv; + + while (1) { + /* Lock */ + { + *pError = NSSCKFWMutex_Lock(find->list_lock); + if (CKR_OK != *pError) { + return (NSSCKMDObject *)NULL; + } + + node = find->found; + if ((struct nss_dbm_dbt_node *)NULL != node) { + find->found = node->next; + } + + *pError = NSSCKFWMutex_Unlock(find->list_lock); + if (CKR_OK != *pError) { + /* screwed now */ + return (NSSCKMDObject *)NULL; + } + } + + if ((struct nss_dbm_dbt_node *)NULL == node) { + break; + } + + if (nss_dbm_db_object_still_exists(node->dbt)) { + break; + } + } + + if ((struct nss_dbm_dbt_node *)NULL == node) { + *pError = CKR_OK; + return (NSSCKMDObject *)NULL; + } + + object = nss_ZNEW(arena, nss_dbm_object_t); + if ((nss_dbm_object_t *)NULL == object) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + + object->arena = arena; + object->handle = nss_ZNEW(arena, nss_dbm_dbt_t); + if ((nss_dbm_dbt_t *)NULL == object->handle) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + + object->handle->my_db = node->dbt->my_db; + object->handle->dbt.size = node->dbt->dbt.size; + object->handle->dbt.data = nss_ZAlloc(arena, node->dbt->dbt.size); + if ((void *)NULL == object->handle->dbt.data) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + + (void)memcpy(object->handle->dbt.data, node->dbt->dbt.data, node->dbt->dbt.size); + + rv = nss_dbm_mdObject_factory(object, pError); + if ((NSSCKMDObject *)NULL == rv) { + return (NSSCKMDObject *)NULL; + } + + return rv; +} + +NSS_IMPLEMENT NSSCKMDFindObjects * +nss_dbm_mdFindObjects_factory( + nss_dbm_find_t *find, + CK_RV *pError) +{ + NSSCKMDFindObjects *rv; + + rv = nss_ZNEW(find->arena, NSSCKMDFindObjects); + if ((NSSCKMDFindObjects *)NULL == rv) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDFindObjects *)NULL; + } + + rv->etc = (void *)find; + rv->Final = nss_dbm_mdFindObjects_Final; + rv->Next = nss_dbm_mdFindObjects_Next; + + return rv; +} diff --git a/security/nss/lib/ckfw/dbm/instance.c b/security/nss/lib/ckfw/dbm/instance.c new file mode 100644 index 000000000..fbb11722d --- /dev/null +++ b/security/nss/lib/ckfw/dbm/instance.c @@ -0,0 +1,147 @@ +/* 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" + +static CK_RV +nss_dbm_mdInstance_Initialize( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSUTF8 *configurationData) +{ + CK_RV rv = CKR_OK; + NSSArena *arena; + nss_dbm_instance_t *instance; + + arena = NSSCKFWInstance_GetArena(fwInstance, &rv); + if (((NSSArena *)NULL == arena) && (CKR_OK != rv)) { + return rv; + } + + instance = nss_ZNEW(arena, nss_dbm_instance_t); + if ((nss_dbm_instance_t *)NULL == instance) { + return CKR_HOST_MEMORY; + } + + instance->arena = arena; + + /* + * This should parse the configuration data for information on + * number and locations of databases, modes (e.g. readonly), etc. + * But for now, we'll have one slot with a creatable read-write + * database called "cert8.db." + */ + + instance->nSlots = 1; + instance->filenames = nss_ZNEWARRAY(arena, char *, instance->nSlots); + if ((char **)NULL == instance->filenames) { + return CKR_HOST_MEMORY; + } + + instance->flags = nss_ZNEWARRAY(arena, int, instance->nSlots); + if ((int *)NULL == instance->flags) { + return CKR_HOST_MEMORY; + } + + instance->filenames[0] = "cert8.db"; + instance->flags[0] = O_RDWR | O_CREAT; + + mdInstance->etc = (void *)instance; + return CKR_OK; +} + +/* nss_dbm_mdInstance_Finalize is not required */ + +static CK_ULONG +nss_dbm_mdInstance_GetNSlots( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + nss_dbm_instance_t *instance = (nss_dbm_instance_t *)mdInstance->etc; + return instance->nSlots; +} + +static CK_VERSION +nss_dbm_mdInstance_GetCryptokiVersion( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + static CK_VERSION rv = { 2, 1 }; + return rv; +} + +static NSSUTF8 * +nss_dbm_mdInstance_GetManufacturerID( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "Mozilla Foundation"; +} + +static NSSUTF8 * +nss_dbm_mdInstance_GetLibraryDescription( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "Berkeley Database Module"; +} + +static CK_VERSION +nss_dbm_mdInstance_GetLibraryVersion( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + static CK_VERSION rv = { 1, 0 }; /* My own version number */ + return rv; +} + +static CK_BBOOL +nss_dbm_mdInstance_ModuleHandlesSessionObjects( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + return CK_TRUE; +} + +static CK_RV +nss_dbm_mdInstance_GetSlots( + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKMDSlot *slots[]) +{ + nss_dbm_instance_t *instance = (nss_dbm_instance_t *)mdInstance->etc; + CK_ULONG i; + CK_RV rv = CKR_OK; + + for (i = 0; i < instance->nSlots; i++) { + slots[i] = nss_dbm_mdSlot_factory(instance, instance->filenames[i], + instance->flags[i], &rv); + if ((NSSCKMDSlot *)NULL == slots[i]) { + return rv; + } + } + + return rv; +} + +/* nss_dbm_mdInstance_WaitForSlotEvent is not relevant */ + +NSS_IMPLEMENT_DATA NSSCKMDInstance + nss_dbm_mdInstance = { + NULL, /* etc; filled in later */ + nss_dbm_mdInstance_Initialize, + NULL, /* nss_dbm_mdInstance_Finalize */ + nss_dbm_mdInstance_GetNSlots, + nss_dbm_mdInstance_GetCryptokiVersion, + nss_dbm_mdInstance_GetManufacturerID, + nss_dbm_mdInstance_GetLibraryDescription, + nss_dbm_mdInstance_GetLibraryVersion, + nss_dbm_mdInstance_ModuleHandlesSessionObjects, + nss_dbm_mdInstance_GetSlots, + NULL, /* nss_dbm_mdInstance_WaitForSlotEvent */ + NULL /* terminator */ + }; diff --git a/security/nss/lib/ckfw/dbm/manifest.mn b/security/nss/lib/ckfw/dbm/manifest.mn new file mode 100644 index 000000000..1f87f4353 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/manifest.mn @@ -0,0 +1,25 @@ +# +# 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/. + +CORE_DEPTH = ../../../.. + +MODULE = nss + +CSRCS = \ + anchor.c \ + instance.c \ + slot.c \ + token.c \ + session.c \ + object.c \ + find.c \ + db.c \ + $(NULL) + +REQUIRES = dbm nspr + +LIBRARY_NAME = nssckdbm + +EXTRA_SHARED_LIBS = -L$(DIST)/lib -lnssckfw -lnssb -ldbm -lnspr4 -lplc4 -lplds4 diff --git a/security/nss/lib/ckfw/dbm/object.c b/security/nss/lib/ckfw/dbm/object.c new file mode 100644 index 000000000..4f6e4d409 --- /dev/null +++ b/security/nss/lib/ckfw/dbm/object.c @@ -0,0 +1,155 @@ +/* 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" + +static void +nss_dbm_mdObject_Finalize( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + ; +} + +static CK_RV +nss_dbm_mdObject_Destroy( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + return nss_dbm_db_delete_object(object->handle); +} + +static CK_ULONG +nss_dbm_mdObject_GetAttributeCount( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return nss_dbm_db_get_object_attribute_count(object->handle, pError, + &session->deviceError); +} + +static CK_RV +nss_dbm_mdObject_GetAttributeTypes( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE_PTR typeArray, + CK_ULONG ulCount) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return nss_dbm_db_get_object_attribute_types(object->handle, typeArray, + ulCount, &session->deviceError); +} + +static CK_ULONG +nss_dbm_mdObject_GetAttributeSize( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + CK_RV *pError) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return nss_dbm_db_get_object_attribute_size(object->handle, attribute, pError, + &session->deviceError); +} + +static NSSItem * +nss_dbm_mdObject_GetAttribute( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + CK_RV *pError) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return nss_dbm_db_get_object_attribute(object->handle, object->arena, attribute, + pError, &session->deviceError); +} + +static CK_RV +nss_dbm_mdObject_SetAttribute( + NSSCKMDObject *mdObject, + NSSCKFWObject *fwObject, + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_TYPE attribute, + NSSItem *value) +{ + nss_dbm_object_t *object = (nss_dbm_object_t *)mdObject->etc; + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return nss_dbm_db_set_object_attribute(object->handle, attribute, value, + &session->deviceError); +} + +NSS_IMPLEMENT NSSCKMDObject * +nss_dbm_mdObject_factory( + nss_dbm_object_t *object, + CK_RV *pError) +{ + NSSCKMDObject *rv; + + rv = nss_ZNEW(object->arena, NSSCKMDObject); + if ((NSSCKMDObject *)NULL == rv) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + + rv->etc = (void *)object; + rv->Finalize = nss_dbm_mdObject_Finalize; + rv->Destroy = nss_dbm_mdObject_Destroy; + /* IsTokenObject can be deferred */ + rv->GetAttributeCount = nss_dbm_mdObject_GetAttributeCount; + rv->GetAttributeTypes = nss_dbm_mdObject_GetAttributeTypes; + rv->GetAttributeSize = nss_dbm_mdObject_GetAttributeSize; + rv->GetAttribute = nss_dbm_mdObject_GetAttribute; + rv->SetAttribute = nss_dbm_mdObject_SetAttribute; + /* GetObjectSize can be deferred */ + + return rv; +} diff --git a/security/nss/lib/ckfw/dbm/session.c b/security/nss/lib/ckfw/dbm/session.c new file mode 100644 index 000000000..a1c2ee5fa --- /dev/null +++ b/security/nss/lib/ckfw/dbm/session.c @@ -0,0 +1,255 @@ +/* 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" + +static void +nss_dbm_mdSession_Close( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + + struct nss_dbm_dbt_node *w; + + /* Lock */ + { + if (CKR_OK != NSSCKFWMutex_Lock(session->list_lock)) { + return; + } + + w = session->session_objects; + session->session_objects = (struct nss_dbm_dbt_node *)NULL; /* sanity */ + + (void)NSSCKFWMutex_Unlock(session->list_lock); + } + + for (; (struct nss_dbm_dbt_node *)NULL != w; w = w->next) { + (void)nss_dbm_db_delete_object(w->dbt); + } +} + +static CK_ULONG +nss_dbm_mdSession_GetDeviceError( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + return session->deviceError; +} + +/* Login isn't needed */ +/* Logout isn't needed */ +/* InitPIN is irrelevant */ +/* SetPIN is irrelevant */ +/* GetOperationStateLen is irrelevant */ +/* GetOperationState is irrelevant */ +/* SetOperationState is irrelevant */ + +static NSSCKMDObject * +nss_dbm_mdSession_CreateObject( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSArena *handyArenaPointer, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError) +{ + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + CK_ULONG i; + CK_BBOOL isToken = CK_FALSE; /* defaults to false */ + NSSCKMDObject *rv; + struct nss_dbm_dbt_node *node = (struct nss_dbm_dbt_node *)NULL; + nss_dbm_object_t *object; + nss_dbm_db_t *which_db; + + /* This framework should really pass this to me */ + for (i = 0; i < ulAttributeCount; i++) { + if (CKA_TOKEN == pTemplate[i].type) { + isToken = *(CK_BBOOL *)pTemplate[i].pValue; + break; + } + } + + object = nss_ZNEW(handyArenaPointer, nss_dbm_object_t); + if ((nss_dbm_object_t *)NULL == object) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + + object->arena = handyArenaPointer; + which_db = isToken ? token->slot->token_db : token->session_db; + + /* Do this before the actual database call; it's easier to recover from */ + rv = nss_dbm_mdObject_factory(object, pError); + if ((NSSCKMDObject *)NULL == rv) { + return (NSSCKMDObject *)NULL; + } + + if (CK_FALSE == isToken) { + node = nss_ZNEW(session->arena, struct nss_dbm_dbt_node); + if ((struct nss_dbm_dbt_node *)NULL == node) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDObject *)NULL; + } + } + + object->handle = nss_dbm_db_create_object(handyArenaPointer, which_db, + pTemplate, ulAttributeCount, + pError, &session->deviceError); + if ((nss_dbm_dbt_t *)NULL == object->handle) { + return (NSSCKMDObject *)NULL; + } + + if (CK_FALSE == isToken) { + node->dbt = object->handle; + /* Lock */ + { + *pError = NSSCKFWMutex_Lock(session->list_lock); + if (CKR_OK != *pError) { + (void)nss_dbm_db_delete_object(object->handle); + return (NSSCKMDObject *)NULL; + } + + node->next = session->session_objects; + session->session_objects = node; + + *pError = NSSCKFWMutex_Unlock(session->list_lock); + } + } + + return rv; +} + +/* CopyObject isn't needed; the framework will use CreateObject */ + +static NSSCKMDFindObjects * +nss_dbm_mdSession_FindObjectsInit( + NSSCKMDSession *mdSession, + NSSCKFWSession *fwSession, + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_RV *pError) +{ + nss_dbm_session_t *session = (nss_dbm_session_t *)mdSession->etc; + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + NSSArena *arena; + nss_dbm_find_t *find; + NSSCKMDFindObjects *rv; + + arena = NSSArena_Create(); + if ((NSSArena *)NULL == arena) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + + find = nss_ZNEW(arena, nss_dbm_find_t); + if ((nss_dbm_find_t *)NULL == find) { + *pError = CKR_HOST_MEMORY; + goto loser; + } + + find->arena = arena; + find->list_lock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError); + if ((NSSCKFWMutex *)NULL == find->list_lock) { + goto loser; + } + + *pError = nss_dbm_db_find_objects(find, token->slot->token_db, pTemplate, + ulAttributeCount, &session->deviceError); + if (CKR_OK != *pError) { + goto loser; + } + + *pError = nss_dbm_db_find_objects(find, token->session_db, pTemplate, + ulAttributeCount, &session->deviceError); + if (CKR_OK != *pError) { + goto loser; + } + + rv = nss_dbm_mdFindObjects_factory(find, pError); + if ((NSSCKMDFindObjects *)NULL == rv) { + goto loser; + } + + return rv; + +loser: + if ((NSSArena *)NULL != arena) { + (void)NSSArena_Destroy(arena); + } + + return (NSSCKMDFindObjects *)NULL; +} + +/* SeedRandom is irrelevant */ +/* GetRandom is irrelevant */ + +NSS_IMPLEMENT NSSCKMDSession * +nss_dbm_mdSession_factory( + nss_dbm_token_t *token, + NSSCKFWSession *fwSession, + NSSCKFWInstance *fwInstance, + CK_BBOOL rw, + CK_RV *pError) +{ + NSSArena *arena; + nss_dbm_session_t *session; + NSSCKMDSession *rv; + + arena = NSSCKFWSession_GetArena(fwSession, pError); + + session = nss_ZNEW(arena, nss_dbm_session_t); + if ((nss_dbm_session_t *)NULL == session) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDSession *)NULL; + } + + rv = nss_ZNEW(arena, NSSCKMDSession); + if ((NSSCKMDSession *)NULL == rv) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDSession *)NULL; + } + + session->arena = arena; + session->token = token; + session->list_lock = NSSCKFWInstance_CreateMutex(fwInstance, arena, pError); + if ((NSSCKFWMutex *)NULL == session->list_lock) { + return (NSSCKMDSession *)NULL; + } + + rv->etc = (void *)session; + rv->Close = nss_dbm_mdSession_Close; + rv->GetDeviceError = nss_dbm_mdSession_GetDeviceError; + /* Login isn't needed */ + /* Logout isn't needed */ + /* InitPIN is irrelevant */ + /* SetPIN is irrelevant */ + /* GetOperationStateLen is irrelevant */ + /* GetOperationState is irrelevant */ + /* SetOperationState is irrelevant */ + rv->CreateObject = nss_dbm_mdSession_CreateObject; + /* CopyObject isn't needed; the framework will use CreateObject */ + rv->FindObjectsInit = nss_dbm_mdSession_FindObjectsInit; + rv->null = NULL; + + return rv; +} diff --git a/security/nss/lib/ckfw/dbm/slot.c b/security/nss/lib/ckfw/dbm/slot.c new file mode 100644 index 000000000..06824d59e --- /dev/null +++ b/security/nss/lib/ckfw/dbm/slot.c @@ -0,0 +1,165 @@ +/* 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" + +static CK_RV +nss_dbm_mdSlot_Initialize( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_slot_t *slot = (nss_dbm_slot_t *)mdSlot->etc; + nss_dbm_instance_t *instance = (nss_dbm_instance_t *)mdInstance->etc; + CK_RV rv = CKR_OK; + + slot->token_db = nss_dbm_db_open(instance->arena, fwInstance, slot->filename, + slot->flags, &rv); + if ((nss_dbm_db_t *)NULL == slot->token_db) { + if (CKR_TOKEN_NOT_PRESENT == rv) { + /* This is not an error-- just means "the token isn't there" */ + rv = CKR_OK; + } + } + + return rv; +} + +static void +nss_dbm_mdSlot_Destroy( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_slot_t *slot = (nss_dbm_slot_t *)mdSlot->etc; + + if ((nss_dbm_db_t *)NULL != slot->token_db) { + nss_dbm_db_close(slot->token_db); + slot->token_db = (nss_dbm_db_t *)NULL; + } +} + +static NSSUTF8 * +nss_dbm_mdSlot_GetSlotDescription( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "Database"; +} + +static NSSUTF8 * +nss_dbm_mdSlot_GetManufacturerID( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "Berkeley"; +} + +static CK_BBOOL +nss_dbm_mdSlot_GetTokenPresent( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_slot_t *slot = (nss_dbm_slot_t *)mdSlot->etc; + + if ((nss_dbm_db_t *)NULL == slot->token_db) { + return CK_FALSE; + } else { + return CK_TRUE; + } +} + +static CK_BBOOL +nss_dbm_mdSlot_GetRemovableDevice( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + /* + * Well, this supports "tokens" (databases) that aren't there, so in + * that sense they're removable. It'd be nice to handle databases + * that suddenly disappear (NFS-mounted home directories and network + * errors, for instance) but that's a harder problem. We'll say + * we support removable devices, badly. + */ + + return CK_TRUE; +} + +/* nss_dbm_mdSlot_GetHardwareSlot defaults to CK_FALSE */ +/* + * nss_dbm_mdSlot_GetHardwareVersion + * nss_dbm_mdSlot_GetFirmwareVersion + * + * These are kinda fuzzy concepts here. I suppose we could return the + * Berkeley DB version for one of them, if we had an actual number we + * were confident in. But mcom's "dbm" has been hacked enough that I + * don't really know from what "real" version it stems.. + */ + +static NSSCKMDToken * +nss_dbm_mdSlot_GetToken( + NSSCKMDSlot *mdSlot, + NSSCKFWSlot *fwSlot, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + nss_dbm_slot_t *slot = (nss_dbm_slot_t *)mdSlot->etc; + return nss_dbm_mdToken_factory(slot, pError); +} + +NSS_IMPLEMENT NSSCKMDSlot * +nss_dbm_mdSlot_factory( + nss_dbm_instance_t *instance, + char *filename, + int flags, + CK_RV *pError) +{ + nss_dbm_slot_t *slot; + NSSCKMDSlot *rv; + + slot = nss_ZNEW(instance->arena, nss_dbm_slot_t); + if ((nss_dbm_slot_t *)NULL == slot) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDSlot *)NULL; + } + + slot->instance = instance; + slot->filename = filename; + slot->flags = flags; + slot->token_db = (nss_dbm_db_t *)NULL; + + rv = nss_ZNEW(instance->arena, NSSCKMDSlot); + if ((NSSCKMDSlot *)NULL == rv) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDSlot *)NULL; + } + + rv->etc = (void *)slot; + rv->Initialize = nss_dbm_mdSlot_Initialize; + rv->Destroy = nss_dbm_mdSlot_Destroy; + rv->GetSlotDescription = nss_dbm_mdSlot_GetSlotDescription; + rv->GetManufacturerID = nss_dbm_mdSlot_GetManufacturerID; + rv->GetTokenPresent = nss_dbm_mdSlot_GetTokenPresent; + rv->GetRemovableDevice = nss_dbm_mdSlot_GetRemovableDevice; + /* GetHardwareSlot */ + /* GetHardwareVersion */ + /* GetFirmwareVersion */ + rv->GetToken = nss_dbm_mdSlot_GetToken; + rv->null = (void *)NULL; + + return rv; +} diff --git a/security/nss/lib/ckfw/dbm/token.c b/security/nss/lib/ckfw/dbm/token.c new file mode 100644 index 000000000..6873bf0ec --- /dev/null +++ b/security/nss/lib/ckfw/dbm/token.c @@ -0,0 +1,260 @@ +/* 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" + +static CK_RV +nss_dbm_mdToken_Setup( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + CK_RV rv = CKR_OK; + + token->arena = NSSCKFWToken_GetArena(fwToken, &rv); + token->session_db = nss_dbm_db_open(token->arena, fwInstance, (char *)NULL, + O_RDWR | O_CREAT, &rv); + if ((nss_dbm_db_t *)NULL == token->session_db) { + return rv; + } + + /* Add a label record if there isn't one? */ + + return CKR_OK; +} + +static void +nss_dbm_mdToken_Invalidate( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + + if ((nss_dbm_db_t *)NULL != token->session_db) { + nss_dbm_db_close(token->session_db); + token->session_db = (nss_dbm_db_t *)NULL; + } +} + +static CK_RV +nss_dbm_mdToken_InitToken( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSItem *pin, + NSSUTF8 *label) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + nss_dbm_instance_t *instance = (nss_dbm_instance_t *)mdInstance->etc; + CK_RV rv; + + /* Wipe the session object data */ + + if ((nss_dbm_db_t *)NULL != token->session_db) { + nss_dbm_db_close(token->session_db); + } + + token->session_db = nss_dbm_db_open(token->arena, fwInstance, (char *)NULL, + O_RDWR | O_CREAT, &rv); + if ((nss_dbm_db_t *)NULL == token->session_db) { + return rv; + } + + /* Wipe the token object data */ + + if (token->slot->flags & O_RDWR) { + if ((nss_dbm_db_t *)NULL != token->slot->token_db) { + nss_dbm_db_close(token->slot->token_db); + } + + token->slot->token_db = nss_dbm_db_open(instance->arena, fwInstance, + token->slot->filename, + token->slot->flags | O_CREAT | O_TRUNC, + &rv); + if ((nss_dbm_db_t *)NULL == token->slot->token_db) { + return rv; + } + + /* PIN is irrelevant */ + + rv = nss_dbm_db_set_label(token->slot->token_db, label); + if (CKR_OK != rv) { + return rv; + } + } + + return CKR_OK; +} + +static NSSUTF8 * +nss_dbm_mdToken_GetLabel( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + + if ((NSSUTF8 *)NULL == token->label) { + token->label = nss_dbm_db_get_label(token->slot->token_db, token->arena, pError); + } + + /* If no label has been set, return *something* */ + if ((NSSUTF8 *)NULL == token->label) { + return token->slot->filename; + } + + return token->label; +} + +static NSSUTF8 * +nss_dbm_mdToken_GetManufacturerID( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "mozilla.org NSS"; +} + +static NSSUTF8 * +nss_dbm_mdToken_GetModel( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + CK_RV *pError) +{ + return "dbm"; +} + +/* GetSerialNumber is irrelevant */ +/* GetHasRNG defaults to CK_FALSE */ + +static CK_BBOOL +nss_dbm_mdToken_GetIsWriteProtected( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + + if (token->slot->flags & O_RDWR) { + return CK_FALSE; + } else { + return CK_TRUE; + } +} + +/* GetLoginRequired defaults to CK_FALSE */ +/* GetUserPinInitialized defaults to CK_FALSE */ +/* GetRestoreKeyNotNeeded is irrelevant */ +/* GetHasClockOnToken defaults to CK_FALSE */ +/* GetHasProtectedAuthenticationPath defaults to CK_FALSE */ +/* GetSupportsDualCryptoOperations is irrelevant */ + +static CK_ULONG +nss_dbm_mdToken_effectively_infinite( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + return CK_EFFECTIVELY_INFINITE; +} + +static CK_VERSION +nss_dbm_mdToken_GetHardwareVersion( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + return nss_dbm_db_get_format_version(token->slot->token_db); +} + +/* GetFirmwareVersion is irrelevant */ +/* GetUTCTime is irrelevant */ + +static NSSCKMDSession * +nss_dbm_mdToken_OpenSession( + NSSCKMDToken *mdToken, + NSSCKFWToken *fwToken, + NSSCKMDInstance *mdInstance, + NSSCKFWInstance *fwInstance, + NSSCKFWSession *fwSession, + CK_BBOOL rw, + CK_RV *pError) +{ + nss_dbm_token_t *token = (nss_dbm_token_t *)mdToken->etc; + return nss_dbm_mdSession_factory(token, fwSession, fwInstance, rw, pError); +} + +/* GetMechanismCount defaults to zero */ +/* GetMechanismTypes is irrelevant */ +/* GetMechanism is irrelevant */ + +NSS_IMPLEMENT NSSCKMDToken * +nss_dbm_mdToken_factory( + nss_dbm_slot_t *slot, + CK_RV *pError) +{ + nss_dbm_token_t *token; + NSSCKMDToken *rv; + + token = nss_ZNEW(slot->instance->arena, nss_dbm_token_t); + if ((nss_dbm_token_t *)NULL == token) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDToken *)NULL; + } + + rv = nss_ZNEW(slot->instance->arena, NSSCKMDToken); + if ((NSSCKMDToken *)NULL == rv) { + *pError = CKR_HOST_MEMORY; + return (NSSCKMDToken *)NULL; + } + + token->slot = slot; + + rv->etc = (void *)token; + rv->Setup = nss_dbm_mdToken_Setup; + rv->Invalidate = nss_dbm_mdToken_Invalidate; + rv->InitToken = nss_dbm_mdToken_InitToken; + rv->GetLabel = nss_dbm_mdToken_GetLabel; + rv->GetManufacturerID = nss_dbm_mdToken_GetManufacturerID; + rv->GetModel = nss_dbm_mdToken_GetModel; + /* GetSerialNumber is irrelevant */ + /* GetHasRNG defaults to CK_FALSE */ + rv->GetIsWriteProtected = nss_dbm_mdToken_GetIsWriteProtected; + /* GetLoginRequired defaults to CK_FALSE */ + /* GetUserPinInitialized defaults to CK_FALSE */ + /* GetRestoreKeyNotNeeded is irrelevant */ + /* GetHasClockOnToken defaults to CK_FALSE */ + /* GetHasProtectedAuthenticationPath defaults to CK_FALSE */ + /* GetSupportsDualCryptoOperations is irrelevant */ + rv->GetMaxSessionCount = nss_dbm_mdToken_effectively_infinite; + rv->GetMaxRwSessionCount = nss_dbm_mdToken_effectively_infinite; + /* GetMaxPinLen is irrelevant */ + /* GetMinPinLen is irrelevant */ + /* GetTotalPublicMemory defaults to CK_UNAVAILABLE_INFORMATION */ + /* GetFreePublicMemory defaults to CK_UNAVAILABLE_INFORMATION */ + /* GetTotalPrivateMemory defaults to CK_UNAVAILABLE_INFORMATION */ + /* GetFreePrivateMemory defaults to CK_UNAVAILABLE_INFORMATION */ + rv->GetHardwareVersion = nss_dbm_mdToken_GetHardwareVersion; + /* GetFirmwareVersion is irrelevant */ + /* GetUTCTime is irrelevant */ + rv->OpenSession = nss_dbm_mdToken_OpenSession; + rv->null = NULL; + + return rv; +} |