epass2003: Fix erase sequence.
The previous erase sequence did not always work. For example: % pkcs15-init -C Using reader with a card: Feitian ePass2003 00 00 New User PIN. Please enter User PIN: 1234 Please type again to verify: 1234 Unblock Code for New User PIN (Optional - press return for no PIN). Please enter User unblocking PIN (PUK): Failed to create PKCS #15 meta structure: Security status not satisfied % pkcs15-init -E Using reader with a card: Feitian ePass2003 00 00 Failed to erase card: Security status not satisfied This apparently bricked many people's ePass2003 devices: https://github.com/OpenSC/OpenSC/issues/767 https://sourceforge.net/p/opensc/mailman/message/33621883/ https://github.com/OpenSC/OpenSC/wiki/Feitian-ePass2003 Feitian provided a proprietary binary blob called `FIX_TOOL' to recover devices from this state, but declined to offer source code when asked: https://download.ftsafe.com/files/ePass/Fix_Tool.tar.gz https://download.ftsafe.com/files/reader/SDK/Fix_Tool_20200604.zip With reverse-engineering help by Saleem Rashid (@saleemrashid on Github), I was able to find the sequence of three APDUs that the tool submits to the device to erase it. The mechanism seems to be: 1. Install a magic PIN. This is like install_secret_key, as used by internal_install_pin, but with a few different magic constants. 2. Verify the magic PIN. 3. Delete the MF file, without selecting anything first. With this patch, `pkcs15-init -E' successfully erases my ePass2003, and I am able to initialize it with `pkcs15-init -C -p pkcs15+onepin' if I set both a user pin and a PUK. (This patch does not prevent the ePass2003 from getting into the state which could not be erased by the old erase sequence.)
This commit is contained in:
parent
56acf7b445
commit
5a369a8f31
@ -2518,12 +2518,48 @@ epass2003_gen_key(struct sc_card *card, sc_epass2003_gen_key_data * data)
|
||||
static int
|
||||
epass2003_erase_card(struct sc_card *card)
|
||||
{
|
||||
static const unsigned char install_magic_pin[26] = {
|
||||
/* compare install_secret_key */
|
||||
0x06,0x01,0x10,0x16, 0x16,0x16,0x00,0x0f, 0xff,0x66,
|
||||
0x31,0x32,0x33,0x34, 0x35,0x36,0x37,0x38,
|
||||
0x31,0x32,0x33,0x34, 0x35,0x36,0x37,0x38,
|
||||
};
|
||||
static const unsigned char magic_pin[16] = "1234567812345678";
|
||||
static const unsigned char mf_path[2] = { 0x3f, 0x00 };
|
||||
sc_apdu_t apdu;
|
||||
int r;
|
||||
|
||||
LOG_FUNC_CALLED(card->ctx);
|
||||
sc_invalidate_cache(card);
|
||||
|
||||
r = sc_delete_file(card, sc_get_mf_path());
|
||||
/* install magic pin */
|
||||
sc_format_apdu(card, &apdu, 0x03, 0xe3, 0x00, 0x00);
|
||||
apdu.cla = 0x80;
|
||||
apdu.data = install_magic_pin;
|
||||
apdu.datalen = apdu.lc = sizeof(install_magic_pin);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU install magic pin failed");
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(card->ctx, r, "install magic pin failed");
|
||||
|
||||
/* verify magic pin */
|
||||
sc_format_apdu(card, &apdu, 0x03, 0x20, 0x00, 0x01);
|
||||
apdu.cla = 0;
|
||||
apdu.data = magic_pin;
|
||||
apdu.datalen = apdu.lc = sizeof(magic_pin);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU verify magic pin failed");
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(card->ctx, r, "verify magic pin failed");
|
||||
|
||||
/* delete MF */
|
||||
sc_format_apdu(card, &apdu, 0x03, 0xe4, 0x00, 0x00);
|
||||
apdu.cla = 0;
|
||||
apdu.data = mf_path;
|
||||
apdu.datalen = apdu.lc = sizeof(mf_path);
|
||||
r = sc_transmit_apdu(card, &apdu);
|
||||
LOG_TEST_RET(card->ctx, r, "APDU delete MF failed");
|
||||
r = sc_check_sw(card, apdu.sw1, apdu.sw2);
|
||||
LOG_TEST_RET(card->ctx, r, "delete MF failed");
|
||||
|
||||
LOG_FUNC_RETURN(card->ctx, r);
|
||||
|
Loading…
Reference in New Issue
Block a user