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

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

unix.superglobalmegacorp.com

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