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

1.1.1.2   root        1: /*     keymgmt.c  - Key management routines for PGP.
                      2:        PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
                      3: 
                      4:        (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
                      5:        The author assumes no liability for damages resulting from the use
                      6:        of this software, even if the damage results from defects in this
                      7:        software.  No warranty is expressed or implied.
                      8: 
                      9:        All the source code Philip Zimmermann wrote for PGP is available for
                     10:        free under the "Copyleft" General Public License from the Free
                     11:        Software Foundation.  A copy of that license agreement is included in
                     12:        the source release package of PGP.  Code developed by others for PGP
                     13:        is also freely available.  Other code that has been incorporated into
                     14:        PGP from other sources was either originally published in the public
                     15:        domain or was used with permission from the various authors.  See the
                     16:        PGP User's Guide for more complete information about licensing,
                     17:        patent restrictions on certain algorithms, trademarks, copyrights,
                     18:        and export controls.  
                     19: */
                     20: 
                     21: #include <stdio.h>
                     22: #include <stdlib.h>
                     23: #ifdef UNIX
                     24: #include <sys/types.h>
                     25: #endif
                     26: #include <time.h>
                     27: #include <ctype.h>
1.1.1.3   root       28: #include "system.h"
1.1.1.2   root       29: #include "mpilib.h"
                     30: #include "idea.h"
                     31: #include "random.h"
                     32: #include "crypto.h"
                     33: #include "fileio.h"
                     34: #include "keymgmt.h"
                     35: #include "rsagen.h"
                     36: #include "mpiio.h"
                     37: #include "language.h"
                     38: #include "pgp.h"
                     39: #include "md5.h"
1.1.1.3   root       40: #include "charset.h"
                     41: #include "keymaint.h"
1.1.1.2   root       42: 
                     43: 
                     44: /*
                     45: **     Convert to or from external byte order.
                     46: **     Note that convert_byteorder does nothing if the external byteorder
                     47: **  is the same as the internal byteorder.
                     48: */
                     49: #define convert2(x,lx) convert_byteorder( (byteptr)&(x), (lx) )
                     50: #define convert(x)             convert2( (x), sizeof(x) )
                     51: 
                     52: 
                     53: /*
                     54:  * check if userid matches the substring, magic characters ^ and $
                     55:  * can be used to match start and end of userid.
                     56:  * if n is NULL, only return TRUE if substr is an exact match of
                     57:  * userid, a substring does not match in this case.
                     58:  * the comparison is always case insensitive
                     59:  */
1.1.1.3   root       60: static boolean userid_match(char *userid, char *substr,unitptr n)
1.1.1.2   root       61: {
                     62:        boolean match_end = FALSE;
                     63:        int id_len, sub_len, i;
                     64:        char buf[256], sub[256], *p;
                     65: 
                     66:        if (substr == NULL || *substr == '\0')
                     67:                return(TRUE);
                     68:        if (userid == NULL || *userid == '\0')
                     69:                return(FALSE);
                     70: 
                     71:        /* Check whether we have an ASCII or hex userID to check for */
                     72:        if (n != NULL && substr[ 0 ] == '0' && to_lower( substr[ 1 ] ) == 'x' )
                     73:        {
                     74:                userid = key2IDstring( n );
                     75:                substr += 2;
                     76:        }
                     77: 
                     78:        id_len = strlen(userid);
                     79:        for (i = 0; i <= id_len; ++i)
                     80:                buf[i] = to_lower(userid[i]);
                     81: 
                     82:        sub_len = strlen(substr);
                     83:        for (i = 0; i <= sub_len; ++i)
                     84:                sub[i] = to_lower(substr[i]);
                     85: 
                     86:        if (n == NULL)
                     87:        {
                     88:                return !strcmp(buf, sub);
                     89:        }
                     90: #ifdef MAGIC_MATCH
                     91:        if (sub_len > 1 && sub[sub_len - 1] == '$')
                     92:        {
                     93:                match_end = TRUE;
                     94:                sub[--sub_len] = '\0';
                     95:        }
                     96:        if (*sub == '^')
                     97:        {       if (match_end)
                     98:                        return(!strcmp(buf, sub + 1));
                     99:                else
                    100:                        return(!strncmp(buf, sub + 1, sub_len - 1));
                    101:        }
                    102: #endif
                    103:        if (sub_len > id_len)
                    104:                return(FALSE);
                    105: 
                    106:        if (match_end)
                    107:                return(!strcmp(buf + id_len - sub_len, sub));
                    108: 
                    109:        p = buf;
                    110:        while ((p = strchr(p, *sub)) != NULL)
                    111:        {
                    112:                if (strncmp(p, sub, sub_len) == 0)
                    113:                        return(TRUE);
                    114:                ++p;
                    115:        }
                    116:        return(FALSE);
                    117: }
                    118: 
                    119: int
                    120: is_key_ctb (byte ctb)
                    121: {
                    122:        return(ctb == CTB_CERT_PUBKEY  ||  ctb == CTB_CERT_SECKEY);
                    123: }
                    124: 
                    125: 
1.1.1.3   root      126: /*
                    127: **     keyIDstring
                    128: **
                    129: **     Return printable key fragment, which is an abbreviation of the public
                    130: **     key.  Show LEAST significant 64 bits (KEYFRAGSIZE bytes) of modulus,
                    131: **     LSB last.  Yes, that's LSB LAST.
                    132: */
                    133: 
                    134: char *keyIDstring( byte *keyID )
                    135:        {
                    136:        short           i;
                    137:        char            *bufptr;        /* ptr to Key ID string */
                    138:        static char     keyIDbuf[2*KEYFRAGSIZE+1];
                    139: 
                    140:        /*      only show bottom 3 bytes of keyID       */
                    141: 
1.1.1.2   root      142:        bufptr = keyIDbuf;
1.1.1.3   root      143:        
                    144: #ifdef XLOWFIRST
                    145:        /*
                    146:        **      LSB-first keyID format
                    147:        */
                    148: 
                    149:        for (i = 2; i >= 0; i--)
                    150:                {
                    151:                sprintf( bufptr, "%02X", keyID[i] );
                    152:                bufptr += 2;
                    153:                }
                    154: #else
                    155:        /*
                    156:        **      MSB-first keyID format
                    157:        */
                    158: 
                    159:        for (i = KEYFRAGSIZE-3; i < KEYFRAGSIZE; i++)
                    160:                {
                    161:                sprintf( bufptr, "%02X", keyID[i] );
                    162:                bufptr += 2;
1.1.1.2   root      163:                }
                    164: #endif
1.1.1.3   root      165:        *bufptr = '\0';
                    166:        return( keyIDbuf );
                    167:        }       /* keyIDstring */
1.1.1.2   root      168: 
                    169: 
                    170: 
                    171: void extract_keyID(byteptr keyID, unitptr n)
                    172: /*     Extract key fragment from modulus n.  keyID byte array must be
                    173:        at least KEYFRAGSIZE bytes long.
                    174: */
                    175: {      byte buf[MAX_BYTE_PRECISION+2];
                    176:        short i, j;
                    177: 
                    178:        fill0(buf,KEYFRAGSIZE+2); /* in case n is too short */
                    179:        reg2mpi(buf,n); /* MUST be at least KEYFRAGSIZE long */
                    180: #ifdef XLOWFIRST
                    181:        i = reg2mpi(buf,n);     /* MUST be at least KEYFRAGSIZE long */
                    182:        /* For LSB-first keyID format, start of keyID is: */
                    183:        i = 2;  /* skip over the 2 bytes of bitcount */
                    184:        for (j=0; j<KEYFRAGSIZE; )
                    185:                keyID[j++] = buf[i++];
                    186: #else
                    187:        i = reg2mpi(buf,n);     /* MUST be at least KEYFRAGSIZE long */
                    188:        /* For MSB-first keyID format, start of keyID is: */
                    189:        i = i + 2 - KEYFRAGSIZE;
                    190:        for (j=0; j<KEYFRAGSIZE; )
                    191:                keyID[j++] = buf[i++];
                    192: #endif
                    193: 
                    194: }      /* extract_keyID */
                    195: 
                    196: 
                    197: 
                    198: char *key2IDstring(unitptr n)
                    199: /*     Derive the key abbreviation fragment from the modulus n,
                    200:        and return printable string of key ID.
                    201:        n is key modulus from which to extract keyID.
                    202: */
                    203: {      byte keyID[KEYFRAGSIZE];
                    204:        extract_keyID(keyID, n);
                    205:        return (keyIDstring(keyID));
                    206: }      /* key2IDstring */
                    207: 
                    208: 
                    209: 
1.1.1.3   root      210: static void showkeyID(byteptr keyID)
1.1.1.2   root      211: /*     Print key fragment, which is an abbreviation of the public key. */
                    212: {
                    213:        fprintf(pgpout,"%s",keyIDstring(keyID));
                    214: }      /* showkeyID */
                    215: 
                    216: 
                    217: 
                    218: void writekeyID(unitptr n, FILE *f)
                    219: /*     Write message prefix keyID to a file.
                    220:        n is key modulus from which to extract keyID.
                    221: */
                    222: {      byte keyID[KEYFRAGSIZE];
                    223:        extract_keyID(keyID, n);
                    224:        fwrite(keyID,1,KEYFRAGSIZE,f);
                    225: }      /* writekeyID */
                    226: 
                    227: 
                    228: 
1.1.1.3   root      229: static boolean checkkeyID(byte *keyID, unitptr n)
1.1.1.2   root      230: /*     Compare specified keyID with one derived from actual key modulus n. */
                    231: {
                    232:        byte keyID0[KEYFRAGSIZE];
                    233:        if (keyID==NULL) /* no key ID -- assume a good match */
                    234:                return (TRUE);
                    235:        extract_keyID(keyID0, n);
                    236:        return(equal_buffers(keyID,keyID0,KEYFRAGSIZE));
                    237: }      /* checkkeyID */
                    238: 
                    239: 
                    240: 
                    241: /* external function prototype, from mpiio.c */
                    242: void dump_unit_array(string s, unitptr r);
                    243: 
                    244: void write_trust (FILE *f, byte trustbyte)
                    245: /*     Write a key control packet to f, with the specified trustbyte data.
                    246:  */
                    247: {
                    248:        byte ctb;
                    249:        byte keyctrllen;
                    250: 
                    251:        ctb = CTB_KEYCTRL;
                    252:        fwrite(&ctb,1,1,f);             /* write key control header byte */
                    253:        keyctrllen = 1;
                    254:        fwrite(&keyctrllen,1,1,f);      /* write key control length */
                    255:        fwrite(&trustbyte,1,1,f);       /* write key control */
                    256: }
                    257: 
