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

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.2   root      872:        byte *timestamp, char *passp, boolean *hkey,
                    873:        byte *userid, unitptr n, unitptr e, unitptr d, unitptr p, unitptr q,
                    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
                    882:        default.  passp and hkey, if non-NULL, get returned with a copy
                    883:        of the pass phrase and hidekey variables.
                    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;
                    891:        boolean hidekey = FALSE;        /* TRUE iff secret key is encrypted */
                    892:        char passphrase[256];
                    893:        word16 iv[4];           /* initialization vector for encryption */
                    894:        byte ideakey[16];
                    895:        int guesses = 3;
                    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: 
                    909:        /* open file f for read, in binary (not text) mode...*/
                    910:        if ((f = fopen(keyfile,FOPRBIN)) == NULL)
                    911:                return(-1);     /* error return */
                    912: 
                    913:        /* First guess is null password, so hidekey is FALSE */
                    914: 
                    915:        do      /* until good password */
                    916:        {       if (hkey != NULL)
                    917:                        *hkey = hidekey;
                    918:                /* Initialize IDEA key */
                    919:                if (hidekey)
                    920:                {       if (passp != NULL)
                    921:                                strcpy (passp, passphrase); /* Save phrase for caller */
                    922:                        fill0(iv,8);
                    923:                        initcfb_idea(iv,ideakey,TRUE);
                    924:                }
                    925:                fseek(f,file_position,SEEK_SET); /* reposition file to key */
                    926:                status = readkeypacket(f,hidekey,&ctb,timestamp,(char *)userid,
                    927:                                                n,e,d,p,q,u,NULL,NULL);
                    928:                if (hidekey)
                    929:                        close_idea();   /* Release resources */
                    930: 
                    931:                burn((byteptr)passphrase);      /* burn sensitive data on stack */
                    932: 
                    933:                if (status == -5)       /* bad pass phrase status */
                    934:                {       if (guesses!=3) /* not first guess of null password? */
                    935:                                fprintf(pgpout,PSTR("\n\007Error:  Bad pass phrase.\n"));
                    936:                        if (!hidekey && *password != '\0')
                    937:                        { /* Try environment variable second */
                    938:                                strncpy (passphrase, password, sizeof(passphrase)-1);
                    939:                                hashpass (passphrase, strlen(passphrase), ideakey);
                    940:                                hidekey = TRUE;
                    941:                                continue;
                    942:                        }
1.1.1.3 ! root      943:                        if (batchmode)
        !           944:                        {       /* PGPPASS (or -z) wrong or not set */
        !           945:                                fprintf(pgpout,PSTR("\n\007Error:  Bad pass phrase.\n"));
        !           946:                                fclose(f);      /* close key file */
        !           947:                                return -1;
        !           948:                        }
1.1.1.2   root      949:                        if (--guesses)  /* not ran out of guesses yet */
                    950:                        {       fprintf(pgpout,PSTR("\nYou need a pass phrase to unlock your RSA secret key. "));
1.1.1.3 ! root      951:                                if (!(flags & GPK_SHOW) && guesses == 2)
1.1.1.2   root      952:                                {       /* let user know for which key he should type his password */
                    953:                                        PascalToC((char *)userid);
                    954:                                        fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n"), 
                    955:                                                LOCAL_CHARSET((char *)userid));
                    956:                                        CToPascal((char *)userid);
                    957:                                }
                    958:                                hidekey = (GetHashedPassPhrase(passphrase, (char *) ideakey, 1) > 0);
1.1.1.3 ! root      959:                                /* Save off this password for future passes.
        !           960:                                 * don't worry -- key signing will DTRT and
        !           961:                                 * not accept this for multiple key siginings
        !           962:                                 *
        !           963:                                 * This should PROBABLY be stored, internally,
        !           964:                                 * as a hashed pass phrase, but thats not how
        !           965:                                 * its done anyways...  sigh.
        !           966:                                 *
        !           967:                                 * Derek Atkins <[email protected]> 93-02-25
        !           968:                                 */
        !           969:                                strncpy(password, passphrase, sizeof(password) - 1);
1.1.1.2   root      970:                                continue;       /* take it from the top */
                    971:                        }       /* more guesses to go */
1.1.1.3 ! root      972:                        else
        !           973:                        {
        !           974:                                fclose(f);      /* close key file */
        !           975:                                return(-5);
        !           976:                        }
1.1.1.2   root      977:                }
1.1.1.3 ! root      978:                if (status < 0 && status != -5)
1.1.1.2   root      979:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                    980:                                keyfile);
                    981:                        fclose(f);      /* close key file */
                    982:                        return(-1);
                    983:                }
                    984:        }       while (status < 0);     /* until key reads OK, with good password */
                    985: 
                    986:        fclose(f);      /* close key file */
                    987: 
                    988:        /* Note that readkeypacket has called set_precision */
                    989: 
                    990:        if (d != NULL)          /* No effective check of pass phrase if d is NULL */
1.1.1.3 ! root      991:        {       
        !           992:                if (!quietmode)
        !           993:                {
        !           994:                        if (!hidekey)
        !           995:                                fprintf(pgpout,PSTR("\nAdvisory warning: This RSA secret key is not protected by a passphrase.\n"));
        !           996:                        else
        !           997:                                fprintf(pgpout,PSTR("Pass phrase is good.  "));
        !           998:                }
1.1.1.2   root      999: 
                   1000:                if (testeq(d,0))        /* didn't get secret key components */
                   1001:                {       fprintf(pgpout,PSTR("\n\007Key file '%s' is not a secret key file.\n"),keyfile);
                   1002:                        return(-1);
                   1003:                }
                   1004:        }
                   1005: 
                   1006:        return(0);      /* normal return */
                   1007: 
                   1008: }      /* getsecretkey */
                   1009: 
                   1010: 
                   1011: int is_compromised(FILE *f)
                   1012: /* check if a key has a compromise certificate, file pointer must
                   1013:    be positioned at or right after the key packet.
                   1014: */
                   1015: {
                   1016:        long pos, savepos;
                   1017:        byte class, ctb;
                   1018:        int cert_len;
                   1019:        int status = 0;
                   1020: 
                   1021:        pos = savepos = ftell(f);
                   1022: 
                   1023:        nextkeypacket(f, &ctb);
                   1024:        if (is_key_ctb(ctb))
                   1025:        {       pos = ftell(f);
                   1026:                nextkeypacket(f, &ctb);
                   1027:        }
                   1028:        if (ctb != CTB_KEYCTRL)
                   1029:                fseek(f, pos, SEEK_SET);
                   1030: 
                   1031:        /* file pointer now positioned where compromise cert. should be */
                   1032:        if (fread(&ctb, 1, 1, f) != 1)
                   1033:        {       status = -1;
                   1034:                goto ex;
                   1035:        }
                   1036:        
                   1037:        if (is_ctb_type(ctb, CTB_SKE_TYPE))
                   1038:        {
                   1039:                cert_len = ( int ) getpastlength(ctb, f);
                   1040:                if (cert_len > MAX_SIGCERT_LENGTH)      /* Huge packet length */
                   1041:                {       status = -1;
                   1042:                        goto ex;
                   1043:                }
                   1044: 
                   1045:                /* skip version and mdlen byte */
                   1046:                fseek(f, 2L, SEEK_CUR);
                   1047:                if (fread(&class, 1, 1, f) != 1)
                   1048:                {       status = -1;
                   1049:                        goto ex;
                   1050:                }
                   1051:                status = (class == KC_SIGNATURE_BYTE);
                   1052:        }
                   1053: ex:
                   1054:        fseek(f, savepos, SEEK_SET);
                   1055:        return(status);
                   1056: }
                   1057: 
                   1058: 
                   1059: /*     Alfred Hitchcock coined the term "mcguffin" for the generic object 
                   1060:        being sought in his films-- the diamond, the microfilm, etc. 
                   1061: */
                   1062: 
                   1063: 
                   1064: /*     Calculate and display a hash for the public components of the key.
                   1065:        The components are converted to their external (big-endian) 
                   1066:        representation, concatenated, and an MD5 on the bit values 
                   1067:        (ie excluding the length value) calculated and displayed in hex.
                   1068: 
                   1069:        The hash, or "fingerprint", of the key is useful mainly for quickly
                   1070:        and easily verifying over the phone that you have a good copy of 
                   1071:        someone's public key.  Just read the hash over the phone and have
                   1072:        them check it against theirs.
                   1073: */
                   1074: 
                   1075: void getKeyHash( byte *hash, unitptr n, unitptr e )
                   1076: {
                   1077:        MD5_CTX mdContext;
                   1078:        byte buffer[ MAX_BYTE_PRECISION + 2 ];
                   1079:        byte mdBuffer[ MAX_BYTE_PRECISION * 2 ];
                   1080:        int i, mdIndex = 0, bufIndex;
                   1081: 
                   1082:        /* Convert n and e to external (big-endian) byte order and move to mdBuffer */
                   1083:        i = reg2mpi( buffer, n );
                   1084:        for( bufIndex = 2; bufIndex < i + 2; bufIndex++ )       /* +2 skips count */
                   1085:                mdBuffer[ mdIndex++ ] = buffer[ bufIndex ];
                   1086:        i = reg2mpi( buffer, e );
                   1087:        for( bufIndex = 2; bufIndex < i + 2; bufIndex++ )       /* +2 skips count */
                   1088:                mdBuffer[ mdIndex++ ] = buffer[ bufIndex ];
                   1089: 
                   1090:        /* Now evaluate the MD5 for the two MPI's */
                   1091:        MD5Init( &mdContext );
                   1092:        MD5Update( &mdContext, mdBuffer, mdIndex );
                   1093:        MD5Final( &mdContext );
                   1094: 
                   1095:        for( i = 0; i < 16; i++ )
                   1096:                hash[i] = mdContext.digest[i];
                   1097: 
                   1098: }      /* getKeyHash */
                   1099: 
                   1100: 
