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

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.  * This file implements PKCS 11 for FORTEZZA using MACI
  34.  *   drivers.  Except for the Mac.  They only have CI libraries, so
  35.  *   that's what we use there.
  36.  *
  37.  *   For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
  38.  *
  39.  *   This implementations queries the MACI to figure out how 
  40.  *    many slots exist on a given system.  There is an artificial boundary
  41.  *    of 32 slots, because allocating slots dynamically caused memory
  42.  *    problems in the client when first this module was first developed.
  43.  *    Some how the heap was being corrupted and we couldn't find out where.
  44.  *    Subsequent attempts to allocate dynamic memory caused no problem.
  45.  *
  46.  *   In this implementation, session objects are only visible to the session
  47.  *   that created or generated them.
  48.  */
  49. #include "fpkmem.h"
  50. #include "seccomon.h"
  51. #include "fpkcs11.h"
  52. #include "fpkcs11i.h"
  53. #include "cryptint.h"
  54. #include "pk11func.h"
  55. #include "fortsock.h"
  56. #include "fmutex.h"
  57. #ifdef notdef
  58. #include <ctype.h>
  59. #include <stdio.h>
  60. #endif
  61. #ifdef XP_MAC 
  62. #ifndef __POWERPC__
  63. #include <A4Stuff.h>
  64. #endif
  65. /* This is not a 4.0 project, so I can't depend on
  66.  * 4.0 defines, so instead I depend on CodeWarrior 
  67.  * defines.  I define XP_MAC in fpkmem.h
  68.  */
  69. #if __POWERPC__
  70. #elif __CFM68K__
  71. #else
  72. /* These include are taken fromn npmac.cpp which are used
  73.  * by the plugin group to properly set-up a plug-in for 
  74.  * dynamic loading on 68K.
  75.  */
  76. #include <Quickdraw.h>
  77. /*
  78. ** The Mixed Mode procInfos defined in npupp.h assume Think C-
  79. ** style calling conventions.  These conventions are used by
  80. ** Metrowerks with the exception of pointer return types, which
  81. ** in Metrowerks 68K are returned in A0, instead of the standard
  82. ** D0. Thus, since NPN_MemAlloc and NPN_UserAgent return pointers,
  83. ** Mixed Mode will return the values to a 68K plugin in D0, but 
  84. ** a 68K plugin compiled by Metrowerks will expect the result in
  85. ** A0.  The following pragma forces Metrowerks to use D0 instead.
  86. */
  87. #ifdef __MWERKS__
  88. #ifndef powerc
  89. #pragma pointers_in_D0
  90. #endif
  91. #endif
  92. #ifdef __MWERKS__
  93. #ifndef powerc
  94. #pragma pointers_in_A0
  95. #endif
  96. #endif
  97. /* The following fix for static initializers fixes a previous
  98. ** incompatibility with some parts of PowerPlant.
  99. */
  100. #ifdef __MWERKS__
  101. #ifdef __cplusplus
  102.     extern "C" {
  103. #endif
  104. #ifndef powerc
  105.     extern void __InitCode__(void);
  106. #else
  107.     extern void __sinit(void);
  108. #endif
  109.     extern void __destroy_global_chain(void);
  110. #ifdef __cplusplus
  111.     }
  112. #endif /* __cplusplus */
  113. #endif /* __MWERKS__ */
  114. #endif
  115. #endif
  116. typedef struct {
  117.    unsigned char *data;
  118.    int len;
  119. } CertItem;
  120. /*
  121.  * ******************** Static data *******************************
  122.  */
  123. /* The next three strings must be exactly 32 characters long */
  124. static char *manufacturerID      = "Netscape Communications Corp    ";
  125. static char *libraryDescription  = "Communicator Fortezza Crypto Svc";
  126. typedef enum {DSA_KEY, KEA_KEY, V1_KEY, INVALID_KEY } PrivKeyType;
  127. static PK11Slot           fort11_slot[NUM_SLOTS];
  128. static FortezzaSocket     fortezzaSockets[NUM_SLOTS];
  129. static PRBool             init = PR_FALSE;
  130. static CK_ULONG           kNumSockets    = 0;
  131. #define __PASTE(x,y)    x##y
  132.  
  133.  
  134. #undef CK_FUNC
  135. #undef CK_EXTERN
  136. #undef CK_NEED_ARG_LIST
  137. #undef _CK_RV
  138. #define fort11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen
  139. #define fort11_SlotFromSession  pk11_SlotFromSession
  140. #define fort11_isToken          pk11_isToken
  141. static CK_FUNCTION_LIST fort11_funcList = {
  142.     { 2, 1 },
  143.  
  144. #undef CK_FUNC
  145. #undef CK_EXTERN
  146. #undef CK_NEED_ARG_LIST
  147. #undef _CK_RV
  148.  
  149. #define CK_EXTERN
  150. #define CK_FUNC(name) name,
  151. #define _CK_RV
  152.  
  153. #include "fpkcs11f.h"
  154.  
  155. };
  156.  
  157. #undef CK_FUNC
  158. #undef CK_EXTERN
  159. #undef _CK_RV
  160.  
  161.  
  162. #undef __PASTE
  163. #undef pk11_SlotFromSessionHandle
  164. #undef pk11_SlotFromID
  165. #define MAJOR_VERSION_MASK 0xFF00
  166. #define MINOR_VERSION_MASK 0x00FF
  167. /* Mechanisms */
  168. struct mechanismList {
  169.     CK_MECHANISM_TYPE type;
  170.     CK_MECHANISM_INFO domestic;
  171.     PRBool              privkey; 
  172. };
  173. static struct mechanismList mechanisms[] = {
  174.      {CKM_DSA,              {512,1024,CKF_SIGN},                 PR_TRUE},
  175.      {CKM_SKIPJACK_KEY_GEN, {92, 92, CKF_GENERATE},              PR_TRUE},
  176.      {CKM_SKIPJACK_CBC64,   {92, 92, CKF_ENCRYPT | CKF_DECRYPT}, PR_TRUE},
  177.      {CKM_SKIPJACK_WRAP,    {92, 92, CKF_WRAP},                  PR_TRUE},
  178.      {CKM_KEA_KEY_DERIVE,   {128, 128, CKF_DERIVE},              PR_TRUE},
  179. };
  180. static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
  181. /*************Static function prototypes********************************/
  182. static PRBool          fort11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type);
  183. static void            fort11_FreeAttribute(PK11Attribute *attribute);
  184. static void            fort11_DestroyAttribute(PK11Attribute *attribute);
  185. static PK11Object*     fort11_NewObject(PK11Slot *slot);
  186. static PK11FreeStatus  fort11_FreeObject(PK11Object *object);
  187. static CK_RV           fort11_AddAttributeType(PK11Object *object,
  188.      CK_ATTRIBUTE_TYPE type,
  189.      void *valPtr,
  190.      CK_ULONG length);
  191. static void            fort11_AddSlotObject(PK11Slot *slot, PK11Object *object);
  192. static PK11Attribute*  fort11_FindAttribute(PK11Object *object,
  193.   CK_ATTRIBUTE_TYPE type);
  194. static PK11Attribute*  fort11_NewAttribute(CK_ATTRIBUTE_TYPE type, 
  195.  CK_VOID_PTR value, CK_ULONG len);
  196. static void            fort11_DeleteAttributeType(PK11Object *object,
  197. CK_ATTRIBUTE_TYPE type);
  198. static void            fort11_AddAttribute(PK11Object *object,
  199.  PK11Attribute *attribute);
  200. static void            fort11_AddObject(PK11Session *session, 
  201.       PK11Object *object);
  202. static PK11Object *    fort11_ObjectFromHandle(CK_OBJECT_HANDLE handle, 
  203.      PK11Session *session);
  204. static void            fort11_DeleteObject(PK11Session *session,PK11Object *object);
  205. static CK_RV           fort11_DestroyObject(PK11Object *object);
  206. void   fort11_FreeSession(PK11Session *session);
  207. #define FIRST_SLOT_SESS_ID   0x00000100L
  208. #define ADD_NEXT_SESS_ID     0x00000100L
  209. #define SLOT_MASK            0x000000FFL
  210. #define FAILED CKR_FUNCTION_FAILED
  211. static void
  212. fort11_FreeFortezzaKey (void *inFortezzaKey) {
  213.     RemoveKey ((FortezzaKey*) inFortezzaKey);
  214. }
  215. static void
  216. fort11_DestroySlotObjects (PK11Slot *slot, PK11Session *session) {
  217.     PK11Object *currObject, *nextObject, *oldObject;
  218.     int i;
  219.     for (i=0; i<HASH_SIZE; i++) {
  220.       currObject = slot->tokObjects[i];
  221.       slot->tokObjects[i] = NULL;
  222.       do {
  223.   FMUTEX_Lock(slot->sessionLock);
  224.   if (currObject) {
  225.       nextObject = currObject->next;
  226.       FMUTEX_Lock(currObject->refLock);
  227.       currObject->refCount++;
  228.       FMUTEX_Unlock(currObject->refLock);
  229.       fort11_DeleteObject(session, currObject);
  230.   }
  231.   FMUTEX_Unlock(slot->sessionLock);
  232.   if (currObject) {
  233.       oldObject = currObject;
  234.       currObject = nextObject;
  235.       fort11_FreeObject(oldObject);
  236.   }
  237.       } while (currObject != NULL);
  238.     }
  239. }
  240. static void
  241. fort11_TokenRemoved(PK11Slot *slot, PK11Session *session) {
  242.     FortezzaSocket *socket = &fortezzaSockets[slot->slotID-1];
  243.     LogoutFromSocket (socket);
  244.     slot->isLoggedIn = PR_FALSE;
  245.     if (session && session->notify) { 
  246.         /*If no session pointer exists, lots of leaked memory*/
  247.         session->notify (session->handle, CKN_SURRENDER,
  248.  session->appData);
  249. fort11_FreeSession(session); /* Release the reference held
  250.       * by the slot with the session
  251.       */
  252.     }
  253.     fort11_DestroySlotObjects(slot, session);
  254.     fort11_FreeSession(session); /* Release the reference held
  255.   * by the slot with the session
  256.   */
  257.     /* All keys will have been freed at this point so we can
  258.      * NULL out this pointer
  259.      */
  260.     socket->keys = NULL;
  261. }
  262. PRBool
  263. fort11_FortezzaIsUserCert(unsigned char * label) {
  264.     if ( (!PORT_Memcmp(label, "KEAK", 4)) ||   /* v3 user certs */
  265.          (!PORT_Memcmp(label, "DSA1", 4)) ||
  266.  (!PORT_Memcmp(label, "DSAI", 4)) ||
  267.          (!PORT_Memcmp(label, "DSAO", 4)) ||
  268.          (!PORT_Memcmp(label, "INKS", 4)) ||   /* v1 user certs */ 
  269.          (!PORT_Memcmp(label, "INKX", 4)) ||
  270.          (!PORT_Memcmp(label, "ONKS", 4)) ||
  271.          (!PORT_Memcmp(label, "ONKX", 4)) ||
  272.          (!PORT_Memcmp(label, "3IXS", 4)) ||   /* old v3 user certs */
  273.          (!PORT_Memcmp(label, "3OXS", 4)) ||
  274.          (!PORT_Memcmp(label, "3IKX", 4)) ) {  
  275.          return PR_TRUE;
  276.     } else { return PR_FALSE; }
  277.     
  278. }
  279. static PRBool
  280. fort11_FortezzaIsACert(unsigned char * label) {
  281.     if (label == NULL) return PR_FALSE;
  282.     if ( (!PORT_Memcmp(label, "DSA1", 4)) ||   /* v3 certs */
  283.          (!PORT_Memcmp(label, "DSAI", 4)) ||
  284.  (!PORT_Memcmp(label, "DSAO", 4)) || 
  285.          (!PORT_Memcmp(label, "DSAX", 4)) ||
  286.          (!PORT_Memcmp(label, "KEAK", 4)) ||
  287.          (!PORT_Memcmp(label, "KEAX", 4)) ||
  288.          (!PORT_Memcmp(label, "CAX1", 4)) ||
  289.          (!PORT_Memcmp(label, "PCA1", 4)) ||
  290.          (!PORT_Memcmp(label, "PAA1", 4)) ||
  291.          (!PORT_Memcmp(label, "ICA1", 4)) ||
  292.          (!PORT_Memcmp(label, "3IXS", 4)) ||   /* old v3 certs */    
  293.          (!PORT_Memcmp(label, "3OXS", 4)) ||    
  294.          (!PORT_Memcmp(label, "3CAX", 4)) ||
  295.          (!PORT_Memcmp(label, "3IKX", 4)) ||
  296.          (!PORT_Memcmp(label, "3PCA", 4)) ||
  297.          (!PORT_Memcmp(label, "3PAA", 4)) ||
  298.          (!PORT_Memcmp(label, "3ICA", 4)) ||
  299.          (!PORT_Memcmp(label, "INKS", 4)) ||   /* v1 certs */    
  300.          (!PORT_Memcmp(label, "INKX", 4)) ||
  301.          (!PORT_Memcmp(label, "ONKS", 4)) ||
  302.          (!PORT_Memcmp(label, "ONKX", 4)) ||
  303.          (!PORT_Memcmp(label, "RRXX", 4)) ||
  304.          (!PORT_Memcmp(label, "RTXX", 4)) ||
  305.          (!PORT_Memcmp(label, "LAXX", 4)) ) {  
  306.          return PR_TRUE;
  307.     } 
  308.     return PR_FALSE; 
  309. }
  310.  
  311. static 
  312. int fort11_cert_length(unsigned char *buf, int length) {
  313.     unsigned char tag;
  314.     int used_length= 0;
  315.     int data_length;
  316.     tag = buf[used_length++];
  317.     /* blow out when we come to the end */
  318.     if (tag == 0) {
  319. return 0;
  320.     }
  321.     data_length = buf[used_length++];
  322.     if (data_length&0x80) {
  323. int  len_count = data_length & 0x7f;
  324. data_length = 0;
  325. while (len_count-- > 0) {
  326.     data_length = (data_length << 8) | buf[used_length++];
  327.     }
  328.     if (data_length > (length-used_length) ) {
  329. return length;
  330.     }
  331.     return (data_length + used_length);
  332. }
  333. unsigned char *fort11_data_start(unsigned char *buf, int length, 
  334.  int *data_length, PRBool includeTag) {
  335.     unsigned char tag;
  336.     int used_length= 0;
  337.     tag = buf[used_length++];
  338.     /* blow out when we come to the end */
  339.     if (tag == 0) {
  340. return NULL;
  341.     }
  342.     *data_length = buf[used_length++];
  343.     if (*data_length&0x80) {
  344. int  len_count = *data_length & 0x7f;
  345. *data_length = 0;
  346. while (len_count-- > 0) {
  347.     *data_length = (*data_length << 8) | buf[used_length++];
  348.     }
  349.     if (*data_length > (length-used_length) ) {
  350. *data_length = length-used_length;
  351. return NULL;
  352.     }
  353.     if (includeTag) *data_length += used_length;
  354.     return (buf + (includeTag ? 0 : used_length));
  355. }
  356. int
  357. fort11_GetCertFields(unsigned char *cert,int cert_length,CertItem *issuer,
  358.      CertItem *serial,CertItem *subject)
  359. {
  360. unsigned char *buf;
  361. int buf_length;
  362. unsigned char *date;
  363. int datelen;
  364. /* get past the signature wrap */
  365. buf = fort11_data_start(cert,cert_length,&buf_length,PR_FALSE);
  366. if (buf == NULL) return FAILED;
  367. /* get into the raw cert data */
  368. buf = fort11_data_start(buf,buf_length,&buf_length,PR_FALSE);
  369. if (buf == NULL) return FAILED;
  370. /* skip past any optional version number */
  371.         if ((buf[0] & 0xa0) == 0xa0) {
  372.             date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
  373.             if (date == NULL) return FAILED;
  374.             buf_length -= (date-buf) + datelen;
  375.             buf = date + datelen;
  376.         }
  377.         /* serial number */
  378. serial->data = fort11_data_start(buf,buf_length,&serial->len,PR_FALSE);
  379. if (serial->data == NULL) return FAILED;
  380. buf_length -= (serial->data-buf) + serial->len;
  381. buf = serial->data + serial->len;
  382. /* skip the OID */
  383. date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
  384. if (date == NULL) return FAILED;
  385. buf_length -= (date-buf) + datelen;
  386. buf = date + datelen;
  387. /* issuer */
  388. issuer->data = fort11_data_start(buf,buf_length,&issuer->len,PR_TRUE);
  389. if (issuer->data == NULL) return FAILED;
  390. buf_length -= (issuer->data-buf) + issuer->len;
  391. buf = issuer->data + issuer->len;
  392. /* skip the date */
  393. date = fort11_data_start(buf,buf_length,&datelen,PR_FALSE);
  394. if (date == NULL) return FAILED;
  395. buf_length -= (date-buf) + datelen;
  396. buf = date + datelen;
  397. /*subject */
  398. subject->data=fort11_data_start(buf,buf_length,&subject->len,PR_TRUE);
  399. if (subject->data == NULL) return FAILED;
  400. buf_length -= (subject->data-buf) + subject->len;
  401. buf = subject->data +subject->len;
  402. /*subject */
  403. return CKR_OK;
  404. }
  405. /* quick tohex function to get rid of scanf */
  406. static
  407. int fort11_tohex(char *s) {
  408.     int val = 0;
  409.     for(;*s;s++) {
  410. if ((*s >= '0') && (*s <= '9')) {
  411.     val = (val << 4) + (*s - '0');
  412.     continue;
  413. } else if ((*s >= 'a') && (*s <= 'f')) {
  414.     val = (val << 4) + (*s - 'a') + 10;
  415.     continue;
  416. } else if ((*s >= 'A') && (*s <= 'F')) {
  417.     val = (val << 4) + (*s - 'A') + 10;
  418.     continue;
  419. }
  420. break;
  421.     }
  422.     return val;
  423. }
  424. /* only should be called for V3 KEA cert labels. */
  425. static int
  426. fort11_GetSibling(CI_CERT_STR label)  {
  427. int value = 0;
  428.         char s[3];
  429.         label +=4;
  430.         strcpy(s,"00");
  431.         memcpy(s, label, 2);
  432. value = fort11_tohex(s);
  433.         
  434. /*  sibling of 255 means no sibling */
  435.         if (value == 255) {
  436.     value = -1;
  437. }
  438. return value;
  439. }
  440. static PrivKeyType
  441. fort11_GetKeyType(CI_CERT_STR label) { 
  442.     if (label == NULL) return INVALID_KEY;
  443.     if ( (!PORT_Memcmp(label, "DSA1", 4)) ||   /* v3 certs */ 
  444.          (!PORT_Memcmp(label, "DSAI", 4)) ||
  445.  (!PORT_Memcmp(label, "DSAO", 4)) ||
  446.          (!PORT_Memcmp(label, "3IXS", 4)) ||   /* old v3 certs */ 
  447.          (!PORT_Memcmp(label, "3OXS", 4)) ) {
  448.         return DSA_KEY;
  449.     }
  450.     if ( (!PORT_Memcmp(label, "KEAK", 4)) || 
  451.          (!PORT_Memcmp(label, "3IKX", 4)) ) {
  452.         return KEA_KEY;
  453.     }
  454.  
  455.     if ( (!PORT_Memcmp(label, "INKS", 4)) ||  /* V1 Certs*/
  456.          (!PORT_Memcmp(label, "INKX", 4)) ||
  457.          (!PORT_Memcmp(label, "ONKS", 4)) ||
  458.          (!PORT_Memcmp(label, "ONKX", 4)) ||  
  459.          (!PORT_Memcmp(label, "RRXX", 4)) ||
  460.          (!PORT_Memcmp(label, "RTXX", 4)) ||
  461.          (!PORT_Memcmp(label, "LAXX", 4)) ) { 
  462.          return V1_KEY;
  463.     }
  464.     return INVALID_KEY;
  465. static CK_RV
  466. fort11_ConvertToDSAKey(PK11Object *privateKey, PK11Slot *slot) {
  467.     CK_KEY_TYPE     key_type  = CKK_DSA;
  468.     CK_BBOOL        cktrue    = TRUE;
  469.     CK_BBOOL        ckfalse   = FALSE;
  470.     CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
  471.     CK_CHAR         label[]   = "A DSA Private Key";
  472.     /* Fill in the common Default values */
  473.     if (fort11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
  474. return CKR_GENERAL_ERROR;
  475.     }
  476.     if (fort11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
  477. return CKR_GENERAL_ERROR;
  478.     }
  479.     if (fort11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
  480. return CKR_GENERAL_ERROR;
  481.     }
  482.     if (fort11_AddAttributeType(privateKey, CKA_CLASS, &privClass, 
  483.       sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
  484.         return CKR_GENERAL_ERROR;
  485.     }
  486.     if (fort11_AddAttributeType(privateKey, CKA_KEY_TYPE, &key_type, 
  487.       sizeof(CK_KEY_TYPE)) != CKR_OK) {
  488.         return CKR_GENERAL_ERROR;
  489.     }
  490.     if (fort11_AddAttributeType (privateKey, CKA_TOKEN, &cktrue, 
  491.       sizeof (CK_BBOOL)) != CKR_OK) {
  492.        return CKR_GENERAL_ERROR;
  493.     }
  494.     if (fort11_AddAttributeType (privateKey, CKA_LABEL, label,
  495.        PORT_Strlen((char*)label)) != CKR_OK) {
  496.         return CKR_GENERAL_ERROR;
  497.     }
  498.     if (fort11_AddAttributeType(privateKey, CKA_SENSITIVE, &cktrue, 
  499.       sizeof (CK_BBOOL)) != CKR_OK) {
  500.         return CKR_GENERAL_ERROR;
  501.     }
  502.     if (fort11_AddAttributeType(privateKey, CKA_SIGN, &cktrue, 
  503.       sizeof (CK_BBOOL)) != CKR_OK) {
  504.         return CKR_GENERAL_ERROR;
  505.     }
  506.     if (fort11_AddAttributeType(privateKey, CKA_DERIVE, &cktrue,
  507.       sizeof(cktrue)) != CKR_OK) {
  508. return CKR_GENERAL_ERROR;
  509.     }
  510.     if (fort11_AddAttributeType(privateKey, CKA_LOCAL, &ckfalse,
  511.       sizeof(ckfalse)) != CKR_OK) {
  512.         return CKR_GENERAL_ERROR;
  513.     }
  514.     if (fort11_AddAttributeType(privateKey, CKA_DECRYPT, &ckfalse,
  515.       sizeof(ckfalse)) != CKR_OK) {
  516.         return CKR_GENERAL_ERROR;
  517.     }
  518.     if (fort11_AddAttributeType(privateKey, CKA_SIGN_RECOVER, &ckfalse,
  519.       sizeof(ckfalse)) != CKR_OK) {
  520.   return CKR_GENERAL_ERROR;
  521.     }
  522.     if (fort11_AddAttributeType(privateKey, CKA_UNWRAP, &ckfalse,
  523.       sizeof(ckfalse)) != CKR_OK) {
  524.   return CKR_GENERAL_ERROR;
  525.     }
  526.     if (fort11_AddAttributeType(privateKey, CKA_EXTRACTABLE, &ckfalse,
  527.       sizeof(ckfalse))  != CKR_OK) {
  528.         return CKR_GENERAL_ERROR;
  529.     }
  530.     if (fort11_AddAttributeType(privateKey, CKA_ALWAYS_SENSITIVE, &cktrue,
  531.       sizeof(cktrue)) != CKR_OK) {
  532.        return CKR_GENERAL_ERROR;
  533.     }
  534.     if (fort11_AddAttributeType(privateKey, CKA_NEVER_EXTRACTABLE, &cktrue,
  535.       sizeof(ckfalse)) != CKR_OK) {
  536.         return CKR_GENERAL_ERROR;
  537.     }
  538.     if (fort11_AddAttributeType(privateKey, CKA_PRIME, NULL, 0) != CKR_OK){
  539.         return CKR_GENERAL_ERROR;
  540.     }
  541.     if (fort11_AddAttributeType(privateKey, CKA_SUBPRIME, NULL, 0) != CKR_OK){
  542.         return CKR_GENERAL_ERROR;
  543.     }
  544.     if (fort11_AddAttributeType(privateKey, CKA_BASE, NULL, 0) != CKR_OK) {
  545.         return CKR_GENERAL_ERROR;
  546.     }
  547.     if (fort11_AddAttributeType(privateKey, CKA_VALUE, NULL, 0) != CKR_OK) {
  548.         return CKR_GENERAL_ERROR;
  549.     }
  550.     if (fort11_AddAttributeType(privateKey, CKA_PRIVATE, &cktrue,
  551.       sizeof(cktrue)) != CKR_OK) {
  552.         return CKR_GENERAL_ERROR;
  553.     }
  554.     if (fort11_AddAttributeType(privateKey, CKA_MODIFIABLE,&ckfalse,
  555.       sizeof(ckfalse)) != CKR_OK) {
  556.         return CKR_GENERAL_ERROR;
  557.     }
  558.     FMUTEX_Lock(slot->objectLock);
  559.     privateKey->handle = slot->tokenIDCount++;
  560.     privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  561.     FMUTEX_Unlock(slot->objectLock);
  562.     privateKey->objclass = privClass;
  563.     privateKey->slot = slot;
  564.     privateKey->inDB = PR_TRUE;
  565.     return CKR_OK;
  566. }
  567. static int
  568. fort11_LoadRootPAAKey(PK11Slot *slot, PK11Session *session) {
  569.     CK_OBJECT_CLASS theClass   = CKO_SECRET_KEY;
  570.     int              id      = 0;
  571.     CK_BBOOL         True    = TRUE;
  572.     CK_BBOOL          False   = FALSE;
  573.     CK_CHAR          label[] = "Trusted Root PAA Key";
  574.     PK11Object      *rootKey;
  575.     FortezzaKey     *newKey;
  576.     FortezzaSocket *socket  = &fortezzaSockets[slot->slotID-1];
  577.     
  578.     /*Don't know the key type.  Does is matter?*/
  579.     rootKey = fort11_NewObject(slot);
  580.     if (rootKey == NULL) {
  581.         return CKR_HOST_MEMORY;
  582.     }
  583.     if (fort11_AddAttributeType(rootKey, CKA_CLASS, &theClass,
  584.       sizeof(theClass)) != CKR_OK) {
  585. return CKR_GENERAL_ERROR;
  586.     }
  587.     if (fort11_AddAttributeType(rootKey, CKA_TOKEN, &True,
  588.       sizeof(True)) != CKR_OK) {        
  589. return CKR_GENERAL_ERROR;
  590.     }
  591.     if (fort11_AddAttributeType(rootKey, CKA_LABEL, label,
  592.       sizeof(label)) != CKR_OK) {
  593. return CKR_GENERAL_ERROR;
  594.     }
  595.     if (fort11_AddAttributeType(rootKey, CKA_PRIVATE, &True,
  596.       sizeof (True)) != CKR_OK) {
  597. return CKR_GENERAL_ERROR;
  598.     }
  599.     if (fort11_AddAttributeType(rootKey,CKA_MODIFIABLE, &False, 
  600.       sizeof(False)) != CKR_OK) {
  601. return CKR_GENERAL_ERROR;
  602.     }
  603.     
  604.     if (fort11_AddAttributeType(rootKey, CKA_ID, &id,
  605.       sizeof(int)) != CKR_OK) {
  606. return CKR_GENERAL_ERROR;
  607.     }
  608.     if (fort11_AddAttributeType(rootKey, CKA_DERIVE, &True,
  609.       sizeof(True)) != CKR_OK) {
  610. return CKR_GENERAL_ERROR;
  611.     }
  612.     if (fort11_AddAttributeType(rootKey, CKA_SENSITIVE, &True,
  613.       sizeof(True)) != CKR_OK) {
  614. return CKR_GENERAL_ERROR;
  615.     }
  616.     FMUTEX_Lock(slot->objectLock);
  617.     rootKey->handle = slot->tokenIDCount++;
  618.     rootKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  619.     FMUTEX_Unlock(slot->objectLock);
  620.     rootKey->objclass = theClass;
  621.     rootKey->slot = slot;
  622.     rootKey->inDB = PR_TRUE;
  623.     newKey = NewFortezzaKey(socket, Ks, NULL, 0);
  624.     if (newKey == NULL) {
  625.         fort11_FreeObject(rootKey);
  626.         return CKR_HOST_MEMORY;
  627.     }
  628.     rootKey->objectInfo = (void*)newKey;
  629.     rootKey->infoFree   = fort11_FreeFortezzaKey;
  630.     fort11_AddObject(session, rootKey);
  631.     return CKR_OK;
  632. }
  633. static CK_RV
  634. fort11_ConvertToKEAKey (PK11Object *privateKey, PK11Slot *slot) {
  635.     CK_OBJECT_CLASS theClass   = CKO_PRIVATE_KEY;
  636.     CK_KEY_TYPE     keyType = CKK_KEA;
  637.     CK_CHAR         label[] = "A KEA private key Object";
  638.     CK_BBOOL        True    = TRUE;
  639.     CK_BBOOL        False   = FALSE;
  640.     if (fort11_AddAttributeType(privateKey, CKA_CLASS, &theClass,
  641.       sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
  642.         return CKR_GENERAL_ERROR;
  643.     }
  644.     if (fort11_AddAttributeType(privateKey, CKA_KEY_TYPE, &keyType,
  645.       sizeof (CK_KEY_TYPE)) != CKR_OK) {
  646.         return CKR_GENERAL_ERROR;
  647.     }
  648.     if (fort11_AddAttributeType(privateKey, CKA_TOKEN, &True, 
  649.       sizeof(CK_BBOOL)) != CKR_OK) {
  650.         return CKR_GENERAL_ERROR;
  651.     }
  652.     if (fort11_AddAttributeType (privateKey, CKA_LABEL, label,
  653.        PORT_Strlen((char*)label)) != CKR_OK) {
  654.         return CKR_GENERAL_ERROR;
  655.     }
  656.     if (fort11_AddAttributeType (privateKey, CKA_SENSITIVE, 
  657.        &True, sizeof(CK_BBOOL)) != CKR_OK) {
  658.         return CKR_GENERAL_ERROR;
  659.     }    
  660.     if (fort11_AddAttributeType (privateKey, CKA_DERIVE, 
  661.        &True, sizeof(CK_BBOOL)) != CKR_OK) {
  662.         return CKR_GENERAL_ERROR;
  663.     }
  664.     if (fort11_AddAttributeType(privateKey, CKA_PRIVATE, &True,
  665.       sizeof(True)) != CKR_OK) {
  666.         return CKR_GENERAL_ERROR;
  667.     }
  668.     if (fort11_AddAttributeType(privateKey, CKA_START_DATE, NULL, 0) != CKR_OK) {
  669.         return CKR_GENERAL_ERROR;
  670.     } 
  671.     if (fort11_AddAttributeType(privateKey, CKA_END_DATE, NULL, 0) != CKR_OK) {
  672.         return CKR_GENERAL_ERROR;
  673.     }
  674.     if (fort11_AddAttributeType(privateKey, CKA_LOCAL, &False,
  675.       sizeof(False)) != CKR_OK) {
  676.         return CKR_GENERAL_ERROR;
  677.     }
  678.     FMUTEX_Lock(slot->objectLock);
  679.     privateKey->handle = slot->tokenIDCount++;
  680.     privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  681.     FMUTEX_Unlock(slot->objectLock);
  682.     privateKey->objclass = theClass;
  683.     privateKey->slot = slot;
  684.     privateKey->inDB = PR_TRUE;
  685.     return CKR_OK;
  686. }
  687. static CK_RV
  688. fort11_ConvertToV1Key (PK11Object* privateKey, PK11Slot *slot) {
  689.     CK_RV    rv;
  690.     CK_BBOOL True = TRUE;
  691.     rv = fort11_ConvertToDSAKey(privateKey, slot);
  692.     if (rv != CKR_OK) {
  693.         return rv;
  694.     }
  695.     if (fort11_AddAttributeType(privateKey, CKA_DERIVE, &True, 
  696.       sizeof (CK_BBOOL)) != CKR_OK) {
  697.         return CKR_GENERAL_ERROR;
  698.     }
  699.     return CKR_OK;
  700. }
  701. static CK_RV
  702. fort11_NewPrivateKey(PK11Object *privKeyObject, PK11Slot *slot,CI_PERSON currPerson) {
  703.   PrivKeyType keyType = fort11_GetKeyType(currPerson.CertLabel);
  704.   CK_RV       rv;
  705.   switch (keyType) {
  706.   case DSA_KEY:
  707.     rv = fort11_ConvertToDSAKey(privKeyObject, slot);
  708.     break;
  709.   case KEA_KEY:
  710.     rv = fort11_ConvertToKEAKey(privKeyObject, slot);
  711.     break;
  712.   case V1_KEY:
  713.     rv = fort11_ConvertToV1Key(privKeyObject, slot);
  714.     break;
  715.   default:
  716.     rv = CKR_GENERAL_ERROR;
  717.     break;
  718.   }
  719.   return rv;
  720. }
  721. PRBool
  722. fort11_LoadCertObjectForSearch(CI_PERSON currPerson, PK11Slot *slot, 
  723. PK11Session *session, CI_PERSON *pers_array) {
  724.     PK11Object          *certObject, *privKeyObject;
  725.     PK11Attribute       *attribute, *newAttribute;
  726.     int                  ci_rv;
  727.     CI_CERTIFICATE       cert;
  728.     CK_OBJECT_CLASS      certClass = CKO_CERTIFICATE;
  729.     CK_CERTIFICATE_TYPE  certType  = CKC_X_509;
  730.     CK_BBOOL             cktrue    = TRUE;
  731.     CK_BBOOL             ckfalse   = FALSE;
  732.     CertItem             issuer, serial, subject;
  733.     int  certSize;
  734.     char                 nickname[50];
  735.     char                *cursor; 
  736.     PrivKeyType  priv_key;
  737.     int  sibling;
  738.   
  739.     certObject = fort11_NewObject(slot);
  740.     if (certObject == NULL)
  741.         return PR_FALSE;
  742.     ci_rv = MACI_GetCertificate (fortezzaSockets[slot->slotID-1].maciSession,
  743.  currPerson.CertificateIndex, cert);
  744.     if (ci_rv != CI_OK){
  745.         fort11_FreeObject(certObject);
  746. return PR_FALSE;
  747.     }
  748.     ci_rv = fort11_GetCertFields(cert,CI_CERT_SIZE,&issuer,&serial,&subject);
  749.     if (ci_rv != CKR_OK) {
  750.         fort11_FreeObject(certObject);
  751. return PR_FALSE;
  752.     }
  753.     if (fort11_AddAttributeType(certObject, CKA_CLASS, &certClass,
  754.       sizeof (CK_OBJECT_CLASS)) != CKR_OK) {
  755.         fort11_FreeObject (certObject);
  756. return PR_FALSE;
  757.     }
  758.     if (fort11_AddAttributeType(certObject, CKA_TOKEN, &cktrue,
  759.       sizeof (CK_BBOOL)) != CKR_OK) {
  760.         fort11_FreeObject(certObject);
  761. return PR_FALSE;
  762.     }
  763.     if (fort11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse,
  764.       sizeof (CK_BBOOL)) != CKR_OK) {
  765.         fort11_FreeObject(certObject);
  766. return PR_FALSE;
  767.     }
  768.     
  769.     /* check if the label represents a KEA key. if so, the
  770.        nickname should be made the same as the corresponding DSA
  771.        sibling cert. */
  772.         
  773.     priv_key = fort11_GetKeyType(currPerson.CertLabel);
  774.     if (priv_key == KEA_KEY) {
  775. sibling = fort11_GetSibling(currPerson.CertLabel);
  776. /* check for failure of fort11_GetSibling.  also check that
  777.    the sibling is not zero.  */
  778. if (sibling > 0) {
  779.     /* assign the KEA cert label to be the same as the
  780.        sibling DSA label */
  781.     sprintf (nickname, "%s", &pers_array[sibling-1].CertLabel[8] );
  782. } else {
  783.     sprintf (nickname, "%s", &currPerson.CertLabel[8]);
  784. }
  785.     } else {
  786.         sprintf (nickname, "%s", &currPerson.CertLabel[8]);
  787.     }
  788.     cursor = nickname+PORT_Strlen(nickname)-1;
  789.     while ((*cursor) == ' ') {
  790.         cursor--;
  791.     }
  792.     cursor[1] = '';
  793.     if (fort11_AddAttributeType(certObject, CKA_LABEL, nickname,
  794.       PORT_Strlen(nickname)) != CKR_OK) {
  795.         fort11_FreeObject(certObject);
  796. return PR_FALSE;
  797.     }
  798.  
  799.     if (fort11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE, &certType,
  800.       sizeof(CK_CERTIFICATE_TYPE)) != CKR_OK) {
  801.         fort11_FreeObject(certObject);
  802. return PR_FALSE;
  803.     }
  804.     certSize = fort11_cert_length(cert,CI_CERT_SIZE);
  805.     if (fort11_AddAttributeType (certObject, CKA_VALUE, cert, certSize)
  806.                                                         != CI_OK) {
  807.         fort11_FreeObject(certObject);
  808. return PR_FALSE;
  809.     }
  810.     if (fort11_AddAttributeType(certObject, CKA_ISSUER, issuer.data,
  811.   issuer.len) != CKR_OK) {
  812.         fort11_FreeObject (certObject);
  813. return PR_FALSE;
  814.     }
  815.     if (fort11_AddAttributeType(certObject, CKA_SUBJECT, subject.data,
  816.       subject.len) != CKR_OK) {
  817.         fort11_FreeObject (certObject);
  818. return PR_FALSE;
  819.     }
  820.     if (fort11_AddAttributeType(certObject, CKA_SERIAL_NUMBER,
  821.       serial.data, serial.len) != CKR_OK) {
  822.         fort11_FreeObject(certObject);
  823. return PR_FALSE;
  824.     }
  825.     /*Change this to a byte array later*/
  826.     if (fort11_AddAttributeType(certObject, CKA_ID, 
  827. &currPerson.CertificateIndex,
  828. sizeof(int)) != CKR_OK) {
  829.         fort11_FreeObject(certObject);
  830. return PR_FALSE;
  831.     }
  832.     certObject->objectInfo = NULL;
  833.     certObject->infoFree   = NULL;
  834.     certObject->objclass = certClass;
  835.     certObject->slot  = slot;
  836.     certObject->inDB  = PR_TRUE;
  837.     FMUTEX_Lock(slot->objectLock);
  838.       
  839.     certObject->handle  = slot->tokenIDCount++;
  840.     certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
  841.     FMUTEX_Unlock(slot->objectLock);
  842.     if (fort11_FortezzaIsUserCert (currPerson.CertLabel)) {
  843.         privKeyObject = fort11_NewObject(slot);
  844.         if (fort11_NewPrivateKey(privKeyObject, slot, currPerson) != CKR_OK) {
  845.     fort11_FreeObject(privKeyObject);
  846.     fort11_FreeObject(certObject);
  847.     return PR_FALSE;
  848. }
  849. if(fort11_AddAttributeType(privKeyObject,CKA_ID,
  850.  &currPerson.CertificateIndex,
  851.  sizeof(int)) != CKR_OK) {
  852.     fort11_FreeObject(privKeyObject);
  853.     fort11_FreeObject(certObject);
  854.     return PR_FALSE;
  855. }     
  856. attribute = fort11_FindAttribute(certObject,CKA_SUBJECT);
  857. newAttribute=
  858.   fort11_NewAttribute(pk11_attr_expand(&attribute->attrib));
  859. fort11_FreeAttribute(attribute);
  860. if (newAttribute != NULL) {
  861.     fort11_DeleteAttributeType(privKeyObject,
  862.      CKA_SUBJECT);
  863.     fort11_AddAttribute(privKeyObject,
  864.       newAttribute);
  865. }
  866. fort11_AddObject (session, privKeyObject);
  867.     }
  868.     fort11_AddObject (session, certObject);
  869.     
  870.     return PR_TRUE;
  871. }
  872. #define TRUSTED_PAA "00000000Trusted Root PAA"
  873. static int
  874. fort11_BuildCertObjects(FortezzaSocket *currSocket, PK11Slot *slot, 
  875.        PK11Session *session) {
  876.        
  877.     int i;
  878.     CI_PERSON rootPAA;
  879.     PORT_Memcpy (rootPAA.CertLabel, TRUSTED_PAA, 1+PORT_Strlen (TRUSTED_PAA));
  880.     rootPAA.CertificateIndex = 0;
  881.     if (!fort11_LoadCertObjectForSearch(rootPAA, slot, session, 
  882.  currSocket->personalityList)) {
  883.         return CKR_GENERAL_ERROR;
  884.     }
  885.     if (fort11_LoadRootPAAKey(slot, session) != CKR_OK) {
  886.         return CKR_GENERAL_ERROR;
  887.     }
  888.     for (i=0 ; i < currSocket->numPersonalities; i++) {
  889.         if (fort11_FortezzaIsACert (currSocket->personalityList[i].CertLabel)){
  890.     if (!fort11_LoadCertObjectForSearch(currSocket->personalityList[i],
  891. slot, session, 
  892. currSocket->personalityList)){
  893.         return CKR_GENERAL_ERROR;
  894. }
  895.       }
  896.     }
  897.     return CKR_OK;
  898. }
  899. PK11Slot*
  900. fort11_SlotFromSessionHandle(CK_SESSION_HANDLE inHandle) {
  901.  CK_SESSION_HANDLE whichSlot = inHandle & SLOT_MASK;
  902.  if (whichSlot >= kNumSockets) return NULL_PTR;
  903.  return &fort11_slot[whichSlot];
  904. }
  905. PK11Slot* 
  906. fort11_SlotFromID (CK_SLOT_ID inSlotID) {
  907.   if (inSlotID == 0 || inSlotID > kNumSockets)
  908.     return NULL;
  909.   return &fort11_slot[inSlotID-1];
  910. }
  911. CK_ULONG fort11_firstSessionID (int inSlotNum) {
  912.         return (CK_ULONG)(inSlotNum);
  913. }
  914. /*
  915.  * Utility to convert passed in PIN to a CI_PIN
  916.  */
  917. void fort11_convertToCIPin (CI_PIN ciPin,CK_CHAR_PTR pPin, CK_ULONG ulLen) {
  918.   unsigned long i;
  919.   for (i=0; i<ulLen; i++) {
  920.     ciPin[i] = pPin[i];
  921.   }
  922.   ciPin[ulLen] = '';
  923. }
  924. /*
  925.  * return true if object has attribute
  926.  */
  927. static PRBool
  928. fort11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
  929.     PK11Attribute *attribute;
  930.     FMUTEX_Lock(object->attributeLock);
  931.     pk11queue_find(attribute,type,object->head,HASH_SIZE);
  932.     FMUTEX_Unlock(object->attributeLock);
  933.     return (PRBool)(attribute != NULL);
  934. }
  935. /*
  936.  * create a new attribute with type, value, and length. Space is allocated
  937.  * to hold value.
  938.  */
  939. static PK11Attribute *
  940. fort11_NewAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len) {
  941.     PK11Attribute *attribute;
  942.     CK_RV mrv;
  943.     attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
  944.     if (attribute == NULL) return NULL;
  945.     attribute->attrib.type = type;
  946.     if (value) {
  947. attribute->attrib.pValue = (CK_VOID_PTR)PORT_Alloc(len);
  948. if (attribute->attrib.pValue == NULL) {
  949.     PORT_Free(attribute);
  950.     return NULL;
  951. }
  952. PORT_Memcpy(attribute->attrib.pValue,value,len);
  953. attribute->attrib.ulValueLen = len;
  954.     } else {
  955. attribute->attrib.pValue = NULL;
  956. attribute->attrib.ulValueLen = 0;
  957.     }
  958.     attribute->handle = type;
  959.     attribute->next = attribute->prev = NULL;
  960.     attribute->refCount = 1;
  961.     if (FMUTEX_MutexEnabled()) {
  962.         mrv = FMUTEX_Create (&attribute->refLock);
  963. if (mrv != CKR_OK) {
  964.     if (attribute->attrib.pValue) PORT_Free(attribute->attrib.pValue);
  965.     PORT_Free(attribute);
  966.     return NULL;
  967. }
  968.     } else {
  969.         attribute->refLock = NULL;
  970.     }
  971.     return attribute;
  972. }
  973. /*
  974.  * add an attribute to an object
  975.  */
  976. static
  977. void fort11_AddAttribute(PK11Object *object,PK11Attribute *attribute) {
  978.     FMUTEX_Lock (object->attributeLock);
  979.     pk11queue_add(attribute,attribute->handle,object->head,HASH_SIZE);
  980.     FMUTEX_Unlock(object->attributeLock);
  981. }
  982. static CK_RV
  983. fort11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
  984. CK_ULONG length) {
  985.     PK11Attribute *attribute;
  986.     attribute = fort11_NewAttribute(type,valPtr,length);
  987.     if (attribute == NULL) { return CKR_HOST_MEMORY; }
  988.     fort11_AddAttribute(object,attribute);
  989.     return CKR_OK;
  990. }
  991. /* Make sure a given attribute exists. If it doesn't, initialize it to
  992.  * value and len
  993.  */
  994. static CK_RV
  995. fort11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *value,
  996. unsigned int len) {
  997.     if ( !fort11_hasAttribute(object, type)) {
  998. return fort11_AddAttributeType(object,type,value,len);
  999.     }
  1000.     return CKR_OK;
  1001. }
  1002. /*
  1003.  * look up and attribute structure from a type and Object structure.
  1004.  * The returned attribute is referenced and needs to be freed when 
  1005.  * it is no longer needed.
  1006.  */
  1007. static PK11Attribute *
  1008. fort11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
  1009.     PK11Attribute *attribute;
  1010.     FMUTEX_Lock(object->attributeLock);
  1011.     pk11queue_find(attribute,type,object->head,HASH_SIZE);
  1012.     if (attribute) {
  1013. /* atomic increment would be nice here */
  1014.         FMUTEX_Lock(attribute->refLock);
  1015. attribute->refCount++;
  1016. FMUTEX_Unlock(attribute->refLock);
  1017.     }
  1018.     FMUTEX_Unlock(object->attributeLock);
  1019.     return(attribute);
  1020. }
  1021. /*
  1022.  * this is only valid for CK_BBOOL type attributes. Return the state
  1023.  * of that attribute.
  1024.  */
  1025. static PRBool
  1026. fort11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
  1027.     PK11Attribute *attribute;
  1028.     PRBool tok = PR_FALSE;
  1029.     attribute=fort11_FindAttribute(object,type);
  1030.     if (attribute == NULL) { return PR_FALSE; }
  1031.     tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
  1032.     fort11_FreeAttribute(attribute);
  1033.     return tok;
  1034. }
  1035. /*
  1036.  * add an object to a slot and session queue
  1037.  */
  1038. static
  1039. void fort11_AddSlotObject(PK11Slot *slot, PK11Object *object) {
  1040.     FMUTEX_Lock(slot->objectLock);
  1041.     pk11queue_add(object,object->handle,slot->tokObjects,HASH_SIZE);
  1042.     FMUTEX_Unlock(slot->objectLock);
  1043. }
  1044. static
  1045. void fort11_AddObject(PK11Session *session, PK11Object *object) {
  1046.     PK11Slot *slot = fort11_SlotFromSession(session);
  1047.     if (!fort11_isToken(object->handle)) {
  1048.         FMUTEX_Lock(session->objectLock);
  1049. pk11queue_add(&object->sessionList,0,session->objects,0);
  1050. FMUTEX_Unlock(session->objectLock);
  1051.     }
  1052.     fort11_AddSlotObject(slot,object);
  1053. /*
  1054.  * free all the data associated with an object. Object reference count must
  1055.  * be 'zero'.
  1056.  */
  1057. static CK_RV
  1058. fort11_DestroyObject(PK11Object *object) {
  1059.     int i;
  1060.     CK_RV crv = CKR_OK;
  1061. /*    PORT_Assert(object->refCount == 0);*/
  1062.     if (object->label) PORT_Free(object->label);
  1063.     /* clean out the attributes */
  1064.     /* since no one is referencing us, it's safe to walk the chain
  1065.      * without a lock */
  1066.     for (i=0; i < HASH_SIZE; i++) {
  1067. PK11Attribute *ap,*next;
  1068. for (ap = object->head[i]; ap != NULL; ap = next) {
  1069.     next = ap->next;
  1070.     /* paranoia */
  1071.     ap->next = ap->prev = NULL;
  1072.     fort11_FreeAttribute(ap);
  1073. }
  1074. object->head[i] = NULL;
  1075.     }
  1076.     FMUTEX_Destroy(object->attributeLock);
  1077.     FMUTEX_Destroy(object->refLock);
  1078.     if (object->objectInfo) {
  1079. (*object->infoFree)(object->objectInfo);
  1080.     }
  1081.     PORT_Free(object);
  1082.     return crv;
  1083. }
  1084. /*
  1085.  * release a reference to an attribute structure
  1086.  */
  1087. static void
  1088. fort11_FreeAttribute(PK11Attribute *attribute) {
  1089.     PRBool destroy = PR_FALSE;
  1090.     FMUTEX_Lock(attribute->refLock);
  1091.     if (attribute->refCount == 1) destroy = PR_TRUE;
  1092.     attribute->refCount--;
  1093.     FMUTEX_Unlock(attribute->refLock);
  1094.     if (destroy) fort11_DestroyAttribute(attribute);
  1095. }
  1096. /*
  1097.  * release a reference to an object handle
  1098.  */
  1099. static PK11FreeStatus
  1100. fort11_FreeObject(PK11Object *object) {
  1101.     PRBool destroy = PR_FALSE;
  1102.     CK_RV crv;
  1103.     FMUTEX_Lock(object->refLock);
  1104.     if (object->refCount == 1) destroy = PR_TRUE;
  1105.     object->refCount--;
  1106.     FMUTEX_Unlock(object->refLock);
  1107.       
  1108.     if (destroy) {
  1109.       crv = fort11_DestroyObject(object);
  1110.       if (crv != CKR_OK) {
  1111. return PK11_DestroyFailure;
  1112.       } 
  1113.       return PK11_Destroyed;
  1114.     }
  1115.     return PK11_Busy;
  1116. }
  1117. static void
  1118. fort11_update_state(PK11Slot *slot,PK11Session *session) {
  1119.     if (slot->isLoggedIn) {
  1120. if (slot->ssoLoggedIn) {
  1121.          session->info.state = CKS_RW_SO_FUNCTIONS;
  1122. } else if (session->info.flags & CKF_RW_SESSION) {
  1123.          session->info.state = CKS_RW_USER_FUNCTIONS;
  1124. } else {
  1125.          session->info.state = CKS_RO_USER_FUNCTIONS;
  1126. }
  1127.     } else {
  1128. if (session->info.flags & CKF_RW_SESSION) {
  1129.          session->info.state = CKS_RW_PUBLIC_SESSION;
  1130. } else {
  1131.          session->info.state = CKS_RO_PUBLIC_SESSION;
  1132. }
  1133.     }
  1134. }
  1135. /* update the state of all the sessions on a slot */
  1136. static void
  1137. fort11_update_all_states(PK11Slot *slot) {
  1138.     int i;
  1139.     PK11Session *session;
  1140.     for (i=0; i < SESSION_HASH_SIZE; i++) {
  1141.         FMUTEX_Lock(slot->sessionLock);
  1142. for (session = slot->head[i]; session; session = session->next) {
  1143.     fort11_update_state(slot,session);
  1144. }
  1145. FMUTEX_Unlock(slot->sessionLock);
  1146.     }
  1147. }
  1148. /*
  1149.  * Create a new object
  1150.  */
  1151. static PK11Object *
  1152. fort11_NewObject(PK11Slot *slot) {
  1153.     PK11Object *object;
  1154.     CK_RV mrv;
  1155.     int i;
  1156.     object = (PK11Object*)PORT_Alloc(sizeof(PK11Object));
  1157.     if (object == NULL) return NULL;
  1158.     object->handle = 0;
  1159.     object->next = object->prev = NULL;
  1160.     object->sessionList.next = NULL;
  1161.     object->sessionList.prev = NULL;
  1162.     object->sessionList.parent = object;
  1163.     object->inDB = PR_FALSE;
  1164.     object->label = NULL;
  1165.     object->refCount = 1;
  1166.     object->session = NULL;
  1167.     object->slot = slot;
  1168.     object->objclass = 0xffff;
  1169.     if (FMUTEX_MutexEnabled()) {
  1170.         mrv = FMUTEX_Create(&object->refLock);
  1171. if (mrv != CKR_OK) {
  1172.     PORT_Free(object);
  1173.     return NULL;
  1174. }
  1175. mrv = FMUTEX_Create(&object->attributeLock);
  1176. if (mrv != CKR_OK) {
  1177.     FMUTEX_Destroy(object->refLock);
  1178.     PORT_Free(object);
  1179.     return NULL;
  1180. }
  1181.     } else {
  1182.         object->attributeLock = NULL;
  1183. object->refLock       = NULL;
  1184.     }   
  1185.     for (i=0; i < HASH_SIZE; i++) {
  1186. object->head[i] = NULL;
  1187.     }
  1188.     object->objectInfo = NULL;
  1189.     object->infoFree = NULL;
  1190.     return object;
  1191. }
  1192. /*
  1193.  * look up and object structure from a handle. OBJECT_Handles only make
  1194.  * sense in terms of a given session.  make a reference to that object
  1195.  * structure returned.
  1196.  */
  1197. static PK11Object * fort11_ObjectFromHandle(CK_OBJECT_HANDLE handle, 
  1198.     PK11Session *session) {
  1199.     PK11Object **head;
  1200.     void *lock;
  1201.     PK11Slot *slot = fort11_SlotFromSession(session);
  1202.     PK11Object *object;
  1203.     /*
  1204.      * Token objects are stored in the slot. Session objects are stored
  1205.      * with the session.
  1206.      */
  1207.     head = slot->tokObjects;
  1208.     lock = slot->objectLock;
  1209.     FMUTEX_Lock(lock);
  1210.     pk11queue_find(object,handle,head,HASH_SIZE);
  1211.     if (object) {
  1212.         FMUTEX_Lock(object->refLock);
  1213. object->refCount++;
  1214. FMUTEX_Unlock(object->refLock);
  1215.     }
  1216.     FMUTEX_Unlock(lock);
  1217.     return(object);
  1218. }
  1219. /*
  1220.  * add an object to a slot andsession queue
  1221.  */
  1222. static
  1223. void fort11_DeleteObject(PK11Session *session, PK11Object *object) {
  1224.     PK11Slot *slot;
  1225.     
  1226.     if (session == NULL) 
  1227.         return;
  1228.     slot = fort11_SlotFromSession(session);
  1229.     if (!fort11_isToken(object->handle)) {
  1230.         FMUTEX_Lock(session->objectLock);
  1231. pk11queue_delete(&object->sessionList,0,session->objects,0);
  1232. FMUTEX_Unlock(session->objectLock);
  1233.     }
  1234.     FMUTEX_Lock(slot->objectLock);
  1235.     pk11queue_delete(object,object->handle,slot->tokObjects,HASH_SIZE);
  1236.     FMUTEX_Unlock(slot->objectLock);
  1237.     fort11_FreeObject(object);
  1238. }
  1239. /*
  1240.  * ******************** Search Utilities *******************************
  1241.  */
  1242. /* add an object to a search list */
  1243. CK_RV
  1244. fort11_AddToList(PK11ObjectListElement **list,PK11Object *object) {
  1245.      PK11ObjectListElement *newelem = 
  1246. (PK11ObjectListElement *)PORT_Alloc(sizeof(PK11ObjectListElement));
  1247.      if (newelem == NULL) return CKR_HOST_MEMORY;
  1248.      newelem->next = *list;
  1249.      newelem->object = object;
  1250.      FMUTEX_Lock(object->refLock);
  1251.      object->refCount++;
  1252.      FMUTEX_Unlock(object->refLock);
  1253.     *list = newelem;
  1254.     return CKR_OK;
  1255. }
  1256. /*
  1257.  * free a single list element. Return the Next object in the list.
  1258.  */
  1259. PK11ObjectListElement *
  1260. fort11_FreeObjectListElement(PK11ObjectListElement *objectList) {
  1261.     PK11ObjectListElement *ol = objectList->next;
  1262.     fort11_FreeObject(objectList->object);
  1263.     PORT_Free(objectList);
  1264.     return ol;
  1265. }
  1266. /* free an entire object list */
  1267. void
  1268. fort11_FreeObjectList(PK11ObjectListElement *objectList) {
  1269.     PK11ObjectListElement *ol;
  1270.     for (ol= objectList; ol != NULL; ol = fort11_FreeObjectListElement(ol)) {}
  1271. }
  1272. /*
  1273.  * free a search structure
  1274.  */
  1275. void
  1276. fort11_FreeSearch(PK11SearchResults *search) {
  1277.     if (search->handles) {
  1278. PORT_Free(search->handles);
  1279.     }
  1280.     PORT_Free(search);
  1281. }
  1282. /*
  1283.  * Free up all the memory associated with an attribute. Reference count
  1284.  * must be zero to call this.
  1285.  */
  1286. static void
  1287. fort11_DestroyAttribute(PK11Attribute *attribute) {
  1288.     /*PORT_Assert(attribute->refCount == 0);*/
  1289.     FMUTEX_Destroy(attribute->refLock);
  1290.     if (attribute->attrib.pValue) {
  1291.  /* clear out the data in the attribute value... it may have been
  1292.   * sensitive data */
  1293.  PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
  1294.  PORT_Free(attribute->attrib.pValue);
  1295.     }
  1296.     PORT_Free(attribute);
  1297. }
  1298.         
  1299. /*
  1300.  * delete an attribute from an object
  1301.  */
  1302. static void
  1303. fort11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute) {
  1304.     FMUTEX_Lock(object->attributeLock);
  1305.     if (attribute->next || attribute->prev) {
  1306. pk11queue_delete(attribute,attribute->handle,
  1307. object->head,HASH_SIZE);
  1308.     }
  1309.     FMUTEX_Unlock(object->attributeLock);
  1310.     fort11_FreeAttribute(attribute);
  1311. }
  1312. /*
  1313.  * decode when a particular attribute may be modified
  1314.  *  PK11_NEVER: This attribute must be set at object creation time and
  1315.  *  can never be modified.
  1316.  * PK11_ONCOPY: This attribute may be modified only when you copy the
  1317.  *  object.
  1318.  * PK11_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
  1319.  *  FALSE to TRUE.
  1320.  * PK11_ALWAYS: This attribute can always be modified.
  1321.  * Some attributes vary their modification type based on the class of the 
  1322.  *   object.
  1323.  */
  1324. PK11ModifyType
  1325. fort11_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) {
  1326.     /* if we don't know about it, user user defined, always allow modify */
  1327.     PK11ModifyType mtype = PK11_ALWAYS; 
  1328.     switch(type) {
  1329.     /* NEVER */
  1330.     case CKA_CLASS:
  1331.     case CKA_CERTIFICATE_TYPE:
  1332.     case CKA_KEY_TYPE:
  1333.     case CKA_MODULUS:
  1334.     case CKA_MODULUS_BITS:
  1335.     case CKA_PUBLIC_EXPONENT:
  1336.     case CKA_PRIVATE_EXPONENT:
  1337.     case CKA_PRIME:
  1338.     case CKA_SUBPRIME:
  1339.     case CKA_BASE:
  1340.     case CKA_PRIME_1:
  1341.     case CKA_PRIME_2:
  1342.     case CKA_EXPONENT_1:
  1343.     case CKA_EXPONENT_2:
  1344.     case CKA_COEFFICIENT:
  1345.     case CKA_VALUE_LEN:
  1346. mtype = PK11_NEVER;
  1347. break;
  1348.     /* ONCOPY */
  1349.     case CKA_TOKEN:
  1350.     case CKA_PRIVATE:
  1351. mtype = PK11_ONCOPY;
  1352. break;
  1353.     /* SENSITIVE */
  1354.     case CKA_SENSITIVE:
  1355. mtype = PK11_SENSITIVE;
  1356. break;
  1357.     /* ALWAYS */
  1358.     case CKA_LABEL:
  1359.     case CKA_APPLICATION:
  1360.     case CKA_ID:
  1361.     case CKA_SERIAL_NUMBER:
  1362.     case CKA_START_DATE:
  1363.     case CKA_END_DATE:
  1364.     case CKA_DERIVE:
  1365.     case CKA_ENCRYPT:
  1366.     case CKA_DECRYPT:
  1367.     case CKA_SIGN:
  1368.     case CKA_VERIFY:
  1369.     case CKA_SIGN_RECOVER:
  1370.     case CKA_VERIFY_RECOVER:
  1371.     case CKA_WRAP:
  1372.     case CKA_UNWRAP:
  1373. mtype = PK11_ALWAYS;
  1374. break;
  1375.     /* DEPENDS ON CLASS */
  1376.     case CKA_VALUE:
  1377. mtype = (inClass == CKO_DATA) ? PK11_ALWAYS : PK11_NEVER;
  1378. break;
  1379.     case CKA_SUBJECT:
  1380. mtype = (inClass == CKO_CERTIFICATE) ? PK11_NEVER : PK11_ALWAYS;
  1381. break;
  1382.     default:
  1383. break;
  1384.     }
  1385.     return mtype;
  1386. }
  1387. /* decode if a particular attribute is sensitive (cannot be read
  1388.  * back to the user of if the object is set to SENSITIVE) */
  1389. PRBool
  1390. fort11_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) {
  1391.     switch(type) {
  1392.     /* ALWAYS */
  1393.     case CKA_PRIVATE_EXPONENT:
  1394.     case CKA_PRIME_1:
  1395.     case CKA_PRIME_2:
  1396.     case CKA_EXPONENT_1:
  1397.     case CKA_EXPONENT_2:
  1398.     case CKA_COEFFICIENT:
  1399. return PR_TRUE;
  1400.     /* DEPENDS ON CLASS */
  1401.     case CKA_VALUE:
  1402. /* PRIVATE and SECRET KEYS have SENSITIVE values */
  1403. return (PRBool)((inClass == CKO_PRIVATE_KEY) || 
  1404. (inClass == CKO_SECRET_KEY));
  1405.     default:
  1406. break;
  1407.     }
  1408.     return PR_FALSE;
  1409. }
  1410. static void
  1411. fort11_DeleteAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type) {
  1412.     PK11Attribute *attribute;
  1413.     attribute = fort11_FindAttribute(object, type);
  1414.     if (attribute == NULL) return ;
  1415.     fort11_DeleteAttribute(object,attribute);
  1416. }
  1417. /*
  1418.  * create a new nession. NOTE: The session handle is not set, and the
  1419.  * session is not added to the slot's session queue.
  1420.  */
  1421. static PK11Session *
  1422. fort11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, 
  1423.   CK_VOID_PTR pApplication,
  1424.   CK_FLAGS flags) {
  1425.     PK11Session *session;
  1426.     PK11Slot *slot = &fort11_slot[slotID-1];
  1427.     CK_RV mrv;
  1428.     if (slot == NULL) return NULL;
  1429.     session = (PK11Session*)PORT_Alloc(sizeof(PK11Session));
  1430.     if (session == NULL) return NULL;
  1431.     session->next = session->prev = NULL;
  1432.     session->refCount = 1;
  1433.     session->context = NULL;
  1434.     session->search = NULL;
  1435.     session->objectIDCount = 1;
  1436.     session->fortezzaContext.fortezzaKey = NULL;
  1437.     session->fortezzaContext.fortezzaSocket = NULL;
  1438.     if (FMUTEX_MutexEnabled()) {
  1439.         mrv = FMUTEX_Create(&session->refLock);
  1440. if (mrv != CKR_OK) {
  1441.     PORT_Free(session);
  1442.     return NULL;
  1443. }
  1444. mrv = FMUTEX_Create(&session->objectLock);
  1445. if (mrv != CKR_OK) {
  1446.     FMUTEX_Destroy(session->refLock);
  1447.     PORT_Free(session);
  1448.     return NULL;
  1449. }
  1450.     } else {
  1451.         session->refLock    = NULL;
  1452. session->objectLock = NULL;
  1453.     }
  1454.     session->objects[0] = NULL;
  1455.     session->slot = slot;
  1456.     session->notify = notify;
  1457.     session->appData = pApplication;
  1458.     session->info.flags = flags;
  1459.     session->info.slotID = slotID;
  1460.     fort11_update_state(slot,session);
  1461.     return session;
  1462. }
  1463. /*
  1464.  * look up a session structure from a session handle
  1465.  * generate a reference to it.
  1466.  */
  1467. PK11Session *
  1468. fort11_SessionFromHandle(CK_SESSION_HANDLE handle, PRBool isCloseSession) {
  1469.     PK11Slot *slot = fort11_SlotFromSessionHandle(handle);
  1470.     PK11Session *session;
  1471.     if (!isCloseSession && 
  1472. !SocketStateUnchanged(&fortezzaSockets[slot->slotID-1]))
  1473.         return NULL;
  1474.     FMUTEX_Lock(slot->sessionLock);
  1475.     pk11queue_find(session,handle,slot->head,SESSION_HASH_SIZE);
  1476.     if (session) session->refCount++;
  1477.     FMUTEX_Unlock(slot->sessionLock);
  1478.     return (session);
  1479. }
  1480. /* free all the data associated with a session. */
  1481. static void
  1482. fort11_DestroySession(PK11Session *session)
  1483. {
  1484.     PK11ObjectList *op,*next;
  1485. /*    PORT_Assert(session->refCount == 0);*/
  1486.     /* clean out the attributes */
  1487.     FMUTEX_Lock(session->objectLock);
  1488.     for (op = session->objects[0]; op != NULL; op = next) {
  1489.         next = op->next;
  1490.         /* paranoia */
  1491. op->next = op->prev = NULL;
  1492. fort11_DeleteObject(session,op->parent);
  1493.     }
  1494.     FMUTEX_Unlock(session->objectLock);
  1495.     FMUTEX_Destroy(session->objectLock);
  1496.     FMUTEX_Destroy(session->refLock);
  1497.     if (session->search) {
  1498. fort11_FreeSearch(session->search);
  1499.     }
  1500.     pk11queue_delete(session, session->handle, session->slot->head,
  1501.      SESSION_HASH_SIZE);
  1502.     PORT_Free(session);
  1503. }
  1504. /*
  1505.  * release a reference to a session handle
  1506.  */
  1507. void
  1508. fort11_FreeSession(PK11Session *session) {
  1509.     PRBool destroy = PR_FALSE;
  1510.     PK11Slot *slot = NULL;
  1511.     if (!session) return;  /*Quick fix to elminate crash*/
  1512.                            /*Fix in later version       */
  1513.     if (FMUTEX_MutexEnabled()) {
  1514.         slot = fort11_SlotFromSession(session);
  1515. FMUTEX_Lock(slot->sessionLock);
  1516.     }
  1517.     if (session->refCount == 1) destroy = PR_TRUE;
  1518.     session->refCount--;
  1519.     if (FMUTEX_MutexEnabled()) {
  1520.         FMUTEX_Unlock(slot->sessionLock);
  1521.     }
  1522.     if (destroy) {
  1523.       fort11_DestroySession(session);
  1524.     }
  1525. }
  1526. /* return true if the object matches the template */
  1527. PRBool
  1528. fort11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count) {
  1529.     int i;
  1530.     for (i=0; i < count; i++) {
  1531. PK11Attribute *attribute = 
  1532.     fort11_FindAttribute(object,theTemplate[i].type);
  1533. if (attribute == NULL) {
  1534.     return PR_FALSE;
  1535. }
  1536. if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
  1537.     if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
  1538. theTemplate[i].ulValueLen) == 0) {
  1539.                 fort11_FreeAttribute(attribute);
  1540. continue;
  1541.     }
  1542. }
  1543.         fort11_FreeAttribute(attribute);
  1544. return PR_FALSE;
  1545.     }
  1546.     return PR_TRUE;
  1547. }
  1548. /* search through all the objects in the queue and return the template matches
  1549.  * in the object list.
  1550.  */
  1551. CK_RV
  1552. fort11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
  1553. void *lock, CK_ATTRIBUTE_PTR theTemplate, int count) {
  1554.     int i;
  1555.     PK11Object *object;
  1556.     CK_RV rv;
  1557.     for(i=0; i < HASH_SIZE; i++) {
  1558.         /* We need to hold the lock to copy a consistant version of
  1559.          * the linked list. */
  1560.         FMUTEX_Lock(lock);
  1561. for (object = head[i]; object != NULL; object= object->next) {
  1562.     if (fort11_objectMatch(object,theTemplate,count)) {
  1563.         rv = fort11_AddToList(objectList,object);
  1564. if (rv != CKR_OK) {
  1565.     return rv;
  1566. }
  1567.     }
  1568. }
  1569. FMUTEX_Unlock(lock);
  1570.     }
  1571.     return CKR_OK;
  1572. }
  1573. static PRBool
  1574. fort11_NotAllFuncsNULL (CK_C_INITIALIZE_ARGS_PTR pArgs) {
  1575.     return (PRBool)(pArgs && pArgs->CreateMutex && pArgs->DestroyMutex &&
  1576.     pArgs->LockMutex   && pArgs->UnlockMutex);
  1577. }
  1578. static PRBool
  1579. fort11_InArgCheck(CK_C_INITIALIZE_ARGS_PTR pArgs) {
  1580.     PRBool rv;
  1581.     /* The only check for now, is to make sure that all of the
  1582.      * function pointers are either all NULL or all Non-NULL.
  1583.      * We also need to make sure the pReserved field in pArgs is
  1584.      * set to NULL.
  1585.      */
  1586.     if (pArgs == NULL) {
  1587.         return  PR_TRUE; /* If the argument is NULL, no
  1588.   * inconsistencies can exist.
  1589.   */
  1590.     }
  1591.     if (pArgs->pReserved != NULL) {
  1592.         return PR_FALSE;
  1593.     }
  1594.     if (pArgs->CreateMutex != NULL) {
  1595.         rv = (PRBool) (pArgs->DestroyMutex != NULL &&
  1596.        pArgs->LockMutex    != NULL &&
  1597.        pArgs->UnlockMutex  != NULL);
  1598.     } else { /*pArgs->CreateMutex == NULL*/
  1599.         rv = (PRBool) (pArgs->DestroyMutex == NULL &&
  1600.        pArgs->LockMutex    == NULL &&
  1601.        pArgs->UnlockMutex  == NULL);
  1602.     }
  1603.     return rv;
  1604. }
  1605. /**********************************************************************
  1606.  *
  1607.  *     Start of PKCS 11 functions 
  1608.  *
  1609.  **********************************************************************/
  1610.  
  1611.  
  1612. /**********************************************************************
  1613.  *
  1614.  * In order to get this to work on 68K, we have to do some special tricks,
  1615.  * First trick is that we need to make the module a Code Resource, and
  1616.  * all Code Resources on 68K have to have a main function.  So we 
  1617.  * define main to be a wrapper for C_GetFunctionList which will be the
  1618.  * first funnction called by any software that uses the PKCS11 module.
  1619.  *
  1620.  * The second trick is that whenever you access a global variable from
  1621.  * the Code Resource, it does funny things to the stack on 68K, so we 
  1622.  * need to call some macros that handle the stack for us.  First thing
  1623.  * you do is call EnterCodeResource() first thing in a function that 
  1624.  * accesses a global, right before you leave that function, you call 
  1625.  * ExitCodeResource.  This will take care of stack management.
  1626.  *
  1627.  * Third trick is to call __InitCode__() when we first enter the module
  1628.  * so that all of the global variables get initialized properly.
  1629.  *
  1630.  **********************************************************************/ 
  1631.  
  1632. #if defined(XP_MAC) && !defined(__POWERPC__)
  1633. #define FORT11_RETURN(exp)  {ExitCodeResource(); return (exp);}
  1634. #define FORT11_ENTER() EnterCodeResource();
  1635. #else /*XP_MAC*/
  1636. #define FORT11_RETURN(exp)  return (exp);
  1637. #define FORT11_ENTER() 
  1638. #endif /*XP_MAC*/
  1639. #define CARD_OK(rv)   if ((rv) != CI_OK) FORT11_RETURN (CKR_DEVICE_ERROR); 
  1640. #define SLOT_OK(slot) if ((slot) > kNumSockets) FORT11_RETURN (CKR_SLOT_ID_INVALID);
  1641.  
  1642. #ifdef XP_MAC 
  1643. /* This is not a 4.0 project, so I can't depend on
  1644.  * 4.0 defines, so instead I depend on CodeWarrior 
  1645.  * defines.
  1646.  */
  1647. #if __POWERPC__
  1648. #elif __CFM68K__
  1649. #else
  1650. /* To get this to work on 68K, we need to have
  1651.  * the symbol main.  So we just make it a wrapper for C_GetFunctionList.
  1652.  */
  1653. PR_PUBLIC_API(CK_RV) main(CK_FUNCTION_LIST_PTR *pFunctionList) {
  1654.     FORT11_ENTER()
  1655.     CK_RV rv;
  1656.   
  1657.     __InitCode__();
  1658.   
  1659.     rv = C_GetFunctionList(pFunctionList);
  1660.     FORT11_RETURN (rv);
  1661. }
  1662. #endif
  1663. #endif /*XP_MAC*/
  1664. /* Return the function list */
  1665. PR_PUBLIC_API(CK_RV) C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) {
  1666.     /* No need to do a FORT11_RETURN as this function will never be directly
  1667.      * called in the case where we need to do stack management.  
  1668.      * The main function will call this after taking care of stack stuff.
  1669.      */
  1670.     *pFunctionList = &fort11_funcList;
  1671.     return CKR_OK;
  1672. }
  1673. /* C_Initialize initializes the Cryptoki library. */
  1674. PR_PUBLIC_API(CK_RV) C_Initialize(CK_VOID_PTR pReserved) {
  1675.     FORT11_ENTER()
  1676.     int i,j, tempNumSockets;
  1677.     int rv = 1;
  1678.     CK_C_INITIALIZE_ARGS_PTR pArgs = (CK_C_INITIALIZE_ARGS_PTR)pReserved;
  1679.     CK_RV mrv;
  1680.     /* intialize all the slots */
  1681.     if (!init) {
  1682.       init = PR_TRUE;
  1683.       /* need to initialize locks before MACI_Initialize is called in
  1684.        * software fortezza. */
  1685.       if (pArgs) {
  1686.   if (!fort11_InArgCheck(pArgs)) {
  1687.       FORT11_RETURN (CKR_ARGUMENTS_BAD);
  1688.   }
  1689.   if (pArgs->flags & CKF_OS_LOCKING_OK){
  1690.       if (!fort11_NotAllFuncsNULL(pArgs)) {
  1691.   FORT11_RETURN (CKR_CANT_LOCK);
  1692.       }
  1693.   }
  1694.   if (fort11_NotAllFuncsNULL(pArgs)) {
  1695.       mrv = FMUTEX_Init(pArgs);
  1696.       if (mrv != CKR_OK) {
  1697.   return CKR_GENERAL_ERROR;
  1698.       }
  1699.   }
  1700.       }
  1701.       rv = MACI_Initialize (&tempNumSockets);
  1702.       kNumSockets = (CK_ULONG)tempNumSockets;
  1703.       
  1704.       CARD_OK (rv);
  1705.       for (i=0; i < (int) kNumSockets; i++) {
  1706. if (FMUTEX_MutexEnabled()) {
  1707.     mrv = FMUTEX_Create(&fort11_slot[i].sessionLock);
  1708.     if (mrv != CKR_OK) {
  1709.         FORT11_RETURN (CKR_GENERAL_ERROR);
  1710.     }
  1711.     mrv = FMUTEX_Create(&fort11_slot[i].objectLock);
  1712.     if (mrv != CKR_OK) {
  1713.         FMUTEX_Destroy(fort11_slot[i].sessionLock);
  1714.         FORT11_RETURN (CKR_GENERAL_ERROR);
  1715.     }
  1716. } else {
  1717.     fort11_slot[i].sessionLock = NULL;
  1718.     fort11_slot[i].objectLock  = NULL;
  1719. }
  1720. for(j=0; j < SESSION_HASH_SIZE; j++) {
  1721.   fort11_slot[i].head[j] = NULL;
  1722. }
  1723. for(j=0; j < HASH_SIZE; j++) {
  1724.   fort11_slot[i].tokObjects[j] = NULL;
  1725. }
  1726. fort11_slot[i].password = NULL;
  1727. fort11_slot[i].hasTokens = PR_FALSE;
  1728. fort11_slot[i].sessionIDCount = fort11_firstSessionID (i);
  1729. fort11_slot[i].sessionCount = 0;
  1730. fort11_slot[i].rwSessionCount = 0;
  1731. fort11_slot[i].tokenIDCount = 1;
  1732. fort11_slot[i].needLogin = PR_TRUE;
  1733. fort11_slot[i].isLoggedIn = PR_FALSE;
  1734. fort11_slot[i].ssoLoggedIn = PR_FALSE;
  1735. fort11_slot[i].DB_loaded = PR_FALSE;
  1736. fort11_slot[i].slotID= i+1;
  1737. InitSocket(&fortezzaSockets[i], i+1);
  1738.       }
  1739.     }
  1740.     FORT11_RETURN (CKR_OK);
  1741. }
  1742. /*C_Finalize indicates that an application is done with the Cryptoki library.*/
  1743. PR_PUBLIC_API(CK_RV) C_Finalize (CK_VOID_PTR pReserved) {
  1744.     FORT11_ENTER()
  1745.     int i;
  1746.     for (i=0; i< (int) kNumSockets; i++) {
  1747.         FreeSocket(&fortezzaSockets[i]);
  1748.     }
  1749.     MACI_Terminate(fortezzaSockets[0].maciSession);
  1750.     init = PR_FALSE;
  1751.     FORT11_RETURN (CKR_OK);
  1752. }
  1753. /* C_GetInfo returns general information about Cryptoki. */
  1754. PR_PUBLIC_API(CK_RV)  C_GetInfo(CK_INFO_PTR pInfo) {
  1755.     FORT11_ENTER()
  1756.     pInfo->cryptokiVersion = fort11_funcList.version;
  1757.     PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
  1758.     pInfo->libraryVersion.major = 1;
  1759.     pInfo->libraryVersion.minor = 7;
  1760.     PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32);
  1761.     pInfo->flags = 0;
  1762.     FORT11_RETURN (CKR_OK);
  1763. }
  1764. /* C_GetSlotList obtains a list of slots in the system. */
  1765. PR_PUBLIC_API(CK_RV) C_GetSlotList(CK_BBOOL    tokenPresent,
  1766.    CK_SLOT_ID_PTR pSlotList, 
  1767.    CK_ULONG_PTR   pulCount) {
  1768.     FORT11_ENTER()
  1769.     int i;
  1770.     if (pSlotList != NULL) {
  1771.       if (*pulCount >= kNumSockets) {
  1772. for (i=0; i < (int) kNumSockets; i++) {
  1773.   pSlotList[i] = i+1; 
  1774. }
  1775.       } else {
  1776. FORT11_RETURN (CKR_BUFFER_TOO_SMALL); 
  1777.       }
  1778.     } else {
  1779.       *pulCount = kNumSockets;
  1780.     }
  1781.     FORT11_RETURN (CKR_OK);
  1782. }
  1783. /* C_GetSlotInfo obtains information about a particular slot in the system. */
  1784. PR_PUBLIC_API(CK_RV) C_GetSlotInfo(CK_SLOT_ID       slotID, 
  1785.    CK_SLOT_INFO_PTR pInfo) {
  1786.   FORT11_ENTER()
  1787.     int        rv;
  1788.     CI_CONFIG  ciConfig;
  1789.     CI_STATE   ciState;
  1790.     HSESSION   maciSession;
  1791.     char       slotDescription[65];
  1792.     FortezzaSocket *socket;
  1793.     
  1794.     SLOT_OK(slotID);
  1795.     
  1796.     socket = &fortezzaSockets[slotID-1];
  1797.     if (!socket->isOpen) {
  1798.         InitSocket(socket, slotID);
  1799.     }
  1800.     maciSession = socket->maciSession;
  1801.     rv = MACI_Select(maciSession, slotID);
  1802.     CARD_OK (rv)
  1803.     rv = MACI_GetConfiguration (maciSession, &ciConfig);
  1804.     pInfo->firmwareVersion.major = 0;
  1805.     pInfo->firmwareVersion.minor = 0;
  1806. #ifdef SWFORT
  1807.     PORT_Memcpy (pInfo->manufacturerID,"Netscape Communications Corp    ",32);
  1808.     PORT_Memcpy (slotDescription,"Netscape Software Slot #        ",32);
  1809. #define _local_BASE 24
  1810. #else
  1811.     PORT_Memcpy (pInfo->manufacturerID,"LITRONIC                        ",32);
  1812.     PORT_Memcpy (slotDescription,"Litronic MACI Slot #            ",32);
  1813. #define _local_BASE 20
  1814. #endif
  1815.     slotDescription[_local_BASE] = (char )((slotID < 10) ? slotID : 
  1816. slotID/10) + '0';
  1817.     if (slotID >= 10) slotDescription[_local_BASE+1] = 
  1818. (char)(slotID % 10) + '0';
  1819.     PORT_Memcpy (&slotDescription[32],"                                ",32);
  1820.     PORT_Memcpy (pInfo->slotDescription, slotDescription          , 64);
  1821.     if (rv == CI_OK) {
  1822.         pInfo->hardwareVersion.major = 
  1823.     (ciConfig.ManufacturerVersion & MAJOR_VERSION_MASK) >> 8;
  1824. pInfo->hardwareVersion.minor = 
  1825.     ciConfig.ManufacturerVersion & MINOR_VERSION_MASK;
  1826. pInfo->flags = CKF_TOKEN_PRESENT;
  1827.     } else {
  1828.        pInfo->hardwareVersion.major = 0;
  1829.        pInfo->hardwareVersion.minor = 0;
  1830.        pInfo->flags = 0;
  1831.     }
  1832. #ifdef SWFORT
  1833.     /* do we need to make it a removable device as well?? */
  1834.     pInfo->flags |= CKF_REMOVABLE_DEVICE;
  1835. #else
  1836.     pInfo->flags |= (CKF_REMOVABLE_DEVICE | CKF_HW_SLOT);
  1837. #endif
  1838.     
  1839.     rv = MACI_GetState(maciSession, &ciState);
  1840.  
  1841.     if (rv == CI_OK) {
  1842.         switch (ciState) {
  1843. case CI_ZEROIZE:
  1844. case CI_INTERNAL_FAILURE:
  1845.     pInfo->flags &= (~CKF_TOKEN_PRESENT);
  1846. default:
  1847.     break;
  1848. }
  1849.     } else {
  1850.         pInfo->flags &= (~CKF_TOKEN_PRESENT);
  1851.     }
  1852.     FORT11_RETURN (CKR_OK);
  1853. }
  1854. #define CKF_THREAD_SAFE 0x8000 
  1855. /* C_GetTokenInfo obtains information about a particular token
  1856.    in the system. */
  1857. PR_PUBLIC_API(CK_RV) C_GetTokenInfo(CK_SLOT_ID        slotID,
  1858.     CK_TOKEN_INFO_PTR pInfo) {
  1859. FORT11_ENTER()
  1860.     CI_STATUS cardStatus;
  1861.     CI_CONFIG ciConfig;
  1862.     PK11Slot *slot;
  1863.     int rv, i;
  1864.     char tmp[33];
  1865.     FortezzaSocket *socket;
  1866.     SLOT_OK (slotID);
  1867.     
  1868.     slot = &fort11_slot[slotID-1];
  1869.     
  1870.     socket = &fortezzaSockets[slotID-1];
  1871.     if (!socket->isOpen) {
  1872.         InitSocket(socket, slotID);
  1873.     }
  1874.     rv = MACI_Select (socket->maciSession, slotID);
  1875.     rv = MACI_GetStatus (socket->maciSession, &cardStatus);
  1876.     if (rv != CI_OK) {
  1877.         FORT11_RETURN (CKR_DEVICE_ERROR);
  1878.     }
  1879. #ifdef SWFORT
  1880.     sprintf (tmp, "Software FORTEZZA Slot #%d", slotID);
  1881. #else
  1882.     sprintf (tmp, "FORTEZZA Slot #%d", slotID);
  1883. #endif
  1884.     
  1885.     PORT_Memcpy (pInfo->label, tmp, PORT_Strlen(tmp)+1);
  1886.     for (i=0; i<8; i++) {
  1887.         int serNum;
  1888. serNum = (int)cardStatus.SerialNumber[i];
  1889. sprintf ((char*)&pInfo->serialNumber[2*i], "%.2x", serNum);
  1890.     }
  1891.     rv = MACI_GetTime (fortezzaSockets[slotID-1].maciSession, pInfo->utcTime);
  1892.     if (rv == CI_OK) {
  1893.       pInfo->flags = CKF_CLOCK_ON_TOKEN;  
  1894.     } else {
  1895.       switch (rv) {
  1896.       case CI_LIB_NOT_INIT:
  1897.       case CI_INV_POINTER:
  1898.       case CI_NO_CARD:
  1899.       case CI_NO_SOCKET:
  1900. FORT11_RETURN (CKR_DEVICE_ERROR);
  1901.       default:
  1902. pInfo->flags = 0;
  1903. break;
  1904.       }
  1905.     }
  1906.     
  1907.     rv = MACI_GetConfiguration (fortezzaSockets[slotID-1].maciSession, 
  1908. &ciConfig);
  1909.     if (rv == CI_OK) {
  1910.         PORT_Memcpy(pInfo->manufacturerID,ciConfig.ManufacturerName,
  1911.     PORT_Strlen(ciConfig.ManufacturerName));
  1912. for (i=PORT_Strlen(ciConfig.ManufacturerName); i<32; i++) {
  1913.     pInfo->manufacturerID[i] = ' ';
  1914. }
  1915. PORT_Memcpy(pInfo->model,ciConfig.ProcessorType,16);    
  1916.     }
  1917.     pInfo->ulMaxPinLen = CI_PIN_SIZE;
  1918.     pInfo->ulMinPinLen = 0;
  1919.     pInfo->ulTotalPublicMemory = 0;
  1920.     pInfo->ulFreePublicMemory  = 0;
  1921.     pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED| CKF_USER_PIN_INITIALIZED | 
  1922.                     CKF_THREAD_SAFE | CKF_WRITE_PROTECTED;
  1923.     pInfo->ulMaxSessionCount = 0; 
  1924.     pInfo->ulSessionCount = slot->sessionCount; 
  1925.     pInfo->ulMaxRwSessionCount = 0; 
  1926.     pInfo->ulRwSessionCount = slot->rwSessionCount; 
  1927.     if (rv == CI_OK) {    
  1928.         pInfo->firmwareVersion.major = 
  1929.     (ciConfig.ManufacturerSWVer & MAJOR_VERSION_MASK) >> 8; 
  1930. pInfo->firmwareVersion.minor = 
  1931.     ciConfig.ManufacturerSWVer & MINOR_VERSION_MASK;
  1932. pInfo->hardwareVersion.major = 
  1933.     (ciConfig.ManufacturerVersion & MAJOR_VERSION_MASK) >> 8;
  1934. pInfo->hardwareVersion.minor = 
  1935.     ciConfig.ManufacturerVersion & MINOR_VERSION_MASK;
  1936.     }
  1937.     FORT11_RETURN (CKR_OK);
  1938. }
  1939. /* C_GetMechanismList obtains a list of mechanism types supported by a 
  1940.    token. */
  1941. PR_PUBLIC_API(CK_RV) C_GetMechanismList(CK_SLOT_ID            slotID,
  1942. CK_MECHANISM_TYPE_PTR pMechanismList, 
  1943. CK_ULONG_PTR          pulCount) {
  1944.   FORT11_ENTER()
  1945.   CK_RV rv = CKR_OK;
  1946.   int i;
  1947.   
  1948.   SLOT_OK (slotID);
  1949.   if (pMechanismList == NULL) {
  1950.     *pulCount = mechanismCount;
  1951.   } else {
  1952.     if (*pulCount >= mechanismCount) {
  1953.       *pulCount = mechanismCount;
  1954.       for (i=0; i< (int)mechanismCount; i++) {
  1955. pMechanismList[i] = mechanisms[i].type;
  1956.       }
  1957.     } else {
  1958.       rv = CKR_BUFFER_TOO_SMALL;
  1959.     }
  1960.   }
  1961.   FORT11_RETURN (rv);
  1962. }
  1963. /* C_GetMechanismInfo obtains information about a particular mechanism 
  1964.  * possibly supported by a token. */
  1965. PR_PUBLIC_API(CK_RV) C_GetMechanismInfo(CK_SLOT_ID            slotID, 
  1966. CK_MECHANISM_TYPE     type,
  1967. CK_MECHANISM_INFO_PTR pInfo) {
  1968.   int i;
  1969.   FORT11_ENTER()
  1970.   SLOT_OK (slotID);
  1971.   for (i=0; i< (int)mechanismCount; i++) {
  1972.     if (type == mechanisms[i].type) {