diff options
Diffstat (limited to 'security/nss/lib/softoken/legacydb/pk11db.c')
-rw-r--r-- | security/nss/lib/softoken/legacydb/pk11db.c | 731 |
1 files changed, 731 insertions, 0 deletions
diff --git a/security/nss/lib/softoken/legacydb/pk11db.c b/security/nss/lib/softoken/legacydb/pk11db.c new file mode 100644 index 0000000000..a7421c83d3 --- /dev/null +++ b/security/nss/lib/softoken/legacydb/pk11db.c @@ -0,0 +1,731 @@ +/* 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/. */ +/* + * 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 "lgdb.h" +#include "mcom_db.h" +#include "secerr.h" +#include "utilpars.h" + +#define FREE_CLEAR(p) \ + if (p) { \ + PORT_Free(p); \ + p = NULL; \ + } + +/* Construct a database key for a given module */ +static SECStatus +lgdb_MakeKey(DBT *key, char *module) +{ + int len = 0; + char *commonName; + + commonName = NSSUTIL_ArgGetParamValue("name", module); + if (commonName == NULL) { + commonName = NSSUTIL_ArgGetParamValue("library", module); + } + if (commonName == NULL) + return SECFailure; + len = PORT_Strlen(commonName); + key->data = commonName; + key->size = len; + return SECSuccess; +} + +/* free out constructed database key */ +static void +lgdb_FreeKey(DBT *key) +{ + if (key->data) { + PORT_Free(key->data); + } + key->data = NULL; + key->size = 0; +} + +typedef struct lgdbDataStr lgdbData; +typedef struct lgdbSlotDataStr lgdbSlotData; +struct lgdbDataStr { + 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 trustOrder[4]; + unsigned char cipherOrder[4]; + unsigned char reserved1; + unsigned char isModuleDB; + unsigned char isModuleDBOnly; + unsigned char isCritical; + unsigned char reserved[4]; + unsigned char names[6]; /* enough space for the length fields */ +}; + +struct lgdbSlotDataStr { + unsigned char slotID[4]; + unsigned char defaultFlags[4]; + unsigned char timeout[4]; + unsigned char askpw; + unsigned char hasRootCerts; + unsigned char reserved[18]; /* this makes it a round 32 bytes */ +}; + +#define LGDB_DB_VERSION_MAJOR 0 +#define LGDB_DB_VERSION_MINOR 6 +#define LGDB_DB_EXT1_VERSION_MAJOR 0 +#define LGDB_DB_EXT1_VERSION_MINOR 6 +#define LGDB_DB_NOUI_VERSION_MAJOR 0 +#define LGDB_DB_NOUI_VERSION_MINOR 4 + +#define LGDB_PUTSHORT(dest, src) \ + (dest)[1] = (unsigned char)((src)&0xff); \ + (dest)[0] = (unsigned char)(((src) >> 8) & 0xff); +#define LGDB_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 LGDB_GETSHORT(src) \ + ((unsigned short)(((src)[0] << 8) | (src)[1])) +#define LGDB_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 +lgdb_EncodeData(DBT *data, char *module) +{ + lgdbData *encoded = NULL; + lgdbSlotData *slot; + unsigned char *dataPtr, *offsetPtr; + unsigned short len, len2 = 0, len3 = 0; + int count = 0; + unsigned short offset; + int dataLen, i; + unsigned long order; + unsigned long ssl[2]; + char *commonName = NULL, *dllName = NULL, *param = NULL, *nss = NULL; + char *slotParams, *ciphers; + struct NSSUTILPreSlotInfoStr *slotInfo = NULL; + SECStatus rv = SECFailure; + + rv = NSSUTIL_ArgParseModuleSpec(module, &dllName, &commonName, ¶m, &nss); + if (rv != SECSuccess) + return rv; + rv = SECFailure; + + if (commonName == NULL) { + /* set error */ + goto loser; + } + + len = PORT_Strlen(commonName); + if (dllName) { + len2 = PORT_Strlen(dllName); + } + if (param) { + len3 = PORT_Strlen(param); + } + + slotParams = NSSUTIL_ArgGetParamValue("slotParams", nss); + slotInfo = NSSUTIL_ArgParseSlotInfo(NULL, slotParams, &count); + if (slotParams) + PORT_Free(slotParams); + + if (count && slotInfo == NULL) { + /* set error */ + goto loser; + } + + dataLen = sizeof(lgdbData) + len + len2 + len3 + sizeof(unsigned short) + + count * sizeof(lgdbSlotData); + + data->data = (unsigned char *)PORT_ZAlloc(dataLen); + encoded = (lgdbData *)data->data; + dataPtr = (unsigned char *)data->data; + data->size = dataLen; + + if (encoded == NULL) { + /* set error */ + goto loser; + } + + encoded->major = LGDB_DB_VERSION_MAJOR; + encoded->minor = LGDB_DB_VERSION_MINOR; + encoded->internal = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "internal", nss) ? 1 : 0); + encoded->fips = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "FIPS", nss) ? 1 : 0); + encoded->isModuleDB = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDB", nss) ? 1 : 0); + encoded->isModuleDBOnly = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "isModuleDBOnly", nss) ? 1 : 0); + encoded->isCritical = (unsigned char)(NSSUTIL_ArgHasFlag("flags", "critical", nss) ? 1 : 0); + + order = NSSUTIL_ArgReadLong("trustOrder", nss, + NSSUTIL_DEFAULT_TRUST_ORDER, NULL); + LGDB_PUTLONG(encoded->trustOrder, order); + order = NSSUTIL_ArgReadLong("cipherOrder", nss, + NSSUTIL_DEFAULT_CIPHER_ORDER, NULL); + LGDB_PUTLONG(encoded->cipherOrder, order); + + ciphers = NSSUTIL_ArgGetParamValue("ciphers", nss); + NSSUTIL_ArgParseCipherFlags(&ssl[0], ciphers); + LGDB_PUTLONG(encoded->ssl, ssl[0]); + LGDB_PUTLONG(&encoded->ssl[4], ssl[1]); + if (ciphers) + PORT_Free(ciphers); + + offset = (unsigned short)offsetof(lgdbData, names); + LGDB_PUTSHORT(encoded->nameStart, offset); + offset = offset + len + len2 + len3 + 3 * sizeof(unsigned short); + LGDB_PUTSHORT(encoded->slotOffset, offset); + + LGDB_PUTSHORT(&dataPtr[offset], ((unsigned short)count)); + slot = (lgdbSlotData *)(dataPtr + offset + sizeof(unsigned short)); + + offsetPtr = encoded->names; + LGDB_PUTSHORT(encoded->names, len); + offsetPtr += sizeof(unsigned short); + PORT_Memcpy(offsetPtr, commonName, len); + offsetPtr += len; + + LGDB_PUTSHORT(offsetPtr, len2); + offsetPtr += sizeof(unsigned short); + if (len2) { + PORT_Memcpy(offsetPtr, dllName, len2); + } + offsetPtr += len2; + + LGDB_PUTSHORT(offsetPtr, len3); + offsetPtr += sizeof(unsigned short); + if (len3) { + PORT_Memcpy(offsetPtr, param, len3); + } + offsetPtr += len3; + + if (count) { + for (i = 0; i < count; i++) { + LGDB_PUTLONG(slot[i].slotID, slotInfo[i].slotID); + LGDB_PUTLONG(slot[i].defaultFlags, + slotInfo[i].defaultFlags); + LGDB_PUTLONG(slot[i].timeout, slotInfo[i].timeout); + slot[i].askpw = slotInfo[i].askpw; + slot[i].hasRootCerts = slotInfo[i].hasRootCerts; + PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved)); + } + } + rv = SECSuccess; + +loser: + if (commonName) + PORT_Free(commonName); + if (dllName) + PORT_Free(dllName); + if (param) + PORT_Free(param); + if (slotInfo) + PORT_Free(slotInfo); + if (nss) + PORT_Free(nss); + return rv; +} + +static void +lgdb_FreeData(DBT *data) +{ + if (data->data) { + PORT_Free(data->data); + } +} + +static void +lgdb_FreeSlotStrings(char **slotStrings, int count) +{ + int i; + + for (i = 0; i < count; i++) { + if (slotStrings[i]) { + PR_smprintf_free(slotStrings[i]); + slotStrings[i] = NULL; + } + } +} + +/* + * build a module from the data base entry. + */ +static char * +lgdb_DecodeData(char *defParams, DBT *data, PRBool *retInternal) +{ + lgdbData *encoded; + lgdbSlotData *slots; + PLArenaPool *arena; + char *commonName = NULL; + char *dllName = NULL; + char *parameters = NULL; + char *nss; + char *moduleSpec; + char **slotStrings = NULL; + unsigned char *names; + unsigned long slotCount; + unsigned long ssl0 = 0; + unsigned long ssl1 = 0; + unsigned long slotID; + unsigned long defaultFlags; + unsigned long timeout; + unsigned long trustOrder = NSSUTIL_DEFAULT_TRUST_ORDER; + unsigned long cipherOrder = NSSUTIL_DEFAULT_CIPHER_ORDER; + unsigned short len; + unsigned short namesOffset = 0; /* start of the names block */ + unsigned long namesRunningOffset; /* offset to name we are + * currently processing */ + unsigned short slotOffset; + PRBool isOldVersion = PR_FALSE; + PRBool internal; + PRBool isFIPS; + PRBool isModuleDB = PR_FALSE; + PRBool isModuleDBOnly = PR_FALSE; + PRBool extended = PR_FALSE; + int i; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) + return NULL; + +#define CHECK_SIZE(x) \ + if ((unsigned int)data->size < (unsigned int)(x)) \ + goto db_loser + + /* ------------------------------------------------------------- + ** Process the buffer header, which is the lgdbData struct. + ** It may be an old or new version. Check the length for each. + */ + + CHECK_SIZE(offsetof(lgdbData, trustOrder[0])); + + encoded = (lgdbData *)data->data; + + internal = (encoded->internal != 0) ? PR_TRUE : PR_FALSE; + isFIPS = (encoded->fips != 0) ? PR_TRUE : PR_FALSE; + + if (retInternal) + *retInternal = internal; + if (internal) { + parameters = PORT_ArenaStrdup(arena, defParams); + if (parameters == NULL) + goto loser; + } + if (internal && (encoded->major == LGDB_DB_NOUI_VERSION_MAJOR) && + (encoded->minor <= LGDB_DB_NOUI_VERSION_MINOR)) { + isOldVersion = PR_TRUE; + } + if ((encoded->major == LGDB_DB_EXT1_VERSION_MAJOR) && + (encoded->minor >= LGDB_DB_EXT1_VERSION_MINOR)) { + CHECK_SIZE(sizeof(lgdbData)); + trustOrder = LGDB_GETLONG(encoded->trustOrder); + cipherOrder = LGDB_GETLONG(encoded->cipherOrder); + isModuleDB = (encoded->isModuleDB != 0) ? PR_TRUE : PR_FALSE; + isModuleDBOnly = (encoded->isModuleDBOnly != 0) ? PR_TRUE : PR_FALSE; + extended = PR_TRUE; + } + if (internal && !extended) { + trustOrder = 0; + cipherOrder = 100; + } + /* decode SSL cipher enable flags */ + ssl0 = LGDB_GETLONG(encoded->ssl); + ssl1 = LGDB_GETLONG(encoded->ssl + 4); + + slotOffset = LGDB_GETSHORT(encoded->slotOffset); + namesOffset = LGDB_GETSHORT(encoded->nameStart); + + /*-------------------------------------------------------------- + ** Now process the variable length set of names. + ** The names have this structure: + ** struct { + ** BYTE commonNameLen[ 2 ]; + ** BYTE commonName [ commonNameLen ]; + ** BTTE libNameLen [ 2 ]; + ** BYTE libName [ libNameLen ]; + ** If it is "extended" it also has these members: + ** BYTE initStringLen[ 2 ]; + ** BYTE initString [ initStringLen ]; + ** } + */ + + namesRunningOffset = namesOffset; + /* copy the module's common name */ + CHECK_SIZE(namesRunningOffset + 2); + names = (unsigned char *)data->data; + len = LGDB_GETSHORT(names + namesRunningOffset); + + CHECK_SIZE(namesRunningOffset + 2 + len); + commonName = (char *)PORT_ArenaAlloc(arena, len + 1); + if (commonName == NULL) + goto loser; + PORT_Memcpy(commonName, names + namesRunningOffset + 2, len); + commonName[len] = 0; + namesRunningOffset += len + 2; + + /* copy the module's shared library file name. */ + CHECK_SIZE(namesRunningOffset + 2); + len = LGDB_GETSHORT(names + namesRunningOffset); + if (len) { + CHECK_SIZE(namesRunningOffset + 2 + len); + dllName = (char *)PORT_ArenaAlloc(arena, len + 1); + if (dllName == NULL) + goto loser; + PORT_Memcpy(dllName, names + namesRunningOffset + 2, len); + dllName[len] = 0; + } + namesRunningOffset += len + 2; + + /* copy the module's initialization string, if present. */ + if (!internal && extended) { + CHECK_SIZE(namesRunningOffset + 2); + len = LGDB_GETSHORT(names + namesRunningOffset); + if (len) { + CHECK_SIZE(namesRunningOffset + 2 + len); + parameters = (char *)PORT_ArenaAlloc(arena, len + 1); + if (parameters == NULL) + goto loser; + PORT_Memcpy(parameters, names + namesRunningOffset + 2, len); + parameters[len] = 0; + } + namesRunningOffset += len + 2; + } + + /* + * Consistency check: Make sure the slot and names blocks don't + * overlap. These blocks can occur in any order, so this check is made + * in 2 parts. First we check the case where the slot block starts + * after the name block. Later, when we have the slot block length, + * we check the case where slot block starts before the name block. + * NOTE: in most cases any overlap will likely be detected by invalid + * data read from the blocks, but it's better to find out sooner + * than later. + */ + if (slotOffset >= namesOffset) { /* slot block starts after name block */ + if (slotOffset < namesRunningOffset) { + goto db_loser; + } + } + + /* ------------------------------------------------------------------ + ** Part 3, process the slot table. + ** This part has this structure: + ** struct { + ** BYTE slotCount [ 2 ]; + ** lgdbSlotData [ slotCount ]; + ** { + */ + + CHECK_SIZE(slotOffset + 2); + slotCount = LGDB_GETSHORT((unsigned char *)data->data + slotOffset); + + /* + * Consistency check: Part 2. We now have the slot block length, we can + * check the case where the slotblock procedes the name block. + */ + if (slotOffset < namesOffset) { /* slot block starts before name block */ + if (namesOffset < slotOffset + 2 + slotCount * sizeof(lgdbSlotData)) { + goto db_loser; + } + } + + CHECK_SIZE((slotOffset + 2 + slotCount * sizeof(lgdbSlotData))); + slots = (lgdbSlotData *)((unsigned char *)data->data + slotOffset + 2); + + /* slotCount; */ + slotStrings = (char **)PORT_ArenaZAlloc(arena, slotCount * sizeof(char *)); + if (slotStrings == NULL) + goto loser; + for (i = 0; i < (int)slotCount; i++, slots++) { + PRBool hasRootCerts = PR_FALSE; + PRBool hasRootTrust = PR_FALSE; + slotID = LGDB_GETLONG(slots->slotID); + defaultFlags = LGDB_GETLONG(slots->defaultFlags); + timeout = LGDB_GETLONG(slots->timeout); + hasRootCerts = slots->hasRootCerts; + if (isOldVersion && internal && (slotID != 2)) { + unsigned long internalFlags = + NSSUTIL_ArgParseSlotFlags("slotFlags", + NSSUTIL_DEFAULT_SFTKN_FLAGS); + defaultFlags |= internalFlags; + } + if (hasRootCerts && !extended) { + trustOrder = 100; + } + + slotStrings[i] = NSSUTIL_MkSlotString(slotID, defaultFlags, timeout, + (unsigned char)slots->askpw, + hasRootCerts, hasRootTrust); + if (slotStrings[i] == NULL) { + lgdb_FreeSlotStrings(slotStrings, i); + goto loser; + } + } + + nss = NSSUTIL_MkNSSString(slotStrings, slotCount, internal, isFIPS, + isModuleDB, isModuleDBOnly, internal, trustOrder, + cipherOrder, ssl0, ssl1); + lgdb_FreeSlotStrings(slotStrings, slotCount); + /* it's permissible (and normal) for nss to be NULL. it simply means + * there are no NSS specific parameters in the database */ + moduleSpec = NSSUTIL_MkModuleSpec(dllName, commonName, parameters, nss); + PR_smprintf_free(nss); + PORT_FreeArena(arena, PR_TRUE); + return moduleSpec; + +db_loser: + PORT_SetError(SEC_ERROR_BAD_DATABASE); +loser: + PORT_FreeArena(arena, PR_TRUE); + return NULL; +} + +static DB * +lgdb_OpenDB(const char *appName, const char *filename, const char *dbName, + PRBool readOnly, PRBool update) +{ + DB *pkcs11db = NULL; + + if (appName) { + char *secname = PORT_Strdup(filename); + int len = strlen(secname); + int status = RDB_FAIL; + + if (len >= 3 && PORT_Strcmp(&secname[len - 3], ".db") == 0) { + secname[len - 3] = 0; + } + pkcs11db = + rdbopen(appName, "", secname, readOnly ? NO_RDONLY : NO_RDWR, NULL); + if (update && !pkcs11db) { + DB *updatedb; + + pkcs11db = rdbopen(appName, "", secname, NO_CREATE, &status); + if (!pkcs11db) { + if (status == RDB_RETRY) { + pkcs11db = rdbopen(appName, "", secname, + readOnly ? NO_RDONLY : NO_RDWR, NULL); + } + PORT_Free(secname); + return pkcs11db; + } + updatedb = dbopen(dbName, NO_RDONLY, 0600, DB_HASH, 0); + if (updatedb) { + db_Copy(pkcs11db, updatedb); + (*updatedb->close)(updatedb); + } else { + (*pkcs11db->close)(pkcs11db); + PORT_Free(secname); + return NULL; + } + } + PORT_Free(secname); + return pkcs11db; + } + + /* I'm sure we should do more checks here sometime... */ + pkcs11db = dbopen(dbName, readOnly ? NO_RDONLY : NO_RDWR, 0600, DB_HASH, 0); + + /* didn't exist? create it */ + if (pkcs11db == NULL) { + if (readOnly) + return NULL; + + pkcs11db = dbopen(dbName, NO_CREATE, 0600, DB_HASH, 0); + if (pkcs11db) + (*pkcs11db->sync)(pkcs11db, 0); + } + return pkcs11db; +} + +static void +lgdb_CloseDB(DB *pkcs11db) +{ + (*pkcs11db->close)(pkcs11db); +} + +SECStatus legacy_AddSecmodDB(const char *appName, const char *filename, + const char *dbname, char *module, PRBool rw); + +#define LGDB_STEP 10 +/* + * Read all the existing modules in + */ +char ** +legacy_ReadSecmodDB(const char *appName, const char *filename, + const char *dbname, char *params, PRBool rw) +{ + DBT key, data; + int ret; + DB *pkcs11db = NULL; + char **moduleList = NULL, **newModuleList = NULL; + int moduleCount = 1; + int useCount = LGDB_STEP; + + moduleList = (char **)PORT_ZAlloc(useCount * sizeof(char **)); + if (moduleList == NULL) + return NULL; + + pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_TRUE, rw); + if (pkcs11db == NULL) + goto done; + + /* read and parse the file or data base */ + ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST); + if (ret) + goto done; + + do { + char *moduleString; + PRBool internal = PR_FALSE; + if ((moduleCount + 1) >= useCount) { + useCount += LGDB_STEP; + newModuleList = + (char **)PORT_Realloc(moduleList, useCount * sizeof(char *)); + if (newModuleList == NULL) + goto done; + moduleList = newModuleList; + PORT_Memset(&moduleList[moduleCount + 1], 0, + sizeof(char *) * LGDB_STEP); + } + moduleString = lgdb_DecodeData(params, &data, &internal); + if (internal) { + moduleList[0] = moduleString; + } else { + moduleList[moduleCount] = moduleString; + moduleCount++; + } + } while ((*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0); + +done: + if (!moduleList[0]) { + char *newparams = NSSUTIL_Quote(params, '"'); + if (newparams) { + moduleList[0] = PR_smprintf( + NSSUTIL_DEFAULT_INTERNAL_INIT1 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT2 "%s" NSSUTIL_DEFAULT_INTERNAL_INIT3, + newparams, NSSUTIL_DEFAULT_SFTKN_FLAGS); + PORT_Free(newparams); + } + } + /* deal with trust cert db here */ + + if (pkcs11db) { + lgdb_CloseDB(pkcs11db); + } else if (moduleList[0] && rw) { + legacy_AddSecmodDB(appName, filename, dbname, moduleList[0], rw); + } + if (!moduleList[0]) { + PORT_Free(moduleList); + moduleList = NULL; + } + return moduleList; +} + +SECStatus +legacy_ReleaseSecmodDBData(const char *appName, const char *filename, + const char *dbname, char **moduleSpecList, PRBool rw) +{ + if (moduleSpecList) { + char **index; + for (index = moduleSpecList; *index; index++) { + PR_smprintf_free(*index); + } + PORT_Free(moduleSpecList); + } + return SECSuccess; +} + +/* + * Delete a module from the Data Base + */ +SECStatus +legacy_DeleteSecmodDB(const char *appName, const char *filename, + const char *dbname, char *args, PRBool rw) +{ + DBT key; + SECStatus rv = SECFailure; + DB *pkcs11db = NULL; + int ret; + + if (!rw) + return SECFailure; + + /* make sure we have a db handle */ + pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE); + if (pkcs11db == NULL) { + return SECFailure; + } + + rv = lgdb_MakeKey(&key, args); + if (rv != SECSuccess) + goto done; + rv = SECFailure; + ret = (*pkcs11db->del)(pkcs11db, &key, 0); + lgdb_FreeKey(&key); + if (ret != 0) + goto done; + + ret = (*pkcs11db->sync)(pkcs11db, 0); + if (ret == 0) + rv = SECSuccess; + +done: + lgdb_CloseDB(pkcs11db); + return rv; +} + +/* + * Add a module to the Data base + */ +SECStatus +legacy_AddSecmodDB(const char *appName, const char *filename, + const char *dbname, char *module, PRBool rw) +{ + DBT key, data; + SECStatus rv = SECFailure; + DB *pkcs11db = NULL; + int ret; + + if (!rw) + return SECFailure; + + /* make sure we have a db handle */ + pkcs11db = lgdb_OpenDB(appName, filename, dbname, PR_FALSE, PR_FALSE); + if (pkcs11db == NULL) { + return SECFailure; + } + + rv = lgdb_MakeKey(&key, module); + if (rv != SECSuccess) + goto done; + rv = lgdb_EncodeData(&data, module); + if (rv != SECSuccess) { + lgdb_FreeKey(&key); + goto done; + } + rv = SECFailure; + ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0); + lgdb_FreeKey(&key); + lgdb_FreeData(&data); + if (ret != 0) + goto done; + + ret = (*pkcs11db->sync)(pkcs11db, 0); + if (ret == 0) + rv = SECSuccess; + +done: + lgdb_CloseDB(pkcs11db); + return rv; +} |