Dear Developers,

this series of patches adds ECC support for the D-Trust 4.1/4.4 cards. All the 
code was already there. Just the security environment parameters had to be 
confirmed which I now successfully did with my test cards.

The patches further allow keys with the derive usage-flag to be used for 
decryption and fixes certificate import for duplicate certificate IDs. These 
issues were already addressed in separate threads on this list.

I am unsure whether patch nr. 0003 is necessary. Feel free to either omit it 
or to squash it with 0002.

Mario Haustein (3):
  scd:p15: Take derive usage into account for decryption.
  scd:p15: Fix typo in a comment
  scd:p15: Add ECC support for D-Trust Card 4.1/4.4

Werner Koch (2):
  scd:p15: Handle duplicate certificate ids.
  scd:p15: Take derive usage into account for decryption.

 scd/app-p15.c | 96 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 71 insertions(+), 25 deletions(-)

-- 
2.43.0

Kind regards
-- 
Mario Haustein
Facharbeitsgruppe Anwendungen
Universitätsrechenzentrum

Technische Universität Chemnitz
Straße der Nationen 62 | R. 1/B303 (neu: A11.303)
09111 Chemnitz
Germany

Tel:    +49 371 531-36606
Fax:    +49 371 531-836606

[email protected]
www.tu-chemnitz.de
>From f7b706b0e78cc7415cd2e512ed4a9731b355078f Mon Sep 17 00:00:00 2001
From: Werner Koch <[email protected]>
Date: Mon, 19 Feb 2024 14:45:06 +0100
Subject: [PATCH GnuPG 1/5] scd:p15: Handle duplicate certificate ids.

* scd/app-p15.c (struct app_local_s): Add field cdf_dup_counter.
(objid_in_cdflist_p): New.
(read_p15_info): Clear the counter.
(read_ef_cdf): Detect and fix duplicate IDs.
--

GnuPG-bug-id: 7001
Reported-by: Mario Haustein <[email protected]>
---
 scd/app-p15.c | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index 2bb90beaa..eb9c53465 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -520,6 +520,9 @@ struct app_local_s
   /* Information on all useful certificates. */
   cdf_object_t useful_certificate_info;
 
+  /* Counter to make object ids of certificates unique.  */
+  unsigned int cdf_dup_counter;
+
   /* Information on all public keys. */
   prkdf_object_t public_key_info;
 
@@ -2419,6 +2422,22 @@ read_ef_pukdf (app_t app, unsigned short fid, pukdf_object_t *result)
 }
 
 
+/* Return true id CDFLIST has the given object id.  */
+static int
+objid_in_cdflist_p (cdf_object_t cdflist,
+                    const unsigned char *objid, size_t objidlen)
+{
+  cdf_object_t cdf;
+
+  if (!objid || !objidlen)
+    return 0;
+  for (cdf = cdflist; cdf; cdf = cdf->next)
+    if (cdf->objidlen == objidlen && !memcmp (cdf->objid, objid, objidlen))
+      return 1;
+  return 0;
+}
+
+
 /* Read and parse the Certificate Directory Files identified by FID.
    On success a newlist of CDF object gets stored at RESULT and the
    caller is then responsible of releasing this list.  On error a
@@ -2464,6 +2483,7 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
       unsigned long ul;
       const unsigned char *objid;
       size_t objidlen;
+      int objidextralen;
 
       err = parse_ber_header (&p, &n, &class, &tag, &constructed,
                               &ndef, &objlen, &hdrlen);
@@ -2588,8 +2608,19 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
           label = NULL;
         }
 
-      cdf->objidlen = objidlen;
-      cdf->objid = xtrymalloc (objidlen);
+      /* Card's have been found in the wild which do not have unique
+       * IDs for their certificate objects.  If we detect this we
+       * append a counter to the ID.  */
+      objidextralen =
+        (objid_in_cdflist_p (cdflist, objid, objidlen)
+         || objid_in_cdflist_p (app->app_local->certificate_info,
+                                objid, objidlen)
+         || objid_in_cdflist_p (app->app_local->trusted_certificate_info,
+                                objid, objidlen)
+         || objid_in_cdflist_p (app->app_local->useful_certificate_info,
+                                objid, objidlen));
+      cdf->objidlen = objidlen + objidextralen;
+      cdf->objid = xtrymalloc (objidlen + objidextralen);
       if (!cdf->objid)
         {
           err = gpg_error_from_syserror ();
@@ -2597,6 +2628,16 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
           goto leave;
         }
       memcpy (cdf->objid, objid, objidlen);
