1 /*
2 * card-starcos.c: Support for STARCOS SPK 2.3 cards
3 *
4 * Copyright (C) 2003 Jörn Zukowski <zukowski@trustcenter.de> and
5 * Nils Larsch <larsch@trustcenter.de>, TrustCenter AG
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #if HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include "asn1.h"
30 #include "cardctl.h"
31 #include "internal.h"
32 #include "iso7816.h"
33
34 static const struct sc_atr_table starcos_atrs[] = {
35 { "3B:B7:94:00:c0:24:31:fe:65:53:50:4b:32:33:90:00:b4", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
36 { "3B:B7:94:00:81:31:fe:65:53:50:4b:32:33:90:00:d1", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
37 { "3b:b7:18:00:c0:3e:31:fe:65:53:50:4b:32:34:90:00:25", NULL, NULL, SC_CARD_TYPE_STARCOS_GENERIC, 0, NULL },
38 { "3b:d8:18:ff:81:b1:fe:45:1f:03:80:64:04:1a:b4:03:81:05:61", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_4, 0, NULL },
39 { "3b:d3:96:ff:81:b1:fe:45:1f:07:80:81:05:2d", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_4, 0, NULL },
40 { "3B:9B:96:C0:0A:31:FE:45:80:67:04:1E:B5:01:00:89:4C:81:05:45", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
41 { "3B:DB:96:FF:81:31:FE:45:80:67:05:34:B5:02:01:C0:A1:81:05:3C", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
42 { "3B:D9:96:FF:81:31:FE:45:80:31:B8:73:86:01:C0:81:05:02", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
43 { "3B:DF:96:FF:81:31:FE:45:80:5B:44:45:2E:42:4E:4F:54:4B:31:31:31:81:05:A0", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
44 { "3B:DF:96:FF:81:31:FE:45:80:5B:44:45:2E:42:4E:4F:54:4B:31:30:30:81:05:A0", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
45 { "3B:D9:96:FF:81:31:FE:45:80:31:B8:73:86:01:E0:81:05:22", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
46 { "3B:D0:97:FF:81:B1:FE:45:1F:07:2B", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_4, 0, NULL },
47 { "3b:df:96:ff:81:31:fe:45:80:5b:44:45:2e:42:41:5f:53:43:33:35:32:81:05:b5", NULL, NULL, SC_CARD_TYPE_STARCOS_V3_5, 0, NULL },
48 { NULL, NULL, NULL, 0, 0, NULL }
49 };
50
51 static struct sc_card_operations starcos_ops;
52 static struct sc_card_operations *iso_ops = NULL;
53
54 static struct sc_card_driver starcos_drv = {
55 "STARCOS",
56 "starcos",
57 &starcos_ops,
58 NULL, 0, NULL
59 };
60
61 static const struct sc_card_error starcos_errors[] =
62 {
63 { 0x6600, SC_ERROR_INCORRECT_PARAMETERS, "Error setting the security env"},
64 { 0x66F0, SC_ERROR_INCORRECT_PARAMETERS, "No space left for padding"},
65 { 0x69F0, SC_ERROR_NOT_ALLOWED, "Command not allowed"},
66 { 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS, "Files exists"},
67 { 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS, "Application exists"},
68 { 0x6F01, SC_ERROR_CARD_CMD_FAILED, "public key not complete"},
69 { 0x6F02, SC_ERROR_CARD_CMD_FAILED, "data overflow"},
70 { 0x6F03, SC_ERROR_CARD_CMD_FAILED, "invalid command sequence"},
71 { 0x6F05, SC_ERROR_CARD_CMD_FAILED, "security environment invalid"},
72 { 0x6F07, SC_ERROR_FILE_NOT_FOUND, "key part not found"},
73 { 0x6F08, SC_ERROR_CARD_CMD_FAILED, "signature failed"},
74 { 0x6F0A, SC_ERROR_INCORRECT_PARAMETERS, "key format does not match key length"},
75 { 0x6F0B, SC_ERROR_INCORRECT_PARAMETERS, "length of key component inconsistent with algorithm"},
76 { 0x6F81, SC_ERROR_CARD_CMD_FAILED, "system error"}
77 };
78
79 /* internal structure to save the current security environment */
80 typedef struct starcos_ex_data_st {
81 int sec_ops; /* the currently selected security operation,
82 * i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */
83 unsigned int fix_digestInfo;
84 unsigned int pin_encoding;
85 } starcos_ex_data;
86
87 #define PIN_ENCODING_DETERMINE 0
88 #define PIN_ENCODING_DEFAULT SC_PIN_ENCODING_GLP
89
90 // known pin formats for StarCOS 3.x cards
91 #define PIN_FORMAT_F1 0x11
92 #define PIN_FORMAT_F2 0x12
93 #define PIN_FORMAT_RSA 0x1230
94 #define PIN_FORMAT_BCD 0x13
95 #define PIN_FORMAT_ASCII 0x14
96 #define PIN_FORMAT_PW_ASCII 0x21
97 // default is the Format 2 PIN Block which is GLP in OpenSC
98 #define PIN_FORMAT_DEFAULT PIN_FORMAT_F2
99
100 #define CHECK_NOT_SUPPORTED_V3_4(card) \
101 do { \
102 if ((card)->type == SC_CARD_TYPE_STARCOS_V3_4) { \
103 sc_log((card)->ctx, \
104 "not supported for STARCOS 3.4 cards"); \
105 return SC_ERROR_NOT_SUPPORTED; \
106 } \
107 } while (0);
108
109 /* the starcos part */
starcos_match_card(sc_card_t * card)110 static int starcos_match_card(sc_card_t *card)
111 {
112 int i;
113
114 i = _sc_match_atr(card, starcos_atrs, &card->type);
115 if (i < 0)
116 return 0;
117 return 1;
118 }
119
120
121 typedef struct starcos_ctrl_ref_template_st {
122 unsigned int transmission_format;
123 #if 0
124 // not relevant values for now
125 unsigned int se_reference;
126 unsigned int ssec_initial_value;
127 #endif
128 } starcos_ctrl_ref_template;
129
130 // tags
131 #define TAG_STARCOS35_PIN_REFERENCE 0x88
132 #define TAG_STARCOS3X_SUPPORTED_SEC_MECHANISMS_tag 0x7B
133 #define TAG_STARCOS3X_CTRL_REF_TEMPLATE 0xA4
134 #define TAG_STARCOS3X_TRANSMISSION_FORMAT 0x89
135
136 static const char * starcos_ef_pwdd = "3F000015";
137 static const char * starcos_ef_keyd = "3F000013";
138
139 /**
140 * Parses supported securiy mechanisms record data.
141 * It returns SC_SUCCESS and the ctrl_ref_template structure data on success
142 */
starcos_parse_supported_sec_mechanisms(struct sc_card * card,const unsigned char * buf,size_t buflen,starcos_ctrl_ref_template * ctrl_ref_template)143 static int starcos_parse_supported_sec_mechanisms(struct sc_card *card, const unsigned char * buf, size_t buflen, starcos_ctrl_ref_template * ctrl_ref_template)
144 {
145 struct sc_context *ctx = card->ctx;
146 const unsigned char *supported_sec_mechanisms_tag = NULL;
147 size_t taglen;
148
149 LOG_FUNC_CALLED(ctx);
150
151 supported_sec_mechanisms_tag = sc_asn1_find_tag(ctx, buf, buflen, TAG_STARCOS3X_SUPPORTED_SEC_MECHANISMS_tag, &taglen);
152 if (supported_sec_mechanisms_tag != NULL && taglen >= 1) {
153 const unsigned char *tx_fmt_tag = NULL;
154 const unsigned char *ctrl_ref_template_tag = NULL;
155 size_t supported_sec_mechanisms_taglen = taglen;
156
157 // control-reference template is either included in the supported security mechanisms tag or it can be the CRT tag itself (EF.PWDD)
158 ctrl_ref_template_tag = sc_asn1_find_tag(ctx, supported_sec_mechanisms_tag, taglen, TAG_STARCOS3X_CTRL_REF_TEMPLATE, &taglen);
159 if ( ctrl_ref_template_tag == NULL || taglen == 0 ) {
160 ctrl_ref_template_tag = supported_sec_mechanisms_tag;
161 taglen = supported_sec_mechanisms_taglen;
162 }
163
164 tx_fmt_tag = sc_asn1_find_tag(ctx, ctrl_ref_template_tag, taglen, TAG_STARCOS3X_TRANSMISSION_FORMAT, &taglen);
165 if ( tx_fmt_tag != NULL && taglen >= 1 ) {
166 ctrl_ref_template->transmission_format = *(tx_fmt_tag + 0);
167 LOG_FUNC_RETURN(ctx, SC_SUCCESS);
168 }
169 }
170
171 LOG_FUNC_RETURN(ctx, SC_ERROR_TEMPLATE_NOT_FOUND);
172 }
173
starcos_determine_pin_format34(sc_card_t * card,unsigned int * pin_format)174 static int starcos_determine_pin_format34(sc_card_t *card, unsigned int * pin_format)
175 {
176 struct sc_context *ctx = card->ctx;
177 struct sc_path path;
178 struct sc_file *file;
179 unsigned char buf[256];
180 int rv;
181 int retval = SC_SUCCESS;
182 int rec_no=1;
183
184 LOG_FUNC_CALLED(ctx);
185
186 sc_format_path(starcos_ef_pwdd, &path);
187 rv = sc_select_file(card, &path, &file);
188 LOG_TEST_RET(ctx, rv, "Cannot select EF.PWDD file");
189
190 if ( (rv = sc_read_record(card, rec_no, buf, sizeof(buf), SC_RECORD_BY_REC_NR)) > 0 ) {
191 starcos_ctrl_ref_template ctrl_ref_template;
192 memset((void*)&ctrl_ref_template, 0, sizeof(ctrl_ref_template));
193 rv = starcos_parse_supported_sec_mechanisms(card, buf, rv, &ctrl_ref_template);
194 if ( rv == SC_SUCCESS ) {
195 *pin_format = ctrl_ref_template.transmission_format;
196 sc_log(ctx, "Determined StarCOS 3.4 PIN format: 0x%x", *pin_format);
197 } else {
198 sc_log(ctx, "Failed to parse record %d of EF.PWD, err=%d", rec_no, rv);
199 retval = rv;
200 }
201 } else {
202 sc_log(ctx, "Failed to read record %d of EF.PWDD, err=%d", rec_no, rv);
203 retval = rv;
204 }
205
206 sc_file_free(file);
207 LOG_FUNC_RETURN(ctx, retval);
208 }
209
starcos_determine_pin_format35(sc_card_t * card,unsigned int * pin_format)210 static int starcos_determine_pin_format35(sc_card_t *card, unsigned int * pin_format)
211 {
212 struct sc_context *ctx = card->ctx;
213 struct sc_path path;
214 struct sc_file *file;
215 unsigned char buf[256];
216 int rv;
217 int retval = SC_ERROR_RECORD_NOT_FOUND;
218 int rec_no=1;
219 starcos_ctrl_ref_template ctrl_ref_template;
220
221 LOG_FUNC_CALLED(ctx);
222
223 sc_format_path(starcos_ef_keyd, &path);
224 rv = sc_select_file(card, &path, &file);
225 LOG_TEST_RET(ctx, rv, "Cannot select EF.KEYD file");
226
227 while ( (rv = sc_read_record(card, rec_no++, buf, sizeof(buf), SC_RECORD_BY_REC_NR)) > 0 ) {
228 if ( buf[0] != TAG_STARCOS35_PIN_REFERENCE ) continue;
229
230 memset((void*)&ctrl_ref_template, 0, sizeof(ctrl_ref_template));
231 rv = starcos_parse_supported_sec_mechanisms(card, buf, rv, &ctrl_ref_template);
232 if ( rv == SC_SUCCESS ) {
233 *pin_format = ctrl_ref_template.transmission_format;
234 sc_log(ctx, "Determined StarCOS 3.5 PIN format: 0x%x", *pin_format);
235 retval = rv;
236 // assuming that all PINs and PUKs have the same transmission format
237 break;
238 } else {
239 sc_log(ctx, "Failed to parse record %d of EF.KEYD, err=%d", rec_no-1, rv);
240 retval = rv;
241 }
242 }
243
244 sc_file_free(file);
245 LOG_FUNC_RETURN(ctx, retval);
246 }
247
248 /**
249 * Determine v3.x PIN encoding by parsing either
250 * EF.PWDD (for v3.4) or EF.KEYD (for v3.5)
251 *
252 * It returns an OpenSC PIN encoding, using the default value on failure
253 */
starcos_determine_pin_encoding(sc_card_t * card)254 static unsigned int starcos_determine_pin_encoding(sc_card_t *card)
255 {
256 unsigned int pin_format = PIN_FORMAT_DEFAULT;
257 unsigned int encoding = PIN_ENCODING_DETERMINE;
258
259 if ( card->type == SC_CARD_TYPE_STARCOS_V3_4 ) {
260 starcos_determine_pin_format34(card, &pin_format);
261 } else if ( card->type == SC_CARD_TYPE_STARCOS_V3_5 ) {
262 starcos_determine_pin_format35(card, &pin_format);
263 }
264
265 switch (pin_format) {
266 case PIN_FORMAT_PW_ASCII:
267 case PIN_FORMAT_ASCII:
268 encoding = SC_PIN_ENCODING_ASCII;
269 break;
270 case PIN_FORMAT_BCD:
271 encoding = SC_PIN_ENCODING_BCD;
272 break;
273 case PIN_FORMAT_F1:
274 case PIN_FORMAT_F2:
275 encoding = SC_PIN_ENCODING_GLP;
276 break;
277 }
278
279 sc_log(card->ctx, "Determined PIN encoding: %d", encoding);
280 return encoding;
281 }
282
283
284
starcos_init(sc_card_t * card)285 static int starcos_init(sc_card_t *card)
286 {
287 unsigned int flags;
288 starcos_ex_data *ex_data;
289
290 ex_data = calloc(1, sizeof(starcos_ex_data));
291 if (ex_data == NULL)
292 return SC_ERROR_OUT_OF_MEMORY;
293
294 card->name = "STARCOS";
295 card->cla = 0x00;
296 card->drv_data = (void *)ex_data;
297 ex_data->pin_encoding = PIN_ENCODING_DETERMINE;
298
299 flags = SC_ALGORITHM_RSA_PAD_PKCS1
300 | SC_ALGORITHM_ONBOARD_KEY_GEN
301 | SC_ALGORITHM_RSA_PAD_ISO9796
302 | SC_ALGORITHM_RSA_HASH_NONE
303 | SC_ALGORITHM_RSA_HASH_SHA1
304 | SC_ALGORITHM_RSA_HASH_MD5
305 | SC_ALGORITHM_RSA_HASH_RIPEMD160
306 | SC_ALGORITHM_RSA_HASH_MD5_SHA1;
307
308 card->caps = SC_CARD_CAP_RNG;
309
310 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
311 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
312 if (card->type == SC_CARD_TYPE_STARCOS_V3_4)
313 card->name = "STARCOS 3.4";
314 else
315 card->name = "STARCOS 3.5";
316 card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
317 card->caps |= SC_CARD_CAP_APDU_EXT;
318
319 flags |= SC_CARD_FLAG_RNG
320 | SC_ALGORITHM_RSA_HASH_SHA224
321 | SC_ALGORITHM_RSA_HASH_SHA256
322 | SC_ALGORITHM_RSA_HASH_SHA384
323 | SC_ALGORITHM_RSA_HASH_SHA512;
324
325 _sc_card_add_rsa_alg(card, 512, flags, 0x10001);
326 _sc_card_add_rsa_alg(card, 768, flags, 0x10001);
327 _sc_card_add_rsa_alg(card,1024, flags, 0x10001);
328 _sc_card_add_rsa_alg(card,1728, flags, 0x10001);
329 _sc_card_add_rsa_alg(card,1976, flags, 0x10001);
330 _sc_card_add_rsa_alg(card,2048, flags, 0x10001);
331 } else {
332 _sc_card_add_rsa_alg(card, 512, flags, 0x10001);
333 _sc_card_add_rsa_alg(card, 768, flags, 0x10001);
334 _sc_card_add_rsa_alg(card,1024, flags, 0x10001);
335
336 /* we need read_binary&friends with max 128 bytes per read */
337 card->max_send_size = 128;
338 card->max_recv_size = 128;
339 }
340
341 if (sc_parse_ef_atr(card) == SC_SUCCESS) {
342 if (card->ef_atr->card_capabilities & ISO7816_CAP_EXTENDED_LENGTH) {
343 card->caps |= SC_CARD_CAP_APDU_EXT;
344 }
345 if (card->ef_atr->max_response_apdu > 0) {
346 card->max_recv_size = card->ef_atr->max_response_apdu;
347 }
348 if (card->ef_atr->max_command_apdu > 0) {
349 card->max_send_size = card->ef_atr->max_command_apdu;
350 }
351 }
352
353 if ( ex_data->pin_encoding == PIN_ENCODING_DETERMINE ) {
354 // about to determine PIN encoding
355 ex_data->pin_encoding = starcos_determine_pin_encoding(card);
356 }
357
358 return 0;
359 }
360
starcos_finish(sc_card_t * card)361 static int starcos_finish(sc_card_t *card)
362 {
363 if (card->drv_data)
364 free((starcos_ex_data *)card->drv_data);
365 return 0;
366 }
367
process_fci(sc_context_t * ctx,sc_file_t * file,const u8 * buf,size_t buflen)368 static int process_fci(sc_context_t *ctx, sc_file_t *file,
369 const u8 *buf, size_t buflen)
370 {
371 /* NOTE: According to the Starcos S 2.1 manual it's possible
372 * that a SELECT DF returns as a FCI arbitrary data which
373 * is stored in a object file (in the corresponding DF)
374 * with the tag 0x6f.
375 */
376
377 size_t taglen, len = buflen;
378 const u8 *tag = NULL, *p;
379
380 sc_log(ctx, "processing FCI bytes\n");
381
382 if (buflen < 2)
383 return SC_ERROR_INTERNAL;
384 if (buf[0] != 0x6f)
385 return SC_ERROR_INVALID_DATA;
386 len = (size_t)buf[1];
387 if (buflen - 2 < len)
388 return SC_ERROR_INVALID_DATA;
389 p = buf + 2;
390
391 /* defaults */
392 file->type = SC_FILE_TYPE_WORKING_EF;
393 file->ef_structure = SC_FILE_EF_UNKNOWN;
394 file->shareable = 0;
395 file->record_length = 0;
396 file->size = 0;
397
398 tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
399 if (tag != NULL && taglen >= 2) {
400 int bytes = (tag[0] << 8) + tag[1];
401 sc_log(ctx,
402 " bytes in file: %d\n", bytes);
403 file->size = bytes;
404 }
405
406 tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
407 if (tag != NULL) {
408 const char *type = "unknown";
409 const char *structure = "unknown";
410
411 if (taglen == 1 && tag[0] == 0x01) {
412 /* transparent EF */
413 type = "working EF";
414 structure = "transparent";
415 file->type = SC_FILE_TYPE_WORKING_EF;
416 file->ef_structure = SC_FILE_EF_TRANSPARENT;
417 } else if (taglen == 1 && tag[0] == 0x11) {
418 /* object EF */
419 type = "working EF";
420 structure = "object";
421 file->type = SC_FILE_TYPE_WORKING_EF;
422 file->ef_structure = SC_FILE_EF_TRANSPARENT; /* TODO */
423 } else if (taglen == 3 && tag[1] == 0x21) {
424 type = "working EF";
425 file->record_length = tag[2];
426 file->type = SC_FILE_TYPE_WORKING_EF;
427 /* linear fixed, cyclic or compute */
428 switch ( tag[0] )
429 {
430 case 0x02:
431 structure = "linear fixed";
432 file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
433 break;
434 case 0x07:
435 structure = "cyclic";
436 file->ef_structure = SC_FILE_EF_CYCLIC;
437 break;
438 case 0x17:
439 structure = "compute";
440 file->ef_structure = SC_FILE_EF_UNKNOWN;
441 break;
442 default:
443 structure = "unknown";
444 file->ef_structure = SC_FILE_EF_UNKNOWN;
445 file->record_length = 0;
446 break;
447 }
448 }
449
450 sc_log(ctx,
451 " type: %s\n", type);
452 sc_log(ctx,
453 " EF structure: %s\n", structure);
454 }
455 file->magic = SC_FILE_MAGIC;
456
457 return SC_SUCCESS;
458 }
459
process_fci_v3_4(sc_context_t * ctx,sc_file_t * file,const u8 * buf,size_t buflen)460 static int process_fci_v3_4(sc_context_t *ctx, sc_file_t *file,
461 const u8 *buf, size_t buflen)
462 {
463 size_t taglen, len = buflen;
464 const u8 *tag = NULL, *p;
465
466 sc_log(ctx,
467 "processing %"SC_FORMAT_LEN_SIZE_T"u FCI bytes\n", buflen);
468
469 if (buflen < 2)
470 return SC_ERROR_INTERNAL;
471 if (buf[0] != 0x6f)
472 return SC_ERROR_INVALID_DATA;
473 len = (size_t)buf[1];
474 if (buflen - 2 < len)
475 return SC_ERROR_INVALID_DATA;
476
477 /* defaults */
478 file->type = SC_FILE_TYPE_WORKING_EF;
479 if (len == 0) {
480 SC_FUNC_RETURN(ctx, 2, SC_SUCCESS);
481 }
482
483 p = buf + 2;
484 file->ef_structure = SC_FILE_TYPE_DF;
485 file->shareable = 1;
486 tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
487 if (tag != NULL && taglen > 0 && taglen <= 16) {
488 memcpy(file->name, tag, taglen);
489 file->namelen = taglen;
490 sc_log(ctx, "filename %s",
491 sc_dump_hex(file->name, file->namelen));
492 }
493 return SC_SUCCESS;
494 }
495
process_fcp_v3_4(sc_context_t * ctx,sc_file_t * file,const u8 * buf,size_t buflen)496 static int process_fcp_v3_4(sc_context_t *ctx, sc_file_t *file,
497 const u8 *buf, size_t buflen)
498 {
499 size_t taglen, len = buflen;
500 const u8 *tag = NULL, *p;
501
502 sc_log(ctx,
503 "processing %"SC_FORMAT_LEN_SIZE_T"u FCP bytes\n", buflen);
504
505 if (buflen < 2)
506 return SC_ERROR_INTERNAL;
507 if (buf[0] != 0x62)
508 return SC_ERROR_INVALID_DATA;
509 len = (size_t)buf[1];
510 if (buflen - 2 < len)
511 return SC_ERROR_INVALID_DATA;
512 p = buf + 2;
513
514 tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
515 if (tag != NULL && taglen >= 2) {
516 int bytes = (tag[0] << 8) + tag[1];
517 sc_log(ctx,
518 " bytes in file: %d\n", bytes);
519 file->size = bytes;
520 }
521
522 tag = sc_asn1_find_tag(ctx, p, len, 0xc5, &taglen);
523 if (tag != NULL && taglen >= 2) {
524 int bytes = (tag[0] << 8) + tag[1];
525 sc_log(ctx,
526 " bytes in file 2: %d\n", bytes);
527 file->size = bytes;
528 }
529
530 tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
531 if (tag != NULL) {
532 const char *type = "unknown";
533 const char *structure = "unknown";
534
535 if (taglen >= 1) {
536 unsigned char byte = tag[0];
537 if (byte & 0x40) {
538 file->shareable = 1;
539 }
540 if (byte == 0x38) {
541 type = "DF";
542 file->type = SC_FILE_TYPE_DF;
543 file->shareable = 1;
544 }
545 switch (byte & 7) {
546 case 1:
547 /* transparent EF */
548 type = "working EF";
549 structure = "transparent";
550 file->type = SC_FILE_TYPE_WORKING_EF;
551 file->ef_structure = SC_FILE_EF_TRANSPARENT;
552 break;
553 case 2:
554 /* linear fixed EF */
555 type = "working EF";
556 structure = "linear fixed";
557 file->type = SC_FILE_TYPE_WORKING_EF;
558 file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
559 break;
560 case 4:
561 /* linear variable EF */
562 type = "working EF";
563 structure = "linear variable";
564 file->type = SC_FILE_TYPE_WORKING_EF;
565 file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
566 break;
567 case 6:
568 /* cyclic EF */
569 type = "working EF";
570 structure = "cyclic";
571 file->type = SC_FILE_TYPE_WORKING_EF;
572 file->ef_structure = SC_FILE_EF_CYCLIC;
573 break;
574 default:
575 /* use defaults from above */
576 break;
577 }
578 }
579 sc_log(ctx,
580 " type: %s\n", type);
581 sc_log(ctx,
582 " EF structure: %s\n", structure);
583 if (taglen >= 2) {
584 if (tag[1] != 0x41 || taglen != 5) {
585 SC_FUNC_RETURN(ctx, 2,SC_ERROR_INVALID_DATA);
586 }
587 /* formatted EF */
588 file->record_length = (tag[2] << 8) + tag[3];
589 file->record_count = tag[4];
590 sc_log(ctx,
591 " rec_len: %"SC_FORMAT_LEN_SIZE_T"u rec_cnt: %"SC_FORMAT_LEN_SIZE_T"u\n\n",
592 file->record_length, file->record_count);
593 }
594 }
595
596 tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
597 if (tag != NULL && taglen >= 2) {
598 file->id = (tag[0] << 8) | tag[1];
599 sc_log(ctx, " file identifier: 0x%02X%02X\n",
600 tag[0], tag[1]);
601 }
602
603 tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
604 if (tag != NULL && taglen > 0 && taglen <= 16) {
605 memcpy(file->name, tag, taglen);
606 file->namelen = taglen;
607 sc_log(ctx, " filename %s",
608 sc_dump_hex(file->name, file->namelen));
609 }
610
611 tag = sc_asn1_find_tag(ctx, p, len, 0x8a, &taglen);
612 if (tag != NULL && taglen == 1) {
613 char* status = "unknown";
614 switch (tag[0]) {
615 case 1:
616 status = "creation";
617 file->status = SC_FILE_STATUS_CREATION;
618 break;
619 case 5:
620 status = "operational active";
621 file->status = SC_FILE_STATUS_ACTIVATED;
622 break;
623 case 12:
624 case 13:
625 status = "creation";
626 file->status = SC_FILE_STATUS_INVALIDATED;
627 break;
628 default:
629 break;
630 }
631 sc_log(ctx, " file status: %s\n", status);
632 }
633
634 file->magic = SC_FILE_MAGIC;
635 return SC_SUCCESS;
636 }
637
starcos_select_aid(sc_card_t * card,u8 aid[16],size_t len,sc_file_t ** file_out)638 static int starcos_select_aid(sc_card_t *card,
639 u8 aid[16], size_t len,
640 sc_file_t **file_out)
641 {
642 sc_apdu_t apdu;
643 int r;
644 size_t i = 0;
645
646 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C);
647 apdu.lc = len;
648 apdu.data = (u8*)aid;
649 apdu.datalen = len;
650 apdu.resplen = 0;
651 apdu.le = 0;
652 r = sc_transmit_apdu(card, &apdu);
653 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
654
655 /* check return value */
656 if (!(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) && apdu.sw1 != 0x61 )
657 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
658
659 /* update cache */
660 card->cache.current_path.type = SC_PATH_TYPE_DF_NAME;
661 card->cache.current_path.len = len;
662 memcpy(card->cache.current_path.value, aid, len);
663
664 if (file_out) {
665 sc_file_t *file = sc_file_new();
666 if (!file)
667 LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
668 file->type = SC_FILE_TYPE_DF;
669 file->ef_structure = SC_FILE_EF_UNKNOWN;
670 file->path.len = 0;
671 file->size = 0;
672 /* AID */
673 for (i = 0; i < len; i++)
674 file->name[i] = aid[i];
675 file->namelen = len;
676 file->id = 0x0000;
677 file->magic = SC_FILE_MAGIC;
678 *file_out = file;
679 }
680 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
681 }
682
starcos_select_fid(sc_card_t * card,unsigned int id_hi,unsigned int id_lo,sc_file_t ** file_out,int is_file)683 static int starcos_select_fid(sc_card_t *card,
684 unsigned int id_hi, unsigned int id_lo,
685 sc_file_t **file_out, int is_file)
686 {
687 sc_apdu_t apdu;
688 u8 data[] = {id_hi & 0xff, id_lo & 0xff};
689 u8 resp[SC_MAX_APDU_BUFFER_SIZE];
690 int bIsDF = 0, r;
691 int isFCP = 0;
692 int isMF = 0;
693
694 /* request FCI to distinguish between EFs and DFs */
695 sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00);
696 apdu.p2 = 0x00;
697 apdu.resp = (u8*)resp;
698 apdu.resplen = SC_MAX_APDU_BUFFER_SIZE;
699 apdu.le = 256;
700 apdu.lc = 2;
701 apdu.data = (u8*)data;
702 apdu.datalen = 2;
703
704 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
705 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
706 if (id_hi == 0x3f && id_lo == 0x0) {
707 apdu.p1 = 0x0;
708 apdu.p2 = 0x0;
709 isMF = 1;
710 } else if (file_out || is_file) {
711 // last component (i.e. file or path)
712 apdu.p1 = 0x2;
713 apdu.p2 = 0x4;
714 } else {
715 // path component
716 apdu.p1 = 0x1;
717 apdu.p2 = 0x0;
718 }
719 }
720
721 r = sc_transmit_apdu(card, &apdu);
722 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
723
724 if (apdu.p2 == 0x00 && apdu.sw1 == 0x62 && apdu.sw2 == 0x84 ) {
725 /* no FCI => we have a DF (see comment in process_fci()) */
726 bIsDF = 1;
727 apdu.p2 = 0x0C;
728 apdu.cse = SC_APDU_CASE_3_SHORT;
729 apdu.resplen = 0;
730 apdu.le = 0;
731 r = sc_transmit_apdu(card, &apdu);
732 LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
733 } else if ((card->type == SC_CARD_TYPE_STARCOS_V3_4
734 || card->type == SC_CARD_TYPE_STARCOS_V3_5)
735 && apdu.p2 == 0x4 && apdu.sw1 == 0x6a && apdu.sw2 == 0x82) {
736 /* not a file, could be a path */
737 bIsDF = 1;
738 apdu.p1 = 0x1;
739 apdu.p2 = 0x0;
740 apdu.resplen = sizeof(resp);
741 apdu.le = 256;
742 apdu.lc = 2;
743 r = sc_transmit_apdu(card, &apdu);
744 LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
745 } else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && !isMF)) {
746 /* SELECT returned some data (possible FCI) =>
747 * try a READ BINARY to see if a EF is selected */
748 sc_apdu_t apdu2;
749 u8 resp2[2];
750 sc_format_apdu(card, &apdu2, SC_APDU_CASE_2_SHORT, 0xB0, 0, 0);
751 apdu2.resp = (u8*)resp2;
752 apdu2.resplen = 2;
753 apdu2.le = 1;
754 apdu2.lc = 0;
755 r = sc_transmit_apdu(card, &apdu2);
756 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
757 if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86) {
758 /* no current EF is selected => we have a DF */
759 bIsDF = 1;
760 } else {
761 isFCP = 1;
762 }
763 }
764
765 if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00))
766 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
767
768 /* update cache */
769 if (bIsDF || isMF) {
770 card->cache.current_path.type = SC_PATH_TYPE_PATH;
771 card->cache.current_path.value[0] = 0x3f;
772 card->cache.current_path.value[1] = 0x00;
773 if (id_hi == 0x3f && id_lo == 0x00)
774 card->cache.current_path.len = 2;
775 else {
776 card->cache.current_path.len = 4;
777 card->cache.current_path.value[2] = id_hi;
778 card->cache.current_path.value[3] = id_lo;
779 }
780 }
781
782 if (file_out) {
783 sc_file_t *file = sc_file_new();
784 if (!file)
785 LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
786 file->id = (id_hi << 8) + id_lo;
787 file->path = card->cache.current_path;
788
789 if (bIsDF) {
790 /* we have a DF */
791 file->type = SC_FILE_TYPE_DF;
792 file->ef_structure = SC_FILE_EF_UNKNOWN;
793 file->size = 0;
794 file->namelen = 0;
795 file->magic = SC_FILE_MAGIC;
796 *file_out = file;
797 } else {
798 /* ok, assume we have a EF */
799 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
800 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
801 if (isFCP) {
802 r = process_fcp_v3_4(card->ctx, file, apdu.resp,
803 apdu.resplen);
804 } else {
805 r = process_fci_v3_4(card->ctx, file, apdu.resp,
806 apdu.resplen);
807 }
808 } else {
809 r = process_fci(card->ctx, file, apdu.resp,
810 apdu.resplen);
811 }
812 if (r != SC_SUCCESS) {
813 sc_file_free(file);
814 return r;
815 }
816
817 *file_out = file;
818 }
819 }
820
821 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
822 }
823
starcos_select_file(sc_card_t * card,const sc_path_t * in_path,sc_file_t ** file_out)824 static int starcos_select_file(sc_card_t *card,
825 const sc_path_t *in_path,
826 sc_file_t **file_out)
827 {
828 u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
829 int r;
830 size_t i, pathlen;
831 char pbuf[SC_MAX_PATH_STRING_SIZE];
832
833 SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
834
835 r = sc_path_print(pbuf, sizeof(pbuf), &card->cache.current_path);
836 if (r != SC_SUCCESS)
837 pbuf[0] = '\0';
838
839 sc_log(card->ctx,
840 "current path (%s, %s): %s (len: %"SC_FORMAT_LEN_SIZE_T"u)\n",
841 card->cache.current_path.type == SC_PATH_TYPE_DF_NAME ?
842 "aid" : "path",
843 card->cache.valid ? "valid" : "invalid", pbuf,
844 card->cache.current_path.len);
845
846 memcpy(path, in_path->value, in_path->len);
847 pathlen = in_path->len;
848
849 if (in_path->type == SC_PATH_TYPE_FILE_ID)
850 { /* SELECT EF/DF with ID */
851 /* Select with 2byte File-ID */
852 if (pathlen != 2)
853 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS);
854 return starcos_select_fid(card, path[0], path[1], file_out, 1);
855 }
856 else if (in_path->type == SC_PATH_TYPE_DF_NAME)
857 { /* SELECT DF with AID */
858 /* Select with 1-16byte Application-ID */
859 if (card->cache.valid
860 && card->cache.current_path.type == SC_PATH_TYPE_DF_NAME
861 && card->cache.current_path.len == pathlen
862 && memcmp(card->cache.current_path.value, pathbuf, pathlen) == 0 )
863 {
864 sc_log(card->ctx, "cache hit\n");
865 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
866 }
867 else
868 return starcos_select_aid(card, pathbuf, pathlen, file_out);
869 }
870 else if (in_path->type == SC_PATH_TYPE_PATH)
871 {
872 u8 n_pathbuf[SC_MAX_PATH_SIZE];
873 int bMatch = -1;
874
875 /* Select with path (sequence of File-IDs) */
876 /* Starcos (S 2.1 and SPK 2.3) only supports one
877 * level of subdirectories, therefore a path is
878 * at most 3 FID long (the last one being the FID
879 * of a EF) => pathlen must be even and less than 6
880 */
881 if (pathlen%2 != 0 || pathlen > 6 || pathlen <= 0)
882 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
883 /* if pathlen == 6 then the first FID must be MF (== 3F00) */
884 if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
885 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
886
887 if (card->type != SC_CARD_TYPE_STARCOS_V3_4
888 && card->type != SC_CARD_TYPE_STARCOS_V3_5) {
889 /* unify path (the first FID should be MF) */
890 if (path[0] != 0x3f || path[1] != 0x00)
891 {
892 n_pathbuf[0] = 0x3f;
893 n_pathbuf[1] = 0x00;
894 memcpy(n_pathbuf+2, path, pathlen);
895 path = n_pathbuf;
896 pathlen += 2;
897 }
898 }
899
900 /* check current working directory */
901 if (card->cache.valid
902 && card->cache.current_path.type == SC_PATH_TYPE_PATH
903 && card->cache.current_path.len >= 2
904 && card->cache.current_path.len <= pathlen )
905 {
906 bMatch = 0;
907 for (i=0; i < card->cache.current_path.len; i+=2)
908 if (card->cache.current_path.value[i] == path[i]
909 && card->cache.current_path.value[i+1] == path[i+1] )
910 bMatch += 2;
911
912 if ((card->type == SC_CARD_TYPE_STARCOS_V3_4
913 || card->type == SC_CARD_TYPE_STARCOS_V3_5)
914 && bMatch > 0 && (size_t) bMatch < card->cache.current_path.len) {
915 /* we're in the wrong folder, start traversing from root */
916 bMatch = 0;
917 card->cache.current_path.len = 0;
918 }
919 }
920
921 if ( card->cache.valid && bMatch >= 0 )
922 {
923 if ( pathlen - bMatch == 2 )
924 /* we are in the right directory */
925 return starcos_select_fid(card, path[bMatch], path[bMatch+1], file_out, 1);
926 else if ( pathlen - bMatch > 2 )
927 {
928 /* two more steps to go */
929 sc_path_t new_path;
930
931 /* first step: change directory */
932 r = starcos_select_fid(card, path[bMatch], path[bMatch+1], NULL, 0);
933 LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
934
935 memset(&new_path, 0, sizeof(sc_path_t));
936 new_path.type = SC_PATH_TYPE_PATH;
937 new_path.len = pathlen - bMatch-2;
938 memcpy(new_path.value, &(path[bMatch+2]), new_path.len);
939 /* final step: select file */
940 return starcos_select_file(card, &new_path, file_out);
941 }
942 else /* if (bMatch - pathlen == 0) */
943 {
944 /* done: we are already in the
945 * requested directory */
946 sc_log(card->ctx,
947 "cache hit\n");
948 /* copy file info (if necessary) */
949 if (file_out) {
950 sc_file_t *file = sc_file_new();
951 if (!file)
952 LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
953 file->id = (path[pathlen-2] << 8) +
954 path[pathlen-1];
955 file->path = card->cache.current_path;
956 file->type = SC_FILE_TYPE_DF;
957 file->ef_structure = SC_FILE_EF_UNKNOWN;
958 file->size = 0;
959 file->namelen = 0;
960 file->magic = SC_FILE_MAGIC;
961 *file_out = file;
962 }
963 /* nothing left to do */
964 return SC_SUCCESS;
965 }
966 }
967 else
968 {
969 /* no usable cache */
970 for ( i=0; i<pathlen-2; i+=2 )
971 {
972 r = starcos_select_fid(card, path[i], path[i+1], NULL, 0);
973 LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
974 }
975 return starcos_select_fid(card, path[pathlen-2], path[pathlen-1], file_out, 1);
976 }
977 }
978 else
979 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
980 }
981
starcos_get_challenge(struct sc_card * card,unsigned char * rnd,size_t len)982 static int starcos_get_challenge(struct sc_card *card, unsigned char *rnd, size_t len)
983 {
984 LOG_FUNC_CALLED(card->ctx);
985
986 if (len > 8) {
987 len = 8;
988 }
989
990 LOG_FUNC_RETURN(card->ctx, iso_ops->get_challenge(card, rnd, len));
991 }
992
993 #define STARCOS_AC_ALWAYS 0x9f
994 #define STARCOS_AC_NEVER 0x5f
995 #define STARCOS_PINID2STATE(a) ((((a) & 0x0f) == 0x01) ? ((a) & 0x0f) : (0x0f - ((0x0f & (a)) >> 1)))
996
process_acl_entry(sc_file_t * in,unsigned int method,unsigned int in_def)997 static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def)
998 {
999 u8 def = (u8)in_def;
1000 const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method);
1001 if (!entry)
1002 return def;
1003 else if (entry->method & SC_AC_CHV) {
1004 unsigned int key_ref = entry->key_ref;
1005 if (key_ref == SC_AC_KEY_REF_NONE)
1006 return def;
1007 else if ((key_ref & 0x0f) == 1)
1008 /* SOPIN */
1009 return (key_ref & 0x80 ? 0x10 : 0x00) | 0x01;
1010 else
1011 return (key_ref & 0x80 ? 0x10 : 0x00) | STARCOS_PINID2STATE(key_ref);
1012 } else if (entry->method & SC_AC_NEVER)
1013 return STARCOS_AC_NEVER;
1014 else
1015 return def;
1016 }
1017
1018 /** starcos_process_acl
1019 * \param card pointer to the sc_card object
1020 * \param file pointer to the sc_file object
1021 * \param data pointer to a sc_starcos_create_data structure
1022 * \return SC_SUCCESS if no error occurred otherwise error code
1023 *
1024 * This function tries to create a somewhat usable Starcos spk 2.3 acl
1025 * from the OpenSC internal acl (storing the result in the supplied
1026 * sc_starcos_create_data structure).
1027 */
starcos_process_acl(sc_card_t * card,sc_file_t * file,sc_starcos_create_data * data)1028 static int starcos_process_acl(sc_card_t *card, sc_file_t *file,
1029 sc_starcos_create_data *data)
1030 {
1031 u8 tmp, *p;
1032 static const u8 def_key[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
1033
1034 if (file->type == SC_FILE_TYPE_DF && file->id == 0x3f00) {
1035 p = data->data.mf.header;
1036 memcpy(p, def_key, 8);
1037 p += 8;
1038 *p++ = (file->size >> 8) & 0xff;
1039 *p++ = file->size & 0xff;
1040 /* guess isf size (mf_size / 4) */
1041 *p++ = (file->size >> 10) & 0xff;
1042 *p++ = (file->size >> 2) & 0xff;
1043 /* ac create ef */
1044 *p++ = process_acl_entry(file,SC_AC_OP_CREATE,STARCOS_AC_ALWAYS);
1045 /* ac create key */
1046 *p++ = process_acl_entry(file,SC_AC_OP_CREATE,STARCOS_AC_ALWAYS);
1047 /* ac create df */
1048 *p++ = process_acl_entry(file,SC_AC_OP_CREATE,STARCOS_AC_ALWAYS);
1049 /* use the same ac for register df and create df */
1050 *p++ = data->data.mf.header[14];
1051 /* if sm is required use combined mode */
1052 if (file->acl[SC_AC_OP_CREATE] && (sc_file_get_acl_entry(file, SC_AC_OP_CREATE))->method & SC_AC_PRO)
1053 tmp = 0x03; /* combinde mode */
1054 else
1055 tmp = 0x00; /* no sm */
1056 *p++ = tmp; /* use the same sm mode for all ops */
1057 *p++ = tmp;
1058 *p = tmp;
1059 data->type = SC_STARCOS_MF_DATA;
1060
1061 return SC_SUCCESS;
1062 } else if (file->type == SC_FILE_TYPE_DF){
1063 p = data->data.df.header;
1064 *p++ = (file->id >> 8) & 0xff;
1065 *p++ = file->id & 0xff;
1066 if (file->namelen) {
1067 /* copy aid */
1068 *p++ = file->namelen & 0xff;
1069 memset(p, 0, 16);
1070 memcpy(p, file->name, (u8)file->namelen);
1071 p += 16;
1072 } else {
1073 /* (mis)use the fid as aid */
1074 *p++ = 2;
1075 memset(p, 0, 16);
1076 *p++ = (file->id >> 8) & 0xff;
1077 *p++ = file->id & 0xff;
1078 p += 14;
1079 }
1080 /* guess isf size */
1081 *p++ = (file->size >> 10) & 0xff; /* ISF space */
1082 *p++ = (file->size >> 2) & 0xff; /* ISF space */
1083 /* ac create ef */
1084 *p++ = process_acl_entry(file,SC_AC_OP_CREATE,STARCOS_AC_ALWAYS);
1085 /* ac create key */
1086 *p++ = process_acl_entry(file,SC_AC_OP_CREATE,STARCOS_AC_ALWAYS);
1087 /* set sm byte (same for keys and ef) */
1088 if (file->acl[SC_AC_OP_CREATE] &&
1089 (sc_file_get_acl_entry(file, SC_AC_OP_CREATE)->method &
1090 SC_AC_PRO))
1091 tmp = 0x03;
1092 else
1093 tmp = 0x00;
1094 *p++ = tmp; /* SM CR */
1095 *p = tmp; /* SM ISF */
1096
1097 data->data.df.size[0] = (file->size >> 8) & 0xff;
1098 data->data.df.size[1] = file->size & 0xff;
1099 data->type = SC_STARCOS_DF_DATA;
1100
1101 return SC_SUCCESS;
1102 } else if (file->type == SC_FILE_TYPE_WORKING_EF) {
1103 p = data->data.ef.header;
1104 *p++ = (file->id >> 8) & 0xff;
1105 *p++ = file->id & 0xff;
1106 /* ac read */
1107 *p++ = process_acl_entry(file, SC_AC_OP_READ,STARCOS_AC_ALWAYS);
1108 /* ac write */
1109 *p++ = process_acl_entry(file, SC_AC_OP_WRITE,STARCOS_AC_ALWAYS);
1110 /* ac erase */
1111 *p++ = process_acl_entry(file, SC_AC_OP_ERASE,STARCOS_AC_ALWAYS);
1112 *p++ = STARCOS_AC_ALWAYS; /* AC LOCK */
1113 *p++ = STARCOS_AC_ALWAYS; /* AC UNLOCK */
1114 *p++ = STARCOS_AC_ALWAYS; /* AC INCREASE */
1115 *p++ = STARCOS_AC_ALWAYS; /* AC DECREASE */
1116 *p++ = 0x00; /* rfu */
1117 *p++ = 0x00; /* rfu */
1118 /* use sm (in combined mode) if wanted */
1119 if ((file->acl[SC_AC_OP_READ] && (sc_file_get_acl_entry(file, SC_AC_OP_READ)->method & SC_AC_PRO)) ||
1120 (file->acl[SC_AC_OP_UPDATE] && (sc_file_get_acl_entry(file, SC_AC_OP_UPDATE)->method & SC_AC_PRO)) ||
1121 (file->acl[SC_AC_OP_WRITE] && (sc_file_get_acl_entry(file, SC_AC_OP_WRITE)->method & SC_AC_PRO)) )
1122 tmp = 0x03;
1123 else
1124 tmp = 0x00;
1125 *p++ = tmp; /* SM byte */
1126 *p++ = 0x00; /* use the least significant 5 bits
1127 * of the FID as SID */
1128 switch (file->ef_structure)
1129 {
1130 case SC_FILE_EF_TRANSPARENT:
1131 *p++ = 0x81;
1132 *p++ = (file->size >> 8) & 0xff;
1133 *p = file->size & 0xff;
1134 break;
1135 case SC_FILE_EF_LINEAR_FIXED:
1136 *p++ = 0x82;
1137 *p++ = file->record_count & 0xff;
1138 *p = file->record_length & 0xff;
1139 break;
1140 case SC_FILE_EF_CYCLIC:
1141 *p++ = 0x84;
1142 *p++ = file->record_count & 0xff;
1143 *p = file->record_length & 0xff;
1144 break;
1145 default:
1146 return SC_ERROR_INVALID_ARGUMENTS;
1147 }
1148 data->type = SC_STARCOS_EF_DATA;
1149
1150 return SC_SUCCESS;
1151 } else
1152 return SC_ERROR_INVALID_ARGUMENTS;
1153 }
1154
1155 /** starcos_create_mf
1156 * internal function to create the MF
1157 * \param card pointer to the sc_card structure
1158 * \param data pointer to a sc_starcos_create_data object
1159 * \return SC_SUCCESS or error code
1160 *
1161 * This function creates the MF based on the information stored
1162 * in the sc_starcos_create_data.mf structure. Note: CREATE END must be
1163 * called separately to activate the ACs.
1164 */
starcos_create_mf(sc_card_t * card,sc_starcos_create_data * data)1165 static int starcos_create_mf(sc_card_t *card, sc_starcos_create_data *data)
1166 {
1167 int r;
1168 sc_apdu_t apdu;
1169 sc_context_t *ctx = card->ctx;
1170
1171 CHECK_NOT_SUPPORTED_V3_4(card);
1172
1173 sc_log(ctx, "creating MF \n");
1174 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
1175 apdu.cla |= 0x80;
1176 apdu.lc = 19;
1177 apdu.datalen = 19;
1178 apdu.data = (u8 *) data->data.mf.header;
1179
1180 r = sc_transmit_apdu(card, &apdu);
1181 LOG_TEST_RET(ctx, r, "APDU transmit failed");
1182 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1183 }
1184
1185 /** starcos_create_df
1186 * internal function to create a DF
1187 * \param card pointer to the sc_card structure
1188 * \param data pointer to a sc_starcos_create_data object
1189 * \return SC_SUCCESS or error code
1190 *
1191 * This functions registers and creates a DF based in the information
1192 * stored in a sc_starcos_create_data.df data structure. Note: CREATE END must
1193 * be called separately to activate the ACs.
1194 */
starcos_create_df(sc_card_t * card,sc_starcos_create_data * data)1195 static int starcos_create_df(sc_card_t *card, sc_starcos_create_data *data)
1196 {
1197 int r;
1198 size_t len;
1199 sc_apdu_t apdu;
1200 sc_context_t *ctx = card->ctx;
1201
1202 CHECK_NOT_SUPPORTED_V3_4(card);
1203
1204 sc_log(ctx, "creating DF\n");
1205 /* first step: REGISTER DF */
1206 sc_log(ctx, "calling REGISTER DF\n");
1207
1208 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x52,
1209 data->data.df.size[0], data->data.df.size[1]);
1210 len = 3 + data->data.df.header[2];
1211 apdu.cla |= 0x80;
1212 apdu.lc = len;
1213 apdu.datalen = len;
1214 apdu.data = data->data.df.header;
1215
1216 r = sc_transmit_apdu(card, &apdu);
1217 LOG_TEST_RET(ctx, r, "APDU transmit failed");
1218 /* second step: CREATE DF */
1219 sc_log(ctx, "calling CREATE DF\n");
1220
1221 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x01, 0x00);
1222 apdu.cla |= 0x80;
1223 apdu.lc = 25;
1224 apdu.datalen = 25;
1225 apdu.data = data->data.df.header;
1226
1227 r = sc_transmit_apdu(card, &apdu);
1228 LOG_TEST_RET(ctx, r, "APDU transmit failed");
1229 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1230 }
1231
1232 /** starcos_create_ef
1233 * internal function to create a EF
1234 * \param card pointer to the sc_card structure
1235 * \param data pointer to a sc_starcos_create_data object
1236 * \return SC_SUCCESS or error code
1237 *
1238 * This function creates a EF based on the information stored in
1239 * the sc_starcos_create_data.ef data structure.
1240 */
starcos_create_ef(sc_card_t * card,sc_starcos_create_data * data)1241 static int starcos_create_ef(sc_card_t *card, sc_starcos_create_data *data)
1242 {
1243 int r;
1244 sc_apdu_t apdu;
1245 sc_context_t *ctx = card->ctx;
1246
1247 CHECK_NOT_SUPPORTED_V3_4(card);
1248
1249 sc_log(ctx, "creating EF\n");
1250
1251 sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT,0xE0,0x03,0x00);
1252 apdu.cla |= 0x80;
1253 apdu.lc = 16;
1254 apdu.datalen = 16;
1255 apdu.data = (u8 *) data->data.ef.header;
1256
1257 r = sc_transmit_apdu(card, &apdu);
1258 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1259 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1260 }
1261
1262 /** starcos_create_end
1263 * internal function to activate the ACs
1264 * \param card pointer to the sc_card structure
1265 * \param file pointer to a sc_file object
1266 * \return SC_SUCCESS or error code
1267 *
1268 * This function finishes the creation of a DF (or MF) and activates
1269 * the ACs.
1270 */
starcos_create_end(sc_card_t * card,sc_file_t * file)1271 static int starcos_create_end(sc_card_t *card, sc_file_t *file)
1272 {
1273 int r;
1274 u8 fid[2];
1275 sc_apdu_t apdu;
1276
1277 if (file->type != SC_FILE_TYPE_DF)
1278 return SC_ERROR_INVALID_ARGUMENTS;
1279
1280 CHECK_NOT_SUPPORTED_V3_4(card);
1281
1282 fid[0] = (file->id >> 8) & 0xff;
1283 fid[1] = file->id & 0xff;
1284 sc_format_apdu(card,&apdu,SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00);
1285 apdu.cla |= 0x80;
1286 apdu.lc = 2;
1287 apdu.datalen = 2;
1288 apdu.data = fid;
1289 r = sc_transmit_apdu(card, &apdu);
1290 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1291 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1292 }
1293
1294 /** starcos_create_file
1295 * \param card pointer to the sc_card structure
1296 * \param file pointer to a sc_file object
1297 * \return SC_SUCCESS or error code
1298 *
1299 * This function creates MF, DF or EF based on the supplied
1300 * information in the sc_file structure (using starcos_process_acl).
1301 */
starcos_create_file(sc_card_t * card,sc_file_t * file)1302 static int starcos_create_file(sc_card_t *card, sc_file_t *file)
1303 {
1304 int r;
1305 sc_starcos_create_data data;
1306
1307 CHECK_NOT_SUPPORTED_V3_4(card);
1308
1309 SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1310
1311 if (file->type == SC_FILE_TYPE_DF) {
1312 if (file->id == 0x3f00) {
1313 /* CREATE MF */
1314 r = starcos_process_acl(card, file, &data);
1315 if (r != SC_SUCCESS)
1316 return r;
1317 return starcos_create_mf(card, &data);
1318 } else {
1319 /* CREATE DF */
1320 r = starcos_process_acl(card, file, &data);
1321 if (r != SC_SUCCESS)
1322 return r;
1323 return starcos_create_df(card, &data);
1324 }
1325 } else if (file->type == SC_FILE_TYPE_WORKING_EF) {
1326 /* CREATE EF */
1327 r = starcos_process_acl(card, file, &data);
1328 if (r != SC_SUCCESS)
1329 return r;
1330 return starcos_create_ef(card, &data);
1331 } else
1332 return SC_ERROR_INVALID_ARGUMENTS;
1333 }
1334
1335 /** starcos_erase_card
1336 * internal function to restore the delivery state
1337 * \param card pointer to the sc_card object
1338 * \return SC_SUCCESS or error code
1339 *
1340 * This function deletes the MF (for 'test cards' only).
1341 */
starcos_erase_card(sc_card_t * card)1342 static int starcos_erase_card(sc_card_t *card)
1343 { /* restore the delivery state */
1344 int r;
1345 u8 sbuf[2];
1346 sc_apdu_t apdu;
1347
1348 sbuf[0] = 0x3f;
1349 sbuf[1] = 0x00;
1350 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
1351 apdu.cla |= 0x80;
1352 apdu.lc = 2;
1353 apdu.datalen = 2;
1354 apdu.data = sbuf;
1355
1356 r = sc_transmit_apdu(card, &apdu);
1357 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1358 sc_invalidate_cache(card);
1359 if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
1360 /* no MF to delete, ignore error */
1361 return SC_SUCCESS;
1362 else return sc_check_sw(card, apdu.sw1, apdu.sw2);
1363 }
1364
1365 #define STARCOS_WKEY_CSIZE 124
1366
1367 /** starcos_write_key
1368 * set key in isf
1369 * \param card pointer to the sc_card object
1370 * \param data pointer to a sc_starcos_wkey_data structure
1371 * \return SC_SUCCESS or error code
1372 *
1373 * This function installs a key header in the ISF (based on the
1374 * information supplied in the sc_starcos_wkey_data structure)
1375 * and set a supplied key (depending on the mode).
1376 */
starcos_write_key(sc_card_t * card,sc_starcos_wkey_data * data)1377 static int starcos_write_key(sc_card_t *card, sc_starcos_wkey_data *data)
1378 {
1379 int r;
1380 u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1381 const u8 *p;
1382 size_t len = sizeof(sbuf), tlen, offset = 0;
1383 sc_apdu_t apdu;
1384
1385 CHECK_NOT_SUPPORTED_V3_4(card);
1386
1387 if (data->mode == 0) { /* mode == 0 => install */
1388 /* install key header */
1389 sbuf[0] = 0xc1; /* key header tag */
1390 sbuf[1] = 0x0c; /* key header length */
1391 memcpy(sbuf + 2, data->key_header, 12);
1392 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xf4,
1393 data->mode, 0x00);
1394 apdu.cla |= 0x80;
1395 apdu.lc = 14;
1396 apdu.datalen = 14;
1397 apdu.data = sbuf;
1398
1399 r = sc_transmit_apdu(card, &apdu);
1400 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1401 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1402 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1403 if (data->key == NULL)
1404 return SC_SUCCESS;
1405 }
1406
1407 if (data->key == NULL)
1408 return SC_ERROR_INVALID_ARGUMENTS;
1409
1410 p = data->key;
1411 tlen = data->key_len;
1412 while (tlen != 0) {
1413 /* transmit the key in chunks of STARCOS_WKEY_CSIZE bytes */
1414 u8 clen = tlen < STARCOS_WKEY_CSIZE ? tlen : STARCOS_WKEY_CSIZE;
1415 sbuf[0] = 0xc2;
1416 sbuf[1] = 3 + clen;
1417 sbuf[2] = data->kid;
1418 sbuf[3] = (offset >> 8) & 0xff;
1419 sbuf[4] = offset & 0xff;
1420 memcpy(sbuf+5, p, clen);
1421 len = 5 + clen;
1422 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xf4,
1423 data->mode, 0x00);
1424 apdu.cla |= 0x80;
1425 apdu.lc = len;
1426 apdu.datalen = len;
1427 apdu.data = sbuf;
1428
1429 r = sc_transmit_apdu(card, &apdu);
1430 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1431 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1432 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1433 offset += clen;
1434 p += clen;
1435 tlen -= clen;
1436 }
1437 return SC_SUCCESS;
1438 }
1439
1440 /** starcos_gen_key
1441 * generate public key pair
1442 * \param card pointer to the sc_card object
1443 * \param data pointer to a sc_starcos_gen_key_data structure
1444 * \return SC_SUCCESS or error code
1445 *
1446 * This function generates a public key pair and stores the created
1447 * private key in the ISF (specified by the KID).
1448 */
starcos_gen_key(sc_card_t * card,sc_starcos_gen_key_data * data)1449 static int starcos_gen_key(sc_card_t *card, sc_starcos_gen_key_data *data)
1450 {
1451 int r;
1452 size_t i, len = data->key_length >> 3;
1453 sc_apdu_t apdu;
1454 u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
1455 u8 sbuf[2], *p, *q;
1456
1457 CHECK_NOT_SUPPORTED_V3_4(card);
1458
1459 /* generate key */
1460 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00,
1461 data->key_id);
1462 apdu.le = 0;
1463 sbuf[0] = (u8)(data->key_length >> 8);
1464 sbuf[1] = (u8)(data->key_length);
1465 apdu.data = sbuf;
1466 apdu.lc = 2;
1467 apdu.datalen = 2;
1468 r = sc_transmit_apdu(card, &apdu);
1469 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1470 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1471 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1472 /* read public key via READ PUBLIC KEY */
1473 sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xf0, 0x9c, 0x00);
1474 sbuf[0] = data->key_id;
1475 apdu.cla |= 0x80;
1476 apdu.data = sbuf;
1477 apdu.datalen = 1;
1478 apdu.lc = 1;
1479 apdu.resp = rbuf;
1480 apdu.resplen = sizeof(rbuf);
1481 apdu.le = 256;
1482 r = sc_transmit_apdu(card, &apdu);
1483 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1484 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1485 return sc_check_sw(card, apdu.sw1, apdu.sw2);
1486
1487 data->modulus = malloc(len);
1488 if (!data->modulus)
1489 return SC_ERROR_OUT_OF_MEMORY;
1490 p = data->modulus;
1491 /* XXX use tags to find starting position of the modulus */
1492 q = &rbuf[18];
1493 /* LSB to MSB -> MSB to LSB */
1494 for (i = len; i != 0; i--)
1495 *p++ = q[i - 1];
1496
1497 return SC_SUCCESS;
1498 }
1499
1500 /** starcos_set_security_env
1501 * sets the security environment
1502 * \param card pointer to the sc_card object
1503 * \param env pointer to a sc_security_env object
1504 * \param se_num not used here
1505 * \return SC_SUCCESS on success or an error code
1506 *
1507 * This function sets the security environment (using the starcos spk 2.3
1508 * command MANAGE SECURITY ENVIRONMENT). In case a COMPUTE SIGNATURE
1509 * operation is requested , this function tries to detect whether
1510 * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE must be used for signature
1511 * calculation.
1512 */
starcos_set_security_env(sc_card_t * card,const sc_security_env_t * env,int se_num)1513 static int starcos_set_security_env(sc_card_t *card,
1514 const sc_security_env_t *env,
1515 int se_num)
1516 {
1517 u8 *p, *pp;
1518 int r, operation = env->operation;
1519 sc_apdu_t apdu;
1520 u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1521 starcos_ex_data *ex_data = (starcos_ex_data *)card->drv_data;
1522
1523 p = sbuf;
1524
1525 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
1526 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
1527 if (!(env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) ||
1528 !(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || env->key_ref_len != 1) {
1529 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
1530 }
1531
1532 /* don't know what these mean but doesn't matter as card seems to take
1533 * algorithm / cipher from PKCS#1 padding prefix */
1534 *p++ = 0x84;
1535 *p++ = 0x01;
1536 if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
1537 *p++ = *env->key_ref | 0x80;
1538 } else {
1539 *p++ = *env->key_ref;
1540 }
1541
1542 switch (operation) {
1543 case SC_SEC_OPERATION_SIGN:
1544 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6);
1545
1546 /* algorithm / cipher selector? */
1547 *p++ = 0x89;
1548 *p++ = 0x02;
1549 *p++ = 0x13;
1550 *p++ = 0x23;
1551 break;
1552
1553 case SC_SEC_OPERATION_DECIPHER:
1554 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8);
1555
1556 /* algorithm / cipher selector? */
1557 *p++ = 0x89;
1558 *p++ = 0x02;
1559 *p++ = 0x11;
1560 if (card->type == SC_CARD_TYPE_STARCOS_V3_4)
1561 *p++ = 0x30;
1562 else
1563 *p++ = 0x31;
1564 break;
1565
1566 default:
1567 sc_log(card->ctx,
1568 "not supported for STARCOS 3.4 cards");
1569 return SC_ERROR_NOT_SUPPORTED;
1570 }
1571
1572 apdu.data = sbuf;
1573 apdu.datalen = p - sbuf;
1574 apdu.lc = p - sbuf;
1575 apdu.le = 0;
1576 r = sc_transmit_apdu(card, &apdu);
1577 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1578 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1579 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
1580
1581 if (env->algorithm_flags == SC_ALGORITHM_RSA_PAD_PKCS1) {
1582 // input data will be already padded
1583 ex_data->fix_digestInfo = 0;
1584 } else {
1585 ex_data->fix_digestInfo = env->algorithm_flags;
1586 }
1587 ex_data->sec_ops = SC_SEC_OPERATION_SIGN;
1588 return SC_SUCCESS;
1589 }
1590
1591 /* copy key reference, if present */
1592 if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
1593 if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1594 *p++ = 0x83;
1595 else
1596 *p++ = 0x84;
1597 *p++ = env->key_ref_len;
1598 memcpy(p, env->key_ref, env->key_ref_len);
1599 p += env->key_ref_len;
1600 }
1601 pp = p;
1602 if (operation == SC_SEC_OPERATION_DECIPHER){
1603 if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
1604 *p++ = 0x80;
1605 *p++ = 0x01;
1606 *p++ = 0x02;
1607 } else
1608 return SC_ERROR_INVALID_ARGUMENTS;
1609 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81,
1610 0xb8);
1611 apdu.data = sbuf;
1612 apdu.datalen = p - sbuf;
1613 apdu.lc = p - sbuf;
1614 apdu.le = 0;
1615 r = sc_transmit_apdu(card, &apdu);
1616 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1617 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1618 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
1619 return SC_SUCCESS;
1620 }
1621 /* try COMPUTE SIGNATURE */
1622 if (operation == SC_SEC_OPERATION_SIGN && (
1623 env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 ||
1624 env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)) {
1625 if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
1626 *p++ = 0x80;
1627 *p++ = 0x01;
1628 *p++ = env->algorithm_ref & 0xFF;
1629 } else if (env->flags & SC_SEC_ENV_ALG_PRESENT &&
1630 env->algorithm == SC_ALGORITHM_RSA) {
1631 /* set the method to use based on the algorithm_flags */
1632 *p++ = 0x80;
1633 *p++ = 0x01;
1634 if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
1635 if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
1636 *p++ = 0x12;
1637 else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
1638 *p++ = 0x22;
1639 else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
1640 *p++ = 0x32;
1641 else {
1642 /* can't use COMPUTE SIGNATURE =>
1643 * try INTERNAL AUTHENTICATE */
1644 p = pp;
1645 operation = SC_SEC_OPERATION_AUTHENTICATE;
1646 goto try_authenticate;
1647 }
1648 } else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796) {
1649 if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
1650 *p++ = 0x11;
1651 else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
1652 *p++ = 0x21;
1653 else
1654 return SC_ERROR_INVALID_ARGUMENTS;
1655 } else
1656 return SC_ERROR_INVALID_ARGUMENTS;
1657 }
1658 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xb6);
1659 apdu.data = sbuf;
1660 apdu.datalen = p - sbuf;
1661 apdu.lc = p - sbuf;
1662 apdu.le = 0;
1663 /* we don't know whether to use
1664 * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
1665 r = sc_transmit_apdu(card, &apdu);
1666 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1667 if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
1668 ex_data->fix_digestInfo = 0;
1669 ex_data->sec_ops = SC_SEC_OPERATION_SIGN;
1670 return SC_SUCCESS;
1671 }
1672 /* reset pointer */
1673 p = pp;
1674 /* doesn't work => try next op */
1675 operation = SC_SEC_OPERATION_AUTHENTICATE;
1676 }
1677 try_authenticate:
1678 /* try INTERNAL AUTHENTICATE */
1679 if (operation == SC_SEC_OPERATION_AUTHENTICATE &&
1680 env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
1681 *p++ = 0x80;
1682 *p++ = 0x01;
1683 *p++ = 0x01;
1684 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41,
1685 0xa4);
1686 apdu.data = sbuf;
1687 apdu.datalen = p - sbuf;
1688 apdu.lc = p - sbuf;
1689 apdu.le = 0;
1690 r = sc_transmit_apdu(card, &apdu);
1691 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1692 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1693 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
1694 ex_data->fix_digestInfo = env->algorithm_flags;
1695 ex_data->sec_ops = SC_SEC_OPERATION_AUTHENTICATE;
1696 return SC_SUCCESS;
1697 }
1698
1699 return SC_ERROR_INVALID_ARGUMENTS;
1700 }
1701
starcos_compute_signature(sc_card_t * card,const u8 * data,size_t datalen,u8 * out,size_t outlen)1702 static int starcos_compute_signature(sc_card_t *card,
1703 const u8 * data, size_t datalen,
1704 u8 * out, size_t outlen)
1705 {
1706 int r;
1707 sc_apdu_t apdu;
1708 u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
1709 u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1710 starcos_ex_data *ex_data = (starcos_ex_data *)card->drv_data;
1711
1712 if (datalen > SC_MAX_APDU_BUFFER_SIZE)
1713 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
1714
1715 if (ex_data->sec_ops == SC_SEC_OPERATION_SIGN) {
1716 /* compute signature with the COMPUTE SIGNATURE command */
1717
1718 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
1719 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
1720 size_t tmp_len;
1721
1722 sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A,
1723 0x9E, 0x9A);
1724 apdu.resp = rbuf;
1725 apdu.resplen = sizeof(rbuf);
1726 apdu.le = 0;
1727 if (ex_data->fix_digestInfo) {
1728 // need to pad data
1729 unsigned int flags = ex_data->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;
1730 if (flags == 0x00) {
1731 flags = SC_ALGORITHM_RSA_HASH_NONE;
1732 }
1733 tmp_len = sizeof(sbuf);
1734 r = sc_pkcs1_encode(card->ctx, flags, data, datalen, sbuf, &tmp_len, sizeof(sbuf)*8);
1735 LOG_TEST_RET(card->ctx, r, "sc_pkcs1_encode failed");
1736 } else {
1737 memcpy(sbuf, data, datalen);
1738 tmp_len = datalen;
1739 }
1740
1741 apdu.data = sbuf;
1742 apdu.datalen = tmp_len;
1743 apdu.lc = tmp_len;
1744 apdu.resp = rbuf;
1745 apdu.resplen = sizeof(rbuf);
1746 apdu.le = 0;
1747 r = sc_transmit_apdu(card, &apdu);
1748 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1749 } else {
1750 /* set the hash value */
1751 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A,
1752 0x90, 0x81);
1753 apdu.resp = rbuf;
1754 apdu.resplen = sizeof(rbuf);
1755 apdu.le = 0;
1756 memcpy(sbuf, data, datalen);
1757 apdu.data = sbuf;
1758 apdu.lc = datalen;
1759 apdu.datalen = datalen;
1760 r = sc_transmit_apdu(card, &apdu);
1761 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1762 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1763 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,
1764 sc_check_sw(card, apdu.sw1, apdu.sw2));
1765
1766 /* call COMPUTE SIGNATURE */
1767 sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A,
1768 0x9E, 0x9A);
1769 apdu.resp = rbuf;
1770 apdu.resplen = sizeof(rbuf);
1771 apdu.le = 256;
1772
1773 apdu.lc = 0;
1774 apdu.datalen = 0;
1775 r = sc_transmit_apdu(card, &apdu);
1776 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1777 }
1778 if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
1779 size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
1780 memcpy(out, apdu.resp, len);
1781 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
1782 }
1783 } else if (ex_data->sec_ops == SC_SEC_OPERATION_AUTHENTICATE) {
1784 size_t tmp_len;
1785 CHECK_NOT_SUPPORTED_V3_4(card);
1786 /* call INTERNAL AUTHENTICATE */
1787 sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x10, 0x00);
1788 /* fix/create DigestInfo structure (if necessary) */
1789 if (ex_data->fix_digestInfo) {
1790 unsigned int flags = ex_data->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;
1791 if (flags == 0x0)
1792 /* XXX: assume no hash is wanted */
1793 flags = SC_ALGORITHM_RSA_HASH_NONE;
1794 tmp_len = sizeof(sbuf);
1795 r = sc_pkcs1_encode(card->ctx, flags, data, datalen,
1796 sbuf, &tmp_len, sizeof(sbuf)*8);
1797 if (r < 0)
1798 return r;
1799 } else {
1800 memcpy(sbuf, data, datalen);
1801 tmp_len = datalen;
1802 }
1803 apdu.lc = tmp_len;
1804 apdu.data = sbuf;
1805 apdu.datalen = tmp_len;
1806 apdu.resp = rbuf;
1807 apdu.resplen = sizeof(rbuf);
1808 apdu.le = 256;
1809 r = sc_transmit_apdu(card, &apdu);
1810 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1811 if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
1812 size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
1813
1814 memcpy(out, apdu.resp, len);
1815 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, len);
1816 }
1817 } else
1818 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
1819
1820 /* clear old state */
1821 ex_data->sec_ops = 0;
1822 ex_data->fix_digestInfo = 0;
1823
1824 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
1825 }
1826
starcos_decipher(struct sc_card * card,const u8 * crgram,size_t crgram_len,u8 * out,size_t outlen)1827 static int starcos_decipher(struct sc_card *card,
1828 const u8 * crgram, size_t crgram_len,
1829 u8 * out, size_t outlen)
1830 {
1831 int r;
1832 size_t card_max_send_size = card->max_send_size;
1833 size_t reader_max_send_size = card->reader->max_send_size;
1834 size_t card_max_recv_size = card->max_recv_size;
1835 size_t reader_max_recv_size = card->reader->max_recv_size;
1836
1837 if (sc_get_max_send_size(card) < crgram_len + 1) {
1838 /* Starcos doesn't support chaining for PSO:DEC, so we just _hope_
1839 * that both, the reader and the card are able to send enough data.
1840 * (data is prefixed with 1 byte padding content indicator) */
1841 card->max_send_size = crgram_len + 1;
1842 card->reader->max_send_size = crgram_len + 1;
1843 }
1844
1845 if (sc_get_max_recv_size(card) < outlen) {
1846 /* Starcos doesn't support get response for PSO:DEC, so we just _hope_
1847 * that both, the reader and the card are able to receive enough data.
1848 */
1849 if (0 == (card->caps & SC_CARD_CAP_APDU_EXT)
1850 && outlen > 256) {
1851 card->max_recv_size = 256;
1852 card->reader->max_recv_size = 256;
1853 } else {
1854 card->max_recv_size = outlen;
1855 card->reader->max_recv_size = outlen;
1856 }
1857 }
1858
1859 if (card->type == SC_CARD_TYPE_STARCOS_V3_4
1860 || card->type == SC_CARD_TYPE_STARCOS_V3_5) {
1861 sc_apdu_t apdu;
1862
1863 u8 *sbuf = malloc(crgram_len + 1);
1864 if (sbuf == NULL)
1865 return SC_ERROR_OUT_OF_MEMORY;
1866
1867 sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
1868 apdu.resp = out;
1869 apdu.resplen = outlen;
1870 apdu.le = outlen;
1871
1872 sbuf[0] = 0x81;
1873 memcpy(sbuf + 1, crgram, crgram_len);
1874 apdu.data = sbuf;
1875 apdu.lc = crgram_len + 1;
1876 apdu.datalen = crgram_len + 1;
1877
1878 r = sc_transmit_apdu(card, &apdu);
1879 sc_mem_clear(sbuf, crgram_len + 1);
1880
1881 free(sbuf);
1882
1883 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1884
1885 if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1886 r = apdu.resplen;
1887 else
1888 r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1889 } else {
1890 r = iso_ops->decipher(card, crgram, crgram_len, out, outlen);
1891 }
1892
1893 /* reset whatever we've modified above */
1894 card->max_send_size = card_max_send_size;
1895 card->reader->max_send_size = reader_max_send_size;
1896 card->max_recv_size = card_max_recv_size;
1897 card->reader->max_recv_size = reader_max_recv_size;
1898
1899 LOG_FUNC_RETURN(card->ctx, r);
1900 }
1901
starcos_check_sw(sc_card_t * card,unsigned int sw1,unsigned int sw2)1902 static int starcos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
1903 {
1904 const int err_count = sizeof(starcos_errors)/sizeof(starcos_errors[0]);
1905 int i;
1906
1907 sc_log(card->ctx,
1908 "sw1 = 0x%02x, sw2 = 0x%02x\n", sw1, sw2);
1909
1910 if (sw1 == 0x90)
1911 return SC_SUCCESS;
1912 if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
1913 {
1914 sc_log(card->ctx, "Verification failed (remaining tries: %d)\n",
1915 (sw2 & 0x0f));
1916 return SC_ERROR_PIN_CODE_INCORRECT;
1917 }
1918
1919 /* check starcos error messages */
1920 for (i = 0; i < err_count; i++)
1921 if (starcos_errors[i].SWs == ((sw1 << 8) | sw2))
1922 {
1923 sc_log(card->ctx, "%s\n", starcos_errors[i].errorstr);
1924 return starcos_errors[i].errorno;
1925 }
1926
1927 /* iso error */
1928 return iso_ops->check_sw(card, sw1, sw2);
1929 }
1930
starcos_get_serialnr(sc_card_t * card,sc_serial_number_t * serial)1931 static int starcos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
1932 {
1933 int r;
1934 u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
1935 sc_apdu_t apdu;
1936
1937 if (!serial)
1938 return SC_ERROR_INVALID_ARGUMENTS;
1939
1940 /* see if we have cached serial number */
1941 if (card->serialnr.len) {
1942 memcpy(serial, &card->serialnr, sizeof(*serial));
1943 return SC_SUCCESS;
1944 }
1945
1946 switch (card->type) {
1947 case SC_CARD_TYPE_STARCOS_V3_4:
1948 case SC_CARD_TYPE_STARCOS_V3_5:
1949 card->serialnr.len = SC_MAX_SERIALNR;
1950 r = sc_parse_ef_gdo(card, card->serialnr.value, &card->serialnr.len, NULL, 0);
1951 if (r < 0) {
1952 card->serialnr.len = 0;
1953 return r;
1954 }
1955 break;
1956
1957 default:
1958 /* get serial number via GET CARD DATA */
1959 sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00);
1960 apdu.cla |= 0x80;
1961 apdu.resp = rbuf;
1962 apdu.resplen = sizeof(rbuf);
1963 apdu.le = 256;
1964 apdu.lc = 0;
1965 apdu.datalen = 0;
1966 r = sc_transmit_apdu(card, &apdu);
1967 LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1968 if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1969 return SC_ERROR_INTERNAL;
1970 /* cache serial number */
1971 memcpy(card->serialnr.value, apdu.resp, MIN(apdu.resplen, SC_MAX_SERIALNR));
1972 card->serialnr.len = MIN(apdu.resplen, SC_MAX_SERIALNR);
1973 break;
1974 }
1975
1976 /* copy and return serial number */
1977 memcpy(serial, &card->serialnr, sizeof(*serial));
1978
1979 return SC_SUCCESS;
1980 }
1981
starcos_card_ctl(sc_card_t * card,unsigned long cmd,void * ptr)1982 static int starcos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
1983 {
1984 sc_starcos_create_data *tmp;
1985
1986 switch (cmd)
1987 {
1988 case SC_CARDCTL_STARCOS_CREATE_FILE:
1989 tmp = (sc_starcos_create_data *) ptr;
1990 if (tmp->type == SC_STARCOS_MF_DATA)
1991 return starcos_create_mf(card, tmp);
1992 else if (tmp->type == SC_STARCOS_DF_DATA)
1993 return starcos_create_df(card, tmp);
1994 else if (tmp->type == SC_STARCOS_EF_DATA)
1995 return starcos_create_ef(card, tmp);
1996 else
1997 return SC_ERROR_INTERNAL;
1998 case SC_CARDCTL_STARCOS_CREATE_END:
1999 return starcos_create_end(card, (sc_file_t *)ptr);
2000 case SC_CARDCTL_STARCOS_WRITE_KEY:
2001 return starcos_write_key(card, (sc_starcos_wkey_data *)ptr);
2002 case SC_CARDCTL_STARCOS_GENERATE_KEY:
2003 return starcos_gen_key(card, (sc_starcos_gen_key_data *)ptr);
2004 case SC_CARDCTL_ERASE_CARD:
2005 return starcos_erase_card(card);
2006 case SC_CARDCTL_GET_SERIALNR:
2007 return starcos_get_serialnr(card, (sc_serial_number_t *)ptr);
2008 default:
2009 return SC_ERROR_NOT_SUPPORTED;
2010 }
2011 }
2012
starcos_logout(sc_card_t * card)2013 static int starcos_logout(sc_card_t *card)
2014 {
2015 int r;
2016 sc_apdu_t apdu;
2017 const u8 mf_buf[2] = {0x3f, 0x00};
2018
2019 sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x0C);
2020 apdu.le = 0;
2021 apdu.lc = 2;
2022 apdu.data = mf_buf;
2023 apdu.datalen = 2;
2024 apdu.resplen = 0;
2025
2026 r = sc_transmit_apdu(card, &apdu);
2027 LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
2028
2029 if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
2030 /* the only possible reason for this error here is, afaik,
2031 * that no MF exists, but then there's no need to logout
2032 * => return SC_SUCCESS
2033 */
2034 return SC_SUCCESS;
2035 return sc_check_sw(card, apdu.sw1, apdu.sw2);
2036 }
2037
starcos_pin_cmd(sc_card_t * card,struct sc_pin_cmd_data * data,int * tries_left)2038 static int starcos_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
2039 int *tries_left)
2040 {
2041 int r;
2042
2043 LOG_FUNC_CALLED(card->ctx);
2044 starcos_ex_data * ex_data = (starcos_ex_data*)card->drv_data;
2045 switch (card->type) {
2046 case SC_CARD_TYPE_STARCOS_V3_4:
2047 case SC_CARD_TYPE_STARCOS_V3_5:
2048 data->flags |= SC_PIN_CMD_NEED_PADDING;
2049 data->pin1.encoding = ex_data->pin_encoding;
2050 /* fall through */
2051 default:
2052 r = iso_ops->pin_cmd(card, data, tries_left);
2053 }
2054 SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
2055 }
2056
sc_get_driver(void)2057 static struct sc_card_driver * sc_get_driver(void)
2058 {
2059 struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
2060 if (iso_ops == NULL)
2061 iso_ops = iso_drv->ops;
2062
2063 starcos_ops = *iso_drv->ops;
2064 starcos_ops.match_card = starcos_match_card;
2065 starcos_ops.init = starcos_init;
2066 starcos_ops.finish = starcos_finish;
2067 starcos_ops.select_file = starcos_select_file;
2068 starcos_ops.get_challenge = starcos_get_challenge;
2069 starcos_ops.check_sw = starcos_check_sw;
2070 starcos_ops.create_file = starcos_create_file;
2071 starcos_ops.delete_file = NULL;
2072 starcos_ops.set_security_env = starcos_set_security_env;
2073 starcos_ops.compute_signature = starcos_compute_signature;
2074 starcos_ops.decipher = starcos_decipher;
2075 starcos_ops.card_ctl = starcos_card_ctl;
2076 starcos_ops.logout = starcos_logout;
2077 starcos_ops.pin_cmd = starcos_pin_cmd;
2078
2079 return &starcos_drv;
2080 }
2081
sc_get_starcos_driver(void)2082 struct sc_card_driver * sc_get_starcos_driver(void)
2083 {
2084 return sc_get_driver();
2085 }
2086