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