- From 469b6567d9adc4af6f49fa65534162673060454d Mon Sep 17 00:00:00 2001
- From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
- <ng.hong.quan@gmail.com>
- Date: Mon, 4 Mar 2013 18:13:03 +0700
- Subject: [PATCH 06/26] openpgp-tool: Support deleting key in Gnuk.
-
- ---
- src/tools/openpgp-tool.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++
- 1 file changed, 142 insertions(+)
-
- diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
- index de1c9d4..374819a 100644
- --- a/src/tools/openpgp-tool.c
- +++ b/src/tools/openpgp-tool.c
- @@ -41,6 +41,7 @@
- #define OPT_PRETTY 257
- #define OPT_VERIFY 258
- #define OPT_PIN 259
- +#define OPT_DELKEY 260
-
- /* define structures */
- struct ef_name_map {
- @@ -79,6 +80,7 @@ static char *pin = NULL;
- static int opt_dump_do = 0;
- static u8 do_dump_idx;
- static int opt_erase = 0;
- +static int opt_delkey = 0;
-
- static const char *app_name = "openpgp-tool";
-
- @@ -98,6 +100,7 @@ static const struct option options[] = {
- { "erase", no_argument, NULL, 'E' },
- { "verify", required_argument, NULL, OPT_VERIFY },
- { "pin", required_argument, NULL, OPT_PIN },
- + { "del-key", required_argument, NULL, OPT_DELKEY },
- { "do", required_argument, NULL, 'd' },
- { NULL, 0, NULL, 0 }
- };
- @@ -118,6 +121,7 @@ static const char *option_help[] = {
- /* E */ "Erase (reset) the card",
- "Verify PIN (CHV1, CHV2, CHV3...)",
- "PIN string",
- + "Delete key (1, 2, 3 or all)",
- /* d */ "Dump private data object number <arg> (i.e. PRIVATE-DO-<arg>)"
- };
-
- @@ -302,6 +306,14 @@ static int decode_options(int argc, char **argv)
- case 'E':
- opt_erase++;
- break;
- + case OPT_DELKEY:
- + opt_delkey++;
- + if (strcmp(optarg, "all") != 0) /* Arg string is not 'all' */
- + key_id = optarg[0] - '0';
- + else /* Arg string is 'all' */
- + key_id = 'a';
- + actions++;
- + break;
- default:
- util_print_usage_and_die(app_name, options, option_help, NULL);
- }
- @@ -457,6 +469,133 @@ int do_verify(sc_card_t *card, char *type, char *pin)
- return r;
- }
-
- +/**
- + * Delete key, for Gnuk.
- + **/
- +int delete_key_gnuk(sc_card_t *card, u8 key_id)
- +{
- + sc_context_t *ctx = card->ctx;
- + int r = SC_SUCCESS;
- + u8 *data = NULL;
- +
- + /* Delete fingerprint */
- + sc_log(ctx, "Delete fingerprints");
- + r |= sc_put_data(card, 0xC6 + key_id, NULL, 0);
- + /* Delete creation time */
- + sc_log(ctx, "Delete creation time");
- + r |= sc_put_data(card, 0xCD + key_id, NULL, 0);
- +
- + /* Rewrite Extended Header List */
- + sc_log(ctx, "Rewrite Extended Header List");
- +
- + if (key_id == 1)
- + data = "\x4D\x02\xB6";
- + else if (key_id == 2)
- + data = "\x4D\x02\xB8";
- + else if (key_id == 3)
- + data = "\x4D\x02\xA4";
- + else
- + return SC_ERROR_INVALID_ARGUMENTS;
- +
- + r |= sc_put_data(card, 0x4D, data, strlen(data) + 1);
- + return r;
- +}
- +
- +/**
- + * Delete key, for OpenPGP card.
- + * This function is not complete and is reserved for future version (> 2) of OpenPGP card.
- + **/
- +int delete_key_openpgp(sc_card_t *card, u8 key_id)
- +{
- + sc_context_t *ctx = card->ctx;
- + char *del_fingerprint = "00:DA:00:C6:14:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00";
- + char *del_creationtime = "00:DA:00:CD:04:00:00:00:00";
- + /* We need to replace the 4th byte later */
- + char *apdustring = NULL;
- + u8 buf[SC_MAX_APDU_BUFFER_SIZE];
- + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
- + sc_apdu_t apdu;
- + size_t len0;
- + int i;
- + int r = SC_SUCCESS;
- +
- + for (i = 0; i < 2; i++) {
- + if (i == 0) /* Reset fingerprint */
- + apdustring = del_fingerprint;
- + else /* Reset creation time */
- + apdustring = del_creationtime;
- + /* Convert the string to binary array */
- + len0 = sizeof(buf);
- + sc_hex_to_bin(apdustring, buf, &len0);
- +
- + /* Replace DO tag, subject to key ID */
- + buf[3] = buf[3] + key_id;
- +
- + /* 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");
- + }
- + /* TODO: Rewrite Extended Header List.
- + * Not support by OpenGPG v2 yet */
- + LOG_FUNC_RETURN(ctx, r);
- +}
- +
- +int delete_key(sc_card_t *card, u8 key_id)
- +{
- + sc_context_t *ctx = card->ctx;
- + int r;
- +
- + LOG_FUNC_CALLED(ctx);
- + /* Check key ID */
- + if (key_id < 1 || key_id > 3) {
- + sc_log(ctx, "Invalid key ID %d", key_id);
- + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
- + }
- +
- + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
- + r = delete_key_gnuk(card, key_id);
- + else
- + r = delete_key_openpgp(card, key_id);
- +
- + LOG_FUNC_RETURN(ctx, r);
- +}
- +
- +int do_delete_key(sc_card_t *card, u8 key_id)
- +{
- + sc_context_t *ctx = card->ctx;
- + int r = SC_SUCCESS;
- +
- + /* Currently, only Gnuk supports deleting keys */
- + if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
- + printf("Only Gnuk supports deleting keys. General OpenPGP doesn't.");
- + return SC_ERROR_NOT_SUPPORTED;
- + }
- +
- + if (key_id < 1 || (key_id > 3 && key_id != 'a')) {
- + printf("Error: Invalid key id %d", key_id);
- + return SC_ERROR_INVALID_ARGUMENTS;
- + }
- + if (key_id == 1 || key_id == 'a') {
- + r |= delete_key(card, 1);
- + }
- + if (key_id == 2 || key_id == 'a') {
- + r |= delete_key(card, 2);
- + }
- + if (key_id == 3 || key_id == 'a') {
- + r |= delete_key(card, 3);
- + }
- + return r;
- +}
- +
- int do_erase(sc_card_t *card)
- {
- int r;
- @@ -548,6 +687,9 @@ int main(int argc, char **argv)
- exit(EXIT_FAILURE);
- }
-
- + if (opt_delkey)
- + exit_status != do_delete_key(card, key_id);
- +
- if (opt_erase)
- exit_status != do_erase(card);
-
- --
- 2.1.3
-
|