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