[git] GnuPG - branch, master, updated. gnupg-2.2.7-370-g43b14b4

by Werner Koch cvs at cvs.gnupg.org
Mon Feb 11 15:33:23 CET 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  43b14b4cc227311aa77b1fc1d9577c5f7d3eda86 (commit)
      from  b2838694402ce0cfc2ef70451bf0e6677b875ca9 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 43b14b4cc227311aa77b1fc1d9577c5f7d3eda86
Author: Werner Koch <wk at gnupg.org>
Date:   Mon Feb 11 15:32:54 2019 +0100

    scd: Implement decryption for PIV cards.
    
    * scd/app-piv.c (do_decipher): New.
    --
    
    Note that ECDH decryption has not been tested due to the lack of ECC
    support in gpgsm.
    
    Signed-off-by: Werner Koch <wk at gnupg.org>

diff --git a/scd/app-piv.c b/scd/app-piv.c
index 36086f5..9e355b4 100644
--- a/scd/app-piv.c
+++ b/scd/app-piv.c
@@ -2259,6 +2259,151 @@ do_auth (app_t app, const char *keyidstr,
 }
 
 
+/* Decrypt the data in (INDATA,INDATALEN) and on success store the
+ * mallocated result at (R_OUTDATA,R_OUTDATALEN).  */
+static gpg_error_t
+do_decipher (app_t app, const char *keyidstr,
+             gpg_error_t (*pincb)(void*, const char *, char **),
+             void *pincb_arg,
+             const void *indata_arg, size_t indatalen,
+             unsigned char **r_outdata, size_t *r_outdatalen,
+             unsigned int *r_info)
+{
+  const unsigned char *indata = indata_arg;
+  gpg_error_t err;
+  data_object_t dobj;
+  unsigned char *outdata = NULL;
+  size_t outdatalen;
+  const unsigned char *s;
+  size_t n;
+  int keyref, mechanism;
+  unsigned int framelen;
+  unsigned char *indata_buffer = NULL; /* Malloced helper.  */
+  unsigned char *apdudata = NULL;
+  size_t apdudatalen;
+
+  if (!keyidstr || !*keyidstr)
+    {
+      err = gpg_error (GPG_ERR_INV_VALUE);
+      goto leave;
+    }
+
+  dobj = find_dobj_by_keyref (app, keyidstr);
+  if ((keyref = keyref_from_dobj (dobj)) == -1)
+    {
+      err = gpg_error (GPG_ERR_INV_ID);
+      goto leave;
+    }
+  if (keyref == 0x9A || keyref == 0x9C || keyref == 0x9E)
+    {
+      /* Signing only reference.  We only allow '9D' and the retired
+       * cert key management DOs.  */
+      err = gpg_error (GPG_ERR_INV_ID);
+      goto leave;
+    }
+
+  err = get_key_algorithm_by_dobj (app, dobj, &mechanism);
+  if (err)
+    goto leave;
+
+  switch (mechanism)
+    {
+    case PIV_ALGORITHM_ECC_P256:
+      framelen = 1+32+32;
+      break;
+    case PIV_ALGORITHM_ECC_P384:
+      framelen = 1+48+48;
+      break;
+    case PIV_ALGORITHM_RSA:
+      framelen = 2048 / 8;
+      break;
+    default:
+      err = gpg_error (GPG_ERR_INTERNAL);
+      log_debug ("piv: unknown PIV mechanism %d while decrypting\n", mechanism);
+      goto leave;
+    }
+
+  /* Check that the ciphertext has the right length; due to internal
+   * convey mechanism using MPIs leading zero bytes might have been
+   * lost.  Adjust for this.  Note that for ECC this actually
+   * superfluous because the first octet is always '04' to indicate an
+   * uncompressed point.  */
+  if (indatalen > framelen)
+    {
+      err = gpg_error (GPG_ERR_INV_VALUE);
+      log_error ("piv: input of %zu octets too large for mechanism %d\n",
+                 indatalen, mechanism);
+      goto leave;
+    }
+  if (indatalen < framelen)
+    {
+      indata_buffer = xtrycalloc (1, framelen);
+      if (!indata_buffer)
+        {
+          err = gpg_error_from_syserror ();
+          goto leave;
+        }
+      memcpy (indata_buffer+(framelen-indatalen), indata, indatalen);
+      indata = indata_buffer;
+      indatalen = framelen;
+    }
+
+  /* Now verify the Application PIN.  */
+  err = verify_chv (app, 0x80, pincb, pincb_arg);
+  if (err)
+    return err;
+
+  /* Build the Dynamic Authentication Template.  */
+  err = concat_tlv_list (&apdudata, &apdudatalen,
+                         (int)0x7c, (size_t)0, NULL, /* Constructed. */
+                         (int)0x82, (size_t)0, "",
+                         mechanism == PIV_ALGORITHM_RSA?
+                         (int)0x81 : (int)0x85, (size_t)indatalen, indata,
+                         (int)0, (size_t)0, NULL);
+  if (err)
+    goto leave;
+
+  /* Note: the -1 requests command chaining.  */
+  err = iso7816_general_authenticate (app->slot, -1,
+                                      mechanism, keyref,
+                                      apdudata, (int)apdudatalen, 0,
+                                      &outdata, &outdatalen);
+  if (err)
+    goto leave;
+
+  /* Parse the response.  */
+  if (outdatalen && *outdata == 0x7c
+      && (s = find_tlv (outdata, outdatalen, 0x82, &n)))
+    {
+      memmove (outdata, outdata + (s - outdata), n);
+      outdatalen = n;
+    }
+  else
+    {
+      err = gpg_error (GPG_ERR_CARD);
+      log_error ("piv: response does not contain a proper result\n");
+      goto leave;
+    }
+
+ leave:
+  if (err)
+    {
+      xfree (outdata);
+      *r_outdata = NULL;
+      *r_outdatalen = 0;
+    }
+  else
+    {
+      *r_outdata = outdata;
+      *r_outdatalen = outdatalen;
+    }
+  *r_info = 0;
+  xfree (apdudata);
+  xfree (indata_buffer);
+  return err;
+}
+
+
 /* Check whether a key for DOBJ already exists.  We detect this by
  * reading the certificate described by DOBJ.  If FORCE is TRUE a
  * diagnositic will be printed but no error returned if the key
@@ -2679,7 +2824,7 @@ app_select_piv (app_t app)
   app->fnc.genkey = do_genkey;
   app->fnc.sign = do_sign;
   app->fnc.auth = do_auth;
-  /* app->fnc.decipher = do_decipher; */
+  app->fnc.decipher = do_decipher;
   app->fnc.change_pin = do_change_chv;
   app->fnc.check_pin = do_check_chv;
 

-----------------------------------------------------------------------

Summary of changes:
 scd/app-piv.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 146 insertions(+), 1 deletion(-)


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list