1.1.1.3   root      258: static
1.1.1.2   root      259: short writekeyfile(char *fname, boolean hidekey, byte *timestamp, byte *userid, 
                    260:        unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u)
                    261: /*     Write key components p, q, n, e, d, and u to specified file.
                    262:        hidekey is TRUE iff key should be encrypted.
                    263:        userid is a length-prefixed Pascal-type character string. 
                    264:        We write three packets: a key packet, a key control packet, and
                    265:        a userid packet.  We assume the key being written is our own,
                    266:        so we set the control bits for full trust.
                    267: */
                    268: {      FILE *f;
                    269:        byte ctb;
                    270:        byte alg, version;
                    271:        word16 validity;
                    272:        word16 cert_length;
                    273:        extern word16 mpi_checksum;
                    274:        byte iv[8];
                    275:        int i;
                    276: 
                    277:        /* open file f for write, in binary (not text) mode...*/
                    278:        if ((f = fopen(fname,FOPWBIN)) == NULL)
                    279:        {       fprintf(pgpout,PSTR("\n\007Unable to create key file '%s'.\n"), fname);
                    280:                return(-1);
                    281:        }
                    282:        /*** Begin key certificate header fields ***/
                    283:        if (d==NULL)
                    284:        {       /* public key certificate */
                    285:                ctb = CTB_CERT_PUBKEY;
                    286:                cert_length = 1 + SIZEOF_TIMESTAMP + 2 + 1 + (countbytes(n)+2)
                    287:                        + (countbytes(e)+2);
                    288:        }       /* public key certificate */
                    289:        else
                    290:        {       /* secret key certificate */
                    291:                ctb = CTB_CERT_SECKEY;
                    292:                        cert_length = 1 + SIZEOF_TIMESTAMP + 2 + 1
                    293:                        + (countbytes(n)+2)
                    294:                        + (countbytes(e)+2)
                    295:                        + 1 + (hidekey ? 8 : 0)         /* IDEA algorithm byte and IV */
                    296:                        + (countbytes(d)+2)
                    297:                        + (countbytes(p)+2)     + (countbytes(q)+2) 
                    298:                        + (countbytes(u)+2) + 2;
                    299: 
                    300:        }       /* secret key certificate */
                    301: 
                    302:        fwrite(&ctb,1,1,f);             /* write key certificate header byte */
                    303:        convert(cert_length);   /* convert to external byteorder */
                    304:        fwrite(&cert_length,1,sizeof(cert_length),f);
                    305:        version = VERSION_BYTE;
                    306:        fwrite(&version,1,1,f);         /* set version number */
                    307:        convert_byteorder(timestamp,4); /* convert to external form */
                    308:        fwrite(timestamp,1,4,f); /* write certificate timestamp */
                    309:        convert_byteorder(timestamp,4); /* convert back to internal form */
                    310:        validity = 0;
                    311:        fwrite (&validity,1,sizeof(validity),f);        /* validity period */
                    312:        alg = RSA_ALGORITHM_BYTE;
                    313:        fwrite(&alg,1,1,f);
                    314:        write_mpi(n,f,FALSE);
                    315:        write_mpi(e,f,FALSE);
                    316: 
                    317:        if (is_secret_key(ctb)) /* secret key */
                    318:        {
                    319:                /* Write byte for following algorithm */
                    320:                alg = (hidekey)?IDEA_ALGORITHM_BYTE:0;
                    321:                fwrite(&alg,1,1,f);
                    322: 
                    323:                if (hidekey)  /* store encrypted IV */
                    324:                {       for (i=0; i<8; i++)
                    325:                                iv[i] = randombyte();
                    326:                        if (hidekey)  /* encrypt the IV */
                    327:                                ideacfb(iv,8);
                    328:                        fwrite(iv,1,8,f);       /* write out the IV */
                    329:                }
                    330:                mpi_checksum = 0;
                    331:                write_mpi(d,f,hidekey);
                    332:                write_mpi(p,f,hidekey);
                    333:                write_mpi(q,f,hidekey);
                    334:                write_mpi(u,f,hidekey);
                    335:                /* Write checksum here - based on plaintext values */
                    336:                convert(mpi_checksum);
                    337:                fwrite (&mpi_checksum,1,sizeof(mpi_checksum),f);
                    338:        } else {
                    339:                /* Keyring control packet, public keys only */
                    340:                write_trust (f, KC_OWNERTRUST_ULTIMATE | KC_BUCKSTOP);
                    341:        }
                    342:        /* User ID packet */
                    343:        ctb = CTB_USERID;
                    344:        fwrite(&ctb,1,1,f);             /* write userid header byte */
                    345:        fwrite(userid,1,userid[0]+1,f); /* write user ID */
                    346:        if (d == NULL)  /* only on public keyring */
                    347:                write_trust (f, KC_LEGIT_COMPLETE);
                    348:        if (write_error(f))
                    349:        {       fclose(f);
                    350:                return -1;
                    351:        }
                    352:        fclose(f);
                    353:        if (verbose)
                    354:                fprintf(pgpout,"%d-bit %s key written to file '%s'.\n",
                    355:                        countbits(n),
                    356:                        is_secret_key(ctb) ? "secret" : "public" ,
                    357:                        fname);
                    358:        return(0);
                    359: }      /* writekeyfile */
                    360: 
                    361: 
                    362: 
                    363: /* Return -1 on EOF, else read next key packet, return its ctb, and
                    364:  * advance pointer to beyond the packet.
                    365:  * This is short of a "short form" of readkeypacket
                    366:  */
                    367: short nextkeypacket(FILE *f, byte *pctb)
                    368: {
                    369:        word32 cert_length;
                    370:        int count;
                    371:        byte ctb;
                    372: 
                    373:        *pctb = 0;      /* assume no ctb for caller at first */
                    374:        count = fread(&ctb,1,1,f);      /* read key certificate CTB byte */
                    375:        if (count==0) return(-1);       /* premature eof */
                    376:        *pctb = ctb;    /* returns type to caller */
                    377:        if ((ctb != CTB_CERT_PUBKEY) && (ctb != CTB_CERT_SECKEY)  &&
                    378:                        (ctb != CTB_USERID)  &&  (ctb != CTB_KEYCTRL)  &&
                    379:                        !is_ctb_type(ctb,CTB_SKE_TYPE) &&
                    380:                        !is_ctb_type(ctb,CTB_COMMENT_TYPE))
                    381:                /* Either bad key packet or X/Ymodem padding detected */
                    382:                return ((ctb == 0x1A) ? -1 : -2);
                    383: 
                    384:        cert_length = getpastlength(ctb, f); /* read certificate length */
                    385: 
                    386:        if (cert_length > MAX_KEYCERT_LENGTH-3)
                    387:                return(-3);     /* bad length */
                    388: 
                    389:        fseek(f, cert_length, SEEK_CUR);
                    390:        return(0);
                    391: } /* nextkeypacket */
                    392: 
                    393: 
                    394: short readkeypacket(FILE *f, boolean hidekey, byte *pctb,
                    395:        byte *timestamp, char *userid,
                    396:        unitptr n ,unitptr e, unitptr d, unitptr p, unitptr q, unitptr u,
                    397:        byte *sigkeyID, byte *keyctrl)
                    398: /*     Reads a key certificate from the current file position of file f.
                    399:        Depending on the certificate type, it will set the proper fields
                    400:        of the return arguments.  Other fields will not be set.
                    401:        pctb is always set.
                    402:        If the packet is CTB_CERT_PUBKEY or CTB_CERT_SECKEY, it will
                    403:        return timestamp, n, e, and if the secret key components are
                    404:        present and d is not NULL, it will read, decrypt if hidekey is
                    405:        true, and return d, p, q, and u.
                    406:        If the packet is CTB_KEYCTRL, it will return keyctrl as that byte.
                    407:        If the packet is CTB_USERID, it will return userid.
                    408:        If the packet is CTB_COMMENT_TYPE, it won't return anything extra.
                    409:        The file pointer is left positioned after the certificate.
                    410: 
                    411:        If the key could not be read because of a version error or bad
                    412:        data, the return value is -6 or -4, the file pointer will be
                    413:        positioned after the certificate, only the arguments pctb and
                    414:        userid will valid in this case, other arguments are undefined.
                    415:        Return value -3 means the error is unrecoverable.
                    416: 
                    417: */
                    418: {
                    419:        byte ctb;
                    420:        word16 cert_length;
                    421:        int count;
                    422:        byte version, alg, mdlen;
                    423:        word16 validity;
                    424:        word16 chksum;
                    425:        extern word16 mpi_checksum;
                    426:        long next_packet;
                    427:        byte iv[8];
                    428: 
                    429:        /*** Begin certificate header fields ***/
                    430:        *pctb = 0;      /* assume no ctb for caller at first */
                    431:        count = fread(&ctb,1,1,f);      /* read key certificate CTB byte */
                    432:        if (count==0) return(-1);       /* premature eof */
                    433:        *pctb = ctb;    /* returns type to caller */
                    434:        if ((ctb != CTB_CERT_PUBKEY) && (ctb != CTB_CERT_SECKEY)  &&
                    435:                        (ctb != CTB_USERID)  &&  (ctb != CTB_KEYCTRL)  &&
                    436:                        !is_ctb_type(ctb,CTB_SKE_TYPE) &&
                    437:                        !is_ctb_type(ctb,CTB_COMMENT_TYPE))
                    438:                /* Either bad key packet or X/Ymodem padding detected */
                    439:                return ((ctb == 0x1A) ? -1 : -2);
                    440: 
                    441:        cert_length = getpastlength(ctb, f); /* read certificate length */
                    442: 
                    443:        if (cert_length > MAX_KEYCERT_LENGTH-3)
                    444:                return(-3);     /* bad length */
                    445: 
                    446:        next_packet = ftell(f) + cert_length;
                    447: 
                    448:        /* skip packet and return, keeps us in sync when we hit a
                    449:           version error or bad data */
                    450: #define        SKIP_RETURN(x) \
1.1.1.3   root      451:        do \
                    452:        { \
                    453:                fseek(f,next_packet,SEEK_SET); \
                    454:                return(x); \
                    455:        } while(0)
1.1.1.2   root      456: 
                    457:        if (ctb == CTB_USERID)
                    458:        {       if (cert_length > 255)
                    459:                        return(-3);                     /* Bad length error */
                    460:                if (userid)
                    461:                {       userid[0] = cert_length;                /* Save user ID length */
                    462:                        fread(userid+1,1,cert_length,f); /* read rest of user ID */
                    463:                } else
                    464:                        fseek (f, (long)cert_length, SEEK_CUR);
                    465:                return(0);      /* normal return */
                    466:        }
                    467:        else if (is_ctb_type (ctb, CTB_SKE_TYPE))
                    468:        {       if (sigkeyID)
                    469:                {       fread(&version,1,1,f);          /* Read version of sig packet */
                    470:                        if (version_error(version, VERSION_BYTE))
                    471:                                SKIP_RETURN(-6);                        /* Need a later version */
                    472:                        /* Skip timestamp, validity period, and type byte */
                    473:                        fread(&mdlen, 1, 1, f);
                    474:                        fseek(f, (long) mdlen, SEEK_CUR);
                    475:                        /* Read and return KEY ID */
                    476:                        fread(sigkeyID,1,KEYFRAGSIZE,f);
                    477:                }
                    478:                SKIP_RETURN(0); /* normal return */
                    479:        }
                    480:        else if (ctb == CTB_KEYCTRL)
                    481:        {       if (cert_length != 1)
                    482:                        return(-3);                     /* Bad length error */
                    483:                if (keyctrl)
                    484:                        fread(keyctrl,1,cert_length,f); /* Read key control byte */
                    485:                else
                    486:                        fseek (f, (long)cert_length, SEEK_CUR);
                    487:                return(0);      /* normal return */
                    488:        }
                    489:        else if (!is_key_ctb(ctb))      /* comment or other packet */
                    490:                SKIP_RETURN(0); /* normal return */
                    491: 
                    492:        /* Here we have a key packet */
                    493:        if (n != NULL)
                    494:                set_precision(MAX_UNIT_PRECISION);      /* safest opening assumption */
                    495:        fread(&version,1,1,f);  /* read and check version */
                    496:        if (version_error(version, VERSION_BYTE))
                    497:                SKIP_RETURN(-6);                        /* Need a later version */
                    498:        if (timestamp)
                    499:        {       fread(timestamp,1,SIZEOF_TIMESTAMP,f);  /* read certificate timestamp */
                    500:                convert_byteorder(timestamp,SIZEOF_TIMESTAMP); /* convert from external form */
                    501:        } else
                    502:                fseek(f, (long)SIZEOF_TIMESTAMP, SEEK_CUR);
                    503:        fread(&validity,1,sizeof(validity),f);  /* Read validity period */
                    504:        convert(validity);      /* convert from external byteorder */
                    505:        /* We don't use validity period yet */
                    506:        fread (&alg, 1, 1, f);
                    507:        if (version_error(alg, RSA_ALGORITHM_BYTE))
                    508:                SKIP_RETURN(-6);                        /* Need a later version */
                    509:        /*** End certificate header fields ***/
                    510: 
                    511:        /* We're past certificate headers, now look at some key material...*/
                    512: 
                    513:        cert_length -= 1 + SIZEOF_TIMESTAMP + 2 + 1;
                    514: 
                    515:        if (n==NULL)    /* Skip key certificate data */
                    516:                SKIP_RETURN(0);
                    517: 
                    518:        if (read_mpi(n,f,TRUE,FALSE) < 0)
                    519:                SKIP_RETURN(-4);        /* data corrupted, return error */
                    520: 
                    521:        /* Note that precision was adjusted for n */
                    522: 
                    523:        if (read_mpi(e,f,FALSE,FALSE) < 0)
                    524:                SKIP_RETURN(-4);        /* data corrupted, error return */
                    525: 
                    526:        cert_length -= (countbytes(n)+2) + (countbytes(e)+2);
                    527: 
                    528:        if (d==NULL)    /* skip rest of this key certificate */
                    529:                SKIP_RETURN(0);                 /* Normal return */
                    530:        if (is_secret_key(ctb))
1.1.1.3   root      531:        {
1.1.1.2   root      532:                fread (&alg,1,1,f);
                    533:                if (alg && version_error(alg,IDEA_ALGORITHM_BYTE))
                    534:                        SKIP_RETURN(-6);                        /* Unknown version */
                    535: 
                    536:                if (!hidekey && alg)
                    537:                        /* Don't bother trying if hidekey is false and alg is true */
                    538:                        SKIP_RETURN(-5);
                    539: 
                    540:                if (alg)        /* if secret components are encrypted... */
                    541:                {       /* process encrypted CFB IV before reading secret components */
                    542:                        count = fread(iv,1,8,f);
                    543:                        if (count < 8)
                    544:                                return(-4);     /* data corrupted, error return */
                    545:                        ideacfb(iv,8);
                    546:                        cert_length -= 8;       /* take IV length into account */
                    547:                }
                    548: 
                    549:                /* Reset checksum before these reads */
                    550:                mpi_checksum = 0;
                    551: 
                    552:                if (read_mpi(d,f,FALSE,hidekey) < 0)
                    553:                        return(-4);     /* data corrupted, error return */
                    554:                if (read_mpi(p,f,FALSE,hidekey) < 0)
                    555:                        return(-4);     /* data corrupted, error return */
                    556:                if (read_mpi(q,f,FALSE,hidekey) < 0)
                    557:                        return(-4);     /* data corrupted, error return */
                    558: 
                    559:                /* use register 'u' briefly as scratchpad */
                    560:                mp_mult(u,p,q); /* compare p*q against n */
                    561:                if (mp_compare(n,u)!=0) /* bad pass phrase? */
                    562:                        return(-5);     /* possible bad pass phrase, error return */
                    563:                /* now read in real u */
                    564:                if (read_mpi(u,f,FALSE,hidekey) < 0)
                    565:                        return(-4);     /* data corrupted, error return */
                    566: 
                    567:                /* Read checksum, compare with mpi_checksum */
                    568:                fread (&chksum,1,sizeof(chksum),f);
                    569:                convert(chksum);
                    570:                if (chksum != mpi_checksum)
                    571:                        return(-5);     /* possible bad pass phrase */
                    572: 
                    573:                cert_length -= 1 + (countbytes(d)+2) + (countbytes(p)+2)
                    574:                        + (countbytes(q)+2) + (countbytes(u)+2) + 2;
                    575: 
                    576:        }       /* secret key */
                    577:        else /* not a secret key */
                    578:        {       mp_init(d,0);
                    579:                mp_init(p,0);
                    580:                mp_init(q,0);
                    581:                mp_init(u,0);
                    582:        }
                    583: 
                    584:        if (cert_length != 0)
                    585:        {       fprintf(pgpout,"\n\007Corrupted key.  Bad length, off by %d bytes.\n",
                    586:                        (int) cert_length);
                    587:                SKIP_RETURN(-4);        /* data corrupted, error return */
                    588:        }
                    589: 
                    590:        return(0);      /* normal return */
                    591: 
                    592: }      /* readkeypacket */
                    593: 
                    594: 
                    595: 
1.1.1.3   root      596: int getpublickey(int flags, char *keyfile, long *_file_position,
                    597:        int *_pktlen, byte *keyID, byte *timestamp, byte *userid,
                    598:        unitptr n, unitptr e)
1.1.1.2   root      599: /*     keyID contains key fragment we expect to find in keyfile.
                    600:        If keyID is NULL, then userid contains a C string search target of
                    601:        userid to find in keyfile.
                    602:        keyfile is the file to begin search in, and it may be modified
                    603:        to indicate true filename of where the key was found.  It can be
                    604:        either a public key file or a secret key file.
                    605:        file_position is returned as the byte offset within the keyfile
                    606:        that the key was found at.  pktlen is the length of the key packet.
                    607:        These values are for the key packet itself, not including any
                    608:        following userid, control, signature, or comment packets.
1.1.1.3   root      609: 
                    610:        possible flags:
                    611:        GPK_GIVEUP: we are just going to do a single file search only.
                    612:        GPK_SHOW: show the key if found.
                    613:        GPK_NORVK: skip revoked keys.
                    614:        GPK_DISABLED: don't ignore disabled keys (when doing userid lookup)
1.1.1.2   root      615: 
                    616:        Returns -6 if the key was found but the key was not read because of a
                    617:        version error or bad data.  The arguments timestamp, n and e are
                    618:        undefined in this case.
                    619: */
                    620: {
                    621:        byte ctb;       /* returned by readkeypacket */
                    622:        FILE *f;
                    623:        int status, keystatus = -1;
                    624:        boolean keyfound = FALSE;
                    625:        boolean secret = FALSE;
1.1.1.3   root      626:        char matchid[256];      /* C string format */
                    627:        long fpos;
                    628:        long file_position = 0;
                    629:        int pktlen = 0;
                    630:        boolean skip = FALSE;   /* if TRUE: skip until next key packet */
                    631:        byte keyctrl;
1.1.1.2   root      632: 
                    633:        if (keyID==NULL)        /* then userid has search target */
1.1.1.3   root      634:                strcpy(matchid,(char *)userid);
                    635:        else
                    636:                matchid[0] = '\0';
1.1.1.2   root      637: 
                    638: top:
                    639:        if (strlen(keyfile) == 0)       /* null filename */
                    640:                return(-1);     /* give up, error return */
                    641: 
                    642:        default_extension(keyfile,PGP_EXTENSION);
                    643: 
                    644:        if (!file_exists(keyfile))
1.1.1.3   root      645:        {       if (flags & GPK_GIVEUP)
1.1.1.2   root      646:                        return(-1);     /* give up, error return */
                    647:                fprintf(pgpout,PSTR("\n\007Keyring file '%s' does not exist. "),keyfile);
                    648:                goto nogood;
                    649:        }
                    650:        if (verbose)
                    651:        {       fprintf(pgpout,"searching key ring file '%s' ",keyfile);
                    652:                if (keyID)
                    653:                        fprintf(pgpout, "for keyID %s\n", keyIDstring(keyID));
                    654:                else
                    655:                        fprintf(pgpout, "for userid \"%s\"\n", userid);
                    656:        }
                    657: 
                    658:        /* open file f for read, in binary (not text) mode...*/
                    659:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
                    660:                return(-1);     /* error return */
                    661: 
1.1.1.3   root      662:        keyfound = FALSE;
1.1.1.2   root      663:        while (TRUE) 
                    664:        {
                    665:                fpos = ftell(f);
                    666:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e,
                    667:                                NULL,NULL,NULL,NULL,NULL,NULL);
                    668:                /* Note that readkeypacket has called set_precision */
                    669: 
                    670:                if (status == -1)       /* end of file */
                    671:                        break;
                    672: 
                    673:                if (status < -1 && status != -4 && status != -6)
                    674:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                    675:                                keyfile);
                    676:                        fclose(f);      /* close key file */
                    677:                        return(status);
                    678:                }
                    679: 
                    680:                /* Remember packet position and size for last key packet */
                    681:                if (is_key_ctb(ctb))
