diff options
-rw-r--r-- | NEWS | 31 | ||||
-rw-r--r-- | doc/README.W32 | 16 | ||||
-rw-r--r-- | g10/ChangeLog | 8 | ||||
-rw-r--r-- | g10/card-util.c | 35 | ||||
-rw-r--r-- | g10/getkey.c | 32 | ||||
-rw-r--r-- | g10/gpgv.c | 1 | ||||
-rw-r--r-- | g10/import.c | 233 | ||||
-rw-r--r-- | g10/keydb.h | 9 | ||||
-rw-r--r-- | g10/keylist.c | 60 | ||||
-rw-r--r-- | g10/main.h | 6 |
10 files changed, 397 insertions, 34 deletions
@@ -1,15 +1,6 @@ Noteworthy changes in version 1.4.1 ------------------------------------------------- - * [W32] The algorithm for the default home directory changed: - First we look at the environment variable GNUPGHOME, if this one - is not set, we check whether the registry entry - HKCU\Software\GNU\GnuPG:HomeDir has been set and if this fails - we use a GnuPG directory below the standard application data - directory (APPDATA) of the current user. Only in the case that - this directory cannot be determined, the old default of c:\gnupg - will be used. The option --homedir still overrides all of them. - * New --rfc2440-text option which controls how text is handled in signatures. This is in response to some problems seen with certain PGP/MIME mail clients and GnuPG version 1.4.0. More @@ -27,6 +18,28 @@ Noteworthy changes in version 1.4.1 option --with-libcurl. Without this option, the existing HTTP code is used for HTTP, and HTTPS and FTP are not supported. + * When running a --card-status or --card-edit and a public key is + available, missing secret key stubs will be created on the fly. + Details of the key are listed too. + + * [W32] The algorithm for the default home directory changed: + First we look at the environment variable GNUPGHOME, if this one + is not set, we check whether the registry entry + {HKCU,HKLM}\Software\GNU\GnuPG:HomeDir has been set. If this + fails we use a GnuPG directory below the standard application + data directory (APPDATA) of the current user. Only in the case + that this directory cannot be determined, the old default of + c:\gnupg will be used. The option --homedir still overrides all + of them. + + * [W32] The locale selection under Windows changed. You need to + enter the locale in the registry at HKCU\Software\GNU\GnuPG:Lang. + For German you would use "de". If it is not set, GnupG falls + back to HKLM. The languages files "*.mo" are expected in a + directory named "gnupg.nls" below the installation directory; + that directory must be stored in the registry at the same key as + above with the name "Install Directory". + Noteworthy changes in version 1.4.0 (2004-12-16) ------------------------------------------------- diff --git a/doc/README.W32 b/doc/README.W32 index a55220593..cbee3195f 100644 --- a/doc/README.W32 +++ b/doc/README.W32 @@ -30,18 +30,10 @@ Installation instructions: Internationalization support: ----------------------------- - 1. Decide where to store the translation files for your language. - Here we assume the directory "c:/gnu/locale/fr" - - 2. Set the directory with the translations into the Registry under - the key: - HKEY_CURRENT_USER -> Control Panel -> Mingw32 -> NLS - (you probably need to create the keys Mingw32 and NLS) using a string - entry with the name "MoDir". - 3. Select which language to use and copy the currect translation file - under the name "gnupg.mo" into the directory set in step 2 - (Example: "copy fr.mo c:\gnu\locale\fr\gnupg.mo") - 4. Done. + 1 + +Store the locale id (like "de") into the registry under the key +HKEY_CURRENT_USER\Software\GNU\GnuPG with the name "Lang". How to build it from the source: diff --git a/g10/ChangeLog b/g10/ChangeLog index 6f6bfc597..4be117f89 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,5 +1,13 @@ 2005-01-20 Werner Koch <[email protected]> + * gpgv.c (tty_fprintf): New stub. + + * card-util.c (card_status): Create asecret key stub on the fly + and print more information about a card key. + * import.c (pub_to_sec_keyblock, auto_create_card_key_stub): New. + * getkey.c (get_seckeyblock_byfprint): New. + * keylist.c (print_card_key_info): New. + * g10.c (i18n_init) [W32]: Pass registry key to gettext initialization. * gpgv.c (i18n_init) [W32]: Ditto. diff --git a/g10/card-util.c b/g10/card-util.c index 8d38fb416..3b67400a4 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -1,5 +1,5 @@ /* card-util.c - Utility functions for the OpenPGP card. - * Copyright (C) 2003 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -270,6 +270,7 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) PKT_public_key *pk = xcalloc (1, sizeof *pk); int rc; unsigned int uval; + const unsigned char *thefpr; if (serialno && serialnobuflen) *serialno = 0; @@ -425,8 +426,34 @@ card_status (FILE *fp, char *serialno, size_t serialnobuflen) tty_fprintf (fp, " created ....: %s\n", asctimestamp (info.fpr3time)); tty_fprintf (fp, "General key info..: "); - if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) - print_pubkey_info (fp, pk); + + thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 : + info.fpr3valid? info.fpr3 : NULL); + if ( thefpr && !get_pubkey_byfprint (pk, thefpr, 20)) + { + KBNODE keyblock = NULL; + + print_pubkey_info (fp, pk); + + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + else if ( !get_keyblock_byfprint (&keyblock, thefpr, 20) ) + { + release_kbnode (keyblock); + keyblock = NULL; + + if (!auto_create_card_key_stub (info.serialno, + info.fpr1valid? info.fpr1:NULL, + info.fpr2valid? info.fpr2:NULL, + info.fpr3valid? info.fpr3:NULL)) + { + if ( !get_seckeyblock_byfprint (&keyblock, thefpr, 20) ) + print_card_key_info (fp, keyblock); + } + } + + release_kbnode (keyblock); + } else tty_fprintf (fp, "[none]\n"); } @@ -1037,7 +1064,7 @@ generate_card_keys (const char *serialno) } -/* This fucntion is used by the key edit menu to generate an arbitrary +/* This function is used by the key edit menu to generate an arbitrary subkey. */ int card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock) diff --git a/g10/getkey.c b/g10/getkey.c index 9cc0cbb7d..824c9bb7a 100644 --- a/g10/getkey.c +++ b/g10/getkey.c @@ -1,6 +1,6 @@ /* getkey.c - Get a key from the database * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1139,13 +1139,41 @@ get_seckey_byfprint( PKT_secret_key *sk, if (!rc && sk ) sk_from_block ( &ctx, sk, kb ); release_kbnode ( kb ); - get_pubkey_end( &ctx ); + get_seckey_end( &ctx ); } else rc = G10ERR_GENERAL; /* Oops */ return rc; } + +/* Search for a secret key with the given fingerprint and return the + complete keyblock which may have more than only this key. */ +int +get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ) +{ + int rc; + struct getkey_ctx_s ctx; + + if (fprint_len != 20 && fprint_len == 16) + return G10ERR_GENERAL; /* Oops */ + + memset (&ctx, 0, sizeof ctx); + ctx.not_allocated = 1; + ctx.kr_handle = keydb_new (1); + ctx.nitems = 1; + ctx.items[0].mode = (fprint_len==16 + ? KEYDB_SEARCH_MODE_FPR16 + : KEYDB_SEARCH_MODE_FPR20); + memcpy (ctx.items[0].u.fpr, fprint, fprint_len); + rc = lookup (&ctx, ret_keyblock, 1); + get_seckey_end (&ctx); + + return rc; +} + + /************************************************ ************* Merging stuff ******************** diff --git a/g10/gpgv.c b/g10/gpgv.c index 020b548bb..3e545cc9b 100644 --- a/g10/gpgv.c +++ b/g10/gpgv.c @@ -380,6 +380,7 @@ void rndlinux_constructor(void) {} /* Stubs to avoid linking to ../util/ttyio.c */ int tty_batchmode( int onoff ) { return 0; } void tty_printf( const char *fmt, ... ) { } +void tty_fprintf (FILE *fp, const char *fmt, ... ) { } void tty_print_string( const byte *p, size_t n ) { } void tty_print_utf8_string( const byte *p, size_t n ) {} void tty_print_utf8_string2( const byte *p, size_t n, size_t max_n ) {} diff --git a/g10/import.c b/g10/import.c index d0c1c01ac..4119b01c1 100644 --- a/g10/import.c +++ b/g10/import.c @@ -1,6 +1,6 @@ -/* import.c +/* import.c - import a key into our key storage. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -2118,3 +2118,232 @@ append_key( KBNODE keyblock, KBNODE node, int *n_sigs, return 0; } + + + +/* Walk a public keyblock and produce a secret keyblock out of it. + Instead of inserting the secret key parameters (which we don't + have), we insert a stub. */ +static KBNODE +pub_to_sec_keyblock (KBNODE pub_keyblock) +{ + KBNODE pubnode, secnode; + KBNODE sec_keyblock = NULL; + KBNODE walkctx = NULL; + + while((pubnode = walk_kbnode (pub_keyblock,&walkctx,0))) + { + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY + || pubnode->pkt->pkttype == PKT_PUBLIC_SUBKEY) + { + /* Make a secret key. We only need to convert enough to + write the keyblock out. */ + PKT_public_key *pk = pubnode->pkt->pkt.public_key; + PACKET *pkt = m_alloc_clear (sizeof *pkt); + PKT_secret_key *sk = m_alloc_clear (sizeof *sk); + int i, n; + + if (pubnode->pkt->pkttype == PKT_PUBLIC_KEY) + pkt->pkttype = PKT_SECRET_KEY; + else + pkt->pkttype = PKT_SECRET_SUBKEY; + + pkt->pkt.secret_key = sk; + + copy_public_parts_to_secret_key ( pk, sk ); + sk->version = pk->version; + sk->timestamp = pk->timestamp; + + n = pubkey_get_npkey (pk->pubkey_algo); + if (!n) + n = 1; /* Unknown number of parameters, however the data + is stored in the first mpi. */ + for (i=0; i < n; i++ ) + sk->skey[i] = mpi_copy (pk->pkey[i]); + + sk->is_protected = 1; + sk->protect.s2k.mode = 1001; + + secnode = new_kbnode (pkt); + } + else + { + secnode = clone_kbnode (pubnode); + } + + if(!sec_keyblock) + sec_keyblock = secnode; + else + add_kbnode (sec_keyblock, secnode); + } + + return sec_keyblock; +} + + +/* Walk over the secret keyring SEC_KEYBLOCK and update any simple + stub keys with the serial number SNNUM of the card if one of the + fingerprints FPR1, FPR2 or FPR3 match. Print a note if the key is + a duplicate (may happen in case of backed uped keys). + + Returns: True if anything changed. +*/ +static int +update_sec_keyblock_with_cardinfo (KBNODE sec_keyblock, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3, + const char *serialnostr) +{ + KBNODE node; + KBNODE walkctx = NULL; + PKT_secret_key *sk; + byte array[MAX_FINGERPRINT_LEN]; + size_t n; + int result = 0; + const char *s; + + while((node = walk_kbnode (sec_keyblock, &walkctx, 0))) + { + if (node->pkt->pkttype != PKT_SECRET_KEY + && node->pkt->pkttype != PKT_SECRET_SUBKEY) + continue; + sk = node->pkt->pkt.secret_key; + + fingerprint_from_sk (sk, array, &n); + if (n != 20) + continue; /* Can't be a card key. */ + if ( !((fpr1 && !memcmp (array, fpr1, 20)) + || (fpr2 && !memcmp (array, fpr2, 20)) + || (fpr3 && !memcmp (array, fpr3, 20))) ) + continue; /* No match. */ + + if (sk->is_protected == 1 && sk->protect.s2k.mode == 1001) + { + /* Standard case: migrate that stub to a key stub. */ + sk->protect.s2k.mode = 1002; + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + sk->protect.iv[sk->protect.ivlen] = xtoi_2 (s); + result = 1; + } + else if (sk->is_protected == 1 && sk->protect.s2k.mode == 1002) + { + s = serialnostr; + for (sk->protect.ivlen=0; sk->protect.ivlen < 16 && *s && s[1]; + sk->protect.ivlen++, s += 2) + if (sk->protect.iv[sk->protect.ivlen] != xtoi_2 (s)) + { + log_info (_("NOTE: a key's S/N does not " + "match the card's one\n")); + break; + } + } + else + { + if (node->pkt->pkttype != PKT_SECRET_KEY) + log_info (_("NOTE: primary key is online and stored on card\n")); + else + log_info (_("NOTE: secondary key is online and stored on card\n")); + } + } + + return result; +} + + + +/* Check whether a secret key stub exists for the public key PK. If + not create such a stub key and store it into the secring. If it + exists, add appropriate subkey stubs and update the secring. + Return 0 if the key could be created. */ +int +auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3) +{ + KBNODE pub_keyblock; + KBNODE sec_keyblock; + KEYDB_HANDLE hd; + int rc; + + /* We only want to do this for an OpenPGP card. */ + if (!serialnostr || strncmp (serialnostr, "D27600012401", 12) + || strlen (serialnostr) != 32 ) + return G10ERR_GENERAL; + + /* First get the public keyring from any of the provided fingerprints. */ + if ( (fpr1 && !get_keyblock_byfprint (&pub_keyblock, fpr1, 20)) + || (fpr2 && !get_keyblock_byfprint (&pub_keyblock, fpr2, 20)) + || (fpr3 && !get_keyblock_byfprint (&pub_keyblock, fpr3, 20))) + ; + else + return G10ERR_GENERAL; + + hd = keydb_new (1); + + /* Now check whether there is a secret keyring. */ + { + PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key; + byte afp[MAX_FINGERPRINT_LEN]; + size_t an; + + fingerprint_from_pk (pk, afp, &an); + memset (afp, 0, MAX_FINGERPRINT_LEN); + rc = keydb_search_fpr (hd, afp); + } + + if (!rc) + { + rc = keydb_get_keyblock (hd, &sec_keyblock); + if (rc) + { + log_error (_("error reading keyblock: %s\n"), g10_errstr(rc) ); + rc = G10ERR_GENERAL; + } + else + { + merge_keys_and_selfsig (sec_keyblock); + + /* FIXME: We need to add new subkeys first. */ + if (update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr)) + { + rc = keydb_update_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + } + else /* A secret key does not exists - create it. */ + { + sec_keyblock = pub_to_sec_keyblock (pub_keyblock); + update_sec_keyblock_with_cardinfo (sec_keyblock, + fpr1, fpr2, fpr3, + serialnostr); + + rc = keydb_locate_writable (hd, NULL); + if (rc) + { + log_error (_("no default secret keyring: %s\n"), g10_errstr (rc)); + rc = G10ERR_GENERAL; + } + else + { + rc = keydb_insert_keyblock (hd, sec_keyblock ); + if (rc) + log_error (_("error writing keyring `%s': %s\n"), + keydb_get_resource_name (hd), g10_errstr(rc) ); + } + } + + release_kbnode (sec_keyblock); + release_kbnode (pub_keyblock); + keydb_release (hd); + return rc; +} + diff --git a/g10/keydb.h b/g10/keydb.h index eb5b2b5a4..7ec0384a1 100644 --- a/g10/keydb.h +++ b/g10/keydb.h @@ -224,10 +224,15 @@ int seckey_available( u32 *keyid ); int get_seckey_byname( PKT_secret_key *sk, const char *name, int unlock ); int get_seckey_bynames( GETKEY_CTX *rx, PKT_secret_key *sk, STRLIST names, KBNODE *ret_keyblock ); +int get_seckey_next (GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock); +void get_seckey_end( GETKEY_CTX ctx ); + int get_seckey_byfprint( PKT_secret_key *sk, const byte *fprint, size_t fprint_len); -int get_seckey_next( GETKEY_CTX ctx, PKT_secret_key *sk, KBNODE *ret_keyblock ); -void get_seckey_end( GETKEY_CTX ctx ); +int get_seckeyblock_byfprint (KBNODE *ret_keyblock, const byte *fprint, + size_t fprint_len ); + + int enum_secret_keys( void **context, PKT_secret_key *sk, int with_subkeys, int with_spm ); void merge_keys_and_selfsig( KBNODE keyblock ); diff --git a/g10/keylist.c b/g10/keylist.c index b712aa466..642598939 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -1,6 +1,6 @@ /* keylist.c * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, - * 2004 Free Software Foundation, Inc. + * 2004, 2005 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -167,6 +167,60 @@ print_pubkey_info (FILE *fp, PKT_public_key *pk) m_free (p); } + +/* Print basic information of a secret key including the card serial + number information. */ +void +print_card_key_info (FILE *fp, KBNODE keyblock) +{ + KBNODE node; + int i; + + for (node = keyblock; node; node = node->next ) + { + if (node->pkt->pkttype == PKT_SECRET_KEY + || (node->pkt->pkttype == PKT_SECRET_SUBKEY) ) + { + PKT_secret_key *sk = node->pkt->pkt.secret_key; + + tty_fprintf (fp, "%s%c %4u%c/%s ", + node->pkt->pkttype == PKT_SECRET_KEY? "sec":"ssb", + (sk->protect.s2k.mode==1001)?'#': + (sk->protect.s2k.mode==1002)?'>':' ', + nbits_from_sk (sk), + pubkey_letter (sk->pubkey_algo), + keystr_from_sk(sk)); + tty_fprintf (fp, _("created: %s"), datestr_from_sk (sk)); + tty_fprintf (fp, " "); + tty_fprintf (fp, _("expires: %s"), expirestr_from_sk (sk)); + if (sk->is_protected && sk->protect.s2k.mode == 1002) + { + tty_fprintf (fp, "\n "); + tty_fprintf (fp, _("card-no: ")); + if (sk->protect.ivlen == 16 + && !memcmp (sk->protect.iv, "\xD2\x76\x00\x01\x24\x01", 6)) + { + /* This is an OpenPGP card. */ + for (i=8; i < 14; i++) + { + if (i == 10) + tty_fprintf (fp, " "); + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + else + { /* Something is wrong: Print all. */ + for (i=0; i < sk->protect.ivlen; i++) + tty_fprintf (fp, "%02X", sk->protect.iv[i]); + } + } + tty_fprintf (fp, "\n"); + } + } +} + + + /* Flags = 0x01 hashed 0x02 critical */ static void status_one_subpacket(sigsubpkttype_t type,size_t len,int flags,const byte *buf) @@ -1437,9 +1491,9 @@ print_fingerprint (PKT_public_key *pk, PKT_secret_key *sk, int mode ) } else if (mode == 2) { fp = NULL; /* use tty */ - /* Translators: this should fit into 24 bytes to that the fingerprint - * data is properly aligned with the user ID */ if(primary) + /* TRANSLATORS: this should fit into 24 bytes to that the + * fingerprint data is properly aligned with the user ID */ text = _(" Primary key fingerprint:"); else text = _(" Subkey fingerprint:"); diff --git a/g10/main.h b/g10/main.h index bf8543f0e..a456c96d5 100644 --- a/g10/main.h +++ b/g10/main.h @@ -211,6 +211,11 @@ void import_print_stats (void *hd); int collapse_uids( KBNODE *keyblock ); +int auto_create_card_key_stub ( const char *serialnostr, + const unsigned char *fpr1, + const unsigned char *fpr2, + const unsigned char *fpr3); + /*-- export.c --*/ int parse_export_options(char *str,unsigned int *options,int noisy); int export_pubkeys( STRLIST users, unsigned int options ); @@ -247,6 +252,7 @@ void dump_attribs(const PKT_user_id *uid, void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); void print_pubkey_info (FILE *fp, PKT_public_key *pk); +void print_card_key_info (FILE *fp, KBNODE keyblock); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); |