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

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

unix.superglobalmegacorp.com

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