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.

258 lines
9.3 KiB

  1. From 471b40173b73f213ee72bf05735abf3357658197 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: Wed, 20 Feb 2013 11:54:30 +0700
  5. Subject: [PATCH 01/26] OpenPGP: Detect and support Gnuk Token.
  6. http://www.fsij.org/gnuk/
  7. ---
  8. src/libopensc/card-openpgp.c | 61 ++++++++++++++++++++++++++++++++++----------
  9. src/libopensc/cards.h | 1 +
  10. src/tools/openpgp-tool.c | 7 ++++-
  11. 3 files changed, 55 insertions(+), 14 deletions(-)
  12. diff --git a/src/libopensc/card-openpgp.c b/src/libopensc/card-openpgp.c
  13. index 6774fe1..c785a55 100644
  14. --- a/src/libopensc/card-openpgp.c
  15. +++ b/src/libopensc/card-openpgp.c
  16. @@ -43,6 +43,7 @@
  17. static struct sc_atr_table pgp_atrs[] = {
  18. { "3b:fa:13:00:ff:81:31:80:45:00:31:c1:73:c0:01:00:00:90:00:b1", NULL, "OpenPGP card v1.0/1.1", SC_CARD_TYPE_OPENPGP_V1, 0, NULL },
  19. { "3b:da:18:ff:81:b1:fe:75:1f:03:00:31:c5:73:c0:01:40:00:90:00:0c", NULL, "CryptoStick v1.2 (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_V2, 0, NULL },
  20. + { "3b:da:11:ff:81:b1:fe:55:1f:03:00:31:84:73:80:01:80:00:90:00:e4", NULL, "Gnuk v1.0.x (OpenPGP v2.0)", SC_CARD_TYPE_OPENPGP_GNUK, 0, NULL },
  21. { NULL, NULL, NULL, 0, 0, NULL }
  22. };
  23. @@ -307,6 +308,8 @@ pgp_init(sc_card_t *card)
  24. int r;
  25. struct blob *child = NULL;
  26. + LOG_FUNC_CALLED(card->ctx);
  27. +
  28. priv = calloc (1, sizeof *priv);
  29. if (!priv)
  30. return SC_ERROR_OUT_OF_MEMORY;
  31. @@ -315,11 +318,11 @@ pgp_init(sc_card_t *card)
  32. card->cla = 0x00;
  33. /* set pointer to correct list of card objects */
  34. - priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2)
  35. + priv->pgp_objects = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
  36. ? pgp2_objects : pgp1_objects;
  37. /* set detailed card version */
  38. - priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2)
  39. + priv->bcd_version = (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK)
  40. ? OPENPGP_CARD_2_0 : OPENPGP_CARD_1_1;
  41. /* select application "OpenPGP" */
  42. @@ -428,7 +431,8 @@ pgp_get_card_features(sc_card_t *card)
  43. if ((pgp_get_blob(card, blob73, 0x00c0, &blob) >= 0) &&
  44. (blob->data != NULL) && (blob->len > 0)) {
  45. /* in v2.0 bit 0x04 in first byte means "algorithm attributes changeable */
  46. - if ((blob->data[0] & 0x04) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
  47. + if ((blob->data[0] & 0x04) &&
  48. + (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
  49. priv->ext_caps |= EXT_CAP_ALG_ATTR_CHANGEABLE;
  50. /* bit 0x08 in first byte means "support for private use DOs" */
  51. if (blob->data[0] & 0x08)
  52. @@ -445,7 +449,8 @@ pgp_get_card_features(sc_card_t *card)
  53. priv->ext_caps |= EXT_CAP_GET_CHALLENGE;
  54. }
  55. /* in v2.0 bit 0x80 in first byte means "support Secure Messaging" */
  56. - if ((blob->data[0] & 0x80) && (card->type == SC_CARD_TYPE_OPENPGP_V2))
  57. + if ((blob->data[0] & 0x80) &&
  58. + (card->type == SC_CARD_TYPE_OPENPGP_V2 || card->type == SC_CARD_TYPE_OPENPGP_GNUK))
  59. priv->ext_caps |= EXT_CAP_SM;
  60. if ((priv->bcd_version >= OPENPGP_CARD_2_0) && (blob->len >= 10)) {
  61. @@ -1057,12 +1062,18 @@ static int
  62. pgp_get_pubkey(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
  63. {
  64. sc_apdu_t apdu;
  65. + u8 apdu_case = SC_APDU_CASE_4;
  66. u8 idbuf[2];
  67. int r;
  68. sc_log(card->ctx, "called, tag=%04x\n", tag);
  69. - sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x47, 0x81, 0);
  70. + /* With Gnuk token, force to use short APDU */
  71. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
  72. + apdu_case = SC_APDU_CASE_4_SHORT;
  73. + }
  74. +
  75. + sc_format_apdu(card, &apdu, apdu_case, 0x47, 0x81, 0);
  76. apdu.lc = 2;
  77. apdu.data = ushort2bebytes(idbuf, tag);
  78. apdu.datalen = 2;
  79. @@ -1154,6 +1165,7 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
  80. u8 ins = 0xDA;
  81. u8 p1 = tag >> 8;
  82. u8 p2 = tag & 0xFF;
  83. + u8 apdu_case = SC_APDU_CASE_3;
  84. int r;
  85. LOG_FUNC_CALLED(card->ctx);
  86. @@ -1195,13 +1207,17 @@ pgp_put_data(sc_card_t *card, unsigned int tag, const u8 *buf, size_t buf_len)
  87. /* Build APDU */
  88. if (buf != NULL && buf_len > 0) {
  89. - sc_format_apdu(card, &apdu, SC_APDU_CASE_3, ins, p1, p2);
  90. + /* Force short APDU for Gnuk */
  91. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
  92. + apdu_case = SC_APDU_CASE_3_SHORT;
  93. + }
  94. + sc_format_apdu(card, &apdu, apdu_case, ins, p1, p2);
  95. /* if card/reader does not support extended APDUs, but chaining, then set it */
  96. if (((card->caps & SC_CARD_CAP_APDU_EXT) == 0) && (priv->ext_caps & EXT_CAP_CHAINING))
  97. apdu.flags |= SC_APDU_FLAGS_CHAINING;
  98. - apdu.data = buf;
  99. + apdu.data = (u8 *)buf;
  100. apdu.datalen = buf_len;
  101. apdu.lc = buf_len;
  102. }
  103. @@ -1328,6 +1344,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
  104. struct pgp_priv_data *priv = DRVDATA(card);
  105. sc_security_env_t *env = &priv->sec_env;
  106. sc_apdu_t apdu;
  107. + u8 apdu_case = SC_APDU_CASE_4;
  108. int r;
  109. LOG_FUNC_CALLED(card->ctx);
  110. @@ -1336,14 +1353,19 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
  111. LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS,
  112. "invalid operation");
  113. + /* Force short APDU for Gnuk Token */
  114. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
  115. + apdu_case = SC_APDU_CASE_4_SHORT;
  116. + }
  117. +
  118. switch (env->key_ref[0]) {
  119. case 0x00: /* signature key */
  120. /* PSO SIGNATURE */
  121. - sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
  122. + sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x9E, 0x9A);
  123. break;
  124. case 0x02: /* authentication key */
  125. /* INTERNAL AUTHENTICATE */
  126. - sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x88, 0, 0);
  127. + sc_format_apdu(card, &apdu, apdu_case, 0x88, 0, 0);
  128. break;
  129. case 0x01:
  130. default:
  131. @@ -1352,7 +1374,7 @@ pgp_compute_signature(sc_card_t *card, const u8 *data,
  132. }
  133. apdu.lc = data_len;
  134. - apdu.data = data;
  135. + apdu.data = (u8 *)data;
  136. apdu.datalen = data_len;
  137. apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
  138. apdu.resp = out;
  139. @@ -1376,6 +1398,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
  140. struct pgp_priv_data *priv = DRVDATA(card);
  141. sc_security_env_t *env = &priv->sec_env;
  142. sc_apdu_t apdu;
  143. + u8 apdu_case = SC_APDU_CASE_4;
  144. u8 *temp = NULL;
  145. int r;
  146. @@ -1400,7 +1423,7 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
  147. case 0x01: /* Decryption key */
  148. case 0x02: /* authentication key */
  149. /* PSO DECIPHER */
  150. - sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
  151. + sc_format_apdu(card, &apdu, apdu_case, 0x2A, 0x80, 0x86);
  152. break;
  153. case 0x00: /* signature key */
  154. default:
  155. @@ -1409,8 +1432,13 @@ pgp_decipher(sc_card_t *card, const u8 *in, size_t inlen,
  156. "invalid key reference");
  157. }
  158. + /* Gnuk only supports short APDU, so we need to use command chaining */
  159. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK) {
  160. + apdu.flags |= SC_APDU_FLAGS_CHAINING;
  161. + }
  162. +
  163. apdu.lc = inlen;
  164. - apdu.data = in;
  165. + apdu.data = (u8 *)in;
  166. apdu.datalen = inlen;
  167. apdu.le = ((outlen >= 256) && !(card->caps & SC_CARD_CAP_APDU_EXT)) ? 256 : outlen;
  168. apdu.resp = out;
  169. @@ -1794,6 +1822,11 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
  170. LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
  171. }
  172. + if (card->type == SC_CARD_TYPE_OPENPGP_GNUK && key_info->modulus_len != 2048) {
  173. + sc_log(card->ctx, "Gnuk does not support other key length than 2048.");
  174. + LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
  175. + }
  176. +
  177. /* Set attributes for new-generated key */
  178. r = pgp_update_new_algo_attr(card, key_info);
  179. LOG_TEST_RET(card->ctx, r, "Cannot set attributes for new-generated key");
  180. @@ -1801,7 +1834,9 @@ static int pgp_gen_key(sc_card_t *card, sc_cardctl_openpgp_keygen_info_t *key_in
  181. /* Test whether we will need extended APDU. 1900 is an
  182. * arbitrary modulus length which for sure fits into a short APDU.
  183. * This idea is borrowed from GnuPG code. */
  184. - if (card->caps & SC_CARD_CAP_APDU_EXT && key_info->modulus_len > 1900) {
  185. + if (card->caps & SC_CARD_CAP_APDU_EXT
  186. + && key_info->modulus_len > 1900
  187. + && card->type != SC_CARD_TYPE_OPENPGP_GNUK) {
  188. /* We won't store to apdu variable yet, because it will be reset in
  189. * sc_format_apdu() */
  190. apdu_le = card->max_recv_size;
  191. diff --git a/src/libopensc/cards.h b/src/libopensc/cards.h
  192. index 7be6667..a3f3634 100644
  193. --- a/src/libopensc/cards.h
  194. +++ b/src/libopensc/cards.h
  195. @@ -105,6 +105,7 @@ enum {
  196. SC_CARD_TYPE_OPENPGP_BASE = 9000,
  197. SC_CARD_TYPE_OPENPGP_V1,
  198. SC_CARD_TYPE_OPENPGP_V2,
  199. + SC_CARD_TYPE_OPENPGP_GNUK,
  200. /* jcop driver */
  201. SC_CARD_TYPE_JCOP_BASE = 10000,
  202. diff --git a/src/tools/openpgp-tool.c b/src/tools/openpgp-tool.c
  203. index f42e6d6..a24a395 100644
  204. --- a/src/tools/openpgp-tool.c
  205. +++ b/src/tools/openpgp-tool.c
  206. @@ -33,6 +33,7 @@
  207. #include "libopensc/cards.h"
  208. #include "libopensc/cardctl.h"
  209. #include "libopensc/errors.h"
  210. +#include "libopensc/log.h"
  211. #include "util.h"
  212. #include "libopensc/log.h"
  213. @@ -396,6 +397,8 @@ int do_genkey(sc_card_t *card, u8 key_id, unsigned int key_len)
  214. sc_path_t path;
  215. sc_file_t *file;
  216. + LOG_FUNC_CALLED(card->ctx);
  217. +
  218. if (key_id < 1 || key_id > 3) {
  219. printf("Unknown key ID %d.\n", key_id);
  220. return 1;
  221. @@ -487,8 +490,10 @@ int main(int argc, char **argv)
  222. /* check card type */
  223. if ((card->type != SC_CARD_TYPE_OPENPGP_V1) &&
  224. - (card->type != SC_CARD_TYPE_OPENPGP_V2)) {
  225. + (card->type != SC_CARD_TYPE_OPENPGP_V2) &&
  226. + (card->type != SC_CARD_TYPE_OPENPGP_GNUK)) {
  227. util_error("not an OpenPGP card");
  228. + sc_log(card->ctx, "Card type %X", card->type);
  229. exit_status = EXIT_FAILURE;
  230. goto out;
  231. }
  232. --
  233. 2.1.3