Skip to content

Commit

Permalink
epass2003: Fix erase sequence.
Browse files Browse the repository at this point in the history
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:

#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.)
  • Loading branch information
Taylor R Campbell authored and frankmorgner committed Sep 23, 2020
1 parent 56acf7b commit 5a369a8
Showing 1 changed file with 37 additions and 1 deletion.
38 changes: 37 additions & 1 deletion src/libopensc/card-epass2003.c
Expand Up @@ -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);
Expand Down

0 comments on commit 5a369a8

Please sign in to comment.