From 6d138f0199575516bfaad18cbbafcfa2ee61e58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?= Date: Mon, 4 Mar 2013 11:28:08 +0700 Subject: [PATCH 05/26] OpenPGP: Support erasing (reset) card. Command: openpgp-tool --erase --- src/libopensc/card-openpgp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ src/tools/openpgp-tool.c | 22 ++++++++++++++- 2 files changed, 85 insertions(+), 1 deletion(-) Index: opensc-20150513/src/libopensc/card-openpgp.c =================================================================== --- opensc-20150513.orig/src/libopensc/card-openpgp.c +++ opensc-20150513/src/libopensc/card-openpgp.c @@ -2206,6 +2206,66 @@ out: #endif /* ENABLE_OPENSSL */ +/** + * Erase card + **/ +static int pgp_erase_card(sc_card_t *card) +{ + sc_context_t *ctx = card->ctx; + u8 *apdustring[10] = { + "00:20:00:81:08:40:40:40:40:40:40:40:40", + "00:20:00:81:08:40:40:40:40:40:40:40:40", + "00:20:00:81:08:40:40:40:40:40:40:40:40", + "00:20:00:81:08:40:40:40:40:40:40:40:40", + "00:20:00:83:08:40:40:40:40:40:40:40:40", + "00:20:00:83:08:40:40:40:40:40:40:40:40", + "00:20:00:83:08:40:40:40:40:40:40:40:40", + "00:20:00:83:08:40:40:40:40:40:40:40:40", + "00:e6:00:00", + "00:44:00:00" + }; + u8 buf[SC_MAX_APDU_BUFFER_SIZE]; + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; + sc_apdu_t apdu; + size_t len0; + int commandsnum = 10; + int i, r; + + LOG_FUNC_CALLED(ctx); + + /* Check card version */ + if (card->type != SC_CARD_TYPE_OPENPGP_V2) { + sc_log(ctx, "Card is not OpenPGP v2"); + LOG_FUNC_RETURN(ctx, SC_ERROR_NO_CARD_SUPPORT); + } + sc_log(ctx, "Card is OpenPGP v2. Erase card."); + + /* Iterate over 10 commands above */ + for (i = 0; i < commandsnum; i++) { + /* Convert the string to binary array */ + len0 = sizeof(buf); + sc_hex_to_bin(apdustring[i], buf, &len0); + printf("Sending: "); + for (r = 0; r < len0; r++) + printf("%02X ", buf[r]); + printf("\n"); + + /* Build APDU from binary array */ + r = sc_bytes2apdu(card->ctx, buf, len0, &apdu); + if (r) { + sc_log(ctx, "Failed to build APDU"); + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL); + } + apdu.resp = rbuf; + apdu.resplen = sizeof(rbuf); + + /* Send APDU to card */ + r = sc_transmit_apdu(card, &apdu); + LOG_TEST_RET(ctx, r, "Transmiting APDU failed"); + } + LOG_FUNC_RETURN(ctx, r); +} + /* ABI: card ctl: perform special card-specific operations */ static int pgp_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr) { @@ -2232,6 +2292,10 @@ static int pgp_card_ctl(sc_card_t *card, LOG_FUNC_RETURN(card->ctx, r); break; #endif /* ENABLE_OPENSSL */ + case SC_CARDCTL_ERASE_CARD: + r = pgp_erase_card(card); + LOG_FUNC_RETURN(card->ctx, r); + break; } LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED); Index: opensc-20150513/src/tools/openpgp-tool.c =================================================================== --- opensc-20150513.orig/src/tools/openpgp-tool.c +++ opensc-20150513/src/tools/openpgp-tool.c @@ -78,6 +78,7 @@ static int opt_pin = 0; static const char *pin = NULL; static int opt_dump_do = 0; static u8 do_dump_idx; +static int opt_erase = 0; static const char *app_name = "openpgp-tool"; @@ -94,6 +95,7 @@ static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "verbose", no_argument, NULL, 'v' }, { "version", no_argument, NULL, 'V' }, + { "erase", no_argument, NULL, 'E' }, { "verify", required_argument, NULL, OPT_VERIFY }, { "pin", required_argument, NULL, OPT_PIN }, { "do", required_argument, NULL, 'd' }, @@ -113,6 +115,7 @@ static const char *option_help[] = { /* h */ "Print this help message", /* v */ "Verbose operation. Use several times to enable debug output.", /* V */ "Show version number", +/* E */ "Erase (reset) the card", "Verify PIN (CHV1, CHV2, CHV3...)", "PIN string", /* d */ "Dump private data object number (i.e. PRIVATE-DO-)" @@ -232,7 +235,7 @@ static int decode_options(int argc, char { int c; - while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVd:", options, (int *) 0)) != EOF) { + while ((c = getopt_long(argc, argv,"r:x:CUG:L:hwvVd:E", options, (int *) 0)) != EOF) { switch (c) { case 'r': opt_reader = optarg; @@ -294,6 +297,8 @@ static int decode_options(int argc, char do_dump_idx = optarg[0] - '0'; opt_dump_do++; actions++; + case 'E': + opt_erase++; break; default: util_print_usage_and_die(app_name, options, option_help, NULL); @@ -452,6 +457,18 @@ int do_verify(sc_card_t *card, char *typ return r; } +int do_erase(sc_card_t *card) +{ + int r; + /* Check card version */ + if (card->type != SC_CARD_TYPE_OPENPGP_V2) { + printf("Do not erase card which is not OpenPGP v2\n"); + } + printf("Erase card\n"); + r = sc_card_ctl(card, SC_CARDCTL_ERASE_CARD, NULL); + return r; +} + int main(int argc, char **argv) { sc_context_t *ctx = NULL; @@ -531,6 +548,9 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } + if (opt_erase) + exit_status != do_erase(card); + out: sc_unlock(card); sc_disconnect_card(card);