1 From 469b6567d9adc4af6f49fa65534162673060454d Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Nguy=E1=BB=85n=20H=E1=BB=93ng=20Qu=C3=A2n?=
3 <ng.hong.quan@gmail.com>
4 Date: Mon, 4 Mar 2013 18:13:03 +0700
5 Subject: [PATCH 06/26] openpgp-tool: Support deleting key in Gnuk.
8 src/tools/openpgp-tool.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++
9 1 file changed, 142 insertions(+)
11 diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
12 index de1c9d4..374819a 100644
13 --- a/src/tools/openpgp-tool.c
14 +++ b/src/tools/openpgp-tool.c
16 #define OPT_PRETTY 257
17 #define OPT_VERIFY 258
19 +#define OPT_DELKEY 260
21 /* define structures */
23 @@ -79,6 +80,7 @@ static char *pin = NULL;
24 static int opt_dump_do = 0;
25 static u8 do_dump_idx;
26 static int opt_erase = 0;
27 +static int opt_delkey = 0;
29 static const char *app_name = "openpgp-tool";
31 @@ -98,6 +100,7 @@ static const struct option options[] = {
32 { "erase", no_argument, NULL, 'E' },
33 { "verify", required_argument, NULL, OPT_VERIFY },
34 { "pin", required_argument, NULL, OPT_PIN },
35 + { "del-key", required_argument, NULL, OPT_DELKEY },
36 { "do", required_argument, NULL, 'd' },
39 @@ -118,6 +121,7 @@ static const char *option_help[] = {
40 /* E */ "Erase (reset) the card",
41 "Verify PIN (CHV1, CHV2, CHV3...)",
43 + "Delete key (1, 2, 3 or all)",
44 /* d */ "Dump private data object number <arg> (i.e. PRIVATE-DO-<arg>)"
47 @@ -302,6 +306,14 @@ static int decode_options(int argc, char **argv)
53 + if (strcmp(optarg, "all") != 0) /* Arg string is not 'all' */
54 + key_id = optarg[0] - '0';
55 + else /* Arg string is 'all' */
60 util_print_usage_and_die(app_name, options, option_help, NULL);
62 @@ -457,6 +469,133 @@ int do_verify(sc_card_t *card, char *type, char *pin)
67 + * Delete key, for Gnuk.
69 +int delete_key_gnuk(sc_card_t *card, u8 key_id)
71 + sc_context_t *ctx = card->ctx;
75 + /* Delete fingerprint */
76 + sc_log(ctx, "Delete fingerprints");
77 + r |= sc_put_data(card, 0xC6 + key_id, NULL, 0);
78 + /* Delete creation time */
79 + sc_log(ctx, "Delete creation time");
80 + r |= sc_put_data(card, 0xCD + key_id, NULL, 0);
82 + /* Rewrite Extended Header List */
83 + sc_log(ctx, "Rewrite Extended Header List");
86 + data = "\x4D\x02\xB6";
87 + else if (key_id == 2)
88 + data = "\x4D\x02\xB8";
89 + else if (key_id == 3)
90 + data = "\x4D\x02\xA4";
92 + return SC_ERROR_INVALID_ARGUMENTS;
94 + r |= sc_put_data(card, 0x4D, data, strlen(data) + 1);
99 + * Delete key, for OpenPGP card.
100 + * This function is not complete and is reserved for future version (> 2) of OpenPGP card.
102 +int delete_key_openpgp(sc_card_t *card, u8 key_id)
104 + sc_context_t *ctx = card->ctx;
105 + 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";
106 + char *del_creationtime = "00:DA:00:CD:04:00:00:00:00";
107 + /* We need to replace the 4th byte later */
108 + char *apdustring = NULL;
109 + u8 buf[SC_MAX_APDU_BUFFER_SIZE];
110 + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
114 + int r = SC_SUCCESS;
116 + for (i = 0; i < 2; i++) {
117 + if (i == 0) /* Reset fingerprint */
118 + apdustring = del_fingerprint;
119 + else /* Reset creation time */
120 + apdustring = del_creationtime;
121 + /* Convert the string to binary array */
122 + len0 = sizeof(buf);
123 + sc_hex_to_bin(apdustring, buf, &len0);
125 + /* Replace DO tag, subject to key ID */
126 + buf[3] = buf[3] + key_id;
128 + /* Build APDU from binary array */
129 + r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
131 + sc_log(ctx, "Failed to build APDU");
132 + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
135 + apdu.resplen = sizeof(rbuf);
137 + /* Send APDU to card */
138 + r = sc_transmit_apdu(card, &apdu);
139 + LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
141 + /* TODO: Rewrite Extended Header List.
142 + * Not support by OpenGPG v2 yet */
143 + LOG_FUNC_RETURN(ctx, r);
146 +int delete_key(sc_card_t *card, u8 key_id)
148 + sc_context_t *ctx = card->ctx;
151 + LOG_FUNC_CALLED(ctx);
153 + if (key_id < 1 || key_id > 3) {
154 + sc_log(ctx, "Invalid key ID %d", key_id);
155 + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
158 + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
159 + r = delete_key_gnuk(card, key_id);
161 + r = delete_key_openpgp(card, key_id);
163 + LOG_FUNC_RETURN(ctx, r);
166 +int do_delete_key(sc_card_t *card, u8 key_id)
168 + sc_context_t *ctx = card->ctx;
169 + int r = SC_SUCCESS;
171 + /* Currently, only Gnuk supports deleting keys */
172 + if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
173 + printf("Only Gnuk supports deleting keys. General OpenPGP doesn't.");
174 + return SC_ERROR_NOT_SUPPORTED;
177 + if (key_id < 1 || (key_id > 3 && key_id != 'a')) {
178 + printf("Error: Invalid key id %d", key_id);
179 + return SC_ERROR_INVALID_ARGUMENTS;
181 + if (key_id == 1 || key_id == 'a') {
182 + r |= delete_key(card, 1);
184 + if (key_id == 2 || key_id == 'a') {
185 + r |= delete_key(card, 2);
187 + if (key_id == 3 || key_id == 'a') {
188 + r |= delete_key(card, 3);
193 int do_erase(sc_card_t *card)
196 @@ -548,6 +687,9 @@ int main(int argc, char **argv)
201 + exit_status != do_delete_key(card, key_id);
204 exit_status != do_erase(card);