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

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.  * CMS digesting.
  35.  *
  36.  * $Id: cmsdigest.c,v 1.2 2000/06/13 21:56:28 chrisk%netscape.com Exp $
  37.  */
  38. #include "cmslocal.h"
  39. #include "cert.h"
  40. #include "key.h"
  41. #include "secitem.h"
  42. #include "secoid.h"
  43. #include "pk11func.h"
  44. #include "prtime.h"
  45. #include "secerr.h"
  46. struct NSSCMSDigestContextStr {
  47.     PRBool saw_contents;
  48.     int digcnt;
  49.     void ** digcxs;
  50.     SECHashObject ** digobjs;
  51. };
  52. /*
  53.  * NSS_CMSDigestContext_StartMultiple - start digest calculation using all the
  54.  *  digest algorithms in "digestalgs" in parallel.
  55.  */
  56. NSSCMSDigestContext *
  57. NSS_CMSDigestContext_StartMultiple(SECAlgorithmID **digestalgs)
  58. {
  59.     NSSCMSDigestContext *cmsdigcx;
  60.     SECHashObject *digobj;
  61.     void *digcx;
  62.     int digcnt;
  63.     int i;
  64.     digcnt = (digestalgs == NULL) ? 0 : NSS_CMSArray_Count((void **)digestalgs);
  65.     cmsdigcx = (NSSCMSDigestContext *)PORT_Alloc(sizeof(NSSCMSDigestContext));
  66.     if (cmsdigcx == NULL)
  67. return NULL;
  68.     if (digcnt > 0) {
  69. cmsdigcx->digcxs = (void **)PORT_Alloc(digcnt * sizeof (void *));
  70. cmsdigcx->digobjs = (SECHashObject **)PORT_Alloc(digcnt * sizeof(SECHashObject *));
  71. if (cmsdigcx->digcxs == NULL || cmsdigcx->digobjs == NULL)
  72.     goto loser;
  73.     }
  74.     cmsdigcx->digcnt = 0;
  75.     /*
  76.      * Create a digest object context for each algorithm.
  77.      */
  78.     for (i = 0; i < digcnt; i++) {
  79. digobj = NSS_CMSUtil_GetHashObjByAlgID(digestalgs[i]);
  80. /*
  81.  * Skip any algorithm we do not even recognize; obviously,
  82.  * this could be a problem, but if it is critical then the
  83.  * result will just be that the signature does not verify.
  84.  * We do not necessarily want to error out here, because
  85.  * the particular algorithm may not actually be important,
  86.  * but we cannot know that until later.
  87.  */
  88. if (digobj == NULL)
  89.     continue;
  90. digcx = (*digobj->create)();
  91. if (digcx != NULL) {
  92.     (*digobj->begin) (digcx);
  93.     cmsdigcx->digobjs[cmsdigcx->digcnt] = digobj;
  94.     cmsdigcx->digcxs[cmsdigcx->digcnt] = digcx;
  95.     cmsdigcx->digcnt++;
  96. }
  97.     }
  98.     cmsdigcx->saw_contents = PR_FALSE;
  99.     return cmsdigcx;
  100. loser:
  101.     if (cmsdigcx) {
  102. if (cmsdigcx->digobjs)
  103.     PORT_Free(cmsdigcx->digobjs);
  104. if (cmsdigcx->digcxs)
  105.     PORT_Free(cmsdigcx->digcxs);
  106.     }
  107.     return NULL;
  108. }
  109. /*
  110.  * NSS_CMSDigestContext_StartSingle - same as NSS_CMSDigestContext_StartMultiple, but
  111.  *  only one algorithm.
  112.  */
  113. NSSCMSDigestContext *
  114. NSS_CMSDigestContext_StartSingle(SECAlgorithmID *digestalg)
  115. {
  116.     SECAlgorithmID *digestalgs[] = { NULL, NULL }; /* fake array */
  117.     digestalgs[0] = digestalg;
  118.     return NSS_CMSDigestContext_StartMultiple(digestalgs);
  119. }
  120. /*
  121.  * NSS_CMSDigestContext_Update - feed more data into the digest machine
  122.  */
  123. void
  124. NSS_CMSDigestContext_Update(NSSCMSDigestContext *cmsdigcx, const unsigned char *data, int len)
  125. {
  126.     int i;
  127.     cmsdigcx->saw_contents = PR_TRUE;
  128.     for (i = 0; i < cmsdigcx->digcnt; i++)
  129. (*cmsdigcx->digobjs[i]->update)(cmsdigcx->digcxs[i], data, len);
  130. }
  131. /*
  132.  * NSS_CMSDigestContext_Cancel - cancel digesting operation
  133.  */
  134. void
  135. NSS_CMSDigestContext_Cancel(NSSCMSDigestContext *cmsdigcx)
  136. {
  137.     int i;
  138.     for (i = 0; i < cmsdigcx->digcnt; i++)
  139. (*cmsdigcx->digobjs[i]->destroy)(cmsdigcx->digcxs[i], PR_TRUE);
  140. }
  141. /*
  142.  * NSS_CMSDigestContext_FinishMultiple - finish the digests and put them
  143.  *  into an array of SECItems (allocated on poolp)
  144.  */
  145. SECStatus
  146. NSS_CMSDigestContext_FinishMultiple(NSSCMSDigestContext *cmsdigcx, PLArenaPool *poolp,
  147.     SECItem ***digestsp)
  148. {
  149.     SECHashObject *digobj;
  150.     void *digcx;
  151.     SECItem **digests, *digest;
  152.     int i;
  153.     void *mark;
  154.     SECStatus rv = SECFailure;
  155.     /* no contents? do not update digests */
  156.     if (digestsp == NULL || !cmsdigcx->saw_contents) {
  157. for (i = 0; i < cmsdigcx->digcnt; i++)
  158.     (*cmsdigcx->digobjs[i]->destroy)(cmsdigcx->digcxs[i], PR_TRUE);
  159. rv = SECSuccess;
  160. goto cleanup;
  161.     }
  162.     mark = PORT_ArenaMark (poolp);
  163.     /* allocate digest array & SECItems on arena */
  164.     digests = (SECItem **)PORT_ArenaAlloc(poolp, (cmsdigcx->digcnt+1) * sizeof(SECItem *));
  165.     digest = (SECItem *)PORT_ArenaZAlloc(poolp, cmsdigcx->digcnt * sizeof(SECItem));
  166.     if (digests == NULL || digest == NULL) {
  167. goto loser;
  168.     }
  169.     for (i = 0; i < cmsdigcx->digcnt; i++, digest++) {
  170. digcx = cmsdigcx->digcxs[i];
  171. digobj = cmsdigcx->digobjs[i];
  172. digest->data = (unsigned char*)PORT_ArenaAlloc(poolp, digobj->length);
  173. if (digest->data == NULL)
  174.     goto loser;
  175. digest->len = digobj->length;
  176. (* digobj->end)(digcx, digest->data, &(digest->len), digest->len);
  177. digests[i] = digest;
  178. (* digobj->destroy)(digcx, PR_TRUE);
  179.     }
  180.     digests[i] = NULL;
  181.     *digestsp = digests;
  182.     rv = SECSuccess;
  183. loser:
  184.     if (rv == SECSuccess)
  185. PORT_ArenaUnmark(poolp, mark);
  186.     else
  187. PORT_ArenaRelease(poolp, mark);
  188. cleanup:
  189.     if (cmsdigcx->digcnt > 0) {
  190. PORT_Free(cmsdigcx->digcxs);
  191. PORT_Free(cmsdigcx->digobjs);
  192.     }
  193.     PORT_Free(cmsdigcx);
  194.     return rv;
  195. }
  196. /*
  197.  * NSS_CMSDigestContext_FinishSingle - same as NSS_CMSDigestContext_FinishMultiple,
  198.  *  but for one digest.
  199.  */
  200. SECStatus
  201. NSS_CMSDigestContext_FinishSingle(NSSCMSDigestContext *cmsdigcx, PLArenaPool *poolp,
  202.     SECItem *digest)
  203. {
  204.     SECStatus rv = SECFailure;
  205.     SECItem **dp;
  206.     PLArenaPool *arena = NULL;
  207.     if ((arena = PORT_NewArena(1024)) == NULL)
  208. goto loser;
  209.     /* get the digests into arena, then copy the first digest into poolp */
  210.     if (NSS_CMSDigestContext_FinishMultiple(cmsdigcx, arena, &dp) != SECSuccess)
  211. goto loser;
  212.     /* now copy it into poolp */
  213.     if (SECITEM_CopyItem(poolp, digest, dp[0]) != SECSuccess)
  214. goto loser;
  215.     rv = SECSuccess;
  216. loser:
  217.     if (arena)
  218. PORT_FreeArena(arena, PR_FALSE);
  219.     return rv;
  220. }