1.1.1.3 ! root     1101: void printKeyHash( byteptr hash, boolean indent )
1.1.1.2   root     1102: {
                   1103:        int i;
                   1104: 
                   1105: /*     Display the hash.  The format is:
                   1106: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1107:           Key fingerprint =  xx xx xx xx xx xx xx xx  xx xx xx xx xx xx xx xx 
                   1108: */
1.1.1.3 ! root     1109:        fprintf( pgpout, "%*s  ", indent ? 27 : 1, PSTR("Key fingerprint =" ) );
1.1.1.2   root     1110:        for( i = 0; i < 8; i++ )
                   1111:                fprintf(pgpout, "%02X ", hash[ i ] );
                   1112:        putc( ' ', pgpout);
                   1113:        for( i = 8; i < 16; i++ )
                   1114:                fprintf(pgpout, "%02X ", hash[ i ] );
                   1115:        putc( '\n', pgpout);
1.1.1.3 ! root     1116: 
        !          1117: }      /* printKeyHash */
        !          1118: 
        !          1119: 
        !          1120: void showKeyHash( unitptr n, unitptr e )
        !          1121: {
        !          1122:        byte hash[16];
        !          1123: 
        !          1124:        getKeyHash(hash,n,e);   /* compute hash of (n,e) */
        !          1125: 
        !          1126:        printKeyHash(hash, TRUE);
1.1.1.2   root     1127: }      /* showKeyHash */
                   1128: 
                   1129: 
                   1130: int view_keyring(char *mcguffin, char *ringfile, boolean show_signatures, boolean show_hashes)
                   1131: /*     Lists all entries in keyring that have mcguffin string in userid.
                   1132:        mcguffin is a null-terminated C string.
                   1133: */
                   1134: {      FILE *f;
1.1.1.3 ! root     1135:        byte ctb, keyctb=0;
1.1.1.2   root     1136:        int status;
                   1137:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1138:        byte keyID[KEYFRAGSIZE];
                   1139:        byte sigkeyID[KEYFRAGSIZE];
                   1140:        byte userid[256];               /* key certificate userid */
1.1.1.3 ! root     1141:        char *siguserid;        /* signator userid */
1.1.1.2   root     1142:        char dfltring[MAX_PATH];
                   1143:        word32 tstamp;
                   1144:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1145:        int keycounter = 0;
                   1146:        int firstuser = 0;
                   1147:        int compromised = 0;
1.1.1.3 ! root     1148:        boolean shownKeyHash=FALSE;
        !          1149:        boolean invalid_key=FALSE;      /* unsupported version or bad data */
1.1.1.2   root     1150:        boolean match = FALSE;
1.1.1.3 ! root     1151:        boolean disabled = FALSE;
1.1.1.2   root     1152: 
                   1153:        /* Default keyring to check signature ID's */
                   1154:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1155: 
                   1156:        /* open file f for read, in binary (not text) mode...*/
                   1157:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1158:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1159:                return(-1);
                   1160:        }
1.1.1.3 ! root     1161:        if (show_signatures)
        !          1162:        {
        !          1163:                setkrent(ringfile);
        !          1164:                setkrent(dfltring);
        !          1165:                init_userhash();
        !          1166:        }
1.1.1.2   root     1167: 
                   1168: /*     Here's a good format for display of key or signature certificates:
                   1169: Type bits/keyID   Date       User ID
                   1170: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1171: sec   512/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1172: sig   384/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1173: */
                   1174: 
                   1175:        if (moreflag)
                   1176:                open_more();
1.1.1.3 ! root     1177:        if (!quietmode)
        !          1178:        {
        !          1179:                fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile);
        !          1180:                if (mcguffin && strlen(mcguffin) > 0)
        !          1181:                        fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin));
        !          1182:        }
1.1.1.2   root     1183:        fprintf(pgpout,PSTR("\nType bits/keyID   Date       User ID\n"));
                   1184:        for ( ; ; )
                   1185:        {
                   1186:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e,
                   1187:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1188:                /* Note that readkeypacket has called set_precision */
                   1189:                if (status== -1)
                   1190:                {       status = 0;
                   1191:                        break;  /* eof reached */
                   1192:                }
                   1193:                if (status == -4 || status == -6)
                   1194:                {       /* only ctb and userid are valid */
                   1195:                        memset(sigkeyID, 0, KEYFRAGSIZE);
                   1196:                        tstamp = 0;
                   1197:                }
                   1198:                else if (status < 0)
                   1199:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                   1200:                                ringfile);
                   1201:                        break;
                   1202:                }
                   1203: 
                   1204:                if (is_key_ctb(ctb))
                   1205:                {
1.1.1.3 ! root     1206:                        byte keyctrl;
        !          1207: 
1.1.1.2   root     1208:                        firstuser = 1;
                   1209:                        keyctb = ctb;
                   1210:                        compromised = is_compromised(f);
                   1211:                        shownKeyHash = FALSE;
                   1212:                        if (status < 0)
                   1213:                        {       invalid_key = TRUE;
                   1214:                                memset(keyID, 0, KEYFRAGSIZE);
                   1215:                        }
                   1216:                        else
                   1217:                        {       invalid_key = FALSE;
                   1218:                                extract_keyID(keyID, n);
1.1.1.3 ! root     1219:                                if (read_trust(f, &keyctrl) == 0 && (keyctrl & KC_DISABLED))
        !          1220:                                        disabled = TRUE;
        !          1221:                                else
        !          1222:                                        disabled = FALSE;
1.1.1.2   root     1223:                        }
                   1224:                }
                   1225: 
                   1226:                if (ctb != CTB_USERID  &&  !is_ctb_type(ctb, CTB_SKE_TYPE))
                   1227:                        continue;
                   1228:                if (ctb == CTB_USERID)
                   1229:                {       PascalToC((char *)userid);
                   1230:                        match = userid_match((char *)userid,mcguffin,n);
                   1231:                }
                   1232:                if (match)
                   1233:                {
                   1234:                        if (ctb == CTB_USERID)
                   1235:                        {       if (firstuser)
                   1236:                                {       keycounter++;
                   1237:                                        if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
                   1238:                                                fprintf(pgpout,"pub");
                   1239:                                        else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
                   1240:                                                fprintf(pgpout,"sec");
                   1241:                                        else
                   1242:                                                fprintf(pgpout,"???");
                   1243:                                        if (invalid_key)
                   1244:                                                fprintf(pgpout,"? ");
1.1.1.3 ! root     1245:                                        else if (disabled)
        !          1246:                                                fprintf(pgpout,"@ ");
1.1.1.2   root     1247:                                        else
                   1248:                                                fprintf(pgpout,"  ");
                   1249:                                        fprintf(pgpout,"%4d/%s %s  ",
                   1250:                                                countbits(n),keyIDstring(keyID),cdate(&tstamp));
                   1251:                                }
                   1252:                                else
                   1253:                                        fprintf(pgpout,"                             ");
                   1254:                                if (compromised && firstuser)
                   1255:                                {       fprintf(pgpout, PSTR("*** KEY REVOKED ***\n"));
                   1256:                                        fprintf(pgpout,"                             ");
                   1257:                                }
                   1258:                                firstuser = 0;
                   1259:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid));
                   1260: 
                   1261:                                /* Display the hashes for n and e if required */
                   1262:                                if( show_hashes && !shownKeyHash )
                   1263:                                {       showKeyHash( n, e );
                   1264:                                        shownKeyHash = TRUE;
                   1265:                                }
                   1266:                        }
                   1267:                        else if (show_signatures && !(firstuser && compromised))        /* Must be sig cert */
                   1268:                        {       fprintf(pgpout,"sig%c      ", status < 0 ? '?' : ' ');
                   1269:                                showkeyID(sigkeyID);
                   1270:                                fprintf(pgpout,"               "); /* Indent signator userid */
1.1.1.3 ! root     1271:                                if ((siguserid = user_from_keyID(sigkeyID)) == NULL)
1.1.1.2   root     1272:                                        fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
1.1.1.3 ! root     1273:                                else
        !          1274:                                        fprintf(pgpout,"%s\n",LOCAL_CHARSET(siguserid));
1.1.1.2   root     1275:                        } /* printing a sig cert */
                   1276:                }       /* if it has mcguffin */
                   1277:        }       /* loop for all packets */
                   1278: 
                   1279:        fclose(f);      /* close key file */
1.1.1.3 ! root     1280:        if (show_signatures)
        !          1281:                endkrent();
1.1.1.2   root     1282:        fprintf(pgpout,PSTR("%d key(s) examined.\n"),keycounter);
                   1283:        close_more();
                   1284: 
1.1.1.3 ! root     1285:        if (status < 0)
        !          1286:                return status;
        !          1287:        if (mcguffin != NULL && *mcguffin != '\0')
        !          1288:        {       /* user specified substring */
        !          1289:                if (keycounter == 0)
        !          1290:                        return 67;      /* user not found */
        !          1291:                else if (keycounter > 1)
        !          1292:                        return 1;       /* more than one match */
        !          1293:        }
        !          1294:        return(0);      /* normal return */
1.1.1.2   root     1295: 
                   1296: }      /* view_keyring */
                   1297: 
                   1298: 
1.1.1.3 ! root     1299: int dokeycheck(char *mcguffin, char *ringfile, int options)
1.1.1.2   root     1300: /*     Lists all entries in keyring that have mcguffin string in userid.
                   1301:        mcguffin is a null-terminated C string.
1.1.1.3 ! root     1302:        If options is CHECK_NEW, only new signatures are checked and are
        !          1303:        marked as being checked in the trustbyte (called from addto_keyring).
1.1.1.2   root     1304: */
1.1.1.3 ! root     1305: {      FILE *f, *fixedf=NULL;
        !          1306:        byte ctb, keyctb=0;
        !          1307:        long fpsig = 0, fpkey = 0, fixpos = 0, trustpos = -1;
1.1.1.2   root     1308:        int status, sigstatus;
1.1.1.3 ! root     1309:        int keypktlen = 0, sigpktlen = 0;
1.1.1.2   root     1310:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1311:        byte keyID[KEYFRAGSIZE];
                   1312:        byte sigkeyID[KEYFRAGSIZE];
                   1313:        byte keyuserid[256];            /* key certificate userid */
                   1314:        byte siguserid[256];            /* sig certificate userid */
                   1315:        char dfltring[MAX_PATH];
1.1.1.3 ! root     1316:        char *tempring = NULL;
1.1.1.2   root     1317:        word32 tstamp;
                   1318:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1319:        word32 sigtstamp;
                   1320:        byte *sigtimestamp = (byte *) &sigtstamp;
                   1321:        byte sigclass;
                   1322:        int firstuser = 0;
                   1323:        int compromised = 0;
1.1.1.3 ! root     1324:        boolean invalid_key=FALSE;      /* unsupported version or bad data */
1.1.1.2   root     1325:        boolean failed=FALSE;
1.1.1.3 ! root     1326:        boolean print_userid=FALSE;
        !          1327:        byte sigtrust;
1.1.1.2   root     1328: 
                   1329:        /* Default keyring to check signature ID's */
                   1330:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1331: 
1.1.1.3 ! root     1332:        /* open file f, in binary (not text) mode...*/
        !          1333:        if (options & CHECK_NEW)
        !          1334:                f = fopen(ringfile,FOPRWBIN);
        !          1335:        else
        !          1336:                f = fopen(ringfile,FOPRBIN);
        !          1337:        if (f == NULL)
1.1.1.2   root     1338:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1339:                return(-1);
                   1340:        }
                   1341: 
                   1342: /*     Here's a good format for display of key or signature certificates:
                   1343: Type bits/keyID   Date       User ID
                   1344: pub  1024/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1345: sec   512/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1346: sig   384/xxxxxx yyyy-mm-dd  aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
                   1347: */
                   1348: 
