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

CA认证

开发平台:

WINDOWS

  1.     context->multi = PR_TRUE;
  2.     switch(pMechanism->mechanism) {
  3.     case CKM_RSA_PKCS:
  4.     case CKM_RSA_X_509:
  5. if (key_type != CKK_RSA) {
  6.     crv = CKR_KEY_TYPE_INCONSISTENT;
  7.     break;
  8. }
  9. context->multi = PR_FALSE;
  10. pubKey = pk11_GetPubKey(key,CKK_RSA);
  11. if (pubKey == NULL) {
  12.     crv = CKR_HOST_MEMORY;
  13.     break;
  14. }
  15. context->cipherInfo = pubKey;
  16. context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
  17. ? RSA_CheckSignRecoverRaw : RSA_CheckSignRecover);
  18. context->destroy = pk11_Null;
  19. break;
  20.     default:
  21. crv = CKR_MECHANISM_INVALID;
  22. break;
  23.     }
  24.     pk11_FreeObject(key);
  25.     if (crv != CKR_OK) {
  26.         PORT_Free(context);
  27. pk11_FreeSession(session);
  28. return crv;
  29.     }
  30.     pk11_SetContextByType(session, PK11_VERIFY_RECOVER, context);
  31.     pk11_FreeSession(session);
  32.     return CKR_OK;
  33. }
  34. /* NSC_VerifyRecover verifies a signature in a single-part operation, 
  35.  * where the data is recovered from the signature. 
  36.  * E.g. Decryption with the user's public key */
  37. CK_RV NSC_VerifyRecover(CK_SESSION_HANDLE hSession,
  38.  CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen,
  39.      CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)
  40. {
  41.     PK11Session *session;
  42.     PK11SessionContext *context;
  43.     unsigned int outlen;
  44.     unsigned int maxoutlen = *pulDataLen;
  45.     CK_RV crv;
  46.     SECStatus rv;
  47.     /* make sure we're legal */
  48.     crv = pk11_GetContext(hSession,&context,PK11_VERIFY_RECOVER,
  49. PR_FALSE,&session);
  50.     if (crv != CKR_OK) return crv;
  51.     rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, 
  52. pSignature, ulSignatureLen);
  53.     *pulDataLen = (CK_ULONG) outlen;
  54.     pk11_FreeContext(context);
  55.     pk11_SetContextByType(session, PK11_VERIFY_RECOVER, NULL);
  56.     pk11_FreeSession(session);
  57.     return (rv == SECSuccess)  ? CKR_OK : CKR_DEVICE_ERROR;
  58. }
  59. /*
  60.  **************************** Random Functions:  ************************
  61.  */
  62. /* NSC_SeedRandom mixes additional seed material into the token's random number 
  63.  * generator. */
  64. CK_RV NSC_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed,
  65.     CK_ULONG ulSeedLen) 
  66. {
  67.     SECStatus rv;
  68.     rv = RNG_RandomUpdate(pSeed, ulSeedLen);
  69.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  70. }
  71. /* NSC_GenerateRandom generates random data. */
  72. CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession,
  73.     CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
  74. {
  75.     SECStatus rv;
  76.     rv = RNG_GenerateGlobalRandomBytes(pRandomData, ulRandomLen);
  77.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  78. }
  79. /*
  80.  **************************** Key Functions:  ************************
  81.  */
  82. /*
  83.  * generate a password based encryption key. This code uses
  84.  * PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is
  85.  * a utility function in secpkcs5.c.  This function is used in here
  86.  * and in PK11_ParamToAlgid.
  87.  */
  88. CK_RV
  89. pk11_pbe_key_gen(SECOidTag algtag,CK_MECHANISM_PTR pMechanism,
  90. char *buf,int *key_length, PRBool faulty3DES)
  91. {
  92.     SECAlgorithmID algid;
  93.     SECItem *pbe_key = NULL, mech;
  94.     CK_PBE_PARAMS *pbe_params = NULL;
  95.     SECStatus pbe_rv;
  96.     *key_length = 0;
  97.     mech.data = (unsigned char *)pMechanism->pParameter;
  98.     mech.len = (unsigned int)pMechanism->ulParameterLen;
  99.     /* A common routine to map from Params to AlgIDs for PBE
  100.      * algorithms was created in secpkcs5.c.  This function is
  101.      * called both by PK11_ParamToAlgid and this function.
  102.      */
  103.     pbe_rv = PBE_PK11ParamToAlgid(algtag, &mech, NULL, &algid);
  104.     if (pbe_rv != SECSuccess) {
  105. return CKR_DATA_INVALID;
  106.     }
  107.     pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter;
  108.     mech.data = (unsigned char *)pbe_params->pPassword;
  109.     mech.len = (unsigned int)pbe_params->ulPasswordLen;
  110.     pbe_key = SEC_PKCS5GetKey(&algid, &mech, faulty3DES);
  111.     if (pbe_key == NULL) {
  112. SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
  113. return CKR_HOST_MEMORY;
  114.     }
  115.     PORT_Memcpy(buf, pbe_key->data, pbe_key->len);
  116.     *key_length = pbe_key->len;
  117.     SECITEM_ZfreeItem(pbe_key, PR_TRUE);
  118.     pbe_key = NULL;
  119.     if (pbe_params->pInitVector == NULL) {
  120. pbe_key = SEC_PKCS5GetIV(&algid, &mech, faulty3DES);
  121. if (pbe_key == NULL) {
  122.     SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
  123.     SECITEM_ZfreeItem(pbe_key, PR_TRUE);
  124.     return CKR_HOST_MEMORY;
  125. }
  126. pbe_params->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(pbe_key->len);
  127. if (pbe_params->pInitVector == NULL) {
  128.     SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
  129.     SECITEM_ZfreeItem(pbe_key, PR_TRUE);
  130.     return CKR_HOST_MEMORY;
  131. }
  132. PORT_Memcpy(pbe_params->pInitVector, pbe_key->data, pbe_key->len);
  133.     }
  134.     SECITEM_ZfreeItem(pbe_key, PR_TRUE);
  135.     SECOID_DestroyAlgorithmID(&algid, PR_FALSE);
  136.     return CKR_OK;
  137. }
  138. /* NSC_GenerateKey generates a secret key, creating a new key object. */
  139. CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,
  140.     CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,
  141.      CK_OBJECT_HANDLE_PTR phKey)
  142. {
  143.     PK11Object *key;
  144.     PK11Session *session;
  145.     PRBool checkWeak = PR_FALSE;
  146.     int key_length = 0;
  147.     CK_KEY_TYPE key_type;
  148.     CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;
  149.     CK_RV crv = CKR_OK;
  150.     CK_BBOOL cktrue = CK_TRUE;
  151.     int i;
  152.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  153.     char buf[MAX_KEY_LEN];
  154.     enum {pk11_pbe, pk11_ssl, pk11_bulk} key_gen_type;
  155.     SECOidTag algtag = SEC_OID_UNKNOWN;
  156.     SSL3RSAPreMasterSecret *rsa_pms;
  157.     CK_VERSION *version;
  158.     /* in very old versions of NSS, there were implementation errors with key 
  159.      * generation methods.  We want to beable to read these, but not 
  160.      * produce them any more.  The affected algorithm was 3DES.
  161.      */
  162.     PRBool faultyPBE3DES = PR_FALSE;
  163.     /*
  164.      * now lets create an object to hang the attributes off of
  165.      */
  166.     key = pk11_NewObject(slot); /* fill in the handle later */
  167.     if (key == NULL) {
  168. return CKR_HOST_MEMORY;
  169.     }
  170.     /*
  171.      * load the template values into the object
  172.      */
  173.     for (i=0; i < (int) ulCount; i++) {
  174. if (pTemplate[i].type == CKA_VALUE_LEN) {
  175.     key_length = *(CK_ULONG *)pTemplate[i].pValue;
  176.     continue;
  177. }
  178. crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
  179. if (crv != CKR_OK) break;
  180.     }
  181.     if (crv != CKR_OK) {
  182. pk11_FreeObject(key);
  183. return crv;
  184.     }
  185.     /* make sure we don't have any class, key_type, or value fields */
  186.     pk11_DeleteAttributeType(key,CKA_CLASS);
  187.     pk11_DeleteAttributeType(key,CKA_KEY_TYPE);
  188.     pk11_DeleteAttributeType(key,CKA_VALUE);
  189.     /* Now Set up the parameters to generate the key (based on mechanism) */
  190.     key_gen_type = pk11_bulk; /* bulk key by default */
  191.     switch (pMechanism->mechanism) {
  192.     case CKM_RC2_KEY_GEN:
  193. key_type = CKK_RC2;
  194. if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
  195. break;
  196. #if NSS_SOFTOKEN_DOES_RC5
  197.     case CKM_RC5_KEY_GEN:
  198. key_type = CKK_RC5;
  199. if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
  200. break;
  201. #endif
  202.     case CKM_RC4_KEY_GEN:
  203. key_type = CKK_RC4;
  204. if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
  205. break;
  206.     case CKM_GENERIC_SECRET_KEY_GEN:
  207. key_type = CKK_GENERIC_SECRET;
  208. if (key_length == 0) crv = CKR_TEMPLATE_INCOMPLETE;
  209. break;
  210.     case CKM_CDMF_KEY_GEN:
  211. key_type = CKK_CDMF;
  212. key_length = 8;
  213. checkWeak = PR_TRUE;
  214. break;
  215.     case CKM_DES_KEY_GEN:
  216. key_type = CKK_DES;
  217. key_length = 8;
  218. checkWeak = PR_TRUE;
  219. break;
  220.     case CKM_DES2_KEY_GEN:
  221. key_type = CKK_DES2;
  222. key_length = 16;
  223. checkWeak = PR_TRUE;
  224. break;
  225.     case CKM_DES3_KEY_GEN:
  226. key_type = CKK_DES3;
  227. key_length = 24;
  228. checkWeak = PR_TRUE;
  229. break;
  230.     case CKM_SSL3_PRE_MASTER_KEY_GEN:
  231. key_type = CKK_GENERIC_SECRET;
  232. key_length = 48;
  233. key_gen_type = pk11_ssl;
  234. break;
  235.     case CKM_PBE_MD2_DES_CBC:
  236. algtag = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC;
  237. key_type = CKK_DES;
  238. goto have_key_type;
  239.     case CKM_PBE_MD5_DES_CBC:
  240. algtag = SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC;
  241. key_type = CKK_DES;
  242. goto have_key_type;
  243.     case CKM_NETSCAPE_PBE_SHA1_DES_CBC:
  244. algtag = SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC;
  245. key_type = CKK_DES;
  246. goto have_key_type;
  247.     case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:
  248. faultyPBE3DES = PR_TRUE;
  249.     case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:
  250. algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC;
  251. key_type = CKK_DES3;
  252. goto have_key_type;
  253.     case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:
  254. algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
  255. key_type = CKK_RC2;
  256. goto have_key_type;
  257.     case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:
  258. algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
  259. key_type = CKK_RC2;
  260. goto have_key_type;
  261.     case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:
  262. algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4;
  263. key_type = CKK_RC4;
  264. goto have_key_type;
  265.     case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:
  266. algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4;
  267. key_type = CKK_RC4;
  268. goto have_key_type;
  269.     case CKM_PBE_SHA1_RC4_40:
  270. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4;
  271. key_length = 5;
  272. key_type = CKK_RC4;
  273. goto have_key_type;
  274.     case CKM_PBE_SHA1_RC4_128:
  275. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4;
  276. key_length = 16;
  277. key_type = CKK_RC4;
  278. goto have_key_type;
  279.     case CKM_PBE_SHA1_RC2_40_CBC:
  280. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC;
  281. key_length = 5;
  282. key_type = CKK_RC2;
  283. goto have_key_type;
  284.     case CKM_PBE_SHA1_RC2_128_CBC:
  285. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC;
  286. key_length = 16;
  287. key_type = CKK_RC2;
  288. goto have_key_type;
  289.     case CKM_PBE_SHA1_DES3_EDE_CBC:
  290. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC;
  291. key_length = 24;
  292. key_type = CKK_DES3;
  293. goto have_key_type;
  294.     case CKM_PBE_SHA1_DES2_EDE_CBC:
  295. algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC;
  296. key_length = 16;
  297. key_type = CKK_DES2;
  298. checkWeak = PR_FALSE;
  299. have_key_type:
  300. key_gen_type = pk11_pbe;
  301. break;
  302.     default:
  303. crv = CKR_MECHANISM_INVALID;
  304.     }
  305.     /* make sure we aren't going to overflow the buffer */
  306.     if (sizeof(buf) < key_length) {
  307. /* someone is getting pretty optimistic about how big their key can
  308.  * be... */
  309.         crv = CKR_TEMPLATE_INCONSISTENT;
  310.     }
  311.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  312.     /*
  313.      * now to the actual key gen.
  314.      */
  315.     switch (key_gen_type) {
  316.     case pk11_pbe:
  317. crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length,
  318.        faultyPBE3DES);
  319. break;
  320.     case pk11_ssl:
  321. rsa_pms = (SSL3RSAPreMasterSecret *)buf;
  322. version = (CK_VERSION *)pMechanism->pParameter;
  323. rsa_pms->client_version[0] = version->major;
  324.         rsa_pms->client_version[1] = version->minor;
  325.         crv = 
  326.     NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));
  327. break;
  328.     case pk11_bulk:
  329. /* get the key, check for weak keys and repeat if found */
  330. do {
  331.             crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length);
  332. } while (crv == CKR_OK && checkWeak && 
  333. pk11_IsWeakKey((unsigned char *)buf,key_type));
  334. break;
  335.     }
  336.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  337.     /* Add the class, key_type, and value */
  338.     crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
  339.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  340.     crv = pk11_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));
  341.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  342.     crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));
  343.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  344.     crv = pk11_AddAttributeType(key,CKA_VALUE,buf,key_length);
  345.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  346.     /* get the session */
  347.     session = pk11_SessionFromHandle(hSession);
  348.     if (session == NULL) {
  349. pk11_FreeObject(key);
  350.         return CKR_SESSION_HANDLE_INVALID;
  351.     }
  352.     /*
  353.      * handle the base object stuff
  354.      */
  355.     crv = pk11_handleObject(key,session);
  356.     pk11_FreeSession(session);
  357.     if (crv != CKR_OK) {
  358. pk11_FreeObject(key);
  359. return crv;
  360.     }
  361.     if (pk11_isTrue(key,CKA_SENSITIVE)) {
  362. pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));
  363.     }
  364.     if (!pk11_isTrue(key,CKA_EXTRACTABLE)) {
  365. pk11_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));
  366.     }
  367.     *phKey = key->handle;
  368.     return CKR_OK;
  369. }
  370. /* NSC_GenerateKeyPair generates a public-key/private-key pair, 
  371.  * creating new key objects. */
  372. CK_RV NSC_GenerateKeyPair (CK_SESSION_HANDLE hSession,
  373.     CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate,
  374.     CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
  375.     CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPrivateKey,
  376.      CK_OBJECT_HANDLE_PTR phPublicKey)
  377. {
  378.     PK11Object * publicKey,*privateKey;
  379.     PK11Session * session;
  380.     CK_KEY_TYPE  key_type;
  381.     CK_RV  crv  = CKR_OK;
  382.     CK_BBOOL  cktrue  = CK_TRUE;
  383.     SECStatus  rv;
  384.     CK_OBJECT_CLASS  pubClass = CKO_PUBLIC_KEY;
  385.     CK_OBJECT_CLASS  privClass = CKO_PRIVATE_KEY;
  386.     int  i;
  387.     PK11Slot * slot  = pk11_SlotFromSessionHandle(hSession);
  388.     /* RSA */
  389.     int  public_modulus_bits = 0;
  390.     SECItem  pubExp;
  391.     RSAPrivateKey * rsaPriv;
  392.     /* DSA */
  393.     PQGParams  pqgParam;
  394.     DHParams   dhParam;
  395.     DSAPrivateKey * dsaPriv;
  396.     /* Diffie Hellman */
  397.     int  private_value_bits = 0;
  398.     DHPrivateKey * dhPriv;
  399.     /*
  400.      * now lets create an object to hang the attributes off of
  401.      */
  402.     publicKey = pk11_NewObject(slot); /* fill in the handle later */
  403.     if (publicKey == NULL) {
  404. return CKR_HOST_MEMORY;
  405.     }
  406.     /*
  407.      * load the template values into the publicKey
  408.      */
  409.     for (i=0; i < (int) ulPublicKeyAttributeCount; i++) {
  410. if (pPublicKeyTemplate[i].type == CKA_MODULUS_BITS) {
  411.     public_modulus_bits = *(CK_ULONG *)pPublicKeyTemplate[i].pValue;
  412.     continue;
  413. }
  414. crv = pk11_AddAttributeType(publicKey,
  415.     pk11_attr_expand(&pPublicKeyTemplate[i]));
  416. if (crv != CKR_OK) break;
  417.     }
  418.     if (crv != CKR_OK) {
  419. pk11_FreeObject(publicKey);
  420. return CKR_HOST_MEMORY;
  421.     }
  422.     privateKey = pk11_NewObject(slot); /* fill in the handle later */
  423.     if (privateKey == NULL) {
  424. pk11_FreeObject(publicKey);
  425. return CKR_HOST_MEMORY;
  426.     }
  427.     /*
  428.      * now load the private key template
  429.      */
  430.     for (i=0; i < (int) ulPrivateKeyAttributeCount; i++) {
  431. if (pPrivateKeyTemplate[i].type == CKA_VALUE_BITS) {
  432.     private_value_bits = *(CK_ULONG *)pPrivateKeyTemplate[i].pValue;
  433.     continue;
  434. }
  435. crv = pk11_AddAttributeType(privateKey,
  436.     pk11_attr_expand(&pPrivateKeyTemplate[i]));
  437. if (crv != CKR_OK) break;
  438.     }
  439.     if (crv != CKR_OK) {
  440. pk11_FreeObject(publicKey);
  441. pk11_FreeObject(privateKey);
  442. return CKR_HOST_MEMORY;
  443.     }
  444.     pk11_DeleteAttributeType(privateKey,CKA_CLASS);
  445.     pk11_DeleteAttributeType(privateKey,CKA_KEY_TYPE);
  446.     pk11_DeleteAttributeType(privateKey,CKA_VALUE);
  447.     pk11_DeleteAttributeType(publicKey,CKA_CLASS);
  448.     pk11_DeleteAttributeType(publicKey,CKA_KEY_TYPE);
  449.     pk11_DeleteAttributeType(publicKey,CKA_VALUE);
  450.     /* Now Set up the parameters to generate the key (based on mechanism) */
  451.     switch (pMechanism->mechanism) {
  452.     case CKM_RSA_PKCS_KEY_PAIR_GEN:
  453. /* format the keys */
  454.      pk11_DeleteAttributeType(publicKey,CKA_MODULUS);
  455.      pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
  456.      pk11_DeleteAttributeType(privateKey,CKA_MODULUS);
  457.      pk11_DeleteAttributeType(privateKey,CKA_PRIVATE_EXPONENT);
  458.      pk11_DeleteAttributeType(privateKey,CKA_PUBLIC_EXPONENT);
  459.      pk11_DeleteAttributeType(privateKey,CKA_PRIME_1);
  460.      pk11_DeleteAttributeType(privateKey,CKA_PRIME_2);
  461.      pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_1);
  462.      pk11_DeleteAttributeType(privateKey,CKA_EXPONENT_2);
  463.      pk11_DeleteAttributeType(privateKey,CKA_COEFFICIENT);
  464. key_type = CKK_RSA;
  465. if (public_modulus_bits == 0) {
  466.     crv = CKR_TEMPLATE_INCOMPLETE;
  467.     break;
  468. }
  469. /* extract the exponent */
  470. crv=pk11_Attribute2SSecItem(NULL,&pubExp,publicKey,CKA_PUBLIC_EXPONENT);
  471. if (crv != CKR_OK) break;
  472.         crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT,
  473.          pk11_item_expand(&pubExp));
  474. if (crv != CKR_OK) {
  475.     PORT_Free(pubExp.data);
  476.     break;
  477. }
  478. rsaPriv = RSA_NewKey(public_modulus_bits, &pubExp);
  479. PORT_Free(pubExp.data);
  480. if (rsaPriv == NULL) {
  481.     crv = CKR_HOST_MEMORY;
  482.     break;
  483. }
  484.         /* now fill in the RSA dependent paramenters in the public key */
  485.         crv = pk11_AddAttributeType(publicKey,CKA_MODULUS,
  486.    pk11_item_expand(&rsaPriv->modulus));
  487. if (crv != CKR_OK) goto kpg_done;
  488.         /* now fill in the RSA dependent paramenters in the private key */
  489.         crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
  490.    pk11_item_expand(&rsaPriv->modulus));
  491. if (crv != CKR_OK) goto kpg_done;
  492.         crv = pk11_AddAttributeType(privateKey,CKA_MODULUS,
  493.    pk11_item_expand(&rsaPriv->modulus));
  494. if (crv != CKR_OK) goto kpg_done;
  495.         crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,
  496.    pk11_item_expand(&rsaPriv->privateExponent));
  497. if (crv != CKR_OK) goto kpg_done;
  498.         crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,
  499.    pk11_item_expand(&rsaPriv->prime1));
  500. if (crv != CKR_OK) goto kpg_done;
  501.         crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,
  502.    pk11_item_expand(&rsaPriv->prime2));
  503. if (crv != CKR_OK) goto kpg_done;
  504.         crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,
  505.    pk11_item_expand(&rsaPriv->exponent1));
  506. if (crv != CKR_OK) goto kpg_done;
  507.         crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,
  508.    pk11_item_expand(&rsaPriv->exponent2));
  509. if (crv != CKR_OK) goto kpg_done;
  510.         crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,
  511.    pk11_item_expand(&rsaPriv->coefficient));
  512. kpg_done:
  513. /* Should zeroize the contents first, since this func doesn't. */
  514. PORT_FreeArena(rsaPriv->arena, PR_TRUE);
  515. break;
  516.     case CKM_DSA_KEY_PAIR_GEN:
  517.      pk11_DeleteAttributeType(publicKey,CKA_VALUE);
  518.      pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB);
  519. pk11_DeleteAttributeType(privateKey,CKA_PRIME);
  520. pk11_DeleteAttributeType(privateKey,CKA_SUBPRIME);
  521. pk11_DeleteAttributeType(privateKey,CKA_BASE);
  522. key_type = CKK_DSA;
  523. /* extract the necessary paramters and copy them to the private key */
  524. crv=pk11_Attribute2SSecItem(NULL,&pqgParam.prime,publicKey,CKA_PRIME);
  525. if (crv != CKR_OK) break;
  526. crv=pk11_Attribute2SSecItem(NULL,&pqgParam.subPrime,publicKey,
  527.                             CKA_SUBPRIME);
  528. if (crv != CKR_OK) {
  529.     PORT_Free(pqgParam.prime.data);
  530.     break;
  531. }
  532. crv=pk11_Attribute2SSecItem(NULL,&pqgParam.base,publicKey,CKA_BASE);
  533. if (crv != CKR_OK) {
  534.     PORT_Free(pqgParam.prime.data);
  535.     PORT_Free(pqgParam.subPrime.data);
  536.     break;
  537. }
  538.         crv = pk11_AddAttributeType(privateKey,CKA_PRIME,
  539.     pk11_item_expand(&pqgParam.prime));
  540. if (crv != CKR_OK) {
  541.     PORT_Free(pqgParam.prime.data);
  542.     PORT_Free(pqgParam.subPrime.data);
  543.     PORT_Free(pqgParam.base.data);
  544.     break;
  545. }
  546.         crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME,
  547.          pk11_item_expand(&pqgParam.subPrime));
  548. if (crv != CKR_OK) {
  549.     PORT_Free(pqgParam.prime.data);
  550.     PORT_Free(pqgParam.subPrime.data);
  551.     PORT_Free(pqgParam.base.data);
  552.     break;
  553. }
  554.         crv = pk11_AddAttributeType(privateKey,CKA_BASE,
  555.          pk11_item_expand(&pqgParam.base));
  556. if (crv != CKR_OK) {
  557.     PORT_Free(pqgParam.prime.data);
  558.     PORT_Free(pqgParam.subPrime.data);
  559.     PORT_Free(pqgParam.base.data);
  560.     break;
  561. }
  562. /* Generate the key */
  563. rv = DSA_NewKey(&pqgParam, &dsaPriv);
  564. PORT_Free(pqgParam.prime.data);
  565. PORT_Free(pqgParam.subPrime.data);
  566. PORT_Free(pqgParam.base.data);
  567. if (rv != SECSuccess) { crv = CKR_HOST_MEMORY; break; }
  568. /* store the generated key into the attributes */
  569.         crv = pk11_AddAttributeType(publicKey,CKA_VALUE,
  570.    pk11_item_expand(&dsaPriv->publicValue));
  571. if (crv != CKR_OK) goto dsagn_done;
  572.         /* now fill in the RSA dependent paramenters in the private key */
  573.         crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB,
  574.    pk11_item_expand(&dsaPriv->publicValue));
  575. if (crv != CKR_OK) goto dsagn_done;
  576.         crv = pk11_AddAttributeType(privateKey,CKA_VALUE,
  577.    pk11_item_expand(&dsaPriv->privateValue));
  578. dsagn_done:
  579. /* should zeroize, since this function doesn't. */
  580. PORT_FreeArena(dsaPriv->params.arena, PR_TRUE);
  581. break;
  582.     case CKM_DH_PKCS_KEY_PAIR_GEN:
  583. pk11_DeleteAttributeType(privateKey,CKA_PRIME);
  584. pk11_DeleteAttributeType(privateKey,CKA_BASE);
  585. pk11_DeleteAttributeType(privateKey,CKA_VALUE);
  586. key_type = CKK_DH;
  587. /* extract the necessary parameters and copy them to private keys */
  588.         crv = pk11_Attribute2SSecItem(NULL, &dhParam.prime, publicKey, 
  589.       CKA_PRIME);
  590. if (crv != CKR_OK) break;
  591. crv = pk11_Attribute2SSecItem(NULL, &dhParam.base, publicKey, CKA_BASE);
  592. if (crv != CKR_OK) {
  593.   PORT_Free(dhParam.prime.data);
  594.   break;
  595. }
  596. crv = pk11_AddAttributeType(privateKey, CKA_PRIME, 
  597.     pk11_item_expand(&dhParam.prime));
  598. if (crv != CKR_OK) {
  599.   PORT_Free(dhParam.prime.data);
  600.   PORT_Free(dhParam.base.data);
  601.   break;
  602. }
  603. crv = pk11_AddAttributeType(privateKey, CKA_BASE, 
  604.     pk11_item_expand(&dhParam.base));
  605. if (crv != CKR_OK) goto dhgn_done;
  606. rv = DH_NewKey(&dhParam, &dhPriv);
  607. PORT_Free(dhParam.prime.data);
  608. PORT_Free(dhParam.base.data);
  609. if (rv != SECSuccess) { 
  610.   crv = CKR_HOST_MEMORY; 
  611.   break;
  612. }
  613. crv=pk11_AddAttributeType(publicKey, CKA_VALUE, 
  614. pk11_item_expand(&dhPriv->publicValue));
  615. if (crv != CKR_OK) goto dhgn_done;
  616. crv=pk11_AddAttributeType(privateKey, CKA_VALUE, 
  617.       pk11_item_expand(&dhPriv->privateValue));
  618. dhgn_done:
  619. /* should zeroize, since this function doesn't. */
  620. PORT_FreeArena(dhPriv->arena, PR_TRUE);
  621. break;
  622.     default:
  623. crv = CKR_MECHANISM_INVALID;
  624.     }
  625.     if (crv != CKR_OK) {
  626. pk11_FreeObject(privateKey);
  627. pk11_FreeObject(publicKey);
  628. return crv;
  629.     }
  630.     /* Add the class, key_type The loop lets us check errors blow out
  631.      *  on errors and clean up at the bottom */
  632.     session = NULL; /* make pedtantic happy... session cannot leave the*/
  633.     /* loop below NULL unless an error is set... */
  634.     do {
  635. crv = pk11_AddAttributeType(privateKey,CKA_CLASS,&privClass,
  636. sizeof(CK_OBJECT_CLASS));
  637.         if (crv != CKR_OK) break;
  638. crv = pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass,
  639. sizeof(CK_OBJECT_CLASS));
  640.         if (crv != CKR_OK) break;
  641. crv = pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type,
  642. sizeof(CK_KEY_TYPE));
  643.         if (crv != CKR_OK) break;
  644. crv = pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type,
  645. sizeof(CK_KEY_TYPE));
  646.         if (crv != CKR_OK) break;
  647.         session = pk11_SessionFromHandle(hSession);
  648.         if (session == NULL) crv = CKR_SESSION_HANDLE_INVALID;
  649.     } while (0);
  650.     if (crv != CKR_OK) {
  651.  pk11_FreeObject(privateKey);
  652.  pk11_FreeObject(publicKey);
  653.  return crv;
  654.     }
  655.     /*
  656.      * handle the base object cleanup for the public Key
  657.      */
  658.     crv = pk11_handleObject(publicKey,session);
  659.     if (crv != CKR_OK) {
  660.         pk11_FreeSession(session);
  661. pk11_FreeObject(privateKey);
  662. pk11_FreeObject(publicKey);
  663. return crv;
  664.     }
  665.     /*
  666.      * handle the base object cleanup for the private Key
  667.      * If we have any problems, we destroy the public Key we've
  668.      * created and linked.
  669.      */
  670.     crv = pk11_handleObject(privateKey,session);
  671.     pk11_FreeSession(session);
  672.     if (crv != CKR_OK) {
  673. pk11_FreeObject(privateKey);
  674. NSC_DestroyObject(hSession,publicKey->handle);
  675. return crv;
  676.     }
  677.     if (pk11_isTrue(privateKey,CKA_SENSITIVE)) {
  678. pk11_forceAttribute(privateKey,CKA_ALWAYS_SENSITIVE,
  679. &cktrue,sizeof(CK_BBOOL));
  680.     }
  681.     if (pk11_isTrue(publicKey,CKA_SENSITIVE)) {
  682. pk11_forceAttribute(publicKey,CKA_ALWAYS_SENSITIVE,
  683. &cktrue,sizeof(CK_BBOOL));
  684.     }
  685.     if (!pk11_isTrue(privateKey,CKA_EXTRACTABLE)) {
  686. pk11_forceAttribute(privateKey,CKA_NEVER_EXTRACTABLE,
  687. &cktrue,sizeof(CK_BBOOL));
  688.     }
  689.     if (!pk11_isTrue(publicKey,CKA_EXTRACTABLE)) {
  690. pk11_forceAttribute(publicKey,CKA_NEVER_EXTRACTABLE,
  691. &cktrue,sizeof(CK_BBOOL));
  692.     }
  693.     *phPrivateKey = privateKey->handle;
  694.     *phPublicKey = publicKey->handle;
  695.     return CKR_OK;
  696. }
  697. static SECItem *pk11_PackagePrivateKey(PK11Object *key)
  698. {
  699.     SECKEYLowPrivateKey *lk = NULL;
  700.     SECKEYPrivateKeyInfo *pki = NULL;
  701.     PK11Attribute *attribute = NULL;
  702.     PLArenaPool *arena = NULL;
  703.     SECOidTag algorithm = SEC_OID_UNKNOWN;
  704.     void *dummy, *param = NULL;
  705.     SECStatus rv = SECSuccess;
  706.     SECItem *encodedKey = NULL;
  707.     if(!key) {
  708. return NULL;
  709.     }
  710.     attribute = pk11_FindAttribute(key, CKA_KEY_TYPE);
  711.     if(!attribute) {
  712. return NULL;
  713.     }
  714.     lk = pk11_GetPrivKey(key, *(CK_KEY_TYPE *)attribute->attrib.pValue);
  715.     pk11_FreeAttribute(attribute);
  716.     if(!lk) {
  717. return NULL;
  718.     }
  719.     arena = PORT_NewArena(2048);  /* XXX different size? */
  720.     if(!arena) {
  721. rv = SECFailure;
  722. goto loser;
  723.     }
  724.     pki = (SECKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, 
  725. sizeof(SECKEYPrivateKeyInfo));
  726.     if(!pki) {
  727. rv = SECFailure;
  728. goto loser;
  729.     }
  730.     pki->arena = arena;
  731.     param = NULL;
  732.     switch(lk->keyType) {
  733. case rsaKey:
  734.     dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
  735.        SECKEY_RSAPrivateKeyTemplate);
  736.     algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
  737.     break;
  738. case dsaKey:
  739.     dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk,
  740.        SECKEY_DSAPrivateKeyExportTemplate);
  741.     param = SEC_ASN1EncodeItem(NULL, NULL, &(lk->u.dsa.params),
  742.        SECKEY_PQGParamsTemplate);
  743.     algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE;
  744.     break;
  745. case fortezzaKey:
  746. case dhKey:
  747. default:
  748.     dummy = NULL;
  749.     break;
  750.     }
  751.  
  752.     if(!dummy || ((lk->keyType == dsaKey) && !param)) {
  753. goto loser;
  754.     }
  755.     rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, 
  756.        (SECItem*)param);
  757.     if(rv != SECSuccess) {
  758. rv = SECFailure;
  759. goto loser;
  760.     }
  761.     dummy = SEC_ASN1EncodeInteger(arena, &pki->version,
  762.   SEC_PRIVATE_KEY_INFO_VERSION);
  763.     if(!dummy) {
  764. rv = SECFailure;
  765. goto loser;
  766.     }
  767.     encodedKey = SEC_ASN1EncodeItem(NULL, NULL, pki, 
  768.     SECKEY_PrivateKeyInfoTemplate);
  769. loser:
  770.     if(arena) {
  771. PORT_FreeArena(arena, PR_TRUE);
  772.     }
  773.     if(lk && (lk != key->objectInfo)) {
  774. SECKEY_LowDestroyPrivateKey(lk);
  775.     }
  776.  
  777.     if(param) {
  778. SECITEM_ZfreeItem((SECItem*)param, PR_TRUE);
  779.     }
  780.     if(rv != SECSuccess) {
  781. return NULL;
  782.     }
  783.     return encodedKey;
  784. }
  785.     
  786. /* it doesn't matter yet, since we colapse error conditions in the
  787.  * level above, but we really should map those few key error differences */
  788. CK_RV pk11_mapWrap(CK_RV crv) { return crv; }
  789. /* NSC_WrapKey wraps (i.e., encrypts) a key. */
  790. CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession,
  791.     CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey,
  792.     CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey,
  793.  CK_ULONG_PTR pulWrappedKeyLen)
  794. {
  795.     PK11Session *session;
  796.     PK11Attribute *attribute;
  797.     PK11Object *key;
  798.     CK_RV crv;
  799.     PRBool isLynks = PR_FALSE;
  800.     CK_ULONG len = 0;
  801.     session = pk11_SessionFromHandle(hSession);
  802.     if (session == NULL) {
  803.      return CKR_SESSION_HANDLE_INVALID;
  804.     }
  805.     key = pk11_ObjectFromHandle(hKey,session);
  806.     pk11_FreeSession(session);
  807.     if (key == NULL) {
  808. return CKR_KEY_HANDLE_INVALID;
  809.     }
  810.     switch(key->objclass) {
  811. case CKO_SECRET_KEY:
  812.     attribute = pk11_FindAttribute(key,CKA_VALUE);
  813.     if (attribute == NULL) {
  814. crv = CKR_KEY_TYPE_INCONSISTENT;
  815. break;
  816.     }
  817.     if (pMechanism->mechanism == CKM_KEY_WRAP_LYNKS) {
  818. isLynks = PR_TRUE;
  819. pMechanism->mechanism = CKM_DES_ECB;
  820. len = *pulWrappedKeyLen;
  821.     }
  822.      
  823.     crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey, 
  824. CKA_WRAP, PK11_ENCRYPT);
  825.     if (crv != CKR_OK) {
  826. pk11_FreeAttribute(attribute);
  827. break;
  828.     }
  829.     crv = NSC_Encrypt(hSession, (CK_BYTE_PTR)attribute->attrib.pValue, 
  830.     attribute->attrib.ulValueLen,pWrappedKey,pulWrappedKeyLen);
  831.     if (isLynks && (crv == CKR_OK)) {
  832. unsigned char buf[2];
  833. crv = pk11_calcLynxChecksum(hSession,hWrappingKey,buf,
  834. (unsigned char*)attribute->attrib.pValue,
  835. attribute->attrib.ulValueLen);
  836. if (len >= 10) {
  837.     pWrappedKey[8] = buf[0];
  838.     pWrappedKey[9] = buf[1];
  839.     *pulWrappedKeyLen = 10;
  840. }
  841.     }
  842.     pk11_FreeAttribute(attribute);
  843.     break;
  844. case CKO_PRIVATE_KEY:
  845.     {
  846. SECItem *bpki = pk11_PackagePrivateKey(key);
  847. if(!bpki) {
  848.     crv = CKR_KEY_TYPE_INCONSISTENT;
  849.     break;
  850. }
  851. crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey,
  852. CKA_WRAP, PK11_ENCRYPT);
  853. if(crv != CKR_OK) {
  854.     SECITEM_ZfreeItem(bpki, PR_TRUE);
  855.     crv = CKR_KEY_TYPE_INCONSISTENT;
  856.     break;
  857. }
  858. crv = NSC_Encrypt(hSession, bpki->data, bpki->len,
  859. pWrappedKey, pulWrappedKeyLen);
  860. SECITEM_ZfreeItem(bpki, PR_TRUE);
  861. break;
  862.     }
  863. default:
  864.     crv = CKR_KEY_TYPE_INCONSISTENT;
  865.     break;
  866.     }
  867.     pk11_FreeObject(key);
  868.     return pk11_mapWrap(crv);
  869. }
  870. /*
  871.  * import a pprivate key info into the desired slot
  872.  */
  873. static SECStatus
  874. pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki)
  875. {
  876.     CK_BBOOL cktrue = CK_TRUE; 
  877.     CK_KEY_TYPE keyType = CKK_RSA;
  878.     SECStatus rv = SECFailure;
  879.     const SEC_ASN1Template *keyTemplate, *paramTemplate;
  880.     void *paramDest = NULL;
  881.     PLArenaPool *arena;
  882.     SECKEYLowPrivateKey *lpk = NULL;
  883.     SECKEYPrivateKeyInfo *pki = NULL;
  884.     SECItem *ck_id = NULL;
  885.     CK_RV crv = CKR_KEY_TYPE_INCONSISTENT;
  886.     arena = PORT_NewArena(2048);
  887.     if(!arena) {
  888. return SECFailure;
  889.     }
  890.     pki = (SECKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena, 
  891. sizeof(SECKEYPrivateKeyInfo));
  892.     if(!pki) {
  893. PORT_FreeArena(arena, PR_TRUE);
  894. return SECFailure;
  895.     }
  896.     if(SEC_ASN1DecodeItem(arena, pki, SECKEY_PrivateKeyInfoTemplate, bpki) 
  897. != SECSuccess) {
  898. PORT_FreeArena(arena, PR_FALSE);
  899. return SECFailure;
  900.     }
  901.     lpk = (SECKEYLowPrivateKey *)PORT_ArenaZAlloc(arena,
  902.   sizeof(SECKEYLowPrivateKey));
  903.     if(lpk == NULL) {
  904. goto loser;
  905.     }
  906.     lpk->arena = arena;
  907.     switch(SECOID_GetAlgorithmTag(&pki->algorithm)) {
  908. case SEC_OID_PKCS1_RSA_ENCRYPTION:
  909.     keyTemplate = SECKEY_RSAPrivateKeyTemplate;
  910.     paramTemplate = NULL;
  911.     paramDest = NULL;
  912.     lpk->keyType = rsaKey;
  913.     break;
  914. case SEC_OID_ANSIX9_DSA_SIGNATURE:
  915.     keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
  916.     paramTemplate = SECKEY_PQGParamsTemplate;
  917.     paramDest = &(lpk->u.dsa.params);
  918.     lpk->keyType = dsaKey;
  919.     break;
  920. /* case dhKey: */
  921. /* case fortezzaKey: */
  922. default:
  923.     keyTemplate = NULL;
  924.     paramTemplate = NULL;
  925.     paramDest = NULL;
  926.     break;
  927.     }
  928.     if(!keyTemplate) {
  929. goto loser;
  930.     }
  931.     /* decode the private key and any algorithm parameters */
  932.     rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
  933.     if(rv != SECSuccess) {
  934. goto loser;
  935.     }
  936.     if(paramDest && paramTemplate) {
  937. rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, 
  938.  &(pki->algorithm.parameters));
  939. if(rv != SECSuccess) {
  940.     goto loser;
  941. }
  942.     }
  943.     rv = SECFailure;
  944.     switch (lpk->keyType) {
  945.         case rsaKey:
  946.     keyType = CKK_RSA;
  947.     if(pk11_hasAttribute(key, CKA_NETSCAPE_DB)) {
  948. pk11_DeleteAttributeType(key, CKA_NETSCAPE_DB);
  949.     }
  950.     crv = pk11_AddAttributeType(key, CKA_KEY_TYPE, &keyType, 
  951. sizeof(keyType));
  952.     if(crv != CKR_OK) break;
  953.     crv = pk11_AddAttributeType(key, CKA_UNWRAP, &cktrue, 
  954. sizeof(CK_BBOOL));
  955.     if(crv != CKR_OK) break;
  956.     crv = pk11_AddAttributeType(key, CKA_DECRYPT, &cktrue, 
  957. sizeof(CK_BBOOL));
  958.     if(crv != CKR_OK) break;
  959.     crv = pk11_AddAttributeType(key, CKA_SIGN, &cktrue, 
  960. sizeof(CK_BBOOL));
  961.     if(crv != CKR_OK) break;
  962.     crv = pk11_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, 
  963.     sizeof(CK_BBOOL));
  964.     if(crv != CKR_OK) break;
  965.     crv = pk11_AddAttributeType(key, CKA_MODULUS, 
  966. pk11_item_expand(&lpk->u.rsa.modulus));
  967.     if(crv != CKR_OK) break;
  968.     crv = pk11_AddAttributeType(key, CKA_PUBLIC_EXPONENT, 
  969.       pk11_item_expand(&lpk->u.rsa.publicExponent));
  970.     if(crv != CKR_OK) break;
  971.     crv = pk11_AddAttributeType(key, CKA_PRIVATE_EXPONENT, 
  972.       pk11_item_expand(&lpk->u.rsa.privateExponent));
  973.     if(crv != CKR_OK) break;
  974.     crv = pk11_AddAttributeType(key, CKA_PRIME_1, 
  975. pk11_item_expand(&lpk->u.rsa.prime1));
  976.     if(crv != CKR_OK) break;
  977.     crv = pk11_AddAttributeType(key, CKA_PRIME_2, 
  978.       pk11_item_expand(&lpk->u.rsa.prime2));
  979.     if(crv != CKR_OK) break;
  980.     crv = pk11_AddAttributeType(key, CKA_EXPONENT_1, 
  981.       pk11_item_expand(&lpk->u.rsa.exponent1));
  982.     if(crv != CKR_OK) break;
  983.     crv = pk11_AddAttributeType(key, CKA_EXPONENT_2, 
  984.       pk11_item_expand(&lpk->u.rsa.exponent2));
  985.     if(crv != CKR_OK) break;
  986.     crv = pk11_AddAttributeType(key, CKA_COEFFICIENT, 
  987.       pk11_item_expand(&lpk->u.rsa.coefficient));
  988.     break;
  989.         case dsaKey:
  990.     keyType = CKK_DSA;
  991.     crv = (pk11_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK :
  992. CKR_KEY_TYPE_INCONSISTENT;
  993.     if(crv != CKR_OK) break;
  994.     crv = pk11_AddAttributeType(key, CKA_KEY_TYPE, &keyType, 
  995. sizeof(keyType));
  996.     if(crv != CKR_OK) break;
  997.     crv = pk11_AddAttributeType(key, CKA_SIGN, &cktrue, 
  998. sizeof(CK_BBOOL));
  999.     if(crv != CKR_OK) break;
  1000.     crv = pk11_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, 
  1001. sizeof(CK_BBOOL)); 
  1002.     if(crv != CKR_OK) break;
  1003.     crv = pk11_AddAttributeType(key, CKA_PRIME,    
  1004.     pk11_item_expand(&lpk->u.dsa.params.prime));
  1005.     if(crv != CKR_OK) break;
  1006.     crv = pk11_AddAttributeType(key, CKA_SUBPRIME,
  1007.  pk11_item_expand(&lpk->u.dsa.params.subPrime));
  1008.     if(crv != CKR_OK) break;
  1009.     crv = pk11_AddAttributeType(key, CKA_BASE,  
  1010.     pk11_item_expand(&lpk->u.dsa.params.base));
  1011.     if(crv != CKR_OK) break;
  1012.     crv = pk11_AddAttributeType(key, CKA_VALUE, 
  1013. pk11_item_expand(&lpk->u.dsa.privateValue));
  1014.     if(crv != CKR_OK) break;
  1015.     break;
  1016. #ifdef notdef
  1017.         case dhKey:
  1018.     template = dhTemplate;
  1019.     templateCount = sizeof(dhTemplate)/sizeof(CK_ATTRIBUTE);
  1020.     keyType = CKK_DH;
  1021.     break;
  1022. #endif
  1023. /* what about fortezza??? */
  1024. default:
  1025.     crv = CKR_KEY_TYPE_INCONSISTENT;
  1026.     break;
  1027.     }
  1028. loser:
  1029.     if(ck_id) {
  1030. SECITEM_ZfreeItem(ck_id, PR_TRUE);
  1031.     }
  1032.     if(lpk) {
  1033. SECKEY_LowDestroyPrivateKey(lpk);
  1034.     }
  1035.     if(crv != CKR_OK) {
  1036. return SECFailure;
  1037.     }
  1038.     return SECSuccess;
  1039. }
  1040. /* NSC_UnwrapKey unwraps (decrypts) a wrapped key, creating a new key object. */
  1041. CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession,
  1042.     CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey,
  1043.     CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen,
  1044.     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount,
  1045.  CK_OBJECT_HANDLE_PTR phKey)
  1046. {
  1047.     PK11Object *key = NULL;
  1048.     PK11Session *session;
  1049.     int key_length = 0;
  1050.     unsigned char * buf = NULL;
  1051.     CK_RV crv = CKR_OK;
  1052.     int i;
  1053.     CK_ULONG bsize = ulWrappedKeyLen;
  1054.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  1055.     PK11Attribute *attr = NULL;
  1056.     SECItem bpki;
  1057.     CK_OBJECT_CLASS target_type = CKO_SECRET_KEY;
  1058.     PRBool isLynks = PR_FALSE;
  1059.     /*
  1060.      * now lets create an object to hang the attributes off of
  1061.      */
  1062.     key = pk11_NewObject(slot); /* fill in the handle later */
  1063.     if (key == NULL) {
  1064. return CKR_HOST_MEMORY;
  1065.     }
  1066.     /*
  1067.      * load the template values into the object
  1068.      */
  1069.     for (i=0; i < (int) ulAttributeCount; i++) {
  1070. if (pTemplate[i].type == CKA_VALUE_LEN) {
  1071.     key_length = *(CK_ULONG *)pTemplate[i].pValue;
  1072.     continue;
  1073. }
  1074.         if (pTemplate[i].type == CKA_CLASS) {
  1075.     target_type = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
  1076. }
  1077. crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
  1078. if (crv != CKR_OK) break;
  1079.     }
  1080.     if (crv != CKR_OK) {
  1081. pk11_FreeObject(key);
  1082. return crv;
  1083.     }
  1084.     /* LYNKS is a special key wrapping mechanism */
  1085.     if (pMechanism->mechanism == CKM_KEY_WRAP_LYNKS) {
  1086. isLynks = PR_TRUE;
  1087. pMechanism->mechanism = CKM_DES_ECB;
  1088. ulWrappedKeyLen -= 2; /* don't decrypt the checksum */
  1089.     }
  1090.     crv = pk11_DecryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP,
  1091. PK11_DECRYPT);
  1092.     if (crv != CKR_OK) {
  1093. pk11_FreeObject(key);
  1094. return pk11_mapWrap(crv);
  1095.     }
  1096.     /* allocate the buffer to decrypt into 
  1097.      * this assumes the unwrapped key is never larger than the
  1098.      * wrapped key. For all the mechanisms we support this is true */
  1099.     buf = (unsigned char *)PORT_Alloc( ulWrappedKeyLen);
  1100.     bsize = ulWrappedKeyLen;
  1101.     crv = NSC_Decrypt(hSession, pWrappedKey, ulWrappedKeyLen, buf, &bsize);
  1102.     if (crv != CKR_OK) {
  1103. pk11_FreeObject(key);
  1104. PORT_Free(buf);
  1105. return pk11_mapWrap(crv);
  1106.     }
  1107.     switch(target_type) {
  1108. case CKO_SECRET_KEY:
  1109.     if (!pk11_hasAttribute(key,CKA_KEY_TYPE)) {
  1110. crv = CKR_TEMPLATE_INCOMPLETE;
  1111. break;
  1112.     }
  1113.     /* verify the Lynx checksum */
  1114.     if (isLynks) {
  1115. unsigned char checkSum[2];
  1116. crv = pk11_calcLynxChecksum(hSession,hUnwrappingKey,checkSum,
  1117. buf,bsize);
  1118. if (crv != CKR_OK) break;
  1119. if ((ulWrappedKeyLen != 8) || (pWrappedKey[8] != checkSum[0]) 
  1120. || (pWrappedKey[9] != checkSum[1])) {
  1121.     crv = CKR_WRAPPED_KEY_INVALID;
  1122.     break;
  1123. }
  1124.     }
  1125.     if(key_length == 0) {
  1126. key_length = bsize;
  1127.     }
  1128.     if (key_length > MAX_KEY_LEN) {
  1129. crv = CKR_TEMPLATE_INCONSISTENT;
  1130. break;
  1131.     }
  1132.     
  1133.     /* add the value */
  1134.     crv = pk11_AddAttributeType(key,CKA_VALUE,buf,key_length);
  1135.     break;
  1136. case CKO_PRIVATE_KEY:
  1137.     bpki.data = (unsigned char *)buf;
  1138.     bpki.len = bsize;
  1139.     crv = CKR_OK;
  1140.     if(pk11_unwrapPrivateKey(key, &bpki) != SECSuccess) {
  1141. crv = CKR_TEMPLATE_INCOMPLETE;
  1142.     }
  1143.     break;
  1144. default:
  1145.     crv = CKR_TEMPLATE_INCONSISTENT;
  1146.     break;
  1147.     }
  1148.     PORT_ZFree(buf, bsize);
  1149.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  1150.     /* get the session */
  1151.     session = pk11_SessionFromHandle(hSession);
  1152.     if (session == NULL) {
  1153. pk11_FreeObject(key);
  1154.         return CKR_SESSION_HANDLE_INVALID;
  1155.     }
  1156.     /*
  1157.      * handle the base object stuff
  1158.      */
  1159.     crv = pk11_handleObject(key,session);
  1160.     pk11_FreeSession(session);
  1161.     if (crv != CKR_OK) {
  1162. pk11_FreeObject(key);
  1163. return crv;
  1164.     }
  1165.     *phKey = key->handle;
  1166.     return CKR_OK;
  1167. }
  1168. /*
  1169.  * The SSL key gen mechanism create's lots of keys. This function handles the
  1170.  * details of each of these key creation.
  1171.  */
  1172. static CK_RV
  1173. pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey, 
  1174.     PRBool isMacKey, unsigned char *keyBlock, unsigned int keySize,
  1175.  CK_OBJECT_HANDLE *keyHandle)
  1176. {
  1177.     PK11Object *key;
  1178.     PK11Session *session;
  1179.     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
  1180.     CK_BBOOL cktrue = CK_TRUE;
  1181.     CK_BBOOL ckfalse = CK_FALSE;
  1182.     CK_RV crv = CKR_HOST_MEMORY;
  1183.     /*
  1184.      * now lets create an object to hang the attributes off of
  1185.      */
  1186.     *keyHandle = CK_INVALID_KEY;
  1187.     key = pk11_NewObject(baseKey->slot); 
  1188.     if (key == NULL) return CKR_HOST_MEMORY;
  1189.     key->wasDerived = PR_TRUE;
  1190.     crv = pk11_CopyObject(key,baseKey);
  1191.     if (crv != CKR_OK) goto loser;
  1192.     if (isMacKey) {
  1193. crv = pk11_forceAttribute(key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
  1194. if (crv != CKR_OK) goto loser;
  1195. crv = pk11_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
  1196. if (crv != CKR_OK) goto loser;
  1197. crv = pk11_forceAttribute(key,CKA_ENCRYPT,&ckfalse,sizeof(CK_BBOOL));
  1198. if (crv != CKR_OK) goto loser;
  1199. crv = pk11_forceAttribute(key,CKA_DECRYPT,&ckfalse,sizeof(CK_BBOOL));
  1200. if (crv != CKR_OK) goto loser;
  1201. crv = pk11_forceAttribute(key,CKA_SIGN,&cktrue,sizeof(CK_BBOOL));
  1202. if (crv != CKR_OK) goto loser;
  1203. crv = pk11_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
  1204. if (crv != CKR_OK) goto loser;
  1205. crv = pk11_forceAttribute(key,CKA_WRAP,&ckfalse,sizeof(CK_BBOOL));
  1206. if (crv != CKR_OK) goto loser;
  1207. crv = pk11_forceAttribute(key,CKA_UNWRAP,&ckfalse,sizeof(CK_BBOOL));
  1208. if (crv != CKR_OK) goto loser;
  1209.     }
  1210.     crv = pk11_forceAttribute(key,CKA_VALUE,keyBlock,keySize);
  1211.     if (crv != CKR_OK) goto loser;
  1212.     /* get the session */
  1213.     crv = CKR_HOST_MEMORY;
  1214.     session = pk11_SessionFromHandle(hSession);
  1215.     if (session == NULL) { goto loser; }
  1216.     crv = pk11_handleObject(key,session);
  1217.     pk11_FreeSession(session);
  1218.     if (crv == CKR_OK) {
  1219. *keyHandle = key->handle;
  1220. return crv;
  1221.     }
  1222. loser:
  1223.     if (key) pk11_FreeObject(key);
  1224.     return crv;
  1225. }
  1226. /*
  1227.  * if there is an error, we need to free the keys we already created in SSL
  1228.  * This is the routine that will do it..
  1229.  */
  1230. static void
  1231. pk11_freeSSLKeys(CK_SESSION_HANDLE session,
  1232. CK_SSL3_KEY_MAT_OUT *returnedMaterial ) {
  1233. if (returnedMaterial->hClientMacSecret != CK_INVALID_KEY) {
  1234.    NSC_DestroyObject(session,returnedMaterial->hClientMacSecret);
  1235. }
  1236. if (returnedMaterial->hServerMacSecret != CK_INVALID_KEY) {
  1237.    NSC_DestroyObject(session, returnedMaterial->hServerMacSecret);
  1238. }
  1239. if (returnedMaterial->hClientKey != CK_INVALID_KEY) {
  1240.    NSC_DestroyObject(session, returnedMaterial->hClientKey);
  1241. }
  1242. if (returnedMaterial->hServerKey != CK_INVALID_KEY) {
  1243.    NSC_DestroyObject(session, returnedMaterial->hServerKey);
  1244. }
  1245. }
  1246. /*
  1247.  * when deriving from sensitive and extractable keys, we need to preserve some
  1248.  * of the semantics in the derived key. This helper routine maintains these
  1249.  * semantics.
  1250.  */
  1251. static CK_RV
  1252. pk11_DeriveSensitiveCheck(PK11Object *baseKey,PK11Object *destKey) {
  1253.     PRBool hasSensitive;
  1254.     PRBool sensitive;
  1255.     PRBool hasExtractable;
  1256.     PRBool extractable;
  1257.     CK_RV crv = PR_TRUE;
  1258.     PK11Attribute *att;
  1259.     hasSensitive = PR_FALSE;
  1260.     att = pk11_FindAttribute(destKey,CKA_SENSITIVE);
  1261.     if (att) {
  1262.         hasSensitive = PR_FALSE;
  1263. sensitive = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
  1264. pk11_FreeAttribute(att);
  1265.     }
  1266.     hasExtractable = PR_FALSE;
  1267.     att = pk11_FindAttribute(destKey,CKA_EXTRACTABLE);
  1268.     if (att) {
  1269.         hasExtractable = PR_FALSE;
  1270. extractable = (PRBool) *(CK_BBOOL *)att->attrib.pValue;
  1271. pk11_FreeAttribute(att);
  1272.     }
  1273.     /* don't make a key more accessible */
  1274.     if (pk11_isTrue(baseKey,CKA_SENSITIVE) && hasSensitive && 
  1275. (sensitive == PR_FALSE)) {
  1276. return CKR_KEY_FUNCTION_NOT_PERMITTED;
  1277.     }
  1278.     if (!pk11_isTrue(baseKey,CKA_EXTRACTABLE) && hasExtractable && 
  1279. (extractable == PR_TRUE)) {
  1280. return CKR_KEY_FUNCTION_NOT_PERMITTED;
  1281.     }
  1282.     /* inherit parent's sensitivity */
  1283.     if (!hasSensitive) {
  1284.         att = pk11_FindAttribute(baseKey,CKA_SENSITIVE);
  1285. if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
  1286. crv = pk11_defaultAttribute(destKey,pk11_attr_expand(&att->attrib));
  1287. pk11_FreeAttribute(att);
  1288. if (crv != CKR_OK) return crv;
  1289.     }
  1290.     if (!hasExtractable) {
  1291.         att = pk11_FindAttribute(baseKey,CKA_EXTRACTABLE);
  1292. if (att == NULL) return CKR_KEY_TYPE_INCONSISTENT;
  1293. crv = pk11_defaultAttribute(destKey,pk11_attr_expand(&att->attrib));
  1294. pk11_FreeAttribute(att);
  1295. if (crv != CKR_OK) return crv;
  1296.     }
  1297.     /* we should inherit the parent's always extractable/ never sensitive info,
  1298.      * but handleObject always forces this attributes, so we would need to do
  1299.      * something special. */
  1300.     return CKR_OK;
  1301. }
  1302. /*
  1303.  * make known fixed PKCS #11 key types to their sizes in bytes
  1304.  */
  1305. static unsigned long
  1306. pk11_MapKeySize(CK_KEY_TYPE keyType) {
  1307.     switch (keyType) {
  1308.     case CKK_CDMF:
  1309. return 8;
  1310.     case CKK_DES:
  1311. return 8;
  1312.     case CKK_DES2:
  1313. return 16;
  1314.     case CKK_DES3:
  1315. return 24;
  1316.     /* IDEA and CAST need to be added */
  1317.     default:
  1318. break;
  1319.     }
  1320.     return 0;
  1321. }
  1322. #define PHASH_STATE_MAX_LEN 20
  1323. /* TLS P_hash function */
  1324. static SECStatus
  1325. pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, 
  1326. SECItem *seed, SECItem *result)
  1327. {
  1328.     unsigned char state[PHASH_STATE_MAX_LEN];
  1329.     unsigned char outbuf[PHASH_STATE_MAX_LEN];
  1330.     unsigned int state_len = 0, label_len = 0, outbuf_len = 0, chunk_size;
  1331.     unsigned int remaining;
  1332.     unsigned char *res;
  1333.     SECStatus status;
  1334.     HMACContext *cx;
  1335.     SECStatus rv = SECFailure;
  1336.     PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
  1337.     PORT_Assert((seed != NULL) && (seed->data != NULL));
  1338.     PORT_Assert((result != NULL) && (result->data != NULL));
  1339.     remaining = result->len;
  1340.     res = result->data;
  1341.     if (label != NULL)
  1342. label_len = PORT_Strlen(label);
  1343.     cx = HMAC_Create(alg, secret->data, secret->len);
  1344.     if (cx == NULL)
  1345. goto loser;
  1346.     /* initialize the state = A(1) = HMAC_hash(secret, seed) */
  1347.     HMAC_Begin(cx);
  1348.     HMAC_Update(cx, (unsigned char *)label, label_len);
  1349.     HMAC_Update(cx, seed->data, seed->len);
  1350.     status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
  1351.     if (status != SECSuccess)
  1352. goto loser;
  1353.     /* generate a block at a time until we're done */
  1354.     while (remaining > 0) {
  1355. HMAC_Begin(cx);
  1356. HMAC_Update(cx, state, state_len);
  1357. if (label_len)
  1358.     HMAC_Update(cx, (unsigned char *)label, label_len);
  1359. HMAC_Update(cx, seed->data, seed->len);
  1360. status = HMAC_Finish(cx, outbuf, &outbuf_len, PHASH_STATE_MAX_LEN);
  1361. if (status != SECSuccess)
  1362.     goto loser;
  1363.         /* Update the state = A(i) = HMAC_hash(secret, A(i-1)) */
  1364. HMAC_Begin(cx); 
  1365. HMAC_Update(cx, state, state_len); 
  1366. status = HMAC_Finish(cx, state, &state_len, PHASH_STATE_MAX_LEN);
  1367. if (status != SECSuccess)
  1368.     goto loser;
  1369. chunk_size = PR_MIN(outbuf_len, remaining);
  1370. PORT_Memcpy(res, &outbuf, chunk_size);
  1371. res += chunk_size;
  1372. remaining -= chunk_size;
  1373.     }
  1374.     rv = SECSuccess;
  1375. loser:
  1376.     /* if (cx) HMAC_Destroy(cx); */
  1377.     /* clear out state so it's not left on the stack */
  1378.     if (cx) HMAC_Destroy(cx);
  1379.     PORT_Memset(state, 0, sizeof(state));
  1380.     PORT_Memset(outbuf, 0, sizeof(outbuf));
  1381.     return rv;
  1382. }
  1383. static SECStatus
  1384. pk11_PRF(const SECItem *secret, const char *label, SECItem *seed, 
  1385.          SECItem *result)
  1386. {
  1387.     SECStatus rv = SECFailure, status;
  1388.     unsigned int i;
  1389.     SECItem tmp = { siBuffer, NULL, 0};
  1390.     SECItem S1;
  1391.     SECItem S2;
  1392.     PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len));
  1393.     PORT_Assert((seed != NULL) && (seed->data != NULL));
  1394.     PORT_Assert((result != NULL) && (result->data != NULL));
  1395.     S1.type = siBuffer;
  1396.     S1.len  = (secret->len / 2) + (secret->len & 1);
  1397.     S1.data = secret->data;
  1398.     S2.type = siBuffer;
  1399.     S2.len  = S1.len;
  1400.     S2.data = secret->data + (secret->len - S2.len);
  1401.     tmp.data = (unsigned char*)PORT_Alloc(result->len);
  1402.     if (tmp.data == NULL)
  1403. goto loser;
  1404.     tmp.len = result->len;
  1405.     status = pk11_P_hash(SEC_OID_MD5, &S1, label, seed, result);
  1406.     if (status != SECSuccess)
  1407. goto loser;
  1408.     status = pk11_P_hash(SEC_OID_SHA1, &S2, label, seed, &tmp);
  1409.     if (status != SECSuccess)
  1410. goto loser;
  1411.     for (i = 0; i < result->len; i++)
  1412. result->data[i] ^= tmp.data[i];
  1413.     rv = SECSuccess;
  1414. loser:
  1415.     if (tmp.data != NULL)
  1416. PORT_ZFree(tmp.data, tmp.len);
  1417.     return rv;
  1418. }
  1419. /*
  1420.  * SSL Key generation given pre master secret
  1421.  */
  1422. static char *mixers[] = { "A", "BB", "CCC", "DDDD", "EEEEE", "FFFFFF", "GGGGGGG"};
  1423. #define NUM_MIXERS 7
  1424. #define SSL3_PMS_LENGTH 48
  1425. #define SSL3_MASTER_SECRET_LENGTH 48
  1426. /* NSC_DeriveKey derives a key from a base key, creating a new key object. */
  1427. CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,
  1428.  CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,
  1429.  CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 
  1430. CK_OBJECT_HANDLE_PTR phKey)
  1431. {
  1432.     PK11Session *   session;
  1433.     PK11Slot    *   slot = pk11_SlotFromSessionHandle(hSession);
  1434.     PK11Object  *   key;
  1435.     PK11Object  *   sourceKey;
  1436.     PK11Attribute * att;
  1437.     PK11Attribute * att2;
  1438.     unsigned char * buf;
  1439.     SHA1Context *   sha;
  1440.     MD5Context *    md5;
  1441.     MD2Context *    md2;
  1442.     CK_ULONG        macSize;
  1443.     CK_ULONG        tmpKeySize;
  1444.     CK_ULONG        IVSize;
  1445.     CK_ULONG        keySize = 0;
  1446.     CK_RV           crv  = CKR_OK;
  1447.     CK_BBOOL        cktrue = CK_TRUE;
  1448.     CK_KEY_TYPE     keyType = CKK_GENERIC_SECRET;
  1449.     CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
  1450.     CK_KEY_DERIVATION_STRING_DATA *stringPtr;
  1451.     PRBool          isTLS = PR_FALSE;
  1452.     SECStatus       rv;
  1453.     int             i;
  1454.     unsigned int    outLen;
  1455.     unsigned char   sha_out[SHA1_LENGTH];
  1456.     unsigned char   key_block[NUM_MIXERS * MD5_LENGTH];
  1457.     unsigned char   key_block2[MD5_LENGTH];
  1458.     /*
  1459.      * now lets create an object to hang the attributes off of
  1460.      */
  1461.     if (phKey) *phKey = CK_INVALID_KEY;
  1462.     key = pk11_NewObject(slot); /* fill in the handle later */
  1463.     if (key == NULL) {
  1464. return CKR_HOST_MEMORY;
  1465.     }
  1466.     /*
  1467.      * load the template values into the object
  1468.      */
  1469.     for (i=0; i < (int) ulAttributeCount; i++) {
  1470. crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));
  1471. if (crv != CKR_OK) break;
  1472. if (pTemplate[i].type == CKA_KEY_TYPE) {
  1473.     keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;
  1474. }
  1475. if (pTemplate[i].type == CKA_VALUE_LEN) {
  1476.     keySize = *(CK_ULONG *)pTemplate[i].pValue;
  1477. }
  1478.     }
  1479.     if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }
  1480.     if (keySize == 0) {
  1481. keySize = pk11_MapKeySize(keyType);
  1482.     }
  1483.     /* Derive can only create SECRET KEY's currently... */
  1484.     classType = CKO_SECRET_KEY;
  1485.     crv = pk11_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));
  1486.     if (crv != CKR_OK) {
  1487. pk11_FreeObject(key);
  1488. return crv;
  1489.     }
  1490.     /* look up the base key we're deriving with */ 
  1491.     session = pk11_SessionFromHandle(hSession);
  1492.     if (session == NULL) {
  1493. pk11_FreeObject(key);
  1494.         return CKR_SESSION_HANDLE_INVALID;
  1495.     }
  1496.     sourceKey = pk11_ObjectFromHandle(hBaseKey,session);
  1497.     pk11_FreeSession(session);
  1498.     if (sourceKey == NULL) {
  1499. pk11_FreeObject(key);
  1500.         return CKR_KEY_HANDLE_INVALID;
  1501.     }
  1502.     /* don't use key derive to expose sensitive keys */
  1503.     crv = pk11_DeriveSensitiveCheck(sourceKey,key);
  1504.     if (crv != CKR_OK) {
  1505. pk11_FreeObject(key);
  1506. pk11_FreeObject(sourceKey);
  1507.         return crv;
  1508.     }
  1509.     /* get the value of the base key */
  1510.     att = pk11_FindAttribute(sourceKey,CKA_VALUE);
  1511.     if (att == NULL) {
  1512. pk11_FreeObject(key);
  1513. pk11_FreeObject(sourceKey);
  1514.         return CKR_KEY_HANDLE_INVALID;
  1515.     }
  1516.     switch (pMechanism->mechanism) {
  1517.     /*
  1518.      * generate the master secret 
  1519.      */
  1520.     case CKM_TLS_MASTER_KEY_DERIVE:
  1521. isTLS = PR_TRUE;
  1522. /* fall thru */
  1523.     case CKM_SSL3_MASTER_KEY_DERIVE:
  1524.       {
  1525. CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;
  1526. SSL3RSAPreMasterSecret *rsa_pms;
  1527. /* first do the consistancy checkes */
  1528. if (att->attrib.ulValueLen != SSL3_PMS_LENGTH) {
  1529.     crv = CKR_KEY_TYPE_INCONSISTENT;
  1530.     break;
  1531. }
  1532. att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);
  1533. if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
  1534. CKK_GENERIC_SECRET)) {
  1535.     if (att2) pk11_FreeAttribute(att2);
  1536.     crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
  1537.     break;
  1538. }
  1539. pk11_FreeAttribute(att2);
  1540. if (keyType != CKK_GENERIC_SECRET) {
  1541.     crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
  1542.     break;
  1543. }
  1544. if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {
  1545.     crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
  1546.     break;
  1547. }
  1548. /* finally do the key gen */
  1549. ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)
  1550. pMechanism->pParameter;
  1551. if (ssl3_master->pVersion) {
  1552.     rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;
  1553.     /* don't leak more key material then necessary for SSL to work */
  1554.     if (key->wasDerived) {
  1555. ssl3_master->pVersion->major = 0xff;
  1556. ssl3_master->pVersion->minor = 0xff;
  1557.     } else {
  1558. ssl3_master->pVersion->major = rsa_pms->client_version[0];
  1559. ssl3_master->pVersion->minor = rsa_pms->client_version[1];
  1560.     }
  1561. }
  1562. if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {
  1563.    crv = CKR_MECHANISM_PARAM_INVALID;
  1564.    break;
  1565. }
  1566. if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {
  1567.    crv = CKR_MECHANISM_PARAM_INVALID;
  1568.    break;
  1569. }
  1570.         if (isTLS) {
  1571.     unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
  1572.     SECItem crsr = { siBuffer, NULL, 0 };
  1573.     SECItem master = { siBuffer, NULL, 0 };
  1574.     SECItem pms = { siBuffer, NULL, 0 };
  1575.     SECStatus status;
  1576.     pms.data = (unsigned char*)att->attrib.pValue;
  1577.     pms.len = att->attrib.ulValueLen;
  1578.     master.data = key_block;
  1579.     master.len = SSL3_MASTER_SECRET_LENGTH;
  1580.     crsr.data = crsrdata;
  1581.     crsr.len = sizeof(crsrdata);
  1582.     PORT_Memcpy(crsrdata, ssl3_master->RandomInfo.pClientRandom,
  1583.  SSL3_RANDOM_LENGTH);
  1584.     PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 
  1585. ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);
  1586.     status = pk11_PRF(&pms, "master secret", &crsr, &master);
  1587.     if (status != SECSuccess) {
  1588.      crv = CKR_FUNCTION_FAILED;
  1589. break;
  1590.     }
  1591. } else {
  1592.     /* now allocate the hash contexts */
  1593.     md5 = MD5_NewContext();
  1594.     if (md5 == NULL) { 
  1595. crv = CKR_HOST_MEMORY;
  1596. break;
  1597.     }
  1598.     sha = SHA1_NewContext();
  1599.     if (sha == NULL) { 
  1600. PORT_Free(md5);
  1601. crv = CKR_HOST_MEMORY;
  1602. break;
  1603.     }
  1604.             for (i = 0; i < 3; i++) {
  1605.               SHA1_Begin(sha);
  1606.               SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
  1607.               SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 
  1608.   att->attrib.ulValueLen);
  1609.               SHA1_Update(sha, ssl3_master->RandomInfo.pClientRandom,
  1610. ssl3_master->RandomInfo.ulClientRandomLen);
  1611.               SHA1_Update(sha, ssl3_master->RandomInfo.pServerRandom, 
  1612. ssl3_master->RandomInfo.ulServerRandomLen);
  1613.               SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
  1614.               PORT_Assert(outLen == SHA1_LENGTH);
  1615.               MD5_Begin(md5);
  1616.               MD5_Update(md5, (const unsigned char*)att->attrib.pValue, 
  1617.  att->attrib.ulValueLen);
  1618.               MD5_Update(md5, sha_out, outLen);
  1619.               MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
  1620.               PORT_Assert(outLen == MD5_LENGTH);
  1621.             }
  1622.     PORT_Free(md5);
  1623.     PORT_Free(sha);
  1624. }
  1625. /* store the results */
  1626. crv = pk11_forceAttribute
  1627. (key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);
  1628. if (crv != CKR_OK) break;
  1629. keyType = CKK_GENERIC_SECRET;
  1630. crv = pk11_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));
  1631. if (isTLS) {
  1632.     /* TLS's master secret is used to "sign" finished msgs with PRF. */
  1633.     /* XXX This seems like a hack.   But PK11_Derive only accepts 
  1634.      * one "operation" argument. */
  1635.     crv = pk11_forceAttribute(key,CKA_SIGN,  &cktrue,sizeof(CK_BBOOL));
  1636.     if (crv != CKR_OK) break;
  1637.     crv = pk11_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));
  1638.     if (crv != CKR_OK) break;
  1639.     /* While we're here, we might as well force this, too. */
  1640.     crv = pk11_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));
  1641.     if (crv != CKR_OK) break;
  1642. }
  1643. break;
  1644.       }
  1645.     case CKM_TLS_KEY_AND_MAC_DERIVE:
  1646. isTLS = PR_TRUE;
  1647. /* fall thru */
  1648.     case CKM_SSL3_KEY_AND_MAC_DERIVE:
  1649.       {
  1650. CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;
  1651. CK_SSL3_KEY_MAT_OUT *   ssl3_keys_out;
  1652. CK_ULONG                effKeySize;
  1653. crv = pk11_DeriveSensitiveCheck(sourceKey,key);
  1654. if (crv != CKR_OK) break;
  1655. if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {
  1656.     crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
  1657.     break;
  1658. }
  1659. att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);
  1660. if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=
  1661. CKK_GENERIC_SECRET)) {
  1662.     if (att2) pk11_FreeAttribute(att2);
  1663.     crv = CKR_KEY_FUNCTION_NOT_PERMITTED;
  1664.     break;
  1665. }
  1666. pk11_FreeAttribute(att2);
  1667. md5 = MD5_NewContext();
  1668. if (md5 == NULL) { 
  1669.     crv = CKR_HOST_MEMORY;
  1670.     break;
  1671. }
  1672. sha = SHA1_NewContext();
  1673. if (sha == NULL) { 
  1674.     PORT_Free(md5);
  1675.     crv = CKR_HOST_MEMORY;
  1676.     break;
  1677. }
  1678. ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;
  1679. /*
  1680.  * clear out our returned keys so we can recover on failure
  1681.  */
  1682. ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;
  1683. ssl3_keys_out->hClientMacSecret = CK_INVALID_KEY;
  1684. ssl3_keys_out->hServerMacSecret = CK_INVALID_KEY;
  1685. ssl3_keys_out->hClientKey       = CK_INVALID_KEY;
  1686. ssl3_keys_out->hServerKey       = CK_INVALID_KEY;
  1687. /*
  1688.  * generate the key material: This looks amazingly similar to the
  1689.  * PMS code, and is clearly crying out for a function to provide it.
  1690.  */
  1691. if (isTLS) {
  1692.     SECStatus     status;
  1693.     SECItem       master = { siBuffer, NULL, 0 };
  1694.     SECItem       srcr   = { siBuffer, NULL, 0 };
  1695.     SECItem       keyblk = { siBuffer, NULL, 0 };
  1696.     unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];
  1697.     master.data = (unsigned char*)att->attrib.pValue;
  1698.     master.len  = att->attrib.ulValueLen;
  1699.     srcr.data   = srcrdata;
  1700.     srcr.len    = sizeof srcrdata;
  1701.     keyblk.data = key_block;
  1702.     keyblk.len  = sizeof key_block;
  1703.     PORT_Memcpy(srcrdata, 
  1704.                 ssl3_keys->RandomInfo.pServerRandom,
  1705. SSL3_RANDOM_LENGTH);
  1706.     PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, 
  1707.         ssl3_keys->RandomInfo.pClientRandom, 
  1708. SSL3_RANDOM_LENGTH);
  1709.     status = pk11_PRF(&master, "key expansion", &srcr, &keyblk);
  1710.     if (status != SECSuccess) {
  1711. goto key_and_mac_derive_fail;
  1712.     }
  1713. } else {
  1714.     /* key_block = 
  1715.      *     MD5(master_secret + SHA('A' + master_secret + 
  1716.      *                      ServerHello.random + ClientHello.random)) +
  1717.      *     MD5(master_secret + SHA('BB' + master_secret + 
  1718.      *                      ServerHello.random + ClientHello.random)) +
  1719.      *     MD5(master_secret + SHA('CCC' + master_secret + 
  1720.      *                      ServerHello.random + ClientHello.random)) +
  1721.      *     [...];
  1722.      */
  1723.     for (i = 0; i < NUM_MIXERS; i++) {
  1724.       SHA1_Begin(sha);
  1725.       SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));
  1726.       SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 
  1727.   att->attrib.ulValueLen);
  1728.               SHA1_Update(sha, ssl3_keys->RandomInfo.pServerRandom, 
  1729. ssl3_keys->RandomInfo.ulServerRandomLen);
  1730.               SHA1_Update(sha, ssl3_keys->RandomInfo.pClientRandom,
  1731. ssl3_keys->RandomInfo.ulClientRandomLen);
  1732.       SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);
  1733.       PORT_Assert(outLen == SHA1_LENGTH);
  1734.       MD5_Begin(md5);
  1735.       MD5_Update(md5, (const unsigned char*)att->attrib.pValue,
  1736.  att->attrib.ulValueLen);
  1737.       MD5_Update(md5, sha_out, outLen);
  1738.       MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);
  1739.       PORT_Assert(outLen == MD5_LENGTH);
  1740.     }
  1741. }
  1742. /*
  1743.  * Put the key material where it goes.
  1744.  */
  1745. i = 0; /* now shows how much consumed */
  1746. macSize    = ssl3_keys->ulMacSizeInBits/8;
  1747. effKeySize = ssl3_keys->ulKeySizeInBits/8;
  1748. IVSize     = ssl3_keys->ulIVSizeInBits/8;
  1749. if (keySize == 0) {
  1750.     effKeySize = keySize;
  1751. }
  1752. /* 
  1753.  * The key_block is partitioned as follows:
  1754.  * client_write_MAC_secret[CipherSpec.hash_size]
  1755.  */
  1756. crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
  1757.  &ssl3_keys_out->hClientMacSecret);
  1758. if (crv != CKR_OK)
  1759.     goto key_and_mac_derive_fail;
  1760. i += macSize;
  1761. /* 
  1762.  * server_write_MAC_secret[CipherSpec.hash_size]
  1763.  */
  1764. crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,
  1765.     &ssl3_keys_out->hServerMacSecret);
  1766. if (crv != CKR_OK) {
  1767.     goto key_and_mac_derive_fail;
  1768. }
  1769. i += macSize;
  1770. if (keySize) {
  1771.     if (!ssl3_keys->bIsExport) {
  1772. /* 
  1773. ** Generate Domestic write keys and IVs.
  1774. ** client_write_key[CipherSpec.key_material]
  1775. */
  1776. crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
  1777. keySize, &ssl3_keys_out->hClientKey);
  1778. if (crv != CKR_OK) {
  1779.     goto key_and_mac_derive_fail;
  1780. }
  1781. i += keySize;
  1782. /* 
  1783. ** server_write_key[CipherSpec.key_material]
  1784. */
  1785. crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],
  1786. keySize, &ssl3_keys_out->hServerKey);
  1787. if (crv != CKR_OK) {
  1788.     goto key_and_mac_derive_fail;
  1789. }
  1790. i += keySize;
  1791. /* 
  1792. ** client_write_IV[CipherSpec.IV_size]
  1793. */
  1794. PORT_Memcpy(ssl3_keys_out->pIVClient, &key_block[i], IVSize);
  1795. i += IVSize;
  1796. /* 
  1797. ** server_write_IV[CipherSpec.IV_size]
  1798. */
  1799. PORT_Memcpy(ssl3_keys_out->pIVServer, &key_block[i], IVSize);
  1800.      i += IVSize;
  1801.     } else if (!isTLS) {
  1802. /*
  1803. ** Generate SSL3 Export write keys and IVs.
  1804. ** client_write_key[CipherSpec.key_material]
  1805. ** final_client_write_key = MD5(client_write_key +
  1806. **                   ClientHello.random + ServerHello.random);
  1807. */
  1808. MD5_Begin(md5);
  1809. MD5_Update(md5, &key_block[i], effKeySize);
  1810.              MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
  1811. ssl3_keys->RandomInfo.ulClientRandomLen);
  1812.              MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 
  1813. ssl3_keys->RandomInfo.ulServerRandomLen);
  1814. MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
  1815. i += effKeySize;
  1816. crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,
  1817.   keySize,&ssl3_keys_out->hClientKey);
  1818. if (crv != CKR_OK) {
  1819.     goto key_and_mac_derive_fail;
  1820. }
  1821. /*
  1822. ** server_write_key[CipherSpec.key_material]
  1823. ** final_server_write_key = MD5(server_write_key +
  1824. **                    ServerHello.random + ClientHello.random);
  1825. */
  1826. MD5_Begin(md5);
  1827. MD5_Update(md5, &key_block[i], effKeySize);
  1828.              MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 
  1829. ssl3_keys->RandomInfo.ulServerRandomLen);
  1830.              MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
  1831. ssl3_keys->RandomInfo.ulClientRandomLen);
  1832. MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
  1833. i += effKeySize;
  1834. crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,
  1835.  keySize,&ssl3_keys_out->hServerKey);
  1836. if (crv != CKR_OK) {
  1837.     goto key_and_mac_derive_fail;
  1838. }
  1839. /*
  1840. ** client_write_IV = 
  1841. ** MD5(ClientHello.random + ServerHello.random);
  1842. */
  1843. MD5_Begin(md5);
  1844.              MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
  1845. ssl3_keys->RandomInfo.ulClientRandomLen);
  1846.              MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 
  1847. ssl3_keys->RandomInfo.ulServerRandomLen);
  1848. MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
  1849. PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);
  1850. /*
  1851. ** server_write_IV = 
  1852. ** MD5(ServerHello.random + ClientHello.random);
  1853. */
  1854. MD5_Begin(md5);
  1855.              MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 
  1856. ssl3_keys->RandomInfo.ulServerRandomLen);
  1857.              MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,
  1858. ssl3_keys->RandomInfo.ulClientRandomLen);
  1859. MD5_End(md5, key_block2, &outLen, MD5_LENGTH);
  1860. PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);
  1861.     } else {
  1862. /*
  1863. ** Generate TLS Export write keys and IVs.
  1864. */
  1865. SECStatus     status;
  1866. SECItem       secret = { siBuffer, NULL, 0 };
  1867. SECItem       crsr   = { siBuffer, NULL, 0 };
  1868. SECItem       keyblk = { siBuffer, NULL, 0 };
  1869. unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];
  1870. crsr.data   = crsrdata;
  1871. crsr.len    = sizeof crsrdata;
  1872. PORT_Memcpy(crsrdata, 
  1873.             ssl3_keys->RandomInfo.pClientRandom, 
  1874.     SSL3_RANDOM_LENGTH);
  1875. PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 
  1876.     ssl3_keys->RandomInfo.pServerRandom,
  1877.     SSL3_RANDOM_LENGTH);
  1878. /*
  1879. ** client_write_key[CipherSpec.key_material]
  1880. ** final_client_write_key = PRF(client_write_key, 
  1881. **                              "client write key",
  1882. **                              client_random + server_random);
  1883. */
  1884. secret.data = &key_block[i];
  1885. secret.len  = effKeySize;
  1886. i          += effKeySize;
  1887. keyblk.data = key_block2;
  1888. keyblk.len  = sizeof key_block2;
  1889. status = pk11_PRF(&secret, "client write key", &crsr, &keyblk);
  1890. if (status != SECSuccess) {
  1891.     goto key_and_mac_derive_fail;
  1892. }
  1893. crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2, 
  1894.        keySize, &ssl3_keys_out->hClientKey);
  1895. if (crv != CKR_OK) {
  1896.     goto key_and_mac_derive_fail;
  1897. }
  1898. /*
  1899. ** server_write_key[CipherSpec.key_material]
  1900. ** final_server_write_key = PRF(server_write_key,
  1901. **                              "server write key",
  1902. **                              client_random + server_random);
  1903. */
  1904. secret.data = &key_block[i];
  1905. secret.len  = effKeySize;
  1906. i          += effKeySize;
  1907. keyblk.data = key_block2;
  1908. keyblk.len  = sizeof key_block2;
  1909. status = pk11_PRF(&secret, "server write key", &crsr, &keyblk);
  1910. if (status != SECSuccess) {
  1911.     goto key_and_mac_derive_fail;
  1912. }
  1913. crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2, 
  1914.        keySize, &ssl3_keys_out->hServerKey);
  1915. if (crv != CKR_OK) {
  1916.     goto key_and_mac_derive_fail;
  1917. }
  1918. /*
  1919. ** iv_block = PRF("", "IV block", 
  1920. **                    client_random + server_random);
  1921. ** client_write_IV[SecurityParameters.IV_size]
  1922. ** server_write_IV[SecurityParameters.IV_size]
  1923. */
  1924. if (IVSize) {
  1925.     secret.data = NULL;
  1926.     secret.len  = 0;
  1927.     keyblk.data = &key_block[i];
  1928.     keyblk.len  = 2 * IVSize;
  1929.     status = pk11_PRF(&secret, "IV block", &crsr, &keyblk);
  1930.     if (status != SECSuccess) {
  1931. goto key_and_mac_derive_fail;
  1932.     }
  1933.     PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);
  1934.     PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,
  1935.                                 IVSize);
  1936. }
  1937.     }
  1938. }
  1939. crv = CKR_OK;
  1940. if (0) {
  1941. key_and_mac_derive_fail:
  1942.     if (crv == CKR_OK)
  1943.      crv = CKR_FUNCTION_FAILED;
  1944.     pk11_freeSSLKeys(hSession, ssl3_keys_out);
  1945. }
  1946. MD5_DestroyContext(md5, PR_TRUE);
  1947. SHA1_DestroyContext(sha, PR_TRUE);
  1948. pk11_FreeObject(key);
  1949. key = NULL;
  1950. break;
  1951.       }
  1952.     case CKM_CONCATENATE_BASE_AND_KEY:
  1953.       {
  1954. PK11Object *newKey;
  1955. crv = pk11_DeriveSensitiveCheck(sourceKey,key);
  1956. if (crv != CKR_OK) break;
  1957. session = pk11_SessionFromHandle(hSession);
  1958. if (session == NULL) {
  1959.             crv = CKR_SESSION_HANDLE_INVALID;
  1960.     break;
  1961.      }
  1962. newKey = pk11_ObjectFromHandle(*(CK_OBJECT_HANDLE *)
  1963. pMechanism->pParameter,session);
  1964. pk11_FreeSession(session);
  1965. if ( newKey == NULL) {
  1966.             crv = CKR_KEY_HANDLE_INVALID;
  1967.     break;
  1968. }
  1969. if (pk11_isTrue(newKey,CKA_SENSITIVE)) {
  1970.     crv = pk11_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,
  1971. sizeof(CK_BBOOL));
  1972.     if (crv != CKR_OK) {
  1973. pk11_FreeObject(newKey);
  1974. break;
  1975.     }
  1976. }
  1977. att2 = pk11_FindAttribute(newKey,CKA_VALUE);
  1978. if (att2 == NULL) {
  1979.     pk11_FreeObject(newKey);
  1980.             crv = CKR_KEY_HANDLE_INVALID;
  1981.     break;
  1982. }
  1983. tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;
  1984. if (keySize == 0) keySize = tmpKeySize;
  1985. if (keySize > tmpKeySize) {
  1986.     pk11_FreeObject(newKey);
  1987.     pk11_FreeAttribute(att2);
  1988.     crv = CKR_TEMPLATE_INCONSISTENT;
  1989.     break;
  1990. }
  1991. buf = (unsigned char*)PORT_Alloc(tmpKeySize);
  1992. if (buf == NULL) {
  1993.     pk11_FreeAttribute(att2);
  1994.     pk11_FreeObject(newKey);
  1995.     crv = CKR_HOST_MEMORY;
  1996.     break;
  1997. }
  1998. PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
  1999. PORT_Memcpy(buf+att->attrib.ulValueLen,
  2000. att2->attrib.pValue,att2->attrib.ulValueLen);
  2001. crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
  2002. PORT_ZFree(buf,tmpKeySize);
  2003. pk11_FreeAttribute(att2);
  2004. pk11_FreeObject(newKey);
  2005. break;
  2006.       }
  2007.     case CKM_CONCATENATE_BASE_AND_DATA:
  2008. stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
  2009. tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
  2010. if (keySize == 0) keySize = tmpKeySize;
  2011. if (keySize > tmpKeySize) {
  2012.     crv = CKR_TEMPLATE_INCONSISTENT;
  2013.     break;
  2014. }
  2015. buf = (unsigned char*)PORT_Alloc(tmpKeySize);
  2016. if (buf == NULL) {
  2017.     crv = CKR_HOST_MEMORY;
  2018.     break;
  2019. }
  2020. PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);
  2021. PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,
  2022. stringPtr->ulLen);
  2023. crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
  2024. PORT_ZFree(buf,tmpKeySize);
  2025. break;
  2026.     case CKM_CONCATENATE_DATA_AND_BASE:
  2027. stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
  2028. tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;
  2029. if (keySize == 0) keySize = tmpKeySize;
  2030. if (keySize > tmpKeySize) {
  2031.     crv = CKR_TEMPLATE_INCONSISTENT;
  2032.     break;
  2033. }
  2034. buf = (unsigned char*)PORT_Alloc(tmpKeySize);
  2035. if (buf == NULL) {
  2036.     crv = CKR_HOST_MEMORY;
  2037.     break;
  2038. }
  2039. PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);
  2040. PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,
  2041. att->attrib.ulValueLen);
  2042. crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
  2043. PORT_ZFree(buf,tmpKeySize);
  2044. break;
  2045.     case CKM_XOR_BASE_AND_DATA:
  2046. stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;
  2047. tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);
  2048. if (keySize == 0) keySize = tmpKeySize;
  2049. if (keySize > tmpKeySize) {
  2050.     crv = CKR_TEMPLATE_INCONSISTENT;
  2051.     break;
  2052. }
  2053. buf = (unsigned char*)PORT_Alloc(keySize);
  2054. if (buf == NULL) {
  2055.     crv = CKR_HOST_MEMORY;
  2056.     break;
  2057. }
  2058. PORT_Memcpy(buf,att->attrib.pValue,keySize);
  2059. for (i=0; i < (int)keySize; i++) {
  2060.     buf[i] ^= stringPtr->pData[i];
  2061. }
  2062. crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
  2063. PORT_ZFree(buf,keySize);
  2064. break;
  2065.     case CKM_EXTRACT_KEY_FROM_KEY:
  2066.       {
  2067. /* the following assumes 8 bits per byte */
  2068. CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;
  2069. CK_ULONG shift   = extract & 0x7;      /* extract mod 8 the fast way */
  2070. CK_ULONG offset  = extract >> 3;       /* extract div 8 the fast way */
  2071. if (keySize == 0)  {
  2072.     crv = CKR_TEMPLATE_INCOMPLETE;
  2073.     break;
  2074. }
  2075. /* make sure we have enough bits in the original key */
  2076. if (att->attrib.ulValueLen < 
  2077. (offset + keySize + ((shift != 0)? 1 :0)) ) {
  2078.     crv = CKR_MECHANISM_PARAM_INVALID;
  2079.     break;
  2080. }
  2081. buf = (unsigned char*)PORT_Alloc(keySize);
  2082. if (buf == NULL) {
  2083.     crv = CKR_HOST_MEMORY;
  2084.     break;
  2085. }
  2086. /* copy the bits we need into the new key */
  2087. for (i=0; i < (int)keySize; i++) {
  2088.     unsigned char *value =
  2089.  ((unsigned char *)att->attrib.pValue)+offset+i;
  2090.     if (shift) {
  2091.         buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));
  2092.     } else {
  2093. buf[i] = value[0];
  2094.     }
  2095. }
  2096. crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);
  2097. PORT_ZFree(buf,keySize);
  2098. break;
  2099.       }
  2100.     case CKM_MD2_KEY_DERIVATION:
  2101. if (keySize == 0) keySize = MD2_LENGTH;
  2102. if (keySize > MD2_LENGTH) {
  2103.     crv = CKR_TEMPLATE_INCONSISTENT;
  2104.     break;
  2105. }
  2106. /* now allocate the hash contexts */
  2107. md2 = MD2_NewContext();
  2108. if (md2 == NULL) { 
  2109.     crv = CKR_HOST_MEMORY;
  2110.     break;
  2111. }
  2112. MD2_Begin(md2);
  2113. MD2_Update(md2,(const unsigned char*)att->attrib.pValue,
  2114.    att->attrib.ulValueLen);
  2115. MD2_End(md2,key_block,&outLen,MD2_LENGTH);
  2116. MD2_DestroyContext(md2, PR_TRUE);
  2117. crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);
  2118. break;
  2119.     case CKM_MD5_KEY_DERIVATION:
  2120. if (keySize == 0) keySize = MD5_LENGTH;
  2121. if (keySize > MD5_LENGTH) {
  2122.     crv = CKR_TEMPLATE_INCONSISTENT;
  2123.     break;
  2124. }
  2125. /* now allocate the hash contexts */
  2126. md5 = MD5_NewContext();
  2127. if (md5 == NULL) { 
  2128.     crv = CKR_HOST_MEMORY;
  2129.     break;
  2130. }
  2131. MD5_Begin(md5);
  2132. MD5_Update(md5,(const unsigned char*)att->attrib.pValue,
  2133.    att->attrib.ulValueLen);
  2134. MD5_End(md5,key_block,&outLen,MD5_LENGTH);
  2135. MD5_DestroyContext(md5, PR_TRUE);
  2136. crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);
  2137. break;
  2138.      case CKM_SHA1_KEY_DERIVATION:
  2139. if (keySize == 0) keySize = SHA1_LENGTH;
  2140. if (keySize > SHA1_LENGTH) {
  2141.     crv = CKR_TEMPLATE_INCONSISTENT;
  2142.     break;
  2143. }
  2144. /* now allocate the hash contexts */
  2145. sha = SHA1_NewContext();
  2146. if (sha == NULL) { 
  2147.     crv = CKR_HOST_MEMORY;
  2148.     break;
  2149. }
  2150. SHA1_Begin(sha);
  2151. SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,
  2152.     att->attrib.ulValueLen);
  2153. SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);
  2154. SHA1_DestroyContext(sha, PR_TRUE);
  2155. crv = pk11_forceAttribute(key,CKA_VALUE,key_block,keySize);
  2156. break;
  2157.     case CKM_DH_PKCS_DERIVE:
  2158.       {
  2159. SECItem  derived,  dhPublic;
  2160. SECItem  dhPrime,  dhValue;
  2161. /* sourceKey - values for the local existing low key */
  2162. /* get prime and value attributes */
  2163. crv = pk11_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); 
  2164. if (crv != SECSuccess) break;
  2165. crv = pk11_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); 
  2166. if (crv != SECSuccess) {
  2167.       PORT_Free(dhPrime.data);
  2168.     break;
  2169. }
  2170. dhPublic.data = pMechanism->pParameter;
  2171. dhPublic.len  = pMechanism->ulParameterLen;
  2172. /* calculate private value - oct */
  2173. rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); 
  2174. PORT_Free(dhPrime.data);
  2175. PORT_Free(dhValue.data);
  2176.      
  2177. if (rv == SECSuccess) {
  2178.     pk11_forceAttribute(key, CKA_VALUE, derived.data, derived.len);
  2179.     PORT_ZFree(derived.data, derived.len);
  2180. } else
  2181.     crv = CKR_HOST_MEMORY;
  2182.     
  2183. break;
  2184.       }
  2185.     default:
  2186. crv = CKR_MECHANISM_INVALID;
  2187.     }
  2188.     pk11_FreeAttribute(att);
  2189.     pk11_FreeObject(sourceKey);
  2190.     if (crv != CKR_OK) { 
  2191. if (key) pk11_FreeObject(key);
  2192. return crv;
  2193.     }
  2194.     /* link the key object into the list */
  2195.     if (key) {
  2196. /* get the session */
  2197. key->wasDerived = PR_TRUE;
  2198. session = pk11_SessionFromHandle(hSession);
  2199. if (session == NULL) {
  2200.     pk11_FreeObject(key);
  2201.     return CKR_HOST_MEMORY;
  2202. }
  2203. crv = pk11_handleObject(key,session);
  2204. pk11_FreeSession(session);
  2205. if (crv == CKR_OK) {
  2206.     *phKey = key->handle;
  2207.      return crv;
  2208. }
  2209. pk11_FreeObject(key);
  2210.     }
  2211.     return crv;
  2212. }
  2213. /* NSC_GetFunctionStatus obtains an updated status of a function running 
  2214.  * in parallel with an application. */
  2215. CK_RV NSC_GetFunctionStatus(CK_SESSION_HANDLE hSession)
  2216. {
  2217.     return CKR_FUNCTION_NOT_PARALLEL;
  2218. }
  2219. /* NSC_CancelFunction cancels a function running in parallel */
  2220. CK_RV NSC_CancelFunction(CK_SESSION_HANDLE hSession)
  2221. {
  2222.     return CKR_FUNCTION_NOT_PARALLEL;
  2223. }
  2224. /* NSC_GetOperationState saves the state of the cryptographic 
  2225.  *operation in a session.
  2226.  * NOTE: This code only works for digest functions for now. eventually need
  2227.  * to add full flatten/resurect to our state stuff so that all types of state
  2228.  * can be saved */
  2229. CK_RV NSC_GetOperationState(CK_SESSION_HANDLE hSession, 
  2230. CK_BYTE_PTR  pOperationState, CK_ULONG_PTR pulOperationStateLen)
  2231. {
  2232.     PK11SessionContext *context;
  2233.     PK11Session *session;
  2234.     CK_RV crv;
  2235.     /* make sure we're legal */
  2236.     crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, &session);
  2237.     if (crv != CKR_OK) return crv;
  2238.     *pulOperationStateLen = context->cipherInfoLen + sizeof(CK_MECHANISM_TYPE)
  2239. + sizeof(PK11ContextType);
  2240.     if (pOperationState == NULL) {
  2241.         pk11_FreeSession(session);
  2242. return CKR_OK;
  2243.     }
  2244.     PORT_Memcpy(pOperationState,&context->type,sizeof(PK11ContextType));
  2245.     pOperationState += sizeof(PK11ContextType);
  2246.     PORT_Memcpy(pOperationState,&context->currentMech,
  2247. sizeof(CK_MECHANISM_TYPE));
  2248.     pOperationState += sizeof(CK_MECHANISM_TYPE);
  2249.     PORT_Memcpy(pOperationState,context->cipherInfo,context->cipherInfoLen);
  2250.     pk11_FreeSession(session);
  2251.     return CKR_OK;
  2252. }
  2253. #define pk11_Decrement(stateSize,len) 
  2254. stateSize = ((stateSize) > (CK_ULONG)(len)) ? 
  2255. ((stateSize) - (CK_ULONG)(len)) : 0;
  2256. /* NSC_SetOperationState restores the state of the cryptographic 
  2257.  * operation in a session. This is coded like it can restore lots of
  2258.  * states, but it only works for truly flat cipher structures. */
  2259. CK_RV NSC_SetOperationState(CK_SESSION_HANDLE hSession, 
  2260. CK_BYTE_PTR  pOperationState, CK_ULONG  ulOperationStateLen,
  2261.         CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey)
  2262. {
  2263.     PK11SessionContext *context;
  2264.     PK11Session *session;
  2265.     PK11ContextType type;
  2266.     CK_MECHANISM mech;
  2267.     CK_RV crv = CKR_OK;
  2268.     while (ulOperationStateLen != 0) {
  2269. /* get what type of state we're dealing with... */
  2270. PORT_Memcpy(&type,pOperationState, sizeof(PK11ContextType));
  2271. /* fix up session contexts based on type */
  2272. session = pk11_SessionFromHandle(hSession);
  2273. if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2274. context = pk11_ReturnContextByType(session, type);
  2275. pk11_SetContextByType(session, type, NULL);
  2276. if (context) { 
  2277.      pk11_FreeContext(context);
  2278. }
  2279. pOperationState += sizeof(PK11ContextType);
  2280. pk11_Decrement(ulOperationStateLen,sizeof(PK11ContextType));
  2281. /* get the mechanism structure */
  2282. PORT_Memcpy(&mech.mechanism,pOperationState,sizeof(CK_MECHANISM_TYPE));
  2283. pOperationState += sizeof(CK_MECHANISM_TYPE);
  2284. pk11_Decrement(ulOperationStateLen, sizeof(CK_MECHANISM_TYPE));
  2285. /* should be filled in... but not necessary for hash */
  2286. mech.pParameter = NULL;
  2287. mech.ulParameterLen = 0;
  2288. switch (type) {
  2289. case PK11_HASH:
  2290.     crv = NSC_DigestInit(hSession,&mech);
  2291.     if (crv != CKR_OK) break;
  2292.     crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, 
  2293. NULL);
  2294.     if (crv != CKR_OK) break;
  2295.     PORT_Memcpy(context->cipherInfo,pOperationState,
  2296. context->cipherInfoLen);
  2297.     pOperationState += context->cipherInfoLen;
  2298.     pk11_Decrement(ulOperationStateLen,context->cipherInfoLen);
  2299.     break;
  2300. default:
  2301.     /* do sign/encrypt/decrypt later */
  2302.     crv = CKR_SAVED_STATE_INVALID;
  2303.          }
  2304.          pk11_FreeSession(session);
  2305.  if (crv != CKR_OK) break;
  2306.     }
  2307.     return crv;
  2308. }
  2309. /* Dual-function cryptographic operations */
  2310. /* NSC_DigestEncryptUpdate continues a multiple-part digesting and encryption 
  2311.  * operation. */
  2312. CK_RV NSC_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR  pPart,
  2313.     CK_ULONG  ulPartLen, CK_BYTE_PTR  pEncryptedPart,
  2314.  CK_ULONG_PTR pulEncryptedPartLen)
  2315. {
  2316.     CK_RV crv;
  2317.     crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
  2318.       pulEncryptedPartLen);
  2319.     if (crv != CKR_OK) return crv;
  2320.     crv = NSC_DigestUpdate(hSession,pPart,ulPartLen);
  2321.     return crv;
  2322. }
  2323. /* NSC_DecryptDigestUpdate continues a multiple-part decryption and 
  2324.  * digesting operation. */
  2325. CK_RV NSC_DecryptDigestUpdate(CK_SESSION_HANDLE hSession,
  2326.     CK_BYTE_PTR  pEncryptedPart, CK_ULONG  ulEncryptedPartLen,
  2327.      CK_BYTE_PTR  pPart, CK_ULONG_PTR pulPartLen)
  2328. {
  2329.     CK_RV crv;
  2330.     crv = NSC_DecryptUpdate(hSession,pEncryptedPart, ulEncryptedPartLen, 
  2331. pPart, pulPartLen);
  2332.     if (crv != CKR_OK) return crv;
  2333.     crv = NSC_DigestUpdate(hSession,pPart,*pulPartLen);
  2334.     return crv;
  2335. }
  2336. /* NSC_SignEncryptUpdate continues a multiple-part signing and 
  2337.  * encryption operation. */
  2338. CK_RV NSC_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR  pPart,
  2339.  CK_ULONG  ulPartLen, CK_BYTE_PTR  pEncryptedPart,
  2340.  CK_ULONG_PTR pulEncryptedPartLen)
  2341. {
  2342.     CK_RV crv;
  2343.     crv = NSC_EncryptUpdate(hSession,pPart,ulPartLen, pEncryptedPart,
  2344.       pulEncryptedPartLen);
  2345.     if (crv != CKR_OK) return crv;
  2346.     crv = NSC_SignUpdate(hSession,pPart,ulPartLen);
  2347.     return crv;
  2348. }
  2349. /* NSC_DecryptVerifyUpdate continues a multiple-part decryption 
  2350.  * and verify operation. */
  2351. CK_RV NSC_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, 
  2352. CK_BYTE_PTR  pEncryptedData, CK_ULONG  ulEncryptedDataLen, 
  2353. CK_BYTE_PTR  pData, CK_ULONG_PTR pulDataLen)
  2354. {
  2355.     CK_RV crv;
  2356.     crv = NSC_DecryptUpdate(hSession,pEncryptedData, ulEncryptedDataLen, 
  2357. pData, pulDataLen);
  2358.     if (crv != CKR_OK) return crv;
  2359.     crv = NSC_VerifyUpdate(hSession, pData, *pulDataLen);
  2360.     return crv;
  2361. }
  2362. /* NSC_DigestKey continues a multi-part message-digesting operation,
  2363.  * by digesting the value of a secret key as part of the data already digested.
  2364.  */
  2365. CK_RV NSC_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) 
  2366. {
  2367.     PK11Session *session = NULL;
  2368.     PK11Object *key = NULL;
  2369.     PK11Attribute *att;
  2370.     CK_RV crv;
  2371.     session = pk11_SessionFromHandle(hSession);
  2372.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2373.     key = pk11_ObjectFromHandle(hKey,session);
  2374.     pk11_FreeSession(session);
  2375.     if (key == NULL)  return CKR_KEY_HANDLE_INVALID;
  2376.     /* PUT ANY DIGEST KEY RESTRICTION CHECKS HERE */
  2377.     /* make sure it's a valid  key for this operation */
  2378.     if (key->objclass != CKO_SECRET_KEY) {
  2379. pk11_FreeObject(key);
  2380. return CKR_KEY_TYPE_INCONSISTENT;
  2381.     }
  2382.     /* get the key value */
  2383.     att = pk11_FindAttribute(key,CKA_VALUE);
  2384.     pk11_FreeObject(key);
  2385.     crv = NSC_DigestUpdate(hSession,(CK_BYTE_PTR)att->attrib.pValue,
  2386.    att->attrib.ulValueLen);
  2387.     pk11_FreeAttribute(att);
  2388.     return crv;
  2389. }