1 /*
2  * iasecc.h Support for IAS/ECC smart cards
3  *
4  * Copyright (C) 2010  Viktor Tarasov <vtarasov@opentrust.com>
5  *			OpenTrust <www.opentrust.com>
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 #include <string.h>
23 #include <stdint.h>
24 #include <stdlib.h>
25 
26 #include "internal.h"
27 #include "asn1.h"
28 #include "cardctl.h"
29 #include "common/compat_strlcpy.h"
30 
31 #include "sm.h"
32 #include "iasecc.h"
33 #include "authentic.h"
34 
35 
36 #ifdef ENABLE_SM
37 
38 static int
sm_save_sc_context(struct sc_card * card,struct sm_info * sm_info)39 sm_save_sc_context (struct sc_card *card, struct sm_info *sm_info)
40 {
41 	struct sc_context *ctx;
42 	struct sc_card_cache *cache;
43 
44 	if (!card || !sm_info)
45 		return SC_ERROR_INVALID_ARGUMENTS;
46 
47 	ctx = card->ctx;
48 	cache = &card->cache;
49 
50 	sc_log(ctx, "SM save context: cache(valid:%i,current_df:%p)", cache->valid, cache->current_df);
51 	if (cache->valid && cache->current_df)   {
52 		sm_info->current_path_df = cache->current_df->path;
53 		if (cache->current_df->path.type == SC_PATH_TYPE_DF_NAME)   {
54 			if (cache->current_df->path.aid.len)   {
55 				sm_info->current_aid = cache->current_df->path.aid;
56 			}
57 			else   {
58 				memcpy(sm_info->current_aid.value, cache->current_df->path.value, cache->current_df->path.len);
59 				sm_info->current_aid.len = cache->current_df->path.len;
60 			}
61 		}
62 	}
63 
64 	if (cache->valid && cache->current_ef)
65 		sm_info->current_path_ef = cache->current_ef->path;
66 
67 	return SC_SUCCESS;
68 }
69 
70 
71 static int
sm_restore_sc_context(struct sc_card * card,struct sm_info * sm_info)72 sm_restore_sc_context(struct sc_card *card, struct sm_info *sm_info)
73 {
74 	int rv = SC_SUCCESS;
75 
76 	if (sm_info->current_path_df.type == SC_PATH_TYPE_DF_NAME && sm_info->current_path_df.len)
77 		rv = sc_select_file(card, &sm_info->current_path_df, NULL);
78 
79 	if (sm_info->current_path_ef.len && rv == SC_SUCCESS)
80 		rv = sc_select_file(card, &sm_info->current_path_ef, NULL);
81 
82 	memset(&sm_info->current_path_df, 0, sizeof(sm_info->current_path_df));
83 	memset(&sm_info->current_path_ef, 0, sizeof(sm_info->current_path_ef));
84 
85 	return rv;
86 }
87 
88 static int
iasecc_sm_transmit_apdus(struct sc_card * card,struct sc_remote_data * rdata,unsigned char * out,size_t * out_len)89 iasecc_sm_transmit_apdus(struct sc_card *card, struct sc_remote_data *rdata,
90 		unsigned char *out, size_t *out_len)
91 {
92 	struct sc_context *ctx = card->ctx;
93 	struct sc_remote_apdu *rapdu = rdata->data;
94 	int rv = SC_SUCCESS, offs = 0;
95 
96 	LOG_FUNC_CALLED(ctx);
97 	sc_log(ctx, "iasecc_sm_transmit_apdus() rdata-length %i", rdata->length);
98 
99 	while (rapdu)   {
100 		sc_log(ctx, "iasecc_sm_transmit_apdus() rAPDU flags 0x%lX", rapdu->apdu.flags);
101 		rv = sc_transmit_apdu(card, &rapdu->apdu);
102 		LOG_TEST_RET(ctx, rv, "iasecc_sm_transmit_apdus() failed to execute r-APDU");
103 		rv = sc_check_sw(card, rapdu->apdu.sw1, rapdu->apdu.sw2);
104 		if (rv < 0 && !(rapdu->flags & SC_REMOTE_APDU_FLAG_NOT_FATAL))
105 			LOG_TEST_RET(ctx, rv, "iasecc_sm_transmit_apdus() fatal error %i");
106 
107 		if (out && out_len && (rapdu->flags & SC_REMOTE_APDU_FLAG_RETURN_ANSWER))   {
108 			int len = rapdu->apdu.resplen > (*out_len - offs) ? (*out_len - offs) : rapdu->apdu.resplen;
109 
110 			memcpy(out + offs, rapdu->apdu.resp, len);
111 			offs += len;
112 			/* TODO: decode and gather data answers */
113 		}
114 
115 		rapdu = rapdu->next;
116 	}
117 
118 	if (out_len)
119 		*out_len = offs;
120 
121 	LOG_FUNC_RETURN(ctx, rv);
122 }
123 
124 
125 /* Big TODO: do SM release in all handles, clean the saved card context -- current DF, EF, etc. */
126 static int
sm_release(struct sc_card * card,struct sc_remote_data * rdata,unsigned char * out,size_t out_len)127 sm_release (struct sc_card *card, struct sc_remote_data *rdata,
128 		unsigned char *out, size_t out_len)
129 {
130 	struct sc_context *ctx = card->ctx;
131 	struct sm_info *sm_info = &card->sm_ctx.info;
132 	int rv;
133 
134 	LOG_FUNC_CALLED(ctx);
135 	if (!card->sm_ctx.module.ops.finalize)
136 		LOG_FUNC_RETURN(ctx, SC_SUCCESS);
137 
138 	rv = card->sm_ctx.module.ops.finalize(ctx, sm_info, rdata, out, out_len);
139 
140 	sm_restore_sc_context(card, sm_info);
141 	LOG_FUNC_RETURN(ctx, rv);
142 }
143 #endif
144 
145 
146 int
iasecc_sm_external_authentication(struct sc_card * card,unsigned skey_ref,int * tries_left)147 iasecc_sm_external_authentication(struct sc_card *card, unsigned skey_ref, int *tries_left)
148 {
149 	struct sc_context *ctx = card->ctx;
150 #ifdef ENABLE_SM
151 	struct sm_info *sm_info = &card->sm_ctx.info;
152 	struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
153 	struct sc_remote_data rdata;
154 	struct sc_apdu apdu;
155 	unsigned char sbuf[0x100];
156 	int rv, offs;
157 
158 	LOG_FUNC_CALLED(ctx);
159 	sc_log(ctx, "iasecc_sm_external_authentication(): SKey ref %i", skey_ref);
160 
161 	if (card->sm_ctx.sm_mode == SM_MODE_NONE)
162 		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Cannot do 'External Authentication' without SM activated ");
163 
164 	strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
165 	sm_info->cmd = SM_CMD_EXTERNAL_AUTH;
166 	sm_info->serialnr = card->serialnr;
167 	sm_info->card_type = card->type;
168 	sm_info->sm_type = SM_TYPE_CWA14890;
169 	cwa_session->params.crt_at.usage = IASECC_UQB_AT_EXTERNAL_AUTHENTICATION;
170 	cwa_session->params.crt_at.algo = IASECC_ALGORITHM_ROLE_AUTH;
171 	cwa_session->params.crt_at.refs[0] = skey_ref;
172 
173 	offs = 0;
174 	sbuf[offs++] = IASECC_CRT_TAG_ALGO;
175 	sbuf[offs++] = 0x01;
176 	sbuf[offs++] = IASECC_ALGORITHM_ROLE_AUTH;
177 	sbuf[offs++] = IASECC_CRT_TAG_REFERENCE;
178 	sbuf[offs++] = 0x01;
179 	sbuf[offs++] = skey_ref;
180 
181 	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xA4);
182 	apdu.data = sbuf;
183 	apdu.datalen = offs;
184 	apdu.lc = offs;
185 
186 	rv = sc_transmit_apdu(card, &apdu);
187 	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): APDU transmit failed");
188 	rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
189 	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
190 
191 	rv = sc_get_challenge(card, cwa_session->card_challenge, sizeof(cwa_session->card_challenge));
192 	LOG_TEST_RET(ctx, rv, "iasecc_sm_external_authentication(): set SE error");
193 
194 	sc_remote_data_init(&rdata);
195 
196 	if (!card->sm_ctx.module.ops.initialize)
197 		LOG_TEST_RET(ctx, SC_ERROR_SM_NOT_INITIALIZED, "No SM module");
198 	rv = card->sm_ctx.module.ops.initialize(ctx, sm_info, &rdata);
199 	LOG_TEST_RET(ctx, rv, "SM: INITIALIZE failed");
200 
201 	sc_log(ctx, "sm_iasecc_external_authentication(): rdata length %i\n", rdata.length);
202 
203 	rv = iasecc_sm_transmit_apdus (card, &rdata, NULL, 0);
204 	if (rv == SC_ERROR_PIN_CODE_INCORRECT && tries_left)
205 		*tries_left = (rdata.data + rdata.length - 1)->apdu.sw2 & 0x0F;
206 	LOG_TEST_RET(ctx, rv, "sm_iasecc_external_authentication(): execute failed");
207 
208 	LOG_FUNC_RETURN(ctx, rv);
209 #else
210 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of SM and External Authentication");
211 	return SC_ERROR_NOT_SUPPORTED;
212 #endif
213 }
214 
215 
216 #ifdef ENABLE_SM
217 static int
iasecc_sm_se_mutual_authentication(struct sc_card * card,unsigned se_num)218 iasecc_sm_se_mutual_authentication(struct sc_card *card, unsigned se_num)
219 {
220 	struct sc_context *ctx = card->ctx;
221 	struct sm_info *sm_info = &card->sm_ctx.info;
222 	struct iasecc_se_info se;
223 	struct sc_crt *crt =  &sm_info->session.cwa.params.crt_at;
224 	struct sc_apdu apdu;
225 	unsigned char sbuf[0x100];
226 	int rv, offs;
227 
228 	memset(&se, 0, sizeof(se));
229 
230 	se.reference = se_num;
231 	crt->usage = IASECC_UQB_AT_MUTUAL_AUTHENTICATION;
232 	crt->tag = IASECC_CRT_TAG_AT;
233 
234 	rv = iasecc_se_get_info(card, &se);
235 	LOG_TEST_RET(ctx, rv, "Get SE info error");
236 
237 	rv = iasecc_se_get_crt(card, &se, crt);
238 	LOG_TEST_RET(ctx, rv, "Cannot get authentication CRT");
239 
240 	sc_file_free(se.df);
241 
242 	/* MSE SET Mutual Authentication SK scheme */
243 	offs = 0;
244 	sbuf[offs++] = IASECC_CRT_TAG_ALGO;
245 	sbuf[offs++] = 0x01;
246 	sbuf[offs++] = crt->algo;
247 	sbuf[offs++] = IASECC_CRT_TAG_REFERENCE;
248 	sbuf[offs++] = 0x01;
249 	sbuf[offs++] = crt->refs[0];
250 
251 	sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xC1, 0xA4);
252 	apdu.data = sbuf;
253 	apdu.datalen = offs;
254 	apdu.lc = offs;
255 
256 	rv = sc_transmit_apdu(card, &apdu);
257 	LOG_TEST_RET(ctx, rv, "SM set SE mutual auth.: APDU transmit failed");
258 	rv = sc_check_sw(card, apdu.sw1, apdu.sw2);
259 	LOG_TEST_RET(ctx, rv, "SM set SE mutual auth.: set SE error");
260 
261 	LOG_FUNC_RETURN(ctx, rv);
262 }
263 #endif
264 
265 
266 int
iasecc_sm_initialize(struct sc_card * card,unsigned se_num,unsigned cmd)267 iasecc_sm_initialize(struct sc_card *card, unsigned se_num, unsigned cmd)
268 {
269 	struct sc_context *ctx = card->ctx;
270 #ifdef ENABLE_SM
271 	struct sm_info *sm_info = &card->sm_ctx.info;
272 	struct sm_cwa_session *cwa_session = &sm_info->session.cwa;
273 	struct sc_remote_data rdata;
274 	int rv;
275 
276 	LOG_FUNC_CALLED(ctx);
277 
278 	strlcpy(sm_info->config_section, card->sm_ctx.config_section, sizeof(sm_info->config_section));
279 	sm_info->cmd = cmd;
280 	sm_info->serialnr = card->serialnr;
281 	sm_info->card_type = card->type;
282 	sm_info->sm_type = SM_TYPE_CWA14890;
283 
284 	rv = iasecc_sm_se_mutual_authentication(card, se_num);
285 	LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() MUTUAL AUTHENTICATION failed");
286 
287 	rv = sc_get_challenge(card, cwa_session->card_challenge, SM_SMALL_CHALLENGE_LEN);
288 	LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() GET CHALLENGE failed");
289 
290 	sc_remote_data_init(&rdata);
291 
292 	rv = sm_save_sc_context(card, sm_info);
293 	LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() cannot save current context");
294 
295 	if (!card->sm_ctx.module.ops.initialize)
296 		LOG_TEST_RET(ctx, SC_ERROR_SM_NOT_INITIALIZED, "iasecc_sm_initialize() no SM module");
297 	rv = card->sm_ctx.module.ops.initialize(ctx, sm_info, &rdata);
298 	LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() INITIALIZE failed");
299 
300 
301 	if (rdata.length == 1)   {
302 		rdata.data->flags |= SC_REMOTE_APDU_FLAG_RETURN_ANSWER;
303 		rdata.data->apdu.flags &= ~SC_APDU_FLAGS_NO_GET_RESP;
304 	}
305 	else   {
306 		LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "TODO: SM init with more then one APDU");
307 	}
308 
309 	cwa_session->mdata_len = sizeof(cwa_session->mdata);
310 	rv = iasecc_sm_transmit_apdus (card, &rdata, cwa_session->mdata, &cwa_session->mdata_len);
311 	if (rv == SC_ERROR_PIN_CODE_INCORRECT)
312 		sc_log(ctx, "SM initialization failed, %i tries left", (rdata.data + rdata.length - 1)->apdu.sw2 & 0x0F);
313 	LOG_TEST_RET(ctx, rv, "iasecc_sm_initialize() transmit APDUs failed");
314 
315 	rdata.free(&rdata);
316 
317 	sc_log(ctx, "MA data(len:%"SC_FORMAT_LEN_SIZE_T"u) '%s'",
318 	       cwa_session->mdata_len,
319 	       sc_dump_hex(cwa_session->mdata, cwa_session->mdata_len));
320 	if (cwa_session->mdata_len != 0x48)
321 		LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "iasecc_sm_initialize() invalid MUTUAL AUTHENTICATE result data");
322 
323 	LOG_FUNC_RETURN(ctx, SC_SUCCESS);
324 #else
325 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
326 	return SC_ERROR_NOT_SUPPORTED;
327 #endif
328 }
329 
330 
331 #ifdef ENABLE_SM
332 static int
iasecc_sm_cmd(struct sc_card * card,struct sc_remote_data * rdata)333 iasecc_sm_cmd(struct sc_card *card, struct sc_remote_data *rdata)
334 {
335 #define AUTH_SM_APDUS_MAX 12
336 #define ENCODED_APDUS_MAX_LENGTH (AUTH_SM_APDUS_MAX * (SC_MAX_APDU_BUFFER_SIZE * 2 + 64) + 32)
337 	struct sc_context *ctx = card->ctx;
338 	struct sm_info *sm_info = &card->sm_ctx.info;
339 	struct sm_cwa_session *session = &sm_info->session.cwa;
340 	struct sc_remote_apdu *rapdu = NULL;
341 	int rv;
342 
343 	LOG_FUNC_CALLED(ctx);
344 	if (!card->sm_ctx.module.ops.get_apdus)
345 		LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
346 
347 	rv =  card->sm_ctx.module.ops.get_apdus(ctx, sm_info, session->mdata, session->mdata_len, rdata);
348 	LOG_TEST_RET(ctx, rv, "iasecc_sm_cmd() 'GET APDUS' failed");
349 
350 	sc_log(ctx, "iasecc_sm_cmd() %i remote APDUs to transmit", rdata->length);
351 	for (rapdu = rdata->data; rapdu; rapdu = rapdu->next)   {
352 		struct sc_apdu *apdu = &rapdu->apdu;
353 
354 		sc_log(ctx,
355 		       "iasecc_sm_cmd() apdu->ins:0x%X, resplen %"SC_FORMAT_LEN_SIZE_T"u",
356 		       apdu->ins, apdu->resplen);
357 		if (!apdu->ins)
358 			break;
359 		rv = sc_transmit_apdu(card, apdu);
360 		if (rv < 0)   {
361 			sc_log(ctx, "iasecc_sm_cmd() APDU transmit error rv:%i", rv);
362 			break;
363 		}
364 
365 		rv = sc_check_sw(card, apdu->sw1, apdu->sw2);
366 		if (rv < 0 && !(rapdu->flags & SC_REMOTE_APDU_FLAG_NOT_FATAL))   {
367 			sc_log(ctx, "iasecc_sm_cmd() APDU error rv:%i", rv);
368 			break;
369 		}
370 		sc_log(ctx,
371 		       "iasecc_sm_cmd() apdu->resplen %"SC_FORMAT_LEN_SIZE_T"u",
372 		       apdu->resplen);
373 	}
374 
375 	LOG_FUNC_RETURN(ctx, rv);
376 }
377 #endif
378 
379 
380 int
iasecc_sm_rsa_generate(struct sc_card * card,unsigned se_num,struct iasecc_sdo * sdo)381 iasecc_sm_rsa_generate(struct sc_card *card, unsigned se_num, struct iasecc_sdo *sdo)
382 {
383 	struct sc_context *ctx = card->ctx;
384 #ifdef ENABLE_SM
385 	struct sm_info *sm_info = &card->sm_ctx.info;
386 	struct sc_remote_data rdata;
387 	int rv;
388 
389 	LOG_FUNC_CALLED(ctx);
390 	sc_log(ctx, "iasecc_sm_rsa_generate() SE#%i, SDO(class:%X,ref:%X)", se_num, sdo->sdo_class, sdo->sdo_ref);
391 
392 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_RSA_GENERATE);
393 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_generate() SM initialize failed");
394 
395 	sm_info->cmd_data = sdo;
396 
397 	sc_remote_data_init(&rdata);
398 	rv = iasecc_sm_cmd(card, &rdata);
399 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_generate() SM cmd failed");
400 
401 	rv = sm_release (card, &rdata, NULL, 0);
402 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_generate() SM release failed");
403 
404 	rdata.free(&rdata);
405 	LOG_FUNC_RETURN(ctx, rv);
406 #else
407 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
408 	return SC_ERROR_NOT_SUPPORTED;
409 #endif
410 }
411 
412 
413 int
iasecc_sm_rsa_update(struct sc_card * card,unsigned se_num,struct iasecc_sdo_rsa_update * udata)414 iasecc_sm_rsa_update(struct sc_card *card, unsigned se_num, struct iasecc_sdo_rsa_update *udata)
415 {
416 	struct sc_context *ctx = card->ctx;
417 #ifdef ENABLE_SM
418 	struct sm_info *sm_info = &card->sm_ctx.info;
419 	struct sc_remote_data rdata;
420 	int rv;
421 
422 	LOG_FUNC_CALLED(ctx);
423 	sc_log(ctx, "SM update RSA: SE#: 0x%X, SDO(class:0x%X:ref:%X)", se_num,
424 			udata->sdo_prv_key->sdo_class, udata->sdo_prv_key->sdo_ref);
425 
426 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_RSA_UPDATE);
427 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM initialize failed");
428 
429 	sm_info->cmd_data = udata;
430 
431 	sc_remote_data_init(&rdata);
432 	rv = iasecc_sm_cmd(card, &rdata);
433 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM cmd failed");
434 
435 	rv = sm_release (card, &rdata, NULL, 0);
436 	LOG_TEST_RET(ctx, rv, "iasecc_sm_rsa_update() SM release failed");
437 
438 	rdata.free(&rdata);
439 	LOG_FUNC_RETURN(ctx, rv);
440 #else
441 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
442 	return SC_ERROR_NOT_SUPPORTED;
443 #endif
444 }
445 
446 
447 int
iasecc_sm_pin_verify(struct sc_card * card,unsigned se_num,struct sc_pin_cmd_data * data,int * tries_left)448 iasecc_sm_pin_verify(struct sc_card *card, unsigned se_num, struct sc_pin_cmd_data *data, int *tries_left)
449 {
450 	struct sc_context *ctx = card->ctx;
451 #ifdef ENABLE_SM
452 	struct sm_info *sm_info = &card->sm_ctx.info;
453 	struct sc_remote_data rdata;
454 	int rv;
455 
456 	LOG_FUNC_CALLED(ctx);
457 	sc_log(ctx, "iasecc_sm_pin_verify() SE#%i, PIN(ref:%i,len:%i)", se_num, data->pin_reference, data->pin1.len);
458 
459 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_PIN_VERIFY);
460 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM INITIALIZE failed");
461 
462 	sm_info->cmd_data = data;
463 
464 	sc_remote_data_init(&rdata);
465 	rv = iasecc_sm_cmd(card, &rdata);
466 	if (rv && rdata.length && tries_left)
467 		if (rdata.data->apdu.sw1 == 0x63 && (rdata.data->apdu.sw2 & 0xF0) == 0xC0)
468 			*tries_left = rdata.data->apdu.sw2 & 0x0F;
469 
470 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM 'PIN VERIFY' failed");
471 
472 	rv = sm_release (card, &rdata, NULL, 0);
473 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_verify() SM release failed");
474 
475 	rdata.free(&rdata);
476 	LOG_FUNC_RETURN(ctx, rv);
477 #else
478 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
479 	return SC_ERROR_NOT_SUPPORTED;
480 #endif
481 }
482 
483 
484 int
iasecc_sm_sdo_update(struct sc_card * card,unsigned se_num,struct iasecc_sdo_update * update)485 iasecc_sm_sdo_update(struct sc_card *card, unsigned se_num, struct iasecc_sdo_update *update)
486 {
487 	struct sc_context *ctx = card->ctx;
488 #ifdef ENABLE_SM
489 	struct sm_info *sm_info = &card->sm_ctx.info;
490 	struct sc_remote_data rdata;
491 	int rv;
492 
493 	LOG_FUNC_CALLED(ctx);
494 	sc_log(ctx, "iasecc_sm_sdo_update() SE#%i, SDO(class:0x%X,ref:%i)", se_num, update->sdo_class, update->sdo_ref);
495 
496 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_SDO_UPDATE);
497 	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM INITIALIZE failed");
498 
499 	sc_log(ctx, "current DF '%s'", sc_print_path(&sm_info->current_path_df));
500 
501 	sm_info->cmd_data = update;
502 
503 	sc_remote_data_init(&rdata);
504 	rv = iasecc_sm_cmd(card, &rdata);
505 	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM 'SDO UPDATE' failed");
506 
507 	rv = sm_release (card, &rdata, NULL, 0);
508 	LOG_TEST_RET(ctx, rv, "iasecc_sm_sdo_update() SM release failed");
509 
510 	rdata.free(&rdata);
511 	LOG_FUNC_RETURN(ctx, rv);
512 #else
513 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
514 	return SC_ERROR_NOT_SUPPORTED;
515 #endif
516 }
517 
518 
519 int
iasecc_sm_pin_reset(struct sc_card * card,unsigned se_num,struct sc_pin_cmd_data * data)520 iasecc_sm_pin_reset(struct sc_card *card, unsigned se_num, struct sc_pin_cmd_data *data)
521 {
522 	struct sc_context *ctx = card->ctx;
523 #ifdef ENABLE_SM
524 	struct sm_info *sm_info = &card->sm_ctx.info;
525 	struct sc_remote_data rdata;
526 	int rv;
527 
528 	LOG_FUNC_CALLED(ctx);
529 	sc_log(ctx, "iasecc_sm_pin_reset() SE#%i, PIN(ref:%i,len:%i)", se_num, data->pin_reference, data->pin2.len);
530 
531 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_PIN_RESET);
532 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM INITIALIZE failed");
533 
534 	sm_info->cmd_data = data;
535 
536 	sc_remote_data_init(&rdata);
537 	rv = iasecc_sm_cmd(card, &rdata);
538 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM 'PIN RESET' failed");
539 
540 	rv = sm_release (card, &rdata, NULL, 0);
541 	LOG_TEST_RET(ctx, rv, "iasecc_sm_pin_reset() SM release failed");
542 
543 	rdata.free(&rdata);
544 	LOG_FUNC_RETURN(ctx, rv);
545 #else
546 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
547 	return SC_ERROR_NOT_SUPPORTED;
548 #endif
549 }
550 
551 
552 int
iasecc_sm_create_file(struct sc_card * card,unsigned se_num,unsigned char * fcp,size_t fcp_len)553 iasecc_sm_create_file(struct sc_card *card, unsigned se_num, unsigned char *fcp, size_t fcp_len)
554 {
555 	struct sc_context *ctx = card->ctx;
556 #ifdef ENABLE_SM
557 	struct sm_info *sm_info = &card->sm_ctx.info;
558 	struct sc_remote_data rdata;
559 	struct iasecc_sm_cmd_create_file cmd_data;
560 	int rv;
561 
562 	LOG_FUNC_CALLED(ctx);
563 	sc_log(ctx,
564 	       "iasecc_sm_create_file() SE#%i, fcp(%"SC_FORMAT_LEN_SIZE_T"u) '%s'",
565 	       se_num, fcp_len, sc_dump_hex(fcp, fcp_len));
566 
567 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_CREATE);
568 	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM INITIALIZE failed");
569 
570 	cmd_data.data = fcp;
571 	cmd_data.size = fcp_len;
572 	sm_info->cmd_data = &cmd_data;
573 
574 	sc_remote_data_init(&rdata);
575 	rv= iasecc_sm_cmd(card, &rdata);
576 	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM 'UPDATE BINARY' failed");
577 
578 	rv = sm_release (card, &rdata, NULL, 0);
579 	LOG_TEST_RET(ctx, rv, "iasecc_sm_create_file() SM release failed");
580 
581 	rdata.free(&rdata);
582 	LOG_FUNC_RETURN(ctx, rv);
583 #else
584 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
585 	return SC_ERROR_NOT_SUPPORTED;
586 #endif
587 }
588 
589 int
iasecc_sm_read_binary(struct sc_card * card,unsigned se_num,size_t offs,unsigned char * buff,size_t count)590 iasecc_sm_read_binary(struct sc_card *card, unsigned se_num, size_t offs, unsigned char *buff, size_t count)
591 {
592 	struct sc_context *ctx = card->ctx;
593 #ifdef ENABLE_SM
594 	struct sm_info *sm_info = &card->sm_ctx.info;
595 	struct sc_remote_data rdata;
596 	struct iasecc_sm_cmd_update_binary cmd_data;
597 	int rv;
598 
599 	LOG_FUNC_CALLED(ctx);
600 	sc_log(ctx,
601 	       "SM read binary: acl:%X, offs:%"SC_FORMAT_LEN_SIZE_T"u, count:%"SC_FORMAT_LEN_SIZE_T"u",
602 	       se_num, offs, count);
603 
604 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_READ);
605 	LOG_TEST_RET(ctx, rv, "iasecc_sm_read_binary() SM INITIALIZE failed");
606 
607 	cmd_data.offs = offs;
608 	cmd_data.count = count;
609 	sm_info->cmd_data = &cmd_data;
610 
611 	sc_remote_data_init(&rdata);
612 	rv = iasecc_sm_cmd(card, &rdata);
613 	LOG_TEST_RET(ctx, rv, "iasecc_sm_read_binary() SM 'READ BINARY' failed");
614 
615 	sc_log(ctx, "IAS/ECC decode answer() rdata length %i", rdata.length);
616 
617 	rv = sm_release (card, &rdata, buff, count);
618 	LOG_TEST_RET(ctx, rv, "iasecc_sm_read_binary() SM release failed");
619 
620 	rdata.free(&rdata);
621 	LOG_FUNC_RETURN(ctx, rv);
622 #else
623 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
624 	return SC_ERROR_NOT_SUPPORTED;
625 #endif
626 }
627 
628 
629 int
iasecc_sm_update_binary(struct sc_card * card,unsigned se_num,size_t offs,const unsigned char * buff,size_t count)630 iasecc_sm_update_binary(struct sc_card *card, unsigned se_num, size_t offs,
631 		const unsigned char *buff, size_t count)
632 {
633 	struct sc_context *ctx = card->ctx;
634 #ifdef ENABLE_SM
635 	struct sm_info *sm_info = &card->sm_ctx.info;
636 	struct sc_remote_data rdata;
637 	struct iasecc_sm_cmd_update_binary cmd_data;
638 	int rv;
639 
640 	LOG_FUNC_CALLED(ctx);
641 	sc_log(ctx,
642 	       "SM update binary: acl:%X, offs:%"SC_FORMAT_LEN_SIZE_T"u, count:%"SC_FORMAT_LEN_SIZE_T"u",
643 	       se_num, offs, count);
644 
645 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_UPDATE);
646 	LOG_TEST_RET(ctx, rv, "iasecc_sm_update_binary() SM INITIALIZE failed");
647 
648 	cmd_data.offs = offs;
649 	cmd_data.count = count;
650 	cmd_data.data = buff;
651 	sm_info->cmd_data = &cmd_data;
652 
653 	sc_remote_data_init(&rdata);
654 	rv = iasecc_sm_cmd(card, &rdata);
655 	LOG_TEST_RET(ctx, rv, "iasecc_sm_update_binary() SM 'UPDATE BINARY' failed");
656 
657 	rv = sm_release (card, &rdata, NULL, 0);
658 	LOG_TEST_RET(ctx, rv, "iasecc_sm_update_binary() SM release failed");
659 
660 	rdata.free(&rdata);
661 	LOG_FUNC_RETURN(ctx, count);
662 #else
663 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
664 	return SC_ERROR_NOT_SUPPORTED;
665 #endif
666 }
667 
668 
669 int
iasecc_sm_delete_file(struct sc_card * card,unsigned se_num,unsigned int file_id)670 iasecc_sm_delete_file(struct sc_card *card, unsigned se_num, unsigned int file_id)
671 {
672 	struct sc_context *ctx = card->ctx;
673 #ifdef ENABLE_SM
674 	struct sm_info *sm_info = &card->sm_ctx.info;
675 	struct sc_remote_data rdata;
676 	int rv;
677 
678 	LOG_FUNC_CALLED(ctx);
679 	sc_log(ctx, "SM delete file: SE#:%X, file-id:%X", se_num, file_id);
680 
681 	rv = iasecc_sm_initialize(card, se_num, SM_CMD_FILE_DELETE);
682 	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM INITIALIZE failed");
683 
684 	sm_info->cmd_data = (void *)(uintptr_t)file_id;
685 
686 	sc_remote_data_init(&rdata);
687 	rv = iasecc_sm_cmd(card, &rdata);
688 	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM 'FILE DELETE' failed");
689 
690 	rv = sm_release (card, &rdata, NULL, 0);
691 	LOG_TEST_RET(ctx, rv, "iasecc_sm_delete_file() SM release failed");
692 
693 	rdata.free(&rdata);
694 	LOG_FUNC_RETURN(ctx, rv);
695 #else
696 	LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "built without support of Secure-Messaging");
697 	return SC_ERROR_NOT_SUPPORTED;
698 #endif
699 }
700 
701 
702