1.1.1.3 ! root     1349:        if (options & CHECK_NEW)
        !          1350:        {       fprintf(pgpout,PSTR("\nChecking signatures...\n"));
        !          1351:        }
        !          1352:        else
        !          1353:        {       
        !          1354:                if (moreflag)
        !          1355:                        open_more();
        !          1356:                if (!quietmode)
        !          1357:                {       fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile);
        !          1358:                        if (mcguffin && strlen(mcguffin) > 0)
        !          1359:                                fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin));
        !          1360:                }
1.1.1.2   root     1361:                fprintf(pgpout,PSTR("\nType bits/keyID   Date       User ID\n"));
                   1362:        }
                   1363:        for ( ; ; )
                   1364:        {       long fpos = ftell(f);
                   1365:                status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)keyuserid,n,e,
                   1366:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1367:                /* Note that readkeypacket has called set_precision */
                   1368:                if (status== -1 ) break;        /* eof reached */
                   1369:                if (status == -4 || status == -6)
                   1370:                {       /* only ctb and userid are valid */
                   1371:                        memset(sigkeyID, 0, KEYFRAGSIZE);
                   1372:                        tstamp = 0;
                   1373:                }
                   1374:                else if (status < 0)
                   1375:                {       fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"),
                   1376:                                ringfile);
                   1377:                        fclose(f);      /* close key file */
                   1378:                        return(-1);
                   1379:                }
                   1380: 
                   1381:                if (is_key_ctb(ctb))
                   1382:                {       firstuser = 1;
                   1383:                        keyctb = ctb;
                   1384:                        fpkey = fpos;
                   1385:                        keypktlen = ( int ) ( ftell(f) - fpkey );
                   1386:                        compromised = is_compromised(f);
                   1387:                        if (status < 0)
                   1388:                        {       invalid_key = TRUE;
                   1389:                                memset(keyID, 0, KEYFRAGSIZE);
                   1390:                        }
                   1391:                        else
                   1392:                        {       invalid_key = FALSE;
                   1393:                                extract_keyID(keyID, n);
                   1394:                        }
1.1.1.3 ! root     1395:                        if (options & CHECK_NEW)
        !          1396:                                print_userid = TRUE;
1.1.1.2   root     1397:                }
                   1398: 
                   1399:                if (ctb == CTB_USERID)
                   1400:                        PascalToC((char *)keyuserid);
1.1.1.3 ! root     1401:                else if (is_ctb_type(ctb, CTB_SKE_TYPE))
        !          1402:                {       fpsig = fpos;
        !          1403:                        sigpktlen = ( int ) ( ftell(f) - fpsig );
        !          1404:                } else
        !          1405:                        continue;
1.1.1.2   root     1406: 
1.1.1.3 ! root     1407:                if (options & CHECK_NEW)
1.1.1.2   root     1408:                {
1.1.1.3 ! root     1409:                        if (!is_ctb_type(ctb, CTB_SKE_TYPE))
        !          1410:                                continue;
        !          1411:                        trustpos = ftell(f);
        !          1412:                        status = read_trust(f, &sigtrust);
        !          1413:                        if (status == -1)
        !          1414:                                break;  /* EOF */
        !          1415:                        if (status == -7)
        !          1416:                        {       trustpos = -1;
        !          1417:                                continue;       /* not a keyring or this was a compromise cert. */
        !          1418:                        }
        !          1419:                        if (status < 0)
        !          1420:                        {       fclose(f);
        !          1421:                                return status;
        !          1422:                        }
        !          1423:                        if (sigtrust & KC_SIG_CHECKED)
        !          1424:                                continue;
        !          1425:                        /* addto_keyring has called setkrent() */
        !          1426:                        if (user_from_keyID(sigkeyID) == NULL)
        !          1427:                                continue;       /* unknown signator */
        !          1428:                }
        !          1429: 
        !          1430:                if ((options & CHECK_NEW) || userid_match((char *)keyuserid,mcguffin,n))
        !          1431:                {
        !          1432:                        if (ctb == CTB_USERID || print_userid)
        !          1433:                        {       /* CHECK_NEW: only print userid if it has new signature */
        !          1434:                                print_userid = FALSE;
1.1.1.2   root     1435:                                if (firstuser)
                   1436:                                {       if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE))
                   1437:                                                fprintf(pgpout,"pub");
                   1438:                                        else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE))
                   1439:                                                fprintf(pgpout,"sec");
                   1440:                                        else
                   1441:                                                fprintf(pgpout,"???");
                   1442:                                        if (invalid_key)
                   1443:                                                fprintf(pgpout,"? ");
                   1444:                                        else
                   1445:                                                fprintf(pgpout,"  ");
                   1446:                                        fprintf(pgpout,"%4d/%s %s  ",
                   1447:                                                countbits(n),keyIDstring(keyID),cdate(&tstamp));
                   1448:                                }
                   1449:                                else
                   1450:                                        fprintf(pgpout,"                             ");
                   1451:                                if (compromised && firstuser)
                   1452:                                {       fprintf(pgpout, PSTR("*** KEY REVOKED ***\n"));
                   1453:                                        fprintf(pgpout,"                             ");
                   1454:                                }
                   1455:                                firstuser = 0;
                   1456:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)keyuserid));
                   1457:                        }
1.1.1.3 ! root     1458:                        if (is_ctb_type(ctb, CTB_SKE_TYPE))
1.1.1.2   root     1459:                        {       /* Try checking signature on either this ring or dflt ring */
                   1460:                                CToPascal((char *)keyuserid);
                   1461:                                sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid,
                   1462:                                        f, fpsig, ringfile, (char *) siguserid, sigtimestamp, &sigclass);
                   1463:                                if (sigstatus == -1  &&  strcmp(ringfile,dfltring) != 0)
                   1464:                                        sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid,
                   1465:                                                f, fpsig, dfltring, (char *) siguserid, sigtimestamp, &sigclass);
                   1466:                                PascalToC((char *)keyuserid);
                   1467:                                fseek (f, fpsig+sigpktlen, SEEK_SET);
                   1468:                                if (sigclass == KC_SIGNATURE_BYTE)
                   1469:                                        fprintf(pgpout,"com");
                   1470:                                else
                   1471:                                        fprintf(pgpout,"sig");
                   1472:                                if (sigstatus >= 0)
                   1473:                                        fprintf(pgpout,"!      ");
                   1474:                                else if (status < 0 || sigstatus == -1)
                   1475:                                        fprintf(pgpout,"?      ");
                   1476:                                else
                   1477:                                        fprintf(pgpout,"*      ");      /* bad signature */
                   1478:                                showkeyID(sigkeyID);
                   1479:                                if (sigstatus == -1)
                   1480:                                {       fprintf(pgpout,"               "); /* Indent signator userid */
                   1481:                                        fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
                   1482:                                }
                   1483:                                else
                   1484:                                {       PascalToC((char *) siguserid);
                   1485:                                        fprintf(pgpout," %s  ",cdate(&sigtstamp));
                   1486:                                        if (sigclass != KC_SIGNATURE_BYTE)
                   1487:                                                fprintf(pgpout, "  ");
                   1488:                                        fprintf(pgpout,"%s\n", LOCAL_CHARSET((char *)siguserid));
1.1.1.3 ! root     1489:                                        if (sigstatus >= 0)
        !          1490:                                        {       if (options & CHECK_NEW && trustpos > 0)
        !          1491:                                                        write_trust_pos(f, sigtrust|KC_SIG_CHECKED, trustpos);
        !          1492:                                        }
        !          1493:                                        else
1.1.1.2   root     1494:                                        {       fprintf(pgpout,"                               ");
                   1495:                                                fprintf(pgpout,PSTR("\007***** BAD SIGNATURE! *****\n"));
                   1496:                                                if (!failed)
                   1497:                                                {       /* first bad signature: create scratch file */
                   1498:                                                        tempring = tempfile(TMP_TMPDIR);
                   1499:                                                        fixedf = fopen(tempring, FOPWBIN);
                   1500:                                                        failed = TRUE;
                   1501:                                                }
                   1502:                                                if (fixedf != NULL)
                   1503:                                                {
                   1504:                                                        copyfilepos(f, fixedf, fpsig - fixpos, fixpos);
                   1505:                                                        fseek(f, fpsig+sigpktlen, SEEK_SET);
                   1506:                                                        if (nextkeypacket(f, &ctb) < 0 || ctb != CTB_KEYCTRL)
                   1507:                                                                fseek(f, fpsig+sigpktlen, SEEK_SET);
                   1508:                                                        fixpos = ftell(f);
                   1509:                                                }
                   1510:                                        }
                   1511:                                }
                   1512:                        } /* checking a signature */
                   1513:                }       /* if it has mcguffin */
                   1514:        }       /* loop for all packets */
                   1515: 
1.1.1.3 ! root     1516:        close_more();
        !          1517:        if (status < -1)
        !          1518:        {
        !          1519:                fclose(f);
        !          1520:                return status;
        !          1521:        }
        !          1522:        fputc('\n',pgpout);
