summaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2020-04-07 16:00:11 +0200
committerWerner Koch <wk@gnupg.org>2020-04-07 16:03:11 +0200
commit42ddcc87f4bca40d605d133b6cdb4e761a49a1c9 (patch)
tree7b4f9db3961f8f9616cde3d01e6971c09acaa6c4 /scd
parenttools: Use internal regexp routines. (diff)
downloadgnupg2-42ddcc87f4bca40d605d133b6cdb4e761a49a1c9.tar.xz
gnupg2-42ddcc87f4bca40d605d133b6cdb4e761a49a1c9.zip
scd:p15: Fix decrypt followed by sign problem for D-Trust cards.
* scd/iso7816.c (iso7816_select_mf): New. * scd/app-p15.c (card_product_t): New. (struct app_local_s): Add field 'card_product'. (read_ef_tokeninfo): Detect D-Trust card. (prepare_verify_pin): Switch to D-Trust AID. (do_decipher): Restore a SE for D-TRust cards. Chnage the passing indicator to 0x81. -- Using what I learned from a USB trace running the Governikus Signer Software on Windows this fixes the left over problem with the new D-Trust card support. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'scd')
-rw-r--r--scd/app-p15.c93
-rw-r--r--scd/iso7816.c11
-rw-r--r--scd/iso7816.h1
3 files changed, 91 insertions, 14 deletions
diff --git a/scd/app-p15.c b/scd/app-p15.c
index 509759069..72240889b 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -55,6 +55,17 @@ typedef enum
}
card_type_t;
+/* The OS of card as specified by card_type_t is not always
+ * sufficient. Thus we also distinguish the actual product build upon
+ * the given OS. */
+typedef enum
+ {
+ CARD_PRODUCT_UNKNOWN,
+ CARD_PRODUCT_DTRUST /* D-Trust GmbH (bundesdruckerei.de) */
+ }
+card_product_t;
+
+
/* A list card types with ATRs noticed with these cards. */
#define X(a) ((unsigned char const *)(a))
static struct
@@ -305,9 +316,12 @@ struct app_local_s
hierarchy. Thus we assume this is directly below the MF. */
unsigned short home_df;
- /* The type of the card. */
+ /* The type of the card's OS. */
card_type_t card_type;
+ /* The vendor's product. */
+ card_product_t card_product;
+
/* Flag indicating whether we may use direct path selection. */
int direct_path_selection;
@@ -2375,6 +2389,7 @@ read_ef_tokeninfo (app_t app)
xfree (app->app_local->manufacturer_id);
app->app_local->manufacturer_id = NULL;
+ app->app_local->card_product = CARD_PRODUCT_UNKNOWN;
err = select_and_read_binary (app_get_slot (app), 0x5032, "TokenInfo",
&buffer, &buflen);
@@ -2472,6 +2487,10 @@ read_ef_tokeninfo (app_t app)
{
if (opt.verbose)
log_info ("p15: label ........: %.*s\n", (int)objlen, p);
+ if (objlen > 15 && !memcmp (p, "D-TRUST Card V3", 15)
+ && app->app_local->card_type == CARD_TYPE_CARDOS_50)
+ app->app_local->card_product = CARD_PRODUCT_DTRUST;
+
p += objlen;
n -= objlen;
/* Get next TLV. */
@@ -3180,12 +3199,33 @@ prepare_verify_pin (app_t app, const char *keyref,
}
}
- /* Select the key file. Note that this may change the security
- * environment thus we need to do it before PIN verification. */
- err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
- if (err)
- log_error ("p15: error selecting file for key %s: %s\n",
- keyref, gpg_strerror (err));
+
+ if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+ {
+ /* According to our protocol analysis we need to select a
+ * special AID here. Before that the master file needs to be
+ * selected. (RID A000000167 is assigned to IBM) */
+ static char const dtrust_aid[] =
+ { 0xA0, 0x00, 0x00, 0x01, 0x67, 0x45, 0x53, 0x49, 0x47, 0x4E };
+
+ err = iso7816_select_mf (app_get_slot (app));
+ if (!err)
+ err = iso7816_select_application (app_get_slot (app),
+ dtrust_aid, sizeof dtrust_aid, 0);
+ if (err)
+ log_error ("p15: error selecting D-TRUST's AID for key %s: %s\n",
+ keyref, gpg_strerror (err));
+ }
+ else
+ {
+ /* Standard case: Select the key file. Note that this may
+ * change the security environment thus we need to do it before
+ * PIN verification. */
+ err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
+ if (err)
+ log_error ("p15: error selecting file for key %s: %s\n",
+ keyref, gpg_strerror (err));
+ }
return err;
}
@@ -3722,10 +3762,30 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
/* The next is guess work for CardOS. */
- if (prkdf->key_reference_valid)
+ if (app->app_local->card_product == CARD_PRODUCT_DTRUST)
+ {
+ /* From analyzing an USB trace of a Windows signing application
+ * we see that the SE is simply reset to 0x14. It seems to be
+ * sufficient to do this for decryption; signing still works
+ * with the standard code despite that our trace showed that
+ * there the SE is restored to 0x09. Note that the special
+ * D-Trust AID is in any case select by prepare_verify_pin.
+ *
+ * Hey, D-Trust please hand over the specs so that you can
+ * actually sell your cards and we can properly implement it;
+ * other vendors understand this and do not demand ridiculous
+ * paper work or complicated procedures to get samples. */
+ err = iso7816_manage_security_env (app_get_slot (app),
+ 0xF3, 0x14, NULL, 0);
+
+ }
+ else if (prkdf->key_reference_valid)
{
unsigned char mse[6];
+ /* Note: This works with CardOS but the D-Trust card has the
+ * problem that the next created signature would be broken. */
+
mse[0] = 0x80; /* Algorithm reference. */
mse[1] = 1;
mse[2] = 0x0a; /* RSA, no padding. */
@@ -3734,13 +3794,13 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
mse[5] = prkdf->key_reference;
err = iso7816_manage_security_env (app_get_slot (app), 0x41, 0xB8,
mse, sizeof mse);
- if (err)
- {
- log_error ("p15: MSE failed: %s\n", gpg_strerror (err));
- return err;
- }
}
-
+ /* Check for MSE error. */
+ if (err)
+ {
+ log_error ("p15: MSE failed: %s\n", gpg_strerror (err));
+ return err;
+ }
exmode = le_value = 0;
padind = 0;
@@ -3750,6 +3810,9 @@ 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)
+ padind = 0x81;
+
err = iso7816_decipher (app_get_slot (app), exmode,
indata, indatalen,
le_value, padind,
@@ -4010,6 +4073,8 @@ app_select_p15 (app_t app)
the common APP structure. */
app->app_local->card_type = card_type;
+ app->app_local->card_product = CARD_PRODUCT_UNKNOWN;
+
/* Store whether we may and should use direct path selection. */
app->app_local->direct_path_selection = direct;
diff --git a/scd/iso7816.c b/scd/iso7816.c
index 9d9ee2d66..96d016a26 100644
--- a/scd/iso7816.c
+++ b/scd/iso7816.c
@@ -145,6 +145,17 @@ iso7816_select_application_ext (int slot, const char *aid, size_t aidlen,
}
+/* Simple MF selection as supported by some cards. */
+gpg_error_t
+iso7816_select_mf (int slot)
+{
+ int sw;
+
+ sw = apdu_send_simple (slot, 0, 0x00, CMD_SELECT_FILE, 0x000, 0x0c, -1, NULL);
+ return map_sw (sw);
+}
+
+
gpg_error_t
iso7816_select_file (int slot, int tag, int is_dir)
{
diff --git a/scd/iso7816.h b/scd/iso7816.h
index 1a9fed726..a8215808b 100644
--- a/scd/iso7816.h
+++ b/scd/iso7816.h
@@ -56,6 +56,7 @@ gpg_error_t iso7816_select_application_ext (int slot,
unsigned int flags,
unsigned char **result,
size_t *resultlen);
+gpg_error_t iso7816_select_mf (int slot);
gpg_error_t iso7816_select_file (int slot, int tag, int is_dir);
gpg_error_t iso7816_select_path (int slot,
const unsigned short *path, size_t pathlen);