- implemented change/unblock pin

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@244 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2002-02-26 16:34:29 +00:00
parent 4fa7283ae2
commit c58b72fc54
1 changed files with 83 additions and 0 deletions

View File

@ -915,6 +915,87 @@ gpk_verify(struct sc_card *card, unsigned int type, int ref,
return SC_ERROR_INVALID_ARGUMENTS;
}
/*
* Change secret code. This is used by reset_retry_counter and
* change_reference_data
*/
static int
gpk_set_secret_code(struct sc_card *card, unsigned int mode,
unsigned int type, int ref,
const u8 *puk, size_t puklen,
const u8 *pin, size_t pinlen,
int *tries_left)
{
struct sc_apdu apdu;
u8 data[8];
unsigned int n;
int r;
if (card->ctx->debug)
debug(card->ctx, "gpk_set_secret_code(mode=%d, ref=%d)\n",
mode, ref);
if (type != SC_AC_CHV || !puk || !puklen)
return SC_ERROR_INVALID_ARGUMENTS;
memset(&apdu, 0, sizeof(apdu));
apdu.cse = SC_APDU_CASE_3_SHORT;
apdu.cla = 0x80;
apdu.ins = 0x24;
apdu.p1 = mode;
apdu.p2 = ref & 7;
apdu.lc = 8;
apdu.data= data;
apdu.datalen = 8;
memset(data, 0, sizeof(data));
for (n = 0; n < 8 && n < puklen; n += 2)
data[n >> 1] = (puk[n] << 4) | (puk[n+1] & 0xf);
for (n = 0; n < 8 && n < pinlen; n += 2)
data[4 + (n >> 1)] = (pin[n] << 4) | (pin[n+1] & 0xf);
r = sc_transmit_apdu(card, &apdu);
SC_TEST_RET(card->ctx, r, "APDU transmit failed");
/* Special case: extract tries_left */
if (apdu.sw1 == 0x63 && (apdu.sw2 & 0xF0) == 0xC0) {
if (tries_left)
*tries_left = apdu.sw2 & 0xF;
return SC_ERROR_PIN_CODE_INCORRECT;
}
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
SC_TEST_RET(card->ctx, r, "Card returned error");
return r;
}
/*
* Unblock the CHV
*/
static int
gpk_reset_retry_counter(struct sc_card *card,
unsigned int type, int ref,
const u8 *puk, size_t puklen,
const u8 *pin, size_t pinlen)
{
return gpk_set_secret_code(card, 0x01, type, ref,
puk, puklen, pin, pinlen, NULL);
}
/*
* Change the PIN
*/
static int
gpk_change_reference_data(struct sc_card *card,
unsigned int type, int ref,
const u8 *puk, size_t puklen,
const u8 *pin, size_t pinlen,
int *tries_left)
{
return gpk_set_secret_code(card, 0x00, type, ref,
puk, puklen, pin, pinlen, tries_left);
}
/*
* Select a security environment (Set Crypto Context in GPK docs).
* When we get here, the PK file has already been selected.
@ -1405,6 +1486,8 @@ sc_get_driver()
gpk_ops.set_security_env= gpk_set_security_env;
gpk_ops.restore_security_env= gpk_restore_security_env;
gpk_ops.compute_signature= gpk_compute_signature;
gpk_ops.reset_retry_counter = gpk_reset_retry_counter;
gpk_ops.change_reference_data = gpk_change_reference_data;
}
return &gpk_drv;
}