1.1.1.2   root     1523: 
                   1524:        if (failed)
                   1525:        {
                   1526:                copyfilepos(f, fixedf, -1L, fixpos);
                   1527:                if (write_error(fixedf))
                   1528:                {       fclose(fixedf);
                   1529:                        fclose(f);
                   1530:                        return -1;
                   1531:                }
                   1532:                fclose(fixedf);
1.1.1.3 ! root     1533:                if (!batchmode)
        !          1534:                        fprintf(pgpout, PSTR("Remove bad signatures (Y/n)? "));
        !          1535:                if (batchmode || getyesno('y'))
1.1.1.2   root     1536:                {
                   1537:                        savetempbak(tempring, ringfile);
                   1538:                        failed = 0;
                   1539:                }
                   1540:        }
                   1541:        fclose(f);      /* close key file */
                   1542: 
                   1543:        return(failed?-1:0);    /* normal return */
                   1544: 
                   1545: }      /* dokeycheck */
                   1546: 
                   1547: int backup_rename(char *scratchfile, char *destfile)
                   1548: {      /* rename scratchfile to destfile after making a backup file */
                   1549:        char bakfile[MAX_PATH];
                   1550: 
                   1551:        if (is_tempfile(destfile))
                   1552:        {
                   1553:                remove(destfile);
                   1554:        }
                   1555:        else
                   1556:        {       if (file_exists(destfile))
                   1557:                {
                   1558:                        strcpy(bakfile, destfile);
                   1559:                        force_extension(bakfile, BAK_EXTENSION);
                   1560:                        remove(bakfile);
                   1561:                        rename(destfile, bakfile);
                   1562:                }
                   1563:        }
                   1564:        return(rename2(scratchfile, destfile));
                   1565: }
                   1566: 
                   1567: int remove_sigs(char *mcguffin, char*ringfile)
                   1568: /* Lists all signatures for keys with specified mcguffin string, and asks
                   1569:  * if they should be removed.
                   1570:  */
                   1571: {      FILE *f, *g;
                   1572:        byte ctb;
1.1.1.3 ! root     1573:        long fp, fpuser;
        !          1574:        int packetlength;
1.1.1.2   root     1575:        int status;
                   1576:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1577:        byte sigkeyID[KEYFRAGSIZE];
                   1578:        byte userid[256];               /* key certificate userid */
                   1579:        char dfltring[MAX_PATH];
                   1580:        word32 tstamp;
                   1581:        byte *timestamp = (byte *) &tstamp;             /* key certificate timestamp */
                   1582:        int nsigs = 0, nremoved = 0;
                   1583:        int keeping;
                   1584:        char *scratchf;
                   1585: 
                   1586:        /* Default keyring to check signature ID's */
                   1587:        buildfilename(dfltring,PUBLIC_KEYRING_FILENAME);
                   1588: 
                   1589:        if (!mcguffin  ||  strlen(mcguffin) == 0)
                   1590:                return(-1);
                   1591: 
                   1592:        setoutdir(ringfile);
                   1593:        scratchf = tempfile(0);
                   1594: 
                   1595:        strcpy((char *)userid,mcguffin);
                   1596: 
                   1597:        fprintf(pgpout,PSTR("\nRemoving signatures from userid '%s' in key ring '%s'\n"),
                   1598:                                LOCAL_CHARSET(mcguffin), ringfile);
                   1599: 
1.1.1.3 ! root     1600:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e);
1.1.1.2   root     1601:        if (status < 0)
                   1602:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile);
                   1603:                return(0);      /* normal return */
                   1604:        }
                   1605: 
                   1606:        strcpy((char *)userid,mcguffin);
                   1607:        getpubuserid (ringfile, fp, userid, &fpuser, &packetlength, FALSE);
                   1608:        packetlength += ( int ) ( fpuser - fp );
                   1609: 
                   1610:        /* open file f for read, in binary (not text) mode...*/
                   1611:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1612:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1613:                return(-1);
                   1614:        }
                   1615: 
                   1616:        /* Count signatures */
                   1617:        fseek (f, fp+packetlength, SEEK_SET);
                   1618:        for ( ; ; )
                   1619:        {       status = nextkeypacket(f, &ctb);
                   1620:                if (status < 0  ||  is_key_ctb(ctb)  ||  ctb==CTB_USERID)
                   1621:                        break;
                   1622:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
                   1623:                        ++nsigs;
                   1624:        }
                   1625:                
                   1626:        rewind(f);
                   1627: 
                   1628:        if (nsigs == 0)
                   1629:        {       fprintf (pgpout,PSTR("\nKey has no signatures to remove.\n"));
                   1630:                fclose (f);
                   1631:                return (0);             /* Normal return */
                   1632:        }
                   1633: 
                   1634:        fprintf (pgpout, PSTR("\nKey has %d signature(s):\n"), nsigs);
                   1635: 
                   1636:        /* open file g for writing, in binary (not text) mode...*/
                   1637:        if ((g = fopen(scratchf,FOPWBIN)) == NULL)
                   1638:        {       fclose(f);
                   1639:                return(-1);
                   1640:        }
                   1641:        copyfile(f,g,fp+packetlength);  /* copy file f to g up through key */
                   1642: 
                   1643:        /* Now print out any following sig certs */
                   1644:        keeping = 1;
                   1645:        for ( ; ; )
                   1646:        {       fp = ftell(f);
                   1647:                status = readkeypacket(f, FALSE, &ctb, NULL, NULL, NULL, NULL,
                   1648:                                NULL,NULL,NULL,NULL,sigkeyID,NULL);
                   1649:                packetlength = ( int ) ( ftell(f) - fp ); 
                   1650:                if ((status < 0 && status != -6 && status != -4) ||
                   1651:                                is_key_ctb(ctb)  ||  ctb==CTB_USERID)
                   1652:                        break;
                   1653:                if (is_ctb_type(ctb,CTB_SKE_TYPE))
                   1654:                {       fprintf(pgpout,"sig%c     ", status < 0 ? '?' : ' ');
                   1655:                        if (status < 0)
                   1656:                                memset(sigkeyID, 0, KEYFRAGSIZE);
                   1657:                        showkeyID(sigkeyID);
                   1658:                        fprintf(pgpout,"               "); /* Indent signator userid */
1.1.1.3 ! root     1659:                        if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, sigkeyID,
        !          1660:                                        timestamp, userid, n, e)>=0 ||
        !          1661:                                getpublickey(GPK_GIVEUP, dfltring, NULL, NULL, sigkeyID,
        !          1662:                                        timestamp, userid, n, e)>=0)
1.1.1.2   root     1663:                        {       PascalToC((char *)userid);
                   1664:                                fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid));
                   1665:                        }
                   1666:                        else
                   1667:                                fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n"));
                   1668:                        fprintf(pgpout, PSTR("Remove this signature (y/N)? "));
                   1669:                        if (!(keeping=!getyesno('n')))
                   1670:                                ++nremoved;
                   1671:                }
                   1672:                if (keeping)
                   1673:                        copyfilepos (f, g, (long) packetlength, fp);
                   1674:        }       /* scanning sig certs */
                   1675:        copyfilepos (f, g, -1L, fp);            /* Copy rest of file */
                   1676: 
                   1677:        fclose(f);      /* close key file */
                   1678:        if (write_error(g))
                   1679:        {       fclose(g);
                   1680:                return -1;
                   1681:        }
                   1682:        fclose(g);      /* close scratch file */
                   1683:        savetempbak(scratchf,ringfile);
                   1684:        if (nremoved == 0)
                   1685:                fprintf(pgpout,PSTR("\nNo key signatures removed.\n"));
                   1686:        else
                   1687:                fprintf(pgpout,PSTR("\n%d key signature(s) removed.\n"), nremoved);
                   1688: 
                   1689:        return(0);      /* normal return */
                   1690: 
                   1691: }      /* remove_sigs */
                   1692: 
                   1693: 
                   1694: int remove_from_keyring(byte *keyID, char *mcguffin, char *ringfile, boolean secring_too)
                   1695: /*     Remove the first entry in key ring that has mcguffin string in userid.
                   1696:        Or it removes the first matching keyID from the ring.
                   1697:        A non-NULL keyID takes precedence over a mcguffin specifier.
                   1698:        mcguffin is a null-terminated C string.
                   1699:        If secring_too is TRUE, the secret keyring is also checked.
                   1700: */
                   1701: {
                   1702:        FILE *f;
                   1703:        FILE *g;
                   1704:        long fp, nfp;
                   1705:        int packetlength;
                   1706:        byte ctb;
                   1707:        int status;
                   1708:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1709:        byte userid[256];               /* key certificate userid */
                   1710:        word32 tstamp; byte *timestamp = (byte *) &tstamp;              /* key certificate timestamp */
                   1711:        int userids;
                   1712:        boolean rmuserid = FALSE;
                   1713:        char *scratchf;
                   1714: 
                   1715:        default_extension(ringfile,PGP_EXTENSION);
                   1716: 
                   1717:        if ((keyID==NULL) && (!mcguffin  ||  strlen(mcguffin)==0))
                   1718:                return(-1); /* error, null mcguffin will match everything */
                   1719: 
                   1720: top:
                   1721:        if (mcguffin)
                   1722:                strcpy((char *)userid,mcguffin);
                   1723: 
                   1724:        fprintf(pgpout,PSTR("\nRemoving from key ring: '%s'"),ringfile);
                   1725:        if (mcguffin  &&  strlen(mcguffin) > 0)
                   1726:                fprintf(pgpout,PSTR(", userid \"%s\".\n"),
                   1727:                        LOCAL_CHARSET(mcguffin));
                   1728: 
1.1.1.3 ! root     1729:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e);
1.1.1.2   root     1730:        if (status < 0 && status != -4 && status != -6)
                   1731:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile);
                   1732:                return(0);      /* normal return */
                   1733:        }
                   1734: 
                   1735:        /* Now add to packetlength the subordinate following certificates */
                   1736:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1737:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1738:                return(-1);
                   1739:        }
                   1740:        fseek (f, fp+packetlength, SEEK_SET);
                   1741:        userids = 0;
                   1742:        do      /* count user ID's, position nfp at next key */
                   1743:        {       nfp = ftell(f);
                   1744:                status = nextkeypacket(f, &ctb);
                   1745:                if (status == 0 && ctb == CTB_USERID)
                   1746:                        ++userids;
                   1747:        } while (status == 0 && !is_key_ctb(ctb));
                   1748:        if (status < -1)
                   1749:        {       fclose(f);
                   1750:                return(-1);
                   1751:        }
                   1752: 
                   1753:        if (keyID==NULL)        /* Human confirmation is required. */
                   1754:        {       /* Supposedly the key was fully displayed by getpublickey */
                   1755:                if (userids > 1)
                   1756:                {       fprintf(pgpout, PSTR("\nKey has more than one user ID.\n\
                   1757: Do you want to remove the whole key (y/N)? "));
                   1758:                        if (!getyesno('n'))
                   1759:                        {       /* find out which userid should be removed */
                   1760:                                rmuserid = TRUE;
                   1761:                                fseek (f, fp+packetlength, SEEK_SET);
                   1762:                                for ( ; ; )
                   1763:                                {       fp = ftell(f);
                   1764:                                        status = readkpacket(f, &ctb, (char *) userid, NULL, NULL);
                   1765:                                        if (status < 0 && status != -4 && status != -6 || is_key_ctb(ctb))
                   1766:                                        {       fclose(f);
                   1767:                                                fprintf(pgpout, PSTR("\nNo more user ID's\n"));
                   1768:                                                return(-1);
                   1769:                                        }
                   1770:                                        if (ctb == CTB_USERID)
                   1771:                                        {       fprintf(pgpout, PSTR("Remove \"%s\" (y/N)? "), userid);
                   1772:                                                if (getyesno('n'))
                   1773:                                                        break;
                   1774:                                        }
                   1775:                                }
                   1776:                                do      /* also remove signatures and trust bytes */
                   1777:                                {       nfp = ftell(f);
                   1778:                                        status = nextkeypacket(f, &ctb);
                   1779:                                } while ((status == 0 || status == -4 || status == -6) &&
                   1780:                                                !is_key_ctb(ctb) && ctb != CTB_USERID);
                   1781:                                if (status < -1 && status != -4 && status != -6)
                   1782:                                {       fclose(f);
                   1783:                                        return(-1);
                   1784:                                }
                   1785:                        }
                   1786:                }
1.1.1.3 ! root     1787:                else if (!force_flag)   /* only one user ID */
1.1.1.2   root     1788:                {       fprintf(pgpout,
                   1789:                                PSTR("\nAre you sure you want this key removed (y/N)? "));
                   1790:                        if (!getyesno('n'))
                   1791:                        {       fclose(f);
                   1792:                                return(-1);     /* user said "no" */
                   1793:                        }
                   1794:                }
                   1795:        }
                   1796:        fclose(f);
                   1797:        packetlength = ( int ) ( nfp - fp );
                   1798: 
                   1799:        /* open file f for read, in binary (not text) mode...*/
                   1800:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1801:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1802:                return(-1);
                   1803:        }
                   1804: 
                   1805:        setoutdir(ringfile);
                   1806:        scratchf = tempfile(0);
                   1807:        /* open file g for writing, in binary (not text) mode...*/
                   1808:        if ((g = fopen(scratchf,FOPWBIN)) == NULL)
                   1809:        {       fclose(f);
                   1810:                return(-1);
                   1811:        }
                   1812:        copyfilepos(f,g,fp,0L); /* copy file f to g up to position fp */
                   1813:        copyfilepos(f,g,-1L,fp+packetlength); /* copy rest of file f */
                   1814:        fclose(f);      /* close key file */
                   1815:        if (write_error(g))
                   1816:        {       fclose(g);
                   1817:                return -1;
                   1818:        }
                   1819:        fclose(g);      /* close scratch file */
