pk11db.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:18k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /* 
  34.  *  The following code handles the storage of PKCS 11 modules used by the
  35.  * NSS. This file is written to abstract away how the modules are
  36.  * stored so we can deside that later.
  37.  */
  38. #include "seccomon.h"
  39. #include "secmod.h"
  40. #include "prlock.h"
  41. #include "pkcs11.h"
  42. #include "secmodi.h"
  43. #include "pk11func.h"
  44. #include "mcom_db.h"
  45. /* create a new module */
  46. SECMODModule *SECMOD_NewModule(void) {
  47.     SECMODModule *newMod;
  48.     PRArenaPool *arena;
  49.     /* create an arena in which dllName and commonName can be
  50.      * allocated.
  51.      */
  52.     arena = PORT_NewArena(512);
  53.     if (arena == NULL) {
  54. return NULL;
  55.     }
  56.     newMod = (SECMODModule *)PORT_ArenaAlloc(arena,sizeof (SECMODModule));
  57.     if (newMod == NULL) {
  58. PORT_FreeArena(arena,PR_FALSE);
  59. return NULL;
  60.     }
  61.     /*
  62.      * initialize of the fields of the module
  63.      */
  64.     newMod->arena = arena;
  65.     newMod->internal = PR_FALSE;
  66.     newMod->loaded = PR_FALSE;
  67.     newMod->isFIPS = PR_FALSE;
  68.     newMod->dllName = NULL;
  69.     newMod->commonName = NULL;
  70.     newMod->library = NULL;
  71.     newMod->functionList = NULL;
  72.     newMod->slotCount = 0;
  73.     newMod->slots = NULL;
  74.     newMod->slotInfo = NULL;
  75.     newMod->slotInfoCount = 0;
  76.     newMod->refCount = 1;
  77.     newMod->ssl[0] = 0;
  78.     newMod->ssl[1] = 0;
  79. #ifdef PKCS11_USE_THREADS
  80.     newMod->refLock = (void *)PR_NewLock();
  81.     if (newMod->refLock == NULL) {
  82. PORT_FreeArena(arena,PR_FALSE);
  83. return NULL;
  84.     }
  85. #else
  86.     newMod->refLock = NULL;
  87. #endif
  88.     return newMod;
  89.     
  90. }
  91. /* create a new ModuleListElement */
  92. SECMODModuleList *SECMOD_NewModuleListElement(void) {
  93.     SECMODModuleList *newModList;
  94.     newModList= (SECMODModuleList *) PORT_Alloc(sizeof(SECMODModuleList));
  95.     if (newModList) {
  96. newModList->next = NULL;
  97. newModList->module = NULL;
  98.     }
  99.     return newModList;
  100. }
  101. static unsigned long internalFlags = SECMOD_RSA_FLAG|SECMOD_DSA_FLAG|
  102. SECMOD_RC2_FLAG| SECMOD_RC4_FLAG|SECMOD_DES_FLAG|SECMOD_RANDOM_FLAG|
  103. SECMOD_SHA1_FLAG|SECMOD_MD5_FLAG|SECMOD_MD2_FLAG|SECMOD_SSL_FLAG|
  104. SECMOD_TLS_FLAG;
  105. /* create a Internal  module */
  106. SECMODModule *SECMOD_NewInternal(void) {
  107.     SECMODModule *intern;
  108.     static PK11PreSlotInfo internSlotInfo =
  109. { 1, SECMOD_RSA_FLAG|SECMOD_DSA_FLAG|SECMOD_RC2_FLAG|
  110. SECMOD_RC4_FLAG|SECMOD_DES_FLAG|SECMOD_RANDOM_FLAG|
  111. SECMOD_SHA1_FLAG|SECMOD_MD5_FLAG|SECMOD_MD2_FLAG|
  112. SECMOD_SSL_FLAG|SECMOD_TLS_FLAG, -1, 30, 0 };
  113.     intern = SECMOD_NewModule();
  114.     if (intern == NULL) {
  115. return NULL;
  116.     }
  117.     /*
  118.      * make this module an internal module
  119.      */
  120.     intern->commonName = "Netscape Internal PKCS #11 Module";
  121.     intern->internal = PR_TRUE;
  122.     intern->slotInfoCount = 1;
  123.     intern->slotInfo = &internSlotInfo;
  124.     return (intern);
  125. }
  126. /* create a FIPS Internal  module */
  127. SECMODModule *SECMOD_GetFIPSInternal(void) {
  128.     SECMODModule *intern;
  129.     intern = SECMOD_NewInternal();
  130.     if (intern == NULL) {
  131. return NULL;
  132.     }
  133.     /*
  134.      * make this module a FIPS internal module
  135.      */
  136.     intern->slotInfo[0].slotID = 3; /* FIPS slot */
  137.     intern->commonName = "Netscape Internal FIPS PKCS #11 Module";
  138.     intern->isFIPS = PR_TRUE;
  139.     return (intern);
  140. }
  141. SECMODModule *SECMOD_DupModule(SECMODModule *old) {
  142.     SECMODModule *newMod;
  143.     newMod = SECMOD_NewModule();
  144.     if (newMod == NULL) {
  145. return NULL;
  146.     }
  147.     /*
  148.      * initialize of the fields of the module
  149.      */
  150.     newMod->dllName = PORT_ArenaStrdup(newMod->arena,old->dllName);
  151.     newMod->commonName = PORT_ArenaStrdup(newMod->arena,old->commonName);;
  152.     return newMod;
  153.     
  154. }
  155. /*
  156.  * make a new reference to a module so It doesn't go away on us
  157.  */
  158. SECMODModule *
  159. SECMOD_ReferenceModule(SECMODModule *module) {
  160.     PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
  161.     PORT_Assert(module->refCount > 0);
  162.     module->refCount++;
  163.     PK11_USE_THREADS(PR_Unlock((PRLock*)module->refLock);)
  164.     return module;
  165. }
  166. /* destroy an existing module */
  167. void
  168. SECMOD_DestroyModule(SECMODModule *module) {
  169.     PRBool willfree = PR_FALSE;
  170.     int slotCount;
  171.     int i;
  172.     PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
  173.     if (module->refCount-- == 1) {
  174. willfree = PR_TRUE;
  175.     }
  176.     PORT_Assert(willfree || (module->refCount > 0));
  177.     PK11_USE_THREADS(PR_Unlock((PRLock *)module->refLock);)
  178.     if (!willfree) {
  179. return;
  180.     }
  181.     /* slots can't really disappear until our module starts freeing them,
  182.      * so this check is safe */
  183.     slotCount = module->slotCount;
  184.     if (slotCount == 0) {
  185. SECMOD_SlotDestroyModule(module,PR_FALSE);
  186. return;
  187.     }
  188.     /* now free all out slots, when they are done, they will cause the
  189.      * module to disappear altogether */
  190.     for (i=0 ; i < slotCount; i++) {
  191. if (!module->slots[i]->disabled) {
  192. PK11_ClearSlotList(module->slots[i]);
  193. }
  194. PK11_FreeSlot(module->slots[i]);
  195.     }
  196.     /* WARNING: once the last slot has been freed is it possible (even likely)
  197.      * that module is no more... touching it now is a good way to go south */
  198. }
  199. /* we can only get here if we've destroyed the module, or some one has
  200.  * erroneously freed a slot that wasn't referenced. */
  201. void
  202. SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot) {
  203.     PRBool willfree = PR_FALSE;
  204.     if (fromSlot) {
  205.         PORT_Assert(module->refCount == 0);
  206. PK11_USE_THREADS(PR_Lock((PRLock *)module->refLock);)
  207. if (module->slotCount-- == 1) {
  208.     willfree = PR_TRUE;
  209. }
  210. PORT_Assert(willfree || (module->slotCount > 0));
  211. PK11_USE_THREADS(PR_Unlock((PRLock *)module->refLock);)
  212.         if (!willfree) return;
  213.     }
  214.     if (module->loaded) {
  215. SECMOD_UnloadModule(module);
  216.     }
  217.     PK11_USE_THREADS(PR_DestroyLock((PRLock *)module->refLock);)
  218.     PORT_FreeArena(module->arena,PR_FALSE);
  219. }
  220. /* destroy a list element
  221.  * this destroys a single element, and returns the next element
  222.  * on the chain. It makes it easy to implement for loops to delete
  223.  * the chain. It also make deleting a single element easy */
  224. SECMODModuleList *
  225. SECMOD_DestroyModuleListElement(SECMODModuleList *element) {
  226.     SECMODModuleList *next = element->next;
  227.     if (element->module) {
  228. SECMOD_DestroyModule(element->module);
  229. element->module = NULL;
  230.     }
  231.     PORT_Free(element);
  232.     return next;
  233. }
  234. /*
  235.  * Destroy an entire module list
  236.  */
  237. void
  238. SECMOD_DestroyModuleList(SECMODModuleList *list) {
  239.     SECMODModuleList *lp;
  240.     for ( lp = list; lp != NULL; lp = SECMOD_DestroyModuleListElement(lp)) ;
  241. }
  242. /* Construct a database key for a given module */
  243. static SECStatus secmod_MakeKey(DBT *key, SECMODModule * module) {
  244.     int len = 0;
  245.     len = PORT_Strlen(module->commonName);
  246.     key->data = module->commonName;
  247.     key->size = len;
  248.     return SECSuccess;
  249. }
  250. /* free out constructed database key */
  251. static void secmod_FreeKey(DBT *key) {
  252.     key->data = NULL;
  253.     key->size = 0;
  254. }
  255. typedef struct secmodDataStr secmodData;
  256. typedef struct secmodSlotDataStr secmodSlotData;
  257. struct secmodDataStr {
  258.     unsigned char major;
  259.     unsigned char minor;
  260.     unsigned char nameStart[2];
  261.     unsigned char slotOffset[2];
  262.     unsigned char internal;
  263.     unsigned char fips;
  264.     unsigned char ssl[8];
  265.     unsigned char names[4]; /* enough space for the length fields */
  266. };
  267. struct secmodSlotDataStr {
  268.     unsigned char slotID[4];
  269.     unsigned char defaultFlags[4];
  270.     unsigned char timeout[4];
  271.     unsigned char askpw;
  272.     unsigned char hasRootCerts;
  273.     unsigned char reserved[18]; /* this makes it a round 32 bytes */
  274. };
  275. #define SECMOD_DB_VERSION_MAJOR 0
  276. #define SECMOD_DB_VERSION_MINOR 4
  277. #define SECMOD_DB_NOUI_VERSION_MAJOR 0
  278. #define SECMOD_DB_NOUI_VERSION_MINOR 3
  279. #define SECMOD_PUTSHORT(dest,src) 
  280. (dest)[1] = (unsigned char) ((src)&0xff); 
  281. (dest)[0] = (unsigned char) (((src) >> 8) & 0xff);
  282. #define SECMOD_PUTLONG(dest,src) 
  283. (dest)[3] = (unsigned char) ((src)&0xff); 
  284. (dest)[2] = (unsigned char) (((src) >> 8) & 0xff); 
  285. (dest)[1] = (unsigned char) (((src) >> 16) & 0xff); 
  286. (dest)[0] = (unsigned char) (((src) >> 24) & 0xff);
  287. #define SECMOD_GETSHORT(src) 
  288. ((unsigned short) (((src)[0] << 8) | (src)[1]))
  289. #define SECMOD_GETLONG(src) 
  290. ((unsigned long) (( (unsigned long) (src)[0] << 24) | 
  291. ( (unsigned long) (src)[1] << 16)  | 
  292. ( (unsigned long) (src)[2] << 8) | 
  293. (unsigned long) (src)[3]))
  294. /*
  295.  * build a data base entry from a module 
  296.  */
  297. static SECStatus secmod_EncodeData(DBT *data, SECMODModule * module) {
  298.     secmodData *encoded;
  299.     secmodSlotData *slot;
  300.     unsigned char *dataPtr;
  301.     unsigned short len, len2 = 0,count = 0;
  302.     unsigned short offset;
  303.     int dataLen, i, si;
  304.     len = PORT_Strlen(module->commonName);
  305.     if (module->dllName) {
  306.      len2 = PORT_Strlen(module->dllName);
  307.     }
  308.     if (module->slotCount != 0) {
  309. for (i=0; i < module->slotCount; i++) {
  310.     if (module->slots[i]->defaultFlags != 0) {
  311. count++;
  312.     }
  313. }
  314.     } else {
  315. count = module->slotInfoCount;
  316.     }
  317.     dataLen = sizeof(secmodData) + len + len2 + 2 +
  318.  count*sizeof(secmodSlotData);
  319.     data->data = (unsigned char *)
  320. PORT_Alloc(dataLen);
  321.     encoded = (secmodData *)data->data;
  322.     dataPtr = (unsigned char *) data->data;
  323.     data->size = dataLen;
  324.     if (encoded == NULL) return SECFailure;
  325.     encoded->major = SECMOD_DB_VERSION_MAJOR;
  326.     encoded->minor = SECMOD_DB_VERSION_MINOR;
  327.     encoded->internal = (unsigned char) (module->internal ? 1 : 0);
  328.     encoded->fips = (unsigned char) (module->isFIPS ? 1 : 0);
  329.     SECMOD_PUTLONG(encoded->ssl,module->ssl[0]);
  330.     SECMOD_PUTLONG(&encoded->ssl[4],module->ssl[1]);
  331.     offset = (unsigned long) &(((secmodData *)0)->names[0]);
  332.     SECMOD_PUTSHORT(encoded->nameStart,offset);
  333.     offset = offset +len + len2 + 4;
  334.     SECMOD_PUTSHORT(encoded->slotOffset,offset);
  335.     SECMOD_PUTSHORT(&dataPtr[offset],count);
  336.     slot = (secmodSlotData *)(dataPtr+offset+2);
  337.     SECMOD_PUTSHORT(encoded->names,len);
  338.     PORT_Memcpy(&encoded->names[2],module->commonName,len);
  339.     SECMOD_PUTSHORT(&encoded->names[len+2],len2);
  340.     if (len2) PORT_Memcpy(&encoded->names[len+4],module->dllName,len2);
  341.     if (module->slotCount) {
  342.       for (i=0,si=0; i < module->slotCount; i++) {
  343. if (module->slots[i]->defaultFlags) {
  344.     SECMOD_PUTLONG(slot[si].slotID, module->slots[i]->slotID);
  345.     SECMOD_PUTLONG(slot[si].defaultFlags,
  346.      module->slots[i]->defaultFlags);
  347.     SECMOD_PUTLONG(slot[si].timeout,module->slots[i]->timeout);
  348.     slot[si].askpw = module->slots[i]->askpw;
  349.     slot[si].hasRootCerts = module->slots[i]->hasRootCerts;
  350.     PORT_Memset(slot[si].reserved, 0, sizeof(slot[si].reserved));
  351.     si++;
  352. }
  353.       }
  354.     } else {
  355. for (i=0; i < module->slotInfoCount; i++) {
  356.     SECMOD_PUTLONG(slot[i].slotID, module->slotInfo[i].slotID);
  357.     SECMOD_PUTLONG(slot[i].defaultFlags,
  358. module->slotInfo[i].defaultFlags);
  359.     SECMOD_PUTLONG(slot[i].timeout,module->slotInfo[i].timeout);
  360.     slot[i].askpw = module->slotInfo[i].askpw;
  361.     slot[i].hasRootCerts = module->slotInfo[i].hasRootCerts;
  362.     PORT_Memset(slot[i].reserved, 0, sizeof(slot[i].reserved));
  363. }
  364.     }
  365.     return SECSuccess;
  366. }
  367. static void secmod_FreeData(DBT *data) {
  368.     if (data->data) {
  369. PORT_Free(data->data);
  370.     }
  371. }
  372. /*
  373.  * build a module from the data base entry.
  374.  */
  375. static SECMODModule *secmod_DecodeData(DBT *data) {
  376.     SECMODModule * module;
  377.     secmodData *encoded;
  378.     secmodSlotData *slots;
  379.     unsigned char *names;
  380.     unsigned short len,len1;
  381.     unsigned long slotCount;
  382.     unsigned short offset;
  383.     PRBool isOldVersion  = PR_FALSE;
  384.     int i;
  385.     encoded = (secmodData *)data->data;
  386.     names = (unsigned char *)data->data;
  387.     offset = SECMOD_GETSHORT(encoded->slotOffset);
  388.     slots = (secmodSlotData *) (names + offset + 2);
  389.     slotCount = SECMOD_GETSHORT(names + offset);
  390.     names += SECMOD_GETSHORT(encoded->nameStart);
  391.     module = SECMOD_NewModule();
  392.     if (module == NULL) return NULL;
  393.     module->internal = (encoded->internal != 0) ? PR_TRUE: PR_FALSE;
  394.     module->isFIPS = (encoded->fips != 0) ? PR_TRUE: PR_FALSE;
  395.     len = SECMOD_GETSHORT(names);
  396.     if (module->internal && (encoded->major == SECMOD_DB_NOUI_VERSION_MAJOR) &&
  397.   (encoded->minor <= SECMOD_DB_NOUI_VERSION_MINOR)) {
  398. isOldVersion = PR_TRUE;
  399.     }
  400.     /* decode the common name */
  401.     module->commonName = (char*)PORT_ArenaAlloc(module->arena,len+1);
  402.     if (module->commonName == NULL) {
  403. SECMOD_DestroyModule(module);
  404. return NULL;
  405.     }
  406.     PORT_Memcpy(module->commonName,&names[2],len);
  407.     module->commonName[len] = 0;
  408.     /* decode the DLL name */
  409.     len1 = (names[len+2] << 8) | names[len+3];
  410.     if (len1) {
  411. module->dllName = (char*)PORT_ArenaAlloc(module->arena,len1 + 1);
  412. if (module->dllName == NULL) {
  413.     SECMOD_DestroyModule(module);
  414.     return NULL;
  415. }
  416. PORT_Memcpy(module->dllName,&names[len+4],len1);
  417. module->dllName[len1] = 0;
  418.     }
  419.     module->slotInfoCount = slotCount;
  420.     module->slotInfo = (PK11PreSlotInfo *) PORT_ArenaAlloc(module->arena,
  421. slotCount * sizeof(PK11PreSlotInfo));
  422.     for (i=0; i < (int) slotCount; i++) {
  423. module->slotInfo[i].slotID = SECMOD_GETLONG(slots[i].slotID);
  424. module->slotInfo[i].defaultFlags = 
  425. SECMOD_GETLONG(slots[i].defaultFlags);
  426. if (isOldVersion && module->internal && 
  427. (module->slotInfo[i].slotID != 2)) {
  428. module->slotInfo[i].defaultFlags |= internalFlags;
  429. }
  430. module->slotInfo[i].timeout = SECMOD_GETLONG(slots[i].timeout);
  431. module->slotInfo[i].askpw = slots[i].askpw;
  432. module->slotInfo[i].hasRootCerts = slots[i].hasRootCerts;
  433. if (module->slotInfo[i].askpw == 0xff) {
  434.    module->slotInfo[i].askpw = -1;
  435. }
  436.     }
  437.     /* decode SSL cipher enable flags */
  438.     module->ssl[0] = SECMOD_GETLONG(encoded->ssl);
  439.     module->ssl[1] = SECMOD_GETLONG(&encoded->ssl[4]);
  440.     return (module);
  441. }
  442. /*
  443.  * open the PKCS #11 data base.
  444.  */
  445. static char *pkcs11dbName = NULL;
  446. void SECMOD_InitDB(char *dbname) {
  447.     pkcs11dbName = PORT_Strdup(dbname);
  448. }
  449. static DB *secmod_OpenDB(PRBool readOnly) {
  450.     DB *pkcs11db = NULL;
  451.     char *dbname;
  452.     if (pkcs11dbName == NULL) return NULL;
  453.     dbname = pkcs11dbName;
  454.    
  455.     /* I'm sure we should do more checks here sometime... */
  456.     pkcs11db = dbopen(dbname, readOnly ? O_RDONLY : O_RDWR, 0600, DB_HASH, 0);
  457.     /* didn't exist? create it */
  458.     if (pkcs11db == NULL) {
  459.  if (readOnly) return NULL;
  460.  pkcs11db = dbopen( dbname,
  461.                              O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 );
  462.  if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0);
  463.     }
  464.     return pkcs11db;
  465. }
  466. static void secmod_CloseDB(DB *pkcs11db) {
  467.      (*pkcs11db->close)(pkcs11db);
  468. }
  469. /*
  470.  * Read all the existing modules in
  471.  */
  472. SECMODModuleList *
  473. SECMOD_ReadPermDB(void) {
  474.     DBT key,data;
  475.     int ret;
  476.     DB *pkcs11db = NULL;
  477.     SECMODModuleList *newmod = NULL,*mod = NULL;
  478.     pkcs11db = secmod_OpenDB(PR_TRUE);
  479.     if (pkcs11db == NULL) {
  480. return NULL;
  481.     }
  482.     /* read and parse the file or data base */
  483.     ret = (*pkcs11db->seq)(pkcs11db, &key, &data, R_FIRST);
  484.     if (ret)  goto done;
  485.     do {
  486.         /* allocate space for modules */
  487. newmod = SECMOD_NewModuleListElement();
  488. if (newmod == NULL) break;
  489. newmod->module = secmod_DecodeData(&data);
  490. if (newmod->module == NULL) {
  491.     SECMOD_DestroyModuleListElement(newmod);
  492.     break;
  493. }
  494. newmod->next = mod;
  495. mod = newmod;
  496.     } while ( (*pkcs11db->seq)(pkcs11db, &key, &data, R_NEXT) == 0);
  497. done:
  498.     secmod_CloseDB(pkcs11db);
  499.     return mod;
  500. }
  501. /*
  502.  * Delete a module from the Data Base
  503.  */
  504. SECStatus
  505. SECMOD_DeletePermDB(SECMODModule * module) {
  506.     DBT key;
  507.     SECStatus rv = SECFailure;
  508.     DB *pkcs11db = NULL;
  509.     int ret;
  510.     /* make sure we have a db handle */
  511.     pkcs11db = secmod_OpenDB(PR_FALSE);
  512.     if (pkcs11db == NULL) {
  513. return SECFailure;
  514.     }
  515.     rv = secmod_MakeKey(&key,module);
  516.     if (rv != SECSuccess) goto done;
  517.     rv = SECFailure;
  518.     ret = (*pkcs11db->del)(pkcs11db, &key, 0);
  519.     secmod_FreeKey(&key);
  520.     if (ret != 0) goto done;
  521.     ret = (*pkcs11db->sync)(pkcs11db, 0);
  522.     if (ret == 0) rv = SECSuccess;
  523. done:
  524.     secmod_CloseDB(pkcs11db);
  525.     return rv;
  526. }
  527. /*
  528.  * Add a module to the Data base 
  529.  */
  530. SECStatus
  531. SECMOD_AddPermDB(SECMODModule *module) {
  532.     DBT key,data;
  533.     SECStatus rv = SECFailure;
  534.     DB *pkcs11db = NULL;
  535.     int ret;
  536.     /* make sure we have a db handle */
  537.     pkcs11db = secmod_OpenDB(PR_FALSE);
  538.     if (pkcs11db == NULL) {
  539. return SECFailure;
  540.     }
  541.     rv = secmod_MakeKey(&key,module);
  542.     if (rv != SECSuccess) goto done;
  543.     rv = secmod_EncodeData(&data,module);
  544.     if (rv != SECSuccess) {
  545. secmod_FreeKey(&key);
  546. goto done;
  547.     }
  548.     rv = SECFailure;
  549.     ret = (*pkcs11db->put)(pkcs11db, &key, &data, 0);
  550.     secmod_FreeKey(&key);
  551.     secmod_FreeData(&data);
  552.     if (ret != 0) goto done;
  553.     ret = (*pkcs11db->sync)(pkcs11db, 0);
  554.     if (ret == 0) rv = SECSuccess;
  555. done:
  556.     secmod_CloseDB(pkcs11db);
  557.     return rv;
  558. }