|
|
1.1.1.6 root 1: /* crypto.c - Cryptographic routines for PGP.
2: PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
1.1.1.7 root 3:
1.1.1.6 root 4: (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved.
5: The author assumes no liability for damages resulting from the use
6: of this software, even if the damage results from defects in this
7: software. No warranty is expressed or implied.
1.1.1.7 root 8:
1.1.1.6 root 9: Note that while most PGP source modules bear Philip Zimmermann's
10: copyright notice, many of them have been revised or entirely written
11: by contributors who frequently failed to put their names in their
12: code. Code that has been incorporated into PGP from other authors
13: was either originally published in the public domain or is used with
14: permission from the various authors.
1.1.1.7 root 15:
1.1.1.6 root 16: PGP is available for free to the public under certain restrictions.
17: See the PGP User's Guide (included in the release package) for
18: important information about licensing, patent restrictions on
19: certain algorithms, trademarks, copyrights, and export controls.
1.1.1.7 root 20:
1.1.1.6 root 21: Modified: 12-Nov-92 HAJK
22: Add FDL stuff for VAX/VMS local mode.
23: Reopen temporary files rather than create new version.
1.1.1.7 root 24:
1.1.1.6 root 25: Modified: 13-Dec-92 Derek Atkins <[email protected])
26: Added Multiple Recipients
1.1.1.7 root 27:
1.1.1.6 root 28: Modified 25-Feb-93 Colin Plumb
29: Improved security of randseed.bin in strong_pseudorandom.
30: Thoroughly revamped make_random_ideakey.
1.1.1.7 root 31:
1.1.1.6 root 32: Modified 6-May-93 Colin Plumb
33: Changed to use the entry points in rsaglue.c.
1.1.1.7 root 34: */
1.1.1.6 root 35:
36: #include <ctype.h>
37: #include <stdlib.h>
38: #include <stdio.h>
39: #include <string.h>
40: #include <time.h>
41:
42: #include "mpilib.h"
43: #include "mpiio.h"
44: #include "random.h"
45: #include "crypto.h"
46: #include "keymgmt.h"
47: #include "keymaint.h"
48: #include "mdfile.h"
49: #include "fileio.h"
50: #include "charset.h"
51: #include "language.h"
52: #include "pgp.h"
53: #include "exitpgp.h"
54: #include "zipup.h"
55: #include "rsaglue.h"
56: #include "idea.h"
57:
58: #define ENCRYPT_IT FALSE /* to pass to idea_file */
59: #define DECRYPT_IT TRUE /* to pass to idea_file */
60:
61: #define USE_LITERAL2
62:
63:
64: /* This variable stores the md5 hash of the current file, if it is
65: available. It is used in make_random_ideakey. */
66: static unsigned char md5buf[16];
67:
68: /* This flag is set if the buffer above has been filled. */
69: static char already_have_md5 = 0;
70:
71:
72: /* Used by encryptfile */
73: static int encryptkeyintofile(FILE *g, char *mcguffin, byte *keybuf,
74: char *keyfile, int ckp_length, int keys_used);
75:
76: #ifdef M_XENIX
77: long time();
78: #endif
79:
80: /*--------------------------------------------------------------------------*/
81:
82:
83: void CToPascal(char *s)
84: {
85: /* "xyz\0" --> "\3xyz" ... converts C string to Pascal string */
86: int i,j;
87: j = string_length(s);
88: for (i=j; i!=0; i--)
89: s[i] = s[i-1]; /* move everything 1 byte to the right */
90: s[0] = j; /* Pascal length byte at beginning */
91: } /* CToPascal */
92:
93:
94: void PascalToC( char *s )
95: {
96: /* "\3xyz" --> "xyz\0" ... converts Pascal string to C string */
97: int i,j;
98: for (i=0,j=((byte *) s)[0]; i<j; i++)
99: s[i] = s[i+1]; /* move everything 1 byte to the left */
100: s[i] = '\0'; /* append C string terminator */
101: } /* PascalToC */
102:
103:
104: /*
105: Note: On MSDOS, the time() function calculates GMT as the local
106: system time plus a built-in timezone correction, which defaults to
107: adding 7 hours (PDT) in the summer, or 8 hours (PST) in the winter,
108: assuming the center of the universe is on the US west coast. Really--
109: I'm not making this up! The only way to change this is by setting
110: the MSDOS environmental variable TZ to reflect your local time zone,
111: for example "set TZ=MST7MDT". This means add 7 hours during standard
112: time season, or 6 hours during daylight time season, and use MST and
113: MDT for the two names of the time zone. If you live in a place like
114: Arizona with no daylight savings time, use "set TZ=MST7". See the
115: Microsoft C function tzset(). Just in case your local software
116: environment is too weird to predict how to set environmental
117: variables for this, PGP also uses its own TZFIX variable in
118: config.pgp to optionally correct this problem further. For example,
119: set TZFIX=-1 in config.pgp if you live in Colorado and the TZ
120: variable is undefined.
121: */
122: word32 get_timestamp(byte *timestamp)
123: /* Return current timestamp as a byte array in internal byteorder,
124: and as a 32-bit word */
125: {
126: word32 t;
127: t = time(NULL); /* returns seconds since GMT 00:00 1 Jan 1970 */
128:
129: #ifdef _MSC_VER
130: #if (_MSC_VER == 700)
131: /* Under MSDOS and MSC 7.0, time() returns elapsed time since
132: * GMT 00:00 31 Dec 1899, instead of Unix's base date of 1 Jan 1970.
133: * So we must subtract 70 years worth of seconds to fix this.
134: * 6/19/92 rgb
135: */
136: #define LEAP_DAYS (((unsigned long)70L/4)+1)
1.1.1.7 root 137: #define CALENDAR_KLUDGE ((unsigned long)86400L * (((unsigned long)365L \
138: * 70L) + LEAP_DAYS))
1.1.1.6 root 139: t -= CALENDAR_KLUDGE;
140: #endif
141: #endif
142:
143: t += timeshift; /* timeshift derived from TZFIX in config.pgp */
144:
145: if (timestamp != NULL) {
146: /* first, fill array in external byte order: */
147: put_word32(t, timestamp);
1.1.1.7 root 148: convert_byteorder(timestamp,4);
149: /* convert to internal byteorder */
1.1.1.6 root 150: }
151:
152: return t; /* return 32-bit timestamp integer */
153: } /* get_timestamp */
154:
155:
156: /* Given timestamp as seconds elapsed since 1970 Jan 1 00:00:00,
157: returns year (1970-2106), month (1-12), day (1-31).
158: Not valid for dates after 2100 Feb 28 (no leap day that year).
159: Also returns day of week (0-6) as functional return.
160: */
1.1.1.7 root 161: static int date_ymd(word32 *tstamp, int *year, int *month, int *day)
1.1.1.6 root 162: {
163: word32 days,y;
164: int m,d,i;
165: static short mdays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
166: days = (*tstamp)/(unsigned long)86400L; /* day 0 is 1970/1/1 */
167: days -= 730L; /* align days relative to 1st leap year, 1972 */
168: y = ((days*4)/(unsigned long)1461L); /* 1972 is year 0 */
169: /* reduce to days elapsed since 1/1 last leap year: */
170: d = (int) (days - ((y/4)*1461L));
171: *year = (int)(y+1972);
172: for (i=0; i<48; i++) { /* count months 0-47 */
173: m = i % 12;
174: d -= mdays[m] + (i==1); /* i==1 is the only leap month */
175: if (d < 0) {
176: d += mdays[m] + (i==1);
177: break;
178: }
179: }
180: *month = m+1;
181: *day = d+1;
1.1.1.7 root 182: i = (int)((days-2) % (unsigned long)7L); /* compute day of week 0-6 */
1.1.1.6 root 183: return i; /* returns weekday 0-6; 0=Sunday, 6=Saturday */
184: } /* date_ymd */
185:
186:
187: /* Return date string, given pointer to 32-bit timestamp */
1.1.1.7 root 188: char *cdate(word32 *tstamp)
1.1.1.6 root 189: {
190: int month,day,year;
191: static char datebuf[20];
192: if (*tstamp == 0)
193: return " ";
194: (void) date_ymd(tstamp,&year,&month,&day);
195: sprintf(datebuf,"%4d/%02d/%02d", year, month, day);
196: return (datebuf);
197: } /* cdate */
198:
199:
200: /* Return date and time string, given pointer to 32-bit timestamp */
1.1.1.7 root 201: char *ctdate(word32 *tstamp)
1.1.1.6 root 202: {
203: int hours,minutes;
204: static char tdatebuf[40];
205: long seconds;
1.1.1.7 root 206: seconds = (*tstamp) % (unsigned long)86400L;
207: /* seconds past midnight today */
208: minutes = (int)((seconds+30L) / 60L);
209: /* round off to minutes past midnight */
210: hours = minutes / 60; /* hours past midnight */
211: minutes = minutes % 60; /* minutes past the hour */
1.1.1.6 root 212: sprintf(tdatebuf,"%s %02d:%02d GMT", cdate(tstamp), hours, minutes);
213: return (tdatebuf);
214: } /* ctdate */
215:
216:
217:
218: /* Warn user he if key in keyfile at position fp of length pktlen, belonging
219: * to userid, is untrusted. Return -1 if the user doesn't want to proceed.
220: */
1.1.1.7 root 221: static int warn_signatures(char *keyfile, long fp,
222: char *userid, boolean warn_only)
1.1.1.6 root 223: {
1.1.1.7 root 224: FILE *f;
225: long fpusr;
226: int usrpktlen;
227: byte keyctrl;
228: int trust_status = -1;
229:
230: keyctrl = KC_LEGIT_UNKNOWN; /* Assume the worst */
231: if (getpubuserid (keyfile, fp, (byte *) userid, &fpusr,
232: &usrpktlen, FALSE) >= 0)
233: {
234: f = fopen(keyfile, FOPRBIN);
235: fseek (f, fpusr+usrpktlen, SEEK_SET);
236: /* Read trust byte */
237: trust_status = read_trust(f, &keyctrl);
238: fseek(f, fp, SEEK_SET);
239: if (is_compromised(f)) {
240: CToPascal(userid);
241: fprintf(pgpout, "\n");
242: show_key(f, fp, 0);
243: fclose (f);
244: fprintf(pgpout,
245: LANG("\007\nWARNING: This key has been revoked by its owner,\n\
1.1.1.6 root 246: possibly because the secret key was compromised.\n"));
1.1.1.7 root 247: if (warn_only) {
248: /* this is only for checking signatures */
249: fprintf(pgpout,
250: LANG("This could mean that this signature is a forgery.\n"));
251: return 1;
252: } else { /* don't use it for encryption */
253: fprintf(pgpout,
254: LANG("You cannot use this revoked key.\n"));
255: return -1;
256: }
257: }
258: fclose (f);
259: }
260: CToPascal(userid);
261: if ((keyctrl & KC_LEGIT_MASK) != KC_LEGIT_COMPLETE) {
262: byte userid0[256];
263: PascalToC(userid);
264: strcpy ((char *) userid0, userid);
265: CToPascal(userid);
266:
267: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNKNOWN)
268: fprintf(pgpout,
269: LANG("\007\nWARNING: Because this public key is not certified with \
270: a trusted\nsignature, it is not known with high confidence that this \
271: public key\nactually belongs to: \"%s\".\n"),
272: LOCAL_CHARSET((char *)userid0));
273:
274: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNTRUSTED)
275: fprintf(pgpout,
276: LANG("\007\nWARNING: This public key is not trusted to actually belong \
277: to:\n\"%s\".\n"), LOCAL_CHARSET((char *)userid0));
1.1.1.6 root 278:
279: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_MARGINAL)
1.1.1.7 root 280: fprintf(pgpout,
281: LANG("\007\nWARNING: Because this public key is not certified with enough \
282: trusted\nsignatures, it is not known with high confidence that this \
283: public key\nactually belongs to: \"%s\".\n"),
284: LOCAL_CHARSET((char *)userid0));
1.1.1.6 root 285:
286: if (keyctrl & KC_WARNONLY) {
1.1.1.7 root 287: /* KC_WARNONLY bit already set,
288: user must have approved before. */
289: fprintf(pgpout,
290: LANG("But you previously approved using this public key anyway.\n"));
1.1.1.6 root 291: }
292:
1.1.1.7 root 293: if (!filter_mode && !batchmode && !warn_only
294: && !(keyctrl & KC_WARNONLY))
1.1.1.6 root 295: {
1.1.1.7 root 296: fprintf(pgpout,
297: LANG("\nAre you sure you want to use this public key (y/N)? "));
1.1.1.6 root 298: if (!getyesno('n'))
299: return -1;
1.1.1.7 root 300: if (trust_status == 0
301: && (f = fopen(keyfile, FOPRWBIN)) != NULL)
1.1.1.6 root 302: {
303: fseek (f, fpusr+usrpktlen, SEEK_SET);
304: keyctrl |= KC_WARNONLY;
305: write_trust(f, keyctrl);
306: fclose(f);
307: }
308: }
309: }
310: return 0;
311: } /* warn_signatures */
312:
313:
314: /* Used to determine if nesting should be allowed. */
1.1.1.7 root 315: boolean legal_ctb(byte ctb)
1.1.1.6 root 316: {
317: boolean legal;
318: byte ctbtype;
319: if (!is_ctb(ctb)) /* not even a bonafide CTB */
320: return FALSE;
321: /* Sure hope CTB internal bit definitions don't change... */
322: ctbtype = (ctb & CTB_TYPE_MASK) >> 2;
323: /* Only allow these CTB types to be nested... */
324: legal = ( (ctbtype==CTB_PKE_TYPE)
325: || (ctbtype==CTB_SKE_TYPE)
326: || (ctbtype==CTB_CERT_SECKEY_TYPE)
327: || (ctbtype==CTB_CERT_PUBKEY_TYPE)
328: || (ctbtype==CTB_LITERAL_TYPE)
329: || (ctbtype==CTB_LITERAL2_TYPE)
330: || (ctbtype==CTB_COMPRESSED_TYPE)
331: || (ctbtype==CTB_CKE_TYPE)
332: );
333: return legal;
334: } /* legal_ctb */
335:
336:
337: /* Return nonzero if val doesn't match checkval, after printing a
338: * warning.
339: */
340: int
341: version_error(int val, int checkval)
342: {
343: if (val != checkval) {
1.1.1.7 root 344: fprintf (pgpout,
345: LANG("\n\007Unsupported packet format - you need a newer version of PGP \
346: for this file.\n"));
1.1.1.6 root 347: return 1;
348: }
349: return 0;
350: }
351:
352: int
353: version_byte_error(int val)
354: {
1.1.1.8 ! root 355: if (val != VERSION_BYTE_OLD && val != VERSION_BYTE_NEW) {
1.1.1.7 root 356: fprintf (pgpout,
357: LANG("\n\007Unsupported packet format - you need a newer version of PGP \
358: for this file.\n"));
1.1.1.6 root 359: return 1;
360: }
361: return 0;
362: }
363:
364:
365: /*-------------------------------------------------------------------------*/
366:
367: #define RAND_PREFIX_LENGTH 8 /* Length of IV for IDEA encryption */
368:
369: /*
370: * Make a random IDEA key. Returns its length (the constant 16).
371: * It also generates a random IV, which is placed in the key array
372: * after the key proper, but is not counted in the length.
373: * Reads IDEA random key and random number seed from file, cranks the
374: * seed through the IDEA strong pseudorandom number generator,
375: * and writes them back out. This is used for generation of
376: * cryptographically strong pseudorandom numbers. This is mainly to
377: * save the user the trouble of having to type in lengthy keyboard
378: * sequences for generation of truly random numbers every time we want
379: * to make a random session key. This pseudorandom generator will only
380: * work if the file containing the random seed exists and is not empty.
381: * If this is not the case, it will be automatically created.
382: *
383: * The MD5 of the current file is used to "prewash" the random numbers,
384: * to make it more difficult for an attacker to predict the output.
385: *
386: * The "skip" parameter says to skip that many bytes at the beginning,
387: * used to generate a random IV only for conventional encryption.
388: */
1.1.1.7 root 389: static int make_random_ideakey(byte key[IDEAKEYSIZE+RAND_PREFIX_LENGTH],
390: int skip)
1.1.1.6 root 391: {
392: int count;
1.1.1.8 ! root 393: struct IdeaCfbContext cfb;
! 394: byte buf[10];
! 395:
! 396: ideaCfbInit(&cfb, md5buf);
! 397: burn(md5buf);
1.1.1.6 root 398:
1.1.1.8 ! root 399: if (cryptRandOpen(&cfb) < 0) {
1.1.1.6 root 400: fprintf(pgpout,LANG("Preparing random session key..."));
401:
402: /* get some random key bits */
403: trueRandAccum((IDEAKEYSIZE+RAND_PREFIX_LENGTH)*8);
404:
1.1.1.8 ! root 405: cryptRandInit(&cfb);
1.1.1.6 root 406: }
407:
408: /*
409: * Generate a good random IDEA key and initial vector. If we have
410: * no random bytes, the trueRandByte() part will be useless
411: */
412: count = IDEAKEYSIZE+RAND_PREFIX_LENGTH;
413: for (count = skip; count < IDEAKEYSIZE+RAND_PREFIX_LENGTH; count++)
414: key[count] = cryptRandByte() ^ trueRandByte();
415:
416: /*
417: * Write out a new randseed.bin. It is encrypted in precisely the
418: * same manner as the message itself, although the leading
419: * IV and check bytes are discarded. This "postwash" is to
420: * ensure that it's easier to decrypt the message directly than to
421: * try to figure out what the key was by examining the entrails
422: * of the random number generator state in randseed.bin.
423: */
1.1.1.8 ! root 424: ideaCfbInit(&cfb, key);
! 425: memcpy(buf, key, 8);
! 426: buf[8] = buf[6];
! 427: buf[9] = buf[7];
! 428: ideaCfbEncrypt(&cfb, buf, buf, 10);
! 429: ideaCfbSync(&cfb);
! 430:
! 431: /* Save out the washed session key */
! 432: cryptRandSave(&cfb);
! 433:
! 434: ideaCfbDestroy(&cfb);
1.1.1.6 root 435:
436: return IDEAKEYSIZE;
437: }
438:
439:
440: /* Returns the length of a packet according to the CTB and
441: the length field. */
1.1.1.7 root 442: word32 getpastlength(byte ctb, FILE *f)
1.1.1.6 root 443: {
444: word32 length;
445: unsigned int llength; /* length of length */
446: byte buf[8];
447:
448: fill0(buf,sizeof(buf));
449: length = 0L;
450: /* Use ctb length-of-length field... */
451: llength = ctb_llength(ctb); /* either 1, 2, 4, or 8 */
1.1.1.7 root 452: if (llength==8) /* 8 means no length field, assume huge length */
1.1.1.6 root 453: return -1L; /* return huge length */
454:
455: /* now read in the actual length field... */
456: if (fread((byteptr) buf,1,llength,f) < llength)
457: return (-2L); /* error -- read failure or premature eof */
458: /* convert length from external byteorder... */
459: if (llength==1)
460: length = (word32) buf[0];
461: if (llength==2)
462: length = (word32) fetch_word16(buf);
463: if (llength==4)
464: length = fetch_word32(buf);
465: return length;
466: } /* getpastlength */
467:
468:
469: /* Write a CTB with the appropriate length field. If big is true,
470: * always use a four-byte length field.
471: */
472: void write_ctb_len (FILE *f, byte ctb_type, word32 length, boolean big)
473: {
474: int llength, llenb;
475: byte ctb;
476: byte buf[4];
477:
478: if (big || (length > 0xFFFFL)) {
479: llength = 4;
480: llenb = 2;
481: } else if ((word16)length > 0xFF) {
482: llength = 2;
483: llenb = 1;
484: } else {
485: llength = 1;
486: llenb = 0;
487: }
488:
489: putc(CTB_BYTE(ctb_type, llenb), f);
490: /* convert length to external byteorder... */
491: if (llength==1)
492: buf[0] = length;
493: if (llength==2)
494: put_word16((word16) length, buf);
495: if (llength==4)
496: put_word32(length, buf);
497: fwrite( buf, 1, llength, f );
498: } /* write_ctb_len */
499:
500: /*
501: * Use IDEA in cipher feedback (CFB) mode to encrypt or decrypt a file.
502: * The encrypted material starts out with a 64-bit random prefix, which
503: * serves as an encrypted random CFB initialization vector, and
504: * following that is 16 bits of "key check" material, which is a
505: * duplicate of the last 2 bytes of the random prefix. Encrypted key
506: * check bytes detect if correct IDEA key was used to decrypt ciphertext.
507: */
1.1.1.7 root 508: static
509: int idea_file(byte *ideakey, boolean decryp, FILE *f, FILE *g, word32 lenfile)
1.1.1.6 root 510: {
511: int count, status = 0;
512: extern byte textbuf[DISKBUFSIZE];
513: struct IdeaCfbContext cfb;
514: #define RAND_PREFIX_LENGTH 8
515:
516: /* init CFB key */
517: ideaCfbInit(&cfb, ideakey);
518:
519: if (!decryp) { /* encrypt-- insert key check bytes */
520: /* There is a random prefix followed by 2 key check bytes */
521:
522: memcpy(textbuf, ideakey+IDEAKEYSIZE, RAND_PREFIX_LENGTH);
1.1.1.7 root 523: /* key check bytes are simply duplicates of final 2 random bytes */
1.1.1.6 root 524: textbuf[RAND_PREFIX_LENGTH] = textbuf[RAND_PREFIX_LENGTH-2];
525: textbuf[RAND_PREFIX_LENGTH+1] = textbuf[RAND_PREFIX_LENGTH-1];
526:
527: ideaCfbEncrypt(&cfb, textbuf, textbuf, RAND_PREFIX_LENGTH+2);
528: fwrite(textbuf,1,RAND_PREFIX_LENGTH+2,g);
529: } else { /* decrypt-- check for key check bytes */
530: /* See if the redundancy is present after the random prefix */
531: count = fread(textbuf,1,RAND_PREFIX_LENGTH+2,f);
532: lenfile -= count;
533: if (count==(RAND_PREFIX_LENGTH+2)) {
1.1.1.7 root 534: ideaCfbDecrypt(&cfb, textbuf, textbuf,
535: RAND_PREFIX_LENGTH+2);
536: if ((textbuf[RAND_PREFIX_LENGTH] !=
537: textbuf[RAND_PREFIX_LENGTH-2])
538: || (textbuf[RAND_PREFIX_LENGTH+1] !=
539: textbuf[RAND_PREFIX_LENGTH-1]))
1.1.1.6 root 540: {
541: status = -2; /* bad key error */
542: }
543: } else /* file too short for key check bytes */
544: status = -3; /* error of the weird kind */
545: }
546:
547: ideaCfbSync(&cfb);
548:
549: /* read and write the whole file in CFB mode... */
550: count = (lenfile < DISKBUFSIZE) ? (int)lenfile : DISKBUFSIZE;
551: while (count && status == 0) {
552: if ((count = fread(textbuf,1,count,f)) <= 0) {
553: status = -3;
554: break;
555: }
556: lenfile -= count;
557: if (decryp)
558: ideaCfbDecrypt(&cfb, textbuf, textbuf, count);
559: else
560: ideaCfbEncrypt(&cfb, textbuf, textbuf, count);
561: if (fwrite(textbuf,1,count,g) != count)
562: status = -3;
563: count = (lenfile < DISKBUFSIZE) ? (int)lenfile : DISKBUFSIZE;
564: }
565:
566: ideaCfbDestroy(&cfb); /* Clean up data structures */
567: burn(textbuf); /* burn sensitive data on stack */
568: return status; /* should always take normal return */
569: } /* idea_file */
570:
571:
572: /* Checksum maintained as a running sum by read_mpi and write_mpi.
573: * The checksum is maintained based on the plaintext values being
574: * read and written. To use it, store a 0 to it before doing a set
575: * of read_mpi's or write_mpi's. Then read it aftwerwards.
576: */
577: word16 mpi_checksum;
578:
579: /*
580: * Read a mutiprecision integer from a file.
581: * adjust_precision is TRUE iff we should call set_precision to the
582: * size of the number read in.
583: * scrambled is TRUE iff field is encrypted (protects secret key fields).
584: * Returns the bitcount of the number read in, or returns a negative
585: * number if an error is detected.
586: */
1.1.1.7 root 587: int read_mpi(unitptr r, FILE *f, boolean adjust_precision,
588: struct IdeaCfbContext *cfb)
1.1.1.6 root 589: {
590: byte buf[MAX_BYTE_PRECISION+2];
591: unsigned int count;
592: word16 bytecount,bitcount;
593:
594: mp_init(r,0);
595:
596: if ((count = fread(buf,1,2,f)) < 2)
597: return (-1); /* error -- read failure or premature eof */
598:
599: bitcount = fetch_word16(buf);
600: if (bits2units(bitcount) > global_precision)
601: return -1; /* error -- possible corrupted bitcount */
602:
603: bytecount = bits2bytes(bitcount);
604:
605: count = fread(buf+2,1,bytecount,f);
606: if (count < bytecount)
607: return -1; /* error -- premature eof */
608:
609: if (cfb) { /* decrypt the field */
610: ideaCfbSync(cfb);
611: ideaCfbDecrypt(cfb, buf+2, buf+2, bytecount);
612: }
613:
614: /* Update running checksum, in case anyone cares... */
615: mpi_checksum += checksum (buf, bytecount+2);
616:
617: /* We assume that the bitcount prefix we read is an exact
618: bitcount, not rounded up to the next byte boundary.
619: Otherwise we would have to call mpi2reg, then call
620: countbits, then call set_precision, then recall mpi2reg
621: again.
622: */
623: if (adjust_precision && bytecount) {
624: /* set the precision to that specified by the number read. */
625: if (bitcount > MAX_BIT_PRECISION-SLOP_BITS)
626: return -1;
627: set_precision(bits2units(bitcount+SLOP_BITS));
628: /* Now that precision is optimally set, call mpi2reg */
629: }
630:
631: if (mpi2reg(r,buf) == -1) /* convert to internal format */
632: return -1;
633: burn(buf); /* burn sensitive data on stack */
634: return (bitcount);
635: } /* read_mpi */
636:
637:
638:
639: /*
640: * Write a multiprecision integer to a file.
641: * scrambled is TRUE iff we should scramble field on the way out,
642: * which is used to protect secret key fields.
643: */
1.1.1.7 root 644: void write_mpi(unitptr n, FILE *f, struct IdeaCfbContext *cfb)
1.1.1.6 root 645: {
646: byte buf[MAX_BYTE_PRECISION+2];
647: short bytecount;
648: bytecount = reg2mpi(buf,n);
649: mpi_checksum += checksum (buf, bytecount+2);
650: if (cfb) { /* encrypt the field, skipping over the bitcount */
651: ideaCfbSync(cfb);
652: ideaCfbEncrypt(cfb, buf+2, buf+2, bytecount);
653: }
654: fwrite(buf,1,bytecount+2,f);
655: burn(buf); /* burn sensitive data on stack */
656: } /* write_mpi */
657:
658: /*======================================================================*/
659:
660: /* Reads the first count bytes from infile into header. */
1.1.1.7 root 661: int get_header_info_from_file(char *infile, byte *header, int count)
1.1.1.6 root 662: {
663: FILE *f;
664: fill0(header,count);
665: /* open file f for read, in binary (not text) mode...*/
666: if ((f = fopen(infile,FOPRBIN)) == NULL)
667: return -1;
668: /* read Cipher Type Byte, and maybe more */
669: count = fread(header,1,count,f);
670: fclose(f);
671: return count; /* normal return */
672: } /* get_header_info_from_file */
673:
674:
675: /* System clock must be broken if it isn't past this date: */
676: #define REASONABLE_DATE ((unsigned long) 0x27804180L) /* 91 Jan 01 00:00:00 */
677:
678:
679: /* Constructs a signed message digest in a signature certificate.
680: Returns total certificate length in bytes, or returns negative
681: error status.
682: */
1.1.1.7 root 683: static
684: int make_signature_certificate(byte *certificate, struct MD5Context *MD,
685: byte class, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u,
686: unitptr n)
1.1.1.6 root 687: {
688: byte inbuf[MAX_BYTE_PRECISION], outbuf[MAX_BYTE_PRECISION];
689: int i, j, certificate_length, blocksize,bytecount;
690: word16 ske_length;
691: word32 tstamp; byte *timestamp = (byte *) &tstamp;
692: byte keyID[KEYFRAGSIZE];
693: byte val;
694: int mdlen = 5; /* length of class plus timestamp, for adding to MD */
695:
696: /* Note that RSA key must be at least big enough to encipher a
697: complete message digest packet in a single RSA block. */
698:
699: blocksize = countbytes(n)-1; /* size of a plaintext block */
700: if (blocksize < 31) {
1.1.1.7 root 701: fprintf(pgpout,
702: "\n\007Error: RSA key length must be at least 256 bits.\n");
1.1.1.6 root 703: return -1;
704: }
705:
1.1.1.7 root 706: get_timestamp(timestamp); /* Timestamp when signature was
707: made */
1.1.1.6 root 708: if (tstamp < REASONABLE_DATE) {
709: /* complain about bad time/date setting */
1.1.1.7 root 710: fprintf(pgpout,
711: LANG("\n\007Error: System clock/calendar is set wrong.\n"));
1.1.1.6 root 712: return -1;
713: }
714: convert_byteorder(timestamp,4); /* convert to external form */
715:
1.1.1.7 root 716: /* Finish off message digest calculation with this information */
1.1.1.6 root 717: MD_addbuffer (MD, &class, 1, 0);
718: MD_addbuffer (MD, timestamp, 4, md5buf);
719: /* We wrote the digest to a static variable because we want to keep it around
720: for random number generation later. Also make a note of that fact. */
721: already_have_md5 = 1;
722:
723: if (!quietmode) {
1.1.1.7 root 724: fprintf(pgpout,LANG("Just a moment...")); /* RSA will take
725: a while. */
1.1.1.6 root 726: fflush(pgpout);
727: }
728:
729: /* do RSA signature calculation: */
730: i = rsa_private_encrypt((unitptr)outbuf, md5buf, sizeof(md5buf),
731: e, d, p, q, u, n);
732: if (i < 0) {
733: if (i == -4) {
1.1.1.7 root 734: fprintf(pgpout,
735: "\n\007Error: RSA key length must be at least 256 bits.\n");
1.1.1.6 root 736: } else if (i == -3) {
1.1.1.7 root 737: fputs(
738: LANG("\a\nError: key is too large. RSA keys may be no longer than 1024 \
739: bits,\ndue to limitations imposed by software provided by RSADSI.\n"), pgpout);
1.1.1.6 root 740: } else {
1.1.1.7 root 741: fprintf(pgpout,"\a\nUnexpected error %d signing\n", i);
1.1.1.6 root 742: }
743: return i;
744: }
745:
746: /* bytecount does not include the 2 prefix bytes */
1.1.1.7 root 747: bytecount = reg2mpi(outbuf,(unitptr)outbuf); /* convert to external
748: format */
1.1.1.6 root 749: /* outbuf now contains a message digest in external byteorder
750: form. Now make a complete signature certificate from this.
751: (Note that the first two bytes of md5buf are used below as
752: part of the certificate.)
753: */
754:
755: certificate_length = 0;
756:
1.1.1.7 root 757: /* SKE is Secret Key Encryption (signed). Append CTB for signed msg. */
1.1.1.6 root 758: certificate[certificate_length++] = CTB_SKE;
759:
1.1.1.7 root 760: /* SKE packet length does not include itself or CTB prefix: */
761: ske_length = 1 + 1 /* version and mdlen byte */
762: + mdlen /* class, timestamp and validation period */
763: + KEYFRAGSIZE + 1 + 1 /* Key ID and 2 algorithm bytes */
764: + 2 + bytecount+2; /* 2 MD bytes and RSA MPI w/bitcount */
1.1.1.6 root 765: put_word16((word16) ske_length, certificate+certificate_length);
766: certificate_length+=2; /* advance past word */
767:
768: certificate[certificate_length++] = version_byte;
769:
770: /* Begin fields that are included in MD calculation... */
771:
1.1.1.7 root 772: certificate[certificate_length++] = mdlen; /* mdlen is length
773: of MD-extras */
1.1.1.6 root 774:
775: certificate[certificate_length++] = class & 0xff;
776:
777: /* timestamp already in external format */
778: for (j=0; j<SIZEOF_TIMESTAMP; j++)
779: certificate[certificate_length++] = timestamp[j];
780:
781: /* ...end of fields that are included in MD calculation */
782:
783: /* Now append keyID... */
784: extract_keyID(keyID, n); /* gets keyID */
785: for (i=0; i<KEYFRAGSIZE; i++)
786: certificate[certificate_length++] = keyID[i];
787:
788: certificate[certificate_length++] = RSA_ALGORITHM_BYTE;
789: certificate[certificate_length++] = MD5_ALGORITHM_BYTE;
790:
791: /* Now append first two bytes of message digest */
792: certificate[certificate_length++] = md5buf[0];
793: certificate[certificate_length++] = md5buf[1];;
794:
795: /* Now append the RSA-signed message digest packet: */
796: for (i=0; i<bytecount+2; i++)
797: certificate[certificate_length++] = outbuf[i];
798:
799: if (!quietmode)
800: fputc('.',pgpout); /* Signal RSA signature completion. */
801:
802: burn(inbuf); /* burn sensitive data on stack */
803: burn(outbuf); /* burn sensitive data on stack */
804:
1.1.1.7 root 805: return certificate_length; /* return length of certificate in bytes */
1.1.1.6 root 806:
807: } /* make_signature_certificate */
808:
809:
810: #ifdef VMS
811: /*
1.1.1.7 root 812: * Local mode VMS, we write out the word VMS to say who owns the data then
813: * we follow that with the file's FDL generated earlier by fdl_generate().
814: * This FDL is preceded by a sixteen bit size. The file follows.
1.1.1.6 root 815: */
1.1.1.7 root 816: void write_litlocal(FILE *g, char *fdl, short fdl_len)
817: {
1.1.1.6 root 818: fputc('\0', g); /* Kludge for null literal file name (supplied by FDL) */
819: fputs("VMS ", g);
1.1.1.7 root 820: fwrite(&fdl_len, 2, 1, g); /* Byte order *not* important,
821: only VMS reads this!*/
1.1.1.6 root 822: fwrite(fdl, 1, fdl_len, g);
823: }
824: #endif /* VMS */
825:
826: /*======================================================================*/
827:
828:
829: /* Write an RSA-signed message digest of input file to specified
830: output file, and append input file to output file.
831: separate_signature is TRUE iff we should not append the
832: plaintext to the output signature certificate.
833: If lit_mode is MODE_TEXT, we know the infile is in canonical form.
834: We create a CTB_LITERAL packet for the plaintext data.
835: */
1.1.1.7 root 836: int signfile(boolean nested, boolean separate_signature,
837: char *mcguffin, char *infile, char *outfile,
838: char lit_mode, char *literalfile)
1.1.1.6 root 839: {
840: FILE *f;
841: FILE *g;
842: int certificate_length; /* signature certificate length */
843: byte certificate[MAX_SIGCERT_LENGTH];
844: char lfile[MAX_PATH];
845: byte signature_class;
846: #ifdef VMS
847: char *fdl;
848: short fdl_len;
849: #endif /* VMS */
850:
851:
852: { /* temporary scope for some buffers */
853: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
854: byte userid[256];
855: char keyfile[MAX_PATH];
856: int status;
857: struct MD5Context MD;
858: byte keyID[KEYFRAGSIZE];
1.1.1.7 root 859: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
860: unit d[MAX_UNIT_PRECISION];
861: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION];
862: unit u[MAX_UNIT_PRECISION];
1.1.1.6 root 863:
1.1.1.7 root 864: set_precision(MAX_UNIT_PRECISION);/* safest opening
865: assumption */
1.1.1.6 root 866:
867: if (verbose)
1.1.1.7 root 868: fprintf(pgpout,
869: "signfile: infile = '%s', outfile = '%s', mode = '%c', literalfile = '%s'\n",
1.1.1.6 root 870: infile,outfile,lit_mode,literalfile);
871:
872: if (MDfile(&MD, infile) < 0)
1.1.1.7 root 873: return -1; /* problem with input file. error return */
1.1.1.6 root 874:
875: userid[0] = '\0';
876: if (mcguffin)
1.1.1.7 root 877: strcpy((char *) userid,mcguffin); /* Who we are
878: looking for */
1.1.1.6 root 879:
880: if (getsecretkey(0, NULL, NULL, timestamp, NULL, NULL,
881: userid, n, e, d, p, q, u) < 0)
1.1.1.7 root 882: return -1; /* problem with secret key file.
883: error return. */
1.1.1.6 root 884:
885: extract_keyID(keyID, n);
886: strcpy(keyfile, globalPubringName); /* use default pathname */
1.1.1.7 root 887: if ((status = getpublickey(GPK_SHOW|GPK_NORVK, keyfile,
888: NULL, NULL, keyID,
1.1.1.6 root 889: timestamp, userid, n, e)) < 0)
1.1.1.7 root 890: return -1; /* problem with public key file.
891: error return. */
1.1.1.6 root 892:
893: if (lit_mode==MODE_TEXT) signature_class = SM_SIGNATURE_BYTE;
894: else signature_class = SB_SIGNATURE_BYTE;
895:
1.1.1.7 root 896: certificate_length = make_signature_certificate(certificate,
897: &MD,
1.1.1.6 root 898: signature_class, e, d, p, q, u, n);
899: if (certificate_length < 0)
1.1.1.7 root 900: return -1; /* error return from
901: make_signature_certificate() */
1.1.1.6 root 902: } /* end of scope for some buffers */
903:
904: /* open file f for read, in binary (not text) mode...*/
905: #ifdef VMS
906: if (lit_mode == MODE_LOCAL) {
907: if (!(fdl_generate(infile, &fdl, &fdl_len ) & 01)) {
1.1.1.7 root 908: fprintf(pgpout,
909: LANG("\n\007Can't open input plaintext file '%s'\n"),infile);
1.1.1.6 root 910: return -1;
911: }
912: }
913: #endif /* VMS */
914: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 915: fprintf(pgpout,
916: LANG("\n\007Can't open plaintext file '%s'\n"),infile);
1.1.1.6 root 917: return -1;
918: }
919:
920: /* open file g for write, in binary (not text) mode...*/
921: if ((g = fopen(outfile,FOPWBIN)) == NULL) {
1.1.1.7 root 922: fprintf(pgpout,
923: LANG("\n\007Can't create signature file '%s'\n"),outfile);
1.1.1.6 root 924: fclose(f);
925: return -1;
926: }
927:
928: /* write out certificate record to outfile ... */
929: fwrite(certificate,1,certificate_length,g);
930:
931: if (literalfile == NULL) {
932: /* Put in a zero byte to indicate no filename */
933: lfile[0] = '\0';
934: } else {
935: strcpy( lfile, literalfile );
936: file_to_canon( lfile );
937: CToPascal( lfile );
938: }
939:
940: if (!separate_signature) {
941: if (!nested) {
942: word32 flen = fsize(f);
943: word32 dummystamp = 0;
944: if (lit_mode == MODE_LOCAL)
945: #ifdef VMS
946: write_ctb_len(g, CTB_LITERAL2_TYPE,
1.1.1.7 root 947: flen + fdl_len + sizeof(fdl_len) + 6,
948: TRUE);
1.1.1.6 root 949: #else
950: /* debug check: should never get here */
951: fprintf(pgpout, "signfile: invalid mode\n");
952: #endif
953: else {
954: #ifdef USE_LITERAL2
1.1.1.7 root 955: write_ctb_len (g, CTB_LITERAL2_TYPE,
956: flen + (unsigned char) lfile[0]
957: + 6, FALSE);
1.1.1.6 root 958: #else
959: write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
960: #endif /* USE_LITERAL2 */
961: }
962: putc(lit_mode, g); /* write lit_mode */
963: if (lit_mode == MODE_LOCAL) {
964: #ifdef VMS
965: write_litlocal( g, fdl, fdl_len);
966: free(fdl);
967: #endif /* VMS */
968: } else {
969: /* write literalfile name */
1.1.1.7 root 970: fwrite (lfile, 1, (unsigned char) lfile[0]+1,
971: g);
1.1.1.6 root 972: /* Dummy file creation timestamp */
973: fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
974: }
975: }
1.1.1.7 root 976: copyfile(f,g,-1L); /* copy rest of file from file f to g */
1.1.1.6 root 977: }
978:
979: fclose(f);
980: if (write_error(g)) {
981: fclose(g);
982: return -1;
983: }
984: fclose(g);
985: return 0; /* normal return */
986:
987: } /* signfile */
988:
989: /*======================================================================*/
990:
991: int compromise(byte *keyID, char *keyfile)
992: {
993: FILE *f, *g;
994: byte ctb; /* Cipher Type Byte */
995: int certificate_length; /* signature certificate length */
996: byte certificate[MAX_SIGCERT_LENGTH];
997: word32 tstamp; byte *timestamp = (byte *) &tstamp;
998: byte userid[256];
999: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1000: struct MD5Context MD;
1001: unit d[MAX_UNIT_PRECISION];
1.1.1.7 root 1002: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION];
1003: unit u[MAX_UNIT_PRECISION];
1.1.1.6 root 1004: long fp, insertpos;
1005: int pktlen;
1006: int prec;
1007: char *scratchf;
1008:
1009: setoutdir(keyfile);
1010: scratchf = tempfile(0);
1011:
1012: if (getsecretkey(0, NULL, keyID, timestamp, NULL, NULL,
1013: userid, n, e, d, p, q, u) < 0)
1.1.1.7 root 1014: return -1; /* problem with secret key file.
1015: error return. */
1.1.1.6 root 1016:
1017: if (getpublickey(0, keyfile, &fp, &pktlen, keyID,
1018: timestamp, userid, n, e) < 0)
1019: return -1;
1020:
1021: /* open file f for read, in binary (not text) mode...*/
1022: if ((f = fopen(keyfile,FOPRBIN)) == NULL) {
1.1.1.7 root 1023: fprintf(pgpout,
1024: LANG("\n\007Can't open key ring file '%s'\n"),keyfile);
1.1.1.6 root 1025: return -1;
1026: }
1027:
1028: fseek (f, fp+pktlen, SEEK_SET);
1029: nextkeypacket(f, &ctb);
1030: if (ctb == CTB_KEYCTRL) {
1031: insertpos = ftell(f);
1032: nextkeypacket(f, &ctb);
1033: } else {
1034: insertpos = fp + pktlen;
1035: }
1036:
1037: if (is_ctb_type(ctb, CTB_SKE_TYPE)) {
1038: fprintf(pgpout, LANG("This key has already been revoked.\n"));
1039: fclose(f);
1040: return -1;
1041: }
1042:
1043: prec = global_precision;
1044: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1045:
1046: fseek(f, fp, SEEK_SET);
1047: /* Calculate signature */
1048: if (MDfile0_len(&MD, f, pktlen) < 0) {
1049: fclose(f);
1050: return -1; /* problem with input file. error return */
1051: }
1052: set_precision(prec);
1053:
1054: certificate_length = make_signature_certificate(certificate, &MD,
1055: KC_SIGNATURE_BYTE, e, d, p, q, u, n);
1056: if (certificate_length < 0) {
1057: fclose(f);
1.1.1.7 root 1058: return -1; /* error return from
1059: make_signature_certificate() */
1.1.1.6 root 1060: }
1061:
1062:
1063: /* open file g for write, in binary (not text) mode...*/
1064: if ((g = fopen(scratchf,FOPWBIN)) == NULL) {
1.1.1.7 root 1065: fprintf(pgpout,
1066: LANG("\n\007Can't create output file to update key ring.\n"));
1.1.1.6 root 1067: fclose(f);
1068: return -1;
1069: }
1070:
1071: /* Copy pre-key and key to file g */
1072: rewind(f);
1073: copyfile (f, g, insertpos);
1074:
1075: /* write out certificate record to outfile ... */
1076: fwrite(certificate,1,certificate_length,g);
1077:
1078: /* Copy the remainder from file f to file g */
1079: copyfile (f, g, -1L);
1.1.1.8 ! root 1080:
! 1081: fclose(f);
1.1.1.6 root 1082:
1083: if (write_error(g)) {
1084: fclose(g);
1085: return -1;
1086: }
1087: fclose(g);
1088:
1089: savetempbak(scratchf,keyfile);
1090:
1091: fprintf(pgpout, LANG("\nKey compromise certificate created.\n"));
1092: return 0; /* normal return */
1093: } /* compromise */
1094:
1095: /*======================================================================*/
1096:
1097: /*
1098: * Write an RSA-signed message digest of key for user keyguffin in
1099: * keyfile, using signature from user sigguffin. Append
1100: * the signature right after the key.
1101: */
1.1.1.7 root 1102: int signkey(char *keyguffin, char *sigguffin, char *keyfile)
1.1.1.6 root 1103: {
1104: FILE *f;
1105: FILE *g;
1106: byte ctb; /* Cipher Type Byte */
1107: int certificate_length; /* signature certificate length */
1108: byte certificate[MAX_SIGCERT_LENGTH];
1109: byte keyID[KEYFRAGSIZE], keyID2[KEYFRAGSIZE];
1110: word32 tstamp; byte *timestamp = (byte *) &tstamp;
1111: byte userid[256];
1112: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1113: long fp, fpusr;
1114: int pktlen, usrpktlen, usrctrllen;
1115: char *tempring;
1116: int status;
1117:
1118: /* Get signature key ID */
1119: strcpy((char *)userid,sigguffin); /* Who we are looking for */
1120: status = getsecretkey(0, NULL, NULL, timestamp, NULL, NULL,
1121: userid, n, e, NULL, NULL, NULL, NULL);
1122: if (status < 0)
1123: return -1; /* problem with secret key file. error return. */
1124: extract_keyID(keyID, n); /* Remember signer key ID */
1125:
1126: /* Check that the public key exists in the destination keyring */
1127: status = getpublickey(GPK_NORVK|GPK_GIVEUP, keyfile, &fp, &pktlen,
1128: keyID, timestamp, userid, n, e);
1129: if (status < 0) {
1130: PascalToC((char *)userid);
1131: fprintf(pgpout, LANG("\nError: Key for signing userid '%s'\n\
1132: does not appear in public keyring '%s'.\n\
1133: Thus, a signature made with this key cannot be checked on this keyring.\n"),
1134: userid, keyfile);
1.1.1.7 root 1135: return -1; /* problem with public key file.
1136: error return. */
1.1.1.6 root 1137: }
1138:
1139: strcpy((char *)userid, keyguffin);
1140: fprintf(pgpout, LANG("\nLooking for key for user '%s':\n"),
1141: LOCAL_CHARSET((char *)userid));
1142:
1143: status = getpublickey(GPK_SHOW|GPK_NORVK, keyfile, &fp, &pktlen, NULL,
1144: timestamp, userid, n, e);
1.1.1.7 root 1145: showKeyHash(n, e);
1.1.1.6 root 1146: if (status < 0)
1147: return -1;
1148: PascalToC((char *) userid);
1149: status = getpubuserid(keyfile, fp, (byte *)keyguffin, &fpusr,
1150: &usrpktlen, FALSE);
1151: if (status < 0)
1152: return -1;
1153:
1154: /* open file f for read, in binary (not text) mode...*/
1155: f = fopen(keyfile,FOPRBIN);
1156: if (f == NULL) {
1.1.1.7 root 1157: fprintf(pgpout,
1158: LANG("\n\007Can't open key ring file '%s'\n"),keyfile);
1.1.1.6 root 1159: return -1;
1160: }
1161:
1162: /* See if there is another signature with this keyID already */
1163: fseek (f, fpusr+usrpktlen, SEEK_SET);
1164: nextkeypacket(f, &ctb); /* Add key control packet to len */
1165: usrctrllen = 0;
1166: if (ctb != CTB_KEYCTRL)
1167: fseek(f,fpusr+usrpktlen,SEEK_SET);
1168: else
1169: usrctrllen = (int) (ftell(f) - (fpusr+usrpktlen));
1170: for (;;) {
1171: status = readkeypacket(f,FALSE,&ctb,NULL,NULL,NULL,NULL,
1172: NULL,NULL,NULL,NULL,keyID2,NULL);
1173: if (status < 0 || is_key_ctb (ctb) || ctb==CTB_USERID)
1174: break;
1175: if (equal_buffers(keyID, keyID2, KEYFRAGSIZE)) {
1.1.1.7 root 1176: fprintf(pgpout,
1177: LANG("\n\007Key is already signed by user '%s'.\n"),
1.1.1.6 root 1178: LOCAL_CHARSET(sigguffin));
1179: fclose(f);
1180: return -1;
1181: }
1182: }
1183: rewind(f);
1184:
1185: if (!batchmode) {
1186: fprintf(pgpout,
1.1.1.7 root 1187: LANG("\n\nREAD CAREFULLY: Based on your own direct first-hand knowledge, \
1188: are\nyou absolutely certain that you are prepared to solemnly certify \
1189: that\nthe above public key actually belongs to the user specified by \
1190: the\nabove user ID (y/N)? "));
1.1.1.6 root 1191: if (!getyesno('n')) {
1192: fclose(f);
1193: return -1;
1194: }
1195: }
1196:
1197: { /* temporary scope for some buffers */
1198: struct MD5Context MD;
1199: unit d[MAX_UNIT_PRECISION], p[MAX_UNIT_PRECISION];
1200: unit q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
1201:
1.1.1.7 root 1202: set_precision(MAX_UNIT_PRECISION); /* safest opening
1203: assumption */
1.1.1.6 root 1204:
1205: if ((g = fopen(keyfile,FOPRBIN)) == NULL) {
1.1.1.8 ! root 1206: fclose(f);
1.1.1.7 root 1207: fprintf(pgpout,
1208: LANG("\n\007Can't open key ring file '%s'\n"),keyfile);
1.1.1.6 root 1209: return -1;
1210: }
1211: fseek(g, fp, SEEK_SET);
1212: /* Calculate signature */
1213: if (MDfile0_len(&MD, g, pktlen) < 0) {
1214: fclose(g);
1215: fclose(f);
1.1.1.7 root 1216: return -1; /* problem with input file.
1217: error return */
1.1.1.6 root 1218: }
1219: fclose(g);
1220:
1221: /* Add data from user id */
1222: CToPascal((char *)userid);
1223: MD5Update(&MD, userid+1, (int)(unsigned char)userid[0]);
1224:
1.1.1.7 root 1225: strcpy((char *)userid,sigguffin); /* Who we are looking for */
1.1.1.6 root 1226:
1227: /* Make sure that we DONT use the internal password to
1228: * get the secret key! This way you need to type your
1229: * pass phrase every time you come to this point!
1230: * Derek Atkins <[email protected]> 93-02-25
1.1.1.7 root 1231: *
1232: * If batchmode, then let it use the passed-in password,
1233: * for signing agents.
1234: * Derek Atkins <[email protected]> 94-06-20
1.1.1.6 root 1235: */
1.1.1.7 root 1236: if (getsecretkey((batchmode ? 0 : GPK_ASKPASS), NULL, NULL,
1237: timestamp, NULL, NULL,
1.1.1.6 root 1238: userid, n, e, d, p, q, u) < 0)
1239: {
1240: fclose(f);
1.1.1.7 root 1241: return -1; /* problem with secret key file.
1242: error return. */
1.1.1.6 root 1243: }
1244:
1.1.1.7 root 1245: certificate_length =
1246: make_signature_certificate(certificate, &MD,
1247: K0_SIGNATURE_BYTE, e, d, p, q,
1248: u, n);
1.1.1.8 ! root 1249: if (certificate_length < 0) {
! 1250: fclose(f);
1.1.1.7 root 1251: return -1; /* error return from
1252: make_signature_certificate() */
1.1.1.8 ! root 1253: }
1.1.1.6 root 1254:
1255: } /* end of scope for some buffers */
1256:
1257: /* open file g for write, in binary (not text) mode...*/
1258: tempring = tempfile(TMP_TMPDIR);
1259: if ((g = fopen(tempring,FOPWBIN)) == NULL) {
1.1.1.7 root 1260: fprintf(pgpout,
1261: LANG("\n\007Can't create output file to update key ring.\n"));
1.1.1.6 root 1262: fclose(f);
1263: return -1;
1264: }
1265:
1266: /* Copy pre-key and key to file g */
1267: copyfile (f, g, fpusr+usrpktlen+usrctrllen);
1268:
1269: /* write out certificate record to outfile ... */
1270: fwrite(certificate,1,certificate_length,g);
1271:
1272: /* Add "trusty" control packet */
1273: write_trust (g, KC_SIGTRUST_ULTIMATE|KC_CONTIG|KC_SIG_CHECKED);
1274:
1275: /* Copy the remainder from file f to file g */
1276: copyfile (f, g, -1L);
1277:
1278: fclose(f);
1279: if (write_error(g)) {
1280: fclose(g);
1281: return -1;
1282: }
1283: fclose(g);
1284:
1285: savetempbak(tempring,keyfile);
1286:
1287: fprintf(pgpout, LANG("\nKey signature certificate added.\n"));
1288: return 0; /* normal return */
1289:
1290: } /* signkey */
1291:
1292: /*======================================================================*/
1293:
1294: /* Check signature in infile for validity. Strip off the signature
1295: * and write the remaining packet to outfile. If strip_signature,
1296: * also write the signature to outfile.sig.
1297: * the original filename is stored in preserved_name
1298: */
1.1.1.7 root 1299: int check_signaturefile(char *infile, char *outfile, boolean strip_signature,
1300: char *preserved_name)
1.1.1.6 root 1301: {
1302: byte ctb,ctb2=0; /* Cipher Type Bytes */
1303: char keyfile[MAX_PATH]; /* for getpublickey */
1304: char sigfile[MAX_PATH]; /* .sig file if strip_signature */
1305: char plainfile[MAX_PATH]; /* buffer for getstring() */
1306: char *tempFileName; /* Name for temporary uncanonicalized file */
1307: FILE *tempFile;
1308: long fp;
1309: FILE *f;
1310: FILE *g;
1311: long start_text; /* marks file position */
1312: int i,count;
1313: word16 cert_length;
1314: byte certbuf[MAX_SIGCERT_LENGTH];
1315: byteptr certificate; /* for parsing certificate buffer */
1316: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1317: byte inbuf[MAX_BYTE_PRECISION];
1318: byte outbuf[MAX_BYTE_PRECISION];
1319: byte keyID[KEYFRAGSIZE];
1320: word32 tstamp;
1.1.1.7 root 1321: byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
1.1.1.6 root 1322: word32 dummystamp;
1323: byte userid[256];
1324: struct MD5Context MD;
1325: byte digest[16];
1326: boolean separate_signature;
1.1.1.7 root 1327: boolean fixedLiteral = FALSE; /* Whether it's a fixed literal2
1328: packet */
1.1.1.6 root 1329: extern char **myArgv;
1330: extern int myArgc;
1331: char lit_mode = MODE_BINARY;
1332: unsigned char litfile[MAX_PATH];
1333: word32 text_len = -1;
1334: int status;
1335: byte *mdextras;
1336: byte mdlensave;
1337: byte version;
1338: byte mdlen; /* length of material to be added to MD calculation */
1339: byte class;
1340: byte algorithm;
1341: byte mdlow2[2];
1342: char org_sys[5]; /* Name of originating system */
1343: #ifdef VMS
1344: char *fdl;
1345: short fdl_len;
1346: #endif
1347: int outbufoffset;
1348:
1349: fill0( keyID, KEYFRAGSIZE );
1350:
1351: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1352:
1353: strcpy(keyfile, globalPubringName); /* use default pathname */
1354:
1355: if (verbose)
1.1.1.7 root 1356: fprintf(pgpout,
1357: "check_signaturefile: infile = '%s', outfile = '%s'\n",
1.1.1.6 root 1358: infile,outfile);
1359:
1360: if (preserved_name)
1361: *preserved_name = '\0';
1362:
1363: /* open file f for read, in binary (not text) mode...*/
1364: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 1365: fprintf(pgpout,
1366: LANG("\n\007Can't open ciphertext file '%s'\n"),infile);
1.1.1.6 root 1367: return -1;
1368: }
1369:
1.1.1.7 root 1370: /******************** Read header CTB and length field ******************/
1.1.1.6 root 1371:
1372: fread(&ctb,1,1,f); /* read certificate CTB byte */
1373: certificate = certbuf;
1374: *certificate++ = ctb; /* copy ctb into certificate */
1375:
1376: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
1377: goto badcert; /* complain and return bad status */
1378:
1379: cert_length = getpastlength(ctb, f); /* read certificate length */
1380: certificate += ctb_llength(ctb); /* either 1, 2, 4, or 8 */
1381: if (cert_length > MAX_SIGCERT_LENGTH-3) /* Huge packet length */
1382: goto badcert; /* complain and return bad status */
1383:
1384: /* read whole certificate: */
1385: if (fread((byteptr) certificate, 1, cert_length, f) < cert_length)
1386: /* bad packet length field */
1387: goto badcert; /* complain and return bad status */
1388:
1389: version = *certificate++;
1390: if (version_byte_error(version))
1391: goto err1;
1392:
1.1.1.7 root 1393: mdlensave = mdlen = *certificate++; /* length of material to
1394: be added to MD */
1395: mdextras = certificate; /* pointer to extra material for
1396: MD calculation */
1.1.1.6 root 1397:
1398: class = *certificate++;
1399: if (class != SM_SIGNATURE_BYTE && class != SB_SIGNATURE_BYTE) {
1400: (void) version_error(class, SM_SIGNATURE_BYTE);
1401: goto err1;
1402: }
1403: mdlen--;
1404:
1405: if (mdlen>0) { /* if more MD material is included... */
1406: for (i=0; i<SIZEOF_TIMESTAMP; ++i) {
1407: timestamp[i] = *certificate++;
1408: mdlen--;
1409: }
1410: }
1411:
1412: if (mdlen>0) { /* if more MD material is included... */
1413: certificate+=2; /* skip past unused validity period field */
1414: mdlen-=2;
1415: }
1416:
1417: for (i=0; i<KEYFRAGSIZE; i++)
1418: keyID[i] = *certificate++; /* copy rest of key fragment */
1419:
1420: algorithm = *certificate++;
1421: if (version_error(algorithm, RSA_ALGORITHM_BYTE))
1422: goto err1;
1423:
1424: algorithm = *certificate++;
1425: if (version_error(algorithm, MD5_ALGORITHM_BYTE))
1426: goto err1;
1427:
1428: mdlow2[0] = *certificate++;
1429: mdlow2[1] = *certificate++;
1430:
1431: /* getpublickey() sets precision for mpi2reg, if key not found: use
1432: maximum precision to avoid error return from mpi2reg() */
1433: if (getpublickey(0, keyfile, &fp, NULL, keyID,
1434: (byte *)&dummystamp, userid, n, e) < 0)
1.1.1.7 root 1435: set_precision(MAX_UNIT_PRECISION); /* safest opening
1436: assumption */
1.1.1.6 root 1437:
1.1.1.7 root 1438: if (mpi2reg((unitptr)inbuf,certificate) == -1) /* get signed message
1439: digest */
1.1.1.6 root 1440: goto err1;
1441: certificate += countbytes((unitptr)inbuf)+2;
1442:
1443: if ((certificate-certbuf) != cert_length+3)
1444: /* Bad length in signature certificate. Off by
1445: ((certificate-certbuf) - (cert_length+3)) */
1446: goto badcert; /* complain and return bad status */
1447:
1448: start_text = ftell(f); /* mark position of text for later */
1449:
1450: if (fread(outbuf,1,1,f) < 1) { /* see if any plaintext is there */
1451: /* Signature certificate has no plaintext following it.
1452: Must be in another file. Go look. */
1453: separate_signature = TRUE;
1.1.1.7 root 1454: if (preserved_name) /* let caller know there is
1455: no output file */
1.1.1.6 root 1456: strcpy(preserved_name, "/dev/null");
1457: fclose(f);
1.1.1.7 root 1458: fprintf(pgpout,
1459: LANG("\nFile '%s' has signature, but with no text."),infile);
1.1.1.6 root 1460: if (myArgc > 3 && file_exists(myArgv[3])) {
1461: outfile = myArgv[3];
1.1.1.7 root 1462: fprintf(pgpout,
1463: LANG("\nText is assumed to be in file '%s'.\n"),outfile);
1.1.1.6 root 1464: } else {
1465: strcpy(plainfile, outfile);
1466: outfile = plainfile;
1467: drop_extension(outfile);
1468:
1469: if (file_exists(outfile)) {
1.1.1.7 root 1470: fprintf(pgpout,
1471: LANG("\nText is assumed to be in file '%s'.\n"),outfile);
1.1.1.6 root 1472: } else {
1473: if (batchmode)
1474: return -1;
1.1.1.7 root 1475: fprintf(pgpout,
1476: LANG("\nPlease enter filename of material that signature applies to: "));
1477: getstring(outfile,59,TRUE); /* echo keyboard */
1.1.1.6 root 1478: if ((int)strlen(outfile) == 0)
1479: return -1;
1480: }
1481: }
1482: /* open file f for read, in binary (not text) mode...*/
1483: if ((f = fopen(outfile,FOPRBIN)) == NULL) {
1.1.1.7 root 1484: fprintf(pgpout,
1485: LANG("\n\007Can't open file '%s'\n"),outfile);
1.1.1.6 root 1486: return -1;
1487: }
1488: start_text = ftell(f); /* mark position of text for later */
1489: text_len = fsize(f); /* remember length of text */
1490: } else {
1491: separate_signature = FALSE;
1.1.1.7 root 1492: /* We just read 1 byte, so outbuf[0] should contain a ctb,
1493: maybe a CTB_LITERAL byte. */
1.1.1.6 root 1494: ctb2 = outbuf[0];
1495: fixedLiteral = is_ctb_type(ctb2,CTB_LITERAL2_TYPE);
1.1.1.7 root 1496: if (is_ctb(ctb2) && (is_ctb_type(ctb2,CTB_LITERAL_TYPE)
1497: ||fixedLiteral))
1.1.1.6 root 1498: { /* Read literal data */
1.1.1.7 root 1499: text_len = getpastlength(ctb2, f); /* read packet
1500: length */
1.1.1.6 root 1501: lit_mode = '\0';
1.1.1.7 root 1502: fread (&lit_mode,1,1,f); /* get literal packet
1503: mode byte */
1504: if (lit_mode != MODE_TEXT
1505: && lit_mode != MODE_BINARY &&
1.1.1.6 root 1506: lit_mode != MODE_LOCAL)
1507: {
1.1.1.7 root 1508: fprintf(pgpout,
1509: "\n\007Error: Illegal mode byte %02x in literal packet.\n",
1510: lit_mode); /* English-only diagnostic
1511: for debugging */
1.1.1.6 root 1512: (void) version_error(lit_mode, MODE_BINARY);
1513: goto err1;
1514: }
1515: if (verbose)
1.1.1.7 root 1516: fprintf(pgpout,
1517: LANG("File type: '%c'\n"), lit_mode);
1.1.1.6 root 1518: /* Read literal file name, use it if possible */
1519: litfile[0] = 0;
1520: fread (litfile,1,1,f);
1521: if( fixedLiteral )
1.1.1.7 root 1522: /* Get corrected text_len value by subtracting
1523: the length of the filename and the
1524: timestamp and mode byte and litfile
1525: length byte */
1526: text_len -= litfile[0]
1527: + sizeof(dummystamp) + 2;
1.1.1.6 root 1528: if (litfile[0] > 0)
1529: {
1530: if ((int)litfile[0] >= MAX_PATH) {
1531: fseek(f, litfile[0], SEEK_CUR);
1532: litfile[0] = 0;
1533: } else {
1534: fread (litfile+1,1,litfile[0],f);
1535: }
1536: }
1.1.1.7 root 1537: /* Use litfile if it's writeable and he
1538: didn't say an outfile */
1.1.1.6 root 1539: if (litfile[0]) {
1540: PascalToC( (char *)litfile );
1541: if (verbose)
1.1.1.7 root 1542: fprintf(pgpout,
1543: LANG("Original plaintext file name was: '%s'\n"), litfile);
1.1.1.6 root 1544: if (preserved_name)
1.1.1.7 root 1545: strcpy(preserved_name,
1546: (char *) litfile);
1.1.1.6 root 1547: }
1548: if (lit_mode == MODE_LOCAL) {
1549: fread(org_sys, 1, 4, f); org_sys[4] = '\0';
1550: #ifdef VMS
1551: #define LOCAL_TEST !strncmp("VMS ",org_sys,4)
1552: #else
1553: #define LOCAL_TEST FALSE
1554: #endif
1555: if (LOCAL_TEST) {
1556: #ifdef VMS
1557: fread(&fdl_len, 2, 1, f);
1558: fdl = (char *) malloc(fdl_len);
1559: fread(fdl, 1, fdl_len, f);
1.1.1.7 root 1560: if ((g =
1561: fdl_create( fdl, fdl_len,
1562: outfile,
1563: (char *) litfile))
1564: == NULL)
1.1.1.6 root 1565: {
1.1.1.7 root 1566: fprintf(pgpout,
1567: "\n\007Unable to create file %s\n", outfile);
1.1.1.6 root 1568: return -1;
1569: }
1570: free(fdl);
1571: if (preserved_name)
1.1.1.7 root 1572: strcpy(preserved_name,
1573: (char *) litfile);
1574: text_len -= (fdl_len
1575: + sizeof(fdl_len));
1.1.1.6 root 1576: #endif /* VMS */
1577: } else {
1.1.1.7 root 1578: fprintf(pgpout,
1579: "\n\007Unrecognised local binary type %s\n",org_sys);
1.1.1.6 root 1580: return -1;
1581: }
1582: } else {
1583: /* Discard file creation timestamp for now */
1584: fread (&dummystamp, 1, sizeof(dummystamp), f);
1585: }
1.1.1.7 root 1586: start_text = ftell(f); /* mark position of
1587: text for later */
1.1.1.6 root 1588: } /* packet is CTB_LITERAL_TYPE */
1589: }
1590:
1591: /* Use keyID prefix to look up key... */
1592:
1593: /* Get and validate public key from a key file: */
1594: if (getpublickey(0, keyfile, &fp, NULL, keyID,
1595: (byte *)&dummystamp, userid, n, e) < 0)
1.1.1.7 root 1596: { /* Can't get public key. Complain and
1597: process file copy anyway. */
1598: fprintf(pgpout,
1599: LANG("\nWARNING: Can't find the right public key-- can't check signature \
1600: integrity.\n"));
1.1.1.6 root 1601: goto outsig;
1602: } /* Can't find public key */
1603:
1604: count = rsa_public_decrypt(outbuf, (unitptr)inbuf, e, n);
1605:
1606: if (!quietmode)
1607: fputc('.',pgpout); /* Signal RSA completion. */
1608:
1609: /* outbuf should contain message digest packet */
1610: /*==================================================================*/
1611: /* Look at nested stuff within RSA block... */
1612:
1613: if (count == -7 || (count > 0 && count != sizeof(digest)))
1614: {
1615: fputs(LANG("\007\nUnrecognized message digest algorithm.\n\
1616: This may require a newer version of PGP.\n\
1617: Can't check signature integrity.\n"), pgpout);
1618: goto outsig; /* Output data anyway */
1619: }
1620: if (count == -5) { /* RSAREF returned malformed */
1.1.1.7 root 1621: fputs(
1622: LANG("\a\nMalformed or obsolete signature. Can't check signature \
1623: integrity.\n"),
1.1.1.6 root 1624: pgpout);
1625: goto outsig;
1626: }
1627: if (count == -3) { /* Key too big */
1.1.1.7 root 1628: fputs(
1629: LANG("\a\nSigning key is too large. RSA keys may be no longer than 1024 \
1630: bits,\ndue to limitations imposed by software provided by RSADSI.\n\
1.1.1.6 root 1631: Can't check signature integrity.\n"), pgpout);
1632: goto outsig;
1633: }
1634: if (count < 0) { /* Catch-all */
1.1.1.7 root 1635: fprintf(pgpout,
1636: LANG("\n\007Error: RSA-decrypted block is corrupted.\n\
1637: This may be caused either by corrupted data or by using the wrong RSA key.\n\
1638: "));
1.1.1.6 root 1639: goto outsig; /* Output data anyway */
1640: }
1641:
1642: /* Distinguish PKCS-compatible from pre-3.3 which has an extra byte */
1643: outbufoffset = (count==sizeof(digest)) ? 0 : 1;
1644:
1645: if (outbuf[outbufoffset] != mdlow2[0] ||
1646: outbuf[outbufoffset+1] != mdlow2[1])
1647: {
1.1.1.7 root 1648: fprintf(pgpout,
1649: LANG("\n\007Error: RSA-decrypted block is corrupted.\n\
1650: This may be caused either by corrupted data or by using the wrong RSA key.\n\
1651: "));
1.1.1.6 root 1652: goto outsig; /* Output data anyway */
1653: }
1654:
1655: /* Reposition file to where that plaintext begins... */
1656: fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
1657:
1.1.1.7 root 1658: MDfile0_len(&MD,f,text_len); /* compute a message digest from
1659: rest of file */
1.1.1.6 root 1660:
1.1.1.7 root 1661: MD_addbuffer (&MD, mdextras, mdlensave, digest); /* Finish message
1662: digest */
1.1.1.6 root 1663:
1.1.1.7 root 1664: convert_byteorder(timestamp,4); /* convert timestamp from external
1665: form */
1.1.1.6 root 1666: PascalToC((char *)userid); /* for display */
1667:
1668: /* now compare computed MD with claimed MD */
1669: /* Assume MSB external byte ordering */
1670: if (!equal_buffers(digest, outbuf+outbufoffset, 16)) {
1671: /* IF the signature is bad, AND this machine does not use
1672: MSDOS-stype canonical text as its native text format, AND
1673: this is a detached signature certificate, AND this file
1674: appears to contain non-canonical ASCII text, THEN we
1675: convert the file to canonical text form and check the
1676: signature again. This is because a detached signature
1677: certificate probably means the file is not currently in
1678: a canonical text packet, but it was in canonical text form
1679: when the signature was created, so by re-canonicalizing
1680: it we can check the signature. */
1.1.1.7 root 1681: if (class == SM_SIGNATURE_BYTE && separate_signature
1682: && is_text_file(outfile))
1683: { /* Reposition file to where the plaintext begins
1684: and canonicalize it */
1.1.1.6 root 1685: rewind( f );
1686: tempFileName = tempfile( TMP_WIPE | TMP_TMPDIR );
1687: if (verbose)
1.1.1.7 root 1688: fprintf(stderr,
1689: "signature checking failed, trying in canonical mode\n");
1.1.1.8 ! root 1690: make_canonical(outfile,tempFileName);
! 1691: if( ( tempFile = fopen( tempFileName, FOPRBIN ) )
1.1.1.7 root 1692: != NULL )
1.1.1.8 ! root 1693: {
! 1694: /* Now check the signature */
1.1.1.7 root 1695: MDfile0_len(&MD, tempFile, -1L );
1696: MD_addbuffer(&MD, mdextras, mdlensave,
1697: digest);
1.1.1.6 root 1698:
1699: /* Clean up behind us */
1700: fclose( tempFile );
1701: rmtemp( tempFileName );
1702:
1.1.1.7 root 1703: /* Check if the signature is OK this time
1704: round */
1.1.1.6 root 1705: /* Assume MSB external byte ordering */
1.1.1.7 root 1706: if(equal_buffers(digest, outbuf+outbufoffset,
1707: 16))
1.1.1.6 root 1708: goto goodsig;
1709: }
1710: }
1711:
1.1.1.7 root 1712: fprintf(pgpout,
1713: LANG("\007\nWARNING: Bad signature, doesn't match file contents!\007\n"));
1.1.1.6 root 1714: fprintf(pgpout,LANG("\nBad signature from user \"%s\".\n"),
1715: LOCAL_CHARSET((char *)userid));
1.1.1.7 root 1716: fprintf(pgpout,
1717: LANG("Signature made %s\n"),ctdate((word32 *)timestamp));
1.1.1.6 root 1718: if (moreflag && !batchmode) {
1719: /* more will scroll the message off the screen */
1720: fprintf(pgpout, LANG("\nPress ENTER to continue..."));
1721: fflush(pgpout);
1722: getyesno('n');
1723: }
1724: goto warnsig; /* Output data anyway */
1725: }
1726:
1727: goodsig:
1728: signature_checked = TRUE; /* set flag for batch processing */
1729: fprintf(pgpout,LANG("\nGood signature from user \"%s\".\n"),
1730: LOCAL_CHARSET((char *)userid));
1.1.1.7 root 1731: fprintf(pgpout,
1732: LANG("Signature made %s\n"),ctdate((word32 *)timestamp));
1.1.1.6 root 1733:
1734: warnsig:
1735: /* warn only, don't ask if user wants to use the key */
1736: warn_signatures(keyfile, fp, (char *)userid, TRUE);
1737:
1738: outsig:
1739: /* Reposition file to where that plaintext begins... */
1740: fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
1741:
1742: if (separate_signature)
1743: {
1744: if (!quietmode)
1.1.1.7 root 1745: fprintf(pgpout,
1746: LANG("\nSignature and text are separate. No output file produced. "));
1.1.1.6 root 1747: } else {
1748: /* signature precedes plaintext in file... */
1749: /* produce a plaintext output file from signature file */
1750: /* open file g for write, in binary or text mode...*/
1751: if (lit_mode==MODE_LOCAL) {
1752: #ifdef VMS
1.1.1.7 root 1753: if (status = fdl_copyfile2bin( f, g, text_len)) {
1754: /* Copy ok? */
1.1.1.6 root 1755: if (status > 0)
1.1.1.7 root 1756: fprintf(stderr,
1757: "\n...copying to literal file\n");
1.1.1.6 root 1758: else
1.1.1.7 root 1759: perror(
1760: "\nError copying from work file");
1.1.1.6 root 1761: fdl_close(g);
1762: goto err1;
1763: }
1764: fdl_close(g);
1765: #endif /*VMS */
1766: } else {
1767: if (lit_mode == MODE_BINARY)
1768: g = fopen(outfile, FOPWBIN);
1769: else
1770: g = fopen(outfile, FOPWTXT);
1771: if (g == NULL) {
1.1.1.7 root 1772: fprintf(pgpout,
1773: LANG("\n\007Can't create plaintext file '%s'\n"),outfile);
1.1.1.6 root 1774: goto err1;
1775: }
1776: CONVERSION = (lit_mode==MODE_TEXT)?EXT_CONV:NO_CONV;
1777: if (lit_mode == MODE_BINARY)
1778: status = copyfile(f, g, text_len);
1779: else
1780: status = copyfile_from_canon(f, g, text_len);
1781: CONVERSION = NO_CONV;
1782: if (write_error(g) || status < 0) {
1783: fclose(g);
1784: goto err1;
1785: }
1786: fclose(g);
1787: }
1788:
1789: if (strip_signature) {
1790: /* Copy signature to a .sig file */
1791: strcpy (sigfile, outfile);
1792: force_extension(sigfile,SIG_EXTENSION);
1793: if (!force_flag && file_exists(sigfile)) {
1.1.1.7 root 1794: fprintf(pgpout,
1795: LANG("\n\007Signature file '%s' already exists. Overwrite (y/N)? "),
1.1.1.6 root 1796: sigfile);
1797: if (!getyesno('n'))
1798: goto err1;
1799: }
1800: if ((g = fopen(sigfile,FOPWBIN)) == NULL) {
1.1.1.7 root 1801: fprintf(pgpout,
1802: LANG("\n\007Can't create signature file '%s'\n"),sigfile);
1.1.1.6 root 1803: goto err1;
1804: }
1805: fseek (f,0L,SEEK_SET);
1.1.1.7 root 1806: copyfile (f,g,(unsigned long)(cert_length
1807: +ctb_llength(ctb)+1));
1.1.1.6 root 1808: if (write_error(g)) {
1809: fclose(g);
1810: goto err1;
1811: }
1812: fclose(g);
1813: if (!quietmode)
1.1.1.7 root 1814: fprintf(pgpout,
1815: LANG("\nWriting signature certificate to '%s'\n"),sigfile);
1.1.1.6 root 1816: }
1817: }
1818:
1819: burn(inbuf); /* burn sensitive data on stack */
1820: burn(outbuf); /* burn sensitive data on stack */
1821: fclose(f);
1822: if (separate_signature)
1823: return 0; /* normal return, no nested info */
1.1.1.7 root 1824: if (is_ctb(ctb2) && (is_ctb_type(ctb2,CTB_LITERAL_TYPE)
1825: || fixedLiteral))
1826: /* we already stripped away the CTB_LITERAL */
1.1.1.6 root 1827: return 0; /* normal return, no nested info */
1.1.1.7 root 1828: /* Otherwise, it's best to assume a
1829: nested CTB */
1830: return 1; /* nested information return */
1.1.1.6 root 1831:
1832: badcert: /* Bad packet. Complain. */
1.1.1.7 root 1833: fprintf(pgpout,
1834: LANG("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
1835: fprintf(pgpout,
1836: LANG("File \"%s\" does not have a properly-formed signature.\n"),infile);
1.1.1.6 root 1837: /* Now just drop through to error exit... */
1838:
1839: err1:
1840: burn(inbuf); /* burn sensitive data on stack */
1841: burn(outbuf); /* burn sensitive data on stack */
1842: fclose(f);
1843: return -1; /* error return */
1844:
1845: } /* check_signaturefile */
1846:
1847: /*
1848: * Check signature of key in file fkey at position fpkey, using signature
1849: * in file fsig and position fpsig. keyfile tells the file to use to
1850: * look for the public key in to check the sig. Return 0 if OK,
1851: * -1 generic error
1852: * -2 Can't find key
1853: * -3 Key too big
1854: * -4 Key too small
1855: * -5 Maybe malformed RSA
1856: * -6 Unknown PK algorithm
1857: * -7 Unknown conventional algorithm
1858: * -8 Unknown version
1859: * -9 Malformed RSA packet
1860: * -10 Malformed packet
1861: * -20 BAD SIGNATURE
1862: */
1.1.1.7 root 1863: int check_key_sig(FILE *fkey, long fpkey, int keypktlen, char *keyuserid,
1864: FILE *fsig, long fpsig, char *keyfile, char *siguserid,
1865: byte *xtimestamp, byte *sigclass)
1.1.1.6 root 1866: {
1867: byte ctb; /* Cipher Type Bytes */
1868: long fp;
1869: word16 cert_length;
1870: int i, count;
1871: byte certbuf[MAX_SIGCERT_LENGTH];
1872: byteptr certificate; /* for parsing certificate buffer */
1873: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1874: byte inbuf[MAX_BYTE_PRECISION];
1875: byte outbuf[MAX_BYTE_PRECISION];
1876: byte keyID[KEYFRAGSIZE];
1877: struct MD5Context MD;
1878: byte digest[16];
1879: byte *mdextras;
1880: word32 tstamp;
1.1.1.7 root 1881: byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
1.1.1.6 root 1882: byte version;
1883: byte mdlen; /* length of material to be added to MD calculation */
1884: byte class;
1885: byte algorithm;
1886: byte mdlow2[2];
1887:
1888: fill0( keyID, KEYFRAGSIZE );
1889:
1890: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1891:
1.1.1.7 root 1892: /******************** Read header CTB and length field ******************/
1.1.1.6 root 1893:
1894: fseek(fsig, fpsig, SEEK_SET);
1895: fread(&ctb,1,1,fsig); /* read certificate CTB byte */
1896: certificate = certbuf;
1897: *certificate++ = ctb; /* copy ctb into certificate */
1898:
1899: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
1900: goto badcert; /* complain and return bad status */
1901:
1902: cert_length = getpastlength(ctb, fsig); /* read certificate length */
1903: certificate += ctb_llength(ctb); /* either 1, 2, 4, or 8 */
1904: if (cert_length > MAX_SIGCERT_LENGTH-3) /* Huge packet length */
1905: goto badcert; /* complain and return bad status */
1906:
1907: /* read whole certificate: */
1908: if (fread((byteptr) certificate, 1, cert_length, fsig) < cert_length)
1909: /* bad packet length field */
1910: goto badcert; /* complain and return bad status */
1911:
1912: version = *certificate++;
1913: if (version_byte_error(version))
1914: return -8;
1915:
1916: mdlen = *certificate++; /* length of material to be added to MD */
1917: if (version_error(mdlen, 5))
1918: return -8;
1919:
1.1.1.7 root 1920: mdextras = certificate; /* pointer to extra material for MD
1921: calculation */
1.1.1.6 root 1922:
1923: *sigclass = class = *certificate++;
1924: if (class != K0_SIGNATURE_BYTE && class != K1_SIGNATURE_BYTE &&
1925: class != K2_SIGNATURE_BYTE && class != K3_SIGNATURE_BYTE &&
1926: class != KC_SIGNATURE_BYTE)
1927: {
1928: (void)version_error(class, K0_SIGNATURE_BYTE);
1929: return -8;
1930: }
1931:
1932: for (i=0; i<SIZEOF_TIMESTAMP; ++i)
1933: timestamp[i] = *certificate++;
1934:
1935: for (i=0; i<KEYFRAGSIZE; i++)
1936: keyID[i] = *certificate++; /* copy rest of key fragment */
1937:
1938: algorithm = *certificate++;
1939: if (version_error(algorithm, RSA_ALGORITHM_BYTE))
1940: return -6;
1941:
1942: algorithm = *certificate++;
1943: if (version_error(algorithm, MD5_ALGORITHM_BYTE))
1944: return -7;
1945:
1946: /* Grab 1st 2 bytes of message digest */
1947: mdlow2[0] = *certificate++;
1948: mdlow2[1] = *certificate++;
1949:
1950: /* We used to set precision here based on certificate value,
1951: * but it was sometimes less than that based on n. Read public
1952: * key here to set precision, before we go on.
1953: */
1954: /* This sets precision, too, based on n. */
1955: if (getpublickey(GPK_GIVEUP, keyfile, &fp, NULL, keyID,
1956: xtimestamp, (unsigned char *)siguserid, n, e) < 0)
1957: return -2;
1958:
1.1.1.7 root 1959: if (mpi2reg((unitptr)inbuf,certificate) == -1) /* get signed message
1960: digest */
1.1.1.6 root 1961: return -10;
1962: certificate += countbytes((unitptr)inbuf)+2;
1963:
1964: if ((certificate-certbuf) != cert_length+3)
1965: /* Bad length in signature certificate. Off by
1966: ((certificate-certbuf) - (cert_length+3)) */
1967: return -10; /* complain and return bad status */
1968:
1969: count = rsa_public_decrypt(outbuf, (unitptr)inbuf, e, n);
1970:
1971: if (count < 0)
1972: return count;
1973:
1974: if (count != sizeof(digest))
1.1.1.7 root 1975: return -9; /* Bad RSA decrypt. Corruption,
1976: or wrong key. */
1.1.1.6 root 1977:
1978: /* outbuf should contain message digest packet */
1979: /*==================================================================*/
1980: /* Look at nested stuff within RSA block... */
1981:
1982: /* Assume MSB external byte ordering */
1983: if (outbuf[0] != mdlow2[0] || outbuf[1] != mdlow2[1])
1.1.1.7 root 1984: return -9; /* Bad RSA decrypt. Corruption,
1985: or wrong key. */
1.1.1.6 root 1986:
1987: /* Position file to where that plaintext begins... */
1988: fseek(fkey,fpkey,SEEK_SET);
1989:
1990: /* compute a message digest from key packet */
1991: MDfile0_len(&MD,fkey,keypktlen);
1992: /* Add data from user id */
1993: if (class != KC_SIGNATURE_BYTE)
1.1.1.7 root 1994: MD5Update(&MD, (unsigned char *) keyuserid+1,
1995: (int)(unsigned char)keyuserid[0]);
1.1.1.6 root 1996: /* Add time and class data */
1.1.1.7 root 1997: MD_addbuffer (&MD, mdextras, mdlen, digest); /* Finish message
1998: digest */
1.1.1.6 root 1999:
2000: /* now compare computed MD with claimed MD */
2001: /* Assume MSB external byte ordering */
2002: if (!equal_buffers(digest, outbuf, 16))
2003: return -20; /* BAD SIGNATURE */
2004:
1.1.1.7 root 2005: convert_byteorder(timestamp,4); /* convert timestamp from external
2006: form */
2007: memcpy (xtimestamp, timestamp, 4); /* Return signature timestamp */
1.1.1.6 root 2008:
2009: return 0; /* normal return */
2010:
2011: badcert: /* Bad packet. Complain. */
1.1.1.7 root 2012: fprintf(pgpout,
2013: LANG("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
1.1.1.6 root 2014: return -10;
2015: } /* check_key_sig */
2016:
2017: /*======================================================================*/
2018: static int squish_and_idea_file(byte *ideakey, FILE *f, FILE *g,
2019: boolean attempt_compression)
2020: {
2021: FILE *t;
2022: char *tempf = NULL;
2023: word32 fpos, fpos0;
2024: extern char plainfile[];
2025:
2026: /*
2027: ** If the caller specified that we should attempt compression, we
2028: ** create a temporary file 't' and compress our input file 'f' into
2029: ** 't'. Ideally, we would see if we get a good compression ratio
2030: ** and if we did, then use file 't' for input and write a
2031: ** CTB_COMPRESSED prefix. But in this implementation we just always
2032: ** use the compressed output, even if it didn't compress well.
2033: */
2034:
2035: rewind( f );
2036:
2037: if (!attempt_compression)
2038: t = f; /* skip compression attempt */
2039: else /* attempt compression-- get a tempfile */
2040: if ((tempf = tempfile(TMP_TMPDIR|TMP_WIPE)) == NULL ||
1.1.1.7 root 2041: (t = fopen(tempf, FOPWPBIN)) == NULL)
2042: /* error: no tempfile */
1.1.1.6 root 2043: t = f; /* skip compression attempt */
2044: else /* attempt compression */
2045: {
2046: extern int zipup( FILE *, FILE * );
2047:
2048:
1.1.1.7 root 2049: if (verbose) fprintf(pgpout,
2050: "\nCompressing [%s] ", plainfile);
1.1.1.6 root 2051:
2052: /* We don't put a length field on CTB_COMPRESSED yet */
2053:
1.1.1.7 root 2054: putc(CTB_COMPRESSED, t); /* write CTB_COMPRESSED */
2055: /* No CTB packet length specified
2056: means indefinite length. */
2057: putc(ZIP2_ALGORITHM_BYTE, t); /* write ZIP algorithm
2058: byte */
1.1.1.6 root 2059:
2060: /* Compression the file */
2061: zipup( f, t);
2062: if (write_error(t)) {
2063: fclose(t);
2064: if (tempf)
2065: rmtemp(tempf);
2066: return -1;
2067: }
2068: if (verbose) fprintf(pgpout, LANG("compressed. ") );
2069: else if (!quietmode)
2070: fputc('.',pgpout); /* show progress */
2071: rewind( t );
2072: }
2073:
2074: /* Now write out file thru IDEA cipher... */
2075:
2076: /* Write CTB prefix, leave 4 bytes for later length */
2077: fpos0 = ftell(g);
2078: write_ctb_len (g, CTB_CKE_TYPE, 0L, TRUE);
2079: fpos = ftell(g) - fpos0;
2080:
2081: idea_file( ideakey, ENCRYPT_IT, t, g, fsize(t) );
2082:
2083: /* Now re-write CTB prefix, this time with length */
2084: fseek(g,fpos0,SEEK_SET);
2085: write_ctb_len (g, CTB_CKE_TYPE, fsize(g)-fpos, TRUE);
2086:
2087: if (t != f) {
2088: fclose( t ); /* close and remove the temporary file */
2089: if (tempf)
2090: rmtemp(tempf);
2091: }
2092:
2093: return 0; /* normal return */
2094:
2095: } /* squish_and_idea_file */
2096:
2097: int squish_file(char *infile, char *outfile)
2098: {
2099: FILE *f, *g;
2100: extern int zip( FILE *, FILE * );
2101:
2102: if (verbose)
2103: fprintf(pgpout,"squish_file: infile = '%s', outfile = '%s'\n",
2104: infile,outfile);
2105:
2106: /* open file f for read, in binary (not text) mode...*/
2107: if ((f = fopen( infile, FOPRBIN )) == NULL) {
2108: fprintf(pgpout,LANG("\n\007Can't open file '%s'\n"), infile );
2109: return -1;
2110: }
2111:
2112: /* open file g for write, in binary (not text) mode...*/
2113: if ((g = fopen( outfile, FOPWBIN )) == NULL) {
1.1.1.7 root 2114: fprintf(pgpout,
2115: LANG("\n\007Can't create compressed file '%s'\n"), outfile );
1.1.1.6 root 2116: fclose(f);
2117: return -1;
2118: }
2119:
2120:
2121: if (verbose) fprintf(pgpout, LANG("Compressing file..."));
2122:
2123: /* We don't put a length field on CTB_COMPRESSED yet */
2124: putc(CTB_COMPRESSED, g); /* use compression prefix CTB */
2125: /* No CTB packet length specified means indefinite length. */
2126: putc(ZIP2_ALGORITHM_BYTE, g); /* use ZIP compression */
2127:
2128: /* Compress/store the file */
2129: zipup( f, g );
2130: if (verbose) fprintf(pgpout, LANG("compressed. ") );
2131:
2132: fclose (f);
2133: if (write_error(g)) {
2134: fclose(g);
2135: return -1;
2136: }
2137: fclose (g);
2138: return 0;
2139: } /* squish_file */
2140:
2141: #define NOECHO1 1 /* Disable password from being displayed on screen */
2142: #define NOECHO2 2 /* Disable password from being displayed on screen */
2143:
2144: int idea_encryptfile(char *infile, char *outfile,
2145: boolean attempt_compression)
2146: {
2147: FILE *f; /* input file */
2148: FILE *g; /* output file */
2149: byte ideakey[24];
2150: struct hashedpw *hpw;
2151:
2152: if (verbose)
1.1.1.7 root 2153: fprintf(pgpout,
2154: "idea_encryptfile: infile = '%s', outfile = '%s'\n",
1.1.1.6 root 2155: infile,outfile);
2156:
2157: /* open file f for read, in binary (not text) mode...*/
2158: if ((f = fopen( infile, FOPRBIN )) == NULL) {
1.1.1.7 root 2159: fprintf(pgpout,
2160: LANG("\n\007Can't open plaintext file '%s'\n"), infile );
1.1.1.6 root 2161: return -1;
2162: }
2163:
2164: /* open file g for write, in binary (not text) mode...*/
2165: if ((g = fopen( outfile, FOPWBIN )) == NULL) {
1.1.1.7 root 2166: fprintf(pgpout,
2167: LANG("\n\007Can't create ciphertext file '%s'\n"), outfile );
1.1.1.6 root 2168: fclose(f);
2169: return -1;
2170: }
2171:
2172: /* Get IDEA password, hashed to a key */
2173: if (passwds) {
2174: memcpy(ideakey, passwds->hash, sizeof(ideakey));
2175: memset(passwds->hash, 0, sizeof(passwds->hash));
2176: hpw = passwds;
2177: passwds = passwds->next;
2178: free(hpw);
2179: } else {
2180: if (!quietmode)
1.1.1.7 root 2181: fprintf(pgpout,
2182: LANG("\nYou need a pass phrase to encrypt the file. "));
2183: if (batchmode
2184: || GetHashedPassPhrase((char *)ideakey,NOECHO2) <= 0)
1.1.1.6 root 2185: {
2186: fclose(f);
2187: fclose(g);
2188: return -1;
2189: }
2190: }
2191: /*
2192: * Get an initial vector, and write out a new randseed.bin.
2193: * We do this now so that we can use the random bytes from the
2194: * user's keystroke timings.
2195: */
2196: make_random_ideakey(ideakey, 16);
2197:
2198: if (!quietmode) {
1.1.1.7 root 2199: fprintf(pgpout,
2200: LANG("Just a moment...")); /* this may take a while */
1.1.1.6 root 2201: fflush(pgpout);
2202: }
2203:
2204: /* Now compress the plaintext and encrypt it with IDEA... */
2205: squish_and_idea_file( ideakey, f, g, attempt_compression );
2206:
2207: burn(ideakey); /* burn sensitive data on stack */
2208:
2209: fclose(f);
2210: if (write_error(g)) {
2211: fclose(g);
2212: return -1;
2213: }
2214: fclose(g);
2215:
2216: return 0;
2217:
2218: } /* idea_encryptfile */
2219:
2220: /*======================================================================*/
2221:
2222: static byte (*keyID_list)[KEYFRAGSIZE] = NULL;
2223:
2224: static int getmyname(char *userid) {
2225: char keyfile[MAX_PATH];
2226: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
2227: word32 tstamp; byte *timestamp = (byte *) &tstamp;
2228: long fp;
2229: int pktlen;
2230:
2231: strcpy(keyfile, globalSecringName);
2232:
2233: getpublickey(GPK_SECRET, keyfile, &fp,
2234: NULL, NULL, timestamp, (unsigned char *)userid, n, e);
2235:
2236: PascalToC((char *)userid);
2237:
2238: return(0);
2239: }
2240:
2241: int encryptfile(char **mcguffins, char *infile, char *outfile,
2242: boolean attempt_compression)
2243: {
2244: int i,ckp_length;
2245: FILE *f;
2246: FILE *g;
2247: byte keybuf[MAX_BYTE_PRECISION]; /* This keeps our IDEA to encrypt */
2248: byte ideakey[24]; /* must be big enough for make_random_ideakey */
2249: word32 chksum;
2250: char keyfile[MAX_PATH];
2251: int keys_used = 0;
2252:
2253: if (mcguffins == NULL || *mcguffins == NULL || **mcguffins == '\0') {
2254: /* Well, we haven't gotten a user, lets die here */
2255: return -1;
2256: }
2257:
2258: if (verbose)
2259: fprintf(pgpout,"encryptfile: infile = %s, outfile = %s\n",
2260: infile,outfile);
2261:
2262: /* open file f for read, in binary (not text) mode...*/
2263: if ((f = fopen( infile, FOPRBIN )) == NULL)
2264: {
1.1.1.7 root 2265: fprintf(pgpout,
2266: LANG("\n\007Can't open plaintext file '%s'\n"), infile );
1.1.1.6 root 2267: return -1;
2268: }
2269:
2270: /* open file g for write, in binary (not text) mode...*/
2271: if ((g = fopen( outfile, FOPWBIN )) == NULL)
2272: {
1.1.1.7 root 2273: fprintf(pgpout,
2274: LANG("\n\007Can't create ciphertext file '%s'\n"), outfile );
1.1.1.6 root 2275: fclose(f);
2276: return -1;
2277: }
2278:
2279: /* Now we have to generate a random session key and IV.
2280: As part of this computation, we use the MD5 hash of the
2281: current file, if it has previously been obtained due to a
2282: signing operation. If it has not been obtained, we hash
2283: the first 2K (for efficiency reasons) for input into
2284: the key generatrion process. This is to ensure that
2285: capturing a randseed.bin file will not allow reconstruction
2286: of subsequent session keys without knowing the message
2287: that was encrypted. (A session key only protects a
2288: single message, so it is reasonable to assume that an
2289: opponent trying to obtain a session key is trying to
2290: obtain, and thus is ignorant of, the message it encrypts.)
2291:
2292: This is not perfect, but it's an improvement on how session
2293: keys used to be generated, and can be changed in future
2294: without compatibility worries.
2295: */
2296:
2297: if (!already_have_md5) {
2298: /* Obtain some random bits from the input file */
2299: struct MD5Context MD;
2300:
2301: MD5Init(&MD);
1.1.1.7 root 2302: MDfile0_len(&MD, f, 4096); /* Ignore errors - what could be
2303: done? */
1.1.1.6 root 2304: MD5Final(md5buf, &MD);
2305: already_have_md5 = 1;
2306:
1.1.1.7 root 2307: fseek(f, 0, SEEK_SET); /* Get back to the beginning for
2308: encryption */
1.1.1.6 root 2309: }
2310:
2311: ckp_length = make_random_ideakey(ideakey, 0);
2312: /* Returns a 24 byte random IDEA key */
2313:
2314: /* Assume MSB external byte ordering */
2315: /* Prepend identifier byte to key */
2316: keybuf[0] = IDEA_ALGORITHM_BYTE;
2317: for (i=0; i<ckp_length; ++i)
2318: keybuf[i+1] = ideakey[i];
2319: /* Compute and append checksum to the key */
2320: chksum = checksum (keybuf+1, ckp_length);
2321: ckp_length++;
2322: put_word16((word16) chksum, keybuf+ckp_length);
2323: ckp_length += 2;
2324:
2325: /* Ok, we now have our IDEA key which we are going to use
2326: * to encrypt our packet. We have stuffed it into a packet
2327: * which we can now encrypt in the Public Key of EACH USER
2328: * which we want to be able to decrypt this message. Now we
2329: * will walk down mcguffins until we hit a NULL or NULL string,
2330: * and we will encrypt for each user in the list, and write
2331: * that out to the output file.
2332: *
2333: * -derek <[email protected]> 13 Dec 1992
2334: */
2335:
2336: for (i = 0; mcguffins[i] != NULL; ++i)
2337: ;
2338: if (encrypt_to_self)
2339: ++i;
2340: keyID_list = xmalloc(i * KEYFRAGSIZE);
2341: /* Iterate through users */
2342: for (; *mcguffins && **mcguffins ; ++mcguffins) {
2343: strcpy(keyfile, globalPubringName);
2344: /* use default pathname */
2345:
2346: keys_used =
2347: encryptkeyintofile(g, *mcguffins, keybuf,
2348: keyfile, ckp_length, keys_used);
2349: } /* for */
2350:
2351: if (!keys_used) {
2352: fclose(f);
2353: fclose(g);
2354: free(keyID_list);
2355: return -1;
2356: }
2357:
2358: /* encrypt to myself if need be */
2359: if (encrypt_to_self) {
2360: if (!*my_name)
2361: /* Find our name from our keyring */
2362: getmyname(my_name);
2363: if (*my_name)
2364: /* If we were successful */
2365: keys_used =
2366: encryptkeyintofile(g, my_name, keybuf,
2367: keyfile, ckp_length, keys_used);
2368: }
2369: free(keyID_list);
2370:
2371: /* Finished with RSA block containing IDEA key. */
2372:
2373: /* Now compress the plaintext and encrypt it with IDEA... */
2374: squish_and_idea_file( ideakey, f, g, attempt_compression );
2375:
2376: burn(keybuf); /* burn the Idea Key Packet */
2377: burn(ideakey); /* burn sensitive data on stack */
2378:
2379: fclose(f);
2380: if (write_error(g)) {
2381: fclose(g);
2382: return -1;
2383: }
2384: fclose(g);
2385:
2386: return 0;
2387: } /* encryptfile */
2388:
2389: static int
2390: encryptkeyintofile(FILE *g, char *mcguffin, byte *keybuf,
2391: char *keyfile, int ckp_length, int keys_used) {
2392: int i;
2393: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
2394: byte keyID[KEYFRAGSIZE];
2395: byte inbuf[MAX_BYTE_PRECISION];
2396: byte outbuf[MAX_BYTE_PRECISION];
1.1.1.7 root 2397: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate
2398: timestamp */
1.1.1.6 root 2399: byte userid[256];
2400: long fp;
2401: int blocksize;
2402: byte (*keyp)[KEYFRAGSIZE];
2403:
2404:
2405: /* This "loop" is so we can break out at opportune moments */
2406: do {
2407: userid[0] = '\0';
2408:
2409: strcpy((char *)userid,mcguffin);
2410: /* Who we are looking for (C string) */
2411:
2412: /* Get and validate public key from a key file:
2413: * We will be nice and ask the user ONCE (and ONLY once)
2414: * for a keyfile if its not in the default.
2415: */
2416:
1.1.1.7 root 2417: if (getpublickey((quietmode?0:GPK_SHOW)|GPK_NORVK,
2418: keyfile, &fp, NULL, NULL,
1.1.1.6 root 2419: timestamp, userid, n, e) < 0)
2420: {
1.1.1.7 root 2421: fprintf(pgpout,
2422: LANG("\n\007Cannot find the public key matching userid '%s'\n\
1.1.1.6 root 2423: This user will not be able to decrypt this message.\n"),
2424: LOCAL_CHARSET(mcguffin));
2425: continue;
2426: }
2427:
2428: /* Make sure we haven't already used this key */
2429: extract_keyID(keyID, n);
2430: for (keyp = keyID_list; keyp < keyID_list+keys_used; ++keyp) {
2431: if (!memcmp(keyp, keyID, KEYFRAGSIZE))
2432: break;
2433: }
2434:
2435: if (keyp < keyID_list + keys_used) {
1.1.1.7 root 2436: /* This key was already specified.
2437: Quietly ignore it. */
1.1.1.6 root 2438: continue;
2439: }
2440:
2441: /* Add this keyID to the list of keys used so far */
2442: memcpy(keyp, keyID, KEYFRAGSIZE);
2443:
2444: PascalToC((char *)userid);
2445: if (warn_signatures(keyfile, fp, (char *)userid,
2446: FALSE) < 0) {
2447: fprintf(pgpout, "Ok, skipping userid %s\n", mcguffin);
2448: continue;
2449: }
2450:
2451: /* set_precision has been properly called by getpublickey */
2452:
2453: /* Note that RSA key must be at least big enough
2454: to encipher a complete conventional key packet
2455: in a single RSA block.
2456: */
2457:
2458: blocksize = countbytes(n)-1;
2459: /* size of a plaintext block */
2460:
2461: if (blocksize < 31) {
1.1.1.7 root 2462: fprintf(pgpout,
2463: "\n\007Error: RSA key length must be at least 256 bits.\n");
1.1.1.6 root 2464: fprintf(pgpout, "Skipping userid %s\n", mcguffin);
2465: continue;
2466: }
2467:
2468: #ifdef MR_DEBUG
2469: /* XXX This is dangerous... This will print out the
2470: * IDEA Key, which is a breach of security!
2471: */
2472: fprintf(pgpout, "Idea Key: ");
2473: for (i = 0; i < ckp_length; i++)
2474: fprintf(pgpout, "%02X ", keybuf[i]);
2475: fprintf(pgpout, "\n");
2476: #endif
1.1.1.7 root 2477: i = rsa_public_encrypt((unitptr)outbuf, keybuf,
2478: ckp_length, e, n);
1.1.1.6 root 2479: if (i < 0) {
2480: if (i == -4) {
1.1.1.7 root 2481: fprintf(pgpout,
2482: "\n\007Error: RSA key length must be at least 256 bits.\n");
1.1.1.6 root 2483: } else if (i == -3) {
1.1.1.7 root 2484: fputs(
2485: LANG("\a\nError: key is too large. RSA keys may be no longer than 1024 \
2486: bits,\ndue to limitations imposed by software provided by RSADSI.\n"), pgpout);
1.1.1.6 root 2487: } else {
1.1.1.7 root 2488: fprintf(pgpout,
2489: "\a\nUnexpected error %d encrypting\n", i);
1.1.1.6 root 2490: }
1.1.1.7 root 2491: fprintf(pgpout,
2492: LANG("Skipping userid %s\n"), mcguffin);
1.1.1.6 root 2493: continue;
2494: }
2495:
2496: /* write out header record to outfile ... */
2497:
2498: /* PKE is Public Key Encryption */
2499: write_ctb_len (g, CTB_PKE_TYPE,
2500: 1+KEYFRAGSIZE+1+2+countbytes((unitptr)outbuf),
2501: FALSE);
2502:
2503: /* Write version byte */
2504: putc(version_byte, g);
2505:
2506: writekeyID( n, g );
2507: /* write msg prefix fragment of modulus n */
2508:
2509: /* Write algorithm byte */
2510: putc(RSA_ALGORITHM_BYTE, g);
2511:
2512: /* convert RSA ciphertext block via reg2mpi and
2513: * write to file
2514: */
2515:
2516: write_mpi( (unitptr)outbuf, g, FALSE );
2517:
2518: burn(inbuf); /* burn sensitive data on stack */
2519: burn(outbuf); /* burn sensitive data on stack */
2520: ++keys_used;
2521:
2522: } while (0);
2523:
2524: return keys_used;
2525: } /* encryptkeyintofile */
2526:
2527: /*======================================================================*/
1.1.1.7 root 2528:
1.1.1.6 root 2529: /*
2530: * Prepend a CTB_LITERAL prefix to a file. Convert to canonical form if
2531: * lit_mode is MODE_TEXT.
2532: */
1.1.1.7 root 2533: int make_literal(char *infile, char *outfile, char lit_mode, char *literalfile)
1.1.1.6 root 2534: {
2535: char lfile[MAX_PATH];
2536: FILE *f;
2537: FILE *g;
2538: int status = 0;
2539: #ifdef VMS
2540: char *fdl;
2541: short fdl_len;
2542: #endif /* VMS */
2543:
2544: word32 flen, fpos;
2545: word32 dummystamp = 0;
2546:
2547: if (verbose)
1.1.1.7 root 2548: fprintf(pgpout,
2549: "make_literal: infile = %s, outfile = %s, mode = '%c', literalfile = '%s'\n",
1.1.1.6 root 2550: infile,outfile,lit_mode,literalfile);
2551:
2552: /* open file f for read, in binary or text mode...*/
2553:
2554: #ifdef VMS
2555: if (lit_mode == MODE_LOCAL) {
2556: if (!(fdl_generate(infile, &fdl, &fdl_len ) & 01)) {
1.1.1.7 root 2557: fprintf(pgpout,
2558: LANG("\n\007Can't open input plaintext file '%s'\n"),infile);
1.1.1.6 root 2559: return -1;
2560: }
2561: }
2562: #endif /*VMS*/
2563: if (lit_mode == MODE_TEXT)
2564: f = fopen(infile, FOPRTXT);
2565: else
2566: f = fopen(infile, FOPRBIN);
2567: if (f == NULL) {
1.1.1.7 root 2568: fprintf(pgpout,
2569: LANG("\n\007Can't open input plaintext file '%s'\n"),infile);
1.1.1.6 root 2570: return -1;
2571: }
2572: flen = fsize(f);
2573:
2574: /* open file g for write, in binary (not text) mode... */
2575: if ((g = fopen( outfile,FOPWBIN )) == NULL) {
1.1.1.7 root 2576: fprintf(pgpout,
2577: LANG("\n\007Can't create plaintext file '%s'\n"), outfile );
1.1.1.6 root 2578: goto err1;
2579: }
2580:
2581: if (literalfile == NULL) {
2582: /* Put in a zero byte to indicate no filename */
2583: lfile[0] = '\0';
2584: } else {
2585: strcpy( lfile, literalfile );
2586: file_to_canon( lfile );
2587: CToPascal( lfile );
2588: }
2589:
2590: #ifdef USE_LITERAL2
2591: #define LENGTH_FIELD (flen + (unsigned char) lfile[0] + 6)
2592: #define LIT_TYPE CTB_LITERAL2_TYPE
2593: #else
2594: #define LENGTH_FIELD flen
2595: #define LIT_TYPE CTB_LITERAL_TYPE
2596: #endif
2597: if (lit_mode == MODE_BINARY)
2598: write_ctb_len (g, LIT_TYPE, LENGTH_FIELD, FALSE);
2599: #ifdef VMS
2600: else if (lit_mode == MODE_LOCAL)
1.1.1.7 root 2601: write_ctb_len (g, CTB_LITERAL2_TYPE, flen
2602: + fdl_len + sizeof(fdl_len) + 6, TRUE);
1.1.1.6 root 2603: #endif /* VMS */
2604: else /* Will put in size field later for text mode */
2605: write_ctb_len (g, LIT_TYPE, 0L, TRUE);
2606: #ifdef USE_LITERAL2
2607: fpos = ftell(g);
2608: #endif
2609: putc(lit_mode, g);
2610:
2611: if (lit_mode == MODE_LOCAL) {
2612: #ifdef VMS
2613: write_litlocal( g, fdl, fdl_len);
2614: free(fdl);
2615: #else
2616: ; /* Null statement if we don't have anything to do! */
2617: #endif /* VMS */
2618: } else {
2619: /* write literalfile name */
2620: fwrite (lfile, 1, (unsigned char) lfile[0]+1, g);
2621: /* Dummy file creation timestamp */
2622: fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
2623: }
2624: #ifndef USE_LITERAL2
2625: fpos = ftell(g);
2626: #endif
2627:
2628: if ((lit_mode == MODE_BINARY) || (lit_mode == MODE_LOCAL)) {
2629: if (copyfile( f, g, -1L )) {
1.1.1.7 root 2630: fprintf(pgpout,
2631: "\n\007Unable to append to literal plaintext file");
1.1.1.6 root 2632: perror("\n");
2633: fclose(g);
2634: goto err1;
2635: }
2636: } else {
2637: CONVERSION = (lit_mode == MODE_TEXT) ? INT_CONV : NO_CONV;
2638: status = copyfile_to_canon( f, g, -1L );
2639: CONVERSION = NO_CONV;
2640: /* Re-write CTB with correct length info */
2641: rewind (g);
2642: write_ctb_len (g, LIT_TYPE, fsize(g)-fpos, TRUE);
2643: }
2644: if (write_error(g) || status < 0) {
2645: fclose(g);
2646: goto err1;
2647: }
2648: fclose(g);
2649: fclose(f);
2650: return 0; /* normal return */
2651:
2652: err1:
2653: fclose(f);
2654: return -1; /* error return */
2655:
2656: } /* make_literal */
2657: #undef LENGTH_FIELD
2658: #undef LIT_TYPE
2659:
2660: /*======================================================================*/
1.1.1.7 root 2661:
1.1.1.6 root 2662: /*
2663: * Strip off literal prefix from infile, copying to outfile.
2664: * Get lit_mode and literalfile info from
2665: * the prefix. Replace outfile with literalfile unless
2666: * literalfile is illegal
2667: * the original filename is stored in preserved_name
2668: * If lit_mode is MODE_TEXT, convert from canonical form as we
2669: * copy the data.
2670: */
1.1.1.7 root 2671: int strip_literal(char *infile, char *outfile, char *preserved_name,
2672: char *lit_mode)
1.1.1.6 root 2673: {
2674: byte ctb; /* Cipher Type Byte */
2675: FILE *f;
2676: FILE *g;
2677: word32 LITlength = 0;
2678: unsigned char litfile[MAX_PATH];
2679: word32 dummystamp;
2680: char org_sys[5]; /* Name of originating system */
2681: int status;
2682: #ifdef VMS
2683: char *fdl;
2684: short fdl_len;
2685: #endif
2686: *lit_mode = MODE_BINARY;
2687: if (verbose)
2688: fprintf(pgpout,"strip_literal: infile = %s, outfile = %s\n",
2689: infile,outfile);
2690:
2691: if (preserved_name)
2692: *preserved_name = '\0';
2693:
2694: /* open file f for read, in binary (not text) mode...*/
2695: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 2696: fprintf(pgpout,
2697: LANG("\n\007Can't open input plaintext file '%s'\n"),infile);
1.1.1.6 root 2698: return -1;
2699: }
2700:
2701: fread(&ctb,1,1,f); /* read Cipher Type Byte */
2702:
2703: if (!is_ctb(ctb) || !(is_ctb_type(ctb,CTB_LITERAL_TYPE) ||
2704: is_ctb_type(ctb,CTB_LITERAL2_TYPE)))
2705: {
2706: /* debug message in English only -- something got corrupted */
1.1.1.7 root 2707: fprintf(pgpout,
2708: "\n\007'%s' is not a literal plaintext file.\n",infile);
1.1.1.6 root 2709: fclose(f);
2710: return -1;
2711: }
2712:
2713: LITlength = getpastlength(ctb, f); /* read packet length */
2714:
2715: /* Read literal data */
2716: *lit_mode = '\0';
2717: fread (lit_mode,1,1,f);
2718: if ((*lit_mode != MODE_BINARY) && (*lit_mode != MODE_TEXT)
2719: && (*lit_mode != MODE_LOCAL))
2720: {
2721: (void) version_error(*lit_mode, MODE_TEXT);
2722: fclose(f);
2723: return -1;
2724: }
2725: if (verbose)
2726: fprintf(pgpout, LANG("File type: '%c'\n"), *lit_mode);
2727: /* Read literal file name, use it if possible */
2728: litfile[0] = 0;
2729: fread (litfile,1,1,f);
2730: if (is_ctb_type(ctb, CTB_LITERAL2_TYPE)) {
1.1.1.7 root 2731: /* subtract header length: namelength
2732: + lengthbyte + modebyte + stamp */
1.1.1.6 root 2733: LITlength -= litfile[0] + 2 + sizeof(dummystamp);
2734: }
2735: /* Use litfile if it's writeable and he didn't say an outfile */
2736: if (litfile[0] > 0) {
2737: if ((int)litfile[0] >= MAX_PATH) {
2738: fseek(f, litfile[0], SEEK_CUR);
2739: litfile[0] = 0;
2740: } else {
2741: fread (litfile+1,1,litfile[0],f);
2742: }
2743: }
2744: if (litfile[0]) {
2745: PascalToC( (char *)litfile );
2746: if (verbose)
1.1.1.7 root 2747: fprintf(pgpout,
2748: LANG("Original plaintext file name was: '%s'\n"), litfile);
1.1.1.6 root 2749: if (preserved_name)
2750: strcpy(preserved_name, (char *) litfile);
2751: }
2752: if (*lit_mode == MODE_LOCAL) {
2753: fread(org_sys, 1, 4, f); org_sys[4] = '\0';
2754: #ifdef VMS
2755: #define LOCAL_TEST !strncmp("VMS ",org_sys,4)
2756: #else
2757: #define LOCAL_TEST FALSE
2758: #endif
2759: if (LOCAL_TEST) {
2760: #ifdef VMS
1.1.1.7 root 2761: remove(outfile); /* Prevent litter, we recreate
2762: the file with correct chars. */
1.1.1.6 root 2763: fread(&fdl_len, 2, 1, f);
2764: fdl = (char *) malloc(fdl_len);
2765: fread(fdl, 1, fdl_len, f);
1.1.1.7 root 2766: if ((g = fdl_create( fdl, fdl_len, outfile,
2767: (char *) litfile)) == NULL) {
2768: fprintf(pgpout,
2769: "\n\007Unable to create file %s\n", outfile);
1.1.1.6 root 2770: return -1;
2771: }
2772: free(fdl);
2773: if (preserved_name)
2774: strcpy(preserved_name, (char *) litfile);
2775: LITlength -= (fdl_len + sizeof(fdl_len));
2776: #endif /* VMS */
2777: } else {
1.1.1.7 root 2778: fprintf(pgpout,
2779: "\n\007Unrecognised local binary type %s\n",org_sys);
1.1.1.6 root 2780: return -1;
2781: }
2782: } else {
2783: /* Discard file creation timestamp for now */
2784: fread (&dummystamp, 1, sizeof(dummystamp), f);
2785: }
2786:
2787: if (*lit_mode==MODE_LOCAL) {
2788: #ifdef VMS
1.1.1.7 root 2789: if (status = fdl_copyfile2bin( f, g, LITlength)) {
2790: /* Copy ok? */
1.1.1.6 root 2791: if (status > 0)
1.1.1.7 root 2792: fprintf(stderr,
2793: "\n...copying to literal file\n");
1.1.1.6 root 2794: else
2795: perror("\nError copying from work file");
2796: fdl_close(g);
2797: goto err1;
2798: }
2799: fdl_close(g);
2800: #endif /*VMS */
2801: } else {
2802: if (*lit_mode == MODE_TEXT)
2803: g = fopen(outfile, FOPWTXT);
2804: else
2805: g = fopen(outfile, FOPWBIN);
2806: if (g == NULL) {
1.1.1.7 root 2807: fprintf(pgpout,
2808: LANG("\n\007Can't create plaintext file '%s'\n"), outfile );
1.1.1.6 root 2809: goto err1;
2810: }
2811: /* copy rest of literal plaintext file */
2812: CONVERSION = (*lit_mode == MODE_TEXT) ? EXT_CONV : NO_CONV;
2813: if (*lit_mode == MODE_BINARY)
2814: status = copyfile(f, g, LITlength);
2815: else
2816: status = copyfile_from_canon(f, g, LITlength);
2817: CONVERSION = NO_CONV;
2818: if (write_error(g) || status < 0) {
2819: fclose(g);
2820: goto err1;
2821: }
2822: fclose(g);
2823: }
2824:
2825: fclose(f);
2826: return 0; /* normal return */
2827:
2828: err1:
2829: fclose(f);
2830: return -1; /* error return */
2831:
2832: } /* strip_literal */
2833:
2834: /*======================================================================*/
2835:
2836: int decryptfile(char *infile, char *outfile)
2837: {
2838: byte ctb; /* Cipher Type Byte */
2839: byte ctbCKE; /* Cipher Type Byte */
2840: FILE *f;
2841: FILE *g;
2842: int count = 0, status, thiskey, gotkey, end_of_pkes;
1.1.1.7 root 2843: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
2844: unit d[MAX_UNIT_PRECISION];
2845: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION];
2846: unit u[MAX_UNIT_PRECISION];
1.1.1.6 root 2847: byte inbuf[MAX_BYTE_PRECISION];
2848: byte outbuf[MAX_BYTE_PRECISION];
2849: byte keyID[KEYFRAGSIZE];
1.1.1.7 root 2850: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate
2851: timestamp */
1.1.1.6 root 2852: byte userid[256];
2853: word32 flen;
2854: word32 fpos = 0;
2855: byte ver, alg;
2856: short realprecision = 0;
2857: word16 chksum;
2858: struct nkey {
2859: byte keyID[KEYFRAGSIZE];
2860: struct nkey *next;
2861: } *nkey, *nkeys = NULL;
2862:
2863: if (verbose)
2864: fprintf(pgpout,"decryptfile: infile = %s, outfile = %s\n",
2865: infile,outfile);
2866:
2867: /* open file f for read, in binary (not text) mode...*/
2868: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 2869: fprintf(pgpout,
2870: LANG("\n\007Can't open ciphertext file '%s'\n"),infile);
1.1.1.6 root 2871: return -1;
2872: }
2873:
2874: /* Now we have to keep reading in packets until we either get
2875: * to a non PKE-type packet or we find our own... Once we find
2876: * our own, we're gonna have to get our private key, and then
2877: * keep going until we find the end of the PKE packets
2878: *
2879: * -derek <[email protected]> 13 Dec 1992
2880: */
2881:
2882: gotkey = end_of_pkes = 0; /* Set this flag now. */
2883: do {
2884: thiskey = 0;
2885:
2886: set_precision(MAX_UNIT_PRECISION);
2887: /* Need to set this EACH TIME... Sigh. This is because
2888: * read_mpi needs to have a global_precision which is
2889: * >= the size of the key. Therefore once we find the
2890: * real key, we save off the precision and then we'll
2891: * reset it later. -derek
2892: */
2893:
2894: fread(&ctb,1,1,f); /* read Cipher Type Byte */
2895: if (!is_ctb(ctb)) {
1.1.1.7 root 2896: fprintf(pgpout,
2897: LANG("\n\007'%s' is not a cipher file.\n"),infile);
1.1.1.6 root 2898: fclose(f);
2899: return -1;
2900: }
2901:
2902: /* PKE is Public Key Encryption */
2903: if (!is_ctb_type(ctb,CTB_PKE_TYPE)) {
2904: end_of_pkes = 1;
2905: continue;
2906: }
2907:
2908: getpastlength(ctb, f); /* read packet length */
2909:
2910: /* Read and check version */
2911: ver = getc(f);
2912: if (version_byte_error(ver)) {
2913: fclose (f);
2914: return (-1);
2915: }
2916:
2917: fread(keyID,1,KEYFRAGSIZE,f); /* read key ID */
2918: /* Use keyID prefix to look up key. */
2919:
2920: /* Add this keyID to the list of keys read in */
2921: nkey = (struct nkey *) malloc(sizeof(struct nkey));
2922: if (nkey == NULL) {
2923: fprintf(stderr, LANG("\n\007Out of memory.\n"));
2924: exitPGP(7);
2925: }
2926: memcpy(nkey->keyID, keyID, KEYFRAGSIZE);
2927: nkey->next = nkeys;
2928: nkeys = nkey;
2929:
2930: /* Read and check algorithm */
2931: alg = getc(f);
2932: if (version_error(alg, RSA_ALGORITHM_BYTE)) {
2933: fclose (f);
2934: return (-1);
2935: }
2936:
2937: if (!gotkey) /* Only do this if we havent already */
2938: /* Get and validate secret key from a key file: */
2939: if (getsecretkey(GPK_GIVEUP|(quietmode?0:GPK_SHOW),
2940: NULL, keyID, timestamp, NULL, NULL,
2941: userid, n, e, d, p, q, u) == 0)
2942: {
2943: thiskey = gotkey = 1;
2944: realprecision = global_precision;
2945: } else {
2946: set_precision(MAX_UNIT_PRECISION);
2947: }
2948: /* DAMN this... This is REALLY frustrating, that I have to
2949: * do this... Basically, if I go to getsecretkey, it will
2950: * set the precision, and the precision might NOT be correct
2951: * if the key I get is not correct, so I have to set the
2952: * precision NUMEROUS times in this loop.. This sucks,
2953: * but its the only way. Sigh.
2954: *
2955: * -derek <[email protected]> 13 Dec 1992
2956: */
2957:
2958: /* Note that RSA key must be at least big enough
2959: to encipher a complete conventional key packet in
2960: a single RSA block. */
2961:
2962: /*========================================================*/
2963: /* read ciphertext block, converting to internal format: */
2964: read_mpi((unitptr)inbuf, f, FALSE, FALSE);
2965:
2966: if (thiskey) {
2967: if (!quietmode) {
2968: fprintf(pgpout,LANG("Just a moment..."));
2969: /* RSA will take a while. */
2970: fflush(pgpout);
2971: }
2972: count = rsa_private_decrypt(outbuf, (unitptr)inbuf,
2973: e, d, p, q, u, n);
2974: if (count < 0) {
2975: if (count == -3) {
1.1.1.7 root 2976: fputs(
2977: LANG("\a\nError: key is too large. RSA keys may be no longer than 1024 bits\
2978: ,\ndue to limitations imposed by software provided by RSADSI.\n"), pgpout);
1.1.1.6 root 2979: } else if (count == -9 || count == -7) {
1.1.1.7 root 2980: fprintf(pgpout,
2981: LANG("\n\007Error: RSA-decrypted block is corrupted.\n\
2982: This may be caused either by corrupted data or by using the wrong RSA key.\n\
2983: "));
1.1.1.6 root 2984: } else if (count == -5) {
1.1.1.7 root 2985: fprintf(pgpout,
2986: LANG("\n\007Error: RSA block is possibly malformed. Old format, maybe?\n"));
1.1.1.6 root 2987: } else {
1.1.1.7 root 2988: fprintf(pgpout,
2989: "\a\nUnexpected error %d decrypting\n", count);
1.1.1.6 root 2990: }
2991: fclose(f);
2992: return count;
2993: }
2994:
2995: if (!quietmode)
2996: fputc('.',pgpout);
2997: /* Signal RSA completion. */
2998: }
2999:
3000: fpos = ftell(f); /* Save this position */
3001:
3002: } while (!end_of_pkes); /* Loop until end of PKE packets */
3003:
3004: /* Should we list the recipients? */
3005: if (!gotkey || verbose) {
3006: char *user;
3007:
3008: setkrent(NULL);
3009: init_userhash();
3010: if (gotkey) /* verbose flag */
3011: fprintf(pgpout,"\nRecipients:\n");
3012: else
1.1.1.7 root 3013: fprintf(pgpout,
3014: LANG("\nThis message can only be read by:\n"));
1.1.1.6 root 3015:
3016: for (nkey = nkeys; nkey; nkey = nkey->next) {
3017: if ((user = user_from_keyID(nkey->keyID)) == NULL)
1.1.1.7 root 3018: fprintf(pgpout,
3019: " keyID: %s\n", keyIDstring(nkey->keyID));
1.1.1.6 root 3020: else
3021: fprintf(pgpout, " %s\n", LOCAL_CHARSET(user));
3022: }
3023: endkrent();
3024: }
3025: for (nkey = nkeys; nkey; ) {
3026: nkey = nkey->next;
3027: free(nkeys);
3028: nkeys = nkey;
3029: }
3030:
3031: /* Ok, Now lets clean up, and continue on to the rest of the file so
3032: * that it can be decrypted properly. Things should be ok once I
3033: * reset some stuff here... -derek
3034: */
3035: if (gotkey) {
3036: fseek(f, fpos, SEEK_SET); /* Get back to the Real McCoy! */
3037: set_precision(realprecision); /* reset the precision */
3038: } else {
3039: /* No secret key, exit gracefully (NOT!) */
1.1.1.7 root 3040: fprintf(pgpout,
3041: LANG("\n\007You do not have the secret key needed to decrypt this file.\n"));
1.1.1.6 root 3042: fclose(f);
3043: return -1;
3044: }
3045: /* Verify that top of buffer has correct algorithm byte */
3046: --count; /* one less byte to drop algorithm byte */
3047: /* Assume MSB external byte ordering */
3048: if (version_error(outbuf[0], IDEA_ALGORITHM_BYTE)) {
3049: fclose(f);
3050: return -1;
3051: }
3052:
3053: /* Verify checksum */
3054: count -= 2; /* back up before checksum */
3055: /* Assume MSB external byte ordering */
3056: chksum = fetch_word16(outbuf+1+count);
3057: if (chksum != checksum(outbuf+1, count)) {
1.1.1.7 root 3058: fprintf(pgpout,
3059: LANG("\n\007Error: RSA-decrypted block is corrupted.\n\
3060: This may be caused either by corrupted data or by using the wrong RSA key.\n\
3061: "));
1.1.1.6 root 3062: fclose(f);
3063: return -1;
3064: }
3065:
3066: /* outbuf should contain random IDEA key packet */
3067: /*==================================================================*/
3068:
3069: /* open file g for write, in binary (not text) mode... */
3070:
3071: if ((g = fopen( outfile, FOPWBIN )) == NULL) {
1.1.1.7 root 3072: fprintf(pgpout,
3073: LANG("\n\007Can't create plaintext file '%s'\n"), outfile );
1.1.1.6 root 3074: goto err1;
3075: }
3076:
3077: fread(&ctbCKE,1,1,f); /* read Cipher Type Byte, should be CTB_CKE */
3078: if (!is_ctb(ctbCKE) || !is_ctb_type(ctbCKE,CTB_CKE_TYPE)) {
3079: /* Should never get here. */
3080: fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
3081: goto err1; /* Abandon ship! */
3082: }
3083:
3084: flen = getpastlength(ctbCKE, f); /* read packet length */
3085:
3086: /* Decrypt ciphertext file */
3087: /* Assume MSB external byte ordering */
3088: status = idea_file( outbuf+1, DECRYPT_IT, f, g, flen );
3089: if (status < 0) {
1.1.1.7 root 3090: fprintf(pgpout,
3091: LANG("\n\007Error: Decrypted plaintext is corrupted.\n"));
1.1.1.6 root 3092: }
3093: if (!quietmode)
3094: fputc('.',pgpout); /* show progress */
3095:
3096: if (write_error(g)) {
3097: fclose(g);
3098: goto err1;
3099: }
3100: fclose(g);
3101: fclose(f);
3102: burn(inbuf); /* burn sensitive data on stack */
3103: burn(outbuf); /* burn sensitive data on stack */
3104: mp_burn(d); /* burn sensitive data on stack */
3105: mp_burn(p); /* burn sensitive data on stack */
3106: mp_burn(q); /* burn sensitive data on stack */
3107: mp_burn(u); /* burn sensitive data on stack */
3108: if (status < 0) /* if idea_file failed, then error return */
3109: return status;
1.1.1.7 root 3110: return 1; /* always indicate output file has
3111: nested stuff in it. */
1.1.1.6 root 3112:
3113: err1:
3114: fclose(f);
3115: burn(inbuf); /* burn sensitive data on stack */
3116: burn(outbuf); /* burn sensitive data on stack */
3117: mp_burn(d); /* burn sensitive data on stack */
3118: mp_burn(p); /* burn sensitive data on stack */
3119: mp_burn(q); /* burn sensitive data on stack */
3120: mp_burn(u); /* burn sensitive data on stack */
3121: return -1; /* error return */
3122:
3123: } /* decryptfile */
3124:
3125: int idea_decryptfile(char *infile, char *outfile)
3126: {
3127: byte ctb; /* Cipher Type Byte */
3128: FILE *f;
3129: FILE *g;
3130: byte ideakey[16];
3131: int status, retries = 0;
3132: struct hashedpw *hpw, **hpwp;
3133: word32 flen;
3134:
3135: if (verbose)
3136: fprintf(pgpout,"idea_decryptfile: infile = %s, outfile = %s\n",
3137: infile,outfile);
3138:
3139: /* open file f for read, in binary (not text) mode...*/
3140: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 3141: fprintf(pgpout,
3142: LANG("\n\007Can't open ciphertext file '%s'\n"),infile);
1.1.1.6 root 3143: return -1;
3144: }
3145:
3146: /* open file g for write, in binary (not text) mode... */
3147: if ((g = fopen( outfile, FOPWBIN )) == NULL) {
1.1.1.7 root 3148: fprintf(pgpout,
3149: LANG("\n\007Can't create plaintext file '%s'\n"), outfile );
1.1.1.6 root 3150: goto err1;
3151: }
3152:
3153: /* First, try all pre-specified passwords */
3154: hpwp = &passwds;
3155: hpw = *hpwp;
3156:
3157: do /* while pass phrase is bad */
3158: {
1.1.1.7 root 3159: fread(&ctb,1,1,f); /* read Cipher Type Byte,
3160: should be CTB_CKE */
1.1.1.6 root 3161:
3162: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_CKE_TYPE)) {
3163: /* Should never get here. */
3164: fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
3165: fclose(g);
3166: goto err1; /* Abandon ship! */
3167: }
3168: flen = getpastlength(ctb, f); /* read packet length */
3169:
3170: /* Get IDEA password, hashed */
3171: if (hpw) {
3172: /* first try environment passwords */
3173: memcpy(ideakey, hpw->hash, sizeof(ideakey));
3174: } else {
1.1.1.7 root 3175: fprintf(pgpout,
3176: LANG("\nYou need a pass phrase to decrypt this file. "));
3177: if (batchmode
3178: || GetHashedPassPhrase((char *)ideakey,NOECHO1)
3179: <= 0)
1.1.1.6 root 3180: {
3181: fclose(f);
3182: fclose(g);
3183: return -1;
3184: }
3185: }
3186:
3187: if (!quietmode) {
1.1.1.7 root 3188: fprintf(pgpout,LANG("Just a moment..."));
3189: /* this may take a while */
1.1.1.6 root 3190: fflush(pgpout);
3191: }
3192:
3193: status = idea_file( ideakey, DECRYPT_IT, f, g, flen );
3194: if (status == 0) {
3195: if (hpw) {
3196: /* "Use up" password. */
3197: *hpwp = hpw->next;
3198: memset(hpw->hash, 0, sizeof(hpw->hash));
3199: free(hpw);
3200: }
3201: break;
3202: }
3203: if (hpw) {
3204: /* Go to next available password */
3205: hpwp = &hpw->next;
3206: hpw = *hpwp;
3207: } else {
3208: ++retries;
1.1.1.7 root 3209: fprintf(pgpout,
3210: LANG("\n\007Error: Bad pass phrase.\n"));
1.1.1.6 root 3211: }
3212:
3213: rewind(f);
3214: rewind(g);
3215: } while (status == -2 && retries < 2);
3216:
3217: burn(ideakey); /* burn sensitive data on stack */
3218:
3219: if (status == 0 && !quietmode)
3220: fputc('.',pgpout); /* show progress */
3221:
3222: if (write_error(g)) {
3223: fclose(g);
3224: goto err1;
3225: }
3226: fclose(g);
3227: fclose(f);
3228:
3229: if (status < 0) { /* if idea_file failed, then complain */
3230: remove(outfile); /* throw away our mistake */
3231: return status; /* error return */
3232: }
3233: if (!quietmode)
3234: fprintf(pgpout,LANG("Pass phrase appears good. "));
1.1.1.7 root 3235: return 1; /* always indicate output file has
3236: nested stuff in it. */
1.1.1.6 root 3237:
3238: err1:
3239: fclose(f);
3240: return -1; /* error return */
3241:
3242: } /* idea_decryptfile */
3243:
3244: int decompress_file(char *infile, char *outfile)
3245: {
3246: byte ctb;
3247: FILE *f;
3248: FILE *g;
3249: extern void lzhDecode( FILE *, FILE * );
3250: extern int unzip( FILE *, FILE * );
3251: if (verbose) fprintf(pgpout, LANG("Decompressing plaintext...") );
3252:
3253: /* open file f for read, in binary (not text) mode...*/
3254: if ((f = fopen(infile,FOPRBIN)) == NULL) {
1.1.1.7 root 3255: fprintf(pgpout,
3256: LANG("\n\007Can't open compressed file '%s'\n"),infile);
1.1.1.6 root 3257: return -1;
3258: }
3259:
3260: fread(&ctb,1,1,f); /* read and skip over Cipher Type Byte */
3261: if (!is_ctb_type( ctb, CTB_COMPRESSED_TYPE )) {
3262: /* Shouldn't get here, or why were we called to begin with? */
3263: fprintf(pgpout,"\007\nBad or missing CTB_COMPRESSED byte.\n");
3264: goto err1; /* Abandon ship! */
3265: }
3266:
3267: getpastlength(ctb, f); /* read packet length */
3268: /* The packet length is ignored. Assume it's huge. */
3269:
1.1.1.7 root 3270: fread(&ctb,1,1,f); /* read and skip over compression
3271: algorithm byte */
1.1.1.6 root 3272: if (ctb != ZIP2_ALGORITHM_BYTE) {
3273: /* We only know how to uncompress deflate-compressed data. We
3274: may hit imploded or Lharc'ed data but treat it as an error
3275: just the same */
1.1.1.7 root 3276: fprintf(pgpout,
3277: LANG("\007\nUnrecognized compression algorithm.\n\
1.1.1.6 root 3278: This may require a newer version of PGP.\n"));
3279: goto err1; /* Abandon ship! */
3280: }
3281:
3282: /* open file g for write, in binary (not text) mode... */
3283: if ((g = fopen( outfile, FOPWBIN )) == NULL) {
1.1.1.7 root 3284: fprintf(pgpout,
3285: LANG("\n\007Can't create decompressed file '%s'\n"), outfile );
1.1.1.6 root 3286: goto err1;
3287: }
3288:
3289: if (unzip( f, g )) {
1.1.1.7 root 3290: fprintf(pgpout,
3291: LANG("\n\007Decompression error. Probable corrupted input.\n"));
1.1.1.6 root 3292: goto err2;
3293: }
3294:
3295: if (verbose)
3296: fprintf(pgpout, LANG("done. ") );
3297: else if (!quietmode)
3298: fputc('.',pgpout); /* show progress */
3299:
3300: if (write_error(g))
3301: goto err2;
3302:
3303: fclose(g);
3304: fclose(f);
1.1.1.7 root 3305: return 1; /* always indicate output file
3306: has nested stuff in it. */
1.1.1.6 root 3307:
3308: err2:
3309: fclose(g);
3310: err1:
3311: fclose(f);
3312: return -1; /* error return */
3313:
3314: } /* decompress_file */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.