1.1.1.3 ! root     1820:        if (secring_too) /* TRUE if this is the public keyring */
        !          1821:                maint_update(scratchf);
1.1.1.2   root     1822:        savetempbak(scratchf,ringfile);
                   1823:        if (rmuserid)
                   1824:                fprintf(pgpout,PSTR("\nUser ID removed from key ring.\n"));
                   1825:        else
                   1826:                fprintf(pgpout,PSTR("\nKey removed from key ring.\n"));
                   1827:        
                   1828:        if (secring_too)
                   1829:        {       secring_too = FALSE;
                   1830:                buildfilename(ringfile, SECRET_KEYRING_FILENAME);
                   1831:                strcpy((char *)userid,mcguffin);
1.1.1.3 ! root     1832:                if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, NULL, timestamp, userid, n, e) == 0)
1.1.1.2   root     1833:                {       fprintf(pgpout, PSTR("\nKey or user ID is also present in secret keyring.\n\
                   1834: Do you also want to remove it from the secret keyring (y/N)? "));
                   1835:                        if (getyesno('n'))
                   1836:                                goto top;
                   1837:                }
                   1838:        }
                   1839: 
                   1840:        return(0);      /* normal return */
                   1841: 
                   1842: }      /* remove_from_keyring */
                   1843: 
                   1844: 
                   1845: int extract_from_keyring (char *mcguffin, char *keyfile, char *ringfile,
                   1846:                                boolean transflag)
                   1847: /*     Copy the first entry in key ring that has mcguffin string in
                   1848:        userid and put it into keyfile.
                   1849:        mcguffin is a null-terminated C string.
                   1850: */
                   1851: {
                   1852:        FILE *f;
                   1853:        FILE *g;
1.1.1.3 ! root     1854:        long fp;
        !          1855:        int packetlength=0;
1.1.1.2   root     1856:        byte ctb;
1.1.1.3 ! root     1857:        byte keyctrl;
1.1.1.2   root     1858:        int status;
                   1859:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
                   1860:        byte keyID[KEYFRAGSIZE];
                   1861:        byte userid[256];       /* key certificate userid */
                   1862:        char fname[MAX_PATH], transfile[MAX_PATH], transname[MAX_PATH];
1.1.1.3 ! root     1863:        char *tempf = NULL;
1.1.1.2   root     1864:        word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key cert tstamp */
                   1865:        boolean append = FALSE;
                   1866:        boolean whole_ring = FALSE;
                   1867: 
                   1868:        default_extension(ringfile, PGP_EXTENSION);
                   1869: 
                   1870:        if (!mcguffin  ||  strlen(mcguffin)==0 || strcmp(mcguffin, "*") == 0)
                   1871:                whole_ring = TRUE;
                   1872: 
                   1873:        /* open file f for read, in binary (not text) mode...*/
                   1874:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   1875:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1876:                return(-1);
                   1877:        }
                   1878: 
                   1879:        if (!whole_ring)
                   1880:        {
                   1881:                strcpy((char *)userid, mcguffin);
                   1882:                fprintf(pgpout,PSTR("\nExtracting from key ring: '%s'"),ringfile);
                   1883:                fprintf(pgpout,PSTR(", userid \"%s\".\n"),LOCAL_CHARSET(mcguffin));
                   1884: 
1.1.1.3 ! root     1885:                status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL,
1.1.1.2   root     1886:                                        timestamp, userid, n, e);
                   1887:                if (status < 0 && status != -4 && status != -6)
                   1888:                {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),
                   1889:                                                                        ringfile);
                   1890:                        fclose(f);
1.1.1.3 ! root     1891:                        return(1);      /* non-normal return */
1.1.1.2   root     1892:                }
                   1893:                extract_keyID(keyID, n);
                   1894:        }
                   1895:        else
                   1896:        {
                   1897:                do      /* set fp to first key packet */
                   1898:                        fp = ftell(f);
                   1899:                while ((status = nextkeypacket(f, &ctb)) >= 0 && !is_key_ctb(ctb));
                   1900:                if (status < 0)
                   1901:                {       fclose(f);
                   1902:                        return(-1);
                   1903:                }
                   1904:                packetlength = ( int ) ( ftell(f) - fp );
                   1905:        }
                   1906: 
                   1907:        if (!keyfile  ||  strlen(keyfile)==0)
                   1908:        {       fprintf(pgpout, PSTR("\nExtract the above key into which file? "));
1.1.1.3 ! root     1909:                if (batchmode)
        !          1910:                        return -1;
1.1.1.2   root     1911:                getstring( fname, sizeof(fname)-4, TRUE );
                   1912:                if (*fname == '\0')
                   1913:                        return(-1);
                   1914:        }
                   1915:        else
                   1916:                strcpy(fname,keyfile);
                   1917:        default_extension(fname,PGP_EXTENSION);
                   1918: 
                   1919:        /* If transport armoring, use a dummy file for keyfile */
                   1920:        if (transflag)
                   1921:        {       strcpy(transname, fname);
                   1922:                strcpy(transfile, fname);
                   1923:                force_extension(transfile, ASC_EXTENSION);
                   1924:                tempf = tempfile(TMP_TMPDIR|TMP_WIPE);
                   1925:                strcpy(fname, tempf);
                   1926:        }
                   1927:        if (file_exists( transflag?transfile:fname ))
                   1928:        {
                   1929:                if (!transflag && !whole_ring)
                   1930:                {       /* see if the key is already present in fname */
1.1.1.3 ! root     1931:                        status = getpublickey(GPK_GIVEUP, fname, NULL, NULL, keyID,
        !          1932:                                        timestamp, userid, n, e);
1.1.1.2   root     1933:                        if (status >= 0 || status == -4 || status == -6)
                   1934:                        {       fclose(f);
                   1935:                                fprintf(pgpout,PSTR("Key ID %s is already included in key ring '%s'.\n"),
                   1936:                                        keyIDstring(keyID), fname);
                   1937:                                return(-1);
                   1938:                        }
                   1939:                }
                   1940:                if (whole_ring || transflag || status < -1)
1.1.1.3 ! root     1941:                {       if (!is_tempfile(fname) && !force_flag) 
        !          1942:                                /* Don't ask this for mailmode or for 
        !          1943:                                 * a tempfile, since its ok.
        !          1944:                                 */
        !          1945:                        { /* if status < -1 then fname is not a keyfile, ask if it should be overwritten */
        !          1946:                                fprintf(pgpout,PSTR("\n\007Output file '%s' already exists.  Overwrite (y/N)? "),
        !          1947:                                        transflag?transfile:fname);
        !          1948:                                if (!getyesno( 'n' ))
        !          1949:                                {       fclose(f);
        !          1950:                                        return(-1);     /* user chose to abort */
        !          1951:                                }
1.1.1.2   root     1952:                        }
                   1953:                }
                   1954:                else
                   1955:                        append = TRUE;
                   1956:        }
                   1957: 
                   1958:        if (append)
                   1959:                g = fopen(fname, FOPRWBIN);
                   1960:        else
                   1961:                g = fopen(fname, FOPWBIN);
                   1962:        if (g == NULL)
                   1963:        {       if (append)
                   1964:                        fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   1965:                else
                   1966:                        fprintf(pgpout,PSTR("\n\007Unable to create key file '%s'.\n"), fname);
                   1967:                fclose(f);
                   1968:                return(-1);
                   1969:        }
                   1970:        if (append)
                   1971:                fseek(g, 0L, SEEK_END);
                   1972:        do
