mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-23 10:29:58 +01:00
scd:nks: Add framework to support IDKey cards.
* scd/app-nks.c (NKS_APP_IDLM): New. (struct app_local_s): Replace NKS_VERSION by the global APPVERSION. (do_learn_status): Always send CHV-STATUS. (find_fid_by_keyref): Basic support for IDLM only use. (do_learn_status_core): Ditto. (do_readcert): Ditto. (verify_pin): Ditto. (parse_pwidstr): Ditto. (do_with_keygrip): Ditto. (switch_application): Ditto. (app_select_nks): Fallback to IDLM. -- Backported-from-master: 1f6a39092fe4b5f02bc4741a0a23d102d30f4063 GnuPG-bug-id: 6252 Also not directly required for the Signature Card 2.0, it is easier to port this patch as well.
This commit is contained in:
parent
a83281176c
commit
60ba61e78e
141
scd/app-nks.c
141
scd/app-nks.c
@ -88,11 +88,14 @@ static char const aid_nks[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x01, 0x02 };
|
||||
static char const aid_sigg[] = { 0xD2, 0x76, 0x00, 0x00, 0x66, 0x01 };
|
||||
static char const aid_esign[] =
|
||||
{ 0xA0, 0x00, 0x00, 0x01, 0x67, 0x45, 0x53, 0x49, 0x47, 0x4E };
|
||||
static char const aid_idlm[] = { 0xD2, 0x76, 0x00, 0x00, 0x03, 0x0c, 0x01 };
|
||||
|
||||
/* The 3 ids of the different apps on our Netkey cards. */
|
||||
|
||||
/* The ids of the different apps on our TCOS cards. */
|
||||
#define NKS_APP_NKS 0
|
||||
#define NKS_APP_SIGG 1
|
||||
#define NKS_APP_ESIGN 2
|
||||
#define NKS_APP_IDLM 3
|
||||
|
||||
|
||||
static struct
|
||||
@ -156,6 +159,14 @@ static struct
|
||||
{ 2, 0xC000, 15,101 }, /* EF.C.SCA.QES (SubCA) */
|
||||
{ 2, 0xC001, 15,100 }, /* EF.C.ICC.QES (Cert) */
|
||||
{ 2, 0xC00E, 15,111 }, /* EF.C.RCA.QES (RootCA */
|
||||
|
||||
{ 3, 0x4E03, 3, 100 }, /* EK_PK_03 */
|
||||
{ 3, 0x4E04, 3, 100 }, /* EK_PK_04 */
|
||||
{ 3, 0x4E05, 3, 100 }, /* EK_PK_05 */
|
||||
{ 3, 0x4E06, 3, 100 }, /* EK_PK_06 */
|
||||
{ 3, 0x4E07, 3, 100 }, /* EK_PK_07 */
|
||||
{ 3, 0x4E08, 3, 100 }, /* EK_PK_08 */
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -172,10 +183,9 @@ struct fid_cache_s {
|
||||
|
||||
/* Object with application (i.e. NKS) specific data. */
|
||||
struct app_local_s {
|
||||
int nks_version; /* NKS version. */
|
||||
|
||||
int active_nks_app; /* One of the NKS_APP_ constants. */
|
||||
|
||||
int only_idlm; /* The application is fixed to IDLM (IDKey card). */
|
||||
int qes_app_id; /* Either NKS_APP_SIGG or NKS_APP_ESIGN. */
|
||||
|
||||
int sigg_msig_checked;/* True if we checked for a mass signature card. */
|
||||
@ -274,7 +284,7 @@ keygripstr_from_pk_file (app_t app, int pkfid, int cfid, char *r_gripstr,
|
||||
return 0; /* Found in cache. */
|
||||
}
|
||||
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
{
|
||||
/* Signature Card v2 - get keygrip from the certificate. */
|
||||
unsigned char *cert, *pk;
|
||||
@ -321,7 +331,7 @@ keygripstr_from_pk_file (app_t app, int pkfid, int cfid, char *r_gripstr,
|
||||
return err;
|
||||
}
|
||||
|
||||
if (app->app_local->nks_version < 3)
|
||||
if (app->appversion < 3)
|
||||
{
|
||||
/* Old versions of NKS store the values in a TLV encoded format.
|
||||
We need to do some checks. */
|
||||
@ -484,6 +494,14 @@ find_fid_by_keyref (app_t app, const char *keyref, int *r_idx, int *r_algo)
|
||||
{
|
||||
if (!filelist[idx].iskeypair)
|
||||
continue;
|
||||
|
||||
if (app->app_local->only_idlm)
|
||||
{
|
||||
if (filelist[idx].nks_app_id != NKS_APP_IDLM)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filelist[idx].nks_app_id != NKS_APP_NKS
|
||||
&& filelist[idx].nks_app_id != app->app_local->qes_app_id)
|
||||
continue;
|
||||
@ -491,6 +509,7 @@ find_fid_by_keyref (app_t app, const char *keyref, int *r_idx, int *r_algo)
|
||||
err = switch_application (app, filelist[idx].nks_app_id);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = keygripstr_from_pk_file (app, filelist[idx].fid,
|
||||
filelist[idx].iskeypair,
|
||||
@ -525,6 +544,8 @@ find_fid_by_keyref (app_t app, const char *keyref, int *r_idx, int *r_algo)
|
||||
else if (!ascii_strncasecmp (keyref, "NKS-SIGG.", 9)
|
||||
&& app->app_local->qes_app_id == NKS_APP_SIGG)
|
||||
nks_app_id = NKS_APP_SIGG;
|
||||
else if (!ascii_strncasecmp (keyref, "NKS-IDLM.", 9))
|
||||
nks_app_id = NKS_APP_IDLM;
|
||||
else if (!ascii_strncasecmp (keyref, "NKS-DF01.", 9))
|
||||
nks_app_id = NKS_APP_NKS;
|
||||
else
|
||||
@ -602,7 +623,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||
{ "$AUTHKEYID", 1 },
|
||||
{ "$ENCRKEYID", 2 },
|
||||
{ "$SIGNKEYID", 3 },
|
||||
{ "NKS-VERSION", 4 },
|
||||
{ "NKS-VERSION", 4 }, /* Legacy (printed decimal) */
|
||||
{ "CHV-STATUS", 5 },
|
||||
{ "$DISPSERIALNO",6 },
|
||||
{ "SERIALNO", 0 }
|
||||
@ -611,7 +632,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||
int idx;
|
||||
char *p, *p2;
|
||||
char buffer[100];
|
||||
int nksver = app->app_local->nks_version;
|
||||
int nksver = app->appversion;
|
||||
|
||||
err = switch_application (app, NKS_APP_NKS);
|
||||
if (err)
|
||||
@ -664,7 +685,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||
break;
|
||||
|
||||
case 4: /* NKS-VERSION */
|
||||
snprintf (buffer, sizeof buffer, "%d", app->app_local->nks_version);
|
||||
snprintf (buffer, sizeof buffer, "%d", app->appversion);
|
||||
send_status_info (ctrl, table[idx].name,
|
||||
buffer, strlen (buffer), NULL, 0);
|
||||
break;
|
||||
@ -688,7 +709,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||
|
||||
/* We use a helper array so that we can control that there is
|
||||
* no superfluous application switches. */
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
{
|
||||
tmp[0] = get_chv_status (app, 0, 0x03);
|
||||
tmp[1] = get_chv_status (app, 0, 0x04);
|
||||
@ -699,7 +720,7 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||
tmp[1] = get_chv_status (app, 0, 0x01);
|
||||
}
|
||||
tmp[2] = get_chv_status (app, app->app_local->qes_app_id, 0x81);
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
tmp[3] = get_chv_status (app, app->app_local->qes_app_id, 0x82);
|
||||
else
|
||||
tmp[3] = get_chv_status (app, app->app_local->qes_app_id, 0x83);
|
||||
@ -747,7 +768,9 @@ do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
|
||||
tag = "ESIGN";
|
||||
else if (nks_app_id == NKS_APP_SIGG)
|
||||
tag = "SIGG";
|
||||
else if (app->app_local->nks_version < 3)
|
||||
else if (nks_app_id == NKS_APP_IDLM)
|
||||
tag = "IDLM";
|
||||
else if (app->appversion < 3)
|
||||
tag = "DF01";
|
||||
else
|
||||
tag = "NKS3";
|
||||
@ -755,7 +778,7 @@ do_learn_status_core (app_t app, ctrl_t ctrl, unsigned int flags,
|
||||
/* Output information about all useful objects in the NKS application. */
|
||||
for (i=0; filelist[i].fid; i++)
|
||||
{
|
||||
if (filelist[i].nks_ver > app->app_local->nks_version)
|
||||
if (filelist[i].nks_ver > app->appversion)
|
||||
continue;
|
||||
|
||||
if (filelist[i].nks_app_id != nks_app_id)
|
||||
@ -819,11 +842,16 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
do_getattr (app, ctrl, "CHV-STATUS");
|
||||
|
||||
err = switch_application (app, NKS_APP_NKS);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
do_learn_status_core (app, ctrl, flags, NKS_APP_NKS);
|
||||
do_learn_status_core (app, ctrl, flags, app->app_local->active_nks_app);
|
||||
|
||||
if (app->app_local->only_idlm)
|
||||
return 0; /* ready. */
|
||||
|
||||
err = switch_application (app, app->app_local->qes_app_id);
|
||||
if (err)
|
||||
@ -960,6 +988,8 @@ do_readcert (app_t app, const char *certid,
|
||||
nks_app_id = NKS_APP_SIGG;
|
||||
else if (!strncmp (certid, "NKS-DF01.", 9))
|
||||
nks_app_id = NKS_APP_NKS;
|
||||
else if (!strncmp (certid, "NKS-IDLM.", 9))
|
||||
nks_app_id = NKS_APP_IDLM;
|
||||
else
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
certid += nks_app_id == NKS_APP_ESIGN? 10 : 9;
|
||||
@ -1015,7 +1045,7 @@ do_readkey (app_t app, ctrl_t ctrl, const char *keyid, unsigned int flags,
|
||||
return GPG_ERR_NOT_SUPPORTED;
|
||||
|
||||
/* We use a generic name to retrieve PK.AUT.IFD-SPK. */
|
||||
if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
|
||||
if (!strcmp (keyid, "$IFDAUTHKEY") && app->appversion >= 3)
|
||||
;
|
||||
else /* Return the error code expected by cmd_readkey. */
|
||||
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||
@ -1081,7 +1111,7 @@ do_writekey (app_t app, ctrl_t ctrl,
|
||||
(void)pincb;
|
||||
(void)pincb_arg;
|
||||
|
||||
if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
|
||||
if (!strcmp (keyid, "$IFDAUTHKEY") && app->appversion >= 3)
|
||||
;
|
||||
else
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
@ -1241,7 +1271,7 @@ verify_pin (app_t app, int pwid, const char *desc,
|
||||
pininfo.fixedlen = -1;
|
||||
|
||||
/* FIXME: TCOS allows to read the min. and max. values - do this. */
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
{
|
||||
if (app->app_local->active_nks_app == NKS_APP_NKS && pwid == 0x03)
|
||||
pininfo.minlen = 6;
|
||||
@ -1251,6 +1281,14 @@ verify_pin (app_t app, int pwid, const char *desc,
|
||||
pininfo.minlen = 8;
|
||||
pininfo.maxlen = 24;
|
||||
}
|
||||
else if (app->app_local->active_nks_app == NKS_APP_IDLM)
|
||||
{
|
||||
if (pwid == 0x00)
|
||||
pininfo.minlen = 6;
|
||||
else
|
||||
pininfo.minlen = 8;
|
||||
pininfo.maxlen = 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For NKS3 we used these fixed values; let's keep this. */
|
||||
@ -1378,7 +1416,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
kid = filelist[idx].kid;
|
||||
|
||||
/* Prepare the DER object from INDATA. */
|
||||
if (app->app_local->nks_version > 2 && (indatalen == 35
|
||||
if (app->appversion > 2 && (indatalen == 35
|
||||
|| indatalen == 47
|
||||
|| indatalen == 51
|
||||
|| indatalen == 67
|
||||
@ -1419,7 +1457,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
|
||||
|
||||
/* Send an MSE for PSO:Computer_Signature. */
|
||||
if (app->app_local->nks_version > 2)
|
||||
if (app->appversion > 2)
|
||||
{
|
||||
unsigned char mse[6];
|
||||
|
||||
@ -1434,7 +1472,7 @@ do_sign (app_t app, ctrl_t ctrl, const char *keyidstr, int hashalgo,
|
||||
}
|
||||
|
||||
/* We use the Global PIN 1 */
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
pwid = 0x03;
|
||||
else
|
||||
pwid = 0x00;
|
||||
@ -1484,7 +1522,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
||||
|
||||
kid = filelist[idx].kid;
|
||||
|
||||
if (app->app_local->nks_version <= 2)
|
||||
if (app->appversion <= 2)
|
||||
{
|
||||
static const unsigned char mse[] =
|
||||
{
|
||||
@ -1528,7 +1566,7 @@ do_decipher (app_t app, ctrl_t ctrl, const char *keyidstr,
|
||||
}
|
||||
|
||||
/* We use the Global PIN 1 */
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
pwid = 0x03;
|
||||
else
|
||||
pwid = 0x00;
|
||||
@ -1579,7 +1617,7 @@ parse_pwidstr (app_t app, const char *pwidstr, int new_mode,
|
||||
int *r_nks_app_id, int *r_pwid)
|
||||
{
|
||||
const char *desc;
|
||||
int nks15 = app->app_local->nks_version == 15;
|
||||
int nks15 = app->appversion == 15;
|
||||
|
||||
if (!pwidstr)
|
||||
desc = NULL;
|
||||
@ -1603,7 +1641,7 @@ parse_pwidstr (app_t app, const char *pwidstr, int new_mode,
|
||||
: _("|P|Please enter the PIN Unblocking Code (PUK) "
|
||||
"for the standard keys."));
|
||||
}
|
||||
else if (!strcmp (pwidstr, "PW1.CH.SIG"))
|
||||
else if (!strcmp (pwidstr, "PW1.CH.SIG") && !app->app_local->only_idlm)
|
||||
{
|
||||
*r_nks_app_id = app->app_local->qes_app_id;
|
||||
*r_pwid = 0x81;
|
||||
@ -1613,7 +1651,7 @@ parse_pwidstr (app_t app, const char *pwidstr, int new_mode,
|
||||
: _("||Please enter the PIN for the key to create "
|
||||
"qualified signatures."));
|
||||
}
|
||||
else if (!strcmp (pwidstr, "PW2.CH.SIG"))
|
||||
else if (!strcmp (pwidstr, "PW2.CH.SIG") && !app->app_local->only_idlm)
|
||||
{
|
||||
*r_nks_app_id = app->app_local->qes_app_id;
|
||||
*r_pwid = nks15? 0x82 : 0x83;
|
||||
@ -1653,6 +1691,16 @@ parse_pwidstr (app_t app, const char *pwidstr, int new_mode,
|
||||
? "|N|Please enter a new PIN for the given ESIGN pwid"
|
||||
: "||Please enter the PIN for the given ESIGN pwid" );
|
||||
}
|
||||
else if (!strncmp (pwidstr, "IDLM.0x", 7)
|
||||
&& hexdigitp (pwidstr+7) && hexdigitp (pwidstr+8) && !pwidstr[9])
|
||||
{
|
||||
/* Hack to help debugging. */
|
||||
*r_nks_app_id = NKS_APP_IDLM;
|
||||
*r_pwid = xtoi_2 (pwidstr+7);
|
||||
desc = (new_mode
|
||||
? "|N|Please enter a new PIN for the given IDLM pwid"
|
||||
: "||Please enter the PIN for the given IDLM pwid" );
|
||||
}
|
||||
else
|
||||
{
|
||||
*r_pwid = 0; /* Only to avoid gcc warning in calling function. */
|
||||
@ -1721,7 +1769,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *pwidstr,
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
if (app->app_local->nks_version == 15)
|
||||
if (app->appversion == 15)
|
||||
{
|
||||
memset (oldpin, '0', 5);
|
||||
oldpinlen = 5; /* 5 ascii zeroes. */
|
||||
@ -1891,19 +1939,26 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
|
||||
|
||||
for (idx=0; filelist[idx].fid; idx++)
|
||||
{
|
||||
if (filelist[idx].nks_ver > app->app_local->nks_version)
|
||||
if (filelist[idx].nks_ver > app->appversion)
|
||||
continue;
|
||||
|
||||
if (!filelist[idx].iskeypair)
|
||||
continue;
|
||||
|
||||
if (app->app_local->only_idlm)
|
||||
{
|
||||
if (filelist[idx].nks_app_id != NKS_APP_IDLM)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filelist[idx].nks_app_id != NKS_APP_NKS
|
||||
&& filelist[idx].nks_app_id != app->app_local->qes_app_id)
|
||||
continue;
|
||||
|
||||
err = switch_application (app, filelist[idx].nks_app_id);
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = keygripstr_from_pk_file (app, filelist[idx].fid,
|
||||
filelist[idx].iskeypair, keygripstr, NULL);
|
||||
@ -1944,7 +1999,9 @@ do_with_keygrip (app_t app, ctrl_t ctrl, int action,
|
||||
tagstr = "ESIGN";
|
||||
else if (app->app_local->active_nks_app == NKS_APP_SIGG)
|
||||
tagstr = "SIGG";
|
||||
else if (app->app_local->nks_version < 3)
|
||||
else if (app->app_local->active_nks_app == NKS_APP_IDLM)
|
||||
tagstr = "IDLM";
|
||||
else if (app->appversion < 3)
|
||||
tagstr = "DF01";
|
||||
else
|
||||
tagstr = "NKS3";
|
||||
@ -2003,7 +2060,7 @@ get_nks_version (int slot)
|
||||
* vendor 4 := Philips
|
||||
* 5 := Infinion
|
||||
* card type 3 := TCOS 3
|
||||
* 15 := TCOS Signature Card
|
||||
* 15 := TCOS Signature Card (bb,cc is the ROM mask version)
|
||||
* Completion code version number Bit 7..5 := pre-completion code version
|
||||
* Bit 4..0 := completion code version
|
||||
* (pre-completion by chip vendor)
|
||||
@ -2014,7 +2071,6 @@ get_nks_version (int slot)
|
||||
else
|
||||
type = result[8];
|
||||
xfree (result);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@ -2026,6 +2082,8 @@ switch_application (app_t app, int nks_app_id)
|
||||
{
|
||||
gpg_error_t err;
|
||||
|
||||
if (app->app_local->only_idlm)
|
||||
return 0; /* No switching at all */
|
||||
if (app->app_local->active_nks_app == nks_app_id
|
||||
&& !app->app_local->need_app_select)
|
||||
return 0; /* Already switched. */
|
||||
@ -2044,7 +2102,7 @@ switch_application (app_t app, int nks_app_id)
|
||||
err = iso7816_select_application (app->slot, aid_nks, sizeof aid_nks, 0);
|
||||
|
||||
if (!err && nks_app_id == NKS_APP_SIGG
|
||||
&& app->app_local->nks_version >= 3
|
||||
&& app->appversion >= 3
|
||||
&& !app->app_local->sigg_msig_checked)
|
||||
{
|
||||
/* Check whether this card is a mass signature card. */
|
||||
@ -2093,8 +2151,14 @@ app_select_nks (app_t app)
|
||||
{
|
||||
int slot = app->slot;
|
||||
int rc;
|
||||
int is_idlm = 0;
|
||||
|
||||
rc = iso7816_select_application (slot, aid_nks, sizeof aid_nks, 0);
|
||||
if (rc)
|
||||
{
|
||||
is_idlm = 1;
|
||||
rc = iso7816_select_application (slot, aid_idlm, sizeof aid_idlm, 0);
|
||||
}
|
||||
if (!rc)
|
||||
{
|
||||
app->apptype = APPTYPE_NKS;
|
||||
@ -2106,10 +2170,19 @@ app_select_nks (app_t app)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
app->app_local->nks_version = get_nks_version (slot);
|
||||
app->appversion = get_nks_version (slot);
|
||||
app->app_local->only_idlm = is_idlm;
|
||||
if (is_idlm) /* Set it once, there won't be any switching. */
|
||||
app->app_local->active_nks_app = NKS_APP_IDLM;
|
||||
|
||||
if (opt.verbose)
|
||||
log_info ("Detected NKS version: %d\n", app->app_local->nks_version);
|
||||
if (app->app_local->nks_version == 15)
|
||||
{
|
||||
log_info ("Detected NKS version: %d\n", app->appversion);
|
||||
if (is_idlm)
|
||||
log_info ("Using only the IDLM application\n");
|
||||
}
|
||||
|
||||
if (app->appversion == 15)
|
||||
app->app_local->qes_app_id = NKS_APP_ESIGN;
|
||||
else
|
||||
app->app_local->qes_app_id = NKS_APP_SIGG;
|
||||
|
Loading…
x
Reference in New Issue
Block a user