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.

210 lines
5.5 KiB

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