1.1.1.3 ! root     1973:        {       /* file f is positioned right after key packet */
        !          1974:                if (whole_ring && read_trust(f, &keyctrl) == 0
        !          1975:                        && (keyctrl & KC_DISABLED))
        !          1976:                {
        !          1977:                        do      /* skip this key */
        !          1978:                        {
        !          1979:                                fp = ftell(f);
        !          1980:                                status = nextkeypacket(f, &ctb);
        !          1981:                                packetlength = ( int ) ( ftell(f) - fp );
        !          1982:                        }
        !          1983:                        while (!is_key_ctb(ctb) && status >= 0);
        !          1984:                        continue;
        !          1985:                }
1.1.1.2   root     1986:                if (copyfilepos(f, g, (long) packetlength, fp) < 0)     /* Copy key out */
                   1987:                {       status = -2;
                   1988:                        break;
                   1989:                }
                   1990:                /* Copy any following signature or userid packets */
                   1991:                for ( ; ; )
                   1992:                {       fp = ftell(f);
                   1993:                        status = nextkeypacket(f, &ctb);
                   1994:                        packetlength = ( int ) ( ftell(f) - fp );
                   1995:                        if (status < 0  ||  is_key_ctb(ctb))
                   1996:                                break;
                   1997:                        if (ctb==CTB_USERID  ||  is_ctb_type(ctb,CTB_SKE_TYPE))
                   1998:                                if (copyfilepos(f, g, (long) packetlength, fp) < 0)
                   1999:                                {       status = -2;
                   2000:                                        break;
                   2001:                                }
                   2002:                }
                   2003:        }
                   2004:        while (whole_ring && status >= 0);
                   2005: 
                   2006:        fclose(f);
                   2007:        if (status < -1 || write_error(g))
                   2008:        {       fclose(g);
                   2009:                return(-1);
                   2010:        }
                   2011:        fclose(g);
                   2012: 
                   2013:        if (transflag)
                   2014:        {       status = armor_file (fname, transfile, transname, NULL);
                   2015:                rmtemp (tempf);
                   2016:                if (status)
                   2017:                        return(-1);
                   2018:        }
                   2019: 
                   2020:        fprintf (pgpout,PSTR("\nKey extracted to file '%s'.\n"), transflag?transfile:fname);
                   2021: 
                   2022:        return (0);     /* normal return */
                   2023: }      /* extract_from_keyring */
                   2024: 
                   2025: 
                   2026: /*======================================================================*/
                   2027: 
1.1.1.3 ! root     2028: static int merge_key_to_ringfile(char *keyfile, char* ringfile, long fp,
1.1.1.2   root     2029:                                int packetlength, long keylen)
                   2030: /* Copy the key data in keyfile into ringfile, replacing the data that
                   2031:    is in ringfile starting at fp and for length packetlength.
                   2032:    keylen is the number of bytes to copy from keyfile
                   2033: */
                   2034: {      FILE    *f, *g, *h;
                   2035:        char *tempf;
                   2036:        int rc;
                   2037: 
                   2038:        setoutdir(ringfile);
                   2039:        tempf = tempfile(TMP_WIPE);
                   2040:        /* open file f for reading, binary, as keyring file */
                   2041:        if ((f = fopen(ringfile,FOPRBIN)) == NULL)
                   2042:                return(-1);
                   2043:        /* open file g for writing, binary, as scratch keyring file */
                   2044:        if ((g = fopen(tempf,FOPWBIN)) == NULL)
                   2045:        {       fclose(f);
                   2046:                return(-1);
                   2047:        }
                   2048:        /* open file h for reading, binary, as key file to be inserted */
                   2049:        if ((h = fopen(keyfile,FOPRBIN)) == NULL)
                   2050:        {       fclose(f);
                   2051:                fclose(g);
                   2052:                return(-1);
                   2053:        }
                   2054:        /* Copy pre-key keyring data from f to g */
                   2055:        copyfile(f,g,fp);
                   2056:        /* Copy temp key data from h to g */
                   2057:        copyfile(h,g,keylen);
                   2058:        /* Copy post-key keyring data from f to g */
                   2059:        copyfilepos(f,g,-1L,fp+packetlength);
                   2060:        fclose(f);
                   2061:        rc = write_error(g);
                   2062:        fclose(g);
                   2063:        fclose(h);
                   2064: 
                   2065:        if (!rc)
                   2066:                savetempbak(tempf,ringfile);
                   2067: 
                   2068:        return(rc ? -1 : 0);
                   2069: }      /* merge_key_to_ringfile */
                   2070: 
                   2071: static int insert_userid(char *keyfile, byte *userid, long fpos)
                   2072: {      /* insert userid and trust byte at position fpos in file keyfile */
                   2073:        char *tmpf;
                   2074:        FILE *f, *g;
                   2075: 
                   2076:        tmpf = tempfile(TMP_TMPDIR);
                   2077:        if ((f = fopen(keyfile, FOPRBIN)) == NULL)
                   2078:                return(-1);
                   2079:        if ((g = fopen(tmpf, FOPWBIN)) == NULL)
                   2080:        {       fclose(f);
                   2081:                return(-1);
                   2082:        }
                   2083:        copyfile(f, g, fpos);
                   2084:        putc(CTB_USERID, g);
                   2085:        fwrite(userid, 1, userid[0]+1, g);
                   2086:        write_trust(g, KC_LEGIT_COMPLETE);
                   2087:        copyfile(f, g, -1L);
                   2088:        fclose(f);
                   2089:        if (write_error(g))
                   2090:        {       fclose(g);
                   2091:                return(-1);
                   2092:        }
                   2093:        fclose(g);
                   2094:        return(savetempbak(tmpf, keyfile));
                   2095: }
                   2096: 
                   2097: int dokeyedit(char *mcguffin, char *ringfile)
                   2098: /*     Edit the userid and/or pass phrase for an RSA key pair, and
                   2099:        put them back into the ring files.
                   2100: */
                   2101: {      unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION],
                   2102:                 p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
                   2103:        char *fname, secring[MAX_PATH];
                   2104:        FILE *f;
                   2105:        word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */
                   2106:        byte userid[256];
                   2107:        byte userid1[256];
                   2108:        char passphrase[256];
                   2109:        word32 tstamp; byte *timestamp = (byte *) &tstamp;      /* key certificate timestamp */
                   2110:        byte keyID[KEYFRAGSIZE];
                   2111:        boolean hidekey;        /* TRUE iff secret key is encrypted */
                   2112:        boolean changed=FALSE, changeID=FALSE;
                   2113:        byte ctb;
                   2114:        int status;
                   2115:        long fpp,fps,trust_pos, keylen;
                   2116:        int pplength=0, pslength=0;
                   2117:        byte ideakey[16];
                   2118:        byte keyctrl;
                   2119: 
                   2120:        if (!ringfile || strlen(ringfile)==0 || !mcguffin || strlen(mcguffin)==0)
                   2121:                return(-1);     /* Need ringfile name, user name */
                   2122: 
                   2123:        force_extension(ringfile,PGP_EXTENSION);
                   2124: 
                   2125:        strcpy((char *)userid, mcguffin);
                   2126:        fprintf(pgpout,PSTR("\nEditing userid \"%s\" in key ring: '%s'.\n"),
                   2127:                LOCAL_CHARSET((char *)userid),ringfile);
                   2128: 
                   2129:        if (!file_exists (ringfile))
                   2130:        {       fprintf(pgpout,PSTR("\nCan't open public key ring file '%s'\n"),
                   2131:                        ringfile);
                   2132:                return(-1);
                   2133:        }
                   2134: 
1.1.1.3 ! root     2135:        status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fpp, &pplength, NULL,
1.1.1.2   root     2136:                                timestamp, userid, n, e);
                   2137:        if (status < 0)
                   2138:        {       fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),
                   2139:                        ringfile);
                   2140:                return(-1);
                   2141:        }
                   2142: 
                   2143:        /* Now add to pplength any following key control certificate */
                   2144:        if ((f = fopen(ringfile,FOPRWBIN)) == NULL)
                   2145:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile);
                   2146:                return(-1);
                   2147:        }
                   2148: 
                   2149:        fseek(f, fpp, SEEK_SET);
                   2150:        if (is_compromised(f))
                   2151:        {       fprintf(pgpout, PSTR("\n\007This key has been revoked by its owner.\n"));
                   2152:                fclose(f);
                   2153:                return(-1);
                   2154:        }
                   2155:        trust_pos = fpp+pplength;
                   2156:        fseek(f, trust_pos, SEEK_SET);
                   2157:        if (read_trust(f, &keyctrl) < 0)
                   2158:                trust_pos = -1;         /* keyfile: no trust byte */
                   2159: 
                   2160:        extract_keyID(keyID, n);
                   2161: 
                   2162:        /* Now read private key, too */
                   2163:        strcpy(secring, ringfile);
                   2164:        strcpy(file_tail(secring), SECRET_KEYRING_FILENAME);
                   2165: 
                   2166:        if (!file_exists (secring))
                   2167:        {       fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"),
                   2168:                        secring);
                   2169:                fclose(f);
                   2170:                return(-1);
                   2171:        }
                   2172: 
                   2173:        /* Get position of key in secret key file */
1.1.1.3 ! root     2174:        (void)getpublickey(GPK_GIVEUP, secring, &fps, &pslength, keyID,
1.1.1.2   root     2175:                timestamp, userid1, n, e);
                   2176:        /* This was done to get us fps and pslength */
