security/nss/lib/smime/cmsdigest.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * CMS digesting.
     7  */
     9 #include "cmslocal.h"
    11 #include "cert.h"
    12 #include "key.h"
    13 #include "secitem.h"
    14 #include "secoid.h"
    15 #include "pk11func.h"
    16 #include "prtime.h"
    17 #include "secerr.h"
    19 /*  #define CMS_FIND_LEAK_MULTIPLE 1 */
    20 #ifdef CMS_FIND_LEAK_MULTIPLE
    21 static int stop_on_err = 1;
    22 static int global_num_digests = 0;
    23 #endif
    25 struct digestPairStr { 
    26     const SECHashObject * digobj;
    27     void *                digcx;
    28 };
    29 typedef struct digestPairStr digestPair;
    31 struct NSSCMSDigestContextStr {
    32     PRBool		saw_contents;
    33     PLArenaPool *       pool;
    34     int			digcnt;
    35     digestPair  *       digPairs;
    36 };
    39 /*
    40  * NSS_CMSDigestContext_StartMultiple - start digest calculation using all the
    41  *  digest algorithms in "digestalgs" in parallel.
    42  */
    43 NSSCMSDigestContext *
    44 NSS_CMSDigestContext_StartMultiple(SECAlgorithmID **digestalgs)
    45 {
    46     PLArenaPool *        pool;
    47     NSSCMSDigestContext *cmsdigcx;
    48     int digcnt;
    49     int i;
    51 #ifdef CMS_FIND_LEAK_MULTIPLE
    52     PORT_Assert(global_num_digests == 0 || !stop_on_err);
    53 #endif
    55     digcnt = (digestalgs == NULL) ? 0 : NSS_CMSArray_Count((void **)digestalgs);
    56     /* It's OK if digcnt is zero.  We have to allow this for "certs only"
    57     ** messages.
    58     */
    59     pool = PORT_NewArena(2048);
    60     if (!pool)
    61     	return NULL;
    63     cmsdigcx = PORT_ArenaNew(pool, NSSCMSDigestContext);
    64     if (cmsdigcx == NULL)
    65 	goto loser;
    67     cmsdigcx->saw_contents = PR_FALSE;
    68     cmsdigcx->pool   = pool;
    69     cmsdigcx->digcnt = digcnt;
    71     cmsdigcx->digPairs = PORT_ArenaZNewArray(pool, digestPair, digcnt);
    72     if (cmsdigcx->digPairs == NULL) {
    73 	goto loser;
    74     }
    76     /*
    77      * Create a digest object context for each algorithm.
    78      */
    79     for (i = 0; i < digcnt; i++) {
    80 	const SECHashObject *digobj;
    81 	void *digcx;
    83 	digobj = NSS_CMSUtil_GetHashObjByAlgID(digestalgs[i]);
    84 	/*
    85 	 * Skip any algorithm we do not even recognize; obviously,
    86 	 * this could be a problem, but if it is critical then the
    87 	 * result will just be that the signature does not verify.
    88 	 * We do not necessarily want to error out here, because
    89 	 * the particular algorithm may not actually be important,
    90 	 * but we cannot know that until later.
    91 	 */
    92 	if (digobj == NULL)
    93 	    continue;
    95 	digcx = (*digobj->create)();
    96 	if (digcx != NULL) {
    97 	    (*digobj->begin) (digcx);
    98 	    cmsdigcx->digPairs[i].digobj = digobj;
    99 	    cmsdigcx->digPairs[i].digcx  = digcx;
   100 #ifdef CMS_FIND_LEAK_MULTIPLE
   101 	    global_num_digests++;
   102 #endif
   103 	}
   104     }
   105     return cmsdigcx;
   107 loser:
   108     /* no digest objects have been created, or need to be destroyed. */
   109     if (pool) {
   110     	PORT_FreeArena(pool, PR_FALSE);
   111     }
   112     return NULL;
   113 }
   115 /*
   116  * NSS_CMSDigestContext_StartSingle - same as 
   117  * NSS_CMSDigestContext_StartMultiple, but only one algorithm.
   118  */
   119 NSSCMSDigestContext *
   120 NSS_CMSDigestContext_StartSingle(SECAlgorithmID *digestalg)
   121 {
   122     SECAlgorithmID *digestalgs[] = { NULL, NULL };		/* fake array */
   124     digestalgs[0] = digestalg;
   125     return NSS_CMSDigestContext_StartMultiple(digestalgs);
   126 }
   128 /*
   129  * NSS_CMSDigestContext_Update - feed more data into the digest machine
   130  */
   131 void
   132 NSS_CMSDigestContext_Update(NSSCMSDigestContext *cmsdigcx, 
   133                             const unsigned char *data, int len)
   134 {
   135     int i;
   136     digestPair *pair = cmsdigcx->digPairs;
   138     cmsdigcx->saw_contents = PR_TRUE;
   140     for (i = 0; i < cmsdigcx->digcnt; i++, pair++) {
   141 	if (pair->digcx) {
   142 	    (*pair->digobj->update)(pair->digcx, data, len);
   143     	}
   144     }
   145 }
   147 /*
   148  * NSS_CMSDigestContext_Cancel - cancel digesting operation
   149  */
   150 void
   151 NSS_CMSDigestContext_Cancel(NSSCMSDigestContext *cmsdigcx)
   152 {
   153     int i;
   154     digestPair *pair = cmsdigcx->digPairs;
   156     for (i = 0; i < cmsdigcx->digcnt; i++, pair++) {
   157 	if (pair->digcx) {
   158 	    (*pair->digobj->destroy)(pair->digcx, PR_TRUE);
   159 #ifdef CMS_FIND_LEAK_MULTIPLE
   160 	    --global_num_digests;
   161 #endif
   162     	}
   163     }
   164 #ifdef CMS_FIND_LEAK_MULTIPLE
   165     PORT_Assert(global_num_digests == 0 || !stop_on_err);
   166 #endif
   167     PORT_FreeArena(cmsdigcx->pool, PR_FALSE);
   168 }
   170 /*
   171  * NSS_CMSDigestContext_FinishMultiple - finish the digests and put them
   172  *  into an array of SECItems (allocated on poolp)
   173  */
   174 SECStatus
   175 NSS_CMSDigestContext_FinishMultiple(NSSCMSDigestContext *cmsdigcx, 
   176                                     PLArenaPool *poolp,
   177 			            SECItem ***digestsp)
   178 {
   179     SECItem **  digests = NULL;
   180     digestPair *pair;
   181     void *      mark;
   182     int         i;
   183     SECStatus   rv;
   185     /* no contents? do not finish digests */
   186     if (digestsp == NULL || !cmsdigcx->saw_contents) {
   187 	rv = SECSuccess;
   188 	goto cleanup;
   189     }
   191     mark = PORT_ArenaMark (poolp);
   193     /* allocate digest array & SECItems on arena */
   194     digests = PORT_ArenaNewArray( poolp, SECItem *, cmsdigcx->digcnt + 1);
   196     rv = ((digests == NULL) ? SECFailure : SECSuccess);
   197     pair = cmsdigcx->digPairs;
   198     for (i = 0; rv == SECSuccess && i < cmsdigcx->digcnt; i++, pair++) {
   199 	SECItem digest;
   200 	unsigned char hash[HASH_LENGTH_MAX];
   202 	if (!pair->digcx) {
   203 	    digests[i] = NULL;
   204 	    continue;
   205 	}
   207 	digest.type = siBuffer;
   208 	digest.data = hash;
   209 	digest.len  = pair->digobj->length;
   210 	(* pair->digobj->end)(pair->digcx, hash, &digest.len, digest.len);
   211 	digests[i] = SECITEM_ArenaDupItem(poolp, &digest);
   212 	if (!digests[i]) {
   213 	    rv = SECFailure;
   214 	}
   215     }
   216     digests[i] = NULL;
   217     if (rv == SECSuccess) {
   218 	PORT_ArenaUnmark(poolp, mark);
   219     } else
   220 	PORT_ArenaRelease(poolp, mark);
   222 cleanup:
   223     NSS_CMSDigestContext_Cancel(cmsdigcx);
   224     /* Don't change the caller's digests pointer if we have no digests.
   225     **  NSS_CMSSignedData_Encode_AfterData depends on this behavior.
   226     */
   227     if (rv == SECSuccess && digestsp && digests) {
   228 	*digestsp = digests;
   229     }
   230     return rv;
   231 }
   233 /*
   234  * NSS_CMSDigestContext_FinishSingle - same as 
   235  * NSS_CMSDigestContext_FinishMultiple, but for one digest.
   236  */
   237 SECStatus
   238 NSS_CMSDigestContext_FinishSingle(NSSCMSDigestContext *cmsdigcx, 
   239                                   PLArenaPool *poolp,
   240 			          SECItem *digest)
   241 {
   242     SECStatus rv = SECFailure;
   243     SECItem **dp;
   244     PLArenaPool *arena = NULL;
   246     if ((arena = PORT_NewArena(1024)) == NULL)
   247 	goto loser;
   249     /* get the digests into arena, then copy the first digest into poolp */
   250     rv = NSS_CMSDigestContext_FinishMultiple(cmsdigcx, arena, &dp);
   251     if (rv == SECSuccess) {
   252 	/* now copy it into poolp */
   253 	rv = SECITEM_CopyItem(poolp, digest, dp[0]);
   254     }
   255 loser:
   256     if (arena)
   257 	PORT_FreeArena(arena, PR_FALSE);
   259     return rv;
   260 }

mercurial