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

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.  * Initialize the PCKS 11 subsystem
  35.  */
  36. #include "seccomon.h"
  37. #include "secmod.h"
  38. #include "prlock.h"
  39. #include "secmodi.h"
  40. #include "pk11func.h"
  41. /* these are for displaying error messages */
  42. static  SECMODModuleList *modules = NULL;
  43. static  SECMODModule *internalModule = NULL;
  44. static SECMODListLock *moduleLock = NULL;
  45. extern SECStatus
  46. PK11_UpdateSlotAttribute(PK11SlotInfo *slot, PK11DefaultArrayEntry *entry,
  47.                         PRBool add);
  48.                         
  49. extern int XP_SEC_MODULE_NO_LIB;
  50. extern PK11DefaultArrayEntry PK11_DefaultArray[];
  51. extern int num_pk11_default_mechanisms;
  52. static PRBool secmod_ModuleHasRoots(SECMODModule *module)
  53. {
  54.     int i;
  55.     for (i=0; i < module->slotInfoCount; i++) {
  56. if (module->slotInfo[i].hasRootCerts) {
  57.     return PR_TRUE;
  58. }
  59.     }
  60.     return PR_FALSE;
  61. }
  62. /*
  63.  * The following code is an attempt to automagically find the external root
  64.  * module. NOTE: This code should be checked out on the MAC! There must be
  65.  * some cross platform support out there to help out with this?
  66.  */
  67. static char *dllnames[]= {
  68. "roots.dll", "libroots.so","libroots.sl","Root Certs",
  69. "roots.dll", "libroots.so","libroots.sl","Root Certs",
  70. "nssckbi.dll","libnssckbi.so","libnssckbi.sl","NSS Builtin Root Certs",
  71. "mozckbi.dll","libmozckbi.so","libmozckbi.sl","Mozilla Builtin Root Certs",
  72. "netckbi.dll","libnetckbi.so","libnetckbi.sl","Netscape Builtin Root Certs",
  73. 0 };
  74. #define MAXDLLNAME 40
  75. /* Should we have platform ifdefs here??? */
  76. #define FILE_SEP '/'
  77. static void
  78. secmod_FindExternalRoot(char *dbname)
  79. {
  80. char *path, *cp, **cur_name;
  81. int len = PORT_Strlen(dbname);
  82. int path_len;
  83. path = PORT_Alloc(len+MAXDLLNAME);
  84. if (path == NULL) return;
  85. /* back up to the top of the directory */
  86. for (cp = &dbname[len]; cp != dbname && (*cp != FILE_SEP); cp--) ;
  87. path_len = cp-dbname;
  88. PORT_Memcpy(path,dbname,path_len);
  89. path[path_len++] = FILE_SEP;
  90. /* now walk our tree of dll names looking for the file of interest. */
  91. for (cur_name= dllnames; *cur_name != 0; cur_name++) {
  92.     PORT_Memcpy(&path[path_len],*cur_name,PORT_Strlen(*cur_name)+1);
  93.     if (SECMOD_AddNewModule("Root Certs",path, 0, 0) == SECSuccess) {
  94. break;
  95.     }
  96. }
  97. PORT_Free(path);
  98. return;
  99. }
  100. void SECMOD_init(char *dbname) {
  101.     SECMODModuleList *thisModule;
  102.     int found=0;
  103.     int rootFound=0;
  104.     SECStatus rv = SECFailure;
  105.     /* don't initialize twice */
  106.     if (modules) return;
  107.     PK11_InitSlotLists();
  108.     SECMOD_InitDB(dbname);
  109.     /*
  110.      * read in the current modules from the database
  111.      */
  112.     modules = SECMOD_ReadPermDB();
  113.     /* make sure that the internal module is loaded */
  114.     for (thisModule = modules; thisModule ; thisModule = thisModule->next) {
  115. if (thisModule->module->internal) {
  116.     found++;
  117.     internalModule = SECMOD_ReferenceModule(thisModule->module);
  118. }
  119. if (secmod_ModuleHasRoots(thisModule->module)) {
  120.     rootFound++;
  121. }
  122.     }
  123.     if (!found) {
  124. thisModule = modules;
  125. modules = SECMOD_NewModuleListElement();
  126. modules->module = SECMOD_NewInternal();
  127. PORT_Assert(modules->module != NULL);
  128. modules->next = thisModule;
  129. SECMOD_AddPermDB(modules->module);
  130. internalModule = SECMOD_ReferenceModule(modules->module);
  131.     }
  132.     /* load it first... we need it to verify the external modules
  133.      * which we are loading.... */
  134.     rv = SECMOD_LoadModule(internalModule);
  135.     if( rv != SECSuccess )
  136.         internalModule = NULL;
  137.     if (! rootFound ) {
  138. secmod_FindExternalRoot(dbname);
  139.     }
  140.     /* Load each new module */
  141.     for (thisModule = modules; thisModule ; thisModule = thisModule->next) {
  142.         if( !( thisModule->module->internal ) )
  143.     SECMOD_LoadModule(thisModule->module);
  144.     }
  145.     moduleLock = SECMOD_NewListLock();
  146. }
  147. /*
  148.  * retrieve the internal module
  149.  */
  150. SECMODModule *
  151. SECMOD_GetInternalModule(void) {
  152.    return internalModule;
  153. }
  154. /* called from  security/cmd/swfort/instinit, which doesn't need a full 
  155.  * security LIBRARY (it used the swfortezza code, but it does have to verify
  156.  * cert chains against it's own list of certs. We need to initialize the 
  157.  * security code without any database.
  158.  */
  159. void
  160. SECMOD_SetInternalModule( SECMODModule *mod) {
  161.    internalModule = SECMOD_ReferenceModule(mod);
  162. }
  163. /*
  164.  * get the list of PKCS11 modules that are available.
  165.  */
  166. SECMODModuleList *SECMOD_GetDefaultModuleList() { return modules; }
  167. SECMODListLock *SECMOD_GetDefaultModuleListLock() { return moduleLock; }
  168. /*
  169.  * find a module by name, and add a reference to it.
  170.  * return that module.
  171.  */
  172. SECMODModule *SECMOD_FindModule(char *name) {
  173.     SECMODModuleList *mlp;
  174.     SECMODModule *module = NULL;
  175.     SECMOD_GetReadLock(moduleLock);
  176.     for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  177. if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
  178.     module = mlp->module;
  179.     SECMOD_ReferenceModule(module);
  180.     break;
  181. }
  182.     }
  183.     SECMOD_ReleaseReadLock(moduleLock);
  184.     return module;
  185. }
  186. /*
  187.  * find a module by ID, and add a reference to it.
  188.  * return that module.
  189.  */
  190. SECMODModule *SECMOD_FindModuleByID(SECMODModuleID id) {
  191.     SECMODModuleList *mlp;
  192.     SECMODModule *module = NULL;
  193.     SECMOD_GetReadLock(moduleLock);
  194.     for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  195. if (id == mlp->module->moduleID) {
  196.     module = mlp->module;
  197.     SECMOD_ReferenceModule(module);
  198.     break;
  199. }
  200.     }
  201.     SECMOD_ReleaseReadLock(moduleLock);
  202.     return module;
  203. }
  204. /*
  205.  * lookup the Slot module based on it's module ID and slot ID.
  206.  */
  207. PK11SlotInfo *SECMOD_LookupSlot(SECMODModuleID moduleID,CK_SLOT_ID slotID) {
  208.     int i;
  209.     SECMODModule *module;
  210.     module = SECMOD_FindModuleByID(moduleID);
  211.     if (module == NULL) return NULL;
  212.     for (i=0; i < module->slotCount; i++) {
  213. PK11SlotInfo *slot = module->slots[i];
  214. if (slot->slotID == slotID) {
  215.     SECMOD_DestroyModule(module);
  216.     return PK11_ReferenceSlot(slot);
  217. }
  218.     }
  219.     SECMOD_DestroyModule(module);
  220.     return NULL;
  221. }
  222. /*
  223.  * find a module by name and delete it of the module list
  224.  */
  225. SECStatus
  226. SECMOD_DeleteModule(char *name, int *type) {
  227.     SECMODModuleList *mlp;
  228.     SECMODModuleList **mlpp;
  229.     SECStatus rv = SECFailure;
  230.     *type = SECMOD_EXTERNAL;
  231.     SECMOD_GetWriteLock(moduleLock);
  232.     for(mlpp = &modules,mlp = modules; 
  233. mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
  234. if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
  235.     /* don't delete the internal module */
  236.     if (!mlp->module->internal) {
  237. SECMOD_RemoveList(mlpp,mlp);
  238. /* delete it after we release the lock */
  239. rv = SECSuccess;
  240.     } else if (mlp->module->isFIPS) {
  241. *type = SECMOD_FIPS;
  242.     } else {
  243. *type = SECMOD_INTERNAL;
  244.     }
  245.     break;
  246. }
  247.     }
  248.     SECMOD_ReleaseWriteLock(moduleLock);
  249.     if (rv == SECSuccess) {
  250.   SECMOD_DeletePermDB(mlp->module);
  251. SECMOD_DestroyModuleListElement(mlp);
  252.     }
  253.     return rv;
  254. }
  255. /*
  256.  * find a module by name and delete it of the module list
  257.  */
  258. SECStatus
  259. SECMOD_DeleteInternalModule(char *name) {
  260.     SECMODModuleList *mlp;
  261.     SECMODModuleList **mlpp;
  262.     SECStatus rv = SECFailure;
  263.     SECMOD_GetWriteLock(moduleLock);
  264.     for(mlpp = &modules,mlp = modules; 
  265. mlp != NULL; mlpp = &mlp->next, mlp = *mlpp) {
  266. if (PORT_Strcmp(name,mlp->module->commonName) == 0) {
  267.     /* don't delete the internal module */
  268.     if (mlp->module->internal) {
  269. rv = SECSuccess;
  270. SECMOD_RemoveList(mlpp,mlp);
  271.     } 
  272.     break;
  273. }
  274.     }
  275.     SECMOD_ReleaseWriteLock(moduleLock);
  276.     if (rv == SECSuccess) {
  277. SECMODModule *newModule,*oldModule;
  278. if (mlp->module->isFIPS) {
  279.     newModule = SECMOD_NewInternal();
  280. } else {
  281.     newModule = SECMOD_GetFIPSInternal();
  282. }
  283. if (newModule == NULL) {
  284.     SECMODModuleList *last,*mlp2;
  285.    /* we're in pretty deep trouble if this happens...Security
  286.     * not going to work well... try to put the old module back on
  287.     * the list */
  288.    SECMOD_GetWriteLock(moduleLock);
  289.    for(mlp2 = modules; mlp2 != NULL; mlp2 = mlp->next) {
  290. last = mlp2;
  291.    }
  292.    if (last == NULL) {
  293. modules = mlp;
  294.    } else {
  295. SECMOD_AddList(last,mlp,NULL);
  296.    }
  297.    SECMOD_ReleaseWriteLock(moduleLock);
  298.    return SECFailure; 
  299. }
  300. oldModule = internalModule;
  301. internalModule = SECMOD_ReferenceModule(newModule);
  302. SECMOD_AddModule(internalModule);
  303. SECMOD_DestroyModule(oldModule);
  304.   SECMOD_DeletePermDB(mlp->module);
  305. SECMOD_DestroyModuleListElement(mlp);
  306.     }
  307.     return rv;
  308. }
  309. SECStatus
  310. SECMOD_AddModule(SECMODModule *newModule) {
  311.     SECStatus rv;
  312.     SECMODModuleList *mlp, *newListElement, *last = NULL;
  313.     /* Test if a module w/ the same name already exists */
  314.     /* and return SECWouldBlock if so. */
  315.     /* We should probably add a new return value such as */
  316.     /* SECDublicateModule, but to minimize ripples, I'll */
  317.     /* give SECWouldBlock a new meaning */
  318.     if (SECMOD_FindModule(newModule->commonName)) {
  319.         return SECWouldBlock;
  320.         /* module already exists. */
  321.     }
  322.     rv = SECMOD_LoadModule(newModule);
  323.     if (rv != SECSuccess) {
  324. return rv;
  325.     }
  326.     newListElement = SECMOD_NewModuleListElement();
  327.     if (newListElement == NULL) {
  328. return SECFailure;
  329.     }
  330.     SECMOD_AddPermDB(newModule);
  331.     newListElement->module = newModule;
  332.     SECMOD_GetWriteLock(moduleLock);
  333.     /* Added it to the end (This is very inefficient, but Adding a module
  334.      * on the fly should happen maybe 2-3 times through the life this program
  335.      * on a given computer, and this list should be *SHORT*. */
  336.     for(mlp = modules; mlp != NULL; mlp = mlp->next) {
  337. last = mlp;
  338.     }
  339.     if (last == NULL) {
  340. modules = newListElement;
  341.     } else {
  342. SECMOD_AddList(last,newListElement,NULL);
  343.     }
  344.     SECMOD_ReleaseWriteLock(moduleLock);
  345.     return SECSuccess;
  346. }
  347. PK11SlotInfo *SECMOD_FindSlot(SECMODModule *module,char *name) {
  348.     int i;
  349.     char *string;
  350.     for (i=0; i < module->slotCount; i++) {
  351. PK11SlotInfo *slot = module->slots[i];
  352. if (PK11_IsPresent(slot)) {
  353.     string = PK11_GetTokenName(slot);
  354. } else {
  355.     string = PK11_GetSlotName(slot);
  356. }
  357. if (PORT_Strcmp(name,string) == 0) {
  358.     return PK11_ReferenceSlot(slot);
  359. }
  360.     }
  361.     return NULL;
  362. }
  363. SECStatus
  364. PK11_GetModInfo(SECMODModule *mod,CK_INFO *info) {
  365.     CK_RV crv;
  366.     if (mod->functionList == NULL) return SECFailure;
  367.     crv = PK11_GETTAB(mod)->C_GetInfo(info);
  368.     return (crv == CKR_OK) ? SECSuccess : SECFailure;
  369. }
  370. /* Determine if we have the FIP's module loaded as the default
  371.  * module to trigger other bogus FIPS requirements in PKCS #12 and
  372.  * SSL
  373.  */
  374. PRBool
  375. PK11_IsFIPS(void)
  376. {
  377.     SECMODModule *mod = SECMOD_GetInternalModule();
  378.     if (mod && mod->internal) {
  379. return mod->isFIPS;
  380.     }
  381.     return PR_FALSE;
  382. }
  383. /* combines NewModule() & AddModule */
  384. /* give a string for the module name & the full-path for the dll, */
  385. /* installs the PKCS11 module & update registry */
  386. SECStatus SECMOD_AddNewModule(char* moduleName, char* dllPath,
  387.                               unsigned long defaultMechanismFlags,
  388.                               unsigned long cipherEnableFlags) {
  389.     SECMODModule *module;
  390.     SECStatus result;
  391.     int s,i;
  392.     PK11SlotInfo* slot;
  393.     module = SECMOD_NewModule();
  394.     
  395.     if (moduleName) {
  396.         module->commonName=PORT_ArenaStrdup(module->arena,moduleName);
  397.     } else {
  398.         module->commonName=NULL;
  399.     }
  400.     if (dllPath) {
  401.         module->dllName=PORT_ArenaStrdup(module->arena,dllPath);
  402.     } else {
  403.         module->dllName=NULL;
  404.     }
  405.     if (module->dllName != NULL) {
  406.         if (module->dllName[0] != 0) {
  407.            SECStatus rv = SECMOD_AddModule(module);
  408.             if (rv != SECSuccess) {
  409.                 /* SECFailure: failed to add module, corrupt or missing module etc. */
  410.                 /* SECBlock: a module with the same name already exists */
  411.                 return rv;
  412.             } else { /* successfully added module */
  413.                 /* turn on SSL cipher enable flags */
  414.                 module->ssl[0] = cipherEnableFlags;
  415.                 /* check each slot to turn on appropriate mechanisms */
  416.                 for (s = 0; s < module->slotCount; s++) {
  417.                     slot = (module->slots)[s];
  418.                     /* for each possible mechanism */
  419.                     for (i=0; i < num_pk11_default_mechanisms; i++) {
  420.                         /* we are told to turn it on by default ? */
  421.                         if (PK11_DefaultArray[i].flag & defaultMechanismFlags) {                            
  422.                             /* it ignores if slot attribute update failes */
  423.                             result = PK11_UpdateSlotAttribute(slot, &(PK11_DefaultArray[i]), PR_TRUE);
  424.                         } else { /* turn this mechanism of the slot off by default */
  425.                             result = PK11_UpdateSlotAttribute(slot, &(PK11_DefaultArray[i]), PR_FALSE);
  426.                         }
  427.                     } /* for each mechanism */
  428.                     /* disable each slot if the defaultFlags say so */
  429.                     if (defaultMechanismFlags & PK11_DISABLE_FLAG) {
  430.                         PK11_UserDisableSlot(slot);
  431.                     }
  432.                 } /* for each slot of this module */
  433.                 /* delete and re-add module in order to save changes to the module */
  434.                 result = SECMOD_DeletePermDB(module);
  435.                 
  436.                 if (result == SECSuccess) {          
  437.                     result = SECMOD_AddPermDB(module);
  438.                     if (result == SECSuccess) {
  439.                         return SECSuccess;
  440.                     }                    
  441.                 }
  442.                 
  443.             }
  444.         }
  445.     }
  446.     SECMOD_DestroyModule(module);
  447.     return SECFailure;
  448. }
  449. /* Public & Internal(Security Library)  representation of
  450.  * encryption mechanism flags conversion */
  451. /* Currently, the only difference is that internal representation 
  452.  * puts RANDOM_FLAG at bit 31 (Most-significant bit), but
  453.  * public representation puts this bit at bit 28
  454.  */
  455. unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags) {
  456.     unsigned long internalFlags = publicFlags;
  457.     if (publicFlags & PUBLIC_MECH_RANDOM_FLAG) {
  458.         internalFlags &= ~PUBLIC_MECH_RANDOM_FLAG;
  459.         internalFlags |= SECMOD_RANDOM_FLAG;
  460.     }
  461.     return internalFlags;
  462. }
  463. unsigned long SECMOD_InternaltoPubMechFlags(unsigned long internalFlags) {
  464.     unsigned long publicFlags = internalFlags;
  465.     if (internalFlags & SECMOD_RANDOM_FLAG) {
  466.         publicFlags &= ~SECMOD_RANDOM_FLAG;
  467.         publicFlags |= PUBLIC_MECH_RANDOM_FLAG;
  468.     }
  469.     return publicFlags;
  470. }
  471. /* Public & Internal(Security Library)  representation of */
  472. /* cipher flags conversion */
  473. /* Note: currently they are just stubs */
  474. unsigned long SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags) {
  475.     return publicFlags;
  476. }
  477. unsigned long SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags) {
  478.     return internalFlags;
  479. }
  480. /* Funtion reports true if module of modType is installed/configured */
  481. PRBool 
  482. SECMOD_IsModulePresent( unsigned long int pubCipherEnableFlags )
  483. {
  484.     PRBool result = PR_FALSE;
  485.     SECMODModuleList *mods = SECMOD_GetDefaultModuleList();
  486.     SECMODListLock *modsLock = SECMOD_GetDefaultModuleListLock();
  487.     SECMOD_GetReadLock(moduleLock);
  488.     for ( ; mods != NULL; mods = mods->next) {
  489.         if (mods->module->ssl[0] & SECMOD_PubCipherFlagstoInternal(pubCipherEnableFlags)) {
  490.             result = PR_TRUE;
  491.         }
  492.     }
  493.     SECMOD_ReleaseReadLock(moduleLock);
  494.     return result;
  495. }