security/nss/lib/jar/jarsign.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.

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

mercurial