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;
 }
 

Attachment: signature.asc
Description: Digital signature

Reply via email to