mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 11:40:13 +01:00
a572ea8ca3
bug1095307, bug1073330(backout), bug1084986, bug1050069, bug942172, bug1054547, bug532081, bug1096348, bug1058870, bug1093940, bug1102985, bug1112461, bug1094492, bug112029, bug1119983, bug1120685, bug1120691, bug1113632, bug863076, bug1082973, bug1124539, bug1117617, bug1117621, bug1121273, bug753136, bug921684, bug1132818, bug1125375, bug647690, bug1055441, bug1134455, bug975010, bug950369, bug1128367, bug1129573, bug1136095, bug1117897, bug1113453, bug1061725, bug1073330, bug1111901, bug1083900, bug1136095, bug1138820, bug1096741, bug1134548, bug345725, bug950348, bug950344, bug1151037, bug991783, bug1153994
1034 lines
22 KiB
C
1034 lines
22 KiB
C
/* 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;
|
|
}
|