diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-11-09 05:12:59 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-11-09 05:12:59 +0000 |
commit | 26c046fbc57d53136b4fb3b5e0d18298318125d4 (patch) | |
tree | 0397d2184e7fba8a51f7fb9a6fc01a82d0748411 /nss/lib/ckfw/dbm | |
parent | c416b91e36567df4ec765a495c5a6ca6a1853f58 (diff) | |
download | nss-26c046fbc57d53136b4fb3b5e0d18298318125d4.tar.gz |
nss-3.21nss-3.21
Diffstat (limited to 'nss/lib/ckfw/dbm')
-rw-r--r-- | nss/lib/ckfw/dbm/Makefile | 9 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/anchor.c | 17 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/ckdbm.h | 248 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/config.mk | 8 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/db.c | 1033 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/find.c | 133 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/instance.c | 163 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/manifest.mn | 25 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/object.c | 171 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/session.c | 265 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/slot.c | 181 | ||||
-rw-r--r-- | nss/lib/ckfw/dbm/token.c | 282 |
12 files changed, 2535 insertions, 0 deletions
diff --git a/nss/lib/ckfw/dbm/Makefile b/nss/lib/ckfw/dbm/Makefile new file mode 100644 index 0000000..07ae967 --- /dev/null +++ b/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/nss/lib/ckfw/dbm/anchor.c b/nss/lib/ckfw/dbm/anchor.c new file mode 100644 index 0000000..f004b1e --- /dev/null +++ b/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/nss/lib/ckfw/dbm/ckdbm.h b/nss/lib/ckfw/dbm/ckdbm.h new file mode 100644 index 0000000..4f9df93 --- /dev/null +++ b/nss/lib/ckfw/dbm/ckdbm.h @@ -0,0 +1,248 @@ +/* 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/nss/lib/ckfw/dbm/config.mk b/nss/lib/ckfw/dbm/config.mk new file mode 100644 index 0000000..a1991e5 --- /dev/null +++ b/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/nss/lib/ckfw/dbm/db.c b/nss/lib/ckfw/dbm/db.c new file mode 100644 index 0000000..8d0a6cb --- /dev/null +++ b/nss/lib/ckfw/dbm/db.c @@ -0,0 +1,1033 @@ +/* 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/nss/lib/ckfw/dbm/find.c b/nss/lib/ckfw/dbm/find.c new file mode 100644 index 0000000..575c0ad --- /dev/null +++ b/nss/lib/ckfw/dbm/find.c @@ -0,0 +1,133 @@ +/* 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/nss/lib/ckfw/dbm/instance.c b/nss/lib/ckfw/dbm/instance.c new file mode 100644 index 0000000..14f7af8 --- /dev/null +++ b/nss/lib/ckfw/dbm/instance.c @@ -0,0 +1,163 @@ +/* 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/nss/lib/ckfw/dbm/manifest.mn b/nss/lib/ckfw/dbm/manifest.mn new file mode 100644 index 0000000..1f87f43 --- /dev/null +++ b/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/nss/lib/ckfw/dbm/object.c b/nss/lib/ckfw/dbm/object.c new file mode 100644 index 0000000..0649d40 --- /dev/null +++ b/nss/lib/ckfw/dbm/object.c @@ -0,0 +1,171 @@ +/* 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/nss/lib/ckfw/dbm/session.c b/nss/lib/ckfw/dbm/session.c new file mode 100644 index 0000000..6101c06 --- /dev/null +++ b/nss/lib/ckfw/dbm/session.c @@ -0,0 +1,265 @@ +/* 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/nss/lib/ckfw/dbm/slot.c b/nss/lib/ckfw/dbm/slot.c new file mode 100644 index 0000000..0b7e645 --- /dev/null +++ b/nss/lib/ckfw/dbm/slot.c @@ -0,0 +1,181 @@ +/* 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/nss/lib/ckfw/dbm/token.c b/nss/lib/ckfw/dbm/token.c new file mode 100644 index 0000000..e033e15 --- /dev/null +++ b/nss/lib/ckfw/dbm/token.c @@ -0,0 +1,282 @@ +/* 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; +} |