1.1.1.3   root      682:                {       file_position = fpos;
                    683:                        pktlen = (int)(ftell(f) - fpos);
1.1.1.2   root      684:                        secret = is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE);
                    685:                        keystatus = status;
1.1.1.3   root      686:                        if (!keyID && !(flags & GPK_DISABLED) && !secret
                    687:                                        && read_trust(f, &keyctrl) == 0
                    688:                                        && (keyctrl & KC_DISABLED))
                    689:                                skip = TRUE;
                    690:                        else
                    691:                                skip = FALSE;
1.1.1.2   root      692:                }
                    693: 
                    694:                /* Only check for matches when we find a USERID packet */
1.1.1.3   root      695:                if (!skip && ctb == CTB_USERID)
1.1.1.2   root      696:                {       /* keyID contains key fragment.  Check it against n from keyfile. */
                    697:                        if (keyID!=NULL)
                    698:                        {       if (keystatus == 0)
                    699:                                        keyfound = checkkeyID(keyID,n);
                    700:                        }
                    701:                        else
1.1.1.3   root      702:                        {       /* matchid is already a C string */
1.1.1.2   root      703:                                PascalToC((char *)userid);      /* for C string functions */
                    704:                                /* Accept any matching subset */
1.1.1.3   root      705:                                keyfound = userid_match((char *)userid,matchid,n);
1.1.1.2   root      706:                                CToPascal((char *)userid);
                    707:                        }
                    708:                }
                    709: 
                    710:                if (keyfound)
1.1.1.3   root      711:                {       if (flags & GPK_SHOW)
                    712:                                show_key(f, file_position, 0);
                    713:                        fseek(f, file_position, SEEK_SET);
                    714:                        if ((flags&GPK_NORVK) && keystatus == 0 && is_compromised(f))
                    715:                        {
                    716:                                if (flags&GPK_SHOW)     /* already printed user ID */
                    717:                                        fprintf(pgpout, PSTR("\n\007Sorry, this key has been revoked by its owner.\n"));
                    718:                                else
                    719:                                {
                    720:                                        PascalToC((char *) userid);
                    721:                                        fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\
                    722: has been revoked.  You cannot use this key.\n"), 
                    723:                                                LOCAL_CHARSET((char *)userid));
1.1.1.2   root      724:                                }
1.1.1.3   root      725:                                keyfound = FALSE;
                    726:                                skip = TRUE;
                    727:                                /* we're positioned at the key packet, skip it */
                    728:                                nextkeypacket(f, &ctb);
1.1.1.2   root      729:                        }
1.1.1.3   root      730:                        else
                    731:                        {       /* found key, normal return */
                    732:                                if (_pktlen)
                    733:                                        *_pktlen = pktlen;
                    734:                                if (_file_position)
                    735:                                        *_file_position = file_position;
                    736:                                fclose(f);
                    737:                                return(keystatus);
1.1.1.2   root      738:                        }
                    739:                }
                    740:        }       /* while TRUE */
                    741: 
                    742:        fclose(f);      /* close key file */
                    743: 
1.1.1.3   root      744:        if (flags & GPK_GIVEUP)
1.1.1.2   root      745:                return(-1);     /* give up, error return */
                    746: 
                    747:        if (keyID!=NULL)
                    748:        {
                    749:                fprintf(pgpout,PSTR("\n\007Key matching expected Key ID %s not found in file '%s'.\n"),
                    750:                        keyIDstring(keyID),keyfile);
                    751:        }
                    752:        else
                    753:        {       fprintf(pgpout,PSTR("\n\007Key matching userid '%s' not found in file '%s'.\n"),
1.1.1.3   root      754:                        LOCAL_CHARSET(matchid),keyfile);
1.1.1.2   root      755:        }
                    756: 
                    757: nogood:
1.1.1.3   root      758:        if (filter_mode || batchmode)
1.1.1.2   root      759:                return(-1);     /* give up, error return */
                    760: 
                    761:        if (secret)
                    762:                fprintf(pgpout,PSTR("Enter secret key filename: "));
                    763:        else
                    764:                fprintf(pgpout,PSTR("Enter public key filename: "));
                    765: 
                    766:        getstring(keyfile,59,TRUE);     /* echo keyboard input */
                    767:        goto top;
                    768: 
                    769: }      /* getpublickey */
                    770: 
                    771: 
                    772: int getpubuserid(char *keyfile, long key_position, byte *userid,
                    773:        long *userid_position, int *userid_len, boolean exact_match)
                    774: /*  Start at key_position in keyfile, and scan for the key packet
                    775:        that contains userid.  Return userid_position and userid_len.
                    776:        Return 0 if OK, -1 on error.  Userid should be a C string.
                    777:        If exact_match is TRUE, the userid must match for full length,
                    778:        a substring is not enough.
                    779: */
                    780: {
                    781:        unit n[MAX_UNIT_PRECISION];
                    782:        unit e[MAX_UNIT_PRECISION];
                    783:        byte ctb;       /* returned by readkeypacket */
                    784:        FILE *f;
                    785:        int status;
                    786:        char userid0[256];      /* C string format */
                    787:        long fpos;
                    788: 
                    789:        /* open file f for read, in binary (not text) mode...*/
                    790:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
                    791:                return(-1);     /* error return */
                    792: 
                    793:        /* Start off at correct location */
                    794:        fseek (f, key_position, SEEK_SET);
                    795:        (void)nextkeypacket(f, &ctb);   /* Skip key */
                    796:        while (TRUE)
                    797:        {
                    798:                fpos = ftell(f);
                    799:                status = readkeypacket(f,FALSE,&ctb,NULL,(char *)userid0,n,e,
                    800:                                NULL,NULL,NULL,NULL,NULL,NULL);
                    801: 
                    802:                if (status < 0  ||  is_key_ctb(ctb))
1.1.1.3   root      803:                {       fclose(f);      /* close key file */
                    804:                        return(status ? status : -1);   /* give up, error return */
                    805:                }
1.1.1.2   root      806: 
                    807:                /* Only check for matches when we find a USERID packet */
                    808:                if (ctb == CTB_USERID)
1.1.1.3   root      809:                {       if (userid[0] == '0' && userid[1] == 'x')
                    810:                                break;  /* use first userid if user specified a keyID */
                    811:                        /* userid is already a C string */
1.1.1.2   root      812:                        PascalToC((char *)userid0);     /* for C string functions */
                    813:                        /* Accept any matching subset if exact_match is FALSE */
                    814:                        if (userid_match((char *)userid0, (char *) userid,
1.1.1.3   root      815:                                        (exact_match ? NULL : n)))
                    816:                                break;
1.1.1.2   root      817:                }
                    818:        }       /* while TRUE */
1.1.1.3   root      819:        *userid_position = fpos;
                    820:        *userid_len = ( int ) ( ftell(f) - fpos );
                    821:        fclose(f);
                    822:        return(0);      /* normal return */
1.1.1.2   root      823: }      /* getpubuserid */
                    824: 
                    825: 
                    826: int getpubusersig(char *keyfile, long user_position, byte *sigkeyID,
                    827:        long *sig_position, int *sig_len)
                    828: /*  Start at user_position in keyfile, and scan for the signature packet
                    829:        that matches sigkeyID.  Return sig_position and sig_len.
                    830:        Return 0 if OK, -1 on error.
                    831: */
                    832: {
                    833:        byte ctb;       /* returned by readkeypacket */
                    834:        FILE *f;
                    835:        int status;
                    836:        byte keyID0[KEYFRAGSIZE];
                    837:        long fpos;
                    838: 
                    839:        /* open file f for read, in binary (not text) mode...*/
                    840:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
                    841:                return(-1);     /* error return */
                    842: 
                    843:        /* Start off at correct location */
                    844:        fseek (f, user_position, SEEK_SET);
                    845:        (void)nextkeypacket(f, &ctb);   /* Skip userid packet */
                    846:        while (TRUE) 
                    847:        {
                    848:                fpos = ftell(f);
                    849:                status = readkeypacket(f,FALSE,&ctb,NULL,NULL,NULL,NULL,
                    850:                                NULL,NULL,NULL,NULL,keyID0,NULL);
                    851: 
                    852:                if (status < 0  ||  is_key_ctb(ctb)  ||  ctb==CTB_USERID)
                    853:                        break;
                    854: 
                    855:                /* Only check for matches when we find a signature packet */
                    856:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
                    857:                {       if (equal_buffers(sigkeyID,keyID0,KEYFRAGSIZE))
                    858:                        {       *sig_position = fpos;
                    859:                                *sig_len = ( int ) ( ftell(f) - fpos );
                    860:                                fclose(f);
                    861:                                return(0);      /* normal return */
                    862:                        }
                    863:                }
                    864:        }       /* while TRUE */
                    865: 
                    866:        fclose(f);      /* close key file */
                    867:        return(status ? status : -1);   /* give up, error return */
                    868: }      /* getpubusersig */
                    869: 
                    870: 
1.1.1.3   root      871: int getsecretkey(int flags, char *keyfile, byte *keyID,
1.1.1.4 ! root      872:        byte *timestamp, byte *hpass, boolean *hkey, byte *userid,
        !           873:         unitptr n, unitptr e, unitptr d, unitptr p, unitptr q,
1.1.1.2   root      874:        unitptr u)
                    875: /*     keyID contains key fragment we expect to find in keyfile.
                    876:        If keyID is NULL, then userid contains search target of
                    877:        userid to find in keyfile.
                    878:        giveup controls whether we ask the user for the name of the
                    879:        secret key file on failure.  showkey controls whether we print
                    880:        out the key information when we find it.  keyfile, if non-NULL,
                    881:        is the name of the secret key file; if NULL, we use the
1.1.1.4 ! root      882:        default.  hpass and hkey, if non-NULL, get returned with a copy
        !           883:        of the hashed password buffer and hidekey variable.
1.1.1.2   root      884: */
                    885: {
                    886:        byte ctb;       /* returned by readkeypacket */
                    887:        FILE *f;
                    888:        char keyfilename[MAX_PATH];     /* for getpublickey */
                    889:        long file_position;
                    890:        int status;
1.1.1.4 ! root      891:        boolean hidekey;        /* TRUE iff secret key is encrypted */
1.1.1.2   root      892:        word16 iv[4];           /* initialization vector for encryption */
                    893:        byte ideakey[16];
                    894:        int guesses = 3;
1.1.1.4 ! root      895:        struct hashedpw *hpw, **hpwp;
1.1.1.2   root      896: 
                    897:        if (keyfile == NULL)
                    898:        {       /* use default pathname */
                    899:                buildfilename(keyfilename,SECRET_KEYRING_FILENAME);
                    900:                keyfile = keyfilename;
                    901:        }
                    902: 
1.1.1.3   root      903:        status = getpublickey(flags, keyfile, &file_position, NULL, keyID,
                    904:                timestamp, userid, n, e);
1.1.1.2   root      905:        if (status < 0)
                    906:                return(status); /* error return */
                    907: 
                    908:        /* open file f for read, in binary (not text) mode...*/
                    909:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
                    910:                return(-1);     /* error return */
                    911: 
1.1.1.4 ! root      912:        /* First guess is no password */
        !           913:        hidekey = FALSE;
        !           914:        fseek(f,file_position,SEEK_SET); /* reposition file to key */
        !           915:        status = readkeypacket(f,hidekey,&ctb,timestamp,(char *)userid,
        !           916:                                        n,e,d,p,q,u,NULL,NULL);
        !           917:        if (status != -5)       /* Anything except bad password */
        !           918:                goto done;
1.1.1.2   root      919: 
1.1.1.4 ! root      920:        /* If we're not signing a key (when we force asking the user),
        !           921:         * check the prevosuly known passwords.
        !           922:         */
        !           923:        if (!(flags & GPK_ASKPASS)) {
        !           924:                hidekey = TRUE;
        !           925:                /* Then come existing key passwords */
        !           926:                hpw = keypasswds;
        !           927:                while (hpw) {
1.1.1.2   root      928:                        fill0(iv,8);
1.1.1.4 ! root      929:                        memcpy(ideakey, hpw->hash, sizeof(ideakey));
1.1.1.2   root      930:                        initcfb_idea(iv,ideakey,TRUE);
1.1.1.4 ! root      931:                        fseek(f,file_position,SEEK_SET);
        !           932:                        status = readkeypacket(f,hidekey,&ctb,timestamp,
        !           933:                                        (char *)userid,n,e,d,p,q,u,NULL,NULL);
        !           934:                        close_idea();
        !           935:                        if (status != -5)
        !           936:                                goto done;
        !           937:                        hpw = hpw->next;
        !           938:                }
        !           939:                /* Then try "other" passwords" */
        !           940:                hpwp = &passwds;
        !           941:                hpw = *hpwp;
        !           942:                while (hpw) {
        !           943:                        fill0(iv,8);
        !           944:                        memcpy(ideakey, hpw->hash, sizeof(ideakey));
        !           945:                        initcfb_idea(iv,ideakey,TRUE);
        !           946:                        fseek(f,file_position,SEEK_SET);
        !           947:                        status = readkeypacket(f,hidekey,&ctb,timestamp,
        !           948:                                        (char *)userid,n,e,d,p,q,u,NULL,NULL);
        !           949:                        close_idea();
        !           950:                        if (status >= 0)
        !           951:                        {       /* Success - move to key password list */
        !           952:                                *hpwp = hpw->next;
        !           953:                                hpw->next = keypasswds;
        !           954:                                keypasswds = hpw;
1.1.1.3   root      955:                        }
1.1.1.4 ! root      956:                        if (status != -5)
        !           957:                                goto done;
        !           958:                        hpwp = &hpw->next;
        !           959:                        hpw = *hpwp;
        !           960:                }
        !           961:        }
        !           962:        /* If batchmode, we don't ask the user. */
        !           963:        if (batchmode)
        !           964:        {       /* PGPPASS (or -z) wrong or not set */
        !           965:                fprintf(pgpout,PSTR("\n\007Error:  Bad pass phrase.\n"));
        !           966:                fclose(f);      /* close key file */
        !           967:                return -1;
        !           968:        }
        !           969:        /* Finally, prompt the user. */
        !           970:        fprintf(pgpout,PSTR("\nYou need a pass phrase to unlock your RSA secret key. "));
        !           971:        if (!(flags & GPK_SHOW))
        !           972:        {       /* let user know for which key he should type his password */
        !           973:                PascalToC((char *)userid);
        !           974:                fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n"), 
        !           975:                        LOCAL_CHARSET((char *)userid));
        !           976:                CToPascal((char *)userid);
        !           977:        }
        !           978:        do
        !           979:        {       hidekey = (GetHashedPassPhrase((char *) ideakey, 1) > 0);
        !           980:                fill0(iv,8);
        !           981:                initcfb_idea(iv,ideakey,TRUE);
        !           982:                fseek(f,file_position,SEEK_SET);
        !           983:                status = readkeypacket(f,hidekey,&ctb,timestamp,
        !           984:                                (char *)userid,n,e,d,p,q,u,NULL,NULL);
        !           985:                close_idea();
        !           986:                if (status >= 0)
        !           987:                {       /* Success - remember this key for later use */
        !           988:                        if (flags & GPK_ASKPASS)
        !           989:                        { /* This may be a duplicate because we didn't
        !           990:                           * search the lists before - check.
        !           991:                           */
        !           992:                                hpw = passwds;
        !           993:                                while (hpw)
        !           994:                                {       if (memcmp(hpw->hash, ideakey,
        !           995:                                                   sizeof(ideakey)) == 0)
        !           996:                                                goto done;
        !           997:                                        hpw = hpw->next;
        !           998:                                }
        !           999:                                hpw = keypasswds;
        !          1000:                                while (hpw)
        !          1001:                                {       if (memcmp(hpw->hash, ideakey,
        !          1002:                                                   sizeof(ideakey)) == 0)
        !          1003:                                                goto done;
        !          1004:                                        hpw = hpw->next;
1.1.1.2   root     1005:                                }
1.1.1.4 ! root     1006:                        }
        !          1007:                        /* Insert new key into remember lists. */
        !          1008:                        hpw = (struct hashedpw *)malloc(sizeof(struct hashedpw));
        !          1009:                        if (hpw)
        !          1010:                        { /* If malloc fails, just don't remember the phrase */
        !          1011:                                memcpy(hpw->hash, ideakey, sizeof(hpw->hash));
        !          1012:                                hpw->next = keypasswds;
        !          1013:                                keypasswds = hpw;
1.1.1.3   root     1014:                        }
1.1.1.2   root     1015:                }
1.1.1.4 ! root     1016:                if (status != -5)
        !          1017:                        goto done;
        !          1018:                fprintf(pgpout, PSTR("\n\007Error:  Bad pass phrase.\n"));
        !          1019:        } while (--guesses);
        !          1020:        /* Failed - fall through to done */
