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

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.  * This file implements PKCS 11 on top of our existing security modules
  35.  *
  36.  * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
  37.  *   This implementation has two slots:
  38.  * slot 1 is our generic crypto support. It does not require login.
  39.  *   It supports Public Key ops, and all they bulk ciphers and hashes. 
  40.  *   It can also support Private Key ops for imported Private keys. It does 
  41.  *   not have any token storage.
  42.  * slot 2 is our private key support. It requires a login before use. It
  43.  *   can store Private Keys and Certs as token objects. Currently only private
  44.  *   keys and their associated Certificates are saved on the token.
  45.  *
  46.  *   In this implementation, session objects are only visible to the session
  47.  *   that created or generated them.
  48.  */
  49. #include "seccomon.h"
  50. #include "secitem.h"
  51. #include "pkcs11.h"
  52. #include "pkcs11i.h"
  53. #include "softoken.h"
  54. #include "cert.h"
  55. #include "keylow.h"
  56. #include "blapi.h"
  57. #include "secder.h"
  58. #include "secport.h"
  59. #include "certdb.h"
  60. #include "private.h"
  61.  
  62. /*
  63.  * ******************** Static data *******************************
  64.  */
  65. /* The next three strings must be exactly 32 characters long */
  66. static char *manufacturerID      = "Netscape Communications Corp    ";
  67. static char *libraryDescription  = "Communicator Internal Crypto Svc";
  68. static char *tokDescription      = "Communicator Generic Crypto Svcs";
  69. static char *privTokDescription  = "Communicator Certificate DB     ";
  70. /* The next two strings must be exactly 64 characters long, with the
  71.    first 32 characters meaningful  */
  72. static char *slotDescription     = 
  73. "Communicator Internal Cryptographic Services Version 4.0        ";
  74. static char *privSlotDescription = 
  75. "Communicator User Private Key and Certificate Services          ";
  76. static int minimumPinLen = 0;
  77. #define __PASTE(x,y)    x##y
  78. /*
  79.  * we renamed all our internal functions, get the correct
  80.  * definitions for them...
  81.  */ 
  82. #undef CK_PKCS11_FUNCTION_INFO
  83. #undef CK_NEED_ARG_LIST
  84. #define CK_EXTERN extern
  85. #define CK_PKCS11_FUNCTION_INFO(func) 
  86. CK_RV __PASTE(NS,func)
  87. #define CK_NEED_ARG_LIST 1
  88.  
  89. #include "pkcs11f.h"
  90.  
  91.  
  92.  
  93. /* build the crypto module table */
  94. static CK_FUNCTION_LIST pk11_funcList = {
  95.     { 1, 10 },
  96.  
  97. #undef CK_PKCS11_FUNCTION_INFO
  98. #undef CK_NEED_ARG_LIST
  99.  
  100. #define CK_PKCS11_FUNCTION_INFO(func) 
  101. __PASTE(NS,func),
  102. #include "pkcs11f.h"
  103.  
  104. };
  105.  
  106. #undef CK_PKCS11_FUNCTION_INFO
  107. #undef CK_NEED_ARG_LIST
  108.  
  109.  
  110. #undef __PASTE
  111. /* List of DES Weak Keys */ 
  112. typedef unsigned char desKey[8];
  113. static desKey  pk11_desWeakTable[] = {
  114. #ifdef noParity
  115.     /* weak */
  116.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
  117.     { 0x1e, 0x1e, 0x1e, 0x1e, 0x0e, 0x0e, 0x0e, 0x0e },
  118.     { 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0 },
  119.     { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
  120.     /* semi-weak */
  121.     { 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe },
  122.     { 0xfe, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0xfe },
  123.     { 0x1e, 0xe0, 0x1e, 0xe0, 0x0e, 0xf0, 0x0e, 0xf0 },
  124.     { 0xe0, 0x1e, 0xe0, 0x1e, 0xf0, 0x0e, 0xf0, 0x0e },
  125.     { 0x00, 0xe0, 0x00, 0xe0, 0x00, 0x0f, 0x00, 0x0f },
  126.     { 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xf0, 0x00 },
  127.     { 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
  128.     { 0xfe, 0x1e, 0xfe, 0x1e, 0xfe, 0x0e, 0xfe, 0x0e },
  129.     { 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e },
  130.     { 0x1e, 0x00, 0x1e, 0x00, 0x0e, 0x00, 0x0e, 0x00 },
  131.     { 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0, 0xfe },
  132.     { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf0, 0xfe, 0xf0 },
  133. #else
  134.     /* weak */
  135.     { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 },
  136.     { 0x1f, 0x1f, 0x1f, 0x1f, 0x0e, 0x0e, 0x0e, 0x0e },
  137.     { 0xe0, 0xe0, 0xe0, 0xe0, 0xf1, 0xf1, 0xf1, 0xf1 },
  138.     { 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe },
  139.     /* semi-weak */
  140.     { 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe },
  141.     { 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01 },
  142.     { 0x1f, 0xe0, 0x1f, 0xe0, 0x0e, 0xf1, 0x0e, 0xf1 },
  143.     { 0xe0, 0x1f, 0xe0, 0x1f, 0xf1, 0x0e, 0xf1, 0x0e },
  144.     { 0x01, 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1 },
  145.     { 0xe0, 0x01, 0xe0, 0x01, 0xf1, 0x01, 0xf1, 0x01 },
  146.     { 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e, 0xfe },
  147.     { 0xfe, 0x1f, 0xfe, 0x1f, 0xfe, 0x0e, 0xfe, 0x0e },
  148.     { 0x01, 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e },
  149.     { 0x1f, 0x01, 0x1f, 0x01, 0x0e, 0x01, 0x0e, 0x01 },
  150.     { 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1, 0xfe },
  151.     { 0xfe, 0xe0, 0xfe, 0xe0, 0xfe, 0xf1, 0xfe, 0xf1 }
  152. #endif
  153. };
  154.     
  155. static int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/
  156. sizeof(pk11_desWeakTable[0]);
  157. /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns
  158.  * that byte with the proper parity bit set */
  159. static unsigned char parityTable[256] = {
  160. /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */
  161. /* E */   0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e,
  162. /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */
  163. /* O */   0x10,0x13,0x15,0x16,0x19,0x1a,0x1c,0x1f,
  164. /* Odd....0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e */
  165. /* O */   0x20,0x23,0x25,0x26,0x29,0x2a,0x2c,0x2f,
  166. /* Even...0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e */
  167. /* E */   0x31,0x32,0x34,0x37,0x38,0x3b,0x3d,0x3e,
  168. /* Odd....0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e */
  169. /* O */   0x40,0x43,0x45,0x46,0x49,0x4a,0x4c,0x4f,
  170. /* Even...0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e */
  171. /* E */   0x51,0x52,0x54,0x57,0x58,0x5b,0x5d,0x5e,
  172. /* Even...0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e */
  173. /* E */   0x61,0x62,0x64,0x67,0x68,0x6b,0x6d,0x6e,
  174. /* Odd....0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e */
  175. /* O */   0x70,0x73,0x75,0x76,0x79,0x7a,0x7c,0x7f,
  176. /* Odd....0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e */
  177. /* O */   0x80,0x83,0x85,0x86,0x89,0x8a,0x8c,0x8f,
  178. /* Even...0x90,0x92,0x94,0x96,0x98,0x9a,0x9c,0x9e */
  179. /* E */   0x91,0x92,0x94,0x97,0x98,0x9b,0x9d,0x9e,
  180. /* Even...0xa0,0xa2,0xa4,0xa6,0xa8,0xaa,0xac,0xae */
  181. /* E */   0xa1,0xa2,0xa4,0xa7,0xa8,0xab,0xad,0xae,
  182. /* Odd....0xb0,0xb2,0xb4,0xb6,0xb8,0xba,0xbc,0xbe */
  183. /* O */   0xb0,0xb3,0xb5,0xb6,0xb9,0xba,0xbc,0xbf,
  184. /* Even...0xc0,0xc2,0xc4,0xc6,0xc8,0xca,0xcc,0xce */
  185. /* E */   0xc1,0xc2,0xc4,0xc7,0xc8,0xcb,0xcd,0xce,
  186. /* Odd....0xd0,0xd2,0xd4,0xd6,0xd8,0xda,0xdc,0xde */
  187. /* O */   0xd0,0xd3,0xd5,0xd6,0xd9,0xda,0xdc,0xdf,
  188. /* Odd....0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xee */
  189. /* O */   0xe0,0xe3,0xe5,0xe6,0xe9,0xea,0xec,0xef,
  190. /* Even...0xf0,0xf2,0xf4,0xf6,0xf8,0xfa,0xfc,0xfe */
  191. /* E */   0xf1,0xf2,0xf4,0xf7,0xf8,0xfb,0xfd,0xfe,
  192. };
  193. /* Mechanisms */
  194. struct mechanismList {
  195.     CK_MECHANISM_TYPE type;
  196.     CK_MECHANISM_INFO domestic;
  197.     PRBool privkey;
  198. };
  199. /*
  200.  * the following table includes a complete list of mechanism defined by
  201.  * PKCS #11 version 2.01. Those Mechanisms not supported by this PKCS #11
  202.  * module are ifdef'ed out.
  203.  */
  204. #define CKF_EN_DE CKF_ENCRYPT      | CKF_DECRYPT
  205. #define CKF_WR_UN CKF_WRAP         | CKF_UNWRAP
  206. #define CKF_SN_VR CKF_SIGN         | CKF_VERIFY
  207. #define CKF_SN_RE CKF_SIGN_RECOVER | CKF_VERIFY_RECOVER
  208. #define CKF_EN_DE_WR_UN  CKF_EN_DE       | CKF_WR_UN
  209. #define CKF_SN_VR_RE CKF_SN_VR       | CKF_SN_RE
  210. #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE
  211. static struct mechanismList mechanisms[] = {
  212.      /* ------------------------- RSA Operations ---------------------------*/
  213.      {CKM_RSA_PKCS_KEY_PAIR_GEN,{128, 2048, CKF_GENERATE_KEY_PAIR}, PR_TRUE},
  214.      {CKM_RSA_PKCS, { 16,  256, CKF_DUZ_IT_ALL}, PR_TRUE},
  215. #ifdef PK11_RSA9796_SUPPORTED
  216.      {CKM_RSA_9796, { 16,  256, CKF_DUZ_IT_ALL}, PR_TRUE}, 
  217. #endif
  218.      {CKM_RSA_X_509, { 16,  256, CKF_DUZ_IT_ALL}, PR_TRUE}, 
  219.      /* -------------- RSA Multipart Signing Operations -------------------- */
  220.      {CKM_MD2_RSA_PKCS, {16, 256, CKF_SN_VR},  PR_TRUE},
  221.      {CKM_MD5_RSA_PKCS, {16, 256, CKF_SN_VR},  PR_TRUE},
  222.      {CKM_SHA1_RSA_PKCS, {16, 256, CKF_SN_VR},  PR_TRUE},
  223.      /* ------------------------- DSA Operations --------------------------- */
  224.      {CKM_DSA_KEY_PAIR_GEN, {64, 128, CKF_GENERATE_KEY_PAIR}, PR_TRUE},
  225.      {CKM_DSA, {64, 128, CKF_SN_VR},  PR_TRUE},
  226.      {CKM_DSA_SHA1, {64, 128, CKF_SN_VR},  PR_TRUE},
  227.      /* -------------------- Diffie Hellman Operations --------------------- */
  228.      /* no diffie hellman yet */
  229.      {CKM_DH_PKCS_KEY_PAIR_GEN, {16, 128, CKF_GENERATE_KEY_PAIR}, PR_TRUE}, 
  230.      {CKM_DH_PKCS_DERIVE, {16, 128, CKF_DERIVE},  PR_TRUE}, 
  231.      /* ------------------------- RC2 Operations --------------------------- */
  232.      {CKM_RC2_KEY_GEN, {1, 128, CKF_GENERATE}, PR_FALSE},
  233.      {CKM_RC2_ECB, {1, 128, CKF_EN_DE_WR_UN}, PR_FALSE},
  234.      {CKM_RC2_CBC, {1, 128, CKF_EN_DE_WR_UN}, PR_FALSE},
  235.      {CKM_RC2_MAC, {1, 128, CKF_SN_VR}, PR_FALSE},
  236.      {CKM_RC2_MAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE},
  237.      {CKM_RC2_CBC_PAD, {1, 128, CKF_EN_DE_WR_UN}, PR_FALSE},
  238.      /* ------------------------- RC4 Operations --------------------------- */
  239.      {CKM_RC4_KEY_GEN, {1, 256, CKF_GENERATE}, PR_FALSE},
  240.      {CKM_RC4, {1, 256, CKF_EN_DE_WR_UN}, PR_FALSE},
  241.      /* ------------------------- DES Operations --------------------------- */
  242.      {CKM_DES_KEY_GEN, { 8,  8, CKF_GENERATE}, PR_FALSE},
  243.      {CKM_DES_ECB, { 8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  244.      {CKM_DES_CBC, { 8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  245.      {CKM_DES_MAC, { 8,  8, CKF_SN_VR}, PR_FALSE},
  246.      {CKM_DES_MAC_GENERAL, { 8,  8, CKF_SN_VR}, PR_FALSE},
  247.      {CKM_DES_CBC_PAD, { 8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  248.      {CKM_DES2_KEY_GEN, {24, 24, CKF_GENERATE}, PR_FALSE},
  249.      {CKM_DES3_KEY_GEN, {24, 24, CKF_GENERATE}, PR_TRUE },
  250.      {CKM_DES3_ECB, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
  251.      {CKM_DES3_CBC, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
  252.      {CKM_DES3_MAC, {24, 24, CKF_SN_VR}, PR_TRUE },
  253.      {CKM_DES3_MAC_GENERAL, {24, 24, CKF_SN_VR}, PR_TRUE },
  254.      {CKM_DES3_CBC_PAD, {24, 24, CKF_EN_DE_WR_UN}, PR_TRUE },
  255.      /* ------------------------- CDMF Operations --------------------------- */
  256.      {CKM_CDMF_KEY_GEN, {8,  8, CKF_GENERATE}, PR_FALSE},
  257.      {CKM_CDMF_ECB, {8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  258.      {CKM_CDMF_CBC, {8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  259.      {CKM_CDMF_MAC, {8,  8, CKF_SN_VR}, PR_FALSE},
  260.      {CKM_CDMF_MAC_GENERAL, {8,  8, CKF_SN_VR}, PR_FALSE},
  261.      {CKM_CDMF_CBC_PAD, {8,  8, CKF_EN_DE_WR_UN}, PR_FALSE},
  262.      /* ------------------------- Hashing Operations ----------------------- */
  263.      {CKM_MD2, {0,   0, CKF_DIGEST}, PR_FALSE},
  264.      {CKM_MD2_HMAC, {1, 128, CKF_SN_VR}, PR_FALSE},
  265.      {CKM_MD2_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE},
  266.      {CKM_MD5, {0,   0, CKF_DIGEST}, PR_FALSE},
  267.      {CKM_MD5_HMAC, {1, 128, CKF_SN_VR}, PR_FALSE},
  268.      {CKM_MD5_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE},
  269.      {CKM_SHA_1, {0,   0, CKF_DIGEST}, PR_FALSE},
  270.      {CKM_SHA_1_HMAC, {1, 128, CKF_SN_VR}, PR_FALSE},
  271.      {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE},
  272.      {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE},
  273.      /* ------------------------- CAST Operations --------------------------- */
  274. #ifdef PK11_CAST_SUPPORTED
  275.      /* Cast operations are not supported ( yet? ) */
  276.      {CKM_CAST_KEY_GEN, {1,  8, CKF_GENERATE}, PR_FALSE}, 
  277.      {CKM_CAST_ECB, {1,  8, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  278.      {CKM_CAST_CBC, {1,  8, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  279.      {CKM_CAST_MAC, {1,  8, CKF_SN_VR}, PR_FALSE}, 
  280.      {CKM_CAST_MAC_GENERAL, {1,  8, CKF_SN_VR}, PR_FALSE}, 
  281.      {CKM_CAST_CBC_PAD, {1,  8, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  282.      {CKM_CAST3_KEY_GEN, {1, 16, CKF_GENERATE}, PR_FALSE}, 
  283.      {CKM_CAST3_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  284.      {CKM_CAST3_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  285.      {CKM_CAST3_MAC, {1, 16, CKF_SN_VR}, PR_FALSE}, 
  286.      {CKM_CAST3_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_FALSE}, 
  287.      {CKM_CAST3_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  288.      {CKM_CAST5_KEY_GEN, {1, 16, CKF_GENERATE}, PR_FALSE}, 
  289.      {CKM_CAST5_ECB, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  290.      {CKM_CAST5_CBC, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  291.      {CKM_CAST5_MAC, {1, 16, CKF_SN_VR}, PR_FALSE}, 
  292.      {CKM_CAST5_MAC_GENERAL, {1, 16, CKF_SN_VR}, PR_FALSE}, 
  293.      {CKM_CAST5_CBC_PAD, {1, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  294. #endif
  295. #if NSS_SOFTOKEN_DOES_RC5
  296.      /* ------------------------- RC5 Operations --------------------------- */
  297.      {CKM_RC5_KEY_GEN, {1, 255, CKF_GENERATE},  PR_FALSE},
  298.      {CKM_RC5_ECB, {1, 255, CKF_EN_DE_WR_UN}, PR_FALSE},
  299.      {CKM_RC5_CBC, {1, 255, CKF_EN_DE_WR_UN}, PR_FALSE},
  300.      {CKM_RC5_MAC, {1, 255, CKF_SN_VR},   PR_FALSE},
  301.      {CKM_RC5_MAC_GENERAL, {1, 255, CKF_SN_VR},   PR_FALSE},
  302.      {CKM_RC5_CBC_PAD, {1, 255, CKF_EN_DE_WR_UN},  PR_FALSE},
  303. #endif
  304. #ifdef PK11_IDEA_SUPPORTED
  305.      /* ------------------------- IDEA Operations -------------------------- */
  306.      {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE},  PR_FALSE}, 
  307.      {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  308.      {CKM_IDEA_CBC, {16, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, 
  309.      {CKM_IDEA_MAC, {16, 16, CKF_SN_VR}, PR_FALSE}, 
  310.      {CKM_IDEA_MAC_GENERAL, {16, 16, CKF_SN_VR}, PR_FALSE}, 
  311.      {CKM_IDEA_CBC_PAD, {16, 16, CKF_EN_DE_WR_UN},  PR_FALSE}, 
  312. #endif
  313.      /* --------------------- Secret Key Operations ------------------------ */
  314.      {CKM_GENERIC_SECRET_KEY_GEN, {1, 256, CKF_GENERATE}, PR_FALSE}, 
  315.      {CKM_CONCATENATE_BASE_AND_KEY, {1, 256, CKF_GENERATE}, PR_FALSE}, 
  316.      {CKM_CONCATENATE_BASE_AND_DATA, {1, 256, CKF_GENERATE}, PR_FALSE}, 
  317.      {CKM_CONCATENATE_DATA_AND_BASE, {1, 256, CKF_GENERATE}, PR_FALSE}, 
  318.      {CKM_XOR_BASE_AND_DATA, {1, 256, CKF_GENERATE}, PR_FALSE}, 
  319.      {CKM_EXTRACT_KEY_FROM_KEY, {1, 256, CKF_DERIVE},   PR_FALSE}, 
  320.      /* ---------------------- SSL Key Derivations ------------------------- */
  321.      {CKM_SSL3_PRE_MASTER_KEY_GEN, {48, 48, CKF_GENERATE}, PR_FALSE}, 
  322.      {CKM_SSL3_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE},   PR_FALSE}, 
  323.      {CKM_SSL3_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE},   PR_FALSE}, 
  324.      {CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE},   PR_FALSE}, 
  325.      {CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE},   PR_FALSE}, 
  326.      {CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE},   PR_FALSE}, 
  327.      {CKM_MD2_KEY_DERIVATION, { 0, 16, CKF_DERIVE},   PR_FALSE}, 
  328.      {CKM_SHA1_KEY_DERIVATION, { 0, 20, CKF_DERIVE},   PR_FALSE}, 
  329.      {CKM_TLS_MASTER_KEY_DERIVE, {48, 48, CKF_DERIVE},   PR_FALSE}, 
  330.      {CKM_TLS_KEY_AND_MAC_DERIVE, {48, 48, CKF_DERIVE},   PR_FALSE}, 
  331.      /* ---------------------- PBE Key Derivations  ------------------------ */
  332.      {CKM_PBE_MD2_DES_CBC, {64, 64, CKF_DERIVE},   PR_TRUE},
  333.      {CKM_PBE_MD5_DES_CBC, {64, 64, CKF_DERIVE},   PR_TRUE},
  334.      /* ------------------ NETSCAPE PBE Key Derivations  ------------------- */
  335.      {CKM_NETSCAPE_PBE_SHA1_DES_CBC,      { 64,  64, CKF_GENERATE}, PR_TRUE},
  336.      {CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC,  {192, 192, CKF_GENERATE}, PR_TRUE},
  337.      {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {192, 192, CKF_GENERATE}, PR_TRUE},
  338.      {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC,  { 40,  40, CKF_GENERATE}, PR_TRUE},
  339.      {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, {128, 128, CKF_GENERATE}, PR_TRUE},
  340.      {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4,      { 40,  40, CKF_GENERATE}, PR_TRUE},
  341.      {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4,     {128, 128, CKF_GENERATE}, PR_TRUE},
  342.      {CKM_PBE_SHA1_DES3_EDE_CBC,      {192, 192, CKF_GENERATE}, PR_TRUE},
  343.      {CKM_PBE_SHA1_DES2_EDE_CBC,      {192, 192, CKF_GENERATE}, PR_TRUE},
  344.      {CKM_PBE_SHA1_RC2_40_CBC,      { 40,  40, CKF_GENERATE}, PR_TRUE},
  345.      {CKM_PBE_SHA1_RC2_128_CBC,      {128, 128, CKF_GENERATE}, PR_TRUE},
  346.      {CKM_PBE_SHA1_RC4_40,      { 40,  40, CKF_GENERATE}, PR_TRUE},
  347.      {CKM_PBE_SHA1_RC4_128,      {128, 128, CKF_GENERATE}, PR_TRUE},
  348. };
  349. static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]);
  350. /* load up our token database */
  351. static CK_RV pk11_importKeyDB(PK11Slot *slot);
  352. /*
  353.  * Configuration utils
  354.  */
  355. void
  356. PK11_ConfigurePKCS11(char *man, char *libdes, char *tokdes, char *ptokdes,
  357. char *slotdes, char *pslotdes, char *fslotdes, char *fpslotdes,
  358. int minPwd, int pwRequired) 
  359. {
  360.     /* make sure the internationalization was done correctly... */
  361.     if (man && (PORT_Strlen(man) == 33)) {
  362. manufacturerID = man;
  363.     }
  364.     if (libdes && (PORT_Strlen(libdes) == 33)) {
  365. libraryDescription = libdes;
  366.     }
  367.     if (tokdes && (PORT_Strlen(tokdes) == 33)) {
  368. tokDescription = tokdes;
  369.     }
  370.     if (ptokdes && (PORT_Strlen(ptokdes) == 33)) {
  371. privTokDescription = ptokdes;
  372.     }
  373.     if (slotdes && (PORT_Strlen(slotdes) == 65)) {
  374. slotDescription = slotdes;
  375.     }
  376.     if (pslotdes && (PORT_Strlen(pslotdes) == 65)) {
  377. privSlotDescription = pslotdes;
  378.     }
  379.     if (minimumPinLen <= PK11_MAX_PIN) {
  380. minimumPinLen = minPwd;
  381.     }
  382.     if ((minimumPinLen == 0) && (pwRequired) && 
  383. (minimumPinLen <= PK11_MAX_PIN)) {
  384. minimumPinLen = 1;
  385.     }
  386.     PK11_ConfigureFIPS(fslotdes,fpslotdes);
  387.     return;
  388. }
  389. /*
  390.  * ******************** Password Utilities *******************************
  391.  */
  392. /* Handle to give the password to the database. user arg should be a pointer
  393.  * to the slot. */
  394. static SECItem *pk11_givePass(void *sp,SECKEYKeyDBHandle *handle)
  395. {
  396.     PK11Slot *slot = (PK11Slot *)sp;
  397.     if (slot->password == NULL) return NULL;
  398.     return SECITEM_DupItem(slot->password);
  399. }
  400. /*
  401.  * see if the key DB password is enabled
  402.  */
  403. PRBool
  404. pk11_hasNullPassword(SECItem **pwitem)
  405. {
  406.     PRBool pwenabled;
  407.     SECKEYKeyDBHandle *keydb;
  408.     
  409.     keydb = SECKEY_GetDefaultKeyDB();
  410.     pwenabled = PR_FALSE;
  411.     *pwitem = NULL;
  412.     if (SECKEY_HasKeyDBPassword (keydb) == SECSuccess) {
  413. *pwitem = SECKEY_HashPassword("", keydb->global_salt);
  414. if ( *pwitem ) {
  415.     if (SECKEY_CheckKeyDBPassword (keydb, *pwitem) == SECSuccess) {
  416. pwenabled = PR_TRUE;
  417.     } else {
  418.      SECITEM_ZfreeItem(*pwitem, PR_TRUE);
  419. *pwitem = NULL;
  420.     }
  421. }
  422.     }
  423.     return pwenabled;
  424. }
  425. /*
  426.  * ******************** Object Creation Utilities ***************************
  427.  */
  428. /* Make sure a given attribute exists. If it doesn't, initialize it to
  429.  * value and len
  430.  */
  431. CK_RV
  432. pk11_defaultAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *value,
  433. unsigned int len)
  434. {
  435.     if ( !pk11_hasAttribute(object, type)) {
  436. return pk11_AddAttributeType(object,type,value,len);
  437.     }
  438.     return CKR_OK;
  439. }
  440. /*
  441.  * check the consistancy and initialize a Data Object 
  442.  */
  443. static CK_RV
  444. pk11_handleDataObject(PK11Session *session,PK11Object *object)
  445. {
  446.     CK_RV crv;
  447.     /* first reject private and token data objects */
  448.     if (pk11_isTrue(object,CKA_PRIVATE) || pk11_isTrue(object,CKA_TOKEN)) {
  449. return CKR_ATTRIBUTE_VALUE_INVALID;
  450.     }
  451.     /* now just verify the required date fields */
  452.     crv = pk11_defaultAttribute(object,CKA_APPLICATION,NULL,0);
  453.     if (crv != CKR_OK) return crv;
  454.     crv = pk11_defaultAttribute(object,CKA_VALUE,NULL,0);
  455.     if (crv != CKR_OK) return crv;
  456.     return CKR_OK;
  457. }
  458. /*
  459.  * check the consistancy and initialize a Certificate Object 
  460.  */
  461. static CK_RV
  462. pk11_handleCertObject(PK11Session *session,PK11Object *object)
  463. {
  464.     PK11Attribute *attribute;
  465.     CK_CERTIFICATE_TYPE type;
  466.     SECItem derCert;
  467.     char *label;
  468.     CERTCertDBHandle *handle;
  469.     CERTCertificate *cert;
  470.     CK_RV crv;
  471.     /* certificates must have a type */
  472.     if ( !pk11_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) {
  473. return CKR_TEMPLATE_INCOMPLETE;
  474.     }
  475.     /* we can't store any certs private */
  476.     if (pk11_isTrue(object,CKA_PRIVATE)) {
  477. return CKR_ATTRIBUTE_VALUE_INVALID;
  478.     }
  479.     /* We only support X.509 Certs for now */
  480.     attribute = pk11_FindAttribute(object,CKA_CERTIFICATE_TYPE);
  481.     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
  482.     type = *(CK_CERTIFICATE_TYPE *)attribute->attrib.pValue;
  483.     pk11_FreeAttribute(attribute);
  484.     if (type != CKC_X_509) {
  485. return CKR_ATTRIBUTE_VALUE_INVALID;
  486.     }
  487.     /* X.509 Certificate */
  488.     /* make sure we have a cert */
  489.     if ( !pk11_hasAttribute(object,CKA_VALUE) ) {
  490. return CKR_TEMPLATE_INCOMPLETE;
  491.     }
  492.     /* in PKCS #11, Subject is a required field */
  493.     if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) {
  494. return CKR_TEMPLATE_INCOMPLETE;
  495.     }
  496.     /*
  497.      * now parse the certificate
  498.      */
  499.     handle = CERT_GetDefaultCertDB();
  500.     /* get the nickname */
  501.     label = pk11_getString(object,CKA_LABEL);
  502.     object->label = label;
  503.     if (label == NULL) {
  504. return CKR_HOST_MEMORY;
  505.     }
  506.   
  507.     /* get the der cert */ 
  508.     attribute = pk11_FindAttribute(object,CKA_VALUE);
  509.     derCert.data = (unsigned char *)attribute->attrib.pValue;
  510.     derCert.len = attribute->attrib.ulValueLen ;
  511.     
  512.     cert = CERT_NewTempCertificate(handle, &derCert, label, PR_FALSE, PR_TRUE);
  513.     pk11_FreeAttribute(attribute);
  514.     if (cert == NULL) {
  515. return CKR_ATTRIBUTE_VALUE_INVALID;
  516.     }
  517.     /* add it to the object */
  518.     object->objectInfo = cert;
  519.     object->infoFree = (PK11Free) CERT_DestroyCertificate;
  520.     
  521.     /* now just verify the required date fields */
  522.     crv = pk11_defaultAttribute(object, CKA_ID, NULL, 0);
  523.     if (crv != CKR_OK) { return crv; }
  524.     crv = pk11_defaultAttribute(object,CKA_ISSUER,
  525. pk11_item_expand(&cert->derIssuer));
  526.     if (crv != CKR_OK) { return crv; }
  527.     crv = pk11_defaultAttribute(object,CKA_SERIAL_NUMBER,
  528. pk11_item_expand(&cert->serialNumber));
  529.     if (crv != CKR_OK) { return crv; }
  530.     if (pk11_isTrue(object,CKA_TOKEN)) {
  531. SECCertUsage *certUsage = NULL;
  532. CERTCertTrust trust = { CERTDB_USER, CERTDB_USER, CERTDB_USER };
  533. attribute = pk11_FindAttribute(object,CKA_NETSCAPE_TRUST);
  534. if(attribute) {
  535.     certUsage = (SECCertUsage*)attribute->attrib.pValue;
  536.     pk11_FreeAttribute(attribute);
  537. }
  538. /* Temporary for PKCS 12 */
  539. if(cert->nickname == NULL) {
  540.     /* use the arena so we at least don't leak memory  */
  541.     cert->nickname = (char *)PORT_ArenaAlloc(cert->arena,
  542. PORT_Strlen(label)+1);
  543.     if(cert->nickname == NULL) {
  544. return CKR_HOST_MEMORY;
  545.     }
  546.     PORT_Memcpy(cert->nickname, label, PORT_Strlen(label));
  547. }
  548. /* only add certs that have a private key */
  549. if (SECKEY_KeyForCertExists(SECKEY_GetDefaultKeyDB(),cert) 
  550. != SECSuccess) {
  551.     return CKR_ATTRIBUTE_VALUE_INVALID;
  552. }
  553. if (CERT_AddTempCertToPerm(cert, label, &trust) != SECSuccess) {
  554.     return CKR_HOST_MEMORY;
  555. }
  556. if(certUsage) {
  557.     if(CERT_ChangeCertTrustByUsage(CERT_GetDefaultCertDB(),
  558. cert, *certUsage) != SECSuccess) {
  559. return CKR_HOST_MEMORY;
  560.     }
  561. }
  562. object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
  563. object->inDB = PR_TRUE;
  564.     }
  565.     /* label has been adopted by object->label */
  566.     /*PORT_Free(label); */
  567.     return CKR_OK;
  568. }
  569. SECKEYLowPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key);
  570. /*
  571.  * check the consistancy and initialize a Public Key Object 
  572.  */
  573. static CK_RV
  574. pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
  575. {
  576.     CK_BBOOL cktrue = CK_TRUE;
  577.     CK_BBOOL encrypt = CK_TRUE;
  578.     CK_BBOOL recover = CK_TRUE;
  579.     CK_BBOOL wrap = CK_TRUE;
  580.     CK_RV crv;
  581.     switch (key_type) {
  582.     case CKK_RSA:
  583. if ( !pk11_hasAttribute(object, CKA_MODULUS)) {
  584.     return CKR_TEMPLATE_INCOMPLETE;
  585. }
  586. if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
  587.     return CKR_TEMPLATE_INCOMPLETE;
  588. }
  589. break;
  590.     case CKK_DSA:
  591. if ( !pk11_hasAttribute(object, CKA_PRIME)) {
  592.     return CKR_TEMPLATE_INCOMPLETE;
  593. }
  594. if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) {
  595.     return CKR_TEMPLATE_INCOMPLETE;
  596. }
  597. if ( !pk11_hasAttribute(object, CKA_BASE)) {
  598.     return CKR_TEMPLATE_INCOMPLETE;
  599. }
  600. if ( !pk11_hasAttribute(object, CKA_VALUE)) {
  601.     return CKR_TEMPLATE_INCOMPLETE;
  602. }
  603. encrypt = CK_FALSE;
  604. recover = CK_FALSE;
  605. wrap = CK_FALSE;
  606. break;
  607.     case CKK_DH:
  608.     default:
  609. return CKR_ATTRIBUTE_VALUE_INVALID;
  610.     }
  611.     /* make sure the required fields exist */
  612.     crv = pk11_defaultAttribute(object,CKA_SUBJECT,NULL,0);
  613.     if (crv != CKR_OK)  return crv; 
  614.     crv = pk11_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL));
  615.     if (crv != CKR_OK)  return crv; 
  616.     crv = pk11_defaultAttribute(object,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
  617.     if (crv != CKR_OK)  return crv; 
  618.     crv = pk11_defaultAttribute(object,CKA_VERIFY_RECOVER,
  619. &recover,sizeof(CK_BBOOL));
  620.     if (crv != CKR_OK)  return crv; 
  621.     crv = pk11_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL));
  622.     if (crv != CKR_OK)  return crv; 
  623.     object->objectInfo = pk11_GetPubKey(object,key_type);
  624.     object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey;
  625.     if (pk11_isTrue(object,CKA_TOKEN)) {
  626.         object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB);
  627.     }
  628.     return CKR_OK;
  629. }
  630. /* pk11_GetPubItem returns data associated with the public key.
  631.  * one only needs to free the public key. This comment is here
  632.  * because this sematic would be non-obvious otherwise. All callers
  633.  * should include this comment.
  634.  */
  635. static SECItem *
  636. pk11_GetPubItem(SECKEYPublicKey *pubKey) {
  637.     SECItem *pubItem = NULL;
  638.     /* get value to compare from the cert's public key */
  639.     switch ( pubKey->keyType ) {
  640.     case rsaKey:
  641.     pubItem = &pubKey->u.rsa.modulus;
  642.     break;
  643.     case dsaKey:
  644.     pubItem = &pubKey->u.dsa.publicValue;
  645.     break;
  646.     default:
  647.     break;
  648.     }
  649.     return pubItem;
  650. }
  651. typedef struct {
  652.     CERTCertificate *cert;
  653.     SECItem *pubKey;
  654. } find_cert_callback_arg;
  655. static SECStatus
  656. find_cert_by_pub_key(CERTCertificate *cert, SECItem *k, void *arg)
  657. {
  658.     find_cert_callback_arg *cbarg;
  659.     SECKEYPublicKey *pubKey = NULL;
  660.     SECItem *pubItem;
  661.     if((cert == NULL) || (arg == NULL)) {
  662. return SECFailure;
  663.     }
  664.     /* if this cert doesn't look like a user cert, we aren't interested */
  665.     if (!((cert->isperm) && (cert->trust) && 
  666.        (( cert->trust->sslFlags & CERTDB_USER ) ||
  667.    ( cert->trust->emailFlags & CERTDB_USER ) ||
  668.    ( cert->trust->objectSigningFlags & CERTDB_USER )) &&
  669.   ( cert->nickname != NULL ) ) ) {
  670. goto done;
  671.     }
  672.     /* get cert's public key */
  673.     pubKey = CERT_ExtractPublicKey(cert);
  674.     if ( pubKey == NULL ) {
  675. goto done;
  676.     }
  677.     /* pk11_GetPubItem returns data associated with the public key.
  678.      * one only needs to free the public key. This comment is here
  679.      * because this sematic would be non-obvious otherwise. All callers
  680.      * should include this comment.
  681.      */
  682.     pubItem = pk11_GetPubItem(pubKey);
  683.     if (pubItem == NULL) goto done;
  684.     
  685.     cbarg = (find_cert_callback_arg *)arg;
  686.     if(SECITEM_CompareItem(pubItem, cbarg->pubKey) == SECEqual) {
  687. cbarg->cert = CERT_DupCertificate(cert);
  688. return SECFailure;
  689.     }
  690. done:
  691.     if ( pubKey ) {
  692. SECKEY_DestroyPublicKey(pubKey);
  693.     }
  694.     return (SECSuccess);
  695. }
  696. static PK11Object *pk11_importCertificate(PK11Slot *slot,CERTCertificate *cert,
  697.  unsigned char *data, unsigned int size, PRBool needCert);
  698. /* 
  699.  * find a cert associated with the key and load it.
  700.  */
  701. static SECStatus
  702. reload_existing_certificate(PK11Object *privKeyObject,SECItem *pubKey)
  703. {
  704.     find_cert_callback_arg cbarg;
  705.     SECItem nickName;
  706.     CERTCertificate *cert = NULL;
  707.     CK_RV crv;
  708.     SECStatus rv;
  709.     
  710.     cbarg.pubKey = pubKey;
  711.     cbarg.cert = NULL;
  712.     SEC_TraversePermCerts(CERT_GetDefaultCertDB(),
  713.        find_cert_by_pub_key, (void *)&cbarg);
  714.     if (cbarg.cert != NULL) {
  715. CERTCertificate *cert = NULL;
  716. /* can anyone tell me why this is call is necessary? rjr */
  717. cert = CERT_FindCertByDERCert(CERT_GetDefaultCertDB(),
  718. &cbarg.cert->derCert);
  719. /* does the certificate in the database have a 
  720.  * nickname?  if not, it probably was inserted 
  721.  * through SMIME and a nickname needs to be 
  722.  * set.
  723.  */
  724. if (cert && !cert->nickname) {
  725.     crv=pk11_Attribute2SecItem(NULL,&nickName,privKeyObject,CKA_LABEL);
  726.     if (crv != CKR_OK) {
  727. goto loser;
  728.     }
  729.     rv = CERT_AddPermNickname(cert, (char *)nickName.data);
  730.     SECITEM_ZfreeItem(&nickName, PR_FALSE);
  731.     if (rv != SECSuccess) {
  732. goto loser;
  733.     }
  734. }
  735. /* associate the certificate with the key */
  736. pk11_importCertificate(privKeyObject->slot, cert, pubKey->data, 
  737. pubKey->len, PR_FALSE);
  738.     }
  739.     return SECSuccess;
  740. loser:
  741.     if (cert) CERT_DestroyCertificate(cert);
  742.     if (cbarg.cert) CERT_DestroyCertificate(cbarg.cert);
  743.     return SECFailure;
  744. }
  745. static SECKEYLowPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key);
  746. /*
  747.  * check the consistancy and initialize a Private Key Object 
  748.  */
  749. static CK_RV
  750. pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type)
  751. {
  752.     CK_BBOOL cktrue = CK_TRUE;
  753.     CK_BBOOL encrypt = CK_TRUE;
  754.     CK_BBOOL recover = CK_TRUE;
  755.     CK_BBOOL wrap = CK_TRUE;
  756.     CK_BBOOL ckfalse = CK_FALSE;
  757.     SECItem mod;
  758.     CK_RV crv;
  759.     switch (key_type) {
  760.     case CKK_RSA:
  761. if ( !pk11_hasAttribute(object, CKA_MODULUS)) {
  762.     return CKR_TEMPLATE_INCOMPLETE;
  763. }
  764. if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) {
  765.     return CKR_TEMPLATE_INCOMPLETE;
  766. }
  767. if ( !pk11_hasAttribute(object, CKA_PRIVATE_EXPONENT)) {
  768.     return CKR_TEMPLATE_INCOMPLETE;
  769. }
  770. if ( !pk11_hasAttribute(object, CKA_PRIME_1)) {
  771.     return CKR_TEMPLATE_INCOMPLETE;
  772. }
  773. if ( !pk11_hasAttribute(object, CKA_PRIME_2)) {
  774.     return CKR_TEMPLATE_INCOMPLETE;
  775. }
  776. if ( !pk11_hasAttribute(object, CKA_EXPONENT_1)) {
  777.     return CKR_TEMPLATE_INCOMPLETE;
  778. }
  779. if ( !pk11_hasAttribute(object, CKA_EXPONENT_2)) {
  780.     return CKR_TEMPLATE_INCOMPLETE;
  781. }
  782. if ( !pk11_hasAttribute(object, CKA_COEFFICIENT)) {
  783.     return CKR_TEMPLATE_INCOMPLETE;
  784. }
  785. /* make sure Netscape DB attribute is set correctly */
  786. crv = pk11_Attribute2SSecItem(NULL, &mod, object, CKA_MODULUS);
  787. if (crv != CKR_OK) return crv;
  788. crv = pk11_forceAttribute(object, CKA_NETSCAPE_DB, 
  789. pk11_item_expand(&mod));
  790. if (mod.data) PORT_Free(mod.data);
  791. if (crv != CKR_OK) return crv;
  792. break;
  793.     case CKK_DSA:
  794. if ( !pk11_hasAttribute(object, CKA_PRIME)) {
  795.     return CKR_TEMPLATE_INCOMPLETE;
  796. }
  797. if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) {
  798.     return CKR_TEMPLATE_INCOMPLETE;
  799. }
  800. if ( !pk11_hasAttribute(object, CKA_BASE)) {
  801.     return CKR_TEMPLATE_INCOMPLETE;
  802. }
  803. if ( !pk11_hasAttribute(object, CKA_VALUE)) {
  804.     return CKR_TEMPLATE_INCOMPLETE;
  805. }
  806. if ( !pk11_hasAttribute(object, CKA_NETSCAPE_DB)) {
  807.     return CKR_TEMPLATE_INCOMPLETE;
  808. }
  809. encrypt = CK_FALSE;
  810. recover = CK_FALSE;
  811. wrap = CK_FALSE;
  812. break;
  813.     case CKK_DH:
  814.     default:
  815. return CKR_ATTRIBUTE_VALUE_INVALID;
  816.     }
  817.     crv = pk11_defaultAttribute(object,CKA_SUBJECT,NULL,0);
  818.     if (crv != CKR_OK)  return crv; 
  819.     crv = pk11_defaultAttribute(object,CKA_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
  820.     if (crv != CKR_OK)  return crv; 
  821.     crv = pk11_defaultAttribute(object,CKA_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
  822.     if (crv != CKR_OK)  return crv; 
  823.     crv = pk11_defaultAttribute(object,CKA_DECRYPT,&encrypt,sizeof(CK_BBOOL));
  824.     if (crv != CKR_OK)  return crv; 
  825.     crv = pk11_defaultAttribute(object,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
  826.     if (crv != CKR_OK)  return crv; 
  827.     crv = pk11_defaultAttribute(object,CKA_SIGN_RECOVER,&recover,
  828.      sizeof(CK_BBOOL));
  829.     if (crv != CKR_OK)  return crv; 
  830.     crv = pk11_defaultAttribute(object,CKA_UNWRAP,&wrap,sizeof(CK_BBOOL));
  831.     if (crv != CKR_OK)  return crv; 
  832.     /* the next two bits get modified only in the key gen and token cases */
  833.     crv = pk11_forceAttribute(object,CKA_ALWAYS_SENSITIVE,
  834. &ckfalse,sizeof(CK_BBOOL));
  835.     if (crv != CKR_OK)  return crv; 
  836.     crv = pk11_forceAttribute(object,CKA_NEVER_EXTRACTABLE,
  837. &ckfalse,sizeof(CK_BBOOL));
  838.     if (crv != CKR_OK)  return crv; 
  839.     if (pk11_isTrue(object,CKA_TOKEN)) {
  840. SECKEYLowPrivateKey *privKey;
  841. char *label;
  842. SECStatus rv = SECSuccess;
  843. SECItem pubKey;
  844. privKey=pk11_mkPrivKey(object,key_type);
  845. if (privKey == NULL) return CKR_HOST_MEMORY;
  846. label = object->label = pk11_getString(object,CKA_LABEL);
  847. crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
  848. if (crv == CKR_OK) {
  849.     rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(),
  850. privKey, &pubKey, label,
  851. (SECKEYGetPasswordKey) pk11_givePass, object->slot);
  852.     /* check for the existance of an existing certificate and activate
  853.      * it if necessary */
  854.     if (rv == SECSuccess) {
  855.         reload_existing_certificate(object,&pubKey);
  856.     }
  857.     if (pubKey.data) PORT_Free(pubKey.data);
  858. } else {
  859.     rv = SECFailure;
  860. }
  861. SECKEY_LowDestroyPrivateKey(privKey);
  862. if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  863. object->inDB = PR_TRUE;
  864.         object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  865.     } else {
  866. object->objectInfo = pk11_mkPrivKey(object,key_type);
  867. if (object->objectInfo == NULL) return CKR_HOST_MEMORY;
  868. object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey;
  869.     }
  870.     /* now NULL out the sensitive attributes */
  871.     if (pk11_isTrue(object,CKA_SENSITIVE)) {
  872. pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT);
  873. pk11_nullAttribute(object,CKA_PRIME_1);
  874. pk11_nullAttribute(object,CKA_PRIME_2);
  875. pk11_nullAttribute(object,CKA_EXPONENT_1);
  876. pk11_nullAttribute(object,CKA_EXPONENT_2);
  877. pk11_nullAttribute(object,CKA_COEFFICIENT);
  878.     }
  879.     return CKR_OK;
  880. }
  881. /* forward delcare the DES formating function for handleSecretKey */
  882. void pk11_FormatDESKey(unsigned char *key, int length);
  883. static SECKEYLowPrivateKey *pk11_mkSecretKeyRep(PK11Object *object);
  884. /* Validate secret key data, and set defaults */
  885. static CK_RV
  886. validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS)
  887. {
  888.     CK_RV crv;
  889.     CK_BBOOL cktrue = CK_TRUE;
  890.     CK_BBOOL ckfalse = CK_FALSE;
  891.     PK11Attribute *attribute = NULL;
  892.     crv = pk11_defaultAttribute(object,CKA_SENSITIVE,
  893. isFIPS?&cktrue:&ckfalse,sizeof(CK_BBOOL));
  894.     if (crv != CKR_OK)  return crv; 
  895.     crv = pk11_defaultAttribute(object,CKA_EXTRACTABLE,
  896. &cktrue,sizeof(CK_BBOOL));
  897.     if (crv != CKR_OK)  return crv; 
  898.     crv = pk11_defaultAttribute(object,CKA_ENCRYPT,&cktrue,sizeof(CK_BBOOL));
  899.     if (crv != CKR_OK)  return crv; 
  900.     crv = pk11_defaultAttribute(object,CKA_DECRYPT,&cktrue,sizeof(CK_BBOOL));
  901.     if (crv != CKR_OK)  return crv; 
  902.     crv = pk11_defaultAttribute(object,CKA_SIGN,&ckfalse,sizeof(CK_BBOOL));
  903.     if (crv != CKR_OK)  return crv; 
  904.     crv = pk11_defaultAttribute(object,CKA_VERIFY,&ckfalse,sizeof(CK_BBOOL));
  905.     if (crv != CKR_OK)  return crv; 
  906.     crv = pk11_defaultAttribute(object,CKA_WRAP,&cktrue,sizeof(CK_BBOOL));
  907.     if (crv != CKR_OK)  return crv; 
  908.     crv = pk11_defaultAttribute(object,CKA_UNWRAP,&cktrue,sizeof(CK_BBOOL));
  909.     if (crv != CKR_OK)  return crv; 
  910.     if ( !pk11_hasAttribute(object, CKA_VALUE)) {
  911. return CKR_TEMPLATE_INCOMPLETE;
  912.     }
  913.     /* the next two bits get modified only in the key gen and token cases */
  914.     crv = pk11_forceAttribute(object,CKA_ALWAYS_SENSITIVE,
  915. &ckfalse,sizeof(CK_BBOOL));
  916.     if (crv != CKR_OK)  return crv; 
  917.     crv = pk11_forceAttribute(object,CKA_NEVER_EXTRACTABLE,
  918. &ckfalse,sizeof(CK_BBOOL));
  919.     if (crv != CKR_OK)  return crv; 
  920.     /* some types of keys have a value length */
  921.     crv = CKR_OK;
  922.     switch (key_type) {
  923.     /* force CKA_VALUE_LEN to be set */
  924.     case CKK_GENERIC_SECRET:
  925.     case CKK_RC2:
  926.     case CKK_RC4:
  927. #if NSS_SOFTOKEN_DOES_RC5
  928.     case CKK_RC5:
  929. #endif
  930.     case CKK_CAST:
  931.     case CKK_CAST3:
  932.     case CKK_CAST5:
  933. attribute = pk11_FindAttribute(object,CKA_VALUE);
  934. /* shouldn't happen */
  935. if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
  936. crv = pk11_forceAttribute(object, CKA_VALUE_LEN, 
  937. &attribute->attrib.ulValueLen, sizeof(CK_ULONG));
  938. pk11_FreeAttribute(attribute);
  939. break;
  940.     /* force the value to have the correct parity */
  941.     case CKK_DES:
  942.     case CKK_DES2:
  943.     case CKK_DES3:
  944.     case CKK_CDMF:
  945. attribute = pk11_FindAttribute(object,CKA_VALUE);
  946. /* shouldn't happen */
  947. if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
  948. pk11_FormatDESKey((unsigned char*)attribute->attrib.pValue,
  949.  attribute->attrib.ulValueLen);
  950. pk11_FreeAttribute(attribute);
  951. break;
  952.     default:
  953. break;
  954.     }
  955.     return crv;
  956. }
  957. /*
  958.  * check the consistancy and initialize a Secret Key Object 
  959.  */
  960. static CK_RV
  961. pk11_handleSecretKeyObject(PK11Object *object,CK_KEY_TYPE key_type,
  962. PRBool isFIPS)
  963. {
  964.     CK_RV crv;
  965.     CK_BBOOL cktrue = CK_TRUE;
  966.     CK_BBOOL ckfalse = CK_FALSE;
  967.     PK11Attribute *attribute = NULL;
  968.     SECKEYLowPrivateKey *privKey = NULL;
  969.     SECItem pubKey;
  970.     pubKey.data = 0;
  971.     /* First validate and set defaults */
  972.     crv = validateSecretKey(object, key_type, isFIPS);
  973.     if (crv != CKR_OK) goto loser;
  974.     /* If the object is a TOKEN object, store in the database */
  975.     if (pk11_isTrue(object,CKA_TOKEN)) {
  976. char *label;
  977. SECStatus rv = SECSuccess;
  978. privKey=pk11_mkSecretKeyRep(object);
  979. if (privKey == NULL) return CKR_HOST_MEMORY;
  980. label = object->label = pk11_getString(object,CKA_LABEL);
  981. crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_ID);  /* Should this be ID? */
  982. if (crv != CKR_OK) goto loser;
  983. rv = SECKEY_StoreKeyByPublicKey(SECKEY_GetDefaultKeyDB(),
  984. privKey, &pubKey, label,
  985. (SECKEYGetPasswordKey) pk11_givePass, object->slot);
  986. object->inDB = PR_TRUE;
  987.         object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  988.     }
  989. loser:
  990.     if (privKey) SECKEY_LowDestroyPrivateKey(privKey);
  991.     if (pubKey.data) PORT_Free(pubKey.data);
  992.     return crv;
  993. }
  994. /*
  995.  * check the consistancy and initialize a Key Object 
  996.  */
  997. static CK_RV
  998. pk11_handleKeyObject(PK11Session *session, PK11Object *object)
  999. {
  1000.     PK11Attribute *attribute;
  1001.     CK_KEY_TYPE key_type;
  1002.     CK_BBOOL cktrue = CK_TRUE;
  1003.     CK_BBOOL ckfalse = CK_FALSE;
  1004.     CK_RV crv;
  1005.     /* verify the required fields */
  1006.     if ( !pk11_hasAttribute(object,CKA_KEY_TYPE) ) {
  1007. return CKR_TEMPLATE_INCOMPLETE;
  1008.     }
  1009.     /* now verify the common fields */
  1010.     crv = pk11_defaultAttribute(object,CKA_ID,NULL,0);
  1011.     if (crv != CKR_OK)  return crv; 
  1012.     crv = pk11_defaultAttribute(object,CKA_START_DATE,NULL,0);
  1013.     if (crv != CKR_OK)  return crv; 
  1014.     crv = pk11_defaultAttribute(object,CKA_END_DATE,NULL,0);
  1015.     if (crv != CKR_OK)  return crv; 
  1016.     crv = pk11_defaultAttribute(object,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
  1017.     if (crv != CKR_OK)  return crv; 
  1018.     crv = pk11_defaultAttribute(object,CKA_LOCAL,&ckfalse,sizeof(CK_BBOOL));
  1019.     if (crv != CKR_OK)  return crv; 
  1020.     /* get the key type */
  1021.     attribute = pk11_FindAttribute(object,CKA_KEY_TYPE);
  1022.     key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
  1023.     pk11_FreeAttribute(attribute);
  1024.     switch (object->objclass) {
  1025.     case CKO_PUBLIC_KEY:
  1026. return pk11_handlePublicKeyObject(object,key_type);
  1027.     case CKO_PRIVATE_KEY:
  1028. return pk11_handlePrivateKeyObject(object,key_type);
  1029.     case CKO_SECRET_KEY:
  1030. /* make sure the required fields exist */
  1031. return pk11_handleSecretKeyObject(object,key_type,
  1032.      (PRBool)(session->slot->slotID == FIPS_SLOT_ID));
  1033.     default:
  1034. break;
  1035.     }
  1036.     return CKR_ATTRIBUTE_VALUE_INVALID;
  1037. }
  1038. /* 
  1039.  * Handle Object does all the object consistancy checks, automatic attribute
  1040.  * generation, attribute defaulting, etc. If handleObject succeeds, the object
  1041.  * will be assigned an object handle, and the object pointer will be adopted
  1042.  * by the session. (that is don't free object).
  1043.  */
  1044. CK_RV
  1045. pk11_handleObject(PK11Object *object, PK11Session *session)
  1046. {
  1047.     PK11Slot *slot = session->slot;
  1048.     CK_BBOOL ckfalse = CK_FALSE;
  1049.     CK_BBOOL cktrue = CK_TRUE;
  1050.     PK11Attribute *attribute;
  1051.     CK_RV crv;
  1052.     /* make sure all the base object types are defined. If not set the
  1053.      * defaults */
  1054.     crv = pk11_defaultAttribute(object,CKA_TOKEN,&ckfalse,sizeof(CK_BBOOL));
  1055.     if (crv != CKR_OK) return crv;
  1056.     crv = pk11_defaultAttribute(object,CKA_PRIVATE,&ckfalse,sizeof(CK_BBOOL));
  1057.     if (crv != CKR_OK) return crv;
  1058.     crv = pk11_defaultAttribute(object,CKA_LABEL,NULL,0);
  1059.     if (crv != CKR_OK) return crv;
  1060.     crv = pk11_defaultAttribute(object,CKA_MODIFIABLE,&cktrue,sizeof(CK_BBOOL));
  1061.     if (crv != CKR_OK) return crv;
  1062.     /* don't create a private object if we aren't logged in */
  1063.     if ((!slot->isLoggedIn) && (slot->needLogin) &&
  1064. (pk11_isTrue(object,CKA_PRIVATE))) {
  1065. return CKR_USER_NOT_LOGGED_IN;
  1066.     }
  1067.     if (((session->info.flags & CKF_RW_SESSION) == 0) &&
  1068. (pk11_isTrue(object,CKA_TOKEN))) {
  1069. return CKR_SESSION_READ_ONLY;
  1070.     }
  1071.     if (pk11_isTrue(object, CKA_TOKEN)) {
  1072. if (slot->DB_loaded == PR_FALSE) {
  1073.     /* we are creating a token object, make sure we load the database
  1074.      * first so we don't get duplicates....
  1075.      * ... NOTE: This assumes we are logged in as well!
  1076.      */
  1077.     pk11_importKeyDB(slot);
  1078.     slot->DB_loaded = PR_TRUE;
  1079. }
  1080.     }
  1081.     /* PKCS #11 object ID's are unique for all objects on a
  1082.      * token */
  1083.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  1084.     object->handle = slot->tokenIDCount++;
  1085.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  1086.     /* get the object class */
  1087.     attribute = pk11_FindAttribute(object,CKA_CLASS);
  1088.     if (attribute == NULL) {
  1089. return CKR_TEMPLATE_INCOMPLETE;
  1090.     }
  1091.     object->objclass = *(CK_OBJECT_CLASS *)attribute->attrib.pValue;
  1092.     pk11_FreeAttribute(attribute);
  1093.     /* now handle the specific. Get a session handle for these functions
  1094.      * to use */
  1095.     switch (object->objclass) {
  1096.     case CKO_DATA:
  1097. crv = pk11_handleDataObject(session,object);
  1098.     case CKO_CERTIFICATE:
  1099. crv = pk11_handleCertObject(session,object);
  1100. break;
  1101.     case CKO_PRIVATE_KEY:
  1102.     case CKO_PUBLIC_KEY:
  1103.     case CKO_SECRET_KEY:
  1104. crv = pk11_handleKeyObject(session,object);
  1105. break;
  1106.     default:
  1107. crv = CKR_ATTRIBUTE_VALUE_INVALID;
  1108. break;
  1109.     }
  1110.     /* can't fail from here on out unless the pk_handlXXX functions have
  1111.      * failed the request */
  1112.     if (crv != CKR_OK) {
  1113. return crv;
  1114.     }
  1115.     /* now link the object into the slot and session structures */
  1116.     object->slot = slot;
  1117.     pk11_AddObject(session,object);
  1118.     return CKR_OK;
  1119. }
  1120. /* import a private key as an object. We don't call handle object.
  1121.  * because we the private key came from the key DB and we don't want to
  1122.  * write back out again */
  1123. static PK11Object *
  1124. pk11_importPrivateKey(PK11Slot *slot,SECKEYLowPrivateKey *lowPriv,
  1125. SECItem *dbKey)
  1126. {
  1127.     PK11Object *privateKey;
  1128.     CK_KEY_TYPE key_type;
  1129.     CK_BBOOL cktrue = CK_TRUE;
  1130.     CK_BBOOL ckfalse = CK_FALSE;
  1131.     CK_BBOOL sign = CK_TRUE;
  1132.     CK_BBOOL recover = CK_TRUE;
  1133.     CK_BBOOL decrypt = CK_TRUE;
  1134.     CK_BBOOL derive = CK_FALSE;
  1135.     CK_RV crv = CKR_OK;
  1136.     CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY;
  1137.     unsigned char cka_id[SHA1_LENGTH];
  1138.     /*
  1139.      * now lets create an object to hang the attributes off of
  1140.      */
  1141.     privateKey = pk11_NewObject(slot); /* fill in the handle later */
  1142.     if (privateKey == NULL) {
  1143. pk11_FreeObject(privateKey);
  1144. return NULL;
  1145.     }
  1146.     /* Netscape Private Attribute for dealing with database storeage */
  1147.     if (pk11_AddAttributeType(privateKey, CKA_NETSCAPE_DB,
  1148. pk11_item_expand(dbKey)) ) {
  1149.  pk11_FreeObject(privateKey);
  1150.  return NULL;
  1151.     }
  1152.     /* now force the CKA_ID */
  1153.     SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len);
  1154.     if (pk11_AddAttributeType(privateKey, CKA_ID, cka_id, sizeof(cka_id))) {
  1155.  pk11_FreeObject(privateKey);
  1156.  return NULL;
  1157.     }
  1158.     /* Fill in the common Default values */
  1159.     if (pk11_AddAttributeType(privateKey,CKA_CLASS, &privClass,
  1160. sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
  1161.  pk11_FreeObject(privateKey);
  1162.  return NULL;
  1163.     }
  1164.     if (pk11_AddAttributeType(privateKey,CKA_TOKEN, &cktrue,
  1165.       sizeof(CK_BBOOL)) != CKR_OK) {
  1166. pk11_FreeObject(privateKey);
  1167. return NULL;
  1168.     }
  1169.     if (pk11_AddAttributeType(privateKey,CKA_PRIVATE, &cktrue,
  1170.       sizeof(CK_BBOOL)) != CKR_OK) {
  1171. pk11_FreeObject(privateKey);
  1172. return NULL;
  1173.     }
  1174.     if (pk11_AddAttributeType(privateKey,CKA_MODIFIABLE, &cktrue,
  1175.       sizeof(CK_BBOOL)) != CKR_OK) {
  1176. pk11_FreeObject(privateKey);
  1177. return NULL;
  1178.     }
  1179.     if (pk11_AddAttributeType(privateKey,CKA_LABEL, NULL, 0) != CKR_OK) {
  1180. pk11_FreeObject(privateKey);
  1181. return NULL;
  1182.     }
  1183.     if (pk11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
  1184. pk11_FreeObject(privateKey);
  1185. return NULL;
  1186.     }
  1187.     if (pk11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
  1188. pk11_FreeObject(privateKey);
  1189. return NULL;
  1190.     }
  1191.     if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &ckfalse,
  1192.       sizeof(CK_BBOOL)) != CKR_OK) {
  1193. pk11_FreeObject(privateKey);
  1194. return NULL;
  1195.     }
  1196.     /* local: well we really don't know for sure... it could have been an 
  1197.      * imported key, but it's not a useful attribute anyway. */
  1198.     if (pk11_AddAttributeType(privateKey,CKA_LOCAL, &cktrue,
  1199.       sizeof(CK_BBOOL)) != CKR_OK) {
  1200. pk11_FreeObject(privateKey);
  1201. return NULL;
  1202.     }
  1203.     if (pk11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
  1204. pk11_FreeObject(privateKey);
  1205. return NULL;
  1206.     }
  1207.     if (pk11_AddAttributeType(privateKey,CKA_SENSITIVE, &cktrue,
  1208.       sizeof(CK_BBOOL)) != CKR_OK) {
  1209. pk11_FreeObject(privateKey);
  1210. return NULL;
  1211.     }
  1212.     if (pk11_AddAttributeType(privateKey,CKA_EXTRACTABLE, &cktrue,
  1213.       sizeof(CK_BBOOL)) != CKR_OK) {
  1214. pk11_FreeObject(privateKey);
  1215. return NULL;
  1216.     }
  1217.     /* is this really true? Maybe we should just say false here? */
  1218.     if (pk11_AddAttributeType(privateKey,CKA_ALWAYS_SENSITIVE, &cktrue,
  1219.       sizeof(CK_BBOOL)) != CKR_OK) {
  1220. pk11_FreeObject(privateKey);
  1221. return NULL;
  1222.     }
  1223.     if (pk11_AddAttributeType(privateKey,CKA_NEVER_EXTRACTABLE, &ckfalse,
  1224.       sizeof(CK_BBOOL)) != CKR_OK) {
  1225. pk11_FreeObject(privateKey);
  1226. return NULL;
  1227.     }
  1228.     /* Now Set up the parameters to generate the key (based on mechanism) */
  1229.     /* NOTE: for safety sake we *DO NOT* remember critical attributes. PKCS #11
  1230.      * will look them up again from the database when it needs them.
  1231.      */
  1232.     switch (lowPriv->keyType) {
  1233.     case rsaKey:
  1234. /* format the keys */
  1235. key_type = CKK_RSA;
  1236. sign = CK_TRUE;
  1237. recover = CK_TRUE;
  1238. decrypt = CK_TRUE;
  1239. derive = CK_FALSE;
  1240.         /* now fill in the RSA dependent parameters in the public key */
  1241.         crv = pk11_AddAttributeType(privateKey,CKA_MODULUS,
  1242.    pk11_item_expand(&lowPriv->u.rsa.modulus));
  1243. if (crv != CKR_OK) break;
  1244.         crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,NULL,0);
  1245. if (crv != CKR_OK) break;
  1246.         crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
  1247.    pk11_item_expand(&lowPriv->u.rsa.publicExponent));
  1248. if (crv != CKR_OK) break;
  1249.         crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,NULL,0);
  1250. if (crv != CKR_OK) break;
  1251.         crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,NULL,0);
  1252. if (crv != CKR_OK) break;
  1253.         crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,NULL,0);
  1254. if (crv != CKR_OK) break;
  1255.         crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,NULL,0);
  1256. if (crv != CKR_OK)  break;
  1257.         crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,NULL,0);
  1258. break;
  1259.     case dsaKey:
  1260. key_type = CKK_DSA;
  1261. sign = CK_TRUE;
  1262. recover = CK_FALSE;
  1263. decrypt = CK_FALSE;
  1264. derive = CK_FALSE;
  1265. crv = pk11_AddAttributeType(privateKey,CKA_PRIME,
  1266.    pk11_item_expand(&lowPriv->u.dsa.params.prime));
  1267. if (crv != CKR_OK) break;
  1268. crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME,
  1269.    pk11_item_expand(&lowPriv->u.dsa.params.subPrime));
  1270. if (crv != CKR_OK) break;
  1271. crv = pk11_AddAttributeType(privateKey,CKA_BASE,
  1272.    pk11_item_expand(&lowPriv->u.dsa.params.base));
  1273. if (crv != CKR_OK) break;
  1274. crv = pk11_AddAttributeType(privateKey,CKA_VALUE,NULL,0);
  1275. if (crv != CKR_OK) break;
  1276. break;
  1277.     case dhKey:
  1278. key_type = CKK_DH;
  1279. sign = CK_FALSE;
  1280. decrypt = CK_FALSE;
  1281. recover = CK_FALSE;
  1282. derive = CK_TRUE;
  1283. crv = CKR_MECHANISM_INVALID;
  1284. break;
  1285.     default:
  1286. crv = CKR_MECHANISM_INVALID;
  1287.     }
  1288.     if (crv != CKR_OK) {
  1289. pk11_FreeObject(privateKey);
  1290. return NULL;
  1291.     }
  1292.     if (pk11_AddAttributeType(privateKey,CKA_SIGN, &sign,
  1293.       sizeof(CK_BBOOL)) != CKR_OK) {
  1294. pk11_FreeObject(privateKey);
  1295. return NULL;
  1296.     }
  1297.     if (pk11_AddAttributeType(privateKey,CKA_SIGN_RECOVER, &recover,
  1298.       sizeof(CK_BBOOL)) != CKR_OK) {
  1299. pk11_FreeObject(privateKey);
  1300. return NULL;
  1301.     }
  1302.     if (pk11_AddAttributeType(privateKey,CKA_DECRYPT, &decrypt,
  1303.       sizeof(CK_BBOOL)) != CKR_OK) {
  1304. pk11_FreeObject(privateKey);
  1305. return NULL;
  1306.     }
  1307.     if (pk11_AddAttributeType(privateKey,CKA_UNWRAP, &decrypt,
  1308.       sizeof(CK_BBOOL)) != CKR_OK) {
  1309. pk11_FreeObject(privateKey);
  1310. return NULL;
  1311.     }
  1312.     if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &derive,
  1313.       sizeof(CK_BBOOL)) != CKR_OK) {
  1314. pk11_FreeObject(privateKey);
  1315. return NULL;
  1316.     }
  1317.     if (pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
  1318.      sizeof(CK_KEY_TYPE)) != CKR_OK) {
  1319.  pk11_FreeObject(privateKey);
  1320.  return NULL;
  1321.     }
  1322.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  1323.     privateKey->handle = slot->tokenIDCount++;
  1324.     privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  1325.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  1326.     privateKey->objclass = privClass;
  1327.     privateKey->slot = slot;
  1328.     privateKey->inDB = PR_TRUE;
  1329.     return privateKey;
  1330. }
  1331. /* import a private key or cert as a public key object.*/
  1332. static PK11Object *
  1333. pk11_importPublicKey(PK11Slot *slot,
  1334. SECKEYLowPrivateKey *lowPriv, CERTCertificate *cert, SECItem *dbKey)
  1335. {
  1336.     PK11Object *publicKey = NULL;
  1337.     CK_KEY_TYPE key_type;
  1338.     CK_BBOOL cktrue = CK_TRUE;
  1339.     CK_BBOOL ckfalse = CK_FALSE;
  1340.     CK_BBOOL verify = CK_TRUE;
  1341.     CK_BBOOL recover = CK_TRUE;
  1342.     CK_BBOOL encrypt = CK_TRUE;
  1343.     CK_BBOOL derive = CK_FALSE;
  1344.     CK_RV crv = CKR_OK;
  1345.     CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
  1346.     unsigned char cka_id[SHA1_LENGTH];
  1347.     KeyType keyType = nullKey;
  1348.     SECKEYPublicKey *pubKey = NULL;
  1349.     CK_ATTRIBUTE theTemplate[2];
  1350.     PK11ObjectListElement *objectList = NULL;
  1351.     if (lowPriv == NULL) {
  1352. pubKey = CERT_ExtractPublicKey(cert);
  1353. if (pubKey == NULL) {
  1354.     goto failed;
  1355. }
  1356. /* pk11_GetPubItem returns data associated with the public key.
  1357.  * one only needs to free the public key. This comment is here
  1358.  * because this sematic would be non-obvious otherwise. All callers
  1359.  * should include this comment.
  1360.  */
  1361. dbKey = pk11_GetPubItem(pubKey);
  1362. if (dbKey == NULL) {
  1363.     goto failed;
  1364. }
  1365.     }
  1366.     SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len);
  1367.     theTemplate[0].type = CKA_ID;
  1368.     theTemplate[0].pValue = cka_id;
  1369.     theTemplate[0].ulValueLen = sizeof(cka_id);
  1370.     theTemplate[1].type = CKA_CLASS;
  1371.     theTemplate[1].pValue = &pubClass;
  1372.     theTemplate[1].ulValueLen = sizeof(CK_OBJECT_CLASS);
  1373.     crv = pk11_searchObjectList(&objectList,slot->tokObjects,
  1374. slot->objectLock, theTemplate, 2, slot->isLoggedIn);
  1375.     if ((crv == CKR_OK) && (objectList != NULL)) {
  1376. goto failed;
  1377.     }
  1378.     /*
  1379.      * now lets create an object to hang the attributes off of
  1380.      */
  1381.     publicKey = pk11_NewObject(slot); /* fill in the handle later */
  1382.     if (publicKey == NULL) {
  1383. goto failed;
  1384.     }
  1385.     /* now force the CKA_ID */
  1386.     if (pk11_AddAttributeType(publicKey, CKA_ID, cka_id, sizeof(cka_id))) {
  1387. goto failed;
  1388.     }
  1389.     /* Fill in the common Default values */
  1390.     if (pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
  1391. sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
  1392. goto failed;
  1393.     }
  1394.     if (pk11_AddAttributeType(publicKey,CKA_TOKEN, &cktrue,
  1395.       sizeof(CK_BBOOL)) != CKR_OK) {
  1396. goto failed;
  1397.     }
  1398.     if (pk11_AddAttributeType(publicKey,CKA_PRIVATE, &ckfalse,
  1399.       sizeof(CK_BBOOL)) != CKR_OK) {
  1400. goto failed;
  1401.     }
  1402.     if (pk11_AddAttributeType(publicKey,CKA_MODIFIABLE, &cktrue,
  1403.       sizeof(CK_BBOOL)) != CKR_OK) {
  1404. goto failed;
  1405.     }
  1406.     if (pk11_AddAttributeType(publicKey,CKA_LABEL, NULL, 0) != CKR_OK) {
  1407. goto failed;
  1408.     }
  1409.     if (pk11_AddAttributeType(publicKey,CKA_START_DATE, NULL, 0) != CKR_OK) {
  1410. goto failed;
  1411.     }
  1412.     if (pk11_AddAttributeType(publicKey,CKA_END_DATE, NULL, 0) != CKR_OK) {
  1413. goto failed;
  1414.     }
  1415.     /* local: well we really don't know for sure... it could have been an 
  1416.      * imported key, but it's not a useful attribute anyway. */
  1417.     if (pk11_AddAttributeType(publicKey,CKA_LOCAL, &cktrue,
  1418.       sizeof(CK_BBOOL)) != CKR_OK) {
  1419. goto failed;
  1420.     }
  1421.     if (pk11_AddAttributeType(publicKey,CKA_SUBJECT, NULL, 0) != CKR_OK) {
  1422. goto failed;
  1423.     }
  1424.     if (pk11_AddAttributeType(publicKey,CKA_SENSITIVE, &ckfalse,
  1425.       sizeof(CK_BBOOL)) != CKR_OK) {
  1426. goto failed;
  1427.     }
  1428.     if (pk11_AddAttributeType(publicKey,CKA_EXTRACTABLE, &cktrue,
  1429.       sizeof(CK_BBOOL)) != CKR_OK) {
  1430. goto failed;
  1431.     }
  1432.     if (pk11_AddAttributeType(publicKey,CKA_ALWAYS_SENSITIVE, &ckfalse,
  1433.       sizeof(CK_BBOOL)) != CKR_OK) {
  1434. goto failed;
  1435.     }
  1436.     if (pk11_AddAttributeType(publicKey,CKA_NEVER_EXTRACTABLE, &ckfalse,
  1437.       sizeof(CK_BBOOL)) != CKR_OK) {
  1438. goto failed;
  1439.     }
  1440.     /* Now Set up the parameters to generate the key (based on mechanism) */
  1441.     if (lowPriv == NULL) {
  1442. keyType = pubKey->keyType;
  1443.     } else {
  1444. keyType = lowPriv->keyType;
  1445.     } 
  1446.     switch (keyType) {
  1447.     case rsaKey:
  1448. /* format the keys */
  1449. key_type = CKK_RSA;
  1450. verify = CK_TRUE;
  1451. recover = CK_TRUE;
  1452. encrypt = CK_TRUE;
  1453. derive = CK_FALSE;
  1454.         /* now fill in the RSA dependent parameters in the public key */
  1455.   if (lowPriv) {
  1456.             crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
  1457.    pk11_item_expand(&lowPriv->u.rsa.modulus));
  1458.     if (crv != CKR_OK) break;
  1459.             crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT,
  1460.    pk11_item_expand(&lowPriv->u.rsa.publicExponent));
  1461.     if (crv != CKR_OK) break;
  1462. } else {
  1463.             crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
  1464.    pk11_item_expand(&pubKey->u.rsa.modulus));
  1465.     if (crv != CKR_OK) break;
  1466.             crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT,
  1467.    pk11_item_expand(&pubKey->u.rsa.publicExponent));
  1468.     if (crv != CKR_OK) break;
  1469. }
  1470. break;
  1471.     case dsaKey:
  1472. key_type = CKK_DSA;
  1473. verify = CK_TRUE;
  1474. recover = CK_FALSE;
  1475. encrypt = CK_FALSE;
  1476. derive = CK_FALSE;
  1477.   if (lowPriv) {
  1478.     crv = pk11_AddAttributeType(publicKey,CKA_PRIME,
  1479.    pk11_item_expand(&lowPriv->u.dsa.params.prime));
  1480.     if (crv != CKR_OK) break;
  1481.     crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME,
  1482.    pk11_item_expand(&lowPriv->u.dsa.params.subPrime));
  1483.     if (crv != CKR_OK) break;
  1484.     crv = pk11_AddAttributeType(publicKey,CKA_BASE,
  1485.    pk11_item_expand(&lowPriv->u.dsa.params.base));
  1486.     if (crv != CKR_OK) break;
  1487.     crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
  1488.    pk11_item_expand(&lowPriv->u.dsa.publicValue));
  1489.     if (crv != CKR_OK) break;
  1490. } else {
  1491.     crv = pk11_AddAttributeType(publicKey,CKA_PRIME,
  1492.    pk11_item_expand(&pubKey->u.dsa.params.prime));
  1493.     if (crv != CKR_OK) break;
  1494.     crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME,
  1495.    pk11_item_expand(&pubKey->u.dsa.params.subPrime));
  1496.     if (crv != CKR_OK) break;
  1497.     crv = pk11_AddAttributeType(publicKey,CKA_BASE,
  1498.    pk11_item_expand(&pubKey->u.dsa.params.base));
  1499.     if (crv != CKR_OK) break;
  1500.     crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
  1501.    pk11_item_expand(&pubKey->u.dsa.publicValue));
  1502.     if (crv != CKR_OK) break;
  1503. }
  1504. break;
  1505.     case dhKey:
  1506. key_type = CKK_DH;
  1507. verify = CK_FALSE;
  1508. encrypt = CK_FALSE;
  1509. recover = CK_FALSE;
  1510. derive = CK_TRUE;
  1511. crv = CKR_MECHANISM_INVALID;
  1512. break;
  1513.     default:
  1514. crv = CKR_MECHANISM_INVALID;
  1515.     }
  1516.     if (pubKey) {
  1517. SECKEY_DestroyPublicKey(pubKey);
  1518. pubKey = NULL;
  1519.     }
  1520.     if (crv != CKR_OK) {
  1521. goto failed;
  1522.     }
  1523.     if (pk11_AddAttributeType(publicKey,CKA_VERIFY, &verify,
  1524.       sizeof(CK_BBOOL)) != CKR_OK) {
  1525. goto failed;
  1526.     }
  1527.     if (pk11_AddAttributeType(publicKey,CKA_VERIFY_RECOVER, &recover,
  1528.       sizeof(CK_BBOOL)) != CKR_OK) {
  1529. goto failed;
  1530.     }
  1531.     if (pk11_AddAttributeType(publicKey,CKA_ENCRYPT, &encrypt,
  1532.       sizeof(CK_BBOOL)) != CKR_OK) {
  1533. goto failed;
  1534.     }
  1535.     if (pk11_AddAttributeType(publicKey,CKA_WRAP, &encrypt,
  1536.       sizeof(CK_BBOOL)) != CKR_OK) {
  1537. goto failed;
  1538.     }
  1539.     if (pk11_AddAttributeType(publicKey,CKA_DERIVE, &derive,
  1540.       sizeof(CK_BBOOL)) != CKR_OK) {
  1541. goto failed;
  1542.     }
  1543.     if (pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
  1544.      sizeof(CK_KEY_TYPE)) != CKR_OK) {
  1545. goto failed;
  1546.     }
  1547.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  1548.     publicKey->handle = slot->tokenIDCount++;
  1549.     publicKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB);
  1550.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  1551.     publicKey->objclass = pubClass;
  1552.     publicKey->slot = slot;
  1553.     publicKey->inDB = PR_FALSE; /* not really in the Database */
  1554.     return publicKey;
  1555. failed:
  1556.     if (pubKey) SECKEY_DestroyPublicKey(pubKey);
  1557.     if (publicKey) pk11_FreeObject(publicKey);
  1558.     return NULL;
  1559. }
  1560. /*
  1561.  * Question.. Why doesn't import Cert call pk11_handleObject, or
  1562.  * pk11 handleCertObject? Answer: because they will try to write
  1563.  * this cert back out to the Database, even though it is already in
  1564.  * the database.
  1565.  */
  1566. static PK11Object *
  1567. pk11_importCertificate(PK11Slot *slot, CERTCertificate *cert, 
  1568. unsigned char *data, unsigned int size, PRBool needObject)
  1569. {
  1570.     PK11Object *certObject = NULL;
  1571.     CK_BBOOL cktrue = CK_TRUE;
  1572.     CK_BBOOL ckfalse = CK_FALSE;
  1573.     CK_CERTIFICATE_TYPE certType = CKC_X_509;
  1574.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1575.     unsigned char cka_id[SHA1_LENGTH];
  1576.     CK_ATTRIBUTE theTemplate;
  1577.     PK11ObjectListElement *objectList = NULL;
  1578.     CK_RV crv;
  1579.     /*
  1580.      * first make sure that no object for this cert already exists.
  1581.      */
  1582.     theTemplate.type = CKA_VALUE;
  1583.     theTemplate.pValue = cert->derCert.data;
  1584.     theTemplate.ulValueLen = cert->derCert.len;
  1585.     crv = pk11_searchObjectList(&objectList,slot->tokObjects,
  1586. slot->objectLock, &theTemplate, 1, slot->isLoggedIn);
  1587.     if ((crv == CKR_OK) && (objectList != NULL)) {
  1588. if (needObject) {
  1589.          pk11_ReferenceObject(objectList->object);
  1590.     certObject = objectList->object;
  1591. }
  1592. pk11_FreeObjectList(objectList);
  1593. return certObject;
  1594.     }
  1595.     /*
  1596.      * now lets create an object to hang the attributes off of
  1597.      */
  1598.     certObject = pk11_NewObject(slot); /* fill in the handle later */
  1599.     if (certObject == NULL) {
  1600. return NULL;
  1601.     }
  1602.     /* First set the CKA_ID */
  1603.     if (data == NULL) {
  1604. SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
  1605. SECItem *pubItem;
  1606. if (pubKey == NULL) {
  1607.     pk11_FreeObject(certObject);
  1608.     return NULL;
  1609. }
  1610. /* pk11_GetPubItem returns data associated with the public key.
  1611.  * one only needs to free the public key. This comment is here
  1612.  * because this sematic would be non-obvious otherwise.
  1613.  */
  1614. pubItem =pk11_GetPubItem(pubKey);
  1615. if (pubItem == NULL)  {
  1616.     SECKEY_DestroyPublicKey(pubKey);
  1617.     pk11_FreeObject(certObject);
  1618.     return NULL;
  1619.      SHA1_HashBuf(cka_id, (unsigned char *)pubItem->data, 
  1620. (uint32)pubItem->len);
  1621. SECKEY_DestroyPublicKey(pubKey);
  1622.     } else {
  1623. SHA1_HashBuf(cka_id, (unsigned char *)data, (uint32)size);
  1624.     }
  1625.     if (pk11_AddAttributeType(certObject, CKA_ID, cka_id, sizeof(cka_id))) {
  1626.  pk11_FreeObject(certObject);
  1627.  return NULL;
  1628.     }
  1629.     /* initalize the certificate attributes */
  1630.     if (pk11_AddAttributeType(certObject, CKA_CLASS, &certClass,
  1631.  sizeof(CK_OBJECT_CLASS)) != CKR_OK) {
  1632.  pk11_FreeObject(certObject);
  1633.  return NULL;
  1634.     }
  1635.     if (pk11_AddAttributeType(certObject, CKA_TOKEN, &cktrue,
  1636.        sizeof(CK_BBOOL)) != CKR_OK) {
  1637.  pk11_FreeObject(certObject);
  1638.  return NULL;
  1639.     }
  1640.     if (pk11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse,
  1641.        sizeof(CK_BBOOL)) != CKR_OK) {
  1642.  pk11_FreeObject(certObject);
  1643.  return NULL;
  1644.     }
  1645.     if (pk11_AddAttributeType(certObject, CKA_LABEL, cert->nickname,
  1646. PORT_Strlen(cert->nickname))
  1647. != CKR_OK) {
  1648.  pk11_FreeObject(certObject);
  1649.  return NULL;
  1650.     }
  1651.     if (pk11_AddAttributeType(certObject, CKA_MODIFIABLE, &cktrue,
  1652.        sizeof(CK_BBOOL)) != CKR_OK) {
  1653.  pk11_FreeObject(certObject);
  1654.  return NULL;
  1655.     }
  1656.     if (pk11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE,  &certType,
  1657. sizeof(CK_CERTIFICATE_TYPE))!=CKR_OK) {
  1658.  pk11_FreeObject(certObject);
  1659.  return NULL;
  1660.     }
  1661.     if (pk11_AddAttributeType(certObject, CKA_VALUE, 
  1662.   pk11_item_expand(&cert->derCert)) != CKR_OK) {
  1663.  pk11_FreeObject(certObject);
  1664.  return NULL;
  1665.     }
  1666.     if (pk11_AddAttributeType(certObject, CKA_ISSUER, 
  1667.   pk11_item_expand(&cert->derIssuer)) != CKR_OK) {
  1668.  pk11_FreeObject(certObject);
  1669.  return NULL;
  1670.     }
  1671.     if (pk11_AddAttributeType(certObject, CKA_SUBJECT, 
  1672.   pk11_item_expand(&cert->derSubject)) != CKR_OK) {
  1673.  pk11_FreeObject(certObject);
  1674.  return NULL;
  1675.     }
  1676.     if (pk11_AddAttributeType(certObject, CKA_SERIAL_NUMBER, 
  1677.   pk11_item_expand(&cert->serialNumber)) != CKR_OK) {
  1678.  pk11_FreeObject(certObject);
  1679.  return NULL;
  1680.     }
  1681.   
  1682.     certObject->objectInfo = CERT_DupCertificate(cert);
  1683.     certObject->infoFree = (PK11Free) CERT_DestroyCertificate;
  1684.     
  1685.     /* now just verify the required date fields */
  1686.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  1687.     certObject->handle = slot->tokenIDCount++;
  1688.     certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT);
  1689.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  1690.     certObject->objclass = certClass;
  1691.     certObject->slot = slot;
  1692.     certObject->inDB = PR_TRUE;
  1693.     pk11_AddSlotObject(slot, certObject);
  1694.     if (needObject) {
  1695. pk11_ReferenceObject(certObject);
  1696.     } else {
  1697. certObject = NULL;
  1698.     }
  1699.     return certObject;
  1700. }
  1701. /*
  1702.  * ******************** Public Key Utilities ***************************
  1703.  */
  1704. /* Generate a low public key structure from an object */
  1705. SECKEYLowPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type)
  1706. {
  1707.     SECKEYLowPublicKey *pubKey;
  1708.     PLArenaPool *arena;
  1709.     CK_RV crv;
  1710.     if (object->objclass != CKO_PUBLIC_KEY) {
  1711. return NULL;
  1712.     }
  1713.     /* If we already have a key, use it */
  1714.     if (object->objectInfo) {
  1715. return (SECKEYLowPublicKey *)object->objectInfo;
  1716.     }
  1717.     /* allocate the structure */
  1718.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1719.     if (arena == NULL) return NULL;
  1720.     pubKey = (SECKEYLowPublicKey *)
  1721. PORT_ArenaAlloc(arena,sizeof(SECKEYLowPublicKey));
  1722.     if (pubKey == NULL) {
  1723.      PORT_FreeArena(arena,PR_FALSE);
  1724. return NULL;
  1725.     }
  1726.     /* fill in the structure */
  1727.     pubKey->arena = arena;
  1728.     switch (key_type) {
  1729.     case CKK_RSA:
  1730. pubKey->keyType = rsaKey;
  1731. crv = pk11_Attribute2SSecItem(arena,&pubKey->u.rsa.modulus,
  1732. object,CKA_MODULUS);
  1733.      if (crv != CKR_OK) break;
  1734.      crv = pk11_Attribute2SSecItem(arena,&pubKey->u.rsa.publicExponent,
  1735. object,CKA_PUBLIC_EXPONENT);
  1736. break;
  1737.     case CKK_DSA:
  1738. pubKey->keyType = dsaKey;
  1739. crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.params.prime,
  1740. object,CKA_PRIME);
  1741.      if (crv != CKR_OK) break;
  1742. crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.params.subPrime,
  1743. object,CKA_SUBPRIME);
  1744.      if (crv != CKR_OK) break;
  1745. crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.params.base,
  1746. object,CKA_BASE);
  1747.      if (crv != CKR_OK) break;
  1748.      crv = pk11_Attribute2SSecItem(arena,&pubKey->u.dsa.publicValue,
  1749. object,CKA_VALUE);
  1750. break;
  1751.     case CKK_DH:
  1752.     default:
  1753. crv = CKR_KEY_TYPE_INCONSISTENT;
  1754. break;
  1755.     }
  1756.     if (crv != CKR_OK) {
  1757.      PORT_FreeArena(arena,PR_FALSE);
  1758. return NULL;
  1759.     }
  1760.     object->objectInfo = pubKey;
  1761.     object->infoFree = (PK11Free) SECKEY_LowDestroyPublicKey;
  1762.     return pubKey;
  1763. }
  1764. /* make a private key from a verified object */
  1765. static SECKEYLowPrivateKey *
  1766. pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
  1767. {
  1768.     SECKEYLowPrivateKey *privKey;
  1769.     PLArenaPool *arena;
  1770.     CK_RV crv = CKR_OK;
  1771.     SECStatus rv;
  1772.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1773.     if (arena == NULL) return NULL;
  1774.     privKey = (SECKEYLowPrivateKey *)
  1775. PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey));
  1776.     if (privKey == NULL)  {
  1777. PORT_FreeArena(arena,PR_FALSE);
  1778. return NULL;
  1779.     }
  1780.     /* in future this would be a switch on key_type */
  1781.     privKey->arena = arena;
  1782.     switch (key_type) {
  1783.     case CKK_RSA:
  1784. privKey->keyType = rsaKey;
  1785. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.modulus,
  1786. object,CKA_MODULUS);
  1787. if (crv != CKR_OK) break;
  1788. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.publicExponent,object,
  1789. CKA_PUBLIC_EXPONENT);
  1790. if (crv != CKR_OK) break;
  1791. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.privateExponent,object,
  1792. CKA_PRIVATE_EXPONENT);
  1793. if (crv != CKR_OK) break;
  1794. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.prime1,object,
  1795. CKA_PRIME_1);
  1796. if (crv != CKR_OK) break;
  1797. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.prime2,object,
  1798. CKA_PRIME_2);
  1799. if (crv != CKR_OK) break;
  1800. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.exponent1,
  1801. object, CKA_EXPONENT_1);
  1802. if (crv != CKR_OK) break;
  1803. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.exponent2,
  1804. object, CKA_EXPONENT_2);
  1805. if (crv != CKR_OK) break;
  1806. crv=pk11_Attribute2SSecItem(arena,&privKey->u.rsa.coefficient,object,
  1807.       CKA_COEFFICIENT);
  1808. if (crv != CKR_OK) break;
  1809.         rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,
  1810.                           SEC_PRIVATE_KEY_VERSION);
  1811. if (rv != SECSuccess) crv = CKR_HOST_MEMORY;
  1812. break;
  1813.     case CKK_DSA:
  1814. privKey->keyType = dsaKey;
  1815. crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.params.prime,
  1816. object,CKA_PRIME);
  1817.      if (crv != CKR_OK) break;
  1818. crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.params.subPrime,
  1819. object,CKA_SUBPRIME);
  1820.      if (crv != CKR_OK) break;
  1821. crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.params.base,
  1822. object,CKA_BASE);
  1823.      if (crv != CKR_OK) break;
  1824.      crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.privateValue,
  1825. object,CKA_VALUE);
  1826.      if (crv != CKR_OK) break;
  1827.      crv = pk11_Attribute2SSecItem(arena,&privKey->u.dsa.publicValue,
  1828. object,CKA_NETSCAPE_DB);
  1829. /* can't set the public value.... */
  1830. break;
  1831.     case CKK_DH:
  1832.     default:
  1833. crv = CKR_KEY_TYPE_INCONSISTENT;
  1834. break;
  1835.     }
  1836.     if (crv != CKR_OK) {
  1837. PORT_FreeArena(arena,PR_FALSE);
  1838. return NULL;
  1839.     }
  1840.     return privKey;
  1841. }
  1842. /* Generate a low private key structure from an object */
  1843. SECKEYLowPrivateKey *
  1844. pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type)
  1845. {
  1846.     SECKEYLowPrivateKey *priv = NULL;
  1847.     if (object->objclass != CKO_PRIVATE_KEY) {
  1848. return NULL;
  1849.     }
  1850.     if (object->objectInfo) {
  1851. return (SECKEYLowPrivateKey *)object->objectInfo;
  1852.     }
  1853.     if (pk11_isTrue(object,CKA_TOKEN)) {
  1854. /* grab it from the data base */
  1855. char *label = pk11_getString(object,CKA_LABEL);
  1856. SECItem pubKey;
  1857. CK_RV crv;
  1858. /* KEYID is the public KEY for DSA and DH, and the MODULUS for
  1859.  *  RSA */
  1860. crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
  1861. if (crv != CKR_OK) return NULL;
  1862. priv=SECKEY_FindKeyByPublicKey(SECKEY_GetDefaultKeyDB(),&pubKey,
  1863.        (SECKEYGetPasswordKey) pk11_givePass,
  1864.        object->slot);
  1865. if (pubKey.data) PORT_Free(pubKey.data);
  1866. /* don't 'cache' DB private keys */
  1867. return priv;
  1868.     } 
  1869.     priv = pk11_mkPrivKey(object, key_type);
  1870.     object->objectInfo = priv;
  1871.     object->infoFree = (PK11Free) SECKEY_LowDestroyPrivateKey;
  1872.     return priv;
  1873. }
  1874. /*
  1875.  **************************** Symetric Key utils ************************
  1876.  */
  1877. /*
  1878.  * set the DES key with parity bits correctly
  1879.  */
  1880. void
  1881. pk11_FormatDESKey(unsigned char *key, int length)
  1882. {
  1883.     int i;
  1884.     /* format the des key */
  1885.     for (i=0; i < length; i++) {
  1886. key[i] = parityTable[key[i]>>1];
  1887.     }
  1888. }
  1889. /*
  1890.  * check a des key (des2 or des3 subkey) for weak keys.
  1891.  */
  1892. PRBool
  1893. pk11_CheckDESKey(unsigned char *key)
  1894. {
  1895.     int i;
  1896.     /* format the des key with parity  */
  1897.     pk11_FormatDESKey(key, 8);
  1898.     for (i=0; i < pk11_desWeakTableSize; i++) {
  1899. if (PORT_Memcmp(key,pk11_desWeakTable[i],8) == 0) {
  1900.     return PR_TRUE;
  1901. }
  1902.     }
  1903.     return PR_FALSE;
  1904. }
  1905. /*
  1906.  * check if a des or triple des key is weak.
  1907.  */
  1908. PRBool
  1909. pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type)
  1910. {
  1911.     switch(key_type) {
  1912.     case CKK_DES:
  1913. return pk11_CheckDESKey(key);
  1914.     case CKM_DES2_KEY_GEN:
  1915. if (pk11_CheckDESKey(key)) return PR_TRUE;
  1916. return pk11_CheckDESKey(&key[8]);
  1917.     case CKM_DES3_KEY_GEN:
  1918. if (pk11_CheckDESKey(key)) return PR_TRUE;
  1919. if (pk11_CheckDESKey(&key[8])) return PR_TRUE;
  1920. return pk11_CheckDESKey(&key[16]);
  1921.     default:
  1922. break;
  1923.     }
  1924.     return PR_FALSE;
  1925. }
  1926. /* make a fake private key representing a symmetric key */
  1927. static SECKEYLowPrivateKey *
  1928. pk11_mkSecretKeyRep(PK11Object *object)
  1929. {
  1930.     SECKEYLowPrivateKey *privKey;
  1931.     PLArenaPool *arena = 0;
  1932.     CK_RV crv;
  1933.     SECStatus rv;
  1934.     static unsigned char derZero[1] = { 0 };
  1935.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1936.     if (arena == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
  1937.     privKey = (SECKEYLowPrivateKey *)
  1938. PORT_ArenaAlloc(arena,sizeof(SECKEYLowPrivateKey));
  1939.     if (privKey == NULL) { crv = CKR_HOST_MEMORY; goto loser; }
  1940.     privKey->arena = arena;
  1941.     /* Secret keys are represented in the database as "fake" RSA keys.  The RSA key
  1942.      * is marked as a secret key representation by setting the public exponent field
  1943.      * to 0, which is an invalid RSA exponent.  The other fields are set as follows:
  1944.      *   modulus - CKA_ID value for the secret key
  1945.      *   private exponent - CKA_VALUE (the key itself)
  1946.      *   coefficient - CKA_KEY_TYPE, which indicates what encryption algorithm
  1947.      *      is used for the key.
  1948.      *   all others - set to integer 0
  1949.      */
  1950.     privKey->keyType = rsaKey;
  1951.     /* The modulus is set to the key id of the symmetric key */
  1952.     crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.modulus,object,CKA_ID);
  1953.     if (crv != CKR_OK) goto loser;
  1954.     /* The public exponent is set to 0 length to indicate a special key */
  1955.     privKey->u.rsa.publicExponent.len = sizeof derZero;
  1956.     privKey->u.rsa.publicExponent.data = derZero;
  1957.     /* The private exponent is the actual key value */
  1958.     crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.privateExponent,object,CKA_VALUE);
  1959.     if (crv != CKR_OK) goto loser;
  1960.     /* All other fields empty - needs testing */
  1961.     privKey->u.rsa.prime1.len = sizeof derZero;
  1962.     privKey->u.rsa.prime1.data = derZero;
  1963.     privKey->u.rsa.prime2.len = sizeof derZero;
  1964.     privKey->u.rsa.prime2.data = derZero;
  1965.     privKey->u.rsa.exponent1.len = sizeof derZero;
  1966.     privKey->u.rsa.exponent1.data = derZero;
  1967.     privKey->u.rsa.exponent2.len = sizeof derZero;
  1968.     privKey->u.rsa.exponent2.data = derZero;
  1969.     /* Coeficient set to KEY_TYPE */
  1970.     crv=pk11_Attribute2SecItem(arena,&privKey->u.rsa.coefficient,object,CKA_KEY_TYPE);
  1971.     if (crv != CKR_OK) goto loser;
  1972.     /* Private key version field set normally for compatibility */
  1973.     rv = DER_SetUInteger(privKey->arena, &privKey->u.rsa.version,SEC_PRIVATE_KEY_VERSION);
  1974.     if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; goto loser; }
  1975. loser:
  1976.     if (crv != CKR_OK) {
  1977. PORT_FreeArena(arena,PR_FALSE);
  1978. privKey = 0;
  1979.     }
  1980.     return privKey;
  1981. }
  1982. static PRBool
  1983. isSecretKey(SECKEYLowPrivateKey *privKey)
  1984. {
  1985.   if (privKey->keyType == rsaKey && privKey->u.rsa.publicExponent.len == 1 &&
  1986.       privKey->u.rsa.publicExponent.data[0] == 0)
  1987.     return PR_TRUE;
  1988.   return PR_FALSE;
  1989. }
  1990. /* Import a Secret Key */
  1991. static PRBool
  1992. importSecretKey(PK11Slot *slot, SECKEYLowPrivateKey *priv)
  1993. {
  1994.     PK11Object *object;
  1995.     CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY;
  1996.     CK_BBOOL cktrue = CK_TRUE;
  1997.     CK_BBOOL ckfalse = CK_FALSE;
  1998.     CK_KEY_TYPE key_type;
  1999.     /* Check for secret key representation, return if it isn't one */
  2000.     if (!isSecretKey(priv))
  2001.         return PR_FALSE;
  2002.     /*
  2003.      * now lets create an object to hang the attributes off of
  2004.      */
  2005.     object = pk11_NewObject(slot); /* fill in the handle later */
  2006.     if (object == NULL) {
  2007. goto loser;
  2008.     }
  2009.     /* Set the ID value */
  2010.     if (pk11_AddAttributeType(object, CKA_ID, 
  2011.           priv->u.rsa.modulus.data, priv->u.rsa.modulus.len)) {
  2012.  pk11_FreeObject(object);
  2013.  goto loser;
  2014.     }
  2015.     /* initalize the object attributes */
  2016.     if (pk11_AddAttributeType(object, CKA_CLASS, &secretClass,
  2017.  sizeof(secretClass)) != CKR_OK) {
  2018.  pk11_FreeObject(object);
  2019.  goto loser;
  2020.     }
  2021.     if (pk11_AddAttributeType(object, CKA_TOKEN, &cktrue,
  2022.        sizeof(cktrue)) != CKR_OK) {
  2023.  pk11_FreeObject(object);
  2024.  goto loser;
  2025.     }
  2026.     if (pk11_AddAttributeType(object, CKA_PRIVATE, &ckfalse,
  2027.        sizeof(CK_BBOOL)) != CKR_OK) {
  2028.  pk11_FreeObject(object);
  2029.  goto loser;
  2030.     }
  2031.     if (pk11_AddAttributeType(object, CKA_VALUE, 
  2032.   pk11_item_expand(&priv->u.rsa.privateExponent)) != CKR_OK) {
  2033.  pk11_FreeObject(object);
  2034.  goto loser;
  2035.     }
  2036.     if (pk11_AddAttributeType(object, CKA_KEY_TYPE, 
  2037.   pk11_item_expand(&priv->u.rsa.coefficient)) != CKR_OK) {
  2038.  pk11_FreeObject(object);
  2039.  goto loser;
  2040.     }
  2041.     key_type = *(CK_KEY_TYPE*)priv->u.rsa.coefficient.data;
  2042.     /* Validate and add default attributes */
  2043.     validateSecretKey(object, key_type, (PRBool)(slot->slotID == FIPS_SLOT_ID));
  2044.     /* now just verify the required date fields */
  2045.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  2046.     object->handle = slot->tokenIDCount++;
  2047.     object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV);
  2048.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  2049.     object->objclass = secretClass;
  2050.     object->slot = slot;
  2051.     object->inDB = PR_TRUE;
  2052.     pk11_AddSlotObject(slot, object);
  2053. loser:
  2054.     return PR_TRUE;
  2055. }
  2056. /**********************************************************************
  2057.  *
  2058.  *     Start of PKCS 11 functions 
  2059.  *
  2060.  **********************************************************************/
  2061. /* return the function list */
  2062. CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList)
  2063. {
  2064.     *pFunctionList = &pk11_funcList;
  2065.     return CKR_OK;
  2066. }
  2067. /*
  2068.  * initialize one of the slot structures. figure out which by the ID
  2069.  */
  2070. CK_RV
  2071. PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin)
  2072. {
  2073.     int i;
  2074.     PK11Slot *slot = pk11_SlotFromID(slotID);
  2075. #ifdef PKCS11_USE_THREADS
  2076.     slot->sessionLock = PR_NewLock();
  2077.     if (slot->sessionLock == NULL) return CKR_HOST_MEMORY;
  2078.     slot->objectLock = PR_NewLock();
  2079.     if (slot->objectLock == NULL) return CKR_HOST_MEMORY;
  2080. #else
  2081.     slot->sessionLock = NULL;
  2082.     slot->objectLock = NULL;
  2083. #endif
  2084.     for(i=0; i < SESSION_HASH_SIZE; i++) {
  2085. slot->head[i] = NULL;
  2086.     }
  2087.     for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) {
  2088. slot->tokObjects[i] = NULL;
  2089.     }
  2090.     slot->password = NULL;
  2091.     slot->hasTokens = PR_FALSE;
  2092.     slot->sessionIDCount = 1;
  2093.     slot->sessionCount = 0;
  2094.     slot->rwSessionCount = 0;
  2095.     slot->tokenIDCount = 1;
  2096.     slot->needLogin = PR_FALSE;
  2097.     slot->isLoggedIn = PR_FALSE;
  2098.     slot->ssoLoggedIn = PR_FALSE;
  2099.     slot->DB_loaded = PR_FALSE;
  2100.     slot->slotID = slotID;
  2101.     if (needLogin) {
  2102. /* if the data base is initialized with a null password,remember that */
  2103. slot->needLogin = (PRBool)!pk11_hasNullPassword(&slot->password);
  2104.     }
  2105.     return CKR_OK;
  2106. }
  2107. /*
  2108.  * common initialization routines between PKCS #11 and FIPS
  2109.  */
  2110. CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved)
  2111. {
  2112.     SECStatus rv = SECSuccess;
  2113.     /* initialize the Random number generater */
  2114.     rv =  RNG_RNGInit();
  2115.     if (rv != SECSuccess) {
  2116. return CKR_DEVICE_ERROR;
  2117.     }
  2118.     SECKEY_SetDefaultKeyDBAlg(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC);
  2119.     return CKR_OK;
  2120. }
  2121. /* NSC_Initialize initializes the Cryptoki library. */
  2122. CK_RV NSC_Initialize(CK_VOID_PTR pReserved)
  2123. {
  2124.     static PRBool init = PR_FALSE;
  2125.     CK_RV crv = CKR_OK;
  2126.     crv = PK11_LowInitialize(pReserved);
  2127.     if (crv != CKR_OK) return crv;
  2128.     /* intialize all the slots */
  2129.     if (!init) {
  2130. crv = PK11_SlotInit(NETSCAPE_SLOT_ID,PR_FALSE);
  2131. if (crv != CKR_OK) return crv;
  2132. crv = PK11_SlotInit(PRIVATE_KEY_SLOT_ID,PR_TRUE);
  2133. init = PR_TRUE;
  2134.     }
  2135.     return crv;
  2136. }
  2137. /* NSC_Finalize indicates that an application is done with the 
  2138.  * Cryptoki library.*/
  2139. CK_RV NSC_Finalize (CK_VOID_PTR pReserved)
  2140. {
  2141.     return CKR_OK;
  2142. }
  2143. /* NSC_GetInfo returns general information about Cryptoki. */
  2144. CK_RV  NSC_GetInfo(CK_INFO_PTR pInfo)
  2145. {
  2146.     pInfo->cryptokiVersion.major = 2;
  2147.     pInfo->cryptokiVersion.minor = 1;
  2148.     PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
  2149.     pInfo->libraryVersion.major = 4;
  2150.     pInfo->libraryVersion.minor = 0;
  2151.     PORT_Memcpy(pInfo->libraryDescription,libraryDescription,32);
  2152.     pInfo->flags = 0;
  2153.     return CKR_OK;
  2154. }
  2155. /* NSC_GetSlotList obtains a list of slots in the system. */
  2156. CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent,
  2157.   CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
  2158. {
  2159.     *pulCount = 2;
  2160.     if (pSlotList != NULL) {
  2161. pSlotList[0] = NETSCAPE_SLOT_ID;
  2162. pSlotList[1] = PRIVATE_KEY_SLOT_ID;
  2163.     }
  2164.     return CKR_OK;
  2165. }
  2166. /* NSC_GetSlotInfo obtains information about a particular slot in the system. */
  2167. CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
  2168. {
  2169.     pInfo->firmwareVersion.major = 0;
  2170.     pInfo->firmwareVersion.minor = 0;
  2171.     switch (slotID) {
  2172.     case NETSCAPE_SLOT_ID:
  2173. PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
  2174. PORT_Memcpy(pInfo->slotDescription,slotDescription,64);
  2175. pInfo->flags = CKF_TOKEN_PRESENT;
  2176.         pInfo->hardwareVersion.major = 4;
  2177.         pInfo->hardwareVersion.minor = 1;
  2178. return CKR_OK;
  2179.     case PRIVATE_KEY_SLOT_ID:
  2180. PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
  2181. PORT_Memcpy(pInfo->slotDescription,privSlotDescription,64);
  2182. pInfo->flags = CKF_TOKEN_PRESENT;
  2183. /* ok we really should read it out of the keydb file. */
  2184.         pInfo->hardwareVersion.major = PRIVATE_KEY_DB_FILE_VERSION;
  2185.         pInfo->hardwareVersion.minor = 0;
  2186. return CKR_OK;
  2187.     default:
  2188. break;
  2189.     }
  2190.     return CKR_SLOT_ID_INVALID;
  2191. }
  2192. #define CKF_THREAD_SAFE 0x8000 /* for now */
  2193. /* NSC_GetTokenInfo obtains information about a particular token in 
  2194.  * the system. */
  2195. CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
  2196. {
  2197.     PK11Slot *slot = pk11_SlotFromID(slotID);
  2198.     SECKEYKeyDBHandle *handle;
  2199.     if (slot == NULL) return CKR_SLOT_ID_INVALID;
  2200.     PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
  2201.     PORT_Memcpy(pInfo->model,"Libsec 4.0      ",16);
  2202.     PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16);
  2203.     pInfo->ulMaxSessionCount = 0; /* arbitrarily large */
  2204.     pInfo->ulSessionCount = slot->sessionCount;
  2205.     pInfo->ulMaxRwSessionCount = 0; /* arbitarily large */
  2206.     pInfo->ulRwSessionCount = slot->rwSessionCount;
  2207.     pInfo->firmwareVersion.major = 0;
  2208.     pInfo->firmwareVersion.minor = 0;
  2209.     switch (slotID) {
  2210.     case NETSCAPE_SLOT_ID:
  2211. PORT_Memcpy(pInfo->label,tokDescription,32);
  2212.         pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE;
  2213. pInfo->ulMaxPinLen = 0;
  2214. pInfo->ulMinPinLen = 0;
  2215. pInfo->ulTotalPublicMemory = 0;
  2216. pInfo->ulFreePublicMemory = 0;
  2217. pInfo->ulTotalPrivateMemory = 0;
  2218. pInfo->ulFreePrivateMemory = 0;
  2219. pInfo->hardwareVersion.major = 4;
  2220. pInfo->hardwareVersion.minor = 0;
  2221. return CKR_OK;
  2222.     case PRIVATE_KEY_SLOT_ID:
  2223. PORT_Memcpy(pInfo->label,privTokDescription,32);
  2224.      handle = SECKEY_GetDefaultKeyDB();
  2225. /*
  2226.  * we have three possible states which we may be in:
  2227.  *   (1) No DB password has been initialized. This also means we
  2228.  *   have no keys in the key db.
  2229.  *   (2) Password initialized to NULL. This means we have keys, but
  2230.  *   the user has chosen not use a password.
  2231.  *   (3) Finally we have an initialized password whicn is not NULL, and
  2232.  *   we will need to prompt for it.
  2233.  */
  2234. if (SECKEY_HasKeyDBPassword(handle) == SECFailure) {
  2235.     pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED;
  2236. } else if (!slot->needLogin) {
  2237.     pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED;
  2238. } else {
  2239.     pInfo->flags = CKF_THREAD_SAFE | 
  2240. CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED;
  2241. }
  2242. pInfo->ulMaxPinLen = PK11_MAX_PIN;
  2243. pInfo->ulMinPinLen = 0;
  2244. if (minimumPinLen > 0) {
  2245.     pInfo->ulMinPinLen = (CK_ULONG)minimumPinLen;
  2246. }
  2247. pInfo->ulTotalPublicMemory = 1;
  2248. pInfo->ulFreePublicMemory = 1;
  2249. pInfo->ulTotalPrivateMemory = 1;
  2250. pInfo->ulFreePrivateMemory = 1;
  2251. pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
  2252. pInfo->hardwareVersion.minor = 0;
  2253. return CKR_OK;
  2254.     default:
  2255. break;
  2256.     }
  2257.     return CKR_SLOT_ID_INVALID;
  2258. }
  2259. /* NSC_GetMechanismList obtains a list of mechanism types 
  2260.  * supported by a token. */
  2261. CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID,
  2262. CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
  2263. {
  2264.     int i;
  2265.     switch (slotID) {
  2266.     case NETSCAPE_SLOT_ID:
  2267. *pulCount = mechanismCount;
  2268. if (pMechanismList != NULL) {
  2269.     for (i=0; i < (int) mechanismCount; i++) {
  2270. pMechanismList[i] = mechanisms[i].type;
  2271.     }
  2272. }
  2273. return CKR_OK;
  2274.     case PRIVATE_KEY_SLOT_ID:
  2275. *pulCount = 0;
  2276. for (i=0; i < (int) mechanismCount; i++) {
  2277.     if (mechanisms[i].privkey) {
  2278. (*pulCount)++;
  2279. if (pMechanismList != NULL) {
  2280.     *pMechanismList++ = mechanisms[i].type;
  2281. }
  2282.     }
  2283. }
  2284. return CKR_OK;
  2285.     default:
  2286. break;
  2287.     }
  2288.     return CKR_SLOT_ID_INVALID;
  2289. }
  2290. /* NSC_GetMechanismInfo obtains information about a particular mechanism 
  2291.  * possibly supported by a token. */
  2292. CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
  2293.      CK_MECHANISM_INFO_PTR pInfo)
  2294. {
  2295.     PRBool isPrivateKey;
  2296.     int i;
  2297.     switch (slotID) {
  2298.     case NETSCAPE_SLOT_ID:
  2299. isPrivateKey = PR_FALSE;
  2300. break;
  2301.     case PRIVATE_KEY_SLOT_ID:
  2302. isPrivateKey = PR_TRUE;
  2303. break;
  2304.     default:
  2305. return CKR_SLOT_ID_INVALID;
  2306.     }
  2307.     for (i=0; i < (int) mechanismCount; i++) {
  2308.         if (type == mechanisms[i].type) {
  2309.     if (isPrivateKey && !mechanisms[i].privkey) {
  2310.      return CKR_MECHANISM_INVALID;
  2311.     }
  2312.     PORT_Memcpy(pInfo,&mechanisms[i].domestic,
  2313. sizeof(CK_MECHANISM_INFO));
  2314.     return CKR_OK;
  2315. }
  2316.     }
  2317.     return CKR_MECHANISM_INVALID;
  2318. }
  2319. static SECStatus
  2320. pk11_TurnOffUser(CERTCertificate *cert, SECItem *k, void *arg)
  2321. {
  2322.    CERTCertTrust trust;
  2323.    SECStatus rv;
  2324.    rv = CERT_GetCertTrust(cert,&trust);
  2325.    if (rv == SECSuccess && ((trust.emailFlags & CERTDB_USER) ||
  2326.     (trust.sslFlags & CERTDB_USER) ||
  2327.     (trust.objectSigningFlags & CERTDB_USER))) {
  2328. trust.emailFlags &= ~CERTDB_USER;
  2329. trust.sslFlags &= ~CERTDB_USER;
  2330. trust.objectSigningFlags &= ~CERTDB_USER;
  2331. CERT_ChangeCertTrust(cert->dbhandle,cert,&trust);
  2332.    }
  2333.    return SECSuccess;
  2334. }
  2335. /* NSC_InitToken initializes a token. */
  2336. CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
  2337.   CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) {
  2338.     PK11Slot *slot = pk11_SlotFromID(slotID);
  2339.     SECKEYKeyDBHandle *handle;
  2340.     CERTCertDBHandle *certHandle;
  2341.     SECStatus rv;
  2342.     int i;
  2343.     PK11Object *object;
  2344.     if (slot == NULL) return CKR_SLOT_ID_INVALID;
  2345.     /* don't initialize the database if we aren't talking to a token
  2346.      * that uses the key database.
  2347.      */
  2348.     if (slotID == NETSCAPE_SLOT_ID) {
  2349. return CKR_TOKEN_WRITE_PROTECTED;
  2350.     }
  2351.     /* first, delete all our loaded key and cert objects from our 
  2352.      * internal list. */
  2353.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  2354.     for (i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) {
  2355. do {
  2356.     object = slot->tokObjects[i];
  2357.     /* hand deque */
  2358.     /* this duplicates function of NSC_close session functions, but 
  2359.      * because we know that we are freeing all the sessions, we can
  2360.      * do more efficient processing */
  2361.     if (object) {
  2362. slot->tokObjects[i] = object->next;
  2363. if (object->next) object->next->prev = NULL;
  2364. object->next = object->prev = NULL;
  2365.     }
  2366.     if (object) pk11_FreeObject(object);
  2367. } while (object != NULL);
  2368.     }
  2369.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  2370.     /* then clear out the key database */
  2371.     handle = SECKEY_GetDefaultKeyDB();
  2372.     if (handle == NULL) {
  2373. return CKR_TOKEN_WRITE_PROTECTED;
  2374.     }
  2375.     /* what to do on an error here? */
  2376.     rv = SECKEY_ResetKeyDB(handle);
  2377.     /* finally  mark all the user certs as non-user certs */
  2378.     certHandle = CERT_GetDefaultCertDB();
  2379.     if (certHandle == NULL) return CKR_OK;
  2380.     SEC_TraversePermCerts(certHandle,pk11_TurnOffUser, NULL);
  2381.     return CKR_OK; /*is this the right function for not implemented*/
  2382. }
  2383. /* NSC_InitPIN initializes the normal user's PIN. */
  2384. CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
  2385.      CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
  2386. {
  2387.     PK11Session *sp;
  2388.     PK11Slot *slot;
  2389.     SECKEYKeyDBHandle *handle;
  2390.     SECItem *newPin;
  2391.     char newPinStr[256];
  2392.     SECStatus rv;
  2393.     
  2394.     sp = pk11_SessionFromHandle(hSession);
  2395.     if (sp == NULL) {
  2396. return CKR_SESSION_HANDLE_INVALID;
  2397.     }
  2398.     if (sp->info.slotID == NETSCAPE_SLOT_ID) {
  2399. pk11_FreeSession(sp);
  2400. return CKR_PIN_LEN_RANGE;
  2401.     }
  2402.     /* should be an assert */
  2403.     if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || 
  2404. (sp->info.slotID == FIPS_SLOT_ID)) ) {
  2405. pk11_FreeSession(sp);
  2406. return CKR_SESSION_HANDLE_INVALID;;
  2407.     }
  2408.     if (sp->info.state != CKS_RW_SO_FUNCTIONS) {
  2409. pk11_FreeSession(sp);
  2410. return CKR_USER_NOT_LOGGED_IN;
  2411.     }
  2412.     slot = pk11_SlotFromSession(sp);
  2413.     pk11_FreeSession(sp);
  2414.     /* make sure the pins aren't too long */
  2415.     if (ulPinLen > 255) {
  2416. return CKR_PIN_LEN_RANGE;
  2417.     }
  2418.     handle = SECKEY_GetDefaultKeyDB();
  2419.     if (handle == NULL) {
  2420. return CKR_TOKEN_WRITE_PROTECTED;
  2421.     }
  2422.     if (SECKEY_HasKeyDBPassword(handle) != SECFailure) {
  2423. return CKR_DEVICE_ERROR;
  2424.     }
  2425.     /* convert to null terminated string */
  2426.     PORT_Memcpy(newPinStr,pPin,ulPinLen);
  2427.     newPinStr[ulPinLen] = 0; 
  2428.     /* build the hashed pins which we pass around */
  2429.     newPin = SECKEY_HashPassword(newPinStr,handle->global_salt);
  2430.     PORT_Memset(newPinStr,0,sizeof(newPinStr));
  2431.     /* change the data base */
  2432.     rv = SECKEY_SetKeyDBPassword(handle,newPin);
  2433.     /* Now update our local copy of the pin */
  2434.     if (rv == SECSuccess) {
  2435. if (slot->password) {
  2436.          SECITEM_ZfreeItem(slot->password, PR_TRUE);
  2437. }
  2438. slot->password = newPin;
  2439. if (ulPinLen == 0) slot->needLogin = PR_FALSE;
  2440. return CKR_OK;
  2441.     }
  2442.     SECITEM_ZfreeItem(newPin, PR_TRUE);
  2443.     return CKR_PIN_INCORRECT;
  2444. }
  2445. /* NSC_SetPIN modifies the PIN of user that is currently logged in. */
  2446. /* NOTE: This is only valid for the PRIVATE_KEY_SLOT */
  2447. CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
  2448.     CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
  2449. {
  2450.     PK11Session *sp;
  2451.     PK11Slot *slot;
  2452.     SECKEYKeyDBHandle *handle;
  2453.     SECItem *newPin;
  2454.     SECItem *oldPin;
  2455.     char newPinStr[256],oldPinStr[256];
  2456.     SECStatus rv;
  2457.     
  2458.     sp = pk11_SessionFromHandle(hSession);
  2459.     if (sp == NULL) {
  2460. return CKR_SESSION_HANDLE_INVALID;
  2461.     }
  2462.     if (sp->info.slotID == NETSCAPE_SLOT_ID) {
  2463. pk11_FreeSession(sp);
  2464. return CKR_PIN_LEN_RANGE;
  2465.     }
  2466.     /* should be an assert */
  2467.     /* should be an assert */
  2468.     if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || 
  2469. (sp->info.slotID == FIPS_SLOT_ID)) ) {
  2470. pk11_FreeSession(sp);
  2471. return CKR_SESSION_HANDLE_INVALID;;
  2472.     }
  2473.     slot = pk11_SlotFromSession(sp);
  2474.     if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) {
  2475. pk11_FreeSession(sp);
  2476. return CKR_USER_NOT_LOGGED_IN;
  2477.     }
  2478.     pk11_FreeSession(sp);
  2479.     /* make sure the pins aren't too long */
  2480.     if ((ulNewLen > 255) || (ulOldLen > 255)) {
  2481. return CKR_PIN_LEN_RANGE;
  2482.     }
  2483.     handle = SECKEY_GetDefaultKeyDB();
  2484.     if (handle == NULL) {
  2485. return CKR_TOKEN_WRITE_PROTECTED;
  2486.     }
  2487.     /* convert to null terminated string */
  2488.     PORT_Memcpy(newPinStr,pNewPin,ulNewLen);
  2489.     newPinStr[ulNewLen] = 0; 
  2490.     PORT_Memcpy(oldPinStr,pOldPin,ulOldLen);
  2491.     oldPinStr[ulOldLen] = 0; 
  2492.     /* build the hashed pins which we pass around */
  2493.     newPin = SECKEY_HashPassword(newPinStr,handle->global_salt);
  2494.     oldPin = SECKEY_HashPassword(oldPinStr,handle->global_salt);
  2495.     PORT_Memset(newPinStr,0,sizeof(newPinStr));
  2496.     PORT_Memset(oldPinStr,0,sizeof(oldPinStr));
  2497.     /* change the data base */
  2498.     rv = SECKEY_ChangeKeyDBPassword(handle,oldPin,newPin);
  2499.     /* Now update our local copy of the pin */
  2500.     SECITEM_ZfreeItem(oldPin, PR_TRUE);
  2501.     if (rv == SECSuccess) {
  2502. if (slot->password) {
  2503.          SECITEM_ZfreeItem(slot->password, PR_TRUE);
  2504. }
  2505. slot->password = newPin;
  2506. slot->needLogin = (PRBool)(ulNewLen != 0);
  2507. return CKR_OK;
  2508.     }
  2509.     SECITEM_ZfreeItem(newPin, PR_TRUE);
  2510.     return CKR_PIN_INCORRECT;
  2511. }
  2512. /* NSC_OpenSession opens a session between an application and a token. */
  2513. CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
  2514.    CK_VOID_PTR pApplication,CK_NOTIFY Notify,CK_SESSION_HANDLE_PTR phSession)
  2515. {
  2516.     PK11Slot *slot;
  2517.     CK_SESSION_HANDLE sessionID;
  2518.     PK11Session *session;
  2519.     slot = pk11_SlotFromID(slotID);
  2520.     if (slot == NULL) return CKR_SLOT_ID_INVALID;
  2521.     /* new session (we only have serial sessions) */
  2522.     session = pk11_NewSession(slotID, Notify, pApplication,
  2523.  flags | CKF_SERIAL_SESSION);
  2524.     if (session == NULL) return CKR_HOST_MEMORY;
  2525.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2526.     sessionID = slot->sessionIDCount++;
  2527.     if (slotID == PRIVATE_KEY_SLOT_ID) {
  2528. sessionID |= PK11_PRIVATE_KEY_FLAG;
  2529.     } else if (slotID == FIPS_SLOT_ID) {
  2530. sessionID |= PK11_FIPS_FLAG;
  2531.     } else if (flags & CKF_RW_SESSION) {
  2532. /* NETSCAPE_SLOT_ID is Read ONLY */
  2533. session->info.flags &= ~CKF_RW_SESSION;
  2534.     }
  2535.     session->handle = sessionID;
  2536.     pk11_update_state(slot, session);
  2537.     pk11queue_add(session, sessionID, slot->head, SESSION_HASH_SIZE);
  2538.     slot->sessionCount++;
  2539.     if (session->info.flags & CKF_RW_SESSION) {
  2540. slot->rwSessionCount++;
  2541.     }
  2542.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2543.     *phSession = sessionID;
  2544.     return CKR_OK;
  2545. }
  2546. /* NSC_CloseSession closes a session between an application and a token. */
  2547. CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
  2548. {
  2549.     PK11Slot *slot;
  2550.     PK11Session *session;
  2551.     SECItem *pw = NULL;
  2552.     session = pk11_SessionFromHandle(hSession);
  2553.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2554.     slot = pk11_SlotFromSession(session);
  2555.     /* lock */
  2556.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2557.     if (pk11queue_is_queued(session,hSession,slot->head,SESSION_HASH_SIZE)) {
  2558. pk11queue_delete(session,hSession,slot->head,SESSION_HASH_SIZE);
  2559. session->refCount--; /* can't go to zero while we hold the reference */
  2560. slot->sessionCount--;
  2561. if (session->info.flags & CKF_RW_SESSION) {
  2562.     slot->rwSessionCount--;
  2563. }
  2564.     }
  2565.     if (slot->sessionCount == 0) {
  2566. pw = slot->password;
  2567. slot->isLoggedIn = PR_FALSE;
  2568. slot->password = NULL;
  2569.     }
  2570.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2571.     pk11_FreeSession(session);
  2572.     if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
  2573.     return CKR_OK;
  2574. }
  2575. /* NSC_CloseAllSessions closes all sessions with a token. */
  2576. CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
  2577. {
  2578.     PK11Slot *slot;
  2579.     SECItem *pw = NULL;
  2580.     PK11Session *session;
  2581.     int i;
  2582.     slot = pk11_SlotFromID(slotID);
  2583.     if (slot == NULL) return CKR_SLOT_ID_INVALID;
  2584.     /* first log out the card */
  2585.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2586.     pw = slot->password;
  2587.     slot->isLoggedIn = PR_FALSE;
  2588.     slot->password = NULL;
  2589.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2590.     if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
  2591.     /* now close all the current sessions */
  2592.     /* NOTE: If you try to open new sessions before NSC_CloseAllSessions
  2593.      * completes, some of those new sessions may or may not be closed by
  2594.      * NSC_CloseAllSessions... but any session running when this code starts
  2595.      * will guarrenteed be close, and no session will be partially closed */
  2596.     for (i=0; i < SESSION_HASH_SIZE; i++) {
  2597. do {
  2598.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2599.     session = slot->head[i];
  2600.     /* hand deque */
  2601.     /* this duplicates function of NSC_close session functions, but 
  2602.      * because we know that we are freeing all the sessions, we can
  2603.      * do more efficient processing */
  2604.     if (session) {
  2605. slot->head[i] = session->next;
  2606. if (session->next) session->next->prev = NULL;
  2607. session->next = session->prev = NULL;
  2608. slot->sessionCount--;
  2609. if (session->info.flags & CKF_RW_SESSION) {
  2610.     slot->rwSessionCount--;
  2611. }
  2612.     }
  2613.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2614.     if (session) pk11_FreeSession(session);
  2615. } while (session != NULL);
  2616.     }
  2617.     return CKR_OK;
  2618. }
  2619. /* NSC_GetSessionInfo obtains information about the session. */
  2620. CK_RV NSC_GetSessionInfo(CK_SESSION_HANDLE hSession,
  2621.      CK_SESSION_INFO_PTR pInfo)
  2622. {
  2623.     PK11Session *session;
  2624.     session = pk11_SessionFromHandle(hSession);
  2625.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2626.     PORT_Memcpy(pInfo,&session->info,sizeof(CK_SESSION_INFO));
  2627.     pk11_FreeSession(session);
  2628.     return CKR_OK;
  2629. }
  2630. /* NSC_Login logs a user into a token. */
  2631. CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
  2632.     CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
  2633. {
  2634.     PK11Slot *slot;
  2635.     PK11Session *session;
  2636.     SECKEYKeyDBHandle *handle;
  2637.     SECItem *pin;
  2638.     char pinStr[256];
  2639.     /* get the slot */
  2640.     slot = pk11_SlotFromSessionHandle(hSession);
  2641.     /* make sure the session is valid */
  2642.     session = pk11_SessionFromHandle(hSession);
  2643.     if (session == NULL) {
  2644. if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2645.     }
  2646.     pk11_FreeSession(session);
  2647.     /* can't log into the Netscape Slot */
  2648.     if (slot->slotID == NETSCAPE_SLOT_ID)
  2649.  return CKR_USER_TYPE_INVALID;
  2650.     if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN;
  2651.     slot->ssoLoggedIn = PR_FALSE;
  2652.     if (ulPinLen > 255) return CKR_PIN_LEN_RANGE;
  2653.     /* convert to null terminated string */
  2654.     PORT_Memcpy(pinStr,pPin,ulPinLen);
  2655.     pinStr[ulPinLen] = 0; 
  2656.     handle = SECKEY_GetDefaultKeyDB();
  2657.     /*
  2658.      * Deal with bootstrap. We allow the SSO to login in with a NULL
  2659.      * password if and only if we haven't initialized the KEY DB yet.
  2660.      * We only allow this on a RW session.
  2661.      */
  2662.     if (SECKEY_HasKeyDBPassword(handle) == SECFailure) {
  2663. /* allow SSO's to log in only if there is not password on the
  2664.  * key database */
  2665. if (((userType == CKU_SO) && (session->info.flags & CKF_RW_SESSION))
  2666.     /* fips always needs to authenticate, even if there isn't a db */
  2667. || (slot->slotID == FIPS_SLOT_ID)) {
  2668.     /* should this be a fixed password? */
  2669.     if (ulPinLen == 0) {
  2670. SECItem *pw;
  2671.      PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2672. pw = slot->password;
  2673. slot->password = NULL;
  2674. slot->isLoggedIn = PR_TRUE;
  2675. slot->ssoLoggedIn = (PRBool)(userType == CKU_SO);
  2676. PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2677. pk11_update_all_states(slot);
  2678. SECITEM_ZfreeItem(pw,PR_TRUE);
  2679. return CKR_OK;
  2680.     }
  2681.     return CKR_PIN_INCORRECT;
  2682. return CKR_USER_TYPE_INVALID;
  2683.     } 
  2684.     /* don't allow the SSO to log in if the user is already initialized */
  2685.     if (userType != CKU_USER) { return CKR_USER_TYPE_INVALID; }
  2686.     /* build the hashed pins which we pass around */
  2687.     pin = SECKEY_HashPassword(pinStr,handle->global_salt);
  2688.     if (pin == NULL) return CKR_HOST_MEMORY;
  2689.     if (SECKEY_CheckKeyDBPassword(handle,pin) == SECSuccess) {
  2690. SECItem *tmp;
  2691. PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2692. tmp = slot->password;
  2693. slot->isLoggedIn = PR_TRUE;
  2694. slot->password = pin;
  2695. PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2696.         if (tmp) SECITEM_ZfreeItem(tmp, PR_TRUE);
  2697. /* update all sessions */
  2698. pk11_update_all_states(slot);
  2699. return CKR_OK;
  2700.     }
  2701.     SECITEM_ZfreeItem(pin, PR_TRUE);
  2702.     return CKR_PIN_INCORRECT;
  2703. }
  2704. /* NSC_Logout logs a user out from a token. */
  2705. CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
  2706. {
  2707.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  2708.     PK11Session *session;
  2709.     SECItem *pw = NULL;
  2710.     session = pk11_SessionFromHandle(hSession);
  2711.     if (session == NULL) {
  2712. if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2713.     }
  2714.     if (!slot->isLoggedIn) return CKR_USER_NOT_LOGGED_IN;
  2715.     PK11_USE_THREADS(PR_Lock(slot->sessionLock);)
  2716.     pw = slot->password;
  2717.     slot->isLoggedIn = PR_FALSE;
  2718.     slot->ssoLoggedIn = PR_FALSE;
  2719.     slot->password = NULL;
  2720.     PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)
  2721.     if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
  2722.     pk11_update_all_states(slot);
  2723.     return CKR_OK;
  2724. }
  2725. /* NSC_CreateObject creates a new object. */
  2726. CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
  2727. CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, 
  2728. CK_OBJECT_HANDLE_PTR phObject)
  2729. {
  2730.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  2731.     PK11Session *session;
  2732.     PK11Object *object;
  2733.     CK_RV crv;
  2734.     int i;
  2735.     /*
  2736.      * now lets create an object to hang the attributes off of
  2737.      */
  2738.     object = pk11_NewObject(slot); /* fill in the handle later */
  2739.     if (object == NULL) {
  2740. return CKR_HOST_MEMORY;
  2741.     }
  2742.     /*
  2743.      * load the template values into the object
  2744.      */
  2745.     for (i=0; i < (int) ulCount; i++) {
  2746. crv = pk11_AddAttributeType(object,pk11_attr_expand(&pTemplate[i]));
  2747. if (crv != CKR_OK) {
  2748.     pk11_FreeObject(object);
  2749.     return crv;
  2750. }
  2751.     }
  2752.     /* get the session */
  2753.     session = pk11_SessionFromHandle(hSession);
  2754.     if (session == NULL) {
  2755. pk11_FreeObject(object);
  2756.         return CKR_SESSION_HANDLE_INVALID;
  2757.     }
  2758.     /*
  2759.      * handle the base object stuff
  2760.      */
  2761.     crv = pk11_handleObject(object,session);
  2762.     pk11_FreeSession(session);
  2763.     if (crv != CKR_OK) {
  2764. pk11_FreeObject(object);
  2765. return crv;
  2766.     }
  2767.     *phObject = object->handle;
  2768.     return CKR_OK;
  2769. }
  2770. /* NSC_CopyObject copies an object, creating a new object for the copy. */
  2771. CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession,
  2772.        CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
  2773. CK_OBJECT_HANDLE_PTR phNewObject) 
  2774. {
  2775.     PK11Object *destObject,*srcObject;
  2776.     PK11Session *session;
  2777.     CK_RV crv = CKR_OK;
  2778.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  2779.     int i;
  2780.     /* Get srcObject so we can find the class */
  2781.     session = pk11_SessionFromHandle(hSession);
  2782.     if (session == NULL) {
  2783.         return CKR_SESSION_HANDLE_INVALID;
  2784.     }
  2785.     srcObject = pk11_ObjectFromHandle(hObject,session);
  2786.     if (srcObject == NULL) {
  2787. pk11_FreeSession(session);
  2788. return CKR_OBJECT_HANDLE_INVALID;
  2789.     }
  2790.     /*
  2791.      * create an object to hang the attributes off of
  2792.      */
  2793.     destObject = pk11_NewObject(slot); /* fill in the handle later */
  2794.     if (destObject == NULL) {
  2795. pk11_FreeSession(session);
  2796.         pk11_FreeObject(srcObject);
  2797. return CKR_HOST_MEMORY;
  2798.     }
  2799.     /*
  2800.      * load the template values into the object
  2801.      */
  2802.     for (i=0; i < (int) ulCount; i++) {
  2803. if (pk11_modifyType(pTemplate[i].type,srcObject->objclass) == PK11_NEVER) {
  2804.     crv = CKR_ATTRIBUTE_READ_ONLY;
  2805.     break;
  2806. }
  2807. crv = pk11_AddAttributeType(destObject,pk11_attr_expand(&pTemplate[i]));
  2808. if (crv != CKR_OK) { break; }
  2809.     }
  2810.     if (crv != CKR_OK) {
  2811. pk11_FreeSession(session);
  2812.         pk11_FreeObject(srcObject);
  2813. pk11_FreeObject(destObject);
  2814. return crv;
  2815.     }
  2816.     /* sensitive can only be changed to CK_TRUE */
  2817.     if (pk11_hasAttribute(destObject,CKA_SENSITIVE)) {
  2818. if (!pk11_isTrue(destObject,CKA_SENSITIVE)) {
  2819.     pk11_FreeSession(session);
  2820.             pk11_FreeObject(srcObject);
  2821.     pk11_FreeObject(destObject);
  2822.     return CKR_ATTRIBUTE_READ_ONLY;
  2823. }
  2824.     }
  2825.     /*
  2826.      * now copy the old attributes from the new attributes
  2827.      */
  2828.     /* don't create a token object if we aren't in a rw session */
  2829.     /* we need to hold the lock to copy a consistant version of
  2830.      * the object. */
  2831.     crv = pk11_CopyObject(destObject,srcObject);
  2832.     destObject->objclass = srcObject->objclass;
  2833.     pk11_FreeObject(srcObject);
  2834.     if (crv != CKR_OK) {
  2835. pk11_FreeObject(destObject);
  2836. pk11_FreeSession(session);
  2837.     }
  2838.     crv = pk11_handleObject(destObject,session);
  2839.     *phNewObject = destObject->handle;
  2840.     pk11_FreeSession(session);
  2841.     if (crv != CKR_OK) {
  2842. pk11_FreeObject(destObject);
  2843. return crv;
  2844.     }
  2845.     
  2846.     return CKR_OK;
  2847. }
  2848. /* NSC_GetObjectSize gets the size of an object in bytes. */
  2849. CK_RV NSC_GetObjectSize(CK_SESSION_HANDLE hSession,
  2850.      CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) {
  2851.     *pulSize = 0;
  2852.     return CKR_OK;
  2853. }
  2854. /* NSC_GetAttributeValue obtains the value of one or more object attributes. */
  2855. CK_RV NSC_GetAttributeValue(CK_SESSION_HANDLE hSession,
  2856.     CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) {
  2857.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  2858.     PK11Session *session;
  2859.     PK11Object *object;
  2860.     PK11Attribute *attribute;
  2861.     PRBool sensitive;
  2862.     int i;
  2863.     /*
  2864.      * make sure we're allowed
  2865.      */
  2866.     session = pk11_SessionFromHandle(hSession);
  2867.     if (session == NULL) {
  2868.         return CKR_SESSION_HANDLE_INVALID;
  2869.     }
  2870.     object = pk11_ObjectFromHandle(hObject,session);
  2871.     pk11_FreeSession(session);
  2872.     if (object == NULL) {
  2873. return CKR_OBJECT_HANDLE_INVALID;
  2874.     }
  2875.     /* don't read a private object if we aren't logged in */
  2876.     if ((!slot->isLoggedIn) && (slot->needLogin) &&
  2877. (pk11_isTrue(object,CKA_PRIVATE))) {
  2878. pk11_FreeObject(object);
  2879. return CKR_USER_NOT_LOGGED_IN;
  2880.     }
  2881.     sensitive = pk11_isTrue(object,CKA_SENSITIVE);
  2882.     for (i=0; i < (int) ulCount; i++) {
  2883. /* Make sure that this attribute is retrievable */
  2884. if (sensitive && pk11_isSensitive(pTemplate[i].type,object->objclass)) {
  2885.     pk11_FreeObject(object);
  2886.     return CKR_ATTRIBUTE_SENSITIVE;
  2887. }
  2888. attribute = pk11_FindAttribute(object,pTemplate[i].type);
  2889. if (attribute == NULL) {
  2890.     pk11_FreeObject(object);
  2891.     return CKR_ATTRIBUTE_TYPE_INVALID;
  2892. }
  2893. if (pTemplate[i].pValue != NULL) {
  2894.     PORT_Memcpy(pTemplate[i].pValue,attribute->attrib.pValue,
  2895. attribute->attrib.ulValueLen);
  2896. }
  2897. pTemplate[i].ulValueLen = attribute->attrib.ulValueLen;
  2898. pk11_FreeAttribute(attribute);
  2899.     }
  2900.     pk11_FreeObject(object);
  2901.     return CKR_OK;
  2902. }
  2903. /* NSC_SetAttributeValue modifies the value of one or more object attributes */
  2904. CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession,
  2905.  CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) {
  2906.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  2907.     PK11Session *session;
  2908.     PK11Attribute *attribute;
  2909.     PK11Object *object;
  2910.     PRBool isToken;
  2911.     CK_RV crv = CKR_OK;
  2912.     CK_BBOOL legal;
  2913.     int i;
  2914.     /*
  2915.      * make sure we're allowed
  2916.      */
  2917.     session = pk11_SessionFromHandle(hSession);
  2918.     if (session == NULL) {
  2919.         return CKR_SESSION_HANDLE_INVALID;
  2920.     }
  2921.     object = pk11_ObjectFromHandle(hObject,session);
  2922.     if (object == NULL) {
  2923.         pk11_FreeSession(session);
  2924. return CKR_OBJECT_HANDLE_INVALID;
  2925.     }
  2926.     /* don't modify a private object if we aren't logged in */
  2927.     if ((!slot->isLoggedIn) && (slot->needLogin) &&
  2928. (pk11_isTrue(object,CKA_PRIVATE))) {
  2929. pk11_FreeSession(session);
  2930. pk11_FreeObject(object);
  2931. return CKR_USER_NOT_LOGGED_IN;
  2932.     }
  2933.     /* don't modify a token object if we aren't in a rw session */
  2934.     isToken = pk11_isTrue(object,CKA_TOKEN);
  2935.     if (((session->info.flags & CKF_RW_SESSION) == 0) && isToken) {
  2936. pk11_FreeSession(session);
  2937. pk11_FreeObject(object);
  2938. return CKR_SESSION_READ_ONLY;
  2939.     }
  2940.     pk11_FreeSession(session);
  2941.     /* only change modifiable objects */
  2942.     if (!pk11_isTrue(object,CKA_MODIFIABLE)) {
  2943. pk11_FreeObject(object);
  2944. return CKR_ATTRIBUTE_READ_ONLY;
  2945.     }
  2946.     for (i=0; i < (int) ulCount; i++) {
  2947. /* Make sure that this attribute is changeable */
  2948. switch (pk11_modifyType(pTemplate[i].type,object->objclass)) {
  2949. case PK11_NEVER:
  2950. case PK11_ONCOPY:
  2951.         default:
  2952.     crv = CKR_ATTRIBUTE_READ_ONLY;
  2953.     break;
  2954.         case PK11_SENSITIVE:
  2955.     legal = (pTemplate[i].type == CKA_EXTRACTABLE) ? CK_FALSE : CK_TRUE;
  2956.     if ((*(CK_BBOOL *)pTemplate[i].pValue) != legal) {
  2957.         crv = CKR_ATTRIBUTE_READ_ONLY;
  2958.     }
  2959.     break;
  2960.         case PK11_ALWAYS:
  2961.     break;
  2962. }
  2963. if (crv != CKR_OK) break;
  2964. /* find the old attribute */
  2965. attribute = pk11_FindAttribute(object,pTemplate[i].type);
  2966. if (attribute == NULL) {
  2967.     crv =CKR_ATTRIBUTE_TYPE_INVALID;
  2968.     break;
  2969. }
  2970.      pk11_FreeAttribute(attribute);
  2971. crv = pk11_forceAttribute(object,pk11_attr_expand(&pTemplate[i]));
  2972. if (crv != CKR_OK) break;
  2973.     }
  2974.     pk11_FreeObject(object);
  2975.     return CKR_OK;
  2976. }
  2977. /* stolen from keydb.c */
  2978. #define KEYDB_PW_CHECK_STRING   "password-check"
  2979. #define KEYDB_PW_CHECK_LEN      14
  2980. SECKEYLowPrivateKey * SECKEY_DecryptKey(DBT *key, SECItem *pwitem,
  2981. SECKEYKeyDBHandle *handle);
  2982. typedef struct pk11keyNodeStr {
  2983.     struct pk11keyNodeStr *next;
  2984.     SECKEYLowPrivateKey *privKey;
  2985.     CERTCertificate *cert;
  2986.     SECItem *pubItem;
  2987. } pk11keyNode;
  2988. typedef struct {
  2989.     PLArenaPool *arena;
  2990.     pk11keyNode *head;
  2991.     PK11Slot *slot;
  2992. } keyList;
  2993. static SECStatus
  2994. add_key_to_list(DBT *key, DBT *data, void *arg)
  2995. {
  2996.     keyList *keylist;
  2997.     pk11keyNode *node;
  2998.     void *keydata;
  2999.     SECKEYLowPrivateKey *privKey = NULL;
  3000.     
  3001.     keylist = (keyList *)arg;
  3002.     privKey = SECKEY_DecryptKey(key, keylist->slot->password,
  3003. SECKEY_GetDefaultKeyDB());
  3004.     if ( privKey == NULL ) {
  3005. goto loser;
  3006.     }
  3007.     /* allocate the node struct */
  3008.     node = (pk11keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(pk11keyNode));
  3009.     if ( node == NULL ) {
  3010. goto loser;
  3011.     }
  3012.     
  3013.     /* allocate room for key data */
  3014.     keydata = PORT_ArenaZAlloc(keylist->arena, key->size);
  3015.     if ( keydata == NULL ) {
  3016. goto loser;
  3017.     }
  3018.     /* link node into list */
  3019.     node->next = keylist->head;
  3020.     keylist->head = node;
  3021.     
  3022.     node->privKey = privKey;
  3023.     switch (privKey->keyType) {
  3024.       case rsaKey:
  3025. node->pubItem = &privKey->u.rsa.modulus;
  3026. break;
  3027.       case dsaKey:
  3028. node->pubItem = &privKey->u.dsa.publicValue;
  3029. break;
  3030.       default:
  3031. break;
  3032.     }
  3033.     
  3034.     return(SECSuccess);
  3035. loser:
  3036.     if ( privKey ) {
  3037. SECKEY_LowDestroyPrivateKey(privKey);
  3038.     }
  3039.     return(SECSuccess);
  3040. }
  3041. /*
  3042.  * If the cert is a user cert, then try to match it to a key on the
  3043.  * linked list of private keys built earlier.
  3044.  * If the cert matches one on the list, then save it.
  3045.  */
  3046. static SECStatus
  3047. add_cert_to_list(CERTCertificate *cert, SECItem *k, void *pdata)
  3048. {
  3049.     keyList *keylist;
  3050.     pk11keyNode *node;
  3051.     SECKEYPublicKey *pubKey = NULL;
  3052.     SECItem *pubItem;
  3053.     CERTCertificate *oldcert;
  3054.     
  3055.     keylist = (keyList *)pdata;
  3056.     
  3057.     /* only if it is a user cert and has a nickname!! */
  3058.     if ( ( ( cert->trust->sslFlags & CERTDB_USER ) ||
  3059.   ( cert->trust->emailFlags & CERTDB_USER ) ||
  3060.   ( cert->trust->objectSigningFlags & CERTDB_USER ) ) &&
  3061. ( cert->nickname != NULL ) ) {
  3062. /* get cert's public key */
  3063. pubKey = CERT_ExtractPublicKey(cert);
  3064. if ( pubKey == NULL ) {
  3065.     goto done;
  3066. }
  3067. /* pk11_GetPubItem returns data associated with the public key.
  3068.  * one only needs to free the public key. This comment is here
  3069.  * because this sematic would be non-obvious otherwise.
  3070.  */
  3071. pubItem = pk11_GetPubItem(pubKey);
  3072. if (pubItem == NULL) goto done;
  3073. node = keylist->head;
  3074. while ( node ) {
  3075.     /* if key type is different, then there is no match */
  3076.     if ( node->privKey->keyType == pubKey->keyType ) {
  3077. /* compare public value from cert with public value from
  3078.  * the key
  3079.  */
  3080. if ( SECITEM_CompareItem(pubItem, node->pubItem) == SECEqual ){
  3081.     /* this is a match */
  3082.     /* if no cert has yet been found for this key, or this
  3083.      * cert is newer, then save this cert
  3084.      */
  3085.     if ( ( node->cert == NULL ) || 
  3086. CERT_IsNewer(cert, node->cert ) ) {
  3087. oldcert = node->cert;
  3088. /* get a real DB copy of the cert, since the one
  3089.  * passed in here is not properly recorded in the
  3090.  * temp database
  3091.  */
  3092. /* We need a better way to deal with this */
  3093. node->cert =
  3094.     CERT_FindCertByKeyNoLocking(CERT_GetDefaultCertDB(),
  3095.         &cert->certKey);
  3096. /* free the old cert if there was one */
  3097. if ( oldcert ) {
  3098.     CERT_DestroyCertificate(oldcert);
  3099. }
  3100.     }
  3101. }
  3102.     }
  3103.     
  3104.     node = node->next;
  3105. }
  3106.     }
  3107. done:
  3108.     if ( pubKey ) {
  3109. SECKEY_DestroyPublicKey(pubKey);
  3110.     }
  3111.     return(SECSuccess);
  3112. }
  3113. #if 0
  3114. /* This appears to be obsolete - TNH */
  3115. static SECItem *
  3116. decodeKeyDBGlobalSalt(DBT *saltData)
  3117. {
  3118.     SECItem *saltitem;
  3119.     
  3120.     saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
  3121.     if ( saltitem == NULL ) {
  3122. return(NULL);
  3123.     }
  3124.     
  3125.     saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size);
  3126.     if ( saltitem->data == NULL ) {
  3127. PORT_Free(saltitem);
  3128. return(NULL);
  3129.     }
  3130.     
  3131.     saltitem->len = saltData->size;
  3132.     PORT_Memcpy(saltitem->data, saltData->data, saltitem->len);
  3133.     
  3134.     return(saltitem);
  3135. }
  3136. #endif
  3137. #if 0
  3138. /*
  3139.  * Create a (fixed) DES3 key [ testing ]
  3140.  */
  3141. static unsigned char keyValue[] = {
  3142.   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
  3143.   0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
  3144.   0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17
  3145. };
  3146. static SECItem keyItem = {
  3147.   0,
  3148.   keyValue,
  3149.   sizeof keyValue
  3150. };
  3151. static unsigned char keyID[] = {
  3152.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  3153.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  3154. };
  3155. static SECItem keyIDItem = {
  3156.   0,
  3157.   keyID,
  3158.   sizeof keyID
  3159. };
  3160. /* +AAA */
  3161. static CK_RV
  3162. pk11_createFixedDES3Key(PK11Slot *slot)
  3163. {
  3164.     CK_RV rv = CKR_OK;
  3165.     PK11Object *keyObject;
  3166.     CK_BBOOL true = CK_TRUE;
  3167.     CK_OBJECT_CLASS class = CKO_SECRET_KEY;
  3168.     CK_KEY_TYPE keyType = CKK_DES3;
  3169.     /*
  3170.      * Create the object
  3171.      */
  3172.     keyObject = pk11_NewObject(slot); /* fill in the handle later */
  3173.     if (keyObject == NULL) {
  3174. return CKR_HOST_MEMORY;
  3175.     }
  3176.     /* Add attributes to the object */
  3177.     rv = pk11_AddAttributeType(keyObject, CKA_ID, keyID, sizeof keyID);
  3178.     if (rv != CKR_OK) {
  3179.  pk11_FreeObject(keyObject);
  3180.  return rv;
  3181.     }
  3182.     rv = pk11_AddAttributeType(keyObject, CKA_VALUE, keyValue, sizeof keyValue);
  3183.     if (rv != CKR_OK) {
  3184.  pk11_FreeObject(keyObject);
  3185.  return rv;
  3186.     }
  3187.     rv = pk11_AddAttributeType(keyObject, CKA_TOKEN, &true, sizeof true);
  3188.     if (rv != CKR_OK) {
  3189.  pk11_FreeObject(keyObject);
  3190.  return rv;
  3191.     }
  3192.     rv = pk11_AddAttributeType(keyObject, CKA_CLASS, &class, sizeof class);
  3193.     if (rv != CKR_OK) {
  3194.  pk11_FreeObject(keyObject);
  3195.  return rv;
  3196.     }
  3197.     rv = pk11_AddAttributeType(keyObject, CKA_KEY_TYPE, &keyType, sizeof keyType);
  3198.     if (rv != CKR_OK) {
  3199.  pk11_FreeObject(keyObject);
  3200.  return rv;
  3201.     }
  3202.     pk11_handleSecretKeyObject(keyObject, keyType, PR_TRUE);
  3203.     PK11_USE_THREADS(PR_Lock(slot->objectLock);)
  3204.     keyObject->handle = slot->tokenIDCount++;
  3205.     PK11_USE_THREADS(PR_Unlock(slot->objectLock);)
  3206.     keyObject->slot = slot;
  3207.     keyObject->objclass = CKO_SECRET_KEY;
  3208.     pk11_AddSlotObject(slot, keyObject);
  3209.     return rv;
  3210. }
  3211. #endif /* Fixed DES key */
  3212. /*
  3213.  * load up our token database
  3214.  */
  3215. static CK_RV
  3216. pk11_importKeyDB(PK11Slot *slot)
  3217. {
  3218.     keyList keylist;
  3219.     pk11keyNode *node;
  3220.     CK_RV crv;
  3221.     SECStatus rv;
  3222.     PK11Object *privateKeyObject;
  3223.     PK11Object *publicKeyObject;
  3224.     PK11Object *certObject;
  3225.     /* traverse the database, collecting the index keys of all
  3226.      * records into a linked list
  3227.      */
  3228.     keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  3229.     if ( keylist.arena  == NULL ) {
  3230. return CKR_HOST_MEMORY;
  3231.     }
  3232.     keylist.head = NULL;
  3233.     keylist.slot = slot;
  3234.     /* collect all of the keys */
  3235.     rv = SECKEY_TraverseKeys(SECKEY_GetDefaultKeyDB(),
  3236.       add_key_to_list, (void *)&keylist);
  3237.     if (rv != SECSuccess) {
  3238. PORT_FreeArena(keylist.arena, PR_FALSE);
  3239. return CKR_HOST_MEMORY;
  3240.     }
  3241.     /* find certs that match any of the keys */
  3242.     crv = SEC_TraversePermCerts(CERT_GetDefaultCertDB(),
  3243.        add_cert_to_list, (void *)&keylist);
  3244.     if ( crv != SECSuccess ) {
  3245. PORT_FreeArena(keylist.arena, PR_FALSE);
  3246. return CKR_HOST_MEMORY;
  3247.     }
  3248.     /* now traverse the list and entry certs/keys into the
  3249.      * pkcs11 world
  3250.      */
  3251.     for (node = keylist.head;  node != NULL; node=node->next ) {
  3252.         /* Check for "special" private key that wraps a symmetric key */
  3253.         if (isSecretKey(node->privKey)) {
  3254.           importSecretKey(slot, node->privKey);
  3255.           goto end_loop;
  3256.         }
  3257. /* create the private key object */
  3258. privateKeyObject = pk11_importPrivateKey(slot, node->privKey, 
  3259. node->pubItem);
  3260. if ( privateKeyObject == NULL ) {
  3261.     goto end_loop;
  3262. }
  3263. publicKeyObject = pk11_importPublicKey(slot, node->privKey, NULL,
  3264. node->pubItem);
  3265. if ( node->cert ) {
  3266.     /* Now import the Cert */
  3267.     certObject = pk11_importCertificate(slot, node->cert,
  3268. node->pubItem->data,
  3269. node->pubItem->len, PR_TRUE);
  3270.     /* Copy the subject */
  3271.     if ( certObject ) {
  3272. /* NOTE: cert has been adopted */
  3273. PK11Attribute *attribute;
  3274. /* Copy the Subject */
  3275. attribute = pk11_FindAttribute(certObject,CKA_SUBJECT);
  3276. if (attribute) {
  3277.     pk11_forceAttribute(privateKeyObject,
  3278. pk11_attr_expand(&attribute->attrib));
  3279.     if (publicKeyObject) {
  3280. pk11_forceAttribute(publicKeyObject,
  3281. pk11_attr_expand(&attribute->attrib));
  3282.     }
  3283.     pk11_FreeAttribute(attribute);
  3284. }
  3285. pk11_FreeObject(certObject);
  3286.     }
  3287. }
  3288. if ( publicKeyObject != NULL ) {
  3289.     pk11_AddSlotObject(slot, publicKeyObject);
  3290. }
  3291. pk11_AddSlotObject(slot, privateKeyObject);
  3292. end_loop:
  3293. SECKEY_LowDestroyPrivateKey(node->privKey);
  3294. if ( node->cert ) {
  3295.     CERT_DestroyCertificate(node->cert);
  3296. }
  3297.     }
  3298.     PORT_FreeArena(keylist.arena, PR_FALSE);
  3299.     return CKR_OK;
  3300. }
  3301. /*
  3302.  * structure to collect certs into
  3303.  */
  3304. typedef struct pk11CertDataStr {
  3305.     int cert_count;
  3306.     int max_cert_count;
  3307.     CERTCertificate **certs;
  3308. } pk11CertData;
  3309. /*
  3310.  * collect all the certs from the traverse call.
  3311.  */
  3312. static SECStatus
  3313. pk11_cert_collect(CERTCertificate *cert,void *arg) {
  3314.     pk11CertData *cd = (pk11CertData *)arg;
  3315.     /* shouldn't happen, but don't crash if it does */
  3316.     if (cd->cert_count >= cd->max_cert_count) {
  3317. PORT_Assert(0);
  3318. return SECFailure;
  3319.     }
  3320.     cd->certs[cd->cert_count++] = CERT_DupCertificate(cert);
  3321.     return SECSuccess;
  3322. }
  3323. /*
  3324.  * find any certs that may match the template and load them.
  3325.  */
  3326. static void
  3327. pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) {
  3328.     int i;
  3329.     SECItem derCert = { siBuffer, NULL, 0 };
  3330.     SECItem derSubject = { siBuffer, NULL, 0 };
  3331.     SECItem name = { siBuffer, NULL, 0 };
  3332.     CERTIssuerAndSN issuerSN = {
  3333. { siBuffer, NULL, 0 },
  3334. { NULL, NULL },
  3335. { siBuffer, NULL, 0 }
  3336.     };
  3337.     SECItem *copy = NULL;
  3338.     CERTCertDBHandle *handle = NULL;
  3339.     SECKEYKeyDBHandle *keyHandle = NULL;
  3340.     pk11CertData certData;
  3341.     /*
  3342.      * These should be stored in the slot some day in the future
  3343.      */
  3344.     handle = CERT_GetDefaultCertDB();
  3345.     if (handle == NULL) return;
  3346.     keyHandle = SECKEY_GetDefaultKeyDB();
  3347.     if (keyHandle == NULL) return;
  3348.     /*
  3349.      * look for things to search on certs for. We only need one of these
  3350.      * items. If we find all the certs that match that item, import them
  3351.      * (as long as they are user certs). We'll let find objects filter out
  3352.      * the ones that don't apply.
  3353.      */
  3354.     for (i=0 ;i < (int)ulCount; i++) {
  3355. switch (pTemplate[i].type) {
  3356. case CKA_SUBJECT: copy = &derSubject; break;
  3357. case CKA_ISSUER: copy = &issuerSN.derIssuer; break;
  3358. case CKA_SERIAL_NUMBER: copy = &issuerSN.serialNumber; break;
  3359. case CKA_VALUE: copy = &derCert; break;
  3360. case CKA_LABEL: copy = &name; break;
  3361. case CKA_CLASS:
  3362.     if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) {
  3363. return;
  3364.     }
  3365.     if (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE) {
  3366. return;
  3367.     }
  3368.     copy = NULL; break;
  3369. case CKA_PRIVATE:
  3370.     if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
  3371. return;
  3372.     }
  3373.     if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_FALSE) {
  3374. return;
  3375.     }
  3376.     copy = NULL; break;
  3377. case CKA_TOKEN:
  3378.     if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
  3379. return;
  3380.     }
  3381.     if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
  3382. return;
  3383.     }
  3384.     copy = NULL; break;
  3385. case CKA_CERTIFICATE_TYPE:
  3386. case CKA_ID:
  3387. case CKA_MODIFIABLE:
  3388.      copy = NULL; break;
  3389. /* can't be a certificate if it doesn't match one of the above 
  3390.  * attributes */
  3391. default: return;
  3392. }
  3393.   if (copy) {
  3394.     copy->data = (unsigned char*)pTemplate[i].pValue;
  3395.     copy->len = pTemplate[i].ulValueLen;
  3396. }
  3397.     }
  3398.     certData.max_cert_count = 0;
  3399.     certData.certs = NULL;
  3400.     certData.cert_count = 0;
  3401.     if (derCert.data != NULL) {
  3402. CERTCertificate *cert = CERT_FindCertByDERCert(handle,&derCert);
  3403. if (cert != NULL) {
  3404.    certData.certs = 
  3405. (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *));
  3406.    if (certData.certs) {
  3407. certData.certs[0] = cert;
  3408.     certData.cert_count = 1;
  3409.    } else CERT_DestroyCertificate(cert);
  3410. }
  3411.     } else if (name.data != NULL) {
  3412. char *tmp_name = (char*)PORT_Alloc(name.len+1);
  3413. if (tmp_name == NULL) {
  3414.     return;
  3415. }
  3416. PORT_Memcpy(tmp_name,name.data,name.len);
  3417. tmp_name[name.len] = 0;
  3418. certData.max_cert_count=CERT_NumPermCertsForNickname(handle,tmp_name);
  3419. if (certData.max_cert_count > 0) {
  3420.     certData.certs = (CERTCertificate **) 
  3421. PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *));
  3422.     if (certData.certs) {
  3423.      CERT_TraversePermCertsForNickname(handle,tmp_name,
  3424. pk11_cert_collect, &certData);
  3425.     }
  3426.    
  3427. }
  3428. PORT_Free(tmp_name);
  3429.     } else if (derSubject.data != NULL) {
  3430. certData.max_cert_count=CERT_NumPermCertsForSubject(handle,&derSubject);
  3431. if (certData.max_cert_count > 0) {
  3432.     certData.certs = (CERTCertificate **) 
  3433. PORT_Alloc(certData.max_cert_count *sizeof(CERTCertificate *));
  3434.     if (certData.certs) {
  3435.      CERT_TraversePermCertsForSubject(handle,&derSubject,
  3436. pk11_cert_collect, &certData);
  3437.     }
  3438. }
  3439.     } else if ((issuerSN.derIssuer.data != NULL) && 
  3440. (issuerSN.serialNumber.data != NULL)) {
  3441. CERTCertificate *cert = CERT_FindCertByIssuerAndSN(handle,&issuerSN);
  3442. if (cert != NULL) {
  3443.    certData.certs = 
  3444. (CERTCertificate **) PORT_Alloc(sizeof (CERTCertificate *));
  3445.    if (certData.certs) {
  3446. certData.certs[0] = cert;
  3447.     certData.cert_count = 1;
  3448.    } else CERT_DestroyCertificate(cert);
  3449. }
  3450.     } else {
  3451. /* PORT_Assert(0); may get called when not looking for certs */
  3452. /* look up all the certs sometime, and get rid of the assert */;
  3453.     }
  3454.     for (i=0 ; i < certData.cert_count ; i++) {
  3455. CERTCertificate *cert = certData.certs[i];
  3456. /* we are only interested in permanment user certs here */
  3457. if ((cert->isperm) && (cert->trust) && 
  3458.        (( cert->trust->sslFlags & CERTDB_USER ) ||
  3459.    ( cert->trust->emailFlags & CERTDB_USER ) ||
  3460.    ( cert->trust->objectSigningFlags & CERTDB_USER )) &&
  3461.   ( cert->nickname != NULL )  &&
  3462. (SECKEY_KeyForCertExists(keyHandle, cert) == SECSuccess)) {
  3463.     PK11Object *obj;
  3464.     pk11_importCertificate(slot, cert, NULL, 0, PR_FALSE);
  3465.     obj = pk11_importPublicKey(slot, NULL, cert, NULL);
  3466.     if (obj) pk11_AddSlotObject(slot, obj);
  3467. }
  3468. CERT_DestroyCertificate(cert);
  3469.     }
  3470.     if (certData.certs) PORT_Free(certData.certs);
  3471.     return;
  3472. }
  3473. /* NSC_FindObjectsInit initializes a search for token and session objects 
  3474.  * that match a template. */
  3475. CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession,
  3476.      CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)
  3477. {
  3478.     PK11ObjectListElement *objectList = NULL;
  3479.     PK11ObjectListElement *olp;
  3480.     PK11SearchResults *search,*freeSearch;
  3481.     PK11Session *session;
  3482.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  3483.     int count, i;
  3484.     CK_RV crv;
  3485.     
  3486.     session = pk11_SessionFromHandle(hSession);
  3487.     if (session == NULL) {
  3488. return CKR_SESSION_HANDLE_INVALID;
  3489.     }
  3490.     
  3491.     /* resync token objects with the data base */
  3492.     if ((session->info.slotID == PRIVATE_KEY_SLOT_ID) || 
  3493.      (session->info.slotID == FIPS_SLOT_ID)) {
  3494. if (slot->DB_loaded == PR_FALSE) {
  3495.     /* if we aren't logged in, we can't unload all key keys
  3496.      * and certs. Just unload those certs we need for this search
  3497.      */
  3498.          if ((!slot->isLoggedIn) && (slot->needLogin)) {
  3499. pk11_searchCerts(slot,pTemplate,ulCount);
  3500.     } else {
  3501. pk11_importKeyDB(slot);
  3502. slot->DB_loaded = PR_TRUE;
  3503.    }
  3504. }
  3505.     }
  3506.     
  3507.     /* build list of found objects in the session */
  3508.     crv = pk11_searchObjectList(&objectList,slot->tokObjects,
  3509. slot->objectLock, pTemplate, ulCount, (PRBool)((!slot->needLogin) ||
  3510. slot->isLoggedIn));
  3511.     if (crv != CKR_OK) {
  3512. pk11_FreeObjectList(objectList);
  3513. pk11_FreeSession(session);
  3514. return crv;
  3515.     }
  3516.     /* copy list to session */
  3517.     count = 0;
  3518.     for (olp = objectList; olp != NULL; olp = olp->next) {
  3519. count++;
  3520.     }
  3521.     search = (PK11SearchResults *)PORT_Alloc(sizeof(PK11SearchResults));
  3522.     if (search == NULL) {
  3523. pk11_FreeObjectList(objectList);
  3524. pk11_FreeSession(session);
  3525. return CKR_HOST_MEMORY;
  3526.     }
  3527.     search->handles = (CK_OBJECT_HANDLE *)
  3528. PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * count);
  3529.     if (search->handles == NULL) {
  3530. PORT_Free(search);
  3531. pk11_FreeObjectList(objectList);
  3532. pk11_FreeSession(session);
  3533. return CKR_HOST_MEMORY;
  3534.     }
  3535.     for (i=0; i < count; i++) {
  3536. search->handles[i] = objectList->object->handle;
  3537. objectList = pk11_FreeObjectListElement(objectList);
  3538.     }
  3539.     /* store the search info */
  3540.     search->index = 0;
  3541.     search->size = count;
  3542.     if ((freeSearch = session->search) != NULL) {
  3543. session->search = NULL;
  3544. pk11_FreeSearch(freeSearch);
  3545.     }
  3546.     session->search = search;
  3547.     pk11_FreeSession(session);
  3548.     return CKR_OK;
  3549. }
  3550. /* NSC_FindObjects continues a search for token and session objects 
  3551.  * that match a template, obtaining additional object handles. */
  3552. CK_RV NSC_FindObjects(CK_SESSION_HANDLE hSession,
  3553.     CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,
  3554.      CK_ULONG_PTR pulObjectCount)
  3555. {
  3556.     PK11Session *session;
  3557.     PK11SearchResults *search;
  3558.     int transfer;
  3559.     int left;
  3560.     *pulObjectCount = 0;
  3561.     session = pk11_SessionFromHandle(hSession);
  3562.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  3563.     if (session->search == NULL) {
  3564. pk11_FreeSession(session);
  3565. return CKR_OK;
  3566.     }
  3567.     search = session->search;
  3568.     left = session->search->size - session->search->index;
  3569.     transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
  3570.     PORT_Memcpy(phObject,&search->handles[search->index],
  3571. transfer*sizeof(CK_OBJECT_HANDLE_PTR));
  3572.     search->index += transfer;
  3573.     if (search->index == search->size) {
  3574. session->search = NULL;
  3575. pk11_FreeSearch(search);
  3576.     }
  3577.     *pulObjectCount = transfer;
  3578.     return CKR_OK;
  3579. }
  3580. /* NSC_FindObjectsFinal finishes a search for token and session objects. */
  3581. CK_RV NSC_FindObjectsFinal(CK_SESSION_HANDLE hSession)
  3582. {
  3583.     PK11Session *session;
  3584.     PK11SearchResults *search;
  3585.     session = pk11_SessionFromHandle(hSession);
  3586.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  3587.     search = session->search;
  3588.     session->search = NULL;
  3589.     if (search == NULL) {
  3590. pk11_FreeSession(session);
  3591. return CKR_OK;
  3592.     }
  3593.     pk11_FreeSearch(search);
  3594.     return CKR_OK;
  3595. }
  3596. CK_RV NSC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot,
  3597.  CK_VOID_PTR pReserved)
  3598. {
  3599.     return CKR_FUNCTION_NOT_SUPPORTED;
  3600. }