+      if (objidextralen)
+        {
+          if (app->app_local->cdf_dup_counter == 255)
+            {
+              log_error ("p15: too many duplicate certificate ids\n");
+              err = gpg_error (GPG_ERR_TOO_MANY);
+              goto parse_error;
+            }
+          cdf->objid[objidlen] = ++app->app_local->cdf_dup_counter;
+        }
 
       cdf->pathlen = objlen/2;
       for (i=0; i < cdf->pathlen; i++, pp += 2, nn -= 2)
@@ -3664,6 +3705,7 @@ read_p15_info (app_t app)
   log_assert (!app->app_local->certificate_info);
   log_assert (!app->app_local->trusted_certificate_info);
   log_assert (!app->app_local->useful_certificate_info);
+  app->app_local->cdf_dup_counter = 0;
   err = read_ef_cdf (app, app->app_local->odf.certificates, 'c',
                      &app->app_local->certificate_info);
   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
-- 
2.43.0

>From 057a668a7994dfb4ad3dcde7d40337cd34bded64 Mon Sep 17 00:00:00 2001
From: Werner Koch <[email protected]>
Date: Mon, 19 Feb 2024 13:51:02 +0100
Subject: [PATCH GnuPG 2/5] scd:p15: Take derive usage into account for
 decryption.

* scd/app-p15.c (set_usage_string): Map usageflags.derive also to 'e'.
(do_auth): Allow usageflags.sign_recover.
(do_decipher): Allow usageflags.derive.
(do_with_keygrip): Take usageflags.derive into account.

(do_decipher): Take a missing AODF for authentication not needed.
--

This is required for D-Trust ECC cards.

The AODF thing is unrelated but seems to be a good idea.

GnuPG-bug-id: 7000
---
 scd/app-p15.c | 33 +++++++++++++++++++--------------
 1 file changed, 19 insertions(+), 14 deletions(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index eb9c53465..8a869279d 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -305,7 +305,7 @@ struct prkdf_object_s
   keyaccess_flags_t accessflags;
 
   /* Extended key usage flags.  Only used if .valid is set.  This
-   * information is computed from an associated certificate15.  */
+   * information is computed from an associated certificate.  */
   struct {
     unsigned int valid:1;
     unsigned int sign:1;
@@ -4256,7 +4256,8 @@ set_usage_string (char usage[5], prkdf_object_t prkdf)
           && (!prkdf->extusage.valid || prkdf->extusage.sign))
         usage[usagelen++] = 'c';
       if ((prkdf->usageflags.decrypt
-           || prkdf->usageflags.unwrap)
+           || prkdf->usageflags.unwrap
+           || prkdf->usageflags.derive)
           && (!prkdf->extusage.valid || prkdf->extusage.encr))
         usage[usagelen++] = 'e';
       if ((prkdf->usageflags.sign
@@ -5969,7 +5970,8 @@ do_auth (app_t app, ctrl_t ctrl, const char *keyidstr,
   err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
   if (err)
     return err;
-  if (!(prkdf->usageflags.sign || prkdf->gpgusage.auth))
+  if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover
+        || prkdf->gpgusage.auth))
     {
       log_error ("p15: key %s may not be used for authentication\n", keyidstr);
       return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
@@ -6012,6 +6014,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
     return err;
   if (!(prkdf->usageflags.decrypt
         || prkdf->usageflags.unwrap
+        || prkdf->usageflags.derive
         || prkdf->gpgusage.encr     ))
     {
       log_error ("p15: key %s may not be used for decryption\n", keyidstr);
@@ -6021,17 +6024,18 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
   /* Find the authentication object to this private key object. */
   if (!prkdf->authid)
     {
-      log_error ("p15: no authentication object defined for %s\n", keyidstr);
-      /* fixme: we might want to go ahead and do without PIN
-         verification. */
-      return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
+      log_info ("p15: no authentication object defined for %s\n", keyidstr);
+      aodf = NULL;
+    }
+  else
+    {
+      for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next)
+        if (aodf->objidlen == prkdf->authidlen
+            && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
+          break;
+      if (!aodf)
+        log_info ("p15: no authentication for %s needed\n", keyidstr);
     }
-  for (aodf = app->app_local->auth_object_info; aodf; aodf = aodf->next)
-    if (aodf->objidlen == prkdf->authidlen
-        && !memcmp (aodf->objid, prkdf->authid, prkdf->authidlen))
-      break;
-  if (!aodf)
-    log_info ("p15: no authentication for %s needed\n", keyidstr);
 
   /* We need some more info about the key - get the keygrip to
    * populate these fields.  */
@@ -6316,7 +6320,8 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
             }
           else if (capability == GCRY_PK_USAGE_ENCR)
             {
-              if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap))
+              if (!(prkdf->usageflags.decrypt || prkdf->usageflags.unwrap
+                    || prkdf->usageflags.derive))
                 continue;
             }
           else if (capability == GCRY_PK_USAGE_AUTH)
