Package: gnupg2 Version: 2.0.12-1 Severity: normal Tags: patch gpg-agent supports the use of gpg authentication subkeys for ssh authentication. Authentication subkeys on smartcards are automatically added to the ssh key list, e.g.: m...@ryu:~$ ssh-add -l 1024 bb:47:f9:e4:02:ad:ca:f1:80:95:aa:ee:b1:47:d7:df cardno:000100000A51 (RSA)
But keys >1024 bits (as used on new v2.0 cards) are not yet recognized. The attached patches were taken from the upstream bugtracker (https://bugs.g10code.com/gnupg/issue1094) and fix the ssh support for bigger key sizes (besides other smartcard fixes). -- System Information: Debian Release: squeeze/sid APT prefers testing APT policy: (990, 'testing'), (500, 'unstable'), (500, 'stable'), (1, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 2.6.30-1-amd64 (SMP w/2 CPU cores) Locale: LANG=de_DE.UTF-8, LC_CTYPE=de_DE.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages gnupg2 depends on: ii dpkg 1.15.3.1+b1 Debian package management system ii install-info 4.13a.dfsg.1-4 Manage installed documentation in ii libbz2-1.0 1.0.5-3 high-quality block-sorting file co ii libc6 2.9-23 GNU C Library: Shared libraries ii libcurl3-gnutls 7.19.5-1 Multi-protocol file transfer libra ii libgcrypt11 1.4.4-3 LGPL Crypto library - runtime libr ii libgpg-error0 1.6-1 library for common error values an ii libksba8 1.0.7-1 X.509 and CMS support library ii libreadline5 5.2-5 GNU readline and history libraries ii zlib1g 1:1.2.3.3.dfsg-15 compression library - runtime Versions of packages gnupg2 recommends: ii gnupg-agent 2.0.12-1 GNU privacy guard - password agent ii libldap-2.4-2 2.4.17-1 OpenLDAP libraries Versions of packages gnupg2 suggests: pn gnupg-doc <none> (no description available) pn xloadimage <none> (no description available) -- no debconf information
#! /bin/sh /usr/share/dpatch/dpatch-run ## 01_scd_pw2.dpatch converted by Michel Messerschmidt <w...@michel-messerschmidt.de> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Fix OpenPGP v2 card support @DPATCH@ 2009-06-18 Werner Koch <w...@g10code.com> * app-openpgp.c (verify_chv2): Remove special case for v2 cards. (get_public_key): Use extended mode. Index: gnupg2-2.0.12/scd/app-openpgp.c =================================================================== --- gnupg2-2.0.12/scd/app-openpgp.c (revision 5047) +++ gnupg2-2.0.12/scd/app-openpgp.c (working copy) @@ -1118,11 +1118,25 @@ if (app->card_version > 0x0100) { + int exmode, le_value; + /* We may simply read the public key out of these cards. */ + if (app->app_local->cardcap.ext_lc_le) + { + exmode = 1; /* Use extended length. */ + le_value = app->app_local->extcap.max_rsp_data; + } + else + { + exmode = 0; + le_value = 256; /* Use legacy value. */ + } + err = iso7816_read_public_key - (app->slot, 0, (const unsigned char*)(keyno == 0? "\xB6" : - keyno == 1? "\xB8" : "\xA4"), 2, - 0, + (app->slot, exmode, + (const unsigned char*)(keyno == 0? "\xB6" : + keyno == 1? "\xB8" : "\xA4"), 2, + le_value, &buffer, &buflen); if (err) { @@ -1579,43 +1593,31 @@ char *pinvalue; if (app->did_chv2) - return 0; /* We already verified CHV2 (PW1 for v2 cards). */ + return 0; /* We already verified CHV2. */ - if (app->app_local->extcap.is_v2) + rc = verify_a_chv (app, pincb, pincb_arg, 2, 0, &pinvalue); + if (rc) + return rc; + app->did_chv2 = 1; + + if (!app->did_chv1 && !app->force_chv1 && pinvalue) { - /* Version two cards don't have a CHV2 anymore. We need to - verify CHV1 (now called PW1) instead. */ - rc = verify_a_chv (app, pincb, pincb_arg, 1, 0, &pinvalue); + /* For convenience we verify CHV1 here too. We do this only if + the card is not configured to require a verification before + each CHV1 controlled operation (force_chv1) and if we are not + using the keypad (PINVALUE == NULL). */ + 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) - return rc; - app->did_chv2 = 1; - } - else - { - /* Version 1 cards only. */ - rc = verify_a_chv (app, pincb, pincb_arg, 2, 0, &pinvalue); - if (rc) - return rc; - app->did_chv2 = 1; - - if (!app->did_chv1 && !app->force_chv1 && pinvalue) { - /* For convenience we verify CHV1 here too. We do this only - if the card is not configured to require a verification - before each CHV1 controlled operation (force_chv1) and if - we are not using the keypad (PINVALUE == NULL). */ - 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 CHV%d failed: %s\n"), 1, gpg_strerror (rc)); - flush_cache_after_error (app); - } - else - app->did_chv1 = 1; + log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc)); + flush_cache_after_error (app); } + else + app->did_chv1 = 1; } + xfree (pinvalue); return rc;
#! /bin/sh /usr/share/dpatch/dpatch-run ## 03_opgp_writekey.dpatch converted by Michel Messerschmidt <w...@michel-messerschmidt.de> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Fix OpenPGP v2 card support @DPATCH@ [scd] 2009-07-09 Werner Koch <w...@g10code.com> * app-openpgp.c (change_keyattr): New. (do_writekey): Call it. * app-openpgp.c (does_key_exist): Add arg GENERATING. Change callers. [g10] 2009-07-09 Werner Koch <w...@g10code.com> * card-util.c (card_store_subkey): Do not restrict to 1024 bit keys. Print an error message on write errors. --- gnupg2-2.0.12/scd/app-openpgp.c (revision 5068) +++ gnupg2-2.0.12/scd/app-openpgp.c (working copy) @@ -213,6 +213,7 @@ void *pincb_arg, const void *indata, size_t indatalen, unsigned char **outdata, size_t *outdatalen); +static void parse_algorithm_attribute (app_t app, int keyno); @@ -2144,9 +2145,10 @@ /* Check whether a key already exists. KEYIDX is the index of the key (0..2). If FORCE is TRUE a diagnositic will be printed but no - error returned if the key already exists. */ + error returned if the key already exists. The flag GENERATING is + only used to print correct messages. */ static gpg_error_t -does_key_exist (app_t app, int keyidx, int force) +does_key_exist (app_t app, int keyidx, int generating, int force) { const unsigned char *fpr; unsigned char *buffer; @@ -2178,8 +2180,10 @@ } else if (i!=20) log_info (_("existing key will be replaced\n")); + else if (generating) + log_info (_("generating new key\n")); else - log_info (_("generating new key\n")); + log_info (_("writing new key\n")); return 0; } @@ -2340,7 +2344,64 @@ } +/* Helper for do_writekley to change the size of a key. Not ethat + this deletes the entire key without asking. */ +static gpg_error_t +change_keyattr (app_t app, int keyno, unsigned int nbits, + gpg_error_t (*pincb)(void*, const char *, char **), + void *pincb_arg) +{ + gpg_error_t err; + unsigned char *buffer; + size_t buflen; + void *relptr; + assert (keyno >=0 && keyno <= 2); + + if (nbits > 3072) + return gpg_error (GPG_ERR_TOO_LARGE); + + /* Read the current attributes into a buffer. */ + relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL); + if (!relptr) + return gpg_error (GPG_ERR_CARD); + if (buflen < 6 || buffer[0] != 1) + { + /* Attriutes too short or not an RSA key. */ + xfree (relptr); + return gpg_error (GPG_ERR_CARD); + } + + /* We only change n_bits and don't touch anything else. Before we + do so, we round up NBITS to a sensible way in the same way as + gpg's key generation does it. This may help to sort out problems + with a few bits too short keys. */ + nbits = ((nbits + 31) / 32) * 32; + buffer[1] = (nbits >> 8); + buffer[2] = nbits; + + /* Prepare for storing the key. */ + err = verify_chv3 (app, pincb, pincb_arg); + if (err) + { + xfree (relptr); + return err; + } + + /* Change the attribute. */ + err = iso7816_put_data (app->slot, 0, 0xC1+keyno, buffer, buflen); + xfree (relptr); + if (err) + log_error ("error changing size of key %d to %u bits\n", keyno+1, nbits); + else + log_info ("size of key %d changed to %u bits\n", keyno+1, nbits); + flush_cache (app); + parse_algorithm_attribute (app, keyno); + return err; +} + + + /* Handle the WRITEKEY command for OpenPGP. This function expects a canonical encoded S-expression with the secret key in KEYDATA and its length (for assertions) in KEYDATALEN. KEYID needs to be the @@ -2385,7 +2446,7 @@ else return gpg_error (GPG_ERR_INV_ID); - err = does_key_exist (app, keyno, force); + err = does_key_exist (app, keyno, 0, force); if (err) return err; @@ -2515,6 +2576,14 @@ if (opt.verbose) log_info ("RSA modulus size is %u bits (%u bytes)\n", nbits, (unsigned int)rsa_n_len); + if (nbits && nbits != maxbits + && app->app_local->extcap.algo_attr_change) + { + /* Try to switch the key to a new length. */ + err = change_keyattr (app, keyno, nbits, pincb, pincb_arg); + if (!err) + maxbits = app->app_local->keyattr[keyno].n_bits; + } if (nbits != maxbits) { log_error (_("RSA modulus missing or not of size %d bits\n"), @@ -2696,7 +2765,7 @@ app->app_local->pk[keyno].read_done = 0; /* Check whether a key already exists. */ - rc = does_key_exist (app, keyno, force); + rc = does_key_exist (app, keyno, 1, force); if (rc) return rc; --- gnupg2-2.0.12/g10/card-util.c (revision 5068) +++ gnupg2-2.0.12/g10/card-util.c (working copy) @@ -1,5 +1,5 @@ /* card-util.c - Utility functions for the OpenPGP card. - * Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. + * Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc. * * This file is part of GnuPG. * @@ -1393,7 +1393,8 @@ show_card_key_info (&info); - if (!is_RSA (sk->pubkey_algo) || nbits_from_sk (sk) != 1024 ) + if (!is_RSA (sk->pubkey_algo) + || (!info.is_v2 && nbits_from_sk (sk) != 1024) ) { tty_printf ("You may only store a 1024 bit RSA key on the card\n"); tty_printf ("\n"); @@ -1461,7 +1462,10 @@ rc = save_unprotected_key_to_card (sk, keyno); if (rc) - goto leave; + { + log_error (_("error writing key to card: %s\n"), gpg_strerror (rc)); + goto leave; + } /* Get back to the maybe protected original secret key. */ if (copied_sk)
#! /bin/sh /usr/share/dpatch/dpatch-run ## 06-opgp-sign3072.dpatch converted by Michel Messerschmidt <w...@michel-messerschmidt.de> ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Fix OpenPGP v2 card support @DPATCH@ 2009-07-10 Werner Koch <w...@g10code.com> * iso7816.c (iso7816_compute_ds): Add args EXTENDED_MODE and LE. Change all callers to use 0. (iso7816_internal_authenticate): Add args EXTENDED_MODE and LE. * app-openpgp.c (do_sign): Take exmode and Le from card capabilities and pass them to iso7816_compute_ds. (do_auth): Ditto for iso7816_internal_authenticate. (change_keyattr): Reset CHV verification status. Index: gnupg2-2.0.12/scd/iso7816.c =================================================================== --- gnupg2-2.0.12/scd/iso7816.c (revision 5072) +++ gnupg2-2.0.12/scd/iso7816.c (working copy) @@ -505,9 +505,10 @@ /* Perform the security operation COMPUTE DIGITAL SIGANTURE. On success 0 is returned and the data is availavle in a newly allocated buffer stored at RESULT with its length stored at - RESULTLEN. */ + RESULTLEN. For LE see do_generate_keypair. */ gpg_error_t -iso7816_compute_ds (int slot, const unsigned char *data, size_t datalen, +iso7816_compute_ds (int slot, int extended_mode, + const unsigned char *data, size_t datalen, int le, unsigned char **result, size_t *resultlen) { int sw; @@ -517,9 +518,16 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0, - 0x00, CMD_PSO, 0x9E, 0x9A, datalen, (const char*)data, - result, resultlen); + if (!extended_mode) + le = 256; /* Ignore provided Le and use what apdu_send uses. */ + else if (le >= 0 && le < 256) + le = 256; + + sw = apdu_send_le (slot, extended_mode, + 0x00, CMD_PSO, 0x9E, 0x9A, + datalen, (const char*)data, + le, + result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ @@ -586,9 +594,11 @@ } +/* For LE see do_generate_keypair. */ gpg_error_t -iso7816_internal_authenticate (int slot, +iso7816_internal_authenticate (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen) { int sw; @@ -598,8 +608,16 @@ *result = NULL; *resultlen = 0; - sw = apdu_send (slot, 0, 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, - datalen, (const char*)data, result, resultlen); + if (!extended_mode) + le = 256; /* Ignore provided Le and use what apdu_send uses. */ + else if (le >= 0 && le < 256) + le = 256; + + sw = apdu_send_le (slot, extended_mode, + 0x00, CMD_INTERNAL_AUTHENTICATE, 0, 0, + datalen, (const char*)data, + le, + result, resultlen); if (sw != SW_SUCCESS) { /* Make sure that pending buffers are released. */ Index: gnupg2-2.0.12/scd/app-openpgp.c =================================================================== --- gnupg2-2.0.12/scd/app-openpgp.c (revision 5072) +++ gnupg2-2.0.12/scd/app-openpgp.c (working copy) @@ -2397,6 +2397,9 @@ log_info ("size of key %d changed to %u bits\n", keyno+1, nbits); flush_cache (app); parse_algorithm_attribute (app, keyno); + app->did_chv1 = 0; + app->did_chv2 = 0; + app->did_chv3 = 0; return err; } @@ -3008,6 +3011,7 @@ const char *fpr = NULL; unsigned long sigcount; int use_auth = 0; + int exmode, le_value; if (!keyidstr || !*keyidstr) return gpg_error (GPG_ERR_INV_VALUE); @@ -3148,7 +3152,19 @@ xfree (pinvalue); } - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + + if (app->app_local->cardcap.ext_lc_le) + { + exmode = 1; /* Use extended length. */ + le_value = app->app_local->extcap.max_rsp_data; + } + else + { + exmode = 0; + le_value = 0; + } + rc = iso7816_compute_ds (app->slot, exmode, data, datalen, le_value, + outdata, outdatalen); return rc; } @@ -3219,8 +3235,23 @@ rc = verify_chv2 (app, pincb, pincb_arg); if (!rc) - rc = iso7816_internal_authenticate (app->slot, indata, indatalen, - outdata, outdatalen); + { + int exmode, le_value; + + if (app->app_local->cardcap.ext_lc_le) + { + exmode = 1; /* Use extended length. */ + le_value = app->app_local->extcap.max_rsp_data; + } + else + { + exmode = 0; + le_value = 0; + } + rc = iso7816_internal_authenticate (app->slot, exmode, + indata, indatalen, le_value, + outdata, outdatalen); + } return rc; } Index: gnupg2-2.0.12/scd/iso7816.h =================================================================== --- gnupg2-2.0.12/scd/iso7816.h (revision 5072) +++ gnupg2-2.0.12/scd/iso7816.h (working copy) @@ -93,15 +93,17 @@ gpg_error_t iso7816_manage_security_env (int slot, int p1, int p2, const unsigned char *data, size_t datalen); -gpg_error_t iso7816_compute_ds (int slot, +gpg_error_t iso7816_compute_ds (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_decipher (int slot, int extended_mode, const unsigned char *data, size_t datalen, int padind, unsigned char **result, size_t *resultlen); -gpg_error_t iso7816_internal_authenticate (int slot, +gpg_error_t iso7816_internal_authenticate (int slot, int extended_mode, const unsigned char *data, size_t datalen, + int le, unsigned char **result, size_t *resultlen); gpg_error_t iso7816_generate_keypair (int slot, int extended_mode, const unsigned char *data, size_t datalen, Index: gnupg2-2.0.12/scd/app-dinsig.c =================================================================== --- gnupg2-2.0.12/scd/app-dinsig.c (revision 5072) +++ gnupg2-2.0.12/scd/app-dinsig.c (working copy) @@ -483,7 +483,8 @@ rc = verify_pin (app, pincb, pincb_arg); if (!rc) - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0, + outdata, outdatalen); return rc; } Index: gnupg2-2.0.12/scd/app-nks.c =================================================================== --- gnupg2-2.0.12/scd/app-nks.c (revision 5072) +++ gnupg2-2.0.12/scd/app-nks.c (working copy) @@ -969,7 +969,8 @@ rc = verify_pin (app, 0, NULL, pincb, pincb_arg); /* Compute the signature. */ if (!rc) - rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen); + rc = iso7816_compute_ds (app->slot, 0, data, datalen, 0, + outdata, outdatalen); return rc; } Index: gnupg2-2.0.12/scd/app-p15.c =================================================================== --- gnupg2-2.0.12/scd/app-p15.c (revision 5072) +++ gnupg2-2.0.12/scd/app-p15.c (working copy) @@ -3180,11 +3180,11 @@ } if (hashalgo == MD_USER_TLS_MD5SHA1) - err = iso7816_compute_ds (app->slot, data, 36, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data, 36, 0, outdata, outdatalen); else if (no_data_padding) - err = iso7816_compute_ds (app->slot, data+15, 20, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data+15, 20, 0,outdata,outdatalen); else - err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen); + err = iso7816_compute_ds (app->slot, 0, data, 35, 0, outdata, outdatalen); return err; }
signature.asc
Description: Digital signature