mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
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
This commit is contained in:
parent
4c04143d81
commit
3f8cb9b339
@ -392,7 +392,7 @@ int parse_compatibility_flags (const char *string, unsigned int *flagvar,
|
||||
/*-- Simple replacement functions. */
|
||||
|
||||
/* We use the gnupg_ttyname macro to be safe not to run into conflicts
|
||||
which an extisting but broken ttyname. */
|
||||
with an existing but broken ttyname. */
|
||||
#if !defined(HAVE_TTYNAME) || defined(HAVE_BROKEN_TTYNAME)
|
||||
# define gnupg_ttyname(n) _gnupg_ttyname ((n))
|
||||
/* Systems without ttyname (W32) will merely return NULL. */
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
53
scd/app.c
53
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 /* 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);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user