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