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