From 99cabff03f3d27f7ac2a12b837b17a538be1fe1f Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 2 Oct 2003 10:20:12 +0000 Subject: [PATCH] * cardglue.c (learn_status_cb): Release values before assignment so that it can be used by getattr to update the structure. (agent_scd_getattr): New. * keylist.c (print_pubkey_info): Add FP arg for optional printing to a stream. Changed all callers. --- ChangeLog | 5 + configure.ac | 5 + g10/ChangeLog | 42 ++++ g10/Makefile.am | 25 ++- g10/apdu.c | 16 +- g10/app-common.h | 72 ++++++- g10/app-openpgp.c | 520 ++++++++++++++++++++++++---------------------- g10/card-util.c | 111 ++++++---- g10/cardglue.c | 39 ++-- g10/cardglue.h | 5 +- g10/ccid-driver.c | 16 +- g10/delkey.c | 2 +- g10/iso7816.c | 16 +- g10/iso7816.h | 2 + g10/keylist.c | 30 ++- g10/main.h | 2 +- g10/revoke.c | 2 +- 17 files changed, 562 insertions(+), 348 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1cad28e6..f61e137bc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2003-10-01 Werner Koch + + * configure.ac (AH_BOTTOM): Define GNUPG_MAJOR_VERSION. + (ENABLE_CARD_SUPPORT): Define as automake conditional. + 2003-09-30 David Shaw * NEWS: Note that SHA-256 is read-write now, that TIGER/192 is no diff --git a/configure.ac b/configure.ac index cb393c829..6d7f43755 100644 --- a/configure.ac +++ b/configure.ac @@ -112,6 +112,7 @@ if test "$card_support" = yes ; then AC_DEFINE(ENABLE_CARD_SUPPORT,1, [Define to include the OpenPGP card support]) fi +AM_CONDITIONAL(ENABLE_CARD_SUPPORT, test "$card_support" = yes) dnl See if we are disabling any algorithms or features for a smaller dnl binary @@ -309,6 +310,10 @@ AH_BOTTOM([ #define EXEC_TEMPFILE_ONLY #endif +/* This is the major version number of GnuPG so that + source included files can test for this. */ +#define GNUPG_MAJOR_VERSION 1 + #include "g10defs.h" ]) diff --git a/g10/ChangeLog b/g10/ChangeLog index a710495e4..0306e2691 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,45 @@ +2003-10-02 Werner Koch + + * cardglue.c (learn_status_cb): Release values before assignment + so that it can be used by getattr to update the structure. + (agent_scd_getattr): New. + + * keylist.c (print_pubkey_info): Add FP arg for optional printing + to a stream. Changed all callers. + +2003-10-01 Werner Koch + + * app-common.h, app-openpgp.c, iso7816.c, iso7816.h, apdu.c + * apdu.h, ccid-driver.c, ccid-driver.h, card-util.c: Updated + from current GnuPG 1.9. Changes over there are: + * card-util.c: Tweaked to use this source also under 1.3. + (card_edit): New command "forcesig". + * card-util.c (print_name, print_isoname): Use 0 and not LF fro + the max_n arg of tty_print_utf8_string2. + * card-util.c (change_pin): Simplified. We now have only a PIN + and an Admin PIN. + * ccid-driver.c: Detect GnuPG 1.3 and include appropriate files. + * apdu.c: Ditto. + * app-openpgp.c: Ditto. + * iso7816.c: Ditto. + (generate_keypair): Renamed to .. + (do_generate_keypair): .. this. + * app-common.h [GNUPG_MAJOR_VERSION]: New. + * iso7816.h [GNUPG_MAJOR_VERSION]: Include cardglue.h + * app-openpgp.c (do_change_pin): Make sure CVH1 and CHV2 are + always synced. + (verify_chv2, verify_chv3): New. Factored out common code. + (do_setattr, do_sign, do_auth, do_decipher): Change the names of + the prompts to match that we have only 2 different PINs. + (app_select_openpgp): Check whether the card enforced CHV1. + (convert_sig_counter_value): New. Factor out code from + get_sig_counter. + + * Makefile.am (card_support_source): Depend on new AM conditional + to get the ifdef ENABLE_CARD_SUPPORT off the way from source + copied files. + (update-source-from-gnupg-2): Maintainer helper. + 2003-10-01 David Shaw * g10.c (main): Add --no-groups to zero --group list. diff --git a/g10/Makefile.am b/g10/Makefile.am index 2be9e35e7..e289a8242 100644 --- a/g10/Makefile.am +++ b/g10/Makefile.am @@ -63,15 +63,22 @@ common_source = \ keylist.c \ signal.c -card_support_source = \ - cardglue.c cardclue.h \ - card-util.c \ +if ENABLE_CARD_SUPPORT +card_support_source_g10 = card-util.c +card_support_source_scd = \ app-common.h \ app-openpgp.c \ iso7816.c iso7816.h \ apdu.c apdu.h \ ccid-driver.c ccid-driver.h +card_support_source_local = cardglue.c cardclue.h +else +card_support_source_g10 = +card_support_source_scd = +card_support_source_local = +endif +card_support_source = $(card_support_source_local) $(card_support_source_g10) $(card_support_source_scd) gpg_SOURCES = g10.c \ $(common_source) \ @@ -132,3 +139,15 @@ install-data-local: echo "removing obsolete gpgm binary" ; \ rm $(DESTDIR)$(bindir)/gpgm ; \ fi + +# Helper to update some source files. +update-source-from-gnupg-2: + test -d ../../gnupg-1.9/scd + @for i in $(card_support_source_scd); do \ + cp ../../gnupg-1.9/scd/$$i $$i; echo $$i; \ + done + @for i in $(card_support_source_g10); do \ + cp ../../gnupg-1.9/g10/$$i $$i; echo $$i; \ + done + @echo "Please remember to update the ChangeLog accordingly!" + diff --git a/g10/apdu.c b/g10/apdu.c index 068949810..d5b93de6e 100644 --- a/g10/apdu.c +++ b/g10/apdu.c @@ -19,13 +19,6 @@ */ #include -#ifdef ENABLE_CARD_SUPPORT -/* - Note, that most of this code has been taken from 1.9.x branch - and is maintained over there if at all possible. Thus, if you make - changes here, please check that a similar change has been commited - to the 1.9.x branch. -*/ #include #include #include @@ -35,12 +28,19 @@ # include #endif +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ #include "options.h" #include "errors.h" #include "memory.h" #include "util.h" #include "i18n.h" #include "cardglue.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ +#include "scdaemon.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ #include "apdu.h" #include "dynload.h" @@ -1190,4 +1190,4 @@ apdu_send_simple (int slot, int class, int ins, int p0, int p1, -#endif /*ENABLE_CARD_SUPPORT*/ + diff --git a/g10/app-common.h b/g10/app-common.h index 26666e7a7..33f23127b 100644 --- a/g10/app-common.h +++ b/g10/app-common.h @@ -1,4 +1,4 @@ -/* app-common.h +/* app-common.h - Common declarations for all card applications * Copyright (C) 2003 Free Software Foundation, Inc. * * This file is part of GnuPG. @@ -18,8 +18,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ -#ifndef APP_COMMON_H -#define APP_COMMON_H +#ifndef GNUPG_SCD_APP_COMMON_H +#define GNUPG_SCD_APP_COMMON_H struct app_ctx_s { int initialized; /* The application has been initialied and the @@ -31,10 +31,12 @@ struct app_ctx_s { size_t serialnolen; /* Length in octets of serialnumber. */ unsigned int card_version; int did_chv1; + int force_chv1; /* True if the card does not cache CHV1. */ int did_chv2; int did_chv3; struct { int (*learn_status) (APP app, CTRL ctrl); + int (*getattr) (APP app, CTRL ctrl, const char *name); int (*setattr) (APP app, const char *name, int (*pincb)(void*, const char *, char **), void *pincb_arg, @@ -64,13 +66,73 @@ struct app_ctx_s { int (*pincb)(void*, const char *, char **), void *pincb_arg); } fnc; + + }; - +#if GNUPG_MAJOR_VERSION == 1 int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); +#else +/*-- app.c --*/ +void app_set_default_reader_port (const char *portstr); +APP select_application (void); +int app_get_serial_and_stamp (APP app, char **serial, time_t *stamp); +int app_write_learn_status (APP app, CTRL ctrl); +int app_getattr (APP app, CTRL ctrl, const char *name); +int app_setattr (APP app, const char *name, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const unsigned char *value, size_t valuelen); +int app_sign (APP app, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); +int app_auth (APP app, const char *keyidstr, + int (*pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen); +int app_decipher (APP app, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + unsigned char **outdata, size_t *outdatalen ); +int app_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); +int app_get_challenge (APP app, size_t nbytes, unsigned char *buffer); +int app_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); -#endif /*APP_COMMON_H*/ + +/*-- app-openpgp.c --*/ +int app_select_openpgp (APP app, unsigned char **sn, size_t *snlen); + +int app_openpgp_cardinfo (APP app, + char **serialno, + char **disp_name, + char **pubkey_url, + unsigned char **fpr1, + unsigned char **fpr2, + unsigned char **fpr3); +int app_openpgp_storekey (APP app, int keyno, + unsigned char *template, size_t template_len, + time_t created_at, + const unsigned char *m, size_t mlen, + const unsigned char *e, size_t elen, + int (*pincb)(void*, const char *, char **), + void *pincb_arg); +int app_openpgp_readkey (APP app, int keyno, + unsigned char **m, size_t *mlen, + unsigned char **e, size_t *elen); +#endif + + + +#endif /*GNUPG_SCD_APP_COMMON_H*/ diff --git a/g10/app-openpgp.c b/g10/app-openpgp.c index 5469a0955..e8fe19ea1 100644 --- a/g10/app-openpgp.c +++ b/g10/app-openpgp.c @@ -19,13 +19,6 @@ */ #include -#ifdef ENABLE_CARD_SUPPORT -/* - Note, that most of this code has been taken from 1.9.x branch - and is maintained over there if at all possible. Thus, if you make - changes here, please check that a similar change has been commited - to the 1.9.x branch. -*/ #include #include #include @@ -33,16 +26,25 @@ #include #include +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ #include "options.h" #include "errors.h" #include "memory.h" #include "util.h" #include "i18n.h" +#include "cardglue.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ +#include "scdaemon.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ #include "iso7816.h" -#include "cardglue.h" #include "app-common.h" + + static struct { int tag; int constructed; @@ -73,10 +75,11 @@ static struct { }; +static unsigned long convert_sig_counter_value (const unsigned char *value, + size_t valuelen); static unsigned long get_sig_counter (APP app); - /* Locate a TLV encoded data object in BUFFER of LENGTH and return a pointer to value as well as its length in NBYTES. Return NULL if it was not found. Note, that the function does not check @@ -403,83 +406,168 @@ send_key_data (CTRL ctrl, const char *name, xfree (buf); } +/* Implement the GETATTR command. This is similar to the LEARN + command but returns just one value via the status interface. */ +static int +do_getattr (APP app, CTRL ctrl, const char *name) +{ + static struct { + const char *name; + int tag; + int special; + } table[] = { + { "DISP-NAME", 0x005B }, + { "LOGIN-DATA", 0x005E }, + { "DISP-LANG", 0x5F2D }, + { "DISP-SEX", 0x5F35 }, + { "PUBKEY-URL", 0x5F50 }, + { "KEY-FPR", 0x00C5, 3 }, + { "CA-FPR", 0x00C6, 3 }, + { "CHV-STATUS", 0x00C4, 1 }, + { "SIG-COUNTER", 0x0093, 2 }, + { NULL, 0 } + }; + int idx, i; + void *relptr; + unsigned char *value; + size_t valuelen; + + for (idx=0; table[idx].name && strcmp (table[idx].name, name); idx++) + ; + if (!table[idx].name) + return gpg_error (GPG_ERR_INV_NAME); + + relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen); + if (relptr) + { + if (table[idx].special == 1) + { + char numbuf[7*23]; + + for (i=0,*numbuf=0; i < valuelen && i < 7; i++) + sprintf (numbuf+strlen (numbuf), " %d", value[i]); + send_status_info (ctrl, table[idx].name, + numbuf, strlen (numbuf), NULL, 0); + } + else if (table[idx].special == 2) + { + char numbuf[50]; + + sprintf (numbuf, "%lu", convert_sig_counter_value (value, valuelen)); + send_status_info (ctrl, table[idx].name, + numbuf, strlen (numbuf), NULL, 0); + } + else if (table[idx].special == 3) + { + if (valuelen >= 60) + for (i=0; i < 3; i++) + send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); + } + else + send_status_info (ctrl, table[idx].name, value, valuelen, NULL, 0); + + xfree (relptr); + } + return 0; +} static int do_learn_status (APP app, CTRL ctrl) { - void *relptr; - unsigned char *value; - size_t valuelen; - int i; + do_getattr (app, ctrl, "DISP-NAME"); + do_getattr (app, ctrl, "DISP-LANG"); + do_getattr (app, ctrl, "DISP-SEX"); + do_getattr (app, ctrl, "PUBKEY-URL"); + do_getattr (app, ctrl, "LOGIN-DATA"); + do_getattr (app, ctrl, "KEY-FPR"); + do_getattr (app, ctrl, "CA-FPR"); + do_getattr (app, ctrl, "CHV-STATUS"); + do_getattr (app, ctrl, "SIG-COUNTER"); - relptr = get_one_do (app->slot, 0x005B, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-NAME", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F2D, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-LANG", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F35, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "DISP-SEX", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x5F50, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "PUBKEY-URL", value, valuelen, NULL, 0); - xfree (relptr); - } - relptr = get_one_do (app->slot, 0x005E, &value, &valuelen); - if (relptr) - { - send_status_info (ctrl, "LOGIN-DATA", value, valuelen, NULL, 0); - xfree (relptr); - } - - relptr = get_one_do (app->slot, 0x00C5, &value, &valuelen); - if (relptr && valuelen >= 60) - { - for (i=0; i < 3; i++) - send_fpr_if_not_null (ctrl, "KEY-FPR", i+1, value+i*20); - } - xfree (relptr); - relptr = get_one_do (app->slot, 0x00C6, &value, &valuelen); - if (relptr && valuelen >= 60) - { - for (i=0; i < 3; i++) - send_fpr_if_not_null (ctrl, "CA-FPR", i+1, value+i*20); - } - xfree (relptr); - relptr = get_one_do (app->slot, 0x00C4, &value, &valuelen); - if (relptr) - { - char numbuf[7*23]; - - for (i=0,*numbuf=0; i < valuelen && i < 7; i++) - sprintf (numbuf+strlen (numbuf), " %d", value[i]); - send_status_info (ctrl, "CHV-STATUS", numbuf, strlen (numbuf), NULL, 0); - xfree (relptr); - } - - { - unsigned long ul = get_sig_counter (app); - char numbuf[23]; - - sprintf (numbuf, "%lu", ul); - send_status_info (ctrl, "SIG-COUNTER", numbuf, strlen (numbuf), NULL, 0); - } return 0; } +/* Verify CHV2 if required. Depending on the configuration of the + card CHV1 will also be verified. */ +static int +verify_chv2 (APP app, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc = 0; + + if (!app->did_chv2) + { + char *pinvalue; + + rc = pincb (pincb_arg, "PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + if (rc) + { + log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc)); + xfree (pinvalue); + return rc; + } + app->did_chv2 = 1; + + if (!app->did_chv1 && !app->force_chv1) + { + rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) + rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); + if (rc) + { + log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc)); + xfree (pinvalue); + return rc; + } + app->did_chv1 = 1; + } + xfree (pinvalue); + } + return rc; +} + +/* Verify CHV3 if required. */ +static int +verify_chv3 (APP app, + int (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + int rc = 0; + + if (!app->did_chv3) + { + char *pinvalue; + + rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + if (rc) + { + log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); + return rc; + } + + rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); + xfree (pinvalue); + if (rc) + { + log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); + return rc; + } + app->did_chv3 = 1; + } + return rc; +} + + /* Handle the SETATTR operation. All arguments are already basically checked. */ static int @@ -512,41 +600,18 @@ do_setattr (APP app, const char *name, if (!table[idx].name) return gpg_error (GPG_ERR_INV_NAME); - if (!app->did_chv3) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Admin PIN (CHV3)", - &pinvalue); -/* pinvalue = xstrdup ("12345678"); */ -/* rc = 0; */ - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc)); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv3 = 1; - } + rc = verify_chv3 (app, pincb, pincb_arg); + if (rc) + return rc; rc = iso7816_put_data (app->slot, table[idx].tag, value, valuelen); if (rc) log_error ("failed to set `%s': %s\n", table[idx].name, gpg_strerror (rc)); - /* FIXME: If this fails we should *once* try again after - doing a verify command, so that in case of a problem with - tracking the verify operation we have a fallback. */ return rc; } + /* Handle the PASSWD command. */ static int do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, @@ -564,51 +629,25 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, } else if (reset_mode || chvno == 3) { - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); + /* we always require that the PIN is entered. */ + app->did_chv3 = 0; + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; } - else if (chvno == 1) + else if (chvno == 1 || chvno == 2) { - rc = pincb (pincb_arg, "Signature PIN", &pinvalue); + /* CHV1 and CVH2 should always have the same value, thus we + enforce it here. */ + int save_force = app->force_chv1; + + app->force_chv1 = 0; + app->did_chv1 = 0; + app->did_chv2 = 0; + rc = verify_chv2 (app, pincb, pincb_arg); + app->force_chv1 = save_force; if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV1 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } - } - else if (chvno == 2) - { - rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - goto leave; - } - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; } else { @@ -616,10 +655,12 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, goto leave; } - - rc = pincb (pincb_arg, chvno == 1? "New Signature PIN" : - chvno == 2? "New Decryption PIN" : - chvno == 3? "New Admin PIN" : "?", &pinvalue); + if (chvno == 3) + app->did_chv3 = 0; + else + app->did_chv1 = app->did_chv2 = 0; + + rc = pincb (pincb_arg, chvno == 3? "New Admin PIN" : "New PIN", &pinvalue); if (rc) { log_error ("error getting new PIN: %s\n", gpg_strerror (rc)); @@ -627,12 +668,27 @@ do_change_pin (APP app, CTRL ctrl, const char *chvnostr, int reset_mode, } if (reset_mode) - rc = iso7816_reset_retry_counter (app->slot, 0x80 + chvno, - pinvalue, strlen (pinvalue)); - else - rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, - NULL, 0, + { + rc = iso7816_reset_retry_counter (app->slot, 0x81, pinvalue, strlen (pinvalue)); + if (!rc) + rc = iso7816_reset_retry_counter (app->slot, 0x82, + pinvalue, strlen (pinvalue)); + } + else + { + if (chvno == 1 || chvno == 2) + { + rc = iso7816_change_reference_data (app->slot, 0x81, NULL, 0, + pinvalue, strlen (pinvalue)); + if (!rc) + rc = iso7816_change_reference_data (app->slot, 0x82, NULL, 0, + pinvalue, strlen (pinvalue)); + } + else + rc = iso7816_change_reference_data (app->slot, 0x80 + chvno, NULL, 0, + pinvalue, strlen (pinvalue)); + } xfree (pinvalue); @@ -692,22 +748,10 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, else log_info ("generating new key\n"); - { - char *pinvalue; - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - return rc; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - } + + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; xfree (buffer); buffer = NULL; #if 1 @@ -777,6 +821,21 @@ do_genkey (APP app, CTRL ctrl, const char *keynostr, unsigned int flags, } +static unsigned long +convert_sig_counter_value (const unsigned char *value, size_t valuelen) +{ + unsigned long ul; + + if (valuelen == 3 ) + ul = (value[0] << 16) | (value[1] << 8) | value[2]; + else + { + log_error ("invalid structure of OpenPGP card (DO 0x93)\n"); + ul = 0; + } + return ul; +} + static unsigned long get_sig_counter (APP app) { @@ -788,13 +847,7 @@ get_sig_counter (APP app) relptr = get_one_do (app->slot, 0x0093, &value, &valuelen); if (!relptr) return 0; - if (valuelen == 3 ) - ul = (value[0] << 16) | (value[1] << 8) | value[2]; - else - { - log_error ("invalid structure of OpenPGP card (DO 0x93)\n"); - ul = 0; - } + ul = convert_sig_counter_value (value, valuelen); xfree (relptr); return ul; } @@ -927,21 +980,17 @@ do_sign (APP app, const char *keyidstr, int hashalgo, sigcount = get_sig_counter (app); log_info ("signatures created so far: %lu\n", sigcount); - /* FIXME: Check whether we are really required to enter the PIN for - each signature. There is a DO for this. */ - if (!app->did_chv1 || 1) + if (!app->did_chv1 || app->force_chv1 ) { char *pinvalue; { char *prompt; - if (asprintf (&prompt, "Signature PIN [sigs done: %lu]", sigcount) < 0) + if (asprintf (&prompt, "PIN [sigs done: %lu]", sigcount) < 0) return gpg_error_from_errno (errno); rc = pincb (pincb_arg, prompt, &pinvalue); free (prompt); } -/* pinvalue = xstrdup ("123456"); */ -/* rc = 0; */ if (rc) { log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); @@ -949,14 +998,28 @@ do_sign (APP app, const char *keyidstr, int hashalgo, } rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue)); - xfree (pinvalue); if (rc) { log_error ("verify CHV1 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); + xfree (pinvalue); return rc; } app->did_chv1 = 1; + if (!app->did_chv2) + { + /* We should also verify CHV2. */ + rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); + if (gpg_err_code (rc) == GPG_ERR_BAD_PIN) + rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED); + if (rc) + { + log_error ("verify CHV2 failed\n"); + xfree (pinvalue); + return rc; + } + app->did_chv2 = 1; + } + xfree (pinvalue); } rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); @@ -1037,30 +1100,10 @@ do_auth (APP app, const char *keyidstr, return rc; } - if (!app->did_chv2) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Authentication/Decryption PIN", &pinvalue); - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv2 = 1; - } - - rc = iso7816_internal_authenticate (app->slot, indata, indatalen, - outdata, outdatalen); + rc = verify_chv2 (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_internal_authenticate (app->slot, indata, indatalen, + outdata, outdatalen); return rc; } @@ -1127,31 +1170,9 @@ do_decipher (APP app, const char *keyidstr, return rc; } - if (!app->did_chv2) - { - char *pinvalue; - - rc = pincb (pincb_arg, "Decryption PIN", &pinvalue); -/* pinvalue = xstrdup ("123456"); */ -/* rc = 0; */ - if (rc) - { - log_info ("PIN callback returned error: %s\n", gpg_strerror (rc)); - return rc; - } - - rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_error ("verify CHV2 failed\n"); - rc = gpg_error (GPG_ERR_GENERAL); - return rc; - } - app->did_chv2 = 1; - } - - rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); + rc = verify_chv2 (app, pincb, pincb_arg); + if (!rc) + rc = iso7816_decipher (app->slot, indata, indatalen, outdata, outdatalen); return rc; } @@ -1168,10 +1189,15 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) int rc; unsigned char *buffer; size_t buflen; + void *relptr; rc = iso7816_select_application (slot, aid, sizeof aid); if (!rc) { + app->did_chv1 = 0; + app->did_chv2 = 0; + app->did_chv3 = 0; + rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen); if (rc) goto leave; @@ -1191,10 +1217,20 @@ app_select_openpgp (APP app, unsigned char **sn, size_t *snlen) else xfree (buffer); + relptr = get_one_do (app->slot, 0x00C4, &buffer, &buflen); + if (!relptr) + { + log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n"); + goto leave; + } + app->force_chv1 = (buflen && *buffer == 0); + xfree (relptr); + if (opt.verbose > 1) dump_all_do (slot); app->fnc.learn_status = do_learn_status; + app->fnc.getattr = do_getattr; app->fnc.setattr = do_setattr; app->fnc.genkey = do_genkey; app->fnc.sign = do_sign; @@ -1319,22 +1355,10 @@ app_openpgp_storekey (APP app, int keyno, return gpg_error (GPG_ERR_INV_ID); keyno--; - { - char *pinvalue; - rc = pincb (pincb_arg, "Admin PIN", &pinvalue); - if (rc) - { - log_error ("error getting PIN: %s\n", gpg_strerror (rc)); - return rc; - } - rc = iso7816_verify (app->slot, 0x83, pinvalue, strlen (pinvalue)); - xfree (pinvalue); - } + rc = verify_chv3 (app, pincb, pincb_arg); if (rc) - { - log_error ("verify CHV3 failed: rc=%s\n", gpg_strerror (rc)); - goto leave; - } + goto leave; + rc = iso7816_put_data (app->slot, (app->card_version > 0x0007? 0xE0 : 0xE9) + keyno, @@ -1426,5 +1450,3 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen, } return rc; } - -#endif /*ENABLE_CARD_SUPPORT*/ diff --git a/g10/card-util.c b/g10/card-util.c index 901ce922c..70518e9ce 100644 --- a/g10/card-util.c +++ b/g10/card-util.c @@ -19,27 +19,26 @@ */ #include -#ifdef ENABLE_CARD_SUPPORT -/* - Note, that most card related code has been taken from 1.9.x branch - and is maintained over there if at all possible. Thus, if you make - changes here, please check that a similar change has been commited - to the 1.9.x branch. -*/ #include #include #include #include #include +#if GNUPG_MAJOR_VERSION != 1 +#include "gpg.h" +#endif #include "util.h" #include "i18n.h" #include "ttyio.h" #include "status.h" #include "options.h" #include "main.h" - +#if GNUPG_MAJOR_VERSION == 1 #include "cardglue.h" +#else +#include "call-agent.h" +#endif #define CONTROL_D ('D' - 'A' + 1) @@ -51,7 +50,6 @@ change_pin (int chvno) { struct agent_card_info_s info; int rc; - int reset_mode = 0; rc = agent_learn (&info); if (rc) @@ -77,17 +75,11 @@ change_pin (int chvno) char *answer; tty_printf ("\n"); - tty_printf ("1 - change signature PIN\n" - "2 - change decryption and authentication PIN\n" - "3 - change Admin's PIN\n" - "R - toggle reset retry counter mode\n" + tty_printf ("1 - change PIN\n" + "2 - unblock PIN\n" + "3 - change Admin PIN\n" "Q - quit\n"); tty_printf ("\n"); - if (reset_mode) - { - tty_printf ("Reset Retry Counter mode active\n"); - tty_printf ("\n"); - } answer = cpr_get("cardutil.change_pin.menu",_("Your selection? ")); cpr_kill_prompt(); @@ -95,30 +87,35 @@ change_pin (int chvno) continue; rc = 0; - if (reset_mode && *answer == '3') + if (*answer == '1') { - tty_printf ("Sorry, reset of the Admin PIN's retry counter " - "is not possible.\n"); - } - else if (*answer == '1' || *answer == '2' || *answer == '3') - { - rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0)); + rc = agent_scd_change_pin (1); if (rc) - tty_printf ("Error changing/resetting the PIN: %s\n", - gpg_strerror (rc)); + tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); else - tty_printf ("New PIN successfully set.\n"); + tty_printf ("PIN changed.\n"); } - else if (*answer == 'r' || *answer == 'R') + else if (*answer == '2') { - reset_mode = !reset_mode; + rc = agent_scd_change_pin (101); + if (rc) + tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc)); + else + tty_printf ("PIN unblocked and new PIN set.\n"); + } + else if (*answer == '3') + { + rc = agent_scd_change_pin (3); + if (rc) + tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc)); + else + tty_printf ("PIN changed.\n"); } else if (*answer == 'q' || *answer == 'Q') { break; } } - } static const char * @@ -182,7 +179,7 @@ print_name (FILE *fp, const char *text, const char *name) if (fp) print_utf8_string2 (fp, name, strlen (name), '\n'); else - tty_print_utf8_string2 (name, strlen (name), '\n'); + tty_print_utf8_string2 (name, strlen (name), 0); } else tty_fprintf (fp, _("[not set]")); @@ -214,7 +211,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, given, strlen (given), '\n'); else - tty_print_utf8_string2 (given, strlen (given), '\n'); + tty_print_utf8_string2 (given, strlen (given), 0); if (opt.with_colons) putc (':', fp); @@ -227,7 +224,7 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name) else if (fp) print_utf8_string2 (fp, buf, strlen (buf), '\n'); else - tty_print_utf8_string2 (buf, strlen (buf), '\n'); + tty_print_utf8_string2 (buf, strlen (buf), 0); xfree (buf); } else @@ -346,7 +343,7 @@ card_status (FILE *fp) print_name (fp, "URL of public key : ", info.pubkey_url); print_name (fp, "Login data .......: ", info.login_data); tty_fprintf (fp, "Signature PIN ....: %s\n", - info.chv1_cached? _("cached"): _("not cached")); + info.chv1_cached? _("not forced"): _("forced")); tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n", info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]); tty_fprintf (fp, "PIN retry counter : %d %d %d\n", @@ -358,11 +355,11 @@ card_status (FILE *fp) print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL); tty_fprintf (fp, "Authentication key:"); print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL); -/* tty_fprintf (fp, "General key info..: "); */ -/* if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) */ -/* print_pubkey_info (fp, pk); */ -/* else */ -/* tty_fprintf (fp, "[none]\n"); */ + tty_fprintf (fp, "General key info..: "); + if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20)) + print_pubkey_info (fp, pk); + else + tty_fprintf (fp, "[none]\n"); } free_public_key (pk); @@ -549,6 +546,30 @@ change_sex (void) } +static void +toggle_forcesig (void) +{ + struct agent_card_info_s info; + int rc; + int newstate; + + memset (&info, 0, sizeof info); + rc = agent_scd_getattr ("CHV-STATUS", &info); + if (rc) + { + log_error ("error getting current status: %s\n", gpg_strerror (rc)); + return; + } + newstate = !info.chv1_cached; + agent_release_card_info (&info); + + rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1); + if (rc) + log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc)); +} + + + /* Menu to edit all user changeable values on an OpenPGP card. Only Key creation is not handled here. */ void @@ -558,7 +579,7 @@ card_edit (STRLIST commands) cmdNOP = 0, cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG, cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX, - + cmdFORCESIG, cmdINVCMD }; @@ -579,9 +600,10 @@ card_edit (STRLIST commands) { N_("login") , cmdLOGIN , N_("change the login name") }, { N_("lang") , cmdLANG , N_("change the language preferences") }, { N_("sex") , cmdSEX , N_("change card holder's sex") }, + { N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") }, { NULL, cmdINVCMD } }; - + enum cmdids cmd = cmdNOP; int have_commands = !!commands; int redisplay = 1; @@ -699,6 +721,10 @@ card_edit (STRLIST commands) change_sex (); break; + case cmdFORCESIG: + toggle_forcesig (); + break; + case cmdQUIT: goto leave; @@ -717,4 +743,3 @@ card_edit (STRLIST commands) xfree (answer); } -#endif /*ENABLE_CARD_SUPPORT*/ diff --git a/g10/cardglue.c b/g10/cardglue.c index 358eb90f6..802bae5d1 100644 --- a/g10/cardglue.c +++ b/g10/cardglue.c @@ -19,13 +19,9 @@ */ #include -#ifdef ENABLE_CARD_SUPPORT -/* - Note, that most card related code has been taken from 1.9.x branch - and is maintained over there if at all possible. Thus, if you make - changes here, please check that a similar change has been commited - to the 1.9.x branch. -*/ +#ifndef ENABLE_CARD_SUPPORT +#error no configured for card support. +#endif #include #include #include @@ -357,14 +353,17 @@ learn_status_cb (void *opaque, const char *line) if (keywordlen == 8 && !memcmp (keyword, "SERIALNO", keywordlen)) { + xfree (parm->serialno); parm->serialno = store_serialno (line); } else if (keywordlen == 9 && !memcmp (keyword, "DISP-NAME", keywordlen)) { + xfree (parm->disp_name); parm->disp_name = unescape_status_string (line); } else if (keywordlen == 9 && !memcmp (keyword, "DISP-LANG", keywordlen)) { + xfree (parm->disp_lang); parm->disp_lang = unescape_status_string (line); } else if (keywordlen == 8 && !memcmp (keyword, "DISP-SEX", keywordlen)) @@ -373,10 +372,12 @@ learn_status_cb (void *opaque, const char *line) } else if (keywordlen == 10 && !memcmp (keyword, "PUBKEY-URL", keywordlen)) { + xfree (parm->pubkey_url); parm->pubkey_url = unescape_status_string (line); } else if (keywordlen == 10 && !memcmp (keyword, "LOGIN-DATA", keywordlen)) { + xfree (parm->login_data); parm->login_data = unescape_status_string (line); } else if (keywordlen == 11 && !memcmp (keyword, "SIG-COUNTER", keywordlen)) @@ -449,6 +450,7 @@ agent_learn (struct agent_card_info_s *info) if (!app) return gpg_error (GPG_ERR_CARD); + memset (info, 0, sizeof *info); memset (&ctrl, 0, sizeof ctrl); ctrl.status_cb = learn_status_cb; ctrl.status_cb_arg = info; @@ -464,6 +466,24 @@ agent_learn (struct agent_card_info_s *info) return rc; } +/* Get an attribite from the card. Make sure info is initialized. */ +int +agent_scd_getattr (const char *name, struct agent_card_info_s *info) +{ + APP app; + struct ctrl_ctx_s ctrl; + + app = current_app? current_app : open_card (); + if (!app) + return gpg_error (GPG_ERR_CARD); + + ctrl.status_cb = learn_status_cb; + ctrl.status_cb_arg = info; + return app->fnc.getattr (app, &ctrl, name); +} + + + static int pin_cb (void *opaque, const char *info, char **retstr) { @@ -548,8 +568,3 @@ agent_scd_change_pin (int chvno) return gpg_error (GPG_ERR_CARD); } - - - -#endif /*ENABLE_CARD_SUPPORT*/ - diff --git a/g10/cardglue.h b/g10/cardglue.h index 076849866..42a22b542 100644 --- a/g10/cardglue.h +++ b/g10/cardglue.h @@ -84,7 +84,7 @@ typedef struct ctrl_ctx_s *CTRL; #define GPG_ERR_USE_CONDITIONS G10ERR_GENERAL #define GPG_ERR_WRONG_CARD G10ERR_GENERAL #define GPG_ERR_WRONG_SECKEY G10ERR_WRONG_SECKEY - +#define GPG_ERR_PIN_NOT_SYNCED G10ERR_GENERAL typedef int gpg_error_t; typedef int gpg_err_code_t; @@ -130,6 +130,9 @@ int agent_learn (struct agent_card_info_s *info); is available. Return 0 for yes or an error code. */ int agent_havekey (const char *hexkeygrip); +/* Return card info. */ +int agent_scd_getattr (const char *name, struct agent_card_info_s *info); + /* Send a SETATTR command to the SCdaemon. */ int agent_scd_setattr (const char *name, const unsigned char *value, size_t valuelen); diff --git a/g10/ccid-driver.c b/g10/ccid-driver.c index de8f870a5..b4fbc0b21 100644 --- a/g10/ccid-driver.c +++ b/g10/ccid-driver.c @@ -74,8 +74,6 @@ #if defined(HAVE_LIBUSB) || defined(TEST) -#define GNUPG_DEFAULT_SCDAEMON 1 /* Hack for 1.3 */ - #include #include #include @@ -89,12 +87,16 @@ #define DRVNAME "ccid-driver: " -#ifdef GNUPG_DEFAULT_SCDAEMON /* This source is used within the - gnupg>=1.9 source tree. */ -# include "options.h" -# include "util.h" -# include "memory.h" +#ifdef GNUPG_MAJOR_VERSION /* This source is used within GnuPG. */ +# if GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */ +# include "options.h" +# include "util.h" +# include "memory.h" +# include "cardglue.h" +# else /* This is the modularized GnuPG 1.9 or later. */ +# include "scdaemon.h" +# endif # define DEBUGOUT(t) do { if (DBG_CARD_IO) \ log_debug (DRVNAME t); } while (0) diff --git a/g10/delkey.c b/g10/delkey.c index 35c903cc0..54cbc7136 100644 --- a/g10/delkey.c +++ b/g10/delkey.c @@ -130,7 +130,7 @@ do_delete_key( const char *username, int secret, int *r_sec_avail ) if( secret ) print_seckey_info( sk ); else - print_pubkey_info( pk ); + print_pubkey_info(NULL, pk ); tty_printf( "\n" ); yes = cpr_get_answer_is_yes( secret? "delete_key.secret.okay" diff --git a/g10/iso7816.c b/g10/iso7816.c index f4308f5b4..f4aa18c6f 100644 --- a/g10/iso7816.c +++ b/g10/iso7816.c @@ -19,23 +19,23 @@ */ #include -#ifdef ENABLE_CARD_SUPPORT -/* - Note, that most of this code has been taken from 1.9.x branch - and is maintained over there if at all possible. Thus, if you make - changes here, please check that a similar change has been commited - to the 1.9.x branch. -*/ #include #include #include #include +#if GNUPG_MAJOR_VERSION == 1 +/* This is used with GnuPG version < 1.9. The code has been source + copied from the current GnuPG >= 1.9 and is maintained over + there. */ #include "options.h" #include "errors.h" #include "memory.h" #include "util.h" #include "i18n.h" +#else /* GNUPG_MAJOR_VERSION != 1 */ +#include "scdaemon.h" +#endif /* GNUPG_MAJOR_VERSION != 1 */ #include "iso7816.h" #include "apdu.h" @@ -381,5 +381,3 @@ iso7816_get_challenge (int slot, int length, unsigned char *buffer) return 0; } - -#endif /*ENABLE_CARD_SUPPORT*/ diff --git a/g10/iso7816.h b/g10/iso7816.h index 99c4a8ed8..26b8d6aba 100644 --- a/g10/iso7816.h +++ b/g10/iso7816.h @@ -21,7 +21,9 @@ #ifndef ISO7816_H #define ISO7816_H +#if GNUPG_MAJOR_VERSION == 1 #include "cardglue.h" +#endif gpg_error_t iso7816_select_application (int slot, const char *aid, size_t aidlen); diff --git a/g10/keylist.c b/g10/keylist.c index 9970f0cb2..06edfa11b 100644 --- a/g10/keylist.c +++ b/g10/keylist.c @@ -129,25 +129,39 @@ print_seckey_info (PKT_secret_key *sk) tty_printf ("\n"); } +/* Print information about the public key. With FP passed as NULL, + the tty output interface is used, otherwise output is directted to + the given stream. */ void -print_pubkey_info (PKT_public_key *pk) +print_pubkey_info (FILE *fp, PKT_public_key *pk) { u32 pk_keyid[2]; size_t n; char *p; keyid_from_pk (pk, pk_keyid); - tty_printf ("\npub %4u%c/%08lX %s ", - nbits_from_pk (pk), - pubkey_letter (pk->pubkey_algo), - (ulong)pk_keyid[1], datestr_from_pk (pk)); - + if (fp) + fprintf (fp, "pub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); + else + tty_printf ("\npub %4u%c/%08lX %s ", + nbits_from_pk (pk), + pubkey_letter (pk->pubkey_algo), + (ulong)pk_keyid[1], datestr_from_pk (pk)); p = get_user_id (pk_keyid, &n); - tty_print_utf8_string (p, n); + if (fp) + print_utf8_string2 (fp, p, n, '\n'); + else + tty_print_utf8_string (p, n); m_free (p); - tty_printf ("\n\n"); + if (fp) + putc ('\n', fp); + else + tty_printf ("\n\n"); } /* diff --git a/g10/main.h b/g10/main.h index 4da7724eb..ca37b620f 100644 --- a/g10/main.h +++ b/g10/main.h @@ -217,7 +217,7 @@ void dump_attribs(const PKT_user_id *uid, PKT_public_key *pk,PKT_secret_key *sk); void set_attrib_fd(int fd); void print_seckey_info (PKT_secret_key *sk); -void print_pubkey_info (PKT_public_key *pk); +void print_pubkey_info (FILE *fp, PKT_public_key *pk); /*-- verify.c --*/ void print_file_status( int status, const char *name, int what ); diff --git a/g10/revoke.c b/g10/revoke.c index 6c1180c71..51dfea20a 100644 --- a/g10/revoke.c +++ b/g10/revoke.c @@ -264,7 +264,7 @@ gen_desig_revoke( const char *uname ) any = 1; - print_pubkey_info (pk); + print_pubkey_info (NULL, pk); tty_printf ("\n"); tty_printf (_("To be revoked by:\n"));