aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-p15.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/app-p15.c')
-rw-r--r--scd/app-p15.c176
1 files changed, 133 insertions, 43 deletions
diff --git a/scd/app-p15.c b/scd/app-p15.c
index 4338a623e..8edd737a6 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -74,8 +74,10 @@ typedef enum
CARD_TYPE_MICARDO,
CARD_TYPE_CARDOS_50,
CARD_TYPE_CARDOS_53,
+ CARD_TYPE_CARDOS_54,
CARD_TYPE_AET, /* A.E.T. Europe JCOP card. */
- CARD_TYPE_BELPIC /* Belgian eID card specs. */
+ CARD_TYPE_BELPIC, /* Belgian eID card specs. */
+ CARD_TYPE_STARCOS_32
}
card_type_t;
@@ -86,7 +88,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 */
}
@@ -123,17 +126,23 @@ static struct
CARD_TYPE_CARDOS_50 }, /* CardOS 5.0 */
{ 11, X("\x3b\xd2\x18\x00\x81\x31\xfe\x58\xc9\x03\x16"),
CARD_TYPE_CARDOS_53 }, /* CardOS 5.3 */
+ { 11, X("\x3b\xd2\x18\x00\x81\x31\xfe\x58\xc9\x04\x11"),
+ CARD_TYPE_CARDOS_54 }, /* CardOS 5.4 */
{ 24, X("\x3b\xfe\x18\x00\x00\x80\x31\xfe\x45\x53\x43\x45"
"\x36\x30\x2d\x43\x44\x30\x38\x31\x2d\x6e\x46\xa9"),
CARD_TYPE_AET },
+ { 25, X("\x3b\x9f\x96\x81\xb1\xfe\x45\x1f\x07\x00\x64\x05"
+ "\x1e\xb2\x00\x31\xb0\x73\x96\x21\xdb\x05\x90\x00\x5c"),
+ CARD_TYPE_STARCOS_32 },
{ 0 }
};
#undef X
-/* Macro to test for CardOS 5.0 and 5.3. */
+/* Macro to test for CardOS 5.0, 5.3 and 5.4. */
#define IS_CARDOS_5(a) ((a)->app_local->card_type == CARD_TYPE_CARDOS_50 \
- || (a)->app_local->card_type == CARD_TYPE_CARDOS_53)
+ || (a)->app_local->card_type == CARD_TYPE_CARDOS_53 \
+ || (a)->app_local->card_type == CARD_TYPE_CARDOS_54)
/* The default PKCS-15 home DF */
#define DEFAULT_HOME_DF 0x5015
@@ -147,6 +156,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
@@ -518,6 +532,8 @@ struct app_local_s
/*** Local prototypes. ***/
static gpg_error_t select_ef_by_path (app_t app, const unsigned short *path,
size_t pathlen);
+static gpg_error_t select_df_by_path (app_t app, const unsigned short *path,
+ size_t pathlen);
static gpg_error_t keygrip_from_prkdf (app_t app, prkdf_object_t prkdf);
static gpg_error_t readcert_by_cdf (app_t app, cdf_object_t cdf,
unsigned char **r_cert, size_t *r_certlen);
@@ -536,8 +552,10 @@ cardtype2str (card_type_t cardtype)
case CARD_TYPE_MICARDO: return "Micardo";
case CARD_TYPE_CARDOS_50: return "CardOS 5.0";
case CARD_TYPE_CARDOS_53: return "CardOS 5.3";
+ case CARD_TYPE_CARDOS_54: return "CardOS 5.4";
case CARD_TYPE_BELPIC: return "Belgian eID";
case CARD_TYPE_AET: return "AET";
+ case CARD_TYPE_STARCOS_32:return "STARCOS 3.2";
}
return "";
}
@@ -549,7 +567,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";
}
@@ -765,20 +784,28 @@ select_and_read_record (app_t app, unsigned short efid, int recno,
/* This function calls select file to read a file using a complete
- path which may or may not start at the master file (MF). */
+ * path which may or may not start at the master file (MF). If
+ * EXPECT_DF is set a directory or file is expected - otherwise an
+ * elementary file expected. */
static gpg_error_t
-select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
+select_by_path (app_t app, const unsigned short *path, size_t pathlen,
+ int expect_df)
{
gpg_error_t err;
int i, j;
+ int home_df_used = 0;
if (!pathlen)
return gpg_error (GPG_ERR_INV_VALUE);
- /* log_debug ("%s: path=", __func__); */
- /* for (j=0; j < pathlen; j++) */
- /* log_printf ("%s%04hX", j? "/":"", path[j]); */
- /* log_printf ("%s\n",app->app_local->direct_path_selection?" (direct)":"");*/
+ if (opt.debug)
+ {
+ log_debug ("%s: path=", __func__);
+ for (j=0; j < pathlen; j++)
+ log_printf ("%s%04hX", j? "/":"", path[j]);
+ log_printf ("%s\n",expect_df?" (DF requested)":"");
+ log_printf ("%s\n",app->app_local->direct_path_selection?" (direct)":"");
+ }
if (app->app_local->direct_path_selection)
{
@@ -791,34 +818,16 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
0);
}
else
- err = iso7816_select_path (app_get_slot (app), path, pathlen,
- app->app_local->home_df);
- if (err)
{
- log_error ("p15: error selecting path ");
- goto err_print_path;
+ home_df_used = 1;
+ err = iso7816_select_path (app_get_slot (app), path, pathlen,
+ app->app_local->home_df);
}
- }
- else if (pathlen > 1 && path[0] == 0x3fff)
- {
- err = iso7816_select_file (app_get_slot (app), 0x3f00, 0);
if (err)
{
- log_error ("p15: error selecting part %d from path ", 0);
+ log_error ("p15: error selecting path ");
goto err_print_path;
}
- path++;
- pathlen--;
- for (i=0; i < pathlen; i++)
- {
- err = iso7816_select_file (app_get_slot (app),
- path[i], (i+1 == pathlen)? 2 : 1);
- if (err)
- {
- log_error ("p15: error selecting part %d from path ", i);
- goto err_print_path;
- }
- }
}
else
{
@@ -829,7 +838,7 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
for (i=0; i < pathlen; i++)
{
err = iso7816_select_file (app_get_slot (app),
- path[i], !(i+1 == pathlen));
+ path[i], (expect_df || (i+1 < pathlen)));
if (err)
{
log_error ("p15: error selecting part %d from path ", i);
@@ -842,7 +851,7 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
err_print_path:
if (pathlen && *path != 0x3f00 )
log_printf ("3F00/");
- else
+ else if (home_df_used)
log_printf ("%04hX/", app->app_local->home_df);
for (j=0; j < pathlen; j++)
log_printf ("%s%04hX", j? "/":"", path[j]);
@@ -851,6 +860,20 @@ select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
}
+static gpg_error_t
+select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
+{
+ return select_by_path (app, path, pathlen, 0);
+}
+
+
+static gpg_error_t
+select_df_by_path (app_t app, const unsigned short *path, size_t pathlen)
+{
+ return select_by_path (app, path, pathlen, 1);
+}
+
+
/* Parse a cert Id string (or a key Id string) and return the binary
object Id string in a newly allocated buffer stored at R_OBJID and
R_OBJIDLEN. On Error NULL will be stored there and an error code
@@ -3245,7 +3268,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
if (aodf->max_length_valid)
log_printf (" max=%lu", aodf->max_length);
if (aodf->pad_char_valid)
- log_printf (" pad=0x%02x", aodf->pad_char);
+ log_printf (" pad=0x%02x", (unsigned char)aodf->pad_char);
log_info ("p15: flags=");
s = "";
@@ -3495,7 +3518,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);
@@ -3829,7 +3852,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;
}
@@ -5007,7 +5037,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
@@ -5023,6 +5053,13 @@ prepare_verify_pin (app_t app, const char *keyref,
log_error ("p15: error selecting D-TRUST's AID for key %s: %s\n",
keyref, gpg_strerror (err));
}
+ else if (prkdf && app->app_local->card_type == CARD_TYPE_STARCOS_32)
+ {
+ err = select_df_by_path (app, prkdf->path, prkdf->pathlen);
+ if (err)
+ log_error ("p15: error selecting file for key %s: %s\n",
+ keyref, gpg_strerror (err));
+ }
else if (prkdf)
{
/* Standard case: Select the key file. Note that this may
@@ -5258,7 +5295,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)
@@ -5622,7 +5660,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
@@ -5708,6 +5747,31 @@ 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. */
+ log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n");
+ 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];
@@ -5863,7 +5927,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
@@ -5880,6 +5944,22 @@ 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. */
+ log_info ("Note: ECC is not yet implemented for DTRUST 4 cards\n");
+ 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];
@@ -5923,7 +6003,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))
@@ -6186,6 +6267,13 @@ 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
does only allow for that. Many other cards supports this
@@ -6284,9 +6372,11 @@ app_select_p15 (app_t app)
{
case CARD_TYPE_CARDOS_50:
case CARD_TYPE_CARDOS_53:
+ case CARD_TYPE_CARDOS_54:
direct = 1;
break;
case CARD_TYPE_AET:
+ case CARD_TYPE_STARCOS_32:
app->app_local->no_extended_mode = 1;
break;
default: