security/nss/lib/jar/jarsign.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/jar/jarsign.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,238 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + *  JARSIGN
    1.10 + *
    1.11 + *  Routines used in signing archives.
    1.12 + */
    1.13 +
    1.14 +
    1.15 +#include "jar.h"
    1.16 +#include "jarint.h"
    1.17 +#include "secpkcs7.h"
    1.18 +#include "pk11func.h"
    1.19 +#include "sechash.h"
    1.20 +
    1.21 +/* from libevent.h */
    1.22 +typedef void (*ETVoidPtrFunc) (void * data);
    1.23 +
    1.24 +/* key database wrapper */
    1.25 +/* static SECKEYKeyDBHandle *jar_open_key_database (void); */
    1.26 +/* CHUNQ is our bite size */
    1.27 +
    1.28 +#define CHUNQ 64000
    1.29 +#define FILECHUNQ 32768
    1.30 +
    1.31 +/*
    1.32 + *  J A R _ c a l c u l a t e _ d i g e s t
    1.33 + *
    1.34 + *  Quick calculation of a digest for
    1.35 + *  the specified block of memory. Will calculate
    1.36 + *  for all supported algorithms, now MD5.
    1.37 + *
    1.38 + *  This version supports huge pointers for WIN16.
    1.39 + *
    1.40 + */
    1.41 +JAR_Digest * PR_CALLBACK 
    1.42 +JAR_calculate_digest(void *data, long length)
    1.43 +{
    1.44 +    PK11Context *md5  = 0;
    1.45 +    PK11Context *sha1 = 0;
    1.46 +    JAR_Digest *dig   = PORT_ZNew(JAR_Digest);
    1.47 +    long chunq;
    1.48 +    unsigned int md5_length, sha1_length;
    1.49 +
    1.50 +    if (dig == NULL) {
    1.51 +	/* out of memory allocating digest */
    1.52 +	return NULL;
    1.53 +    }
    1.54 +
    1.55 +    md5  = PK11_CreateDigestContext(SEC_OID_MD5);
    1.56 +    sha1 = PK11_CreateDigestContext(SEC_OID_SHA1);
    1.57 +
    1.58 +    if (length >= 0) {
    1.59 +	PK11_DigestBegin (md5);
    1.60 +	PK11_DigestBegin (sha1);
    1.61 +
    1.62 +	do {
    1.63 +	    chunq = length;
    1.64 +
    1.65 +	    PK11_DigestOp(md5,  (unsigned char*)data, chunq);
    1.66 +	    PK11_DigestOp(sha1, (unsigned char*)data, chunq);
    1.67 +	    length -= chunq;
    1.68 +	    data = ((char *) data + chunq);
    1.69 +	}
    1.70 +	while (length > 0);
    1.71 +
    1.72 +	PK11_DigestFinal (md5,	dig->md5,  &md5_length,  MD5_LENGTH);
    1.73 +	PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
    1.74 +
    1.75 +	PK11_DestroyContext (md5,  PR_TRUE);
    1.76 +	PK11_DestroyContext (sha1, PR_TRUE);
    1.77 +    }
    1.78 +    return dig;
    1.79 +}
    1.80 +
    1.81 +/*
    1.82 + *  J A R _ d i g e s t _ f i l e
    1.83 + *
    1.84 + *  Calculates the MD5 and SHA1 digests for a file
    1.85 + *  present on disk, and returns these in JAR_Digest struct.
    1.86 + *
    1.87 + */
    1.88 +int 
    1.89 +JAR_digest_file (char *filename, JAR_Digest *dig)
    1.90 +{
    1.91 +    JAR_FILE fp;
    1.92 +    PK11Context *md5 = 0;
    1.93 +    PK11Context *sha1 = 0;
    1.94 +    unsigned char *buf = (unsigned char *) PORT_ZAlloc (FILECHUNQ);
    1.95 +    int num;
    1.96 +    unsigned int md5_length, sha1_length;
    1.97 +
    1.98 +    if (buf == NULL) {
    1.99 +	/* out of memory */
   1.100 +	return JAR_ERR_MEMORY;
   1.101 +    }
   1.102 +
   1.103 +    if ((fp = JAR_FOPEN (filename, "rb")) == 0) {
   1.104 +	/* perror (filename); FIX XXX XXX XXX XXX XXX XXX */
   1.105 +	PORT_Free (buf);
   1.106 +	return JAR_ERR_FNF;
   1.107 +    }
   1.108 +
   1.109 +    md5 = PK11_CreateDigestContext (SEC_OID_MD5);
   1.110 +    sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
   1.111 +
   1.112 +    if (md5 == NULL || sha1 == NULL) {
   1.113 +	/* can't generate digest contexts */
   1.114 +	PORT_Free (buf);
   1.115 +	JAR_FCLOSE (fp);
   1.116 +	return JAR_ERR_GENERAL;
   1.117 +    }
   1.118 +
   1.119 +    PK11_DigestBegin (md5);
   1.120 +    PK11_DigestBegin (sha1);
   1.121 +
   1.122 +    while (1) {
   1.123 +	if ((num = JAR_FREAD (fp, buf, FILECHUNQ)) == 0)
   1.124 +	    break;
   1.125 +
   1.126 +	PK11_DigestOp (md5, buf, num);
   1.127 +	PK11_DigestOp (sha1, buf, num);
   1.128 +    }
   1.129 +
   1.130 +    PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
   1.131 +    PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
   1.132 +
   1.133 +    PK11_DestroyContext (md5, PR_TRUE);
   1.134 +    PK11_DestroyContext (sha1, PR_TRUE);
   1.135 +
   1.136 +    PORT_Free (buf);
   1.137 +    JAR_FCLOSE (fp);
   1.138 +
   1.139 +    return 0;
   1.140 +}
   1.141 +
   1.142 +/*
   1.143 + *  J A R _ o p e n _ k e y _ d a t a b a s e
   1.144 + *
   1.145 + */
   1.146 +
   1.147 +void* 
   1.148 +jar_open_key_database(void)
   1.149 +{
   1.150 +    return NULL;
   1.151 +}
   1.152 +
   1.153 +int 
   1.154 +jar_close_key_database(void *keydb)
   1.155 +{
   1.156 +    /* We never do close it */
   1.157 +    return 0;
   1.158 +}
   1.159 +
   1.160 +
   1.161 +/*
   1.162 + *  j a r _ c r e a t e _ p k 7
   1.163 + *
   1.164 + */
   1.165 +
   1.166 +static void jar_pk7_out (void *arg, const char *buf, unsigned long len)
   1.167 +{
   1.168 +    JAR_FWRITE ((JAR_FILE) arg, buf, len);
   1.169 +}
   1.170 +
   1.171 +int 
   1.172 +jar_create_pk7(CERTCertDBHandle *certdb, void *keydb, CERTCertificate *cert, 
   1.173 +               char *password, JAR_FILE infp, JAR_FILE outfp)
   1.174 +{
   1.175 +    SEC_PKCS7ContentInfo *cinfo;
   1.176 +    const SECHashObject *hashObj;
   1.177 +    char *errstring;
   1.178 +    void *mw = NULL;
   1.179 +    void *hashcx;
   1.180 +    unsigned int len;
   1.181 +    int status = 0;
   1.182 +    SECStatus rv;
   1.183 +    SECItem digest;
   1.184 +    unsigned char digestdata[32];
   1.185 +    unsigned char buffer[4096];
   1.186 +
   1.187 +    if (outfp == NULL || infp == NULL || cert == NULL)
   1.188 +	return JAR_ERR_GENERAL;
   1.189 +
   1.190 +    /* we sign with SHA */
   1.191 +    hashObj = HASH_GetHashObject(HASH_AlgSHA1);
   1.192 +
   1.193 +    hashcx = (* hashObj->create)();
   1.194 +    if (hashcx == NULL)
   1.195 +	return JAR_ERR_GENERAL;
   1.196 +
   1.197 +    (* hashObj->begin)(hashcx);
   1.198 +    while (1) {
   1.199 +	int nb = JAR_FREAD(infp, buffer, sizeof buffer);
   1.200 +	if (nb == 0) { /* eof */
   1.201 +	    break;
   1.202 +	}
   1.203 +	(* hashObj->update) (hashcx, buffer, nb);
   1.204 +    }
   1.205 +    (* hashObj->end)(hashcx, digestdata, &len, 32);
   1.206 +    (* hashObj->destroy)(hashcx, PR_TRUE);
   1.207 +
   1.208 +    digest.data = digestdata;
   1.209 +    digest.len = len;
   1.210 +
   1.211 +    /* signtool must use any old context it can find since it's
   1.212 +	 calling from inside javaland. */
   1.213 +    PORT_SetError (0);
   1.214 +    cinfo = SEC_PKCS7CreateSignedData(cert, certUsageObjectSigner, NULL,
   1.215 +                                      SEC_OID_SHA1, &digest, NULL, mw);
   1.216 +    if (cinfo == NULL)
   1.217 +	return JAR_ERR_PK7;
   1.218 +
   1.219 +    rv = SEC_PKCS7IncludeCertChain(cinfo, NULL);
   1.220 +    if (rv != SECSuccess) {
   1.221 +	status = PORT_GetError();
   1.222 +	SEC_PKCS7DestroyContentInfo(cinfo);
   1.223 +	return status;
   1.224 +    }
   1.225 +
   1.226 +    /* Having this here forces signtool to always include signing time. */
   1.227 +    rv = SEC_PKCS7AddSigningTime(cinfo);
   1.228 +    /* don't check error */
   1.229 +    PORT_SetError(0);
   1.230 +
   1.231 +    /* if calling from mozilla thread*/
   1.232 +    rv = SEC_PKCS7Encode(cinfo, jar_pk7_out, outfp, NULL, NULL, mw);
   1.233 +    if (rv != SECSuccess)
   1.234 +	status = PORT_GetError();
   1.235 +    SEC_PKCS7DestroyContentInfo (cinfo);
   1.236 +    if (rv != SECSuccess) {
   1.237 +	errstring = JAR_get_error (status);
   1.238 +	return ((status < 0) ? status : JAR_ERR_GENERAL);
   1.239 +    }
   1.240 +    return 0;
   1.241 +}

mercurial