home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1998 February / PCOnline_02_1998.iso / filesbbs / os2 / pgp263.arj / PGP263I.SRC / PGP263II.ZIP / src / crypto.c < prev    next >
C/C++ Source or Header  |  1996-01-15  |  102KB  |  3,435 lines

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