Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / jar / jarsign.c
blobfb4ad15559b7b15420c492ef2cf5ea682d0ba36d
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * JARSIGN
40 * Routines used in signing archives.
44 #include "jar.h"
45 #include "jarint.h"
46 #include "secpkcs7.h"
47 #include "pk11func.h"
48 #include "sechash.h"
50 /* from libevent.h */
51 typedef void (*ETVoidPtrFunc) (void * data);
53 #ifdef MOZILLA_CLIENT_OLD
55 extern void ET_moz_CallFunction (ETVoidPtrFunc fn, void *data);
57 /* from proto.h */
58 /* extern MWContext *XP_FindSomeContext(void); */
59 extern void *XP_FindSomeContext(void);
61 #endif
63 /* key database wrapper */
65 /* static SECKEYKeyDBHandle *jar_open_key_database (void); */
67 /* CHUNQ is our bite size */
69 #define CHUNQ 64000
70 #define FILECHUNQ 32768
73 * J A R _ c a l c u l a t e _ d i g e s t
75 * Quick calculation of a digest for
76 * the specified block of memory. Will calculate
77 * for all supported algorithms, now MD5.
79 * This version supports huge pointers for WIN16.
83 JAR_Digest * PR_CALLBACK JAR_calculate_digest (void ZHUGEP *data, long length)
85 long chunq;
86 JAR_Digest *dig;
88 unsigned int md5_length, sha1_length;
90 PK11Context *md5 = 0;
91 PK11Context *sha1 = 0;
93 dig = (JAR_Digest *) PORT_ZAlloc (sizeof (JAR_Digest));
95 if (dig == NULL)
97 /* out of memory allocating digest */
98 return NULL;
101 #if defined(XP_WIN16)
102 PORT_Assert ( !IsBadHugeReadPtr(data, length) );
103 #endif
105 md5 = PK11_CreateDigestContext (SEC_OID_MD5);
106 sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
108 if (length >= 0)
110 PK11_DigestBegin (md5);
111 PK11_DigestBegin (sha1);
113 do {
114 chunq = length;
116 #ifdef XP_WIN16
117 if (length > CHUNQ) chunq = CHUNQ;
120 * If the block of data crosses one or more segment
121 * boundaries then only pass the chunk of data in the
122 * first segment.
124 * This allows the data to be treated as FAR by the
125 * PK11_DigestOp(...) routine.
129 if (OFFSETOF(data) + chunq >= 0x10000)
130 chunq = 0x10000 - OFFSETOF(data);
131 #endif
133 PK11_DigestOp (md5, (unsigned char*)data, chunq);
134 PK11_DigestOp (sha1, (unsigned char*)data, chunq);
136 length -= chunq;
137 data = ((char ZHUGEP *) data + chunq);
139 while (length > 0);
141 PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
142 PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
144 PK11_DestroyContext (md5, PR_TRUE);
145 PK11_DestroyContext (sha1, PR_TRUE);
148 return dig;
152 * J A R _ d i g e s t _ f i l e
154 * Calculates the MD5 and SHA1 digests for a file
155 * present on disk, and returns these in JAR_Digest struct.
159 int JAR_digest_file (char *filename, JAR_Digest *dig)
161 JAR_FILE fp;
163 int num;
164 unsigned char *buf;
166 PK11Context *md5 = 0;
167 PK11Context *sha1 = 0;
169 unsigned int md5_length, sha1_length;
171 buf = (unsigned char *) PORT_ZAlloc (FILECHUNQ);
172 if (buf == NULL)
174 /* out of memory */
175 return JAR_ERR_MEMORY;
178 if ((fp = JAR_FOPEN (filename, "rb")) == 0)
180 /* perror (filename); FIX XXX XXX XXX XXX XXX XXX */
181 PORT_Free (buf);
182 return JAR_ERR_FNF;
185 md5 = PK11_CreateDigestContext (SEC_OID_MD5);
186 sha1 = PK11_CreateDigestContext (SEC_OID_SHA1);
188 if (md5 == NULL || sha1 == NULL)
190 /* can't generate digest contexts */
191 PORT_Free (buf);
192 JAR_FCLOSE (fp);
193 return JAR_ERR_GENERAL;
196 PK11_DigestBegin (md5);
197 PK11_DigestBegin (sha1);
199 while (1)
201 if ((num = JAR_FREAD (fp, buf, FILECHUNQ)) == 0)
202 break;
204 PK11_DigestOp (md5, buf, num);
205 PK11_DigestOp (sha1, buf, num);
208 PK11_DigestFinal (md5, dig->md5, &md5_length, MD5_LENGTH);
209 PK11_DigestFinal (sha1, dig->sha1, &sha1_length, SHA1_LENGTH);
211 PK11_DestroyContext (md5, PR_TRUE);
212 PK11_DestroyContext (sha1, PR_TRUE);
214 PORT_Free (buf);
215 JAR_FCLOSE (fp);
217 return 0;
221 * J A R _ o p e n _ k e y _ d a t a b a s e
225 void* jar_open_key_database (void)
227 return NULL;
230 int jar_close_key_database (void *keydb)
232 /* We never do close it */
233 return 0;
238 * j a r _ c r e a t e _ p k 7
242 static void jar_pk7_out (void *arg, const char *buf, unsigned long len)
244 JAR_FWRITE ((JAR_FILE) arg, buf, len);
247 int jar_create_pk7
248 (CERTCertDBHandle *certdb, void *keydb,
249 CERTCertificate *cert, char *password, JAR_FILE infp, JAR_FILE outfp)
251 int nb;
252 unsigned char buffer [4096], digestdata[32];
253 const SECHashObject *hashObj;
254 void *hashcx;
255 unsigned int len;
257 int status = 0;
258 char *errstring;
260 SECItem digest;
261 SEC_PKCS7ContentInfo *cinfo;
262 SECStatus rv;
264 void /*MWContext*/ *mw;
266 if (outfp == NULL || infp == NULL || cert == NULL)
267 return JAR_ERR_GENERAL;
269 /* we sign with SHA */
270 hashObj = HASH_GetHashObject(HASH_AlgSHA1);
272 hashcx = (* hashObj->create)();
273 if (hashcx == NULL)
274 return JAR_ERR_GENERAL;
276 (* hashObj->begin)(hashcx);
278 while (1)
280 /* nspr2.0 doesn't support feof
281 if (feof (infp)) break; */
283 nb = JAR_FREAD (infp, buffer, sizeof (buffer));
284 if (nb == 0)
286 /* eof */
287 break;
289 (* hashObj->update) (hashcx, buffer, nb);
292 (* hashObj->end) (hashcx, digestdata, &len, 32);
293 (* hashObj->destroy) (hashcx, PR_TRUE);
295 digest.data = digestdata;
296 digest.len = len;
298 /* signtool must use any old context it can find since it's
299 calling from inside javaland. */
301 #ifdef MOZILLA_CLIENT_OLD
302 mw = XP_FindSomeContext();
303 #else
304 mw = NULL;
305 #endif
307 PORT_SetError (0);
309 cinfo = SEC_PKCS7CreateSignedData
310 (cert, certUsageObjectSigner, NULL,
311 SEC_OID_SHA1, &digest, NULL, (void *) mw);
313 if (cinfo == NULL)
314 return JAR_ERR_PK7;
316 rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
317 if (rv != SECSuccess)
319 status = PORT_GetError();
320 SEC_PKCS7DestroyContentInfo (cinfo);
321 return status;
324 /* Having this here forces signtool to always include
325 signing time. */
327 rv = SEC_PKCS7AddSigningTime (cinfo);
328 if (rv != SECSuccess)
330 /* don't check error */
333 PORT_SetError (0);
335 /* if calling from mozilla thread*/
336 rv = SEC_PKCS7Encode
337 (cinfo, jar_pk7_out, outfp,
338 NULL, /* pwfn */ NULL, /* pwarg */ (void *) mw);
340 if (rv != SECSuccess)
341 status = PORT_GetError();
343 SEC_PKCS7DestroyContentInfo (cinfo);
345 if (rv != SECSuccess)
347 errstring = JAR_get_error (status);
348 /*XP_TRACE (("Jar signing failed (reason %d = %s)", status, errstring));*/
349 return status < 0 ? status : JAR_ERR_GENERAL;
352 return 0;