1.1.1.2   root     1021: 
1.1.1.4 ! root     1022: done:
        !          1023:        fclose(f);
        !          1024:        if (hkey)
        !          1025:                *hkey = hidekey;
        !          1026:        if (status == -5)
        !          1027:                return status;
        !          1028:        if (status < 0)
        !          1029:        {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
        !          1030:                        keyfile);
        !          1031:                fclose(f);      /* close key file */
        !          1032:                return(-1);
        !          1033:        }
        !          1034: 
        !          1035:        if (hpass)
        !          1036:                memcpy(hpass, ideakey, sizeof(ideakey));
        !          1037:        burn (ideakey);
1.1.1.2   root     1038: 
                   1039:        /* Note that readkeypacket has called set_precision */
                   1040: 
1.1.1.4 ! root     1041:        if (d != NULL)  /* No effective check of pass phrase if d is NULL */
1.1.1.3   root     1042:        {       
                   1043:                if (!quietmode)
                   1044:                {
                   1045:                        if (!hidekey)
                   1046:                                fprintf(pgpout,PSTR("\nAdvisory warning: This RSA secret key is not protected by a passphrase.\n"));
                   1047:                        else
                   1048:                                fprintf(pgpout,PSTR("Pass phrase is good.  "));
                   1049:                }
1.1.1.2   root     1050: 
                   1051:                if (testeq(d,0))        /* didn't get secret key components */
                   1052:                {       fprintf(pgpout,PSTR("\n\007Key file '%s' is not a secret key file.\n"),keyfile);
                   1053:                        return(-1);
                   1054:                }
                   1055:        }
                   1056: 
                   1057:        return(0);      /* normal return */
                   1058: 
                   1059: }      /* getsecretkey */
                   1060: 
                   1061: 
                   1062: int is_compromised(FILE *f)
                   1063: /* check if a key has a compromise certificate, file pointer must
                   1064:    be positioned at or right after the key packet.
                   1065: */
                   1066: {
                   1067:        long pos, savepos;
                   1068:        byte class, ctb;
                   1069:        int cert_len;
                   1070:        int status = 0;
                   1071: 
                   1072:        pos = savepos = ftell(f);
                   1073: 
                   1074:        nextkeypacket(f, &ctb);
                   1075:        if (is_key_ctb(ctb))
                   1076:        {       pos = ftell(f);
                   1077:                nextkeypacket(f, &ctb);
                   1078:        }
                   1079:        if (ctb != CTB_KEYCTRL)
                   1080:                fseek(f, pos, SEEK_SET);
                   1081: 
                   1082:        /* file pointer now positioned where compromise cert. should be */
                   1083:        if (fread(&ctb, 1, 1, f) != 1)
                   1084:        {       status = -1;
                   1085:                goto ex;
                   1086:        }
                   1087:        
                   1088:        if (is_ctb_type(ctb, CTB_SKE_TYPE))
                   1089:        {
                   1090:                cert_len = ( int ) getpastlength(ctb, f);
                   1091:                if (cert_len > MAX_SIGCERT_LENGTH)      /* Huge packet length */
                   1092:                {       status = -1;
                   1093:                        goto ex;
                   1094:                }
                   1095: 
                   1096:                /* skip version and mdlen byte */
                   1097:                fseek(f, 2L, SEEK_CUR);
                   1098:                if (fread(&class, 1, 1, f) != 1)
                   1099:                {       status = -1;
                   1100:                        goto ex;
                   1101:                }
                   1102:                status = (class == KC_SIGNATURE_BYTE);
                   1103:        }
                   1104: ex:
                   1105:        fseek(f, savepos, SEEK_SET);
                   1106:        return(status);
                   1107: }
                   1108: 
                   1109: 
                   1110: /*     Alfred Hitchcock coined the term "mcguffin" for the generic object 
                   1111:        being sought in his films-- the diamond, the microfilm, etc. 
                   1112: */
                   1113: 
                   1114: 
                   1115: /*     Calculate and display a hash for the public components of the key.
                   1116:        The components are converted to their external (big-endian) 
                   1117:        representation, concatenated, and an MD5 on the bit values 
                   1118:        (ie excluding the length value) calculated and displayed in hex.
                   1119: 
                   1120:        The hash, or "fingerprint", of the key is useful mainly for quickly
                   1121:        and easily verifying over the phone that you have a good copy of 
                   1122:        someone's public key.  Just read the hash over the phone and have
                   1123:        them check it against theirs.
                   1124: */
                   1125: 
                   1126: void getKeyHash( byte *hash, unitptr n, unitptr e )
                   1127: {
                   1128:        MD5_CTX mdContext;
                   1129:        byte buffer[ MAX_BYTE_PRECISION + 2 ];
                   1130:        byte mdBuffer[ MAX_BYTE_PRECISION * 2 ];
                   1131:        int i, mdIndex = 0, bufIndex;
                   1132: 
                   1133:        /* Convert n and e to external (big-endian) byte order and move to mdBuffer */
                   1134:        i = reg2mpi( buffer, n );
                   1135:        for( bufIndex = 2; bufIndex < i + 2; bufIndex++ )       /* +2 skips count */
                   1136:                mdBuffer[ mdIndex++ ] = buffer[ bufIndex ];
                   1137:        i = reg2mpi( buffer, e );
                   1138:        for( bufIndex = 2; bufIndex < i + 2; bufIndex++ )       /* +2 skips count */
                   1139:                mdBuffer[ mdIndex++ ] = buffer[ bufIndex ];
                   1140: 
                   1141:        /* Now evaluate the MD5 for the two MPI's */
                   1142:        MD5Init( &mdContext );
                   1143:        MD5Update( &mdContext, mdBuffer, mdIndex );
1.1.1.4 ! root     1144:        MD5Final( hash, &mdContext );
1.1.1.2   root     1145: 
                   1146: }      /* getKeyHash */
                   1147: 
                   1148: 
1.1.1.3   root     1149: void printKeyHash( byteptr hash, boolean indent )
1.1.1.2   root     1150: {
                   1151:        int i;
                   1152: 
                   1153: /*     Display the hash.  The format is:
                   1154: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1155:           Key fingerprint =  xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx 
                   1156: */
1.1.1.3   root     1157:        fprintf( pgpout, "%*s  ", indent ? 27 : 1, PSTR("Key fingerprint =" ) );
1.1.1.2   root     1158:        for( i = 0; i < 8; i++ )
                   1159:                fprintf(pgpout, "%02X ", hash[ i ] );
                   1160:        putc( ' ', pgpout);
                   1161:        for( i = 8; i < 16; i++ )
                   1162:                fprintf(pgpout, "%02X ", hash[ i ] );
                   1163:        putc( '\n', pgpout);
1.1.1.3   root     1164: 
                   1165: }      /* printKeyHash */
                   1166: 
                   1167: 
                   1168: void showKeyHash( unitptr n, unitptr e )
                   1169: {
                   1170:        byte hash[16];
                   1171: 
                   1172:        getKeyHash(hash,n,e);   /* compute hash of (n,e) */
                   1173: 
                   1174:        printKeyHash(hash, TRUE);
1.1.1.2   root     1175: }      /* showKeyHash */
                   1176: 
                   1177: 
                   1178: int view_keyring(char *mcguffin, char *ringfile, boolean show_signatures, boolean show_hashes)
                   1179: /*     Lists all entries in keyring that have mcguffin string in userid.
                   1180:        mcguffin is a null-terminated C string.
                   1181: */
                   1182: {      FILE *f;
1.1.1.3   root     1183:        byte ctb, keyctb=0;
1.1.1.2   root     1184:        int status;
                   1185:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1186:        byte keyID[KEYFRAGSIZE];
                   1187:        byte sigkeyID[KEYFRAGSIZE];
                   1188:        byte userid[256];               /* key certificate userid */
1.1.1.3   root     1189:        char *siguserid;        /* signator userid */
1.1.1.2   root     1190:        char dfltring[MAX_PATH];
                   1191:        word32 tstamp;
                   1192:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1193:        int keycounter = 0;
                   1194:        int firstuser = 0;
                   1195:        int compromised = 0;
1.1.1.3   root     1196:        boolean shownKeyHash=FALSE;
                   1197:        boolean invalid_key=FALSE;      /* unsupported version or bad data */
1.1.1.2   root     1198:        boolean match = FALSE;
1.1.1.3   root     1199:        boolean disabled = FALSE;
1.1.1.2   root     1200: 
                   1201:        /* Default keyring to check signature ID's */
                   1202:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1203: 
                   1204:        /* open file f for read, in binary (not text) mode...*/
                   1205:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1206:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1207:                return(-1);
                   1208:        }
1.1.1.3   root     1209:        if (show_signatures)
                   1210:        {
                   1211:                setkrent(ringfile);
                   1212:                setkrent(dfltring);
                   1213:                init_userhash();
                   1214:        }
1.1.1.2   root     1215: 
                   1216: /*     Here's a good format for display of key or signature certificates:
                   1217: Type bits/keyID   Date       User ID
                   1218: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1219: sec   512/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1220: sig   384/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1221: */
                   1222: 
                   1223:        if (moreflag)
                   1224:                open_more();
1.1.1.3   root     1225:        if (!quietmode)
                   1226:        {
                   1227:                fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile);
                   1228:                if (mcguffin && strlen(mcguffin) > 0)
                   1229:                        fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin));
                   1230:        }
1.1.1.2   root     1231:        fprintf(pgpout,PSTR("\nType bits/keyID   Date       User ID\n"));
                   1232:        for ( ; ; )
                   1233:        {
                   1234:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e,
                   1235:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1236:                /* Note that readkeypacket has called set_precision */
                   1237:                if (status== -1)
                   1238:                {       status = 0;
                   1239:                        break;  /* eof reached */
                   1240:                }
                   1241:                if (status == -4 || status == -6)
                   1242:                {       /* only ctb and userid are valid */
                   1243:                        memset(sigkeyID, 0, KEYFRAGSIZE);
                   1244:                        tstamp = 0;
                   1245:                }
                   1246:                else if (status < 0)
                   1247:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                   1248:                                ringfile);
                   1249:                        break;
                   1250:                }
                   1251: 
                   1252:                if (is_key_ctb(ctb))
                   1253:                {
1.1.1.3   root     1254:                        byte keyctrl;
                   1255: 
1.1.1.2   root     1256:                        firstuser = 1;
                   1257:                        keyctb = ctb;
                   1258:                        compromised = is_compromised(f);
                   1259:                        shownKeyHash = FALSE;
                   1260:                        if (status < 0)
                   1261:                        {       invalid_key = TRUE;
                   1262:                                memset(keyID, 0, KEYFRAGSIZE);
                   1263:                        }
                   1264:                        else
                   1265:                        {       invalid_key = FALSE;
                   1266:                                extract_keyID(keyID, n);
1.1.1.3   root     1267:                                if (read_trust(f, &keyctrl) == 0 && (keyctrl & KC_DISABLED))
                   1268:                                        disabled = TRUE;
                   1269:                                else
                   1270:                                        disabled = FALSE;
1.1.1.2   root     1271:                        }
                   1272:                }
                   1273: 
                   1274:                if (ctb != CTB_USERID  &&  !is_ctb_type(ctb, CTB_SKE_TYPE))
                   1275:                        continue;
                   1276:                if (ctb == CTB_USERID)
                   1277:                {       PascalToC((char *)userid);
                   1278:                        match = userid_match((char *)userid,mcguffin,n);
                   1279:                }
                   1280:                if (match)
                   1281:                {
                   1282:                        if (ctb == CTB_USERID)
                   1283:                        {       if (firstuser)
                   1284:                                {       keycounter++;
                   1285:                                        if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
                   1286:                                                fprintf(pgpout,"pub");
                   1287:                                        else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
                   1288:                                                fprintf(pgpout,"sec");
                   1289:                                        else
                   1290:                                                fprintf(pgpout,"???");
                   1291:                                        if (invalid_key)
                   1292:                                                fprintf(pgpout,"? ");
1.1.1.3   root     1293:                                        else if (disabled)
                   1294:                                                fprintf(pgpout,"@ ");
1.1.1.2   root     1295:                                        else
                   1296:                                                fprintf(pgpout,"  ");
                   1297:                                        fprintf(pgpout,"%4d/%s %s  ",
                   1298:                                                countbits(n),keyIDstring(keyID),cdate(&tstamp));
                   1299:                                }
                   1300:                                else
                   1301:                                        fprintf(pgpout,"                             ");
                   1302:                                if (compromised && firstuser)
                   1303:                                {       fprintf(pgpout, PSTR("*** KEY REVOKED ***\n"));
                   1304:                                        fprintf(pgpout,"                             ");
                   1305:                                }
                   1306:                                firstuser = 0;
                   1307:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid));
                   1308: 
                   1309:                                /* Display the hashes for n and e if required */
                   1310:                                if( show_hashes && !shownKeyHash )
                   1311:                                {       showKeyHash( n, e );
                   1312:                                        shownKeyHash = TRUE;
                   1313:                                }
                   1314:                        }
                   1315:                        else if (show_signatures && !(firstuser && compromised))        /* Must be sig cert */
                   1316:                        {       fprintf(pgpout,"sig%c      ", status < 0 ? '?' : ' ');
                   1317:                                showkeyID(sigkeyID);
                   1318:                                fprintf(pgpout,"               "); /* Indent signator userid */
1.1.1.3   root     1319:                                if ((siguserid = user_from_keyID(sigkeyID)) == NULL)
1.1.1.2   root     1320:                                        fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
1.1.1.3   root     1321:                                else
                   1322:                                        fprintf(pgpout,"%s\n",LOCAL_CHARSET(siguserid));
1.1.1.2   root     1323:                        } /* printing a sig cert */
                   1324:                }       /* if it has mcguffin */
                   1325:        }       /* loop for all packets */
                   1326: 
                   1327:        fclose(f);      /* close key file */
1.1.1.3   root     1328:        if (show_signatures)
                   1329:                endkrent();
1.1.1.2   root     1330:        fprintf(pgpout,PSTR("%d key(s) examined.\n"),keycounter);
                   1331:        close_more();
                   1332: 
