Annotation of pgp/src/crypto.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.