1.1.1.3 ! root     2177:        status = getsecretkey(GPK_GIVEUP, secring, keyID, timestamp,
1.1.1.2   root     2178:                passphrase, &hidekey, userid1, n, e, d, p, q, u);
                   2179: 
                   2180:        if (status < 0)         /* key not in secret keyring: edit owner trust */
                   2181:        {       int i;
                   2182: 
                   2183:                fprintf(pgpout, PSTR("\nNo secret key available.  Editing public key trust parameter.\n"));
                   2184:                if (trust_pos < 0)
                   2185:                {       fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), ringfile);
                   2186:                        fclose(f);
                   2187:                        return(-1);
                   2188:                }
                   2189:                show_key(f, fpp, SHOW_ALL);
                   2190: 
                   2191:                init_trust_lst();
                   2192:                fprintf(pgpout, PSTR("Current trust for this key's owner is: %s\n"),
                   2193:                                trust_lst[keyctrl & KC_OWNERTRUST_MASK]);
                   2194: 
                   2195:                PascalToC((char *)userid);      /* convert to C string for display */
                   2196:                i = ask_owntrust((char *) userid, keyctrl);
                   2197:                if (i == (keyctrl & KC_OWNERTRUST_MASK))
                   2198:                {       fclose(f);
                   2199:                        return(0);      /* unchanged */
                   2200:                }
                   2201: 
                   2202:                if (i < 0 || i > KC_OWNERTRUST_ALWAYS)
                   2203:                {
                   2204:                        fclose(f);
                   2205:                        return(-1);
                   2206:                }
                   2207:                keyctrl = (keyctrl & ~KC_OWNERTRUST_MASK) | i;
                   2208: 
                   2209:                fseek(f, trust_pos, SEEK_SET);
                   2210:                write_trust(f, keyctrl);
                   2211:                fclose(f);
                   2212:                fprintf (pgpout, PSTR("Public key ring updated.\n"));
                   2213:                return(0);
                   2214:        }
                   2215:        if (trust_pos > 0 && (keyctrl & (KC_BUCKSTOP|KC_OWNERTRUST_MASK)) !=
                   2216:                        (KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP))
                   2217:        {       /* key is in secret keyring but buckstop is not set */
                   2218:                fprintf(pgpout, PSTR("\nUse this key as an ultimately-trusted introducer (y/N)? "), userid);
                   2219:                if (getyesno('n'))
                   2220:                {       fseek(f, trust_pos, SEEK_SET);
                   2221:                        keyctrl = KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP;
                   2222:                        write_trust(f, keyctrl);
                   2223:                }
                   2224:        }
                   2225: 
                   2226:        /* Show user her ID again to be clear */
                   2227:        PascalToC((char *)userid);
                   2228:        fprintf(pgpout,PSTR("\nCurrent user ID: %s"),
                   2229:                LOCAL_CHARSET((char *)userid));
                   2230:        CToPascal((char *)userid);
                   2231: 
                   2232:        fprintf(pgpout, PSTR("\nDo you want to change your user ID (y/N)? "));
                   2233:        if (getyesno('n'))      /* user said yes */
                   2234:        {       fprintf(pgpout,PSTR("\nEnter the new user ID: "));
                   2235:                getstring((char *)userid,255,TRUE); /* echo keyboard input */
                   2236:                if (userid[0] == '\0')
                   2237:                {       fclose(f);
                   2238:                        return(-1);
                   2239:                }
                   2240:                CONVERT_TO_CANONICAL_CHARSET((char *)userid);
                   2241:                fprintf(pgpout, PSTR("\nMake this user ID the primary user ID for this key (y/N)? "));
                   2242:                if (!getyesno('n'))
                   2243:                {       /* position file pointer at selected user id */
                   2244:                        int pktlen;
                   2245:                        long fpuser;
                   2246: 
                   2247:                        strcpy((char *)userid1, mcguffin);
                   2248:                        if (getpubuserid(ringfile, fpp, userid1, &fpuser, &pktlen, FALSE) < 0)
                   2249:                        {       fclose(f);
                   2250:                                return(-1);
                   2251:                        }
                   2252:                        fseek(f, fpuser, SEEK_SET);
                   2253:                }
                   2254:                else    /* possition file pointer at key packet */
                   2255:                        fseek(f, fpp, SEEK_SET);
                   2256:                nextkeypacket(f, &ctb); /* skip userid or key packet */
                   2257:                do      /* new user id will be inserted before next userid or key packet */
                   2258:                {       fpp = ftell(f);
                   2259:                        if (nextkeypacket(f, &ctb) < 0)
                   2260:                                break;
                   2261:                } while (ctb != CTB_USERID && !is_key_ctb(ctb));
                   2262:                CToPascal((char *)userid);          /* convert to length-prefixed string */
                   2263:                changeID = TRUE;
                   2264:                changed = TRUE;
                   2265:        }
                   2266:        fclose(f);
                   2267: 
                   2268:        fprintf (pgpout,PSTR("\nDo you want to change your pass phrase (y/N)? "));
                   2269:        if (getyesno('n'))      /* user said yes */
                   2270:        {       hidekey = (GetHashedPassPhrase(passphrase, (char *) ideakey, 2) > 0);
                   2271:                changed = TRUE;
                   2272:        }
                   2273:        else
                   2274:        {       if (hidekey)
                   2275:                        hashpass( passphrase, strlen(passphrase), ideakey );
                   2276:        }
                   2277: 
                   2278:        if (!changed)
                   2279:        {       fprintf (pgpout, PSTR("(No changes will be made.)\n"));
                   2280:                if (hidekey)
                   2281:                        burn((byteptr)passphrase);
                   2282:                goto done;
                   2283:        }
                   2284: 
                   2285:        /* init CFB IDEA key */
                   2286:        if (hidekey)
                   2287:        {       fill0(iv,8);
                   2288:                initcfb_idea(iv,ideakey,FALSE);
                   2289:                burn((byteptr)passphrase);      /* burn sensitive data on stack */
                   2290:        }
                   2291: 
                   2292:        /* First write secret key data to a file */
                   2293:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2294:        writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u);
                   2295:        if (changeID)
                   2296:                keylen = -1;
                   2297:        else
                   2298:        {       /* don't copy userid */
                   2299:                f = fopen(fname, FOPRBIN);
                   2300:                if (f == NULL)
                   2301:                        goto err;
                   2302:                nextkeypacket(f, &ctb); /* skip key packet */
                   2303:                keylen = ftell(f);
                   2304:                fclose(f);
                   2305:        }
                   2306:        if (merge_key_to_ringfile(fname,secring,fps,pslength,keylen) < 0)
                   2307:        {       fprintf (pgpout, PSTR("\n\007Unable to update secret key ring.\n"));
                   2308:                goto err;
                   2309:        }
                   2310:        fprintf (pgpout, PSTR("\nSecret key ring updated...\n"));
                   2311: 
                   2312:        /* Now write public key data to file */
                   2313:        if (changeID)
                   2314:        {
                   2315:                if (insert_userid(ringfile, userid, fpp) < 0)
                   2316:                {       fprintf (pgpout, PSTR("\n\007Unable to update public key ring.\n"));
                   2317:                        goto err;
                   2318:                }
                   2319:                fprintf (pgpout, PSTR("Public key ring updated.\n"));
                   2320:        }
                   2321:        else
                   2322:                fprintf (pgpout, PSTR("(No need to update public key ring)\n"));
                   2323: 
                   2324:        if (hidekey)    /* done with IDEA to protect RSA secret key */
                   2325:                close_idea();
                   2326: 
                   2327:        rmtemp(fname);
                   2328: 
                   2329: done:
                   2330:        mp_burn(d);     /* burn sensitive data on stack */
                   2331:        mp_burn(p);     /*      "               "               "       "       "       */
                   2332:        mp_burn(q);     /*      "               "               "       "       "       */
                   2333:        mp_burn(u);     /*      "               "               "       "       "       */
                   2334:        mp_burn(e);     /*      "               "               "       "       "       */
                   2335:        mp_burn(n);     /*      "               "               "       "       "       */
                   2336:        burn(iv);       /*      "               "               "       "       "       */
                   2337: 
                   2338:        return(0);      /* normal return */
                   2339: err:
                   2340:        mp_burn(d);     /* burn sensitive data on stack */
                   2341:        mp_burn(p);     /*      "               "               "       "       "       */
                   2342:        mp_burn(q);     /*      "               "               "       "       "       */
                   2343:        mp_burn(u);     /*      "               "               "       "       "       */
                   2344:        mp_burn(e);     /*      "               "               "       "       "       */
                   2345:        mp_burn(n);     /*      "               "               "       "       "       */
                   2346:        burn(iv);       /*      "               "               "       "       "       */
                   2347: 
                   2348:        rmtemp(fname);
                   2349: 
                   2350:        return(-1);     /* error return */
                   2351: 
                   2352: }      /* dokeyedit */
                   2353: 
                   2354: 
1.1.1.3 ! root     2355: int disable_key(char *keyguffin, char *keyfile)
        !          2356: {      
        !          2357:        FILE *f;
        !          2358:        byte keyctrl;
        !          2359:        byte keyID[KEYFRAGSIZE];
        !          2360:        byte userid[256];
        !          2361:        unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION];
        !          2362:        long fp;
        !          2363:        int pktlen;
        !          2364: 
        !          2365:        strcpy((char *)userid, keyguffin);
        !          2366:        if (getpublickey(GPK_SHOW|GPK_DISABLED, keyfile, &fp, &pktlen, NULL,
        !          2367:                        NULL, userid, n, e) < 0)
        !          2368:                return(-1);
        !          2369: 
        !          2370:        extract_keyID(keyID, n);
        !          2371:        if (getsecretkey(GPK_GIVEUP, NULL, keyID, NULL, NULL, NULL,
        !          2372:                                         userid, n, e, NULL, NULL, NULL, NULL) >= 0)
        !          2373:        {       /* can only compromise if key also in secring */
        !          2374:                PascalToC((char *) userid);
        !          2375:                fprintf(pgpout, 
        !          2376: PSTR("\nDo you want to permanently revoke your public key\n\
        !          2377: by issuing a secret key compromise certificate\n\
        !          2378: for \"%s\" (y/N)? "), LOCAL_CHARSET((char *)userid));
        !          2379:                if (getyesno('n'))
        !          2380:                        return compromise(keyID, keyfile);
        !          2381:        }
        !          2382:        if ((f = fopen(keyfile,FOPRWBIN)) == NULL)
        !          2383:        {       fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile);
        !          2384:                return(-1);
        !          2385:        }
        !          2386:        fseek(f, fp+pktlen, SEEK_SET);
        !          2387:        if (read_trust(f, &keyctrl) < 0)
        !          2388:        {
        !          2389:                fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), keyfile);
        !          2390:                fprintf(pgpout, PSTR("You can only disable keys on your public keyring.\n"));
        !          2391:                fclose(f);
        !          2392:                return -1;
        !          2393:        }
        !          2394:        if (keyctrl & KC_DISABLED)
        !          2395:        {
        !          2396:                fprintf(pgpout, PSTR("\nKey is already disabled.\n\
        !          2397: Do you want to enable this key again (y/N)? "));
        !          2398:                keyctrl &= ~KC_DISABLED;
        !          2399:        }
        !          2400:        else
        !          2401:        {
        !          2402:                fprintf(pgpout, PSTR("\nDisable this key (y/N)? "));
        !          2403:                keyctrl |= KC_DISABLED;
        !          2404:        }
        !          2405:        if (!getyesno('n'))
        !          2406:        {       fclose(f);
        !          2407:                return -1;
        !          2408:        }
        !          2409:        write_trust_pos(f, keyctrl, fp+pktlen);
        !          2410:        fclose(f);
        !          2411:        return 0;
        !          2412: }      /* disable_key */
        !          2413: 
        !          2414: 
