scd: Factor common PIN status check out.

* scd/iso7816.h (ISO7816_VERIFY_ERROR): New.
(ISO7816_VERIFY_NO_PIN): New.
(ISO7816_VERIFY_BLOCKED): New.
(ISO7816_VERIFY_NULLPIN): New.
(ISO7816_VERIFY_NOT_NEEDED): New.
* scd/iso7816.c (iso7816_verify_status): New.
* scd/app-nks.c (get_chv_status): Use new function.
--

Signed-off-by: Werner Koch <wk@gnupg.org>

Backported from master:
- Removed the non-existant app-piv.c patches.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-04-07 18:25:41 +02:00
parent 471b06e91b
commit 9497d25c56
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
4 changed files with 49 additions and 42 deletions

View File

@ -1164,7 +1164,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
by OpenPGP cards for the stored key creation time. A '-' means no
info available. The format is the usual ISO string are a number
with the seconds since Epoch.
*** MANUFACTORER <n> [<string>]
*** MANUFACTURER <n> [<string>]
This status returns the Manufactorer ID as the unsigned number N.
For OpenPGP this is weel defined; for other cards this is 0. The

View File

@ -248,53 +248,17 @@ keygripstr_from_pk_file (app_t app, int fid, char *r_gripstr)
/* TCOS responds to a verify with empty data (i.e. without the Lc
byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
true, the application is switched into SigG mode.
Returns:
-1 = Error retrieving the data,
-2 = No such PIN,
-3 = PIN blocked,
-4 = NullPIN activ,
n >= 0 = Number of verification attempts left. */
* byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
* true, the application is switched into SigG mode. Returns:
* ISO7816_VERIFY_* codes or non-negative number of verification
* attempts left. */
static int
get_chv_status (app_t app, int sigg, int pwid)
{
unsigned char *result = NULL;
size_t resultlen;
char command[4];
int rc;
if (switch_application (app, sigg))
return sigg? -2 : -1; /* No such PIN / General error. */
command[0] = 0x00;
command[1] = 0x20;
command[2] = 0x00;
command[3] = pwid;
if (apdu_send_direct (app->slot, 0, (unsigned char *)command,
4, 0, NULL, &result, &resultlen))
rc = -1; /* Error. */
else if (resultlen < 2)
rc = -1; /* Error. */
else
{
unsigned int sw = buf16_to_uint (result+resultlen-2);
if (sw == 0x6a88)
rc = -2; /* No such PIN. */
else if (sw == 0x6983)
rc = -3; /* PIN is blocked. */
else if (sw == 0x6985)
rc = -4; /* NullPIN is activ. */
else if ((sw & 0xfff0) == 0x63C0)
rc = (sw & 0x000f); /* PIN has N tries left. */
else
rc = -1; /* Other error. */
}
xfree (result);
return rc;
return iso7816_verify_status (app_get_slot (app), pwid);
}

View File

@ -315,6 +315,39 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
return map_sw (sw);
}
/* Some cards support a VERIFY command variant to check the status of
* the the CHV without a need to try a CHV. In contrast to the other
* functions this function returns the special codes ISO7816_VERIFY_*
* or a non-negative number with the left attempts. */
int
iso7816_verify_status (int slot, int chvno)
{
unsigned char apdu[4];
unsigned int sw;
int result;
apdu[0] = 0x00;
apdu[1] = ISO7816_VERIFY;
apdu[2] = 0x00;
apdu[3] = chvno;
if (!iso7816_apdu_direct (slot, apdu, 4, 0, &sw, NULL, NULL))
result = ISO7816_VERIFY_NOT_NEEDED; /* Not returned by all cards. */
else if (sw == 0x6a88 || sw == 0x6a80)
result = ISO7816_VERIFY_NO_PIN;
else if (sw == 0x6983)
result = ISO7816_VERIFY_BLOCKED;
else if (sw == 0x6985)
result = ISO7816_VERIFY_NULLPIN; /* TCOS card */
else if ((sw & 0xfff0) == 0x63C0)
result = (sw & 0x000f);
else
result = ISO7816_VERIFY_ERROR;
return result;
}
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
verification vector CHVNO. With PININFO non-NULL the pinpad of the
reader will be used. If IS_EXCHANGE is 0, a "change reference

View File

@ -29,6 +29,15 @@
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
#define ISO7816_RESET_RETRY_COUNTER 0x2C
/* Error codes returned by iso7816_verify_status. A non-negative
* number gives the number of left tries.
* NB: The values are also used by the CHV-STATUS lines and thus are
* part of the public interface. Do not change them. */
#define ISO7816_VERIFY_ERROR (-1)
#define ISO7816_VERIFY_NO_PIN (-2)
#define ISO7816_VERIFY_BLOCKED (-3)
#define ISO7816_VERIFY_NULLPIN (-4)
#define ISO7816_VERIFY_NOT_NEEDED (-5)
/* Information to be passed to pinpad equipped readers. See
ccid-driver.c for details. */
@ -71,6 +80,7 @@ gpg_error_t iso7816_check_pinpad (int slot, int command,
gpg_error_t iso7816_verify (int slot,
int chvno, const char *chv, size_t chvlen);
gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
int iso7816_verify_status (int slot, int chvno);
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
const char *oldchv, size_t oldchvlen,
const char *newchv, size_t newchvlen);