[PATCH GnuPG 2/2] scd:p15: Add support for D-Trust Card 4.1/4.4

Mario Haustein mario.haustein at hrz.tu-chemnitz.de
Tue Nov 28 23:09:26 CET 2023


* scd/app-p15.c (CARD_PRODUCT_DTRUST4) New.
(app_select_p15): This cards uses a different AID for PKCS#15
application
(do_sign): The card doesn't support MSE SET, but requires MSE RESTORE to
a predefined template.
(do_decipher): Ditto.
---
 scd/app-p15.c | 80 +++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 71 insertions(+), 9 deletions(-)

diff --git a/scd/app-p15.c b/scd/app-p15.c
index dab1f4901..c4eb1e019 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -87,7 +87,8 @@ typedef enum
   {
     CARD_PRODUCT_UNKNOWN,
     CARD_PRODUCT_RSCS,     /* Rohde&Schwarz Cybersecurity       */
-    CARD_PRODUCT_DTRUST,   /* D-Trust GmbH (bundesdruckerei.de) */
+    CARD_PRODUCT_DTRUST3,  /* D-Trust GmbH (bundesdruckerei.de) */
+    CARD_PRODUCT_DTRUST4,
     CARD_PRODUCT_GENUA,    /* GeNUA mbH                         */
     CARD_PRODUCT_NEXUS     /* Technology Nexus                  */
   }
@@ -151,6 +152,11 @@ static char const pkcs15_aid[] = { 0xA0, 0, 0, 0, 0x63,
 static char const pkcs15be_aid[] = { 0xA0, 0, 0, 0x01, 0x77,
                                    0x50, 0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35 };
 
+/* The D-TRUST Card 4.x variant - dito */
+static char const pkcs15dtrust4_aid[] = { 0xE8, 0x28, 0xBD, 0x08, 0x0F, 0xA0,
+                                          0x00, 0x00, 0x01, 0x67, 0x45, 0x53,
+                                          0x49, 0x47, 0x4E };
+
 
 /* The PIN types as defined in pkcs#15 v1.1 */
 typedef enum
@@ -554,7 +560,8 @@ cardproduct2str (card_product_t cardproduct)
     {
     case CARD_PRODUCT_UNKNOWN: return "";
     case CARD_PRODUCT_RSCS:    return "R&S";
-    case CARD_PRODUCT_DTRUST:  return "D-Trust";
+    case CARD_PRODUCT_DTRUST3: return "D-Trust 3";
+    case CARD_PRODUCT_DTRUST4: return "D-Trust 4.1/4.4";
     case CARD_PRODUCT_GENUA:   return "GeNUA";
     case CARD_PRODUCT_NEXUS:   return "Nexus";
     }
@@ -3500,7 +3507,7 @@ read_ef_tokeninfo (app_t app)
       ul |= (*p++) & 0xff;
       n--;
     }
-  if (ul)
+  if (ul > 1)
     {
       log_error ("p15: invalid version %lu in TokenInfo\n", ul);
       err = gpg_error (GPG_ERR_INV_OBJ);
@@ -3834,7 +3841,14 @@ read_p15_info (app_t app)
       && !strncmp (app->app_local->token_label, "D-TRUST Card V3", 15)
       && app->app_local->card_type == CARD_TYPE_CARDOS_50)
     {
-      app->app_local->card_product = CARD_PRODUCT_DTRUST;
+      app->app_local->card_product = CARD_PRODUCT_DTRUST3;
+    }
+  if (!app->app_local->card_product
+      && app->app_local->token_label
+      && !strncmp (app->app_local->token_label, "D-TRUST Card 4.", 15)
+      && app->app_local->card_type == CARD_TYPE_CARDOS_54)
+    {
+      app->app_local->card_product = CARD_PRODUCT_DTRUST4;
     }
 
 
@@ -5012,7 +5026,7 @@ prepare_verify_pin (app_t app, const char *keyref,
     }
 
 