-- 
2.43.0

>From 3c61ac16e8b6a90f3efeb917bd20612660755c54 Mon Sep 17 00:00:00 2001
From: Mario Haustein <[email protected]>
Date: Mon, 19 Feb 2024 10:22:08 +0100
Subject: [PATCH GnuPG 4/5] scd:p15: Fix typo in a comment

---
 scd/app-p15.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index 4ad3bc3b7..fb1b67c21 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -4704,7 +4704,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
 
       /* We return the ID of the first private key capable of the
        * requested action.  If any gpgusage flag has been set for the
-       * card we consult the gpgusage flags and not the regualr usage
+       * card we consult the gpgusage flags and not the regular usage
        * flags.
        */
       /* FIXME: This changed: Note that we do not yet return
-- 
2.43.0

>From c944a0cb15a332426105a33bf01d4f301b60cbe7 Mon Sep 17 00:00:00 2001
From: Mario Haustein <[email protected]>
Date: Mon, 19 Feb 2024 10:21:24 +0100
Subject: [PATCH GnuPG 3/5] scd:p15: Take derive usage into account for
 decryption.

* scd/app-p15.c (do_getattr): Map usageflags.derive also to 'e'.
---
 scd/app-p15.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index 8a869279d..4ad3bc3b7 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -4726,7 +4726,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
               if ((name[1] == 'A' && (prkdf->usageflags.sign
                                       || prkdf->usageflags.sign_recover))
                   || (name[1] == 'E' && (prkdf->usageflags.decrypt
-                                         || prkdf->usageflags.unwrap))
+                                         || prkdf->usageflags.unwrap
+                                         || prkdf->usageflags.derive))
                   || (name[1] == 'S' && (prkdf->usageflags.sign
                                          || prkdf->usageflags.sign_recover)))
                 break;
@@ -4935,7 +4936,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
             }
           else
             {
-              if (prkdf->usageflags.decrypt || prkdf->usageflags.unwrap)
+              if (prkdf->usageflags.decrypt || prkdf->usageflags.unwrap || prkdf->usageflags.derive)
                 break;
             }
         }
-- 
2.43.0

>From 5fecff0baed5d8b7ef0f53a08a75976794dd739e Mon Sep 17 00:00:00 2001
From: Mario Haustein <[email protected]>
Date: Mon, 19 Feb 2024 10:22:35 +0100
Subject: [PATCH GnuPG 5/5] scd:p15: Add ECC support for D-Trust Card 4.1/4.4

* scd/app-p15.c (do_sign): Add MSE RESTORE parameters for D-Trust ECC
cards.
(do_decipher): Ditto.
---
 scd/app-p15.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index fb1b67c21..877db8bfc 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -5828,9 +5828,8 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
     {
       if (prkdf->is_ecc)
         {
-          /* Not implemented due to lacking test hardware. */
-          log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n");
-          err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+          err = iso7816_manage_security_env (app_get_slot (app),
+                                             0xf3, 0x21, NULL, 0);
         }
       else
         {
@@ -6089,9 +6088,8 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
     {
       if (prkdf->is_ecc)
         {
-          /* Not implemented due to lacking test hardware. */
-          log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n");
-          err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+          err = iso7816_manage_security_env (app_get_slot (app),
+                                             0xF3, 0x39, NULL, 0);
         }
       else
         {
-- 
2.43.0

Attachment: signature.asc
Description: This is a digitally signed message part.

_______________________________________________
Gnupg-devel mailing list
[email protected]
https://lists.gnupg.org/mailman/listinfo/gnupg-devel

Reply via email to