/security/nss/lib/softoken/pkcs11c.c

http://github.com/zpao/v8monkey · C · 6575 lines · 5055 code · 667 blank · 853 comment · 1335 complexity · dc7e5c203f1d91eb1f4d216671ed2d02 MD5 · raw file

Large files are truncated click here to view the full file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is the Netscape security libraries.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Netscape Communications Corporation.
  18. * Portions created by the Initial Developer are Copyright (C) 1994-2000
  19. * the Initial Developer. All Rights Reserved.
  20. *
  21. * Contributor(s):
  22. * Dr Stephen Henson <stephen.henson@gemplus.com>
  23. * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK ***** */
  38. /*
  39. * This file implements PKCS 11 on top of our existing security modules
  40. *
  41. * For more information about PKCS 11 See PKCS 11 Token Inteface Standard.
  42. * This implementation has two slots:
  43. * slot 1 is our generic crypto support. It does not require login.
  44. * It supports Public Key ops, and all they bulk ciphers and hashes.
  45. * It can also support Private Key ops for imported Private keys. It does
  46. * not have any token storage.
  47. * slot 2 is our private key support. It requires a login before use. It
  48. * can store Private Keys and Certs as token objects. Currently only private
  49. * keys and their associated Certificates are saved on the token.
  50. *
  51. * In this implementation, session objects are only visible to the session
  52. * that created or generated them.
  53. */
  54. #include "seccomon.h"
  55. #include "secitem.h"
  56. #include "secport.h"
  57. #include "blapi.h"
  58. #include "pkcs11.h"
  59. #include "pkcs11i.h"
  60. #include "lowkeyi.h"
  61. #include "sechash.h"
  62. #include "secder.h"
  63. #include "secdig.h"
  64. #include "lowpbe.h" /* We do PBE below */
  65. #include "pkcs11t.h"
  66. #include "secoid.h"
  67. #include "alghmac.h"
  68. #include "softoken.h"
  69. #include "secasn1.h"
  70. #include "secerr.h"
  71. #include "prprf.h"
  72. #define __PASTE(x,y) x##y
  73. /*
  74. * we renamed all our internal functions, get the correct
  75. * definitions for them...
  76. */
  77. #undef CK_PKCS11_FUNCTION_INFO
  78. #undef CK_NEED_ARG_LIST
  79. #define CK_EXTERN extern
  80. #define CK_PKCS11_FUNCTION_INFO(func) \
  81. CK_RV __PASTE(NS,func)
  82. #define CK_NEED_ARG_LIST 1
  83. #include "pkcs11f.h"
  84. typedef struct {
  85. uint8 client_version[2];
  86. uint8 random[46];
  87. } SSL3RSAPreMasterSecret;
  88. static void sftk_Null(void *data, PRBool freeit)
  89. {
  90. return;
  91. }
  92. #ifdef NSS_ENABLE_ECC
  93. #ifdef EC_DEBUG
  94. #define SEC_PRINT(str1, str2, num, sitem) \
  95. printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \
  96. str1, str2, num, sitem->len); \
  97. for (i = 0; i < sitem->len; i++) { \
  98. printf("%02x:", sitem->data[i]); \
  99. } \
  100. printf("\n")
  101. #else
  102. #define SEC_PRINT(a, b, c, d)
  103. #endif
  104. #endif /* NSS_ENABLE_ECC */
  105. /*
  106. * free routines.... Free local type allocated data, and convert
  107. * other free routines to the destroy signature.
  108. */
  109. static void
  110. sftk_FreePrivKey(NSSLOWKEYPrivateKey *key, PRBool freeit)
  111. {
  112. nsslowkey_DestroyPrivateKey(key);
  113. }
  114. static void
  115. sftk_Space(void *data, PRBool freeit)
  116. {
  117. PORT_Free(data);
  118. }
  119. /*
  120. * map all the SEC_ERROR_xxx error codes that may be returned by freebl
  121. * functions to CKR_xxx. return CKR_DEVICE_ERROR by default for backward
  122. * compatibility.
  123. */
  124. static CK_RV
  125. sftk_MapCryptError(int error)
  126. {
  127. switch (error) {
  128. case SEC_ERROR_INVALID_ARGS:
  129. case SEC_ERROR_BAD_DATA: /* MP_RANGE gets mapped to this */
  130. return CKR_ARGUMENTS_BAD;
  131. case SEC_ERROR_INPUT_LEN:
  132. return CKR_DATA_LEN_RANGE;
  133. case SEC_ERROR_OUTPUT_LEN:
  134. return CKR_BUFFER_TOO_SMALL;
  135. case SEC_ERROR_LIBRARY_FAILURE:
  136. return CKR_GENERAL_ERROR;
  137. case SEC_ERROR_NO_MEMORY:
  138. return CKR_HOST_MEMORY;
  139. case SEC_ERROR_BAD_SIGNATURE:
  140. return CKR_SIGNATURE_INVALID;
  141. case SEC_ERROR_INVALID_KEY:
  142. return CKR_KEY_SIZE_RANGE;
  143. case SEC_ERROR_BAD_KEY: /* an EC public key that fails validation */
  144. return CKR_KEY_SIZE_RANGE; /* the closest error code */
  145. case SEC_ERROR_UNSUPPORTED_EC_POINT_FORM:
  146. return CKR_TEMPLATE_INCONSISTENT;
  147. /* EC functions set this error if NSS_ENABLE_ECC is not defined */
  148. case SEC_ERROR_UNSUPPORTED_KEYALG:
  149. return CKR_MECHANISM_INVALID;
  150. case SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE:
  151. return CKR_DOMAIN_PARAMS_INVALID;
  152. /* key pair generation failed after max number of attempts */
  153. case SEC_ERROR_NEED_RANDOM:
  154. return CKR_FUNCTION_FAILED;
  155. }
  156. return CKR_DEVICE_ERROR;
  157. }
  158. /* used by Decrypt and UnwrapKey (indirectly) */
  159. static CK_RV
  160. sftk_MapDecryptError(int error)
  161. {
  162. switch (error) {
  163. case SEC_ERROR_BAD_DATA:
  164. return CKR_ENCRYPTED_DATA_INVALID;
  165. default:
  166. return sftk_MapCryptError(error);
  167. }
  168. }
  169. /*
  170. * return CKR_SIGNATURE_INVALID instead of CKR_DEVICE_ERROR by default for
  171. * backward compatibilty.
  172. */
  173. static CK_RV
  174. sftk_MapVerifyError(int error)
  175. {
  176. CK_RV crv = sftk_MapCryptError(error);
  177. if (crv == CKR_DEVICE_ERROR)
  178. crv = CKR_SIGNATURE_INVALID;
  179. return crv;
  180. }
  181. /*
  182. * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by
  183. * Deprecating a full des key to 40 bit key strenth.
  184. */
  185. static CK_RV
  186. sftk_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey)
  187. {
  188. unsigned char key1[8] = { 0xc4, 0x08, 0xb0, 0x54, 0x0b, 0xa1, 0xe0, 0xae };
  189. unsigned char key2[8] = { 0xef, 0x2c, 0x04, 0x1c, 0xe6, 0x38, 0x2f, 0xe6 };
  190. unsigned char enc_src[8];
  191. unsigned char enc_dest[8];
  192. unsigned int leng,i;
  193. DESContext *descx;
  194. SECStatus rv;
  195. /* zero the parity bits */
  196. for (i=0; i < 8; i++) {
  197. enc_src[i] = cdmfkey[i] & 0xfe;
  198. }
  199. /* encrypt with key 1 */
  200. descx = DES_CreateContext(key1, NULL, NSS_DES, PR_TRUE);
  201. if (descx == NULL) return CKR_HOST_MEMORY;
  202. rv = DES_Encrypt(descx, enc_dest, &leng, 8, enc_src, 8);
  203. DES_DestroyContext(descx,PR_TRUE);
  204. if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
  205. /* xor source with des, zero the parity bits and deprecate the key*/
  206. for (i=0; i < 8; i++) {
  207. if (i & 1) {
  208. enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0xfe;
  209. } else {
  210. enc_src[i] = (enc_src[i] ^ enc_dest[i]) & 0x0e;
  211. }
  212. }
  213. /* encrypt with key 2 */
  214. descx = DES_CreateContext(key2, NULL, NSS_DES, PR_TRUE);
  215. if (descx == NULL) return CKR_HOST_MEMORY;
  216. rv = DES_Encrypt(descx, deskey, &leng, 8, enc_src, 8);
  217. DES_DestroyContext(descx,PR_TRUE);
  218. if (rv != SECSuccess) return sftk_MapCryptError(PORT_GetError());
  219. /* set the corret parity on our new des key */
  220. sftk_FormatDESKey(deskey, 8);
  221. return CKR_OK;
  222. }
  223. /* NSC_DestroyObject destroys an object. */
  224. CK_RV
  225. NSC_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
  226. {
  227. SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
  228. SFTKSession *session;
  229. SFTKObject *object;
  230. SFTKFreeStatus status;
  231. CHECK_FORK();
  232. if (slot == NULL) {
  233. return CKR_SESSION_HANDLE_INVALID;
  234. }
  235. /*
  236. * This whole block just makes sure we really can destroy the
  237. * requested object.
  238. */
  239. session = sftk_SessionFromHandle(hSession);
  240. if (session == NULL) {
  241. return CKR_SESSION_HANDLE_INVALID;
  242. }
  243. object = sftk_ObjectFromHandle(hObject,session);
  244. if (object == NULL) {
  245. sftk_FreeSession(session);
  246. return CKR_OBJECT_HANDLE_INVALID;
  247. }
  248. /* don't destroy a private object if we aren't logged in */
  249. if ((!slot->isLoggedIn) && (slot->needLogin) &&
  250. (sftk_isTrue(object,CKA_PRIVATE))) {
  251. sftk_FreeSession(session);
  252. sftk_FreeObject(object);
  253. return CKR_USER_NOT_LOGGED_IN;
  254. }
  255. /* don't destroy a token object if we aren't in a rw session */
  256. if (((session->info.flags & CKF_RW_SESSION) == 0) &&
  257. (sftk_isTrue(object,CKA_TOKEN))) {
  258. sftk_FreeSession(session);
  259. sftk_FreeObject(object);
  260. return CKR_SESSION_READ_ONLY;
  261. }
  262. sftk_DeleteObject(session,object);
  263. sftk_FreeSession(session);
  264. /*
  265. * get some indication if the object is destroyed. Note: this is not
  266. * 100%. Someone may have an object reference outstanding (though that
  267. * should not be the case by here. Also note that the object is "half"
  268. * destroyed. Our internal representation is destroyed, but it may still
  269. * be in the data base.
  270. */
  271. status = sftk_FreeObject(object);
  272. return (status != SFTK_DestroyFailure) ? CKR_OK : CKR_DEVICE_ERROR;
  273. }
  274. /*
  275. ************** Crypto Functions: Utilities ************************
  276. */
  277. /*
  278. * return a context based on the SFTKContext type.
  279. */
  280. SFTKSessionContext *
  281. sftk_ReturnContextByType(SFTKSession *session, SFTKContextType type)
  282. {
  283. switch (type) {
  284. case SFTK_ENCRYPT:
  285. case SFTK_DECRYPT:
  286. return session->enc_context;
  287. case SFTK_HASH:
  288. return session->hash_context;
  289. case SFTK_SIGN:
  290. case SFTK_SIGN_RECOVER:
  291. case SFTK_VERIFY:
  292. case SFTK_VERIFY_RECOVER:
  293. return session->hash_context;
  294. }
  295. return NULL;
  296. }
  297. /*
  298. * change a context based on the SFTKContext type.
  299. */
  300. void
  301. sftk_SetContextByType(SFTKSession *session, SFTKContextType type,
  302. SFTKSessionContext *context)
  303. {
  304. switch (type) {
  305. case SFTK_ENCRYPT:
  306. case SFTK_DECRYPT:
  307. session->enc_context = context;
  308. break;
  309. case SFTK_HASH:
  310. session->hash_context = context;
  311. break;
  312. case SFTK_SIGN:
  313. case SFTK_SIGN_RECOVER:
  314. case SFTK_VERIFY:
  315. case SFTK_VERIFY_RECOVER:
  316. session->hash_context = context;
  317. break;
  318. }
  319. return;
  320. }
  321. /*
  322. * code to grab the context. Needed by every C_XXXUpdate, C_XXXFinal,
  323. * and C_XXX function. The function takes a session handle, the context type,
  324. * and wether or not the session needs to be multipart. It returns the context,
  325. * and optionally returns the session pointer (if sessionPtr != NULL) if session
  326. * pointer is returned, the caller is responsible for freeing it.
  327. */
  328. static CK_RV
  329. sftk_GetContext(CK_SESSION_HANDLE handle,SFTKSessionContext **contextPtr,
  330. SFTKContextType type, PRBool needMulti, SFTKSession **sessionPtr)
  331. {
  332. SFTKSession *session;
  333. SFTKSessionContext *context;
  334. session = sftk_SessionFromHandle(handle);
  335. if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  336. context = sftk_ReturnContextByType(session,type);
  337. /* make sure the context is valid */
  338. if((context==NULL)||(context->type!=type)||(needMulti&&!(context->multi))){
  339. sftk_FreeSession(session);
  340. return CKR_OPERATION_NOT_INITIALIZED;
  341. }
  342. *contextPtr = context;
  343. if (sessionPtr != NULL) {
  344. *sessionPtr = session;
  345. } else {
  346. sftk_FreeSession(session);
  347. }
  348. return CKR_OK;
  349. }
  350. /** Terminate operation (in the PKCS#11 spec sense).
  351. * Intuitive name for FreeContext/SetNullContext pair.
  352. */
  353. static void
  354. sftk_TerminateOp( SFTKSession *session, SFTKContextType ctype,
  355. SFTKSessionContext *context )
  356. {
  357. sftk_FreeContext( context );
  358. sftk_SetContextByType( session, ctype, NULL );
  359. }
  360. /*
  361. ************** Crypto Functions: Encrypt ************************
  362. */
  363. /*
  364. * All the NSC_InitXXX functions have a set of common checks and processing they
  365. * all need to do at the beginning. This is done here.
  366. */
  367. static CK_RV
  368. sftk_InitGeneric(SFTKSession *session,SFTKSessionContext **contextPtr,
  369. SFTKContextType ctype,SFTKObject **keyPtr,
  370. CK_OBJECT_HANDLE hKey, CK_KEY_TYPE *keyTypePtr,
  371. CK_OBJECT_CLASS pubKeyType, CK_ATTRIBUTE_TYPE operation)
  372. {
  373. SFTKObject *key = NULL;
  374. SFTKAttribute *att;
  375. SFTKSessionContext *context;
  376. /* We can only init if there is not current context active */
  377. if (sftk_ReturnContextByType(session,ctype) != NULL) {
  378. return CKR_OPERATION_ACTIVE;
  379. }
  380. /* find the key */
  381. if (keyPtr) {
  382. key = sftk_ObjectFromHandle(hKey,session);
  383. if (key == NULL) {
  384. return CKR_KEY_HANDLE_INVALID;
  385. }
  386. /* make sure it's a valid key for this operation */
  387. if (((key->objclass != CKO_SECRET_KEY) && (key->objclass != pubKeyType))
  388. || !sftk_isTrue(key,operation)) {
  389. sftk_FreeObject(key);
  390. return CKR_KEY_TYPE_INCONSISTENT;
  391. }
  392. /* get the key type */
  393. att = sftk_FindAttribute(key,CKA_KEY_TYPE);
  394. if (att == NULL) {
  395. sftk_FreeObject(key);
  396. return CKR_KEY_TYPE_INCONSISTENT;
  397. }
  398. PORT_Assert(att->attrib.ulValueLen == sizeof(CK_KEY_TYPE));
  399. if (att->attrib.ulValueLen != sizeof(CK_KEY_TYPE)) {
  400. sftk_FreeAttribute(att);
  401. sftk_FreeObject(key);
  402. return CKR_ATTRIBUTE_VALUE_INVALID;
  403. }
  404. PORT_Memcpy(keyTypePtr, att->attrib.pValue, sizeof(CK_KEY_TYPE));
  405. sftk_FreeAttribute(att);
  406. *keyPtr = key;
  407. }
  408. /* allocate the context structure */
  409. context = (SFTKSessionContext *)PORT_Alloc(sizeof(SFTKSessionContext));
  410. if (context == NULL) {
  411. if (key) sftk_FreeObject(key);
  412. return CKR_HOST_MEMORY;
  413. }
  414. context->type = ctype;
  415. context->multi = PR_TRUE;
  416. context->cipherInfo = NULL;
  417. context->hashInfo = NULL;
  418. context->doPad = PR_FALSE;
  419. context->padDataLength = 0;
  420. context->key = key;
  421. context->blockSize = 0;
  422. *contextPtr = context;
  423. return CKR_OK;
  424. }
  425. /** NSC_CryptInit initializes an encryption/Decryption operation.
  426. *
  427. * Always called by NSC_EncryptInit, NSC_DecryptInit, NSC_WrapKey,NSC_UnwrapKey.
  428. * Called by NSC_SignInit, NSC_VerifyInit (via sftk_InitCBCMac) only for block
  429. * ciphers MAC'ing.
  430. */
  431. static CK_RV
  432. sftk_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
  433. CK_OBJECT_HANDLE hKey,
  434. CK_ATTRIBUTE_TYPE mechUsage, CK_ATTRIBUTE_TYPE keyUsage,
  435. SFTKContextType contextType, PRBool isEncrypt)
  436. {
  437. SFTKSession *session;
  438. SFTKObject *key;
  439. SFTKSessionContext *context;
  440. SFTKAttribute *att;
  441. CK_RC2_CBC_PARAMS *rc2_param;
  442. #if NSS_SOFTOKEN_DOES_RC5
  443. CK_RC5_CBC_PARAMS *rc5_param;
  444. SECItem rc5Key;
  445. #endif
  446. CK_KEY_TYPE key_type;
  447. CK_RV crv = CKR_OK;
  448. unsigned effectiveKeyLength;
  449. unsigned char newdeskey[24];
  450. PRBool useNewKey=PR_FALSE;
  451. int t;
  452. crv = sftk_MechAllowsOperation(pMechanism->mechanism, mechUsage );
  453. if (crv != CKR_OK)
  454. return crv;
  455. session = sftk_SessionFromHandle(hSession);
  456. if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
  457. crv = sftk_InitGeneric(session,&context,contextType,&key,hKey,&key_type,
  458. isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, keyUsage);
  459. if (crv != CKR_OK) {
  460. sftk_FreeSession(session);
  461. return crv;
  462. }
  463. context->doPad = PR_FALSE;
  464. switch(pMechanism->mechanism) {
  465. case CKM_RSA_PKCS:
  466. case CKM_RSA_X_509:
  467. if (key_type != CKK_RSA) {
  468. crv = CKR_KEY_TYPE_INCONSISTENT;
  469. break;
  470. }
  471. context->multi = PR_FALSE;
  472. if (isEncrypt) {
  473. NSSLOWKEYPublicKey *pubKey = sftk_GetPubKey(key,CKK_RSA,&crv);
  474. if (pubKey == NULL) {
  475. break;
  476. }
  477. context->maxLen = nsslowkey_PublicModulusLen(pubKey);
  478. context->cipherInfo = (void *)pubKey;
  479. context->update = (SFTKCipher)
  480. (pMechanism->mechanism == CKM_RSA_X_509
  481. ? RSA_EncryptRaw : RSA_EncryptBlock);
  482. } else {
  483. NSSLOWKEYPrivateKey *privKey = sftk_GetPrivKey(key,CKK_RSA,&crv);
  484. if (privKey == NULL) {
  485. break;
  486. }
  487. context->maxLen = nsslowkey_PrivateModulusLen(privKey);
  488. context->cipherInfo = (void *)privKey;
  489. context->update = (SFTKCipher)
  490. (pMechanism->mechanism == CKM_RSA_X_509
  491. ? RSA_DecryptRaw : RSA_DecryptBlock);
  492. }
  493. context->destroy = sftk_Null;
  494. break;
  495. case CKM_RC2_CBC_PAD:
  496. context->doPad = PR_TRUE;
  497. /* fall thru */
  498. case CKM_RC2_ECB:
  499. case CKM_RC2_CBC:
  500. context->blockSize = 8;
  501. if (key_type != CKK_RC2) {
  502. crv = CKR_KEY_TYPE_INCONSISTENT;
  503. break;
  504. }
  505. att = sftk_FindAttribute(key,CKA_VALUE);
  506. if (att == NULL) {
  507. crv = CKR_KEY_HANDLE_INVALID;
  508. break;
  509. }
  510. rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter;
  511. effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8;
  512. context->cipherInfo =
  513. RC2_CreateContext((unsigned char*)att->attrib.pValue,
  514. att->attrib.ulValueLen, rc2_param->iv,
  515. pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 :
  516. NSS_RC2_CBC,effectiveKeyLength);
  517. sftk_FreeAttribute(att);
  518. if (context->cipherInfo == NULL) {
  519. crv = CKR_HOST_MEMORY;
  520. break;
  521. }
  522. context->update = (SFTKCipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt);
  523. context->destroy = (SFTKDestroy) RC2_DestroyContext;
  524. break;
  525. #if NSS_SOFTOKEN_DOES_RC5
  526. case CKM_RC5_CBC_PAD:
  527. context->doPad = PR_TRUE;
  528. /* fall thru */
  529. case CKM_RC5_ECB:
  530. case CKM_RC5_CBC:
  531. if (key_type != CKK_RC5) {
  532. crv = CKR_KEY_TYPE_INCONSISTENT;
  533. break;
  534. }
  535. att = sftk_FindAttribute(key,CKA_VALUE);
  536. if (att == NULL) {
  537. crv = CKR_KEY_HANDLE_INVALID;
  538. break;
  539. }
  540. rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter;
  541. context->blockSize = rc5_param->ulWordsize*2;
  542. rc5Key.data = (unsigned char*)att->attrib.pValue;
  543. rc5Key.len = att->attrib.ulValueLen;
  544. context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds,
  545. rc5_param->ulWordsize,rc5_param->pIv,
  546. pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC);
  547. sftk_FreeAttribute(att);
  548. if (context->cipherInfo == NULL) {
  549. crv = CKR_HOST_MEMORY;
  550. break;
  551. }
  552. context->update = (SFTKCipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt);
  553. context->destroy = (SFTKDestroy) RC5_DestroyContext;
  554. break;
  555. #endif
  556. case CKM_RC4:
  557. if (key_type != CKK_RC4) {
  558. crv = CKR_KEY_TYPE_INCONSISTENT;
  559. break;
  560. }
  561. att = sftk_FindAttribute(key,CKA_VALUE);
  562. if (att == NULL) {
  563. crv = CKR_KEY_HANDLE_INVALID;
  564. break;
  565. }
  566. context->cipherInfo =
  567. RC4_CreateContext((unsigned char*)att->attrib.pValue,
  568. att->attrib.ulValueLen);
  569. sftk_FreeAttribute(att);
  570. if (context->cipherInfo == NULL) {
  571. crv = CKR_HOST_MEMORY; /* WRONG !!! */
  572. break;
  573. }
  574. context->update = (SFTKCipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt);
  575. context->destroy = (SFTKDestroy) RC4_DestroyContext;
  576. break;
  577. case CKM_CDMF_CBC_PAD:
  578. context->doPad = PR_TRUE;
  579. /* fall thru */
  580. case CKM_CDMF_ECB:
  581. case CKM_CDMF_CBC:
  582. if (key_type != CKK_CDMF) {
  583. crv = CKR_KEY_TYPE_INCONSISTENT;
  584. break;
  585. }
  586. t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC;
  587. if (crv != CKR_OK) break;
  588. goto finish_des;
  589. case CKM_DES_ECB:
  590. if (key_type != CKK_DES) {
  591. crv = CKR_KEY_TYPE_INCONSISTENT;
  592. break;
  593. }
  594. t = NSS_DES;
  595. goto finish_des;
  596. case CKM_DES_CBC_PAD:
  597. context->doPad = PR_TRUE;
  598. /* fall thru */
  599. case CKM_DES_CBC:
  600. if (key_type != CKK_DES) {
  601. crv = CKR_KEY_TYPE_INCONSISTENT;
  602. break;
  603. }
  604. t = NSS_DES_CBC;
  605. goto finish_des;
  606. case CKM_DES3_ECB:
  607. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  608. crv = CKR_KEY_TYPE_INCONSISTENT;
  609. break;
  610. }
  611. t = NSS_DES_EDE3;
  612. goto finish_des;
  613. case CKM_DES3_CBC_PAD:
  614. context->doPad = PR_TRUE;
  615. /* fall thru */
  616. case CKM_DES3_CBC:
  617. if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) {
  618. crv = CKR_KEY_TYPE_INCONSISTENT;
  619. break;
  620. }
  621. t = NSS_DES_EDE3_CBC;
  622. finish_des:
  623. context->blockSize = 8;
  624. att = sftk_FindAttribute(key,CKA_VALUE);
  625. if (att == NULL) {
  626. crv = CKR_KEY_HANDLE_INVALID;
  627. break;
  628. }
  629. if (key_type == CKK_DES2 &&
  630. (t == NSS_DES_EDE3_CBC || t == NSS_DES_EDE3)) {
  631. /* extend DES2 key to DES3 key. */
  632. memcpy(newdeskey, att->attrib.pValue, 16);
  633. memcpy(newdeskey + 16, newdeskey, 8);
  634. useNewKey=PR_TRUE;
  635. } else if (key_type == CKK_CDMF) {
  636. crv = sftk_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey);
  637. if (crv != CKR_OK) {
  638. sftk_FreeAttribute(att);
  639. break;
  640. }
  641. useNewKey=PR_TRUE;
  642. }
  643. context->cipherInfo = DES_CreateContext(
  644. useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue,
  645. (unsigned char*)pMechanism->pParameter,t, isEncrypt);
  646. if (useNewKey)
  647. memset(newdeskey, 0, sizeof newdeskey);
  648. sftk_FreeAttribute(att);
  649. if (context->cipherInfo == NULL) {
  650. crv = CKR_HOST_MEMORY;
  651. break;
  652. }
  653. context->update = (SFTKCipher) (isEncrypt ? DES_Encrypt : DES_Decrypt);
  654. context->destroy = (SFTKDestroy) DES_DestroyContext;
  655. break;
  656. case CKM_SEED_CBC_PAD:
  657. context->doPad = PR_TRUE;
  658. /* fall thru */
  659. case CKM_SEED_CBC:
  660. if (!pMechanism->pParameter ||
  661. pMechanism->ulParameterLen != 16) {
  662. crv = CKR_MECHANISM_PARAM_INVALID;
  663. break;
  664. }
  665. /* fall thru */
  666. case CKM_SEED_ECB:
  667. context->blockSize = 16;
  668. if (key_type != CKK_SEED) {
  669. crv = CKR_KEY_TYPE_INCONSISTENT;
  670. break;
  671. }
  672. att = sftk_FindAttribute(key,CKA_VALUE);
  673. if (att == NULL) {
  674. crv = CKR_KEY_HANDLE_INVALID;
  675. break;
  676. }
  677. context->cipherInfo = SEED_CreateContext(
  678. (unsigned char*)att->attrib.pValue,
  679. (unsigned char*)pMechanism->pParameter,
  680. pMechanism->mechanism == CKM_SEED_ECB ? NSS_SEED : NSS_SEED_CBC,
  681. isEncrypt);
  682. sftk_FreeAttribute(att);
  683. if (context->cipherInfo == NULL) {
  684. crv = CKR_HOST_MEMORY;
  685. break;
  686. }
  687. context->update = (SFTKCipher)(isEncrypt ? SEED_Encrypt : SEED_Decrypt);
  688. context->destroy = (SFTKDestroy) SEED_DestroyContext;
  689. break;
  690. case CKM_CAMELLIA_CBC_PAD:
  691. context->doPad = PR_TRUE;
  692. /* fall thru */
  693. case CKM_CAMELLIA_CBC:
  694. if (!pMechanism->pParameter ||
  695. pMechanism->ulParameterLen != 16) {
  696. crv = CKR_MECHANISM_PARAM_INVALID;
  697. break;
  698. }
  699. /* fall thru */
  700. case CKM_CAMELLIA_ECB:
  701. context->blockSize = 16;
  702. if (key_type != CKK_CAMELLIA) {
  703. crv = CKR_KEY_TYPE_INCONSISTENT;
  704. break;
  705. }
  706. att = sftk_FindAttribute(key,CKA_VALUE);
  707. if (att == NULL) {
  708. crv = CKR_KEY_HANDLE_INVALID;
  709. break;
  710. }
  711. context->cipherInfo = Camellia_CreateContext(
  712. (unsigned char*)att->attrib.pValue,
  713. (unsigned char*)pMechanism->pParameter,
  714. pMechanism->mechanism ==
  715. CKM_CAMELLIA_ECB ? NSS_CAMELLIA : NSS_CAMELLIA_CBC,
  716. isEncrypt, att->attrib.ulValueLen);
  717. sftk_FreeAttribute(att);
  718. if (context->cipherInfo == NULL) {
  719. crv = CKR_HOST_MEMORY;
  720. break;
  721. }
  722. context->update = (SFTKCipher) (isEncrypt ?
  723. Camellia_Encrypt : Camellia_Decrypt);
  724. context->destroy = (SFTKDestroy) Camellia_DestroyContext;
  725. break;
  726. case CKM_AES_CBC_PAD:
  727. context->doPad = PR_TRUE;
  728. /* fall thru */
  729. case CKM_AES_ECB:
  730. case CKM_AES_CBC:
  731. context->blockSize = 16;
  732. if (key_type != CKK_AES) {
  733. crv = CKR_KEY_TYPE_INCONSISTENT;
  734. break;
  735. }
  736. att = sftk_FindAttribute(key,CKA_VALUE);
  737. if (att == NULL) {
  738. crv = CKR_KEY_HANDLE_INVALID;
  739. break;
  740. }
  741. context->cipherInfo = AES_CreateContext(
  742. (unsigned char*)att->attrib.pValue,
  743. (unsigned char*)pMechanism->pParameter,
  744. pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC,
  745. isEncrypt, att->attrib.ulValueLen, 16);
  746. sftk_FreeAttribute(att);
  747. if (context->cipherInfo == NULL) {
  748. crv = CKR_HOST_MEMORY;
  749. break;
  750. }
  751. context->update = (SFTKCipher) (isEncrypt ? AES_Encrypt : AES_Decrypt);
  752. context->destroy = (SFTKDestroy) AES_DestroyContext;
  753. break;
  754. case CKM_NETSCAPE_AES_KEY_WRAP_PAD:
  755. context->doPad = PR_TRUE;
  756. /* fall thru */
  757. case CKM_NETSCAPE_AES_KEY_WRAP:
  758. context->multi = PR_FALSE;
  759. context->blockSize = 8;
  760. if (key_type != CKK_AES) {
  761. crv = CKR_KEY_TYPE_INCONSISTENT;
  762. break;
  763. }
  764. att = sftk_FindAttribute(key,CKA_VALUE);
  765. if (att == NULL) {
  766. crv = CKR_KEY_HANDLE_INVALID;
  767. break;
  768. }
  769. context->cipherInfo = AESKeyWrap_CreateContext(
  770. (unsigned char*)att->attrib.pValue,
  771. (unsigned char*)pMechanism->pParameter,
  772. isEncrypt, att->attrib.ulValueLen);
  773. sftk_FreeAttribute(att);
  774. if (context->cipherInfo == NULL) {
  775. crv = CKR_HOST_MEMORY;
  776. break;
  777. }
  778. context->update = (SFTKCipher) (isEncrypt ? AESKeyWrap_Encrypt
  779. : AESKeyWrap_Decrypt);
  780. context->destroy = (SFTKDestroy) AESKeyWrap_DestroyContext;
  781. break;
  782. default:
  783. crv = CKR_MECHANISM_INVALID;
  784. break;
  785. }
  786. if (crv != CKR_OK) {
  787. sftk_FreeContext(context);
  788. sftk_FreeSession(session);
  789. return crv;
  790. }
  791. sftk_SetContextByType(session, contextType, context);
  792. sftk_FreeSession(session);
  793. return CKR_OK;
  794. }
  795. /* NSC_EncryptInit initializes an encryption operation. */
  796. CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession,
  797. CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
  798. {
  799. CHECK_FORK();
  800. return sftk_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, CKA_ENCRYPT,
  801. SFTK_ENCRYPT, PR_TRUE);
  802. }
  803. /* NSC_EncryptUpdate continues a multiple-part encryption operation. */
  804. CK_RV NSC_EncryptUpdate(CK_SESSION_HANDLE hSession,
  805. CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
  806. CK_ULONG_PTR pulEncryptedPartLen)
  807. {
  808. SFTKSessionContext *context;
  809. unsigned int outlen,i;
  810. unsigned int padoutlen = 0;
  811. unsigned int maxout = *pulEncryptedPartLen;
  812. CK_RV crv;
  813. SECStatus rv;
  814. CHECK_FORK();
  815. /* make sure we're legal */
  816. crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,NULL);
  817. if (crv != CKR_OK) return crv;
  818. if (!pEncryptedPart) {
  819. if (context->doPad) {
  820. CK_ULONG totalDataAvailable = ulPartLen + context->padDataLength;
  821. CK_ULONG blocksToSend = totalDataAvailable/context->blockSize;
  822. *pulEncryptedPartLen = blocksToSend * context->blockSize;
  823. return CKR_OK;
  824. }
  825. *pulEncryptedPartLen = ulPartLen;
  826. return CKR_OK;
  827. }
  828. /* do padding */
  829. if (context->doPad) {
  830. /* deal with previous buffered data */
  831. if (context->padDataLength != 0) {
  832. /* fill in the padded to a full block size */
  833. for (i=context->padDataLength;
  834. (ulPartLen != 0) && i < context->blockSize; i++) {
  835. context->padBuf[i] = *pPart++;
  836. ulPartLen--;
  837. context->padDataLength++;
  838. }
  839. /* not enough data to encrypt yet? then return */
  840. if (context->padDataLength != context->blockSize) {
  841. *pulEncryptedPartLen = 0;
  842. return CKR_OK;
  843. }
  844. /* encrypt the current padded data */
  845. rv = (*context->update)(context->cipherInfo, pEncryptedPart,
  846. &padoutlen, context->blockSize, context->padBuf,
  847. context->blockSize);
  848. if (rv != SECSuccess) {
  849. return sftk_MapCryptError(PORT_GetError());
  850. }
  851. pEncryptedPart += padoutlen;
  852. maxout -= padoutlen;
  853. }
  854. /* save the residual */
  855. context->padDataLength = ulPartLen % context->blockSize;
  856. if (context->padDataLength) {
  857. PORT_Memcpy(context->padBuf,
  858. &pPart[ulPartLen-context->padDataLength],
  859. context->padDataLength);
  860. ulPartLen -= context->padDataLength;
  861. }
  862. /* if we've exhausted our new buffer, we're done */
  863. if (ulPartLen == 0) {
  864. *pulEncryptedPartLen = padoutlen;
  865. return CKR_OK;
  866. }
  867. }
  868. /* do it: NOTE: this assumes buf size in is >= buf size out! */
  869. rv = (*context->update)(context->cipherInfo,pEncryptedPart,
  870. &outlen, maxout, pPart, ulPartLen);
  871. *pulEncryptedPartLen = (CK_ULONG) (outlen + padoutlen);
  872. return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
  873. }
  874. /* NSC_EncryptFinal finishes a multiple-part encryption operation. */
  875. CK_RV NSC_EncryptFinal(CK_SESSION_HANDLE hSession,
  876. CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen)
  877. {
  878. SFTKSession *session;
  879. SFTKSessionContext *context;
  880. unsigned int outlen,i;
  881. unsigned int maxout = *pulLastEncryptedPartLen;
  882. CK_RV crv;
  883. SECStatus rv = SECSuccess;
  884. PRBool contextFinished = PR_TRUE;
  885. CHECK_FORK();
  886. /* make sure we're legal */
  887. crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_TRUE,&session);
  888. if (crv != CKR_OK) return crv;
  889. *pulLastEncryptedPartLen = 0;
  890. if (!pLastEncryptedPart) {
  891. /* caller is checking the amount of remaining data */
  892. if (context->blockSize > 0 && context->doPad) {
  893. *pulLastEncryptedPartLen = context->blockSize;
  894. contextFinished = PR_FALSE; /* still have padding to go */
  895. }
  896. goto finish;
  897. }
  898. /* do padding */
  899. if (context->doPad) {
  900. unsigned char padbyte = (unsigned char)
  901. (context->blockSize - context->padDataLength);
  902. /* fill out rest of pad buffer with pad magic*/
  903. for (i=context->padDataLength; i < context->blockSize; i++) {
  904. context->padBuf[i] = padbyte;
  905. }
  906. rv = (*context->update)(context->cipherInfo,pLastEncryptedPart,
  907. &outlen, maxout, context->padBuf, context->blockSize);
  908. if (rv == SECSuccess) *pulLastEncryptedPartLen = (CK_ULONG) outlen;
  909. }
  910. finish:
  911. if (contextFinished)
  912. sftk_TerminateOp( session, SFTK_ENCRYPT, context );
  913. sftk_FreeSession(session);
  914. return (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
  915. }
  916. /* NSC_Encrypt encrypts single-part data. */
  917. CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData,
  918. CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
  919. CK_ULONG_PTR pulEncryptedDataLen)
  920. {
  921. SFTKSession *session;
  922. SFTKSessionContext *context;
  923. unsigned int outlen;
  924. unsigned int maxoutlen = *pulEncryptedDataLen;
  925. CK_RV crv;
  926. CK_RV crv2;
  927. SECStatus rv = SECSuccess;
  928. SECItem pText;
  929. pText.type = siBuffer;
  930. pText.data = pData;
  931. pText.len = ulDataLen;
  932. CHECK_FORK();
  933. /* make sure we're legal */
  934. crv = sftk_GetContext(hSession,&context,SFTK_ENCRYPT,PR_FALSE,&session);
  935. if (crv != CKR_OK) return crv;
  936. if (!pEncryptedData) {
  937. *pulEncryptedDataLen = context->multi ?
  938. ulDataLen + 2 * context->blockSize : context->maxLen;
  939. goto finish;
  940. }
  941. if (context->doPad) {
  942. if (context->multi) {
  943. CK_ULONG finalLen;
  944. /* padding is fairly complicated, have the update and final
  945. * code deal with it */
  946. sftk_FreeSession(session);
  947. crv = NSC_EncryptUpdate(hSession, pData, ulDataLen, pEncryptedData,
  948. pulEncryptedDataLen);
  949. if (crv != CKR_OK)
  950. *pulEncryptedDataLen = 0;
  951. maxoutlen -= *pulEncryptedDataLen;
  952. pEncryptedData += *pulEncryptedDataLen;
  953. finalLen = maxoutlen;
  954. crv2 = NSC_EncryptFinal(hSession, pEncryptedData, &finalLen);
  955. if (crv2 == CKR_OK)
  956. *pulEncryptedDataLen += finalLen;
  957. return crv == CKR_OK ? crv2 : crv;
  958. }
  959. /* doPad without multi means that padding must be done on the first
  960. ** and only update. There will be no final.
  961. */
  962. PORT_Assert(context->blockSize > 1);
  963. if (context->blockSize > 1) {
  964. CK_ULONG remainder = ulDataLen % context->blockSize;
  965. CK_ULONG padding = context->blockSize - remainder;
  966. pText.len += padding;
  967. pText.data = PORT_ZAlloc(pText.len);
  968. if (pText.data) {
  969. memcpy(pText.data, pData, ulDataLen);
  970. memset(pText.data + ulDataLen, padding, padding);
  971. } else {
  972. crv = CKR_HOST_MEMORY;
  973. goto fail;
  974. }
  975. }
  976. }
  977. /* do it: NOTE: this assumes buf size is big enough. */
  978. rv = (*context->update)(context->cipherInfo, pEncryptedData,
  979. &outlen, maxoutlen, pText.data, pText.len);
  980. crv = (rv == SECSuccess) ? CKR_OK : sftk_MapCryptError(PORT_GetError());
  981. *pulEncryptedDataLen = (CK_ULONG) outlen;
  982. if (pText.data != pData)
  983. PORT_ZFree(pText.data, pText.len);
  984. fail:
  985. sftk_TerminateOp( session, SFTK_ENCRYPT, context );
  986. finish:
  987. sftk_FreeSession(session);
  988. return crv;
  989. }
  990. /*
  991. ************** Crypto Functions: Decrypt ************************
  992. */
  993. /* NSC_DecryptInit initializes a decryption operation. */
  994. CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession,
  995. CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
  996. {
  997. CHECK_FORK();
  998. return sftk_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, CKA_DECRYPT,
  999. SFTK_DECRYPT, PR_FALSE);
  1000. }
  1001. /* NSC_DecryptUpdate continues a multiple-part decryption operation. */
  1002. CK_RV NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
  1003. CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen,
  1004. CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen)
  1005. {
  1006. SFTKSessionContext *context;
  1007. unsigned int padoutlen = 0;
  1008. unsigned int outlen;
  1009. unsigned int maxout = *pulPartLen;
  1010. CK_RV crv;
  1011. SECStatus rv;
  1012. CHECK_FORK();
  1013. /* make sure we're legal */
  1014. crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,NULL);
  1015. if (crv != CKR_OK) return crv;
  1016. /* this can only happen on an NSS programming error */
  1017. PORT_Assert((context->padDataLength == 0)
  1018. || context->padDataLength == context->blockSize);
  1019. if (!pPart) {
  1020. if (context->doPad) {
  1021. /* we can check the data length here because if we are padding,
  1022. * then we must be using a block cipher. In the non-padding case
  1023. * the error will be returned by the underlying decryption
  1024. * function when do do the actual decrypt. We need to do the
  1025. * check here to avoid returning a negative length to the caller.
  1026. */
  1027. if ((ulEncryptedPartLen == 0) ||
  1028. (ulEncryptedPartLen % context->blockSize) != 0) {
  1029. return CKR_ENCRYPTED_DATA_LEN_RANGE;
  1030. }
  1031. *pulPartLen =
  1032. ulEncryptedPartLen + context->padDataLength - context->blockSize;
  1033. return CKR_OK;
  1034. }
  1035. /* for stream ciphers there is are no constraints on ulEncryptedPartLen.
  1036. * for block ciphers, it must be a multiple of blockSize. The error is
  1037. * detected when this function is called again do decrypt the output.
  1038. */
  1039. *pulPartLen = ulEncryptedPartLen;
  1040. return CKR_OK;
  1041. }
  1042. if (context->doPad) {
  1043. /* first decrypt our saved buffer */
  1044. if (context->padDataLength != 0) {
  1045. rv = (*context->update)(context->cipherInfo, pPart, &padoutlen,
  1046. maxout, context->padBuf, context->blockSize);
  1047. if (rv != SECSuccess) return sftk_MapDecryptError(PORT_GetError());
  1048. pPart += padoutlen;
  1049. maxout -= padoutlen;
  1050. }
  1051. /* now save the final block for the next decrypt or the final */
  1052. PORT_Memcpy(context->padBuf,&pEncryptedPart[ulEncryptedPartLen -
  1053. context->blockSize], context->blockSize);
  1054. context->padDataLength = context->blockSize;
  1055. ulEncryptedPartLen -= context->padDataLength;
  1056. }
  1057. /* do it: NOTE: this assumes buf size in is >= buf size out! */
  1058. rv = (*context->update)(context->cipherInfo,pPart, &outlen,
  1059. maxout, pEncryptedPart, ulEncryptedPartLen);
  1060. *pulPartLen = (CK_ULONG) (outlen + padoutlen);
  1061. return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
  1062. }
  1063. /* NSC_DecryptFinal finishes a multiple-part decryption operation. */
  1064. CK_RV NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
  1065. CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen)
  1066. {
  1067. SFTKSession *session;
  1068. SFTKSessionContext *context;
  1069. unsigned int outlen;
  1070. unsigned int maxout = *pulLastPartLen;
  1071. CK_RV crv;
  1072. SECStatus rv = SECSuccess;
  1073. CHECK_FORK();
  1074. /* make sure we're legal */
  1075. crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_TRUE,&session);
  1076. if (crv != CKR_OK) return crv;
  1077. *pulLastPartLen = 0;
  1078. if (!pLastPart) {
  1079. /* caller is checking the amount of remaining data */
  1080. if (context->padDataLength > 0) {
  1081. *pulLastPartLen = context->padDataLength;
  1082. }
  1083. rv = SECSuccess;
  1084. goto finish;
  1085. }
  1086. if (context->doPad) {
  1087. /* decrypt our saved buffer */
  1088. if (context->padDataLength != 0) {
  1089. /* this assumes that pLastPart is big enough to hold the *whole*
  1090. * buffer!!! */
  1091. rv = (*context->update)(context->cipherInfo, pLastPart, &outlen,
  1092. maxout, context->padBuf, context->blockSize);
  1093. if (rv == SECSuccess) {
  1094. unsigned int padSize =
  1095. (unsigned int) pLastPart[context->blockSize-1];
  1096. if ((padSize > context->blockSize) || (padSize == 0)) {
  1097. rv = SECFailure;
  1098. } else {
  1099. *pulLastPartLen = outlen - padSize;
  1100. }
  1101. }
  1102. }
  1103. }
  1104. sftk_TerminateOp( session, SFTK_DECRYPT, context );
  1105. finish:
  1106. sftk_FreeSession(session);
  1107. return (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
  1108. }
  1109. /* NSC_Decrypt decrypts encrypted data in a single part. */
  1110. CK_RV NSC_Decrypt(CK_SESSION_HANDLE hSession,
  1111. CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,
  1112. CK_ULONG_PTR pulDataLen)
  1113. {
  1114. SFTKSession *session;
  1115. SFTKSessionContext *context;
  1116. unsigned int outlen;
  1117. unsigned int maxoutlen = *pulDataLen;
  1118. CK_RV crv;
  1119. CK_RV crv2;
  1120. SECStatus rv = SECSuccess;
  1121. CHECK_FORK();
  1122. /* make sure we're legal */
  1123. crv = sftk_GetContext(hSession,&context,SFTK_DECRYPT,PR_FALSE,&session);
  1124. if (crv != CKR_OK) return crv;
  1125. if (!pData) {
  1126. *pulDataLen = ulEncryptedDataLen + context->blockSize;
  1127. goto finish;
  1128. }
  1129. if (context->doPad && context->multi) {
  1130. CK_ULONG finalLen;
  1131. /* padding is fairly complicated, have the update and final
  1132. * code deal with it */
  1133. sftk_FreeSession(session);
  1134. crv = NSC_DecryptUpdate(hSession,pEncryptedData,ulEncryptedDataLen,
  1135. pData, pulDataLen);
  1136. if (crv != CKR_OK)
  1137. *pulDataLen = 0;
  1138. maxoutlen -= *pulDataLen;
  1139. pData += *pulDataLen;
  1140. finalLen = maxoutlen;
  1141. crv2 = NSC_DecryptFinal(hSession, pData, &finalLen);
  1142. if (crv2 == CKR_OK)
  1143. *pulDataLen += finalLen;
  1144. return crv == CKR_OK ? crv2 : crv;
  1145. }
  1146. rv = (*context->update)(context->cipherInfo, pData, &outlen, maxoutlen,
  1147. pEncryptedData, ulEncryptedDataLen);
  1148. /* XXX need to do MUCH better error mapping than this. */
  1149. crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
  1150. if (rv == SECSuccess && context->doPad) {
  1151. CK_ULONG padding = pData[outlen - 1];
  1152. if (padding > context->blockSize || !padding) {
  1153. crv = CKR_ENCRYPTED_DATA_INVALID;
  1154. } else
  1155. outlen -= padding;
  1156. }
  1157. *pulDataLen = (CK_ULONG) outlen;
  1158. sftk_TerminateOp( session, SFTK_DECRYPT, context );
  1159. finish:
  1160. sftk_FreeSession(session);
  1161. return crv;
  1162. }
  1163. /*
  1164. ************** Crypto Functions: Digest (HASH) ************************
  1165. */
  1166. /* NSC_DigestInit initializes a message-digesting operation. */
  1167. CK_RV NSC_DigestInit(CK_SESSION_HANDLE hSession,
  1168. CK_MECHANISM_PTR pMechanism)
  1169. {
  1170. SFTKSession *session;
  1171. SFTKSessionContext *context;
  1172. CK_RV crv = CKR_OK;
  1173. CHECK_FORK();
  1174. session = sftk_SessionFromHandle(hSession);
  1175. if (session == NULL)
  1176. return CKR_SESSION_HANDLE_INVALID;
  1177. crv = sftk_InitGeneric(session,&context,SFTK_HASH,NULL,0,NULL, 0, 0);
  1178. if (crv != CKR_OK) {
  1179. sftk_FreeSession(session);
  1180. return crv;
  1181. }
  1182. #define INIT_MECH(mech,mmm) \
  1183. case mech: { \
  1184. mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
  1185. context->cipherInfo = (void *)mmm ## _ctx; \
  1186. context->cipherInfoLen = mmm ## _FlattenSize(mmm ## _ctx); \
  1187. context->currentMech = mech; \
  1188. context->hashUpdate = (SFTKHash) mmm ## _Update; \
  1189. context->end = (SFTKEnd) mmm ## _End; \
  1190. context->destroy = (SFTKDestroy) mmm ## _DestroyContext; \
  1191. context->maxLen = mmm ## _LENGTH; \
  1192. if (mmm ## _ctx) \
  1193. mmm ## _Begin(mmm ## _ctx); \
  1194. else \
  1195. crv = CKR_HOST_MEMORY; \
  1196. break; \
  1197. }
  1198. switch(pMechanism->mechanism) {
  1199. INIT_MECH(CKM_MD2, MD2)
  1200. INIT_MECH(CKM_MD5, MD5)
  1201. INIT_MECH(CKM_SHA_1, SHA1)
  1202. INIT_MECH(CKM_SHA224, SHA224)
  1203. INIT_MECH(CKM_SHA256, SHA256)
  1204. INIT_MECH(CKM_SHA384, SHA384)
  1205. INIT_MECH(CKM_SHA512, SHA512)
  1206. default:
  1207. crv = CKR_MECHANISM_INVALID;
  1208. break;
  1209. }
  1210. if (crv != CKR_OK) {
  1211. sftk_FreeContext(context);
  1212. sftk_FreeSession(session);
  1213. return crv;
  1214. }
  1215. sftk_SetContextByType(session, SFTK_HASH, context);
  1216. sftk_FreeSession(session);
  1217. return CKR_OK;
  1218. }
  1219. /* NSC_Digest digests data in a single part. */
  1220. CK_RV NSC_Digest(CK_SESSION_HANDLE hSession,
  1221. CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest,
  1222. CK_ULONG_PTR pulDigestLen)
  1223. {
  1224. SFTKSession *session;
  1225. SFTKSessionContext *context;
  1226. unsigned int digestLen;
  1227. unsigned int maxout = *pulDigestLen;
  1228. CK_RV crv;
  1229. CHECK_FORK();
  1230. /* make sure we're legal */
  1231. crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_FALSE,&session);
  1232. if (crv != CKR_OK) return crv;
  1233. if (pDigest == NULL) {
  1234. *pulDigestLen = context->maxLen;
  1235. goto finish;
  1236. }
  1237. /* do it: */
  1238. (*context->hashUpdate)(context->cipherInfo, pData, ulDataLen);
  1239. /* NOTE: this assumes buf size is bigenough for the algorithm */
  1240. (*context->end)(context->cipherInfo, pDigest, &digestLen,maxout);
  1241. *pulDigestLen = digestLen;
  1242. sftk_TerminateOp( session, SFTK_HASH, context );
  1243. finish:
  1244. sftk_FreeSession(session);
  1245. return CKR_OK;
  1246. }
  1247. /* NSC_DigestUpdate continues a multiple-part message-digesting operation. */
  1248. CK_RV NSC_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,
  1249. CK_ULONG ulPartLen)
  1250. {
  1251. SFTKSessionContext *context;
  1252. CK_RV crv;
  1253. CHECK_FORK();
  1254. /* make sure we're legal */
  1255. crv = sftk_GetContext(hSession,&context,SFTK_HASH,PR_TRUE,NULL);
  1256. if (crv != CKR_OK) return crv;
  1257. /* do it: */
  1258. (*context->hashUpdate)(context->cipherInfo, pPart, ulPartLen);
  1259. return CKR_OK;
  1260. }
  1261. /* NSC_DigestFinal finishes a multiple-part message-digesting operation. */
  1262. CK_RV NSC_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,
  1263. CK_ULONG_PTR pulDigestLen)
  1264. {
  1265. SFTKSession *session;
  1266. SFTKSessionContext *context;
  1267. unsigned int maxout = *pulDigestLen;
  1268. unsigned int digestLen;
  1269. CK_RV crv;
  1270. CHECK_FORK();
  1271. /* make sure we're legal */
  1272. crv = sftk_GetContext(hSession, &context, SFTK_HASH, PR_TRUE, &session);
  1273. if (crv != CKR_OK) return crv;
  1274. if (pDigest != NULL) {
  1275. (*context->end)(context->cipherInfo, pDigest, &digestLen, maxout);
  1276. *pulDigestLen = digestLen;
  1277. sftk_TerminateOp( session, SFTK_HASH, context );
  1278. } else {
  1279. *pulDigestLen = context->maxLen;
  1280. }
  1281. sftk_FreeSession(session);
  1282. return CKR_OK;
  1283. }
  1284. /*
  1285. * these helper functions are used by Generic Macing and Signing functions
  1286. * that use hashes as part of their operations.
  1287. */
  1288. #define DOSUB(mmm) \
  1289. static CK_RV \
  1290. sftk_doSub ## mmm(SFTKSessionContext *context) { \
  1291. mmm ## Context * mmm ## _ctx = mmm ## _NewContext(); \
  1292. context->hashInfo = (void *) mmm ## _ctx; \
  1293. context->hashUpdate = (SFTKHash) mmm ## _Update; \
  1294. context->end = (SFTKEnd) mmm ## _End; \
  1295. context->hashdestroy = (SFTKDestroy) mmm ## _DestroyContext; \
  1296. if (!context->hashInfo) { \
  1297. return CKR_HOST_MEMORY; \
  1298. } \
  1299. mmm ## _Begin( mmm ## _ctx ); \
  1300. return CKR_OK; \
  1301. }
  1302. DOSUB(MD2)
  1303. DOSUB(MD5)
  1304. DOSUB(SHA1)
  1305. DOSUB(SHA224)
  1306. DOSUB(SHA256)
  1307. DOSUB(SHA384)
  1308. DOSUB(SHA512)
  1309. /*
  1310. * HMAC General copies only a portion of the result. This update routine likes
  1311. * the final HMAC output with the signature.
  1312. */
  1313. static SECStatus
  1314. sftk_HMACCopy(CK_ULONG *copyLen,unsigned char *sig,unsigned int *sigLen,
  1315. unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
  1316. {
  1317. if (maxLen < *copyLen) return SECFailure;
  1318. PORT_Memcpy(sig,hash,*copyLen);
  1319. *sigLen = *copyLen;
  1320. return SECSuccess;
  1321. }
  1322. /* Verify is just a compare for HMAC */
  1323. static SECStatus
  1324. sftk_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen,
  1325. unsigned char *hash, unsigned int hashLen)
  1326. {
  1327. return (PORT_Memcmp(sig,hash,*copyLen) == 0) ? SECSuccess : SECFailure ;
  1328. }
  1329. /*
  1330. * common HMAC initalization routine
  1331. */
  1332. static CK_RV
  1333. sftk_doHMACInit(SFTKSessionContext *context,HASH_HashType hash,
  1334. SFTKObject *key, CK_ULONG mac_size)
  1335. {
  1336. SFTKAttribute *keyval;
  1337. HMACContext *HMACcontext;
  1338. CK_ULONG *intpointer;
  1339. const SECHashObject *hashObj = HASH_GetRawHashObject(hash);
  1340. PRBool isFIPS = (key->slot->slotID == FIPS_SLOT_ID);
  1341. /* required by FIPS 198 Section 4 */
  1342. if (isFIPS && (mac_size < 4 || mac_size < hashObj->length/2)) {
  1343. return CKR_BUFFER_TOO_SMALL;
  1344. }
  1345. keyval = sftk_FindAttribute(key,CKA_VALUE);
  1346. if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
  1347. HMACcontext = HMAC_Create(hashObj,
  1348. (const unsigned char*)keyval->attrib.pValue,
  1349. keyval->attrib.ulValueLen, isFIPS);
  1350. context->hashInfo = HMACcontext;
  1351. context->multi = PR_TRUE;
  1352. sftk_FreeAttribute(keyval);
  1353. if (context->hashInfo == NULL) {
  1354. if (PORT_GetError() == SEC_ERROR_INVALID_ARGS) {
  1355. return CKR_KEY_SIZE_RANGE;
  1356. }
  1357. return CKR_HOST_MEMORY;
  1358. }
  1359. context->hashUpdate = (SFTKHash) HMAC_Update;
  1360. context->end = (SFTKEnd) HMAC_Finish;
  1361. context->hashdestroy = (SFTKDestroy) HMAC_Destroy;
  1362. intpointer = (CK_ULONG *) PORT_Alloc(sizeof(CK_ULONG));
  1363. if (intpointer == NULL) {
  1364. return CKR_HOST_MEMORY;
  1365. }
  1366. *intpointer = mac_size;
  1367. context->cipherInfo = (void *) intpointer;
  1368. context->destroy = (SFTKDestroy) sftk_Space;
  1369. context->update = (SFTKCipher) sftk_HMACCopy;
  1370. context->verify = (SFTKVerify) sftk_HMACCmp;
  1371. context->maxLen = hashObj->length;
  1372. HMAC_Begin(HMACcontext);
  1373. return CKR_OK;
  1374. }
  1375. /*
  1376. * SSL Macing support. SSL Macs are inited, then update with the base
  1377. * hashing algorithm, then finalized in sign and verify
  1378. */
  1379. /*
  1380. * FROM SSL:
  1381. * 60 bytes is 3 times the maximum length MAC size that is supported.
  1382. * We probably should have one copy of this table. We still need this table
  1383. * in ssl to 'sign' the handshake hashes.
  1384. */
  1385. static unsigned char ssl_pad_1 [60] = {
  1386. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1387. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1388. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1389. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1390. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1391. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1392. 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
  1393. 0x36, 0x36, 0x36, 0x36
  1394. };
  1395. static unsigned char ssl_pad_2 [60] = {
  1396. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1397. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1398. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1399. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1400. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1401. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1402. 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
  1403. 0x5c, 0x5c, 0x5c, 0x5c
  1404. };
  1405. static SECStatus
  1406. sftk_SSLMACSign(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int *sigLen,
  1407. unsigned int maxLen,unsigned char *hash, unsigned int hashLen)
  1408. {
  1409. unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
  1410. unsigned int out;
  1411. info->begin(info->hashContext);
  1412. info->update(info->hashContext,info->key,info->keySize);
  1413. info->update(info->hashContext,ssl_pad_2,info->padSize);
  1414. info->update(info->hashContext,hash,hashLen);
  1415. info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
  1416. PORT_Memcpy(sig,tmpBuf,info->macSize);
  1417. *sigLen = info->macSize;
  1418. return SECSuccess;
  1419. }
  1420. static SECStatus
  1421. sftk_SSLMACVerify(SFTKSSLMACInfo *info,unsigned char *sig,unsigned int sigLen,
  1422. unsigned char *hash, unsigned int hashLen)
  1423. {
  1424. unsigned char tmpBuf[SFTK_MAX_MAC_LENGTH];
  1425. unsigned int out;
  1426. info->begin(info->hashContext);
  1427. info->update(info->hashContext,info->key,info->keySize);
  1428. info->update(info->hashContext,ssl_pad_2,info->padSize);
  1429. info->update(info->hashContext,hash,hashLen);
  1430. info->end(info->hashContext,tmpBuf,&out,SFTK_MAX_MAC_LENGTH);
  1431. return (PORT_Memcmp(sig,tmpBuf,info->macSize) == 0) ?
  1432. SECSuccess : SECFailure;
  1433. }
  1434. /*
  1435. * common HMAC initalization routine
  1436. */
  1437. static CK_RV
  1438. sftk_doSSLMACInit(SFTKSessionContext *context,SECOidTag oid,
  1439. SFTKObject *key, CK_ULONG mac_size)
  1440. {
  1441. SFTKAttribute *keyval;
  1442. SFTKBegin begin;
  1443. int padSize;
  1444. SFTKSSLMACInfo *sslmacinfo;
  1445. CK_RV crv = CKR_MECHANISM_INVALID;
  1446. if (oid == SEC_OID_SHA1) {
  1447. crv = sftk_doSubSHA1(context);
  1448. if (crv != CKR_OK) return crv;
  1449. begin = (SFTKBegin) SHA1_Begin;
  1450. padSize = 40;
  1451. } else {
  1452. crv = sftk_doSubMD5(context);
  1453. if (crv != CKR_OK) return crv;
  1454. begin = (SFTKBegin) MD5_Begin;
  1455. padSize = 48;
  1456. }
  1457. context->multi = PR_TRUE;
  1458. keyval = sftk_FindAttribute(key,CKA_VALUE);
  1459. if (keyval == NULL) return CKR_KEY_SIZE_RANGE;
  1460. context->hashUpdate(context->hashInfo,keyval->attrib.pValue,
  1461. keyval->attrib.ulValueLen);
  1462. context->hashUpdate(context->hashInfo,ssl_pad_1,padSize);
  1463. sslmacinfo = (SFTKSSLMACInfo *) PORT_Alloc(sizeof(SFTKSSLMACInfo));
  1464. if (sslmacinfo == NULL) {
  1465. sftk_FreeAttribute(keyval);
  1466. return CKR_HOST_MEMORY;
  1467. }
  1468. sslmacinfo->macSize = mac_size;
  1469. sslmacinfo->hashContext = context->hashInfo;
  1470. PORT_Memcpy(sslmacinfo->key,keyval->attrib.pValue,
  1471. keyval->attrib.ulValueLen);
  1472. sslmacinfo->keySize = keyval->attrib.ulValueLen;
  1473. sslmacinfo->begin = begin;
  1474. sslmacinfo->end = context->end;
  1475. sslmacinfo->update = context->hashUpdate;
  1476. sslmacinfo->padSize = padSize;
  1477. sftk_FreeAttribute(keyval);
  1478. context->cipherInfo = (void *) sslmacinfo;
  1479. context->destroy = (SFTKDestroy) sftk_Space;
  1480. context->update = (SFTKCipher) sftk_SSLMACSign;
  1481. context->verify = (SFTKVerify) sftk_SSLMACVerify;
  1482. context->maxLen = mac_size;
  1483. return CKR_OK;
  1484. }
  1485. /*
  1486. ************** Crypto Functions: Sign ************************
  1487. */
  1488. /**
  1489. * Check if We're using CBCMacing and initialize the session context if we are.
  1490. * @param contextType SFTK_SIGN or SFTK_VERIFY
  1491. * @param keyUsage check whether key allows this usage
  1492. */
  1493. static CK_RV
  1494. sftk_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
  1495. CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE keyUsage,
  1496. SFTKContextType contextType)
  1497. {
  1498. CK_MECHANISM cbc_mechanism;
  1499. CK_ULONG mac_bytes = SFTK_INVALID_MAC_SIZE;
  1500. CK_RC2_CBC_PARAMS rc2_params;
  1501. #if NSS_SOFTOKEN_DOES_RC5
  1502. CK_RC5_CBC_PARAMS rc5_params;
  1503. CK_RC5_MAC_GENERAL_PARAMS *rc5_mac;
  1504. #endif
  1505. unsigned char ivBlock[SFTK_MAX_BLOCK_SIZE];
  1506. SFTKSessionContext *context;
  1507. CK_RV crv;
  1508. unsigned int blockSize;
  1509. switch (pMechanism->mechanism) {
  1510. case CKM_RC2_MAC_GENERAL:
  1511. mac_bytes =
  1512. ((CK_RC2_MAC_GENERAL_PARAMS *)pMechanism->pParameter)->ulMacLength;
  1513. /* fall through */
  1514. case CKM_RC2_MAC:
  1515. /* this works because ulEffectiveBits is in t…