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

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.  * Internal PKCS #11 functions. Should only be called by pkcs11.c
  35.  */
  36. #include "pkcs11.h"
  37. #include "pkcs11i.h"
  38. #include "key.h"
  39. #include "certdb.h"
  40. /* declare the internal pkcs11 slot structures:
  41.  *  There are threee:
  42.  * slot 0 is the generic crypto service token.
  43.  * slot 1 is the Database service token.
  44.  * slot 2 is the FIPS token (both generic and database).
  45.  */
  46. static PK11Slot pk11_slot[3];
  47. /*
  48.  * ******************** Attribute Utilities *******************************
  49.  */
  50. /*
  51.  * create a new attribute with type, value, and length. Space is allocated
  52.  * to hold value.
  53.  */
  54. static PK11Attribute *
  55. pk11_NewAttribute(PK11Object *object,
  56. CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len)
  57. {
  58.     PK11Attribute *attribute;
  59. #ifdef NO_ARENA
  60.     int index;
  61.     /* 
  62.      * NO_ARENA attempts to keep down contention on Malloc and Arena locks
  63.      * by limiting the number of these calls on high traversed paths. this
  64.      * is done for attributes by 'allocating' them from a pool already allocated
  65.      * by the parent object.
  66.      */
  67.     PK11_USE_THREADS(PR_Lock(object->attributeLock);)
  68.     index = object->nextAttr++;
  69.     PK11_USE_THREADS(PR_Unlock(object->attributeLock);)
  70.     PORT_Assert(index < MAX_OBJS_ATTRS);
  71.     if (index >= MAX_OBJS_ATTRS) return NULL;
  72.     attribute = &object->attrList[index];
  73.     attribute->attrib.type = type;
  74.     if (value) {
  75.         if (len <= ATTR_SPACE) {
  76.     attribute->attrib.pValue = attribute->space;
  77. } else {
  78.     attribute->attrib.pValue = PORT_Alloc(len);
  79. }
  80. if (attribute->attrib.pValue == NULL) {
  81.     return NULL;
  82. }
  83. PORT_Memcpy(attribute->attrib.pValue,value,len);
  84. attribute->attrib.ulValueLen = len;
  85.     } else {
  86. attribute->attrib.pValue = NULL;
  87. attribute->attrib.ulValueLen = 0;
  88.     }
  89. #else
  90. #ifdef REF_COUNT_ATTRIBUTE
  91.     attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));
  92. #else
  93.     attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute));
  94. #endif /* REF_COUNT_ATTRIBUTE */
  95.     if (attribute == NULL) return NULL;
  96.     if (value) {
  97. #ifdef REF_COUNT_ATTRIBUTE
  98. attribute->attrib.pValue = PORT_Alloc(len);
  99. #else
  100. attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len);
  101. #endif /* REF_COUNT_ATTRIBUTE */
  102. if (attribute->attrib.pValue == NULL) {
  103. #ifdef REF_COUNT_ATTRIBUTE
  104.     PORT_Free(attribute);
  105. #endif /* REF_COUNT_ATTRIBUTE */
  106.     return NULL;
  107. }
  108. PORT_Memcpy(attribute->attrib.pValue,value,len);
  109. attribute->attrib.ulValueLen = len;
  110.     } else {
  111. attribute->attrib.pValue = NULL;
  112. attribute->attrib.ulValueLen = 0;
  113.     }
  114. #endif /* NO_ARENA */
  115.     attribute->attrib.type = type;
  116.     attribute->handle = type;
  117.     attribute->next = attribute->prev = NULL;
  118. #ifdef REF_COUNT_ATTRIBUTE
  119.     attribute->refCount = 1;
  120. #ifdef PKCS11_USE_THREADS
  121.     attribute->refLock = PR_NewLock();
  122.     if (attribute->refLock == NULL) {
  123. if (attribute->attrib.pValue) PORT_Free(attribute->attrib.pValue);
  124. PORT_Free(attribute);
  125. return NULL;
  126.     }
  127. #else
  128.     attribute->refLock = NULL;
  129. #endif
  130. #endif /* REF_COUNT_ATTRIBUTE */
  131.     return attribute;
  132. }
  133. /*
  134.  * Free up all the memory associated with an attribute. Reference count
  135.  * must be zero to call this.
  136.  */
  137. static void
  138. pk11_DestroyAttribute(PK11Attribute *attribute)
  139. {
  140. #ifdef REF_COUNT_ATTRIBUTE
  141.     PORT_Assert(attribute->refCount == 0);
  142.     PK11_USE_THREADS(PR_DestroyLock(attribute->refLock);)
  143.     if (attribute->attrib.pValue) {
  144.  /* clear out the data in the attribute value... it may have been
  145.   * sensitive data */
  146.  PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
  147.  PORT_Free(attribute->attrib.pValue);
  148.     }
  149.     PORT_Free(attribute);
  150. #endif
  151. }
  152.     
  153.     
  154. /*
  155.  * look up and attribute structure from a type and Object structure.
  156.  * The returned attribute is referenced and needs to be freed when 
  157.  * it is no longer needed.
  158.  */
  159. PK11Attribute *
  160. pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  161. {
  162.     PK11Attribute *attribute;
  163.     PK11_USE_THREADS(PR_Lock(object->attributeLock);)
  164.     pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
  165. #ifdef REF_COUNT_ATTRIBUTE
  166.     if (attribute) {
  167. /* atomic increment would be nice here */
  168. PK11_USE_THREADS(PR_Lock(attribute->refLock);)
  169. attribute->refCount++;
  170. PK11_USE_THREADS(PR_Unlock(attribute->refLock);)
  171.     }
  172. #endif
  173.     PK11_USE_THREADS(PR_Unlock(object->attributeLock);)
  174.     return(attribute);
  175. }
  176. /*
  177.  * release a reference to an attribute structure
  178.  */
  179. void
  180. pk11_FreeAttribute(PK11Attribute *attribute)
  181. {
  182. #ifdef REF_COUNT_ATTRIBUTE
  183.     PRBool destroy = PR_FALSE;
  184.     PK11_USE_THREADS(PR_Lock(attribute->refLock);)
  185.     if (attribute->refCount == 1) destroy = PR_TRUE;
  186.     attribute->refCount--;
  187.     PK11_USE_THREADS(PR_Unlock(attribute->refLock);)
  188.     if (destroy) pk11_DestroyAttribute(attribute);
  189. #endif
  190. }
  191. /*
  192.  * return true if object has attribute
  193.  */
  194. PRBool
  195. pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  196. {
  197.     PK11Attribute *attribute;
  198.     PK11_USE_THREADS(PR_Lock(object->attributeLock);)
  199.     pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);
  200.     PK11_USE_THREADS(PR_Unlock(object->attributeLock);)
  201.     return (PRBool)(attribute != NULL);
  202. }
  203. /*
  204.  * add an attribute to an object
  205.  */
  206. static
  207. void pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute)
  208. {
  209.     PK11_USE_THREADS(PR_Lock(object->attributeLock);)
  210.     pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE);
  211.     PK11_USE_THREADS(PR_Unlock(object->attributeLock);)
  212. }
  213. /* 
  214.  * copy an unsigned attribute into a 'signed' SECItem. Secitem is allocated in
  215.  * the specified arena.
  216.  */
  217. CK_RV
  218. pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,
  219.                                       CK_ATTRIBUTE_TYPE type)
  220. {
  221.     int len;
  222.     PK11Attribute *attribute;
  223.     unsigned char *start;
  224.     int real_len;
  225.     attribute = pk11_FindAttribute(object, type);
  226.     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
  227.     real_len = len = attribute->attrib.ulValueLen;
  228.     if ((*((unsigned char *)attribute->attrib.pValue) & 0x80) != 0) {
  229. real_len++;
  230.     }
  231.     if (arena) {
  232. start = item->data = (unsigned char *) PORT_ArenaAlloc(arena,real_len);
  233.     } else {
  234. start = item->data = (unsigned char *) PORT_Alloc(real_len);
  235.     }
  236.     if (item->data == NULL) {
  237. pk11_FreeAttribute(attribute);
  238. return CKR_HOST_MEMORY;
  239.     }
  240.     item->len = real_len;
  241.     if (real_len != len) {
  242. *start = 0;
  243. start++;
  244.     }
  245.     PORT_Memcpy(start, attribute->attrib.pValue, len);
  246.     pk11_FreeAttribute(attribute);
  247.     return CKR_OK;
  248. }
  249. /*
  250.  * delete an attribute from an object
  251.  */
  252. static void
  253. pk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute)
  254. {
  255.     PK11_USE_THREADS(PR_Lock(object->attributeLock);)
  256.     if (pk11queue_is_queued(attribute,attribute->handle,
  257. object->head,ATTRIBUTE_HASH_SIZE)) {
  258. pk11queue_delete(attribute,attribute->handle,
  259. object->head,ATTRIBUTE_HASH_SIZE);
  260.     }
  261.     PK11_USE_THREADS(PR_Unlock(object->attributeLock);)
  262.     pk11_FreeAttribute(attribute);
  263. }
  264. /*
  265.  * this is only valid for CK_BBOOL type attributes. Return the state
  266.  * of that attribute.
  267.  */
  268. PRBool
  269. pk11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  270. {
  271.     PK11Attribute *attribute;
  272.     PRBool tok = PR_FALSE;
  273.     attribute=pk11_FindAttribute(object,type);
  274.     if (attribute == NULL) { return PR_FALSE; }
  275.     tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
  276.     pk11_FreeAttribute(attribute);
  277.     return tok;
  278. }
  279. /*
  280.  * force an attribute to null.
  281.  * this is for sensitive keys which are stored in the database, we don't
  282.  * want to keep this info around in memory in the clear.
  283.  */
  284. void
  285. pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  286. {
  287.     PK11Attribute *attribute;
  288.     attribute=pk11_FindAttribute(object,type);
  289.     if (attribute == NULL) return;
  290.     if (attribute->attrib.pValue != NULL) {
  291. PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
  292. #ifdef REF_COUNT_ATTRIBUTE
  293. PORT_Free(attribute->attrib.pValue);
  294. #endif /* REF_COUNT_ATTRIBUTE */
  295. #ifdef NO_ARENA
  296. if (attribute->attrib.pValue != attribute->space) {
  297.     PORT_Free(attribute->attrib.pValue);
  298. }
  299. #endif /* NO_ARENA */
  300. attribute->attrib.pValue = NULL;
  301. attribute->attrib.ulValueLen = 0;
  302.     }
  303.     pk11_FreeAttribute(attribute);
  304. }
  305. /*
  306.  * force an attribute to a spaecif value.
  307.  */
  308. CK_RV
  309. pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,
  310. unsigned int len)
  311. {
  312.     PK11Attribute *attribute;
  313.     void *att_val = NULL;
  314.     attribute=pk11_FindAttribute(object,type);
  315.     if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len);
  316.     if (value) {
  317. #ifdef NO_ARENA
  318.         if (len <= ATTR_SPACE) {
  319.     att_val = attribute->space;
  320. } else {
  321.     att_val = PORT_Alloc(len);
  322. }
  323. #else
  324. #ifdef REF_COUNT_ATTRIBUTE
  325. att_val = PORT_Alloc(len);
  326. #else
  327. att_val = PORT_ArenaAlloc(object->arena,len);
  328. #endif /* REF_COUNT_ATTRIBUTE */
  329. #endif /* NO_ARENA */
  330. if (att_val == NULL) {
  331.     return CKR_HOST_MEMORY;
  332. }
  333. if (attribute->attrib.pValue == att_val) {
  334.     PORT_Memset(attribute->attrib.pValue,0,
  335. attribute->attrib.ulValueLen);
  336. }
  337. PORT_Memcpy(att_val,value,len);
  338.     }
  339.     if (attribute->attrib.pValue != NULL) {
  340. if (attribute->attrib.pValue != att_val) {
  341.     PORT_Memset(attribute->attrib.pValue,0,
  342. attribute->attrib.ulValueLen);
  343. }
  344. #ifdef REF_COUNT_ATTRIBUTE
  345. PORT_Free(attribute->attrib.pValue);
  346. #endif /* REF_COUNT_ATTRIBUTE */
  347. #ifdef NO_ARENA
  348. if (attribute->attrib.pValue != attribute->space) {
  349.     PORT_Free(attribute->attrib.pValue);
  350. }
  351. #endif /* NO_ARENA */
  352. attribute->attrib.pValue = NULL;
  353. attribute->attrib.ulValueLen = 0;
  354.     }
  355.     if (att_val) {
  356. attribute->attrib.pValue = att_val;
  357. attribute->attrib.ulValueLen = len;
  358.     }
  359.     return CKR_OK;
  360. }
  361. /*
  362.  * return a null terminated string from attribute 'type'. This string
  363.  * is allocated and needs to be freed with PORT_Free() When complete.
  364.  */
  365. char *
  366. pk11_getString(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  367. {
  368.     PK11Attribute *attribute;
  369.     char *label = NULL;
  370.     attribute=pk11_FindAttribute(object,type);
  371.     if (attribute == NULL) return NULL;
  372.     if (attribute->attrib.pValue != NULL) {
  373. label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);
  374. if (label == NULL) {
  375.          pk11_FreeAttribute(attribute);
  376.     return NULL;
  377. }
  378. PORT_Memcpy(label,attribute->attrib.pValue,
  379. attribute->attrib.ulValueLen);
  380. label[attribute->attrib.ulValueLen] = 0;
  381.     }
  382.     pk11_FreeAttribute(attribute);
  383.     return label;
  384. }
  385. /*
  386.  * decode when a particular attribute may be modified
  387.  *  PK11_NEVER: This attribute must be set at object creation time and
  388.  *  can never be modified.
  389.  * PK11_ONCOPY: This attribute may be modified only when you copy the
  390.  *  object.
  391.  * PK11_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
  392.  *  CK_FALSE to CK_TRUE.
  393.  * PK11_ALWAYS: This attribute can always be modified.
  394.  * Some attributes vary their modification type based on the class of the 
  395.  *   object.
  396.  */
  397. PK11ModifyType
  398. pk11_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
  399. {
  400.     /* if we don't know about it, user user defined, always allow modify */
  401.     PK11ModifyType mtype = PK11_ALWAYS; 
  402.     switch(type) {
  403.     /* NEVER */
  404.     case CKA_CLASS:
  405.     case CKA_CERTIFICATE_TYPE:
  406.     case CKA_KEY_TYPE:
  407.     case CKA_MODULUS:
  408.     case CKA_MODULUS_BITS:
  409.     case CKA_PUBLIC_EXPONENT:
  410.     case CKA_PRIVATE_EXPONENT:
  411.     case CKA_PRIME:
  412.     case CKA_SUBPRIME:
  413.     case CKA_BASE:
  414.     case CKA_PRIME_1:
  415.     case CKA_PRIME_2:
  416.     case CKA_EXPONENT_1:
  417.     case CKA_EXPONENT_2:
  418.     case CKA_COEFFICIENT:
  419.     case CKA_VALUE_LEN:
  420.     case CKA_ALWAYS_SENSITIVE:
  421.     case CKA_NEVER_EXTRACTABLE:
  422.     case CKA_NETSCAPE_DB:
  423. mtype = PK11_NEVER;
  424. break;
  425.     /* ONCOPY */
  426.     case CKA_TOKEN:
  427.     case CKA_PRIVATE:
  428.     case CKA_MODIFIABLE:
  429. mtype = PK11_ONCOPY;
  430. break;
  431.     /* SENSITIVE */
  432.     case CKA_SENSITIVE:
  433.     case CKA_EXTRACTABLE:
  434. mtype = PK11_SENSITIVE;
  435. break;
  436.     /* ALWAYS */
  437.     case CKA_LABEL:
  438.     case CKA_APPLICATION:
  439.     case CKA_ID:
  440.     case CKA_SERIAL_NUMBER:
  441.     case CKA_START_DATE:
  442.     case CKA_END_DATE:
  443.     case CKA_DERIVE:
  444.     case CKA_ENCRYPT:
  445.     case CKA_DECRYPT:
  446.     case CKA_SIGN:
  447.     case CKA_VERIFY:
  448.     case CKA_SIGN_RECOVER:
  449.     case CKA_VERIFY_RECOVER:
  450.     case CKA_WRAP:
  451.     case CKA_UNWRAP:
  452. mtype = PK11_ALWAYS;
  453. break;
  454.     /* DEPENDS ON CLASS */
  455.     case CKA_VALUE:
  456. mtype = (inClass == CKO_DATA) ? PK11_ALWAYS : PK11_NEVER;
  457. break;
  458.     case CKA_SUBJECT:
  459. mtype = (inClass == CKO_CERTIFICATE) ? PK11_NEVER : PK11_ALWAYS;
  460. break;
  461.     default:
  462. break;
  463.     }
  464.     return mtype;
  465. }
  466. /* decode if a particular attribute is sensitive (cannot be read
  467.  * back to the user of if the object is set to SENSITIVE) */
  468. PRBool
  469. pk11_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
  470. {
  471.     switch(type) {
  472.     /* ALWAYS */
  473.     case CKA_PRIVATE_EXPONENT:
  474.     case CKA_PRIME_1:
  475.     case CKA_PRIME_2:
  476.     case CKA_EXPONENT_1:
  477.     case CKA_EXPONENT_2:
  478.     case CKA_COEFFICIENT:
  479. return PR_TRUE;
  480.     /* DEPENDS ON CLASS */
  481.     case CKA_VALUE:
  482. /* PRIVATE and SECRET KEYS have SENSITIVE values */
  483. return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY));
  484.     default:
  485. break;
  486.     }
  487.     return PR_FALSE;
  488. }
  489. /* 
  490.  * copy an attribute into a SECItem. Secitem is allocated in the specified
  491.  * arena.
  492.  */
  493. CK_RV
  494. pk11_Attribute2SecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,
  495. CK_ATTRIBUTE_TYPE type)
  496. {
  497.     int len;
  498.     PK11Attribute *attribute;
  499.     attribute = pk11_FindAttribute(object, type);
  500.     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
  501.     len = attribute->attrib.ulValueLen;
  502.     if (arena) {
  503.      item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
  504.     } else {
  505.      item->data = (unsigned char *) PORT_Alloc(len);
  506.     }
  507.     if (item->data == NULL) {
  508. pk11_FreeAttribute(attribute);
  509. return CKR_HOST_MEMORY;
  510.     }
  511.     item->len = len;
  512.     PORT_Memcpy(item->data,attribute->attrib.pValue, len);
  513.     pk11_FreeAttribute(attribute);
  514.     return CKR_OK;
  515. }
  516. void
  517. pk11_DeleteAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type)
  518. {
  519.     PK11Attribute *attribute;
  520.     attribute = pk11_FindAttribute(object, type);
  521.     if (attribute == NULL) return ;
  522.     pk11_DeleteAttribute(object,attribute);
  523.     pk11_FreeAttribute(attribute);
  524. }
  525. CK_RV
  526. pk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,
  527. CK_ULONG length)
  528. {
  529.     PK11Attribute *attribute;
  530.     attribute = pk11_NewAttribute(object,type,valPtr,length);
  531.     if (attribute == NULL) { return CKR_HOST_MEMORY; }
  532.     pk11_AddAttribute(object,attribute);
  533.     return CKR_OK;
  534. }
  535. /*
  536.  * ******************** Object Utilities *******************************
  537.  */
  538. /* allocation hooks that allow us to recycle old object structures */
  539. #ifdef MAX_OBJECT_LIST_SIZE
  540. static PK11Object * objectFreeList = NULL;
  541. static PRLock *objectLock = NULL;
  542. static int object_count = 0;
  543. #endif
  544. PK11Object *
  545. pk11_GetObjectFromList(PRBool *hasLocks) {
  546.     PK11Object *object;
  547. #if MAX_OBJECT_LIST_SIZE
  548.     if (objectLock == NULL) {
  549. objectLock = PR_NewLock();
  550.     }
  551.     PK11_USE_THREADS(PR_Lock(objectLock));
  552.     object = objectFreeList;
  553.     if (object) {
  554. objectFreeList = object->next;
  555. object_count--;
  556.     }    
  557.     PK11_USE_THREADS(PR_Unlock(objectLock));
  558.     if (object) {
  559. object->next = object->prev = NULL;
  560.         *hasLocks = PR_TRUE;
  561. return object;
  562.     }
  563. #endif
  564.     object  = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object));
  565.     *hasLocks = PR_FALSE;
  566.     return object;
  567. }
  568. static void
  569. pk11_PutObjectToList(PK11Object *object) {
  570. #ifdef MAX_OBJECT_LIST_SIZE
  571.     if (object_count < MAX_OBJECT_LIST_SIZE) {
  572. PK11_USE_THREADS(PR_Lock(objectLock));
  573. object->next = objectFreeList;
  574. objectFreeList = object;
  575. object_count++;
  576. PK11_USE_THREADS(PR_Unlock(objectLock));
  577. return;
  578.      }
  579. #endif
  580.     PK11_USE_THREADS(PR_DestroyLock(object->attributeLock);)
  581.     PK11_USE_THREADS(PR_DestroyLock(object->refLock);)
  582.     object->attributeLock = object->refLock = NULL;
  583.     PORT_Free(object);
  584. }
  585. /*
  586.  * Create a new object
  587.  */
  588. PK11Object *
  589. pk11_NewObject(PK11Slot *slot)
  590. {
  591.     PK11Object *object;
  592.     PLArenaPool *arena;
  593.     PRBool hasLocks = PR_FALSE;
  594.     int i;
  595. #ifdef NO_ARENA
  596.     object = pk11_GetObjectFromList(&hasLocks);
  597.     if (object == NULL) {
  598. return NULL;
  599.     }
  600.     object->nextAttr = 0;
  601. #else
  602.     arena = PORT_NewArena(2048);
  603.     if (arena == NULL) return NULL;
  604.     object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object));
  605.     if (object == NULL) {
  606. PORT_FreeArena(arena,PR_FALSE);
  607. return NULL;
  608.     }
  609.     object->arena = arena;
  610.     for (i=0; i < MAX_OBJS_ATTRS; i++) {
  611. object->attrList[i].attrib.pValue = NULL;
  612.     }
  613. #endif
  614.     object->handle = 0;
  615.     object->next = object->prev = NULL;
  616.     object->sessionList.next = NULL;
  617.     object->sessionList.prev = NULL;
  618.     object->sessionList.parent = object;
  619.     object->inDB = PR_FALSE;
  620.     object->label = NULL;
  621.     object->refCount = 1;
  622.     object->session = NULL;
  623.     object->slot = slot;
  624.     object->objclass = 0xffff;
  625.     object->wasDerived = PR_FALSE;
  626. #ifdef PKCS11_USE_THREADS
  627.     if (!hasLocks) object->refLock = PR_NewLock();
  628.     if (object->refLock == NULL) {
  629. #ifdef NO_ARENA
  630. PORT_Free(object);
  631. #else
  632. PORT_FreeArena(arena,PR_FALSE);
  633. #endif
  634. return NULL;
  635.     }
  636.     if (!hasLocks) object->attributeLock = PR_NewLock();
  637.     if (object->attributeLock == NULL) {
  638. PK11_USE_THREADS(PR_DestroyLock(object->refLock);)
  639. #ifdef NO_ARENA
  640. PORT_Free(object);
  641. #else
  642. PORT_FreeArena(arena,PR_FALSE);
  643. #endif
  644. return NULL;
  645.     }
  646. #else
  647.     object->attributeLock = NULL;
  648.     object->refLock = NULL;
  649. #endif
  650.     for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
  651. object->head[i] = NULL;
  652.     }
  653.     object->objectInfo = NULL;
  654.     object->infoFree = NULL;
  655.     return object;
  656. }
  657. /*
  658.  * free all the data associated with an object. Object reference count must
  659.  * be 'zero'.
  660.  */
  661. static CK_RV
  662. pk11_DestroyObject(PK11Object *object)
  663. {
  664. #if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA)
  665.     int i;
  666. #endif
  667.     SECItem pubKey;
  668.     CK_RV crv = CKR_OK;
  669.     SECStatus rv;
  670.     PLArenaPool *arena = NULL;
  671.     PORT_Assert(object->refCount == 0);
  672.     /* delete the database value */
  673.     if (object->inDB) {
  674. if (pk11_isToken(object->handle)) {
  675. /* remove the objects from the real data base */
  676.     switch (object->handle & PK11_TOKEN_TYPE_MASK) {
  677.       case PK11_TOKEN_TYPE_PRIV:
  678. /* KEYID is the public KEY for DSA and DH, and the MODULUS for
  679.  *  RSA */
  680. crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
  681. if (crv != CKR_OK) break;
  682. rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &pubKey);
  683. if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
  684. break;
  685.       case PK11_TOKEN_TYPE_CERT:
  686. rv = SEC_DeletePermCertificate((CERTCertificate *)object->objectInfo);
  687. if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
  688. break;
  689.     }
  690. }
  691.     } 
  692.     if (object->label) PORT_Free(object->label);
  693.     object->inDB = PR_FALSE;
  694.     object->label = NULL;
  695. #ifdef NO_ARENA
  696.     for (i=0; i < MAX_OBJS_ATTRS; i++) {
  697. unsigned char *value = object->attrList[i].attrib.pValue;
  698. if (value) {
  699.     PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen);
  700.     if (value != object->attrList[i].space) {
  701. PORT_Free(value);
  702.     }
  703.     object->attrList[i].attrib.pValue = NULL;
  704. }
  705.     }
  706. #endif
  707. #ifdef REF_COUNT_ATTRIBUTE
  708.     /* clean out the attributes */
  709.     /* since no one is referencing us, it's safe to walk the chain
  710.      * without a lock */
  711.     for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
  712. PK11Attribute *ap,*next;
  713. for (ap = object->head[i]; ap != NULL; ap = next) {
  714.     next = ap->next;
  715.     /* paranoia */
  716.     ap->next = ap->prev = NULL;
  717.     pk11_FreeAttribute(ap);
  718. }
  719. object->head[i] = NULL;
  720.     }
  721. #endif
  722.     if (object->objectInfo) {
  723. (*object->infoFree)(object->objectInfo);
  724.     }
  725. #ifdef NO_ARENA
  726.     pk11_PutObjectToList(object);
  727. #else
  728.     PK11_USE_THREADS(PR_DestroyLock(object->attributeLock);)
  729.     PK11_USE_THREADS(PR_DestroyLock(object->refLock);)
  730.     arena = object->arena;
  731.     PORT_FreeArena(arena,PR_FALSE);
  732. #endif
  733.     return crv;
  734. }
  735. void
  736. pk11_ReferenceObject(PK11Object *object)
  737. {
  738.     PK11_USE_THREADS(PR_Lock(object->refLock);)
  739.     object->refCount++;
  740.     PK11_USE_THREADS(PR_Unlock(object->refLock);)
  741. }
  742. static PK11Object *
  743. pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot)
  744. {
  745.     PK11Object **head;
  746.     PRLock *lock;
  747.     PK11Object *object;
  748.     head = slot->tokObjects;
  749.     lock = slot->objectLock;
  750.     PK11_USE_THREADS(PR_Lock(lock);)
  751.     pk11queue_find(object,handle,head,TOKEN_OBJECT_HASH_SIZE);
  752.     if (object) {
  753. pk11_ReferenceObject(object);
  754.     }
  755.     PK11_USE_THREADS(PR_Unlock(lock);)
  756.     return(object);
  757. }
  758. /*
  759.  * look up and object structure from a handle. OBJECT_Handles only make
  760.  * sense in terms of a given session.  make a reference to that object
  761.  * structure returned.
  762.  */
  763. PK11Object *
  764. pk11_ObjectFromHandle(CK_OBJECT_HANDLE handle, PK11Session *session)
  765. {
  766.     PK11Slot *slot = pk11_SlotFromSession(session);
  767.     return pk11_ObjectFromHandleOnSlot(handle,slot);
  768. }
  769. /*
  770.  * release a reference to an object handle
  771.  */
  772. PK11FreeStatus
  773. pk11_FreeObject(PK11Object *object)
  774. {
  775.     PRBool destroy = PR_FALSE;
  776.     CK_RV crv;
  777.     PK11_USE_THREADS(PR_Lock(object->refLock);)
  778.     if (object->refCount == 1) destroy = PR_TRUE;
  779.     object->refCount--;
  780.     PK11_USE_THREADS(PR_Unlock(object->refLock);)
  781.     if (destroy) {
  782. crv = pk11_DestroyObject(object);
  783. if (crv != CKR_OK) {
  784.    return PK11_DestroyFailure;
  785. return PK11_Destroyed;
  786.     }
  787.     return PK11_Busy;
  788. }
  789.  
  790. /*
  791.  * add an object to a slot and session queue. These two functions
  792.  * adopt the object.
  793.  */
  794. void
  795. pk11_AddSlotObject(PK11Slot *slot, PK11Object *object)
  796. {
  797.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  798.     pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE);
  799.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  800. }
  801. void
  802. pk11_AddObject(PK11Session *session, PK11Object *object)
  803. {
  804.     PK11Slot *slot = pk11_SlotFromSession(session);
  805.     if (!pk11_isToken(object->handle)) {
  806. PK11_USE_THREADS(PR_Lock(session->objectLock);)
  807. pk11queue_add(&object->sessionList,0,session->objects,0);
  808. object->session = session;
  809. PK11_USE_THREADS(PR_Unlock(session->objectLock);)
  810.     }
  811.     pk11_AddSlotObject(slot,object);
  812. /*
  813.  * add an object to a slot andsession queue
  814.  */
  815. void
  816. pk11_DeleteObject(PK11Session *session, PK11Object *object)
  817. {
  818.     PK11Slot *slot = pk11_SlotFromSession(session);
  819.     if (object->session) {
  820. PK11Session *session = object->session;
  821. PK11_USE_THREADS(PR_Lock(session->objectLock);)
  822. pk11queue_delete(&object->sessionList,0,session->objects,0);
  823. PK11_USE_THREADS(PR_Unlock(session->objectLock);)
  824.     }
  825.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  826.     pk11queue_delete(object,object->handle,slot->tokObjects,
  827. TOKEN_OBJECT_HASH_SIZE);
  828.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  829.     pk11_FreeObject(object);
  830. }
  831. /*
  832.  * copy the attributes from one object to another. Don't overwrite existing
  833.  * attributes. NOTE: This is a pretty expensive operation since it
  834.  * grabs the attribute locks for the src object for a *long* time.
  835.  */
  836. CK_RV
  837. pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject)
  838. {
  839.     PK11Attribute *attribute;
  840.     int i;
  841.     PK11_USE_THREADS(PR_Lock(srcObject->attributeLock);)
  842.     for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) {
  843. attribute = srcObject->head[i];
  844. do {
  845.     if (attribute) {
  846. if (!pk11_hasAttribute(destObject,attribute->handle)) {
  847.     /* we need to copy the attribute since each attribute
  848.      * only has one set of link list pointers */
  849.     PK11Attribute *newAttribute = pk11_NewAttribute(
  850.   destObject,pk11_attr_expand(&attribute->attrib));
  851.     if (newAttribute == NULL) {
  852. PK11_USE_THREADS(PR_Unlock(srcObject->attributeLock);)
  853. return CKR_HOST_MEMORY;
  854.     }
  855.     pk11_AddAttribute(destObject,newAttribute);
  856. }
  857. attribute=attribute->next;
  858.     }
  859. } while (attribute != NULL);
  860.     }
  861.     PK11_USE_THREADS(PR_Unlock(srcObject->attributeLock);)
  862.     return CKR_OK;
  863. }
  864. /*
  865.  * ******************** Search Utilities *******************************
  866.  */
  867. /* add an object to a search list */
  868. CK_RV
  869. AddToList(PK11ObjectListElement **list,PK11Object *object)
  870. {
  871.      PK11ObjectListElement *newElem = 
  872. (PK11ObjectListElement *)PORT_Alloc(sizeof(PK11ObjectListElement));
  873.      if (newElem == NULL) return CKR_HOST_MEMORY;
  874.      newElem->next = *list;
  875.      newElem->object = object;
  876.      pk11_ReferenceObject(object);
  877.     *list = newElem;
  878.     return CKR_OK;
  879. }
  880. /* return true if the object matches the template */
  881. PRBool
  882. pk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count)
  883. {
  884.     int i;
  885.     for (i=0; i < count; i++) {
  886. PK11Attribute *attribute = pk11_FindAttribute(object,theTemplate[i].type);
  887. if (attribute == NULL) {
  888.     return PR_FALSE;
  889. }
  890. if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
  891.     if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
  892. theTemplate[i].ulValueLen) == 0) {
  893.          pk11_FreeAttribute(attribute);
  894. continue;
  895.     }
  896. }
  897.         pk11_FreeAttribute(attribute);
  898. return PR_FALSE;
  899.     }
  900.     return PR_TRUE;
  901. }
  902. /* search through all the objects in the queue and return the template matches
  903.  * in the object list.
  904.  */
  905. CK_RV
  906. pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,
  907.         PRLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn)
  908. {
  909.     int i;
  910.     PK11Object *object;
  911.     CK_RV crv = CKR_OK;
  912.     for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) {
  913.         /* We need to hold the lock to copy a consistant version of
  914.          * the linked list. */
  915.         PK11_USE_THREADS(PR_Lock(lock);)
  916. for (object = head[i]; object != NULL; object= object->next) {
  917.     if (pk11_objectMatch(object,theTemplate,count)) {
  918. /* don't return objects that aren't yet visible */
  919. if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue;
  920.         crv = AddToList(objectList,object);
  921. if (crv != CKR_OK) {
  922.     break;
  923. }
  924.     }
  925. }
  926.         PK11_USE_THREADS(PR_Unlock(lock);)
  927.     }
  928.     return crv;
  929. }
  930. /*
  931.  * free a single list element. Return the Next object in the list.
  932.  */
  933. PK11ObjectListElement *
  934. pk11_FreeObjectListElement(PK11ObjectListElement *objectList)
  935. {
  936.     PK11ObjectListElement *ol = objectList->next;
  937.     pk11_FreeObject(objectList->object);
  938.     PORT_Free(objectList);
  939.     return ol;
  940. }
  941. /* free an entire object list */
  942. void
  943. pk11_FreeObjectList(PK11ObjectListElement *objectList)
  944. {
  945.     PK11ObjectListElement *ol;
  946.     for (ol= objectList; ol != NULL; ol = pk11_FreeObjectListElement(ol)) {}
  947. }
  948. /*
  949.  * free a search structure
  950.  */
  951. void
  952. pk11_FreeSearch(PK11SearchResults *search)
  953. {
  954.     if (search->handles) {
  955. PORT_Free(search->handles);
  956.     }
  957.     PORT_Free(search);
  958. }
  959. /*
  960.  * ******************** Session Utilities *******************************
  961.  */
  962. /* update the sessions state based in it's flags and wether or not it's
  963.  * logged in */
  964. void
  965. pk11_update_state(PK11Slot *slot,PK11Session *session)
  966. {
  967.     if (slot->isLoggedIn) {
  968. if (slot->ssoLoggedIn) {
  969.          session->info.state = CKS_RW_SO_FUNCTIONS;
  970. } else if (session->info.flags & CKF_RW_SESSION) {
  971.          session->info.state = CKS_RW_USER_FUNCTIONS;
  972. } else {
  973.          session->info.state = CKS_RO_USER_FUNCTIONS;
  974. }
  975.     } else {
  976. if (session->info.flags & CKF_RW_SESSION) {
  977.          session->info.state = CKS_RW_PUBLIC_SESSION;
  978. } else {
  979.          session->info.state = CKS_RO_PUBLIC_SESSION;
  980. }
  981.     }
  982. }
  983. /* update the state of all the sessions on a slot */
  984. void
  985. pk11_update_all_states(PK11Slot *slot)
  986. {
  987.     int i;
  988.     PK11Session *session;
  989.     for (i=0; i < SESSION_HASH_SIZE; i++) {
  990. PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  991. for (session = slot->head[i]; session; session = session->next) {
  992.     pk11_update_state(slot,session);
  993. }
  994. PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  995.     }
  996. }
  997. /*
  998.  * context are cipher and digest contexts that are associated with a session
  999.  */
  1000. void
  1001. pk11_FreeContext(PK11SessionContext *context)
  1002. {
  1003.     if (context->cipherInfo) {
  1004. (*context->destroy)(context->cipherInfo,PR_TRUE);
  1005.     }
  1006.     if (context->hashInfo) {
  1007. (*context->hashdestroy)(context->hashInfo,PR_TRUE);
  1008.     }
  1009.     PORT_Free(context);
  1010. }
  1011. /* look up a slot structure from the ID (used to be a macro when we only
  1012.  * had two slots) */
  1013. PK11Slot *
  1014. pk11_SlotFromID(CK_SLOT_ID slotID)
  1015. {
  1016.     switch (slotID) {
  1017.     case NETSCAPE_SLOT_ID:
  1018. return &pk11_slot[0];
  1019.     case PRIVATE_KEY_SLOT_ID:
  1020. return &pk11_slot[1];
  1021.     case FIPS_SLOT_ID:
  1022. return &pk11_slot[2];
  1023.     default:
  1024. break; /* fall through to NULL */
  1025.     }
  1026.     return NULL;
  1027. }
  1028. PK11Slot *
  1029. pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
  1030. {
  1031.     if (handle & PK11_PRIVATE_KEY_FLAG) {
  1032. return &pk11_slot[1];
  1033.     }
  1034.     if (handle & PK11_FIPS_FLAG) {
  1035. return &pk11_slot[2];
  1036.     }
  1037.     return &pk11_slot[0];
  1038. }
  1039. /*
  1040.  * create a new nession. NOTE: The session handle is not set, and the
  1041.  * session is not added to the slot's session queue.
  1042.  */
  1043. PK11Session *
  1044. pk11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
  1045.      CK_FLAGS flags)
  1046. {
  1047.     PK11Session *session;
  1048.     PK11Slot *slot = pk11_SlotFromID(slotID);
  1049.     if (slot == NULL) return NULL;
  1050.     session = (PK11Session*)PORT_Alloc(sizeof(PK11Session));
  1051.     if (session == NULL) return NULL;
  1052.     session->next = session->prev = NULL;
  1053.     session->refCount = 1;
  1054.     session->enc_context = NULL;
  1055.     session->hash_context = NULL;
  1056.     session->sign_context = NULL;
  1057.     session->search = NULL;
  1058.     session->objectIDCount = 1;
  1059. #ifdef PKCS11_USE_THREADS
  1060.     session->refLock = PR_NewLock();
  1061.     if (session->refLock == NULL) {
  1062. PORT_Free(session);
  1063. return NULL;
  1064.     }
  1065.     session->objectLock = PR_NewLock();
  1066.     if (session->objectLock == NULL) {
  1067. PK11_USE_THREADS(PR_DestroyLock(session->refLock);)
  1068. PORT_Free(session);
  1069. return NULL;
  1070.     }
  1071. #else
  1072.     session->refLock = NULL;
  1073.     session->objectLock = NULL;
  1074. #endif
  1075.     session->objects[0] = NULL;
  1076.     session->slot = slot;
  1077.     session->notify = notify;
  1078.     session->appData = pApplication;
  1079.     session->info.flags = flags;
  1080.     session->info.slotID = slotID;
  1081.     pk11_update_state(slot,session);
  1082.     return session;
  1083. }
  1084. /* free all the data associated with a session. */
  1085. static void
  1086. pk11_DestroySession(PK11Session *session)
  1087. {
  1088.     PK11ObjectList *op,*next;
  1089.     PORT_Assert(session->refCount == 0);
  1090.     /* clean out the attributes */
  1091.     /* since no one is referencing us, it's safe to walk the chain
  1092.      * without a lock */
  1093.     for (op = session->objects[0]; op != NULL; op = next) {
  1094.         next = op->next;
  1095.         /* paranoia */
  1096. op->next = op->prev = NULL;
  1097. pk11_DeleteObject(session,op->parent);
  1098.     }
  1099.     PK11_USE_THREADS(PR_DestroyLock(session->objectLock);)
  1100.     PK11_USE_THREADS(PR_DestroyLock(session->refLock);)
  1101.     if (session->enc_context) {
  1102. pk11_FreeContext(session->enc_context);
  1103.     }
  1104.     if (session->hash_context) {
  1105. pk11_FreeContext(session->hash_context);
  1106.     }
  1107.     if (session->sign_context) {
  1108. pk11_FreeContext(session->sign_context);
  1109.     }
  1110.     if (session->search) {
  1111. pk11_FreeSearch(session->search);
  1112.     }
  1113.     PORT_Free(session);
  1114. }
  1115. /*
  1116.  * look up a session structure from a session handle
  1117.  * generate a reference to it.
  1118.  */
  1119. PK11Session *
  1120. pk11_SessionFromHandle(CK_SESSION_HANDLE handle)
  1121. {
  1122.     PK11Slot *slot = pk11_SlotFromSessionHandle(handle);
  1123.     PK11Session *session;
  1124.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  1125.     pk11queue_find(session,handle,slot->head,SESSION_HASH_SIZE);
  1126.     if (session) session->refCount++;
  1127.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  1128.     return (session);
  1129. }
  1130. /*
  1131.  * release a reference to a session handle
  1132.  */
  1133. void
  1134. pk11_FreeSession(PK11Session *session)
  1135. {
  1136.     PRBool destroy = PR_FALSE;
  1137.     PK11_USE_THREADS(PK11Slot *slot = pk11_SlotFromSession(session);)
  1138.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  1139.     if (session->refCount == 1) destroy = PR_TRUE;
  1140.     session->refCount--;
  1141.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  1142.     if (destroy) pk11_DestroySession(session);
  1143. }