-  if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+  if (app->app_local->card_product == CARD_PRODUCT_DTRUST3)
     {
       /* According to our protocol analysis we need to select a
        * special AID here.  Before that the master file needs to be
@@ -5263,7 +5277,8 @@ verify_pin (app_t app,
   if (prkdf
       && prkdf->usageflags.non_repudiation
       && (app->app_local->card_type == CARD_TYPE_BELPIC
-          || app->app_local->card_product == CARD_PRODUCT_DTRUST))
+          || app->app_local->card_product == CARD_PRODUCT_DTRUST3
+          || app->app_local->card_product == CARD_PRODUCT_DTRUST4))
     label = _("||Please enter the PIN for the key to create "
               "qualified signatures.");
   else if (aodf->pinflags.so_pin)
@@ -5627,7 +5642,8 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
           goto leave;
         }
       if (app->app_local->card_type == CARD_TYPE_BELPIC
-          || app->app_local->card_product == CARD_PRODUCT_NEXUS)
+          || app->app_local->card_product == CARD_PRODUCT_NEXUS
+          || app->app_local->card_product == CARD_PRODUCT_DTRUST4)
         {
           /* The default for these cards is to use a plain hash.  We
            * assume that due to the used certificate the correct hash
@@ -5713,6 +5729,30 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
       else
         err = micardo_mse (app, prkdf->path[prkdf->pathlen-1]);
     }
+  else if (app->app_local->card_product == CARD_PRODUCT_DTRUST4)
+    {
+      if (prkdf->is_ecc)
+        {
+          /* Not implemented due to lacking test hardware. */
+          err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+        }
+      else
+        {
+          /* The D-TRUST Card 4.x doesn't support setting a security
+           * environment, at least as specified in the specs.  Insted a
+           * predefined security environment has to be loaded depending on the
+           * cipher and message digest used.  The spec states SE-ID 0x25 for
+           * SHA256, 0x26 for SHA384 and 0x27 for SHA512, when using PKCS#1
+           * padding.  But this matters only if the message digest is computed
+           * on the card.  When providing the digest info and a pre-calculated
+           * hash, all security environments yield the same result.  Thus we
+           * choose 0x25.
+           *
+           * Note: For PSS signatures, different values apply. */
+            err = iso7816_manage_security_env (app_get_slot (app),
+                                               0xf3, 0x25, NULL, 0);
+        }
+    }
   else if (prkdf->key_reference_valid)
     {
       unsigned char mse[3];
@@ -5868,7 +5908,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
 
 
   /* The next is guess work for CardOS.  */
-  if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+  if (app->app_local->card_product == CARD_PRODUCT_DTRUST3)
     {
       /* From analyzing an USB trace of a Windows signing application
        * we see that the SE is simply reset to 0x14.  It seems to be
@@ -5885,6 +5925,21 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
                                          0xF3, 0x14, NULL, 0);
 
     }
+  else if (app->app_local->card_product == CARD_PRODUCT_DTRUST4)
+    {
+      if (prkdf->is_ecc)
+        {
+          /* Not implemented due to lacking test hardware. */
+          err = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
+        }
+      else
+        {
+          /* SE-ID 0x31 is for PKCS#1 padded cryptograms. For OAEP encryption
+           * schemes, different values apply. */
+          err = iso7816_manage_security_env (app_get_slot (app),
+                                             0xF3, 0x31, NULL, 0);
+        }
+    }
   else if (prkdf->key_reference_valid)
     {
       unsigned char mse[9];
@@ -5928,7 +5983,8 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
       le_value = prkdf->keynbits / 8;
     }
 
-  if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+  if (app->app_local->card_product == CARD_PRODUCT_DTRUST3
+      || app->app_local->card_product == CARD_PRODUCT_DTRUST4)
     padind = 0x81;
 
   if (prkdf->is_ecc && IS_CARDOS_5(app))
@@ -6190,6 +6246,12 @@ app_select_p15 (app_t app)
 
   rc = iso7816_select_application_ext (slot, pkcs15_aid, sizeof pkcs15_aid, 1,
                                        &fci, &fcilen);
+  if (rc)
+    {
+      /* D-TRUST Card 4.x uses a different AID. */
+      rc = iso7816_select_application_ext (slot, pkcs15dtrust4_aid, sizeof pkcs15dtrust4_aid, 1,
+                                           &fci, &fcilen);
+    }
   if (rc)
     { /* Not found: Try to locate it from 2F00.  We use direct path
          selection here because it seems that the Belgian eID card
-- 
2.41.0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 5734 bytes
Desc: not available
URL: <https://lists.gnupg.org/pipermail/gnupg-devel/attachments/20231128/b8161c1b/attachment-0001.bin>


More information about the Gnupg-devel mailing list