1 /*
2  * card-westcos.c: support for westcos card
3  *
4  * Copyright (C) 2009 francois.leblanc@cev-sa.com
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #if HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include <assert.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 
30 #include "internal.h"
31 #include "asn1.h"
32 #include "cardctl.h"
33 
34 #ifdef ENABLE_OPENSSL
35 #include <openssl/des.h>
36 #include <openssl/rsa.h>
37 #include <openssl/evp.h>
38 #include <openssl/pem.h>
39 #include <openssl/err.h>
40 #include <openssl/bio.h>
41 #endif
42 
43 #ifndef min
44 #define min(a,b) (((a)<(b))?(a):(b))
45 #endif
46 
47 #define DEFAULT_TRANSPORT_KEY "6f:59:b0:ed:6e:62:46:4a:5d:25:37:68:23:a8:a2:2d"
48 
49 #define JAVACARD             (0x01) /* westcos applet on javacard   */
50 #define RSA_CRYPTO_COMPONENT (0x02) /* card component can do crypto */
51 
52 #define WESTCOS_RSA_NO_HASH_NO_PAD		(0x20)
53 #define WESTCOS_RSA_NO_HASH_PAD_PKCS1	(0x21)
54 
55 #ifdef ENABLE_OPENSSL
56 #define DEBUG_SSL
57 #ifdef DEBUG_SSL
print_openssl_error(void)58 static void print_openssl_error(void)
59 {
60 	static int charge = 0;
61 	long r;
62 
63 	if (!charge) {
64 		ERR_load_crypto_strings();
65 		charge = 1;
66 	}
67 	while ((r = ERR_get_error()) != 0)
68 		fprintf(stderr, "%s\n", ERR_error_string(r, NULL));
69 }
70 #endif
71 #endif
72 
73 typedef struct {
74 	sc_security_env_t env;
75 	sc_autkey_t default_key;
76 	int flags;
77 	int file_id;
78 } priv_data_t;
79 
80 static const struct sc_card_operations *iso_ops = NULL;
81 static struct sc_card_operations westcos_ops;
82 
83 static struct sc_card_driver westcos_drv = {
84 	"WESTCOS compatible cards", "westcos", &westcos_ops, NULL, 0, NULL
85 };
86 
westcos_get_default_key(sc_card_t * card,struct sc_cardctl_default_key * data)87 static int westcos_get_default_key(sc_card_t * card,
88 				   struct sc_cardctl_default_key *data)
89 {
90 	const char *default_key;
91 	sc_log(card->ctx,
92 		 "westcos_get_default_key:data->method=%d, data->key_ref=%d\n",
93 		 data->method, data->key_ref);
94 	if (data->method != SC_AC_AUT || data->key_ref != 0)
95 		return SC_ERROR_NO_DEFAULT_KEY;
96 	default_key =
97 	    scconf_get_str(card->ctx->conf_blocks[0], "westcos_default_key",
98 			   DEFAULT_TRANSPORT_KEY);
99 	return sc_hex_to_bin(default_key, data->key_data, &data->len);
100 }
101 
102 #define CRC_A 1
103 #define CRC_B 2
104 
westcos_update_crc(unsigned char ch,unsigned short * lpwCrc)105 static unsigned short westcos_update_crc(unsigned char ch, unsigned short *lpwCrc)
106 {
107 	ch = (ch ^ (unsigned char)((*lpwCrc) & 0x00FF));
108 	ch = (ch ^ (ch << 4));
109 	*lpwCrc =
110 	    (*lpwCrc >> 8) ^ ((unsigned short)ch << 8) ^ ((unsigned short)ch <<
111 							  3) ^ ((unsigned short)
112 								ch >> 4);
113 	return (*lpwCrc);
114 }
115 
westcos_compute_aetb_crc(int CRCType,unsigned char * Data,size_t Length,unsigned char * TransmitFirst,unsigned char * TransmitSecond)116 static void westcos_compute_aetb_crc(int CRCType,
117 					unsigned char *Data,
118 					size_t Length,
119 					unsigned char * TransmitFirst,
120 					unsigned char * TransmitSecond)
121 {
122 	unsigned char chBlock;
123 	unsigned short wCrc;
124 	switch (CRCType) {
125 	case CRC_A:
126 		wCrc = 0x6363;	/* ITU-V.41 */
127 		break;
128 	case CRC_B:
129 		wCrc = 0xFFFF;	/* ISO 3309 */
130 		break;
131 	default:
132 		return;
133 	}
134 
135 	do {
136 		chBlock = *Data++;
137 		westcos_update_crc(chBlock, &wCrc);
138 	} while (--Length);
139 	if (CRCType == CRC_B)
140 		wCrc = ~wCrc;	/* ISO 3309 */
141 	*TransmitFirst = (unsigned char) (wCrc & 0xFF);
142 	*TransmitSecond = (unsigned char) ((wCrc >> 8) & 0xFF);
143 	return;
144 }
145 
westcos_check_sw(sc_card_t * card,unsigned int sw1,unsigned int sw2)146 static int westcos_check_sw(sc_card_t * card, unsigned int sw1,
147 			    unsigned int sw2)
148 {
149 	if ((sw1 == 0x69) && (sw2 == 0x88))
150 		return SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
151 	assert(iso_ops && iso_ops->check_sw);
152 	return iso_ops->check_sw(card, sw1, sw2);
153 }
154 
155 static const struct sc_atr_table westcos_atrs[] = {
156 	/* westcos 2ko */
157 	{ "3F:69:00:00:00:64:01:00:00:00:80:90:00", "ff:ff:ff:ff:ff:ff:ff:00:00:00:f0:ff:ff", NULL, 0x00, 0, NULL },
158 	/* westcos applet */
159 	{ "3B:95:94:80:1F:C3:80:73:C8:21:13:54", "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff", NULL, JAVACARD, 0, NULL },
160 	{ NULL, NULL, NULL, 0, 0, NULL }
161 };
162 
westcos_finish(sc_card_t * card)163 static int westcos_finish(sc_card_t * card)
164 {
165 	if (card->algorithms)
166 		free(card->algorithms);
167 	card->algorithms = NULL;
168 	card->algorithm_count = 0;
169 	if (card->drv_data)
170 		free(card->drv_data);
171 	return 0;
172 }
173 
westcos_match_card(sc_card_t * card)174 static int westcos_match_card(sc_card_t * card)
175 {
176 	int i;
177 
178 	i = _sc_match_atr(card, westcos_atrs, &card->type);
179 	if (i < 0)
180 		return 0;
181 
182 	/* JAVACARD, look for westcos applet */
183 	if (i == 1) {
184 		int r;
185 		sc_apdu_t apdu;
186 		u8 aid[] = {
187 			0xA0, 0x00, 0xCE, 0x00, 0x07, 0x01
188 		};
189 		sc_format_apdu(card, &apdu,
190 				SC_APDU_CASE_3_SHORT, 0xA4, 0x04,
191 				0);
192 		apdu.cla = 0x00;
193 		apdu.lc = sizeof(aid);
194 		apdu.datalen = sizeof(aid);
195 		apdu.data = aid;
196 		r = sc_transmit_apdu(card, &apdu);
197 		if (r)
198 			return 0;
199 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
200 		if (r)
201 			return 0;
202 	}
203 
204 	return 1;
205 }
206 
westcos_init(sc_card_t * card)207 static int westcos_init(sc_card_t * card)
208 {
209 	int r;
210 	const char *default_key;
211 	unsigned long exponent, flags;
212 	priv_data_t *priv_data;
213 
214 	if (card == NULL)
215 		return SC_ERROR_INVALID_ARGUMENTS;
216 
217 	card->drv_data = malloc(sizeof(priv_data_t));
218 	if (card->drv_data == NULL)
219 		return SC_ERROR_OUT_OF_MEMORY;
220 	memset(card->drv_data, 0, sizeof(priv_data_t));
221 
222 	priv_data = (priv_data_t *) card->drv_data;
223 
224 	default_key =
225 	    scconf_get_str(card->ctx->conf_blocks[0], "westcos_default_key",
226 			   DEFAULT_TRANSPORT_KEY);
227 	if (default_key) {
228 		priv_data = (priv_data_t *) (card->drv_data);
229 		priv_data->default_key.key_reference = 0;
230 		priv_data->default_key.key_len =
231 			sizeof(priv_data->default_key.key_value);
232 		r = sc_hex_to_bin(default_key, priv_data->default_key.key_value,
233 				&(priv_data->default_key.key_len));
234 		if (r) {
235 			free (priv_data);
236 			card->drv_data = NULL;
237 			return (r);
238 		}
239 	}
240 
241 	if (card->type & JAVACARD) {
242 		priv_data->flags |= JAVACARD;
243 	}
244 
245 	/* check for crypto component */
246 	if(card->atr.value[9] == 0xD0)
247 	{
248 		priv_data->flags |= RSA_CRYPTO_COMPONENT;
249 	}
250 
251 	card->cla = 0x00;
252 	card->max_send_size = 240;
253 	card->max_recv_size = 240;
254 	exponent = 0;
255 	flags = SC_ALGORITHM_RSA_RAW;
256 	flags |= SC_ALGORITHM_RSA_HASH_NONE;
257 	flags |= SC_ALGORITHM_RSA_PAD_NONE | SC_ALGORITHM_RSA_PAD_PKCS1;
258 	flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
259 	_sc_card_add_rsa_alg(card, 128, flags, exponent);
260 	_sc_card_add_rsa_alg(card, 256, flags, exponent);
261 	_sc_card_add_rsa_alg(card, 512, flags, exponent);
262 	_sc_card_add_rsa_alg(card, 768, flags, exponent);
263 	_sc_card_add_rsa_alg(card, 1024, flags, exponent);
264 	_sc_card_add_rsa_alg(card, 1100, flags, exponent);
265 	_sc_card_add_rsa_alg(card, 1200, flags, exponent);
266 	_sc_card_add_rsa_alg(card, 1300, flags, exponent);
267 	_sc_card_add_rsa_alg(card, 1400, flags, exponent);
268 	_sc_card_add_rsa_alg(card, 1536, flags, exponent);
269 	_sc_card_add_rsa_alg(card, 2048, flags, exponent);
270 	return 0;
271 }
272 
westcos_select_file(sc_card_t * card,const sc_path_t * in_path,sc_file_t ** file_out)273 static int westcos_select_file(sc_card_t * card, const sc_path_t * in_path,
274 			       sc_file_t ** file_out)
275 {
276 	priv_data_t *priv_data = (priv_data_t *) card->drv_data;
277 
278 	assert(iso_ops && iso_ops->select_file);
279 	priv_data->file_id = 0;
280 	return iso_ops->select_file(card, in_path, file_out);
281 }
282 
_westcos2opensc_ac(u8 flag)283 static int _westcos2opensc_ac(u8 flag)
284 {
285 	if (flag == 0)
286 		return SC_AC_NEVER;
287 	else if (flag == 1)
288 		return SC_AC_CHV;
289 	else if (flag == 2)
290 		return SC_AC_AUT;
291 	else if (flag == 15)
292 		return SC_AC_NONE;
293 	return SC_AC_UNKNOWN;
294 }
295 
westcos_process_fci(sc_card_t * card,sc_file_t * file,const u8 * buf,size_t buflen)296 static int westcos_process_fci(sc_card_t * card, sc_file_t * file,
297 			       const u8 * buf, size_t buflen)
298 {
299 	sc_context_t *ctx = card->ctx;
300 	size_t taglen, len = buflen;
301 	const u8 *tag = NULL, *p = buf;
302 	sc_log(card->ctx,  "processing FCI bytes\n");
303 	tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
304 	if (tag != NULL && taglen == 2) {
305 		file->id = (tag[0] << 8) | tag[1];
306 		sc_log(card->ctx,
307 			"  file identifier: 0x%02X%02X\n", tag[0], tag[1]);
308 	}
309 	tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
310 	if (tag != NULL && taglen >= 2) {
311 		int bytes = (tag[0] << 8) + tag[1];
312 		sc_log(card->ctx,
313 			"  bytes in file: %d\n", bytes);
314 		file->size = bytes;
315 	}
316 	if (tag == NULL) {
317 		tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
318 		if (tag != NULL && taglen >= 2) {
319 			int bytes = (tag[0] << 8) + tag[1];
320 			sc_log(card->ctx,
321 				"  bytes in file: %d\n", bytes);
322 			file->size = bytes;
323 		}
324 	}
325 	tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
326 	if (tag != NULL) {
327 		if (taglen > 0) {
328 			unsigned char byte = tag[0];
329 			const char *type;
330 			file->shareable = 0;
331 			sc_log(card->ctx,
332 				"  shareable: %s\n",
333 				 (file->shareable) ? "yes" : "no");
334 			file->ef_structure = SC_FILE_EF_UNKNOWN;
335 			switch (byte) {
336 			case 0x38:
337 				type = "DF";
338 				file->type = SC_FILE_TYPE_DF;
339 				break;
340 			case 0x01:
341 				type = "working or internal EF";
342 				file->type = SC_FILE_TYPE_WORKING_EF;
343 				file->ef_structure = SC_FILE_EF_TRANSPARENT;
344 				break;
345 			case 0x02:
346 				type = "working or internal EF";
347 				file->type = SC_FILE_TYPE_WORKING_EF;
348 				file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
349 				break;
350 			case 0x06:
351 				type = "working or internal EF";
352 				file->type = SC_FILE_TYPE_WORKING_EF;
353 				file->ef_structure = SC_FILE_EF_CYCLIC;
354 				break;
355 			default:
356 				type = "unknown";
357 			}
358 			sc_log(card->ctx,
359 				"  type: %s\n", type);
360 			sc_log(card->ctx,
361 				"  EF structure: %d\n", file->ef_structure);
362 		}
363 	}
364 	tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
365 	if (tag != NULL && taglen > 0 && taglen <= 16) {
366 		memcpy(file->name, tag, taglen);
367 		file->namelen = taglen;
368 		sc_log_hex(card->ctx, "  File name", file->name, file->namelen);
369 	}
370 	if (file->type == SC_FILE_TYPE_DF) {
371 		tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
372 		if (tag != NULL && taglen == 3) {
373 			file->size = tag[1] * 256 + tag[2];
374 		} else
375 			file->size = 0;
376 	}
377 	tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen);
378 	if (tag != NULL && taglen) {
379 		sc_file_set_prop_attr(file, tag, taglen);
380 	}
381 	tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen);
382 	if (tag != NULL && taglen) {
383 		sc_file_set_sec_attr(file, tag, taglen);
384 
385 		/* FIXME: compact file system only */
386 		if (file->type == SC_FILE_TYPE_DF) {
387 			sc_file_add_acl_entry(file, SC_AC_OP_SELECT,
388 					      _westcos2opensc_ac(tag[0] >>
389 								 4),
390 					      tag[0 + 4] >> 4);
391 			sc_file_add_acl_entry(file, SC_AC_OP_CREATE,
392 					      _westcos2opensc_ac(tag[0] &
393 								 0x0f),
394 					      tag[0 + 4] & 0x0f);
395 			sc_file_add_acl_entry(file, SC_AC_OP_INVALIDATE,
396 					      _westcos2opensc_ac(tag[1] >>
397 								 4),
398 					      tag[1 + 4] >> 4);
399 		}
400 
401 		else {
402 			if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
403 				sc_file_add_acl_entry(file, SC_AC_OP_READ,
404 						      _westcos2opensc_ac(tag[0]
405 									 >>
406 									 4),
407 						      tag[0 + 4] >> 4);
408 				sc_file_add_acl_entry(file, SC_AC_OP_UPDATE,
409 						      _westcos2opensc_ac(tag[0]
410 									 &
411 									 0x0f),
412 						      tag[0 + 4] & 0x0f);
413 				sc_file_add_acl_entry(file,
414 						      SC_AC_OP_INVALIDATE,
415 						      _westcos2opensc_ac(tag[1]
416 									 >>
417 									 4),
418 						      tag[1 + 4] >> 4);
419 				sc_file_add_acl_entry(file, SC_AC_OP_ERASE,
420 						      _westcos2opensc_ac(tag[1]
421 									 &
422 									 0x0f),
423 						      tag[1 + 4] & 0x0f);
424 			}
425 
426 			else {
427 				sc_file_add_acl_entry(file, SC_AC_OP_READ,
428 						      _westcos2opensc_ac(tag[0]
429 									 >>
430 									 4),
431 						      tag[0 + 4] >> 4);
432 				sc_file_add_acl_entry(file, SC_AC_OP_UPDATE,
433 						      _westcos2opensc_ac(tag[0]
434 									 &
435 									 0x0f),
436 						      tag[0 + 4] & 0x0f);
437 				sc_file_add_acl_entry(file,
438 						      SC_AC_OP_INVALIDATE,
439 						      _westcos2opensc_ac(tag[1]
440 									 >>
441 									 4),
442 						      tag[1 + 4] >> 4);
443 			}
444 		}
445 	}
446 	return 0;
447 }
448 
449 #define HIGH (0)
450 #define LOW (1)
_convertion_ac_methode(sc_file_t * file,int low,unsigned int operation,u8 * buf,u8 * buf_key)451 static int _convertion_ac_methode(sc_file_t * file, int low,
452 				  unsigned int operation, u8 * buf,
453 				  u8 * buf_key)
454 {
455 	const struct sc_acl_entry *acl;
456 	acl = sc_file_get_acl_entry(file, operation);
457 	if (acl == NULL) {
458 
459 		/* per default always */
460 		*buf = 0xff;
461 		*buf_key = 0x00;
462 		return 0;
463 	}
464 	switch (acl->method) {
465 	case SC_AC_NONE:
466 		if (low)
467 			*buf |= 0x0f;
468 
469 		else
470 			*buf |= 0xf0;
471 		break;
472 	case SC_AC_CHV:	/* Card Holder Verif. */
473 		if (low)
474 			*buf |= 0x01;
475 
476 		else
477 			*buf |= 0x10;
478 		break;
479 	case SC_AC_TERM:	/* Terminal auth. */
480 		return SC_ERROR_NOT_SUPPORTED;
481 	case SC_AC_PRO:	/* Secure Messaging */
482 		return SC_ERROR_NOT_SUPPORTED;
483 	case SC_AC_AUT:	/* Key auth. */
484 		if (low)
485 			*buf |= 0x02;
486 
487 		else
488 			*buf |= 0x20;
489 		if (acl->key_ref > 15)
490 			return SC_ERROR_NOT_SUPPORTED;
491 		if (low)
492 			*buf_key |= acl->key_ref;
493 
494 		else
495 			*buf_key |= (acl->key_ref) << 4;
496 		break;
497 	case SC_AC_NEVER:
498 		*buf |= 0;
499 		break;
500 	default:
501 		return SC_ERROR_NOT_SUPPORTED;
502 	}
503 	return 0;
504 }
505 
westcos_create_file(sc_card_t * card,struct sc_file * file)506 static int westcos_create_file(sc_card_t *card, struct sc_file *file)
507 {
508 	int r;
509 	sc_apdu_t apdu;
510 	u8 buf[12], p1 = 0, p2 = 0;
511 	int buflen;
512 	if (card == NULL)
513 		return SC_ERROR_INVALID_ARGUMENTS;
514 	sc_log(card->ctx,  "westcos_create_file\n");
515 	memset(buf, 0, sizeof(buf));
516 
517 	/* transport key */
518 	r = sc_card_ctl(card, SC_CARDCTL_WESTCOS_AUT_KEY, NULL);
519 	if (r)
520 		return (r);
521 	buflen = sizeof(buf);
522 	switch (file->type) {
523 	case SC_FILE_TYPE_DF:
524 		buf[0] = 0x00;
525 		buf[1] = 0x01;
526 		_convertion_ac_methode(file, HIGH, SC_AC_OP_SELECT, &buf[2],
527 				       &buf[2 + 4]);
528 		_convertion_ac_methode(file, LOW, SC_AC_OP_CREATE, &buf[2],
529 				       &buf[2 + 4]);
530 		_convertion_ac_methode(file, HIGH, SC_AC_OP_INVALIDATE,
531 				       &buf[3], &buf[3 + 4]);
532 		buflen = 10;
533 		break;
534 	case SC_FILE_TYPE_INTERNAL_EF:
535 		buf[0] |= 0x80;
536 		/* fall through */
537 	case SC_FILE_TYPE_WORKING_EF:
538 		switch (file->ef_structure) {
539 		case SC_FILE_EF_TRANSPARENT:
540 			buf[0] |= 0x20; /* no transaction support */
541 			buf[1] |= 0;
542 			_convertion_ac_methode(file, HIGH, SC_AC_OP_READ,
543 					       &buf[2], &buf[2 + 4]);
544 			_convertion_ac_methode(file, LOW, SC_AC_OP_UPDATE,
545 					       &buf[2], &buf[2 + 4]);
546 			_convertion_ac_methode(file, HIGH, SC_AC_OP_INVALIDATE,
547 					       &buf[3], &buf[3 + 4]);
548 			_convertion_ac_methode(file, LOW, SC_AC_OP_ERASE,
549 					       &buf[3], &buf[3 + 4]);
550 			buf[10] = (u8) ((file->size) / 256);
551 			buf[11] = (u8) ((file->size) % 256);
552 			break;
553 		case SC_FILE_EF_LINEAR_FIXED:
554 			buf[0] |= 0x40; /* no transaction support */
555 			buf[1] |= 0;
556 			_convertion_ac_methode(file, HIGH, SC_AC_OP_READ,
557 					       &buf[2], &buf[2 + 4]);
558 			_convertion_ac_methode(file, LOW, SC_AC_OP_UPDATE,
559 					       &buf[2], &buf[2 + 4]);
560 			_convertion_ac_methode(file, HIGH, SC_AC_OP_INVALIDATE,
561 					       &buf[3], &buf[3 + 4]);
562 			buf[10] = file->record_count;
563 			buf[11] = file->record_length;
564 			break;
565 		case SC_FILE_EF_CYCLIC:
566 			buf[0] |= 0x60; /* no transaction support */
567 			buf[1] |= 0;
568 			_convertion_ac_methode(file, HIGH, SC_AC_OP_READ,
569 					       &buf[2], &buf[2 + 4]);
570 			_convertion_ac_methode(file, LOW, SC_AC_OP_UPDATE,
571 					       &buf[2], &buf[2 + 4]);
572 			_convertion_ac_methode(file, HIGH, SC_AC_OP_INVALIDATE,
573 					       &buf[3], &buf[3 + 4]);
574 			buf[10] = file->record_count;
575 			buf[11] = file->record_length;
576 			break;
577 		case SC_FILE_EF_LINEAR_VARIABLE:
578 		case SC_FILE_EF_UNKNOWN:
579 		case SC_FILE_EF_LINEAR_FIXED_TLV:
580 		case SC_FILE_EF_LINEAR_VARIABLE_TLV:
581 		case SC_FILE_EF_CYCLIC_TLV:
582 		default:
583 			return SC_ERROR_NOT_SUPPORTED;
584 		}
585 		break;
586 	default:
587 		return SC_ERROR_NOT_SUPPORTED;
588 	}
589 	if (file->shareable)
590 		buf[0] |= 0x08;
591 	if (file->path.len >= 2) {
592 		p1 = file->path.value[file->path.len - 2];
593 		p2 = file->path.value[file->path.len - 1];
594 	}
595 
596 	else if (file->id) {
597 		p1 = (file->id) / 256;
598 		p2 = (file->id) % 256;
599 	}
600 	sc_log(card->ctx,
601 		 "create file %s, id %X size %"SC_FORMAT_LEN_SIZE_T"u\n",
602 		 file->path.value, file->id, file->size);
603 	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, p1, p2);
604 	apdu.cla = 0x80;
605 	apdu.lc = buflen;
606 	apdu.datalen = buflen;
607 	apdu.data = buf;
608 	r = sc_transmit_apdu(card, &apdu);
609 	if (r)
610 		return (r);
611 	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
612 	return r;
613 }
614 
westcos_delete_file(sc_card_t * card,const sc_path_t * path_in)615 static int westcos_delete_file(sc_card_t * card, const sc_path_t * path_in)
616 {
617 	int r;
618 	sc_apdu_t apdu;
619 	if (card == NULL || path_in == NULL || path_in->len < 2)
620 		return SC_ERROR_INVALID_ARGUMENTS;
621 	sc_log(card->ctx,  "westcos_delete_file\n");
622 	if (path_in->len > 2) {
623 		r = sc_select_file(card, path_in, NULL);
624 		if (r)
625 			return (r);
626 	}
627 	sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4,
628 		       path_in->value[path_in->len - 2],
629 		       path_in->value[path_in->len - 1]);
630 	apdu.cla = 0x80;
631 	r = sc_transmit_apdu(card, &apdu);
632 	if (r)
633 		return (r);
634 	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
635 	if (r)
636 		return (r);
637 	return 0;
638 }
639 
westcos_list_files(sc_card_t * card,u8 * buf,size_t buflen)640 static int westcos_list_files(sc_card_t * card, u8 * buf, size_t buflen)
641 {
642 	int r;
643 	sc_apdu_t apdu;
644 	if (card == NULL)
645 		return SC_ERROR_INVALID_ARGUMENTS;
646 	sc_log(card->ctx,  "westcos_list_files\n");
647 	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x34, 0x00, 0x00);
648 	apdu.cla = 0x80;
649 	apdu.le = buflen;
650 	apdu.resplen = buflen;
651 	apdu.resp = buf;
652 	r = sc_transmit_apdu(card, &apdu);
653 	if (r)
654 		return (r);
655 	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
656 	if (r)
657 		return (r);
658 	return apdu.resplen;
659 }
660 
westcos_get_crypte_challenge(sc_card_t * card,const u8 * key,u8 * result,size_t * len)661 static int westcos_get_crypte_challenge(sc_card_t * card, const u8 * key,
662 					u8 * result, size_t * len)
663 {
664 	int r;
665 #ifdef ENABLE_OPENSSL
666 	DES_key_schedule ks1, ks2;
667 #endif
668 	u8 buf[8];
669 	if ((*len) < sizeof(buf))
670 		return SC_ERROR_INVALID_ARGUMENTS;
671 	*len = 8;
672 	r = sc_get_challenge(card, buf, *len);
673 	if (r)
674 		return r;
675 #ifdef ENABLE_OPENSSL
676 	DES_set_key((const_DES_cblock *) & key[0], &ks1);
677 	DES_set_key((const_DES_cblock *) & key[8], &ks2);
678 	DES_ecb2_encrypt((const_DES_cblock *)buf, (DES_cblock*)result, &ks1, &ks2, DES_ENCRYPT);
679 	return SC_SUCCESS;
680 #else
681 	return SC_ERROR_NOT_SUPPORTED;
682 #endif
683 }
684 
westcos_pin_cmd(sc_card_t * card,struct sc_pin_cmd_data * data,int * tries_left)685 static int westcos_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data *data,
686 			   int *tries_left)
687 {
688 	int r;
689 	u8 buf[20];
690 	sc_apdu_t apdu;
691 	size_t len = 0;
692 	int pad = 0, use_pin_pad = 0, ins, p1 = 0;
693 	if (card == NULL)
694 		return SC_ERROR_INVALID_ARGUMENTS;
695 	sc_log(card->ctx,
696 		 "westcos_pin_cmd:data->pin_type=%X, data->cmd=%X\n",
697 		 data->pin_type, data->cmd);
698 	if (tries_left)
699 		*tries_left = -1;
700 	switch (data->pin_type) {
701 	case SC_AC_AUT:
702 		len = sizeof(buf);
703 		r = westcos_get_crypte_challenge(card, data->pin1.data, buf,
704 						 &len);
705 		if (r)
706 			return (r);
707 		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x82, 0x00,
708 			       data->pin_reference);
709 		apdu.lc = len;
710 		apdu.datalen = len;
711 		apdu.data = buf;
712 		r = sc_transmit_apdu(card, &apdu);
713 		if (r)
714 			return (r);
715 		return sc_check_sw(card, apdu.sw1, apdu.sw2);
716 		break;
717 	case SC_AC_CHV:
718 		if (data->flags & SC_PIN_CMD_NEED_PADDING)
719 			pad = 1;
720 		if (data->flags & SC_PIN_CMD_USE_PINPAD)
721 			use_pin_pad = 1;
722 		data->pin1.offset = 0;
723 		data->pin1.encoding = SC_PIN_ENCODING_GLP;
724 		if (data->pin1.min_length == 0)
725 			data->pin1.min_length = 4;
726 		if (data->pin1.max_length == 0)
727 			data->pin1.max_length = 12;
728 		switch (data->cmd) {
729 		case SC_PIN_CMD_VERIFY:
730 			ins = 0x20;
731 			if ((r =
732 			     sc_build_pin(buf, sizeof(buf), &data->pin1,
733 					  pad)) < 0)
734 				return r;
735 			len = r;
736 			break;
737 		case SC_PIN_CMD_CHANGE:
738 			ins = 0x24;
739 			if (data->pin1.len != 0 || use_pin_pad) {
740 				if ((r =
741 				     sc_build_pin(buf, sizeof(buf),
742 						  &data->pin1, pad)) < 0)
743 					return r;
744 				len += r;
745 			} else {
746 
747 				/* implicit test */
748 				p1 = 1;
749 			}
750 			data->pin2.offset = data->pin1.offset + len;
751 			data->pin2.encoding = SC_PIN_ENCODING_GLP;
752 			if ((r =
753 			     sc_build_pin(buf + len, sizeof(buf) - len,
754 					  &data->pin2, pad)) < 0)
755 				return r;
756 			len += r;
757 			break;
758 		case SC_PIN_CMD_UNBLOCK:
759 			ins = 0x2C;
760 			if (data->pin1.len != 0 || use_pin_pad) {
761 				if ((r =
762 				     sc_build_pin(buf, sizeof(buf),
763 						  &data->pin1, pad)) < 0)
764 					return r;
765 				len += r;
766 			} else {
767 				p1 |= 0x02;
768 			}
769 			if (data->pin2.len != 0 || use_pin_pad) {
770 				data->pin2.offset = data->pin1.offset + len;
771 				data->pin2.encoding = SC_PIN_ENCODING_GLP;
772 				if ((r =
773 				     sc_build_pin(buf + len, sizeof(buf) - len,
774 						  &data->pin2, pad)) < 0)
775 					return r;
776 				len += r;
777 			} else {
778 				p1 |= 0x01;
779 			}
780 			break;
781 		default:
782 			return SC_ERROR_NOT_SUPPORTED;
783 		}
784 		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, ins, p1,
785 			       data->pin_reference);
786 		apdu.lc = len;
787 		apdu.datalen = len;
788 		apdu.data = buf;
789 		apdu.resplen = 0;
790 		if (!use_pin_pad) {
791 
792 			/* Transmit the APDU to the card */
793 			r = sc_transmit_apdu(card, &apdu);
794 
795 			/* Clear the buffer - it may contain pins */
796 			sc_mem_clear(buf, sizeof(buf));
797 		} else {
798 			data->apdu = &apdu;
799 			if (card->reader
800 			    && card->reader->ops
801 			    && card->reader->ops->perform_verify) {
802 				r = card->reader->ops->perform_verify(card->
803 								      reader,
804 								      data);
805 			} else {
806 				r = SC_ERROR_NOT_SUPPORTED;
807 			}
808 			data->apdu = NULL;
809 		}
810 		if (r)
811 			return (r);
812 		return sc_check_sw(card, apdu.sw1, apdu.sw2);
813 	default:
814 		return SC_ERROR_NOT_SUPPORTED;
815 	}
816 }
817 
sc_get_atr(sc_card_t * card)818 static int sc_get_atr(sc_card_t * card)
819 {
820 	int r;
821 	sc_apdu_t apdu;
822 	u8 buf[sizeof(card->atr.value)];
823 	if (card == NULL)
824 		return SC_ERROR_INVALID_ARGUMENTS;
825 	sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xEC, 0x00, 0x00);
826 	apdu.cla = 0x80;
827 	apdu.le = 0x0d;
828 	apdu.resplen = 0x0d;
829 	apdu.resp = buf;
830 	r = sc_transmit_apdu(card, &apdu);
831 	if (r)
832 		return (r);
833 	r = sc_check_sw(card, apdu.sw1, apdu.sw2);
834 	if (r)
835 		return (r);
836 	memcpy(card->atr.value, buf, sizeof(card->atr.value));
837 	card->atr.len = apdu.resplen;
838 	return r;
839 }
840 
sc_lock_phase(sc_card_t * card,u8 phase)841 static int sc_lock_phase(sc_card_t * card, u8 phase)
842 {
843 	int r;
844 	sc_apdu_t apdu;
845 	if (card == NULL)
846 		return SC_ERROR_INVALID_ARGUMENTS;
847 	sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x16, phase, 0x00);
848 	apdu.cla = 0x80;
849 	r = sc_transmit_apdu(card, &apdu);
850 	if (r)
851 		return (r);
852 	return sc_check_sw(card, apdu.sw1, apdu.sw2);
853 }
854 
westcos_card_ctl(sc_card_t * card,unsigned long cmd,void * ptr)855 static int westcos_card_ctl(sc_card_t * card, unsigned long cmd, void *ptr)
856 {
857 	unsigned int i;
858 	int r;
859 	size_t buflen;
860 	u8 buf[256];
861 	sc_apdu_t apdu;
862 	struct sc_pin_cmd_data data;
863 	sc_serial_number_t *serialnr;
864 	priv_data_t *priv_data = NULL;
865 	if (card == NULL)
866 		return SC_ERROR_INVALID_ARGUMENTS;
867 	sc_log(card->ctx,
868 		"westcos_card_ctl cmd = %lX\n", cmd);
869 	priv_data = (priv_data_t *) card->drv_data;
870 	switch (cmd) {
871 	case SC_CARDCTL_GET_DEFAULT_KEY:
872 		return westcos_get_default_key(card,
873 					       (struct sc_cardctl_default_key
874 						*)ptr);
875 		break;
876 	case SC_CARDCTL_LIFECYCLE_SET:
877 		if (1) {
878 			int mode = *((int *)ptr);
879 			switch (mode) {
880 			case SC_CARDCTRL_LIFECYCLE_ADMIN:
881 				if (priv_data->flags & JAVACARD) {
882 					return 0;
883 				}
884 				if (card->atr.value[10] == 0x80
885 				    || card->atr.value[10] == 0x81)
886 					return 0;
887 				return SC_ERROR_CARD_CMD_FAILED;
888 			case SC_CARDCTRL_LIFECYCLE_USER:
889 				if (card->atr.value[10] == 0x80) {
890 					r = sc_lock_phase(card, 0x02);
891 					if (r)
892 						return (r);
893 					r = sc_get_atr(card);
894 					if (r)
895 						return (r);
896 					r = sc_card_ctl(card,
897 							SC_CARDCTL_WESTCOS_AUT_KEY,
898 							NULL);
899 					if (r)
900 						return (r);
901 				}
902 				if (card->atr.value[10] == 0x81) {
903 					r = sc_lock_phase(card, 0x01);
904 					if (r)
905 						return (r);
906 					r = sc_get_atr(card);
907 					if (r)
908 						return (r);
909 					return 0;
910 				}
911 				return SC_ERROR_CARD_CMD_FAILED;
912 			case SC_CARDCTRL_LIFECYCLE_OTHER:
913 			default:
914 				break;
915 			}
916 		}
917 		break;
918 	case SC_CARDCTL_GET_SERIALNR:
919 		sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xEE, 0x00,
920 			       0x00);
921 		apdu.cla = 0xb0;
922 		apdu.le = 8;
923 		apdu.resp = buf;
924 		apdu.resplen = 10;	/* include SW's */
925 		r = sc_transmit_apdu(card, &apdu);
926 		if (r)
927 			return (r);
928 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
929 		if (r)
930 			return (r);
931 		if (SC_MAX_SERIALNR < 8)
932 			return SC_ERROR_NOT_SUPPORTED;
933 		serialnr = (sc_serial_number_t *) ptr;
934 		serialnr->len = 8;
935 		memcpy(serialnr->value, buf, serialnr->len);
936 		return 0;
937 	case SC_CARDCTL_WESTCOS_CREATE_MF:
938 		buf[0] = *((u8 *) ptr);
939 		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x3F,
940 			       0x00);
941 		apdu.cla = 0x80;
942 		apdu.lc = 1;
943 		apdu.datalen = 1;
944 		apdu.data = buf;
945 		apdu.le = 0;
946 		r = sc_transmit_apdu(card, &apdu);
947 		if (r)
948 			return (r);
949 		return sc_check_sw(card, apdu.sw1, apdu.sw2);
950 	case SC_CARDCTL_WESTCOS_COMMIT:
951 		sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2C, 0x00, 0x00);
952 		apdu.cla = 0x80;
953 		r = sc_transmit_apdu(card, &apdu);
954 		if (r)
955 			return (r);
956 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
957 		if (r)
958 			return (r);
959 		return r;
960 	case SC_CARDCTL_WESTCOS_ROLLBACK:
961 		sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x24, 0x00, 0x00);
962 		apdu.cla = 0x80;
963 		r = sc_transmit_apdu(card, &apdu);
964 		if (r)
965 			return (r);
966 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
967 		if (r)
968 			return (r);
969 		return r;
970 	case SC_CARDCTL_WESTCOS_AUT_KEY:
971 		if (ptr != NULL)
972 			priv_data->default_key = *((sc_autkey_t *) ptr);
973 		memset(&data, 0, sizeof(data));
974 		data.pin_type = SC_AC_AUT;
975 		data.pin_reference = priv_data->default_key.key_reference;
976 		data.pin1.len = priv_data->default_key.key_len;
977 		data.pin1.data = priv_data->default_key.key_value;
978 		return sc_pin_cmd(card, &data, NULL);
979 	case SC_CARDCTL_WESTCOS_CHANGE_KEY:
980 		{
981 			int lrc;
982 			u8 temp[7];
983 			sc_changekey_t *ck = (sc_changekey_t *) ptr;
984 			sc_autkey_t master_key;
985 			if (ck->master_key.key_len != 0)
986 				master_key = ck->master_key;
987 
988 			else
989 				master_key = priv_data->default_key;
990 			memcpy(temp, ck->key_template, sizeof(temp));
991 			westcos_compute_aetb_crc(CRC_A, ck->new_key.key_value,
992 				   ck->new_key.key_len, &temp[5], &temp[6]);
993 			for (i = 0, temp[4] = 0xAA, lrc = 0; i < sizeof(temp);
994 			    i++)
995 				lrc += temp[i];
996 			temp[4] = (lrc % 256);
997 			buflen = sizeof(buf);
998 			r = westcos_get_crypte_challenge(card,
999 							 master_key.key_value,
1000 							 buf, &buflen);
1001 			if (r)
1002 				return (r);
1003 			memcpy(&buf[buflen], temp, sizeof(temp));
1004 			buflen += sizeof(temp);
1005 			memcpy(&buf[buflen], ck->new_key.key_value,
1006 			       ck->new_key.key_len);
1007 			buflen += ck->new_key.key_len;
1008 			sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT,
1009 				       0xD8, ck->new_key.key_reference,
1010 				       master_key.key_reference);
1011 			apdu.cla = 0x80;
1012 			apdu.lc = buflen;
1013 			apdu.datalen = buflen;
1014 			apdu.data = buf;
1015 			r = sc_transmit_apdu(card, &apdu);
1016 			if (r)
1017 				return (r);
1018 			r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1019 			if (r)
1020 				return (r);
1021 			return r;
1022 		}
1023 	case SC_CARDCTL_WESTCOS_SET_DEFAULT_KEY:
1024 		priv_data->default_key = *((sc_autkey_t *) ptr);
1025 		return 0;
1026 	case SC_CARDCTL_WESTCOS_LOAD_DATA:
1027 
1028 		/* ptr[0] = 0x01 pour generique appli, 0x81 pour appli avec pme */
1029 		buf[0] = *((u8 *) ptr);
1030 		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xB2, 0x80,
1031 			       0x14);
1032 		apdu.cla = 0xB0;
1033 		apdu.lc = 1;
1034 		apdu.datalen = 1;
1035 		apdu.data = buf;
1036 		r = sc_transmit_apdu(card, &apdu);
1037 		if (r)
1038 			return (r);
1039 		return sc_check_sw(card, apdu.sw1, apdu.sw2);
1040 	}
1041 	return SC_ERROR_NOT_SUPPORTED;
1042 }
1043 
westcos_set_security_env(sc_card_t * card,const struct sc_security_env * env,int se_num)1044 static int westcos_set_security_env(sc_card_t *card,
1045 				    const struct sc_security_env *env,
1046 				    int se_num)
1047 {
1048 	int r = 0;
1049 	priv_data_t *priv_data = NULL;
1050 	if (card == NULL)
1051 		return SC_ERROR_INVALID_ARGUMENTS;
1052 	sc_log(card->ctx,
1053 		"westcos_set_security_env\n");
1054 	priv_data = (priv_data_t *) card->drv_data;
1055 	priv_data->env = *env;
1056 
1057 	if(priv_data->flags & RSA_CRYPTO_COMPONENT)
1058 	{
1059 		sc_apdu_t apdu;
1060 		unsigned char mode = 0;
1061 		u8 buf[128];
1062 
1063 		if ((priv_data->env.flags) & SC_ALGORITHM_RSA_PAD_PKCS1)
1064 			mode = WESTCOS_RSA_NO_HASH_PAD_PKCS1;
1065 		else if ((priv_data->env.flags) & SC_ALGORITHM_RSA_RAW)
1066 			mode = WESTCOS_RSA_NO_HASH_NO_PAD;
1067 
1068 		r = sc_path_print((char *)buf, sizeof(buf), &(env->file_ref));
1069 		if(r)
1070 			return r;
1071 
1072 		sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xf0, mode);
1073 		apdu.cla = 0x00;
1074 		apdu.lc = strlen((char *)buf);
1075 		apdu.datalen = apdu.lc;
1076 		apdu.data = buf;
1077 		r = sc_transmit_apdu(card, &apdu);
1078 		if (r)
1079 			return (r);
1080 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1081 	}
1082 
1083 	return r;
1084 }
1085 
westcos_restore_security_env(sc_card_t * card,int se_num)1086 static int westcos_restore_security_env(sc_card_t *card, int se_num)
1087 {
1088 	if (card == NULL)
1089 		return SC_ERROR_INVALID_ARGUMENTS;
1090 	sc_log(card->ctx,
1091 		"westcos_restore_security_env\n");
1092 	return 0;
1093 }
1094 
westcos_sign_decipher(int mode,sc_card_t * card,const u8 * data,size_t data_len,u8 * out,size_t outlen)1095 static int westcos_sign_decipher(int mode, sc_card_t *card,
1096 				 const u8 * data, size_t data_len, u8 * out,
1097 				 size_t outlen)
1098 {
1099 	int r;
1100 	sc_file_t *keyfile = NULL;
1101 #ifdef ENABLE_OPENSSL
1102 	int idx = 0;
1103 	u8 buf[180];
1104 	priv_data_t *priv_data = NULL;
1105 	int pad;
1106 	RSA *rsa = NULL;
1107 	BIO *mem = BIO_new(BIO_s_mem());
1108 #endif
1109 
1110 	if (card == NULL)
1111 		return SC_ERROR_INVALID_ARGUMENTS;
1112 
1113 	sc_log(card->ctx,
1114 		 "westcos_sign_decipher outlen=%"SC_FORMAT_LEN_SIZE_T"u\n",
1115 		 outlen);
1116 
1117 #ifndef ENABLE_OPENSSL
1118 	r = SC_ERROR_NOT_SUPPORTED;
1119 #else
1120 	if (mem == NULL || card->drv_data == NULL) {
1121 		r = SC_ERROR_OUT_OF_MEMORY;
1122 		goto out;
1123 	}
1124 
1125 	priv_data = (priv_data_t *) card->drv_data;
1126 
1127 	if(priv_data->flags & RSA_CRYPTO_COMPONENT)
1128 	{
1129 		sc_apdu_t apdu;
1130 
1131 		sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, mode);
1132 		apdu.datalen = data_len;
1133 		apdu.data = data;
1134 		apdu.lc = data_len;
1135 		apdu.le = outlen > 240 ? 240 : outlen;
1136 		apdu.resp = out;
1137 		apdu.resplen = outlen;
1138 
1139 		r = sc_transmit_apdu(card, &apdu);
1140 		if (r)
1141 			goto out2;
1142 		r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1143 		if(r)
1144 			goto out2;
1145 
1146 		/* correct */
1147 		r = apdu.resplen;
1148 		goto out2;
1149 	}
1150 	if ((priv_data->env.flags) & SC_ALGORITHM_RSA_PAD_PKCS1)
1151 		pad = RSA_PKCS1_PADDING;
1152 
1153 	else if ((priv_data->env.flags) & SC_ALGORITHM_RSA_RAW)
1154 		pad = RSA_NO_PADDING;
1155 
1156 	else {
1157 		r = SC_ERROR_INVALID_ARGUMENTS;
1158 		goto out;
1159 	}
1160 	r = sc_select_file(card, &(priv_data->env.file_ref), &keyfile);
1161 	if (r || !keyfile)
1162 		goto out;
1163 
1164 	do {
1165 		int alire;
1166 		alire = min(((keyfile->size) - idx), sizeof(buf));
1167 		if (alire <= 0)
1168 			break;
1169 		sc_log(card->ctx,
1170 			"idx = %d, alire=%d\n", idx, alire);
1171 		r = sc_read_binary(card, idx, buf, alire, 0);
1172 		if (r < 0)
1173 			goto out;
1174 		BIO_write(mem, buf, r);
1175 		idx += r;
1176 	} while (1);
1177 	BIO_set_mem_eof_return(mem, -1);
1178 	if (!d2i_RSAPrivateKey_bio(mem, &rsa)) {
1179 		sc_log(card->ctx,
1180 			"RSA key invalid, %lu\n", ERR_get_error());
1181 		r = SC_ERROR_UNKNOWN;
1182 		goto out;
1183 	}
1184 
1185 	/* pkcs11 reset openssl functions */
1186 	RSA_set_method(rsa, RSA_PKCS1_OpenSSL());
1187 
1188 	if ((size_t)RSA_size(rsa) > outlen) {
1189 		sc_log(card->ctx,  "Buffer too small\n");
1190 		r = SC_ERROR_OUT_OF_MEMORY;
1191 		goto out;
1192 	}
1193 #if 1
1194 	if (mode) {		/* decipher */
1195 		r = RSA_private_decrypt(data_len, data, out, rsa, pad);
1196 		if (r == -1) {
1197 
1198 #ifdef DEBUG_SSL
1199 			print_openssl_error();
1200 
1201 #endif
1202 			sc_log(card->ctx,
1203 				"Decipher error %lu\n", ERR_get_error());
1204 			r = SC_ERROR_UNKNOWN;
1205 			goto out;
1206 		}
1207 	}
1208 
1209 	else {			/* sign */
1210 
1211 		r = RSA_private_encrypt(data_len, data, out, rsa, pad);
1212 		if (r == -1) {
1213 
1214 #ifdef DEBUG_SSL
1215 			print_openssl_error();
1216 
1217 #endif
1218 			sc_log(card->ctx,
1219 				"Signature error %lu\n", ERR_get_error());
1220 			r = SC_ERROR_UNKNOWN;
1221 			goto out;
1222 		}
1223 	}
1224 
1225 #else
1226 	if (RSA_sign(nid, data, data_len, out, &outlen, rsa) != 1) {
1227 		sc_log(card->ctx,
1228 			"RSA_sign error %d \n", ERR_get_error());
1229 		r = SC_ERROR_UNKNOWN;
1230 		goto out;
1231 	}
1232 	r = outlen;
1233 
1234 #endif
1235 out:
1236 	if (mem)
1237 		BIO_free(mem);
1238 	if (rsa)
1239 		RSA_free(rsa);
1240 out2:
1241 #endif /* ENABLE_OPENSSL */
1242 	sc_file_free(keyfile);
1243 	return r;
1244 }
1245 
westcos_compute_signature(sc_card_t * card,const u8 * data,size_t data_len,u8 * out,size_t outlen)1246 static int westcos_compute_signature(sc_card_t *card, const u8 * data,
1247 				     size_t data_len, u8 * out, size_t outlen)
1248 {
1249 	return westcos_sign_decipher(0, card, data, data_len, out, outlen);
1250 }
1251 
westcos_decipher(sc_card_t * card,const u8 * crgram,size_t crgram_len,u8 * out,size_t outlen)1252 static int westcos_decipher(sc_card_t *card, const u8 * crgram,
1253 			    size_t crgram_len, u8 * out, size_t outlen)
1254 {
1255 	return westcos_sign_decipher(1, card, crgram, crgram_len, out, outlen);
1256 }
1257 
sc_get_westcos_driver(void)1258 struct sc_card_driver *sc_get_westcos_driver(void)
1259 {
1260 	if (iso_ops == NULL)
1261 		iso_ops = sc_get_iso7816_driver()->ops;
1262 	westcos_ops = *iso_ops;
1263 
1264 	westcos_ops.match_card = westcos_match_card;
1265 	westcos_ops.init = westcos_init;
1266 	westcos_ops.finish = westcos_finish;
1267 	/* read_binary */
1268 	/* write_binary */
1269 	/* update_binary */
1270 	/* read_record */
1271 	/* write_record */
1272 	/* append_record */
1273 	/* update_record */
1274 	westcos_ops.select_file = westcos_select_file;
1275 	/* get_response */
1276 	/* get_challenge */
1277 	westcos_ops.restore_security_env = westcos_restore_security_env;
1278 	westcos_ops.set_security_env = westcos_set_security_env;
1279 	westcos_ops.decipher = westcos_decipher;
1280 	westcos_ops.compute_signature = westcos_compute_signature;
1281 	westcos_ops.create_file = westcos_create_file;
1282 	westcos_ops.delete_file = westcos_delete_file;
1283 	westcos_ops.list_files = westcos_list_files;
1284 	westcos_ops.check_sw = westcos_check_sw;
1285 	westcos_ops.card_ctl = westcos_card_ctl;
1286 	westcos_ops.process_fci = westcos_process_fci;
1287 	westcos_ops.construct_fci = NULL;
1288 	westcos_ops.pin_cmd = westcos_pin_cmd;
1289 
1290 	return &westcos_drv;
1291 }
1292 
1293