1.1.1.3   root     1333:        if (status < 0)
                   1334:                return status;
                   1335:        if (mcguffin != NULL && *mcguffin != '\0')
                   1336:        {       /* user specified substring */
                   1337:                if (keycounter == 0)
                   1338:                        return 67;      /* user not found */
                   1339:                else if (keycounter > 1)
                   1340:                        return 1;       /* more than one match */
                   1341:        }
                   1342:        return(0);      /* normal return */
1.1.1.2   root     1343: 
                   1344: }      /* view_keyring */
                   1345: 
                   1346: 
1.1.1.3   root     1347: int dokeycheck(char *mcguffin, char *ringfile, int options)
1.1.1.2   root     1348: /*     Lists all entries in keyring that have mcguffin string in userid.
                   1349:        mcguffin is a null-terminated C string.
1.1.1.3   root     1350:        If options is CHECK_NEW, only new signatures are checked and are
                   1351:        marked as being checked in the trustbyte (called from addto_keyring).
1.1.1.2   root     1352: */
1.1.1.3   root     1353: {      FILE *f, *fixedf=NULL;
                   1354:        byte ctb, keyctb=0;
                   1355:        long fpsig = 0, fpkey = 0, fixpos = 0, trustpos = -1;
1.1.1.2   root     1356:        int status, sigstatus;
1.1.1.3   root     1357:        int keypktlen = 0, sigpktlen = 0;
1.1.1.2   root     1358:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1359:        byte keyID[KEYFRAGSIZE];
                   1360:        byte sigkeyID[KEYFRAGSIZE];
                   1361:        byte keyuserid[256];            /* key certificate userid */
                   1362:        byte siguserid[256];            /* sig certificate userid */
                   1363:        char dfltring[MAX_PATH];
1.1.1.3   root     1364:        char *tempring = NULL;
1.1.1.2   root     1365:        word32 tstamp;
                   1366:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1367:        word32 sigtstamp;
                   1368:        byte *sigtimestamp = (byte *) &sigtstamp;
                   1369:        byte sigclass;
                   1370:        int firstuser = 0;
                   1371:        int compromised = 0;
1.1.1.3   root     1372:        boolean invalid_key=FALSE;      /* unsupported version or bad data */
1.1.1.2   root     1373:        boolean failed=FALSE;
1.1.1.3   root     1374:        boolean print_userid=FALSE;
                   1375:        byte sigtrust;
1.1.1.2   root     1376: 
                   1377:        /* Default keyring to check signature ID's */
                   1378:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1379: 
1.1.1.3   root     1380:        /* open file f, in binary (not text) mode...*/
                   1381:        if (options & CHECK_NEW)
                   1382:                f = fopen(ringfile,FOPRWBIN);
                   1383:        else
                   1384:                f = fopen(ringfile,FOPRBIN);
                   1385:        if (f == NULL)
1.1.1.2   root     1386:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1387:                return(-1);
                   1388:        }
                   1389: 
                   1390: /*     Here's a good format for display of key or signature certificates:
                   1391: Type bits/keyID   Date       User ID
                   1392: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1393: sec   512/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1394: sig   384/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1395: */
                   1396: 
1.1.1.3   root     1397:        if (options & CHECK_NEW)
                   1398:        {       fprintf(pgpout,PSTR("\nChecking signatures...\n"));
                   1399:        }
                   1400:        else
                   1401:        {       
                   1402:                if (moreflag)
                   1403:                        open_more();
                   1404:                if (!quietmode)
                   1405:                {       fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile);
                   1406:                        if (mcguffin && strlen(mcguffin) > 0)
                   1407:                                fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin));
                   1408:                }
1.1.1.2   root     1409:                fprintf(pgpout,PSTR("\nType bits/keyID   Date       User ID\n"));
                   1410:        }
                   1411:        for ( ; ; )
                   1412:        {       long fpos = ftell(f);
                   1413:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)keyuserid,n,e,
                   1414:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1415:                /* Note that readkeypacket has called set_precision */
                   1416:                if (status== -1 ) break;        /* eof reached */
                   1417:                if (status == -4 || status == -6)
                   1418:                {       /* only ctb and userid are valid */
                   1419:                        memset(sigkeyID, 0, KEYFRAGSIZE);
                   1420:                        tstamp = 0;
                   1421:                }
                   1422:                else if (status < 0)
                   1423:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                   1424:                                ringfile);
                   1425:                        fclose(f);      /* close key file */
                   1426:                        return(-1);
                   1427:                }
                   1428: 
                   1429:                if (is_key_ctb(ctb))
                   1430:                {       firstuser = 1;
                   1431:                        keyctb = ctb;
                   1432:                        fpkey = fpos;
                   1433:                        keypktlen = ( int ) ( ftell(f) - fpkey );
                   1434:                        compromised = is_compromised(f);
                   1435:                        if (status < 0)
                   1436:                        {       invalid_key = TRUE;
                   1437:                                memset(keyID, 0, KEYFRAGSIZE);
                   1438:                        }
                   1439:                        else
                   1440:                        {       invalid_key = FALSE;
                   1441:                                extract_keyID(keyID, n);
                   1442:                        }
1.1.1.3   root     1443:                        if (options & CHECK_NEW)
                   1444:                                print_userid = TRUE;
1.1.1.2   root     1445:                }
                   1446: 
                   1447:                if (ctb == CTB_USERID)
                   1448:                        PascalToC((char *)keyuserid);
1.1.1.3   root     1449:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
                   1450:                {       fpsig = fpos;
                   1451:                        sigpktlen = ( int ) ( ftell(f) - fpsig );
                   1452:                } else
                   1453:                        continue;
1.1.1.2   root     1454: 
1.1.1.3   root     1455:                if (options & CHECK_NEW)
1.1.1.2   root     1456:                {
1.1.1.3   root     1457:                        if (!is_ctb_type(ctb, CTB_SKE_TYPE))
                   1458:                                continue;
                   1459:                        trustpos = ftell(f);
                   1460:                        status = read_trust(f, &sigtrust);
                   1461:                        if (status == -1)
                   1462:                                break;  /* EOF */
                   1463:                        if (status == -7)
                   1464:                        {       trustpos = -1;
                   1465:                                continue;       /* not a keyring or this was a compromise cert. */
                   1466:                        }
                   1467:                        if (status < 0)
                   1468:                        {       fclose(f);
                   1469:                                return status;
                   1470:                        }
                   1471:                        if (sigtrust & KC_SIG_CHECKED)
                   1472:                                continue;
                   1473:                        /* addto_keyring has called setkrent() */
                   1474:                        if (user_from_keyID(sigkeyID) == NULL)
                   1475:                                continue;       /* unknown signator */
                   1476:                }
                   1477: 
                   1478:                if ((options & CHECK_NEW) || userid_match((char *)keyuserid,mcguffin,n))
                   1479:                {
                   1480:                        if (ctb == CTB_USERID || print_userid)
                   1481:                        {       /* CHECK_NEW: only print userid if it has new signature */
                   1482:                                print_userid = FALSE;
1.1.1.2   root     1483:                                if (firstuser)
                   1484:                                {       if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
                   1485:                                                fprintf(pgpout,"pub");
                   1486:                                        else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
                   1487:                                                fprintf(pgpout,"sec");
                   1488:                                        else
                   1489:                                                fprintf(pgpout,"???");
                   1490:                                        if (invalid_key)
                   1491:                                                fprintf(pgpout,"? ");
                   1492:                                        else
                   1493:                                                fprintf(pgpout,"  ");
                   1494:                                        fprintf(pgpout,"%4d/%s %s  ",
                   1495:                                                countbits(n),keyIDstring(keyID),cdate(&tstamp));
                   1496:                                }
                   1497:                                else
                   1498:                                        fprintf(pgpout,"                             ");
                   1499:                                if (compromised && firstuser)
                   1500:                                {       fprintf(pgpout, PSTR("*** KEY REVOKED ***\n"));
                   1501:                                        fprintf(pgpout,"                             ");
                   1502:                                }
                   1503:                                firstuser = 0;
                   1504:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)keyuserid));
                   1505:                        }
1.1.1.3   root     1506:                        if (is_ctb_type(ctb, CTB_SKE_TYPE))
1.1.1.2   root     1507:                        {       /* Try checking signature on either this ring or dflt ring */
                   1508:                                CToPascal((char *)keyuserid);
                   1509:                                sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid,
                   1510:                                        f, fpsig, ringfile, (char *) siguserid, sigtimestamp, &sigclass);
                   1511:                                if (sigstatus == -1  &&  strcmp(ringfile,dfltring) != 0)
                   1512:                                        sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid,
                   1513:                                                f, fpsig, dfltring, (char *) siguserid, sigtimestamp, &sigclass);
                   1514:                                PascalToC((char *)keyuserid);
                   1515:                                fseek (f, fpsig+sigpktlen, SEEK_SET);
                   1516:                                if (sigclass == KC_SIGNATURE_BYTE)
                   1517:                                        fprintf(pgpout,"com");
                   1518:                                else
                   1519:                                        fprintf(pgpout,"sig");
                   1520:                                if (sigstatus >= 0)
                   1521:                                        fprintf(pgpout,"!      ");
                   1522:                                else if (status < 0 || sigstatus == -1)
                   1523:                                        fprintf(pgpout,"?      ");
                   1524:                                else
                   1525:                                        fprintf(pgpout,"*      ");      /* bad signature */
                   1526:                                showkeyID(sigkeyID);
                   1527:                                if (sigstatus == -1)
                   1528:                                {       fprintf(pgpout,"               "); /* Indent signator userid */
                   1529:                                        fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
                   1530:                                }
                   1531:                                else
                   1532:                                {       PascalToC((char *) siguserid);
                   1533:                                        fprintf(pgpout," %s  ",cdate(&sigtstamp));
                   1534:                                        if (sigclass != KC_SIGNATURE_BYTE)
                   1535:                                                fprintf(pgpout, "  ");
                   1536:                                        fprintf(pgpout,"%s\n", LOCAL_CHARSET((char *)siguserid));
1.1.1.3   root     1537:                                        if (sigstatus >= 0)
                   1538:                                        {       if (options & CHECK_NEW && trustpos > 0)
                   1539:                                                        write_trust_pos(f, sigtrust|KC_SIG_CHECKED, trustpos);
                   1540:                                        }
                   1541:                                        else
1.1.1.2   root     1542:                                        {       fprintf(pgpout,"                               ");
                   1543:                                                fprintf(pgpout,PSTR("\007***** BAD SIGNATURE! *****\n"));
                   1544:                                                if (!failed)
                   1545:                                                {       /* first bad signature: create scratch file */
                   1546:                                                        tempring = tempfile(TMP_TMPDIR);
                   1547:                                                        fixedf = fopen(tempring, FOPWBIN);
                   1548:                                                        failed = TRUE;
                   1549:                                                }
                   1550:                                                if (fixedf != NULL)
                   1551:                                                {
                   1552:                                                        copyfilepos(f, fixedf, fpsig - fixpos, fixpos);
                   1553:                                                        fseek(f, fpsig+sigpktlen, SEEK_SET);
                   1554:                                                        if (nextkeypacket(f, &ctb) < 0 || ctb != CTB_KEYCTRL)
                   1555:                                                                fseek(f, fpsig+sigpktlen, SEEK_SET);
                   1556:                                                        fixpos = ftell(f);
                   1557:                                                }
                   1558:                                        }
                   1559:                                }
                   1560:                        } /* checking a signature */
                   1561:                }       /* if it has mcguffin */
                   1562:        }       /* loop for all packets */
                   1563: 
1.1.1.3   root     1564:        close_more();
                   1565:        if (status < -1)
                   1566:        {
                   1567:                fclose(f);
                   1568:                return status;
                   1569:        }
                   1570:        fputc('\n',pgpout);
