Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

include my patches against upstream

Patched files:
* src/libopensc/card-openpgp.c
  Support of OpenPGP card 2.0
* src/tools/opensc-explorer.c
  Bugfixes, functional extensions
  • Loading branch information...
commit c51dafb40cc55ce190e238397a347c84267f0d65 1 parent b49b971
Peter Marschall authored

Showing 2 changed files with 183 additions and 110 deletions. Show diff stats Hide diff stats

  1. +155 81 src/libopensc/card-openpgp.c
  2. +28 29 src/tools/opensc-explorer.c
236 src/libopensc/card-openpgp.c
@@ -33,6 +33,7 @@
33 33 #include "internal.h"
34 34 #include "asn1.h"
35 35 #include "cardctl.h"
  36 +#include "errors.h"
36 37
37 38 static struct sc_atr_table pgp_atrs[] = {
38 39 { "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 },
@@ -61,8 +62,8 @@ static struct sc_card_driver pgp_drv = {
61 62 * Everything else is mapped to "file" IDs.
62 63 */
63 64 struct blob {
64   - struct blob * next;
65   - struct blob * parent;
  65 + struct blob * next; /* pointer to next sibling */
  66 + struct blob * parent; /* pointer to parent */
66 67 struct do_info *info;
67 68
68 69 sc_file_t * file;
@@ -71,7 +72,7 @@ struct blob {
71 72
72 73 unsigned char * data;
73 74 unsigned int len;
74   - struct blob * files;
  75 + struct blob * files; /* pointer to 1st child */
75 76 };
76 77
77 78 struct do_info {
@@ -82,8 +83,12 @@ struct do_info {
82 83 int (*put_fn)(sc_card_t *, unsigned int, const u8 *, size_t);
83 84 };
84 85
  86 +static int pgp_finish(sc_card_t *card);
  87 +static void pgp_iterate_blobs(struct blob *, int, void (*func)());
  88 +
85 89 static struct blob * pgp_new_blob(struct blob *, unsigned int, int,
86 90 struct do_info *);
  91 +static void pgp_free_blob(struct blob *);
87 92 static int pgp_get_pubkey(sc_card_t *, unsigned int,
88 93 u8 *, size_t);
89 94 static int pgp_get_pubkey_pem(sc_card_t *, unsigned int,
@@ -91,12 +96,17 @@ static int pgp_get_pubkey_pem(sc_card_t *, unsigned int,
91 96
92 97 static struct do_info pgp_objects[] = {
93 98 { 0x004f, 0, 0, sc_get_data, sc_put_data },
94   - { 0x005e, 1, 0, sc_get_data, sc_put_data },
  99 + { 0x005e, 0, 0, sc_get_data, sc_put_data },
95 100 { 0x0065, 1, 0, sc_get_data, sc_put_data },
96 101 { 0x006e, 1, 0, sc_get_data, sc_put_data },
97   - { 0x0073, 1, 0, sc_get_data, sc_put_data },
98 102 { 0x007a, 1, 0, sc_get_data, sc_put_data },
  103 + { 0x00c4, 0, 0, sc_get_data, sc_put_data },
  104 + { 0x0101, 0, 0, sc_get_data, sc_put_data },
  105 + { 0x0102, 0, 0, sc_get_data, sc_put_data },
  106 +// { 0x0103, 0, 0, sc_get_data, sc_put_data }, // needs verify with PW1
  107 +// { 0x0104, 0, 0, sc_get_data, sc_put_data }, // needs verify with PW3
99 108 { 0x5f50, 0, 0, sc_get_data, sc_put_data },
  109 + { 0x7f21, 1, 0, sc_get_data, sc_put_data },
100 110 { 0xb600, 1, 0, pgp_get_pubkey, NULL },
101 111 { 0xb800, 1, 0, pgp_get_pubkey, NULL },
102 112 { 0xa400, 1, 0, pgp_get_pubkey, NULL },
@@ -109,7 +119,7 @@ static struct do_info pgp_objects[] = {
109 119
110 120 #define DRVDATA(card) ((struct pgp_priv_data *) ((card)->drv_data))
111 121 struct pgp_priv_data {
112   - struct blob mf;
  122 + struct blob * mf;
113 123 struct blob * current;
114 124
115 125 sc_security_env_t sec_env;
@@ -138,22 +148,43 @@ pgp_init(sc_card_t *card)
138 148 sc_file_t *file = NULL;
139 149 struct do_info *info;
140 150 int r;
  151 + struct blob *child;
141 152
142 153 priv = calloc (1, sizeof *priv);
143 154 if (!priv)
144 155 return SC_ERROR_OUT_OF_MEMORY;
  156 + priv->mf = calloc(1, sizeof(struct blob));
  157 + if (!priv->mf) {
  158 + free(priv);
  159 + return SC_ERROR_OUT_OF_MEMORY;
  160 + }
  161 +
145 162 card->drv_data = priv;
146 163 card->cla = 0x00;
147 164
148 165 /* Is this correct? */
  166 + /* OpenPGP card spec 1.1 & 2.0, section 2.1 */
149 167 flags = SC_ALGORITHM_RSA_RAW;
  168 + /* OpenPGP card spec 1.1 & 2.0, section 7.2.9 & 7.2.10 */
150 169 flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
  170 + /* OpenPGP card 2.0 spec, section 7.2.8.1 */
  171 + /*
  172 + flags |= SC_ALGORITHM_RSA_HASH_SHA1 |
  173 + SC_ALGORITHM_RSA_HASH_RIPEMD160;
  174 + if (card->type == SC_CARD_TYPE_OPENPGP_V2)
  175 + flags |= SC_ALGORITHM_RSA_HASH_SHA224 |
  176 + SC_ALGORITHM_RSA_HASH_SHA256 |
  177 + SC_ALGORITHM_RSA_HASH_SHA384 |
  178 + SC_ALGORITHM_RSA_HASH_SHA512;
  179 + */
151 180 flags |= SC_ALGORITHM_RSA_HASH_NONE;
152 181
153 182 /* Is this correct? */
154 183 _sc_card_add_rsa_alg(card, 512, flags, 0);
155 184 _sc_card_add_rsa_alg(card, 768, flags, 0);
156 185 _sc_card_add_rsa_alg(card, 1024, flags, 0);
  186 + if (card->type == SC_CARD_TYPE_OPENPGP_V2)
  187 + _sc_card_add_rsa_alg(card, 2048, flags, 0);
157 188
158 189 sc_format_path("D276:0001:2401", &aid);
159 190 aid.type = SC_PATH_TYPE_DF_NAME;
@@ -165,20 +196,29 @@ pgp_init(sc_card_t *card)
165 196 file->type = SC_FILE_TYPE_DF;
166 197 file->id = 0x3f00;
167 198
168   - priv->mf.file = file;
169   - priv->mf.id = 0x3F00;
  199 + priv->mf->file = file;
  200 + priv->mf->id = 0x3F00;
170 201
171   - priv->current = &priv->mf;
  202 + priv->current = priv->mf;
172 203
173   - /* Populate MF - add all blobs listed in the pgp_objects
174   - * table. */
  204 + /* Populate MF - add all blobs listed in the pgp_objects table. */
175 205 for (info = pgp_objects; info->id > 0; info++) {
176   - pgp_new_blob(&priv->mf, info->id,
  206 + child = pgp_new_blob(priv->mf, info->id,
177 207 info->constructed? SC_FILE_TYPE_DF
178 208 : SC_FILE_TYPE_WORKING_EF,
179 209 info);
  210 + /* catch out of memory condition */
  211 + if (child == NULL)
  212 + break;
180 213 }
181   - return 0;
  214 +
  215 + /* treat out of memory condition */
  216 + if (child == NULL) {
  217 + pgp_finish(card);
  218 + return SC_ERROR_OUT_OF_MEMORY;
  219 + }
  220 +
  221 + return SC_SUCCESS;
182 222 }
183 223
184 224 static int
@@ -187,13 +227,15 @@ pgp_finish(sc_card_t *card)
187 227 struct pgp_priv_data *priv;
188 228
189 229 if (card == NULL)
190   - return 0;
  230 + return SC_SUCCESS;
191 231 priv = DRVDATA (card);
192 232
193   - /* XXX delete fake file hierarchy */
  233 + /* delete fake file hierarchy */
  234 + pgp_iterate_blobs(priv->mf, 99, pgp_free_blob);
194 235
195 236 free(priv);
196   - return 0;
  237 + card->drv_data = NULL;
  238 + return SC_SUCCESS;
197 239 }
198 240
199 241 static int
@@ -201,13 +243,25 @@ pgp_set_blob(struct blob *blob, const u8 *data, size_t len)
201 243 {
202 244 if (blob->data)
203 245 free(blob->data);
204   - blob->len = len;
  246 + blob->data = NULL;
  247 + blob->len = 0;
205 248 blob->status = 0;
206   - blob->data = malloc(len);
207   - memcpy(blob->data, data, len);
208 249
209   - blob->file->size = len;
210   - return 0;
  250 + if (len > 0) {
  251 + void *tmp = malloc(len);
  252 +
  253 + if (tmp == NULL)
  254 + return SC_ERROR_OUT_OF_MEMORY;
  255 +
  256 + blob->data = tmp;
  257 + blob->len = len;
  258 + memcpy(blob->data, data, len);
  259 + }
  260 +
  261 + if (blob->file)
  262 + blob->file->size = len;
  263 +
  264 + return SC_SUCCESS;
211 265 }
212 266
213 267 static struct blob *
@@ -217,24 +271,56 @@ pgp_new_blob(struct blob *parent, unsigned int file_id,
217 271 sc_file_t *file = sc_file_new();
218 272 struct blob *blob, **p;
219 273
220   - blob = calloc(1, sizeof(*blob));
221   - blob->parent = parent;
222   - blob->id = file_id;
223   - blob->file = file;
224   - blob->info = info;
  274 + if ((blob = calloc(1, sizeof(*blob))) != NULL) {
  275 + blob->parent = parent;
  276 + blob->id = file_id;
  277 + blob->file = file;
  278 + blob->info = info;
225 279
226   - file->type = file_type;
227   - file->path = parent->file->path;
228   - file->ef_structure = SC_FILE_EF_TRANSPARENT;
229   - sc_append_file_id(&file->path, file_id);
  280 + file->type = file_type;
  281 + file->path = parent->file->path;
  282 + file->ef_structure = SC_FILE_EF_TRANSPARENT;
  283 + sc_append_file_id(&file->path, file_id);
230 284
231   - for (p = &parent->files; *p; p = &(*p)->next)
232   - ;
233   - *p = blob;
  285 + for (p = &parent->files; *p; p = &(*p)->next)
  286 + ;
  287 + *p = blob;
  288 + }
234 289
235 290 return blob;
236 291 }
237 292
  293 +static void
  294 +pgp_free_blob(struct blob *blob)
  295 +{
  296 + if (blob) {
  297 + if (blob->file)
  298 + sc_file_free(blob->file);
  299 + if (blob->data)
  300 + free(blob->data);
  301 + free(blob);
  302 + }
  303 +}
  304 +
  305 +
  306 +static void
  307 +pgp_iterate_blobs(struct blob *blob, int level, void (*func)())
  308 +{
  309 + if (blob) {
  310 + if (level > 0) {
  311 + struct blob *child = blob->files;
  312 +
  313 + while (child != NULL) {
  314 + struct blob *next = child->next;
  315 +
  316 + pgp_iterate_blobs(child, level-1, func);
  317 + child = next;
  318 + }
  319 + }
  320 + func(blob);
  321 + }
  322 +}
  323 +
238 324 static int
239 325 pgp_read_blob(sc_card_t *card, struct blob *blob)
240 326 {
@@ -242,13 +328,13 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
242 328 int r;
243 329
244 330 if (blob->data != NULL)
245   - return 0;
  331 + return SC_SUCCESS;
246 332 if (blob->info == NULL)
247 333 return blob->status;
248 334
249 335 r = blob->info->get_fn(card, blob->id, buffer, sizeof(buffer));
250 336
251   - if (r < 0) {
  337 + if (r < 0) { /* an error occurred */
252 338 blob->status = r;
253 339 return r;
254 340 }
@@ -258,67 +344,55 @@ pgp_read_blob(sc_card_t *card, struct blob *blob)
258 344
259 345 /*
260 346 * Enumerate contents of a data blob.
261   - * The OpenPGP card has a funny TLV encoding.
  347 + * The OpenPGP card has a TLV encoding according ASN.1 BER-encoding rules.
262 348 */
263 349 static int
264 350 pgp_enumerate_blob(sc_card_t *card, struct blob *blob)
265 351 {
266   - const u8 *in, *end;
  352 + const u8 *in;
267 353 int r;
268 354
269 355 if (blob->files != NULL)
270   - return 0;
  356 + return SC_SUCCESS;
271 357
272 358 if ((r = pgp_read_blob(card, blob)) < 0)
273 359 return r;
274 360
275 361 in = blob->data;
276   - end = blob->data + blob->len;
277   - while (in < end) {
278   - unsigned int tag, len, type = SC_FILE_TYPE_WORKING_EF;
279   - unsigned char c;
280 362
281   - c = *in++;
282   - if (c == 0x00 || c == 0xFF)
283   - continue;
  363 + while (blob->len > (in - blob->data)) {
  364 + unsigned int cla, tag, tmptag;
  365 + unsigned int type = SC_FILE_TYPE_WORKING_EF;
  366 + size_t len;
  367 + u8 *data = in;
  368 + struct blob *new;
284 369
285   - tag = c;
286   - if (tag & 0x20)
287   - type = SC_FILE_TYPE_DF;
288   - while ((c & 0x1f) == 0x1f) {
289   - if (in >= end)
290   - goto eoc;
291   - c = *in++;
292   - tag = (tag << 8) | c;
  370 + r = sc_asn1_read_tag(&data, blob->len - (in - blob->data),
  371 + &cla, &tag, &len);
  372 + if (r < 0) {
  373 + sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,
  374 + "Unexpected end of contents\n");
  375 + return SC_ERROR_OBJECT_NOT_VALID;
293 376 }
294 377
295   - if (in >= end)
296   - goto eoc;
297   - c = *in++;
298   - if (c < 0x80) {
299   - len = c;
300   - } else {
301   - len = 0;
302   - c &= 0x7F;
303   - while (c--) {
304   - if (in >= end)
305   - goto eoc;
306   - len = (len << 8) | *in++;
307   - }
308   - }
  378 + /* create fake file system hierarchy by
  379 + * using constructed DOs as DF */
  380 + if (cla & SC_ASN1_TAG_CONSTRUCTED)
  381 + type = SC_FILE_TYPE_DF;
309 382
310   - /* Don't search past end of content */
311   - if (in + len > end)
312   - goto eoc;
  383 + /* undo ASN1's split of tag & class */
  384 + for (tmptag = tag; tmptag > 0x0FF; tmptag >>= 8) {
  385 + cla <<= 8;
  386 + }
  387 + tag |= cla;
313 388
314   - pgp_set_blob(pgp_new_blob(blob, tag, type, NULL), in, len);
315   - in += len;
  389 + if ((new = pgp_new_blob(blob, tag, type, NULL)) == NULL)
  390 + return SC_ERROR_OUT_OF_MEMORY;
  391 + pgp_set_blob(new, data, len);
  392 + in = data + len;
316 393 }
317 394
318   - return 0;
319   -
320   -eoc: sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unexpected end of contents\n");
321   - return SC_ERROR_OBJECT_NOT_VALID;
  395 + return SC_SUCCESS;
322 396 }
323 397
324 398 static int
@@ -339,7 +413,7 @@ pgp_get_blob(sc_card_t *card, struct blob *blob, unsigned int id,
339 413 if (child != NULL) {
340 414 (void) pgp_read_blob(card, child);
341 415 *ret = child;
342   - return 0;
  416 + return SC_SUCCESS;
343 417 }
344 418
345 419 return SC_ERROR_FILE_NOT_FOUND;
@@ -368,7 +442,7 @@ pgp_select_file(sc_card_t *card, const sc_path_t *path, sc_file_t **ret)
368 442 path = &path_copy;
369 443 }
370 444
371   - blob = &priv->mf;
  445 + blob = priv->mf;
372 446 for (n = 0; n < path->len; n += 2) {
373 447 r = pgp_get_blob(card, blob,
374 448 (path->value[n] << 8) | path->value[n+1],
@@ -383,7 +457,7 @@ pgp_select_file(sc_card_t *card, const sc_path_t *path, sc_file_t **ret)
383 457
384 458 if (ret)
385 459 sc_file_dup(ret, blob->file);
386   - return 0;
  460 + return SC_SUCCESS;
387 461 }
388 462
389 463 static int
@@ -485,7 +559,7 @@ pgp_get_pubkey_pem(sc_card_t *card, unsigned int tag, u8 *buf, size_t buf_len)
485 559
486 560 sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "called, tag=%04x\n", tag);
487 561
488   - if ((r = pgp_get_blob(card, &priv->mf, tag & 0xFFFE, &blob)) < 0
  562 + if ((r = pgp_get_blob(card, priv->mf, tag & 0xFFFE, &blob)) < 0
489 563 || (r = pgp_get_blob(card, blob, 0x7F49, &blob)) < 0
490 564 || (r = pgp_get_blob(card, blob, 0x0081, &mod_blob)) < 0
491 565 || (r = pgp_get_blob(card, blob, 0x0082, &exp_blob)) < 0
@@ -586,7 +660,7 @@ pgp_set_security_env(sc_card_t *card,
586 660 }
587 661
588 662 priv->sec_env = *env;
589   - return 0;
  663 + return SC_SUCCESS;
590 664 }
591 665
592 666 static int
57 src/tools/opensc-explorer.c
@@ -164,17 +164,9 @@ static int arg_to_path(const char *arg, sc_path_t *path, int is_id)
164 164
165 165 static void print_file(const sc_file_t *file)
166 166 {
167   - const char *st;
  167 + const char *format = " %02X%02X ";
  168 + const char *st = "???";
168 169
169   - if (file->type == SC_FILE_TYPE_DF)
170   - printf("[");
171   - else
172   - printf(" ");
173   - printf("%02X%02X", file->id >> 8, file->id & 0xFF);
174   - if (file->type == SC_FILE_TYPE_DF)
175   - printf("]");
176   - else
177   - printf(" ");
178 170 switch (file->type) {
179 171 case SC_FILE_TYPE_WORKING_EF:
180 172 st = "wEF";
@@ -183,12 +175,11 @@ static void print_file(const sc_file_t *file)
183 175 st = "iEF";
184 176 break;
185 177 case SC_FILE_TYPE_DF:
  178 + format = "[%02X%02X]";
186 179 st = "DF";
187 180 break;
188   - default:
189   - st = "???";
190   - break;
191 181 }
  182 + printf(format, file->id >> 8, file->id & 0xFF);
192 183 printf("\t%4s", st);
193 184 printf(" %5lu", (unsigned long)file->size);
194 185 if (file->namelen) {
@@ -351,7 +342,6 @@ static int do_cat(int argc, char **argv)
351 342 sc_file_t *file = NULL;
352 343 int not_current = 1;
353 344 int sfi = 0;
354   - const char sfi_prefix[] = "sfi:";
355 345
356 346 if (argc > 1)
357 347 goto usage;
@@ -360,17 +350,10 @@ static int do_cat(int argc, char **argv)
360 350 file = current_file;
361 351 not_current = 0;
362 352 } else {
363   - if (strncmp(argv[0], sfi_prefix, sizeof(sfi_prefix)-1)) {
364   - if (arg_to_path(argv[0], &path, 1) != 0)
365   - goto usage;
366   - r = sc_select_file(card, &path, &file);
367   - if (r) {
368   - check_ret(r, SC_AC_OP_SELECT, "unable to select file",
369   - current_file);
370   - goto err;
371   - }
372   - } else {
373   - const char *sfi_n = &argv[0][sizeof(sfi_prefix)-1];
  353 + const char sfi_prefix[] = "sfi:";
  354 +
  355 + if (strncasecmp(argv[0], sfi_prefix, strlen(sfi_prefix)) == 0) {
  356 + const char *sfi_n = argv[0] + strlen(sfi_prefix);
374 357
375 358 if(!current_file) {
376 359 printf("A DF must be selected to read by SFI\n");
@@ -384,6 +367,15 @@ static int do_cat(int argc, char **argv)
384 367 printf("Invalid SFI: %s\n", sfi_n);
385 368 goto usage;
386 369 }
  370 + } else {
  371 + if (arg_to_path(argv[0], &path, 0) != 0)
  372 + goto usage;
  373 + r = sc_select_file(card, &path, &file);
  374 + if (r) {
  375 + check_ret(r, SC_AC_OP_SELECT, "unable to select file",
  376 + current_file);
  377 + goto err;
  378 + }
387 379 }
388 380 }
389 381 if (file->type != SC_FILE_TYPE_WORKING_EF &&
@@ -903,7 +895,9 @@ static int do_get(int argc, char **argv)
903 895 fbuf[5*i-1] = 0;
904 896 filename = fbuf;
905 897 }
906   - outf = fopen(filename, "wb");
  898 + outf = (strcmp(filename, "-") == 0)
  899 + ? stdout
  900 + : fopen(filename, "wb");
907 901 if (outf == NULL) {
908 902 perror(filename);
909 903 goto err;
@@ -936,14 +930,19 @@ static int do_get(int argc, char **argv)
936 930 idx += r;
937 931 count -= r;
938 932 }
939   - printf("Total of %d bytes read from %s and saved to %s.\n",
940   - idx, argv[0], filename);
  933 + if (outf == stdout) {
  934 + fwrite("\n", 1, 1, outf);
  935 + }
  936 + else {
  937 + printf("Total of %d bytes read from %s and saved to %s.\n",
  938 + idx, argv[0], filename);
  939 + }
941 940
942 941 err = 0;
943 942 err:
944 943 if (file)
945 944 sc_file_free(file);
946   - if (outf)
  945 + if (outf != NULL && outf != stdout)
947 946 fclose(outf);
948 947 select_current_path_or_die();
949 948 return -err;

0 comments on commit c51dafb

Please sign in to comment.
Something went wrong with that request. Please try again.