You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
5.5 KiB

  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.
  6. ---
  7. src/tools/openpgp-tool.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++
  8. 1 file changed, 142 insertions(+)
  9. diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
  10. index de1c9d4..374819a 100644
  11. --- a/src/tools/openpgp-tool.c
  12. +++ b/src/tools/openpgp-tool.c
  13. @@ -41,6 +41,7 @@
  14. #define OPT_PRETTY 257
  15. #define OPT_VERIFY 258
  16. #define OPT_PIN 259
  17. +#define OPT_DELKEY 260
  18. /* define structures */
  19. struct ef_name_map {
  20. @@ -79,6 +80,7 @@ static char *pin = NULL;
  21. static int opt_dump_do = 0;
  22. static u8 do_dump_idx;
  23. static int opt_erase = 0;
  24. +static int opt_delkey = 0;
  25. static const char *app_name = "openpgp-tool";
  26. @@ -98,6 +100,7 @@ static const struct option options[] = {
  27. { "erase", no_argument, NULL, 'E' },
  28. { "verify", required_argument, NULL, OPT_VERIFY },
  29. { "pin", required_argument, NULL, OPT_PIN },
  30. + { "del-key", required_argument, NULL, OPT_DELKEY },
  31. { "do", required_argument, NULL, 'd' },
  32. { NULL, 0, NULL, 0 }
  33. };
  34. @@ -118,6 +121,7 @@ static const char *option_help[] = {
  35. /* E */ "Erase (reset) the card",
  36. "Verify PIN (CHV1, CHV2, CHV3...)",
  37. "PIN string",
  38. + "Delete key (1, 2, 3 or all)",
  39. /* d */ "Dump private data object number <arg> (i.e. PRIVATE-DO-<arg>)"
  40. };
  41. @@ -302,6 +306,14 @@ static int decode_options(int argc, char **argv)
  42. case 'E':
  43. opt_erase++;
  44. break;
  45. + case OPT_DELKEY:
  46. + opt_delkey++;
  47. + if (strcmp(optarg, "all") != 0) /* Arg string is not 'all' */
  48. + key_id = optarg[0] - '0';
  49. + else /* Arg string is 'all' */
  50. + key_id = 'a';
  51. + actions++;
  52. + break;
  53. default:
  54. util_print_usage_and_die(app_name, options, option_help, NULL);
  55. }
  56. @@ -457,6 +469,133 @@ int do_verify(sc_card_t *card, char *type, char *pin)
  57. return r;
  58. }
  59. +/**
  60. + * Delete key, for Gnuk.
  61. + **/
  62. +int delete_key_gnuk(sc_card_t *card, u8 key_id)
  63. +{
  64. + sc_context_t *ctx = card->ctx;
  65. + int r = SC_SUCCESS;
  66. + u8 *data = NULL;
  67. +
  68. + /* Delete fingerprint */
  69. + sc_log(ctx, "Delete fingerprints");
  70. + r |= sc_put_data(card, 0xC6 + key_id, NULL, 0);
  71. + /* Delete creation time */
  72. + sc_log(ctx, "Delete creation time");
  73. + r |= sc_put_data(card, 0xCD + key_id, NULL, 0);
  74. +
  75. + /* Rewrite Extended Header List */
  76. + sc_log(ctx, "Rewrite Extended Header List");
  77. +
  78. + if (key_id == 1)
  79. + data = "\x4D\x02\xB6";
  80. + else if (key_id == 2)
  81. + data = "\x4D\x02\xB8";
  82. + else if (key_id == 3)
  83. + data = "\x4D\x02\xA4";
  84. + else
  85. + return SC_ERROR_INVALID_ARGUMENTS;
  86. +
  87. + r |= sc_put_data(card, 0x4D, data, strlen(data) + 1);
  88. + return r;
  89. +}
  90. +
  91. +/**
  92. + * Delete key, for OpenPGP card.
  93. + * This function is not complete and is reserved for future version (> 2) of OpenPGP card.
  94. + **/
  95. +int delete_key_openpgp(sc_card_t *card, u8 key_id)
  96. +{
  97. + sc_context_t *ctx = card->ctx;
  98. + 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";
  99. + char *del_creationtime = "00:DA:00:CD:04:00:00:00:00";
  100. + /* We need to replace the 4th byte later */
  101. + char *apdustring = NULL;
  102. + u8 buf[SC_MAX_APDU_BUFFER_SIZE];
  103. + u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
  104. + sc_apdu_t apdu;
  105. + size_t len0;
  106. + int i;
  107. + int r = SC_SUCCESS;
  108. +
  109. + for (i = 0; i < 2; i++) {
  110. + if (i == 0) /* Reset fingerprint */
  111. + apdustring = del_fingerprint;
  112. + else /* Reset creation time */
  113. + apdustring = del_creationtime;
  114. + /* Convert the string to binary array */
  115. + len0 = sizeof(buf);
  116. + sc_hex_to_bin(apdustring, buf, &len0);
  117. +
  118. + /* Replace DO tag, subject to key ID */
  119. + buf[3] = buf[3] + key_id;
  120. +
  121. + /* Build APDU from binary array */
  122. + r = sc_bytes2apdu(card->ctx, buf, len0, &apdu);
  123. + if (r) {
  124. + sc_log(ctx, "Failed to build APDU");
  125. + LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
  126. + }
  127. + apdu.resp = rbuf;
  128. + apdu.resplen = sizeof(rbuf);
  129. +
  130. + /* Send APDU to card */
  131. + r = sc_transmit_apdu(card, &apdu);
  132. + LOG_TEST_RET(ctx, r, "Transmiting APDU failed");
  133. + }
  134. + /* TODO: Rewrite Extended Header List.
  135. + * Not support by OpenGPG v2 yet */
  136. + LOG_FUNC_RETURN(ctx, r);
  137. +}
  138. +
  139. +int delete_key(sc_card_t *card, u8 key_id)
  140. +{
  141. + sc_context_t *ctx = card->ctx;
  142. + int r;
  143. +
  144. + LOG_FUNC_CALLED(ctx);
  145. + /* Check key ID */
  146. + if (key_id < 1 || key_id > 3) {
  147. + sc_log(ctx, "Invalid key ID %d", key_id);
  148. + LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
  149. + }
  150. +
  151. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK)
  152. + r = delete_key_gnuk(card, key_id);
  153. + else
  154. + r = delete_key_openpgp(card, key_id);
  155. +
  156. + LOG_FUNC_RETURN(ctx, r);
  157. +}
  158. +
  159. +int do_delete_key(sc_card_t *card, u8 key_id)
  160. +{
  161. + sc_context_t *ctx = card->ctx;
  162. + int r = SC_SUCCESS;
  163. +
  164. + /* Currently, only Gnuk supports deleting keys */
  165. + if (card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
  166. + printf("Only Gnuk supports deleting keys. General OpenPGP doesn't.");
  167. + return SC_ERROR_NOT_SUPPORTED;
  168. + }
  169. +
  170. + if (key_id < 1 || (key_id > 3 && key_id != 'a')) {
  171. + printf("Error: Invalid key id %d", key_id);
  172. + return SC_ERROR_INVALID_ARGUMENTS;
  173. + }
  174. + if (key_id == 1 || key_id == 'a') {
  175. + r |= delete_key(card, 1);
  176. + }
  177. + if (key_id == 2 || key_id == 'a') {
  178. + r |= delete_key(card, 2);
  179. + }
  180. + if (key_id == 3 || key_id == 'a') {
  181. + r |= delete_key(card, 3);
  182. + }
  183. + return r;
  184. +}
  185. +
  186. int do_erase(sc_card_t *card)
  187. {
  188. int r;
  189. @@ -548,6 +687,9 @@ int main(int argc, char **argv)
  190. exit(EXIT_FAILURE);
  191. }
  192. + if (opt_delkey)
  193. + exit_status != do_delete_key(card, key_id);
  194. +
  195. if (opt_erase)
  196. exit_status != do_erase(card);
  197. --
  198. 2.1.3