1.1.1.2   root     1571: 
                   1572:        if (failed)
                   1573:        {
                   1574:                copyfilepos(f, fixedf, -1L, fixpos);
                   1575:                if (write_error(fixedf))
                   1576:                {       fclose(fixedf);
                   1577:                        fclose(f);
                   1578:                        return -1;
                   1579:                }
                   1580:                fclose(fixedf);
1.1.1.3   root     1581:                if (!batchmode)
                   1582:                        fprintf(pgpout, PSTR("Remove bad signatures (Y/n)? "));
                   1583:                if (batchmode || getyesno('y'))
1.1.1.2   root     1584:                {
                   1585:                        savetempbak(tempring, ringfile);
                   1586:                        failed = 0;
                   1587:                }
                   1588:        }
                   1589:        fclose(f);      /* close key file */
                   1590: 
                   1591:        return(failed?-1:0);    /* normal return */
                   1592: 
                   1593: }      /* dokeycheck */
                   1594: 
                   1595: int backup_rename(char *scratchfile, char *destfile)
                   1596: {      /* rename scratchfile to destfile after making a backup file */
                   1597:        char bakfile[MAX_PATH];
                   1598: 
                   1599:        if (is_tempfile(destfile))
                   1600:        {
                   1601:                remove(destfile);
                   1602:        }
                   1603:        else
                   1604:        {       if (file_exists(destfile))
                   1605:                {
                   1606:                        strcpy(bakfile, destfile);
                   1607:                        force_extension(bakfile, BAK_EXTENSION);
                   1608:                        remove(bakfile);
                   1609:                        rename(destfile, bakfile);
                   1610:                }
                   1611:        }
                   1612:        return(rename2(scratchfile, destfile));
                   1613: }
                   1614: 
                   1615: int remove_sigs(char *mcguffin, char*ringfile)
                   1616: /* Lists all signatures for keys with specified mcguffin string, and asks
                   1617:  * if they should be removed.
                   1618:  */
                   1619: {      FILE *f, *g;
                   1620:        byte ctb;
1.1.1.3   root     1621:        long fp, fpuser;
                   1622:        int packetlength;
1.1.1.2   root     1623:        int status;
                   1624:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1625:        byte sigkeyID[KEYFRAGSIZE];
                   1626:        byte userid[256];               /* key certificate userid */
                   1627:        char dfltring[MAX_PATH];
                   1628:        word32 tstamp;
                   1629:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1630:        int nsigs = 0, nremoved = 0;
                   1631:        int keeping;
                   1632:        char *scratchf;
                   1633: 
                   1634:        /* Default keyring to check signature ID's */
                   1635:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1636: 
                   1637:        if (!mcguffin  ||  strlen(mcguffin) == 0)
                   1638:                return(-1);
                   1639: 
                   1640:        setoutdir(ringfile);
                   1641:        scratchf = tempfile(0);
                   1642: 
                   1643:        strcpy((char *)userid,mcguffin);
                   1644: 
                   1645:        fprintf(pgpout,PSTR("\nRemoving signatures from userid '%s' in key ring '%s'\n"),
                   1646:                                LOCAL_CHARSET(mcguffin), ringfile);
                   1647: 
1.1.1.3   root     1648:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e);
1.1.1.2   root     1649:        if (status < 0)
                   1650:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile);
                   1651:                return(0);      /* normal return */
                   1652:        }
                   1653: 
                   1654:        strcpy((char *)userid,mcguffin);
                   1655:        getpubuserid (ringfile, fp, userid, &fpuser, &packetlength, FALSE);
                   1656:        packetlength += ( int ) ( fpuser - fp );
                   1657: 
                   1658:        /* open file f for read, in binary (not text) mode...*/
                   1659:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1660:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1661:                return(-1);
                   1662:        }
                   1663: 
                   1664:        /* Count signatures */
                   1665:        fseek (f, fp+packetlength, SEEK_SET);
                   1666:        for ( ; ; )
                   1667:        {       status = nextkeypacket(f, &ctb);
                   1668:                if (status < 0  ||  is_key_ctb(ctb)  ||  ctb==CTB_USERID)
                   1669:                        break;
                   1670:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
                   1671:                        ++nsigs;
                   1672:        }
                   1673:                
                   1674:        rewind(f);
                   1675: 
                   1676:        if (nsigs == 0)
                   1677:        {       fprintf (pgpout,PSTR("\nKey has no signatures to remove.\n"));
                   1678:                fclose (f);
                   1679:                return (0);             /* Normal return */
                   1680:        }
                   1681: 
                   1682:        fprintf (pgpout, PSTR("\nKey has %d signature(s):\n"), nsigs);
                   1683: 
                   1684:        /* open file g for writing, in binary (not text) mode...*/
                   1685:        if ((g = fopen(scratchf,FOPWBIN)) == NULL)
                   1686:        {       fclose(f);
                   1687:                return(-1);
                   1688:        }
                   1689:        copyfile(f,g,fp+packetlength);  /* copy file f to g up through key */
                   1690: 
                   1691:        /* Now print out any following sig certs */
                   1692:        keeping = 1;
                   1693:        for ( ; ; )
                   1694:        {       fp = ftell(f);
                   1695:                status = readkeypacket(f, FALSE, &ctb, NULL, NULL, NULL, NULL,
                   1696:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1697:                packetlength = ( int ) ( ftell(f) - fp ); 
                   1698:                if ((status < 0 && status != -6 && status != -4) ||
                   1699:                                is_key_ctb(ctb)  ||  ctb==CTB_USERID)
                   1700:                        break;
                   1701:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
                   1702:                {       fprintf(pgpout,"sig%c     ", status < 0 ? '?' : ' ');
                   1703:                        if (status < 0)
                   1704:                                memset(sigkeyID, 0, KEYFRAGSIZE);
                   1705:                        showkeyID(sigkeyID);
                   1706:                        fprintf(pgpout,"               "); /* Indent signator userid */
1.1.1.3   root     1707:                        if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, sigkeyID,
                   1708:                                        timestamp, userid, n, e)>=0 ||
                   1709:                                getpublickey(GPK_GIVEUP, dfltring, NULL, NULL, sigkeyID,
                   1710:                                        timestamp, userid, n, e)>=0)
1.1.1.2   root     1711:                        {       PascalToC((char *)userid);
                   1712:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid));
                   1713:                        }
                   1714:                        else
                   1715:                                fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
                   1716:                        fprintf(pgpout, PSTR("Remove this signature (y/N)? "));
                   1717:                        if (!(keeping=!getyesno('n')))
                   1718:                                ++nremoved;
                   1719:                }
                   1720:                if (keeping)
                   1721:                        copyfilepos (f, g, (long) packetlength, fp);
                   1722:        }       /* scanning sig certs */
                   1723:        copyfilepos (f, g, -1L, fp);            /* Copy rest of file */
                   1724: 
                   1725:        fclose(f);      /* close key file */
                   1726:        if (write_error(g))
                   1727:        {       fclose(g);
                   1728:                return -1;
                   1729:        }
                   1730:        fclose(g);      /* close scratch file */
                   1731:        savetempbak(scratchf,ringfile);
                   1732:        if (nremoved == 0)
                   1733:                fprintf(pgpout,PSTR("\nNo key signatures removed.\n"));
                   1734:        else
                   1735:                fprintf(pgpout,PSTR("\n%d key signature(s) removed.\n"), nremoved);
                   1736: 
                   1737:        return(0);      /* normal return */
                   1738: 
                   1739: }      /* remove_sigs */
                   1740: 
                   1741: 
                   1742: int remove_from_keyring(byte *keyID, char *mcguffin, char *ringfile, boolean secring_too)
                   1743: /*     Remove the first entry in key ring that has mcguffin string in userid.
                   1744:        Or it removes the first matching keyID from the ring.
                   1745:        A non-NULL keyID takes precedence over a mcguffin specifier.
                   1746:        mcguffin is a null-terminated C string.
                   1747:        If secring_too is TRUE, the secret keyring is also checked.
                   1748: */
                   1749: {
                   1750:        FILE *f;
                   1751:        FILE *g;
                   1752:        long fp, nfp;
                   1753:        int packetlength;
                   1754:        byte ctb;
                   1755:        int status;
                   1756:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1757:        byte userid[256];               /* key certificate userid */
                   1758:        word32 tstamp; byte *timestamp = (byte *) &tstamp;              /* key certificate timestamp */
                   1759:        int userids;
                   1760:        boolean rmuserid = FALSE;
                   1761:        char *scratchf;
                   1762: 
                   1763:        default_extension(ringfile,PGP_EXTENSION);
                   1764: 
                   1765:        if ((keyID==NULL) && (!mcguffin  ||  strlen(mcguffin)==0))
                   1766:                return(-1); /* error, null mcguffin will match everything */
                   1767: 
                   1768: top:
                   1769:        if (mcguffin)
                   1770:                strcpy((char *)userid,mcguffin);
                   1771: 
                   1772:        fprintf(pgpout,PSTR("\nRemoving from key ring: '%s'"),ringfile);
                   1773:        if (mcguffin  &&  strlen(mcguffin) > 0)
                   1774:                fprintf(pgpout,PSTR(", userid \"%s\".\n"),
                   1775:                        LOCAL_CHARSET(mcguffin));
                   1776: 
1.1.1.3   root     1777:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e);
1.1.1.2   root     1778:        if (status < 0 && status != -4 && status != -6)
                   1779:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile);
                   1780:                return(0);      /* normal return */
                   1781:        }
                   1782: 
                   1783:        /* Now add to packetlength the subordinate following certificates */
                   1784:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1785:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1786:                return(-1);
                   1787:        }
                   1788:        fseek (f, fp+packetlength, SEEK_SET);
                   1789:        userids = 0;
                   1790:        do      /* count user ID's, position nfp at next key */
                   1791:        {       nfp = ftell(f);
                   1792:                status = nextkeypacket(f, &ctb);
                   1793:                if (status == 0 && ctb == CTB_USERID)
                   1794:                        ++userids;
                   1795:        } while (status == 0 && !is_key_ctb(ctb));
                   1796:        if (status < -1)
                   1797:        {       fclose(f);
                   1798:                return(-1);
                   1799:        }
                   1800: 
                   1801:        if (keyID==NULL)        /* Human confirmation is required. */
                   1802:        {       /* Supposedly the key was fully displayed by getpublickey */
                   1803:                if (userids > 1)
                   1804:                {       fprintf(pgpout, PSTR("\nKey has more than one user ID.\n\
                   1805: Do you want to remove the whole key (y/N)? "));
                   1806:                        if (!getyesno('n'))
                   1807:                        {       /* find out which userid should be removed */
                   1808:                                rmuserid = TRUE;
                   1809:                                fseek (f, fp+packetlength, SEEK_SET);
                   1810:                                for ( ; ; )
                   1811:                                {       fp = ftell(f);
                   1812:                                        status = readkpacket(f, &ctb, (char *) userid, NULL, NULL);
                   1813:                                        if (status < 0 && status != -4 && status != -6 || is_key_ctb(ctb))
                   1814:                                        {       fclose(f);
                   1815:                                                fprintf(pgpout, PSTR("\nNo more user ID's\n"));
                   1816:                                                return(-1);
                   1817:                                        }
                   1818:                                        if (ctb == CTB_USERID)
                   1819:                                        {       fprintf(pgpout, PSTR("Remove \"%s\" (y/N)? "), userid);
                   1820:                                                if (getyesno('n'))
                   1821:                                                        break;
                   1822:                                        }
                   1823:                                }
                   1824:                                do      /* also remove signatures and trust bytes */
                   1825:                                {       nfp = ftell(f);
                   1826:                                        status = nextkeypacket(f, &ctb);
                   1827:                                } while ((status == 0 || status == -4 || status == -6) &&
                   1828:                                                !is_key_ctb(ctb) && ctb != CTB_USERID);
                   1829:                                if (status < -1 && status != -4 && status != -6)
                   1830:                                {       fclose(f);
                   1831:                                        return(-1);
                   1832:                                }
                   1833:                        }
                   1834:                }
1.1.1.3   root     1835:                else if (!force_flag)   /* only one user ID */
1.1.1.2   root     1836:                {       fprintf(pgpout,
                   1837:                                PSTR("\nAre you sure you want this key removed (y/N)? "));
                   1838:                        if (!getyesno('n'))
                   1839:                        {       fclose(f);
                   1840:                                return(-1);     /* user said "no" */
                   1841:                        }
                   1842:                }
                   1843:        }
                   1844:        fclose(f);
                   1845:        packetlength = ( int ) ( nfp - fp );
                   1846: 
                   1847:        /* open file f for read, in binary (not text) mode...*/
                   1848:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1849:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1850:                return(-1);
                   1851:        }
                   1852: 
                   1853:        setoutdir(ringfile);
                   1854:        scratchf = tempfile(0);
                   1855:        /* open file g for writing, in binary (not text) mode...*/
                   1856:        if ((g = fopen(scratchf,FOPWBIN)) == NULL)
                   1857:        {       fclose(f);
                   1858:                return(-1);
                   1859:        }
                   1860:        copyfilepos(f,g,fp,0L); /* copy file f to g up to position fp */
                   1861:        copyfilepos(f,g,-1L,fp+packetlength); /* copy rest of file f */
                   1862:        fclose(f);      /* close key file */
                   1863:        if (write_error(g))
                   1864:        {       fclose(g);
                   1865:                return -1;
                   1866:        }
                   1867:        fclose(g);      /* close scratch file */
1.1.1.3   root     1868:        if (secring_too) /* TRUE if this is the public keyring */
                   1869:                maint_update(scratchf);
1.1.1.2   root     1870:        savetempbak(scratchf,ringfile);
                   1871:        if (rmuserid)
                   1872:                fprintf(pgpout,PSTR("\nUser ID removed from key ring.\n"));
                   1873:        else
                   1874:                fprintf(pgpout,PSTR("\nKey removed from key ring.\n"));
                   1875:        
                   1876:        if (secring_too)
                   1877:        {       secring_too = FALSE;
                   1878:                buildfilename(ringfile, SECRET_KEYRING_FILENAME);
                   1879:                strcpy((char *)userid,mcguffin);
1.1.1.3   root     1880:                if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, NULL, timestamp, userid, n, e) == 0)
1.1.1.2   root     1881:                {       fprintf(pgpout, PSTR("\nKey or user ID is also present in secret keyring.\n\
                   1882: Do you also want to remove it from the secret keyring (y/N)? "));
                   1883:                        if (getyesno('n'))
                   1884:                                goto top;
                   1885:                }
                   1886:        }
                   1887: 
                   1888:        return(0);      /* normal return */
                   1889: 
                   1890: }      /* remove_from_keyring */
                   1891: 
                   1892: 
                   1893: int extract_from_keyring (char *mcguffin, char *keyfile, char *ringfile,
                   1894:                                boolean transflag)
                   1895: /*     Copy the first entry in key ring that has mcguffin string in
                   1896:        userid and put it into keyfile.
                   1897:        mcguffin is a null-terminated C string.
                   1898: */
                   1899: {
                   1900:        FILE *f;
                   1901:        FILE *g;
1.1.1.3   root     1902:        long fp;
                   1903:        int packetlength=0;
1.1.1.2   root     1904:        byte ctb;
1.1.1.3   root     1905:        byte keyctrl;
1.1.1.2   root     1906:        int status;
                   1907:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1908:        byte keyID[KEYFRAGSIZE];
                   1909:        byte userid[256];       /* key certificate userid */
                   1910:        char fname[MAX_PATH], transfile[MAX_PATH], transname[MAX_PATH];
1.1.1.3   root     1911:        char *tempf = NULL;
1.1.1.2   root     1912:        word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key cert tstamp */
                   1913:        boolean append = FALSE;
                   1914:        boolean whole_ring = FALSE;
                   1915: 
                   1916:        default_extension(ringfile, PGP_EXTENSION);
                   1917: 
                   1918:        if (!mcguffin  ||  strlen(mcguffin)==0 || strcmp(mcguffin, "*") == 0)
                   1919:                whole_ring = TRUE;
                   1920: 
                   1921:        /* open file f for read, in binary (not text) mode...*/
                   1922:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1923:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1924:                return(-1);
                   1925:        }
                   1926: 
                   1927:        if (!whole_ring)
                   1928:        {
                   1929:                strcpy((char *)userid, mcguffin);
                   1930:                fprintf(pgpout,PSTR("\nExtracting from key ring: '%s'"),ringfile);
                   1931:                fprintf(pgpout,PSTR(", userid \"%s\".\n"),LOCAL_CHARSET(mcguffin));
                   1932: 
1.1.1.3   root     1933:                status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL,
1.1.1.2   root     1934:                                        timestamp, userid, n, e);
                   1935:                if (status < 0 && status != -4 && status != -6)
                   1936:                {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),
                   1937:                                                                        ringfile);
                   1938:                        fclose(f);
1.1.1.3   root     1939:                        return(1);      /* non-normal return */
1.1.1.2   root     1940:                }
                   1941:                extract_keyID(keyID, n);
                   1942:        }
                   1943:        else
                   1944:        {
                   1945:                do      /* set fp to first key packet */
                   1946:                        fp = ftell(f);
                   1947:                while ((status = nextkeypacket(f, &ctb)) >= 0 && !is_key_ctb(ctb));
                   1948:                if (status < 0)
                   1949:                {       fclose(f);
                   1950:                        return(-1);
                   1951:                }
                   1952:                packetlength = ( int ) ( ftell(f) - fp );
                   1953:        }
                   1954: 
                   1955:        if (!keyfile  ||  strlen(keyfile)==0)
                   1956:        {       fprintf(pgpout, PSTR("\nExtract the above key into which file? "));
1.1.1.3   root     1957:                if (batchmode)
                   1958:                        return -1;
1.1.1.2   root     1959:                getstring( fname, sizeof(fname)-4, TRUE );
                   1960:                if (*fname == '\0')
                   1961:                        return(-1);
                   1962:        }
                   1963:        else
                   1964:                strcpy(fname,keyfile);
                   1965:        default_extension(fname,PGP_EXTENSION);
                   1966: 
                   1967:        /* If transport armoring, use a dummy file for keyfile */
                   1968:        if (transflag)
                   1969:        {       strcpy(transname, fname);
                   1970:                strcpy(transfile, fname);
                   1971:                force_extension(transfile, ASC_EXTENSION);
                   1972:                tempf = tempfile(TMP_TMPDIR|TMP_WIPE);
                   1973:                strcpy(fname, tempf);
                   1974:        }
                   1975:        if (file_exists( transflag?transfile:fname ))
                   1976:        {
                   1977:                if (!transflag && !whole_ring)
                   1978:                {       /* see if the key is already present in fname */
1.1.1.3   root     1979:                        status = getpublickey(GPK_GIVEUP, fname, NULL, NULL, keyID,
                   1980:                                        timestamp, userid, n, e);
1.1.1.2   root     1981:                        if (status >= 0 || status == -4 || status == -6)
                   1982:                        {       fclose(f);
                   1983:                                fprintf(pgpout,PSTR("Key ID %s is already included in key ring '%s'.\n"),
                   1984:                                        keyIDstring(keyID), fname);
                   1985:                                return(-1);
                   1986:                        }
                   1987:                }
                   1988:                if (whole_ring || transflag || status < -1)
1.1.1.3   root     1989:                {       if (!is_tempfile(fname) && !force_flag) 
                   1990:                                /* Don't ask this for mailmode or for 
                   1991:                                 * a tempfile, since its ok.
                   1992:                                 */
                   1993:                        { /* if status < -1 then fname is not a keyfile, ask if it should be overwritten */
                   1994:                                fprintf(pgpout,PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "),
                   1995:                                        transflag?transfile:fname);
                   1996:                                if (!getyesno( 'n' ))
                   1997:                                {       fclose(f);
                   1998:                                        return(-1);     /* user chose to abort */
                   1999:                                }
1.1.1.2   root     2000:                        }
                   2001:                }
                   2002:                else
                   2003:                        append = TRUE;
                   2004:        }
                   2005: 
                   2006:        if (append)
                   2007:                g = fopen(fname, FOPRWBIN);
                   2008:        else
                   2009:                g = fopen(fname, FOPWBIN);
                   2010:        if (g == NULL)
                   2011:        {       if (append)
                   2012:                        fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   2013:                else
                   2014:                        fprintf(pgpout,PSTR("\n\007Unable to create key file '%s'.\n"), fname);
                   2015:                fclose(f);
                   2016:                return(-1);
                   2017:        }
                   2018:        if (append)
                   2019:                fseek(g, 0L, SEEK_END);
                   2020:        do
