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

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.  *   thayes@netscape.com
  21.  * 
  22.  * Alternatively, the contents of this file may be used under the
  23.  * terms of the GNU General Public License Version 2 or later (the
  24.  * "GPL"), in which case the provisions of the GPL are applicable 
  25.  * instead of those above.  If you wish to allow use of your 
  26.  * version of this file only under the terms of the GPL and not to
  27.  * allow others to use your version of this file under the MPL,
  28.  * indicate your decision by deleting the provisions above and
  29.  * replace them with the notice and other provisions required by
  30.  * the GPL.  If you do not delete the provisions above, a recipient
  31.  * may use your version of this file under either the MPL or the
  32.  * GPL.
  33.  *
  34.  * PKCS #11 Wrapper functions which handles authenticating to the card's
  35.  * choosing the best cards, etc.
  36.  */
  37. #include "seccomon.h"
  38. #include "secoid.h"
  39. #include "secasn1.h"
  40. #include "pkcs11.h"
  41. #include "pk11func.h"
  42. #include "pk11sdr.h"
  43. /*
  44.  * Data structure and template for encoding the result of an SDR operation
  45.  *  This is temporary.  It should include the algorithm ID of the encryption mechanism
  46.  */
  47. struct SDRResult
  48. {
  49.   SECItem keyid;
  50.   SECAlgorithmID alg;
  51.   SECItem data;
  52. };
  53. typedef struct SDRResult SDRResult;
  54. static SEC_ASN1Template template[] = {
  55.   { SEC_ASN1_SEQUENCE, 0, NULL, sizeof (SDRResult) },
  56.   { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) },
  57.   { SEC_ASN1_INLINE, offsetof(SDRResult, alg), SECOID_AlgorithmIDTemplate },
  58.   { SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) },
  59.   { 0 }
  60. };
  61. static unsigned char keyID[] = {
  62.   0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  63.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
  64. };
  65. static SECItem keyIDItem = {
  66.   0,
  67.   keyID,
  68.   sizeof keyID
  69. };
  70. /* local utility function for padding an incoming data block
  71.  * to the mechanism block size.
  72.  */
  73. static SECStatus
  74. padBlock(SECItem *data, int blockSize, SECItem *result)
  75. {
  76.   SECStatus rv = SECSuccess;
  77.   int padLength;
  78.   unsigned int i;
  79.   result->data = 0;
  80.   result->len = 0;
  81.   /* This algorithm always adds to the block (to indicate the number
  82.    * of pad bytes).  So allocate a block large enough.
  83.    */
  84.   padLength = blockSize - (data->len % blockSize);
  85.   result->len = data->len + padLength;
  86.   result->data = (unsigned char *)PORT_Alloc(result->len);
  87.   /* Copy the data */
  88.   PORT_Memcpy(result->data, data->data, data->len);
  89.   /* Add the pad values */
  90.   for(i = data->len; i < result->len; i++)
  91.     result->data[i] = (unsigned char)padLength;
  92.   return rv;
  93. }
  94. static SECStatus
  95. unpadBlock(SECItem *data, int blockSize, SECItem *result)
  96. {
  97.   SECStatus rv = SECSuccess;
  98.   int padLength;
  99.   result->data = 0;
  100.   result->len = 0;
  101.   /* Remove the padding from the end if the input data */
  102.   if (data->len == 0 || data->len % blockSize  != 0) { rv = SECFailure; goto loser; }
  103.   padLength = data->data[data->len-1];
  104.   if (padLength > blockSize) { rv = SECFailure; goto loser; }
  105.   result->len = data->len - padLength;
  106.   result->data = (unsigned char *)PORT_Alloc(result->len);
  107.   if (!result->data) { rv = SECFailure; goto loser; }
  108.   PORT_Memcpy(result->data, data->data, result->len);
  109. loser:
  110.   return rv;
  111. }
  112. /*
  113.  * PK11SDR_Encrypt
  114.  *  Encrypt a block of data using the symmetric key identified.  The result
  115.  *  is an ASN.1 (DER) encoded block of keyid, params and data.
  116.  */
  117. SECStatus
  118. PK11SDR_Encrypt(SECItem *keyid, SECItem *data, SECItem *result, void *cx)
  119. {
  120.   SECStatus rv = SECSuccess;
  121.   PK11SlotInfo *slot = 0;
  122.   PK11SymKey *key = 0;
  123.   SECItem *params = 0;
  124.   PK11Context *ctx = 0;
  125.   CK_MECHANISM_TYPE type;
  126.   SDRResult sdrResult;
  127.   SECItem paddedData;
  128.   SECItem *pKeyID;
  129.   PLArenaPool *arena = 0;
  130.   /* Initialize */
  131.   paddedData.len = 0;
  132.   paddedData.data = 0;
  133.   arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  134.   if (!arena) { rv = SECFailure; goto loser; }
  135.   /* 1. Locate the requested keyid, or the default key (which has a keyid)
  136.    * 2. Create an encryption context
  137.    * 3. Encrypt
  138.    * 4. Encode the results (using ASN.1)
  139.    */
  140.   slot = PK11_GetInternalKeySlot();
  141.   if (!slot) { rv = SECFailure; goto loser; }
  142.   /* Use triple-DES */
  143.   type = CKM_DES3_CBC;
  144.   /* Find the key to use */
  145.   pKeyID = keyid;
  146.   if (pKeyID->len == 0) {
  147.   pKeyID = &keyIDItem;  /* Use default value */
  148.   /* Try to find the key */
  149.   key = PK11_FindFixedKey(slot, type, pKeyID, cx);
  150.   
  151.   /* If the default key doesn't exist yet, try to create it */
  152.   if (!key) key = PK11_GenDES3TokenKey(slot, pKeyID, cx);
  153.   } else {
  154.   key = PK11_FindFixedKey(slot, type, pKeyID, cx);
  155.   }
  156.   if (!key) { rv = SECFailure; goto loser; }
  157.   params = PK11_GenerateNewParam(type, key);
  158.   if (!params) { rv = SECFailure; goto loser; }
  159.   ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params);
  160.   if (!ctx) { rv = SECFailure; goto loser; }
  161.   rv = padBlock(data, PK11_GetBlockSize(type, 0), &paddedData);
  162.   if (rv != SECSuccess) goto loser;
  163.   sdrResult.data.len = paddedData.len;
  164.   sdrResult.data.data = (unsigned char *)PORT_ArenaAlloc(arena, sdrResult.data.len);
  165.   rv = PK11_CipherOp(ctx, sdrResult.data.data, (int*)&sdrResult.data.len, sdrResult.data.len,
  166.                      paddedData.data, paddedData.len);
  167.   if (rv != SECSuccess) goto loser;
  168.   PK11_Finalize(ctx);
  169.   sdrResult.keyid = *pKeyID;
  170.   rv = PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg);
  171.   if (rv != SECSuccess) goto loser;
  172.   if (!SEC_ASN1EncodeItem(0, result, &sdrResult, template)) { rv = SECFailure; goto loser; }
  173. loser:
  174.   SECITEM_ZfreeItem(&paddedData, PR_FALSE);
  175.   if (arena) PORT_FreeArena(arena, PR_TRUE);
  176.   if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
  177.   if (params) SECITEM_ZfreeItem(params, PR_TRUE);
  178.   if (key) PK11_FreeSymKey(key);
  179.   if (slot) PK11_FreeSlot(slot);
  180.   return rv;
  181. }
  182. /*
  183.  * PK11SDR_Decrypt
  184.  *  Decrypt a block of data produced by PK11SDR_Encrypt.  The key used is identified
  185.  *  by the keyid field within the input.
  186.  */
  187. SECStatus
  188. PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx)
  189. {
  190.   SECStatus rv = SECSuccess;
  191.   PK11SlotInfo *slot = 0;
  192.   PK11SymKey *key = 0;
  193.   PK11Context *ctx = 0;
  194.   CK_MECHANISM_TYPE type;
  195.   SDRResult sdrResult;
  196.   SECItem *params = 0;
  197.   SECItem paddedResult;
  198.   PLArenaPool *arena = 0;
  199.   paddedResult.len = 0;
  200.   paddedResult.data = 0;
  201.   arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
  202.   if (!arena) { rv = SECFailure; goto loser; }
  203.   /* Decode the incoming data */
  204.   memset(&sdrResult, 0, sizeof sdrResult);
  205.   rv = SEC_ASN1DecodeItem(arena, &sdrResult, template, data);
  206.   if (rv != SECSuccess) goto loser;  /* Invalid format */
  207.   /* Find the slot and key for the given keyid */
  208.   slot = PK11_GetInternalKeySlot();
  209.   if (!slot) { rv = SECFailure; goto loser; }
  210.   /* Use triple-DES (Should look up the algorithm) */
  211.   type = CKM_DES3_CBC;
  212.   key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
  213.   if (!key) { rv = SECFailure; goto loser; }
  214.   /* Get the parameter values from the data */
  215.   params = PK11_ParamFromAlgid(&sdrResult.alg);
  216.   if (!params) { rv = SECFailure; goto loser; }
  217.   ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
  218.   if (!ctx) { rv = SECFailure; goto loser; }
  219.   paddedResult.len = sdrResult.data.len;
  220.   paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len);
  221.   rv = PK11_CipherOp(ctx, paddedResult.data, (int*)&paddedResult.len, paddedResult.len,
  222.                      sdrResult.data.data, sdrResult.data.len);
  223.   if (rv != SECSuccess) goto loser;
  224.   PK11_Finalize(ctx);
  225.   /* Remove the padding */
  226.   rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
  227.   if (rv) goto loser;
  228. loser:
  229.   /* SECITEM_ZfreeItem(&paddedResult, PR_FALSE); */
  230.   if (arena) PORT_FreeArena(arena, PR_TRUE);
  231.   if (ctx) PK11_DestroyContext(ctx, PR_TRUE);
  232.   if (key) PK11_FreeSymKey(key);
  233.   if (params) SECITEM_ZfreeItem(params, PR_TRUE);
  234.   if (slot) PK11_FreeSlot(slot);
  235.   return rv;
  236. }