/src/opensc/src/sm/sm-eac.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2011-2018 Frank Morgner |
3 | | * |
4 | | * This file is part of OpenSC. |
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | #ifdef HAVE_CONFIG_H |
21 | | #include "config.h" |
22 | | #endif |
23 | | |
24 | | #include "sm/sm-iso.h" |
25 | | #include "libopensc/asn1.h" |
26 | | #include "libopensc/log.h" |
27 | | #include "libopensc/opensc.h" |
28 | | #include "sm-eac.h" |
29 | | #include <stdlib.h> |
30 | | #include <string.h> |
31 | | |
32 | | #ifdef ENABLE_OPENSSL |
33 | | #include <openssl/evp.h> |
34 | | #endif |
35 | | |
36 | | char eac_default_flags = 0; |
37 | 0 | #define ISO_MSE 0x22 |
38 | | |
39 | | #if defined(ENABLE_OPENPACE) && defined(ENABLE_SM) |
40 | | #include <eac/ca.h> |
41 | | #include <eac/cv_cert.h> |
42 | | #include <eac/eac.h> |
43 | | #include <eac/objects.h> |
44 | | #include <eac/pace.h> |
45 | | #include <eac/ta.h> |
46 | | #include <openssl/bio.h> |
47 | | #include <openssl/buffer.h> |
48 | | #include <openssl/err.h> |
49 | | #include <openssl/evp.h> |
50 | | #include <openssl/objects.h> |
51 | | |
52 | | |
53 | | /** @brief EAC secure messaging context */ |
54 | | struct eac_sm_ctx { |
55 | | /** @brief EAC context */ |
56 | | EAC_CTX *ctx; |
57 | | /** @brief picc's compressed ephemeral public key of PACE */ |
58 | | BUF_MEM *id_icc; |
59 | | /** @brief PCD's compressed ephemeral public key of CA */ |
60 | | BUF_MEM *eph_pub_key; |
61 | | /** @brief Auxiliary Data */ |
62 | | BUF_MEM *auxiliary_data; |
63 | | char flags; |
64 | | }; |
65 | | |
66 | | |
67 | | /* included in OpenPACE, but not propagated */ |
68 | | extern BUF_MEM *BUF_MEM_create(size_t len); |
69 | | extern BUF_MEM *BUF_MEM_create_init(const void *buf, size_t len); |
70 | | |
71 | | |
72 | | static int eac_sm_encrypt(sc_card_t *card, const struct iso_sm_ctx *ctx, |
73 | | const u8 *data, size_t datalen, u8 **enc); |
74 | | static int eac_sm_decrypt(sc_card_t *card, const struct iso_sm_ctx *ctx, |
75 | | const u8 *enc, size_t enclen, u8 **data); |
76 | | static int eac_sm_authenticate(sc_card_t *card, const struct iso_sm_ctx *ctx, |
77 | | const u8 *data, size_t datalen, u8 **outdata); |
78 | | static int eac_sm_verify_authentication(sc_card_t *card, const struct iso_sm_ctx *ctx, |
79 | | const u8 *mac, size_t maclen, |
80 | | const u8 *macdata, size_t macdatalen); |
81 | | static int eac_sm_pre_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx, |
82 | | sc_apdu_t *apdu); |
83 | | static int eac_sm_post_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx, |
84 | | sc_apdu_t *sm_apdu); |
85 | | static int eac_sm_finish(sc_card_t *card, const struct iso_sm_ctx *ctx, |
86 | | sc_apdu_t *apdu); |
87 | | static void eac_sm_clear_free(const struct iso_sm_ctx *ctx); |
88 | | |
89 | | |
90 | | |
91 | | |
92 | | static struct eac_sm_ctx * |
93 | | eac_sm_ctx_create(EAC_CTX *ctx, |
94 | | const unsigned char *id_icc, size_t id_icc_length) |
95 | 0 | { |
96 | 0 | struct eac_sm_ctx *out = malloc(sizeof *out); |
97 | 0 | if (!out) |
98 | 0 | goto err; |
99 | | |
100 | 0 | out->ctx = ctx; |
101 | |
|
102 | 0 | if (id_icc && id_icc_length) { |
103 | 0 | out->id_icc = BUF_MEM_create_init(id_icc, id_icc_length); |
104 | 0 | if (!out->id_icc) |
105 | 0 | goto err; |
106 | 0 | } else |
107 | 0 | out->id_icc = NULL; |
108 | | |
109 | 0 | out->eph_pub_key = NULL; |
110 | 0 | out->auxiliary_data = NULL; |
111 | |
|
112 | 0 | out->flags = eac_default_flags; |
113 | 0 | if (out->flags & EAC_FLAG_DISABLE_CHECK_TA) |
114 | 0 | TA_disable_checks(out->ctx); |
115 | 0 | if (out->flags & EAC_FLAG_DISABLE_CHECK_CA) |
116 | 0 | CA_disable_passive_authentication(out->ctx); |
117 | |
|
118 | 0 | return out; |
119 | | |
120 | 0 | err: |
121 | 0 | free(out); |
122 | 0 | return NULL; |
123 | 0 | } |
124 | | |
125 | | static int |
126 | | eac_sm_start(sc_card_t *card, EAC_CTX *eac_ctx, |
127 | | const unsigned char *id_icc, size_t id_icc_length) |
128 | 0 | { |
129 | 0 | int r; |
130 | 0 | struct iso_sm_ctx *sctx = NULL; |
131 | |
|
132 | 0 | if (!eac_ctx || !eac_ctx->key_ctx) { |
133 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
134 | 0 | goto err; |
135 | 0 | } |
136 | | |
137 | 0 | sctx = iso_sm_ctx_create(); |
138 | 0 | if (!sctx) { |
139 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
140 | 0 | goto err; |
141 | 0 | } |
142 | | |
143 | 0 | sctx->priv_data = eac_sm_ctx_create(eac_ctx, |
144 | 0 | id_icc, id_icc_length); |
145 | 0 | if (!sctx->priv_data) { |
146 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
147 | 0 | goto err; |
148 | 0 | } |
149 | | |
150 | 0 | sctx->authenticate = eac_sm_authenticate; |
151 | 0 | sctx->encrypt = eac_sm_encrypt; |
152 | 0 | sctx->decrypt = eac_sm_decrypt; |
153 | 0 | sctx->verify_authentication = eac_sm_verify_authentication; |
154 | 0 | sctx->pre_transmit = eac_sm_pre_transmit; |
155 | 0 | sctx->post_transmit = eac_sm_post_transmit; |
156 | 0 | sctx->finish = eac_sm_finish; |
157 | 0 | sctx->clear_free = eac_sm_clear_free; |
158 | 0 | sctx->padding_indicator = SM_ISO_PADDING; |
159 | 0 | sctx->block_length = EVP_CIPHER_block_size(eac_ctx->key_ctx->cipher); |
160 | |
|
161 | 0 | r = iso_sm_start(card, sctx); |
162 | |
|
163 | 0 | err: |
164 | 0 | if (r < 0) |
165 | 0 | iso_sm_ctx_clear_free(sctx); |
166 | |
|
167 | 0 | return r; |
168 | 0 | } |
169 | | |
170 | | static int get_ef_card_access(sc_card_t *card, |
171 | | u8 **ef_cardaccess, size_t *length_ef_cardaccess) |
172 | 0 | { |
173 | 0 | return iso7816_read_binary_sfid(card, SFID_EF_CARDACCESS, ef_cardaccess, length_ef_cardaccess); |
174 | 0 | } |
175 | | |
176 | | /* |
177 | | * MSE:Set AT |
178 | | */ |
179 | | static int encode_mse_cdata(struct sc_context *ctx, int protocol, |
180 | | const unsigned char *key_reference1, size_t key_reference1_len, |
181 | | const unsigned char *key_reference2, size_t key_reference2_len, |
182 | | const unsigned char *eph_pub_key, size_t eph_pub_key_len, |
183 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len, |
184 | | const CVC_CHAT *chat, unsigned char **cdata) |
185 | 0 | { |
186 | 0 | unsigned char *data = NULL, *encoded_chat = NULL, oid[16], *p = NULL; |
187 | 0 | size_t data_len = 0, oid_len = 0; |
188 | 0 | int r, encoded_chat_len = 0; |
189 | |
|
190 | 0 | struct sc_asn1_entry capdu_eac_mse[] = { |
191 | 0 | { "Cryptographic mechanism reference", |
192 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x00, SC_ASN1_OPTIONAL, NULL, NULL }, |
193 | 0 | { "Reference of a public key / secret key", |
194 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x03, SC_ASN1_OPTIONAL, NULL, NULL }, |
195 | 0 | { "Reference of a private key / Reference for computing a session key", |
196 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x04, SC_ASN1_OPTIONAL, NULL, NULL }, |
197 | 0 | { "Ephemeral Public Key", |
198 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x11, SC_ASN1_OPTIONAL, NULL, NULL }, |
199 | 0 | { "Auxiliary authenticated data", |
200 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_APP|SC_ASN1_CONS|0x07, SC_ASN1_OPTIONAL, NULL, NULL }, |
201 | | /* "Certificate Holder Authorization Template", */ |
202 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
203 | 0 | }; |
204 | |
|
205 | 0 | if (!cdata) { |
206 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
207 | 0 | goto err; |
208 | 0 | } |
209 | | |
210 | 0 | if (protocol) { |
211 | 0 | ASN1_OBJECT *object = NULL; |
212 | | #ifndef HAVE_EAC_OBJ_NID2OBJ |
213 | | object = OBJ_nid2obj(protocol); |
214 | | #else |
215 | 0 | object = EAC_OBJ_nid2obj(protocol); |
216 | 0 | #endif |
217 | 0 | if (!object) { |
218 | 0 | sc_debug(ctx, SC_LOG_DEBUG_VERBOSE, "Error setting Cryptographic mechanism reference of MSE:Set AT data"); |
219 | 0 | r = SC_ERROR_INTERNAL; |
220 | 0 | goto err; |
221 | 0 | } |
222 | 0 | oid_len = OBJ_length(object); |
223 | 0 | memcpy(oid, OBJ_get0_data(object), oid_len); |
224 | 0 | } |
225 | | |
226 | 0 | sc_format_asn1_entry(capdu_eac_mse + 0, oid, &oid_len, oid_len > 0); |
227 | 0 | sc_format_asn1_entry(capdu_eac_mse + 1, (unsigned char *) key_reference1, &key_reference1_len, key_reference1 && key_reference1_len); |
228 | 0 | sc_format_asn1_entry(capdu_eac_mse + 2, (unsigned char *) key_reference2, &key_reference2_len, key_reference2 && key_reference2_len); |
229 | 0 | sc_format_asn1_entry(capdu_eac_mse + 3, (unsigned char *) eph_pub_key, &eph_pub_key_len, eph_pub_key && eph_pub_key_len); |
230 | 0 | sc_format_asn1_entry(capdu_eac_mse + 4, (unsigned char *) auxiliary_data, &auxiliary_data_len, auxiliary_data && auxiliary_data_len); |
231 | |
|
232 | 0 | r = sc_asn1_encode(ctx, capdu_eac_mse, &data, &data_len); |
233 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, r, "Error encoding MSE:Set AT APDU data"); |
234 | | |
235 | 0 | if (chat) { |
236 | 0 | encoded_chat_len = i2d_CVC_CHAT((CVC_CHAT *) chat, &encoded_chat); |
237 | 0 | if (encoded_chat_len < 0) { |
238 | 0 | sc_log_openssl(ctx); |
239 | 0 | r = SC_ERROR_INTERNAL; |
240 | 0 | goto err; |
241 | 0 | } |
242 | 0 | } |
243 | | |
244 | | |
245 | 0 | p = realloc(*cdata, data_len + encoded_chat_len); |
246 | 0 | if (!p) { |
247 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
248 | 0 | goto err; |
249 | 0 | } |
250 | 0 | memcpy(p, data, data_len); |
251 | 0 | memcpy(p+data_len, encoded_chat, encoded_chat_len); |
252 | 0 | *cdata = p; |
253 | 0 | r = (int)(data_len + encoded_chat_len); |
254 | |
|
255 | 0 | sc_debug_hex(ctx, SC_LOG_DEBUG_SM, "MSE command data", p, r); |
256 | |
|
257 | 0 | err: |
258 | 0 | free(data); |
259 | 0 | if (encoded_chat) |
260 | 0 | OPENSSL_free(encoded_chat); |
261 | |
|
262 | 0 | return r; |
263 | 0 | } |
264 | | |
265 | | static int eac_mse(sc_card_t *card, |
266 | | unsigned char p1, unsigned char p2, int protocol, |
267 | | const unsigned char *key_reference1, size_t key_reference1_len, |
268 | | const unsigned char *key_reference2, size_t key_reference2_len, |
269 | | const unsigned char *eph_pub_key, size_t eph_pub_key_len, |
270 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len, |
271 | | const CVC_CHAT *chat, u8 *sw1, u8 *sw2) |
272 | 0 | { |
273 | 0 | sc_apdu_t apdu; |
274 | 0 | unsigned char *d = NULL; |
275 | 0 | int r; |
276 | |
|
277 | 0 | if (!card) { |
278 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
279 | 0 | goto err; |
280 | 0 | } |
281 | | |
282 | 0 | r = encode_mse_cdata(card->ctx, protocol, key_reference1, |
283 | 0 | key_reference1_len, key_reference2, key_reference2_len, |
284 | 0 | eph_pub_key, eph_pub_key_len, auxiliary_data, auxiliary_data_len, |
285 | 0 | chat, &d); |
286 | 0 | if (r < 0) |
287 | 0 | goto err; |
288 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_MSE, p1, p2, |
289 | 0 | d, r, NULL, 0); |
290 | |
|
291 | 0 | r = sc_transmit_apdu(card, &apdu); |
292 | 0 | if (r < 0) |
293 | 0 | goto err; |
294 | | |
295 | 0 | if (apdu.resplen) { |
296 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "MSE:Set AT response data should be empty " |
297 | 0 | "(contains %"SC_FORMAT_LEN_SIZE_T"u bytes)", apdu.resplen); |
298 | 0 | r = SC_ERROR_UNKNOWN_DATA_RECEIVED; |
299 | 0 | goto err; |
300 | 0 | } |
301 | | |
302 | 0 | if (sw1) |
303 | 0 | *sw1 = apdu.sw1; |
304 | 0 | if (sw2) |
305 | 0 | *sw2 = apdu.sw2; |
306 | |
|
307 | 0 | err: |
308 | 0 | free(d); |
309 | |
|
310 | 0 | return r; |
311 | 0 | } |
312 | | |
313 | | static int eac_mse_set_at(sc_card_t *card, unsigned char p1, int protocol, |
314 | | const unsigned char *key_reference1, size_t key_reference1_len, |
315 | | const unsigned char *key_reference2, size_t key_reference2_len, |
316 | | const unsigned char *eph_pub_key, size_t eph_pub_key_len, |
317 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len, |
318 | | const CVC_CHAT *chat, u8 *sw1, u8 *sw2) |
319 | 0 | { |
320 | 0 | return eac_mse(card, p1, 0xA4, protocol, key_reference1, |
321 | 0 | key_reference1_len, key_reference2, key_reference2_len, |
322 | 0 | eph_pub_key, eph_pub_key_len, auxiliary_data, auxiliary_data_len, |
323 | 0 | chat, sw1, sw2); |
324 | 0 | } |
325 | | |
326 | | static int eac_mse_set_at_pace(sc_card_t *card, int protocol, |
327 | | enum s_type secret_key, const CVC_CHAT *chat, u8 *sw1, u8 *sw2) |
328 | 0 | { |
329 | 0 | int r, tries; |
330 | 0 | unsigned char key = secret_key; |
331 | |
|
332 | 0 | r = eac_mse_set_at(card, 0xC1, protocol, &key, sizeof key, NULL, |
333 | 0 | 0, NULL, 0, NULL, 0, chat, sw1, sw2); |
334 | 0 | if (0 > r) |
335 | 0 | goto err; |
336 | | |
337 | 0 | if (*sw1 == 0x63) { |
338 | 0 | if ((*sw2 & 0xc0) == 0xc0) { |
339 | 0 | tries = *sw2 & 0x0f; |
340 | 0 | if (tries <= 1) { |
341 | | /* this is only a warning... */ |
342 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Remaining tries: %d (%s must be %s)\n", |
343 | 0 | tries, eac_secret_name(secret_key), |
344 | 0 | tries ? "resumed" : "unblocked"); |
345 | 0 | } |
346 | 0 | r = SC_SUCCESS; |
347 | 0 | } else { |
348 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Unknown status bytes: SW1=%02X, SW2=%02X\n", |
349 | 0 | *sw1, *sw2); |
350 | 0 | r = SC_ERROR_CARD_CMD_FAILED; |
351 | 0 | } |
352 | 0 | } else if (*sw1 == 0x62 && *sw2 == 0x83) { |
353 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Password is deactivated\n"); |
354 | 0 | r = SC_ERROR_AUTH_METHOD_BLOCKED; |
355 | 0 | } else { |
356 | 0 | r = sc_check_sw(card, *sw1, *sw2); |
357 | 0 | } |
358 | |
|
359 | 0 | err: |
360 | 0 | return r; |
361 | 0 | } |
362 | | |
363 | | |
364 | | /* |
365 | | * General Authenticate |
366 | | */ |
367 | | static int encode_gen_auth_cdata(struct sc_context *ctx, |
368 | | const unsigned char *ca_eph_pub_key, size_t ca_eph_pub_key_len, |
369 | | const unsigned char *mapping_data, size_t mapping_data_len, |
370 | | const unsigned char *eph_pub_key, size_t eph_pub_key_len, |
371 | | const unsigned char *auth_token, size_t auth_token_len, |
372 | | unsigned char **cdata) |
373 | 0 | { |
374 | 0 | size_t data_len = 0; |
375 | 0 | int r; |
376 | |
|
377 | 0 | struct sc_asn1_entry capdu_eac_gen_auth_data[] = { |
378 | 0 | { "Ephemeral Public Key (CA)", |
379 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x00, SC_ASN1_OPTIONAL, NULL, NULL }, |
380 | 0 | { "Mapping Data", |
381 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x01, SC_ASN1_OPTIONAL, NULL, NULL }, |
382 | 0 | { "Ephemeral Public Key (PACE)", |
383 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x03, SC_ASN1_OPTIONAL, NULL, NULL }, |
384 | 0 | { "Authentication Token", |
385 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x05, SC_ASN1_OPTIONAL, NULL, NULL }, |
386 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
387 | 0 | }; |
388 | |
|
389 | 0 | struct sc_asn1_entry capdu_eac_gen_auth[] = { |
390 | 0 | { "Dynamic Authentication Data", SC_ASN1_STRUCT, SC_ASN1_APP|SC_ASN1_CONS|0x1c, 0, NULL, NULL }, |
391 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
392 | 0 | }; |
393 | |
|
394 | 0 | if (!cdata) { |
395 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
396 | 0 | goto err; |
397 | 0 | } |
398 | | |
399 | 0 | sc_format_asn1_entry(capdu_eac_gen_auth + 0, capdu_eac_gen_auth_data, &capdu_eac_gen_auth_data, 1); |
400 | |
|
401 | 0 | sc_format_asn1_entry(capdu_eac_gen_auth_data + 0, (unsigned char *) ca_eph_pub_key, &ca_eph_pub_key_len, ca_eph_pub_key && ca_eph_pub_key_len); |
402 | 0 | sc_format_asn1_entry(capdu_eac_gen_auth_data + 1, (unsigned char *) mapping_data, &mapping_data_len, mapping_data && mapping_data_len); |
403 | 0 | sc_format_asn1_entry(capdu_eac_gen_auth_data + 2, (unsigned char *) eph_pub_key, &eph_pub_key_len, eph_pub_key && eph_pub_key_len); |
404 | 0 | sc_format_asn1_entry(capdu_eac_gen_auth_data + 3, (unsigned char *) auth_token, &auth_token_len, auth_token && auth_token_len); |
405 | |
|
406 | 0 | r = sc_asn1_encode(ctx, capdu_eac_gen_auth, cdata, &data_len); |
407 | 0 | SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, r, "Error encoding General Authenticate APDU data"); |
408 | 0 | r = (int)data_len; |
409 | |
|
410 | 0 | err: |
411 | 0 | return r; |
412 | 0 | } |
413 | | static int decode_gen_auth_rdata(struct sc_context *ctx, |
414 | | const unsigned char *rdata, size_t rdata_len, |
415 | | unsigned char **enc_nonce, size_t *enc_nonce_len, |
416 | | unsigned char **mapping_data, size_t *mapping_data_len, |
417 | | unsigned char **eph_pub_key, size_t *eph_pub_key_len, |
418 | | unsigned char **auth_token, size_t *auth_token_len, |
419 | | unsigned char **cur_car, size_t *cur_car_len, |
420 | | unsigned char **prev_car, size_t *prev_car_len) |
421 | 0 | { |
422 | 0 | struct sc_asn1_entry rapdu_eac_gen_auth_data[] = { |
423 | 0 | { "Encrypted Nonce", |
424 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x00, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
425 | 0 | { "Mapping Data", |
426 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x02, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
427 | 0 | { "Ephemeral Public Key", |
428 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x04, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
429 | 0 | { "Authentication Token", |
430 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x06, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
431 | 0 | { "Most recent Certification Authority Reference", |
432 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
433 | 0 | { "Pverious recent Certification Authority Reference", |
434 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x07, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
435 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
436 | 0 | }; |
437 | |
|
438 | 0 | struct sc_asn1_entry rapdu_eac_gen_auth[] = { |
439 | 0 | { "Dynamic Authentication Data", SC_ASN1_STRUCT, SC_ASN1_APP|SC_ASN1_CONS|0x1c, 0, NULL, NULL }, |
440 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
441 | 0 | }; |
442 | |
|
443 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth + 0, rapdu_eac_gen_auth_data, &rapdu_eac_gen_auth_data, 1); |
444 | |
|
445 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 0, enc_nonce, enc_nonce_len, 0); |
446 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 1, mapping_data, mapping_data_len, 0); |
447 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 2, eph_pub_key, eph_pub_key_len, 0); |
448 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 3, auth_token, auth_token_len, 0); |
449 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 4, cur_car, cur_car_len, 0); |
450 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_data + 5, prev_car, prev_car_len, 0); |
451 | |
|
452 | 0 | return sc_asn1_decode(ctx, rapdu_eac_gen_auth, rdata, rdata_len, NULL, NULL); |
453 | 0 | } |
454 | 0 | #define ISO_GENERAL_AUTHENTICATE 0x86 |
455 | 0 | #define ISO_COMMAND_CHAINING 0x10 |
456 | | static int eac_gen_auth_1_encrypted_nonce(sc_card_t *card, |
457 | | u8 **enc_nonce, size_t *enc_nonce_len) |
458 | 0 | { |
459 | 0 | sc_apdu_t apdu; |
460 | 0 | unsigned char *d = NULL; |
461 | 0 | int r; |
462 | 0 | unsigned char resp[SC_MAX_APDU_RESP_SIZE]; |
463 | |
|
464 | 0 | r = encode_gen_auth_cdata(card->ctx, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &d); |
465 | 0 | if (r < 0) |
466 | 0 | goto err; |
467 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00, |
468 | 0 | d, r, resp, sizeof resp); |
469 | 0 | apdu.cla = ISO_COMMAND_CHAINING; |
470 | |
|
471 | 0 | r = sc_transmit_apdu(card, &apdu); |
472 | 0 | if (r < 0) |
473 | 0 | goto err; |
474 | | |
475 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
476 | 0 | if (r < 0) |
477 | 0 | goto err; |
478 | 0 | r = decode_gen_auth_rdata(card->ctx, apdu.resp, apdu.resplen, |
479 | 0 | enc_nonce, enc_nonce_len, |
480 | 0 | NULL, NULL, |
481 | 0 | NULL, NULL, |
482 | 0 | NULL, NULL, |
483 | 0 | NULL, NULL, |
484 | 0 | NULL, NULL); |
485 | |
|
486 | 0 | err: |
487 | 0 | free(d); |
488 | |
|
489 | 0 | return r; |
490 | 0 | } |
491 | | static int eac_gen_auth_2_map_nonce(sc_card_t *card, |
492 | | const u8 *in, size_t in_len, |
493 | | u8 **map_data_out, size_t *map_data_out_len) |
494 | 0 | { |
495 | 0 | sc_apdu_t apdu; |
496 | 0 | unsigned char *d = NULL; |
497 | 0 | int r; |
498 | 0 | unsigned char resp[SC_MAX_APDU_RESP_SIZE]; |
499 | |
|
500 | 0 | r = encode_gen_auth_cdata(card->ctx, NULL, 0, in, in_len, NULL, 0, NULL, 0, &d); |
501 | 0 | if (r < 0) |
502 | 0 | goto err; |
503 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00, |
504 | 0 | d, r, resp, sizeof resp); |
505 | 0 | apdu.cla = ISO_COMMAND_CHAINING; |
506 | |
|
507 | 0 | r = sc_transmit_apdu(card, &apdu); |
508 | 0 | if (r < 0) |
509 | 0 | goto err; |
510 | | |
511 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
512 | 0 | if (r < 0) |
513 | 0 | goto err; |
514 | | |
515 | 0 | r = decode_gen_auth_rdata(card->ctx, apdu.resp, apdu.resplen, |
516 | 0 | NULL, NULL, |
517 | 0 | map_data_out, map_data_out_len, |
518 | 0 | NULL, NULL, |
519 | 0 | NULL, NULL, |
520 | 0 | NULL, NULL, |
521 | 0 | NULL, NULL); |
522 | |
|
523 | 0 | err: |
524 | 0 | free(d); |
525 | |
|
526 | 0 | return r; |
527 | 0 | } |
528 | | static int eac_gen_auth_3_perform_key_agreement(sc_card_t *card, |
529 | | const u8 *in, size_t in_len, |
530 | | u8 **eph_pub_key_out, size_t *eph_pub_key_out_len) |
531 | 0 | { |
532 | 0 | sc_apdu_t apdu; |
533 | 0 | unsigned char *d = NULL; |
534 | 0 | int r; |
535 | 0 | unsigned char resp[SC_MAX_APDU_RESP_SIZE]; |
536 | |
|
537 | 0 | r = encode_gen_auth_cdata(card->ctx, NULL, 0, NULL, 0, in, in_len, NULL, 0, &d); |
538 | 0 | if (r < 0) |
539 | 0 | goto err; |
540 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00, |
541 | 0 | d, r, resp, sizeof resp); |
542 | 0 | apdu.cla = ISO_COMMAND_CHAINING; |
543 | |
|
544 | 0 | r = sc_transmit_apdu(card, &apdu); |
545 | 0 | if (r < 0) |
546 | 0 | goto err; |
547 | | |
548 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
549 | 0 | if (r < 0) |
550 | 0 | goto err; |
551 | | |
552 | 0 | r = decode_gen_auth_rdata(card->ctx, apdu.resp, apdu.resplen, |
553 | 0 | NULL, NULL, |
554 | 0 | NULL, NULL, |
555 | 0 | eph_pub_key_out, eph_pub_key_out_len, |
556 | 0 | NULL, NULL, |
557 | 0 | NULL, NULL, |
558 | 0 | NULL, NULL); |
559 | |
|
560 | 0 | err: |
561 | 0 | free(d); |
562 | |
|
563 | 0 | return r; |
564 | 0 | } |
565 | | static int eac_gen_auth_4_mutual_authentication(sc_card_t *card, |
566 | | const u8 *in, size_t in_len, |
567 | | u8 **auth_token_out, size_t *auth_token_out_len, |
568 | | u8 **recent_car_out, size_t *recent_car_len, |
569 | | u8 **prev_car_out, size_t *prev_car_len) |
570 | 0 | { |
571 | 0 | sc_apdu_t apdu; |
572 | 0 | unsigned char *d = NULL; |
573 | 0 | int r; |
574 | 0 | unsigned char resp[SC_MAX_APDU_RESP_SIZE]; |
575 | |
|
576 | 0 | r = encode_gen_auth_cdata(card->ctx, NULL, 0, NULL, 0, NULL, 0, in, in_len, &d); |
577 | 0 | if (r < 0) |
578 | 0 | goto err; |
579 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_GENERAL_AUTHENTICATE, 0x00, 0x00, |
580 | 0 | d, r, resp, sizeof resp); |
581 | |
|
582 | 0 | r = sc_transmit_apdu(card, &apdu); |
583 | 0 | if (r < 0) |
584 | 0 | goto err; |
585 | | |
586 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
587 | 0 | if (r < 0) |
588 | 0 | goto err; |
589 | | |
590 | 0 | r = decode_gen_auth_rdata(card->ctx, apdu.resp, apdu.resplen, |
591 | 0 | NULL, NULL, |
592 | 0 | NULL, NULL, |
593 | 0 | NULL, NULL, |
594 | 0 | auth_token_out, auth_token_out_len, |
595 | 0 | recent_car_out, recent_car_len, |
596 | 0 | prev_car_out, prev_car_len); |
597 | |
|
598 | 0 | err: |
599 | 0 | free(d); |
600 | |
|
601 | 0 | return r; |
602 | 0 | } |
603 | | |
604 | | static PACE_SEC * |
605 | | get_psec(sc_card_t *card, const char *pin, size_t length_pin, enum s_type pin_id) |
606 | 0 | { |
607 | 0 | char *p = NULL; |
608 | 0 | PACE_SEC *r; |
609 | 0 | char buf[EAC_MAX_MRZ_LEN > 32 ? EAC_MAX_MRZ_LEN : 32]; |
610 | |
|
611 | 0 | if (!length_pin || !pin) { |
612 | 0 | if (0 > snprintf(buf, sizeof buf, "Please enter your %s: ", |
613 | 0 | eac_secret_name(pin_id))) { |
614 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create password prompt.\n"); |
615 | 0 | return NULL; |
616 | 0 | } |
617 | 0 | p = malloc(EAC_MAX_MRZ_LEN+1); |
618 | 0 | if (!p) { |
619 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for %s.\n", |
620 | 0 | eac_secret_name(pin_id)); |
621 | 0 | return NULL; |
622 | 0 | } |
623 | 0 | if (0 > EVP_read_pw_string_min(p, 0, EAC_MAX_MRZ_LEN, buf, 0)) { |
624 | 0 | sc_log_openssl(card->ctx); |
625 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not read %s.\n", |
626 | 0 | eac_secret_name(pin_id)); |
627 | 0 | return NULL; |
628 | 0 | } |
629 | 0 | length_pin = strlen(p); |
630 | 0 | if (length_pin > EAC_MAX_MRZ_LEN) { |
631 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "MRZ too long"); |
632 | 0 | return NULL; |
633 | 0 | } |
634 | 0 | pin = p; |
635 | 0 | } |
636 | | |
637 | 0 | if (pin_id != PACE_PIN && pin_id != PACE_CAN && pin_id != PACE_MRZ && pin_id != PACE_PUK) |
638 | 0 | pin_id = PACE_RAW; |
639 | |
|
640 | 0 | r = PACE_SEC_new(pin, length_pin, pin_id); |
641 | |
|
642 | 0 | if (p) { |
643 | 0 | OPENSSL_cleanse(p, length_pin); |
644 | 0 | free(p); |
645 | 0 | } |
646 | |
|
647 | 0 | return r; |
648 | 0 | } |
649 | | |
650 | | |
651 | | int perform_pace(sc_card_t *card, |
652 | | struct establish_pace_channel_input pace_input, |
653 | | struct establish_pace_channel_output *pace_output, |
654 | | enum eac_tr_version tr_version) |
655 | 0 | { |
656 | 0 | u8 *p = NULL; |
657 | 0 | EAC_CTX *eac_ctx = NULL; |
658 | 0 | BUF_MEM *enc_nonce = NULL, *mdata = NULL, *mdata_opp = NULL, |
659 | 0 | *token_opp = NULL, *token = NULL, *pub = NULL, *pub_opp = NULL, |
660 | 0 | *comp_pub = NULL, *comp_pub_opp = NULL; |
661 | 0 | PACE_SEC *sec = NULL; |
662 | 0 | CVC_CHAT *chat = NULL; |
663 | 0 | BIO *bio_stdout = NULL; |
664 | 0 | CVC_CERTIFICATE_DESCRIPTION *desc = NULL; |
665 | 0 | int r; |
666 | 0 | const unsigned char *pp; |
667 | |
|
668 | 0 | if (!card || !card->reader || !card->reader->ops || !pace_output) |
669 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
670 | | |
671 | | /* show description in advance to give the user more time to read it... |
672 | | * This behaviour differs from TR-03119 v1.1 p. 44. */ |
673 | 0 | if (pace_input.certificate_description_length && |
674 | 0 | pace_input.certificate_description) { |
675 | |
|
676 | 0 | pp = pace_input.certificate_description; |
677 | 0 | if (!d2i_CVC_CERTIFICATE_DESCRIPTION(&desc, |
678 | 0 | &pp, pace_input.certificate_description_length)) { |
679 | 0 | sc_log_openssl(card->ctx); |
680 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse certificate description."); |
681 | 0 | r = SC_ERROR_INTERNAL; |
682 | 0 | goto err; |
683 | 0 | } |
684 | | |
685 | 0 | if (!bio_stdout) { |
686 | 0 | bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); |
687 | 0 | if (!bio_stdout) { |
688 | 0 | sc_log_openssl(card->ctx); |
689 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create output buffer."); |
690 | 0 | r = SC_ERROR_INTERNAL; |
691 | 0 | goto err; |
692 | 0 | } |
693 | 0 | } |
694 | | |
695 | 0 | printf("Certificate Description\n"); |
696 | 0 | switch(certificate_description_print(bio_stdout, desc, 8)) { |
697 | 0 | case 0: |
698 | 0 | sc_log_openssl(card->ctx); |
699 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not print certificate description."); |
700 | 0 | r = SC_ERROR_INTERNAL; |
701 | 0 | goto err; |
702 | 0 | break; |
703 | 0 | case 1: |
704 | | /* text format */ |
705 | 0 | break; |
706 | 0 | case 2: |
707 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in " |
708 | 0 | "HTML format can not (yet) be handled."); |
709 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
710 | 0 | goto err; |
711 | 0 | break; |
712 | 0 | case 3: |
713 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in " |
714 | 0 | "PDF format can not (yet) be handled."); |
715 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
716 | 0 | goto err; |
717 | 0 | break; |
718 | 0 | default: |
719 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Certificate description in " |
720 | 0 | "unknown format can not be handled."); |
721 | 0 | r = SC_ERROR_NOT_SUPPORTED; |
722 | 0 | goto err; |
723 | 0 | break; |
724 | 0 | } |
725 | 0 | } |
726 | | |
727 | | /* show chat in advance to give the user more time to read it... |
728 | | * This behaviour differs from TR-03119 v1.1 p. 44. */ |
729 | 0 | if (pace_input.chat_length && pace_input.chat) { |
730 | |
|
731 | 0 | if (!bio_stdout) { |
732 | 0 | bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE); |
733 | 0 | if (!bio_stdout) { |
734 | 0 | sc_log_openssl(card->ctx); |
735 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not create output buffer."); |
736 | 0 | r = SC_ERROR_INTERNAL; |
737 | 0 | goto err; |
738 | 0 | } |
739 | 0 | } |
740 | | |
741 | 0 | pp = pace_input.chat; |
742 | 0 | if (!d2i_CVC_CHAT(&chat, &pp, pace_input.chat_length)) { |
743 | 0 | sc_log_openssl(card->ctx); |
744 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse card holder authorization template (CHAT)."); |
745 | 0 | r = SC_ERROR_INTERNAL; |
746 | 0 | goto err; |
747 | 0 | } |
748 | | |
749 | 0 | printf("Card holder authorization template (CHAT)\n"); |
750 | 0 | if (!cvc_chat_print(bio_stdout, chat, 8)) { |
751 | 0 | sc_log_openssl(card->ctx); |
752 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not print card holder authorization template (CHAT)."); |
753 | 0 | r = SC_ERROR_INTERNAL; |
754 | 0 | goto err; |
755 | 0 | } |
756 | 0 | } |
757 | | |
758 | 0 | if (card->reader->capabilities & SC_READER_CAP_PACE_GENERIC |
759 | 0 | && card->reader->ops->perform_pace) { |
760 | 0 | r = card->reader->ops->perform_pace(card->reader, &pace_input, pace_output); |
761 | 0 | if (r < 0) |
762 | 0 | goto err; |
763 | 0 | } else { |
764 | 0 | if (!pace_output->ef_cardaccess_length || !pace_output->ef_cardaccess) { |
765 | 0 | r = get_ef_card_access(card, &pace_output->ef_cardaccess, |
766 | 0 | &pace_output->ef_cardaccess_length); |
767 | 0 | if (r < 0) { |
768 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess."); |
769 | 0 | goto err; |
770 | 0 | } |
771 | 0 | } |
772 | | |
773 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "EF.CardAccess", pace_output->ef_cardaccess, |
774 | 0 | pace_output->ef_cardaccess_length); |
775 | |
|
776 | 0 | EAC_init(); |
777 | 0 | eac_ctx = EAC_CTX_new(); |
778 | 0 | if (!eac_ctx |
779 | 0 | || !EAC_CTX_init_ef_cardaccess(pace_output->ef_cardaccess, |
780 | 0 | pace_output->ef_cardaccess_length, eac_ctx) |
781 | 0 | || !eac_ctx->pace_ctx) { |
782 | 0 | sc_log_openssl(card->ctx); |
783 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse EF.CardAccess."); |
784 | 0 | r = SC_ERROR_INTERNAL; |
785 | 0 | goto err; |
786 | 0 | } |
787 | | |
788 | 0 | eac_ctx->tr_version = tr_version; |
789 | |
|
790 | 0 | r = eac_mse_set_at_pace(card, eac_ctx->pace_ctx->protocol, |
791 | 0 | pace_input.pin_id, chat, &pace_output->mse_set_at_sw1, |
792 | 0 | &pace_output->mse_set_at_sw2); |
793 | 0 | if (r < 0) { |
794 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol properties " |
795 | 0 | "(MSE: Set AT failed)."); |
796 | 0 | goto err; |
797 | 0 | } |
798 | | |
799 | 0 | enc_nonce = BUF_MEM_new(); |
800 | 0 | if (!enc_nonce) { |
801 | 0 | sc_log_openssl(card->ctx); |
802 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
803 | 0 | goto err; |
804 | 0 | } |
805 | 0 | p = (u8 *) enc_nonce->data; |
806 | 0 | r = eac_gen_auth_1_encrypted_nonce(card, &p, &enc_nonce->length); |
807 | 0 | enc_nonce->data = (char *) p; |
808 | 0 | if (r < 0) { |
809 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get encrypted nonce from card " |
810 | 0 | "(General Authenticate step 1 failed)."); |
811 | 0 | goto err; |
812 | 0 | } |
813 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "Encrypted nonce from MRTD", (u8 *)enc_nonce->data, enc_nonce->length); |
814 | 0 | enc_nonce->max = enc_nonce->length; |
815 | |
|
816 | 0 | sec = get_psec(card, (char *) pace_input.pin, pace_input.pin_length, |
817 | 0 | pace_input.pin_id); |
818 | 0 | if (!sec) { |
819 | 0 | sc_log_openssl(card->ctx); |
820 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encode PACE secret."); |
821 | 0 | r = SC_ERROR_INTERNAL; |
822 | 0 | goto err; |
823 | 0 | } |
824 | | |
825 | 0 | if (!PACE_STEP2_dec_nonce(eac_ctx, sec, enc_nonce)) { |
826 | 0 | sc_log_openssl(card->ctx); |
827 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not decrypt MRTD's nonce."); |
828 | 0 | r = SC_ERROR_INTERNAL; |
829 | 0 | goto err; |
830 | 0 | } |
831 | | |
832 | 0 | mdata_opp = BUF_MEM_new(); |
833 | 0 | mdata = PACE_STEP3A_generate_mapping_data(eac_ctx); |
834 | 0 | if (!mdata || !mdata_opp) { |
835 | 0 | sc_log_openssl(card->ctx); |
836 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate mapping data."); |
837 | 0 | r = SC_ERROR_INTERNAL; |
838 | 0 | goto err; |
839 | 0 | } |
840 | 0 | p = (u8 *) mdata_opp->data; |
841 | 0 | r = eac_gen_auth_2_map_nonce(card, (u8 *) mdata->data, mdata->length, |
842 | 0 | &p, &mdata_opp->length); |
843 | 0 | mdata_opp->data = (char *) p; |
844 | 0 | if (r < 0) { |
845 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange mapping data with card " |
846 | 0 | "(General Authenticate step 2 failed)."); |
847 | 0 | goto err; |
848 | 0 | } |
849 | 0 | mdata_opp->max = mdata_opp->length; |
850 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "Mapping data from MRTD", (u8 *) mdata_opp->data, mdata_opp->length); |
851 | |
|
852 | 0 | if (!PACE_STEP3A_map_generator(eac_ctx, mdata_opp)) { |
853 | 0 | sc_log_openssl(card->ctx); |
854 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not map generator."); |
855 | 0 | r = SC_ERROR_INTERNAL; |
856 | 0 | goto err; |
857 | 0 | } |
858 | | |
859 | 0 | pub = PACE_STEP3B_generate_ephemeral_key(eac_ctx); |
860 | 0 | pub_opp = BUF_MEM_new(); |
861 | 0 | if (!pub || !pub_opp) { |
862 | 0 | sc_log_openssl(card->ctx); |
863 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate ephemeral domain parameter or " |
864 | 0 | "ephemeral key pair."); |
865 | 0 | r = SC_ERROR_INTERNAL; |
866 | 0 | goto err; |
867 | 0 | } |
868 | 0 | p = (u8 *) pub_opp->data; |
869 | 0 | r = eac_gen_auth_3_perform_key_agreement(card, (u8 *) pub->data, pub->length, |
870 | 0 | &p, &pub_opp->length); |
871 | 0 | pub_opp->data = (char *) p; |
872 | 0 | if (r < 0) { |
873 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange ephemeral public key with card " |
874 | 0 | "(General Authenticate step 3 failed)."); |
875 | 0 | goto err; |
876 | 0 | } |
877 | 0 | pub_opp->max = pub_opp->length; |
878 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "Ephemeral public key from MRTD", (u8 *) pub_opp->data, pub_opp->length); |
879 | | |
880 | |
|
881 | 0 | if (!PACE_STEP3B_compute_shared_secret(eac_ctx, pub_opp) |
882 | 0 | || !PACE_STEP3C_derive_keys(eac_ctx)) { |
883 | 0 | sc_log_openssl(card->ctx); |
884 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute ephemeral shared secret or " |
885 | 0 | "derive keys for encryption and authentication."); |
886 | 0 | r = SC_ERROR_INTERNAL; |
887 | 0 | goto err; |
888 | 0 | } |
889 | 0 | token = PACE_STEP3D_compute_authentication_token(eac_ctx, pub_opp); |
890 | 0 | token_opp = BUF_MEM_new(); |
891 | 0 | if (!token || !token_opp) { |
892 | 0 | sc_log_openssl(card->ctx); |
893 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute authentication token."); |
894 | 0 | r = SC_ERROR_INTERNAL; |
895 | 0 | goto err; |
896 | 0 | } |
897 | 0 | p = (u8 *) token_opp->data; |
898 | 0 | r = eac_gen_auth_4_mutual_authentication(card, (u8 *) token->data, token->length, |
899 | 0 | &p, &token_opp->length, |
900 | 0 | &pace_output->recent_car, &pace_output->recent_car_length, |
901 | 0 | &pace_output->previous_car, &pace_output->previous_car_length); |
902 | 0 | token_opp->data = (char *) p; |
903 | |
|
904 | 0 | if (r < 0) { |
905 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not exchange authentication token with card " |
906 | 0 | "(General Authenticate step 4 failed)."); |
907 | 0 | goto err; |
908 | 0 | } |
909 | 0 | token_opp->max = token_opp->length; |
910 | |
|
911 | 0 | if (!PACE_STEP3D_verify_authentication_token(eac_ctx, token_opp)) { |
912 | 0 | sc_log_openssl(card->ctx); |
913 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify authentication token."); |
914 | 0 | r = SC_ERROR_INTERNAL; |
915 | 0 | goto err; |
916 | 0 | } |
917 | | |
918 | | /* Initialize secure channel */ |
919 | 0 | if (!EAC_CTX_set_encryption_ctx(eac_ctx, EAC_ID_PACE)) { |
920 | 0 | sc_log_openssl(card->ctx); |
921 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize encryption."); |
922 | 0 | r = SC_ERROR_INTERNAL; |
923 | 0 | goto err; |
924 | 0 | } |
925 | | |
926 | | /* Identifier for ICC and PCD */ |
927 | 0 | comp_pub = EAC_Comp(eac_ctx, EAC_ID_PACE, pub); |
928 | 0 | comp_pub_opp = EAC_Comp(eac_ctx, EAC_ID_PACE, pub_opp); |
929 | 0 | if (!comp_pub || !comp_pub_opp) { |
930 | 0 | sc_log_openssl(card->ctx); |
931 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compress public keys for identification."); |
932 | 0 | r = SC_ERROR_INTERNAL; |
933 | 0 | goto err; |
934 | 0 | } |
935 | 0 | if (comp_pub_opp->length == 0) { |
936 | 0 | r = SC_ERROR_INTERNAL; |
937 | 0 | goto err; |
938 | 0 | } |
939 | 0 | p = realloc(pace_output->id_icc, comp_pub_opp->length); |
940 | 0 | if (!p) { |
941 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID ICC.\n"); |
942 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
943 | 0 | goto err; |
944 | 0 | } |
945 | 0 | pace_output->id_icc = p; |
946 | 0 | pace_output->id_icc_length = comp_pub_opp->length; |
947 | 0 | memcpy(pace_output->id_icc, comp_pub_opp->data, comp_pub_opp->length); |
948 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "ID ICC", pace_output->id_icc, |
949 | 0 | pace_output->id_icc_length); |
950 | 0 | if (comp_pub->length == 0) { |
951 | 0 | r = SC_ERROR_INTERNAL; |
952 | 0 | goto err; |
953 | 0 | } |
954 | 0 | p = realloc(pace_output->id_pcd, comp_pub->length); |
955 | 0 | if (!p) { |
956 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Not enough memory for ID PCD.\n"); |
957 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
958 | 0 | goto err; |
959 | 0 | } |
960 | 0 | pace_output->id_pcd = p; |
961 | 0 | pace_output->id_pcd_length = comp_pub->length; |
962 | 0 | memcpy(pace_output->id_pcd, comp_pub->data, comp_pub->length); |
963 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "ID PCD", pace_output->id_pcd, |
964 | 0 | pace_output->id_pcd_length); |
965 | |
|
966 | 0 | r = eac_sm_start(card, eac_ctx, pace_output->id_icc, pace_output->id_icc_length); |
967 | 0 | } |
968 | | |
969 | 0 | err: |
970 | 0 | if (enc_nonce) |
971 | 0 | BUF_MEM_free(enc_nonce); |
972 | 0 | if (mdata) |
973 | 0 | BUF_MEM_free(mdata); |
974 | 0 | if (mdata_opp) |
975 | 0 | BUF_MEM_free(mdata_opp); |
976 | 0 | if (token_opp) |
977 | 0 | BUF_MEM_free(token_opp); |
978 | 0 | if (token) |
979 | 0 | BUF_MEM_free(token); |
980 | 0 | if (pub) |
981 | 0 | BUF_MEM_free(pub); |
982 | 0 | if (pub_opp) |
983 | 0 | BUF_MEM_free(pub_opp); |
984 | 0 | if (comp_pub_opp) |
985 | 0 | BUF_MEM_free(comp_pub_opp); |
986 | 0 | if (comp_pub) |
987 | 0 | BUF_MEM_free(comp_pub); |
988 | 0 | PACE_SEC_clear_free(sec); |
989 | 0 | if (bio_stdout) |
990 | 0 | BIO_free_all(bio_stdout); |
991 | 0 | if (desc) |
992 | 0 | CVC_CERTIFICATE_DESCRIPTION_free(desc); |
993 | 0 | if (chat) |
994 | 0 | CVC_CHAT_free(chat); |
995 | |
|
996 | 0 | if (r < 0) |
997 | 0 | EAC_CTX_clear_free(eac_ctx); |
998 | |
|
999 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1000 | 0 | } |
1001 | | |
1002 | | static int eac_mse_set_at_ta(sc_card_t *card, int protocol, |
1003 | | const unsigned char *chr, size_t chr_len, |
1004 | | const unsigned char *eph_pub_key, size_t eph_pub_key_len, |
1005 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len) |
1006 | 0 | { |
1007 | 0 | return eac_mse_set_at(card, 0x81, protocol, chr, chr_len, NULL, 0, |
1008 | 0 | eph_pub_key, eph_pub_key_len, auxiliary_data, auxiliary_data_len, |
1009 | 0 | NULL, NULL, NULL); |
1010 | 0 | } |
1011 | | |
1012 | | static int eac_mse_set_dst(sc_card_t *card, |
1013 | | const unsigned char *chr, size_t chr_len) |
1014 | 0 | { |
1015 | 0 | return eac_mse(card, 0x81, 0xb6, 0, chr, chr_len, NULL, 0, NULL, 0, NULL, |
1016 | 0 | 0, NULL, NULL, NULL); |
1017 | 0 | } |
1018 | | |
1019 | | static int eac_get_challenge(sc_card_t *card, |
1020 | | unsigned char *challenge, size_t len) |
1021 | 0 | { |
1022 | 0 | sc_apdu_t apdu; |
1023 | 0 | int r; |
1024 | |
|
1025 | 0 | if (!card) { |
1026 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1027 | 0 | goto err; |
1028 | 0 | } |
1029 | | |
1030 | 0 | sc_format_apdu_ex(&apdu, 0x00, 0x84, 0x00, 0x00, NULL, 0, challenge, len); |
1031 | |
|
1032 | 0 | r = sc_transmit_apdu(card, &apdu); |
1033 | 0 | if (r < 0) |
1034 | 0 | goto err; |
1035 | | |
1036 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1037 | |
|
1038 | 0 | err: |
1039 | 0 | return r; |
1040 | 0 | } |
1041 | | |
1042 | | static int eac_verify(sc_card_t *card, |
1043 | | const unsigned char *cert, size_t cert_len) |
1044 | 0 | { |
1045 | 0 | sc_apdu_t apdu; |
1046 | 0 | int r, class, tag; |
1047 | 0 | long int length; |
1048 | |
|
1049 | 0 | memset(&apdu, 0, sizeof apdu); |
1050 | |
|
1051 | 0 | if (!card) { |
1052 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1053 | 0 | goto err; |
1054 | 0 | } |
1055 | | |
1056 | 0 | if (0x80 & ASN1_get_object(&cert, &length, &tag, &class, cert_len)) { |
1057 | 0 | sc_log_openssl(card->ctx); |
1058 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Error decoding Certificate"); |
1059 | 0 | r = SC_ERROR_INTERNAL; |
1060 | 0 | goto err; |
1061 | 0 | } |
1062 | | |
1063 | 0 | sc_format_apdu_ex(&apdu, 0x00, 0x2A, 0x00, 0xbe, (unsigned char *) cert, length, NULL, 0); |
1064 | |
|
1065 | 0 | r = sc_transmit_apdu(card, &apdu); |
1066 | 0 | if (r < 0) |
1067 | 0 | goto err; |
1068 | | |
1069 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1070 | |
|
1071 | 0 | err: |
1072 | 0 | return r; |
1073 | 0 | } |
1074 | | |
1075 | | static int eac_external_authenticate(sc_card_t *card, |
1076 | | unsigned char *signature, size_t signature_len) |
1077 | 0 | { |
1078 | 0 | int r; |
1079 | 0 | sc_apdu_t apdu; |
1080 | 0 | memset(&apdu, 0, sizeof apdu); |
1081 | |
|
1082 | 0 | if (!card) { |
1083 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1084 | 0 | goto err; |
1085 | 0 | } |
1086 | | |
1087 | 0 | sc_format_apdu_ex(&apdu, 0x00, 0x82, 0x00, 0x00, signature, signature_len, NULL, 0); |
1088 | |
|
1089 | 0 | r = sc_transmit_apdu(card, &apdu); |
1090 | 0 | if (r < 0) |
1091 | 0 | goto err; |
1092 | | |
1093 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1094 | |
|
1095 | 0 | err: |
1096 | 0 | return r; |
1097 | 0 | } |
1098 | | |
1099 | | static void eac_sm_clear_free_without_ctx(const struct iso_sm_ctx *ctx) |
1100 | 0 | { |
1101 | 0 | if (ctx) { |
1102 | 0 | struct eac_sm_ctx *eacsmctx = ctx->priv_data; |
1103 | 0 | if (eacsmctx) |
1104 | 0 | eacsmctx->ctx = NULL; |
1105 | 0 | eac_sm_clear_free(ctx); |
1106 | 0 | } |
1107 | 0 | } |
1108 | | |
1109 | 0 | #define TA_NONCE_LENGTH 8 |
1110 | | int perform_terminal_authentication(sc_card_t *card, |
1111 | | const unsigned char **certs, const size_t *certs_lens, |
1112 | | const unsigned char *privkey, size_t privkey_len, |
1113 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len) |
1114 | 0 | { |
1115 | 0 | int r; |
1116 | 0 | const unsigned char *cert = NULL; |
1117 | 0 | size_t cert_len = 0, ef_cardaccess_length = 0; |
1118 | 0 | CVC_CERT *cvc_cert = NULL; |
1119 | 0 | BUF_MEM *nonce = NULL, *signature = NULL; |
1120 | 0 | struct iso_sm_ctx *isosmctx = NULL; |
1121 | 0 | struct eac_sm_ctx *eacsmctx = NULL; |
1122 | 0 | unsigned char *ef_cardaccess = NULL; |
1123 | 0 | EAC_CTX *eac_ctx = NULL; |
1124 | 0 | const unsigned char *chr = NULL; |
1125 | 0 | size_t chr_len = 0; |
1126 | |
|
1127 | 0 | if (!card || !certs_lens || !certs) { |
1128 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1129 | 0 | goto err; |
1130 | 0 | } |
1131 | 0 | if (!card->sm_ctx.info.cmd_data) { |
1132 | 0 | card->sm_ctx.info.cmd_data = iso_sm_ctx_create(); |
1133 | 0 | card->sm_ctx.ops.close = iso_sm_close; |
1134 | 0 | } |
1135 | 0 | if (!card->sm_ctx.info.cmd_data) { |
1136 | 0 | r = SC_ERROR_INTERNAL; |
1137 | 0 | goto err; |
1138 | 0 | } |
1139 | | |
1140 | 0 | isosmctx = card->sm_ctx.info.cmd_data; |
1141 | 0 | if (!isosmctx->priv_data) { |
1142 | 0 | r = get_ef_card_access(card, &ef_cardaccess, &ef_cardaccess_length); |
1143 | 0 | if (r < 0) { |
1144 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardAccess."); |
1145 | 0 | goto err; |
1146 | 0 | } |
1147 | | |
1148 | 0 | sc_debug_hex(card->ctx, SC_LOG_DEBUG_SM, "EF.CardAccess", ef_cardaccess, |
1149 | 0 | ef_cardaccess_length); |
1150 | |
|
1151 | 0 | EAC_init(); |
1152 | 0 | eac_ctx = EAC_CTX_new(); |
1153 | 0 | if (!eac_ctx |
1154 | 0 | || !EAC_CTX_init_ef_cardaccess(ef_cardaccess, |
1155 | 0 | ef_cardaccess_length, eac_ctx)) { |
1156 | 0 | sc_log_openssl(card->ctx); |
1157 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not parse EF.CardAccess."); |
1158 | 0 | r = SC_ERROR_INTERNAL; |
1159 | 0 | goto err; |
1160 | 0 | } |
1161 | | |
1162 | 0 | isosmctx->priv_data = eac_sm_ctx_create(eac_ctx, NULL, 0); |
1163 | 0 | if (!isosmctx->priv_data) { |
1164 | 0 | r = SC_ERROR_INTERNAL; |
1165 | 0 | goto err; |
1166 | 0 | } |
1167 | | /* when iso_sm_ctx_clear_free is called, we want everything to be freed |
1168 | | * except the EAC_CTX, because it is needed for performing SM *after* |
1169 | | * iso_sm_start was called. */ |
1170 | 0 | isosmctx->clear_free = eac_sm_clear_free_without_ctx; |
1171 | 0 | eac_ctx = NULL; |
1172 | 0 | } |
1173 | 0 | eacsmctx = isosmctx->priv_data; |
1174 | | |
1175 | |
|
1176 | 0 | while (*certs && *certs_lens) { |
1177 | 0 | cert = *certs; |
1178 | 0 | cert_len = *certs_lens; |
1179 | 0 | if (!CVC_d2i_CVC_CERT(&cvc_cert, &cert, cert_len) || !cvc_cert |
1180 | 0 | || !cvc_cert->body || !cvc_cert->body->certificate_authority_reference |
1181 | 0 | || !cvc_cert->body->certificate_holder_reference) { |
1182 | 0 | sc_log_openssl(card->ctx); |
1183 | 0 | r = SC_ERROR_INVALID_DATA; |
1184 | 0 | goto err; |
1185 | 0 | } |
1186 | 0 | cert = *certs; |
1187 | |
|
1188 | 0 | r = eac_mse_set_dst(card, |
1189 | 0 | cvc_cert->body->certificate_authority_reference->data, |
1190 | 0 | cvc_cert->body->certificate_authority_reference->length); |
1191 | 0 | if (r < 0) { |
1192 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol properties " |
1193 | 0 | "(MSE: Set AT failed)."); |
1194 | 0 | goto err; |
1195 | 0 | } |
1196 | | |
1197 | 0 | r = eac_verify(card, cert, cert_len); |
1198 | 0 | if (r < 0) |
1199 | 0 | goto err; |
1200 | | |
1201 | 0 | chr = cvc_cert->body->certificate_holder_reference->data; |
1202 | 0 | chr_len = cvc_cert->body->certificate_holder_reference->length; |
1203 | |
|
1204 | 0 | certs++; |
1205 | 0 | certs_lens++; |
1206 | 0 | } |
1207 | | |
1208 | | |
1209 | 0 | if (!EAC_CTX_init_ta(eacsmctx->ctx, privkey, privkey_len, cert, cert_len)) { |
1210 | 0 | sc_log_openssl(card->ctx); |
1211 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize TA."); |
1212 | 0 | r = SC_ERROR_INTERNAL; |
1213 | 0 | goto err; |
1214 | 0 | } |
1215 | | |
1216 | | |
1217 | 0 | if (eacsmctx->eph_pub_key) |
1218 | 0 | BUF_MEM_free(eacsmctx->eph_pub_key); |
1219 | 0 | eacsmctx->eph_pub_key = TA_STEP3_generate_ephemeral_key(eacsmctx->ctx); |
1220 | 0 | if (!eacsmctx->eph_pub_key) { |
1221 | 0 | sc_log_openssl(card->ctx); |
1222 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate CA ephemeral key."); |
1223 | 0 | r = SC_ERROR_INTERNAL; |
1224 | 0 | goto err; |
1225 | 0 | } |
1226 | | |
1227 | | |
1228 | 0 | r = eac_mse_set_at_ta(card, eacsmctx->ctx->ta_ctx->protocol, chr, chr_len, |
1229 | 0 | (unsigned char *) eacsmctx->eph_pub_key->data, eacsmctx->eph_pub_key->length, |
1230 | 0 | auxiliary_data, auxiliary_data_len); |
1231 | 0 | if (r < 0) { |
1232 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol properties " |
1233 | 0 | "(MSE: Set AT failed)."); |
1234 | 0 | goto err; |
1235 | 0 | } |
1236 | | |
1237 | 0 | nonce = BUF_MEM_create(TA_NONCE_LENGTH); |
1238 | 0 | if (!nonce) { |
1239 | 0 | sc_log_openssl(card->ctx); |
1240 | 0 | r = SC_ERROR_INTERNAL; |
1241 | 0 | goto err; |
1242 | 0 | } |
1243 | 0 | r = eac_get_challenge(card, (unsigned char *) nonce->data, nonce->length); |
1244 | 0 | if (r < 0) { |
1245 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get nonce for TA."); |
1246 | 0 | goto err; |
1247 | 0 | } |
1248 | 0 | if (!TA_STEP4_set_nonce(eacsmctx->ctx, nonce)) { |
1249 | 0 | sc_log_openssl(card->ctx); |
1250 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not set nonce for TA."); |
1251 | 0 | r = SC_ERROR_INTERNAL; |
1252 | 0 | goto err; |
1253 | 0 | } |
1254 | | |
1255 | 0 | if (eacsmctx->auxiliary_data) |
1256 | 0 | BUF_MEM_free(eacsmctx->auxiliary_data); |
1257 | 0 | eacsmctx->auxiliary_data = BUF_MEM_create_init(auxiliary_data, |
1258 | 0 | auxiliary_data_len); |
1259 | 0 | if (!eacsmctx->id_icc) |
1260 | 0 | eacsmctx->id_icc = BUF_MEM_new(); |
1261 | 0 | signature = TA_STEP5_sign(eacsmctx->ctx, eacsmctx->eph_pub_key, |
1262 | 0 | eacsmctx->id_icc, eacsmctx->auxiliary_data); |
1263 | 0 | if (!signature) { |
1264 | 0 | sc_log_openssl(card->ctx); |
1265 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not generate signature."); |
1266 | 0 | r = SC_ERROR_INTERNAL; |
1267 | 0 | goto err; |
1268 | 0 | } |
1269 | 0 | r = eac_external_authenticate(card, (unsigned char *) signature->data, |
1270 | 0 | signature->length); |
1271 | |
|
1272 | 0 | err: |
1273 | 0 | if (cvc_cert) |
1274 | 0 | CVC_CERT_free(cvc_cert); |
1275 | 0 | free(ef_cardaccess); |
1276 | 0 | EAC_CTX_clear_free(eac_ctx); |
1277 | 0 | BUF_MEM_clear_free(nonce); |
1278 | 0 | BUF_MEM_clear_free(signature); |
1279 | |
|
1280 | 0 | if (card) |
1281 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1282 | 0 | else |
1283 | 0 | return r; |
1284 | 0 | } |
1285 | | |
1286 | | static int eac_mse_set_at_ca(sc_card_t *card, int protocol) |
1287 | 0 | { |
1288 | 0 | return eac_mse_set_at(card, 0x41, protocol, NULL, 0, NULL, 0, NULL, 0, |
1289 | 0 | NULL, 0, NULL, NULL, NULL); |
1290 | 0 | } |
1291 | | |
1292 | | static int decode_gen_auth_ca_rdata(struct sc_context *ctx, |
1293 | | const unsigned char *rdata, size_t rdata_len, |
1294 | | unsigned char **nonce, size_t *enc_nonce_len, |
1295 | | unsigned char **auth_token, size_t *auth_token_len) |
1296 | 0 | { |
1297 | 0 | struct sc_asn1_entry rapdu_eac_gen_auth_ca_data[] = { |
1298 | 0 | { "Nonce", |
1299 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x01, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
1300 | 0 | { "Authentication Token", |
1301 | 0 | SC_ASN1_OCTET_STRING, SC_ASN1_CTX|0x02, SC_ASN1_OPTIONAL|SC_ASN1_ALLOC, NULL, NULL }, |
1302 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
1303 | 0 | }; |
1304 | |
|
1305 | 0 | struct sc_asn1_entry rapdu_eac_gen_auth_ca[] = { |
1306 | 0 | { "Dynamic Authentication Data", SC_ASN1_STRUCT, SC_ASN1_APP|SC_ASN1_CONS|0x1c, 0, NULL, NULL }, |
1307 | 0 | { NULL , 0 , 0 , 0 , NULL , NULL } |
1308 | 0 | }; |
1309 | |
|
1310 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_ca + 0, rapdu_eac_gen_auth_ca_data, &rapdu_eac_gen_auth_ca_data, 1); |
1311 | |
|
1312 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_ca_data + 0, nonce, enc_nonce_len, 0); |
1313 | 0 | sc_format_asn1_entry(rapdu_eac_gen_auth_ca_data + 1, auth_token, auth_token_len, 0); |
1314 | |
|
1315 | 0 | return sc_asn1_decode(ctx, rapdu_eac_gen_auth_ca, rdata, rdata_len, NULL, NULL); |
1316 | 0 | } |
1317 | | static int eac_gen_auth_ca(sc_card_t *card, const BUF_MEM *eph_pub_key, |
1318 | | BUF_MEM **nonce, BUF_MEM **token) |
1319 | 0 | { |
1320 | 0 | sc_apdu_t apdu; |
1321 | 0 | unsigned char *d = NULL, *p, *q; |
1322 | 0 | int r; |
1323 | 0 | unsigned char resp[SC_MAX_APDU_RESP_SIZE]; |
1324 | 0 | BUF_MEM *nonce_out = NULL, *token_out = NULL; |
1325 | |
|
1326 | 0 | if (!eph_pub_key) { |
1327 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1328 | 0 | goto err; |
1329 | 0 | } |
1330 | | |
1331 | 0 | r = encode_gen_auth_cdata(card->ctx, (unsigned char *) eph_pub_key->data, eph_pub_key->length, NULL, 0, NULL, 0, NULL, 0, &d); |
1332 | 0 | if (r < 0) |
1333 | 0 | goto err; |
1334 | 0 | sc_format_apdu_ex(&apdu, 0x00, ISO_GENERAL_AUTHENTICATE, 0, 0, d, r, resp, sizeof resp); |
1335 | |
|
1336 | 0 | r = sc_transmit_apdu(card, &apdu); |
1337 | 0 | if (r < 0) |
1338 | 0 | goto err; |
1339 | | |
1340 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1341 | 0 | if (r < 0) |
1342 | 0 | goto err; |
1343 | | |
1344 | 0 | nonce_out = BUF_MEM_new(); |
1345 | 0 | token_out = BUF_MEM_new(); |
1346 | 0 | if (!nonce_out || !token_out) { |
1347 | 0 | r = SC_ERROR_NOT_ENOUGH_MEMORY; |
1348 | 0 | goto err; |
1349 | 0 | } |
1350 | | |
1351 | 0 | p = (u8 *) nonce_out->data; |
1352 | 0 | q = (u8 *) token_out->data; |
1353 | 0 | r = decode_gen_auth_ca_rdata(card->ctx, apdu.resp, apdu.resplen, |
1354 | 0 | &p, &nonce_out->length, |
1355 | 0 | &q, &token_out->length); |
1356 | 0 | nonce_out->data = (char *) p; |
1357 | 0 | token_out->data = (char *) q; |
1358 | 0 | if (r < 0) |
1359 | 0 | goto err; |
1360 | | |
1361 | 0 | if (*nonce) |
1362 | 0 | BUF_MEM_free(*nonce); |
1363 | 0 | if (*token) |
1364 | 0 | BUF_MEM_free(*token); |
1365 | 0 | *nonce = nonce_out; |
1366 | 0 | *token = token_out; |
1367 | 0 | nonce_out = NULL; |
1368 | 0 | token_out = NULL; |
1369 | |
|
1370 | 0 | err: |
1371 | 0 | BUF_MEM_free(nonce_out); |
1372 | 0 | BUF_MEM_free(token_out); |
1373 | 0 | free(d); |
1374 | |
|
1375 | 0 | return r; |
1376 | 0 | } |
1377 | | |
1378 | | static int get_ef_card_security(sc_card_t *card, |
1379 | | u8 **ef_security, size_t *length_ef_security) |
1380 | 0 | { |
1381 | 0 | return iso7816_read_binary_sfid(card, SFID_EF_CARDSECURITY, ef_security, length_ef_security); |
1382 | 0 | } |
1383 | | |
1384 | | int perform_chip_authentication(sc_card_t *card, |
1385 | | unsigned char **ef_cardsecurity, size_t *ef_cardsecurity_len) |
1386 | 0 | { |
1387 | 0 | int r; |
1388 | 0 | BUF_MEM *picc_pubkey = NULL; |
1389 | 0 | struct iso_sm_ctx *isosmctx; |
1390 | 0 | struct eac_sm_ctx *eacsmctx; |
1391 | |
|
1392 | 0 | if (!card || !ef_cardsecurity || !ef_cardsecurity_len) { |
1393 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1394 | 0 | goto err; |
1395 | 0 | } |
1396 | 0 | isosmctx = card->sm_ctx.info.cmd_data; |
1397 | 0 | if (!isosmctx->priv_data) { |
1398 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1399 | 0 | goto err; |
1400 | 0 | } |
1401 | 0 | eacsmctx = isosmctx->priv_data; |
1402 | | |
1403 | | /* Passive Authentication */ |
1404 | 0 | if (!*ef_cardsecurity && !*ef_cardsecurity_len) { |
1405 | 0 | r = get_ef_card_security(card, ef_cardsecurity, ef_cardsecurity_len); |
1406 | 0 | if (r < 0 || !ef_cardsecurity || !ef_cardsecurity_len) { |
1407 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not get EF.CardSecurity."); |
1408 | 0 | goto err; |
1409 | 0 | } |
1410 | 0 | } |
1411 | 0 | picc_pubkey = CA_get_pubkey(eacsmctx->ctx, *ef_cardsecurity, *ef_cardsecurity_len); |
1412 | 0 | if (!picc_pubkey) { |
1413 | 0 | sc_log_openssl(card->ctx); |
1414 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify EF.CardSecurity."); |
1415 | 0 | r = SC_ERROR_INTERNAL; |
1416 | 0 | goto err; |
1417 | 0 | } |
1418 | | |
1419 | 0 | r = perform_chip_authentication_ex(card, eacsmctx->ctx, |
1420 | 0 | (unsigned char *) picc_pubkey->data, picc_pubkey->length); |
1421 | |
|
1422 | 0 | err: |
1423 | 0 | BUF_MEM_clear_free(picc_pubkey); |
1424 | |
|
1425 | 0 | if (card) |
1426 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1427 | 0 | else |
1428 | 0 | return r; |
1429 | 0 | } |
1430 | | |
1431 | | int perform_chip_authentication_ex(sc_card_t *card, void *eac_ctx, |
1432 | | unsigned char *picc_pubkey, size_t picc_pubkey_len) |
1433 | 0 | { |
1434 | 0 | int r; |
1435 | 0 | BUF_MEM *picc_pubkey_buf = NULL, *nonce = NULL, *token = NULL, |
1436 | 0 | *eph_pub_key = NULL; |
1437 | 0 | EAC_CTX *ctx = eac_ctx; |
1438 | |
|
1439 | 0 | if (!card || !ctx) { |
1440 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1441 | 0 | goto err; |
1442 | 0 | } |
1443 | | |
1444 | | |
1445 | 0 | picc_pubkey_buf = BUF_MEM_create_init(picc_pubkey, picc_pubkey_len); |
1446 | 0 | if (!picc_pubkey_buf) { |
1447 | 0 | sc_log_openssl(card->ctx); |
1448 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not verify EF.CardSecurity."); |
1449 | 0 | r = SC_ERROR_INTERNAL; |
1450 | 0 | goto err; |
1451 | 0 | } |
1452 | | |
1453 | | |
1454 | 0 | r = eac_mse_set_at_ca(card, ctx->ca_ctx->protocol); |
1455 | 0 | if (r < 0) { |
1456 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not select protocol properties " |
1457 | 0 | "(MSE: Set AT failed)."); |
1458 | 0 | goto err; |
1459 | 0 | } |
1460 | | |
1461 | | |
1462 | 0 | eph_pub_key = CA_STEP2_get_eph_pubkey(ctx); |
1463 | 0 | if (!eph_pub_key) { |
1464 | 0 | sc_log_openssl(card->ctx); |
1465 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not derive keys."); |
1466 | 0 | r = SC_ERROR_INTERNAL; |
1467 | 0 | goto err; |
1468 | 0 | } |
1469 | 0 | r = eac_gen_auth_ca(card, eph_pub_key, &nonce, &token); |
1470 | 0 | if (r < 0) { |
1471 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "(General Authenticate failed)."); |
1472 | 0 | goto err; |
1473 | 0 | } |
1474 | | |
1475 | | |
1476 | 0 | if (!CA_STEP4_compute_shared_secret(ctx, picc_pubkey_buf)) { |
1477 | 0 | sc_log_openssl(card->ctx); |
1478 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not compute shared secret."); |
1479 | 0 | r = SC_ERROR_INTERNAL; |
1480 | 0 | goto err; |
1481 | 0 | } |
1482 | | |
1483 | | |
1484 | 0 | if (!CA_STEP6_derive_keys(ctx, nonce, token)) { |
1485 | 0 | sc_log_openssl(card->ctx); |
1486 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not derive keys."); |
1487 | 0 | r = SC_ERROR_INTERNAL; |
1488 | 0 | goto err; |
1489 | 0 | } |
1490 | | |
1491 | | |
1492 | | /* Initialize secure channel */ |
1493 | 0 | if (!EAC_CTX_set_encryption_ctx(ctx, EAC_ID_CA)) { |
1494 | 0 | sc_log_openssl(card->ctx); |
1495 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not initialize encryption."); |
1496 | 0 | r = SC_ERROR_INTERNAL; |
1497 | 0 | goto err; |
1498 | 0 | } |
1499 | | |
1500 | 0 | if (card->sm_ctx.sm_mode != SM_MODE_TRANSMIT) { |
1501 | 0 | r = eac_sm_start(card, ctx, NULL, 0); |
1502 | 0 | } |
1503 | |
|
1504 | 0 | err: |
1505 | 0 | BUF_MEM_clear_free(picc_pubkey_buf); |
1506 | 0 | BUF_MEM_clear_free(nonce); |
1507 | 0 | BUF_MEM_clear_free(token); |
1508 | 0 | BUF_MEM_clear_free(eph_pub_key); |
1509 | |
|
1510 | 0 | if (card) |
1511 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1512 | 0 | else |
1513 | 0 | return r; |
1514 | 0 | } |
1515 | | |
1516 | | static int |
1517 | | increment_ssc(struct eac_sm_ctx *eacsmctx) |
1518 | 0 | { |
1519 | 0 | if (!eacsmctx) |
1520 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1521 | | |
1522 | 0 | if (!EAC_increment_ssc(eacsmctx->ctx)) |
1523 | 0 | return SC_ERROR_INTERNAL; |
1524 | | |
1525 | 0 | return SC_SUCCESS; |
1526 | 0 | } |
1527 | | |
1528 | | static int |
1529 | | eac_sm_encrypt(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1530 | | const u8 *data, size_t datalen, u8 **enc) |
1531 | 0 | { |
1532 | 0 | BUF_MEM *encbuf = NULL, *databuf = NULL; |
1533 | 0 | u8 *p = NULL; |
1534 | 0 | int r; |
1535 | 0 | struct eac_sm_ctx *eacsmctx; |
1536 | |
|
1537 | 0 | if (!card || !ctx || !enc || !ctx->priv_data) { |
1538 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1539 | 0 | goto err; |
1540 | 0 | } |
1541 | 0 | eacsmctx = ctx->priv_data; |
1542 | |
|
1543 | 0 | databuf = BUF_MEM_create_init(data, datalen); |
1544 | 0 | encbuf = EAC_encrypt(eacsmctx->ctx, databuf); |
1545 | 0 | if (!databuf || !encbuf || !encbuf->length) { |
1546 | 0 | sc_log_openssl(card->ctx); |
1547 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not encrypt data."); |
1548 | 0 | r = SC_ERROR_INTERNAL; |
1549 | 0 | goto err; |
1550 | 0 | } |
1551 | | |
1552 | 0 | p = realloc(*enc, encbuf->length); |
1553 | 0 | if (!p) { |
1554 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1555 | 0 | goto err; |
1556 | 0 | } |
1557 | 0 | *enc = p; |
1558 | 0 | memcpy(*enc, encbuf->data, encbuf->length); |
1559 | 0 | r = (int)encbuf->length; |
1560 | |
|
1561 | 0 | err: |
1562 | 0 | BUF_MEM_clear_free(databuf); |
1563 | 0 | if (encbuf) |
1564 | 0 | BUF_MEM_free(encbuf); |
1565 | |
|
1566 | 0 | return r; |
1567 | 0 | } |
1568 | | |
1569 | | static int |
1570 | | eac_sm_decrypt(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1571 | | const u8 *enc, size_t enclen, u8 **data) |
1572 | 0 | { |
1573 | 0 | BUF_MEM *encbuf = NULL, *databuf = NULL; |
1574 | 0 | u8 *p = NULL; |
1575 | 0 | int r; |
1576 | 0 | struct eac_sm_ctx *eacsmctx; |
1577 | |
|
1578 | 0 | if (!card || !ctx || !enc || !ctx->priv_data || !data) { |
1579 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1580 | 0 | goto err; |
1581 | 0 | } |
1582 | 0 | eacsmctx = ctx->priv_data; |
1583 | |
|
1584 | 0 | encbuf = BUF_MEM_create_init(enc, enclen); |
1585 | 0 | databuf = EAC_decrypt(eacsmctx->ctx, encbuf); |
1586 | 0 | if (!encbuf || !databuf || !databuf->length) { |
1587 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "Could not decrypt data."); |
1588 | 0 | sc_log_openssl(card->ctx); |
1589 | 0 | r = SC_ERROR_INTERNAL; |
1590 | 0 | goto err; |
1591 | 0 | } |
1592 | | |
1593 | 0 | p = realloc(*data, databuf->length); |
1594 | 0 | if (!p) { |
1595 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1596 | 0 | goto err; |
1597 | 0 | } |
1598 | 0 | *data = p; |
1599 | 0 | memcpy(*data, databuf->data, databuf->length); |
1600 | 0 | r = (int)databuf->length; |
1601 | |
|
1602 | 0 | err: |
1603 | 0 | BUF_MEM_clear_free(databuf); |
1604 | 0 | if (encbuf) |
1605 | 0 | BUF_MEM_free(encbuf); |
1606 | |
|
1607 | 0 | return r; |
1608 | 0 | } |
1609 | | |
1610 | | static int |
1611 | | eac_sm_authenticate(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1612 | | const u8 *data, size_t datalen, u8 **macdata) |
1613 | 0 | { |
1614 | 0 | BUF_MEM *inbuf = NULL, *macbuf = NULL; |
1615 | 0 | u8 *p = NULL; |
1616 | 0 | int r; |
1617 | 0 | struct eac_sm_ctx *eacsmctx; |
1618 | |
|
1619 | 0 | if (!card || !ctx || !ctx->priv_data || !macdata) { |
1620 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1621 | 0 | goto err; |
1622 | 0 | } |
1623 | 0 | eacsmctx = ctx->priv_data; |
1624 | |
|
1625 | 0 | inbuf = BUF_MEM_create_init(data, datalen); |
1626 | 0 | if (!inbuf) { |
1627 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1628 | 0 | goto err; |
1629 | 0 | } |
1630 | | |
1631 | 0 | macbuf = EAC_authenticate(eacsmctx->ctx, inbuf); |
1632 | 0 | if (!macbuf || !macbuf->length) { |
1633 | 0 | sc_log_openssl(card->ctx); |
1634 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, |
1635 | 0 | "Could not compute message authentication code (MAC)."); |
1636 | 0 | r = SC_ERROR_INTERNAL; |
1637 | 0 | goto err; |
1638 | 0 | } |
1639 | | |
1640 | 0 | p = realloc(*macdata, macbuf->length); |
1641 | 0 | if (!p) { |
1642 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1643 | 0 | goto err; |
1644 | 0 | } |
1645 | 0 | *macdata = p; |
1646 | 0 | memcpy(*macdata, macbuf->data, macbuf->length); |
1647 | 0 | r = (int)macbuf->length; |
1648 | |
|
1649 | 0 | err: |
1650 | 0 | if (inbuf) |
1651 | 0 | BUF_MEM_free(inbuf); |
1652 | 0 | if (macbuf) |
1653 | 0 | BUF_MEM_free(macbuf); |
1654 | |
|
1655 | 0 | return r; |
1656 | 0 | } |
1657 | | |
1658 | | static int |
1659 | | eac_sm_verify_authentication(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1660 | | const u8 *mac, size_t maclen, |
1661 | | const u8 *macdata, size_t macdatalen) |
1662 | 0 | { |
1663 | 0 | int r; |
1664 | 0 | BUF_MEM *inbuf = NULL, *my_mac = NULL; |
1665 | 0 | struct eac_sm_ctx *eacsmctx; |
1666 | |
|
1667 | 0 | if (!card || !ctx || !ctx->priv_data) { |
1668 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1669 | 0 | goto err; |
1670 | 0 | } |
1671 | 0 | eacsmctx = ctx->priv_data; |
1672 | |
|
1673 | 0 | inbuf = BUF_MEM_create_init(macdata, macdatalen); |
1674 | 0 | if (!inbuf) { |
1675 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
1676 | 0 | goto err; |
1677 | 0 | } |
1678 | | |
1679 | 0 | my_mac = EAC_authenticate(eacsmctx->ctx, inbuf); |
1680 | 0 | if (!my_mac) { |
1681 | 0 | sc_log_openssl(card->ctx); |
1682 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, |
1683 | 0 | "Could not compute message authentication code (MAC) for verification."); |
1684 | 0 | r = SC_ERROR_INTERNAL; |
1685 | 0 | goto err; |
1686 | 0 | } |
1687 | | |
1688 | 0 | if (my_mac->length != maclen || |
1689 | 0 | memcmp(my_mac->data, mac, maclen) != 0) { |
1690 | 0 | r = SC_ERROR_OBJECT_NOT_VALID; |
1691 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, |
1692 | 0 | "Authentication data not verified"); |
1693 | 0 | goto err; |
1694 | 0 | } |
1695 | | |
1696 | 0 | sc_debug(card->ctx, SC_LOG_DEBUG_SM, "Authentication data verified"); |
1697 | |
|
1698 | 0 | r = SC_SUCCESS; |
1699 | |
|
1700 | 0 | err: |
1701 | 0 | if (inbuf) |
1702 | 0 | BUF_MEM_free(inbuf); |
1703 | 0 | if (my_mac) |
1704 | 0 | BUF_MEM_free(my_mac); |
1705 | |
|
1706 | 0 | return r; |
1707 | 0 | } |
1708 | | |
1709 | | static int |
1710 | | eac_sm_pre_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1711 | | sc_apdu_t *apdu) |
1712 | 0 | { |
1713 | 0 | int r; |
1714 | 0 | CVC_CERT *cvc_cert = NULL; |
1715 | 0 | unsigned char *cert = NULL; |
1716 | 0 | BUF_MEM *signature = NULL; |
1717 | 0 | unsigned char *sequence = NULL; |
1718 | |
|
1719 | 0 | if (!card) |
1720 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1721 | 0 | if(!ctx || !apdu || !ctx->priv_data) { |
1722 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1723 | 0 | goto err; |
1724 | 0 | } |
1725 | | |
1726 | 0 | r = increment_ssc(ctx->priv_data); |
1727 | |
|
1728 | 0 | err: |
1729 | 0 | if (cvc_cert) |
1730 | 0 | CVC_CERT_free(cvc_cert); |
1731 | 0 | if (signature) |
1732 | 0 | BUF_MEM_free(signature); |
1733 | 0 | if (cert) |
1734 | 0 | OPENSSL_free(cert); |
1735 | 0 | if (sequence) |
1736 | 0 | OPENSSL_free(sequence); |
1737 | |
|
1738 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1739 | 0 | } |
1740 | | |
1741 | | static int |
1742 | | eac_sm_post_transmit(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1743 | | sc_apdu_t *sm_apdu) |
1744 | 0 | { |
1745 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, |
1746 | 0 | increment_ssc(ctx->priv_data)); |
1747 | 0 | } |
1748 | | |
1749 | | static int |
1750 | | eac_sm_finish(sc_card_t *card, const struct iso_sm_ctx *ctx, |
1751 | | sc_apdu_t *apdu) |
1752 | 0 | { |
1753 | 0 | if (!card) |
1754 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1755 | 0 | if(!ctx || !ctx->priv_data || !apdu) |
1756 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, |
1757 | 0 | SC_ERROR_INVALID_ARGUMENTS); |
1758 | | |
1759 | 0 | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, SC_SUCCESS); |
1760 | 0 | } |
1761 | | |
1762 | | static void |
1763 | | eac_sm_clear_free(const struct iso_sm_ctx *ctx) |
1764 | 0 | { |
1765 | 0 | if (ctx) { |
1766 | 0 | struct eac_sm_ctx *eacsmctx = ctx->priv_data; |
1767 | 0 | if (eacsmctx) { |
1768 | 0 | EAC_CTX_clear_free(eacsmctx->ctx); |
1769 | 0 | if (eacsmctx->id_icc) |
1770 | 0 | BUF_MEM_free(eacsmctx->id_icc); |
1771 | 0 | if (eacsmctx->eph_pub_key) |
1772 | 0 | BUF_MEM_free(eacsmctx->eph_pub_key); |
1773 | 0 | if (eacsmctx->auxiliary_data) |
1774 | 0 | BUF_MEM_free(eacsmctx->auxiliary_data); |
1775 | 0 | free(eacsmctx); |
1776 | 0 | } |
1777 | 0 | } |
1778 | 0 | } |
1779 | | |
1780 | | #else |
1781 | | |
1782 | | int perform_pace(sc_card_t *card, |
1783 | | struct establish_pace_channel_input pace_input, |
1784 | | struct establish_pace_channel_output *pace_output, |
1785 | | enum eac_tr_version tr_version) |
1786 | | { |
1787 | | int r; |
1788 | | |
1789 | | if (!card) |
1790 | | return SC_ERROR_INVALID_ARGUMENTS; |
1791 | | |
1792 | | if (card->reader |
1793 | | && card->reader->capabilities & SC_READER_CAP_PACE_GENERIC |
1794 | | && card->reader->ops->perform_pace) { |
1795 | | r = card->reader->ops->perform_pace(card->reader, &pace_input, pace_output); |
1796 | | } else { |
1797 | | r = SC_ERROR_NOT_SUPPORTED; |
1798 | | } |
1799 | | |
1800 | | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, r); |
1801 | | } |
1802 | | |
1803 | | int perform_terminal_authentication(sc_card_t *card, |
1804 | | const unsigned char **certs, const size_t *certs_lens, |
1805 | | const unsigned char *privkey, size_t privkey_len, |
1806 | | const unsigned char *auxiliary_data, size_t auxiliary_data_len) |
1807 | | { |
1808 | | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, SC_ERROR_NOT_SUPPORTED); |
1809 | | } |
1810 | | |
1811 | | int perform_chip_authentication(sc_card_t *card, |
1812 | | unsigned char **ef_cardsecurity, size_t *ef_cardsecurity_len) |
1813 | | { |
1814 | | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, SC_ERROR_NOT_SUPPORTED); |
1815 | | } |
1816 | | |
1817 | | int perform_chip_authentication_ex(sc_card_t *card, void *eac_ctx, |
1818 | | unsigned char *picc_pubkey, size_t picc_pubkey_len) |
1819 | | { |
1820 | | SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_SM, SC_ERROR_NOT_SUPPORTED); |
1821 | | } |
1822 | | |
1823 | | #endif |
1824 | | |
1825 | | static const char *MRZ_name = "MRZ"; |
1826 | | static const char *PIN_name = "eID PIN"; |
1827 | | static const char *PUK_name = "PUK"; |
1828 | | static const char *CAN_name = "CAN"; |
1829 | | static const char *UNDEF_name = "UNDEF"; |
1830 | 0 | const char *eac_secret_name(enum s_type pin_id) { |
1831 | 0 | switch (pin_id) { |
1832 | 0 | case PACE_MRZ: |
1833 | 0 | return MRZ_name; |
1834 | 0 | case PACE_PUK: |
1835 | 0 | return PUK_name; |
1836 | 0 | case PACE_PIN: |
1837 | 0 | return PIN_name; |
1838 | 0 | case PACE_CAN: |
1839 | 0 | return CAN_name; |
1840 | 0 | default: |
1841 | 0 | return UNDEF_name; |
1842 | 0 | } |
1843 | 0 | } |
1844 | | |
1845 | | int eac_pace_get_tries_left(sc_card_t *card, |
1846 | | enum s_type pin_id, int *tries_left) |
1847 | 0 | { |
1848 | 0 | int r; |
1849 | 0 | u8 sw1, sw2; |
1850 | |
|
1851 | 0 | if (tries_left) { |
1852 | 0 | #if defined(ENABLE_OPENPACE) && defined(ENABLE_SM) |
1853 | 0 | r = eac_mse_set_at_pace(card, 0, pin_id, 0, &sw1, &sw2); |
1854 | | #else |
1855 | | sc_apdu_t apdu; |
1856 | | sc_format_apdu_ex(&apdu, 0x00, ISO_MSE, 0xC1, 0xA4, NULL, 0, NULL, 0); |
1857 | | r = sc_transmit_apdu(card, &apdu); |
1858 | | sw1 = apdu.sw1; |
1859 | | sw2 = apdu.sw2; |
1860 | | #endif |
1861 | |
|
1862 | 0 | if (r > 0 && (sw1 == 0x63) && ((sw2 & 0xc0) == 0xc0)) { |
1863 | 0 | *tries_left = sw2 & 0x0f; |
1864 | 0 | } else { |
1865 | 0 | *tries_left = -1; |
1866 | 0 | } |
1867 | 0 | } else { |
1868 | 0 | r = SC_ERROR_INVALID_ARGUMENTS; |
1869 | 0 | } |
1870 | |
|
1871 | 0 | return r; |
1872 | 0 | } |