summaryrefslogtreecommitdiffstats
path: root/scd
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2024-01-04 16:29:33 +0100
committerWerner Koch <wk@gnupg.org>2024-01-04 16:29:33 +0100
commit3f8cb9b33949494202fefaa8901ab252467cc1f1 (patch)
tree3af38e6e2a1694cb215aa19e4a006d982679e57a /scd
parentgpg: Choose key from inserted card over a non-inserted card (diff)
downloadgnupg2-3f8cb9b33949494202fefaa8901ab252467cc1f1.tar.xz
gnupg2-3f8cb9b33949494202fefaa8901ab252467cc1f1.zip
scd: Add support for SCE 7.0
* scd/app-common.h (CARDTYPE_SCE7): New. * scd/app.c (strcardtype): Support it. (atr_to_cardtype): New. (app_new_register): Try to get the cardtype from atr_to_cardtype. * scd/app-piv.c (app_select_piv): Tweak for SCE7. Add general method to construct a S/N from the Card UUID. -- The test cards I have are rsa2048 with X.509 certificates. I don't have the entire chain but loading the certificates work. For testing I created an OpenPGP key from the keys and tested signing and decryption. GnuPG-bug-id: 6919
Diffstat (limited to 'scd')
-rw-r--r--scd/app-common.h4
-rw-r--r--scd/app-piv.c56
-rw-r--r--scd/app.c53
3 files changed, 108 insertions, 5 deletions
diff --git a/scd/app-common.h b/scd/app-common.h
index 988cddf3f..f4035f766 100644
--- a/scd/app-common.h
+++ b/scd/app-common.h
@@ -56,8 +56,8 @@ typedef enum
CARDTYPE_GENERIC = 0,
CARDTYPE_GNUK,
CARDTYPE_YUBIKEY,
- CARDTYPE_ZEITCONTROL
-
+ CARDTYPE_ZEITCONTROL,
+ CARDTYPE_SCE7 /* G+D SmartCafe Expert 7.0 */
} cardtype_t;
/* List of supported card applications. The source code for each
diff --git a/scd/app-piv.c b/scd/app-piv.c
index c8ef7b43a..dc92bd2e2 100644
--- a/scd/app-piv.c
+++ b/scd/app-piv.c
@@ -1,5 +1,5 @@
/* app-piv.c - The OpenPGP card application.
- * Copyright (C) 2019, 2020 g10 Code GmbH
+ * Copyright (C) 2019, 2020, 2024 g10 Code GmbH
*
* This file is part of GnuPG.
*
@@ -3642,6 +3642,7 @@ app_select_piv (app_t app)
size_t aptlen;
const unsigned char *s;
size_t n;
+ void *relptr1 = NULL;
/* Note that we select using the AID without the 2 octet version
* number. This allows for better reporting of future specs. We
@@ -3667,7 +3668,21 @@ app_select_piv (app_t app)
s = find_tlv (apt, aptlen, 0x4F, &n);
/* Some cards (new Yubikey) return only the PIX, while others
- * (old Yubikey, PivApplet) return the RID+PIX. */
+ * (old Yubikey, PivApplet) return the RID+PIX.
+ * Sample APTs:
+ * Yubikey 5.4.3: 6111 4f06 000010000100 7907 4f05 a000000308
+ * SCE7.0-G-F-P : 610f 4f06 001000010000 7905 a000000308
+ */
+ if (app->card->cardtype == CARDTYPE_SCE7
+ && s && apt && aptlen == 17
+ && !memcmp (apt, ("\x61\x0f\x4f\x06\x00\x10\x00\x01"
+ "\x00\x00\x79\x05\xa0\x00\x00\x03\x08"), aptlen))
+ {
+ if (opt.verbose)
+ log_info ("piv: assuming G&D SCE7.0-G-F-P\n");
+ app->appversion = 0x0100; /* Let's assume this. */
+ goto apt_checked;
+ }
if (!s || !((n == 6 && !memcmp (s, piv_aid+5, 4))
|| (n == 11 && !memcmp (s, piv_aid, 9))))
{
@@ -3702,6 +3717,7 @@ app_select_piv (app_t app)
goto leave;
}
+ apt_checked:
app->app_local = xtrycalloc (1, sizeof *app->app_local);
if (!app->app_local)
{
@@ -3712,6 +3728,41 @@ app_select_piv (app_t app)
if (app->card->cardtype == CARDTYPE_YUBIKEY)
app->app_local->flags.yubikey = 1;
+ /* If we don't have a s/n construct it from the CHUID. */
+ if (!APP_CARD(app)->serialno)
+ {
+ unsigned char *chuid;
+ size_t chuidlen;
+
+ relptr1 = get_one_do (app, 0x5FC102, &chuid, &chuidlen, NULL);
+ if (!relptr1)
+ log_error ("piv: CHUID not found\n");
+ else
+ {
+ s = find_tlv (chuid, chuidlen, 0x34, &n);
+ if (!s || n != 16)
+ {
+ log_error ("piv: Card UUID %s in CHUID\n",
+ s? "invalid":"missing");
+ if (opt.debug && s)
+ log_printhex (s, n, "got");
+ }
+ else
+ {
+ APP_CARD(app)->serialno = xtrymalloc (n);
+ if (!APP_CARD(app)->serialno)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ memcpy (APP_CARD(app)->serialno, s, n);
+ APP_CARD(app)->serialnolen = n;
+ err = app_munge_serialno (APP_CARD(app));
+ if (err)
+ goto leave;
+ }
+ }
+ }
/* FIXME: Parse the optional and conditional DOs in the APT. */
@@ -3739,6 +3790,7 @@ app_select_piv (app_t app)
leave:
+ xfree (relptr1);
xfree (apt);
if (err)
do_deinit (app);
diff --git a/scd/app.c b/scd/app.c
index 3686c0f6c..2c92201cf 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -112,6 +112,7 @@ strcardtype (cardtype_t t)
case CARDTYPE_GNUK: return "gnuk";
case CARDTYPE_YUBIKEY: return "yubikey";
case CARDTYPE_ZEITCONTROL: return "zeitcontrol";
+ case CARDTYPE_SCE7: return "smartcafe";
}
return "?";
}
@@ -549,6 +550,51 @@ card_reset (card_t card)
return err;
}
+
+/* Return the card type from (ATR,ATRLEN) or CARDTYPE_GENERIC in case
+ * of error or if the ATR was not found. If ATR is NULL, SLOT is used
+ * to retrieve the ATR from the reader. */
+static cardtype_t
+atr_to_cardtype (int slot, const unsigned char *atr, size_t atrlen)
+{
+#define X(a) ((unsigned char const *)(a))
+ static struct
+ {
+ size_t atrlen;
+ unsigned char const *atr;
+ cardtype_t type;
+ } atrlist[] = {
+ { 19, X("\x3b\xf9\x96\x00\x00\x80\x31\xfe"
+ "\x45\x53\x43\x45\x37\x20\x0f\x00\x20\x46\x4e"),
+ CARDTYPE_SCE7 },
+ { 0 }
+ };
+#undef X
+ unsigned char *atrbuf = NULL;
+ cardtype_t cardtype = 0;
+ int i;
+
+ if (atr)
+ {
+ atrbuf = apdu_get_atr (slot, &atrlen);
+ if (!atrbuf)
+ return 0;
+ atr = atrbuf;
+ }
+
+ for (i=0; atrlist[i].atrlen; i++)
+ if (atrlist[i].atrlen == atrlen
+ && !memcmp (atrlist[i].atr, atr, atrlen))
+ {
+ cardtype = atrlist[i].type;
+ break;
+ }
+ xfree (atrbuf);
+ return cardtype;
+}
+
+
+
static gpg_error_t
app_new_register (int slot, ctrl_t ctrl, const char *name,
int periodical_check_needed)
@@ -666,13 +712,16 @@ app_new_register (int slot, ctrl_t ctrl, const char *name,
}
xfree (buf);
}
+ else
+ card->cardtype = atr_to_cardtype (slot, NULL, 0);
}
- else
+ else /* Got 3F00 */
{
unsigned char *atr;
size_t atrlen;
/* This is heuristics to identify different implementations. */
+ /* FIXME: The first two checks are pretty OpenPGP card specific. */
atr = apdu_get_atr (slot, &atrlen);
if (atr)
{
@@ -680,6 +729,8 @@ app_new_register (int slot, ctrl_t ctrl, const char *name,
card->cardtype = CARDTYPE_GNUK;
else if (atrlen == 21 && atr[7] == 0x75)
card->cardtype = CARDTYPE_ZEITCONTROL;
+ else
+ card->cardtype = atr_to_cardtype (slot, atr, atrlen);
xfree (atr);
}
}