/src/opensc/src/libopensc/card-myeid.c
Line | Count | Source |
1 | | /* |
2 | | * card-myeid.c |
3 | | * |
4 | | * Copyright (C) 2008-2019 Aventra Ltd. |
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 | | |
21 | | #ifdef HAVE_CONFIG_H |
22 | | #include "config.h" |
23 | | #endif |
24 | | |
25 | | #include <string.h> |
26 | | #include <stdlib.h> |
27 | | |
28 | | #include "internal.h" |
29 | | #include "asn1.h" |
30 | | #include "cardctl.h" |
31 | | #include "types.h" |
32 | | |
33 | | /* Low byte is the MyEID card's key type specific component ID. High byte is used |
34 | | * internally for key type, so myeid_loadkey() is aware of the exact component. */ |
35 | 0 | #define LOAD_KEY_MODULUS 0x0080 |
36 | 0 | #define LOAD_KEY_PUBLIC_EXPONENT 0x0081 |
37 | 0 | #define LOAD_KEY_PRIME_P 0x0083 |
38 | 0 | #define LOAD_KEY_PRIME_Q 0x0084 |
39 | 0 | #define LOAD_KEY_DP1 0x0085 |
40 | 0 | #define LOAD_KEY_DQ1 0x0086 |
41 | 0 | #define LOAD_KEY_INVQ 0x0087 |
42 | 0 | #define LOAD_KEY_EC_PUBLIC 0x1086 |
43 | 0 | #define LOAD_KEY_EC_PRIVATE 0x1087 |
44 | 0 | #define LOAD_KEY_SYMMETRIC 0x20a0 |
45 | | |
46 | | #define MYEID_CARD_NAME_MAX_LEN 100 |
47 | | |
48 | | /* The following flags define the features supported by the card currently in use. |
49 | | They are used in 'card_supported_features' field in myeid_card_caps struct */ |
50 | 232 | #define MYEID_CARD_CAP_RSA 0x01 |
51 | 232 | #define MYEID_CARD_CAP_3DES 0x02 |
52 | 232 | #define MYEID_CARD_CAP_AES 0x04 |
53 | | #define MYEID_CARD_CAP_ECC 0x08 |
54 | | #define MYEID_CARD_CAP_GRIDPIN 0x10 |
55 | | #define MYEID_CARD_CAP_PIV_EMU 0x20 |
56 | | |
57 | 0 | #define MYEID_MAX_APDU_DATA_LEN 0xFF |
58 | 0 | #define MYEID_MAX_RSA_KEY_LEN 4096 |
59 | | |
60 | | #define MYEID_MAX_EXT_APDU_BUFFER_SIZE (MYEID_MAX_RSA_KEY_LEN/8+16) |
61 | | |
62 | | static const char *myeid_card_name = "MyEID"; |
63 | | static const char *oseid_card_name = "OsEID"; |
64 | | static char card_name_buf[MYEID_CARD_NAME_MAX_LEN]; |
65 | | |
66 | | static struct sc_card_operations myeid_ops; |
67 | | static struct sc_card_driver myeid_drv = { |
68 | | "MyEID cards with PKCS#15 applet", |
69 | | "myeid", |
70 | | &myeid_ops, |
71 | | NULL, |
72 | | 0, |
73 | | NULL |
74 | | }; |
75 | | |
76 | | typedef struct myeid_private_data { |
77 | | int card_state; |
78 | | |
79 | | unsigned short change_counter; |
80 | | unsigned char cap_chaining; |
81 | | /* the driver sets sec_env pointer in myeid_set_security_env and |
82 | | it is used immediately in myeid_decipher to differentiate between RSA decryption and |
83 | | ECDH key agreement. Note that this pointer is usually not valid |
84 | | after this pair of calls and must not be used elsewhere. */ |
85 | | const struct sc_security_env* sec_env; |
86 | | int disable_hw_pkcs1_padding; |
87 | | /* buffers for AES(DES) block cipher */ |
88 | | uint8_t sym_crypt_buffer[16]; |
89 | | uint8_t sym_plain_buffer[16]; |
90 | | uint8_t sym_crypt_buffer_len; |
91 | | uint8_t sym_plain_buffer_len; |
92 | | /* PSO for AES/DES need algo+flags from sec env */ |
93 | | unsigned long algorithm, algorithm_flags; |
94 | | } myeid_private_data_t; |
95 | | |
96 | | typedef struct myeid_card_caps { |
97 | | unsigned char card_caps_ver; |
98 | | unsigned short card_supported_features; |
99 | | unsigned short max_rsa_key_length; |
100 | | unsigned short max_des_key_length; |
101 | | unsigned short max_aes_key_length; |
102 | | unsigned short max_ecc_key_length; |
103 | | } myeid_card_caps_t; |
104 | | |
105 | | static struct myeid_supported_ec_curves { |
106 | | char *curve_name; |
107 | | struct sc_object_id curve_oid; |
108 | | size_t size; |
109 | | } ec_curves[] = { |
110 | | {"secp192r1", {{1, 2, 840, 10045, 3, 1, 1, -1}},192}, |
111 | | /* {"secp224r1", {{1, 3, 132, 0, 33, -1}}, 224}, */ |
112 | | {"secp256r1", {{1, 2, 840, 10045, 3, 1, 7, -1}},256}, |
113 | | {"secp384r1", {{1, 3, 132, 0, 34, -1}}, 384}, |
114 | | {"secp521r1", {{1, 3, 132, 0, 35, -1}}, 521}, |
115 | | {NULL, {{-1}}, 0}, |
116 | | }; |
117 | | |
118 | | static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen); |
119 | | static int myeid_get_card_caps(struct sc_card *card, myeid_card_caps_t* card_caps); |
120 | | |
121 | | static int myeid_match_card(struct sc_card *card) |
122 | 8.81k | { |
123 | 8.81k | size_t len = card->reader->atr_info.hist_bytes_len; |
124 | | /* Normally the historical bytes are exactly "MyEID", but there might |
125 | | * be some historic units which have a small prefix byte sequence. */ |
126 | 8.81k | if (len >= 5) { |
127 | 2.71k | if (!memcmp(&card->reader->atr_info.hist_bytes[len - 5], "MyEID", 5)) { |
128 | 186 | sc_log(card->ctx, "Matched MyEID card"); |
129 | 186 | card->type = SC_CARD_TYPE_MYEID_GENERIC; |
130 | 186 | return 1; |
131 | 186 | } |
132 | | /* The software implementation of MyEID is identified by OsEID bytes */ |
133 | 2.52k | if (!memcmp(&card->reader->atr_info.hist_bytes[len - 5], "OsEID", 5)) { |
134 | 175 | sc_log(card->ctx, "Matched OsEID card"); |
135 | 175 | card->type = SC_CARD_TYPE_MYEID_OSEID; |
136 | 175 | return 1; |
137 | 175 | } |
138 | 2.52k | } |
139 | 8.45k | return 0; |
140 | 8.81k | } |
141 | | |
142 | | static int myeid_load_options(sc_context_t *ctx, myeid_private_data_t *priv) |
143 | 361 | { |
144 | 361 | int r; |
145 | 361 | size_t i, j; |
146 | 361 | scconf_block **found_blocks, *block; |
147 | | |
148 | 361 | if (!ctx || !priv) { |
149 | 0 | r = SC_ERROR_INTERNAL; |
150 | 0 | goto err; |
151 | 0 | } |
152 | 361 | priv->disable_hw_pkcs1_padding = 0; |
153 | 722 | for (i = 0; ctx->conf_blocks[i]; i++) { |
154 | 361 | found_blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], |
155 | 361 | "card_driver", "myeid"); |
156 | 361 | if (!found_blocks) |
157 | 0 | continue; |
158 | 361 | for (j = 0, block = found_blocks[j]; block; j++, block = found_blocks[j]) { |
159 | 0 | priv->disable_hw_pkcs1_padding = scconf_get_int(block, "disable_hw_pkcs1_padding", 0); |
160 | 0 | sc_log(ctx,"Found config option: disable_hw_pkcs1_padding = %d\n", priv->disable_hw_pkcs1_padding); |
161 | 0 | } |
162 | 361 | free(found_blocks); |
163 | 361 | } |
164 | 361 | r = SC_SUCCESS; |
165 | | |
166 | 361 | err: |
167 | 361 | return r; |
168 | 361 | } |
169 | | |
170 | | static int myeid_init(struct sc_card *card) |
171 | 361 | { |
172 | 361 | unsigned long flags = 0, ext_flags = 0; |
173 | 361 | myeid_private_data_t *priv; |
174 | 361 | u8 appletInfo[20]; |
175 | 361 | size_t appletInfoLen; |
176 | 361 | myeid_card_caps_t card_caps; |
177 | 361 | static struct sc_aid myeid_aid = { "\xA0\x00\x00\x00\x63\x50\x4B\x43\x53\x2D\x31\x35", 0x0C }; |
178 | 361 | int rv = 0; |
179 | 361 | void *old_drv_data = card->drv_data; |
180 | | |
181 | 361 | LOG_FUNC_CALLED(card->ctx); |
182 | | |
183 | 361 | switch (card->type) { |
184 | 175 | case SC_CARD_TYPE_MYEID_OSEID: |
185 | 175 | card->name = oseid_card_name; |
186 | 175 | break; |
187 | 186 | case SC_CARD_TYPE_MYEID_GENERIC: |
188 | 186 | card->name = myeid_card_name; |
189 | 186 | break; |
190 | 0 | default: |
191 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_CARD); |
192 | 361 | } |
193 | | |
194 | 361 | priv = calloc(1, sizeof(myeid_private_data_t)); |
195 | | |
196 | 361 | if (!priv) |
197 | 361 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
198 | | |
199 | 361 | rv = myeid_load_options (card->ctx, priv); |
200 | 361 | LOG_TEST_GOTO_ERR(card->ctx, rv, "Unable to read options from opensc.conf"); |
201 | | |
202 | 361 | priv->card_state = SC_FILE_STATUS_CREATION; |
203 | 361 | card->drv_data = priv; |
204 | | |
205 | | /* Ensure that the MyEID applet is selected. */ |
206 | 361 | rv = iso7816_select_aid(card, myeid_aid.value, myeid_aid.len, NULL, NULL); |
207 | 361 | LOG_TEST_GOTO_ERR(card->ctx, rv, "Failed to select MyEID applet."); |
208 | | |
209 | | /* find out MyEID version */ |
210 | | |
211 | 348 | appletInfoLen = 20; |
212 | | |
213 | 348 | if (0 > myeid_get_info(card, appletInfo, appletInfoLen)) |
214 | 348 | LOG_TEST_GOTO_ERR(card->ctx, SC_ERROR_INVALID_CARD, "Failed to get MyEID applet information."); |
215 | | |
216 | 232 | priv->change_counter = appletInfo[19] | appletInfo[18] << 8; |
217 | | |
218 | 232 | memset(&card_caps, 0, sizeof(myeid_card_caps_t)); |
219 | 232 | card_caps.max_ecc_key_length = 256; |
220 | 232 | card_caps.max_rsa_key_length = 2048; |
221 | | |
222 | 232 | if (card->version.fw_major >= 40) { |
223 | | /* Since 4.0, we can query available algorithms and key sizes. |
224 | | * Since 3.5.0 RSA up to 2048 and ECC up to 256 are always supported, so we check only max ECC key length. */ |
225 | 99 | if (myeid_get_card_caps(card, &card_caps) != SC_SUCCESS) { |
226 | 48 | sc_log(card->ctx, "Failed to get card capabilities. Using default max ECC key length 256."); |
227 | 48 | } |
228 | 99 | } |
229 | | |
230 | 232 | flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN; |
231 | 232 | if (priv->disable_hw_pkcs1_padding == 0) |
232 | 232 | flags |= SC_ALGORITHM_RSA_PAD_PKCS1; |
233 | 232 | flags |= SC_ALGORITHM_RSA_HASH_NONE; |
234 | | |
235 | 232 | _sc_card_add_rsa_alg(card, 512, flags, 0); |
236 | 232 | _sc_card_add_rsa_alg(card, 768, flags, 0); |
237 | 232 | _sc_card_add_rsa_alg(card, 1024, flags, 0); |
238 | 232 | _sc_card_add_rsa_alg(card, 1536, flags, 0); |
239 | 232 | _sc_card_add_rsa_alg(card, 2048, flags, 0); |
240 | | |
241 | 232 | if (card_caps.card_supported_features & MYEID_CARD_CAP_RSA) { |
242 | 46 | if (card_caps.max_rsa_key_length >= 3072) |
243 | 34 | _sc_card_add_rsa_alg(card, 3072, flags, 0); |
244 | 46 | if (card_caps.max_rsa_key_length >= 4096) |
245 | 25 | _sc_card_add_rsa_alg(card, 4096, flags, 0); |
246 | 46 | } |
247 | | |
248 | | /* show ECC algorithms if the applet version of the inserted card supports them */ |
249 | 232 | if (card->version.fw_major >= 35) { |
250 | 102 | int i; |
251 | | |
252 | 102 | flags = SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDH_CDH_RAW | SC_ALGORITHM_ONBOARD_KEY_GEN; |
253 | 102 | flags |= SC_ALGORITHM_ECDSA_HASH_NONE; |
254 | 102 | ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES; |
255 | | |
256 | 510 | for (i=0; ec_curves[i].curve_name != NULL; i++) { |
257 | 408 | if (card_caps.max_ecc_key_length >= ec_curves[i].size) |
258 | 257 | _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].curve_oid); |
259 | 408 | } |
260 | 102 | } |
261 | | |
262 | | /* show supported symmetric algorithms */ |
263 | 232 | flags = 0; |
264 | 232 | if (card_caps.card_supported_features & MYEID_CARD_CAP_3DES) { |
265 | 46 | if (card_caps.max_des_key_length >= 64) |
266 | 36 | _sc_card_add_symmetric_alg(card, SC_ALGORITHM_DES, 64, flags); |
267 | 46 | if (card_caps.max_des_key_length >= 128) |
268 | 34 | _sc_card_add_symmetric_alg(card, SC_ALGORITHM_3DES, 128, flags); |
269 | 46 | if (card_caps.max_des_key_length >= 192) |
270 | 31 | _sc_card_add_symmetric_alg(card, SC_ALGORITHM_3DES, 192, flags); |
271 | 46 | } |
272 | 232 | if (card_caps.card_supported_features & MYEID_CARD_CAP_AES) { |
273 | 41 | if (card_caps.max_aes_key_length >= 128) |
274 | 32 | _sc_card_add_symmetric_alg(card, SC_ALGORITHM_AES, 128, flags); |
275 | 41 | if (card_caps.max_aes_key_length >= 256) |
276 | 26 | _sc_card_add_symmetric_alg(card, SC_ALGORITHM_AES, 256, flags); |
277 | 41 | } |
278 | | |
279 | | /* State that we have an RNG */ |
280 | 232 | card->caps |= SC_CARD_CAP_RNG | SC_CARD_CAP_ISO7816_PIN_INFO; |
281 | | |
282 | 232 | if ((card->version.fw_major == 40 && card->version.fw_minor >= 10 ) |
283 | 231 | || card->version.fw_major >= 41) |
284 | 97 | card->caps |= SC_CARD_CAP_WRAP_KEY | SC_CARD_CAP_UNWRAP_KEY |
285 | 97 | | SC_CARD_CAP_ONCARD_SESSION_OBJECTS; |
286 | | |
287 | 232 | if (card->version.fw_major >= 45) |
288 | 83 | priv->cap_chaining = 1; |
289 | 232 | if (card->version.fw_major >= 40) |
290 | 99 | card->max_recv_size = 256; |
291 | 133 | else |
292 | 133 | card->max_recv_size = 255; |
293 | 232 | card->max_send_size = 255; |
294 | | |
295 | 232 | rv = SC_SUCCESS; |
296 | | |
297 | 361 | err: |
298 | 361 | if (rv < 0) { |
299 | 13 | free(priv); |
300 | 13 | card->drv_data = old_drv_data; |
301 | 13 | } |
302 | | |
303 | 361 | LOG_FUNC_RETURN(card->ctx, rv); |
304 | 361 | } |
305 | | |
306 | | static const struct sc_card_operations *iso_ops = NULL; |
307 | | |
308 | | static int acl_to_byte(const struct sc_acl_entry *e) |
309 | 0 | { |
310 | 0 | if (NULL == e) |
311 | 0 | return 0x00; |
312 | 0 | switch (e->method) { |
313 | 0 | case SC_AC_NONE: |
314 | 0 | return 0x00; |
315 | 0 | case SC_AC_CHV: |
316 | 0 | case SC_AC_TERM: |
317 | 0 | case SC_AC_AUT: |
318 | 0 | if (e->key_ref == SC_AC_KEY_REF_NONE) |
319 | 0 | return 0x00; |
320 | 0 | if (e->key_ref < 1 || e->key_ref > 14) |
321 | 0 | return 0x00; |
322 | 0 | return e->key_ref; |
323 | 0 | case SC_AC_NEVER: |
324 | 0 | return 0x0F; |
325 | 0 | } |
326 | 0 | return 0x00; |
327 | 0 | } |
328 | | |
329 | | static void add_acl_entry(struct sc_file *file, int op, u8 byte) |
330 | 156 | { |
331 | 156 | unsigned int method, key_ref = SC_AC_KEY_REF_NONE; |
332 | | |
333 | 156 | switch (byte) |
334 | 156 | { |
335 | 38 | case 0: |
336 | 38 | method = SC_AC_NONE; |
337 | 38 | break; |
338 | 32 | case 15: |
339 | 32 | method = SC_AC_NEVER; |
340 | 32 | break; |
341 | 86 | default: |
342 | 86 | method = SC_AC_CHV; |
343 | 86 | key_ref = byte; |
344 | 86 | break; |
345 | 156 | } |
346 | 156 | sc_file_add_acl_entry(file, op, method, key_ref); |
347 | 156 | } |
348 | | |
349 | | static void parse_sec_attr(struct sc_file *file, const u8 *buf, size_t len) |
350 | 117 | { |
351 | 117 | int i; |
352 | 117 | const int df_ops[4] = |
353 | 117 | { SC_AC_OP_CREATE, SC_AC_OP_CREATE, SC_AC_OP_DELETE, -1 }; |
354 | 117 | const int ef_ops[4] = |
355 | 117 | { SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_DELETE, -1 }; |
356 | 117 | const int key_ops[4] = |
357 | 117 | { SC_AC_OP_CRYPTO, SC_AC_OP_UPDATE, SC_AC_OP_DELETE, SC_AC_OP_GENERATE }; |
358 | | |
359 | 117 | const int *ops; |
360 | | |
361 | 117 | if (len < 2) |
362 | 76 | return; |
363 | | |
364 | 41 | switch (file->type) { |
365 | 4 | case SC_FILE_TYPE_WORKING_EF: |
366 | 4 | ops = ef_ops; |
367 | 4 | break; |
368 | 6 | case SC_FILE_TYPE_INTERNAL_EF: |
369 | 6 | ops = key_ops; |
370 | 6 | break; |
371 | 4 | case SC_FILE_TYPE_DF: |
372 | 4 | ops = df_ops; |
373 | 4 | break; |
374 | 27 | default: |
375 | 27 | ops = key_ops; |
376 | 27 | break; |
377 | 41 | } |
378 | | |
379 | 205 | for (i = 0; i < 4; i++) |
380 | 164 | { |
381 | 164 | if (ops[i] == -1) |
382 | 8 | continue; |
383 | 156 | if ((i & 1) == 0) |
384 | 82 | add_acl_entry(file, ops[i], (u8)(buf[i / 2] >> 4)); |
385 | 74 | else |
386 | 74 | add_acl_entry(file, ops[i], (u8)(buf[i / 2] & 0x0F)); |
387 | 156 | } |
388 | 41 | } |
389 | | |
390 | | static int myeid_select_file(struct sc_card *card, const struct sc_path *in_path, |
391 | | struct sc_file **file) |
392 | 2.38k | { |
393 | 2.38k | int r; |
394 | | |
395 | 2.38k | LOG_FUNC_CALLED(card->ctx); |
396 | 2.38k | r = iso_ops->select_file(card, in_path, file); |
397 | | |
398 | 2.38k | if (r == 0 && file != NULL && *file != NULL) |
399 | 117 | parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len); |
400 | | |
401 | 2.38k | LOG_FUNC_RETURN(card->ctx, r); |
402 | 2.38k | } |
403 | | |
404 | | static int myeid_logout(struct sc_card *card) |
405 | 0 | { |
406 | 0 | sc_apdu_t apdu; |
407 | 0 | int r; |
408 | |
|
409 | 0 | LOG_FUNC_CALLED(card->ctx); |
410 | |
|
411 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x2E, 0x00, 0x00 /*pin ref: 0x01-0x0E, 0=ALL*/); |
412 | 0 | apdu.cla = 0; |
413 | |
|
414 | 0 | r = sc_transmit_apdu(card, &apdu); |
415 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
416 | | |
417 | 0 | LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); |
418 | 0 | } |
419 | | |
420 | | static int myeid_list_files(struct sc_card *card, u8 *buf, size_t buflen) |
421 | 0 | { |
422 | 0 | struct sc_apdu apdu; |
423 | 0 | int r; |
424 | |
|
425 | 0 | LOG_FUNC_CALLED(card->ctx); |
426 | |
|
427 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, 0xA1); |
428 | 0 | apdu.resp = buf; |
429 | 0 | apdu.resplen = buflen; |
430 | 0 | apdu.le = buflen > 256 ? 256 : buflen; |
431 | |
|
432 | 0 | r = sc_transmit_apdu(card, &apdu); |
433 | |
|
434 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
435 | 0 | if (apdu.resplen == 0) |
436 | 0 | return sc_check_sw(card, apdu.sw1, apdu.sw2); |
437 | 0 | return (int)apdu.resplen; |
438 | 0 | } |
439 | | |
440 | | static int myeid_process_fci(struct sc_card *card, struct sc_file *file, |
441 | | const u8 *buf, size_t buflen) |
442 | 115 | { |
443 | 115 | myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data; |
444 | 115 | size_t taglen = 0; |
445 | 115 | const u8 *tag = NULL; |
446 | 115 | int r; |
447 | | |
448 | 115 | LOG_FUNC_CALLED(card->ctx); |
449 | 115 | r = iso_ops->process_fci(card, file, buf, buflen); |
450 | 115 | if (r < 0) |
451 | 115 | LOG_FUNC_RETURN(card->ctx, r); |
452 | | |
453 | 115 | if(file->type == SC_FILE_EF_UNKNOWN) |
454 | 85 | { |
455 | 85 | tag = sc_asn1_find_tag(NULL, buf, buflen, 0x82, &taglen); |
456 | 85 | if (tag != NULL && taglen > 0 && *tag == 17) |
457 | 6 | { |
458 | 6 | file->type = SC_FILE_TYPE_INTERNAL_EF; |
459 | 6 | } |
460 | 85 | } |
461 | 115 | if(file->sec_attr_len >= 3) |
462 | 33 | { |
463 | 33 | sc_log(card->ctx, "id (%X) sec_attr (%X %X %X)", file->id, |
464 | 33 | file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); |
465 | 33 | } |
466 | | |
467 | 115 | priv->card_state = file->status; |
468 | 115 | switch (file->status) { |
469 | 3 | case SC_FILE_STATUS_CREATION: |
470 | 3 | file->acl_inactive = 1; |
471 | 3 | sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_CREATION", file->id); |
472 | 3 | break; |
473 | 11 | case SC_FILE_STATUS_ACTIVATED: |
474 | 11 | sc_log(card->ctx, "File id (%X) status SC_FILE_STATUS_ACTIVATED", file->id); |
475 | 11 | break; |
476 | 101 | default: |
477 | 101 | sc_log(card->ctx, "File id (%X) unusual status (0x%X)", file->id, file->status); |
478 | 115 | } |
479 | | |
480 | 115 | LOG_FUNC_RETURN(card->ctx, 0); |
481 | 115 | } |
482 | | |
483 | | static int encode_file_structure(sc_card_t *card, const sc_file_t *file, |
484 | | u8 *buf, size_t *outlen) |
485 | 0 | { |
486 | 0 | const sc_acl_entry_t *read, *update, *delete, *generate; |
487 | 0 | size_t i; |
488 | |
|
489 | 0 | LOG_FUNC_CALLED(card->ctx); |
490 | |
|
491 | 0 | if (!buf || !outlen || *outlen < 45) |
492 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL); |
493 | | |
494 | | /* PrivateKey |
495 | | * 0E0000019 6217 81020400 820111 83024B01 8603000000 85028000 8A0100 RESULT 6984 |
496 | | * 6217 81020400 820111 83024B01 8603000000 85021000 8A0100 */ |
497 | 0 | memset(buf, 0x0, *outlen); |
498 | |
|
499 | 0 | buf[0] = 0x62; |
500 | 0 | buf[1] = 0x17; |
501 | | /* File size */ |
502 | 0 | buf[2] = (SC_FILE_TYPE_WORKING_EF == file->type ? 0x80 : 0x81); |
503 | 0 | buf[3] = 0x02; |
504 | 0 | buf[4] = (file->size >> 8) & 0xFF; |
505 | 0 | buf[5] = file->size & 0xFF; |
506 | | |
507 | | /* File Description tag */ |
508 | 0 | buf[6] = 0x82; |
509 | 0 | buf[7] = 0x01; |
510 | 0 | buf[8] = 0x01; |
511 | | |
512 | | /* File Identifier tag */ |
513 | 0 | buf[9] = 0x83; |
514 | 0 | buf[10] = 0x02; |
515 | 0 | buf[11] = (file->id >> 8) & 0xFF; |
516 | 0 | buf[12] = file->id & 0xFF; |
517 | | |
518 | | /* Security Attributes Tag */ |
519 | 0 | buf[13] = 0x86; |
520 | 0 | buf[14] = 0x03; |
521 | 0 | buf[15] = 0xFF; |
522 | 0 | buf[16] = 0xFF; |
523 | 0 | buf[17] = 0xFF; |
524 | |
|
525 | 0 | if (file->sec_attr_len == 3 && file->sec_attr) { |
526 | 0 | buf[15] = file->sec_attr[0]; |
527 | 0 | buf[16] = file->sec_attr[1]; |
528 | 0 | buf[17] = file->sec_attr[2]; |
529 | |
|
530 | 0 | sc_log(card->ctx, "id (%X), sec_attr %X %X %X", file->id, |
531 | 0 | file->sec_attr[0],file->sec_attr[1],file->sec_attr[2]); |
532 | 0 | } |
533 | 0 | else { |
534 | 0 | delete = sc_file_get_acl_entry(file, SC_AC_OP_DELETE); |
535 | |
|
536 | 0 | sc_log(card->ctx, "id (%X), type (%X)", file->id, file->type); |
537 | |
|
538 | 0 | switch (file->type) { |
539 | 0 | case SC_FILE_TYPE_WORKING_EF: |
540 | |
|
541 | 0 | read = sc_file_get_acl_entry(file, SC_AC_OP_READ); |
542 | 0 | update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE); |
543 | |
|
544 | 0 | buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update); |
545 | 0 | buf[16] = (acl_to_byte(delete)<< 4) | 0x0F; |
546 | 0 | break; |
547 | 0 | case SC_FILE_TYPE_INTERNAL_EF: |
548 | |
|
549 | 0 | read = sc_file_get_acl_entry(file, SC_AC_OP_CRYPTO); |
550 | 0 | update = sc_file_get_acl_entry(file, SC_AC_OP_UPDATE); |
551 | 0 | generate = sc_file_get_acl_entry(file, SC_AC_OP_GENERATE); |
552 | |
|
553 | 0 | buf[15] = (acl_to_byte(read) << 4) | acl_to_byte(update); |
554 | 0 | buf[16] = (acl_to_byte(delete)<< 4) | acl_to_byte(generate); |
555 | 0 | break; |
556 | 0 | case SC_FILE_TYPE_DF: |
557 | |
|
558 | 0 | update = sc_file_get_acl_entry(file, SC_AC_OP_CREATE); |
559 | |
|
560 | 0 | buf[15] = (acl_to_byte(update) << 4) | acl_to_byte(update); |
561 | 0 | buf[16] = (acl_to_byte(delete) << 4) | 0x0F; |
562 | 0 | break; |
563 | 0 | default: |
564 | 0 | break; |
565 | 0 | } |
566 | 0 | } |
567 | | |
568 | | /* Proprietary Information */ |
569 | 0 | buf[18] = 0x85; |
570 | 0 | buf[19] = 0x02; |
571 | 0 | if (file->prop_attr_len == 2 && file->prop_attr != NULL) |
572 | 0 | memcpy(&buf[20], file->prop_attr, 2); |
573 | 0 | else |
574 | 0 | { |
575 | 0 | buf[20] = 0x00; |
576 | 0 | buf[21] = 0x00; |
577 | 0 | } |
578 | | |
579 | | /* Life Cycle Status tag */ |
580 | 0 | buf[22] = 0x8A; |
581 | 0 | buf[23] = 0x01; |
582 | 0 | buf[24] = 0x0; /* RFU */ |
583 | |
|
584 | 0 | switch (file->type) |
585 | 0 | { |
586 | 0 | case SC_FILE_TYPE_WORKING_EF: |
587 | 0 | break; |
588 | | |
589 | 0 | case SC_FILE_TYPE_INTERNAL_EF: |
590 | 0 | buf[8] = file->ef_structure; /* RSA or EC */ |
591 | 0 | break; |
592 | | |
593 | 0 | case SC_FILE_TYPE_DF: |
594 | 0 | buf[8] = 0x38; |
595 | 0 | if(file->namelen > 0 && file->namelen <= 16) |
596 | 0 | { |
597 | 0 | buf[25] = 0x84; |
598 | 0 | buf[26] = (u8)file->namelen; |
599 | |
|
600 | 0 | for(i=0;i < file->namelen;i++) |
601 | 0 | buf[i + 27] = file->name[i]; |
602 | |
|
603 | 0 | buf[1] = 27 + file->namelen; |
604 | 0 | } |
605 | 0 | break; |
606 | 0 | default: |
607 | 0 | sc_log(card->ctx, "Unknown file type\n"); |
608 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
609 | 0 | } |
610 | | |
611 | 0 | *outlen = buf[1]+2; |
612 | |
|
613 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
614 | 0 | } |
615 | | |
616 | | static int myeid_create_file(struct sc_card *card, struct sc_file *file) |
617 | 0 | { |
618 | 0 | sc_apdu_t apdu; |
619 | 0 | u8 sbuf[45]; |
620 | 0 | size_t buflen = sizeof sbuf; |
621 | 0 | int r; |
622 | |
|
623 | 0 | LOG_FUNC_CALLED(card->ctx); |
624 | |
|
625 | 0 | r = encode_file_structure(card, file, sbuf, &buflen); |
626 | 0 | if (r) |
627 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
628 | | |
629 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00); |
630 | 0 | apdu.data = sbuf; |
631 | 0 | apdu.datalen = buflen; |
632 | 0 | apdu.lc = buflen; |
633 | |
|
634 | 0 | r = sc_transmit_apdu(card, &apdu); |
635 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
636 | 0 | if (apdu.sw1 == 0x6A && apdu.sw2 == 0x89) |
637 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_FILE_ALREADY_EXISTS); |
638 | | |
639 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
640 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
641 | 0 | } |
642 | | |
643 | | static int myeid_delete_file(struct sc_card *card, const struct sc_path *path) |
644 | 0 | { |
645 | 0 | int r; |
646 | 0 | struct sc_apdu apdu; |
647 | |
|
648 | 0 | LOG_FUNC_CALLED(card->ctx); |
649 | 0 | if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) |
650 | 0 | { |
651 | 0 | sc_log(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n"); |
652 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
653 | 0 | } |
654 | 0 | r = sc_select_file(card, path, NULL); |
655 | 0 | LOG_TEST_RET(card->ctx, r, "Unable to select file to be deleted"); |
656 | | |
657 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4, 0x00, 0x00); |
658 | 0 | apdu.cla = 0xA0; |
659 | |
|
660 | 0 | r = sc_transmit_apdu(card, &apdu); |
661 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
662 | | |
663 | 0 | LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); |
664 | 0 | } |
665 | | |
666 | | static int myeid_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, |
667 | | int *tries_left) |
668 | 241 | { |
669 | 241 | myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data; |
670 | | |
671 | 241 | LOG_FUNC_CALLED(card->ctx); |
672 | | |
673 | 241 | sc_log(card->ctx, "ref (%d), pin1 len(%zu), pin2 len (%zu)\n", |
674 | 241 | data->pin_reference, data->pin1.len, data->pin2.len); |
675 | | |
676 | 241 | if(data->pin1.len > 8 || data->pin2.len > 8) |
677 | 241 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_LENGTH); |
678 | | |
679 | 241 | data->pin1.pad_length = data->pin2.pad_length = 8; |
680 | 241 | data->pin1.pad_char = data->pin2.pad_char = 0xFF; |
681 | | |
682 | 241 | if (data->cmd == SC_PIN_CMD_VERIFY && priv->card_state == SC_FILE_STATUS_CREATION) { |
683 | 71 | sc_log(card->ctx, "Card in creation state, no need to verify"); |
684 | 71 | return SC_SUCCESS; |
685 | 71 | } |
686 | | |
687 | 170 | LOG_FUNC_RETURN(card->ctx, iso_ops->pin_cmd(card, data, tries_left)); |
688 | 170 | } |
689 | | |
690 | 696 | #define IS_SYMETRIC_CRYPT(x) ((x) == SC_SEC_OPERATION_ENCRYPT_SYM || (x) == SC_SEC_OPERATION_DECRYPT_SYM) |
691 | | |
692 | | static int myeid_set_security_env_rsa(sc_card_t *card, const sc_security_env_t *env, |
693 | | int se_num) |
694 | 174 | { |
695 | 174 | sc_apdu_t apdu; |
696 | 174 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
697 | 174 | u8 *p; |
698 | 174 | int r; |
699 | 174 | size_t i, sz; |
700 | 174 | sc_path_t *target_file; |
701 | | |
702 | 174 | assert(card != NULL && env != NULL); |
703 | 174 | LOG_FUNC_CALLED(card->ctx); |
704 | | |
705 | 174 | if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC) |
706 | 0 | { |
707 | 0 | sc_log(card->ctx, "symmetric keyref not supported.\n"); |
708 | 0 | return SC_ERROR_NOT_SUPPORTED; |
709 | 0 | } |
710 | 174 | if (se_num > 0) |
711 | 0 | { |
712 | 0 | sc_log(card->ctx, "restore security environment not supported.\n"); |
713 | 0 | return SC_ERROR_NOT_SUPPORTED; |
714 | 0 | } |
715 | | |
716 | 174 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); |
717 | 174 | switch (env->operation) |
718 | 174 | { |
719 | 133 | case SC_SEC_OPERATION_DECIPHER: |
720 | 133 | apdu.p1 = 0x41; |
721 | 133 | apdu.p2 = 0xB8; |
722 | 133 | break; |
723 | 41 | case SC_SEC_OPERATION_SIGN: |
724 | 41 | apdu.p1 = 0x41; |
725 | 41 | apdu.p2 = 0xB6; |
726 | 41 | break; |
727 | 0 | case SC_SEC_OPERATION_UNWRAP: |
728 | 0 | apdu.p1 = 0x41; |
729 | 0 | apdu.p2 = 0xB8; |
730 | 0 | break; |
731 | 0 | case SC_SEC_OPERATION_WRAP: |
732 | 0 | apdu.p1 = 0x81; |
733 | 0 | apdu.p2 = 0xB8; |
734 | 0 | break; |
735 | 0 | case SC_SEC_OPERATION_ENCRYPT_SYM: |
736 | 0 | apdu.p1 = 0x81; |
737 | 0 | apdu.p2 = 0xB8; |
738 | 0 | break; |
739 | 0 | case SC_SEC_OPERATION_DECRYPT_SYM: |
740 | 0 | apdu.p1 = 0x41; |
741 | 0 | apdu.p2 = 0xB8; |
742 | 0 | break; |
743 | 0 | default: |
744 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
745 | 174 | } |
746 | 174 | apdu.le = 0; |
747 | 174 | p = sbuf; |
748 | 174 | if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) |
749 | 174 | { |
750 | 174 | *p++ = 0x80; /* algorithm reference */ |
751 | 174 | *p++ = 0x01; |
752 | 174 | *p++ = env->algorithm_ref & 0xFF; |
753 | 174 | } |
754 | 174 | if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) |
755 | 22 | { |
756 | 22 | *p++ = 0x81; |
757 | 22 | *p++ = 2; |
758 | 22 | memcpy(p, env->file_ref.value, 2); |
759 | 22 | p += 2; |
760 | 22 | } |
761 | | /* symmetric operations: we need to set the key reference */ |
762 | 174 | if (IS_SYMETRIC_CRYPT(env->operation)) { |
763 | 0 | *p++ = 0x83; |
764 | 0 | *p++ = 1; |
765 | 0 | *p++ = 0; |
766 | 0 | } |
767 | 174 | if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT && env->operation != SC_SEC_OPERATION_UNWRAP && |
768 | 174 | env->operation != SC_SEC_OPERATION_WRAP && |
769 | 174 | env->operation != SC_SEC_OPERATION_ENCRYPT_SYM && |
770 | 174 | env->operation != SC_SEC_OPERATION_DECRYPT_SYM) { |
771 | 174 | *p++ = 0x84; |
772 | 174 | *p++ = 1; |
773 | 174 | *p++ = 0; |
774 | 174 | } |
775 | 1.91k | for (i = 0; i < SC_SEC_ENV_MAX_PARAMS; i++) |
776 | 1.74k | if (env->params[i].param_type == SC_SEC_ENV_PARAM_TARGET_FILE) { |
777 | 0 | target_file = (sc_path_t*) env->params[i].value; |
778 | 0 | if (env->params[i].value_len < sizeof(sc_path_t) || target_file->len != 2) { |
779 | 0 | sc_log(card->ctx, "wrong length of target file reference.\n"); |
780 | 0 | return SC_ERROR_WRONG_LENGTH; |
781 | 0 | } |
782 | 0 | *p++ = 0x83; |
783 | 0 | *p++ = 2; |
784 | 0 | memcpy(p, target_file->value, 2); |
785 | 0 | p+= 2; |
786 | 0 | break; |
787 | 0 | } |
788 | | |
789 | 174 | r = 0; |
790 | 174 | if (env->operation == SC_SEC_OPERATION_UNWRAP || env->operation == SC_SEC_OPERATION_WRAP || |
791 | 174 | IS_SYMETRIC_CRYPT(env->operation)) { |
792 | | /* add IV if present */ |
793 | 0 | for (i = 0; i < SC_SEC_ENV_MAX_PARAMS; i++) |
794 | 0 | if (env->params[i].param_type == SC_SEC_ENV_PARAM_IV) { |
795 | 0 | r = 1; |
796 | 0 | *p++ = 0x87; |
797 | 0 | *p++ = (unsigned char) env->params[i].value_len; |
798 | 0 | if (p + env->params[i].value_len >= sbuf + SC_MAX_APDU_BUFFER_SIZE) { |
799 | 0 | sc_log(card->ctx, "IV too long.\n"); |
800 | 0 | return SC_ERROR_WRONG_LENGTH; |
801 | 0 | } |
802 | 0 | memcpy(p, env->params[i].value, env->params[i].value_len); |
803 | 0 | p+=(unsigned char) env->params[i].value_len; |
804 | 0 | break; |
805 | 0 | } |
806 | 0 | } |
807 | | /* for AES_ECB we need to reset the IV but we respect if the IV is already present */ |
808 | 174 | if (IS_SYMETRIC_CRYPT(env->operation) && env->algorithm == SC_ALGORITHM_AES && |
809 | 0 | env->algorithm_flags == SC_ALGORITHM_AES_ECB && r == 0) { |
810 | 0 | *p++ = 0x87; |
811 | 0 | *p++ = 16; |
812 | 0 | memset(p, 0, 16); |
813 | 0 | p += 16; |
814 | 0 | } |
815 | | |
816 | 174 | sz = p - sbuf; |
817 | 174 | apdu.lc = sz; |
818 | 174 | apdu.datalen = sz; |
819 | 174 | apdu.data = sbuf; |
820 | 174 | apdu.resplen = 0; |
821 | 174 | r = (int)sz; |
822 | 174 | if (apdu.datalen != 0) |
823 | 174 | { |
824 | 174 | r = sc_transmit_apdu(card, &apdu); |
825 | 174 | if (r) |
826 | 2 | { |
827 | 2 | sc_log(card->ctx, |
828 | 2 | "%s: APDU transmit failed", sc_strerror(r)); |
829 | 2 | goto err; |
830 | 2 | } |
831 | 172 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
832 | 172 | if (r) |
833 | 26 | { |
834 | 26 | sc_log(card->ctx, |
835 | 26 | "%s: Card returned error", sc_strerror(r)); |
836 | 26 | goto err; |
837 | 26 | } |
838 | 172 | } |
839 | 174 | err: |
840 | 174 | LOG_FUNC_RETURN(card->ctx, r); |
841 | 174 | } |
842 | | |
843 | | static int myeid_set_security_env_ec(sc_card_t *card, const sc_security_env_t *env, |
844 | | int se_num) |
845 | 0 | { |
846 | 0 | sc_apdu_t apdu; |
847 | 0 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
848 | 0 | u8 *p; |
849 | 0 | size_t sz; |
850 | 0 | int r; |
851 | |
|
852 | 0 | assert(card != NULL && env != NULL); |
853 | 0 | LOG_FUNC_CALLED(card->ctx); |
854 | |
|
855 | 0 | if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC) |
856 | 0 | { |
857 | 0 | sc_log(card->ctx, "symmetric keyref not supported."); |
858 | 0 | return SC_ERROR_NOT_SUPPORTED; |
859 | 0 | } |
860 | 0 | if (se_num > 0) |
861 | 0 | { |
862 | 0 | sc_log(card->ctx, "restore security environment not supported."); |
863 | 0 | return SC_ERROR_NOT_SUPPORTED; |
864 | 0 | } |
865 | | |
866 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0); |
867 | 0 | switch (env->operation) |
868 | 0 | { |
869 | 0 | case SC_SEC_OPERATION_DECIPHER: |
870 | 0 | sc_log(card->ctx, "Decipher operation is not supported with EC keys."); |
871 | 0 | return SC_ERROR_NOT_SUPPORTED; |
872 | 0 | break; |
873 | 0 | case SC_SEC_OPERATION_SIGN: |
874 | 0 | apdu.p1 = 0x41; |
875 | 0 | apdu.p2 = 0xB6; |
876 | 0 | break; |
877 | 0 | case SC_SEC_OPERATION_DERIVE: |
878 | 0 | apdu.p1 = 0x41; |
879 | 0 | apdu.p2 = 0xA4; |
880 | 0 | break; |
881 | 0 | default: |
882 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
883 | 0 | } |
884 | 0 | apdu.le = 0; |
885 | 0 | p = sbuf; |
886 | 0 | if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) |
887 | 0 | { |
888 | 0 | *p++ = 0x80; /* algorithm reference */ |
889 | 0 | *p++ = 0x01; |
890 | 0 | *p++ = env->algorithm_ref & 0xFF; |
891 | 0 | } |
892 | 0 | if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) |
893 | 0 | { |
894 | 0 | *p++ = 0x81; |
895 | 0 | *p++ = 0x02; |
896 | 0 | memcpy(p, env->file_ref.value, 2); |
897 | 0 | p += 2; |
898 | 0 | } |
899 | 0 | if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) |
900 | 0 | { |
901 | 0 | *p++ = 0x84; |
902 | 0 | *p++ = 1; |
903 | 0 | *p++ = 0; |
904 | 0 | } |
905 | 0 | sz = p - sbuf; |
906 | 0 | apdu.lc = sz; |
907 | 0 | apdu.datalen = sz; |
908 | 0 | apdu.data = sbuf; |
909 | 0 | apdu.resplen = 0; |
910 | 0 | r = (int)sz; |
911 | 0 | if (apdu.datalen != 0) |
912 | 0 | { |
913 | 0 | r = sc_transmit_apdu(card, &apdu); |
914 | 0 | if (r) |
915 | 0 | { |
916 | 0 | sc_log(card->ctx, |
917 | 0 | "%s: APDU transmit failed", sc_strerror(r)); |
918 | 0 | goto err; |
919 | 0 | } |
920 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
921 | 0 | if (r) |
922 | 0 | { |
923 | 0 | sc_log(card->ctx, |
924 | 0 | "%s: Card returned error", sc_strerror(r)); |
925 | 0 | goto err; |
926 | 0 | } |
927 | 0 | } |
928 | 0 | err: |
929 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
930 | 0 | } |
931 | | |
932 | | static int myeid_set_security_env(struct sc_card *card, |
933 | | const struct sc_security_env *env, int se_num) |
934 | 152 | { |
935 | 152 | struct sc_context *ctx = card->ctx; |
936 | 152 | myeid_private_data_t* priv; |
937 | | |
938 | 152 | LOG_FUNC_CALLED(ctx); |
939 | | |
940 | 152 | priv = (myeid_private_data_t*) card->drv_data; |
941 | | /* store security environment to differentiate between ECDH and RSA in decipher - Hannu*/ |
942 | 152 | priv->sec_env = env; |
943 | | |
944 | | /* for symmetric operation save algo and algo flags */ |
945 | 152 | priv->algorithm_flags = env->algorithm_flags; |
946 | 152 | priv->algorithm = env->algorithm; |
947 | | |
948 | 152 | if (env->flags & SC_SEC_ENV_ALG_PRESENT) |
949 | 152 | { |
950 | 152 | sc_security_env_t tmp; |
951 | | |
952 | 152 | tmp = *env; |
953 | 152 | tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT; |
954 | 152 | tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT; |
955 | | |
956 | 152 | if (tmp.algorithm == SC_ALGORITHM_RSA) |
957 | 152 | { |
958 | 152 | if (tmp.operation == SC_SEC_OPERATION_UNWRAP || tmp.operation == SC_SEC_OPERATION_WRAP) |
959 | 0 | { |
960 | 0 | tmp.algorithm_ref = 0x0A; |
961 | 0 | } |
962 | 152 | else |
963 | 152 | { |
964 | 152 | tmp.algorithm_ref = 0x00; |
965 | | /* potential FIXME: return an error, if an unsupported |
966 | | * pad or hash was requested, although this shouldn't happen */ |
967 | 152 | if ((env->operation == SC_SEC_OPERATION_SIGN && env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01) |
968 | 152 | || (env->operation == SC_SEC_OPERATION_DECIPHER && env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02)) |
969 | 0 | tmp.algorithm_ref = 0x02; |
970 | 152 | if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1) |
971 | 0 | tmp.algorithm_ref |= 0x10; |
972 | 152 | } |
973 | | |
974 | 152 | return myeid_set_security_env_rsa(card, &tmp, se_num); |
975 | 152 | } |
976 | 0 | else if (tmp.algorithm == SC_ALGORITHM_EC) |
977 | 0 | { |
978 | 0 | tmp.algorithm_ref = 0x04; |
979 | 0 | tmp.algorithm_flags = 0; |
980 | 0 | return myeid_set_security_env_ec(card, &tmp, se_num); |
981 | 0 | } |
982 | 0 | else if (tmp.algorithm == SC_ALGORITHM_AES) |
983 | 0 | { |
984 | 0 | if (tmp.operation == SC_SEC_OPERATION_UNWRAP || tmp.operation == SC_SEC_OPERATION_WRAP) |
985 | 0 | { |
986 | 0 | tmp.algorithm_ref = 0x0A; |
987 | 0 | } |
988 | 0 | else |
989 | 0 | { |
990 | 0 | tmp.algorithm_ref = 0x00; |
991 | 0 | } |
992 | |
|
993 | 0 | if ((tmp.algorithm_flags & SC_ALGORITHM_AES_CBC_PAD) == SC_ALGORITHM_AES_CBC_PAD) |
994 | 0 | tmp.algorithm_ref |= 0x80; /* set PKCS#7 padding */ |
995 | | /* Tag 0x80 algorithm_ref - value 0x80 or 0x8A is working only for UNWRAP/WRAP |
996 | | * AES is supported from version 4.0 but without pkcs#7 padding. |
997 | | * For SC_SEC_OPERATION_ENCRYPT_SYM and SC_SEC_OPERATION_DECRYPT_SYM we running |
998 | | * PKCS#7 in software, here we fix the algorithm_ref variable. |
999 | | */ |
1000 | 0 | if (IS_SYMETRIC_CRYPT(env->operation)) |
1001 | 0 | tmp.algorithm_ref &= ~0x80; /* do not handle padding in card */ |
1002 | | |
1003 | | /* from this point, there's no difference to RSA SE */ |
1004 | 0 | return myeid_set_security_env_rsa(card, &tmp, se_num); |
1005 | 0 | } |
1006 | 0 | else |
1007 | 0 | { |
1008 | |
|
1009 | 0 | sc_log(ctx, "Unsupported algorithm."); |
1010 | 0 | return SC_ERROR_NOT_SUPPORTED; |
1011 | 0 | } |
1012 | 152 | } |
1013 | 0 | return myeid_set_security_env_rsa(card, env, se_num); |
1014 | 152 | } |
1015 | | |
1016 | | |
1017 | | static int |
1018 | | myeid_convert_ec_signature(struct sc_context *ctx, size_t s_len, unsigned char *data, size_t datalen) |
1019 | 0 | { |
1020 | 0 | unsigned char *buf; |
1021 | 0 | size_t buflen; |
1022 | 0 | int r; |
1023 | 0 | size_t len_size = 1; |
1024 | 0 | size_t sig_len = 0; |
1025 | |
|
1026 | 0 | assert(data && datalen && datalen > 3); |
1027 | | |
1028 | | /* |
1029 | | * When validating the signature data, we have to consider that length of the signature |
1030 | | * can be encoded in either one or two bytes depending on key size. With 521 bit keys |
1031 | | * length of the structure takes two bytes. |
1032 | | */ |
1033 | |
|
1034 | 0 | if (*data != 0x30) |
1035 | 0 | return SC_ERROR_INVALID_DATA; |
1036 | | |
1037 | 0 | if ((*(data + 1) & 0x80) == 0x80) |
1038 | 0 | len_size += *(data + 1) & 0x7F; |
1039 | |
|
1040 | 0 | if (len_size == 1) |
1041 | 0 | sig_len = *(data + 1); |
1042 | 0 | else if (len_size == 2) |
1043 | 0 | sig_len = *(data + 2); |
1044 | 0 | else if (len_size == 3) |
1045 | 0 | { |
1046 | 0 | sig_len = *(data + 2) | (*data + 3) << 8; |
1047 | 0 | } |
1048 | 0 | else |
1049 | 0 | return SC_ERROR_INVALID_DATA; |
1050 | | |
1051 | 0 | if (*(data + 1 + len_size) != 0x02) /* Verify that it is an INTEGER */ |
1052 | | |
1053 | 0 | if (sig_len != (datalen - len_size - 1)) /* validate size of the DER structure */ |
1054 | 0 | return SC_ERROR_INVALID_DATA; |
1055 | | |
1056 | | /* test&fail early */ |
1057 | 0 | buflen = BYTES4BITS(s_len) * 2; |
1058 | 0 | if (buflen > datalen) |
1059 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA); |
1060 | | |
1061 | 0 | buf = calloc(1, buflen); |
1062 | 0 | if (!buf) |
1063 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY); |
1064 | | |
1065 | 0 | r = sc_asn1_sig_value_sequence_to_rs(ctx, data, datalen, buf, buflen); |
1066 | 0 | if (r < 0) { |
1067 | 0 | free(buf); |
1068 | 0 | sc_log(ctx, "Failed to convert Sig-Value to the raw RS format"); |
1069 | 0 | return r; |
1070 | 0 | } |
1071 | | |
1072 | 0 | memmove(data, buf, buflen); |
1073 | 0 | free(buf); |
1074 | 0 | return (int)buflen; |
1075 | 0 | } |
1076 | | /* MyEID cards before version 4.5 do not support RAW RSA signature for 2048 bit RSA keys. |
1077 | | * (Source: MyEID reference manual 2.1.4) |
1078 | | * |
1079 | | * This function uses decipher operation for calculating RAW 2048 bit signature. */ |
1080 | | static int |
1081 | | myeid_compute_raw_2048_signature(struct sc_card *card, const u8 * data, size_t datalen, |
1082 | | u8 * out, size_t outlen) |
1083 | 22 | { |
1084 | 22 | int r; |
1085 | 22 | struct sc_context *ctx; |
1086 | 22 | struct myeid_private_data *priv; |
1087 | 22 | struct sc_apdu apdu; |
1088 | 22 | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1089 | 22 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1090 | 22 | sc_security_env_t env; |
1091 | | |
1092 | 22 | ctx = card->ctx; |
1093 | 22 | LOG_FUNC_CALLED(ctx); |
1094 | | |
1095 | 22 | priv = (myeid_private_data_t *) card->drv_data; |
1096 | | |
1097 | | /* security env change - use DECIPHER operation */ |
1098 | 22 | memcpy(&env, priv->sec_env, sizeof(sc_security_env_t)); |
1099 | 22 | env.flags |= SC_SEC_ENV_ALG_REF_PRESENT; |
1100 | 22 | env.flags |= SC_SEC_ENV_FILE_REF_PRESENT; |
1101 | 22 | env.flags |= SC_SEC_ENV_KEY_REF_PRESENT; |
1102 | 22 | env.operation = SC_SEC_OPERATION_DECIPHER; |
1103 | 22 | myeid_set_security_env_rsa(card, &env, 0); |
1104 | | |
1105 | 22 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x80, 0x86); |
1106 | 22 | apdu.resp = rbuf; |
1107 | 22 | apdu.resplen = sizeof(rbuf); |
1108 | 22 | apdu.le = 0; /* there is no response to 1st part of data */ |
1109 | | |
1110 | | /* prepare 1st part of data */ |
1111 | 22 | sbuf[0] = 0x81; |
1112 | 22 | memcpy(sbuf + 1, data, datalen / 2); |
1113 | 22 | apdu.lc = datalen / 2 + 1; |
1114 | 22 | apdu.datalen = apdu.lc; |
1115 | 22 | apdu.data = sbuf; |
1116 | | |
1117 | 22 | r = sc_transmit_apdu(card, &apdu); |
1118 | 22 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1119 | 21 | if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { |
1120 | | /* prepare 2nd part of data */ |
1121 | 13 | sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86); |
1122 | 13 | apdu.resp = rbuf; |
1123 | 13 | apdu.resplen = sizeof(rbuf); |
1124 | 13 | apdu.le = datalen; |
1125 | 13 | sbuf[0] = 0x82; |
1126 | 13 | memcpy(sbuf + 1, data + datalen / 2, datalen / 2); |
1127 | 13 | apdu.lc = datalen / 2 + 1; |
1128 | 13 | apdu.datalen = apdu.lc; |
1129 | 13 | apdu.data = sbuf; |
1130 | | |
1131 | 13 | r = sc_transmit_apdu(card, &apdu); |
1132 | 13 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1133 | | |
1134 | 12 | if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { |
1135 | 2 | size_t len = apdu.resplen > outlen ? outlen : apdu.resplen; |
1136 | 2 | memcpy(out, apdu.resp, len); |
1137 | 2 | LOG_FUNC_RETURN(card->ctx, (int)len); |
1138 | 2 | } |
1139 | 12 | } |
1140 | 18 | LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2)); |
1141 | 18 | } |
1142 | | |
1143 | | static int |
1144 | | myeid_compute_signature(struct sc_card *card, const u8 * data, size_t datalen, |
1145 | | u8 * out, size_t outlen) |
1146 | 36 | { |
1147 | 36 | struct sc_context *ctx; |
1148 | 36 | struct sc_apdu apdu; |
1149 | 36 | u8 rbuf[MYEID_MAX_EXT_APDU_BUFFER_SIZE]; |
1150 | 36 | u8 sbuf[MYEID_MAX_EXT_APDU_BUFFER_SIZE]; |
1151 | 36 | struct myeid_private_data* priv; |
1152 | 36 | int r; |
1153 | 36 | size_t field_length = 0; |
1154 | 36 | size_t pad_chars = 0; |
1155 | | |
1156 | | |
1157 | 36 | assert(card != NULL && data != NULL && out != NULL); |
1158 | 36 | ctx = card->ctx; |
1159 | 36 | LOG_FUNC_CALLED(ctx); |
1160 | | |
1161 | 36 | priv = (myeid_private_data_t*) card->drv_data; |
1162 | 36 | sc_log(ctx, "key type %lu, key length %lu", priv->sec_env->algorithm, priv->sec_env->algorithm_ref); |
1163 | | |
1164 | 36 | if (priv->sec_env->algorithm == SC_ALGORITHM_EC ) { |
1165 | |
|
1166 | 0 | field_length = priv->sec_env->algorithm_ref; |
1167 | | |
1168 | | /* pad with zeros if needed */ |
1169 | 0 | if (datalen < BYTES4BITS(field_length)) { |
1170 | 0 | pad_chars = BYTES4BITS(field_length) - datalen; |
1171 | |
|
1172 | 0 | memset(sbuf, 0, pad_chars); |
1173 | 0 | } |
1174 | 0 | } |
1175 | | |
1176 | 36 | if ((datalen + pad_chars) > sizeof(sbuf)) |
1177 | 36 | LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS); |
1178 | | |
1179 | 36 | if (priv->sec_env->algorithm == SC_ALGORITHM_RSA && datalen == 256 && !priv->cap_chaining) |
1180 | 22 | return myeid_compute_raw_2048_signature(card, data, datalen, out, outlen); |
1181 | | |
1182 | | /* INS: 0x2A PERFORM SECURITY OPERATION |
1183 | | * P1: 0x9E Resp: Digital Signature |
1184 | | * P2: 0x9A Cmd: Input for Digital Signature */ |
1185 | 14 | sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0x9A); |
1186 | 14 | apdu.flags |= SC_APDU_FLAGS_CHAINING; |
1187 | 14 | apdu.resp = rbuf; |
1188 | 14 | apdu.resplen = sizeof(rbuf); |
1189 | 14 | apdu.le = 256; |
1190 | 14 | memcpy(sbuf + pad_chars, data, datalen); |
1191 | 14 | apdu.lc = datalen + pad_chars; |
1192 | 14 | apdu.datalen = datalen + pad_chars; |
1193 | | |
1194 | 14 | apdu.data = sbuf; |
1195 | 14 | r = sc_transmit_apdu(card, &apdu); |
1196 | 14 | LOG_TEST_RET(ctx, r, "APDU transmit failed"); |
1197 | 11 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1198 | 11 | LOG_TEST_RET(ctx, r, "compute_signature failed"); |
1199 | | |
1200 | 4 | if (priv->sec_env->algorithm == SC_ALGORITHM_EC) { |
1201 | 0 | r = myeid_convert_ec_signature(ctx, priv->sec_env->algorithm_ref, apdu.resp, apdu.resplen); |
1202 | 0 | LOG_TEST_RET(ctx, r, "compute_signature convert signature failed"); |
1203 | 0 | apdu.resplen = r; |
1204 | 0 | } |
1205 | | |
1206 | 4 | if (apdu.resplen > outlen) |
1207 | 4 | LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); |
1208 | | |
1209 | 4 | memcpy(out, apdu.resp, apdu.resplen); |
1210 | 4 | LOG_FUNC_RETURN(ctx, (int)apdu.resplen); |
1211 | 4 | } |
1212 | | |
1213 | | |
1214 | | /* takes other party's public key as input, performs ECDH key derivation and returns the shared secret in [out]. */ |
1215 | | int myeid_ecdh_derive(struct sc_card *card, const u8* pubkey, size_t pubkey_len, u8* out, size_t outlen) |
1216 | 0 | { |
1217 | | |
1218 | | /* MyEID uses GENERAL AUTHENTICATE ISO command for ECDH */ |
1219 | |
|
1220 | 0 | struct sc_apdu apdu; |
1221 | 0 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1222 | 0 | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1223 | |
|
1224 | 0 | int r; |
1225 | 0 | size_t ext_len_bytes; |
1226 | |
|
1227 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x86, 0x00, 0x00); |
1228 | |
|
1229 | 0 | apdu.resp = rbuf; |
1230 | 0 | apdu.resplen = sizeof(rbuf); |
1231 | | |
1232 | | /* Fill in "Data objects in dynamic authentication template" (tag 0x7C) structure |
1233 | | * |
1234 | | * TODO: encode the structure using OpenSC's ASN1-functions. |
1235 | | * |
1236 | | * Size of the structure depends on key length. With 521 bit keys two bytes are needed for defining length of a point. |
1237 | | */ |
1238 | |
|
1239 | 0 | sbuf[0] = 0x7C; |
1240 | 0 | ext_len_bytes = 0; |
1241 | |
|
1242 | 0 | if (pubkey_len > 127) |
1243 | 0 | { |
1244 | 0 | sbuf[1] = 0x81; |
1245 | 0 | sbuf[2] = (u8) (pubkey_len + 3); |
1246 | 0 | sbuf[3] = 0x85; |
1247 | 0 | sbuf[4] = 0x81; |
1248 | 0 | sbuf[5] = (u8) (pubkey_len); |
1249 | 0 | ext_len_bytes = 2; |
1250 | 0 | } |
1251 | 0 | else |
1252 | 0 | { |
1253 | 0 | sbuf[1] = pubkey_len + 2; |
1254 | 0 | sbuf[2] = 0x85; |
1255 | 0 | sbuf[3] = pubkey_len; |
1256 | 0 | } |
1257 | |
|
1258 | 0 | memcpy(&sbuf[4 + ext_len_bytes], pubkey, pubkey_len); |
1259 | |
|
1260 | 0 | apdu.lc = pubkey_len + 4 + ext_len_bytes; |
1261 | 0 | apdu.le = pubkey_len / 2; |
1262 | 0 | apdu.datalen = apdu.lc; |
1263 | 0 | apdu.data = sbuf; |
1264 | |
|
1265 | 0 | r = sc_transmit_apdu(card, &apdu); |
1266 | |
|
1267 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed."); |
1268 | | |
1269 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1270 | 0 | LOG_TEST_RET(card->ctx, r, "ECDH operation failed - GENERAL AUTHENTICATE returned error."); |
1271 | | |
1272 | 0 | if (outlen < apdu.resplen) |
1273 | 0 | { |
1274 | 0 | r = SC_ERROR_BUFFER_TOO_SMALL; |
1275 | 0 | LOG_TEST_RET(card->ctx, r, "Buffer too small to hold shared secret."); |
1276 | 0 | } |
1277 | | |
1278 | 0 | memcpy(out, rbuf, apdu.resplen); |
1279 | |
|
1280 | 0 | LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen); |
1281 | 0 | } |
1282 | | |
1283 | | static int myeid_transmit_decipher_pi_split(struct sc_card *card, struct sc_apdu *apdu, u8 *sbuf) |
1284 | 13 | { |
1285 | | /* MyEID before 4.5.x does not support APDU chaining. The payload |
1286 | | * is split to two regular APDUs and Padding Indicator field is used to |
1287 | | * describe which slice it is. */ |
1288 | 13 | size_t crgram_len = apdu->lc - 1; |
1289 | 13 | size_t crgram_half = crgram_len / 2; |
1290 | 13 | size_t resplen = apdu->resplen; |
1291 | 13 | unsigned char *resp = apdu->resp; |
1292 | 13 | int r; |
1293 | | |
1294 | 13 | LOG_FUNC_CALLED(card->ctx); |
1295 | | |
1296 | | /* Send 1st part, no response */ |
1297 | 13 | apdu->cse = SC_APDU_CASE_3_SHORT; |
1298 | 13 | apdu->data = &sbuf[0]; |
1299 | 13 | apdu->datalen = apdu->lc = crgram_half + 1; |
1300 | 13 | apdu->resp = 0; |
1301 | 13 | apdu->resplen = 0; |
1302 | 13 | apdu->le = 0; |
1303 | 13 | sbuf[0] = 0x81; /* Padding Indicator, 0x81 = First half */ |
1304 | | |
1305 | 13 | r = sc_transmit_apdu(card, apdu); |
1306 | 13 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1307 | 12 | if (apdu->sw1 != 0x90 || apdu->sw2 != 0x00) |
1308 | 9 | return 0; |
1309 | | |
1310 | | /* Send 2nd part, expect response */ |
1311 | 3 | apdu->cse = resplen ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT; |
1312 | 3 | apdu->data = &sbuf[crgram_half]; |
1313 | 3 | apdu->datalen = apdu->lc = crgram_len - crgram_half + 1; |
1314 | 3 | apdu->resp = resp; |
1315 | 3 | apdu->resplen = resplen; |
1316 | 3 | apdu->le = resplen ? MIN(card->max_recv_size, crgram_len) : 0; |
1317 | 3 | sbuf[crgram_half] = 0x82; /* Padding Indicator, 0x82 = Second half */ |
1318 | | |
1319 | 3 | r = sc_transmit_apdu(card, apdu); |
1320 | 3 | LOG_FUNC_RETURN(card->ctx, r); |
1321 | 3 | } |
1322 | | |
1323 | | static int myeid_transmit_decipher(struct sc_card *card, u8 p1, u8 p2, |
1324 | | const u8 * crgram, size_t crgram_len, u8 * out, size_t outlen) |
1325 | 103 | { |
1326 | 103 | myeid_private_data_t *priv = card->drv_data; |
1327 | 103 | struct sc_apdu apdu; |
1328 | 103 | u8 rbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; |
1329 | 103 | u8 sbuf[SC_MAX_EXT_APDU_BUFFER_SIZE]; |
1330 | 103 | int r; |
1331 | | |
1332 | 103 | LOG_FUNC_CALLED(card->ctx); |
1333 | | |
1334 | | /* INS: 0x2A PERFORM SECURITY OPERATION |
1335 | | * P1: 0x00 Resp: No response (unwrapping) |
1336 | | * P1: 0x80 Resp: Plain value |
1337 | | * P2: 0x84 Cmd: Cryptogram (no padding byte) |
1338 | | * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram */ |
1339 | 103 | sc_format_apdu(card, &apdu, p1 ? SC_APDU_CASE_4_SHORT : SC_APDU_CASE_3_SHORT, 0x2A, p1, p2); |
1340 | 103 | if (p2 == 0x86) { |
1341 | 103 | if (crgram_len+1 > sizeof(sbuf)) |
1342 | 103 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
1343 | 103 | sbuf[0] = 0; /* Padding indicator: 0x00 = No further indication */ |
1344 | 103 | memcpy(sbuf + 1, crgram, crgram_len); |
1345 | 103 | apdu.data = sbuf; |
1346 | 103 | apdu.datalen = apdu.lc = crgram_len + 1; |
1347 | 103 | } else { |
1348 | 0 | apdu.data = crgram; |
1349 | 0 | apdu.datalen = apdu.lc = crgram_len; |
1350 | 0 | } |
1351 | 103 | if (p1 != 0x00) { |
1352 | 103 | apdu.resp = rbuf; |
1353 | 103 | apdu.resplen = sizeof(rbuf); |
1354 | 103 | apdu.le = MIN(card->max_recv_size, crgram_len); |
1355 | 103 | } |
1356 | | |
1357 | | /* In MyEID 4.5.x, unwrapping with 2K RSA using APDU chaining doesn't work properly. Split the APDU in the old way in this case. */ |
1358 | 103 | if (p2 == 0x86 && crgram_len == 256 && priv && (!priv->cap_chaining || (card->version.fw_major == 45 && priv->sec_env != NULL && priv->sec_env->operation == SC_SEC_OPERATION_UNWRAP))) { |
1359 | 13 | r = myeid_transmit_decipher_pi_split(card, &apdu, sbuf); |
1360 | 90 | } else { |
1361 | 90 | apdu.flags |= SC_APDU_FLAGS_CHAINING; |
1362 | 90 | r = sc_transmit_apdu(card, &apdu); |
1363 | 90 | } |
1364 | 103 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1365 | | |
1366 | 77 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1367 | 77 | LOG_TEST_RET(card->ctx, r, "DECIPHER returned error"); |
1368 | | |
1369 | 55 | if (out && outlen) { |
1370 | 55 | outlen = MIN(apdu.resplen, outlen); |
1371 | 55 | memcpy(out, apdu.resp, outlen); |
1372 | 55 | } else { |
1373 | 0 | outlen = 0; |
1374 | 0 | } |
1375 | 55 | LOG_FUNC_RETURN(card->ctx, (int)outlen); |
1376 | 55 | } |
1377 | | |
1378 | | static int myeid_decipher(struct sc_card *card, const u8 * crgram, |
1379 | | size_t crgram_len, u8 * out, size_t outlen) |
1380 | 103 | { |
1381 | 103 | int r; |
1382 | 103 | myeid_private_data_t* priv; |
1383 | | |
1384 | 103 | LOG_FUNC_CALLED(card->ctx); |
1385 | | |
1386 | 103 | assert(card != NULL && crgram != NULL && out != NULL); |
1387 | | |
1388 | 103 | priv = (myeid_private_data_t*) card->drv_data; |
1389 | | |
1390 | 103 | if (priv->sec_env && priv->sec_env->algorithm == SC_ALGORITHM_EC |
1391 | 0 | && priv->sec_env->operation == SC_SEC_OPERATION_DERIVE |
1392 | 0 | && priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDH_CDH_RAW) |
1393 | 0 | { |
1394 | 0 | r = myeid_ecdh_derive(card, crgram, crgram_len, out, outlen); |
1395 | 0 | priv->sec_env = NULL; /* clear after operation */ |
1396 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1397 | 0 | } |
1398 | | |
1399 | 103 | r = myeid_transmit_decipher(card, 0x80, 0x86, crgram, crgram_len, out, outlen); |
1400 | 103 | LOG_FUNC_RETURN(card->ctx, r); |
1401 | 103 | } |
1402 | | |
1403 | | |
1404 | | static int myeid_wrap_key(struct sc_card *card, u8 *out, size_t outlen) |
1405 | 0 | { |
1406 | 0 | struct sc_context *ctx; |
1407 | 0 | struct sc_apdu apdu; |
1408 | 0 | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1409 | 0 | int r; |
1410 | |
|
1411 | 0 | assert(card != NULL); |
1412 | 0 | ctx = card->ctx; |
1413 | 0 | LOG_FUNC_CALLED(ctx); |
1414 | | |
1415 | | /* INS: 0x2A PERFORM SECURITY OPERATION |
1416 | | P1: 0x84 Resp: Return a cryptogram |
1417 | | * P2: 0x00 The data field is absent */ |
1418 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, 0x84, 0x00); |
1419 | 0 | apdu.resp = rbuf; |
1420 | 0 | apdu.resplen = sizeof(rbuf); |
1421 | 0 | apdu.le = sizeof(rbuf) <= 256 ? sizeof(rbuf) : 256; |
1422 | 0 | apdu.lc = 0; |
1423 | |
|
1424 | 0 | r = sc_transmit_apdu(card, &apdu); |
1425 | 0 | LOG_TEST_RET(ctx, r, "APDU transmit failed"); |
1426 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1427 | 0 | LOG_TEST_RET(ctx, r, "wrap key failed"); |
1428 | | |
1429 | 0 | if (apdu.resplen <= outlen && out != NULL) |
1430 | 0 | memcpy(out, apdu.resp, apdu.resplen); |
1431 | |
|
1432 | 0 | LOG_FUNC_RETURN(ctx, (int)apdu.resplen); |
1433 | 0 | } |
1434 | | |
1435 | | static int myeid_unwrap_key(struct sc_card *card, const u8 *crgram, size_t crgram_len) |
1436 | 0 | { |
1437 | 0 | myeid_private_data_t* priv; |
1438 | 0 | u8 p2 = 0x86; /* init P2 for asymmetric crypto by default.*/ |
1439 | 0 | int r; |
1440 | |
|
1441 | 0 | if (card == NULL || crgram == NULL) |
1442 | 0 | return SC_ERROR_INVALID_ARGUMENTS; |
1443 | 0 | priv = card->drv_data; |
1444 | |
|
1445 | 0 | LOG_FUNC_CALLED(card->ctx); |
1446 | |
|
1447 | 0 | if (crgram_len > MYEID_MAX_RSA_KEY_LEN / 8) |
1448 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS); |
1449 | | |
1450 | 0 | if (priv && priv->sec_env) |
1451 | 0 | { |
1452 | 0 | if (priv->sec_env->algorithm == SC_ALGORITHM_AES || |
1453 | 0 | priv->sec_env->algorithm == SC_ALGORITHM_3DES || |
1454 | 0 | priv->sec_env->algorithm == SC_ALGORITHM_DES) |
1455 | 0 | p2 = 0x84; |
1456 | 0 | } |
1457 | |
|
1458 | 0 | if (p2 == 0x84 && crgram_len > MYEID_MAX_APDU_DATA_LEN) |
1459 | 0 | LOG_TEST_RET(card->ctx, SC_ERROR_WRONG_LENGTH, "Unwrapping symmetric data longer that 255 bytes is not supported\n"); |
1460 | | |
1461 | | /* INS: 0x2A PERFORM SECURITY OPERATION |
1462 | | * P1: 0x00 Do not expect response - the deciphered data will be placed into the target key EF. |
1463 | | * P2: 0x86 Cmd: Padding indicator byte followed by cryptogram |
1464 | | * P2: 0x84 Cmd: AES/3DES Cryptogram (plain value encoded in BER-TLV DO, but not including SM DOs) */ |
1465 | 0 | r = myeid_transmit_decipher(card, 0x00, p2, crgram, crgram_len, 0, 0); |
1466 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1467 | 0 | } |
1468 | | |
1469 | | |
1470 | | /* Write internal data, e.g. add default pin-records to pin */ |
1471 | | static int myeid_putdata(struct sc_card *card, struct sc_cardctl_myeid_data_obj* data_obj) |
1472 | 0 | { |
1473 | 0 | int r; |
1474 | 0 | struct sc_apdu apdu; |
1475 | |
|
1476 | 0 | LOG_FUNC_CALLED(card->ctx); |
1477 | |
|
1478 | 0 | memset(&apdu, 0, sizeof(apdu)); |
1479 | 0 | apdu.cse = SC_APDU_CASE_3_SHORT; |
1480 | 0 | apdu.cla = 0x00; |
1481 | 0 | apdu.ins = 0xDA; |
1482 | 0 | apdu.p1 = data_obj->P1; |
1483 | 0 | apdu.p2 = data_obj->P2; |
1484 | 0 | apdu.lc = data_obj->DataLen; |
1485 | 0 | apdu.datalen = data_obj->DataLen; |
1486 | 0 | apdu.data = data_obj->Data; |
1487 | |
|
1488 | 0 | r = sc_transmit_apdu(card, &apdu); |
1489 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1490 | | |
1491 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1492 | 0 | LOG_TEST_RET(card->ctx, r, "PUT_DATA returned error"); |
1493 | | |
1494 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1495 | 0 | } |
1496 | | |
1497 | | /* Read internal data, e.g. get RSA public key */ |
1498 | | static int myeid_getdata(struct sc_card *card, struct sc_cardctl_myeid_data_obj* data_obj) |
1499 | 0 | { |
1500 | 0 | int r; |
1501 | 0 | struct sc_apdu apdu; |
1502 | |
|
1503 | 0 | LOG_FUNC_CALLED(card->ctx); |
1504 | |
|
1505 | 0 | memset(&apdu, 0, sizeof(apdu)); |
1506 | 0 | apdu.cse = SC_APDU_CASE_2_SHORT; |
1507 | 0 | apdu.cla = 0x00; |
1508 | 0 | apdu.ins = 0xCA; /* GET DATA */ |
1509 | 0 | apdu.p1 = data_obj->P1; |
1510 | 0 | apdu.p2 = data_obj->P2; |
1511 | 0 | apdu.lc = 0; |
1512 | 0 | apdu.datalen = 0; |
1513 | 0 | apdu.data = data_obj->Data; |
1514 | |
|
1515 | 0 | apdu.le = card->max_recv_size; |
1516 | 0 | apdu.resp = data_obj->Data; |
1517 | 0 | apdu.resplen = data_obj->DataLen; |
1518 | |
|
1519 | 0 | r = sc_transmit_apdu(card, &apdu); |
1520 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1521 | | |
1522 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1523 | 0 | LOG_TEST_RET(card->ctx, r, "GET_DATA returned error"); |
1524 | | |
1525 | 0 | if (apdu.resplen > data_obj->DataLen) |
1526 | 0 | r = SC_ERROR_WRONG_LENGTH; |
1527 | 0 | else |
1528 | 0 | data_obj->DataLen = apdu.resplen; |
1529 | |
|
1530 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1531 | 0 | } |
1532 | | |
1533 | | static int myeid_loadkey(sc_card_t *card, unsigned mode, u8 *value, size_t value_len) |
1534 | 0 | { |
1535 | 0 | myeid_private_data_t *priv = (myeid_private_data_t *) card->drv_data; |
1536 | 0 | sc_apdu_t apdu; |
1537 | 0 | u8 sbuf[MYEID_MAX_EXT_APDU_BUFFER_SIZE]; |
1538 | 0 | int r; |
1539 | |
|
1540 | 0 | LOG_FUNC_CALLED(card->ctx); |
1541 | 0 | if (value_len == 0 || value == NULL) |
1542 | 0 | return 0; |
1543 | | |
1544 | 0 | if (mode == LOAD_KEY_MODULUS && value_len == 256 && !priv->cap_chaining) |
1545 | 0 | { |
1546 | 0 | mode = 0x88; |
1547 | 0 | memset(&apdu, 0, sizeof(apdu)); |
1548 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDA, 0x01, mode); |
1549 | |
|
1550 | 0 | apdu.cla = 0x00; |
1551 | 0 | apdu.data = value; |
1552 | 0 | apdu.datalen = 128; |
1553 | 0 | apdu.lc = 128; |
1554 | |
|
1555 | 0 | r = sc_transmit_apdu(card, &apdu); |
1556 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1557 | | |
1558 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1559 | 0 | LOG_TEST_RET(card->ctx, r, "LOAD KEY returned error"); |
1560 | | |
1561 | 0 | mode = 0x89; |
1562 | 0 | value += 128; |
1563 | 0 | value_len -= 128; |
1564 | 0 | } |
1565 | 0 | else if ((mode & 0xff00) == 0 && mode != LOAD_KEY_PUBLIC_EXPONENT && |
1566 | 0 | value[0] != 0x00) |
1567 | 0 | { |
1568 | | /* RSA components needing leading zero byte */ |
1569 | 0 | sbuf[0] = 0x0; |
1570 | 0 | memcpy(&sbuf[1], value, value_len); |
1571 | 0 | value = sbuf; |
1572 | 0 | value_len ++; |
1573 | 0 | } |
1574 | | |
1575 | 0 | memset(&apdu, 0, sizeof(apdu)); |
1576 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDA, 0x01, mode & 0xFF); |
1577 | 0 | apdu.flags = SC_APDU_FLAGS_CHAINING; |
1578 | 0 | apdu.cla = 0x00; |
1579 | 0 | apdu.data = value; |
1580 | 0 | apdu.datalen = value_len; |
1581 | 0 | apdu.lc = value_len; |
1582 | |
|
1583 | 0 | r = sc_transmit_apdu(card, &apdu); |
1584 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1585 | | |
1586 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1587 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1588 | 0 | } |
1589 | | |
1590 | | /* Generate or store a key */ |
1591 | | static int myeid_generate_store_key(struct sc_card *card, |
1592 | | struct sc_cardctl_myeid_gen_store_key_info *data) |
1593 | 0 | { |
1594 | 0 | struct sc_apdu apdu; |
1595 | 0 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1596 | 0 | int r=0,len; |
1597 | |
|
1598 | 0 | LOG_FUNC_CALLED(card->ctx); |
1599 | | /* Setup key-generation parameters */ |
1600 | 0 | if (data->op_type == OP_TYPE_GENERATE) |
1601 | 0 | { |
1602 | 0 | len = 0; |
1603 | 0 | memset(&apdu, 0, sizeof(apdu)); |
1604 | |
|
1605 | 0 | if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA) |
1606 | 0 | { |
1607 | 0 | sbuf[len++] = 0x30; |
1608 | 0 | sbuf[len++] = 0x05; |
1609 | 0 | sbuf[len++] = 0x81; |
1610 | 0 | sbuf[len++] = data->pubexp_len; |
1611 | |
|
1612 | 0 | memcpy(sbuf + len, data->pubexp, data->pubexp_len); |
1613 | 0 | len += data->pubexp_len; |
1614 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00); |
1615 | 0 | apdu.data = sbuf; |
1616 | 0 | } |
1617 | 0 | else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { |
1618 | |
|
1619 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x46, 0x00, 0x00); |
1620 | |
|
1621 | 0 | apdu.data = NULL; |
1622 | 0 | apdu.resp = sbuf; |
1623 | 0 | apdu.resplen = 0x00; |
1624 | 0 | apdu.le = 0x00; |
1625 | 0 | } |
1626 | |
|
1627 | 0 | apdu.cla = 0x00; |
1628 | 0 | apdu.datalen = len; |
1629 | 0 | apdu.lc = len; |
1630 | |
|
1631 | 0 | r = sc_transmit_apdu(card, &apdu); |
1632 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1633 | | |
1634 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1635 | 0 | LOG_TEST_RET(card->ctx, r, "GENERATE_KEY returned error"); |
1636 | 0 | } |
1637 | 0 | else |
1638 | 0 | { |
1639 | 0 | if(data->key_type == SC_CARDCTL_MYEID_KEY_RSA) |
1640 | 0 | { |
1641 | 0 | if((r=myeid_loadkey(card, LOAD_KEY_PRIME_P, |
1642 | 0 | data->primep, data->primep_len)) >= 0 && |
1643 | 0 | (r=myeid_loadkey(card, LOAD_KEY_PRIME_Q, |
1644 | 0 | data->primeq, data->primeq_len)) >= 0 && |
1645 | 0 | (r=myeid_loadkey(card, LOAD_KEY_DP1, |
1646 | 0 | data->dp1, data->dp1_len)) >= 0 && |
1647 | 0 | (r=myeid_loadkey(card, LOAD_KEY_DQ1, |
1648 | 0 | data->dq1, data->dq1_len)) >= 0 && |
1649 | 0 | (r=myeid_loadkey(card, LOAD_KEY_INVQ, |
1650 | 0 | data->invq, data->invq_len)) >= 0 && |
1651 | 0 | (r=myeid_loadkey(card, LOAD_KEY_MODULUS, |
1652 | 0 | data->mod, data->key_len_bits)) >= 0 && |
1653 | 0 | (r=myeid_loadkey(card, LOAD_KEY_PUBLIC_EXPONENT, |
1654 | 0 | data->pubexp, data->pubexp_len)) >= 0) |
1655 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1656 | 0 | } |
1657 | 0 | else if(data->key_type == SC_CARDCTL_MYEID_KEY_EC) { |
1658 | 0 | if((r = myeid_loadkey(card, LOAD_KEY_EC_PRIVATE, data->d, |
1659 | 0 | data->d_len)) >= 0 && |
1660 | 0 | (r = myeid_loadkey(card, LOAD_KEY_EC_PUBLIC, data->ecpublic_point, |
1661 | 0 | data->ecpublic_point_len)) >= 0) |
1662 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1663 | 0 | } |
1664 | 0 | else if(data->key_type == SC_CARDCTL_MYEID_KEY_AES || |
1665 | 0 | data->key_type == SC_CARDCTL_MYEID_KEY_DES) { |
1666 | 0 | if((r = myeid_loadkey(card, LOAD_KEY_SYMMETRIC, data->d, |
1667 | 0 | data->d_len)) >= 0) |
1668 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1669 | 0 | } |
1670 | 0 | } |
1671 | | |
1672 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1673 | 0 | } |
1674 | | |
1675 | | static int myeid_activate_card(struct sc_card *card) |
1676 | 0 | { |
1677 | 0 | int r; |
1678 | 0 | u8 sbuf[] ="\xA0\x00\x00\x00\x63\x50\x4B\x43\x53\x2D\x31\x35"; |
1679 | 0 | sc_apdu_t apdu; |
1680 | |
|
1681 | 0 | LOG_FUNC_CALLED(card->ctx); |
1682 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x44, 0x04, 0x00); |
1683 | 0 | apdu.cla = 0x00; |
1684 | 0 | apdu.data = sbuf; |
1685 | 0 | apdu.datalen = 0x0C; |
1686 | 0 | apdu.lc = 0x0C; |
1687 | |
|
1688 | 0 | r = sc_transmit_apdu(card, &apdu); |
1689 | 0 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1690 | | |
1691 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
1692 | 0 | LOG_TEST_RET(card->ctx, r, "ACTIVATE_APPLET returned error"); |
1693 | | |
1694 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1695 | 0 | } |
1696 | | |
1697 | | static int myeid_get_info(struct sc_card *card, u8 *rbuf, size_t buflen) |
1698 | 577 | { |
1699 | 577 | sc_apdu_t apdu; |
1700 | 577 | int r; |
1701 | | |
1702 | 577 | LOG_FUNC_CALLED(card->ctx); |
1703 | | |
1704 | 577 | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xA0); |
1705 | 577 | apdu.resp = rbuf; |
1706 | 577 | apdu.resplen = buflen; |
1707 | 577 | apdu.le = buflen; |
1708 | | |
1709 | 577 | r = sc_transmit_apdu(card, &apdu); |
1710 | 577 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1711 | | |
1712 | 554 | if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) |
1713 | 274 | return SC_ERROR_INTERNAL; |
1714 | | |
1715 | 280 | if (apdu.resplen != 20) |
1716 | 31 | { |
1717 | 31 | sc_log(card->ctx, "Unexpected response to GET DATA (applet info)"); |
1718 | 31 | return SC_ERROR_INTERNAL; |
1719 | 31 | } |
1720 | | |
1721 | | /* store the applet version */ |
1722 | 249 | card->version.fw_major = rbuf[5] * 10 + rbuf[6]; |
1723 | 249 | card->version.fw_minor = rbuf[7]; |
1724 | | /* add version to name */ |
1725 | 249 | snprintf(card_name_buf, sizeof(card_name_buf), |
1726 | 249 | "%s %d.%d.%d", card->name, rbuf[5], rbuf[6], rbuf[7]); |
1727 | 249 | card->name = card_name_buf; |
1728 | | |
1729 | 249 | LOG_FUNC_RETURN(card->ctx, r); |
1730 | 249 | } |
1731 | | |
1732 | | static int myeid_get_serialnr(sc_card_t *card, sc_serial_number_t *serial) |
1733 | 181 | { |
1734 | 181 | int r; |
1735 | 181 | u8 rbuf[256]; |
1736 | | |
1737 | 181 | LOG_FUNC_CALLED(card->ctx); |
1738 | | |
1739 | | /* if number cached, get it |
1740 | | if(card->serialnr.value) { |
1741 | | memcpy(serial, &card->serialnr, sizeof(*serial)); |
1742 | | LOG_FUNC_RETURN(card->ctx, r); |
1743 | | }*/ |
1744 | | |
1745 | | /* get number from card */ |
1746 | 181 | r = myeid_get_info(card, rbuf, sizeof(rbuf)); |
1747 | 181 | LOG_TEST_RET(card->ctx, r, "Get applet info failed"); |
1748 | | |
1749 | | /* cache serial number */ |
1750 | 10 | memcpy(card->serialnr.value, &rbuf[8], 10); |
1751 | 10 | card->serialnr.len = 10; |
1752 | | |
1753 | | /* copy and return serial number */ |
1754 | 10 | memcpy(serial, &card->serialnr, sizeof(*serial)); |
1755 | | |
1756 | 10 | LOG_FUNC_RETURN(card->ctx, r); |
1757 | 10 | } |
1758 | | |
1759 | | static int |
1760 | | myeid_get_change_counter(sc_card_t *card, size_t *change_counter) |
1761 | 48 | { |
1762 | 48 | int r; |
1763 | 48 | u8 rbuf[256]; |
1764 | | |
1765 | 48 | LOG_FUNC_CALLED(card->ctx); |
1766 | | |
1767 | | /* get change counter from card */ |
1768 | 48 | r = myeid_get_info(card, rbuf, sizeof(rbuf)); |
1769 | 48 | LOG_TEST_RET(card->ctx, r, "Get applet info failed"); |
1770 | | |
1771 | 7 | *change_counter = rbuf[18] * 256 + rbuf[19]; |
1772 | | |
1773 | 7 | LOG_FUNC_RETURN(card->ctx, r); |
1774 | 7 | } |
1775 | | |
1776 | | /* |
1777 | | Get information of features that the card supports. MyEID 4.x cards are available on different |
1778 | | hardware and maximum key sizes cannot be determined simply from the version number anymore. |
1779 | | */ |
1780 | | static int myeid_get_card_caps(struct sc_card *card, myeid_card_caps_t* card_caps) |
1781 | 99 | { |
1782 | 99 | sc_apdu_t apdu; |
1783 | 99 | int r; |
1784 | 99 | unsigned char rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1785 | | |
1786 | 99 | LOG_FUNC_CALLED(card->ctx); |
1787 | | |
1788 | 99 | sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0xAA); |
1789 | 99 | apdu.resp = rbuf; |
1790 | 99 | apdu.resplen = sizeof(myeid_card_caps_t); |
1791 | 99 | apdu.le = sizeof(myeid_card_caps_t); |
1792 | | |
1793 | 99 | r = sc_transmit_apdu(card, &apdu); |
1794 | 99 | LOG_TEST_RET(card->ctx, r, "APDU transmit failed"); |
1795 | | |
1796 | 98 | if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00) |
1797 | 46 | return SC_ERROR_INTERNAL; |
1798 | | |
1799 | 52 | if (apdu.resplen < 11) { |
1800 | 1 | sc_log(card->ctx, "Unexpected response to GET DATA (MyEIC card capabilities)"); |
1801 | 1 | return SC_ERROR_INTERNAL; |
1802 | 1 | } |
1803 | | |
1804 | 51 | card_caps->card_caps_ver = rbuf[0]; |
1805 | | /* the card returns big endian values */ |
1806 | 51 | card_caps->card_supported_features = (unsigned short) rbuf[1] << 8 | rbuf[2]; |
1807 | 51 | card_caps->max_rsa_key_length = (unsigned short) rbuf[3] << 8 | rbuf[4]; |
1808 | 51 | card_caps->max_des_key_length = (unsigned short) rbuf[5] << 8 | rbuf[6]; |
1809 | 51 | card_caps->max_aes_key_length = (unsigned short) rbuf[7] << 8 | rbuf[8]; |
1810 | 51 | card_caps->max_ecc_key_length = (unsigned short) rbuf[9] << 8 | rbuf[10]; |
1811 | | |
1812 | 51 | LOG_FUNC_RETURN(card->ctx, r); |
1813 | 51 | } |
1814 | | |
1815 | | static int myeid_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr) |
1816 | 229 | { |
1817 | 229 | int r = SC_ERROR_NOT_SUPPORTED; |
1818 | 229 | LOG_FUNC_CALLED(card->ctx); |
1819 | | |
1820 | 229 | switch(cmd) { |
1821 | 0 | case SC_CARDCTL_MYEID_PUTDATA: |
1822 | 0 | r = myeid_putdata(card, |
1823 | 0 | (struct sc_cardctl_myeid_data_obj*) ptr); |
1824 | 0 | break; |
1825 | 0 | case SC_CARDCTL_MYEID_GETDATA: |
1826 | 0 | r = myeid_getdata(card, |
1827 | 0 | (struct sc_cardctl_myeid_data_obj*) ptr); |
1828 | 0 | break; |
1829 | 0 | case SC_CARDCTL_MYEID_GENERATE_STORE_KEY: |
1830 | 0 | r = myeid_generate_store_key(card, |
1831 | 0 | (struct sc_cardctl_myeid_gen_store_key_info *) ptr); |
1832 | 0 | break; |
1833 | 0 | case SC_CARDCTL_MYEID_ACTIVATE_CARD: |
1834 | 0 | r = myeid_activate_card(card); |
1835 | 0 | break; |
1836 | 181 | case SC_CARDCTL_GET_SERIALNR: |
1837 | 181 | r = myeid_get_serialnr(card, (sc_serial_number_t *)ptr); |
1838 | 181 | break; |
1839 | 48 | case SC_CARDCTL_GET_CHANGE_COUNTER: |
1840 | 48 | r = myeid_get_change_counter(card, (size_t *)ptr); |
1841 | 48 | break; |
1842 | 0 | case SC_CARDCTL_GET_DEFAULT_KEY: |
1843 | 0 | case SC_CARDCTL_LIFECYCLE_SET: |
1844 | 0 | case SC_CARDCTL_LIFECYCLE_GET: |
1845 | 0 | break; |
1846 | 229 | } |
1847 | 229 | LOG_FUNC_RETURN(card->ctx, r); |
1848 | 229 | } |
1849 | | |
1850 | | static int myeid_finish(sc_card_t * card) |
1851 | 348 | { |
1852 | 348 | struct myeid_private_data *priv = (struct myeid_private_data *) card->drv_data; |
1853 | 348 | free(priv); |
1854 | 348 | return SC_SUCCESS; |
1855 | 348 | } |
1856 | | |
1857 | | static int |
1858 | | myeid_enc_dec_sym(struct sc_card *card, const u8 *data, size_t datalen, |
1859 | | u8 *out, size_t *outlen, int decipher) |
1860 | 0 | { |
1861 | |
|
1862 | 0 | struct sc_context *ctx; |
1863 | |
|
1864 | 0 | struct sc_apdu apdu; |
1865 | 0 | u8 rbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1866 | 0 | u8 sbuf[SC_MAX_APDU_BUFFER_SIZE]; |
1867 | 0 | u8 *sdata; |
1868 | 0 | int r, padding = 0, cbc = 0; |
1869 | |
|
1870 | 0 | size_t block_size; |
1871 | 0 | size_t len, rest_len; |
1872 | 0 | size_t return_len = 0; |
1873 | |
|
1874 | 0 | size_t max_apdu_datalen; |
1875 | 0 | size_t apdu_datalen; |
1876 | |
|
1877 | 0 | assert(card != NULL); |
1878 | |
|
1879 | 0 | ctx = card->ctx; |
1880 | 0 | LOG_FUNC_CALLED(ctx); |
1881 | |
|
1882 | 0 | myeid_private_data_t *priv; |
1883 | 0 | priv = (myeid_private_data_t *)card->drv_data; |
1884 | | |
1885 | | /* How many cipher blocks will fit in the APDU. We do not use the APDU chaining |
1886 | | * mechanism from OpenSC, because we need the size of the APDU data block |
1887 | | * to match a multiple of the cipher block size */ |
1888 | |
|
1889 | 0 | max_apdu_datalen = sc_get_max_send_size(card); |
1890 | 0 | if (max_apdu_datalen > sc_get_max_recv_size(card)) |
1891 | 0 | max_apdu_datalen = sc_get_max_recv_size(card); |
1892 | |
|
1893 | 0 | if (max_apdu_datalen > SC_MAX_APDU_BUFFER_SIZE) |
1894 | 0 | max_apdu_datalen = SC_MAX_APDU_BUFFER_SIZE; |
1895 | |
|
1896 | 0 | sc_log(ctx, "algorithm %lu algorithm_flags %lx", priv->algorithm, priv->algorithm_flags); |
1897 | | |
1898 | | /* for C_Encrypt/C_EncryptUpdate/C_EncryptFinalize/C_Decrypt/C_DecryptUpdate/C_DecryptFinalize |
1899 | | * the 'outlen' is always not NULL (src/pkcs11/framework-pkcs15.c). |
1900 | | * For C_EncryptInit and C_DecrytpInit the 'outlen' is set to NULL |
1901 | | */ |
1902 | 0 | if (outlen == NULL) { |
1903 | | /* C_EncryptInit/C_DecryptInit - clear buffers */ |
1904 | 0 | sc_log(ctx, "%s (symmetric key) initialized", decipher ? "C_DecryptInit" : "C_EncryptInit"); |
1905 | 0 | priv->sym_crypt_buffer_len = 0; |
1906 | 0 | priv->sym_plain_buffer_len = 0; |
1907 | 0 | return SC_SUCCESS; |
1908 | 0 | } |
1909 | | |
1910 | 0 | switch (priv->algorithm) { |
1911 | 0 | case SC_ALGORITHM_AES: |
1912 | 0 | block_size = 16; |
1913 | 0 | if (priv->algorithm_flags & SC_ALGORITHM_AES_ECB) { |
1914 | 0 | padding = 0; |
1915 | 0 | cbc = 0; |
1916 | 0 | } else if (priv->algorithm_flags & SC_ALGORITHM_AES_CBC) { |
1917 | 0 | padding = 0; |
1918 | 0 | cbc = 1; |
1919 | 0 | } else if (priv->algorithm_flags & SC_ALGORITHM_AES_CBC_PAD) { |
1920 | 0 | padding = 1; |
1921 | 0 | cbc = 1; |
1922 | 0 | } |
1923 | 0 | break; |
1924 | 0 | default: |
1925 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED); |
1926 | 0 | } |
1927 | | |
1928 | | /* MyEID: ECB APDU must match exact cipher block size in CBC |
1929 | | * mode up to 240 bytes can be handled in one APDU |
1930 | | * round max_apdu_datalen to multiple of block_size (CBC mode) */ |
1931 | | |
1932 | 0 | if (cbc) |
1933 | 0 | max_apdu_datalen -= max_apdu_datalen % block_size; |
1934 | 0 | else |
1935 | 0 | max_apdu_datalen = block_size; |
1936 | | |
1937 | | /* Maybe we have more input data (from previous PSO operation). */ |
1938 | 0 | rest_len = priv->sym_crypt_buffer_len; |
1939 | | |
1940 | | /* no input data from application (this is C_EncryptFinalize/C_DecryptFinalize */ |
1941 | 0 | if (data == NULL) { |
1942 | 0 | if (datalen != 0) |
1943 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_LENGTH); |
1944 | 0 | if (decipher) { |
1945 | | /* C_DecryptFinalize */ |
1946 | | /* decrypted buffer size must match the block size */ |
1947 | 0 | if (priv->sym_plain_buffer_len != block_size) |
1948 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_LENGTH); |
1949 | | /* do we have any encrypted data left? */ |
1950 | 0 | if (rest_len) |
1951 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_LENGTH); |
1952 | | |
1953 | 0 | return_len = block_size; |
1954 | 0 | if (padding) { |
1955 | | /* check padding */ |
1956 | 0 | uint8_t i, pad_byte = *(priv->sym_plain_buffer + block_size - 1); |
1957 | |
|
1958 | 0 | sc_log(ctx, "Found padding byte %02x", pad_byte); |
1959 | 0 | if (pad_byte == 0 || pad_byte > block_size) |
1960 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); |
1961 | 0 | sdata = priv->sym_plain_buffer + block_size; |
1962 | 0 | for (i = 0; i < pad_byte; i++) |
1963 | 0 | if (*(--sdata) != pad_byte) |
1964 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_PADDING); |
1965 | 0 | return_len = block_size - pad_byte; |
1966 | 0 | } |
1967 | | /* application can request buffer size or actual buffer size is too small */ |
1968 | 0 | if (out == NULL) { |
1969 | 0 | *outlen = return_len; |
1970 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
1971 | 0 | } |
1972 | 0 | if (return_len > *outlen) |
1973 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); |
1974 | 0 | *outlen = return_len; |
1975 | 0 | memcpy(out, priv->sym_plain_buffer, return_len); |
1976 | 0 | sc_log(ctx, "C_DecryptFinal %zu bytes", *outlen); |
1977 | 0 | return SC_SUCCESS; |
1978 | 0 | } else { |
1979 | | /* C_EncryptFinalize */ |
1980 | 0 | if (padding) { |
1981 | 0 | uint8_t pad_byte = block_size - rest_len; |
1982 | 0 | sc_log(ctx, "Generating padding, padding byte: %d", pad_byte); |
1983 | 0 | sdata = priv->sym_crypt_buffer + rest_len; |
1984 | 0 | memset(sdata, pad_byte, pad_byte); |
1985 | 0 | rest_len = block_size; |
1986 | |
|
1987 | 0 | } else if (rest_len) { |
1988 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_LENGTH); |
1989 | 0 | } |
1990 | | /* fall through - encipher last block */ |
1991 | 0 | } |
1992 | 0 | } |
1993 | | /* check output buffer size */ |
1994 | 0 | len = datalen + rest_len; |
1995 | |
|
1996 | 0 | sc_log(ctx, "datalen=%zu rest_len=%zu len=%zu outlen=%zu", datalen, rest_len, len, *outlen); |
1997 | | /* there is block_size bytes space that can be saved to next run */ |
1998 | 0 | len -= (len % block_size); |
1999 | | |
2000 | | /* application can request buffer size or actual buffer size is too small */ |
2001 | 0 | *outlen = len; |
2002 | 0 | if (out == NULL) |
2003 | 0 | LOG_FUNC_RETURN(ctx, SC_SUCCESS); |
2004 | | /* application buffer is too small */ |
2005 | 0 | if (*outlen < len) |
2006 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL); |
2007 | | |
2008 | | /* main loop */ |
2009 | 0 | while (len >= block_size) { |
2010 | 0 | if (!decipher) |
2011 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x84, 0x80); |
2012 | 0 | else |
2013 | 0 | sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x84); |
2014 | 0 | apdu.cla = 0; |
2015 | |
|
2016 | 0 | if (len > max_apdu_datalen) |
2017 | 0 | apdu_datalen = max_apdu_datalen; |
2018 | 0 | else |
2019 | 0 | apdu_datalen = len; |
2020 | |
|
2021 | 0 | if (cbc) |
2022 | 0 | apdu.cla = 0x10; |
2023 | |
|
2024 | 0 | len -= apdu_datalen; |
2025 | 0 | sdata = sbuf; |
2026 | |
|
2027 | 0 | apdu.le = apdu_datalen; |
2028 | 0 | apdu.lc = apdu_datalen; |
2029 | 0 | apdu.datalen = apdu_datalen; |
2030 | 0 | apdu.data = sbuf; |
2031 | 0 | apdu.resplen = sizeof(rbuf); |
2032 | 0 | apdu.resp = rbuf; |
2033 | | |
2034 | | /* do we have any data from the previous step ? */ |
2035 | 0 | if (rest_len) { |
2036 | 0 | memcpy(sbuf, priv->sym_crypt_buffer, rest_len); |
2037 | 0 | sdata += rest_len; |
2038 | 0 | apdu_datalen -= rest_len; |
2039 | 0 | priv->sym_crypt_buffer_len = 0; |
2040 | 0 | rest_len = 0; |
2041 | 0 | } |
2042 | 0 | if (data) { |
2043 | 0 | memcpy(sdata, data, apdu_datalen); |
2044 | 0 | data += apdu_datalen; |
2045 | 0 | datalen -= apdu_datalen; |
2046 | 0 | } |
2047 | 0 | r = sc_transmit_apdu(card, &apdu); |
2048 | 0 | LOG_TEST_RET(ctx, r, "APDU transmit failed"); |
2049 | 0 | r = sc_check_sw(card, apdu.sw1, apdu.sw2); |
2050 | 0 | LOG_TEST_RET(ctx, r, "decrypt_sym/encrypt_sym failed"); |
2051 | 0 | if (apdu.resplen != apdu.datalen) |
2052 | 0 | LOG_FUNC_RETURN(ctx, SC_ERROR_WRONG_LENGTH); |
2053 | 0 | memcpy(out, apdu.resp, apdu.resplen); |
2054 | 0 | out += apdu.resplen; |
2055 | 0 | return_len += apdu.resplen; |
2056 | 0 | } |
2057 | | /* last block is stored in buffer and is returned to application |
2058 | | * in next call to C_DecryptUpdate or C_DecryptFinal. This allow us |
2059 | | * to compute how many bytes is to be returned after padding removal. |
2060 | | * Whole handling of this is here, because "data" and "out" buffer |
2061 | | * can be in the same place. |
2062 | | */ |
2063 | 0 | if (decipher) { |
2064 | 0 | uint8_t tmp_buf[16]; |
2065 | 0 | if (return_len >= block_size) { |
2066 | | /* save last block to temp buffer */ |
2067 | 0 | memcpy(tmp_buf, out - block_size, block_size); |
2068 | 0 | if (priv->sym_plain_buffer_len) { |
2069 | | /* insert previous last block to output buffer */ |
2070 | 0 | sc_log(ctx, "inserting block from previous decrypt"); |
2071 | 0 | memmove(out - return_len + block_size, out - return_len, return_len - block_size); |
2072 | 0 | memcpy(out - return_len, priv->sym_plain_buffer, block_size); |
2073 | 0 | } else |
2074 | 0 | return_len -= block_size; |
2075 | | /* save last (decrypted) block */ |
2076 | 0 | memcpy(priv->sym_plain_buffer, tmp_buf, block_size); |
2077 | 0 | priv->sym_plain_buffer_len = block_size; |
2078 | |
|
2079 | 0 | } else |
2080 | 0 | priv->sym_plain_buffer_len = 0; |
2081 | 0 | } |
2082 | | /* save rest of data for next run */ |
2083 | 0 | priv->sym_crypt_buffer_len = datalen; |
2084 | 0 | sc_log(ctx, "rest data len = %zu", datalen); |
2085 | 0 | if (data) |
2086 | 0 | memcpy(priv->sym_crypt_buffer, data, datalen); |
2087 | 0 | sc_log(ctx, "return data len = %zu", return_len); |
2088 | 0 | *outlen = return_len; |
2089 | 0 | return SC_SUCCESS; |
2090 | 0 | } |
2091 | | |
2092 | | static int |
2093 | | myeid_encrypt_sym(struct sc_card *card, const u8 *data, size_t datalen, u8 *out, size_t *outlen) |
2094 | 0 | { |
2095 | 0 | return myeid_enc_dec_sym(card, data, datalen, out, outlen, 0); |
2096 | 0 | } |
2097 | | |
2098 | | static int |
2099 | | myeid_decrypt_sym(struct sc_card *card, const u8 *data, size_t datalen, u8 *out, size_t *outlen) |
2100 | 0 | { |
2101 | 0 | return myeid_enc_dec_sym(card, data, datalen, out, outlen, 1); |
2102 | 0 | } |
2103 | | |
2104 | | static struct sc_card_driver * sc_get_driver(void) |
2105 | 15.1k | { |
2106 | 15.1k | struct sc_card_driver *iso_drv = sc_get_iso7816_driver(); |
2107 | | |
2108 | 15.1k | if (iso_ops == NULL) |
2109 | 1 | iso_ops = iso_drv->ops; |
2110 | | |
2111 | 15.1k | myeid_ops = *iso_drv->ops; |
2112 | 15.1k | myeid_ops.match_card = myeid_match_card; |
2113 | 15.1k | myeid_ops.init = myeid_init; |
2114 | 15.1k | myeid_ops.finish = myeid_finish; |
2115 | | /* no record oriented file services */ |
2116 | 15.1k | myeid_ops.read_record = NULL; |
2117 | 15.1k | myeid_ops.write_record = NULL; |
2118 | 15.1k | myeid_ops.append_record = NULL; |
2119 | 15.1k | myeid_ops.update_record = NULL; |
2120 | 15.1k | myeid_ops.select_file = myeid_select_file; |
2121 | 15.1k | myeid_ops.get_response = iso_ops->get_response; |
2122 | 15.1k | myeid_ops.logout = myeid_logout; |
2123 | 15.1k | myeid_ops.create_file = myeid_create_file; |
2124 | 15.1k | myeid_ops.delete_file = myeid_delete_file; |
2125 | 15.1k | myeid_ops.list_files = myeid_list_files; |
2126 | 15.1k | myeid_ops.set_security_env = myeid_set_security_env; |
2127 | 15.1k | myeid_ops.compute_signature = myeid_compute_signature; |
2128 | 15.1k | myeid_ops.decipher = myeid_decipher; |
2129 | 15.1k | myeid_ops.process_fci = myeid_process_fci; |
2130 | 15.1k | myeid_ops.card_ctl = myeid_card_ctl; |
2131 | 15.1k | myeid_ops.pin_cmd = myeid_pin_cmd; |
2132 | 15.1k | myeid_ops.wrap = myeid_wrap_key; |
2133 | 15.1k | myeid_ops.unwrap = myeid_unwrap_key; |
2134 | 15.1k | myeid_ops.encrypt_sym = myeid_encrypt_sym; |
2135 | 15.1k | myeid_ops.decrypt_sym = myeid_decrypt_sym; |
2136 | 15.1k | return &myeid_drv; |
2137 | 15.1k | } |
2138 | | |
2139 | | struct sc_card_driver * sc_get_myeid_driver(void) |
2140 | 15.1k | { |
2141 | 15.1k | return sc_get_driver(); |
2142 | 15.1k | } |
2143 | | |