security/nss/lib/jar/jarsign.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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  *  JARSIGN
     7  *
     8  *  Routines used in signing archives.
     9  */
    12 #include "jar.h"
    13 #include "jarint.h"
    14 #include "secpkcs7.h"
    15 #include "pk11func.h"
    16 #include "sechash.h"
    18 /* from libevent.h */
    19 typedef void (*ETVoidPtrFunc) (void * data);
    21 /* key database wrapper */
    22 /* static SECKEYKeyDBHandle *jar_open_key_database (void); */
    23 /* CHUNQ is our bite size */
    25 #define CHUNQ 64000
    26 #define FILECHUNQ 32768
    28 /*
    29  *  J A R _ c a l c u l a t e _ d i g e s t
    30  *
    31  *  Quick calculation of a digest for
    32  *  the specified block of memory. Will calculate
    33  *  for all supported algorithms, now MD5.
    34  *
    35  *  This version supports huge pointers for WIN16.
    36  *
    37  */
    38 JAR_Digest * PR_CALLBACK 
    39 JAR_calculate_digest(void *data, long length)
    40 {
    41     PK11Context *md5  = 0;
    42     PK11Context *sha1 = 0;
    43     JAR_Digest *dig   = PORT_ZNew(JAR_Digest);
    44     long chunq;
    45     unsigned int md5_length, sha1_length;
    47     if (dig == NULL) {
    48 	/* out of memory allocating digest */
    49 	return NULL;
    50     }
    52     md5  = PK11_CreateDigestContext(SEC_OID_MD5);
    53     sha1 = PK11_CreateDigestContext(SEC_OID_SHA1);
    55     if (length >= 0) {
    56 	PK11_DigestBegin (md5);
    57 	PK11_DigestBegin (sha1);
    59 	do {
    60 	    chunq = length;
    62 	    PK11_DigestOp(md5,  (unsigned char*)data, chunq);
    63 	    PK11_DigestOp(sha1, (unsigned char*)data, chunq);
    64 	    length -= chunq;
    65 	    data = ((char *) data + chunq);
    66 	}
    67 	while (length > 0);
    69 	PK11_DigestFinal (md5,	dig->md5,  &md5_length,  MD5_LENGTH);
    70 	PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
    72 	PK11_DestroyContext (md5,  PR_TRUE);
    73 	PK11_DestroyContext (sha1, PR_TRUE);
    74     }
    75     return dig;
    76 }
    78 /*
    79  *  J A R _ d i g e s t _ f i l e
    80  *
    81  *  Calculates the MD5 and SHA1 digests for a file
    82  *  present on disk, and returns these in JAR_Digest struct.
    83  *
    84  */
    85 int 
    86 JAR_digest_file (char *filename, JAR_Digest *dig)
    87 {
    88     JAR_FILE fp;
    89     PK11Context *md5 = 0;
    90     PK11Context *sha1 = 0;
    91     unsigned char *buf = (unsigned char *) PORT_ZAlloc (FILECHUNQ);
    92     int num;
    93     unsigned int md5_length, sha1_length;
    95     if (buf == NULL) {
    96 	/* out of memory */
    97 	return JAR_ERR_MEMORY;
    98     }
   100     if ((fp = JAR_FOPEN (filename, "rb")) == 0) {
   101 	/* perror (filename); FIX XXX XXX XXX XXX XXX XXX */
   102 	PORT_Free (buf);
   103 	return JAR_ERR_FNF;
   104     }
   106     md5 = PK11_CreateDigestContext (SEC_OID_MD5);
   107     sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
   109     if (md5 == NULL || sha1 == NULL) {
   110 	/* can't generate digest contexts */
   111 	PORT_Free (buf);
   112 	JAR_FCLOSE (fp);
   113 	return JAR_ERR_GENERAL;
   114     }
   116     PK11_DigestBegin (md5);
   117     PK11_DigestBegin (sha1);
   119     while (1) {
   120 	if ((num = JAR_FREAD (fp, buf, FILECHUNQ)) == 0)
   121 	    break;
   123 	PK11_DigestOp (md5, buf, num);
   124 	PK11_DigestOp (sha1, buf, num);
   125     }
   127     PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
   128     PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
   130     PK11_DestroyContext (md5, PR_TRUE);
   131     PK11_DestroyContext (sha1, PR_TRUE);
   133     PORT_Free (buf);
   134     JAR_FCLOSE (fp);
   136     return 0;
   137 }
   139 /*
   140  *  J A R _ o p e n _ k e y _ d a t a b a s e
   141  *
   142  */
   144 void* 
   145 jar_open_key_database(void)
   146 {
   147     return NULL;
   148 }
   150 int 
   151 jar_close_key_database(void *keydb)
   152 {
   153     /* We never do close it */
   154     return 0;
   155 }
   158 /*
   159  *  j a r _ c r e a t e _ p k 7
   160  *
   161  */
   163 static void jar_pk7_out (void *arg, const char *buf, unsigned long len)
   164 {
   165     JAR_FWRITE ((JAR_FILE) arg, buf, len);
   166 }
   168 int 
   169 jar_create_pk7(CERTCertDBHandle *certdb, void *keydb, CERTCertificate *cert, 
   170                char *password, JAR_FILE infp, JAR_FILE outfp)
   171 {
   172     SEC_PKCS7ContentInfo *cinfo;
   173     const SECHashObject *hashObj;
   174     char *errstring;
   175     void *mw = NULL;
   176     void *hashcx;
   177     unsigned int len;
   178     int status = 0;
   179     SECStatus rv;
   180     SECItem digest;
   181     unsigned char digestdata[32];
   182     unsigned char buffer[4096];
   184     if (outfp == NULL || infp == NULL || cert == NULL)
   185 	return JAR_ERR_GENERAL;
   187     /* we sign with SHA */
   188     hashObj = HASH_GetHashObject(HASH_AlgSHA1);
   190     hashcx = (* hashObj->create)();
   191     if (hashcx == NULL)
   192 	return JAR_ERR_GENERAL;
   194     (* hashObj->begin)(hashcx);
   195     while (1) {
   196 	int nb = JAR_FREAD(infp, buffer, sizeof buffer);
   197 	if (nb == 0) { /* eof */
   198 	    break;
   199 	}
   200 	(* hashObj->update) (hashcx, buffer, nb);
   201     }
   202     (* hashObj->end)(hashcx, digestdata, &len, 32);
   203     (* hashObj->destroy)(hashcx, PR_TRUE);
   205     digest.data = digestdata;
   206     digest.len = len;
   208     /* signtool must use any old context it can find since it's
   209 	 calling from inside javaland. */
   210     PORT_SetError (0);
   211     cinfo = SEC_PKCS7CreateSignedData(cert, certUsageObjectSigner, NULL,
   212                                       SEC_OID_SHA1, &digest, NULL, mw);
   213     if (cinfo == NULL)
   214 	return JAR_ERR_PK7;
   216     rv = SEC_PKCS7IncludeCertChain(cinfo, NULL);
   217     if (rv != SECSuccess) {
   218 	status = PORT_GetError();
   219 	SEC_PKCS7DestroyContentInfo(cinfo);
   220 	return status;
   221     }
   223     /* Having this here forces signtool to always include signing time. */
   224     rv = SEC_PKCS7AddSigningTime(cinfo);
   225     /* don't check error */
   226     PORT_SetError(0);
   228     /* if calling from mozilla thread*/
   229     rv = SEC_PKCS7Encode(cinfo, jar_pk7_out, outfp, NULL, NULL, mw);
   230     if (rv != SECSuccess)
   231 	status = PORT_GetError();
   232     SEC_PKCS7DestroyContentInfo (cinfo);
   233     if (rv != SECSuccess) {
   234 	errstring = JAR_get_error (status);
   235 	return ((status < 0) ? status : JAR_ERR_GENERAL);
   236     }
   237     return 0;
   238 }

mercurial