1.1.1.3   root     2021:        {       /* file f is positioned right after key packet */
                   2022:                if (whole_ring && read_trust(f, &keyctrl) == 0
                   2023:                        && (keyctrl & KC_DISABLED))
                   2024:                {
                   2025:                        do      /* skip this key */
                   2026:                        {
                   2027:                                fp = ftell(f);
                   2028:                                status = nextkeypacket(f, &ctb);
                   2029:                                packetlength = ( int ) ( ftell(f) - fp );
                   2030:                        }
                   2031:                        while (!is_key_ctb(ctb) && status >= 0);
                   2032:                        continue;
                   2033:                }
1.1.1.2   root     2034:                if (copyfilepos(f, g, (long) packetlength, fp) < 0)     /* Copy key out */
                   2035:                {       status = -2;
                   2036:                        break;
                   2037:                }
                   2038:                /* Copy any following signature or userid packets */
                   2039:                for ( ; ; )
                   2040:                {       fp = ftell(f);
                   2041:                        status = nextkeypacket(f, &ctb);
                   2042:                        packetlength = ( int ) ( ftell(f) - fp );
                   2043:                        if (status < 0  ||  is_key_ctb(ctb))
                   2044:                                break;
                   2045:                        if (ctb==CTB_USERID  ||  is_ctb_type(ctb,CTB_SKE_TYPE))
                   2046:                                if (copyfilepos(f, g, (long) packetlength, fp) < 0)
                   2047:                                {       status = -2;
                   2048:                                        break;
                   2049:                                }
                   2050:                }
                   2051:        }
                   2052:        while (whole_ring && status >= 0);
                   2053: 
                   2054:        fclose(f);
                   2055:        if (status < -1 || write_error(g))
                   2056:        {       fclose(g);
                   2057:                return(-1);
                   2058:        }
                   2059:        fclose(g);
                   2060: 
                   2061:        if (transflag)
                   2062:        {       status = armor_file (fname, transfile, transname, NULL);
                   2063:                rmtemp (tempf);
                   2064:                if (status)
                   2065:                        return(-1);
                   2066:        }
                   2067: 
                   2068:        fprintf (pgpout,PSTR("\nKey extracted to file '%s'.\n"), transflag?transfile:fname);
                   2069: 
                   2070:        return (0);     /* normal return */
                   2071: }      /* extract_from_keyring */
                   2072: 
                   2073: 
                   2074: /*======================================================================*/
                   2075: 
1.1.1.3   root     2076: static int merge_key_to_ringfile(char *keyfile, char* ringfile, long fp,
1.1.1.2   root     2077:                                int packetlength, long keylen)
                   2078: /* Copy the key data in keyfile into ringfile, replacing the data that
                   2079:    is in ringfile starting at fp and for length packetlength.
                   2080:    keylen is the number of bytes to copy from keyfile
                   2081: */
                   2082: {      FILE    *f, *g, *h;
                   2083:        char *tempf;
                   2084:        int rc;
                   2085: 
                   2086:        setoutdir(ringfile);
                   2087:        tempf = tempfile(TMP_WIPE);
                   2088:        /* open file f for reading, binary, as keyring file */
                   2089:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   2090:                return(-1);
                   2091:        /* open file g for writing, binary, as scratch keyring file */
                   2092:        if ((g = fopen(tempf,FOPWBIN)) == NULL)
                   2093:        {       fclose(f);
                   2094:                return(-1);
                   2095:        }
                   2096:        /* open file h for reading, binary, as key file to be inserted */
                   2097:        if ((h = fopen(keyfile,FOPRBIN)) == NULL)
                   2098:        {       fclose(f);
                   2099:                fclose(g);
                   2100:                return(-1);
                   2101:        }
                   2102:        /* Copy pre-key keyring data from f to g */
                   2103:        copyfile(f,g,fp);
                   2104:        /* Copy temp key data from h to g */
                   2105:        copyfile(h,g,keylen);
                   2106:        /* Copy post-key keyring data from f to g */
                   2107:        copyfilepos(f,g,-1L,fp+packetlength);
                   2108:        fclose(f);
                   2109:        rc = write_error(g);
                   2110:        fclose(g);
                   2111:        fclose(h);
                   2112: 
                   2113:        if (!rc)
                   2114:                savetempbak(tempf,ringfile);
                   2115: 
                   2116:        return(rc ? -1 : 0);
                   2117: }      /* merge_key_to_ringfile */
                   2118: 
                   2119: static int insert_userid(char *keyfile, byte *userid, long fpos)
                   2120: {      /* insert userid and trust byte at position fpos in file keyfile */
                   2121:        char *tmpf;
                   2122:        FILE *f, *g;
                   2123: 
                   2124:        tmpf = tempfile(TMP_TMPDIR);
                   2125:        if ((f = fopen(keyfile, FOPRBIN)) == NULL)
                   2126:                return(-1);
                   2127:        if ((g = fopen(tmpf, FOPWBIN)) == NULL)
                   2128:        {       fclose(f);
                   2129:                return(-1);
                   2130:        }
                   2131:        copyfile(f, g, fpos);
                   2132:        putc(CTB_USERID, g);
                   2133:        fwrite(userid, 1, userid[0]+1, g);
                   2134:        write_trust(g, KC_LEGIT_COMPLETE);
                   2135:        copyfile(f, g, -1L);
                   2136:        fclose(f);
                   2137:        if (write_error(g))
                   2138:        {       fclose(g);
                   2139:                return(-1);
                   2140:        }
                   2141:        fclose(g);
                   2142:        return(savetempbak(tmpf, keyfile));
                   2143: }
                   2144: 
                   2145: int dokeyedit(char *mcguffin, char *ringfile)
                   2146: /*     Edit the userid and/or pass phrase for an RSA key pair, and
                   2147:        put them back into the ring files.
                   2148: */
1.1.1.4 ! root     2149: {      unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION],
        !          2150:                 d[MAX_UNIT_PRECISION], p[MAX_UNIT_PRECISION],
        !          2151:                 q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
1.1.1.2   root     2152:        char *fname, secring[MAX_PATH];
                   2153:        FILE *f;
                   2154:        word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */
                   2155:        byte userid[256];
                   2156:        byte userid1[256];
                   2157:        word32 tstamp; byte *timestamp = (byte *) &tstamp;      /* key certificate timestamp */
                   2158:        byte keyID[KEYFRAGSIZE];
                   2159:        boolean hidekey;        /* TRUE iff secret key is encrypted */
                   2160:        boolean changed=FALSE, changeID=FALSE;
                   2161:        byte ctb;
                   2162:        int status;
                   2163:        long fpp,fps,trust_pos, keylen;
                   2164:        int pplength=0, pslength=0;
                   2165:        byte ideakey[16];
                   2166:        byte keyctrl;
                   2167: 
                   2168:        if (!ringfile || strlen(ringfile)==0 || !mcguffin || strlen(mcguffin)==0)
                   2169:                return(-1);     /* Need ringfile name, user name */
                   2170: 
                   2171:        force_extension(ringfile,PGP_EXTENSION);
                   2172: 
1.1.1.4 ! root     2173:        if (!strncmp( ringfile, SECRET_KEYRING_FILENAME, strlen( SECRET_KEYRING_FILENAME )))
        !          2174:        {
        !          2175:                fprintf(pgpout, PSTR("\nThis operation may not be performed on a secret keyring.\n\
        !          2176: Defaulting to public keyring."));
        !          2177:                buildfilename( ringfile, PUBLIC_KEYRING_FILENAME );
        !          2178:        }
        !          2179: 
1.1.1.2   root     2180:        strcpy((char *)userid, mcguffin);
                   2181:        fprintf(pgpout,PSTR("\nEditing userid \"%s\" in key ring: '%s'.\n"),
                   2182:                LOCAL_CHARSET((char *)userid),ringfile);
                   2183: 
                   2184:        if (!file_exists (ringfile))
                   2185:        {       fprintf(pgpout,PSTR("\nCan't open public key ring file '%s'\n"),
                   2186:                        ringfile);
                   2187:                return(-1);
                   2188:        }
                   2189: 
1.1.1.3   root     2190:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fpp, &pplength, NULL,
1.1.1.2   root     2191:                                timestamp, userid, n, e);
                   2192:        if (status < 0)
                   2193:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),
                   2194:                        ringfile);
                   2195:                return(-1);
                   2196:        }
                   2197: 
                   2198:        /* Now add to pplength any following key control certificate */
                   2199:        if ((f = fopen(ringfile,FOPRWBIN)) == NULL)
                   2200:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   2201:                return(-1);
                   2202:        }
                   2203: 
1.1.1.4 ! root     2204:        if (fread(&ctb, 1, 1, f) != 1 || !is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE))
        !          2205:        {       fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"),ringfile);
        !          2206:                fclose(f);
        !          2207:                return(-1);
        !          2208:        }
        !          2209: 
1.1.1.2   root     2210:        fseek(f, fpp, SEEK_SET);
                   2211:        if (is_compromised(f))
                   2212:        {       fprintf(pgpout, PSTR("\n\007This key has been revoked by its owner.\n"));
                   2213:                fclose(f);
                   2214:                return(-1);
                   2215:        }
                   2216:        trust_pos = fpp+pplength;
                   2217:        fseek(f, trust_pos, SEEK_SET);
                   2218:        if (read_trust(f, &keyctrl) < 0)
                   2219:                trust_pos = -1;         /* keyfile: no trust byte */
                   2220: 
                   2221:        extract_keyID(keyID, n);
                   2222: 
                   2223:        /* Now read private key, too */
                   2224:        strcpy(secring, ringfile);
                   2225:        strcpy(file_tail(secring), SECRET_KEYRING_FILENAME);
                   2226: 
                   2227:        if (!file_exists (secring))
                   2228:        {       fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
                   2229:                        secring);
                   2230:                fclose(f);
                   2231:                return(-1);
                   2232:        }
                   2233: 
                   2234:        /* Get position of key in secret key file */
1.1.1.3   root     2235:        (void)getpublickey(GPK_GIVEUP, secring, &fps, &pslength, keyID,
1.1.1.2   root     2236:                timestamp, userid1, n, e);
                   2237:        /* This was done to get us fps and pslength */
1.1.1.3   root     2238:        status = getsecretkey(GPK_GIVEUP, secring, keyID, timestamp,
1.1.1.4 ! root     2239:                ideakey, &hidekey, userid1, n, e, d, p, q, u);
1.1.1.2   root     2240: 
                   2241:        if (status < 0)         /* key not in secret keyring: edit owner trust */
                   2242:        {       int i;
                   2243: 
                   2244:                fprintf(pgpout, PSTR("\nNo secret key available.  Editing public key trust parameter.\n"));
                   2245:                if (trust_pos < 0)
                   2246:                {       fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), ringfile);
                   2247:                        fclose(f);
                   2248:                        return(-1);
                   2249:                }
                   2250:                show_key(f, fpp, SHOW_ALL);
                   2251: 
                   2252:                init_trust_lst();
                   2253:                fprintf(pgpout, PSTR("Current trust for this key's owner is: %s\n"),
                   2254:                                trust_lst[keyctrl & KC_OWNERTRUST_MASK]);
                   2255: 
                   2256:                PascalToC((char *)userid);      /* convert to C string for display */
                   2257:                i = ask_owntrust((char *) userid, keyctrl);
                   2258:                if (i == (keyctrl & KC_OWNERTRUST_MASK))
                   2259:                {       fclose(f);
                   2260:                        return(0);      /* unchanged */
                   2261:                }
                   2262: 
                   2263:                if (i < 0 || i > KC_OWNERTRUST_ALWAYS)
                   2264:                {
                   2265:                        fclose(f);
                   2266:                        return(-1);
                   2267:                }
                   2268:                keyctrl = (keyctrl & ~KC_OWNERTRUST_MASK) | i;
                   2269: 
                   2270:                fseek(f, trust_pos, SEEK_SET);
                   2271:                write_trust(f, keyctrl);
                   2272:                fclose(f);
                   2273:                fprintf (pgpout, PSTR("Public key ring updated.\n"));
                   2274:                return(0);
                   2275:        }
                   2276:        if (trust_pos > 0 && (keyctrl & (KC_BUCKSTOP|KC_OWNERTRUST_MASK)) !=
                   2277:                        (KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP))
                   2278:        {       /* key is in secret keyring but buckstop is not set */
                   2279:                fprintf(pgpout, PSTR("\nUse this key as an ultimately-trusted introducer (y/N)? "), userid);
                   2280:                if (getyesno('n'))
                   2281:                {       fseek(f, trust_pos, SEEK_SET);
                   2282:                        keyctrl = KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP;
                   2283:                        write_trust(f, keyctrl);
                   2284:                }
                   2285:        }
                   2286: 
                   2287:        /* Show user her ID again to be clear */
                   2288:        PascalToC((char *)userid);
                   2289:        fprintf(pgpout,PSTR("\nCurrent user ID: %s"),
                   2290:                LOCAL_CHARSET((char *)userid));
                   2291:        CToPascal((char *)userid);
                   2292: 
                   2293:        fprintf(pgpout, PSTR("\nDo you want to change your user ID (y/N)? "));
                   2294:        if (getyesno('n'))      /* user said yes */
                   2295:        {       fprintf(pgpout,PSTR("\nEnter the new user ID: "));
                   2296:                getstring((char *)userid,255,TRUE); /* echo keyboard input */
                   2297:                if (userid[0] == '\0')
                   2298:                {       fclose(f);
                   2299:                        return(-1);
                   2300:                }
                   2301:                CONVERT_TO_CANONICAL_CHARSET((char *)userid);
                   2302:                fprintf(pgpout, PSTR("\nMake this user ID the primary user ID for this key (y/N)? "));
                   2303:                if (!getyesno('n'))
                   2304:                {       /* position file pointer at selected user id */
                   2305:                        int pktlen;
                   2306:                        long fpuser;
                   2307: 
                   2308:                        strcpy((char *)userid1, mcguffin);
                   2309:                        if (getpubuserid(ringfile, fpp, userid1, &fpuser, &pktlen, FALSE) < 0)
                   2310:                        {       fclose(f);
                   2311:                                return(-1);
                   2312:                        }
                   2313:                        fseek(f, fpuser, SEEK_SET);
                   2314:                }
1.1.1.4 ! root     2315:                else    /* position file pointer at key packet */
1.1.1.2   root     2316:                        fseek(f, fpp, SEEK_SET);
                   2317:                nextkeypacket(f, &ctb); /* skip userid or key packet */
                   2318:                do      /* new user id will be inserted before next userid or key packet */
                   2319:                {       fpp = ftell(f);
                   2320:                        if (nextkeypacket(f, &ctb) < 0)
                   2321:                                break;
                   2322:                } while (ctb != CTB_USERID && !is_key_ctb(ctb));
                   2323:                CToPascal((char *)userid);          /* convert to length-prefixed string */
                   2324:                changeID = TRUE;
                   2325:                changed = TRUE;
                   2326:        }
                   2327:        fclose(f);
                   2328: 
                   2329:        fprintf (pgpout,PSTR("\nDo you want to change your pass phrase (y/N)? "));
                   2330:        if (getyesno('n'))      /* user said yes */
