--- pgp/src/keymgmt.c 2018/04/24 16:40:28 1.1.1.4 +++ pgp/src/keymgmt.c 2018/04/24 16:42:37 1.1.1.6 @@ -1,21 +1,22 @@ /* keymgmt.c - Key management routines for PGP. PGP: Pretty Good(tm) Privacy - public key cryptography for the masses. - (c) Copyright 1990-1992 by Philip Zimmermann. All rights reserved. + (c) Copyright 1990-1994 by Philip Zimmermann. All rights reserved. The author assumes no liability for damages resulting from the use of this software, even if the damage results from defects in this software. No warranty is expressed or implied. - All the source code Philip Zimmermann wrote for PGP is available for - free under the "Copyleft" General Public License from the Free - Software Foundation. A copy of that license agreement is included in - the source release package of PGP. Code developed by others for PGP - is also freely available. Other code that has been incorporated into - PGP from other sources was either originally published in the public - domain or was used with permission from the various authors. See the - PGP User's Guide for more complete information about licensing, - patent restrictions on certain algorithms, trademarks, copyrights, - and export controls. + Note that while most PGP source modules bear Philip Zimmermann's + copyright notice, many of them have been revised or entirely written + by contributors who frequently failed to put their names in their + code. Code that has been incorporated into PGP from other authors + was either originally published in the public domain or is used with + permission from the various authors. + + PGP is available for free to the public under certain restrictions. + See the PGP User's Guide (included in the release package) for + important information about licensing, patent restrictions on + certain algorithms, trademarks, copyrights, and export controls. */ #include @@ -27,7 +28,6 @@ #include #include "system.h" #include "mpilib.h" -#include "idea.h" #include "random.h" #include "crypto.h" #include "fileio.h" @@ -39,6 +39,7 @@ #include "md5.h" #include "charset.h" #include "keymaint.h" +#include "idea.h" /* @@ -64,9 +65,9 @@ static boolean userid_match(char *userid char buf[256], sub[256], *p; if (substr == NULL || *substr == '\0') - return(TRUE); + return TRUE; if (userid == NULL || *userid == '\0') - return(FALSE); + return FALSE; /* Check whether we have an ASCII or hex userID to check for */ if (n != NULL && substr[ 0 ] == '0' && to_lower( substr[ 1 ] ) == 'x' ) @@ -83,43 +84,40 @@ static boolean userid_match(char *userid for (i = 0; i <= sub_len; ++i) sub[i] = to_lower(substr[i]); - if (n == NULL) - { + if (n == NULL) { return !strcmp(buf, sub); } #ifdef MAGIC_MATCH - if (sub_len > 1 && sub[sub_len - 1] == '$') - { + if (sub_len > 1 && sub[sub_len - 1] == '$') { match_end = TRUE; sub[--sub_len] = '\0'; } - if (*sub == '^') - { if (match_end) - return(!strcmp(buf, sub + 1)); + if (*sub == '^') { + if (match_end) + return !strcmp(buf, sub + 1); else - return(!strncmp(buf, sub + 1, sub_len - 1)); + return !strncmp(buf, sub + 1, sub_len - 1); } #endif if (sub_len > id_len) - return(FALSE); + return FALSE; if (match_end) - return(!strcmp(buf + id_len - sub_len, sub)); + return !strcmp(buf + id_len - sub_len, sub); p = buf; - while ((p = strchr(p, *sub)) != NULL) - { + while ((p = strchr(p, *sub)) != NULL) { if (strncmp(p, sub, sub_len) == 0) - return(TRUE); + return TRUE; ++p; } - return(FALSE); + return FALSE; } int is_key_ctb (byte ctb) { - return(ctb == CTB_CERT_PUBKEY || ctb == CTB_CERT_SECKEY); + return ctb == CTB_CERT_PUBKEY || ctb == CTB_CERT_SECKEY; } @@ -127,52 +125,52 @@ is_key_ctb (byte ctb) ** keyIDstring ** ** Return printable key fragment, which is an abbreviation of the public -** key. Show LEAST significant 64 bits (KEYFRAGSIZE bytes) of modulus, +** key. Show LEAST significant 32 bits (KEYFRAGSIZE bytes) of modulus, ** LSB last. Yes, that's LSB LAST. */ +char const blankkeyID[] = " "; + char *keyIDstring( byte *keyID ) - { +{ short i; char *bufptr; /* ptr to Key ID string */ - static char keyIDbuf[2*KEYFRAGSIZE+1]; + static char keyIDbuf[9]; - /* only show bottom 3 bytes of keyID */ + /* only show bottom 4 bytes of keyID */ bufptr = keyIDbuf; #ifdef XLOWFIRST - /* - ** LSB-first keyID format - */ + /* LSB-first keyID format */ - for (i = 2; i >= 0; i--) + for (i = 3; i >= 0; i--) { sprintf( bufptr, "%02X", keyID[i] ); bufptr += 2; } #else - /* - ** MSB-first keyID format - */ + /* MSB-first keyID format */ - for (i = KEYFRAGSIZE-3; i < KEYFRAGSIZE; i++) + for (i = KEYFRAGSIZE-4; i < KEYFRAGSIZE; i++) { sprintf( bufptr, "%02X", keyID[i] ); bufptr += 2; } #endif *bufptr = '\0'; - return( keyIDbuf ); - } /* keyIDstring */ + return keyIDbuf; +} /* keyIDstring */ void extract_keyID(byteptr keyID, unitptr n) -/* Extract key fragment from modulus n. keyID byte array must be - at least KEYFRAGSIZE bytes long. +/* + * Extract key fragment from modulus n. keyID byte array must be + * at least KEYFRAGSIZE bytes long. */ -{ byte buf[MAX_BYTE_PRECISION+2]; +{ + byte buf[MAX_BYTE_PRECISION+2]; short i, j; fill0(buf,KEYFRAGSIZE+2); /* in case n is too short */ @@ -191,7 +189,7 @@ void extract_keyID(byteptr keyID, unitpt keyID[j++] = buf[i++]; #endif -} /* extract_keyID */ +} /* extract_keyID */ @@ -200,10 +198,11 @@ char *key2IDstring(unitptr n) and return printable string of key ID. n is key modulus from which to extract keyID. */ -{ byte keyID[KEYFRAGSIZE]; +{ + byte keyID[KEYFRAGSIZE]; extract_keyID(keyID, n); - return (keyIDstring(keyID)); -} /* key2IDstring */ + return keyIDstring(keyID); +} /* key2IDstring */ @@ -211,7 +210,7 @@ static void showkeyID(byteptr keyID) /* Print key fragment, which is an abbreviation of the public key. */ { fprintf(pgpout,"%s",keyIDstring(keyID)); -} /* showkeyID */ +} /* showkeyID */ @@ -219,10 +218,11 @@ void writekeyID(unitptr n, FILE *f) /* Write message prefix keyID to a file. n is key modulus from which to extract keyID. */ -{ byte keyID[KEYFRAGSIZE]; +{ + byte keyID[KEYFRAGSIZE]; extract_keyID(keyID, n); fwrite(keyID,1,KEYFRAGSIZE,f); -} /* writekeyID */ +} /* writekeyID */ @@ -231,10 +231,10 @@ static boolean checkkeyID(byte *keyID, u { byte keyID0[KEYFRAGSIZE]; if (keyID==NULL) /* no key ID -- assume a good match */ - return (TRUE); + return TRUE; extract_keyID(keyID0, n); - return(equal_buffers(keyID,keyID0,KEYFRAGSIZE)); -} /* checkkeyID */ + return equal_buffers(keyID,keyID0,KEYFRAGSIZE); +} /* checkkeyID */ @@ -245,19 +245,15 @@ void write_trust (FILE *f, byte trustbyt /* Write a key control packet to f, with the specified trustbyte data. */ { - byte ctb; - byte keyctrllen; - - ctb = CTB_KEYCTRL; - fwrite(&ctb,1,1,f); /* write key control header byte */ - keyctrllen = 1; - fwrite(&keyctrllen,1,1,f); /* write key control length */ - fwrite(&trustbyte,1,1,f); /* write key control */ + putc(CTB_KEYCTRL, f); /* Key control header byte */ + putc(1, f); /* Key control length */ + putc(trustbyte, f); /* Key control byte */ } static -short writekeyfile(char *fname, boolean hidekey, byte *timestamp, byte *userid, - unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u) +short writekeyfile(char *fname, struct IdeaCfbContext *cfb, word32 timestamp, + byte *userid, unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, + unitptr u) /* Write key components p, q, n, e, d, and u to specified file. hidekey is TRUE iff key should be encrypted. userid is a length-prefixed Pascal-type character string. @@ -265,7 +261,8 @@ short writekeyfile(char *fname, boolean a userid packet. We assume the key being written is our own, so we set the control bits for full trust. */ -{ FILE *f; +{ + FILE *f; byte ctb; byte alg, version; word16 validity; @@ -275,38 +272,37 @@ short writekeyfile(char *fname, boolean int i; /* open file f for write, in binary (not text) mode...*/ - if ((f = fopen(fname,FOPWBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Unable to create key file '%s'.\n"), fname); - return(-1); + if ((f = fopen(fname,FOPWBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Unable to create key file '%s'.\n"), fname); + return -1; } /*** Begin key certificate header fields ***/ - if (d==NULL) - { /* public key certificate */ + if (d==NULL) { + /* public key certificate */ ctb = CTB_CERT_PUBKEY; cert_length = 1 + SIZEOF_TIMESTAMP + 2 + 1 + (countbytes(n)+2) + (countbytes(e)+2); - } /* public key certificate */ - else - { /* secret key certificate */ + } else { + /* secret key certificate */ ctb = CTB_CERT_SECKEY; cert_length = 1 + SIZEOF_TIMESTAMP + 2 + 1 + (countbytes(n)+2) + (countbytes(e)+2) - + 1 + (hidekey ? 8 : 0) /* IDEA algorithm byte and IV */ + + 1 + (cfb ? 8 : 0) /* IDEA algorithm byte and IV */ + (countbytes(d)+2) + (countbytes(p)+2) + (countbytes(q)+2) + (countbytes(u)+2) + 2; - } /* secret key certificate */ + } fwrite(&ctb,1,1,f); /* write key certificate header byte */ convert(cert_length); /* convert to external byteorder */ fwrite(&cert_length,1,sizeof(cert_length),f); - version = VERSION_BYTE; + version = version_byte; fwrite(&version,1,1,f); /* set version number */ - convert_byteorder(timestamp,4); /* convert to external form */ - fwrite(timestamp,1,4,f); /* write certificate timestamp */ - convert_byteorder(timestamp,4); /* convert back to internal form */ + memcpy(iv, ×tamp, 4); + convert_byteorder(iv,4); /* convert to external form */ + fwrite(iv,1,4,f); /* write certificate timestamp */ validity = 0; fwrite (&validity,1,sizeof(validity),f); /* validity period */ alg = RSA_ALGORITHM_BYTE; @@ -314,24 +310,22 @@ short writekeyfile(char *fname, boolean write_mpi(n,f,FALSE); write_mpi(e,f,FALSE); - if (is_secret_key(ctb)) /* secret key */ - { + if (is_secret_key(ctb)) { /* secret key */ /* Write byte for following algorithm */ - alg = (hidekey)?IDEA_ALGORITHM_BYTE:0; - fwrite(&alg,1,1,f); + alg = cfb ? IDEA_ALGORITHM_BYTE : 0; + putc(alg, f); - if (hidekey) /* store encrypted IV */ - { for (i=0; i<8; i++) - iv[i] = randombyte(); - if (hidekey) /* encrypt the IV */ - ideacfb(iv,8); + if (cfb) { /* store encrypted IV */ + for (i=0; i<8; i++) + iv[i] = trueRandByte(); + ideaCfbEncrypt(cfb, iv, iv, 8); fwrite(iv,1,8,f); /* write out the IV */ } mpi_checksum = 0; - write_mpi(d,f,hidekey); - write_mpi(p,f,hidekey); - write_mpi(q,f,hidekey); - write_mpi(u,f,hidekey); + write_mpi(d,f,cfb); + write_mpi(p,f,cfb); + write_mpi(q,f,cfb); + write_mpi(u,f,cfb); /* Write checksum here - based on plaintext values */ convert(mpi_checksum); fwrite (&mpi_checksum,1,sizeof(mpi_checksum),f); @@ -345,8 +339,8 @@ short writekeyfile(char *fname, boolean fwrite(userid,1,userid[0]+1,f); /* write user ID */ if (d == NULL) /* only on public keyring */ write_trust (f, KC_LEGIT_COMPLETE); - if (write_error(f)) - { fclose(f); + if (write_error(f)) { + fclose(f); return -1; } fclose(f); @@ -355,8 +349,8 @@ short writekeyfile(char *fname, boolean countbits(n), is_secret_key(ctb) ? "secret" : "public" , fname); - return(0); -} /* writekeyfile */ + return 0; +} /* writekeyfile */ @@ -372,49 +366,49 @@ short nextkeypacket(FILE *f, byte *pctb) *pctb = 0; /* assume no ctb for caller at first */ count = fread(&ctb,1,1,f); /* read key certificate CTB byte */ - if (count==0) return(-1); /* premature eof */ + if (count==0) return -1; /* premature eof */ *pctb = ctb; /* returns type to caller */ if ((ctb != CTB_CERT_PUBKEY) && (ctb != CTB_CERT_SECKEY) && (ctb != CTB_USERID) && (ctb != CTB_KEYCTRL) && !is_ctb_type(ctb,CTB_SKE_TYPE) && !is_ctb_type(ctb,CTB_COMMENT_TYPE)) /* Either bad key packet or X/Ymodem padding detected */ - return ((ctb == 0x1A) ? -1 : -2); + return (ctb == 0x1A) ? -1 : -2; cert_length = getpastlength(ctb, f); /* read certificate length */ if (cert_length > MAX_KEYCERT_LENGTH-3) - return(-3); /* bad length */ + return -3; /* bad length */ fseek(f, cert_length, SEEK_CUR); - return(0); + return 0; } /* nextkeypacket */ -short readkeypacket(FILE *f, boolean hidekey, byte *pctb, +short readkeypacket(FILE *f, struct IdeaCfbContext *cfb, byte *pctb, byte *timestamp, char *userid, unitptr n ,unitptr e, unitptr d, unitptr p, unitptr q, unitptr u, byte *sigkeyID, byte *keyctrl) -/* Reads a key certificate from the current file position of file f. - Depending on the certificate type, it will set the proper fields - of the return arguments. Other fields will not be set. - pctb is always set. - If the packet is CTB_CERT_PUBKEY or CTB_CERT_SECKEY, it will - return timestamp, n, e, and if the secret key components are - present and d is not NULL, it will read, decrypt if hidekey is - true, and return d, p, q, and u. - If the packet is CTB_KEYCTRL, it will return keyctrl as that byte. - If the packet is CTB_USERID, it will return userid. - If the packet is CTB_COMMENT_TYPE, it won't return anything extra. - The file pointer is left positioned after the certificate. - - If the key could not be read because of a version error or bad - data, the return value is -6 or -4, the file pointer will be - positioned after the certificate, only the arguments pctb and - userid will valid in this case, other arguments are undefined. - Return value -3 means the error is unrecoverable. - -*/ +/* + * Reads a key certificate from the current file position of file f. + * Depending on the certificate type, it will set the proper fields + * of the return arguments. Other fields will not be set. + * pctb is always set. + * If the packet is CTB_CERT_PUBKEY or CTB_CERT_SECKEY, it will + * return timestamp, n, e, and if the secret key components are + * present and d is not NULL, it will read, decrypt if hidekey is + * true, and return d, p, q, and u. + * If the packet is CTB_KEYCTRL, it will return keyctrl as that byte. + * If the packet is CTB_USERID, it will return userid. + * If the packet is CTB_COMMENT_TYPE, it won't return anything extra. + * The file pointer is left positioned after the certificate. + * + * If the key could not be read because of a version error or bad + * data, the return value is -6 or -4, the file pointer will be + * positioned after the certificate, only the arguments pctb and + * userid will valid in this case, other arguments are undefined. + * Return value -3 means the error is unrecoverable. + */ { byte ctb; word16 cert_length; @@ -429,45 +423,44 @@ short readkeypacket(FILE *f, boolean hid /*** Begin certificate header fields ***/ *pctb = 0; /* assume no ctb for caller at first */ count = fread(&ctb,1,1,f); /* read key certificate CTB byte */ - if (count==0) return(-1); /* premature eof */ + if (count==0) return -1; /* premature eof */ *pctb = ctb; /* returns type to caller */ if ((ctb != CTB_CERT_PUBKEY) && (ctb != CTB_CERT_SECKEY) && (ctb != CTB_USERID) && (ctb != CTB_KEYCTRL) && !is_ctb_type(ctb,CTB_SKE_TYPE) && !is_ctb_type(ctb,CTB_COMMENT_TYPE)) /* Either bad key packet or X/Ymodem padding detected */ - return ((ctb == 0x1A) ? -1 : -2); + return (ctb == 0x1A) ? -1 : -2; cert_length = getpastlength(ctb, f); /* read certificate length */ if (cert_length > MAX_KEYCERT_LENGTH-3) - return(-3); /* bad length */ + return -3; /* bad length */ next_packet = ftell(f) + cert_length; - /* skip packet and return, keeps us in sync when we hit a - version error or bad data */ -#define SKIP_RETURN(x) \ - do \ - { \ - fseek(f,next_packet,SEEK_SET); \ - return(x); \ - } while(0) - - if (ctb == CTB_USERID) - { if (cert_length > 255) - return(-3); /* Bad length error */ - if (userid) - { userid[0] = cert_length; /* Save user ID length */ + /* + * skip packet and return, keeps us in sync when we hit a + * version error or bad data. Implemented oddly to make it + * only one statement. + */ +#define SKIP_RETURN(x) return fseek(f, next_packet, SEEK_SET), x + + if (ctb == CTB_USERID) { + if (cert_length > 255) + return -3; /* Bad length error */ + if (userid) { + userid[0] = cert_length; /* Save user ID length */ fread(userid+1,1,cert_length,f); /* read rest of user ID */ } else fseek (f, (long)cert_length, SEEK_CUR); - return(0); /* normal return */ - } - else if (is_ctb_type (ctb, CTB_SKE_TYPE)) - { if (sigkeyID) - { fread(&version,1,1,f); /* Read version of sig packet */ - if (version_error(version, VERSION_BYTE)) + return 0; /* normal return */ + + } else if (is_ctb_type (ctb, CTB_SKE_TYPE)) { + + if (sigkeyID) { + fread(&version,1,1,f); /* Read version of sig packet */ + if (version_byte_error(version)) SKIP_RETURN(-6); /* Need a later version */ /* Skip timestamp, validity period, and type byte */ fread(&mdlen, 1, 1, f); @@ -476,30 +469,32 @@ short readkeypacket(FILE *f, boolean hid fread(sigkeyID,1,KEYFRAGSIZE,f); } SKIP_RETURN(0); /* normal return */ - } - else if (ctb == CTB_KEYCTRL) - { if (cert_length != 1) - return(-3); /* Bad length error */ + + } else if (ctb == CTB_KEYCTRL) { + + if (cert_length != 1) + return -3; /* Bad length error */ if (keyctrl) fread(keyctrl,1,cert_length,f); /* Read key control byte */ else fseek (f, (long)cert_length, SEEK_CUR); - return(0); /* normal return */ - } - else if (!is_key_ctb(ctb)) /* comment or other packet */ + return 0; /* normal return */ + + } else if (!is_key_ctb(ctb)) /* comment or other packet */ SKIP_RETURN(0); /* normal return */ /* Here we have a key packet */ if (n != NULL) set_precision(MAX_UNIT_PRECISION); /* safest opening assumption */ fread(&version,1,1,f); /* read and check version */ - if (version_error(version, VERSION_BYTE)) + if (version_byte_error(version)) SKIP_RETURN(-6); /* Need a later version */ - if (timestamp) - { fread(timestamp,1,SIZEOF_TIMESTAMP,f); /* read certificate timestamp */ + if (timestamp) { + fread(timestamp,1,SIZEOF_TIMESTAMP,f); /* read certificate timestamp */ convert_byteorder(timestamp,SIZEOF_TIMESTAMP); /* convert from external form */ - } else + } else { fseek(f, (long)SIZEOF_TIMESTAMP, SEEK_CUR); + } fread(&validity,1,sizeof(validity),f); /* Read validity period */ convert(validity); /* convert from external byteorder */ /* We don't use validity period yet */ @@ -527,102 +522,104 @@ short readkeypacket(FILE *f, boolean hid if (d==NULL) /* skip rest of this key certificate */ SKIP_RETURN(0); /* Normal return */ - if (is_secret_key(ctb)) - { + + if (is_secret_key(ctb)) { fread (&alg,1,1,f); if (alg && version_error(alg,IDEA_ALGORITHM_BYTE)) - SKIP_RETURN(-6); /* Unknown version */ + SKIP_RETURN(-6); /* Unknown version */ - if (!hidekey && alg) + if (!cfb && alg) /* Don't bother trying if hidekey is false and alg is true */ SKIP_RETURN(-5); - if (alg) /* if secret components are encrypted... */ - { /* process encrypted CFB IV before reading secret components */ + if (alg) { /* if secret components are encrypted... */ + /* process encrypted CFB IV before reading secret components */ count = fread(iv,1,8,f); if (count < 8) - return(-4); /* data corrupted, error return */ - ideacfb(iv,8); + return -4; /* data corrupted, error return */ + + ideaCfbDecrypt(cfb, iv, iv, 8); cert_length -= 8; /* take IV length into account */ } /* Reset checksum before these reads */ mpi_checksum = 0; - if (read_mpi(d,f,FALSE,hidekey) < 0) - return(-4); /* data corrupted, error return */ - if (read_mpi(p,f,FALSE,hidekey) < 0) - return(-4); /* data corrupted, error return */ - if (read_mpi(q,f,FALSE,hidekey) < 0) - return(-4); /* data corrupted, error return */ + if (read_mpi(d,f,FALSE,cfb) < 0) + return -4; /* data corrupted, error return */ + if (read_mpi(p,f,FALSE,cfb) < 0) + return -4; /* data corrupted, error return */ + if (read_mpi(q,f,FALSE,cfb) < 0) + return -4; /* data corrupted, error return */ /* use register 'u' briefly as scratchpad */ mp_mult(u,p,q); /* compare p*q against n */ if (mp_compare(n,u)!=0) /* bad pass phrase? */ - return(-5); /* possible bad pass phrase, error return */ + return -5; /* possible bad pass phrase, error return */ /* now read in real u */ - if (read_mpi(u,f,FALSE,hidekey) < 0) - return(-4); /* data corrupted, error return */ + if (read_mpi(u,f,FALSE,cfb) < 0) + return -4; /* data corrupted, error return */ /* Read checksum, compare with mpi_checksum */ fread (&chksum,1,sizeof(chksum),f); convert(chksum); if (chksum != mpi_checksum) - return(-5); /* possible bad pass phrase */ + return -5; /* possible bad pass phrase */ cert_length -= 1 + (countbytes(d)+2) + (countbytes(p)+2) + (countbytes(q)+2) + (countbytes(u)+2) + 2; - } /* secret key */ - else /* not a secret key */ - { mp_init(d,0); + } else { /* not a secret key */ + + mp_init(d,0); mp_init(p,0); mp_init(q,0); mp_init(u,0); } - if (cert_length != 0) - { fprintf(pgpout,"\n\007Corrupted key. Bad length, off by %d bytes.\n", + if (cert_length != 0) { + fprintf(pgpout,"\n\007Corrupted key. Bad length, off by %d bytes.\n", (int) cert_length); SKIP_RETURN(-4); /* data corrupted, error return */ } - return(0); /* normal return */ + return 0; /* normal return */ -} /* readkeypacket */ +} /* readkeypacket */ int getpublickey(int flags, char *keyfile, long *_file_position, int *_pktlen, byte *keyID, byte *timestamp, byte *userid, unitptr n, unitptr e) -/* keyID contains key fragment we expect to find in keyfile. - If keyID is NULL, then userid contains a C string search target of - userid to find in keyfile. - keyfile is the file to begin search in, and it may be modified - to indicate true filename of where the key was found. It can be - either a public key file or a secret key file. - file_position is returned as the byte offset within the keyfile - that the key was found at. pktlen is the length of the key packet. - These values are for the key packet itself, not including any - following userid, control, signature, or comment packets. - - possible flags: - GPK_GIVEUP: we are just going to do a single file search only. - GPK_SHOW: show the key if found. - GPK_NORVK: skip revoked keys. - GPK_DISABLED: don't ignore disabled keys (when doing userid lookup) - - Returns -6 if the key was found but the key was not read because of a - version error or bad data. The arguments timestamp, n and e are - undefined in this case. -*/ +/* + * keyID contains key fragment we expect to find in keyfile. + * If keyID is NULL, then userid contains a C string search target of + * userid to find in keyfile. + * keyfile is the file to begin search in, and it may be modified + * to indicate true filename of where the key was found. It can be + * either a public key file or a secret key file. + * file_position is returned as the byte offset within the keyfile + * that the key was found at. pktlen is the length of the key packet. + * These values are for the key packet itself, not including any + * following userid, control, signature, or comment packets. + * + * possible flags: + * GPK_GIVEUP: we are just going to do a single file search only. + * GPK_SHOW: show the key if found. + * GPK_NORVK: skip revoked keys. + * GPK_DISABLED: don't ignore disabled keys (when doing userid lookup) + * GPK_SECRET: looking for a secret key + * + * Returns -6 if the key was found but the key was not read because of a + * version error or bad data. The arguments timestamp, n and e are + * undefined in this case. + */ { byte ctb; /* returned by readkeypacket */ FILE *f; int status, keystatus = -1; boolean keyfound = FALSE; - boolean secret = FALSE; char matchid[256]; /* C string format */ long fpos; long file_position = 0; @@ -637,18 +634,19 @@ int getpublickey(int flags, char *keyfil top: if (strlen(keyfile) == 0) /* null filename */ - return(-1); /* give up, error return */ + return -1; /* give up, error return */ default_extension(keyfile,PGP_EXTENSION); - if (!file_exists(keyfile)) - { if (flags & GPK_GIVEUP) - return(-1); /* give up, error return */ - fprintf(pgpout,PSTR("\n\007Keyring file '%s' does not exist. "),keyfile); + if (!file_exists(keyfile)) { + if (flags & GPK_GIVEUP) + return -1; /* give up, error return */ + fprintf(pgpout,LANG("\n\007Keyring file '%s' does not exist. "),keyfile); goto nogood; } - if (verbose) - { fprintf(pgpout,"searching key ring file '%s' ",keyfile); + + if (verbose) { + fprintf(pgpout,"searching key ring file '%s' ",keyfile); if (keyID) fprintf(pgpout, "for keyID %s\n", keyIDstring(keyID)); else @@ -657,49 +655,47 @@ top: /* open file f for read, in binary (not text) mode...*/ if ((f = fopen(keyfile,FOPRBIN)) == NULL) - return(-1); /* error return */ + return -1; /* error return */ keyfound = FALSE; - while (TRUE) - { + for (;;) { fpos = ftell(f); - status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e, - NULL,NULL,NULL,NULL,NULL,NULL); + status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid, + n, e, NULL,NULL,NULL,NULL,NULL,NULL); /* Note that readkeypacket has called set_precision */ if (status == -1) /* end of file */ break; - if (status < -1 && status != -4 && status != -6) - { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), + if (status < -1 && status != -4 && status != -6) { + fprintf(pgpout,LANG("\n\007Could not read key from file '%s'.\n"), keyfile); fclose(f); /* close key file */ - return(status); + return status; } /* Remember packet position and size for last key packet */ - if (is_key_ctb(ctb)) - { file_position = fpos; + if (is_key_ctb(ctb)) { + file_position = fpos; pktlen = (int)(ftell(f) - fpos); - secret = is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE); keystatus = status; - if (!keyID && !(flags & GPK_DISABLED) && !secret - && read_trust(f, &keyctrl) == 0 - && (keyctrl & KC_DISABLED)) + if (!keyID && !(flags & GPK_DISABLED) && + is_ctb_type(ctb, CTB_CERT_SECKEY_TYPE) && + read_trust(f, &keyctrl) == 0 && + (keyctrl & KC_DISABLED)) skip = TRUE; else skip = FALSE; } /* Only check for matches when we find a USERID packet */ - if (!skip && ctb == CTB_USERID) - { /* keyID contains key fragment. Check it against n from keyfile. */ - if (keyID!=NULL) - { if (keystatus == 0) + if (!skip && ctb == CTB_USERID) { + /* keyID contains key fragment. Check it against n from keyfile. */ + if (keyID!=NULL) { + if (keystatus == 0) keyfound = checkkeyID(keyID,n); - } - else - { /* matchid is already a C string */ + } else { + /* matchid is already a C string */ PascalToC((char *)userid); /* for C string functions */ /* Accept any matching subset */ keyfound = userid_match((char *)userid,matchid,n); @@ -707,18 +703,17 @@ top: } } - if (keyfound) - { if (flags & GPK_SHOW) + if (keyfound) { + if (flags & GPK_SHOW) show_key(f, file_position, 0); fseek(f, file_position, SEEK_SET); if ((flags&GPK_NORVK) && keystatus == 0 && is_compromised(f)) { - if (flags&GPK_SHOW) /* already printed user ID */ - fprintf(pgpout, PSTR("\n\007Sorry, this key has been revoked by its owner.\n")); - else - { + if (flags&GPK_SHOW) { /* already printed user ID */ + fprintf(pgpout, LANG("\n\007Sorry, this key has been revoked by its owner.\n")); + } else { PascalToC((char *) userid); - fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n\ + fprintf(pgpout, LANG("\nKey for user ID \"%s\"\n\ has been revoked. You cannot use this key.\n"), LOCAL_CHARSET((char *)userid)); } @@ -726,15 +721,14 @@ has been revoked. You cannot use this k skip = TRUE; /* we're positioned at the key packet, skip it */ nextkeypacket(f, &ctb); - } - else - { /* found key, normal return */ + } else { + /* found key, normal return */ if (_pktlen) *_pktlen = pktlen; if (_file_position) *_file_position = file_position; fclose(f); - return(keystatus); + return keystatus; } } } /* while TRUE */ @@ -742,31 +736,28 @@ has been revoked. You cannot use this k fclose(f); /* close key file */ if (flags & GPK_GIVEUP) - return(-1); /* give up, error return */ + return -1; /* give up, error return */ - if (keyID!=NULL) - { - fprintf(pgpout,PSTR("\n\007Key matching expected Key ID %s not found in file '%s'.\n"), + if (keyID!=NULL) { + fprintf(pgpout,LANG("\n\007Key matching expected Key ID %s not found in file '%s'.\n"), keyIDstring(keyID),keyfile); - } - else - { fprintf(pgpout,PSTR("\n\007Key matching userid '%s' not found in file '%s'.\n"), - LOCAL_CHARSET(matchid),keyfile); + } else { + fprintf(pgpout,LANG("\n\007Key matching userid '%s' not found in file '%s'.\n"), LOCAL_CHARSET(matchid),keyfile); } nogood: if (filter_mode || batchmode) - return(-1); /* give up, error return */ + return -1; /* give up, error return */ - if (secret) - fprintf(pgpout,PSTR("Enter secret key filename: ")); + if (flags & GPK_SECRET) + fprintf(pgpout,LANG("Enter secret key filename: ")); else - fprintf(pgpout,PSTR("Enter public key filename: ")); + fprintf(pgpout,LANG("Enter public key filename: ")); getstring(keyfile,59,TRUE); /* echo keyboard input */ goto top; -} /* getpublickey */ +} /* getpublickey */ int getpubuserid(char *keyfile, long key_position, byte *userid, @@ -788,25 +779,24 @@ int getpubuserid(char *keyfile, long key /* open file f for read, in binary (not text) mode...*/ if ((f = fopen(keyfile,FOPRBIN)) == NULL) - return(-1); /* error return */ + return -1; /* error return */ /* Start off at correct location */ fseek (f, key_position, SEEK_SET); (void)nextkeypacket(f, &ctb); /* Skip key */ - while (TRUE) - { + for (;;) { fpos = ftell(f); status = readkeypacket(f,FALSE,&ctb,NULL,(char *)userid0,n,e, NULL,NULL,NULL,NULL,NULL,NULL); - if (status < 0 || is_key_ctb(ctb)) - { fclose(f); /* close key file */ - return(status ? status : -1); /* give up, error return */ + if (status < 0 || is_key_ctb(ctb)) { + fclose(f); /* close key file */ + return status ? status : -1; /* give up, error return */ } /* Only check for matches when we find a USERID packet */ - if (ctb == CTB_USERID) - { if (userid[0] == '0' && userid[1] == 'x') + if (ctb == CTB_USERID) { + if (userid[0] == '0' && userid[1] == 'x') break; /* use first userid if user specified a keyID */ /* userid is already a C string */ PascalToC((char *)userid0); /* for C string functions */ @@ -815,20 +805,23 @@ int getpubuserid(char *keyfile, long key (exact_match ? NULL : n))) break; } - } /* while TRUE */ + } /* for(;;) */ *userid_position = fpos; *userid_len = ( int ) ( ftell(f) - fpos ); fclose(f); - return(0); /* normal return */ -} /* getpubuserid */ + return 0; /* normal return */ +} /* getpubuserid */ int getpubusersig(char *keyfile, long user_position, byte *sigkeyID, - long *sig_position, int *sig_len) -/* Start at user_position in keyfile, and scan for the signature packet - that matches sigkeyID. Return sig_position and sig_len. - Return 0 if OK, -1 on error. -*/ + byte *timestamp, long *sig_position, int *sig_len) +/* + * Start at user_position in keyfile, and scan for the signature packet + * that matches sigkeyID. Return the signature timestamp, sig_position + * and sig_len. + * + * Return 0 if OK, -1 on error. + */ { byte ctb; /* returned by readkeypacket */ FILE *f; @@ -838,13 +831,12 @@ int getpubusersig(char *keyfile, long us /* open file f for read, in binary (not text) mode...*/ if ((f = fopen(keyfile,FOPRBIN)) == NULL) - return(-1); /* error return */ + return -1; /* error return */ /* Start off at correct location */ fseek (f, user_position, SEEK_SET); (void)nextkeypacket(f, &ctb); /* Skip userid packet */ - while (TRUE) - { + for (;;) { fpos = ftell(f); status = readkeypacket(f,FALSE,&ctb,NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL,keyID0,NULL); @@ -853,35 +845,39 @@ int getpubusersig(char *keyfile, long us break; /* Only check for matches when we find a signature packet */ - if (is_ctb_type(ctb,CTB_SKE_TYPE)) - { if (equal_buffers(sigkeyID,keyID0,KEYFRAGSIZE)) - { *sig_position = fpos; + if (is_ctb_type(ctb,CTB_SKE_TYPE)) { + if (equal_buffers(sigkeyID,keyID0,KEYFRAGSIZE)) { + *sig_position = fpos; *sig_len = ( int ) ( ftell(f) - fpos ); + fseek(f, fpos+6, SEEK_SET); + fread(timestamp,1,SIZEOF_TIMESTAMP,f); /* read certificate timestamp */ + convert_byteorder(timestamp,SIZEOF_TIMESTAMP); /* convert from external form */ fclose(f); - return(0); /* normal return */ + return 0; /* normal return */ } } - } /* while TRUE */ + } /* for (;;) */ fclose(f); /* close key file */ - return(status ? status : -1); /* give up, error return */ -} /* getpubusersig */ + return status ? status : -1; /* give up, error return */ +} /* getpubusersig */ int getsecretkey(int flags, char *keyfile, byte *keyID, byte *timestamp, byte *hpass, boolean *hkey, byte *userid, unitptr n, unitptr e, unitptr d, unitptr p, unitptr q, unitptr u) -/* keyID contains key fragment we expect to find in keyfile. - If keyID is NULL, then userid contains search target of - userid to find in keyfile. - giveup controls whether we ask the user for the name of the - secret key file on failure. showkey controls whether we print - out the key information when we find it. keyfile, if non-NULL, - is the name of the secret key file; if NULL, we use the - default. hpass and hkey, if non-NULL, get returned with a copy - of the hashed password buffer and hidekey variable. -*/ +/* + * keyID contains key fragment we expect to find in keyfile. + * If keyID is NULL, then userid contains search target of + * userid to find in keyfile. + * giveup controls whether we ask the user for the name of the + * secret key file on failure. showkey controls whether we print + * out the key information when we find it. keyfile, if non-NULL, + * is the name of the secret key file; if NULL, we use the + * default. hpass and hkey, if non-NULL, get returned with a copy + * of the hashed password buffer and hidekey variable. + */ { byte ctb; /* returned by readkeypacket */ FILE *f; @@ -891,28 +887,29 @@ int getsecretkey(int flags, char *keyfil boolean hidekey; /* TRUE iff secret key is encrypted */ word16 iv[4]; /* initialization vector for encryption */ byte ideakey[16]; - int guesses = 3; + int guesses; struct hashedpw *hpw, **hpwp; + struct IdeaCfbContext cfb; - if (keyfile == NULL) - { /* use default pathname */ - buildfilename(keyfilename,SECRET_KEYRING_FILENAME); + if (keyfile == NULL) { + /* use default pathname */ + strcpy(keyfilename, globalSecringName); keyfile = keyfilename; } - status = getpublickey(flags, keyfile, &file_position, NULL, keyID, - timestamp, userid, n, e); + status = getpublickey(flags | GPK_SECRET, keyfile, &file_position, + NULL, keyID, timestamp, userid, n, e); if (status < 0) - return(status); /* error return */ + return status; /* error return */ /* open file f for read, in binary (not text) mode...*/ if ((f = fopen(keyfile,FOPRBIN)) == NULL) - return(-1); /* error return */ + return -1; /* error return */ /* First guess is no password */ hidekey = FALSE; fseek(f,file_position,SEEK_SET); /* reposition file to key */ - status = readkeypacket(f,hidekey,&ctb,timestamp,(char *)userid, + status = readkeypacket(f,0,&ctb,timestamp,(char *)userid, n,e,d,p,q,u,NULL,NULL); if (status != -5) /* Anything except bad password */ goto done; @@ -925,13 +922,11 @@ int getsecretkey(int flags, char *keyfil /* Then come existing key passwords */ hpw = keypasswds; while (hpw) { - fill0(iv,8); - memcpy(ideakey, hpw->hash, sizeof(ideakey)); - initcfb_idea(iv,ideakey,TRUE); + ideaCfbInit(&cfb, hpw->hash); fseek(f,file_position,SEEK_SET); - status = readkeypacket(f,hidekey,&ctb,timestamp, + status = readkeypacket(f,&cfb,&ctb,timestamp, (char *)userid,n,e,d,p,q,u,NULL,NULL); - close_idea(); + ideaCfbDestroy(&cfb); if (status != -5) goto done; hpw = hpw->next; @@ -940,15 +935,14 @@ int getsecretkey(int flags, char *keyfil hpwp = &passwds; hpw = *hpwp; while (hpw) { - fill0(iv,8); - memcpy(ideakey, hpw->hash, sizeof(ideakey)); - initcfb_idea(iv,ideakey,TRUE); + ideaCfbInit(&cfb, hpw->hash); fseek(f,file_position,SEEK_SET); - status = readkeypacket(f,hidekey,&ctb,timestamp, + status = readkeypacket(f,&cfb,&ctb,timestamp, (char *)userid,n,e,d,p,q,u,NULL,NULL); - close_idea(); + ideaCfbDestroy(&cfb); if (status >= 0) - { /* Success - move to key password list */ + { + /* Success - move to key password list */ *hpwp = hpw->next; hpw->next = keypasswds; keypasswds = hpw; @@ -960,45 +954,60 @@ int getsecretkey(int flags, char *keyfil } } /* If batchmode, we don't ask the user. */ - if (batchmode) - { /* PGPPASS (or -z) wrong or not set */ - fprintf(pgpout,PSTR("\n\007Error: Bad pass phrase.\n")); + if (batchmode) { + /* PGPPASS (or -z) wrong or not set */ + fprintf(pgpout,LANG("\n\007Error: Bad pass phrase.\n")); fclose(f); /* close key file */ return -1; } /* Finally, prompt the user. */ - fprintf(pgpout,PSTR("\nYou need a pass phrase to unlock your RSA secret key. ")); - if (!(flags & GPK_SHOW)) - { /* let user know for which key he should type his password */ + fprintf(pgpout,LANG("\nYou need a pass phrase to unlock your RSA secret key. ")); + if (!(flags & GPK_SHOW)) { + /* let user know for which key he should type his password */ PascalToC((char *)userid); - fprintf(pgpout, PSTR("\nKey for user ID \"%s\"\n"), + fprintf(pgpout, LANG("\nKey for user ID \"%s\"\n"), LOCAL_CHARSET((char *)userid)); CToPascal((char *)userid); } - do - { hidekey = (GetHashedPassPhrase((char *) ideakey, 1) > 0); - fill0(iv,8); - initcfb_idea(iv,ideakey,TRUE); + guesses = 0; + for (;;) { + if (++guesses > 3) + hidekey = 0; + else + hidekey = (GetHashedPassPhrase(ideakey, 1) > 0); + /* + * We've already tried the null password - interpret + * a null string as "I dunno". + */ + if (!hidekey) { + status = -5; /* Bad passphrase */ + fputs(LANG("No passphrase; secret key unavailable.\n"), +pgpout); + break; + } + + ideaCfbInit(&cfb, ideakey); fseek(f,file_position,SEEK_SET); - status = readkeypacket(f,hidekey,&ctb,timestamp, + status = readkeypacket(f,&cfb,&ctb,timestamp, (char *)userid,n,e,d,p,q,u,NULL,NULL); - close_idea(); - if (status >= 0) - { /* Success - remember this key for later use */ - if (flags & GPK_ASKPASS) - { /* This may be a duplicate because we didn't + ideaCfbDestroy(&cfb); + if (status >= 0) { + /* Success - remember this key for later use */ + if (flags & GPK_ASKPASS) { + /* + * This may be a duplicate because we didn't * search the lists before - check. */ hpw = passwds; - while (hpw) - { if (memcmp(hpw->hash, ideakey, + while (hpw) { + if (memcmp(hpw->hash, ideakey, sizeof(ideakey)) == 0) goto done; hpw = hpw->next; } hpw = keypasswds; - while (hpw) - { if (memcmp(hpw->hash, ideakey, + while (hpw) { + if (memcmp(hpw->hash, ideakey, sizeof(ideakey)) == 0) goto done; hpw = hpw->next; @@ -1006,8 +1015,8 @@ int getsecretkey(int flags, char *keyfil } /* Insert new key into remember lists. */ hpw = (struct hashedpw *)malloc(sizeof(struct hashedpw)); - if (hpw) - { /* If malloc fails, just don't remember the phrase */ + if (hpw) { + /* If malloc fails, just don't remember the phrase */ memcpy(hpw->hash, ideakey, sizeof(hpw->hash)); hpw->next = keypasswds; keypasswds = hpw; @@ -1015,7 +1024,7 @@ int getsecretkey(int flags, char *keyfil } if (status != -5) goto done; - fprintf(pgpout, PSTR("\n\007Error: Bad pass phrase.\n")); + fprintf(pgpout, LANG("\n\007Error: Bad pass phrase.\n")); } while (--guesses); /* Failed - fall through to done */ @@ -1025,11 +1034,11 @@ done: *hkey = hidekey; if (status == -5) return status; - if (status < 0) - { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), + if (status < 0) { + fprintf(pgpout,LANG("\n\007Could not read key from file '%s'.\n"), keyfile); fclose(f); /* close key file */ - return(-1); + return -1; } if (hpass) @@ -1038,31 +1047,30 @@ done: /* Note that readkeypacket has called set_precision */ - if (d != NULL) /* No effective check of pass phrase if d is NULL */ - { - if (!quietmode) - { + if (d != NULL) { /* No effective check of pass phrase if d is NULL */ + if (!quietmode) { if (!hidekey) - fprintf(pgpout,PSTR("\nAdvisory warning: This RSA secret key is not protected by a passphrase.\n")); + fprintf(pgpout,LANG("\nAdvisory warning: This RSA secret key is not protected by a passphrase.\n")); else - fprintf(pgpout,PSTR("Pass phrase is good. ")); + fprintf(pgpout,LANG("Pass phrase is good. ")); } - if (testeq(d,0)) /* didn't get secret key components */ - { fprintf(pgpout,PSTR("\n\007Key file '%s' is not a secret key file.\n"),keyfile); - return(-1); + if (testeq(d,0)) { /* didn't get secret key components */ + fprintf(pgpout,LANG("\n\007Key file '%s' is not a secret key file.\n"),keyfile); + return -1; } } - return(0); /* normal return */ + return 0; /* normal return */ -} /* getsecretkey */ +} /* getsecretkey */ int is_compromised(FILE *f) -/* check if a key has a compromise certificate, file pointer must - be positioned at or right after the key packet. -*/ +/* + * check if a key has a compromise certificate, file pointer must + * be positioned at or right after the key packet. + */ { long pos, savepos; byte class, ctb; @@ -1072,38 +1080,37 @@ int is_compromised(FILE *f) pos = savepos = ftell(f); nextkeypacket(f, &ctb); - if (is_key_ctb(ctb)) - { pos = ftell(f); + if (is_key_ctb(ctb)) { + pos = ftell(f); nextkeypacket(f, &ctb); } if (ctb != CTB_KEYCTRL) fseek(f, pos, SEEK_SET); /* file pointer now positioned where compromise cert. should be */ - if (fread(&ctb, 1, 1, f) != 1) - { status = -1; + if (fread(&ctb, 1, 1, f) != 1) { + status = -1; goto ex; } - if (is_ctb_type(ctb, CTB_SKE_TYPE)) - { + if (is_ctb_type(ctb, CTB_SKE_TYPE)) { cert_len = ( int ) getpastlength(ctb, f); - if (cert_len > MAX_SIGCERT_LENGTH) /* Huge packet length */ - { status = -1; + if (cert_len > MAX_SIGCERT_LENGTH) { /* Huge packet length */ + status = -1; goto ex; } /* skip version and mdlen byte */ fseek(f, 2L, SEEK_CUR); - if (fread(&class, 1, 1, f) != 1) - { status = -1; + if (fread(&class, 1, 1, f) != 1) { + status = -1; goto ex; } status = (class == KC_SIGNATURE_BYTE); } ex: fseek(f, savepos, SEEK_SET); - return(status); + return status; } @@ -1112,20 +1119,21 @@ ex: */ -/* Calculate and display a hash for the public components of the key. - The components are converted to their external (big-endian) - representation, concatenated, and an MD5 on the bit values - (ie excluding the length value) calculated and displayed in hex. - - The hash, or "fingerprint", of the key is useful mainly for quickly - and easily verifying over the phone that you have a good copy of - someone's public key. Just read the hash over the phone and have - them check it against theirs. -*/ +/* + * Calculate and display a hash for the public components of the key. + * The components are converted to their external (big-endian) + * representation, concatenated, and an MD5 on the bit values + * (i.e. excluding the length value) calculated and displayed in hex. + * + * The hash, or "fingerprint", of the key is useful mainly for quickly + * and easily verifying over the phone that you have a good copy of + * someone's public key. Just read the hash over the phone and have + * them check it against theirs. + */ void getKeyHash( byte *hash, unitptr n, unitptr e ) { - MD5_CTX mdContext; + struct MD5Context mdContext; byte buffer[ MAX_BYTE_PRECISION + 2 ]; byte mdBuffer[ MAX_BYTE_PRECISION * 2 ]; int i, mdIndex = 0, bufIndex; @@ -1143,7 +1151,7 @@ void getKeyHash( byte *hash, unitptr n, MD5Update( &mdContext, mdBuffer, mdIndex ); MD5Final( hash, &mdContext ); -} /* getKeyHash */ +} /* getKeyHash */ void printKeyHash( byteptr hash, boolean indent ) @@ -1154,7 +1162,7 @@ void printKeyHash( byteptr hash, boolean pub 1024/xxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Key fingerprint = xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx */ - fprintf( pgpout, "%*s ", indent ? 27 : 1, PSTR("Key fingerprint =" ) ); + fprintf( pgpout, "%*s ", indent ? 27 : 1, LANG("Key fingerprint =" ) ); for( i = 0; i < 8; i++ ) fprintf(pgpout, "%02X ", hash[ i ] ); putc( ' ', pgpout); @@ -1162,7 +1170,7 @@ pub 1024/xxxxxx yyyy-mm-dd aaaaaaaaaaa fprintf(pgpout, "%02X ", hash[ i ] ); putc( '\n', pgpout); -} /* printKeyHash */ +} /* printKeyHash */ void showKeyHash( unitptr n, unitptr e ) @@ -1172,14 +1180,16 @@ void showKeyHash( unitptr n, unitptr e ) getKeyHash(hash,n,e); /* compute hash of (n,e) */ printKeyHash(hash, TRUE); -} /* showKeyHash */ +} /* showKeyHash */ int view_keyring(char *mcguffin, char *ringfile, boolean show_signatures, boolean show_hashes) -/* Lists all entries in keyring that have mcguffin string in userid. - mcguffin is a null-terminated C string. -*/ -{ FILE *f; +/* + * Lists all entries in keyring that have mcguffin string in userid. + * mcguffin is a null-terminated C string. + */ +{ + FILE *f; byte ctb, keyctb=0; int status; unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; @@ -1197,72 +1207,74 @@ int view_keyring(char *mcguffin, char *r boolean invalid_key=FALSE; /* unsupported version or bad data */ boolean match = FALSE; boolean disabled = FALSE; + FILE *savepgpout; /* Default keyring to check signature ID's */ - buildfilename(dfltring,PUBLIC_KEYRING_FILENAME); + strcpy(dfltring, globalPubringName); /* open file f for read, in binary (not text) mode...*/ - if ((f = fopen(ringfile,FOPRBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } - if (show_signatures) - { + if (show_signatures) { setkrent(ringfile); setkrent(dfltring); init_userhash(); } /* Here's a good format for display of key or signature certificates: -Type bits/keyID Date User ID -pub 1024/xxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -sec 512/xxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -sig 384/xxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +Type bits/keyID Date User ID +pub 1024/xxxxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +sec 512/xxxxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +sig 384/xxxxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */ + /* XXX Send this to stdout. Do we always want to do this? + * Why couldn't we have a PGPOUT and PGPERR, and then we wouldn't + * have this problem? -warlord + */ + savepgpout=pgpout; + pgpout=stdout; + if (moreflag) open_more(); - if (!quietmode) - { - fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile); + if (!quietmode) { + fprintf(pgpout,LANG("\nKey ring: '%s'"),ringfile); if (mcguffin && strlen(mcguffin) > 0) - fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin)); + fprintf(pgpout,LANG(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin)); } - fprintf(pgpout,PSTR("\nType bits/keyID Date User ID\n")); - for ( ; ; ) - { + fprintf(pgpout,LANG("\nType bits/keyID Date User ID\n")); + for (;;) { status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)userid,n,e, NULL,NULL,NULL,NULL,sigkeyID,NULL); /* Note that readkeypacket has called set_precision */ - if (status== -1) - { status = 0; + if (status== -1) { + status = 0; break; /* eof reached */ } - if (status == -4 || status == -6) - { /* only ctb and userid are valid */ + if (status == -4 || status == -6) { + /* only ctb and userid are valid */ memset(sigkeyID, 0, KEYFRAGSIZE); tstamp = 0; - } - else if (status < 0) - { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), + } else if (status < 0) { + fprintf(pgpout,LANG("\n\007Could not read key from file '%s'.\n"), ringfile); break; } - if (is_key_ctb(ctb)) - { + if (is_key_ctb(ctb)) { byte keyctrl; firstuser = 1; keyctb = ctb; compromised = is_compromised(f); shownKeyHash = FALSE; - if (status < 0) - { invalid_key = TRUE; + if (status < 0) { + invalid_key = TRUE; memset(keyID, 0, KEYFRAGSIZE); - } - else - { invalid_key = FALSE; + } else { + invalid_key = FALSE; extract_keyID(keyID, n); if (read_trust(f, &keyctrl) == 0 && (keyctrl & KC_DISABLED)) disabled = TRUE; @@ -1273,15 +1285,14 @@ sig 384/xxxxxx yyyy-mm-dd aaaaaaaaaaa if (ctb != CTB_USERID && !is_ctb_type(ctb, CTB_SKE_TYPE)) continue; - if (ctb == CTB_USERID) - { PascalToC((char *)userid); + if (ctb == CTB_USERID) { + PascalToC((char *)userid); match = userid_match((char *)userid,mcguffin,n); } - if (match) - { - if (ctb == CTB_USERID) - { if (firstuser) - { keycounter++; + if (match) { + if (ctb == CTB_USERID) { + if (firstuser) { + keycounter++; if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE)) fprintf(pgpout,"pub"); else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE)) @@ -1294,54 +1305,61 @@ sig 384/xxxxxx yyyy-mm-dd aaaaaaaaaaa fprintf(pgpout,"@ "); else fprintf(pgpout," "); - fprintf(pgpout,"%4d/%s %s ", + fprintf(pgpout,"%4d/%s %s ", countbits(n),keyIDstring(keyID),cdate(&tstamp)); + } else { + fprintf(pgpout," %s ", blankkeyID); } - else - fprintf(pgpout," "); - if (compromised && firstuser) - { fprintf(pgpout, PSTR("*** KEY REVOKED ***\n")); - fprintf(pgpout," "); + if (compromised && firstuser) { + fprintf(pgpout, LANG("*** KEY REVOKED ***\n")); + fprintf(pgpout," %s ", blankkeyID); } firstuser = 0; fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid)); /* Display the hashes for n and e if required */ if( show_hashes && !shownKeyHash ) - { showKeyHash( n, e ); + { + showKeyHash( n, e ); shownKeyHash = TRUE; } - } - else if (show_signatures && !(firstuser && compromised)) /* Must be sig cert */ - { fprintf(pgpout,"sig%c ", status < 0 ? '?' : ' '); + } else if (show_signatures && + !(firstuser && compromised)) + { + /* Must be sig cert */ + fprintf(pgpout,"sig%c ", status < 0 ? '?' : ' '); showkeyID(sigkeyID); - fprintf(pgpout," "); /* Indent signator userid */ + fprintf(pgpout," "); /* Indent signator userid */ if ((siguserid = user_from_keyID(sigkeyID)) == NULL) - fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n")); + fprintf(pgpout,LANG("(Unknown signator, can't be checked)\n")); else fprintf(pgpout,"%s\n",LOCAL_CHARSET(siguserid)); } /* printing a sig cert */ - } /* if it has mcguffin */ - } /* loop for all packets */ + } /* if it has mcguffin */ + } /* loop for all packets */ fclose(f); /* close key file */ if (show_signatures) endkrent(); - fprintf(pgpout,PSTR("%d key(s) examined.\n"),keycounter); + if (keycounter == 1) + fprintf(pgpout,LANG("1 matching key found.\n")); + else + fprintf(pgpout,LANG("%d matching keys found.\n"),keycounter); close_more(); + pgpout=savepgpout; if (status < 0) return status; - if (mcguffin != NULL && *mcguffin != '\0') - { /* user specified substring */ + if (mcguffin != NULL && *mcguffin != '\0') { + /* user specified substring */ if (keycounter == 0) return 67; /* user not found */ else if (keycounter > 1) return 1; /* more than one match */ } - return(0); /* normal return */ + return 0; /* normal return */ -} /* view_keyring */ +} /* view_keyring */ int dokeycheck(char *mcguffin, char *ringfile, int options) @@ -1350,7 +1368,8 @@ int dokeycheck(char *mcguffin, char *rin If options is CHECK_NEW, only new signatures are checked and are marked as being checked in the trustbyte (called from addto_keyring). */ -{ FILE *f, *fixedf=NULL; +{ + FILE *f, *fixedf=NULL; byte ctb, keyctb=0; long fpsig = 0, fpkey = 0, fixpos = 0, trustpos = -1; int status, sigstatus; @@ -1372,19 +1391,17 @@ int dokeycheck(char *mcguffin, char *rin boolean invalid_key=FALSE; /* unsupported version or bad data */ boolean failed=FALSE; boolean print_userid=FALSE; - byte sigtrust; + byte sigtrust, newtrust; + FILE *savepgpout; /* Default keyring to check signature ID's */ - buildfilename(dfltring,PUBLIC_KEYRING_FILENAME); + strcpy(dfltring, globalPubringName); /* open file f, in binary (not text) mode...*/ - if (options & CHECK_NEW) - f = fopen(ringfile,FOPRWBIN); - else - f = fopen(ringfile,FOPRBIN); - if (f == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + f = fopen(ringfile,FOPRWBIN); + if (f == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } /* Here's a good format for display of key or signature certificates: @@ -1394,80 +1411,84 @@ sec 512/xxxxxx yyyy-mm-dd aaaaaaaaaaa sig 384/xxxxxx yyyy-mm-dd aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa */ - if (options & CHECK_NEW) - { fprintf(pgpout,PSTR("\nChecking signatures...\n")); - } - else - { + /* XXX Send this to stdout. Do we always want to do this? + * Why couldn't we have a PGPOUT and PGPERR, and then we wouldn't + * have this problem? -warlord + */ + savepgpout=pgpout; + pgpout=stdout; + + if (options & CHECK_NEW) { + fprintf(pgpout,LANG("\nChecking signatures...\n")); + } else { if (moreflag) open_more(); - if (!quietmode) - { fprintf(pgpout,PSTR("\nKey ring: '%s'"),ringfile); + if (!quietmode) { + fprintf(pgpout,LANG("\nKey ring: '%s'"),ringfile); if (mcguffin && strlen(mcguffin) > 0) - fprintf(pgpout,PSTR(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin)); + fprintf(pgpout,LANG(", looking for user ID \"%s\"."),LOCAL_CHARSET(mcguffin)); } - fprintf(pgpout,PSTR("\nType bits/keyID Date User ID\n")); + fprintf(pgpout,LANG("\nType bits/keyID Date User ID\n")); } - for ( ; ; ) - { long fpos = ftell(f); + for (;;) { + long fpos = ftell(f); status = readkeypacket(f,FALSE,&ctb,timestamp,(char *)keyuserid,n,e, NULL,NULL,NULL,NULL,sigkeyID,NULL); /* Note that readkeypacket has called set_precision */ if (status== -1 ) break; /* eof reached */ - if (status == -4 || status == -6) - { /* only ctb and userid are valid */ + if (status == -4 || status == -6) { + /* only ctb and userid are valid */ memset(sigkeyID, 0, KEYFRAGSIZE); tstamp = 0; - } - else if (status < 0) - { fprintf(pgpout,PSTR("\n\007Could not read key from file '%s'.\n"), + } else if (status < 0) { + fprintf(pgpout,LANG("\n\007Could not read key from file '%s'.\n"), ringfile); fclose(f); /* close key file */ - return(-1); + return -1; } - if (is_key_ctb(ctb)) - { firstuser = 1; + if (is_key_ctb(ctb)) { + firstuser = 1; keyctb = ctb; fpkey = fpos; keypktlen = ( int ) ( ftell(f) - fpkey ); compromised = is_compromised(f); - if (status < 0) - { invalid_key = TRUE; + if (status < 0) { + invalid_key = TRUE; memset(keyID, 0, KEYFRAGSIZE); - } - else - { invalid_key = FALSE; + } else { + invalid_key = FALSE; extract_keyID(keyID, n); } if (options & CHECK_NEW) print_userid = TRUE; } - if (ctb == CTB_USERID) + if (ctb == CTB_USERID) { PascalToC((char *)keyuserid); - else if (is_ctb_type(ctb, CTB_SKE_TYPE)) - { fpsig = fpos; + } else if (is_ctb_type(ctb, CTB_SKE_TYPE)) { + fpsig = fpos; sigpktlen = ( int ) ( ftell(f) - fpsig ); - } else + } else { continue; + } - if (options & CHECK_NEW) - { + trustpos = ftell(f); + status = read_trust(f, &sigtrust); + if (status == -1) + break; /* EOF */ + if (status == -7) { + trustpos = -1; + continue; /* not a keyring or this was a compromise cert. */ + } + if (status < 0) { + fclose(f); + return status; + } + + if (options & CHECK_NEW) { if (!is_ctb_type(ctb, CTB_SKE_TYPE)) continue; - trustpos = ftell(f); - status = read_trust(f, &sigtrust); - if (status == -1) - break; /* EOF */ - if (status == -7) - { trustpos = -1; - continue; /* not a keyring or this was a compromise cert. */ - } - if (status < 0) - { fclose(f); - return status; - } if (sigtrust & KC_SIG_CHECKED) continue; /* addto_keyring has called setkrent() */ @@ -1475,148 +1496,231 @@ sig 384/xxxxxx yyyy-mm-dd aaaaaaaaaaa continue; /* unknown signator */ } - if ((options & CHECK_NEW) || userid_match((char *)keyuserid,mcguffin,n)) - { - if (ctb == CTB_USERID || print_userid) - { /* CHECK_NEW: only print userid if it has new signature */ - print_userid = FALSE; - if (firstuser) - { if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE)) - fprintf(pgpout,"pub"); - else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE)) - fprintf(pgpout,"sec"); - else - fprintf(pgpout,"???"); - if (invalid_key) - fprintf(pgpout,"? "); - else - fprintf(pgpout," "); - fprintf(pgpout,"%4d/%s %s ", - countbits(n),keyIDstring(keyID),cdate(&tstamp)); - } - else - fprintf(pgpout," "); - if (compromised && firstuser) - { fprintf(pgpout, PSTR("*** KEY REVOKED ***\n")); - fprintf(pgpout," "); - } - firstuser = 0; - fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)keyuserid)); - } - if (is_ctb_type(ctb, CTB_SKE_TYPE)) - { /* Try checking signature on either this ring or dflt ring */ - CToPascal((char *)keyuserid); - sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid, - f, fpsig, ringfile, (char *) siguserid, sigtimestamp, &sigclass); - if (sigstatus == -1 && strcmp(ringfile,dfltring) != 0) - sigstatus = check_key_sig (f, fpkey, keypktlen, (char *) keyuserid, - f, fpsig, dfltring, (char *) siguserid, sigtimestamp, &sigclass); - PascalToC((char *)keyuserid); - fseek (f, fpsig+sigpktlen, SEEK_SET); - if (sigclass == KC_SIGNATURE_BYTE) - fprintf(pgpout,"com"); - else - fprintf(pgpout,"sig"); - if (sigstatus >= 0) - fprintf(pgpout,"! "); - else if (status < 0 || sigstatus == -1) - fprintf(pgpout,"? "); + /* If we don't list the signatures, continue */ + if (!(options & CHECK_NEW) && + !userid_match((char *)keyuserid, mcguffin, n)) + continue; + + if (ctb == CTB_USERID || print_userid) { + /* CHECK_NEW: only print userid if it has new signature */ + print_userid = FALSE; + if (firstuser) { + if (is_ctb_type(keyctb,CTB_CERT_PUBKEY_TYPE)) + fprintf(pgpout,"pub"); + else if (is_ctb_type(keyctb,CTB_CERT_SECKEY_TYPE)) + fprintf(pgpout,"sec"); else - fprintf(pgpout,"* "); /* bad signature */ - showkeyID(sigkeyID); - if (sigstatus == -1) - { fprintf(pgpout," "); /* Indent signator userid */ - fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n")); - } + fprintf(pgpout,"???"); + if (invalid_key) + fprintf(pgpout,"? "); else - { PascalToC((char *) siguserid); - fprintf(pgpout," %s ",cdate(&sigtstamp)); - if (sigclass != KC_SIGNATURE_BYTE) - fprintf(pgpout, " "); - fprintf(pgpout,"%s\n", LOCAL_CHARSET((char *)siguserid)); - if (sigstatus >= 0) - { if (options & CHECK_NEW && trustpos > 0) - write_trust_pos(f, sigtrust|KC_SIG_CHECKED, trustpos); - } - else - { fprintf(pgpout," "); - fprintf(pgpout,PSTR("\007***** BAD SIGNATURE! *****\n")); - if (!failed) - { /* first bad signature: create scratch file */ - tempring = tempfile(TMP_TMPDIR); - fixedf = fopen(tempring, FOPWBIN); - failed = TRUE; - } - if (fixedf != NULL) - { - copyfilepos(f, fixedf, fpsig - fixpos, fixpos); - fseek(f, fpsig+sigpktlen, SEEK_SET); - if (nextkeypacket(f, &ctb) < 0 || ctb != CTB_KEYCTRL) - fseek(f, fpsig+sigpktlen, SEEK_SET); - fixpos = ftell(f); - } - } - } - } /* checking a signature */ - } /* if it has mcguffin */ + fprintf(pgpout," "); + fprintf(pgpout,"%4d/%s %s ", + countbits(n),keyIDstring(keyID),cdate(&tstamp)); + } else { + fprintf(pgpout," %s ", + blankkeyID); + } + if (compromised && firstuser) { + fprintf(pgpout, LANG("*** KEY REVOKED ***\n")); + fprintf(pgpout," %s ", + blankkeyID); + } + firstuser = 0; + fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)keyuserid)); + } + + /* Ignore comments and anything else */ + if (!is_ctb_type(ctb, CTB_SKE_TYPE)) + continue; + + /* So now we're checking a signature... */ + /* Try checking signature on either this ring or dflt ring */ + + CToPascal((char *)keyuserid); + sigstatus = check_key_sig(f, fpkey, keypktlen, + (char *)keyuserid, f, fpsig, + ringfile, (char *) siguserid, + sigtimestamp, &sigclass); + if (sigstatus == -2 && strcmp(ringfile,dfltring) != 0) { + sigstatus = check_key_sig (f, fpkey, keypktlen, + (char *) keyuserid, f, fpsig, + dfltring, (char *) siguserid, + sigtimestamp, &sigclass); + } + /* + * Note: sigstatus has the following values: + * 0 Good signature + * -1 Generic error + * -2 Can't find key + * -3 Key too big + * -4 Key too small + * -5 Maybe malformed RSA (RSAREF) + * -6 Unknown PK algorithm + * -7 Unknown conventional algorithm + * -8 Unknown version + * -9 Malformed RSA packet + * -10 Malformed packet + * -20 BAD SIGNATURE + */ + PascalToC((char *)keyuserid); + fseek (f, fpsig+sigpktlen, SEEK_SET); + if (sigclass == KC_SIGNATURE_BYTE) + fprintf(pgpout,"com"); + else + fprintf(pgpout,"sig"); + if (sigstatus >= 0) + fputs("! ", pgpout); /* Good */ + else if (status < 0 || sigstatus == -2 || sigstatus == -3) + fputs("? ", pgpout); /* Uncheckable */ + else if (sigstatus != -20) + fputs("% ", pgpout); /* Malformed */ + else + fputs("* ", pgpout); /* BAD! */ + + showkeyID(sigkeyID); + + /* If we got a keyID, show it */ + if (sigstatus >= 0 || sigstatus == -3 || + (sigstatus <= -5 && sigstatus >= -9) || + sigstatus == -20) + { + PascalToC((char *) siguserid); + fprintf(pgpout," %s ",cdate(&sigtstamp)); + if (sigclass != KC_SIGNATURE_BYTE) + putc(' ', pgpout); + fputs(LOCAL_CHARSET((char *)siguserid), pgpout); + putc('\n', pgpout); + /* If an error, prepare next line for message */ + if (sigstatus < 0) + fprintf(pgpout," %s ", + blankkeyID); + } else { + /* Indent error messages past date field */ + fprintf(pgpout," "); + } + + /* Compute new trust */ + newtrust = sigtrust; + if (sigstatus >= 0) { + newtrust |= KC_SIG_CHECKED; + } else if (sigstatus == -2) { + newtrust |= KC_SIG_CHECKED; + newtrust &= ~KC_SIGTRUST_MASK; + } else { + newtrust &= ~KC_SIGTRUST_MASK & ~KC_SIG_CHECKED; + newtrust |= KC_SIGTRUST_UNTRUSTED; + } + + /* If it changed, write it out */ + if (trustpos > 0 && newtrust != sigtrust) + write_trust_pos(f, newtrust, trustpos); + if (sigstatus >= 0) + continue; /* Skip error code */ + + /* An error: print an appropriate message */ + if (sigstatus == -2) + fprintf(pgpout,LANG("(Unknown signator, can't be checked)")); + else if (sigstatus == -3) + fprintf(pgpout,LANG("(Key too long, can't be checked)")); + else if (sigstatus == -5) + fprintf(pgpout,LANG("(Malformed or obsolete signature format)")); + else if (sigstatus == -6) + fprintf(pgpout,LANG("(Unknown public-key algorithm)")); + else if (sigstatus == -7) + fprintf(pgpout,LANG("(Unknown hash algorithm)")); + else if (sigstatus == -8) + fprintf(pgpout,LANG("(Unknown signature packet version)")); + else if (sigstatus == -9) + fprintf(pgpout,LANG("(Malformed signature)")); + else if (sigstatus == -10) + fprintf(pgpout,LANG("(Corrupted signature packet)")); + else if (sigstatus == -20) + fprintf(pgpout,LANG("\007**** BAD SIGNATURE! ****")); + else + fprintf(pgpout,"(Unexpected signature error %d)", sigstatus); + putc('\n', pgpout); + + /* + * If the signature was not too bad, leave it on the key + * ring. + */ + if (sigstatus == -2 || sigstatus == -3) + continue; + /* + * The signature was unacceptable, and + * likely to remain that way, so remove it + * from the keyring. + */ + if (!failed) { + /* first bad signature: create scratch file */ + tempring = tempfile(TMP_TMPDIR); + fixedf = fopen(tempring, FOPWBIN); + failed = TRUE; + } + if (fixedf != NULL) { + copyfilepos(f, fixedf, fpsig - fixpos, fixpos); + fseek(f, fpsig+sigpktlen, SEEK_SET); + if (nextkeypacket(f, &ctb) < 0 || ctb != CTB_KEYCTRL) + fseek(f, fpsig+sigpktlen, SEEK_SET); + fixpos = ftell(f); + } } /* loop for all packets */ close_more(); - if (status < -1) - { + pgpout=savepgpout; + + if (status < -1) { fclose(f); return status; } fputc('\n',pgpout); - if (failed) - { + if (failed && fixedf) { copyfilepos(f, fixedf, -1L, fixpos); - if (write_error(fixedf)) - { fclose(fixedf); + if (write_error(fixedf)) { + fclose(fixedf); fclose(f); return -1; } fclose(fixedf); if (!batchmode) - fprintf(pgpout, PSTR("Remove bad signatures (Y/n)? ")); - if (batchmode || getyesno('y')) - { + fprintf(pgpout, LANG("Remove bad signatures (Y/n)? ")); + if (batchmode || getyesno('y')) { savetempbak(tempring, ringfile); failed = 0; } } fclose(f); /* close key file */ - return(failed?-1:0); /* normal return */ + return 0; /* normal return */ -} /* dokeycheck */ +} /* dokeycheck */ int backup_rename(char *scratchfile, char *destfile) -{ /* rename scratchfile to destfile after making a backup file */ +{ + /* rename scratchfile to destfile after making a backup file */ char bakfile[MAX_PATH]; - if (is_tempfile(destfile)) - { + if (is_tempfile(destfile)) { remove(destfile); - } - else - { if (file_exists(destfile)) - { + } else { + if (file_exists(destfile)) { strcpy(bakfile, destfile); force_extension(bakfile, BAK_EXTENSION); remove(bakfile); rename(destfile, bakfile); } } - return(rename2(scratchfile, destfile)); + return rename2(scratchfile, destfile); } int remove_sigs(char *mcguffin, char*ringfile) /* Lists all signatures for keys with specified mcguffin string, and asks * if they should be removed. */ -{ FILE *f, *g; +{ + FILE *f, *g; byte ctb; long fp, fpuser; int packetlength; @@ -1632,23 +1736,23 @@ int remove_sigs(char *mcguffin, char*rin char *scratchf; /* Default keyring to check signature ID's */ - buildfilename(dfltring,PUBLIC_KEYRING_FILENAME); + strcpy(dfltring, globalPubringName); if (!mcguffin || strlen(mcguffin) == 0) - return(-1); + return -1; setoutdir(ringfile); scratchf = tempfile(0); strcpy((char *)userid,mcguffin); - fprintf(pgpout,PSTR("\nRemoving signatures from userid '%s' in key ring '%s'\n"), + fprintf(pgpout,LANG("\nRemoving signatures from userid '%s' in key ring '%s'\n"), LOCAL_CHARSET(mcguffin), ringfile); status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e); - if (status < 0) - { fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile); - return(0); /* normal return */ + if (status < 0) { + fprintf(pgpout,LANG("\n\007Key not found in key ring '%s'.\n"),ringfile); + return 0; /* normal return */ } strcpy((char *)userid,mcguffin); @@ -1656,15 +1760,15 @@ int remove_sigs(char *mcguffin, char*rin packetlength += ( int ) ( fpuser - fp ); /* open file f for read, in binary (not text) mode...*/ - if ((f = fopen(ringfile,FOPRBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } /* Count signatures */ fseek (f, fp+packetlength, SEEK_SET); - for ( ; ; ) - { status = nextkeypacket(f, &ctb); + for (;;) { + status = nextkeypacket(f, &ctb); if (status < 0 || is_key_ctb(ctb) || ctb==CTB_USERID) break; if (is_ctb_type(ctb,CTB_SKE_TYPE)) @@ -1673,79 +1777,81 @@ int remove_sigs(char *mcguffin, char*rin rewind(f); - if (nsigs == 0) - { fprintf (pgpout,PSTR("\nKey has no signatures to remove.\n")); + if (nsigs == 0) { + fprintf (pgpout,LANG("\nKey has no signatures to remove.\n")); fclose (f); - return (0); /* Normal return */ + return 0; /* Normal return */ } - fprintf (pgpout, PSTR("\nKey has %d signature(s):\n"), nsigs); + fprintf (pgpout, LANG("\nKey has %d signature(s):\n"), nsigs); /* open file g for writing, in binary (not text) mode...*/ - if ((g = fopen(scratchf,FOPWBIN)) == NULL) - { fclose(f); - return(-1); + if ((g = fopen(scratchf,FOPWBIN)) == NULL) { + fclose(f); + return -1; } copyfile(f,g,fp+packetlength); /* copy file f to g up through key */ /* Now print out any following sig certs */ keeping = 1; - for ( ; ; ) - { fp = ftell(f); + for (;;) { + fp = ftell(f); status = readkeypacket(f, FALSE, &ctb, NULL, NULL, NULL, NULL, NULL,NULL,NULL,NULL,sigkeyID,NULL); packetlength = ( int ) ( ftell(f) - fp ); if ((status < 0 && status != -6 && status != -4) || is_key_ctb(ctb) || ctb==CTB_USERID) break; - if (is_ctb_type(ctb,CTB_SKE_TYPE)) - { fprintf(pgpout,"sig%c ", status < 0 ? '?' : ' '); + if (is_ctb_type(ctb,CTB_SKE_TYPE)) { + fprintf(pgpout,"sig%c ", status < 0 ? '?' : ' '); if (status < 0) memset(sigkeyID, 0, KEYFRAGSIZE); showkeyID(sigkeyID); fprintf(pgpout," "); /* Indent signator userid */ - if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, sigkeyID, - timestamp, userid, n, e)>=0 || - getpublickey(GPK_GIVEUP, dfltring, NULL, NULL, sigkeyID, - timestamp, userid, n, e)>=0) - { PascalToC((char *)userid); + if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, + sigkeyID, timestamp, userid, n, e)>=0 || + getpublickey(GPK_GIVEUP, dfltring, NULL, NULL, + sigkeyID, timestamp, userid, n, e)>=0) + { + PascalToC((char *)userid); fprintf(pgpout,"%s\n",LOCAL_CHARSET((char *)userid)); + } else { + fprintf(pgpout,LANG("(Unknown signator, can't be checked)\n")); } - else - fprintf(pgpout,PSTR("(Unknown signator, can't be checked)\n")); - fprintf(pgpout, PSTR("Remove this signature (y/N)? ")); + fprintf(pgpout, LANG("Remove this signature (y/N)? ")); if (!(keeping=!getyesno('n'))) ++nremoved; } if (keeping) copyfilepos (f, g, (long) packetlength, fp); - } /* scanning sig certs */ + } /* scanning sig certs */ copyfilepos (f, g, -1L, fp); /* Copy rest of file */ fclose(f); /* close key file */ - if (write_error(g)) - { fclose(g); + if (write_error(g)) { + fclose(g); return -1; } fclose(g); /* close scratch file */ savetempbak(scratchf,ringfile); if (nremoved == 0) - fprintf(pgpout,PSTR("\nNo key signatures removed.\n")); + fprintf(pgpout,LANG("\nNo key signatures removed.\n")); else - fprintf(pgpout,PSTR("\n%d key signature(s) removed.\n"), nremoved); + fprintf(pgpout,LANG("\n%d key signature(s) removed.\n"), nremoved); - return(0); /* normal return */ + return 0; /* normal return */ -} /* remove_sigs */ +} /* remove_sigs */ int remove_from_keyring(byte *keyID, char *mcguffin, char *ringfile, boolean secring_too) -/* Remove the first entry in key ring that has mcguffin string in userid. - Or it removes the first matching keyID from the ring. - A non-NULL keyID takes precedence over a mcguffin specifier. - mcguffin is a null-terminated C string. - If secring_too is TRUE, the secret keyring is also checked. -*/ +/* + * Remove the first entry in key ring that has mcguffin string in userid. + * Or it removes the first matching keyID from the ring. + * A non-NULL keyID takes precedence over a mcguffin specifier. + * mcguffin is a null-terminated C string. + * If secring_too is TRUE, the secret keyring is also checked. + */ { FILE *f; FILE *g; @@ -1759,85 +1865,88 @@ int remove_from_keyring(byte *keyID, cha int userids; boolean rmuserid = FALSE; char *scratchf; + unsigned secflag = 0; default_extension(ringfile,PGP_EXTENSION); if ((keyID==NULL) && (!mcguffin || strlen(mcguffin)==0)) - return(-1); /* error, null mcguffin will match everything */ + return -1; /* error, null mcguffin will match everything */ top: if (mcguffin) strcpy((char *)userid,mcguffin); - fprintf(pgpout,PSTR("\nRemoving from key ring: '%s'"),ringfile); + fprintf(pgpout,LANG("\nRemoving from key ring: '%s'"),ringfile); if (mcguffin && strlen(mcguffin) > 0) - fprintf(pgpout,PSTR(", userid \"%s\".\n"), + fprintf(pgpout,LANG(", userid \"%s\".\n"), LOCAL_CHARSET(mcguffin)); - status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e); - if (status < 0 && status != -4 && status != -6) - { fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"),ringfile); - return(0); /* normal return */ + status = getpublickey(secflag|GPK_GIVEUP|GPK_SHOW, ringfile, &fp, + &packetlength, NULL, timestamp, userid, n, e); + if (status < 0 && status != -4 && status != -6) { + fprintf(pgpout,LANG("\n\007Key not found in key ring '%s'.\n"),ringfile); + return 0; /* normal return */ } /* Now add to packetlength the subordinate following certificates */ - if ((f = fopen(ringfile,FOPRBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } fseek (f, fp+packetlength, SEEK_SET); userids = 0; - do /* count user ID's, position nfp at next key */ - { nfp = ftell(f); + do { /* count user ID's, position nfp at next key */ + nfp = ftell(f); status = nextkeypacket(f, &ctb); if (status == 0 && ctb == CTB_USERID) ++userids; } while (status == 0 && !is_key_ctb(ctb)); - if (status < -1) - { fclose(f); - return(-1); + if (status < -1) { + fclose(f); + return -1; } - if (keyID==NULL) /* Human confirmation is required. */ - { /* Supposedly the key was fully displayed by getpublickey */ - if (userids > 1) - { fprintf(pgpout, PSTR("\nKey has more than one user ID.\n\ + if (keyID==NULL) { /* Human confirmation is required. */ + /* Supposedly the key was fully displayed by getpublickey */ + if (userids > 1) { + fprintf(pgpout, LANG("\nKey has more than one user ID.\n\ Do you want to remove the whole key (y/N)? ")); - if (!getyesno('n')) - { /* find out which userid should be removed */ + if (!getyesno('n')) { + /* find out which userid should be removed */ rmuserid = TRUE; fseek (f, fp+packetlength, SEEK_SET); - for ( ; ; ) - { fp = ftell(f); + for (;;) { + fp = ftell(f); status = readkpacket(f, &ctb, (char *) userid, NULL, NULL); if (status < 0 && status != -4 && status != -6 || is_key_ctb(ctb)) - { fclose(f); - fprintf(pgpout, PSTR("\nNo more user ID's\n")); - return(-1); + { + fclose(f); + fprintf(pgpout, LANG("\nNo more user ID's\n")); + return -1; } - if (ctb == CTB_USERID) - { fprintf(pgpout, PSTR("Remove \"%s\" (y/N)? "), userid); + if (ctb == CTB_USERID) { + fprintf(pgpout, LANG("Remove \"%s\" (y/N)? "), userid); if (getyesno('n')) break; } } - do /* also remove signatures and trust bytes */ - { nfp = ftell(f); + do { /* also remove signatures and trust bytes */ + nfp = ftell(f); status = nextkeypacket(f, &ctb); } while ((status == 0 || status == -4 || status == -6) && !is_key_ctb(ctb) && ctb != CTB_USERID); if (status < -1 && status != -4 && status != -6) - { fclose(f); - return(-1); + { + fclose(f); + return -1; } } - } - else if (!force_flag) /* only one user ID */ - { fprintf(pgpout, - PSTR("\nAre you sure you want this key removed (y/N)? ")); - if (!getyesno('n')) - { fclose(f); - return(-1); /* user said "no" */ + } else if (!force_flag) { /* only one user ID */ + fprintf(pgpout, + LANG("\nAre you sure you want this key removed (y/N)? ")); + if (!getyesno('n')) { + fclose(f); + return -1; /* user said "no" */ } } } @@ -1845,57 +1954,62 @@ Do you want to remove the whole key (y/N packetlength = ( int ) ( nfp - fp ); /* open file f for read, in binary (not text) mode...*/ - if ((f = fopen(ringfile,FOPRBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } setoutdir(ringfile); scratchf = tempfile(0); /* open file g for writing, in binary (not text) mode...*/ - if ((g = fopen(scratchf,FOPWBIN)) == NULL) - { fclose(f); - return(-1); + if ((g = fopen(scratchf,FOPWBIN)) == NULL) { + fclose(f); + return -1; } copyfilepos(f,g,fp,0L); /* copy file f to g up to position fp */ copyfilepos(f,g,-1L,fp+packetlength); /* copy rest of file f */ fclose(f); /* close key file */ - if (write_error(g)) - { fclose(g); + if (write_error(g)) { + fclose(g); return -1; } fclose(g); /* close scratch file */ if (secring_too) /* TRUE if this is the public keyring */ - maint_update(scratchf); + maint_update(scratchf, 0); savetempbak(scratchf,ringfile); if (rmuserid) - fprintf(pgpout,PSTR("\nUser ID removed from key ring.\n")); + fprintf(pgpout,LANG("\nUser ID removed from key ring.\n")); else - fprintf(pgpout,PSTR("\nKey removed from key ring.\n")); + fprintf(pgpout,LANG("\nKey removed from key ring.\n")); - if (secring_too) - { secring_too = FALSE; - buildfilename(ringfile, SECRET_KEYRING_FILENAME); + if (secring_too) { + secring_too = FALSE; + strcpy(ringfile, globalSecringName); strcpy((char *)userid,mcguffin); - if (getpublickey(GPK_GIVEUP, ringfile, NULL, NULL, NULL, timestamp, userid, n, e) == 0) - { fprintf(pgpout, PSTR("\nKey or user ID is also present in secret keyring.\n\ + if (getpublickey(GPK_GIVEUP|GPK_SECRET, ringfile, NULL, + NULL, NULL, timestamp, userid, n, e) == 0) + { + fprintf(pgpout, LANG("\nKey or user ID is also present in secret keyring.\n\ Do you also want to remove it from the secret keyring (y/N)? ")); - if (getyesno('n')) + if (getyesno('n')) { + secflag = GPK_SECRET; goto top; + } } } - return(0); /* normal return */ + return 0; /* normal return */ -} /* remove_from_keyring */ +} /* remove_from_keyring */ int extract_from_keyring (char *mcguffin, char *keyfile, char *ringfile, boolean transflag) -/* Copy the first entry in key ring that has mcguffin string in - userid and put it into keyfile. - mcguffin is a null-terminated C string. -*/ +/* + * Copy the first entry in key ring that has mcguffin string in + * userid and put it into keyfile. + * mcguffin is a null-terminated C string. + */ { FILE *f; FILE *g; @@ -1919,111 +2033,109 @@ int extract_from_keyring (char *mcguffin whole_ring = TRUE; /* open file f for read, in binary (not text) mode...*/ - if ((f = fopen(ringfile,FOPRBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } - if (!whole_ring) - { + if (!whole_ring) { strcpy((char *)userid, mcguffin); - fprintf(pgpout,PSTR("\nExtracting from key ring: '%s'"),ringfile); - fprintf(pgpout,PSTR(", userid \"%s\".\n"),LOCAL_CHARSET(mcguffin)); + fprintf(pgpout,LANG("\nExtracting from key ring: '%s'"),ringfile); + fprintf(pgpout,LANG(", userid \"%s\".\n"),LOCAL_CHARSET(mcguffin)); status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fp, &packetlength, NULL, timestamp, userid, n, e); - if (status < 0 && status != -4 && status != -6) - { fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"), + if (status < 0 && status != -4 && status != -6) { + fprintf(pgpout,LANG("\n\007Key not found in key ring '%s'.\n"), ringfile); fclose(f); - return(1); /* non-normal return */ + return 1; /* non-normal return */ } extract_keyID(keyID, n); - } - else - { + } else { do /* set fp to first key packet */ fp = ftell(f); while ((status = nextkeypacket(f, &ctb)) >= 0 && !is_key_ctb(ctb)); - if (status < 0) - { fclose(f); - return(-1); + if (status < 0) { + fclose(f); + return -1; } packetlength = ( int ) ( ftell(f) - fp ); } - if (!keyfile || strlen(keyfile)==0) - { fprintf(pgpout, PSTR("\nExtract the above key into which file? ")); + if (!keyfile || strlen(keyfile)==0) { + fprintf(pgpout, LANG("\nExtract the above key into which file? ")); if (batchmode) return -1; getstring( fname, sizeof(fname)-4, TRUE ); if (*fname == '\0') - return(-1); - } - else + return -1; + } else { strcpy(fname,keyfile); + } default_extension(fname,PGP_EXTENSION); /* If transport armoring, use a dummy file for keyfile */ - if (transflag) - { strcpy(transname, fname); + if (transflag) { + strcpy(transname, fname); strcpy(transfile, fname); force_extension(transfile, ASC_EXTENSION); tempf = tempfile(TMP_TMPDIR|TMP_WIPE); strcpy(fname, tempf); } - if (file_exists( transflag?transfile:fname )) - { - if (!transflag && !whole_ring) - { /* see if the key is already present in fname */ + if (file_exists( transflag?transfile:fname )) { + if (!transflag && !whole_ring) { + /* see if the key is already present in fname */ status = getpublickey(GPK_GIVEUP, fname, NULL, NULL, keyID, timestamp, userid, n, e); if (status >= 0 || status == -4 || status == -6) - { fclose(f); - fprintf(pgpout,PSTR("Key ID %s is already included in key ring '%s'.\n"), + { + fclose(f); + fprintf(pgpout,LANG("Key ID %s is already included in key ring '%s'.\n"), keyIDstring(keyID), fname); - return(-1); + return -1; } } - if (whole_ring || transflag || status < -1) - { if (!is_tempfile(fname) && !force_flag) + if (whole_ring || transflag || status < -1) { + if (!is_tempfile(fname) && !force_flag) /* Don't ask this for mailmode or for * a tempfile, since its ok. */ - { /* if status < -1 then fname is not a keyfile, ask if it should be overwritten */ - fprintf(pgpout,PSTR("\n\007Output file '%s' already exists. Overwrite (y/N)? "), + { + /* if status < -1 then fname is not a keyfile, ask if it should be overwritten */ + fprintf(pgpout,LANG("\n\007Output file '%s' already exists. Overwrite (y/N)? "), transflag?transfile:fname); if (!getyesno( 'n' )) - { fclose(f); - return(-1); /* user chose to abort */ + { + fclose(f); + return -1; /* user chose to abort */ } } - } - else + } else { append = TRUE; + } } if (append) g = fopen(fname, FOPRWBIN); else g = fopen(fname, FOPWBIN); - if (g == NULL) - { if (append) - fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); + if (g == NULL) { + if (append) + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); else - fprintf(pgpout,PSTR("\n\007Unable to create key file '%s'.\n"), fname); + fprintf(pgpout,LANG("\n\007Unable to create key file '%s'.\n"), fname); fclose(f); - return(-1); + return -1; } if (append) fseek(g, 0L, SEEK_END); - do - { /* file f is positioned right after key packet */ + do { + /* file f is positioned right after key packet */ if (whole_ring && read_trust(f, &keyctrl) == 0 && (keyctrl & KC_DISABLED)) { - do /* skip this key */ - { + do { /* skip this key */ fp = ftell(f); status = nextkeypacket(f, &ctb); packetlength = ( int ) ( ftell(f) - fp ); @@ -2031,20 +2143,22 @@ int extract_from_keyring (char *mcguffin while (!is_key_ctb(ctb) && status >= 0); continue; } - if (copyfilepos(f, g, (long) packetlength, fp) < 0) /* Copy key out */ - { status = -2; + if (copyfilepos(f, g, (long) packetlength, fp) < 0) { + /* Copy key out */ + status = -2; break; } /* Copy any following signature or userid packets */ - for ( ; ; ) - { fp = ftell(f); + for (;;) { + fp = ftell(f); status = nextkeypacket(f, &ctb); packetlength = ( int ) ( ftell(f) - fp ); if (status < 0 || is_key_ctb(ctb)) break; if (ctb==CTB_USERID || is_ctb_type(ctb,CTB_SKE_TYPE)) if (copyfilepos(f, g, (long) packetlength, fp) < 0) - { status = -2; + { + status = -2; break; } } @@ -2052,23 +2166,23 @@ int extract_from_keyring (char *mcguffin while (whole_ring && status >= 0); fclose(f); - if (status < -1 || write_error(g)) - { fclose(g); - return(-1); + if (status < -1 || write_error(g)) { + fclose(g); + return -1; } fclose(g); - if (transflag) - { status = armor_file (fname, transfile, transname, NULL); + if (transflag) { + status = armor_file (fname, transfile, transname, NULL); rmtemp (tempf); if (status) - return(-1); + return -1; } - fprintf (pgpout,PSTR("\nKey extracted to file '%s'.\n"), transflag?transfile:fname); + fprintf (pgpout,LANG("\nKey extracted to file '%s'.\n"), transflag?transfile:fname); - return (0); /* normal return */ -} /* extract_from_keyring */ + return 0; /* normal return */ +} /* extract_from_keyring */ /*======================================================================*/ @@ -2079,7 +2193,8 @@ static int merge_key_to_ringfile(char *k is in ringfile starting at fp and for length packetlength. keylen is the number of bytes to copy from keyfile */ -{ FILE *f, *g, *h; +{ + FILE *f, *g, *h; char *tempf; int rc; @@ -2087,17 +2202,17 @@ static int merge_key_to_ringfile(char *k tempf = tempfile(TMP_WIPE); /* open file f for reading, binary, as keyring file */ if ((f = fopen(ringfile,FOPRBIN)) == NULL) - return(-1); + return -1; /* open file g for writing, binary, as scratch keyring file */ - if ((g = fopen(tempf,FOPWBIN)) == NULL) - { fclose(f); - return(-1); + if ((g = fopen(tempf,FOPWBIN)) == NULL) { + fclose(f); + return -1; } /* open file h for reading, binary, as key file to be inserted */ - if ((h = fopen(keyfile,FOPRBIN)) == NULL) - { fclose(f); + if ((h = fopen(keyfile,FOPRBIN)) == NULL) { + fclose(f); fclose(g); - return(-1); + return -1; } /* Copy pre-key keyring data from f to g */ copyfile(f,g,fp); @@ -2113,20 +2228,21 @@ static int merge_key_to_ringfile(char *k if (!rc) savetempbak(tempf,ringfile); - return(rc ? -1 : 0); -} /* merge_key_to_ringfile */ + return rc ? -1 : 0; +} /* merge_key_to_ringfile */ static int insert_userid(char *keyfile, byte *userid, long fpos) -{ /* insert userid and trust byte at position fpos in file keyfile */ +{ + /* insert userid and trust byte at position fpos in file keyfile */ char *tmpf; FILE *f, *g; tmpf = tempfile(TMP_TMPDIR); if ((f = fopen(keyfile, FOPRBIN)) == NULL) - return(-1); - if ((g = fopen(tmpf, FOPWBIN)) == NULL) - { fclose(f); - return(-1); + return -1; + if ((g = fopen(tmpf, FOPWBIN)) == NULL) { + fclose(f); + return -1; } copyfile(f, g, fpos); putc(CTB_USERID, g); @@ -2134,27 +2250,28 @@ static int insert_userid(char *keyfile, write_trust(g, KC_LEGIT_COMPLETE); copyfile(f, g, -1L); fclose(f); - if (write_error(g)) - { fclose(g); - return(-1); + if (write_error(g)) { + fclose(g); + return -1; } fclose(g); - return(savetempbak(tmpf, keyfile)); + return savetempbak(tmpf, keyfile); } int dokeyedit(char *mcguffin, char *ringfile) -/* Edit the userid and/or pass phrase for an RSA key pair, and - put them back into the ring files. -*/ -{ unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], +/* + * Edit the userid and/or pass phrase for an RSA key pair, and + * put them back into the ring files. + */ +{ + unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION], p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION]; char *fname, secring[MAX_PATH]; FILE *f; - word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */ byte userid[256]; byte userid1[256]; - word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */ + word32 timestamp; /* key certificate timestamp */ byte keyID[KEYFRAGSIZE]; boolean hidekey; /* TRUE iff secret key is encrypted */ boolean changed=FALSE, changeID=FALSE; @@ -2164,54 +2281,62 @@ int dokeyedit(char *mcguffin, char *ring int pplength=0, pslength=0; byte ideakey[16]; byte keyctrl; + struct IdeaCfbContext cfb; if (!ringfile || strlen(ringfile)==0 || !mcguffin || strlen(mcguffin)==0) - return(-1); /* Need ringfile name, user name */ + return -1; /* Need ringfile name, user name */ force_extension(ringfile,PGP_EXTENSION); - if (!strncmp( ringfile, SECRET_KEYRING_FILENAME, strlen( SECRET_KEYRING_FILENAME ))) + /* + * Although the name of a secret keyring may change in the future, it + * is a safe bet that anything named "secring.pgp" will be a secret + * key ring for the indefinite future. + */ + if (!strcmp(file_tail(ringfile), "secring.pgp") || + !strcmp(file_tail(ringfile), file_tail(globalSecringName))) { - fprintf(pgpout, PSTR("\nThis operation may not be performed on a secret keyring.\n\ + fprintf(pgpout, LANG("\nThis operation may not be performed on a secret keyring.\n\ Defaulting to public keyring.")); - buildfilename( ringfile, PUBLIC_KEYRING_FILENAME ); + strcpy(ringfile, globalPubringName); } strcpy((char *)userid, mcguffin); - fprintf(pgpout,PSTR("\nEditing userid \"%s\" in key ring: '%s'.\n"), + fprintf(pgpout,LANG("\nEditing userid \"%s\" in key ring: '%s'.\n"), LOCAL_CHARSET((char *)userid),ringfile); - if (!file_exists (ringfile)) - { fprintf(pgpout,PSTR("\nCan't open public key ring file '%s'\n"), + if (!file_exists (ringfile)) { + fprintf(pgpout,LANG("\nCan't open public key ring file '%s'\n"), ringfile); - return(-1); + return -1; } - status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fpp, &pplength, NULL, - timestamp, userid, n, e); - if (status < 0) - { fprintf(pgpout,PSTR("\n\007Key not found in key ring '%s'.\n"), + status = getpublickey(GPK_GIVEUP|GPK_SHOW, ringfile, &fpp, &pplength, + NULL, (byte *)×tamp, userid, n, e); + if (status < 0) { + fprintf(pgpout,LANG("\n\007Key not found in key ring '%s'.\n"), ringfile); - return(-1); + return -1; } /* Now add to pplength any following key control certificate */ - if ((f = fopen(ringfile,FOPRWBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),ringfile); - return(-1); + if ((f = fopen(ringfile,FOPRWBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),ringfile); + return -1; } if (fread(&ctb, 1, 1, f) != 1 || !is_ctb_type(ctb, CTB_CERT_PUBKEY_TYPE)) - { fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"),ringfile); + { + fprintf(pgpout,LANG("\n\007File '%s' is not a public keyring.\n"),ringfile); fclose(f); - return(-1); + return -1; } fseek(f, fpp, SEEK_SET); - if (is_compromised(f)) - { fprintf(pgpout, PSTR("\n\007This key has been revoked by its owner.\n")); + if (is_compromised(f)) { + fprintf(pgpout, LANG("\n\007This key has been revoked by its owner.\n")); fclose(f); - return(-1); + return -1; } trust_pos = fpp+pplength; fseek(f, trust_pos, SEEK_SET); @@ -2220,65 +2345,72 @@ Defaulting to public keyring.")); extract_keyID(keyID, n); - /* Now read private key, too */ + /* Now read private key, too + * Default name is the same as your secret keyring, then try + * "secring.pgp" if that fails. + */ strcpy(secring, ringfile); - strcpy(file_tail(secring), SECRET_KEYRING_FILENAME); + strcpy(file_tail(secring), file_tail(globalSecringName)); + if (!file_exists(secring) && strcmp(file_tail(secring), "secring.pgp")) + { + strcpy(file_tail(secring), "secring.pgp"); + } - if (!file_exists (secring)) - { fprintf(pgpout,PSTR("\nCan't open secret key ring file '%s'\n"), + if (!file_exists (secring)) { + fprintf(pgpout,LANG("\nCan't open secret key ring file '%s'\n"), secring); fclose(f); - return(-1); + return -1; } /* Get position of key in secret key file */ - (void)getpublickey(GPK_GIVEUP, secring, &fps, &pslength, keyID, - timestamp, userid1, n, e); + (void)getpublickey(GPK_GIVEUP|GPK_SECRET, secring, &fps, &pslength, + keyID, (byte *)×tamp, userid1, n, e); /* This was done to get us fps and pslength */ - status = getsecretkey(GPK_GIVEUP, secring, keyID, timestamp, + status = getsecretkey(GPK_GIVEUP, secring, keyID, (byte *)×tamp, ideakey, &hidekey, userid1, n, e, d, p, q, u); - if (status < 0) /* key not in secret keyring: edit owner trust */ - { int i; + if (status < 0) { /* key not in secret keyring: edit owner trust */ + int i; - fprintf(pgpout, PSTR("\nNo secret key available. Editing public key trust parameter.\n")); - if (trust_pos < 0) - { fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), ringfile); + fprintf(pgpout, LANG("\nNo secret key available. Editing public key trust parameter.\n")); + if (trust_pos < 0) { + fprintf(pgpout,LANG("\n\007File '%s' is not a public keyring.\n"), ringfile); fclose(f); - return(-1); + return -1; } show_key(f, fpp, SHOW_ALL); init_trust_lst(); - fprintf(pgpout, PSTR("Current trust for this key's owner is: %s\n"), + fprintf(pgpout, LANG("Current trust for this key's owner is: %s\n"), trust_lst[keyctrl & KC_OWNERTRUST_MASK]); PascalToC((char *)userid); /* convert to C string for display */ i = ask_owntrust((char *) userid, keyctrl); - if (i == (keyctrl & KC_OWNERTRUST_MASK)) - { fclose(f); - return(0); /* unchanged */ + if (i == (keyctrl & KC_OWNERTRUST_MASK)) { + fclose(f); + return 0; /* unchanged */ } - if (i < 0 || i > KC_OWNERTRUST_ALWAYS) - { + if (i < 0 || i > KC_OWNERTRUST_ALWAYS) { fclose(f); - return(-1); + return -1; } keyctrl = (keyctrl & ~KC_OWNERTRUST_MASK) | i; fseek(f, trust_pos, SEEK_SET); write_trust(f, keyctrl); fclose(f); - fprintf (pgpout, PSTR("Public key ring updated.\n")); - return(0); + fprintf (pgpout, LANG("Public key ring updated.\n")); + return 0; } if (trust_pos > 0 && (keyctrl & (KC_BUCKSTOP|KC_OWNERTRUST_MASK)) != (KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP)) - { /* key is in secret keyring but buckstop is not set */ - fprintf(pgpout, PSTR("\nUse this key as an ultimately-trusted introducer (y/N)? "), userid); - if (getyesno('n')) - { fseek(f, trust_pos, SEEK_SET); + { + /* key is in secret keyring but buckstop is not set */ + fprintf(pgpout, LANG("\nUse this key as an ultimately-trusted introducer (y/N)? "), userid); + if (getyesno('n')) { + fseek(f, trust_pos, SEEK_SET); keyctrl = KC_OWNERTRUST_ULTIMATE|KC_BUCKSTOP; write_trust(f, keyctrl); } @@ -2286,37 +2418,38 @@ Defaulting to public keyring.")); /* Show user her ID again to be clear */ PascalToC((char *)userid); - fprintf(pgpout,PSTR("\nCurrent user ID: %s"), + fprintf(pgpout,LANG("\nCurrent user ID: %s"), LOCAL_CHARSET((char *)userid)); CToPascal((char *)userid); - fprintf(pgpout, PSTR("\nDo you want to change your user ID (y/N)? ")); - if (getyesno('n')) /* user said yes */ - { fprintf(pgpout,PSTR("\nEnter the new user ID: ")); + fprintf(pgpout, LANG("\nDo you want to add a new user ID (y/N)? ")); + if (getyesno('n')) { /* user said yes */ + fprintf(pgpout,LANG("\nEnter the new user ID: ")); getstring((char *)userid,255,TRUE); /* echo keyboard input */ - if (userid[0] == '\0') - { fclose(f); - return(-1); + if (userid[0] == '\0') { + fclose(f); + return -1; } CONVERT_TO_CANONICAL_CHARSET((char *)userid); - fprintf(pgpout, PSTR("\nMake this user ID the primary user ID for this key (y/N)? ")); - if (!getyesno('n')) - { /* position file pointer at selected user id */ + fprintf(pgpout, LANG("\nMake this user ID the primary user ID for this key (y/N)? ")); + if (!getyesno('n')) { + /* position file pointer at selected user id */ int pktlen; long fpuser; strcpy((char *)userid1, mcguffin); if (getpubuserid(ringfile, fpp, userid1, &fpuser, &pktlen, FALSE) < 0) - { fclose(f); - return(-1); + { + fclose(f); + return -1; } fseek(f, fpuser, SEEK_SET); - } - else /* position file pointer at key packet */ + } else { /* position file pointer at key packet */ fseek(f, fpp, SEEK_SET); + } nextkeypacket(f, &ctb); /* skip userid or key packet */ - do /* new user id will be inserted before next userid or key packet */ - { fpp = ftell(f); + do { /* new user id will be inserted before next userid or key packet */ + fpp = ftell(f); if (nextkeypacket(f, &ctb) < 0) break; } while (ctb != CTB_USERID && !is_key_ctb(ctb)); @@ -2326,33 +2459,36 @@ Defaulting to public keyring.")); } fclose(f); - fprintf (pgpout,PSTR("\nDo you want to change your pass phrase (y/N)? ")); - if (getyesno('n')) /* user said yes */ - { hidekey = (GetHashedPassPhrase((char *) ideakey, 2) > 0); + fprintf (pgpout,LANG("\nDo you want to change your pass phrase (y/N)? ")); + if (getyesno('n')) { /* user said yes */ + hidekey = (GetHashedPassPhrase((char *) ideakey, 2) > 0); changed = TRUE; } - if (!changed) - { fprintf (pgpout, PSTR("(No changes will be made.)\n")); + if (!changed) { + fprintf (pgpout, LANG("(No changes will be made.)\n")); if (hidekey) burn(ideakey); goto done; } /* init CFB IDEA key */ - if (hidekey) - { fill0(iv,8); - initcfb_idea(iv,ideakey,FALSE); + if (hidekey) { + ideaCfbInit(&cfb, ideakey); burn(ideakey); } /* First write secret key data to a file */ fname = tempfile(TMP_TMPDIR|TMP_WIPE); - writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u); - if (changeID) + writekeyfile(fname, hidekey ? &cfb : 0, timestamp, userid, n,e,d,p,q,u); + + if (hidekey) /* done with IDEA to protect RSA secret key */ + ideaCfbDestroy(&cfb); + + if (changeID) { keylen = -1; - else - { /* don't copy userid */ + } else { + /* don't copy userid */ f = fopen(fname, FOPRBIN); if (f == NULL) goto err; @@ -2361,25 +2497,22 @@ Defaulting to public keyring.")); fclose(f); } if (merge_key_to_ringfile(fname,secring,fps,pslength,keylen) < 0) - { fprintf (pgpout, PSTR("\n\007Unable to update secret key ring.\n")); + { + fprintf (pgpout, LANG("\n\007Unable to update secret key ring.\n")); goto err; } - fprintf (pgpout, PSTR("\nSecret key ring updated...\n")); + fprintf (pgpout, LANG("\nSecret key ring updated...\n")); /* Now write public key data to file */ - if (changeID) - { - if (insert_userid(ringfile, userid, fpp) < 0) - { fprintf (pgpout, PSTR("\n\007Unable to update public key ring.\n")); + if (changeID) { + if (insert_userid(ringfile, userid, fpp) < 0) { + fprintf (pgpout, LANG("\n\007Unable to update public key ring.\n")); goto err; } - fprintf (pgpout, PSTR("Public key ring updated.\n")); + fprintf (pgpout, LANG("Public key ring updated.\n")); + } else { + fprintf (pgpout, LANG("(No need to update public key ring)\n")); } - else - fprintf (pgpout, PSTR("(No need to update public key ring)\n")); - - if (hidekey) /* done with IDEA to protect RSA secret key */ - close_idea(); rmtemp(fname); @@ -2390,9 +2523,8 @@ done: mp_burn(u); mp_burn(e); mp_burn(n); - burn(iv); - return(0); /* normal return */ + return 0; /* normal return */ err: mp_burn(d); /* burn sensitive data on stack */ mp_burn(p); @@ -2400,17 +2532,16 @@ err: mp_burn(u); mp_burn(e); mp_burn(n); - burn(iv); rmtemp(fname); - return(-1); /* error return */ + return -1; /* error return */ -} /* dokeyedit */ +} /* dokeyedit */ int disable_key(char *keyguffin, char *keyfile) -{ +{ FILE *f; byte keyctrl; byte keyID[KEYFRAGSIZE]; @@ -2422,80 +2553,79 @@ int disable_key(char *keyguffin, char *k strcpy((char *)userid, keyguffin); if (getpublickey(GPK_SHOW|GPK_DISABLED, keyfile, &fp, &pktlen, NULL, NULL, userid, n, e) < 0) - return(-1); + return -1; extract_keyID(keyID, n); if (getsecretkey(GPK_GIVEUP, NULL, keyID, NULL, NULL, NULL, userid, n, e, NULL, NULL, NULL, NULL) >= 0) - { /* can only compromise if key also in secring */ + { + /* can only compromise if key also in secring */ PascalToC((char *) userid); fprintf(pgpout, -PSTR("\nDo you want to permanently revoke your public key\n\ +LANG("\nDo you want to permanently revoke your public key\n\ by issuing a secret key compromise certificate\n\ for \"%s\" (y/N)? "), LOCAL_CHARSET((char *)userid)); if (getyesno('n')) return compromise(keyID, keyfile); } - if ((f = fopen(keyfile,FOPRWBIN)) == NULL) - { fprintf(pgpout,PSTR("\n\007Can't open key ring file '%s'\n"),keyfile); - return(-1); + if ((f = fopen(keyfile,FOPRWBIN)) == NULL) { + fprintf(pgpout,LANG("\n\007Can't open key ring file '%s'\n"),keyfile); + return -1; } fseek(f, fp+pktlen, SEEK_SET); - if (read_trust(f, &keyctrl) < 0) - { - fprintf(pgpout,PSTR("\n\007File '%s' is not a public keyring.\n"), keyfile); - fprintf(pgpout, PSTR("You can only disable keys on your public keyring.\n")); + if (read_trust(f, &keyctrl) < 0) { + fprintf(pgpout,LANG("\n\007File '%s' is not a public keyring.\n"), keyfile); + fprintf(pgpout, LANG("You can only disable keys on your public keyring.\n")); fclose(f); return -1; } - if (keyctrl & KC_DISABLED) - { - fprintf(pgpout, PSTR("\nKey is already disabled.\n\ + if (keyctrl & KC_DISABLED) { + fprintf(pgpout, LANG("\nKey is already disabled.\n\ Do you want to enable this key again (y/N)? ")); keyctrl &= ~KC_DISABLED; - } - else - { - fprintf(pgpout, PSTR("\nDisable this key (y/N)? ")); + } else { + fprintf(pgpout, LANG("\nDisable this key (y/N)? ")); keyctrl |= KC_DISABLED; } - if (!getyesno('n')) - { fclose(f); + if (!getyesno('n')) { + fclose(f); return -1; } write_trust_pos(f, keyctrl, fp+pktlen); fclose(f); return 0; -} /* disable_key */ +} /* disable_key */ /*======================================================================*/ - int dokeygen(char *numstr, char *numstr2) -/* Do an RSA key pair generation, and write them out to the keyring files. - numstr is a decimal string, the desired bitcount for the modulus n. - numstr2 is a decimal string, the desired bitcount for the exponent e. -*/ -{ unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION], d[MAX_UNIT_PRECISION], - p[MAX_UNIT_PRECISION], q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION]; +/* + * Do an RSA key pair generation, and write them out to the keyring files. + * numstr is a decimal string, the desired bitcount for the modulus n. + * numstr2 is a decimal string, the desired bitcount for the exponent e. + */ +{ + unit n[MAX_UNIT_PRECISION], e[MAX_UNIT_PRECISION]; + unit d[MAX_UNIT_PRECISION], p[MAX_UNIT_PRECISION]; + unit q[MAX_UNIT_PRECISION], u[MAX_UNIT_PRECISION]; char *fname; - char ringfile[MAX_PATH]; word16 iv[4]; /* for IDEA CFB mode, to protect RSA secret key */ byte userid[256]; - short keybits,ebits; - word32 tstamp; byte *timestamp = (byte *) &tstamp; /* key certificate timestamp */ + short keybits, ebits; + word32 tstamp; boolean hidekey; /* TRUE iff secret key is encrypted */ - boolean seedfileexists; /* FALSE if we need to create one */ + boolean cryptrandflag; byte ideakey[16]; + struct IdeaCfbContext cfb; - if (!numstr || strlen(numstr)==0) - { fprintf(pgpout,PSTR("\nPick your RSA key size:\ -\n 1) 384 bits- Casual grade, fast but less secure\ -\n 2) 512 bits- Commercial grade, medium speed, good security\ -\n 3) 1024 bits- Military grade, very slow, highest security\ -\nChoose 1, 2, or 3, or enter desired number of bits: ")); + if (!numstr || strlen(numstr)==0) { + fputs(LANG("Pick your RSA key size:\n\ + 1) 512 bits- Low commercial grade, fast but less secure\n\ + 2) 768 bits- High commercial grade, medium speed, good security\n\ + 3) 1024 bits- \"Military\" grade, slow, highest security\n\ +Choose 1, 2, or 3, or enter desired number of bits: "), pgpout); numstr = (char *)userid; /* use userid buffer as scratchpad */ getstring(numstr,5,TRUE); /* echo keyboard */ } @@ -2505,135 +2635,129 @@ int dokeygen(char *numstr, char *numstr2 keybits = keybits*10 + (*numstr++ - '0'); if (keybits==0) /* user entered null response */ - return(-1); /* error return */ + return -1; /* error return */ /* Standard default key sizes: */ - if (keybits==1) keybits=384; /* Casual grade */ - if (keybits==2) keybits=512; /* Commercial grade */ + if (keybits==1) keybits=512; /* Low commercial grade */ + if (keybits==2) keybits=768; /* High commercial grade */ if (keybits==3) keybits=1024; /* Military grade */ #ifndef DEBUG /* minimum RSA keysize: */ if (keybits < 384) keybits=384; - if (keybits > MAX_BIT_PRECISION-UNITSIZE) /* Paranoia */ - keybits = MAX_BIT_PRECISION-UNITSIZE; + if (keybits > 1024) + keybits = 1024; #else if (keybits > MAX_BIT_PRECISION) keybits = MAX_BIT_PRECISION; #endif -#ifdef notdef /* This annoys everyone, so take it out. */ -/* If we use Merritt's modmult algorithm, the primes p and q's - bit length should not be an exact multiple of UNITSIZE, - because Merritt's modmult algorithm performs slowest in that - case, wasting an extra unit of precision for overflow. -*/ - if ((keybits % (2*UNITSIZE))==0) - keybits -= 2; /* make each prime one bit shorter. */ -#endif /* MERRITT */ - ebits = 0; /* number of bits in e */ - while ((*numstr2>='0') && (*numstr2<='9')) + while ((*numstr2>='0') && (*numstr2<='9')) ebits = ebits*10 + (*numstr2++ - '0'); - fprintf(pgpout,PSTR("\nGenerating an RSA key with a %d-bit modulus... "),keybits); + fprintf(pgpout,LANG("Generating an RSA key with a %d-bit modulus.\n"),keybits); - fprintf(pgpout, -PSTR("\nYou need a user ID for your public key. The desired form for this\n\ + fputs(LANG("\nYou need a user ID for your public key. The desired form for this\n\ user ID is your name, followed by your E-mail address enclosed in\n\ , if you have an E-mail address.\n\ -For example: John Q. Smith <12345.6789@compuserve.com>\n")); - fprintf(pgpout,PSTR("\nEnter a user ID for your public key: \n")); +For example: John Q. Smith <12345.6789@compuserve.com>\n\ +Enter a user ID for your public key: \n"), pgpout); #ifdef VMS putch('\n'); /* That last newline was just a return, do a real one */ #endif getstring((char *)userid,255,TRUE); /* echo keyboard input */ if (userid[0]=='\0') /* user entered null response */ - return(-1); /* error return */ + return -1; /* error return */ CONVERT_TO_CANONICAL_CHARSET((char *)userid); - CToPascal((char *)userid); /* convert to length-prefixed string */ + CToPascal((char *)userid); /* convert to length-prefixed string */ - { fprintf(pgpout, -PSTR("\nYou need a pass phrase to protect your RSA secret key.\n\ + fputs(LANG("\nYou need a pass phrase to protect your RSA secret key.\n\ Your pass phrase can be any sentence or phrase and may have many\n\ -words, spaces, punctuation, or any other printable characters. ")); - hidekey = (GetHashedPassPhrase((char *) ideakey, 2) > 0); - /* init CFB IDEA key */ - if (hidekey) - { fill0(iv,8); - initcfb_idea(iv,ideakey,FALSE); - randaccum_later(64); /* IV for encryption */ - } +words, spaces, punctuation, or any other printable characters.\n"), pgpout); + hidekey = (GetHashedPassPhrase(ideakey, 2) > 0); + /* init CFB IDEA key */ + if (hidekey) { + ideaCfbInit(&cfb, ideakey); + trueRandAccumLater(64); /* IV for encryption */ } + /* As rsa_keygen does a major accumulation of random bits, if we need - any others for a seed file, let's get them at the same time. */ - seedfileexists = seedfile_exists(); + * any others for a seed file, let's get them at the same time. + */ + cryptrandflag = (cryptRandOpen() < 0); + if (cryptrandflag) + trueRandAccumLater(192); - fprintf(pgpout,PSTR("\nNote that key generation is a VERY lengthy process.\n")); + fputs(LANG("\nNote that key generation is a lengthy process.\n"), pgpout); - if (rsa_keygen(n,e,d,p,q,u,keybits,ebits) < 0) - { fprintf(pgpout,PSTR("\n\007Keygen failed!\n")); - return(-1); /* error return */ + if (rsa_keygen(n, e, d, p, q, u, keybits, ebits) < 0) { + fputs(LANG("\n\007Keygen failed!\n"), pgpout); + return -1; /* error return */ } + putc('\n', pgpout); - if (verbose) - { - fprintf(pgpout,PSTR("Key ID %s\n"), key2IDstring(n)); + if (verbose) { + fprintf(pgpout,LANG("Key ID %s\n"), key2IDstring(n)); - mp_display(" modulus n = ",n); - mp_display("exponent e = ",e); + mp_display(" modulus n = ", n); + mp_display("exponent e = ", e); - mp_display("exponent d = ",d); - mp_display(" prime p = ",p); - mp_display(" prime q = ",q); - mp_display(" inverse u = ",u); + fputs(LANG("Display secret components (y/N)?"), pgpout); + if (getyesno('n')) { + mp_display("exponent d = ", d); + mp_display(" prime p = ", p); + mp_display(" prime q = ", q); + mp_display(" inverse u = ", u); + } } - get_timestamp(timestamp); /* Timestamp when key was generated */ + tstamp = get_timestamp(NULL); /* Timestamp when key was generated */ fputc('\007',pgpout); /* sound the bell when done with lengthy process */ - fputc('\n',pgpout); + fflush(pgpout); /* First, write out the secret key... */ fname = tempfile(TMP_TMPDIR|TMP_WIPE); - writekeyfile(fname,hidekey,timestamp,userid,n,e,d,p,q,u); - buildfilename(ringfile,SECRET_KEYRING_FILENAME); - if (file_exists(ringfile)) - { merge_key_to_ringfile(fname,ringfile,0L,0,-1L); + writekeyfile(fname, hidekey?&cfb:0, tstamp, userid, n, e, d, p, q, u); + + mp_burn(d); + mp_burn(p); + mp_burn(q); + mp_burn(u); + + if (hidekey) /* done with IDEA to protect RSA secret key */ + ideaCfbDestroy(&cfb); + + if (file_exists(globalSecringName)) { + merge_key_to_ringfile(fname,globalSecringName,0L,0,-1L); rmtemp(fname); + } else { + savetemp(fname, globalSecringName); } - else - savetemp(fname, ringfile); /* Second, write out the public key... */ fname = tempfile(TMP_TMPDIR|TMP_WIPE); - writekeyfile(fname,FALSE,timestamp,userid,n,e,NULL,NULL,NULL,NULL); - buildfilename(ringfile,PUBLIC_KEYRING_FILENAME); - if (file_exists(ringfile)) - { merge_key_to_ringfile(fname,ringfile,0L,0,-1L); + writekeyfile(fname, NULL, tstamp, userid, n, e, NULL, NULL, NULL, NULL); + if (file_exists(globalPubringName)) { + merge_key_to_ringfile(fname,globalPubringName,0L,0,-1L); rmtemp(fname); + } else { + savetemp(fname, globalPubringName); } - else - savetemp(fname, ringfile); - - if (hidekey) /* done with IDEA to protect RSA secret key */ - close_idea(); - mp_burn(d); /* burn sensitive data on stack */ - mp_burn(p); /* burn sensitive data on stack */ - mp_burn(q); /* burn sensitive data on stack */ - mp_burn(u); /* burn sensitive data on stack */ - mp_burn(e); /* burn sensitive data on stack */ - mp_burn(n); /* burn sensitive data on stack */ - burn(iv); /* burn sensitive data on stack */ - - fprintf(pgpout,PSTR("\007Key generation completed.\n")); - - /* If we need a seed file, create it now. - */ - if (!seedfileexists) - create_seedfile(); + mp_burn(e); + mp_burn(n); + + fputs(LANG("\007Key generation completed.\n"), pgpout); - return(0); /* normal return */ -} /* dokeygen */ + /* + * If we need a seed file, create it now. + */ + if (cryptrandflag) { + trueRandConsume(192); + cryptRandCreate(); + } + return 0; /* normal return */ +} /* dokeygen */