|
|
1.1 root 1: /* crypto.c - Cryptographic routines for PGP.
2: PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
3:
4: (c) Copyright 1990-1992 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.
8:
9: All the source code Philip Zimmermann wrote for PGP is available for
10: free under the "Copyleft" General Public License from the Free
11: Software Foundation. A copy of that license agreement is included in
12: the source release package of PGP. Code developed by others for PGP
13: is also freely available. Other code that has been incorporated into
14: PGP from other sources was either originally published in the public
15: domain or was used with permission from the various authors. See the
16: PGP User's Guide for more complete information about licensing,
17: patent restrictions on certain algorithms, trademarks, copyrights,
18: and export controls.
19: */
20:
21: #include <ctype.h>
22: #include <stdio.h>
23: #include <string.h>
24: #include <time.h>
25:
26: #include "mpilib.h"
27: #include "mpiio.h"
28: #include "random.h"
29: #include "idea.h"
30: #include "crypto.h"
31: #include "keymgmt.h"
32: #include "mdfile.h"
33: #include "fileio.h"
34: #include "language.h"
35: #include "pgp.h"
36:
37: #define ENCRYPT_IT FALSE /* to pass to idea_file */
38: #define DECRYPT_IT TRUE /* to pass to idea_file */
39:
40: /* The kbhit() function: Determines if a key has been hit. May not be
41: available in some implementations */
42:
43: int kbhit( void );
44: int zipup(FILE *, FILE *);
45: #ifdef M_XENIX
46: long time();
47: #endif
48:
49: /*--------------------------------------------------------------------------*/
50:
51:
52: void CToPascal(char *s)
53: { /* "xyz\0" --> "\3xyz" ... converts C string to Pascal string */
54: int i,j;
55: j = string_length(s);
56: for (i=j; i!=0; i--)
57: s[i] = s[i-1]; /* move everything 1 byte to the right */
58: s[0] = j; /* Pascal length byte at beginning */
59: } /* CToPascal */
60:
61:
62: void PascalToC( char *s )
63: { /* "\3xyz" --> "xyz\0" ... converts Pascal string to C string */
64: int i,j;
65: for (i=0,j=((byte *) s)[0]; i<j; i++)
66: s[i] = s[i+1]; /* move everything 1 byte to the left */
67: s[i] = '\0'; /* append C string terminator */
68: } /* PascalToC */
69:
70:
71: /*
72: Note: On MSDOS, the time() function calculates GMT as the local
73: system time plus a built-in timezone correction, which defaults to
74: adding 7 hours (PDT) in the summer, or 8 hours (PST) in the winter,
75: assuming the center of the universe is on the US west coast. Really--
76: I'm not making this up! The only way to change this is by setting
77: the MSDOS environmental variable TZ to reflect your local time zone,
78: for example "set TZ=MST7MDT". This means add 7 hours during standard
79: time season, or 6 hours during daylight time season, and use MST and
80: MDT for the two names of the time zone. If you live in a place like
81: Arizona with no daylight savings time, use "set TZ=MST7". See the
82: Microsoft C function tzset(). Just in case your local software
83: environment is too weird to predict how to set environmental
84: variables for this, PGP also uses its own TZFIX variable in
85: config.pgp to optionally correct this problem further. For example,
86: set TZFIX=-1 in config.pgp if you live in Colorado and the TZ
87: variable is undefined.
88: */
89:
90: word32 get_timestamp(byte *timestamp)
91: /* Return current timestamp as a byte array in internal byteorder,
92: and as a 32-bit word */
93: { word32 t;
94: t = time(NULL); /* returns seconds since GMT 00:00 1 Jan 1970 */
95:
96: #ifdef _MSC_VER
97: #if (_MSC_VER == 700)
98: /* Under MSDOS and MSC 7.0, time() returns elapsed time since
99: * GMT 00:00 31 Dec 1899, instead of Unix's base date of 1 Jan 1970.
100: * So we must subtract 70 years worth of seconds to fix this.
101: * 6/19/92 rgb
102: */
103: #define LEAP_DAYS (((unsigned long)70L/4)+1)
104: #define CALENDAR_KLUDGE ((unsigned long)86400L * (((unsigned long)365L * 70L) + LEAP_DAYS))
105: t -= CALENDAR_KLUDGE;
106: #endif
107: #endif
108:
109: t += timeshift; /* timeshift derived from TZFIX in config.pgp */
110:
111: if (timestamp != NULL)
112: { /* first, fill array in external byte order: */
113: put_word32(t, timestamp);
114: convert_byteorder(timestamp,4); /* convert to internal byteorder */
115: }
116:
117: return(t); /* return 32-bit timestamp integer */
118: } /* get_timestamp */
119:
120:
121: int date_ymd(word32 *tstamp, int *year, int *month, int *day)
122: /* Given timestamp as seconds elapsed since 1970 Jan 1 00:00:00,
123: returns year (1970-2106), month (1-12), day (1-31).
124: Not valid for dates after 2100 Feb 28 (no leap day that year).
125: Also returns day of week (0-6) as functional return.
126: */
127: { word32 days,y;
128: int m,d,i;
129: static short mdays[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
130: days = (*tstamp)/(unsigned long)86400L; /* day 0 is 1970/1/1 */
131: days -= 730L; /* align days relative to 1st leap year, 1972 */
132: y = ((days*4)/(unsigned long)1461L); /* 1972 is year 0 */
133: /* reduce to days elapsed since 1/1 last leap year: */
134: d = (int) (days - ((y/4)*1461L));
135: *year = (int)(y+1972);
136: for (i=0; i<48; i++) /* count months 0-47 */
137: { m = i % 12;
138: d -= mdays[m] + (i==1); /* i==1 is the only leap month */
139: if (d < 0)
140: { d += mdays[m] + (i==1);
141: break;
142: }
143: }
144: *month = m+1;
145: *day = d+1;
146: i = (int)((days-2) % (unsigned long)7L); /* compute day of week 0-6 */
147: return(i); /* returns weekday 0-6; 0=Sunday, 6=Saturday */
148: } /* date_ymd */
149:
150:
151: char *cdate(word32 *tstamp)
152: /* Return date string, given pointer to 32-bit timestamp */
153: { int month,day,year;
154: static char datebuf[20];
155: (void) date_ymd(tstamp,&year,&month,&day);
156: sprintf(datebuf,"%4d/%02d/%02d", year, month, day);
157: return (datebuf);
158: } /* cdate */
159:
160:
161: char *ctdate(word32 *tstamp)
162: /* Return date and time string, given pointer to 32-bit timestamp */
163: { int hours,minutes;
164: static char tdatebuf[40];
165: long seconds;
166: seconds = (*tstamp) % (unsigned long)86400L; /* seconds past midnight today */
167: minutes = (seconds+30L) / 60L; /* round off to minutes past midnight */
168: hours = minutes / 60; /* hours past midnight */
169: minutes = minutes % 60; /* minutes past the hour */
170: sprintf(tdatebuf,"%s %02d:%02d GMT", cdate(tstamp), hours, minutes);
171: return (tdatebuf);
172: } /* ctdate */
173:
174:
175:
176: /* Warn user he if key in keyfile at position fp of length pktlen, belonging
177: * to userid, is untrusted. Return -1 if the user doesn't want to proceed.
178: */
179: int warn_signatures(char *keyfile, long fp, int pktlen, char *userid,
180: boolean warn_only)
181: { FILE *f;
182: byte ctb;
183: long fpusr;
184: int usrpktlen;
185: byte keyctrl;
186: int trust_status = -1;
187:
188: keyctrl = KC_LEGIT_UNKNOWN; /* Assume the worst */
189: PascalToC(userid);
190: if (getpubuserid (keyfile, fp, (byte *) userid, &fpusr, &usrpktlen) >= 0)
191: { f = fopen(keyfile, "rb");
192: fseek (f, fpusr+usrpktlen, SEEK_SET);
193: /* Read trust byte */
194: trust_status = read_trust(f, &keyctrl);
195: fseek(f, fp, SEEK_SET);
196: if (is_compromised(f))
197: {
198: CToPascal(userid);
199: fprintf(pgpout, "\n");
200: show_key(f, fp, 0);
201: fclose (f);
202: fprintf(pgpout, PSTR("\007\nWARNING: This key has been revoked by its owner,\n\
203: possibly because the secret key was compromised.\n"));
204: if (warn_only)
205: { /* this is only for checking signatures */
206: fprintf(pgpout, PSTR("This could mean that this signature is a forgery.\n"));
207: return(1);
208: }
209: else
210: { /* don't use it for encryption */
211: fprintf(pgpout, PSTR("You cannot use this revoked key.\n"));
212: return(-1);
213: }
214: }
215: fclose (f);
216: }
217: CToPascal(userid);
218: if ((keyctrl & KC_LEGIT_MASK) != KC_LEGIT_COMPLETE)
219: { byte userid0[256];
220: PascalToC(userid);
221: strcpy ((char *) userid0, userid);
222: CToPascal(userid);
223: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNKNOWN)
224: fprintf(pgpout,PSTR("\007\nWARNING: Because this public key is not certified with a trusted\n\
225: signature, it is not known with high confidence that this public key\n\
226: actually belongs to: \"%s\".\n"), EXTERNAL((char *)userid0));
227: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_UNTRUSTED)
228: fprintf(pgpout, PSTR("\007\nWARNING: This public key is not trusted to actually belong to:\n\
229: \"%s\".\n"), EXTERNAL((char *)userid0));
230: if ((keyctrl & KC_LEGIT_MASK) == KC_LEGIT_MARGINAL)
231: fprintf(pgpout,PSTR("\007\nWARNING: Because this public key is not certified with enough trusted\n\
232: signatures, it is not known with high confidence that this public key\n\
233: actually belongs to: \"%s\".\n"), EXTERNAL((char *)userid0));
234: if (!filter_mode && !warn_only && !(keyctrl & KC_WARNONLY))
235: { fprintf(pgpout,PSTR("\nAre you sure you want to use this public key (y/N)? "));
236: if (!getyesno('n'))
237: return(-1);
238: if (trust_status == 0 && (f = fopen(keyfile, "r+b")) != NULL)
239: { fseek (f, fpusr+usrpktlen, SEEK_SET);
240: keyctrl |= KC_WARNONLY;
241: write_trust(f, keyctrl);
242: fclose(f);
243: }
244: }
245: }
246: return(0);
247: } /* warn_signatures */
248:
249:
250: boolean legal_ctb(byte ctb)
251: { /* Used to determine if nesting should be allowed. */
252: boolean legal;
253: byte ctbtype;
254: if (!is_ctb(ctb)) /* not even a bonafide CTB */
255: return(FALSE);
256: /* Sure hope CTB internal bit definitions don't change... */
257: ctbtype = (ctb & CTB_TYPE_MASK) >> 2;
258: /* Only allow these CTB types to be nested... */
259: legal = (
260: (ctbtype==CTB_PKE_TYPE)
261: || (ctbtype==CTB_SKE_TYPE)
262: || (ctbtype==CTB_CERT_SECKEY_TYPE)
263: || (ctbtype==CTB_CERT_PUBKEY_TYPE)
264: || (ctbtype==CTB_LITERAL_TYPE)
265: || (ctbtype==CTB_COMPRESSED_TYPE)
266: || (ctbtype==CTB_CKE_TYPE)
267: );
268: return(legal);
269: } /* legal_ctb */
270:
271:
272: /* Return nonzero if val doesn't match checkval, after printing a
273: * warning.
274: */
275: int
276: version_error(int val, int checkval)
277: { if (val != checkval)
278: { fprintf (pgpout, PSTR(
279: "\n\007Unsupported packet format - you need a newer version of PGP for this file.\n"));
280: return(1);
281: }
282: return(0);
283: }
284:
285: /*-------------------------------------------------------------------------*/
286:
287:
288: int strong_pseudorandom(byte *buf, int bufsize)
289: /*
290: Reads IDEA random key and random number seed from file, cranks the
291: the seed through the idearand strong pseudorandom number generator,
292: and writes them back out. This is used for generation of
293: cryptographically strong pseudorandom numbers. This is mainly to
294: save the user the trouble of having to type in lengthy keyboard
295: sequences for generation of truly random numbers every time we want
296: to make a random session key. This pseudorandom generator will only
297: work if the file containing the random seed exists and is not empty.
298: If it doesn't exist, it will be automatically created. If it exists
299: and is empty or nearly empty, it will not be used.
300: */
301: { char seedfile[MAX_PATH]; /* Random seed filename */
302: FILE *f;
303: byte key[IDEAKEYSIZE];
304: byte seed[IDEABLOCKSIZE];
305: int i;
306: word32 tstamp; byte *timestamp = (byte *) &tstamp;
307:
308: buildfilename(seedfile,RANDSEED_FILENAME);
309:
310: if (!file_exists(seedfile)) /* No seed file. Start one... */
311: { f = fopen(seedfile,"wb"); /* open for writing binary */
312: if (f==NULL) /* failed to create seedfile */
313: return(-1); /* error: no random number seed file available */
314: fclose(f); /* close new empty seed file */
315: /* kickstart the generator with true random numbers */
316: fprintf(pgpout,PSTR("Initializing random seed file..."));
317: randaccum(8*(sizeof(key)+sizeof(seed)));
318: for (i=1; i<sizeof(key); i++)
319: key[i] ^= randombyte();
320: for (i=0; i<sizeof(seed); i++)
321: seed[i] ^= randombyte();
322: } /* seedfile does not exist */
323:
324: else /* seedfile DOES exist. Open it and read it. */
325: { f = fopen(seedfile,"rb"); /* open for reading binary */
326: if (f==NULL) /* did open fail? */
327: return(-1); /* error: no random number seed file available */
328: /* read IDEA random generator key */
329: if (fread(key,1,sizeof(key),f) < sizeof(key)) /* empty file? */
330: { /* Empty or nearly empty file means don't use it. */
331: fclose(f);
332: return(-1); /* error: no random number seed file available */
333: }
334: else
335: fread(seed,1,sizeof(seed),f); /* read pseudorandom seed */
336: fclose(f);
337: } /* seedfile exists */
338:
339:
340: /* Initialize, key, and seed the IDEA pseudorandom generator: */
341: get_timestamp(timestamp); /* timestamp points to tstamp */
342: init_idearand(key, seed, tstamp);
343:
344: /* Note that the seed will be cycled thru IDEA before use */
345:
346: /* Now fill the user's buffer with gobbledygook... */
347: while (bufsize--)
348: *buf++ = idearand() ^ randombyte();
349:
350: /* now cover up evidence of what user got */
351: for (i=1; i<sizeof(key); i++)
352: key[i] ^= idearand() ^ randombyte();
353: for (i=0; i<sizeof(seed); i++)
354: seed[i] = idearand() ^ randombyte();
355:
356: close_idearand(); /* close IDEA random number generator */
357:
358: f = fopen(seedfile,"wb"); /* open for writing binary */
359: if (f==NULL) /* did open fail? */
360: return(-1); /* error: no random number seed file available */
361: /* Now at start of file again */
362: fwrite(key,1,sizeof(key),f);
363: fwrite(seed,1,sizeof(seed),f);
364: fclose(f);
365: burn(key); /* burn sensitive data on stack */
366: burn(seed); /* burn sensitive data on stack */
367: return(0); /* normal return */
368: } /* strong_pseudorandom */
369:
370:
371:
372: int make_random_ideakey(byte key[16])
373: /* Make a random IDEA key. Returns its length (a constant). */
374: { int count;
375:
376: if (strong_pseudorandom(key, IDEAKEYSIZE) == 0)
377: return(IDEAKEYSIZE);
378:
379: fprintf(pgpout,PSTR("Preparing random session key..."));
380:
381: randaccum(IDEAKEYSIZE*8); /* get some random key bits */
382:
383: count=0;
384: while (++count <= IDEAKEYSIZE)
385: key[count] = randombyte();
386:
387: return(IDEAKEYSIZE);
388:
389: } /* make_random_ideakey */
390:
391:
392: word32 getpastlength(byte ctb, FILE *f)
393: /* Returns the length of a packet according to the CTB and
394: the length field. */
395: { word32 length;
396: unsigned int llength; /* length of length */
397: byte buf[8];
398:
399: fill0(buf,sizeof(buf));
400: length = 0L;
401: /* Use ctb length-of-length field... */
402: llength = ctb_llength(ctb); /* either 1, 2, 4, or 8 */
403: if (llength==8) /* 8 means no length field, assume huge length */
404: return(-1L); /* return huge length */
405:
406: /* now read in the actual length field... */
407: if (fread((byteptr) buf,1,llength,f) < llength)
408: return (-2L); /* error -- read failure or premature eof */
409: /* convert length from external byteorder... */
410: if (llength==1)
411: length = (word32) buf[0];
412: if (llength==2)
413: length = (word32) fetch_word16(buf);
414: if (llength==4)
415: length = fetch_word32(buf);
416: return(length);
417: } /* getpastlength */
418:
419:
420: /* Write a CTB with the appropriate length field. If big is true,
421: * always use a four-byte length field.
422: */
423: void write_ctb_len (FILE *f, byte ctb_type, word32 length, boolean big)
424: {
425: int llength, llenb;
426: byte ctb;
427: byte buf[4];
428: int i;
429:
430: if (big || (length > 0xFFFFL))
431: { llength = 4;
432: llenb = 2;
433: }
434: else if ((word16)length > 0xFF)
435: { llength = 2;
436: llenb = 1;
437: }
438: else
439: { llength = 1;
440: llenb = 0;
441: }
442: ctb = CTB_BYTE(ctb_type, llenb);
443: fwrite( &ctb, 1, 1, f );
444: /* convert length to external byteorder... */
445: if (llength==1)
446: buf[0] = length;
447: if (llength==2)
448: put_word16((word16) length, buf);
449: if (llength==4)
450: put_word32(length, buf);
451: fwrite( buf, 1, llength, f );
452: } /* write_ctb_len */
453:
454:
455: int idea_file(byte *ideakey, boolean decryp, FILE *f, FILE *g, word32 lenfile)
456: /* Use IDEA in cipher feedback (CFB) mode to encrypt or decrypt a file.
457: The encrypted material starts out with a 64-bit random prefix, which
458: serves as an encrypted random CFB initialization vector, and
459: following that is 16 bits of "key check" material, which is a
460: duplicate of the last 2 bytes of the random prefix. Encrypted key
461: check bytes detect if correct IDEA key was used to decrypt ciphertext.
462: */
463: { int count;
464: word16 iv[4];
465: extern byte textbuf[DISKBUFSIZE];
466: #define RAND_PREFIX_LENGTH 8
467:
468: /* init CFB key */
469: fill0(iv,sizeof(iv)); /* define initialization vector IV as 0 */
470: initcfb_idea(iv,ideakey,decryp);
471:
472: if (!decryp) /* encrypt-- insert key check bytes */
473: { /* There is a random prefix followed by 2 key check bytes */
474: int i;
475:
476: for (i=0; i<RAND_PREFIX_LENGTH; ++i)
477: textbuf[i] = randombyte();
478: /* key check bytes are simply duplicates of final 2 random bytes */
479: textbuf[i] = textbuf[i-2]; /* key check bytes for redundancy */
480: textbuf[i+1] = textbuf[i-1];
481:
482: ideacfb(textbuf,RAND_PREFIX_LENGTH+2);
483: fwrite(textbuf,1,RAND_PREFIX_LENGTH+2,g);
484: }
485: else /* decrypt-- check for key check bytes */
486: { /* See if the redundancy is present after the random prefix */
487: count = fread(textbuf,1,RAND_PREFIX_LENGTH+2,f);
488: lenfile -= count;
489: if (count==(RAND_PREFIX_LENGTH+2))
490: { ideacfb(textbuf,RAND_PREFIX_LENGTH+2);
491: if ((textbuf[RAND_PREFIX_LENGTH] != textbuf[RAND_PREFIX_LENGTH-2])
492: || (textbuf[RAND_PREFIX_LENGTH+1] != textbuf[RAND_PREFIX_LENGTH-1]))
493: { return(-2); /* bad key error */
494: }
495: }
496: else /* file too short for key check bytes */
497: return(-3); /* error of the weird kind */
498: }
499:
500:
501: do /* read and write the whole file in CFB mode... */
502: { count = (lenfile < DISKBUFSIZE) ? (int)lenfile : DISKBUFSIZE;
503: count = fread(textbuf,1,count,f);
504: lenfile -= count;
505: if (count>0)
506: { ideacfb(textbuf,count);
507: fwrite(textbuf,1,count,g);
508: }
509: /* if text block was short, exit loop */
510: } while (count==DISKBUFSIZE);
511:
512: close_idea(); /* Clean up data structures */
513: burn(iv); /* burn sensitive data on stack */
514: burn(textbuf); /* burn sensitive data on stack */
515: return(0); /* should always take normal return */
516: } /* idea_file */
517:
518:
519: /* Checksum maintained as a running sum by read_mpi and write_mpi.
520: * The checksum is maintained based on the plaintext values being
521: * read and written. To use it, store a 0 to it before doing a set
522: * of read_mpi's or write_mpi's. Then read it aftwerwards.
523: */
524: word16 mpi_checksum;
525:
526: int read_mpi(unitptr r, FILE *f, boolean adjust_precision, boolean scrambled)
527: /* Read a mutiprecision integer from a file.
528: adjust_precision is TRUE iff we should call set_precision to the
529: size of the number read in.
530: scrambled is TRUE iff field is encrypted (protects secret key fields).
531: Returns the bitcount of the number read in, or returns a negative
532: number if an error is detected.
533: */
534: { byte buf[MAX_BYTE_PRECISION+2];
535: unsigned int count;
536: word16 bytecount,bitcount;
537:
538: mp_init(r,0);
539:
540: if ((count = fread(buf,1,2,f)) < 2)
541: return (-1); /* error -- read failure or premature eof */
542:
543: bitcount = fetch_word16(buf);
544: if (bits2units(bitcount) > global_precision)
545: return(-1); /* error -- possible corrupted bitcount */
546:
547: bytecount = bits2bytes(bitcount);
548:
549: count = fread(buf+2,1,bytecount,f);
550: if (count < bytecount)
551: return(-1); /* error -- premature eof */
552:
553: if (scrambled) /* decrypt the field */
554: ideacfb(buf+2,bytecount);
555:
556: /* Update running checksum, in case anyone cares... */
557: mpi_checksum += checksum (buf, bytecount+2);
558:
559: /* We assume that the bitcount prefix we read is an exact
560: bitcount, not rounded up to the next byte boundary.
561: Otherwise we would have to call mpi2reg, then call
562: countbits, then call set_precision, then recall mpi2reg
563: again.
564: */
565: if (adjust_precision && bytecount)
566: { /* set the precision to that specified by the number read. */
567: set_precision(bits2units(bitcount+SLOP_BITS));
568: /* Now that precision is optimally set, call mpi2reg */
569: }
570:
571: mpi2reg(r,buf); /* convert to internal format */
572: burn(buf); /* burn sensitive data on stack */
573: return (bitcount);
574: } /* read_mpi */
575:
576:
577:
578: void write_mpi(unitptr n, FILE *f, boolean scrambled)
579: /* Write a multiprecision integer to a file.
580: scrambled is TRUE iff we should scramble field on the way out,
581: which is used to protect secret key fields.
582: */
583: { byte buf[MAX_BYTE_PRECISION+2];
584: short bytecount;
585: bytecount = reg2mpi(buf,n);
586: mpi_checksum += checksum (buf, bytecount+2);
587: if (scrambled) /* encrypt the field, skipping over the bitcount */
588: ideacfb(buf+2,bytecount);
589: fwrite(buf,1,bytecount+2,f);
590: burn(buf); /* burn sensitive data on stack */
591: } /* write_mpi */
592:
593:
594: /*======================================================================*/
595:
596:
597: int get_header_info_from_file(char *infile, byte *header, int count)
598: /* Reads the first count bytes from infile into header. */
599: { FILE *f;
600: fill0(header,count);
601: /* open file f for read, in binary (not text) mode...*/
602: if ((f = fopen(infile,"rb")) == NULL)
603: return(-1);
604: /* read Cipher Type Byte, and maybe more */
605: count = fread(header,1,count,f);
606: fclose(f);
607: return(count); /* normal return */
608: } /* get_header_info_from_file */
609:
610:
611: /* System clock must be broken if it isn't past this date: */
612: #define REASONABLE_DATE ((unsigned long) 0x27804180L) /* 91 Jan 01 00:00:00 */
613:
614:
615: int make_signature_certificate(byte *certificate, MD5_CTX *MD, byte class,
616: unitptr n, unitptr d, unitptr p, unitptr q, unitptr u)
617: /* Constructs a signed message digest in a signature certificate.
618: Returns total certificate length in bytes, or returns negative
619: error status.
620: */
621: {
622: byte inbuf[MAX_BYTE_PRECISION], outbuf[MAX_BYTE_PRECISION];
623: byte mdpacket[17];
624: byte *mdbufptr;
625: int i,j,certificate_length,blocksize,bytecount;
626: word16 ske_length;
627: word32 tstamp; byte *timestamp = (byte *) &tstamp;
628: byte keyID[KEYFRAGSIZE];
629: byte val;
630: int mdlen = 5; /* length of class plus timestamp, for adding to MD */
631:
632: /* Note that RSA key must be at least big enough to encipher a
633: complete message digest packet in a single RSA block. */
634:
635: blocksize = countbytes(n)-1; /* size of a plaintext block */
636: if (blocksize < 31)
637: { fprintf(pgpout,"\n\007Error: RSA key length must be at least 256 bits.\n");
638: return(-1);
639: }
640:
641: get_timestamp(timestamp); /* Timestamp when signature was made */
642: if (tstamp < REASONABLE_DATE) /* complain about bad time/date setting */
643: { fprintf(pgpout,PSTR("\n\007Error: System clock/calendar is set wrong.\n"));
644: return(-1);
645: }
646: convert_byteorder(timestamp,4); /* convert to external form */
647:
648: /* Finish off message digest calculation with this information */
649: MD_addbuffer (MD, &class, 1, FALSE);
650: MD_addbuffer (MD, timestamp, 4, TRUE);
651:
652: #ifdef XLOWFIRST /* Assumes LSB-first order */
653: mdbufptr = MD->digest; /* point at actual message digest */
654: for (i=0; i<sizeof(mdpacket)-1; i++)
655: { mdpacket[i] = *mdbufptr++;
656: }
657: mdpacket[i] = MD5_ALGORITHM_BYTE;
658: #else
659: /* Assumes MSB-first order */
660: mdpacket[0] = MD5_ALGORITHM_BYTE;
661: mdbufptr = MD->digest; /* point at actual message digest */
662: for (i=1; i<sizeof(mdpacket); i++)
663: { mdpacket[i] = *mdbufptr++;
664: }
665: #endif
666: /* Pre-block mdpacket, and convert to INTERNAL byte order: */
667: preblock((unitptr)inbuf, mdpacket, sizeof(mdpacket), n, NULL);
668:
669: fprintf(pgpout,PSTR("Just a moment...")); /* RSA will take a while. */
670: fflush(pgpout);
671:
672: /* do RSA signature calculation: */
673: rsa_decrypt((unitptr)outbuf,(unitptr)inbuf,d,p,q,u);
674:
675: /* bytecount does not include the 2 prefix bytes */
676: bytecount = reg2mpi(outbuf,(unitptr)outbuf); /* convert to external format */
677: /* outbuf now contains a message digest in external byteorder
678: form. Now make a complete signature certificate from this.
679: */
680:
681: certificate_length = 0;
682:
683: /* SKE is Secret Key Encryption (signed). Append CTB for signed msg. */
684: certificate[certificate_length++] = CTB_SKE;
685:
686: /* SKE packet length does not include itself or CTB prefix: */
687: ske_length = 1 + 1 /* version and mdlen byte */
688: + mdlen /* class, timestamp and validation period */
689: + KEYFRAGSIZE + 1 + 1 /* Key ID and 2 algorithm bytes */
690: + 2 + bytecount+2; /* 2 MD bytes and RSA MPI w/bitcount */
691: put_word16((word16) ske_length, certificate+certificate_length);
692: certificate_length+=2; /* advance past word */
693:
694: certificate[certificate_length++] = VERSION_BYTE;
695:
696: /* Begin fields that are included in MD calculation... */
697:
698: certificate[certificate_length++] = mdlen; /* mdlen is length of MD-extras */
699:
700: certificate[certificate_length++] = class & 0xff;
701: mdlen--; /* assume class byte always present */
702:
703: /* timestamp already in external format */
704: if (mdlen>0)
705: { for (j=0; j<SIZEOF_TIMESTAMP; j++)
706: { certificate[certificate_length++] = timestamp[j];
707: mdlen--;
708: }
709: }
710:
711: /* if any bytes remain in mdlen, assume it's the validation period */
712: if (mdlen>0)
713: { val = 0; /* Validation period */
714: put_word16(val, certificate+certificate_length);
715: certificate_length+=2; /* advance past word */
716: mdlen-=2;
717: }
718: /* hopefully, mdlen is now zero. */
719:
720: /* ...end of fields that are included in MD calculation */
721:
722: /* Now append keyID... */
723: extract_keyID(keyID, n); /* gets keyID */
724: for (i=0; i<KEYFRAGSIZE; i++)
725: certificate[certificate_length++] = keyID[i];
726:
727: certificate[certificate_length++] = RSA_ALGORITHM_BYTE;
728: certificate[certificate_length++] = MD5_ALGORITHM_BYTE;
729:
730: /* Now append first two bytes of message digest */
731: mdbufptr = MD->digest;
732: certificate[certificate_length++] = *mdbufptr++;
733: certificate[certificate_length++] = *mdbufptr++;
734:
735: /* Now append the RSA-signed message digest packet: */
736: for (i=0; i<bytecount+2; i++)
737: certificate[certificate_length++] = outbuf[i];
738:
739: fputc('.',pgpout); /* Signal RSA signature completion. */
740:
741: burn(inbuf); /* burn sensitive data on stack */
742: burn(outbuf); /* burn sensitive data on stack */
743:
744: return(certificate_length); /* return length of certificate in bytes */
745:
746: } /* make_signature_certificate */
747:
748:
749: /*======================================================================*/
750:
751:
752: int signfile(boolean nested, boolean separate_signature,
753: char *mcguffin, char *infile, char *outfile,
754: char lit_mode, char *literalfile)
755: /* Write an RSA-signed message digest of input file to specified
756: output file, and append input file to output file.
757: separate_signature is TRUE iff we should not append the
758: plaintext to the output signature certificate.
759: If lit_mode is MODE_TEXT, we know the infile is in canonical form.
760: We create a CTB_LITERAL packet for the plaintext data.
761: */
762: {
763: FILE *f;
764: FILE *g;
765: int certificate_length; /* signature certificate length */
766: byte certificate[MAX_SIGCERT_LENGTH];
767: char lfile[MAX_PATH];
768: byte signature_class;
769:
770: { /* temporary scope for some buffers */
771: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
772: byte userid[256];
773: char keyfile[MAX_PATH];
774: long fp;
775: int pktlen, status;
776: MD5_CTX MD;
777: byte keyID[KEYFRAGSIZE];
778: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION];
779: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
780:
781: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
782:
783: if (verbose)
784: fprintf(pgpout,PSTR("\nPlaintext file: %s, signature file: %s\n"),
785: infile,outfile);
786:
787: if (MDfile(&MD, infile) < 0)
788: return(-1); /* problem with input file. error return */
789:
790: userid[0] = '\0';
791: if (mcguffin)
792: strcpy((char *) userid,mcguffin); /* Who we are looking for */
793:
794: if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
795: userid, n, e, d, p, q, u) < 0)
796: return(-1); /* problem with secret key file. error return. */
797:
798: extract_keyID(keyID, n);
799: buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
800: if ((status = getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
801: keyID, timestamp, userid, n, e)) != 0)
802: { if (status == 1)
803: { PascalToC((char *) userid);
804: fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\
805: has been revoked. You cannot use this key.\n"), EXTERNAL((char *)userid)); /* same msg in signkey */
806: }
807: return(-1); /* problem with public key file. error return. */
808: }
809:
810: if (lit_mode==MODE_TEXT) signature_class = SM_SIGNATURE_BYTE;
811: else signature_class = SB_SIGNATURE_BYTE;
812:
813: certificate_length = make_signature_certificate(certificate, &MD,
814: signature_class, n, d, p, q, u);
815: if (certificate_length < 0)
816: return(-1); /* error return from make_signature_certificate() */
817: } /* end of scope for some buffers */
818:
819: /* open file f for read, in binary (not text) mode...*/
820: #ifdef VMS
821: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
822: #else /* VMS */
823: if ((f = fopen(infile,"rb")) == NULL)
824: #endif /* VMS */
825: { fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"),infile);
826: return(-1);
827: }
828:
829: /* open file g for write, in binary (not text) mode...*/
830: if ((g = fopen(outfile,"wb")) == NULL)
831: { fprintf(pgpout,PSTR("\n\007Can't create signature file '%s'\n"),outfile);
832: fclose(f);
833: return(-1);
834: }
835:
836: /* write out certificate record to outfile ... */
837: fwrite(certificate,1,certificate_length,g);
838:
839: if (!separate_signature)
840: { if (!nested)
841: { word32 flen = fsize(f);
842: word32 dummystamp = 0;
843: write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
844: fwrite ( &lit_mode, 1, 1, g ); /* write lit_mode */
845: /* write literalfile name */
846: if (literalfile == NULL)
847: { /* Put in a zero byte to indicate no filename */
848: fputc ('\0', g);
849: }
850: else
851: { strcpy( lfile, literalfile );
852: file_to_canon( lfile );
853: CToPascal( lfile );
854: fwrite ( lfile, 1, lfile[0]+1, g);
855: }
856: /* Dummy file creation timestamp */
857: fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
858: }
859: copyfile(f,g,-1L); /* copy rest of file from file f to g */
860: }
861:
862: fclose(g);
863: fclose(f);
864: return(0); /* normal return */
865:
866: } /* signfile */
867:
868:
869: /*======================================================================*/
870:
871:
872: int compromise(char *keyguffin, char *keyfile)
873: {
874: FILE *f, *g;
875: byte ctb; /* Cipher Type Byte */
876: int certificate_length; /* signature certificate length */
877: byte certificate[MAX_SIGCERT_LENGTH];
878: byte keyID[KEYFRAGSIZE];
879: word32 tstamp; byte *timestamp = (byte *) &tstamp;
880: byte userid[256];
881: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
882: MD5_CTX MD;
883: unit d[MAX_UNIT_PRECISION];
884: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
885: long fp, insertpos;
886: int pktlen;
887: int status, prec;
888:
889: if (build_path(SCRATCH_KEYRING_PATH,SCRATCH_KEYRING_FILENAME,keyfile)<0)
890: return(-1); /* File path too long */
891:
892: strcpy((char *)userid, keyguffin);
893: if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
894: userid, n, e, d, p, q, u) < 0)
895: return(-1); /* problem with secret key file. error return. */
896:
897: extract_keyID(keyID, n);
898:
899: strcpy((char *)userid, keyguffin);
900:
901: if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
902: keyID, timestamp, userid, n, e) < 0)
903: return(-1);
904:
905: PascalToC((char *) userid);
906: fprintf(pgpout,
907: PSTR("\nDo you want to permanently revoke your public key\n\
908: by issuing a secret key compromise certificate\n\
909: for \"%s\" (y/N)? "), EXTERNAL((char *)userid));
910: if (!getyesno('n'))
911: return(-1);
912:
913: /* open file f for read, in binary (not text) mode...*/
914: if ((f = fopenbin(keyfile,"r")) == NULL)
915: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
916: return(-1);
917: }
918:
919: fseek (f, fp+pktlen, SEEK_SET);
920: nextkeypacket(f, &ctb);
921: if (ctb == CTB_KEYCTRL)
922: { insertpos = ftell(f);
923: nextkeypacket(f, &ctb);
924: }
925: else
926: insertpos = fp + pktlen;
927:
928: if (is_ctb_type(ctb, CTB_SKE_TYPE))
929: {
930: fprintf(pgpout, PSTR("This key has already been revoked.\n"));
931: fclose(f);
932: return(-1);
933: }
934:
935: prec = global_precision;
936: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
937:
938: fseek(f, fp, SEEK_SET);
939: /* Calculate signature */
940: if (MDfile0_len(&MD, f, pktlen) < 0)
941: { fclose(f);
942: return(-1); /* problem with input file. error return */
943: }
944: set_precision(prec);
945:
946: certificate_length = make_signature_certificate(certificate, &MD,
947: KC_SIGNATURE_BYTE, n, d, p, q, u);
948: if (certificate_length < 0)
949: { fclose(f);
950: return(-1); /* error return from make_signature_certificate() */
951: }
952:
953:
954: /* open file g for write, in binary (not text) mode...*/
955: remove(SCRATCH_KEYRING_PATH);
956: if ((g = fopen(SCRATCH_KEYRING_PATH,"wb")) == NULL)
957: { fprintf(pgpout,PSTR("\n\007Can't create output file to update key ring.\n"));
958: fclose(f);
959: return(-1);
960: }
961:
962: /* Copy pre-key and key to file g */
963: rewind(f);
964: copyfile (f, g, insertpos);
965:
966: /* write out certificate record to outfile ... */
967: fwrite(certificate,1,certificate_length,g);
968:
969: /* Copy the remainder from file f to file g */
970: copyfile (f, g, -1L);
971:
972: fflush(g);
973: if (ferror(g))
974: { fclose(g);
975: return(-1);
976: }
977: fclose(g);
978:
979: backup_rename(SCRATCH_KEYRING_PATH,keyfile);
980:
981: fprintf(pgpout, PSTR("\nKey compromise certificate created.\n"));
982: return(0); /* normal return */
983: } /* compromise */
984:
985: /*======================================================================*/
986:
987:
988: int signkey(char *keyguffin, char *sigguffin, char *keyfile)
989: /* Write an RSA-signed message digest of key for user keyguffin in
990: keyfile, using signature from user sigguffin. Append
991: the signature right after the key.
992: */
993: {
994: FILE *f;
995: FILE *g;
996: byte ctb; /* Cipher Type Byte */
997: int certificate_length; /* signature certificate length */
998: byte certificate[MAX_SIGCERT_LENGTH];
999: byte keyID[KEYFRAGSIZE], keyID2[KEYFRAGSIZE];
1000: word32 tstamp; byte *timestamp = (byte *) &tstamp;
1001: byte userid[256];
1002: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1003: char pubring[MAX_PATH];
1004: long fp, fpusr;
1005: int pktlen, usrpktlen, usrctrllen;
1006: char *tempring;
1007: int status;
1008:
1009: /* Get signature key ID */
1010: strcpy((char *)userid,sigguffin); /* Who we are looking for */
1011: if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
1012: userid, n, e, NULL, NULL, NULL, NULL) < 0)
1013: {
1014: return(-1); /* problem with secret key file. error return. */
1015: }
1016: extract_keyID(keyID, n); /* Remember signer key ID */
1017: buildfilename(pubring,PUBLIC_KEYRING_FILENAME); /* use default pathname */
1018: if ((status = getpublickey(FALSE, FALSE, pubring, &fp, &pktlen,
1019: keyID, timestamp, userid, n, e)) != 0)
1020: { if (status == 1)
1021: { PascalToC((char *) userid);
1022: fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\
1023: has been revoked. You cannot use this key.\n"), EXTERNAL((char *)userid)); /* same msg in signfile */
1024: }
1025: return(-1); /* problem with public key file. error return. */
1026: }
1027:
1028: strcpy((char *)userid, keyguffin);
1029: fprintf(pgpout, PSTR("\nLooking for key for user '%s':\n"), EXTERNAL((char *)userid));
1030:
1031: if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen,
1032: NULL, timestamp, userid, n, e) < 0)
1033: return(-1);
1034: PascalToC((char *) userid);
1035: if (getpubuserid (keyfile, fp, (byte *)keyguffin, &fpusr, &usrpktlen) < 0)
1036: return(-1);
1037:
1038: /* open file f for read, in binary (not text) mode...*/
1039: #ifdef VMS
1040: if ((f = fopen(keyfile,"rb","ctx=stm")) == NULL)
1041: #else
1042: if ((f = fopen(keyfile,"rb")) == NULL)
1043: #endif
1044: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
1045: return(-1);
1046: }
1047:
1048: fseek(f, fp, SEEK_SET);
1049: if (is_compromised(f))
1050: { fprintf(pgpout, PSTR("\n\007Sorry, this key has been revoked by its owner.\n"));
1051: fclose(f);
1052: return(-1);
1053: }
1054: /* See if there is another signature with this keyID already */
1055: fseek (f, fpusr+usrpktlen, SEEK_SET);
1056: nextkeypacket(f, &ctb); /* Add key control packet to len */
1057: usrctrllen = 0;
1058: if (ctb != CTB_KEYCTRL)
1059: fseek(f,fpusr+usrpktlen,SEEK_SET);
1060: else
1061: usrctrllen = ftell(f) - (fpusr+usrpktlen);
1062: for ( ; ; )
1063: { status = readkeypacket(f,FALSE,&ctb,NULL,NULL,NULL,NULL,
1064: NULL,NULL,NULL,NULL,keyID2,NULL);
1065: if (status < 0 || is_key_ctb (ctb) || ctb==CTB_USERID)
1066: break;
1067: if (equal_buffers(keyID, keyID2, KEYFRAGSIZE))
1068: { fprintf(pgpout,PSTR("\n\007Key is already signed by user '%s'.\n"),
1069: EXTERNAL(sigguffin));
1070: fclose(f);
1071: return(-1);
1072: }
1073: }
1074: rewind(f);
1075:
1076: fprintf(pgpout,
1077: PSTR("\n\nREAD CAREFULLY: Based on your own direct first-hand knowledge, are\n\
1078: you absolutely certain that you are prepared to solemnly certify that\n\
1079: the above public key actually belongs to the user specified by the\n\
1080: above user ID (y/N)? "));
1081:
1082: if (!getyesno('n'))
1083: { fclose(f);
1084: return(-1);
1085: }
1086:
1087: { /* temporary scope for some buffers */
1088: MD5_CTX MD;
1089: unit d[MAX_UNIT_PRECISION];
1090: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
1091:
1092: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1093:
1094: if ((g = fopen(keyfile,"rb")) == NULL)
1095: { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
1096: return(-1);
1097: }
1098: fseek(g, fp, SEEK_SET);
1099: /* Calculate signature */
1100: if (MDfile0_len(&MD, g, pktlen) < 0)
1101: { fclose(g);
1102: fclose(f);
1103: return(-1); /* problem with input file. error return */
1104: }
1105: fclose(g);
1106:
1107: /* Add data from user id */
1108: CToPascal((char *)userid);
1109: MD5Update(&MD, userid+1, (int)(unsigned char)userid[0]);
1110:
1111: strcpy((char *)userid,sigguffin); /* Who we are looking for */
1112:
1113: if (getsecretkey(FALSE, FALSE, NULL, NULL, timestamp, NULL, NULL,
1114: userid, n, e, d, p, q, u) < 0)
1115: { fclose(f);
1116: return(-1); /* problem with secret key file. error return. */
1117: }
1118:
1119: certificate_length = make_signature_certificate(certificate, &MD,
1120: K0_SIGNATURE_BYTE, n, d, p, q, u);
1121: if (certificate_length < 0)
1122: return(-1); /* error return from make_signature_certificate() */
1123:
1124: } /* end of scope for some buffers */
1125:
1126: /* open file g for write, in binary (not text) mode...*/
1127: tempring = tempfile(TMP_TMPDIR);
1128: if ((g = fopen(tempring,"wb")) == NULL)
1129: { fprintf(pgpout,PSTR("\n\007Can't create output file to update key ring.\n"));
1130: fclose(f);
1131: return(-1);
1132: }
1133:
1134: /* Copy pre-key and key to file g */
1135: copyfile (f, g, fpusr+usrpktlen+usrctrllen);
1136:
1137: /* write out certificate record to outfile ... */
1138: fwrite(certificate,1,certificate_length,g);
1139:
1140: /* Add "trusty" control packet */
1141: write_trust (g, KC_SIGTRUST_ULTIMATE | KC_CONTIG);
1142:
1143: /* Copy the remainder from file f to file g */
1144: copyfile (f, g, -1L);
1145:
1146: fclose(g);
1147: fclose(f);
1148:
1149: savetempbak(tempring,keyfile);
1150:
1151: fprintf(pgpout, PSTR("\nKey signature certificate added.\n"));
1152: return(0); /* normal return */
1153:
1154: } /* signkey */
1155:
1156:
1157: /*======================================================================*/
1158:
1159: int check_signaturefile(char *infile, char *outfile, boolean strip_signature,
1160: boolean explicit_outfile_flag)
1161: { /* Check signature in infile for validity. Strip off the signature
1162: and write the remaining packet to outfile. If strip_signature,
1163: also write the signature to outfile.sig. If the packet after
1164: the signature is a LITERAL2, use the filename from there unless
1165: explict_outfile_flag is set.
1166: */
1167: byte ctb,ctb2; /* Cipher Type Bytes */
1168: char keyfile[MAX_PATH]; /* for getpublickey */
1169: char sigfile[MAX_PATH]; /* .sig file if strip_signature */
1170: long fp; /* unused, just to satisfy getpublickey */
1171: int pktlen; /* unused, just to satisfy getpublickey */
1172: FILE *f;
1173: FILE *g;
1174: long start_text; /* marks file position */
1175: int i,count;
1176: word16 cert_length;
1177: byte certbuf[MAX_SIGCERT_LENGTH];
1178: byteptr certificate; /* for parsing certificate buffer */
1179: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1180: byte inbuf[MAX_BYTE_PRECISION];
1181: byte outbuf[MAX_BYTE_PRECISION];
1182: byte keyID[KEYFRAGSIZE];
1183: word32 tstamp;
1184: byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
1185: word32 dummystamp;
1186: byte userid[256];
1187: MD5_CTX MD;
1188: boolean separate_signature;
1189: extern boolean moreflag;
1190: char lit_mode = MODE_BINARY;
1191: unsigned char litfile[MAX_PATH];
1192: word32 text_len;
1193: byte *mdextras;
1194: byte mdlensave;
1195: byte version;
1196: byte mdlen; /* length of material to be added to MD calculation */
1197: byte class;
1198: byte algorithm;
1199: byte mdlow2[2];
1200:
1201: fill0( keyID, KEYFRAGSIZE );
1202:
1203: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1204:
1205: buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
1206:
1207: if (verbose)
1208: fprintf(pgpout,PSTR("\nSignature file: %s, output file: %s\n"),
1209: infile,outfile);
1210:
1211: /* open file f for read, in binary (not text) mode...*/
1212: #ifdef VMS
1213: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
1214: #else
1215: if ((f = fopen(infile,"rb")) == NULL)
1216: #endif /* VMS */
1217: { fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
1218: return(-1);
1219: }
1220:
1221: /******************** Read header CTB and length field ******************/
1222:
1223: fread(&ctb,1,1,f); /* read certificate CTB byte */
1224: certificate = certbuf;
1225: *certificate++ = ctb; /* copy ctb into certificate */
1226:
1227: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
1228: goto badcert; /* complain and return bad status */
1229:
1230: cert_length = getpastlength(ctb, f); /* read certificate length */
1231: certificate += ctb_llength(ctb); /* either 1, 2, 4, or 8 */
1232: if (cert_length > MAX_SIGCERT_LENGTH-3) /* Huge packet length */
1233: goto badcert; /* complain and return bad status */
1234:
1235: /* read whole certificate: */
1236: if (fread((byteptr) certificate, 1, cert_length, f) < cert_length)
1237: /* bad packet length field */
1238: goto badcert; /* complain and return bad status */
1239:
1240: version = *certificate++;
1241: if (version_error(version, VERSION_BYTE))
1242: goto err1;
1243:
1244: mdlensave = mdlen = *certificate++; /* length of material to be added to MD */
1245: mdextras = certificate; /* pointer to extra material for MD calculation */
1246:
1247: class = *certificate++;
1248: if (class != SM_SIGNATURE_BYTE && class != SB_SIGNATURE_BYTE)
1249: { (void) version_error(class, SM_SIGNATURE_BYTE);
1250: goto err1;
1251: }
1252: mdlen--;
1253:
1254: if (mdlen>0) /* if more MD material is included... */
1255: { for (i=0; i<SIZEOF_TIMESTAMP; ++i)
1256: { timestamp[i] = *certificate++;
1257: mdlen--;
1258: }
1259: }
1260:
1261: if (mdlen>0) /* if more MD material is included... */
1262: { certificate+=2; /* skip past unused validity period field */
1263: mdlen-=2;
1264: }
1265:
1266: for (i=0; i<KEYFRAGSIZE; i++)
1267: keyID[i] = *certificate++; /* copy rest of key fragment */
1268:
1269: algorithm = *certificate++;
1270: if (version_error(algorithm, RSA_ALGORITHM_BYTE))
1271: goto err1;
1272:
1273: algorithm = *certificate++;
1274: if (version_error(algorithm, MD5_ALGORITHM_BYTE))
1275: goto err1;
1276:
1277: mdlow2[0] = *certificate++;
1278: mdlow2[1] = *certificate++;
1279:
1280: /* We used to set precision here based on certificate, but it is
1281: better to use the value based on n, since that was used when we
1282: signed the message. The certificate length could be less than n's
1283: length. We will call getpublickey here just to set the precision.
1284: */
1285: (void)getpublickey(FALSE, verbose, keyfile, &fp, &pktlen,
1286: keyID, (byte *)&dummystamp, userid, n, e);
1287:
1288: mpi2reg((unitptr)inbuf,certificate); /* get signed message digest */
1289: certificate += countbytes((unitptr)inbuf)+2;
1290:
1291: if ((certificate-certbuf) != cert_length+3)
1292: /* Bad length in signature certificate. Off by
1293: ((certificate-certbuf) - (cert_length+3)) */
1294: goto badcert; /* complain and return bad status */
1295:
1296: start_text = ftell(f); /* mark position of text for later */
1297:
1298: if (fread(outbuf,1,1,f) < 1) /* see if any plaintext is there */
1299: { /* Signature certificate has no plaintext following it.
1300: Must be in another file. Go look. */
1301: separate_signature = TRUE;
1302: fclose(f);
1303: fprintf(pgpout,PSTR("\nFile '%s' has signature, but with no text."),infile);
1304: if (!file_exists(outfile))
1305: force_extension(outfile, "");
1306: if (file_exists(outfile))
1307: { fprintf(pgpout,PSTR("\nText is assumed to be in file '%s'.\n"),outfile);
1308: }
1309: else
1310: { fprintf(pgpout,PSTR("\nPlease enter filename of text that signature applies to: "));
1311: getstring(outfile,59,TRUE); /* echo keyboard */
1312: if ((int)strlen(outfile) == 0)
1313: return(-1);
1314: }
1315: /* open file f for read, in binary (not text) mode...*/
1316: #ifdef VMS
1317: if ((f = fopen(outfile,"rb","ctx=stm")) == NULL)
1318: #else /* VMS */
1319: if ((f = fopen(outfile,"rb")) == NULL)
1320: #endif /* VMS */
1321: { fprintf(pgpout,PSTR("\n\007Can't open file '%s'\n"),outfile);
1322: return(-1);
1323: }
1324: start_text = ftell(f); /* mark position of text for later */
1325: text_len = fsize(f); /* remember length of text */
1326: } /* had to open new input file */
1327: else
1328: { separate_signature = FALSE;
1329: /* We just read 1 byte, so outbuf[0] should contain a ctb,
1330: maybe a CTB_LITERAL byte. */
1331: ctb2 = outbuf[0];
1332: if (is_ctb(ctb2) && is_ctb_type(ctb2,CTB_LITERAL_TYPE))
1333: { /* Read literal data */
1334: text_len = getpastlength(ctb2, f); /* read packet length */
1335: lit_mode = '\0';
1336: fread (&lit_mode,1,1,f); /* get literal packet mode byte */
1337: if (lit_mode != MODE_TEXT && lit_mode != MODE_BINARY)
1338: { fprintf(pgpout,"\n\007Error: Illegal mode byte %02x in literal packet.\n",
1339: lit_mode); /* English-only diagnostic for debugging */
1340: (void) version_error(lit_mode, MODE_BINARY);
1341: goto err1;
1342: }
1343: if (verbose)
1344: fprintf(pgpout, PSTR("File type: '%c'\n"), lit_mode);
1345: /* Read literal file name, use it if possible */
1346: litfile[0] = 0;
1347: fread (litfile,1,1,f);
1348: if ((int)litfile[0] > MAX_PATH)
1349: litfile[0] = 0; /* If too long for us, ignore it */
1350: if (litfile[0] > 0)
1351: fread (litfile+1,1,litfile[0],f);
1352: /* Use litfile if it's writeable and he didn't say an outfile */
1353: if (litfile[0] > 0)
1354: { PascalToC( (char *)litfile );
1355: if (verbose)
1356: fprintf(pgpout, PSTR("Original plaintext file name was: '%s'\n"), litfile);
1357: if (!strcmp((char *) litfile, CONSOLE_FILENAME) || !explicit_outfile_flag)
1358: { file_from_canon( (char *)litfile );
1359: if (file_ok_write( (char *)litfile ))
1360: strcpy ( outfile, (char *)litfile );
1361: }
1362: }
1363: /* Discard file creation timestamp for now */
1364: fread (&dummystamp, 1, sizeof(dummystamp), f);
1365: start_text = ftell(f); /* mark position of text for later */
1366: } /* packet is CTB_LITERAL_TYPE */
1367: }
1368:
1369: /* Use keyID prefix to look up key... */
1370:
1371: /* Get and validate public key from a key file: */
1372: if (getpublickey(FALSE, verbose, keyfile, &fp, &pktlen,
1373: keyID, (byte *)&dummystamp, userid, n, e) < 0)
1374: { /* Can't get public key. Complain and process file copy anyway. */
1375: fprintf(pgpout,PSTR("\n\007WARNING: Can't find the right public key-- can't check signature integrity.\n"));
1376: goto outsig;
1377: } /* Can't find public key */
1378:
1379: if (warn_signatures(keyfile, fp, pktlen, (char *)userid, TRUE) < 0)
1380: goto err1;
1381:
1382: /* Recover message digest via public key */
1383: mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n);
1384:
1385: fputc('.',pgpout); /* Signal RSA completion. */
1386:
1387: /* Unblock message digest, and convert to external byte order: */
1388: count = postunblock(outbuf, (unitptr)outbuf, n);
1389: if (count < 0)
1390: { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
1391: This may be caused either by corrupted data or by using the wrong RSA key.\n"));
1392: goto outsig; /* Output data anyway */
1393: }
1394:
1395: /* outbuf should contain message digest packet */
1396: /*==================================================================*/
1397: /* Look at nested stuff within RSA block... */
1398:
1399: #ifdef XLOWFIRST
1400: /* Position of algorithm byte assumes LSB-first byteorder... */
1401: if (outbuf[count-1] != MD5_ALGORITHM_BYTE)
1402: #else
1403: /* Position of algorithm byte assumes MSB-first byteorder... */
1404: if (outbuf[0] != MD5_ALGORITHM_BYTE)
1405: #endif
1406: { fprintf(pgpout,PSTR("\007\nUnrecognized message digest algorithm.\n"));
1407: fprintf(pgpout,PSTR("This may require a newer version of PGP.\n"));
1408: fprintf(pgpout,PSTR("Can't check signature integrity.\n"));
1409: goto outsig; /* Output data anyway */
1410: }
1411:
1412: #ifdef XLOWFIRST
1413: if (outbuf[0] != mdlow2[0] || outbuf[1] != mdlow2[1])
1414: #else
1415: if (outbuf[1] != mdlow2[0] || outbuf[2] != mdlow2[1])
1416: #endif
1417: { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
1418: This may be caused either by corrupted data or by using the wrong RSA key.\n"));
1419: goto outsig; /* Output data anyway */
1420: }
1421:
1422: /* Reposition file to where that plaintext begins... */
1423: fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
1424:
1425: MDfile0_len(&MD,f,text_len);/* compute a message digest from rest of file */
1426:
1427: MD_addbuffer (&MD, mdextras, mdlensave, TRUE); /* Finish message digest */
1428:
1429: convert_byteorder(timestamp,4); /* convert timestamp from external form */
1430: PascalToC((char *)userid); /* for display */
1431:
1432: /* now compare computed MD with claimed MD */
1433: #ifdef XLOWFIRST
1434: if (!equal_buffers((byte *)(MD.digest), outbuf, 16))
1435: #else
1436: if (!equal_buffers((byte *)(MD.digest), outbuf+1, 16))
1437: #endif
1438: { fprintf(pgpout,PSTR("\007\nWARNING: Bad signature, doesn't match file contents!\007\n"));
1439: fprintf(pgpout,PSTR("\nBad signature from user \"%s\".\n"),EXTERNAL((char *)userid));
1440: fprintf(pgpout,PSTR("Signature made %s\n"),ctdate((word32 *)timestamp));
1441: #ifndef CANONICAL_TEXT /* native text format is not canonical text */
1442: /* NOTE: IF the signature is bad, AND this machine does not
1443: use MSDOS-style canonical text as its native text format,
1444: AND this is a detached signature certificate, AND this
1445: file appears to contain ASCII text, THEN maybe we should
1446: convert the file to canonical text form and try checking
1447: the signature again.
1448: This is because a detached signature certificate probably
1449: means the file is not currently in a canonical text packet,
1450: but it may have been in canonical text form when the
1451: signature was created.
1452: */
1453: if (class == SM_SIGNATURE_BYTE && separate_signature)
1454: { if (is_text_file(outfile))
1455: fprintf(pgpout,PSTR("\n\007PGP may have problems checking signatures against text files\n\
1456: if the text was created on a different system with a different\n\
1457: text file format.\n"));
1458: /* Unfortunately, we don't give the user a way to convert it. */
1459: }
1460: #endif /* not CANONICAL_TEXT */
1461: if (moreflag)
1462: { /* more will scroll the message off the screen */
1463: fprintf(pgpout, PSTR("\nPress ENTER to continue..."));
1464: fflush(pgpout);
1465: getyesno('n');
1466: }
1467: goto outsig; /* Output data anyway */
1468: }
1469:
1470: fprintf(pgpout,PSTR("\nGood signature from user \"%s\".\n"),EXTERNAL((char *)userid));
1471: fprintf(pgpout,PSTR("Signature made %s\n"),ctdate((word32 *)timestamp));
1472:
1473: outsig:
1474: /* Reposition file to where that plaintext begins... */
1475: fseek(f,start_text,SEEK_SET); /* reposition file from last ftell */
1476:
1477: if (separate_signature)
1478: fprintf(pgpout,PSTR("\nSignature and text are separate. No output file produced. "));
1479: else /* signature precedes plaintext in file... */
1480: { /* produce a plaintext output file from signature file */
1481: if (file_exists(outfile))
1482: { fprintf(pgpout,PSTR("\n\007Output file '%s' already exists. Overwrite (y/N)? "),outfile);
1483: if (!getyesno('n')) /* user said don't do it. */
1484: goto err1; /* abort operation */
1485: }
1486: /* open file g for write, in binary or text mode...*/
1487: #ifdef CANONICAL_TEXT
1488: if ((g = fopen(outfile,"wb")) == NULL)
1489: #else
1490: if ((g = fopen(outfile,(lit_mode==MODE_BINARY)?"wb":"w")) == NULL)
1491: #endif
1492: { fprintf(pgpout,PSTR("\n\007Can't create plaintext file '%s'\n"),outfile);
1493: goto err1;
1494: }
1495: CONVERSION = (lit_mode == MODE_TEXT) ? EXT_CONV : NO_CONV;
1496: #ifdef CANONICAL_TEXT
1497: copyfile(f,g,-1L); /* copy rest of file from file f to g */
1498: #else
1499: if (lit_mode == MODE_BINARY)
1500: copyfile( f, g, -1L );
1501: else
1502: copyfile_from_canon( f, g, -1L );
1503: #endif
1504: CONVERSION = NO_CONV;
1505:
1506: fclose(g);
1507:
1508: if (strip_signature)
1509: { /* Copy signature to a .sig file */
1510: strcpy (sigfile, outfile);
1511: force_extension(sigfile,SIG_EXTENSION);
1512: if (file_exists(sigfile))
1513: { fprintf(pgpout,PSTR("\n\007Signature file '%s' already exists. Overwrite (y/N)? "),sigfile);
1514: if (!getyesno('n'))
1515: goto err1;
1516: }
1517: if ((g = fopen(sigfile,"wb")) == NULL)
1518: { fprintf(pgpout,PSTR("\n\007Can't create signature file '%s'\n"),sigfile);
1519: goto err1;
1520: }
1521: fseek (f,0L,SEEK_SET);
1522: copyfile (f,g,(unsigned long)(cert_length+ctb_llength(ctb)+1));
1523: fclose(g);
1524: fprintf(pgpout,PSTR("\nWriting signature certificate to '%s'\n"),sigfile);
1525: }
1526: }
1527:
1528: burn(inbuf); /* burn sensitive data on stack */
1529: burn(outbuf); /* burn sensitive data on stack */
1530: fclose(f);
1531: if (separate_signature)
1532: { *outfile = '\0';
1533: return(0); /* normal return, no nested info */
1534: }
1535: if (is_ctb(ctb2) && (is_ctb_type(ctb2,CTB_LITERAL_TYPE)))
1536: /* we already stripped away the CTB_LITERAL */
1537: return(0); /* normal return, no nested info */
1538: /* Otherwise, it's best to assume a nested CTB */
1539: return(1); /* nested information return */
1540:
1541: badcert: /* Bad packet. Complain. */
1542: fprintf(pgpout,PSTR("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
1543: fprintf(pgpout,PSTR("File \"%s\" does not have a properly-formed signature.\n"),infile);
1544: /* Now just drop through to error exit... */
1545:
1546: err1:
1547: burn(inbuf); /* burn sensitive data on stack */
1548: burn(outbuf); /* burn sensitive data on stack */
1549: fclose(f);
1550: return(-1); /* error return */
1551:
1552: } /* check_signaturefile */
1553:
1554:
1555: int check_key_sig(FILE *fkey, long fpkey, int keypktlen, char *keyuserid,
1556: FILE *fsig, long fpsig, char *keyfile, char *siguserid, byte *xtimestamp,
1557: byte *sigclass)
1558: { /* Check signature of key in file fkey at position fpkey, using signature
1559: in file fsig and position fpsig. keyfile tells the file to use to
1560: look for the public key in to check the sig. Return 0 if OK, -1 if
1561: we can't check the signature, -2 if bad or other problem.
1562: */
1563: byte ctb; /* Cipher Type Bytes */
1564: long fp; /* unused, just to satisfy getpublickey */
1565: int pktlen; /* unused, just to satisfy getpublickey */
1566: word16 cert_length;
1567: int i, count;
1568: byte certbuf[MAX_SIGCERT_LENGTH];
1569: byteptr certificate; /* for parsing certificate buffer */
1570: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1571: byte inbuf[MAX_BYTE_PRECISION];
1572: byte outbuf[MAX_BYTE_PRECISION];
1573: byte keyID[KEYFRAGSIZE];
1574: MD5_CTX MD;
1575: byte mdlensave;
1576: byte *mdextras;
1577: word32 tstamp;
1578: byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
1579: byte version;
1580: byte mdlen; /* length of material to be added to MD calculation */
1581: byte class;
1582: byte algorithm;
1583: byte mdlow2[2];
1584:
1585: fill0( keyID, KEYFRAGSIZE );
1586:
1587: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
1588:
1589: /******************** Read header CTB and length field ******************/
1590:
1591: fseek(fsig, fpsig, SEEK_SET);
1592: fread(&ctb,1,1,fsig); /* read certificate CTB byte */
1593: certificate = certbuf;
1594: *certificate++ = ctb; /* copy ctb into certificate */
1595:
1596: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_SKE_TYPE))
1597: goto badcert2; /* complain and return bad status */
1598:
1599: cert_length = getpastlength(ctb, fsig); /* read certificate length */
1600: certificate += ctb_llength(ctb); /* either 1, 2, 4, or 8 */
1601: if (cert_length > MAX_SIGCERT_LENGTH-3) /* Huge packet length */
1602: goto badcert2; /* complain and return bad status */
1603:
1604: /* read whole certificate: */
1605: if (fread((byteptr) certificate, 1, cert_length, fsig) < cert_length)
1606: /* bad packet length field */
1607: goto badcert2; /* complain and return bad status */
1608:
1609: version = *certificate++;
1610: if (version_error(version, VERSION_BYTE))
1611: goto err2;
1612:
1613: mdlensave = mdlen = *certificate++; /* length of material to be added to MD */
1614: mdextras = certificate; /* pointer to extra material for MD calculation */
1615:
1616: *sigclass = class = *certificate++;
1617: if (class != K0_SIGNATURE_BYTE && class != K1_SIGNATURE_BYTE &&
1618: class != K2_SIGNATURE_BYTE && class != K3_SIGNATURE_BYTE &&
1619: class != KC_SIGNATURE_BYTE)
1620: { (void) version_error(class, K0_SIGNATURE_BYTE);
1621: goto err2;
1622: }
1623: mdlen--;
1624:
1625: if (mdlen>0) /* if more MD material is included... */
1626: { for (i=0; i<SIZEOF_TIMESTAMP; ++i)
1627: { timestamp[i] = *certificate++;
1628: mdlen--;
1629: }
1630: }
1631:
1632: if (mdlen>0) /* if more MD material is included... */
1633: { certificate+=2; /* skip past unused validity period word */
1634: mdlen-=2;
1635: }
1636:
1637: if (mdlen>0) /* if more MD material is included... */
1638: certificate+=mdlen; /* skip over the rest */
1639:
1640: for (i=0; i<KEYFRAGSIZE; i++)
1641: keyID[i] = *certificate++; /* copy rest of key fragment */
1642:
1643: algorithm = *certificate++;
1644: if (version_error(algorithm, RSA_ALGORITHM_BYTE))
1645: goto err2;
1646:
1647: algorithm = *certificate++;
1648: if (version_error(algorithm, MD5_ALGORITHM_BYTE))
1649: goto err2;
1650:
1651: /* Grab 1st 2 bytes of message digest */
1652: mdlow2[0] = *certificate++;
1653: mdlow2[1] = *certificate++;
1654:
1655: /* We used to set precision here based on certificate value,
1656: * but it was sometimes less than that based on n. Read public
1657: * key here to set precision, before we go on.
1658: */
1659: /* This sets precision, too, based on n. */
1660: if (getpublickey(TRUE, FALSE, keyfile, &fp, &pktlen,
1661: keyID, xtimestamp, (unsigned char *)siguserid, n, e) < 0)
1662: goto err1;
1663:
1664: mpi2reg((unitptr)inbuf,certificate); /* get signed message digest */
1665: certificate += countbytes((unitptr)inbuf)+2;
1666:
1667: if ((certificate-certbuf) != cert_length+3)
1668: /* Bad length in signature certificate. Off by
1669: ((certificate-certbuf) - (cert_length+3)) */
1670: goto badcert2; /* complain and return bad status */
1671:
1672: /* Recover message digest via public key */
1673: mp_modexp((unitptr)outbuf,(unitptr)inbuf,e,n);
1674:
1675: /* Unblock message digest, and convert to external byte order: */
1676: if ((count = postunblock(outbuf, (unitptr)outbuf, n)) < 0)
1677: goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */
1678:
1679: /* outbuf should contain message digest packet */
1680: /*==================================================================*/
1681: /* Look at nested stuff within RSA block... */
1682:
1683: #ifdef XLOWFIRST /* assumes LSB-first */
1684: if (outbuf[count-1] != MD5_ALGORITHM_BYTE)
1685: goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */
1686: if (outbuf[0] != mdlow2[0] || outbuf[1] != mdlow2[1])
1687: goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */
1688: #else
1689: if (outbuf[0] != MD5_ALGORITHM_BYTE)
1690: goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */
1691: if (outbuf[1] != mdlow2[0] || outbuf[2] != mdlow2[1])
1692: goto err2; /* Bad RSA decrypt. Corruption, or wrong key. */
1693: #endif
1694:
1695: /* Position file to where that plaintext begins... */
1696: fseek(fkey,fpkey,SEEK_SET);
1697:
1698: /* compute a message digest from key packet */
1699: MDfile0_len(&MD,fkey,keypktlen);
1700: /* Add data from user id */
1701: if (class != KC_SIGNATURE_BYTE)
1702: MD5Update(&MD, (unsigned char *) keyuserid+1, (int)(unsigned char)keyuserid[0]);
1703: /* Add time and class data */
1704: MD_addbuffer (&MD, mdextras, mdlensave, TRUE); /* Finish message digest */
1705:
1706: /* now compare computed MD with claimed MD */
1707: #ifdef XLOWFIRST /* assumes LSB-first */
1708: if (!equal_buffers((byte *)(MD.digest), outbuf, 16))
1709: goto err2;
1710: #else
1711: if (!equal_buffers((byte *)(MD.digest), outbuf+1, 16))
1712: goto err2;
1713: #endif
1714:
1715: convert_byteorder(timestamp,4); /* convert timestamp from external form */
1716: memcpy (xtimestamp, timestamp, 4); /* Return signature timestamp */
1717:
1718: burn(inbuf); /* burn sensitive data on stack */
1719: burn(outbuf); /* burn sensitive data on stack */
1720: return(0); /* normal return */
1721:
1722: err1:
1723: burn(inbuf); /* burn sensitive data on stack */
1724: burn(outbuf); /* burn sensitive data on stack */
1725: return(-1); /* error return */
1726:
1727: badcert2: /* Bad packet. Complain. */
1728: fprintf(pgpout,PSTR("\n\007Error: Badly-formed or corrupted signature certificate.\n"));
1729: /* Now just drop through to error exit... */
1730:
1731: err2:
1732: burn(inbuf); /* burn sensitive data on stack */
1733: burn(outbuf); /* burn sensitive data on stack */
1734: return(-2); /* error return */
1735:
1736: } /* check_key_sig */
1737:
1738:
1739:
1740: /*======================================================================*/
1741: int squish_and_idea_file(byte *ideakey, FILE *f, FILE *g,
1742: boolean attempt_compression)
1743: {
1744: FILE *t;
1745: byte ctb;
1746: word32 fpos, fpos0;
1747: extern char plainfile[];
1748:
1749: /*
1750: ** If the caller specified that we should attempt compression, we
1751: ** create a temporary file 't' and compress our input file 'f' into
1752: ** 't'. Ideally, we would see if we get a good compression ratio
1753: ** and if we did, then use file 't' for input and write a
1754: ** CTB_COMPRESSED prefix. But in this implementation we just always
1755: ** use the compressed output, even if it didn't compress well.
1756: */
1757:
1758: rewind( f );
1759:
1760: if (!attempt_compression)
1761: t = f; /* skip compression attempt */
1762: else /* attempt compression-- get a tempfile */
1763: if ((t = tmpfile()) == NULL) /* error: no tempfile */
1764: t = f; /* skip compression attempt */
1765: else /* attempt compression */
1766: {
1767: extern int zipup( FILE *, FILE * );
1768:
1769: if (verbose) fprintf(pgpout, PSTR("\nCompressing plaintext [%s]..."),
1770: plainfile );
1771:
1772: /* We don't put a length field on CTB_COMPRESSED yet */
1773: ctb = CTB_COMPRESSED; /* use compression prefix CTB */
1774: fwrite( &ctb, 1, 1, t ); /* write CTB_COMPRESSED */
1775: /* No CTB packet length specified means indefinite length. */
1776: ctb = ZIP2_ALGORITHM_BYTE; /* use ZIP compression */
1777: fwrite( &ctb, 1, 1, t ); /* write ZIP algorithm byte */
1778:
1779: /* Compression the file */
1780: zipup( f, t);
1781: if (verbose) fprintf(pgpout, PSTR("compressed. ") );
1782: else fputc('.',pgpout); /* show progress */
1783: rewind( t );
1784: }
1785:
1786: /* Now write out file thru IDEA cipher... */
1787:
1788: /* Write CTB prefix, leave 4 bytes for later length */
1789: fpos0 = ftell(g);
1790: write_ctb_len (g, CTB_CKE_TYPE, 0L, TRUE);
1791: fpos = ftell(g) - fpos0;
1792:
1793: idea_file( ideakey, ENCRYPT_IT, t, g, fsize(t) );
1794:
1795: /* Now re-write CTB prefix, this time with length */
1796: fseek(g,fpos0,SEEK_SET);
1797: write_ctb_len (g, CTB_CKE_TYPE, fsize(g)-fpos, TRUE);
1798:
1799: if (t != f)
1800: { wipeout( t );
1801: fclose( t ); /* close and remove the temporary file */
1802: }
1803:
1804: return(0); /* normal return */
1805:
1806: } /* squish_and_idea_file */
1807:
1808:
1809: int squish_file(char *infile, char *outfile)
1810: {
1811: FILE *f, *g;
1812: byte ctb;
1813: extern int zip( FILE *, FILE * );
1814:
1815: if (verbose)
1816: fprintf(pgpout,PSTR("\nInput file: %s, compressed file: %s\n"),
1817: infile,outfile);
1818:
1819: /* open file f for read, in binary (not text) mode...*/
1820: #ifdef VMS
1821: if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
1822: #else
1823: if ((f = fopen( infile, "rb" )) == NULL)
1824: #endif
1825: {
1826: fprintf(pgpout,PSTR("\n\007Can't open file '%s'\n"), infile );
1827: return(-1);
1828: }
1829:
1830: /* open file g for write, in binary (not text) mode...*/
1831: if ((g = fopen( outfile, "wb" )) == NULL)
1832: {
1833: fprintf(pgpout,PSTR("\n\007Can't create compressed file '%s'\n"), outfile );
1834: fclose(f);
1835: return(-1);
1836: }
1837:
1838:
1839: if (verbose) fprintf(pgpout, PSTR("Compressing file..."));
1840:
1841: /* We don't put a length field on CTB_COMPRESSED yet */
1842: ctb = CTB_COMPRESSED; /* use compression prefix CTB */
1843: fwrite( &ctb, 1, 1, g ); /* write CTB_COMPRESSED */
1844: /* No CTB packet length specified means indefinite length. */
1845: ctb = ZIP2_ALGORITHM_BYTE; /* use ZIP compression */
1846: fwrite( &ctb, 1, 1, g ); /* write ZIP algorithm byte */
1847:
1848: /* Compress/store the file */
1849: zipup( f, g );
1850: if (verbose) fprintf(pgpout, PSTR("compressed. ") );
1851:
1852: fclose (f);
1853: fclose (g);
1854: return(0);
1855: } /* squish_file */
1856:
1857: #define NOECHO1 1 /* Disable password from being displayed on screen */
1858: #define NOECHO2 2 /* Disable password from being displayed on screen */
1859:
1860: int idea_encryptfile(char *infile, char *outfile,
1861: boolean attempt_compression)
1862: {
1863: FILE *f; /* input file */
1864: FILE *g; /* output file */
1865: byte ideakey[16];
1866: byte passphrase[256];
1867:
1868: if (verbose)
1869: fprintf(pgpout,PSTR("\nPlaintext file: %s, ciphertext file: %s\n"),
1870: infile,outfile);
1871:
1872: /* open file f for read, in binary (not text) mode...*/
1873: #ifdef VMS
1874: if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
1875: #else
1876: if ((f = fopen( infile, "rb" )) == NULL)
1877: #endif
1878: {
1879: fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"), infile );
1880: return(-1);
1881: }
1882:
1883: /* open file g for write, in binary (not text) mode...*/
1884: if ((g = fopen( outfile, "wb" )) == NULL)
1885: {
1886: fprintf(pgpout,PSTR("\n\007Can't create ciphertext file '%s'\n"), outfile );
1887: fclose(f);
1888: return(-1);
1889: }
1890:
1891: /* Get IDEA password, hashed to a key */
1892: fprintf(pgpout,PSTR("\nYou need a pass phrase to encrypt the file. "));
1893: if (getideakey((char *)passphrase,(char *)ideakey,NOECHO2) <= 0)
1894: { fclose(f);
1895: fclose(g);
1896: return(-1);
1897: }
1898:
1899: fprintf(pgpout,PSTR("Just a moment...")); /* this may take a while */
1900: fflush(pgpout);
1901:
1902: /* Now compress the plaintext and encrypt it with IDEA... */
1903: squish_and_idea_file( ideakey, f, g, attempt_compression );
1904:
1905: burn(ideakey); /* burn sensitive data on stack */
1906: burn(passphrase);
1907:
1908: fclose(g);
1909: fclose(f);
1910:
1911: return(0);
1912:
1913: } /* idea_encryptfile */
1914:
1915:
1916: /*======================================================================*/
1917:
1918:
1919: int encryptfile(char *mcguffin, char *infile, char *outfile,
1920: boolean attempt_compression)
1921: {
1922: byte randompad[MAX_BYTE_PRECISION]; /* buffer of random pad bytes */
1923: int i,blocksize,ckp_length;
1924: FILE *f;
1925: FILE *g;
1926: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
1927: byte inbuf[MAX_BYTE_PRECISION];
1928: byte outbuf[MAX_BYTE_PRECISION];
1929: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
1930: byte userid[256];
1931: byte ideakey[16]; /* must be big enough for make_random_ideakey */
1932: char keyfile[MAX_PATH]; /* for getpublickey */
1933: long fp; /* unused, just to satisfy getpublickey */
1934: int pktlen; /* unused, just to satisfy getpublickey */
1935: word32 chksum;
1936: byte ver, alg;
1937:
1938:
1939: buildfilename(keyfile,PUBLIC_KEYRING_FILENAME); /* use default pathname */
1940:
1941: if (verbose)
1942: fprintf(pgpout,PSTR("\nPlaintext file: %s, ciphertext file: %s\n"),
1943: infile,outfile);
1944:
1945: userid[0] = '\0';
1946: if (mcguffin)
1947: strcpy((char *)userid,mcguffin);/* Who we are looking for (C string) */
1948:
1949: /* Get and validate public key from a key file: */
1950: if (getpublickey(FALSE, TRUE, keyfile, &fp, &pktlen, NULL, timestamp, userid, n, e) < 0)
1951: { return(-1);
1952: }
1953:
1954: if (warn_signatures(keyfile, fp, pktlen, (char *)userid, FALSE) < 0)
1955: return(-1);
1956:
1957: /* set_precision has been properly called by getpublickey */
1958:
1959: /* Note that RSA key must be at least big enough to encipher a
1960: complete conventional key packet in a single RSA block.
1961: */
1962:
1963: blocksize = countbytes(n)-1; /* size of a plaintext block */
1964: if (blocksize < 31)
1965: { fprintf(pgpout,"\n\007Error: RSA key length must be at least 256 bits.\n");
1966: return(-1);
1967: }
1968:
1969: /* open file f for read, in binary (not text) mode...*/
1970: #ifdef VMS
1971: if ((f = fopen( infile, "rb", "ctx=stm" )) == NULL)
1972: #else
1973: if ((f = fopen( infile, "rb" )) == NULL)
1974: #endif
1975: {
1976: fprintf(pgpout,PSTR("\n\007Can't open plaintext file '%s'\n"), infile );
1977: return(-1);
1978: }
1979:
1980: /* open file g for write, in binary (not text) mode...*/
1981: if ((g = fopen( outfile, "wb" )) == NULL)
1982: {
1983: fprintf(pgpout,PSTR("\n\007Can't create ciphertext file '%s'\n"), outfile );
1984: fclose(f);
1985: return(-1);
1986: }
1987:
1988: /* Now we have to time some user keystrokes to get some random
1989: bytes for generating a random IDEA cipher key.
1990: We would have to solicit fewer keystrokes for random IDEA
1991: key generation if we had already accumulated some keystrokes
1992: incidental to some other purpose, such as asking for a password
1993: to decode an RSA secret key so that a signature could be applied
1994: to the message before encrypting it.
1995: */
1996:
1997: ckp_length = make_random_ideakey(ideakey);
1998: /* Returns an 16 byte random IDEA key */
1999:
2000: #ifdef XLOWFIRST /* Assumes LSB-first order */
2001: for (i=0; i<ckp_length; ++i)
2002: outbuf[i] = ideakey[i];
2003: /* Compute and append checksum to the key */
2004: chksum = checksum (outbuf, ckp_length);
2005: put_word16((word16) chksum, outbuf+ckp_length);
2006: ckp_length += 2;
2007: /* Append identifier byte to key */
2008: outbuf[ckp_length++] = IDEA_ALGORITHM_BYTE;
2009: #else /* Assumes MSB-first order */
2010: /* Prepend identifier byte to key */
2011: outbuf[0] = IDEA_ALGORITHM_BYTE;
2012: for (i=0; i<ckp_length; ++i)
2013: outbuf[i+1] = ideakey[i];
2014: /* Compute and append checksum to the key */
2015: chksum = checksum (outbuf+1, ckp_length);
2016: ckp_length++;
2017: put_word16((word16) chksum, outbuf+ckp_length);
2018: ckp_length += 2;
2019: #endif
2020:
2021: /*
2022: ** Messages encrypted with a public key should use random padding,
2023: ** while messages "signed" with a secret key should use constant
2024: ** padding.
2025: */
2026:
2027: for (i = 0; i < (blocksize - ckp_length); i++)
2028: while (!(randompad[i] = randombyte()))
2029: ; /* Allow only nonzero values */
2030:
2031: /*
2032: ** Note that RSA key must be at least big enough to encipher a
2033: ** complete conventional key packet in a single RSA block.
2034: */
2035:
2036: /* ckp_length is conventional key packet length. */
2037:
2038: preblock( (unitptr)inbuf, outbuf, ckp_length, n, randompad );
2039: mp_modexp( (unitptr)outbuf, (unitptr)inbuf, e, n ); /* RSA encrypt */
2040:
2041: /* write out header record to outfile ... */
2042:
2043: /* PKE is Public Key Encryption */
2044: write_ctb_len (g, CTB_PKE_TYPE,
2045: 1+KEYFRAGSIZE+1+2+countbytes((unitptr)outbuf), FALSE);
2046:
2047: /* Write version byte */
2048: ver = VERSION_BYTE;
2049: fwrite (&ver, 1, 1, g);
2050:
2051: writekeyID( n, g ); /* write msg prefix fragment of modulus n */
2052:
2053: /* Write algorithm byte */
2054: alg = RSA_ALGORITHM_BYTE;
2055: fwrite (&alg, 1, 1, g);
2056:
2057: /* convert RSA ciphertext block via reg2mpi and write to file */
2058:
2059: write_mpi( (unitptr)outbuf, g, FALSE );
2060:
2061: burn(inbuf); /* burn sensitive data on stack */
2062: burn(outbuf); /* burn sensitive data on stack */
2063:
2064: /** Finished with RSA block containing IDEA key. */
2065:
2066: /* Now compress the plaintext and encrypt it with IDEA... */
2067: squish_and_idea_file( ideakey, f, g, attempt_compression );
2068:
2069: burn(ideakey); /* burn sensitive data on stack */
2070:
2071: fclose(g);
2072: fclose(f);
2073:
2074: return(0);
2075: } /* encryptfile */
2076:
2077:
2078: /*======================================================================*/
2079: int make_literal(char *infile, char *outfile, char lit_mode, char *literalfile)
2080: { /* Prepend a CTB_LITERAL prefix to a file. Convert to canonical form if
2081: lit_mode is MODE_TEXT.
2082: */
2083: char lfile[MAX_PATH];
2084: FILE *f;
2085: FILE *g;
2086: word32 flen, fpos;
2087: word32 dummystamp = 0;
2088:
2089: if (verbose)
2090: fprintf(pgpout,PSTR("\nInput plaintext file: %s, Output plaintext file: %s\n"),
2091: infile,outfile);
2092:
2093: /* open file f for read, in binary or text mode...*/
2094: #ifdef CANONICAL_TEXT
2095: if ((f = fopen(infile,"rb")) == NULL) /* Always binary */
2096: #else
2097: if ((f = fopen(infile,(lit_mode==MODE_BINARY)?"rb":"r")) == NULL)
2098: #endif
2099: { fprintf(pgpout,PSTR("\n\007Can't open input plaintext file '%s'\n"),infile);
2100: return(-1);
2101: }
2102: flen = fsize(f);
2103:
2104: /* open file g for write, in binary (not text) mode... */
2105: if ((g = fopen( outfile,"wb" )) == NULL)
2106: { fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
2107: goto err1;
2108: }
2109:
2110: if (lit_mode == MODE_BINARY)
2111: write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
2112: else
2113: #ifdef CANONICAL_TEXT
2114: write_ctb_len (g, CTB_LITERAL_TYPE, flen, FALSE);
2115: #else
2116: /* Will put in size field later for text mode */
2117: write_ctb_len (g, CTB_LITERAL_TYPE, 0L, TRUE);
2118: #endif
2119: fwrite ( &lit_mode, 1, 1, g ); /* write lit_mode */
2120: /* write literalfile name */
2121: if (literalfile == NULL)
2122: { /* Put in a zero byte to indicate no filename */
2123: fputc ('\0', g);
2124: }
2125: else
2126: { strcpy( lfile, literalfile );
2127: file_to_canon( lfile );
2128: CToPascal( lfile );
2129: fwrite ( lfile, 1, lfile[0]+1, g);
2130: }
2131: /* Dummy file creation timestamp */
2132: fwrite ( &dummystamp, 1, sizeof(dummystamp), g);
2133:
2134: fpos = ftell(g);
2135:
2136: CONVERSION = (lit_mode == MODE_TEXT) ? INT_CONV : NO_CONV;
2137: #ifdef CANONICAL_TEXT
2138: copyfile( f, g, -1L ); /* Simple copy on canonical systems */
2139: CONVERSION = NO_CONV;
2140: #else
2141: if (lit_mode == MODE_BINARY)
2142: copyfile( f, g, -1L );
2143: else
2144: { copyfile_to_canon( f, g, -1L );
2145: CONVERSION = NO_CONV;
2146: /* Re-write CTB with correct length info */
2147: rewind (g);
2148: write_ctb_len (g, CTB_LITERAL_TYPE, fsize(f)-fpos, TRUE);
2149: }
2150: #endif
2151:
2152: fclose(g);
2153: fclose(f);
2154: return(0); /* normal return */
2155:
2156: err1:
2157: fclose(f);
2158: return(-1); /* error return */
2159:
2160: } /* make_literal */
2161:
2162:
2163: /*======================================================================*/
2164: int strip_literal(char *infile, char *outfile, boolean explicit_outfile_flag,
2165: char *lit_mode)
2166: { /* Strip off literal prefix from infile, copying to outfile.
2167: Get lit_mode and literalfile info from
2168: the prefix. Replace outfile with literalfile unless
2169: literalfile is illegal or explicit_outfile_flag is TRUE.
2170: If lit_mode is MODE_TEXT, convert from canonical form as we
2171: copy the data.
2172: */
2173: byte ctb; /* Cipher Type Byte */
2174: FILE *f;
2175: FILE *g;
2176: word32 LITlength = 0;
2177: unsigned char litfile[MAX_PATH];
2178: word32 dummystamp;
2179:
2180: *lit_mode = MODE_BINARY;
2181: if (verbose)
2182: fprintf(pgpout,PSTR("\nInput plaintext file: %s, Output plaintext file: %s\n"),
2183: infile,outfile);
2184:
2185: /* open file f for read, in binary (not text) mode...*/
2186: #ifdef VMS
2187: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
2188: #else
2189: if ((f = fopen(infile,"rb")) == NULL)
2190: #endif
2191: { fprintf(pgpout,PSTR("\n\007Can't open input plaintext file '%s'\n"),infile);
2192: return(-1);
2193: }
2194:
2195: fread(&ctb,1,1,f); /* read Cipher Type Byte */
2196:
2197: if (!is_ctb(ctb) || !(is_ctb_type(ctb,CTB_LITERAL_TYPE)))
2198: { /* debug message in English only -- something got corrupted */
2199: fprintf(pgpout,"\n\007'%s' is not a literal plaintext file.\n",infile);
2200: fclose(f);
2201: return(-1);
2202: }
2203:
2204: LITlength = getpastlength(ctb, f); /* read packet length */
2205:
2206: /* Read literal data */
2207: *lit_mode = '\0';
2208: fread (lit_mode,1,1,f);
2209: if ((*lit_mode != MODE_BINARY) && (*lit_mode != MODE_TEXT))
2210: { (void) version_error(*lit_mode, MODE_TEXT);
2211: fclose(f);
2212: return(-1);
2213: }
2214: if (verbose)
2215: fprintf(pgpout, PSTR("File type: '%c'\n"), lit_mode);
2216: /* Read literal file name, use it if possible */
2217: litfile[0] = 0;
2218: fread (litfile,1,1,f);
2219: if ((int)litfile[0] > MAX_PATH)
2220: litfile[0] = 0; /* If too long for us, ignore it */
2221: if (litfile[0] > 0)
2222: fread (litfile+1,1,litfile[0],f);
2223: /* Use litfile if it's writeable and he didn't say an outfile */
2224: if (litfile[0] > 0)
2225: { PascalToC( (char *)litfile );
2226: if (verbose)
2227: fprintf(pgpout, PSTR("Original plaintext file name was: '%s'\n"), litfile);
2228: if (!strcmp((char *) litfile, CONSOLE_FILENAME) || !explicit_outfile_flag)
2229: { file_from_canon( (char *)litfile );
2230: if (file_ok_write( (char *)litfile ))
2231: strcpy ( outfile, (char *)litfile );
2232: }
2233: }
2234: /* Discard file creation timestamp for now */
2235: fread (&dummystamp, 1, sizeof(dummystamp), f);
2236:
2237: if (file_exists( outfile ))
2238: { fprintf(pgpout, PSTR("\n\007Output file '%s' already exists. Overwrite (y/N)? "), outfile );
2239: if (! getyesno( 'n' ))
2240: goto err1; /* user said don't do it - abort operation */
2241: }
2242:
2243: /* open file g for write, in binary or text mode... */
2244: #ifdef CANONICAL_TEXT
2245: if ((g = fopen( outfile, "wb" )) == NULL) /* Always binary */
2246: #else
2247: if ((g = fopen( outfile, (*lit_mode==MODE_BINARY)?"wb":"w" )) == NULL)
2248: #endif
2249: { fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
2250: goto err1;
2251: }
2252:
2253: /* copy rest of literal plaintext file */
2254: CONVERSION = (*lit_mode == MODE_TEXT) ? EXT_CONV : NO_CONV;
2255: #ifdef CANONICAL_TEXT
2256: copyfile( f, g, LITlength ); /* Simple copy on canonical systems */
2257: #else
2258: if (*lit_mode == MODE_BINARY)
2259: copyfile( f, g, LITlength );
2260: else
2261: copyfile_from_canon( f, g, LITlength );
2262: #endif
2263: CONVERSION = NO_CONV;
2264:
2265: fclose(g);
2266: fclose(f);
2267: return(0); /* normal return */
2268:
2269: err1:
2270: fclose(f);
2271: return(-1); /* error return */
2272:
2273: } /* strip_literal */
2274:
2275:
2276: /*======================================================================*/
2277:
2278:
2279: int decryptfile(char *infile, char *outfile)
2280: {
2281: byte ctb; /* Cipher Type Byte */
2282: byte ctbCKE; /* Cipher Type Byte */
2283: FILE *f;
2284: FILE *g;
2285: int count, status;
2286: unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION];
2287: unit p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
2288: byte inbuf[MAX_BYTE_PRECISION];
2289: byte outbuf[MAX_BYTE_PRECISION];
2290: byte keyID[KEYFRAGSIZE];
2291: word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */
2292: byte userid[256];
2293: word32 flen;
2294: byte ver, alg;
2295: word16 chksum;
2296:
2297: set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */
2298:
2299: if (verbose)
2300: fprintf(pgpout,PSTR("\nCiphertext file: %s, plaintext file: %s\n"),
2301: infile,outfile);
2302:
2303: /* open file f for read, in binary (not text) mode...*/
2304: #ifdef VMS
2305: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
2306: #else
2307: if ((f = fopen(infile,"rb")) == NULL)
2308: #endif
2309: { fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
2310: return(-1);
2311: }
2312:
2313: fread(&ctb,1,1,f); /* read Cipher Type Byte */
2314: if (!is_ctb(ctb))
2315: { fprintf(pgpout,PSTR("\n\007'%s' is not a cipher file.\n"),infile);
2316: fclose(f);
2317: return(-1);
2318: }
2319:
2320: /* PKE is Public Key Encryption */
2321: if (!is_ctb_type(ctb,CTB_PKE_TYPE))
2322: { fprintf(pgpout,PSTR("\n\007'%s' is not enciphered with a public key.\n"),infile);
2323: fclose(f);
2324: return(-1);
2325: }
2326:
2327: getpastlength(ctb, f); /* read packet length */
2328:
2329: /* Read and check version */
2330: fread (&ver, 1, 1, f);
2331: if (version_error(ver, VERSION_BYTE))
2332: { fclose (f);
2333: return (-1);
2334: }
2335:
2336: fread(keyID,1,KEYFRAGSIZE,f); /* read key ID */
2337: /* Use keyID prefix to look up key. */
2338:
2339: /* Read and check algorithm */
2340: fread (&alg, 1, 1, f);
2341: if (version_error(alg, RSA_ALGORITHM_BYTE))
2342: { fclose (f);
2343: return (-1);
2344: }
2345:
2346: /* Get and validate secret key from a key file: */
2347: if (getsecretkey(FALSE, TRUE, NULL, keyID, timestamp, NULL, NULL,userid,
2348: n, e, d, p, q, u) < 0)
2349: { fclose(f);
2350: return(-1);
2351: }
2352:
2353: /* Note that RSA key must be at least big enough to encipher a
2354: complete conventional key packet in a single RSA block. */
2355:
2356: /*==================================================================*/
2357: /* read ciphertext block, converting to internal format: */
2358: read_mpi((unitptr)inbuf, f, FALSE, FALSE);
2359:
2360: fprintf(pgpout,PSTR("Just a moment...")); /* RSA will take a while. */
2361: fflush(pgpout);
2362:
2363: rsa_decrypt((unitptr)outbuf, (unitptr)inbuf, d, p, q, u);
2364:
2365: fputc('.',pgpout); /* Signal RSA completion. */
2366:
2367: if ((count = postunblock(outbuf, (unitptr)outbuf, n)) < 0)
2368: { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
2369: This may be caused either by corrupted data or by using the wrong RSA key.\n"));
2370: fclose(f);
2371: return(-1);
2372: }
2373:
2374: /* Verify that top of buffer has correct algorithm byte */
2375: --count; /* one less byte to drop algorithm byte */
2376: #ifdef XLOWFIRST /* Assumes LSB-first order */
2377: if (version_error(outbuf[count], IDEA_ALGORITHM_BYTE))
2378: #else /* Assumes MSB-first order */
2379: if (version_error(outbuf[0], IDEA_ALGORITHM_BYTE))
2380: #endif
2381: { fclose(f);
2382: return(-1);
2383: }
2384:
2385: /* Verify checksum */
2386: count -= 2; /* back up before checksum */
2387: #ifdef XLOWFIRST /* Assumes LSB-first order */
2388: chksum = fetch_word16(outbuf+count);
2389: if (chksum != checksum(outbuf, count))
2390: #else /* Assumes MSB-first order */
2391: chksum = fetch_word16(outbuf+1+count);
2392: if (chksum != checksum(outbuf+1, count))
2393: #endif
2394: { fprintf(pgpout,PSTR("\n\007Error: RSA-decrypted block is corrupted.\n\
2395: This may be caused either by corrupted data or by using the wrong RSA key.\n"));
2396: fclose(f);
2397: return(-1);
2398: }
2399:
2400: /* outbuf should contain random IDEA key packet */
2401: /*==================================================================*/
2402:
2403: if (file_exists( outfile ))
2404: { fprintf(pgpout, PSTR("\n\007Output file '%s' already exists. Overwrite (y/N)? "), outfile );
2405: if (! getyesno( 'n' ))
2406: goto err1; /* user said don't do it - abort operation */
2407: }
2408:
2409: /* open file g for write, in binary (not text) mode... */
2410: if ((g = fopen( outfile, "wb" )) == NULL)
2411: { fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
2412: goto err1;
2413: }
2414:
2415: fread(&ctbCKE,1,1,f); /* read Cipher Type Byte, should be CTB_CKE */
2416: if (!is_ctb(ctbCKE) || !is_ctb_type(ctbCKE,CTB_CKE_TYPE))
2417: { /* Should never get here. */
2418: fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
2419: goto err1; /* Abandon ship! */
2420: }
2421:
2422: flen = getpastlength(ctbCKE, f); /* read packet length */
2423:
2424: /* Decrypt ciphertext file */
2425: #ifdef XLOWFIRST /* Assumes LSB-first order */
2426: status = idea_file( outbuf, DECRYPT_IT, f, g, flen );
2427: #else /* Assumes MSB-first order */
2428: status = idea_file( outbuf+1, DECRYPT_IT, f, g, flen );
2429: #endif
2430: if (status < 0)
2431: { fprintf(pgpout,PSTR("\n\007Error: Decrypted plaintext is corrupted.\n"));
2432: }
2433: fputc('.',pgpout); /* show progress */
2434:
2435: fclose(g);
2436: fclose(f);
2437: burn(inbuf); /* burn sensitive data on stack */
2438: burn(outbuf); /* burn sensitive data on stack */
2439: mp_burn(d); /* burn sensitive data on stack */
2440: mp_burn(p); /* burn sensitive data on stack */
2441: mp_burn(q); /* burn sensitive data on stack */
2442: mp_burn(u); /* burn sensitive data on stack */
2443: if (status < 0) /* if idea_file failed, then error return */
2444: return(status);
2445: return(1); /* always indicate output file has nested stuff in it. */
2446:
2447: err1:
2448: fclose(f);
2449: burn(inbuf); /* burn sensitive data on stack */
2450: burn(outbuf); /* burn sensitive data on stack */
2451: mp_burn(d); /* burn sensitive data on stack */
2452: mp_burn(p); /* burn sensitive data on stack */
2453: mp_burn(q); /* burn sensitive data on stack */
2454: mp_burn(u); /* burn sensitive data on stack */
2455: return(-1); /* error return */
2456:
2457: } /* decryptfile */
2458:
2459:
2460:
2461: int idea_decryptfile(char *infile, char *outfile)
2462: {
2463: byte ctb; /* Cipher Type Byte */
2464: FILE *f;
2465: FILE *g;
2466: byte ideakey[16];
2467: byte passphrase[256];
2468: int status;
2469: word32 flen;
2470:
2471: if (verbose)
2472: fprintf(pgpout,PSTR("\nCiphertext file: %s, plaintext file: %s\n"),
2473: infile,outfile);
2474:
2475: /* open file f for read, in binary (not text) mode...*/
2476: #ifdef VMS
2477: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
2478: #else
2479: if ((f = fopen(infile,"rb")) == NULL)
2480: #endif
2481: { fprintf(pgpout,PSTR("\n\007Can't open ciphertext file '%s'\n"),infile);
2482: return(-1);
2483: }
2484:
2485: fread(&ctb,1,1,f); /* read Cipher Type Byte, should be CTB_CKE */
2486:
2487: if (!is_ctb(ctb) || !is_ctb_type(ctb,CTB_CKE_TYPE))
2488: { /* Should never get here. */
2489: fprintf(pgpout,"\007\nBad or missing CTB_CKE byte.\n");
2490: goto err1; /* Abandon ship! */
2491: }
2492:
2493: flen = getpastlength(ctb, f); /* read packet length */
2494:
2495: if (file_exists( outfile ))
2496: { fprintf(pgpout, PSTR("\n\007Output file '%s' already exists. Overwrite (y/N)? "), outfile );
2497: if (! getyesno( 'n' ))
2498: goto err1; /* user said don't do it - abort operation */
2499: }
2500:
2501: /* open file g for write, in binary (not text) mode... */
2502: if ((g = fopen( outfile, "wb" )) == NULL)
2503: { fprintf(pgpout, PSTR("\n\007Can't create plaintext file '%s'\n"), outfile );
2504: goto err1;
2505: }
2506:
2507: /* Get IDEA password, hashed */
2508: fprintf(pgpout,PSTR("\nYou need a pass phrase to decrypt this file. "));
2509: if (getideakey((char *)passphrase,(char *)ideakey,NOECHO1) <= 0)
2510: { fclose(f);
2511: fclose(g);
2512: return(-1);
2513: }
2514:
2515: fprintf(pgpout,PSTR("Just a moment...")); /* this may take a while */
2516: fflush(pgpout);
2517:
2518: status = idea_file( ideakey, DECRYPT_IT, f, g, flen );
2519:
2520: burn(ideakey); /* burn sensitive data on stack */
2521: burn(passphrase);
2522:
2523: fputc('.',pgpout); /* show progress */
2524:
2525: fclose(g);
2526: fclose(f);
2527:
2528: if (status < 0) /* if idea_file failed, then complain */
2529: { fprintf(pgpout,PSTR("\n\007Error: Bad pass phrase.\n"));
2530: remove(outfile); /* throw away our mistake */
2531: return(status); /* error return */
2532: }
2533: fprintf(pgpout,PSTR("Pass phrase appears good. "));
2534: return(1); /* always indicate output file has nested stuff in it. */
2535:
2536: err1:
2537: fclose(f);
2538: return(-1); /* error return */
2539:
2540: } /* idea_decryptfile */
2541:
2542:
2543:
2544: int decompress_file(char *infile, char *outfile)
2545: {
2546: byte ctb;
2547: FILE *f;
2548: FILE *g;
2549: extern void lzhDecode( FILE *, FILE * );
2550: extern void unzip( FILE *, FILE * );
2551: if (verbose) fprintf(pgpout, PSTR("Decompressing plaintext...") );
2552:
2553: /* open file f for read, in binary (not text) mode...*/
2554: #ifdef VMS
2555: if ((f = fopen(infile,"rb","ctx=stm")) == NULL)
2556: #else
2557: if ((f = fopen(infile,"rb")) == NULL)
2558: #endif
2559: { fprintf(pgpout,PSTR("\n\007Can't open compressed file '%s'\n"),infile);
2560: return(-1);
2561: }
2562:
2563: fread(&ctb,1,1,f); /* read and skip over Cipher Type Byte */
2564: if (!is_ctb_type( ctb, CTB_COMPRESSED_TYPE ))
2565: { /* Shouldn't get here, or why were we called to begin with? */
2566: fprintf(pgpout,"\007\nBad or missing CTB_COMPRESSED byte.\n");
2567: goto err1; /* Abandon ship! */
2568: }
2569:
2570: getpastlength(ctb, f); /* read packet length */
2571: /* The packet length is ignored. Assume it's huge. */
2572:
2573: fread(&ctb,1,1,f); /* read and skip over compression algorithm byte */
2574: if (ctb != ZIP2_ALGORITHM_BYTE)
2575: { /* We only know how to uncompress deflate-compressed data. We
2576: may hit imploded or Lharc'ed data but treat it as an error just
2577: the same */
2578: fprintf(pgpout,PSTR("\007\nUnrecognized compression algorithm.\n\
2579: This may require a newer version of PGP.\n"));
2580: goto err1; /* Abandon ship! */
2581: }
2582:
2583: /* open file g for write, in binary (not text) mode... */
2584: if ((g = fopen( outfile, "wb" )) == NULL)
2585: { fprintf(pgpout, PSTR("\n\007Can't create decompressed file '%s'\n"), outfile );
2586: goto err1;
2587: }
2588:
2589: unzip( f, g );
2590: if (verbose) fprintf(pgpout, PSTR("done. ") );
2591: else fputc('.',pgpout); /* show progress */
2592:
2593: fclose(g);
2594: fclose(f);
2595: return(1); /* always indicate output file has nested stuff in it. */
2596: err1:
2597: fclose(f);
2598: return(-1); /* error return */
2599:
2600: } /* decompress_file */
2601:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.