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

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * This file implements PKCS 11 on top of our existing security modules
  35.  *
  36.  * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
  37.  *   This implementation has two slots:
  38.  * slot 1 is our generic crypto support. It does not require login.
  39.  *   It supports Public Key ops, and all they bulk ciphers and hashes. 
  40.  *   It can also support Private Key ops for imported Private keys. It does 
  41.  *   not have any token storage.
  42.  * slot 2 is our private key support. It requires a login before use. It
  43.  *   can store Private Keys and Certs as token objects. Currently only private
  44.  *   keys and their associated Certificates are saved on the token.
  45.  *
  46.  *   In this implementation, session objects are only visible to the session
  47.  *   that created or generated them.
  48.  */
  49. #include "seccomon.h"
  50. #include "secitem.h"
  51. #include "secport.h"
  52. #include "blapi.h"
  53. #include "pkcs11.h"
  54. #include "pkcs11i.h"
  55. #include "keylow.h"
  56. #include "cert.h"
  57. #include "sechash.h"
  58. #include "secder.h"
  59. #include "secdig.h"
  60. #include "secpkcs5.h" /* We do PBE below */
  61. #include "pkcs11t.h"
  62. #include "secoid.h"
  63. #include "alghmac.h"
  64. #include "softoken.h"
  65. #include "secasn1.h"
  66. #include "secmodi.h"
  67. #include "certdb.h"
  68. #include "ssl3prot.h"  /* for SSL3_RANDOM_LENGTH */
  69. #define __PASTE(x,y)    x##y
  70. /*
  71.  * we renamed all our internal functions, get the correct
  72.  * definitions for them...
  73.  */ 
  74. #undef CK_PKCS11_FUNCTION_INFO
  75. #undef CK_NEED_ARG_LIST
  76. #define CK_EXTERN extern
  77. #define CK_PKCS11_FUNCTION_INFO(func) 
  78. CK_RV __PASTE(NS,func)
  79. #define CK_NEED_ARG_LIST 1
  80.  
  81. #include "pkcs11f.h"
  82. /* forward static declaration. */
  83. static SECStatus pk11_PRF(const SECItem *secret, const char *label, 
  84.                           SECItem *seed, SECItem *result);  
  85. #define PK11_OFFSETOF(str, memb) ((PRPtrdiff)(&(((str *)0)->memb)))
  86. static void pk11_Null(void *data, PRBool freeit)
  87. {
  88.     return;
  89. /*
  90.  * free routines.... Free local type  allocated data, and convert
  91.  * other free routines to the destroy signature.
  92.  */
  93. static void
  94. pk11_FreePrivKey(SECKEYLowPrivateKey *key, PRBool freeit)
  95. {
  96.     SECKEY_LowDestroyPrivateKey(key);
  97. }
  98. static void
  99. pk11_HMAC_Destroy(HMACContext *context, PRBool freeit)
  100. {
  101.     HMAC_Destroy(context);
  102. }
  103. static void
  104. pk11_Space(void *data, PRBool freeit)
  105. {
  106.     PORT_Free(data);
  107. static void pk11_FreeSignInfo(PK11HashSignInfo *data, PRBool freeit)
  108. {
  109.     SECKEY_LowDestroyPrivateKey(data->key);
  110.     PORT_Free(data);
  111. static DSAPublicKey *
  112. DSA_CreateVerifyContext(SECKEYLowPublicKey *pubKey)
  113. {
  114.     PLArenaPool * arena;
  115.     DSAPublicKey * dsaKey;
  116.     SECStatus      rv;
  117.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  118.     if (!arena) goto loser; 
  119.     dsaKey = (DSAPublicKey *)PORT_ArenaZAlloc(arena, sizeof (DSAPublicKey));
  120.     if (!dsaKey) goto loser;
  121.     dsaKey->params.arena = arena;
  122. #define COPY_DSA_ITEM(item) 
  123.     rv = SECITEM_CopyItem(arena, &dsaKey->item, &pubKey->u.dsa.item); 
  124.     if (rv != SECSuccess) goto loser;
  125.     COPY_DSA_ITEM(params.prime);
  126.     COPY_DSA_ITEM(params.subPrime);
  127.     COPY_DSA_ITEM(params.base);
  128.     COPY_DSA_ITEM(publicValue);
  129.     return dsaKey;
  130. loser:
  131.     if (arena)
  132. PORT_FreeArena(arena, PR_TRUE);
  133.     return NULL;
  134. #undef COPY_DSA_ITEM
  135. }
  136. static void 
  137. DSA_DestroyVerifyContext(DSAPublicKey * key)
  138. {
  139.     if (key && key->params.arena)
  140. PORT_FreeArena(key->params.arena, PR_TRUE);
  141. }
  142. static DSAPrivateKey *
  143. DSA_CreateSignContext(SECKEYLowPrivateKey *privKey)
  144. {
  145.     PLArenaPool *  arena;
  146.     DSAPrivateKey * dsaKey;
  147.     SECStatus       rv;
  148.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  149.     if (!arena) goto loser; 
  150.     dsaKey = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof (DSAPrivateKey));
  151.     if (!dsaKey) goto loser;
  152.     dsaKey->params.arena = arena;
  153. #define COPY_DSA_ITEM(item) 
  154.     rv = SECITEM_CopyItem(arena, &dsaKey->item, &privKey->u.dsa.item); 
  155.     if (rv != SECSuccess) goto loser;
  156.     COPY_DSA_ITEM(params.prime);
  157.     COPY_DSA_ITEM(params.subPrime);
  158.     COPY_DSA_ITEM(params.base);
  159.     COPY_DSA_ITEM(publicValue);
  160.     COPY_DSA_ITEM(privateValue);
  161.     return dsaKey;
  162. loser:
  163.     if (arena)
  164. PORT_FreeArena(arena, PR_TRUE);
  165.     return NULL;
  166. #undef COPY_DSA_ITEM
  167. }
  168. static void 
  169. DSA_DestroySignContext(DSAPrivateKey * key)
  170. {
  171.     if (key && key->params.arena)
  172. PORT_FreeArena(key->params.arena, PR_TRUE);
  173. }
  174. /*
  175.  * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
  176.  * Deprecating a full des key to 40 bit key strenth.
  177.  */
  178. static CK_RV
  179. pk11_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
  180. {
  181.     unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
  182.     unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
  183.     unsigned char enc_src[8];
  184.     unsigned char enc_dest[8];
  185.     unsigned int leng,i;
  186.     DESContext *descx;
  187.     SECStatus rv;
  188.     
  189.     
  190.     /* zero the parity bits */
  191.     for (i=0; i < 8; i++) {
  192. enc_src[i] = cdmfkey[i] & 0xfe;
  193.     }
  194.     /* encrypt with key 1 */
  195.     descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
  196.     if (descx == NULL) return CKR_HOST_MEMORY;
  197.     rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
  198.     DES_DestroyContext(descx,PR_TRUE);
  199.     if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  200.     /* xor source with des, zero the parity bits and depricate the key*/
  201.     for (i=0; i < 8; i++) {
  202. if (i & 1) {
  203.     enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
  204. } else {
  205.     enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
  206. }
  207.     }
  208.     /* encrypt with key 2 */
  209.     descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
  210.     if (descx == NULL) return CKR_HOST_MEMORY;
  211.     rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
  212.     DES_DestroyContext(descx,PR_TRUE);
  213.     if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  214.     /* set the corret parity on our new des key */
  215.     pk11_FormatDESKey(deskey, 8);
  216.     return CKR_OK;
  217. }
  218. static CK_RV
  219. pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
  220.  CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,
  221.  PK11ContextType contextType);
  222. /*
  223.  * Calculate a Lynx checksum for CKM_LYNX_WRAP mechanism.
  224.  */
  225. static CK_RV
  226. pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey,
  227. unsigned char *checksum, unsigned char *key, CK_ULONG len)
  228. {
  229.     CK_BYTE E[10];
  230.     CK_ULONG Elen = sizeof (E);
  231.     CK_BYTE C[8];
  232.     CK_ULONG Clen = sizeof (C);
  233.     unsigned short sum1 = 0, sum2 = 0;
  234.     CK_MECHANISM mech = { CKM_DES_ECB, NULL, 0 };
  235.     int i;
  236.     CK_RV crv;
  237.     if (len != 8) return CKR_WRAPPED_KEY_LEN_RANGE;
  238.     
  239.     /* zero the parity bits */
  240.     for (i=0; i < 8; i++) {
  241. sum1 = sum1 + key[i];
  242. sum2 = sum2 + sum1;
  243.     }
  244.     /* encrypt with key 1 */
  245.     crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);
  246.     if (crv != CKR_OK) return crv;
  247.     crv = NSC_Encrypt(hSession,key,len,E,&Elen);
  248.     if (crv != CKR_OK) return crv;
  249.     E[8] = (sum2 >> 8) & 0xff;
  250.     E[9] = sum2 & 0xff;
  251.     crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT);
  252.     if (crv != CKR_OK) return crv;
  253.     crv = NSC_Encrypt(hSession,&E[2],len,C,&Clen);
  254.     if (crv != CKR_OK) return crv;
  255.     checksum[0] = C[6];
  256.     checksum[1] = C[7];
  257.     
  258.     return CKR_OK;
  259. }
  260. /* NSC_DestroyObject destroys an object. */
  261. CK_RV
  262. NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
  263. {
  264.     PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);
  265.     PK11Session *session;
  266.     PK11Object *object;
  267.     PK11FreeStatus status;
  268.     /*
  269.      * This whole block just makes sure we really can destroy the
  270.      * requested object.
  271.      */
  272.     session = pk11_SessionFromHandle(hSession);
  273.     if (session == NULL) {
  274.         return CKR_SESSION_HANDLE_INVALID;
  275.     }
  276.     object = pk11_ObjectFromHandle(hObject,session);
  277.     if (object == NULL) {
  278. pk11_FreeSession(session);
  279. return CKR_OBJECT_HANDLE_INVALID;
  280.     }
  281.     /* don't destroy a private object if we aren't logged in */
  282.     if ((!slot->isLoggedIn) && (slot->needLogin) &&
  283. (pk11_isTrue(object,CKA_PRIVATE))) {
  284. pk11_FreeSession(session);
  285. pk11_FreeObject(object);
  286. return CKR_USER_NOT_LOGGED_IN;
  287.     }
  288.     /* don't destroy a token object if we aren't in a rw session */
  289.     if (((session->info.flags & CKF_RW_SESSION) == 0) &&
  290. (pk11_isTrue(object,CKA_TOKEN))) {
  291. pk11_FreeSession(session);
  292. pk11_FreeObject(object);
  293. return CKR_SESSION_READ_ONLY;
  294.     }
  295.     pk11_DeleteObject(session,object);
  296.     pk11_FreeSession(session);
  297.     /*
  298.      * get some indication if the object is destroyed. Note: this is not
  299.      * 100%. Someone may have an object reference outstanding (though that
  300.      * should not be the case by here. Also note that the object is "half"
  301.      * destroyed. Our internal representation is destroyed, but it may still
  302.      * be in the data base.
  303.      */
  304.     status = pk11_FreeObject(object);
  305.     return (status != PK11_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
  306. }
  307. /*
  308.  ************** Crypto Functions:     Utilities ************************
  309.  */
  310. /* 
  311.  * return a context based on the PK11Context type.
  312.  */
  313. PK11SessionContext *
  314. pk11_ReturnContextByType(PK11Session *session, PK11ContextType type)
  315. {
  316.     switch (type) {
  317. case PK11_ENCRYPT:
  318. case PK11_DECRYPT:
  319.     return session->enc_context;
  320. case PK11_HASH:
  321.     return session->hash_context;
  322. case PK11_SIGN:
  323. case PK11_SIGN_RECOVER:
  324. case PK11_VERIFY:
  325. case PK11_VERIFY_RECOVER:
  326.     return session->hash_context;
  327.     }
  328.     return NULL;
  329. }
  330. /* 
  331.  * change a context based on the PK11Context type.
  332.  */
  333. void
  334. pk11_SetContextByType(PK11Session *session, PK11ContextType type, 
  335. PK11SessionContext *context)
  336. {
  337.     switch (type) {
  338. case PK11_ENCRYPT:
  339. case PK11_DECRYPT:
  340.     session->enc_context = context;
  341.     break;
  342. case PK11_HASH:
  343.     session->hash_context = context;
  344.     break;
  345. case PK11_SIGN:
  346. case PK11_SIGN_RECOVER:
  347. case PK11_VERIFY:
  348. case PK11_VERIFY_RECOVER:
  349.     session->hash_context = context;
  350.     break;
  351.     }
  352.     return;
  353. }
  354. /*
  355.  * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
  356.  * and C_XXX function. The function takes a session handle, the context type,
  357.  * and wether or not the session needs to be multipart. It returns the context,
  358.  * and optionally returns the session pointer (if sessionPtr != NULL) if session
  359.  * pointer is returned, the caller is responsible for freeing it.
  360.  */
  361. static CK_RV
  362. pk11_GetContext(CK_SESSION_HANDLE handle,PK11SessionContext **contextPtr,
  363. PK11ContextType type, PRBool needMulti, PK11Session **sessionPtr)
  364. {
  365.     PK11Session *session;
  366.     PK11SessionContext *context;
  367.     session = pk11_SessionFromHandle(handle);
  368.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  369.     context = pk11_ReturnContextByType(session,type);
  370.     /* make sure the context is valid */
  371.     if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){
  372.         pk11_FreeSession(session);
  373. return CKR_OPERATION_NOT_INITIALIZED;
  374.     }
  375.     *contextPtr = context;
  376.     if (sessionPtr != NULL) {
  377. *sessionPtr = session;
  378.     } else {
  379. pk11_FreeSession(session);
  380.     }
  381.     return CKR_OK;
  382. }
  383. /*
  384.  ************** Crypto Functions:     Encrypt ************************
  385.  */
  386. /*
  387.  * All the NSC_InitXXX functions have a set of common checks and processing they
  388.  * all need to do at the beginning. This is done here.
  389.  */
  390. static CK_RV
  391. pk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr,
  392.  PK11ContextType ctype,PK11Object **keyPtr,
  393.  CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
  394.  CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
  395. {
  396.     PK11Object *key = NULL;
  397.     PK11Attribute *att;
  398.     PK11SessionContext *context;
  399.     /* We can only init if there is not current context active */
  400.     if (pk11_ReturnContextByType(session,ctype) != NULL) {
  401. return CKR_OPERATION_ACTIVE;
  402.     }
  403.     /* find the key */
  404.     if (keyPtr) {
  405.         key = pk11_ObjectFromHandle(hKey,session);
  406.         if (key == NULL) {
  407.     return CKR_KEY_HANDLE_INVALID;
  408.      }
  409. /* make sure it's a valid  key for this operation */
  410. if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))
  411. || !pk11_isTrue(key,operation)) {
  412.     pk11_FreeObject(key);
  413.     return CKR_KEY_TYPE_INCONSISTENT;
  414. }
  415. /* get the key type */
  416. att = pk11_FindAttribute(key,CKA_KEY_TYPE);
  417. PORT_Assert(att != NULL);
  418. *keyTypePtr = *(CK_KEY_TYPE *)att->attrib.pValue;
  419. pk11_FreeAttribute(att);
  420. *keyPtr = key;
  421.     }
  422.     /* allocate the context structure */
  423.     context = (PK11SessionContext *)PORT_Alloc(sizeof(PK11SessionContext));
  424.     if (context == NULL) {
  425. if (key) pk11_FreeObject(key);
  426. return CKR_HOST_MEMORY;
  427.     }
  428.     context->type = ctype;
  429.     context->multi = PR_TRUE;
  430.     context->cipherInfo = NULL;
  431.     context->hashInfo = NULL;
  432.     context->doPad = PR_FALSE;
  433.     context->padDataLength = 0;
  434.     *contextPtr = context;
  435.     return CKR_OK;
  436. }
  437. /* NSC_EncryptInit initializes an encryption operation. */
  438. /* This function is used by NSC_EncryptInit and NSC_WrapKey. The only difference
  439.  * in their uses if whether or not etype is CKA_ENCRYPT or CKA_WRAP */
  440. static CK_RV
  441. pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
  442.  CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype,
  443.  PK11ContextType contextType)
  444. {
  445.     PK11Session *session;
  446.     PK11Object *key;
  447.     PK11SessionContext *context;
  448.     PK11Attribute *att;
  449.     CK_RC2_CBC_PARAMS *rc2_param;
  450. #if NSS_SOFTOKEN_DOES_RC5
  451.     CK_RC5_CBC_PARAMS *rc5_param;
  452.     SECItem rc5Key;
  453. #endif
  454.     CK_KEY_TYPE key_type;
  455.     CK_RV crv = CKR_OK;
  456.     SECKEYLowPublicKey *pubKey;
  457.     unsigned effectiveKeyLength;
  458.     unsigned char newdeskey[8];
  459.     PRBool useNewKey=PR_FALSE;
  460.     int t;
  461.     session = pk11_SessionFromHandle(hSession);
  462.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  463.     crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
  464.      CKO_PUBLIC_KEY, etype);
  465.     if (crv != CKR_OK) {
  466. pk11_FreeSession(session);
  467. return crv;
  468.     }
  469.     context->doPad = PR_FALSE;
  470.     switch(pMechanism->mechanism) {
  471.     case CKM_RSA_PKCS:
  472.     case CKM_RSA_X_509:
  473. if (key_type != CKK_RSA) {
  474.     crv = CKR_KEY_TYPE_INCONSISTENT;
  475.     break;
  476. }
  477. context->multi = PR_FALSE;
  478. pubKey = pk11_GetPubKey(key,CKK_RSA);
  479. if (pubKey == NULL) {
  480.     crv = CKR_HOST_MEMORY;
  481.     break;
  482. }
  483. context->cipherInfo = pubKey;
  484. context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
  485. ? RSA_EncryptRaw : RSA_EncryptBlock);
  486. context->destroy = pk11_Null;
  487. break;
  488.     case CKM_RC2_CBC_PAD:
  489. context->doPad = PR_TRUE;
  490. context->blockSize = 8;
  491. /* fall thru */
  492.     case CKM_RC2_ECB:
  493.     case CKM_RC2_CBC:
  494. if (key_type != CKK_RC2) {
  495.     crv = CKR_KEY_TYPE_INCONSISTENT;
  496.     break;
  497. }
  498. att = pk11_FindAttribute(key,CKA_VALUE);
  499. if (att == NULL) {
  500.     crv = CKR_KEY_HANDLE_INVALID;
  501.     break;
  502. }
  503. rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
  504. effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
  505. context->cipherInfo = 
  506.     RC2_CreateContext((unsigned char*)att->attrib.pValue,
  507.       att->attrib.ulValueLen, rc2_param->iv,
  508.       pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
  509.       NSS_RC2_CBC,effectiveKeyLength);
  510. pk11_FreeAttribute(att);
  511. if (context->cipherInfo == NULL) {
  512.     crv = CKR_HOST_MEMORY;
  513.     break;
  514. }
  515. context->update = (PK11Cipher) RC2_Encrypt;
  516. context->destroy = (PK11Destroy) RC2_DestroyContext;
  517. break;
  518. #if NSS_SOFTOKEN_DOES_RC5
  519.     case CKM_RC5_CBC_PAD:
  520. context->doPad = PR_TRUE;
  521. /* fall thru */
  522.     case CKM_RC5_ECB:
  523.     case CKM_RC5_CBC:
  524. if (key_type != CKK_RC5) {
  525.     crv = CKR_KEY_TYPE_INCONSISTENT;
  526.     break;
  527. }
  528. att = pk11_FindAttribute(key,CKA_VALUE);
  529. if (att == NULL) {
  530.     crv = CKR_KEY_HANDLE_INVALID;
  531.     break;
  532. }
  533. rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
  534. if (context->doPad) {
  535.    context->blockSize = rc5_param->ulWordsize*2;
  536. }
  537. rc5Key.data = (unsigned char*)att->attrib.pValue;
  538. rc5Key.len = att->attrib.ulValueLen;
  539. context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
  540.    rc5_param->ulWordsize,rc5_param->pIv,
  541.  pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
  542. pk11_FreeAttribute(att);
  543. if (context->cipherInfo == NULL) {
  544.     crv = CKR_HOST_MEMORY;
  545.     break;
  546. }
  547. context->update = (PK11Cipher) RC5_Encrypt;
  548. context->destroy = (PK11Destroy) RC5_DestroyContext;
  549. break;
  550. #endif
  551.     case CKM_RC4:
  552. if (key_type != CKK_RC4) {
  553.     crv = CKR_KEY_TYPE_INCONSISTENT;
  554.     break;
  555. }
  556. att = pk11_FindAttribute(key,CKA_VALUE);
  557. if (att == NULL) {
  558.     crv = CKR_KEY_HANDLE_INVALID;
  559.     break;
  560. }
  561. context->cipherInfo = 
  562.     RC4_CreateContext((unsigned char*)att->attrib.pValue,
  563.       att->attrib.ulValueLen);
  564. pk11_FreeAttribute(att);
  565. if (context->cipherInfo == NULL) {
  566.     crv = CKR_HOST_MEMORY;  /* WRONG !!! */
  567.     break;
  568. }
  569. context->update = (PK11Cipher) RC4_Encrypt;
  570. context->destroy = (PK11Destroy) RC4_DestroyContext;
  571. break;
  572.     case CKM_CDMF_CBC_PAD:
  573. context->doPad = PR_TRUE;
  574. context->blockSize = 8;
  575. /* fall thru */
  576.     case CKM_CDMF_ECB:
  577.     case CKM_CDMF_CBC:
  578. if (key_type != CKK_CDMF) {
  579.     crv = CKR_KEY_TYPE_INCONSISTENT;
  580.     break;
  581. }
  582. t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
  583. useNewKey=PR_TRUE;
  584. if (crv != CKR_OK) break;
  585. goto finish_des;
  586.     case CKM_DES_ECB:
  587. if (key_type != CKK_DES) {
  588.     crv = CKR_KEY_TYPE_INCONSISTENT;
  589.     break;
  590. }
  591. t = NSS_DES;
  592. goto finish_des;
  593.     case CKM_DES_CBC_PAD:
  594. context->doPad = PR_TRUE;
  595. context->blockSize = 8;
  596. /* fall thru */
  597.     case CKM_DES_CBC:
  598. if (key_type != CKK_DES) {
  599.     crv = CKR_KEY_TYPE_INCONSISTENT;
  600.     break;
  601. }
  602. t = NSS_DES_CBC;
  603. goto finish_des;
  604.     case CKM_DES3_ECB:
  605. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  606.     crv = CKR_KEY_TYPE_INCONSISTENT;
  607.     break;
  608. }
  609. t = NSS_DES_EDE3;
  610. goto finish_des;
  611.     case CKM_DES3_CBC_PAD:
  612. context->doPad = PR_TRUE;
  613. context->blockSize = 8;
  614. /* fall thru */
  615.     case CKM_DES3_CBC:
  616. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  617.     crv = CKR_KEY_TYPE_INCONSISTENT;
  618.     break;
  619. }
  620. t = NSS_DES_EDE3_CBC;
  621. finish_des:
  622. att = pk11_FindAttribute(key,CKA_VALUE);
  623. if (att == NULL) {
  624.     crv = CKR_KEY_HANDLE_INVALID;
  625.     break;
  626. }
  627. if (useNewKey) {
  628.     crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
  629.     if (crv != CKR_OK) {
  630. pk11_FreeAttribute(att);
  631. break;
  632.      }
  633. }
  634. context->cipherInfo = DES_CreateContext(
  635. useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
  636. (unsigned char*)pMechanism->pParameter,t, PR_TRUE);
  637. pk11_FreeAttribute(att);
  638. if (context->cipherInfo == NULL) {
  639.     crv = CKR_HOST_MEMORY;
  640.     break;
  641. }
  642. context->update = (PK11Cipher) DES_Encrypt;
  643. context->destroy = (PK11Destroy) DES_DestroyContext;
  644. break;
  645.     default:
  646. crv = CKR_MECHANISM_INVALID;
  647. break;
  648.     }
  649.     pk11_FreeObject(key);
  650.     if (crv != CKR_OK) {
  651.         pk11_FreeContext(context);
  652. pk11_FreeSession(session);
  653. return crv;
  654.     }
  655.     pk11_SetContextByType(session, contextType, context);
  656.     pk11_FreeSession(session);
  657.     return CKR_OK;
  658. }
  659. /* NSC_EncryptInit initializes an encryption operation. */
  660. CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
  661.  CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
  662. {
  663.     return pk11_EncryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, 
  664. PK11_ENCRYPT);
  665. }
  666. /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
  667. CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
  668.     CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
  669. CK_ULONG_PTR pulEncryptedPartLen)
  670. {
  671.     PK11SessionContext *context;
  672.     unsigned int outlen,i;
  673.     unsigned int padoutlen = 0;
  674.     unsigned int maxout = *pulEncryptedPartLen;
  675.     CK_RV crv;
  676.     SECStatus rv;
  677.     /* make sure we're legal */
  678.     crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_TRUE,NULL);
  679.     if (crv != CKR_OK) return crv;
  680.     /* do padding */
  681.     if (context->doPad) {
  682. /* deal with previous buffered data */
  683. if (context->padDataLength != 0) {
  684.     /* fill in the padded to a full block size */
  685.     for (i=context->padDataLength; 
  686. (ulPartLen != 0) && i < context->blockSize; i++) {
  687. context->padBuf[i] = *pPart++;
  688. ulPartLen--;
  689. context->padDataLength++;
  690.     }
  691.     /* not enough data to encrypt yet? then return */
  692.     if (context->padDataLength != context->blockSize) {
  693. *pulEncryptedPartLen = 0;
  694. return CKR_OK;
  695.     }
  696.     /* encrypt the current padded data */
  697.          rv = (*context->update)(context->cipherInfo,pEncryptedPart, 
  698. &outlen,context->blockSize,context->padBuf,context->blockSize);
  699.          if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  700.     pEncryptedPart += padoutlen;
  701.     maxout -= padoutlen;
  702. }
  703. /* save the residual */
  704. context->padDataLength = ulPartLen % context->blockSize;
  705. if (context->padDataLength) {
  706.     PORT_Memcpy(context->padBuf,
  707. &pPart[ulPartLen-context->padDataLength],
  708. context->padDataLength);
  709.     ulPartLen -= context->padDataLength;
  710. }
  711. /* if we've exhausted our new buffer, we're done */
  712. if (ulPartLen == 0) {
  713.     *pulEncryptedPartLen = padoutlen;
  714.     return CKR_OK;
  715. }
  716.     }
  717.     /* do it: NOTE: this assumes buf size in is >= buf size out! */
  718.     rv = (*context->update)(context->cipherInfo,pEncryptedPart, 
  719. &outlen, maxout, pPart, ulPartLen);
  720.     *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);
  721.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  722. }
  723. /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
  724. CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
  725.     CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
  726. {
  727.     PK11Session *session;
  728.     PK11SessionContext *context;
  729.     unsigned int outlen,i;
  730.     unsigned int maxout = *pulLastEncryptedPartLen;
  731.     CK_RV crv;
  732.     SECStatus rv = SECSuccess;
  733.     /* make sure we're legal */
  734.     crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_TRUE,&session);
  735.     if (crv != CKR_OK) return crv;
  736.     *pulLastEncryptedPartLen = 0;
  737.     /* do padding */
  738.     if (context->doPad) {
  739. unsigned char  padbyte = (unsigned char) 
  740. (context->blockSize - context->padDataLength); 
  741. /* fill out rest of pad buffer with pad magic*/
  742. for (i=context->padDataLength; i < context->blockSize; i++) {
  743.     context->padBuf[i] = padbyte;
  744. }
  745. rv = (*context->update)(context->cipherInfo,pLastEncryptedPart, 
  746. &outlen, maxout, context->padBuf, context->blockSize);
  747. if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
  748.     }
  749.     /* do it */
  750.     pk11_SetContextByType(session, PK11_ENCRYPT, NULL);
  751.     pk11_FreeContext(context);
  752.     pk11_FreeSession(session);
  753.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  754. }
  755. /* NSC_Encrypt encrypts single-part data. */
  756. CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
  757.      CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
  758.  CK_ULONG_PTR pulEncryptedDataLen)
  759. {
  760.     PK11Session *session;
  761.     PK11SessionContext *context;
  762.     unsigned int outlen;
  763.     unsigned int maxoutlen = *pulEncryptedDataLen;
  764.     CK_RV crv;
  765.     CK_RV crv2;
  766.     SECStatus rv;
  767.     /* make sure we're legal */
  768.     crv = pk11_GetContext(hSession,&context,PK11_ENCRYPT,PR_FALSE,&session);
  769.     if (crv != CKR_OK) return crv;
  770.     if (context->doPad) {
  771. CK_ULONG finalLen;
  772. /* padding is fairly complicated, have the update and final 
  773.  * code deal with it */
  774.         pk11_FreeSession(session);
  775. crv = NSC_EncryptUpdate(hSession,pData,ulDataLen,pEncryptedData,
  776. pulEncryptedDataLen);
  777. if (crv != CKR_OK) *pulEncryptedDataLen = 0;
  778. maxoutlen -= *pulEncryptedDataLen;
  779. pEncryptedData += *pulEncryptedDataLen;
  780. finalLen = maxoutlen;
  781. crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
  782. if (crv2 == CKR_OK) { *pulEncryptedDataLen += finalLen; }
  783. return crv == CKR_OK ? crv2 :crv;
  784.     }
  785.     /* do it: NOTE: this assumes buf size is big enough. */
  786.     rv = (*context->update)(context->cipherInfo, pEncryptedData, 
  787. &outlen, maxoutlen, pData, ulDataLen);
  788.     *pulEncryptedDataLen = (CK_ULONG) outlen;
  789.     pk11_FreeContext(context);
  790.     pk11_SetContextByType(session, PK11_ENCRYPT, NULL);
  791.     pk11_FreeSession(session);
  792.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  793. }
  794. /*
  795.  ************** Crypto Functions:     Decrypt ************************
  796.  */
  797. /* NSC_DecryptInit initializes a decryption operation. */
  798. static CK_RV pk11_DecryptInit( CK_SESSION_HANDLE hSession,
  799.   CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE dtype,
  800. PK11ContextType contextType)
  801. {
  802.     PK11Session *session;
  803.     PK11Object *key;
  804.     PK11Attribute *att;
  805.     PK11SessionContext *context;
  806.     CK_RC2_CBC_PARAMS *rc2_param;
  807. #if NSS_SOFTOKEN_DOES_RC5
  808.     CK_RC5_CBC_PARAMS *rc5_param;
  809.     SECItem rc5Key;
  810. #endif
  811.     CK_KEY_TYPE key_type;
  812.     CK_RV crv = CKR_OK;
  813.     unsigned effectiveKeyLength;
  814.     SECKEYLowPrivateKey *privKey;
  815.     unsigned char newdeskey[8];
  816.     PRBool useNewKey=PR_FALSE;
  817.     int t;
  818.     session = pk11_SessionFromHandle(hSession);
  819.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  820.     crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
  821. CKO_PRIVATE_KEY,dtype);
  822.     if (crv != CKR_OK) {
  823. pk11_FreeSession(session);
  824. return crv;
  825.     }
  826.     /*
  827.      * now handle each mechanism
  828.      */
  829.     switch(pMechanism->mechanism) {
  830.     case CKM_RSA_PKCS:
  831.     case CKM_RSA_X_509:
  832. if (key_type != CKK_RSA) {
  833.     crv = CKR_KEY_TYPE_INCONSISTENT;
  834.     break;
  835. }
  836. context->multi = PR_FALSE;
  837. privKey = pk11_GetPrivKey(key,CKK_RSA);
  838. if (privKey == NULL) {
  839.     crv = CKR_HOST_MEMORY;
  840.     break;
  841. }
  842. context->cipherInfo = privKey;
  843. context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509
  844. ? RSA_DecryptRaw : RSA_DecryptBlock);
  845. context->destroy = (context->cipherInfo == key->objectInfo) ?
  846. (PK11Destroy) pk11_Null : (PK11Destroy) pk11_FreePrivKey;
  847. break;
  848.     case CKM_RC2_CBC_PAD:
  849. context->doPad = PR_TRUE;
  850. context->blockSize = 8;
  851. /* fall thru */
  852.     case CKM_RC2_ECB:
  853.     case CKM_RC2_CBC:
  854. if (key_type != CKK_RC2) {
  855.     crv = CKR_KEY_TYPE_INCONSISTENT;
  856.     break;
  857. }
  858. att = pk11_FindAttribute(key,CKA_VALUE);
  859. rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
  860. effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
  861. context->cipherInfo = RC2_CreateContext((unsigned char*)att->attrib.pValue,
  862. att->attrib.ulValueLen, rc2_param->iv,
  863.  pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
  864.  NSS_RC2_CBC, effectiveKeyLength);
  865. pk11_FreeAttribute(att);
  866. if (context->cipherInfo == NULL) {
  867.     crv = CKR_HOST_MEMORY;
  868.     break;
  869. }
  870. context->update = (PK11Cipher) RC2_Decrypt;
  871. context->destroy = (PK11Destroy) RC2_DestroyContext;
  872. break;
  873. #if NSS_SOFTOKEN_DOES_RC5
  874.     case CKM_RC5_CBC_PAD:
  875. context->doPad = PR_TRUE;
  876. /* fall thru */
  877.     case CKM_RC5_ECB:
  878.     case CKM_RC5_CBC:
  879. if (key_type != CKK_RC5) {
  880.     crv = CKR_KEY_TYPE_INCONSISTENT;
  881.     break;
  882. }
  883. att = pk11_FindAttribute(key,CKA_VALUE);
  884. if (att == NULL) {
  885.     crv = CKR_KEY_HANDLE_INVALID;
  886.     break;
  887. }
  888. rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
  889. if (context->doPad) {
  890.    context->blockSize = rc5_param->ulWordsize*2;
  891. }
  892. rc5Key.data = (unsigned char*)att->attrib.pValue;
  893. rc5Key.len = att->attrib.ulValueLen;
  894. context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
  895.    rc5_param->ulWordsize,rc5_param->pIv,
  896.  pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
  897. pk11_FreeAttribute(att);
  898. if (context->cipherInfo == NULL) {
  899.     crv = CKR_HOST_MEMORY;
  900.     break;
  901. }
  902. context->update = (PK11Cipher) RC5_Decrypt;
  903. context->destroy = (PK11Destroy) RC5_DestroyContext;
  904. break;
  905. #endif
  906.     case CKM_RC4:
  907. if (key_type != CKK_RC4) {
  908.     crv = CKR_KEY_TYPE_INCONSISTENT;
  909.     break;
  910. }
  911. att = pk11_FindAttribute(key,CKA_VALUE);
  912. context->cipherInfo = 
  913.     RC4_CreateContext((unsigned char*)att->attrib.pValue,
  914.       att->attrib.ulValueLen);
  915. pk11_FreeAttribute(att);
  916. if (context->cipherInfo == NULL) {
  917.     crv = CKR_HOST_MEMORY;
  918.     break;
  919. }
  920. context->update = (PK11Cipher) RC4_Decrypt;
  921. context->destroy = (PK11Destroy) RC4_DestroyContext;
  922. break;
  923.     case CKM_CDMF_CBC_PAD:
  924. context->doPad = PR_TRUE;
  925. context->blockSize = 8;
  926. /* fall thru */
  927.     case CKM_CDMF_ECB:
  928.     case CKM_CDMF_CBC:
  929. if (key_type != CKK_CDMF) {
  930.     crv = CKR_KEY_TYPE_INCONSISTENT;
  931.     break;
  932. }
  933. t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
  934. useNewKey = PR_TRUE;
  935. if (crv != CKR_OK) break;
  936. goto finish_des;
  937.     case CKM_DES_ECB:
  938. if (key_type != CKK_DES) {
  939.     crv = CKR_KEY_TYPE_INCONSISTENT;
  940.     break;
  941. }
  942. t = NSS_DES;
  943. goto finish_des;
  944.     case CKM_DES_CBC_PAD:
  945. context->doPad = PR_TRUE;
  946. context->blockSize = 8;
  947. /* fall thru */
  948.     case CKM_DES_CBC:
  949. if (key_type != CKK_DES) {
  950.     crv = CKR_KEY_TYPE_INCONSISTENT;
  951.     break;
  952. }
  953. t = NSS_DES_CBC;
  954. goto finish_des;
  955.     case CKM_DES3_ECB:
  956. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  957.     crv = CKR_KEY_TYPE_INCONSISTENT;
  958.     break;
  959. }
  960. t = NSS_DES_EDE3;
  961. goto finish_des;
  962.     case CKM_DES3_CBC_PAD:
  963. context->doPad = PR_TRUE;
  964. context->blockSize = 8;
  965. /* fall thru */
  966.     case CKM_DES3_CBC:
  967. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  968.     crv = CKR_KEY_TYPE_INCONSISTENT;
  969.     break;
  970. }
  971. t = NSS_DES_EDE3_CBC;
  972. finish_des:
  973. att = pk11_FindAttribute(key,CKA_VALUE);
  974. if (att == NULL) {
  975.     crv = CKR_KEY_HANDLE_INVALID;
  976.     break;
  977. }
  978. if (useNewKey) {
  979.     crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
  980.     if (crv != CKR_OK) {
  981. pk11_FreeAttribute(att);
  982. break;
  983.      }
  984. }
  985. context->cipherInfo = DES_CreateContext(
  986. useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
  987. (unsigned char*)pMechanism->pParameter,t, PR_FALSE);
  988. pk11_FreeAttribute(att);
  989. if (context->cipherInfo == NULL) {
  990.     crv = CKR_HOST_MEMORY;
  991.     break;
  992. }
  993. context->update = (PK11Cipher) DES_Decrypt;
  994. context->destroy = (PK11Destroy) DES_DestroyContext;
  995. break;
  996.     default:
  997. crv = CKR_MECHANISM_INVALID;
  998. break;
  999.     }
  1000.     pk11_FreeObject(key);
  1001.     if (crv != CKR_OK) {
  1002.         pk11_FreeContext(context);
  1003. pk11_FreeSession(session);
  1004. return crv;
  1005.     }
  1006.     pk11_SetContextByType(session, contextType, context);
  1007.     pk11_FreeSession(session);
  1008.     return CKR_OK;
  1009. }
  1010. /* NSC_DecryptInit initializes a decryption operation. */
  1011. CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
  1012.  CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
  1013. {
  1014.     return pk11_DecryptInit(hSession,pMechanism,hKey,CKA_DECRYPT,PK11_DECRYPT);
  1015. }
  1016. /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
  1017. CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
  1018.     CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
  1019.      CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
  1020. {
  1021.     PK11SessionContext *context;
  1022.     unsigned int padoutlen = 0;
  1023.     unsigned int outlen;
  1024.     unsigned int maxout = *pulPartLen;
  1025.     CK_RV crv;
  1026.     SECStatus rv;
  1027.     /* make sure we're legal */
  1028.     crv = pk11_GetContext(hSession,&context,PK11_DECRYPT,PR_TRUE,NULL);
  1029.     if (crv != CKR_OK) return crv;
  1030.     if (context->doPad) {
  1031. /* first decrypt our saved buffer */
  1032. if (context->padDataLength != 0) {
  1033.          rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
  1034.  maxout, context->padBuf, context->blockSize);
  1035.          if (rv != SECSuccess)  return CKR_DEVICE_ERROR;
  1036.     pPart += padoutlen;
  1037.     maxout -= padoutlen;
  1038. }
  1039. /* now save the final block for the next decrypt or the final */
  1040. PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen -
  1041. context->blockSize], context->blockSize);
  1042. context->padDataLength = context->blockSize;
  1043. ulEncryptedPartLen -= context->padDataLength;
  1044.     }
  1045.     /* do it: NOTE: this assumes buf size in is >= buf size out! */
  1046.     rv = (*context->update)(context->cipherInfo,pPart, &outlen,
  1047.  maxout, pEncryptedPart, ulEncryptedPartLen);
  1048.     *pulPartLen = (CK_ULONG) (outlen + padoutlen);
  1049.     return (rv == SECSuccess)  ? CKR_OK : CKR_DEVICE_ERROR;
  1050. }
  1051. /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
  1052. CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
  1053.     CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
  1054. {
  1055.     PK11Session *session;
  1056.     PK11SessionContext *context;
  1057.     unsigned int outlen;
  1058.     unsigned int maxout = *pulLastPartLen;
  1059.     CK_RV crv;
  1060.     SECStatus rv = SECSuccess;
  1061.     /* make sure we're legal */
  1062.     crv = pk11_GetContext(hSession,&context,PK11_DECRYPT,PR_TRUE,&session);
  1063.     if (crv != CKR_OK) return crv;
  1064.     *pulLastPartLen = 0;
  1065.     if (context->doPad) {
  1066. /* decrypt our saved buffer */
  1067. if (context->padDataLength != 0) {
  1068.     /* this assumes that pLastPart is big enough to hold the *whole*
  1069.      * buffer!!! */
  1070.          rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
  1071.  maxout, context->padBuf, context->blockSize);
  1072.          if (rv == SECSuccess) {
  1073. unsigned int padSize = 
  1074.     (unsigned int) pLastPart[context->blockSize-1];
  1075. *pulLastPartLen = outlen - padSize;
  1076.     }
  1077. }
  1078.     }
  1079.     /* do it */
  1080.     pk11_SetContextByType(session, PK11_DECRYPT, NULL);
  1081.     pk11_FreeContext(context);
  1082.     pk11_FreeSession(session);
  1083.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  1084. }
  1085. /* NSC_Decrypt decrypts encrypted data in a single part. */
  1086. CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
  1087.     CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,
  1088.      CK_ULONG_PTR pulDataLen)
  1089. {
  1090.     PK11Session *session;
  1091.     PK11SessionContext *context;
  1092.     unsigned int outlen;
  1093.     unsigned int maxoutlen = *pulDataLen;
  1094.     CK_RV crv;
  1095.     CK_RV crv2;
  1096.     SECStatus rv;
  1097.     /* make sure we're legal */
  1098.     crv = pk11_GetContext(hSession,&context,PK11_DECRYPT,PR_FALSE,&session);
  1099.     if (crv != CKR_OK) return crv;
  1100.     if (context->doPad) {
  1101. CK_ULONG finalLen;
  1102. /* padding is fairly complicated, have the update and final 
  1103.  * code deal with it */
  1104.         pk11_FreeSession(session);
  1105. crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
  1106. pData, pulDataLen);
  1107. if (crv != CKR_OK) *pulDataLen = 0;
  1108. maxoutlen -= *pulDataLen;
  1109. pData += *pulDataLen;
  1110. finalLen = maxoutlen;
  1111. crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
  1112. if (crv2 == CKR_OK) { *pulDataLen += finalLen; }
  1113. return crv == CKR_OK ? crv2 :crv;
  1114.     }
  1115.     rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen, 
  1116. pEncryptedData, ulEncryptedDataLen);
  1117.     *pulDataLen = (CK_ULONG) outlen;
  1118.     pk11_FreeContext(context);
  1119.     pk11_SetContextByType(session, PK11_DECRYPT, NULL);
  1120.     pk11_FreeSession(session);
  1121.     return (rv == SECSuccess)  ? CKR_OK : CKR_DEVICE_ERROR;
  1122. }
  1123. /*
  1124.  ************** Crypto Functions:     Digest (HASH)  ************************
  1125.  */
  1126. /* NSC_DigestInit initializes a message-digesting operation. */
  1127. CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
  1128.      CK_MECHANISM_PTR pMechanism)
  1129. {
  1130.     PK11Session *session;
  1131.     PK11SessionContext *context;
  1132.     MD2Context *md2_context;
  1133.     MD5Context *md5_context;
  1134.     SHA1Context *sha1_context;
  1135.     CK_RV crv = CKR_OK;
  1136.     session = pk11_SessionFromHandle(hSession);
  1137.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  1138.     crv = pk11_InitGeneric(session,&context,PK11_HASH,NULL,0,NULL, 0, 0);
  1139.     if (crv != CKR_OK) {
  1140. pk11_FreeSession(session);
  1141. return crv;
  1142.     }
  1143.     switch(pMechanism->mechanism) {
  1144.     case CKM_MD2:
  1145. md2_context = MD2_NewContext();
  1146. context->cipherInfo = (void *)md2_context;
  1147. context->cipherInfoLen = MD2_FlattenSize(md2_context);
  1148. context->currentMech = CKM_MD2;
  1149.         if (context->cipherInfo == NULL) {
  1150.     crv= CKR_HOST_MEMORY;
  1151.     
  1152. }
  1153. context->hashUpdate = (PK11Hash) MD2_Update;
  1154. context->end = (PK11End) MD2_End;
  1155. context->destroy = (PK11Destroy) MD2_DestroyContext;
  1156. MD2_Begin(md2_context);
  1157. break;
  1158.     case CKM_MD5:
  1159. md5_context = MD5_NewContext();
  1160. context->cipherInfo = (void *)md5_context;
  1161. context->cipherInfoLen = MD5_FlattenSize(md5_context);
  1162. context->currentMech = CKM_MD5;
  1163.         if (context->cipherInfo == NULL) {
  1164.     crv= CKR_HOST_MEMORY;
  1165.     
  1166. }
  1167. context->hashUpdate = (PK11Hash) MD5_Update;
  1168. context->end = (PK11End) MD5_End;
  1169. context->destroy = (PK11Destroy) MD5_DestroyContext;
  1170. MD5_Begin(md5_context);
  1171. break;
  1172.     case CKM_SHA_1:
  1173. sha1_context = SHA1_NewContext();
  1174. context->cipherInfo = (void *)sha1_context;
  1175. context->cipherInfoLen = SHA1_FlattenSize(sha1_context);
  1176. context->currentMech = CKM_SHA_1;
  1177.         if (context->cipherInfo == NULL) {
  1178.     crv= CKR_HOST_MEMORY;
  1179.     break;
  1180. }
  1181. context->hashUpdate = (PK11Hash) SHA1_Update;
  1182. context->end = (PK11End) SHA1_End;
  1183. context->destroy = (PK11Destroy) SHA1_DestroyContext;
  1184. SHA1_Begin(sha1_context);
  1185. break;
  1186.     default:
  1187. crv = CKR_MECHANISM_INVALID;
  1188. break;
  1189.     }
  1190.     if (crv != CKR_OK) {
  1191.         pk11_FreeContext(context);
  1192. pk11_FreeSession(session);
  1193. return crv;
  1194.     }
  1195.     pk11_SetContextByType(session, PK11_HASH, context);
  1196.     pk11_FreeSession(session);
  1197.     return CKR_OK;
  1198. }
  1199. /* NSC_Digest digests data in a single part. */
  1200. CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
  1201.     CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
  1202.      CK_ULONG_PTR pulDigestLen)
  1203. {
  1204.     PK11Session *session;
  1205.     PK11SessionContext *context;
  1206.     unsigned int digestLen;
  1207.     unsigned int maxout = *pulDigestLen;
  1208.     CK_RV crv;
  1209.     /* make sure we're legal */
  1210.     crv = pk11_GetContext(hSession,&context,PK11_HASH,PR_FALSE,&session);
  1211.     if (crv != CKR_OK) return crv;
  1212.     /* do it: */
  1213.     (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
  1214.     /*  NOTE: this assumes buf size is bigenough for the algorithm */
  1215.     (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);
  1216.     *pulDigestLen = digestLen;
  1217.     pk11_SetContextByType(session, PK11_HASH, NULL);
  1218.     pk11_FreeContext(context);
  1219.     pk11_FreeSession(session);
  1220.     return CKR_OK;
  1221. }
  1222. /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
  1223. CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
  1224.     CK_ULONG ulPartLen)
  1225. {
  1226.     PK11SessionContext *context;
  1227.     CK_RV crv;
  1228.     /* make sure we're legal */
  1229.     crv = pk11_GetContext(hSession,&context,PK11_HASH,PR_TRUE,NULL);
  1230.     if (crv != CKR_OK) return crv;
  1231.     /* do it: */
  1232.     (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
  1233.     return CKR_OK;
  1234. }
  1235. /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
  1236. CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
  1237.      CK_ULONG_PTR pulDigestLen)
  1238. {
  1239.     PK11Session *session;
  1240.     PK11SessionContext *context;
  1241.     unsigned int maxout = *pulDigestLen;
  1242.     unsigned int digestLen;
  1243.     CK_RV crv;
  1244.     /* make sure we're legal */
  1245.     crv = pk11_GetContext(hSession, &context, PK11_HASH, PR_TRUE, &session);
  1246.     if (crv != CKR_OK) return crv;
  1247.     if (pDigest != NULL) {
  1248.         (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
  1249.         *pulDigestLen = digestLen;
  1250.     } else {
  1251. *pulDigestLen = 0;
  1252.     }
  1253.     pk11_SetContextByType(session, PK11_HASH, NULL);
  1254.     pk11_FreeContext(context);
  1255.     pk11_FreeSession(session);
  1256.     return CKR_OK;
  1257. }
  1258. /*
  1259.  * this helper functions are used by Generic Macing and Signing functions
  1260.  * that use hashes as part of their operations. 
  1261.  */
  1262. static CK_RV
  1263. pk11_doSubMD2(PK11SessionContext *context) {
  1264. MD2Context *md2_context = MD2_NewContext();
  1265. context->hashInfo = (void *)md2_context;
  1266.         if (context->hashInfo == NULL) {
  1267.     return CKR_HOST_MEMORY;
  1268. }
  1269. context->hashUpdate = (PK11Hash) MD2_Update;
  1270. context->end = (PK11End) MD2_End;
  1271. context->hashdestroy = (PK11Destroy) MD2_DestroyContext;
  1272. MD2_Begin(md2_context);
  1273. return CKR_OK;
  1274. }
  1275. static CK_RV
  1276. pk11_doSubMD5(PK11SessionContext *context) {
  1277. MD5Context *md5_context = MD5_NewContext();
  1278. context->hashInfo = (void *)md5_context;
  1279.         if (context->hashInfo == NULL) {
  1280.     return CKR_HOST_MEMORY;
  1281. }
  1282. context->hashUpdate = (PK11Hash) MD5_Update;
  1283. context->end = (PK11End) MD5_End;
  1284. context->hashdestroy = (PK11Destroy) MD5_DestroyContext;
  1285. MD5_Begin(md5_context);
  1286. return CKR_OK;
  1287. }
  1288. static CK_RV
  1289. pk11_doSubSHA1(PK11SessionContext *context) {
  1290. SHA1Context *sha1_context = SHA1_NewContext();
  1291. context->hashInfo = (void *)sha1_context;
  1292.         if (context->hashInfo == NULL) {
  1293.     return CKR_HOST_MEMORY;
  1294. }
  1295. context->hashUpdate = (PK11Hash) SHA1_Update;
  1296. context->end = (PK11End) SHA1_End;
  1297. context->hashdestroy = (PK11Destroy) SHA1_DestroyContext;
  1298. SHA1_Begin(sha1_context);
  1299. return CKR_OK;
  1300. }
  1301. /*
  1302.  * HMAC General copies only a portion of the result. This update routine likes
  1303.  * the final HMAC output with the signature.
  1304.  */
  1305. static SECStatus
  1306. pk11_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen,
  1307. unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
  1308. {
  1309.     if (maxLen < *copyLen) return SECFailure;
  1310.     PORT_Memcpy(sig,hash,*copyLen);
  1311.     *sigLen = *copyLen;
  1312.     return SECSuccess;
  1313. }
  1314. /* Verify is just a compare for HMAC */
  1315. static SECStatus
  1316. pk11_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
  1317. unsigned char *hash, unsigned int hashLen)
  1318. {
  1319.     return PORT_Memcmp(sig,hash,*copyLen) ? SECSuccess : SECFailure ;
  1320. }
  1321. /*
  1322.  * common HMAC initalization routine
  1323.  */
  1324. static CK_RV
  1325. pk11_doHMACInit(PK11SessionContext *context,SECOidTag oid,
  1326. PK11Object *key, CK_ULONG mac_size)
  1327. {
  1328.     PK11Attribute *keyval;
  1329.     HMACContext *HMACcontext;
  1330.     CK_ULONG *intpointer;
  1331.     keyval = pk11_FindAttribute(key,CKA_VALUE);
  1332.     if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
  1333.     HMACcontext = HMAC_Create(oid, (const unsigned char*)keyval->attrib.pValue,
  1334.  keyval->attrib.ulValueLen);
  1335.     context->hashInfo = HMACcontext;
  1336.     context->multi = PR_TRUE;
  1337.     pk11_FreeAttribute(keyval);
  1338.     if (context->hashInfo == NULL) {
  1339. return CKR_HOST_MEMORY;
  1340.     }
  1341.     context->hashUpdate = (PK11Hash) HMAC_Update;
  1342.     context->end = (PK11End) HMAC_Finish;
  1343.     context->hashdestroy = (PK11Destroy) pk11_HMAC_Destroy;
  1344.     intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG));
  1345.     if (intpointer == NULL) {
  1346. return CKR_HOST_MEMORY;
  1347.     }
  1348.     *intpointer = mac_size;
  1349.     context->cipherInfo = (void *) intpointer;
  1350.     context->destroy = (PK11Destroy) pk11_Space;
  1351.     context->update = (PK11Cipher) pk11_HMACCopy;
  1352.     context->verify = (PK11Verify) pk11_HMACCmp;
  1353.     HMAC_Begin(HMACcontext);
  1354.     return CKR_OK;
  1355. }
  1356. /*
  1357.  *  SSL Macing support. SSL Macs are inited, then update with the base
  1358.  * hashing algorithm, then finalized in sign and verify
  1359.  */
  1360. /*
  1361.  * FROM SSL:
  1362.  * 60 bytes is 3 times the maximum length MAC size that is supported.
  1363.  * We probably should have one copy of this table. We still need this table
  1364.  * in ssl to 'sign' the handshake hashes.
  1365.  */
  1366. static unsigned char ssl_pad_1 [60] = {
  1367.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1368.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1369.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1370.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1371.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1372.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1373.     0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1374.     0x36, 0x36, 0x36, 0x36
  1375. };
  1376. static unsigned char ssl_pad_2 [60] = {
  1377.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1378.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1379.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1380.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1381.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1382.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1383.     0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1384.     0x5c, 0x5c, 0x5c, 0x5c
  1385. };
  1386. static SECStatus
  1387. pk11_SSLMACSign(PK11SSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,
  1388. unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
  1389. {
  1390.     unsigned char tmpBuf[PK11_MAX_MAC_LENGTH];
  1391.     unsigned int out;
  1392.     info->begin(info->hashContext);
  1393.     info->update(info->hashContext,info->key,info->keySize);
  1394.     info->update(info->hashContext,ssl_pad_2,info->padSize);
  1395.     info->update(info->hashContext,hash,hashLen);
  1396.     info->end(info->hashContext,tmpBuf,&out,PK11_MAX_MAC_LENGTH);
  1397.     PORT_Memcpy(sig,tmpBuf,info->macSize);
  1398.     *sigLen = info->macSize;
  1399.     return SECSuccess;
  1400. }
  1401. static SECStatus
  1402. pk11_SSLMACVerify(PK11SSLMACInfo *info,unsigned char *sig,unsigned int sigLen,
  1403. unsigned char *hash, unsigned int hashLen)
  1404. {
  1405.     unsigned char tmpBuf[PK11_MAX_MAC_LENGTH];
  1406.     unsigned int out;
  1407.     info->begin(info->hashContext);
  1408.     info->update(info->hashContext,info->key,info->keySize);
  1409.     info->update(info->hashContext,ssl_pad_2,info->padSize);
  1410.     info->update(info->hashContext,hash,hashLen);
  1411.     info->end(info->hashContext,tmpBuf,&out,PK11_MAX_MAC_LENGTH);
  1412.     return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ? 
  1413. SECSuccess : SECFailure;
  1414. }
  1415. /*
  1416.  * common HMAC initalization routine
  1417.  */
  1418. static CK_RV
  1419. pk11_doSSLMACInit(PK11SessionContext *context,SECOidTag oid,
  1420. PK11Object *key, CK_ULONG mac_size)
  1421. {
  1422.     PK11Attribute *keyval;
  1423.     PK11Begin begin;
  1424.     int padSize;
  1425.     PK11SSLMACInfo *sslmacinfo;
  1426.     CK_RV crv = CKR_MECHANISM_INVALID;
  1427.     if (oid == SEC_OID_SHA1) {
  1428. crv = pk11_doSubSHA1(context);
  1429. begin = (PK11Begin) SHA1_Begin;
  1430. if (crv != CKR_OK) return crv;
  1431. padSize = 40;
  1432.     } else {
  1433. crv = pk11_doSubMD5(context);
  1434. if (crv != CKR_OK) return crv;
  1435. begin = (PK11Begin) MD5_Begin;
  1436. padSize = 48;
  1437.     }
  1438.     context->multi = PR_TRUE;
  1439.     keyval = pk11_FindAttribute(key,CKA_VALUE);
  1440.     if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
  1441.     context->hashUpdate(context->hashInfo,keyval->attrib.pValue,
  1442.  keyval->attrib.ulValueLen);
  1443.     context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);
  1444.     sslmacinfo = (PK11SSLMACInfo *) PORT_Alloc(sizeof(PK11SSLMACInfo));
  1445.     if (sslmacinfo == NULL) {
  1446.         pk11_FreeAttribute(keyval);
  1447. return CKR_HOST_MEMORY;
  1448.     }
  1449.     sslmacinfo->macSize = mac_size;
  1450.     sslmacinfo->hashContext = context->hashInfo;
  1451.     PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,
  1452. keyval->attrib.ulValueLen);
  1453.     sslmacinfo->keySize = keyval->attrib.ulValueLen;
  1454.     sslmacinfo->begin = begin;
  1455.     sslmacinfo->end = context->end;
  1456.     sslmacinfo->update = context->hashUpdate;
  1457.     sslmacinfo->padSize = padSize;
  1458.     pk11_FreeAttribute(keyval);
  1459.     context->cipherInfo = (void *) sslmacinfo;
  1460.     context->destroy = (PK11Destroy) pk11_Space;
  1461.     context->update = (PK11Cipher) pk11_SSLMACSign;
  1462.     context->verify = (PK11Verify) pk11_SSLMACVerify;
  1463.     return CKR_OK;
  1464. }
  1465. typedef struct {
  1466.     PRUint32 cxSize; /* size of allocated block, in bytes.        */
  1467.     PRUint32 cxKeyLen; /* number of bytes of cxBuf containing key.  */
  1468.     PRUint32 cxDataLen; /* number of bytes of cxBuf containing data. */
  1469.     SECStatus cxRv; /* records failure of void functions.        */
  1470.     unsigned char cxBuf[512]; /* actual size may be larger than 512.       */
  1471. } TLSPRFContext;
  1472. static void
  1473. pk11_TLSPRFHashUpdate(TLSPRFContext *cx, const unsigned char *data, 
  1474.                         unsigned int data_len)
  1475. {
  1476.     PRUint32 bytesUsed = PK11_OFFSETOF(TLSPRFContext, cxBuf) + 
  1477.                          cx->cxKeyLen + cx->cxDataLen;
  1478.     if (cx->cxRv != SECSuccess) /* function has previously failed. */
  1479.      return;
  1480.     if (bytesUsed + data_len > cx->cxSize) {
  1481. /* We don't use realloc here because 
  1482. ** (a) realloc doesn't zero out the old block, and 
  1483. ** (b) if realloc fails, we lose the old block.
  1484. */
  1485. PRUint32 blockSize = bytesUsed + data_len + 512;
  1486.      TLSPRFContext *new_cx = (TLSPRFContext *)PORT_Alloc(blockSize);
  1487. if (!new_cx) {
  1488.    cx->cxRv = SECFailure;
  1489.    return;
  1490. }
  1491. PORT_Memcpy(new_cx, cx, cx->cxSize);
  1492. new_cx->cxSize = blockSize;
  1493. PORT_ZFree(cx, cx->cxSize);
  1494. cx = new_cx;
  1495.     }
  1496.     PORT_Memcpy(cx->cxBuf + cx->cxKeyLen + cx->cxDataLen, data, data_len);
  1497.     cx->cxDataLen += data_len;
  1498. }
  1499. static void 
  1500. pk11_TLSPRFEnd(TLSPRFContext *ctx, unsigned char *hashout,
  1501.  unsigned int *pDigestLen, unsigned int maxDigestLen)
  1502. {
  1503.     *pDigestLen = 0; /* tells Verify that no data has been input yet. */
  1504. }
  1505. /* Compute the PRF values from the data previously input. */
  1506. static SECStatus
  1507. pk11_TLSPRFUpdate(TLSPRFContext *cx, 
  1508.                   unsigned char *sig, /* output goes here. */
  1509.   unsigned int * sigLen,  /* how much output.  */
  1510.   unsigned int   maxLen,  /* output buffer size */
  1511.   unsigned char *hash,  /* unused. */
  1512.   unsigned int   hashLen) /* unused. */
  1513. {
  1514.     SECStatus rv;
  1515.     SECItem sigItem;
  1516.     SECItem seedItem;
  1517.     SECItem secretItem;
  1518.     if (cx->cxRv != SECSuccess)
  1519.      return cx->cxRv;
  1520.     secretItem.data = cx->cxBuf;
  1521.     secretItem.len  = cx->cxKeyLen;
  1522.     seedItem.data = cx->cxBuf + cx->cxKeyLen;
  1523.     seedItem.len  = cx->cxDataLen;
  1524.     sigItem.data = sig;
  1525.     sigItem.len  = maxLen;
  1526.     rv = pk11_PRF(&secretItem, NULL, &seedItem, &sigItem);
  1527.     if (rv == SECSuccess && sigLen != NULL)
  1528.      *sigLen = sigItem.len;
  1529.     return rv;
  1530. }
  1531. static SECStatus
  1532. pk11_TLSPRFVerify(TLSPRFContext *cx, 
  1533.                   unsigned char *sig,  /* input, for comparison. */
  1534.   unsigned int   sigLen, /* length of sig.         */
  1535.   unsigned char *hash,  /* data to be verified.   */
  1536.   unsigned int   hashLen) /* size of hash data.     */
  1537. {
  1538.     unsigned char * tmp    = (unsigned char *)PORT_Alloc(sigLen);
  1539.     unsigned int    tmpLen = sigLen;
  1540.     SECStatus       rv;
  1541.     if (!tmp)
  1542.      return SECFailure;
  1543.     if (hashLen) {
  1544.      /* hashLen is non-zero when the user does a one-step verify.
  1545. ** In this case, none of the data has been input yet.
  1546. */
  1547.      pk11_TLSPRFHashUpdate(cx, hash, hashLen);
  1548.     }
  1549.     rv = pk11_TLSPRFUpdate(cx, tmp, &tmpLen, sigLen, NULL, 0);
  1550.     if (rv == SECSuccess) {
  1551.      rv = (SECStatus)(1 - !PORT_Memcmp(tmp, sig, sigLen));
  1552.     }
  1553.     PORT_ZFree(tmp, sigLen);
  1554.     return rv;
  1555. }
  1556. static void
  1557. pk11_TLSPRFHashDestroy(TLSPRFContext *cx, PRBool freeit)
  1558. {
  1559.     if (freeit)
  1560. PORT_ZFree(cx, cx->cxSize);
  1561. }
  1562. static CK_RV
  1563. pk11_TLSPRFInit(PK11SessionContext *context, 
  1564.   PK11Object *        key, 
  1565.   CK_KEY_TYPE         key_type)
  1566. {
  1567.     PK11Attribute * keyVal;
  1568.     TLSPRFContext * prf_cx;
  1569.     CK_RV           crv = CKR_HOST_MEMORY;
  1570.     PRUint32        keySize;
  1571.     PRUint32        blockSize;
  1572.     if (key_type != CKK_GENERIC_SECRET)
  1573.      return CKR_KEY_TYPE_INCONSISTENT; /* CKR_KEY_FUNCTION_NOT_PERMITTED */
  1574.     context->multi = PR_TRUE;
  1575.     keyVal = pk11_FindAttribute(key, CKA_VALUE);
  1576.     keySize = (!keyVal) ? 0 : keyVal->attrib.ulValueLen;
  1577.     blockSize = keySize + sizeof(TLSPRFContext);
  1578.     prf_cx = (TLSPRFContext *)PORT_Alloc(blockSize);
  1579.     if (!prf_cx) 
  1580.      goto done;
  1581.     prf_cx->cxSize    = blockSize;
  1582.     prf_cx->cxKeyLen  = keySize;
  1583.     prf_cx->cxDataLen = 0;
  1584.     prf_cx->cxRv        = SECSuccess;
  1585.     if (keySize)
  1586. PORT_Memcpy(prf_cx->cxBuf, keyVal->attrib.pValue, keySize);
  1587.     context->hashInfo    = (void *) prf_cx;
  1588.     context->cipherInfo  = (void *) prf_cx;
  1589.     context->hashUpdate  = (PK11Hash)    pk11_TLSPRFHashUpdate;
  1590.     context->end         = (PK11End)     pk11_TLSPRFEnd;
  1591.     context->update      = (PK11Cipher)  pk11_TLSPRFUpdate;
  1592.     context->verify      = (PK11Verify)  pk11_TLSPRFVerify;
  1593.     context->destroy     = (PK11Destroy) pk11_Null;
  1594.     context->hashdestroy = (PK11Destroy) pk11_TLSPRFHashDestroy;
  1595.     crv = CKR_OK;
  1596. done:
  1597.     if (keyVal) 
  1598. pk11_FreeAttribute(keyVal);
  1599.     return crv;
  1600. }
  1601. /*
  1602.  ************** Crypto Functions:     Sign  ************************
  1603.  */
  1604. /*
  1605.  * Check if We're using CBCMacing and initialize the session context if we are.
  1606.  */
  1607. static CK_RV
  1608. pk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
  1609.   CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
  1610.  PK11ContextType contextType)
  1611. {
  1612.     CK_MECHANISM cbc_mechanism;
  1613.     CK_ULONG mac_bytes = PK11_INVALID_MAC_SIZE;
  1614.     CK_RC2_CBC_PARAMS rc2_params;
  1615. #if NSS_SOFTOKEN_DOES_RC5
  1616.     CK_RC5_CBC_PARAMS rc5_params;
  1617.     CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
  1618. #endif
  1619.     unsigned char ivBlock[PK11_MAX_BLOCK_SIZE];
  1620.     PK11SessionContext *context;
  1621.     CK_RV crv;
  1622.     int blockSize;
  1623.     switch (pMechanism->mechanism) {
  1624.     case CKM_RC2_MAC_GENERAL:
  1625. mac_bytes = 
  1626.     ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
  1627. /* fall through */
  1628.     case CKM_RC2_MAC:
  1629. /* this works because ulEffectiveBits is in the same place in both the
  1630.  * CK_RC2_MAC_GENERAL_PARAMS and CK_RC2_CBC_PARAMS */
  1631. rc2_params.ulEffectiveBits = ((CK_RC2_MAC_GENERAL_PARAMS *)
  1632. pMechanism->pParameter)->ulEffectiveBits;
  1633. PORT_Memset(rc2_params.iv,0,sizeof(rc2_params.iv));
  1634. cbc_mechanism.mechanism = CKM_RC2_CBC;
  1635. cbc_mechanism.pParameter = &rc2_params;
  1636. cbc_mechanism.ulParameterLen = sizeof(rc2_params);
  1637. blockSize = 8;
  1638. break;
  1639. #if NSS_SOFTOKEN_DOES_RC5
  1640.     case CKM_RC5_MAC_GENERAL:
  1641. mac_bytes = 
  1642.     ((CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
  1643. /* fall through */
  1644.     case CKM_RC5_MAC:
  1645. /* this works because ulEffectiveBits is in the same place in both the
  1646.  * CK_RC5_MAC_GENERAL_PARAMS and CK_RC5_CBC_PARAMS */
  1647. rc5_mac = (CK_RC5_MAC_GENERAL_PARAMS *)pMechanism->pParameter;
  1648. rc5_params.ulWordsize = rc5_mac->ulWordsize;
  1649. rc5_params.ulRounds = rc5_mac->ulRounds;
  1650. rc5_params.pIv = ivBlock;
  1651. blockSize = rc5_mac->ulWordsize*2;
  1652. rc5_params.ulIvLen = blockSize;
  1653. PORT_Memset(ivBlock,0,blockSize);
  1654. cbc_mechanism.mechanism = CKM_RC5_CBC;
  1655. cbc_mechanism.pParameter = &rc5_params;
  1656. cbc_mechanism.ulParameterLen = sizeof(rc5_params);
  1657. break;
  1658. #endif
  1659.     /* add cast and idea later */
  1660.     case CKM_DES_MAC_GENERAL:
  1661. mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
  1662. /* fall through */
  1663.     case CKM_DES_MAC:
  1664. blockSize = 8;
  1665. PORT_Memset(ivBlock,0,blockSize);
  1666. cbc_mechanism.mechanism = CKM_DES_CBC;
  1667. cbc_mechanism.pParameter = &ivBlock;
  1668. cbc_mechanism.ulParameterLen = blockSize;
  1669. break;
  1670.     case CKM_DES3_MAC_GENERAL:
  1671. mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
  1672. /* fall through */
  1673.     case CKM_DES3_MAC:
  1674. blockSize = 8;
  1675. PORT_Memset(ivBlock,0,blockSize);
  1676. cbc_mechanism.mechanism = CKM_DES3_CBC;
  1677. cbc_mechanism.pParameter = &ivBlock;
  1678. cbc_mechanism.ulParameterLen = blockSize;
  1679. break;
  1680.     case CKM_CDMF_MAC_GENERAL:
  1681. mac_bytes = *(CK_ULONG *)pMechanism->pParameter;
  1682. /* fall through */
  1683.     case CKM_CDMF_MAC:
  1684. blockSize = 8;
  1685. PORT_Memset(ivBlock,0,blockSize);
  1686. cbc_mechanism.mechanism = CKM_CDMF_CBC;
  1687. cbc_mechanism.pParameter = &ivBlock;
  1688. cbc_mechanism.ulParameterLen = blockSize;
  1689. break;
  1690.     default:
  1691. return CKR_FUNCTION_NOT_SUPPORTED;
  1692.     }
  1693.     crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage,
  1694. contextType);
  1695.     if (crv != CKR_OK) return crv;
  1696.     crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL);
  1697.     /* this shouldn't happen! */
  1698.     PORT_Assert(crv == CKR_OK);
  1699.     if (crv != CKR_OK) return crv;
  1700.     context->blockSize = blockSize;
  1701.     if (mac_bytes == PK11_INVALID_MAC_SIZE) mac_bytes = blockSize/2;
  1702.     context->macSize = mac_bytes;
  1703.     return CKR_OK;
  1704. }
  1705. /*
  1706.  * encode RSA PKCS #1 Signature data before signing... 
  1707.  */
  1708. static SECStatus
  1709. pk11_HashSign(PK11HashSignInfo *info,unsigned char *sig,unsigned int *sigLen,
  1710. unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
  1711. {
  1712.     
  1713.     SECStatus rv = SECFailure;
  1714.     SECItem digder;
  1715.     PLArenaPool *arena = NULL;
  1716.     SGNDigestInfo *di = NULL;
  1717.     digder.data = NULL;
  1718.     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1719.     if ( !arena ) { goto loser; }
  1720.     
  1721.     /* Construct digest info */
  1722.     di = SGN_CreateDigestInfo(info->hashOid, hash, hashLen);
  1723.     if (!di) { goto loser; }
  1724.     /* Der encode the digest as a DigestInfo */
  1725.     rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate, di);
  1726.     if (rv != SECSuccess) {
  1727. goto loser;
  1728.     }
  1729.     /*
  1730.     ** Encrypt signature after constructing appropriate PKCS#1 signature
  1731.     ** block
  1732.     */
  1733.     rv = RSA_Sign(info->key,sig,sigLen,maxLen,digder.data,digder.len);
  1734.   loser:
  1735.     SGN_DestroyDigestInfo(di);
  1736.     if (arena != NULL) {
  1737. PORT_FreeArena(arena, PR_FALSE);
  1738.     }
  1739.     return rv;
  1740. }
  1741. static SECStatus
  1742. nsc_DSA_Verify_Stub(void *ctx, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen,
  1743.     CK_BYTE_PTR pData, CK_ULONG ulDataLen)
  1744. {
  1745.     SECItem signature, digest;
  1746.     signature.data = pSignature;
  1747.     signature.len = ulSignatureLen;
  1748.     digest.data = pData;
  1749.     digest.len = ulDataLen;
  1750.     return DSA_VerifyDigest((DSAPublicKey *)ctx, &signature, &digest);
  1751. }
  1752. static SECStatus
  1753. nsc_DSA_Sign_Stub(void *ctx, CK_BYTE_PTR pSignature,
  1754.     CK_ULONG_PTR ulSignatureLen, CK_ULONG maxulSignatureLen,
  1755.     CK_BYTE_PTR pData, CK_ULONG ulDataLen)
  1756. {
  1757.     SECItem signature = { 0 }, digest;
  1758.     SECStatus rv;
  1759.     (void)SECITEM_AllocItem(NULL, &signature, maxulSignatureLen);
  1760.     digest.data = pData;
  1761.     digest.len = ulDataLen;
  1762.     rv = DSA_SignDigest((DSAPrivateKey *)ctx, &signature, &digest);
  1763.     *ulSignatureLen = signature.len;
  1764.     PORT_Memcpy(pSignature, signature.data, signature.len);
  1765.     SECITEM_FreeItem(&signature, PR_FALSE);
  1766.     return rv;
  1767. }
  1768. /* NSC_SignInit setups up the signing operations. There are three basic
  1769.  * types of signing:
  1770.  * (1) the tradition single part, where "Raw RSA" or "Raw DSA" is applied
  1771.  *  to data in a single Sign operation (which often looks a lot like an
  1772.  *  encrypt, with data coming in and data going out).
  1773.  * (2) Hash based signing, where we continually hash the data, then apply
  1774.  *  some sort of signature to the end.
  1775.  * (3) Block Encryption CBC MAC's, where the Data is encrypted with a key,
  1776.  *  and only the final block is part of the mac.
  1777.  *
  1778.  *  For case number 3, we initialize a context much like the Encryption Context
  1779.  *  (in fact we share code). We detect case 3 in C_SignUpdate, C_Sign, and 
  1780.  *  C_Final by the following method... if it's not multi-part, and it's doesn't
  1781.  *  have a hash context, it must be a block Encryption CBC MAC.
  1782.  *
  1783.  *  For case number 2, we initialize a hash structure, as well as make it 
  1784.  *  multi-part. Updates are simple calls to the hash update function. Final
  1785.  *  calls the hashend, then passes the result to the 'update' function (which
  1786.  *  operates as a final signature function). In some hash based MAC'ing (as
  1787.  *  opposed to hash base signatures), the update function is can be simply a 
  1788.  *  copy (as is the case with HMAC).
  1789.  */
  1790. CK_RV NSC_SignInit(CK_SESSION_HANDLE hSession,
  1791.  CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
  1792. {
  1793.     PK11Session *session;
  1794.     PK11Object *key;
  1795.     PK11SessionContext *context;
  1796.     CK_KEY_TYPE key_type;
  1797.     CK_RV crv = CKR_OK;
  1798.     SECKEYLowPrivateKey *privKey;
  1799.     PK11HashSignInfo *info = NULL;
  1800.     /* Block Cipher MACing Algorithms use a different Context init method..*/
  1801.     crv = pk11_InitCBCMac(hSession, pMechanism, hKey, CKA_SIGN, PK11_SIGN);
  1802.     if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
  1803.     /* we're not using a block cipher mac */
  1804.     session = pk11_SessionFromHandle(hSession);
  1805.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  1806.     crv = pk11_InitGeneric(session,&context,PK11_SIGN,&key,hKey,&key_type,
  1807. CKO_PRIVATE_KEY,CKA_SIGN);
  1808.     if (crv != CKR_OK) {
  1809. pk11_FreeSession(session);
  1810. return crv;
  1811.     }
  1812.     context->multi = PR_FALSE;
  1813.     switch(pMechanism->mechanism) {
  1814.     case CKM_MD5_RSA_PKCS:
  1815.         context->multi = PR_TRUE;
  1816. crv = pk11_doSubMD2(context);
  1817. if (crv != CKR_OK) break;
  1818. context->update = (PK11Cipher) pk11_HashSign;
  1819. info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));
  1820. if (info == NULL) {
  1821.    crv = CKR_HOST_MEMORY;
  1822.    break;
  1823. }
  1824. info->hashOid = SEC_OID_MD5;
  1825. goto finish_rsa;
  1826.     case CKM_MD2_RSA_PKCS:
  1827.         context->multi = PR_TRUE;
  1828. crv = pk11_doSubMD2(context);
  1829. if (crv != CKR_OK) break;
  1830. context->update = (PK11Cipher) pk11_HashSign;
  1831. info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));
  1832. if (info == NULL) {
  1833.    crv = CKR_HOST_MEMORY;
  1834.    break;
  1835. }
  1836. info->hashOid = SEC_OID_MD2;
  1837. goto finish_rsa;
  1838.     case CKM_SHA1_RSA_PKCS:
  1839.         context->multi = PR_TRUE;
  1840. crv = pk11_doSubSHA1(context);
  1841. if (crv != CKR_OK) break;
  1842. context->update = (PK11Cipher) pk11_HashSign;
  1843. info = (PK11HashSignInfo *)PORT_Alloc(sizeof(PK11HashSignInfo));
  1844. if (info == NULL) {
  1845.    crv = CKR_HOST_MEMORY;
  1846.    break;
  1847. }
  1848. info->hashOid = SEC_OID_SHA1;
  1849. goto finish_rsa;
  1850.     case CKM_RSA_PKCS:
  1851. context->update = (PK11Cipher) RSA_Sign;
  1852. goto finish_rsa;
  1853.     case CKM_RSA_X_509:
  1854. context->update = (PK11Cipher)  RSA_SignRaw;
  1855. finish_rsa:
  1856. if (key_type != CKK_RSA) {
  1857.     if (info) PORT_Free(info);
  1858.     crv = CKR_KEY_TYPE_INCONSISTENT;
  1859.     break;
  1860. }
  1861. context->multi = PR_FALSE;
  1862. privKey = pk11_GetPrivKey(key,CKK_RSA);
  1863. if (privKey == NULL) {
  1864.     if (info) PORT_Free(info);
  1865.     crv = CKR_HOST_MEMORY;
  1866.     break;
  1867. }
  1868. /* OK, info is allocated only if we're doing hash and sign mechanism.
  1869.  * It's necessary to be able to set the correct OID in the final 
  1870.  * signature.
  1871.  * Second, what's special about privKey == key->objectInfo?
  1872.  * Well we don't 'cache' token versions
  1873.  * of private keys because (1) it's sensitive data, and (2) it never
  1874.  * gets destroyed. Instead we grab the key out of the database as
  1875.  * necessary, but now the key is our context, and we need to free
  1876.  * it when we are done. Non-token private keys will get freed when
  1877.  * the user destroys the session object (or the session the session
  1878.  * object lives in) */
  1879. if (info) {
  1880.     info->key = privKey;
  1881.     context->cipherInfo = info;
  1882.     context->destroy = (privKey == key->objectInfo) ?
  1883. (PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo;
  1884. } else {
  1885.     context->cipherInfo = privKey;
  1886.     context->destroy = (privKey == key->objectInfo) ?
  1887. (PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey;
  1888. }
  1889. break;
  1890.     case CKM_DSA_SHA1:
  1891.         context->multi = PR_TRUE;
  1892. crv = pk11_doSubSHA1(context);
  1893. if (crv != CKR_OK) break;
  1894. /* fall through */
  1895.     case CKM_DSA:
  1896. if (key_type != CKK_DSA) {
  1897.     crv = CKR_KEY_TYPE_INCONSISTENT;
  1898.     break;
  1899. }
  1900. privKey = pk11_GetPrivKey(key,CKK_DSA);
  1901. if (privKey == NULL) {
  1902.     crv = CKR_HOST_MEMORY;
  1903.     break;
  1904. }
  1905. context->cipherInfo = &(privKey->u.dsa);
  1906. context->update     = (PK11Cipher) nsc_DSA_Sign_Stub;
  1907. context->destroy    = pk11_Null;
  1908.         if (key->objectInfo != privKey) SECKEY_LowDestroyPrivateKey(privKey);
  1909. break;
  1910.     case CKM_MD2_HMAC_GENERAL:
  1911. crv = pk11_doHMACInit(context,SEC_OID_MD2,key,
  1912. *(CK_ULONG *)pMechanism->pParameter);
  1913. break;
  1914.     case CKM_MD2_HMAC:
  1915. crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);
  1916. break;
  1917.     case CKM_MD5_HMAC_GENERAL:
  1918. crv = pk11_doHMACInit(context,SEC_OID_MD5,key,
  1919. *(CK_ULONG *)pMechanism->pParameter);
  1920. break;
  1921.     case CKM_MD5_HMAC:
  1922. crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);
  1923. break;
  1924.     case CKM_SHA_1_HMAC_GENERAL:
  1925. crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,
  1926. *(CK_ULONG *)pMechanism->pParameter);
  1927. break;
  1928.     case CKM_SHA_1_HMAC:
  1929. crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);
  1930. break;
  1931.     case CKM_SSL3_MD5_MAC:
  1932. crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,
  1933. *(CK_ULONG *)pMechanism->pParameter);
  1934. break;
  1935.     case CKM_SSL3_SHA1_MAC:
  1936. crv = pk11_doSSLMACInit(context,SEC_OID_SHA1,key,
  1937. *(CK_ULONG *)pMechanism->pParameter);
  1938. break;
  1939.     case CKM_TLS_PRF_GENERAL:
  1940. crv = pk11_TLSPRFInit(context, key, key_type);
  1941. break;
  1942.     default:
  1943. crv = CKR_MECHANISM_INVALID;
  1944. break;
  1945.     }
  1946.     pk11_FreeObject(key);
  1947.     if (crv != CKR_OK) {
  1948.         PORT_Free(context);
  1949. pk11_FreeSession(session);
  1950. return crv;
  1951.     }
  1952.     pk11_SetContextByType(session, PK11_SIGN, context);
  1953.     pk11_FreeSession(session);
  1954.     return CKR_OK;
  1955. }
  1956. /* MACUpdate is the common implementation for SignUpdate and VerifyUpdate.
  1957.  * (sign and verify only very in their setup and final operations) */
  1958. static CK_RV 
  1959. pk11_MACUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
  1960.      CK_ULONG ulPartLen,PK11ContextType type)
  1961. {
  1962.     unsigned int outlen;
  1963.     PK11SessionContext *context;
  1964.     CK_RV crv;
  1965.     SECStatus rv;
  1966.     /* make sure we're legal */
  1967.     crv = pk11_GetContext(hSession,&context,type,PR_FALSE,NULL);
  1968.     if (crv != CKR_OK) return crv;
  1969.     if (context->hashInfo) {
  1970. (*context->hashUpdate)(context->hashInfo, pPart, ulPartLen);
  1971. return CKR_OK;
  1972.     }
  1973.     /* must be block cipher macing */
  1974.     /* deal with previous buffered data */
  1975.     if (context->padDataLength != 0) {
  1976. int i;
  1977. /* fill in the padded to a full block size */
  1978. for (i=context->padDataLength; (ulPartLen != 0) && 
  1979. i < (int)context->blockSize; i++) {
  1980.     context->padBuf[i] = *pPart++;
  1981.     ulPartLen--;
  1982.     context->padDataLength++;
  1983. }
  1984. /* not enough data to encrypt yet? then return */
  1985. if (context->padDataLength != context->blockSize)  return CKR_OK;
  1986. /* encrypt the current padded data */
  1987.      rv = (*context->update)(context->cipherInfo,context->macBuf,&outlen,
  1988. PK11_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
  1989.      if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  1990.     }
  1991.     /* save the residual */
  1992.     context->padDataLength = ulPartLen % context->blockSize;
  1993.     if (context->padDataLength) {
  1994.     PORT_Memcpy(context->padBuf,
  1995. &pPart[ulPartLen-context->padDataLength],
  1996. context->padDataLength);
  1997.     ulPartLen -= context->padDataLength;
  1998.     }
  1999.     /* if we've exhausted our new buffer, we're done */
  2000.     if (ulPartLen == 0) { return CKR_OK; }
  2001.     /* run the data through out encrypter */
  2002.     while (ulPartLen) {
  2003.      rv = (*context->update)(context->cipherInfo, context->padBuf, &outlen, 
  2004. PK11_MAX_BLOCK_SIZE, pPart, context->blockSize);
  2005. if (rv != SECSuccess) return CKR_DEVICE_ERROR;
  2006. /* paranoia.. make sure we exit the loop */
  2007. PORT_Assert(ulPartLen >= context->blockSize);
  2008. if (ulPartLen < context->blockSize) break;
  2009. ulPartLen -= context->blockSize;
  2010.     }
  2011.     return CKR_OK;
  2012. }
  2013. /* NSC_SignUpdate continues a multiple-part signature operation,
  2014.  * where the signature is (will be) an appendix to the data, 
  2015.  * and plaintext cannot be recovered from the signature */
  2016. CK_RV NSC_SignUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
  2017.      CK_ULONG ulPartLen)
  2018. {
  2019.     return pk11_MACUpdate(hSession, pPart, ulPartLen, PK11_SIGN);
  2020. }
  2021. /* NSC_SignFinal finishes a multiple-part signature operation, 
  2022.  * returning the signature. */
  2023. CK_RV NSC_SignFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pSignature,
  2024.     CK_ULONG_PTR pulSignatureLen)
  2025. {
  2026.     PK11Session *session;
  2027.     PK11SessionContext *context;
  2028.     unsigned int outlen;
  2029.     unsigned int digestLen;
  2030.     unsigned int maxoutlen = *pulSignatureLen;
  2031.     unsigned char tmpbuf[PK11_MAX_MAC_LENGTH];
  2032.     CK_RV crv;
  2033.     SECStatus rv = SECSuccess;
  2034.     /* make sure we're legal */
  2035.     *pulSignatureLen = 0;
  2036.     crv = pk11_GetContext(hSession,&context,PK11_SIGN,PR_TRUE,&session);
  2037.     if (crv != CKR_OK) return crv;
  2038.     if (context->hashInfo) {
  2039.         (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
  2040. rv = (*context->update)(context->cipherInfo, pSignature,
  2041. &outlen, maxoutlen, tmpbuf, digestLen);
  2042.         *pulSignatureLen = (CK_ULONG) outlen;
  2043.     } else {
  2044. /* deal with the last block if any residual */
  2045. if (context->padDataLength) {
  2046.     /* fill out rest of pad buffer with pad magic*/
  2047.     int i;
  2048.     for (i=context->padDataLength; i < (int)context->blockSize; i++) {
  2049. context->padBuf[i] = 0;
  2050.     }
  2051.     rv = (*context->update)(context->cipherInfo,context->macBuf,
  2052. &outlen,PK11_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
  2053. }
  2054. if (rv == SECSuccess) {
  2055.     PORT_Memcpy(pSignature,context->macBuf,context->macSize);
  2056.     *pulSignatureLen = context->macSize;
  2057. }
  2058.     }
  2059.     pk11_FreeContext(context);
  2060.     pk11_SetContextByType(session, PK11_SIGN, NULL);
  2061.     pk11_FreeSession(session);
  2062.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  2063. }
  2064. /* NSC_Sign signs (encrypts with private key) data in a single part,
  2065.  * where the signature is (will be) an appendix to the data, 
  2066.  * and plaintext cannot be recovered from the signature */
  2067. CK_RV NSC_Sign(CK_SESSION_HANDLE hSession,
  2068.     CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pSignature,
  2069.      CK_ULONG_PTR pulSignatureLen)
  2070. {
  2071.     PK11Session *session;
  2072.     PK11SessionContext *context;
  2073.     unsigned int outlen;
  2074.     unsigned int maxoutlen = *pulSignatureLen;
  2075.     CK_RV crv,crv2;
  2076.     SECStatus rv;
  2077.     /* make sure we're legal */
  2078.     crv = pk11_GetContext(hSession,&context,PK11_SIGN,PR_FALSE,&session);
  2079.     if (crv != CKR_OK) return crv;
  2080.     /* multi part Signing are completely implemented by SignUpdate and
  2081.      * sign Final */
  2082.     if (context->multi) {
  2083.         pk11_FreeSession(session);
  2084. crv = NSC_SignUpdate(hSession,pData,ulDataLen);
  2085. if (crv != CKR_OK) *pulSignatureLen = 0;
  2086. crv2 = NSC_SignFinal(hSession, pSignature, pulSignatureLen);
  2087. return crv == CKR_OK ? crv2 :crv;
  2088.     }
  2089.     rv = (*context->update)(context->cipherInfo, pSignature,
  2090. &outlen, maxoutlen, pData, ulDataLen);
  2091.     *pulSignatureLen = (CK_ULONG) outlen;
  2092.     pk11_FreeContext(context);
  2093.     pk11_SetContextByType(session, PK11_SIGN, NULL);
  2094.     pk11_FreeSession(session);
  2095.     return (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  2096. }
  2097. /*
  2098.  ************** Crypto Functions:     Sign Recover  ************************
  2099.  */
  2100. /* NSC_SignRecoverInit initializes a signature operation,
  2101.  * where the (digest) data can be recovered from the signature. 
  2102.  * E.g. encryption with the user's private key */
  2103. CK_RV NSC_SignRecoverInit(CK_SESSION_HANDLE hSession,
  2104.  CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
  2105. {
  2106.     switch (pMechanism->mechanism) {
  2107.     case CKM_RSA_PKCS:
  2108.     case CKM_RSA_X_509:
  2109. return NSC_SignInit(hSession,pMechanism,hKey);
  2110.     default:
  2111. break;
  2112.     }
  2113.     return CKR_MECHANISM_INVALID;
  2114. }
  2115. /* NSC_SignRecover signs data in a single operation
  2116.  * where the (digest) data can be recovered from the signature. 
  2117.  * E.g. encryption with the user's private key */
  2118. CK_RV NSC_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
  2119.   CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
  2120. {
  2121.     return NSC_Sign(hSession,pData,ulDataLen,pSignature,pulSignatureLen);
  2122. }
  2123. /*
  2124.  ************** Crypto Functions:     verify  ************************
  2125.  */
  2126. /* Handle RSA Signature formating */
  2127. static SECStatus
  2128. pk11_hashCheckSign(PK11HashVerifyInfo *info, unsigned char *sig, 
  2129. unsigned int sigLen, unsigned char *digest, unsigned int digestLen)
  2130. {
  2131.     SECItem it;
  2132.     SGNDigestInfo *di = NULL;
  2133.     SECStatus rv = SECSuccess;
  2134.     
  2135.     it.data = NULL;
  2136.     if (info->key == NULL) goto loser;
  2137.     it.len = SECKEY_LowPublicModulusLen(info->key); 
  2138.     if (!it.len) goto loser;
  2139.     it.data = (unsigned char *) PORT_Alloc(it.len);
  2140.     if (it.data == NULL) goto loser;
  2141.     /* decrypt the block */
  2142.     rv = RSA_CheckSignRecover(info->key, it.data, &it.len, it.len, sig, sigLen);
  2143.     if (rv != SECSuccess) goto loser;
  2144.     di = SGN_DecodeDigestInfo(&it);
  2145.     if (di == NULL) goto loser;
  2146.     if (di->digest.len != digestLen)  goto loser; 
  2147.     /* make sure the tag is OK */
  2148.     if (SECOID_GetAlgorithmTag(&di->digestAlgorithm) != info->hashOid) {
  2149. goto loser;
  2150.     }
  2151.     /* Now check the signature */
  2152.     if (PORT_Memcmp(digest, di->digest.data, di->digest.len) == 0) {
  2153. goto done;
  2154.     }
  2155.   loser:
  2156.     rv = SECFailure;
  2157.   done:
  2158.     if (it.data != NULL) PORT_Free(it.data);
  2159.     if (di != NULL) SGN_DestroyDigestInfo(di);
  2160.     
  2161.     return rv;
  2162. }
  2163. /* NSC_VerifyInit initializes a verification operation, 
  2164.  * where the signature is an appendix to the data, 
  2165.  * and plaintext cannot be recovered from the signature (e.g. DSA) */
  2166. CK_RV NSC_VerifyInit(CK_SESSION_HANDLE hSession,
  2167.    CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey) 
  2168. {
  2169.     PK11Session *session;
  2170.     PK11Object *key;
  2171.     PK11SessionContext *context;
  2172.     CK_KEY_TYPE key_type;
  2173.     CK_RV crv = CKR_OK;
  2174.     SECKEYLowPublicKey *pubKey;
  2175.     PK11HashVerifyInfo *info = NULL;
  2176.     /* Block Cipher MACing Algorithms use a different Context init method..*/
  2177.     crv = pk11_InitCBCMac(hSession, pMechanism, hKey, CKA_VERIFY, PK11_VERIFY);
  2178.     if (crv != CKR_FUNCTION_NOT_SUPPORTED) return crv;
  2179.     session = pk11_SessionFromHandle(hSession);
  2180.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2181.     crv = pk11_InitGeneric(session,&context,PK11_VERIFY,&key,hKey,&key_type,
  2182. CKO_PUBLIC_KEY,CKA_VERIFY);
  2183.     if (crv != CKR_OK) {
  2184. pk11_FreeSession(session);
  2185. return crv;
  2186.     }
  2187.     context->multi = PR_FALSE;
  2188.     switch(pMechanism->mechanism) {
  2189.     case CKM_MD5_RSA_PKCS:
  2190.         context->multi = PR_TRUE;
  2191. crv = pk11_doSubMD5(context);
  2192. if (crv != CKR_OK) break;
  2193. context->verify = (PK11Verify) pk11_hashCheckSign;
  2194. info = (PK11HashVerifyInfo *)PORT_Alloc(sizeof(PK11HashVerifyInfo));
  2195. if (info == NULL) {
  2196.    crv = CKR_HOST_MEMORY;
  2197.    break;
  2198. }
  2199. info->hashOid = SEC_OID_MD5;
  2200. goto finish_rsa;
  2201.     case CKM_MD2_RSA_PKCS:
  2202.         context->multi = PR_TRUE;
  2203. crv = pk11_doSubMD2(context);
  2204. if (crv != CKR_OK) break;
  2205. context->verify = (PK11Verify) pk11_hashCheckSign;
  2206. info = (PK11HashVerifyInfo *)PORT_Alloc(sizeof(PK11HashVerifyInfo));
  2207. if (info == NULL) {
  2208.    crv = CKR_HOST_MEMORY;
  2209.    break;
  2210. }
  2211. info->hashOid = SEC_OID_MD2;
  2212. goto finish_rsa;
  2213.     case CKM_SHA1_RSA_PKCS:
  2214.         context->multi = PR_TRUE;
  2215. crv = pk11_doSubSHA1(context);
  2216. if (crv != CKR_OK) break;
  2217. context->verify = (PK11Verify) pk11_hashCheckSign;
  2218. info = (PK11HashVerifyInfo *)PORT_Alloc(sizeof(PK11HashVerifyInfo));
  2219. if (info == NULL) {
  2220.    crv = CKR_HOST_MEMORY;
  2221.    break;
  2222. }
  2223. info->hashOid = SEC_OID_SHA1;
  2224. goto finish_rsa;
  2225.     case CKM_RSA_PKCS:
  2226. context->verify = (PK11Verify) RSA_CheckSign;
  2227. goto finish_rsa;
  2228.     case CKM_RSA_X_509:
  2229. context->verify = (PK11Verify) RSA_CheckSignRaw;
  2230. finish_rsa:
  2231. if (key_type != CKK_RSA) {
  2232.     crv = CKR_KEY_TYPE_INCONSISTENT;
  2233.     break;
  2234. }
  2235. pubKey = pk11_GetPubKey(key,CKK_RSA);
  2236. if (pubKey == NULL) {
  2237.     crv = CKR_HOST_MEMORY;
  2238.     break;
  2239. }
  2240. if (info) {
  2241.     info->key = pubKey;
  2242.     context->cipherInfo = info;
  2243.     context->destroy = pk11_Space;
  2244. } else {
  2245.     context->cipherInfo = pubKey;
  2246.     context->destroy = pk11_Null;
  2247. }
  2248. break;
  2249.     case CKM_DSA_SHA1:
  2250.         context->multi = PR_TRUE;
  2251. crv = pk11_doSubSHA1(context);
  2252. if (crv != CKR_OK) break;
  2253. /* fall through */
  2254.     case CKM_DSA:
  2255. if (key_type != CKK_DSA) {
  2256.     crv = CKR_KEY_TYPE_INCONSISTENT;
  2257.     break;
  2258. }
  2259. context->multi = PR_FALSE;
  2260. pubKey = pk11_GetPubKey(key,CKK_DSA);
  2261. if (pubKey == NULL) {
  2262.     crv = CKR_HOST_MEMORY;
  2263.     break;
  2264. }
  2265. context->cipherInfo = &(pubKey->u.dsa);
  2266. context->verify     = (PK11Verify) nsc_DSA_Verify_Stub;
  2267. context->destroy    = pk11_Null;
  2268. break;
  2269.     case CKM_MD2_HMAC_GENERAL:
  2270. crv = pk11_doHMACInit(context,SEC_OID_MD2,key,
  2271. *(CK_ULONG *)pMechanism->pParameter);
  2272. break;
  2273.     case CKM_MD2_HMAC:
  2274. crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH);
  2275. break;
  2276.     case CKM_MD5_HMAC_GENERAL:
  2277. crv = pk11_doHMACInit(context,SEC_OID_MD5,key,
  2278. *(CK_ULONG *)pMechanism->pParameter);
  2279. break;
  2280.     case CKM_MD5_HMAC:
  2281. crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH);
  2282. break;
  2283.     case CKM_SHA_1_HMAC_GENERAL:
  2284. crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,
  2285. *(CK_ULONG *)pMechanism->pParameter);
  2286. break;
  2287.     case CKM_SHA_1_HMAC:
  2288. crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH);
  2289. break;
  2290.     case CKM_SSL3_MD5_MAC:
  2291. crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key,
  2292. *(CK_ULONG *)pMechanism->pParameter);
  2293. break;
  2294.     case CKM_SSL3_SHA1_MAC:
  2295. crv = pk11_doSSLMACInit(context,SEC_OID_SHA1,key,
  2296. *(CK_ULONG *)pMechanism->pParameter);
  2297. break;
  2298.     case CKM_TLS_PRF_GENERAL:
  2299. crv = pk11_TLSPRFInit(context, key, key_type);
  2300.     default:
  2301. crv = CKR_MECHANISM_INVALID;
  2302. break;
  2303.     }
  2304.     pk11_FreeObject(key);
  2305.     if (crv != CKR_OK) {
  2306.         PORT_Free(context);
  2307. pk11_FreeSession(session);
  2308. return crv;
  2309.     }
  2310.     pk11_SetContextByType(session, PK11_VERIFY, context);
  2311.     pk11_FreeSession(session);
  2312.     return CKR_OK;
  2313. }
  2314. /* NSC_Verify verifies a signature in a single-part operation, 
  2315.  * where the signature is an appendix to the data, 
  2316.  * and plaintext cannot be recovered from the signature */
  2317. CK_RV NSC_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
  2318.     CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
  2319. {
  2320.     PK11Session *session;
  2321.     PK11SessionContext *context;
  2322.     CK_RV crv;
  2323.     SECStatus rv;
  2324.     /* make sure we're legal */
  2325.     crv = pk11_GetContext(hSession,&context,PK11_VERIFY,PR_FALSE,&session);
  2326.     if (crv != CKR_OK) return crv;
  2327.     rv = (*context->verify)(context->cipherInfo,pSignature, ulSignatureLen,
  2328.  pData, ulDataLen);
  2329.     pk11_FreeContext(context);
  2330.     pk11_SetContextByType(session, PK11_VERIFY, NULL);
  2331.     pk11_FreeSession(session);
  2332.     return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID;
  2333. }
  2334. /* NSC_VerifyUpdate continues a multiple-part verification operation, 
  2335.  * where the signature is an appendix to the data, 
  2336.  * and plaintext cannot be recovered from the signature */
  2337. CK_RV NSC_VerifyUpdate( CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
  2338. CK_ULONG ulPartLen)
  2339. {
  2340.     return pk11_MACUpdate(hSession, pPart, ulPartLen, PK11_VERIFY);
  2341. }
  2342. /* NSC_VerifyFinal finishes a multiple-part verification operation, 
  2343.  * checking the signature. */
  2344. CK_RV NSC_VerifyFinal(CK_SESSION_HANDLE hSession,
  2345. CK_BYTE_PTR pSignature,CK_ULONG ulSignatureLen)
  2346. {
  2347.     PK11Session *session;
  2348.     PK11SessionContext *context;
  2349.     unsigned int outlen;
  2350.     unsigned int digestLen;
  2351.     unsigned char tmpbuf[PK11_MAX_MAC_LENGTH];
  2352.     CK_RV crv;
  2353.     SECStatus rv = SECSuccess;
  2354.     /* make sure we're legal */
  2355.     crv = pk11_GetContext(hSession,&context,PK11_VERIFY,PR_TRUE,&session);
  2356.     if (crv != CKR_OK) return crv;
  2357.     if (context->hashInfo) {
  2358.         (*context->end)(context->hashInfo, tmpbuf, &digestLen, sizeof(tmpbuf));
  2359. rv = (*context->verify)(context->cipherInfo, pSignature, 
  2360. ulSignatureLen, tmpbuf, digestLen);
  2361.     } else {
  2362. if (context->padDataLength) {
  2363.     /* fill out rest of pad buffer with pad magic*/
  2364.     int i;
  2365.     for (i=context->padDataLength; i < (int)context->blockSize; i++) {
  2366. context->padBuf[i] = 0;
  2367.     }
  2368.     rv = (*context->update)(context->cipherInfo,context->macBuf, 
  2369. &outlen,PK11_MAX_BLOCK_SIZE,context->padBuf,context->blockSize);
  2370. }
  2371. if (rv == SECSuccess) {
  2372.     rv =(PORT_Memcmp(pSignature,context->macBuf,context->macSize) == 0)
  2373.  ? SECSuccess : SECFailure;
  2374. }
  2375.     }
  2376.     pk11_FreeContext(context);
  2377.     pk11_SetContextByType(session, PK11_VERIFY, NULL);
  2378.     pk11_FreeSession(session);
  2379.     return (rv == SECSuccess) ? CKR_OK : CKR_SIGNATURE_INVALID;
  2380. }
  2381. /*
  2382.  ************** Crypto Functions:     Verify  Recover ************************
  2383.  */
  2384. /* NSC_VerifyRecoverInit initializes a signature verification operation, 
  2385.  * where the data is recovered from the signature. 
  2386.  * E.g. Decryption with the user's public key */
  2387. CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession,
  2388. CK_MECHANISM_PTR pMechanism,CK_OBJECT_HANDLE hKey)
  2389. {
  2390.     PK11Session *session;
  2391.     PK11Object *key;
  2392.     PK11SessionContext *context;
  2393.     CK_KEY_TYPE key_type;
  2394.     CK_RV crv = CKR_OK;
  2395.     SECKEYLowPublicKey *pubKey;
  2396.     session = pk11_SessionFromHandle(hSession);
  2397.     if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  2398.     crv = pk11_InitGeneric(session,&context,PK11_VERIFY_RECOVER,
  2399. &key,hKey,&key_type,CKO_PUBLIC_KEY,CKA_VERIFY_RECOVER);
  2400.     if (crv != CKR_OK) {
  2401. pk11_FreeSession(session);
  2402. return crv;
  2403.     }