mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-28 20:55:39 +00:00
646 lines
18 KiB
C
646 lines
18 KiB
C
/*
|
|
* The contents of this file are subject to the Mozilla Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/MPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is the Netscape security libraries.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*
|
|
* Alternatively, the contents of this file may be used under the
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
* instead of those above. If you wish to allow use of your
|
|
* version of this file only under the terms of the GPL and not to
|
|
* allow others to use your version of this file under the MPL,
|
|
* indicate your decision by deleting the provisions above and
|
|
* replace them with the notice and other provisions required by
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
* may use your version of this file under either the MPL or the
|
|
* GPL.
|
|
*/
|
|
/*
|
|
* The following code handles the storage of PKCS 11 modules used by the
|
|
* NSS. This file is written to abstract away how the modules are
|
|
* stored so we can deside that later.
|
|
*/
|
|
#include "seccomon.h"
|
|
#include "secmod.h"
|
|
#include "prlock.h"
|
|
#include "pkcs11.h"
|
|
#include "secmodi.h"
|
|
#include "pk11func.h"
|
|
#include "mcom_db.h"
|
|
|
|
/* create a new module */
|
|
SECMODModule *SECMOD_NewModule(void) {
|
|
SECMODModule *newMod;
|
|
PRArenaPool *arena;
|
|
|
|
|
|
/* create an arena in which dllName and commonName can be
|
|
* allocated.
|
|
*/
|
|
arena = PORT_NewArena(512);
|
|
if (arena == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule));
|
|
if (newMod == NULL) {
|
|
PORT_FreeArena(arena,PR_FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* initialize of the fields of the module
|
|
*/
|
|
newMod->arena = arena;
|
|
newMod->internal = PR_FALSE;
|
|
newMod->loaded = PR_FALSE;
|
|
newMod->isFIPS = PR_FALSE;
|
|
newMod->dllName = NULL;
|
|
newMod->commonName = NULL;
|
|
newMod->library = NULL;
|
|
newMod->functionList = NULL;
|
|
newMod->slotCount = 0;
|
|
newMod->slots = NULL;
|
|
newMod->slotInfo = NULL;
|
|
newMod->slotInfoCount = 0;
|
|
newMod->refCount = 1;
|
|
newMod->ssl[0] = 0;
|
|
newMod->ssl[1] = 0;
|
|
#ifdef PKCS11_USE_THREADS
|
|
newMod->refLock = (void *)PR_NewLock();
|
|
if (newMod->refLock == NULL) {
|
|
PORT_FreeArena(arena,PR_FALSE);
|
|
return NULL;
|
|
}
|
|
#else
|
|
newMod->refLock = NULL;
|
|
#endif
|
|
return newMod;
|
|
|
|
}
|
|
|
|
/* create a new ModuleListElement */
|
|
SECMODModuleList *SECMOD_NewModuleListElement(void) {
|
|
SECMODModuleList *newModList;
|
|
|
|
newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
|
|
if (newModList) {
|
|
newModList->next = NULL;
|
|
newModList->module = NULL;
|
|
}
|
|
return newModList;
|
|
}
|
|
|
|
static unsigned long internalFlags = SECMOD_RSA_FLAG|SECMOD_DSA_FLAG|
|
|
SECMOD_RC2_FLAG| SECMOD_RC4_FLAG|SECMOD_DES_FLAG|SECMOD_RANDOM_FLAG|
|
|
SECMOD_SHA1_FLAG|SECMOD_MD5_FLAG|SECMOD_MD2_FLAG|SECMOD_SSL_FLAG|
|
|
SECMOD_TLS_FLAG;
|
|
|
|
/* create a Internal module */
|
|
SECMODModule *SECMOD_NewInternal(void) {
|
|
SECMODModule *intern;
|
|
static PK11PreSlotInfo internSlotInfo =
|
|
{ 1, SECMOD_RSA_FLAG|SECMOD_DSA_FLAG|SECMOD_RC2_FLAG|
|
|
SECMOD_RC4_FLAG|SECMOD_DES_FLAG|SECMOD_RANDOM_FLAG|
|
|
SECMOD_SHA1_FLAG|SECMOD_MD5_FLAG|SECMOD_MD2_FLAG|
|
|
SECMOD_SSL_FLAG|SECMOD_TLS_FLAG, -1, 30 };
|
|
|
|
intern = SECMOD_NewModule();
|
|
if (intern == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* make this module an internal module
|
|
*/
|
|
intern->commonName = "Netscape Internal PKCS #11 Module";
|
|
intern->internal = PR_TRUE;
|
|
intern->slotInfoCount = 1;
|
|
intern->slotInfo = &internSlotInfo;
|
|
|
|
return (intern);
|
|
}
|
|
|
|
/* create a FIPS Internal module */
|
|
SECMODModule *SECMOD_GetFIPSInternal(void) {
|
|
SECMODModule *intern;
|
|
|
|
intern = SECMOD_NewInternal();
|
|
if (intern == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* make this module a FIPS internal module
|
|
*/
|
|
intern->slotInfo[0].slotID = 3; /* FIPS slot */
|
|
intern->commonName = "Netscape Internal FIPS PKCS #11 Module";
|
|
intern->isFIPS = PR_TRUE;
|
|
|
|
return (intern);
|
|
}
|
|
|
|
SECMODModule *SECMOD_DupModule(SECMODModule *old) {
|
|
SECMODModule *newMod;
|
|
|
|
newMod = SECMOD_NewModule();
|
|
if (newMod == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* initialize of the fields of the module
|
|
*/
|
|
newMod->dllName = PORT_ArenaStrdup(newMod->arena,old->dllName);
|
|
newMod->commonName = PORT_ArenaStrdup(newMod->arena,old->commonName);;
|
|
|
|
return newMod;
|
|
|
|
}
|
|
|
|
/*
|
|
* make a new reference to a module so It doesn't go away on us
|
|
*/
|
|
SECMODModule *
|
|
SECMOD_ReferenceModule(SECMODModule *module) {
|
|
PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
|
|
PORT_Assert(module->refCount > 0);
|
|
|
|
module->refCount++;
|
|
PK11_USE_THREADS(PR_Unlock((PRLock*)module->refLock);)
|
|
return module;
|
|
}
|
|
|
|
|
|
/* destroy an existing module */
|
|
void
|
|
SECMOD_DestroyModule(SECMODModule *module) {
|
|
PRBool willfree = PR_FALSE;
|
|
int slotCount;
|
|
int i;
|
|
|
|
PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
|
|
if (module->refCount-- == 1) {
|
|
willfree = PR_TRUE;
|
|
}
|
|
PORT_Assert(willfree || (module->refCount > 0));
|
|
PK11_USE_THREADS(PR_Unlock((PRLock *)module->refLock);)
|
|
|
|
if (!willfree) {
|
|
return;
|
|
}
|
|
|
|
/* slots can't really disappear until our module starts freeing them,
|
|
* so this check is safe */
|
|
slotCount = module->slotCount;
|
|
if (slotCount == 0) {
|
|
SECMOD_SlotDestroyModule(module,PR_FALSE);
|
|
return;
|
|
}
|
|
|
|
/* now free all out slots, when they are done, they will cause the
|
|
* module to disappear altogether */
|
|
for (i=0 ; i < slotCount; i++) {
|
|
if (!module->slots[i]->disabled) {
|
|
PK11_ClearSlotList(module->slots[i]);
|
|
}
|
|
PK11_FreeSlot(module->slots[i]);
|
|
}
|
|
/* WARNING: once the last slot has been freed is it possible (even likely)
|
|
* that module is no more... touching it now is a good way to go south */
|
|
}
|
|
|
|
|
|
/* we can only get here if we've destroyed the module, or some one has
|
|
* erroneously freed a slot that wasn't referenced. */
|
|
void
|
|
SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) {
|
|
PRBool willfree = PR_FALSE;
|
|
if (fromSlot) {
|
|
PORT_Assert(module->refCount == 0);
|
|
PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
|
|
if (module->slotCount-- == 1) {
|
|
willfree = PR_TRUE;
|
|
}
|
|
PORT_Assert(willfree || (module->slotCount > 0));
|
|
PK11_USE_THREADS(PR_Unlock((PRLock *)module->refLock);)
|
|
if (!willfree) return;
|
|
}
|
|
if (module->loaded) {
|
|
SECMOD_UnloadModule(module);
|
|
}
|
|
PK11_USE_THREADS(PR_DestroyLock((PRLock *)module->refLock);)
|
|
PORT_FreeArena(module->arena,PR_FALSE);
|
|
}
|
|
|
|
/* destroy a list element
|
|
* this destroys a single element, and returns the next element
|
|
* on the chain. It makes it easy to implement for loops to delete
|
|
* the chain. It also make deleting a single element easy */
|
|
SECMODModuleList *
|
|
SECMOD_DestroyModuleListElement(SECMODModuleList *element) {
|
|
SECMODModuleList *next = element->next;
|
|
|
|
if (element->module) {
|
|
SECMOD_DestroyModule(element->module);
|
|
element->module = NULL;
|
|
}
|
|
PORT_Free(element);
|
|
return next;
|
|
}
|
|
|
|
|
|
/*
|
|
* Destroy an entire module list
|
|
*/
|
|
void
|
|
SECMOD_DestroyModuleList(SECMODModuleList *list) {
|
|
SECMODModuleList *lp;
|
|
|
|
for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
|
|
}
|
|
|
|
|
|
/* Construct a database key for a given module */
|
|
static SECStatus secmod_MakeKey(DBT *key, SECMODModule * module) {
|
|
int len = 0;
|
|
|
|
len = PORT_Strlen(module->commonName);
|
|
key->data = module->commonName;
|
|
key->size = len;
|
|
return SECSuccess;
|
|
}
|
|
|
|
/* free out constructed database key */
|
|
static void secmod_FreeKey(DBT *key) {
|
|
key->data = NULL;
|
|
key->size = 0;
|
|
}
|
|
|
|
typedef struct secmodDataStr secmodData;
|
|
typedef struct secmodSlotDataStr secmodSlotData;
|
|
struct secmodDataStr {
|
|
unsigned char major;
|
|
unsigned char minor;
|
|
unsigned char nameStart[2];
|
|
unsigned char slotOffset[2];
|
|
unsigned char internal;
|
|
unsigned char fips;
|
|
unsigned char ssl[8];
|
|
unsigned char names[4]; /* enough space for the length fields */
|
|
};
|
|
|
|
struct secmodSlotDataStr {
|
|
unsigned char slotID[4];
|
|
unsigned char defaultFlags[4];
|
|
unsigned char timeout[4];
|
|
unsigned char askpw;
|
|
unsigned char reserved[19]; /* this makes it a round 32 bytes */
|
|
};
|
|
|
|
#define SECMOD_DB_VERSION_MAJOR 0
|
|
#define SECMOD_DB_VERSION_MINOR 4
|
|
#define SECMOD_DB_NOUI_VERSION_MAJOR 0
|
|
#define SECMOD_DB_NOUI_VERSION_MINOR 3
|
|
|
|
#define SECMOD_PUTSHORT(dest,src) \
|
|
(dest)[1] = (unsigned char) ((src)&0xff); \
|
|
(dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
|
|
#define SECMOD_PUTLONG(dest,src) \
|
|
(dest)[3] = (unsigned char) ((src)&0xff); \
|
|
(dest)[2] = (unsigned char) (((src) >> 8) & 0xff); \
|
|
(dest)[1] = (unsigned char) (((src) >> 16) & 0xff); \
|
|
(dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
|
|
#define SECMOD_GETSHORT(src) \
|
|
((unsigned short) (((src)[0] << 8) | (src)[1]))
|
|
#define SECMOD_GETLONG(src) \
|
|
((unsigned long) (( (unsigned long) (src)[0] << 24) | \
|
|
( (unsigned long) (src)[1] << 16) | \
|
|
( (unsigned long) (src)[2] << 8) | \
|
|
(unsigned long) (src)[3]))
|
|
/*
|
|
* build a data base entry from a module
|
|
*/
|
|
static SECStatus secmod_EncodeData(DBT *data, SECMODModule * module) {
|
|
secmodData *encoded;
|
|
secmodSlotData *slot;
|
|
unsigned char *dataPtr;
|
|
unsigned short len, len2 = 0,count = 0;
|
|
unsigned short offset;
|
|
int dataLen, i, si;
|
|
|
|
len = PORT_Strlen(module->commonName);
|
|
if (module->dllName) {
|
|
len2 = PORT_Strlen(module->dllName);
|
|
}
|
|
if (module->slotCount != 0) {
|
|
for (i=0; i < module->slotCount; i++) {
|
|
if (module->slots[i]->defaultFlags != 0) {
|
|
count++;
|
|
}
|
|
}
|
|
} else {
|
|
count = module->slotInfoCount;
|
|
}
|
|
dataLen = sizeof(secmodData) + len + len2 + 2 +
|
|
count*sizeof(secmodSlotData);
|
|
|
|
data->data = (unsigned char *)
|
|
PORT_Alloc(dataLen);
|
|
encoded = (secmodData *)data->data;
|
|
dataPtr = (unsigned char *) data->data;
|
|
data->size = dataLen;
|
|
|
|
if (encoded == NULL) return SECFailure;
|
|
|
|
encoded->major = SECMOD_DB_VERSION_MAJOR;
|
|
encoded->minor = SECMOD_DB_VERSION_MINOR;
|
|
encoded->internal = (unsigned char) (module->internal ? 1 : 0);
|
|
encoded->fips = (unsigned char) (module->isFIPS ? 1 : 0);
|
|
SECMOD_PUTLONG(encoded->ssl,module->ssl[0]);
|
|
SECMOD_PUTLONG(&encoded->ssl[4],module->ssl[1]);
|
|
|
|
offset = (unsigned long) &(((secmodData *)0)->names[0]);
|
|
SECMOD_PUTSHORT(encoded->nameStart,offset);
|
|
offset = offset +len + len2 + 4;
|
|
SECMOD_PUTSHORT(encoded->slotOffset,offset);
|
|
|
|
|
|
SECMOD_PUTSHORT(&dataPtr[offset],count);
|
|
slot = (secmodSlotData *)(dataPtr+offset+2);
|
|
|
|
SECMOD_PUTSHORT(encoded->names,len);
|
|
PORT_Memcpy(&encoded->names[2],module->commonName,len);
|
|
|
|
|
|
SECMOD_PUTSHORT(&encoded->names[len+2],len2);
|
|
if (len2) PORT_Memcpy(&encoded->names[len+4],module->dllName,len2);
|
|
|
|
if (module->slotCount) {
|
|
for (i=0,si=0; i < module->slotCount; i++) {
|
|
if (module->slots[i]->defaultFlags) {
|
|
SECMOD_PUTLONG(slot[si].slotID, module->slots[i]->slotID);
|
|
SECMOD_PUTLONG(slot[si].defaultFlags,
|
|
module->slots[i]->defaultFlags);
|
|
SECMOD_PUTLONG(slot[si].timeout,module->slots[i]->timeout);
|
|
slot[si].askpw = module->slots[i]->askpw;
|
|
PORT_Memset(slot[si].reserved, 0, sizeof(slot[si].reserved));
|
|
si++;
|
|
}
|
|
}
|
|
} else {
|
|
for (i=0; i < module->slotInfoCount; i++) {
|
|
SECMOD_PUTLONG(slot[i].slotID, module->slotInfo[i].slotID);
|
|
SECMOD_PUTLONG(slot[i].defaultFlags,
|
|
module->slotInfo[i].defaultFlags);
|
|
SECMOD_PUTLONG(slot[i].timeout,module->slotInfo[i].timeout);
|
|
slot[i].askpw = module->slotInfo[i].askpw;
|
|
PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
|
|
}
|
|
}
|
|
|
|
return SECSuccess;
|
|
|
|
}
|
|
|
|
static void secmod_FreeData(DBT *data) {
|
|
if (data->data) {
|
|
PORT_Free(data->data);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* build a module from the data base entry.
|
|
*/
|
|
static SECMODModule *secmod_DecodeData(DBT *data) {
|
|
SECMODModule * module;
|
|
secmodData *encoded;
|
|
secmodSlotData *slots;
|
|
unsigned char *names;
|
|
unsigned short len,len1;
|
|
unsigned long slotCount;
|
|
unsigned short offset;
|
|
PRBool isOldVersion = PR_FALSE;
|
|
int i;
|
|
|
|
encoded = (secmodData *)data->data;
|
|
names = (unsigned char *)data->data;
|
|
offset = SECMOD_GETSHORT(encoded->slotOffset);
|
|
slots = (secmodSlotData *) (names + offset + 2);
|
|
slotCount = SECMOD_GETSHORT(names + offset);
|
|
names += SECMOD_GETSHORT(encoded->nameStart);
|
|
|
|
module = SECMOD_NewModule();
|
|
if (module == NULL) return NULL;
|
|
|
|
module->internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
|
|
module->isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
|
|
len = SECMOD_GETSHORT(names);
|
|
|
|
if (module->internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
|
|
(encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
|
|
isOldVersion = PR_TRUE;
|
|
}
|
|
|
|
/* decode the common name */
|
|
module->commonName = (char*)PORT_ArenaAlloc(module->arena,len+1);
|
|
if (module->commonName == NULL) {
|
|
SECMOD_DestroyModule(module);
|
|
return NULL;
|
|
}
|
|
PORT_Memcpy(module->commonName,&names[2],len);
|
|
module->commonName[len] = 0;
|
|
|
|
/* decode the DLL name */
|
|
len1 = (names[len+2] << 8) | names[len+3];
|
|
if (len1) {
|
|
module->dllName = (char*)PORT_ArenaAlloc(module->arena,len1 + 1);
|
|
if (module->dllName == NULL) {
|
|
SECMOD_DestroyModule(module);
|
|
return NULL;
|
|
}
|
|
PORT_Memcpy(module->dllName,&names[len+4],len1);
|
|
module->dllName[len1] = 0;
|
|
}
|
|
|
|
module->slotInfoCount = slotCount;
|
|
module->slotInfo = (PK11PreSlotInfo *) PORT_ArenaAlloc(module->arena,
|
|
slotCount * sizeof(PK11PreSlotInfo));
|
|
for (i=0; i < (int) slotCount; i++) {
|
|
module->slotInfo[i].slotID = SECMOD_GETLONG(slots[i].slotID);
|
|
module->slotInfo[i].defaultFlags =
|
|
SECMOD_GETLONG(slots[i].defaultFlags);
|
|
if (isOldVersion && module->internal &&
|
|
(module->slotInfo[i].slotID != 2)) {
|
|
module->slotInfo[i].defaultFlags |= internalFlags;
|
|
}
|
|
module->slotInfo[i].timeout = SECMOD_GETLONG(slots[i].timeout);
|
|
module->slotInfo[i].askpw = slots[i].askpw;
|
|
if (module->slotInfo[i].askpw == 0xff) {
|
|
module->slotInfo[i].askpw = -1;
|
|
}
|
|
}
|
|
|
|
/* decode SSL cipher enable flags */
|
|
module->ssl[0] = SECMOD_GETLONG(encoded->ssl);
|
|
module->ssl[1] = SECMOD_GETLONG(&encoded->ssl[4]);
|
|
|
|
return (module);
|
|
}
|
|
|
|
/*
|
|
* open the PKCS #11 data base.
|
|
*/
|
|
static char *pkcs11dbName = NULL;
|
|
void SECMOD_InitDB(char *dbname) {
|
|
pkcs11dbName = PORT_Strdup(dbname);
|
|
}
|
|
|
|
|
|
static DB *secmod_OpenDB(PRBool readOnly) {
|
|
DB *pkcs11db = NULL;
|
|
char *dbname;
|
|
|
|
if (pkcs11dbName == NULL) return NULL;
|
|
dbname = pkcs11dbName;
|
|
|
|
/* I'm sure we should do more checks here sometime... */
|
|
pkcs11db = dbopen(dbname, readOnly ? O_RDONLY : O_RDWR, 0600, DB_HASH, 0);
|
|
|
|
/* didn't exist? create it */
|
|
if (pkcs11db == NULL) {
|
|
if (readOnly) return NULL;
|
|
|
|
pkcs11db = dbopen( dbname,
|
|
O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 );
|
|
if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0);
|
|
}
|
|
return pkcs11db;
|
|
}
|
|
|
|
static void secmod_CloseDB(DB *pkcs11db) {
|
|
(*pkcs11db->close)(pkcs11db);
|
|
}
|
|
|
|
/*
|
|
* Read all the existing modules in
|
|
*/
|
|
SECMODModuleList *
|
|
SECMOD_ReadPermDB(void) {
|
|
DBT key,data;
|
|
int ret;
|
|
DB *pkcs11db = NULL;
|
|
SECMODModuleList *newmod = NULL,*mod = NULL;
|
|
|
|
pkcs11db = secmod_OpenDB(PR_TRUE);
|
|
if (pkcs11db == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
/* read and parse the file or data base */
|
|
ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
|
|
if (ret) goto done;
|
|
|
|
do {
|
|
/* allocate space for modules */
|
|
newmod = SECMOD_NewModuleListElement();
|
|
if (newmod == NULL) break;
|
|
newmod->module = secmod_DecodeData(&data);
|
|
if (newmod->module == NULL) {
|
|
SECMOD_DestroyModuleListElement(newmod);
|
|
break;
|
|
}
|
|
newmod->next = mod;
|
|
mod = newmod;
|
|
} while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
|
|
|
|
done:
|
|
secmod_CloseDB(pkcs11db);
|
|
return mod;
|
|
}
|
|
|
|
/*
|
|
* Delete a module from the Data Base
|
|
*/
|
|
SECStatus
|
|
SECMOD_DeletePermDB(SECMODModule * module) {
|
|
DBT key;
|
|
SECStatus rv = SECFailure;
|
|
DB *pkcs11db = NULL;
|
|
int ret;
|
|
|
|
/* make sure we have a db handle */
|
|
pkcs11db = secmod_OpenDB(PR_FALSE);
|
|
if (pkcs11db == NULL) {
|
|
return SECFailure;
|
|
}
|
|
|
|
rv = secmod_MakeKey(&key,module);
|
|
if (rv != SECSuccess) goto done;
|
|
rv = SECFailure;
|
|
ret = (*pkcs11db->del)(pkcs11db, &key, 0);
|
|
secmod_FreeKey(&key);
|
|
if (ret != 0) goto done;
|
|
|
|
|
|
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
|
if (ret == 0) rv = SECSuccess;
|
|
|
|
done:
|
|
secmod_CloseDB(pkcs11db);
|
|
return rv;
|
|
}
|
|
|
|
/*
|
|
* Add a module to the Data base
|
|
*/
|
|
SECStatus
|
|
SECMOD_AddPermDB(SECMODModule *module) {
|
|
DBT key,data;
|
|
SECStatus rv = SECFailure;
|
|
DB *pkcs11db = NULL;
|
|
int ret;
|
|
|
|
/* make sure we have a db handle */
|
|
pkcs11db = secmod_OpenDB(PR_FALSE);
|
|
if (pkcs11db == NULL) {
|
|
return SECFailure;
|
|
}
|
|
|
|
rv = secmod_MakeKey(&key,module);
|
|
if (rv != SECSuccess) goto done;
|
|
rv = secmod_EncodeData(&data,module);
|
|
if (rv != SECSuccess) {
|
|
secmod_FreeKey(&key);
|
|
goto done;
|
|
}
|
|
rv = SECFailure;
|
|
ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
|
|
secmod_FreeKey(&key);
|
|
secmod_FreeData(&data);
|
|
if (ret != 0) goto done;
|
|
|
|
ret = (*pkcs11db->sync)(pkcs11db, 0);
|
|
if (ret == 0) rv = SECSuccess;
|
|
|
|
done:
|
|
secmod_CloseDB(pkcs11db);
|
|
return rv;
|
|
}
|