mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
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. * scd/app-piv.c (get_chv_status): Ditto. (verify_chv): Ditto. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
5ec1f66793
commit
60d018f6a9
@ -1171,7 +1171,7 @@ pkd:0:1024:B665B1435F4C2 .... FF26ABB:
|
|||||||
by OpenPGP cards for the stored key creation time. A '-' means no
|
by OpenPGP cards for the stored key creation time. A '-' means no
|
||||||
info available. The format is the usual ISO string are a number
|
info available. The format is the usual ISO string are a number
|
||||||
with the seconds since Epoch.
|
with the seconds since Epoch.
|
||||||
*** MANUFACTORER <n> [<string>]
|
*** MANUFACTURER <n> [<string>]
|
||||||
|
|
||||||
This status returns the Manufactorer ID as the unsigned number N.
|
This status returns the Manufactorer ID as the unsigned number N.
|
||||||
For OpenPGP this is weel defined; for other cards this is 0. The
|
For OpenPGP this is weel defined; for other cards this is 0. The
|
||||||
|
@ -249,53 +249,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
|
/* 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
|
* byte) with the status of the PIN. PWID is the PIN ID, If SIGG is
|
||||||
true, the application is switched into SigG mode.
|
* true, the application is switched into SigG mode. Returns:
|
||||||
Returns:
|
* ISO7816_VERIFY_* codes or non-negative number of verification
|
||||||
-1 = Error retrieving the data,
|
* attempts left. */
|
||||||
-2 = No such PIN,
|
|
||||||
-3 = PIN blocked,
|
|
||||||
-4 = NullPIN active,
|
|
||||||
n >= 0 = Number of verification attempts left. */
|
|
||||||
static int
|
static int
|
||||||
get_chv_status (app_t app, int sigg, int pwid)
|
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))
|
if (switch_application (app, sigg))
|
||||||
return sigg? -2 : -1; /* No such PIN / General error. */
|
return sigg? -2 : -1; /* No such PIN / General error. */
|
||||||
|
|
||||||
command[0] = 0x00;
|
return iso7816_verify_status (app_get_slot (app), pwid);
|
||||||
command[1] = 0x20;
|
|
||||||
command[2] = 0x00;
|
|
||||||
command[3] = pwid;
|
|
||||||
|
|
||||||
if (apdu_send_direct (app_get_slot (app), 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 active. */
|
|
||||||
else if ((sw & 0xfff0) == 0x63C0)
|
|
||||||
rc = (sw & 0x000f); /* PIN has N tries left. */
|
|
||||||
else
|
|
||||||
rc = -1; /* Other error. */
|
|
||||||
}
|
|
||||||
xfree (result);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -780,42 +780,17 @@ get_dispserialno (app_t app, int failmode)
|
|||||||
|
|
||||||
/* The verify command can be used to retrieve the security status of
|
/* The verify command can be used to retrieve the security status of
|
||||||
* the card. Given the PIN name (e.g. "PIV.80" for the application
|
* the card. Given the PIN name (e.g. "PIV.80" for the application
|
||||||
* pin, a status is returned:
|
* pin, a ISO7817_VERIFY_* code is returned or a non-negative number
|
||||||
*
|
* of verification attempts left. */
|
||||||
* -1 = Error retrieving the data,
|
|
||||||
* -2 = No such PIN,
|
|
||||||
* -3 = PIN blocked,
|
|
||||||
* -5 = Verified and still valid,
|
|
||||||
* n >= 0 = Number of verification attempts left.
|
|
||||||
*/
|
|
||||||
static int
|
static int
|
||||||
get_chv_status (app_t app, const char *keyrefstr)
|
get_chv_status (app_t app, const char *keyrefstr)
|
||||||
{
|
{
|
||||||
unsigned char apdu[4];
|
|
||||||
unsigned int sw;
|
|
||||||
int result;
|
|
||||||
int keyref;
|
int keyref;
|
||||||
|
|
||||||
keyref = parse_chv_keyref (keyrefstr);
|
keyref = parse_chv_keyref (keyrefstr);
|
||||||
if (!keyrefstr)
|
if (!keyrefstr)
|
||||||
return -1;
|
return ISO7816_VERIFY_ERROR;
|
||||||
|
return iso7816_verify_status (app_get_slot (app), keyref);
|
||||||
apdu[0] = 0x00;
|
|
||||||
apdu[1] = ISO7816_VERIFY;
|
|
||||||
apdu[2] = 0x00;
|
|
||||||
apdu[3] = keyref;
|
|
||||||
if (!iso7816_apdu_direct (app_get_slot (app), apdu, 4, 0, &sw, NULL, NULL))
|
|
||||||
result = -5; /* No need to verification. */
|
|
||||||
else if (sw == 0x6a88 || sw == 0x6a80)
|
|
||||||
result = -2; /* No such PIN. */
|
|
||||||
else if (sw == 0x6983)
|
|
||||||
result = -3; /* PIN is blocked. */
|
|
||||||
else if ((sw & 0xfff0) == 0x63C0)
|
|
||||||
result = (sw & 0x000f);
|
|
||||||
else
|
|
||||||
result = -1; /* Error. */
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1999,29 +1974,22 @@ verify_chv (app_t app, ctrl_t ctrl, int keyref, int force,
|
|||||||
gpg_error_t (*pincb)(void*,const char *,char **), void *pincb_arg)
|
gpg_error_t (*pincb)(void*,const char *,char **), void *pincb_arg)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char apdu[4];
|
|
||||||
unsigned int sw;
|
|
||||||
int remaining;
|
int remaining;
|
||||||
char *pin = NULL;
|
char *pin = NULL;
|
||||||
unsigned int pinlen, unpaddedpinlen;
|
unsigned int pinlen, unpaddedpinlen;
|
||||||
|
|
||||||
/* First check whether a verify is at all needed. This is done with
|
/* First check whether a verify is at all needed. */
|
||||||
* P1 being 0 and no Lc and command data send. */
|
remaining = iso7816_verify_status (app_get_slot (app), keyref);
|
||||||
apdu[0] = 0x00;
|
if (remaining == ISO7816_VERIFY_NOT_NEEDED)
|
||||||
apdu[1] = ISO7816_VERIFY;
|
|
||||||
apdu[2] = 0x00;
|
|
||||||
apdu[3] = keyref;
|
|
||||||
if (!iso7816_apdu_direct (app_get_slot (app), apdu, 4, 0, &sw, NULL, NULL))
|
|
||||||
{
|
{
|
||||||
if (!force) /* No need to verification. */
|
if (!force) /* No need to verification. */
|
||||||
return 0; /* All fine. */
|
return 0; /* All fine. */
|
||||||
remaining = -1;
|
remaining = -1;
|
||||||
}
|
}
|
||||||
else if ((sw & 0xfff0) == 0x63C0)
|
else if (remaining < 0) /* We don't care about other errors. */
|
||||||
remaining = (sw & 0x000f); /* PIN has REMAINING tries left. */
|
|
||||||
else
|
|
||||||
remaining = -1;
|
remaining = -1;
|
||||||
|
|
||||||
|
|
||||||
err = ask_and_prepare_chv (app, ctrl, keyref, 0, remaining, force,
|
err = ask_and_prepare_chv (app, ctrl, keyref, 0, remaining, force,
|
||||||
pincb, pincb_arg,
|
pincb, pincb_arg,
|
||||||
&pin, &pinlen, &unpaddedpinlen);
|
&pin, &pinlen, &unpaddedpinlen);
|
||||||
|
@ -339,6 +339,39 @@ iso7816_verify (int slot, int chvno, const char *chv, size_t chvlen)
|
|||||||
return map_sw (sw);
|
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
|
/* Perform a CHANGE_REFERENCE_DATA command on SLOT for the card holder
|
||||||
verification vector CHVNO. With PININFO non-NULL the pinpad of the
|
verification vector CHVNO. With PININFO non-NULL the pinpad of the
|
||||||
reader will be used. If IS_EXCHANGE is 0, a "change reference
|
reader will be used. If IS_EXCHANGE is 0, a "change reference
|
||||||
|
@ -29,6 +29,15 @@
|
|||||||
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
|
#define ISO7816_CHANGE_REFERENCE_DATA 0x24
|
||||||
#define ISO7816_RESET_RETRY_COUNTER 0x2C
|
#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
|
/* Information to be passed to pinpad equipped readers. See
|
||||||
ccid-driver.c for details. */
|
ccid-driver.c for details. */
|
||||||
@ -76,6 +85,7 @@ gpg_error_t iso7816_check_pinpad (int slot, int command,
|
|||||||
gpg_error_t iso7816_verify (int slot,
|
gpg_error_t iso7816_verify (int slot,
|
||||||
int chvno, const char *chv, size_t chvlen);
|
int chvno, const char *chv, size_t chvlen);
|
||||||
gpg_error_t iso7816_verify_kp (int slot, int chvno, pininfo_t *pininfo);
|
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,
|
gpg_error_t iso7816_change_reference_data (int slot, int chvno,
|
||||||
const char *oldchv, size_t oldchvlen,
|
const char *oldchv, size_t oldchvlen,
|
||||||
const char *newchv, size_t newchvlen);
|
const char *newchv, size_t newchvlen);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user