1.1.1.4 ! root     2331:        {       hidekey = (GetHashedPassPhrase((char *) ideakey, 2) > 0);
1.1.1.2   root     2332:                changed = TRUE;
                   2333:        }
                   2334: 
                   2335:        if (!changed)
                   2336:        {       fprintf (pgpout, PSTR("(No changes will be made.)\n"));
                   2337:                if (hidekey)
1.1.1.4 ! root     2338:                        burn(ideakey);
1.1.1.2   root     2339:                goto done;
                   2340:        }
                   2341: 
                   2342:        /* init CFB IDEA key */
                   2343:        if (hidekey)
                   2344:        {       fill0(iv,8);
                   2345:                initcfb_idea(iv,ideakey,FALSE);
1.1.1.4 ! root     2346:                burn(ideakey);
1.1.1.2   root     2347:        }
                   2348: 
                   2349:        /* First write secret key data to a file */
                   2350:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2351:        writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u);
                   2352:        if (changeID)
                   2353:                keylen = -1;
                   2354:        else
                   2355:        {       /* don't copy userid */
                   2356:                f = fopen(fname, FOPRBIN);
                   2357:                if (f == NULL)
                   2358:                        goto err;
                   2359:                nextkeypacket(f, &ctb); /* skip key packet */
                   2360:                keylen = ftell(f);
                   2361:                fclose(f);
                   2362:        }
                   2363:        if (merge_key_to_ringfile(fname,secring,fps,pslength,keylen) < 0)
                   2364:        {       fprintf (pgpout, PSTR("\n\007Unable to update secret key ring.\n"));
                   2365:                goto err;
                   2366:        }
                   2367:        fprintf (pgpout, PSTR("\nSecret key ring updated...\n"));
                   2368: 
                   2369:        /* Now write public key data to file */
                   2370:        if (changeID)
                   2371:        {
                   2372:                if (insert_userid(ringfile, userid, fpp) < 0)
                   2373:                {       fprintf (pgpout, PSTR("\n\007Unable to update public key ring.\n"));
                   2374:                        goto err;
                   2375:                }
                   2376:                fprintf (pgpout, PSTR("Public key ring updated.\n"));
                   2377:        }
                   2378:        else
                   2379:                fprintf (pgpout, PSTR("(No need to update public key ring)\n"));
                   2380: 
                   2381:        if (hidekey)    /* done with IDEA to protect RSA secret key */
                   2382:                close_idea();
                   2383: 
                   2384:        rmtemp(fname);
                   2385: 
                   2386: done:
                   2387:        mp_burn(d);     /* burn sensitive data on stack */
1.1.1.4 ! root     2388:        mp_burn(p);
        !          2389:        mp_burn(q);
        !          2390:        mp_burn(u);
        !          2391:        mp_burn(e);
        !          2392:        mp_burn(n);
        !          2393:        burn(iv);
1.1.1.2   root     2394: 
                   2395:        return(0);      /* normal return */
                   2396: err:
                   2397:        mp_burn(d);     /* burn sensitive data on stack */
1.1.1.4 ! root     2398:        mp_burn(p);
        !          2399:        mp_burn(q);
        !          2400:        mp_burn(u);
        !          2401:        mp_burn(e);
        !          2402:        mp_burn(n);
        !          2403:        burn(iv);
1.1.1.2   root     2404: 
                   2405:        rmtemp(fname);
                   2406: 
                   2407:        return(-1);     /* error return */
                   2408: 
                   2409: }      /* dokeyedit */
                   2410: 
                   2411: 
1.1.1.3   root     2412: int disable_key(char *keyguffin, char *keyfile)
                   2413: {      
                   2414:        FILE *f;
                   2415:        byte keyctrl;
                   2416:        byte keyID[KEYFRAGSIZE];
                   2417:        byte userid[256];
                   2418:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   2419:        long fp;
                   2420:        int pktlen;
                   2421: 
                   2422:        strcpy((char *)userid, keyguffin);
                   2423:        if (getpublickey(GPK_SHOW|GPK_DISABLED, keyfile, &fp, &pktlen, NULL,
                   2424:                        NULL, userid, n, e) < 0)
                   2425:                return(-1);
                   2426: 
                   2427:        extract_keyID(keyID, n);
                   2428:        if (getsecretkey(GPK_GIVEUP, NULL, keyID, NULL, NULL, NULL,
                   2429:                                         userid, n, e, NULL, NULL, NULL, NULL) >= 0)
                   2430:        {       /* can only compromise if key also in secring */
                   2431:                PascalToC((char *) userid);
                   2432:                fprintf(pgpout, 
                   2433: PSTR("\nDo you want to permanently revoke your public key\n\
                   2434: by issuing a secret key compromise certificate\n\
                   2435: for \"%s\" (y/N)? "), LOCAL_CHARSET((char *)userid));
                   2436:                if (getyesno('n'))
                   2437:                        return compromise(keyID, keyfile);
                   2438:        }
                   2439:        if ((f = fopen(keyfile,FOPRWBIN)) == NULL)
                   2440:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
                   2441:                return(-1);
                   2442:        }
                   2443:        fseek(f, fp+pktlen, SEEK_SET);
                   2444:        if (read_trust(f, &keyctrl) < 0)
                   2445:        {
                   2446:                fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), keyfile);
                   2447:                fprintf(pgpout, PSTR("You can only disable keys on your public keyring.\n"));
                   2448:                fclose(f);
                   2449:                return -1;
                   2450:        }
                   2451:        if (keyctrl & KC_DISABLED)
                   2452:        {
                   2453:                fprintf(pgpout, PSTR("\nKey is already disabled.\n\
                   2454: Do you want to enable this key again (y/N)? "));
                   2455:                keyctrl &= ~KC_DISABLED;
                   2456:        }
                   2457:        else
                   2458:        {
                   2459:                fprintf(pgpout, PSTR("\nDisable this key (y/N)? "));
                   2460:                keyctrl |= KC_DISABLED;
                   2461:        }
                   2462:        if (!getyesno('n'))
                   2463:        {       fclose(f);
                   2464:                return -1;
                   2465:        }
                   2466:        write_trust_pos(f, keyctrl, fp+pktlen);
                   2467:        fclose(f);
                   2468:        return 0;
                   2469: }      /* disable_key */
                   2470: 
                   2471: 
1.1.1.2   root     2472: /*======================================================================*/
                   2473: 
                   2474: 
                   2475: 
                   2476: int dokeygen(char *numstr, char *numstr2)
                   2477: /*     Do an RSA key pair generation, and write them out to the keyring files.
                   2478:        numstr is a decimal string, the desired bitcount for the modulus n.
                   2479:        numstr2 is a decimal string, the desired bitcount for the exponent e.
                   2480: */
                   2481: {      unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION],
                   2482:                 p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
                   2483:        char *fname;
                   2484:        char ringfile[MAX_PATH];
                   2485:        word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */
                   2486:        byte userid[256];
                   2487:        short keybits,ebits;
                   2488:        word32 tstamp; byte *timestamp = (byte *) &tstamp;              /* key certificate timestamp */
                   2489:        boolean hidekey;        /* TRUE iff secret key is encrypted */
1.1.1.3   root     2490:        boolean seedfileexists; /* FALSE if we need to create one */
1.1.1.2   root     2491:        byte ideakey[16];
                   2492: 
                   2493:        if (!numstr || strlen(numstr)==0)
                   2494:        {       fprintf(pgpout,PSTR("\nPick your RSA key size:\
                   2495: \n     1)       384 bits- Casual grade, fast but less secure\
                   2496: \n     2)       512 bits- Commercial grade, medium speed, good security\
                   2497: \n     3)      1024 bits- Military grade, very slow, highest security\
                   2498: \nChoose 1, 2, or 3, or enter desired number of bits: "));
                   2499:                numstr = (char *)userid;        /* use userid buffer as scratchpad */
                   2500:                getstring(numstr,5,TRUE);       /* echo keyboard */
                   2501:        }
                   2502: 
                   2503:        keybits = 0;
                   2504:        while ((*numstr>='0') && (*numstr<='9'))
                   2505:                keybits = keybits*10 + (*numstr++ - '0');
                   2506: 
                   2507:        if (keybits==0) /* user entered null response */
                   2508:                return(-1);     /* error return */
                   2509: 
                   2510:        /* Standard default key sizes: */
                   2511:        if (keybits==1) keybits=384;    /* Casual grade */
                   2512:        if (keybits==2) keybits=512;    /* Commercial grade */
                   2513:        if (keybits==3) keybits=1024;   /* Military grade */
                   2514: 
                   2515: #ifndef DEBUG
                   2516:        /* minimum RSA keysize: */
1.1.1.4 ! root     2517:        if (keybits < 384) keybits=384;
        !          2518:        if (keybits > MAX_BIT_PRECISION-UNITSIZE)       /* Paranoia */
        !          2519:                keybits = MAX_BIT_PRECISION-UNITSIZE;
        !          2520: #else
        !          2521:        if (keybits > MAX_BIT_PRECISION)
        !          2522:                keybits = MAX_BIT_PRECISION;
1.1.1.2   root     2523: #endif
                   2524: 
1.1.1.4 ! root     2525: #ifdef notdef  /* This annoys everyone, so take it out. */
1.1.1.2   root     2526: /*     If we use Merritt's modmult algorithm, the primes p and q's 
                   2527:        bit length should not be an exact multiple of UNITSIZE, 
                   2528:        because Merritt's modmult algorithm performs slowest in that 
                   2529:        case, wasting an extra unit of precision for overflow.
                   2530: */
                   2531:        if ((keybits % (2*UNITSIZE))==0)
                   2532:                keybits -= 2;   /* make each prime one bit shorter. */
                   2533: #endif /* MERRITT */
                   2534: 
                   2535:        ebits = 0;      /* number of bits in e */
                   2536:        while ((*numstr2>='0') && (*numstr2<='9')) 
                   2537:                ebits = ebits*10 + (*numstr2++ - '0');
                   2538: 
                   2539:        fprintf(pgpout,PSTR("\nGenerating an RSA key with a %d-bit modulus... "),keybits);
                   2540: 
                   2541:        fprintf(pgpout,
                   2542: PSTR("\nYou need a user ID for your public key.  The desired form for this\n\
                   2543: user ID is your name, followed by your E-mail address enclosed in\n\
                   2544: <angle brackets>, if you have an E-mail address.\n\
                   2545: For example:  John Q. Smith <[email protected]>\n"));
                   2546:        fprintf(pgpout,PSTR("\nEnter a user ID for your public key: \n"));
1.1.1.3   root     2547: #ifdef VMS
                   2548:        putch('\n'); /* That last newline was just a return, do a real one */
                   2549: #endif
1.1.1.2   root     2550:        getstring((char *)userid,255,TRUE);     /* echo keyboard input */
                   2551:        if (userid[0]=='\0')    /* user entered null response */
                   2552:                return(-1);     /* error return */
                   2553:        CONVERT_TO_CANONICAL_CHARSET((char *)userid);
                   2554:        CToPascal((char *)userid);      /* convert to length-prefixed string */
                   2555: 
1.1.1.4 ! root     2556:        {       fprintf(pgpout,
1.1.1.2   root     2557: PSTR("\nYou need a pass phrase to protect your RSA secret key.\n\
                   2558: Your pass phrase can be any sentence or phrase and may have many\n\
                   2559: words, spaces, punctuation, or any other printable characters. "));
1.1.1.4 ! root     2560:                hidekey = (GetHashedPassPhrase((char *) ideakey, 2) > 0);
1.1.1.2   root     2561:                /* init CFB IDEA key */
                   2562:                if (hidekey)
                   2563:                {       fill0(iv,8);
                   2564:                        initcfb_idea(iv,ideakey,FALSE);
1.1.1.3   root     2565:                        randaccum_later(64);    /* IV for encryption */
1.1.1.2   root     2566:                }
                   2567:        }
1.1.1.3   root     2568: /* As rsa_keygen does a major accumulation of random bits, if we need
                   2569:    any others for a seed file, let's get them at the same time. */
                   2570:        seedfileexists = seedfile_exists();
1.1.1.2   root     2571: 
                   2572:        fprintf(pgpout,PSTR("\nNote that key generation is a VERY lengthy process.\n"));
                   2573: 
                   2574:        if (rsa_keygen(n,e,d,p,q,u,keybits,ebits) < 0)
                   2575:        {       fprintf(pgpout,PSTR("\n\007Keygen failed!\n"));
                   2576:                return(-1);     /* error return */
                   2577:        }
                   2578: 
                   2579:        if (verbose)
                   2580:        {
                   2581:                fprintf(pgpout,PSTR("Key ID %s\n"), key2IDstring(n));
                   2582: 
                   2583:                mp_display(" modulus n = ",n);
                   2584:                mp_display("exponent e = ",e);
                   2585: 
                   2586:                mp_display("exponent d = ",d);
                   2587:                mp_display("   prime p = ",p);
                   2588:                mp_display("   prime q = ",q);
                   2589:                mp_display(" inverse u = ",u);
                   2590:        }
                   2591: 
                   2592:        get_timestamp(timestamp);       /* Timestamp when key was generated */
                   2593: 
                   2594:        fputc('\007',pgpout);  /* sound the bell when done with lengthy process */
                   2595:        fputc('\n',pgpout);
                   2596: 
                   2597:        /* First, write out the secret key... */
                   2598:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2599:        writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u); 
                   2600:        buildfilename(ringfile,SECRET_KEYRING_FILENAME);
                   2601:        if (file_exists(ringfile))
                   2602:        {       merge_key_to_ringfile(fname,ringfile,0L,0,-1L);
                   2603:                rmtemp(fname);
                   2604:        }
                   2605:        else
                   2606:                savetemp(fname, ringfile);
                   2607: 
                   2608:        /* Second, write out the public key... */
                   2609:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2610:        writekeyfile(fname,FALSE,timestamp,userid,n,e,NULL,NULL,NULL,NULL);
                   2611:        buildfilename(ringfile,PUBLIC_KEYRING_FILENAME);
                   2612:        if (file_exists(ringfile))
                   2613:        {       merge_key_to_ringfile(fname,ringfile,0L,0,-1L);
                   2614:                rmtemp(fname);
                   2615:        }
                   2616:        else
                   2617:                savetemp(fname, ringfile);
                   2618:        
                   2619:        if (hidekey)    /* done with IDEA to protect RSA secret key */
                   2620:                close_idea();
                   2621: 
                   2622:        mp_burn(d);     /* burn sensitive data on stack */
                   2623:        mp_burn(p);     /* burn sensitive data on stack */
                   2624:        mp_burn(q);     /* burn sensitive data on stack */
                   2625:        mp_burn(u);     /* burn sensitive data on stack */
                   2626:        mp_burn(e);     /* burn sensitive data on stack */
                   2627:        mp_burn(n);     /* burn sensitive data on stack */
                   2628:        burn(iv);       /* burn sensitive data on stack */
                   2629: 
                   2630:        fprintf(pgpout,PSTR("\007Key generation completed.\n"));
                   2631: 
1.1.1.3   root     2632:        /*      If we need a seed file, create it now.
1.1.1.2   root     2633:        */
1.1.1.3   root     2634:        if (!seedfileexists)
                   2635:                create_seedfile();
1.1.1.2   root     2636: 
                   2637:        return(0);      /* normal return */
                   2638: }      /* dokeygen */
                   2639: 

unix.superglobalmegacorp.com

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