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