1.1.1.2   root     2415: /*======================================================================*/
                   2416: 
                   2417: 
                   2418: 
                   2419: int dokeygen(char *numstr, char *numstr2)
                   2420: /*     Do an RSA key pair generation, and write them out to the keyring files.
                   2421:        numstr is a decimal string, the desired bitcount for the modulus n.
                   2422:        numstr2 is a decimal string, the desired bitcount for the exponent e.
                   2423: */
                   2424: {      unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION],
                   2425:                 p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION];
                   2426:        char *fname;
                   2427:        char ringfile[MAX_PATH];
                   2428:        word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */
                   2429:        byte userid[256];
                   2430:        short keybits,ebits;
                   2431:        word32 tstamp; byte *timestamp = (byte *) &tstamp;              /* key certificate timestamp */
                   2432:        boolean hidekey;        /* TRUE iff secret key is encrypted */
1.1.1.3 ! root     2433:        boolean seedfileexists; /* FALSE if we need to create one */
1.1.1.2   root     2434:        byte ideakey[16];
                   2435: 
                   2436:        if (!numstr || strlen(numstr)==0)
                   2437:        {       fprintf(pgpout,PSTR("\nPick your RSA key size:\
                   2438: \n     1)       384 bits- Casual grade, fast but less secure\
                   2439: \n     2)       512 bits- Commercial grade, medium speed, good security\
                   2440: \n     3)      1024 bits- Military grade, very slow, highest security\
                   2441: \nChoose 1, 2, or 3, or enter desired number of bits: "));
                   2442:                numstr = (char *)userid;        /* use userid buffer as scratchpad */
                   2443:                getstring(numstr,5,TRUE);       /* echo keyboard */
                   2444:        }
                   2445: 
                   2446:        keybits = 0;
                   2447:        while ((*numstr>='0') && (*numstr<='9'))
                   2448:                keybits = keybits*10 + (*numstr++ - '0');
                   2449: 
                   2450:        if (keybits==0) /* user entered null response */
                   2451:                return(-1);     /* error return */
                   2452: 
                   2453:        /* Standard default key sizes: */
                   2454:        if (keybits==1) keybits=384;    /* Casual grade */
                   2455:        if (keybits==2) keybits=512;    /* Commercial grade */
                   2456:        if (keybits==3) keybits=1024;   /* Military grade */
                   2457: 
                   2458: #ifndef DEBUG
                   2459:        /* minimum RSA keysize: */
                   2460:        if (keybits<384) keybits=384;
                   2461:        if (keybits>1024) keybits=1024;
                   2462: #endif
                   2463: 
                   2464: #ifdef notdef  
                   2465: /*     If we use Merritt's modmult algorithm, the primes p and q's 
                   2466:        bit length should not be an exact multiple of UNITSIZE, 
                   2467:        because Merritt's modmult algorithm performs slowest in that 
                   2468:        case, wasting an extra unit of precision for overflow.
                   2469: */
                   2470:        if ((keybits % (2*UNITSIZE))==0)
                   2471:                keybits -= 2;   /* make each prime one bit shorter. */
                   2472: #endif /* MERRITT */
                   2473: 
                   2474:        ebits = 0;      /* number of bits in e */
                   2475:        while ((*numstr2>='0') && (*numstr2<='9')) 
                   2476:                ebits = ebits*10 + (*numstr2++ - '0');
                   2477: 
                   2478:        fprintf(pgpout,PSTR("\nGenerating an RSA key with a %d-bit modulus... "),keybits);
                   2479: 
                   2480:        fprintf(pgpout,
                   2481: PSTR("\nYou need a user ID for your public key.  The desired form for this\n\
                   2482: user ID is your name, followed by your E-mail address enclosed in\n\
                   2483: <angle brackets>, if you have an E-mail address.\n\
                   2484: For example:  John Q. Smith <[email protected]>\n"));
                   2485:        fprintf(pgpout,PSTR("\nEnter a user ID for your public key: \n"));
1.1.1.3 ! root     2486: #ifdef VMS
        !          2487:        putch('\n'); /* That last newline was just a return, do a real one */
        !          2488: #endif
1.1.1.2   root     2489:        getstring((char *)userid,255,TRUE);     /* echo keyboard input */
                   2490:        if (userid[0]=='\0')    /* user entered null response */
                   2491:                return(-1);     /* error return */
                   2492:        CONVERT_TO_CANONICAL_CHARSET((char *)userid);
                   2493:        CToPascal((char *)userid);      /* convert to length-prefixed string */
                   2494: 
                   2495:        {       char passphrase[256];
                   2496:                fprintf(pgpout,
                   2497: PSTR("\nYou need a pass phrase to protect your RSA secret key.\n\
                   2498: Your pass phrase can be any sentence or phrase and may have many\n\
                   2499: words, spaces, punctuation, or any other printable characters. "));
                   2500:                hidekey = (GetHashedPassPhrase(passphrase, (char *) ideakey, 2) > 0);
                   2501:                /* init CFB IDEA key */
                   2502:                if (hidekey)
                   2503:                {       fill0(iv,8);
                   2504:                        initcfb_idea(iv,ideakey,FALSE);
                   2505:                        burn((byteptr)passphrase);      /* burn sensitive data on stack */
1.1.1.3 ! root     2506:                        randaccum_later(64);    /* IV for encryption */
1.1.1.2   root     2507:                }
                   2508:        }
1.1.1.3 ! root     2509: /* As rsa_keygen does a major accumulation of random bits, if we need
        !          2510:    any others for a seed file, let's get them at the same time. */
        !          2511:        seedfileexists = seedfile_exists();
1.1.1.2   root     2512: 
                   2513:        fprintf(pgpout,PSTR("\nNote that key generation is a VERY lengthy process.\n"));
                   2514: 
                   2515:        if (rsa_keygen(n,e,d,p,q,u,keybits,ebits) < 0)
                   2516:        {       fprintf(pgpout,PSTR("\n\007Keygen failed!\n"));
                   2517:                return(-1);     /* error return */
                   2518:        }
                   2519: 
                   2520:        if (verbose)
                   2521:        {
                   2522:                fprintf(pgpout,PSTR("Key ID %s\n"), key2IDstring(n));
                   2523: 
                   2524:                mp_display(" modulus n = ",n);
                   2525:                mp_display("exponent e = ",e);
                   2526: 
                   2527:                mp_display("exponent d = ",d);
                   2528:                mp_display("   prime p = ",p);
                   2529:                mp_display("   prime q = ",q);
                   2530:                mp_display(" inverse u = ",u);
                   2531:        }
                   2532: 
                   2533:        get_timestamp(timestamp);       /* Timestamp when key was generated */
                   2534: 
                   2535:        fputc('\007',pgpout);  /* sound the bell when done with lengthy process */
                   2536:        fputc('\n',pgpout);
                   2537: 
                   2538:        /* First, write out the secret key... */
                   2539:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2540:        writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u); 
                   2541:        buildfilename(ringfile,SECRET_KEYRING_FILENAME);
                   2542:        if (file_exists(ringfile))
                   2543:        {       merge_key_to_ringfile(fname,ringfile,0L,0,-1L);
                   2544:                rmtemp(fname);
                   2545:        }
                   2546:        else
                   2547:                savetemp(fname, ringfile);
                   2548: 
                   2549:        /* Second, write out the public key... */
                   2550:        fname = tempfile(TMP_TMPDIR|TMP_WIPE);
                   2551:        writekeyfile(fname,FALSE,timestamp,userid,n,e,NULL,NULL,NULL,NULL);
                   2552:        buildfilename(ringfile,PUBLIC_KEYRING_FILENAME);
                   2553:        if (file_exists(ringfile))
                   2554:        {       merge_key_to_ringfile(fname,ringfile,0L,0,-1L);
                   2555:                rmtemp(fname);
                   2556:        }
                   2557:        else
                   2558:                savetemp(fname, ringfile);
                   2559:        
                   2560:        if (hidekey)    /* done with IDEA to protect RSA secret key */
                   2561:                close_idea();
                   2562: 
                   2563:        mp_burn(d);     /* burn sensitive data on stack */
                   2564:        mp_burn(p);     /* burn sensitive data on stack */
                   2565:        mp_burn(q);     /* burn sensitive data on stack */
                   2566:        mp_burn(u);     /* burn sensitive data on stack */
                   2567:        mp_burn(e);     /* burn sensitive data on stack */
                   2568:        mp_burn(n);     /* burn sensitive data on stack */
                   2569:        burn(iv);       /* burn sensitive data on stack */
                   2570: 
                   2571:        fprintf(pgpout,PSTR("\007Key generation completed.\n"));
                   2572: 
1.1.1.3 ! root     2573:        /*      If we need a seed file, create it now.
1.1.1.2   root     2574:        */
1.1.1.3 ! root     2575:        if (!seedfileexists)
        !          2576:                create_seedfile();
1.1.1.2   root     2577: 
                   2578:        return(0);      /* normal return */
                   2579: }      /* dokeygen */
                   2580: 

unix.superglobalmegacorp.com

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