security/nss/cmd/signtool/sign.c

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:37cb8aeef943
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/. */
4
5 #include "signtool.h"
6 #include "zip.h"
7 #include "prmem.h"
8 #include "blapi.h"
9 #include "sechash.h" /* for HASH_GetHashObject() */
10
11 static int create_pk7 (char *dir, char *keyName, int *keyType);
12 static int jar_find_key_type (CERTCertificate *cert);
13 static int manifesto (char *dirname, char *install_script, PRBool recurse);
14 static int manifesto_fn(char *relpath, char *basedir, char *reldir,
15 char *filename, void *arg);
16 static int manifesto_xpi_fn(char *relpath, char *basedir, char *reldir,
17 char *filename, void *arg);
18 static int sign_all_arc_fn(char *relpath, char *basedir, char *reldir,
19 char *filename, void *arg);
20 static int add_meta (FILE *fp, char *name);
21 static int SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert);
22 static int generate_SF_file (char *manifile, char *who);
23 static int calculate_MD5_range (FILE *fp, long r1, long r2,
24 JAR_Digest *dig);
25 static void SignOut (void *arg, const char *buf, unsigned long len);
26
27 static char *metafile = NULL;
28 static int optimize = 0;
29 static FILE *mf;
30 static ZIPfile *zipfile = NULL;
31
32 /*
33 * S i g n A r c h i v e
34 *
35 * Sign an individual archive tree. A directory
36 * called META-INF is created underneath this.
37 *
38 */
39 int
40 SignArchive(char *tree, char *keyName, char *zip_file, int javascript,
41 char *meta_file, char *install_script, int _optimize, PRBool recurse)
42 {
43 int status;
44 char tempfn [FNSIZE], fullfn [FNSIZE];
45 int keyType = rsaKey;
46
47 metafile = meta_file;
48 optimize = _optimize;
49
50 /* To create XPI compatible Archive manifesto() must be run before
51 * the zipfile is opened. This is so the signed files are not added
52 * the archive before the crucial rsa/dsa file*/
53 if (xpi_arc) {
54 manifesto (tree, install_script, recurse);
55 }
56
57 if (zip_file) {
58 zipfile = JzipOpen(zip_file, NULL /*no comment*/);
59 }
60
61 /*Sign and add files to the archive normally with manifesto()*/
62 if (!xpi_arc) {
63 manifesto (tree, install_script, recurse);
64 }
65
66 if (keyName) {
67 status = create_pk7 (tree, keyName, &keyType);
68 if (status < 0) {
69 PR_fprintf(errorFD, "the tree \"%s\" was NOT SUCCESSFULLY SIGNED\n",
70 tree);
71 errorCount++;
72 exit (ERRX);
73 }
74 }
75
76 /* Add the rsa/dsa file as the first file in the archive. This is crucial
77 * for a XPInstall compatible archive */
78 if (xpi_arc) {
79 if (verbosity >= 0) {
80 PR_fprintf(outputFD, "%s \n", XPI_TEXT);
81 }
82
83 /* rsa/dsa to zip */
84 sprintf (tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ?
85 "dsa" : "rsa"));
86 sprintf (fullfn, "%s/%s", tree, tempfn);
87 JzipAdd(fullfn, tempfn, zipfile, compression_level);
88
89 /* Loop through all files & subdirectories, add to archive */
90 foreach (tree, "", manifesto_xpi_fn, recurse, PR_FALSE /*include dirs */,
91 (void * )NULL);
92 }
93 /* mf to zip */
94 strcpy (tempfn, "META-INF/manifest.mf");
95 sprintf (fullfn, "%s/%s", tree, tempfn);
96 JzipAdd(fullfn, tempfn, zipfile, compression_level);
97
98 /* sf to zip */
99 sprintf (tempfn, "META-INF/%s.sf", base);
100 sprintf (fullfn, "%s/%s", tree, tempfn);
101 JzipAdd(fullfn, tempfn, zipfile, compression_level);
102
103 /* Add the rsa/dsa file to the zip archive normally */
104 if (!xpi_arc) {
105 /* rsa/dsa to zip */
106 sprintf (tempfn, "META-INF/%s.%s", base, (keyType == dsaKey ?
107 "dsa" : "rsa"));
108 sprintf (fullfn, "%s/%s", tree, tempfn);
109 JzipAdd(fullfn, tempfn, zipfile, compression_level);
110 }
111
112 JzipClose(zipfile);
113
114 if (verbosity >= 0) {
115 if (javascript) {
116 PR_fprintf(outputFD, "jarfile \"%s\" signed successfully\n",
117 zip_file);
118 } else {
119 PR_fprintf(outputFD, "tree \"%s\" signed successfully\n",
120 tree);
121 }
122 }
123
124 return 0;
125 }
126
127
128 typedef struct {
129 char *keyName;
130 int javascript;
131 char *metafile;
132 char *install_script;
133 int optimize;
134 } SignArcInfo;
135
136 /*
137 * S i g n A l l A r c
138 *
139 * Javascript may generate multiple .arc directories, one
140 * for each jar archive needed. Sign them all.
141 *
142 */
143 int
144 SignAllArc(char *jartree, char *keyName, int javascript, char *metafile,
145 char *install_script, int optimize, PRBool recurse)
146 {
147 SignArcInfo info;
148
149 info.keyName = keyName;
150 info.javascript = javascript;
151 info.metafile = metafile;
152 info.install_script = install_script;
153 info.optimize = optimize;
154
155 return foreach(jartree, "", sign_all_arc_fn, recurse,
156 PR_TRUE /*include dirs*/, (void * )&info);
157 }
158
159
160 static int
161 sign_all_arc_fn(char *relpath, char *basedir, char *reldir, char *filename,
162 void *arg)
163 {
164 char *zipfile = NULL;
165 char *arc = NULL, *archive = NULL;
166 int retval = 0;
167 SignArcInfo * infop = (SignArcInfo * )arg;
168
169 /* Make sure there is one and only one ".arc" in the relative path,
170 * and that it is at the end of the path (don't sign .arcs within .arcs) */
171 if ( (PL_strcaserstr(relpath, ".arc") == relpath + strlen(relpath) -
172 4) &&
173 (PL_strcasestr(relpath, ".arc") == relpath + strlen(relpath) - 4) ) {
174
175 if (!infop) {
176 PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
177 errorCount++;
178 retval = -1;
179 goto finish;
180 }
181 archive = PR_smprintf("%s/%s", basedir, relpath);
182
183 zipfile = PL_strdup(archive);
184 arc = PORT_Strrchr (zipfile, '.');
185
186 if (arc == NULL) {
187 PR_fprintf(errorFD, "%s: Internal failure\n", PROGRAM_NAME);
188 errorCount++;
189 retval = -1;
190 goto finish;
191 }
192
193 PL_strcpy (arc, ".jar");
194
195 if (verbosity >= 0) {
196 PR_fprintf(outputFD, "\nsigning: %s\n", zipfile);
197 }
198 retval = SignArchive(archive, infop->keyName, zipfile,
199 infop->javascript, infop->metafile, infop->install_script,
200 infop->optimize, PR_TRUE /* recurse */);
201 }
202 finish:
203 if (archive)
204 PR_Free(archive);
205 if (zipfile)
206 PR_Free(zipfile);
207
208 return retval;
209 }
210
211
212 /*********************************************************************
213 *
214 * c r e a t e _ p k 7
215 */
216 static int
217 create_pk7 (char *dir, char *keyName, int *keyType)
218 {
219 int status = 0;
220 char *file_ext;
221
222 CERTCertificate * cert;
223 CERTCertDBHandle * db;
224
225 FILE * in, *out;
226
227 char sf_file [FNSIZE];
228 char pk7_file [FNSIZE];
229
230 /* open cert database */
231 db = CERT_GetDefaultCertDB();
232
233 if (db == NULL)
234 return - 1;
235
236 /* find cert */
237 /*cert = CERT_FindCertByNicknameOrEmailAddr(db, keyName);*/
238 cert = PK11_FindCertFromNickname(keyName, &pwdata);
239
240 if (cert == NULL) {
241 SECU_PrintError ( PROGRAM_NAME,
242 "Cannot find the cert \"%s\"", keyName);
243 return -1;
244 }
245
246
247 /* determine the key type, which sets the extension for pkcs7 object */
248
249 *keyType = jar_find_key_type (cert);
250 file_ext = (*keyType == dsaKey) ? "dsa" : "rsa";
251
252 sprintf (sf_file, "%s/META-INF/%s.sf", dir, base);
253 sprintf (pk7_file, "%s/META-INF/%s.%s", dir, base, file_ext);
254
255 if ((in = fopen (sf_file, "rb")) == NULL) {
256 PR_fprintf(errorFD, "%s: Can't open %s for reading\n", PROGRAM_NAME,
257 sf_file);
258 errorCount++;
259 exit (ERRX);
260 }
261
262 if ((out = fopen (pk7_file, "wb")) == NULL) {
263 PR_fprintf(errorFD, "%s: Can't open %s for writing\n", PROGRAM_NAME,
264 sf_file);
265 errorCount++;
266 exit (ERRX);
267 }
268
269 status = SignFile (out, in, cert);
270
271 CERT_DestroyCertificate (cert);
272 fclose (in);
273 fclose (out);
274
275 if (status) {
276 PR_fprintf(errorFD, "%s: PROBLEM signing data (%s)\n",
277 PROGRAM_NAME, SECU_Strerror(PORT_GetError()));
278 errorCount++;
279 return - 1;
280 }
281
282 return 0;
283 }
284
285
286 /*
287 * j a r _ f i n d _ k e y _ t y p e
288 *
289 * Determine the key type for a given cert, which
290 * should be rsaKey or dsaKey. Any error return 0.
291 *
292 */
293 static int
294 jar_find_key_type (CERTCertificate *cert)
295 {
296 SECKEYPrivateKey * privk = NULL;
297 KeyType keyType;
298
299 /* determine its type */
300 privk = PK11_FindKeyByAnyCert (cert, &pwdata);
301 if (privk == NULL) {
302 PR_fprintf(errorFD, "warning - can't find private key for this cert\n");
303 warningCount++;
304 return 0;
305 }
306
307 keyType = privk->keyType;
308 SECKEY_DestroyPrivateKey (privk);
309 return keyType;
310 }
311
312
313 /*
314 * m a n i f e s t o
315 *
316 * Run once for every subdirectory in which a
317 * manifest is to be created -- usually exactly once.
318 *
319 */
320 static int
321 manifesto (char *dirname, char *install_script, PRBool recurse)
322 {
323 char metadir [FNSIZE], sfname [FNSIZE];
324
325 /* Create the META-INF directory to hold signing info */
326
327 if (PR_Access (dirname, PR_ACCESS_READ_OK)) {
328 PR_fprintf(errorFD, "%s: unable to read your directory: %s\n",
329 PROGRAM_NAME, dirname);
330 errorCount++;
331 perror (dirname);
332 exit (ERRX);
333 }
334
335 if (PR_Access (dirname, PR_ACCESS_WRITE_OK)) {
336 PR_fprintf(errorFD, "%s: unable to write to your directory: %s\n",
337 PROGRAM_NAME, dirname);
338 errorCount++;
339 perror(dirname);
340 exit(ERRX);
341 }
342
343 sprintf (metadir, "%s/META-INF", dirname);
344
345 strcpy (sfname, metadir);
346
347 PR_MkDir (metadir, 0777);
348
349 strcat (metadir, "/");
350 strcat (metadir, MANIFEST);
351
352 if ((mf = fopen (metadir, "wb")) == NULL) {
353 perror (MANIFEST);
354 PR_fprintf(errorFD, "%s: Probably, the directory you are trying to"
355 " sign has\n", PROGRAM_NAME);
356 PR_fprintf(errorFD, "%s: permissions problems or may not exist.\n",
357 PROGRAM_NAME);
358 errorCount++;
359 exit (ERRX);
360 }
361
362 if (verbosity >= 0) {
363 PR_fprintf(outputFD, "Generating %s file..\n", metadir);
364 }
365
366 fprintf(mf, "Manifest-Version: 1.0\n");
367 fprintf (mf, "Created-By: %s\n", CREATOR);
368 fprintf (mf, "Comments: %s\n", BREAKAGE);
369
370 if (scriptdir) {
371 fprintf (mf, "Comments: --\n");
372 fprintf (mf, "Comments: --\n");
373 fprintf (mf, "Comments: -- This archive signs Javascripts which may not necessarily\n");
374 fprintf (mf, "Comments: -- be included in the physical jar file.\n");
375 fprintf (mf, "Comments: --\n");
376 fprintf (mf, "Comments: --\n");
377 }
378
379 if (install_script)
380 fprintf (mf, "Install-Script: %s\n", install_script);
381
382 if (metafile)
383 add_meta (mf, "+");
384
385 /* Loop through all files & subdirectories */
386 foreach (dirname, "", manifesto_fn, recurse, PR_FALSE /*include dirs */,
387 (void * )NULL);
388
389 fclose (mf);
390
391 strcat (sfname, "/");
392 strcat (sfname, base);
393 strcat (sfname, ".sf");
394
395 if (verbosity >= 0) {
396 PR_fprintf(outputFD, "Generating %s.sf file..\n", base);
397 }
398 generate_SF_file (metadir, sfname);
399
400 return 0;
401 }
402
403
404 /*
405 * m a n i f e s t o _ x p i _ f n
406 *
407 * Called by pointer from SignArchive(), once for
408 * each file within the directory. This function
409 * is only used for adding to XPI compatible archive
410 *
411 */
412 static int manifesto_xpi_fn
413 (char *relpath, char *basedir, char *reldir, char *filename, void *arg)
414 {
415 char fullname [FNSIZE];
416
417 if (verbosity >= 0) {
418 PR_fprintf(outputFD, "--> %s\n", relpath);
419 }
420
421 /* extension matching */
422 if (extensionsGiven) {
423 char *ext = PL_strrchr(relpath, '.');
424 if (!ext)
425 return 0;
426 if (!PL_HashTableLookup(extensions, ext))
427 return 0;
428 }
429 sprintf (fullname, "%s/%s", basedir, relpath);
430 JzipAdd(fullname, relpath, zipfile, compression_level);
431
432 return 0;
433 }
434
435
436 /*
437 * m a n i f e s t o _ f n
438 *
439 * Called by pointer from manifesto(), once for
440 * each file within the directory.
441 *
442 */
443 static int manifesto_fn
444 (char *relpath, char *basedir, char *reldir, char *filename, void *arg)
445 {
446 int use_js;
447
448 JAR_Digest dig;
449 char fullname [FNSIZE];
450
451 if (verbosity >= 0) {
452 PR_fprintf(outputFD, "--> %s\n", relpath);
453 }
454
455 /* extension matching */
456 if (extensionsGiven) {
457 char *ext = PL_strrchr(relpath, '.');
458 if (!ext)
459 return 0;
460 if (!PL_HashTableLookup(extensions, ext))
461 return 0;
462 }
463
464 sprintf (fullname, "%s/%s", basedir, relpath);
465
466 fprintf (mf, "\n");
467
468 use_js = 0;
469
470 if (scriptdir && !PORT_Strcmp (scriptdir, reldir))
471 use_js++;
472
473 /* sign non-.js files inside .arc directories using the javascript magic */
474
475 if ( (PL_strcaserstr(filename, ".js") != filename + strlen(filename) - 3)
476 && (PL_strcaserstr(reldir, ".arc") == reldir + strlen(filename) - 4))
477 use_js++;
478
479 if (use_js) {
480 fprintf (mf, "Name: %s\n", filename);
481 fprintf (mf, "Magic: javascript\n");
482
483 if (optimize == 0)
484 fprintf (mf, "javascript.id: %s\n", filename);
485
486 if (metafile)
487 add_meta (mf, filename);
488 } else {
489 fprintf (mf, "Name: %s\n", relpath);
490 if (metafile)
491 add_meta (mf, relpath);
492 }
493
494 JAR_digest_file (fullname, &dig);
495
496
497 if (optimize == 0) {
498 fprintf (mf, "Digest-Algorithms: MD5 SHA1\n");
499 fprintf (mf, "MD5-Digest: %s\n", BTOA_DataToAscii (dig.md5,
500 MD5_LENGTH));
501 }
502
503 fprintf (mf, "SHA1-Digest: %s\n", BTOA_DataToAscii (dig.sha1, SHA1_LENGTH));
504
505 if (!use_js) {
506 JzipAdd(fullname, relpath, zipfile, compression_level);
507 }
508
509 return 0;
510 }
511
512
513 /*
514 * a d d _ m e t a
515 *
516 * Parse the metainfo file, and add any details
517 * necessary to the manifest file. In most cases you
518 * should be using the -i option (ie, for SmartUpdate).
519 *
520 */
521 static int add_meta (FILE *fp, char *name)
522 {
523 FILE * met;
524 char buf [BUFSIZ];
525
526 int place;
527 char *pattern, *meta;
528
529 int num = 0;
530
531 if ((met = fopen (metafile, "r")) != NULL) {
532 while (fgets (buf, BUFSIZ, met)) {
533 char *s;
534
535 for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
536 ;
537 *s = 0;
538
539 if (*buf == 0)
540 continue;
541
542 pattern = buf;
543
544 /* skip to whitespace */
545 for (s = buf; *s && *s != ' ' && *s != '\t'; s++)
546 ;
547
548 /* terminate pattern */
549 if (*s == ' ' || *s == '\t')
550 *s++ = 0;
551
552 /* eat through whitespace */
553 while (*s == ' ' || *s == '\t')
554 s++;
555
556 meta = s;
557
558 /* this will eventually be regexp matching */
559
560 place = 0;
561 if (!PORT_Strcmp (pattern, name))
562 place = 1;
563
564 if (place) {
565 num++;
566 if (verbosity >= 0) {
567 PR_fprintf(outputFD, "[%s] %s\n", name, meta);
568 }
569 fprintf (fp, "%s\n", meta);
570 }
571 }
572 fclose (met);
573 } else {
574 PR_fprintf(errorFD, "%s: can't open metafile: %s\n", PROGRAM_NAME,
575 metafile);
576 errorCount++;
577 exit (ERRX);
578 }
579
580 return num;
581 }
582
583
584 /**********************************************************************
585 *
586 * S i g n F i l e
587 */
588 static int
589 SignFile (FILE *outFile, FILE *inFile, CERTCertificate *cert)
590 {
591 int nb;
592 char ibuf[4096], digestdata[32];
593 const SECHashObject *hashObj;
594 void *hashcx;
595 unsigned int len;
596
597 SECItem digest;
598 SEC_PKCS7ContentInfo * cinfo;
599 SECStatus rv;
600
601 if (outFile == NULL || inFile == NULL || cert == NULL)
602 return - 1;
603
604 /* XXX probably want to extend interface to allow other hash algorithms */
605 hashObj = HASH_GetHashObject(HASH_AlgSHA1);
606
607 hashcx = (*hashObj->create)();
608 if (hashcx == NULL)
609 return - 1;
610
611 (*hashObj->begin)(hashcx);
612
613 for (; ; ) {
614 if (feof(inFile))
615 break;
616 nb = fread(ibuf, 1, sizeof(ibuf), inFile);
617 if (nb == 0) {
618 if (ferror(inFile)) {
619 PORT_SetError(SEC_ERROR_IO);
620 (*hashObj->destroy)(hashcx, PR_TRUE);
621 return - 1;
622 }
623 /* eof */
624 break;
625 }
626 (*hashObj->update)(hashcx, (unsigned char *) ibuf, nb);
627 }
628
629 (*hashObj->end)(hashcx, (unsigned char *) digestdata, &len, 32);
630 (*hashObj->destroy)(hashcx, PR_TRUE);
631
632 digest.data = (unsigned char *) digestdata;
633 digest.len = len;
634
635 cinfo = SEC_PKCS7CreateSignedData
636 (cert, certUsageObjectSigner, NULL,
637 SEC_OID_SHA1, &digest, NULL, NULL);
638
639 if (cinfo == NULL)
640 return - 1;
641
642 rv = SEC_PKCS7IncludeCertChain (cinfo, NULL);
643 if (rv != SECSuccess) {
644 SEC_PKCS7DestroyContentInfo (cinfo);
645 return - 1;
646 }
647
648 if (no_time == 0) {
649 rv = SEC_PKCS7AddSigningTime (cinfo);
650 if (rv != SECSuccess) {
651 /* don't check error */
652 }
653 }
654
655 rv = SEC_PKCS7Encode(cinfo, SignOut, outFile, NULL, NULL, &pwdata);
656
657 SEC_PKCS7DestroyContentInfo (cinfo);
658
659 if (rv != SECSuccess)
660 return - 1;
661
662 return 0;
663 }
664
665
666 /*
667 * g e n e r a t e _ S F _ f i l e
668 *
669 * From the supplied manifest file, calculates
670 * digests on the various sections, creating a .SF
671 * file in the process.
672 *
673 */
674 static int generate_SF_file (char *manifile, char *who)
675 {
676 FILE * sf;
677 FILE * mf;
678 long r1, r2, r3;
679 char whofile [FNSIZE];
680 char *buf, *name = NULL;
681 JAR_Digest dig;
682 int line = 0;
683
684 strcpy (whofile, who);
685
686 if ((mf = fopen (manifile, "rb")) == NULL) {
687 perror (manifile);
688 exit (ERRX);
689 }
690
691 if ((sf = fopen (whofile, "wb")) == NULL) {
692 perror (who);
693 exit (ERRX);
694 }
695
696 buf = (char *) PORT_ZAlloc (BUFSIZ);
697
698 if (buf)
699 name = (char *) PORT_ZAlloc (BUFSIZ);
700
701 if (buf == NULL || name == NULL)
702 out_of_memory();
703
704 fprintf (sf, "Signature-Version: 1.0\n");
705 fprintf (sf, "Created-By: %s\n", CREATOR);
706 fprintf (sf, "Comments: %s\n", BREAKAGE);
707
708 if (fgets (buf, BUFSIZ, mf) == NULL) {
709 PR_fprintf(errorFD, "%s: empty manifest file!\n", PROGRAM_NAME);
710 errorCount++;
711 exit (ERRX);
712 }
713
714 if (strncmp (buf, "Manifest-Version:", 17)) {
715 PR_fprintf(errorFD, "%s: not a manifest file!\n", PROGRAM_NAME);
716 errorCount++;
717 exit (ERRX);
718 }
719
720 fseek (mf, 0L, SEEK_SET);
721
722 /* Process blocks of headers, and calculate their hashen */
723
724 while (1) {
725 /* Beginning range */
726 r1 = ftell (mf);
727
728 if (fgets (name, BUFSIZ, mf) == NULL)
729 break;
730
731 line++;
732
733 if (r1 != 0 && strncmp (name, "Name:", 5)) {
734 PR_fprintf(errorFD,
735 "warning: unexpected input in manifest file \"%s\" at line %d:\n",
736 manifile, line);
737 PR_fprintf(errorFD, "%s\n", name);
738 warningCount++;
739 }
740
741 r2 = r1;
742 while (fgets (buf, BUFSIZ, mf)) {
743 if (*buf == 0 || *buf == '\n' || *buf == '\r')
744 break;
745
746 line++;
747
748 /* Ending range for hashing */
749 r2 = ftell (mf);
750 }
751
752 r3 = ftell (mf);
753
754 if (r1) {
755 fprintf (sf, "\n");
756 fprintf (sf, "%s", name);
757 }
758
759 calculate_MD5_range (mf, r1, r2, &dig);
760
761 if (optimize == 0) {
762 fprintf (sf, "Digest-Algorithms: MD5 SHA1\n");
763 fprintf (sf, "MD5-Digest: %s\n",
764 BTOA_DataToAscii (dig.md5, MD5_LENGTH));
765 }
766
767 fprintf (sf, "SHA1-Digest: %s\n",
768 BTOA_DataToAscii (dig.sha1, SHA1_LENGTH));
769
770 /* restore normalcy after changing offset position */
771 fseek (mf, r3, SEEK_SET);
772 }
773
774 PORT_Free (buf);
775 PORT_Free (name);
776
777 fclose (sf);
778 fclose (mf);
779
780 return 0;
781 }
782
783
784 /*
785 * c a l c u l a t e _ M D 5 _ r a n g e
786 *
787 * Calculate the MD5 digest on a range of bytes in
788 * the specified fopen'd file. Returns base64.
789 *
790 */
791 static int
792 calculate_MD5_range (FILE *fp, long r1, long r2, JAR_Digest *dig)
793 {
794 int num;
795 int range;
796 unsigned char *buf;
797 SECStatus rv;
798
799 range = r2 - r1;
800
801 /* position to the beginning of range */
802 fseek (fp, r1, SEEK_SET);
803
804 buf = (unsigned char *) PORT_ZAlloc (range);
805 if (buf == NULL)
806 out_of_memory();
807
808 if ((num = fread (buf, 1, range, fp)) != range) {
809 PR_fprintf(errorFD, "%s: expected %d bytes, got %d\n", PROGRAM_NAME,
810 range, num);
811 errorCount++;
812 exit (ERRX);
813 }
814
815 rv = PK11_HashBuf(SEC_OID_MD5, dig->md5, buf, range);
816 if (rv == SECSuccess) {
817 rv =PK11_HashBuf(SEC_OID_SHA1, dig->sha1, buf, range);
818 }
819 if (rv != SECSuccess) {
820 PR_fprintf(errorFD, "%s: can't generate digest context\n",
821 PROGRAM_NAME);
822 errorCount++;
823 exit (ERRX);
824 }
825
826 PORT_Free (buf);
827
828 return 0;
829 }
830
831
832 static void SignOut (void *arg, const char *buf, unsigned long len)
833 {
834 fwrite (buf, len, 1, (FILE * ) arg);
835 }
836
837

mercurial