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

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

unix.superglobalmegacorp.com

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