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

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

unix.superglobalmegacorp.com

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