Coverage Report

Created: 2025-11-09 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-eoi.c
Line
Count
Source
1
/*
2
 * Support for the eOI card
3
 *
4
 * Copyright (C) 2022 Luka Logar <luka.logar@iname.com>
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
#include <stdlib.h>
22
#include <string.h>
23
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
#include "opensc.h"
28
29
#if defined(ENABLE_SM) && defined(ENABLE_OPENPACE)
30
31
#include <openssl/aes.h>
32
#include <openssl/sha.h>
33
#include "internal.h"
34
#include "sm/sm-eac.h"
35
#include "common/compat_strlcpy.h"
36
#include "card-eoi.h"
37
38
static struct sc_card_operations eoi_ops;
39
40
static struct {
41
  int len;
42
  struct sc_object_id oid;
43
} eoi_curves[] = {
44
  /* secp384r1 */
45
  {384, {{1, 3, 132, 0, 34, -1}}}
46
};
47
48
static char *eoi_model = "ChipDocLite";
49
50
/* The description of the driver. */
51
static struct sc_card_driver eoi_drv =
52
{
53
  "eOI (Slovenian eID card)",
54
  "eOI",
55
  &eoi_ops,
56
  NULL, 0, NULL
57
};
58
59
static const struct sc_atr_table eoi_atrs[] = {
60
  /* Contact interface */
61
  { "3b:d5:18:ff:81:91:fe:1f:c3:80:73:c8:21:10:0a", NULL, NULL, SC_CARD_TYPE_EOI, 0, NULL },
62
  /* Contactless interface */
63
  { "3b:85:80:01:80:73:c8:21:10:0e", NULL, NULL, SC_CARD_TYPE_EOI_CONTACTLESS, 0, NULL },
64
  { NULL, NULL, NULL, 0, 0, NULL }
65
};
66
67
/*
68
 * CAN is stored encrypted in a file that (looks like) is pointed to by 'Card CAN' PIN object.
69
 * eoi_decrypt_can() decrypts CAN from it's encrypted form
70
 */
71
72
static void rol(u8 *to, const u8 *from)
73
0
{
74
0
  int i;
75
0
  u8 b = from[0] & 0x80;
76
0
  for (i = 15; i >= 0; i--) {
77
0
    u8 bo = b;
78
0
    b = from[i] & 0x80;
79
0
    to[i] = (from[i] << 1) | (bo ? 1 : 0);
80
0
    if ((i == 15) && bo)
81
0
      to[i] = (to[i] ^ 0x87) | 1;
82
0
  }
83
0
}
84
85
static int aes256_ecb_encrypt(const u8 *key, const u8 input[AES_BLOCK_SIZE], u8 output[AES_BLOCK_SIZE])
86
0
{
87
0
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
88
0
  int r = 0, pos, len = pos = AES_BLOCK_SIZE;
89
0
  if (!ctx)
90
0
    goto err;
91
0
  if (!EVP_EncryptInit(ctx, EVP_aes_256_ecb(), key, NULL))
92
0
    goto err;
93
  /* Disable padding, otherwise EVP_EncryptFinal() will fail */
94
0
  if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
95
0
    goto err;
96
0
  if (!EVP_EncryptUpdate(ctx, output, &pos, input, len))
97
0
    goto err;
98
0
  len -= pos;
99
0
  if (!EVP_EncryptFinal(ctx, output + pos, &len))
100
0
    goto err;
101
0
  r = 1;
102
0
err:
103
0
  if (ctx)
104
0
    EVP_CIPHER_CTX_free(ctx);
105
0
  return r;
106
0
}
107
108
static int aes256_ecb_decrypt(const u8 *key, const u8 input[AES_BLOCK_SIZE], u8 output[AES_BLOCK_SIZE])
109
0
{
110
0
  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
111
0
  int r = 0, pos, len = pos = AES_BLOCK_SIZE;
112
0
  if (!ctx)
113
0
    goto err;
114
0
  if (!EVP_DecryptInit(ctx, EVP_aes_256_ecb(), key, NULL))
115
0
    goto err;
116
  /* Disable padding, otherwise it will fail to decrypt non-padded inputs */
117
0
  if (!EVP_CIPHER_CTX_set_padding(ctx, 0))
118
0
    goto err;
119
0
  if (!EVP_DecryptUpdate(ctx, output, &pos, input, len))
120
0
    goto err;
121
0
  len -= pos;
122
0
  if (!EVP_DecryptFinal(ctx, output + pos, &len))
123
0
    goto err;
124
0
  r = 1;
125
0
err:
126
0
  if (ctx)
127
0
    EVP_CIPHER_CTX_free(ctx);
128
0
  return r;
129
0
}
130
131
/*
132
 * CAN decrypt magic...
133
 */
134
static int get_can_key(const u8 *key, const u8 round, const u8 *input, u8 *output)
135
0
{
136
0
  size_t i;
137
0
  u8 tmp[3][AES_BLOCK_SIZE];
138
0
  memset(tmp[0], 0, AES_BLOCK_SIZE);
139
0
  if (!aes256_ecb_encrypt(key, tmp[0], tmp[0]))
140
0
    return 0;
141
0
  rol(tmp[1], tmp[0]);
142
0
  rol(tmp[0], tmp[1]);
143
0
  memset(tmp[1], 0, AES_BLOCK_SIZE);
144
0
  tmp[1][11] = 4;
145
0
  tmp[1][13] = 1;
146
0
  tmp[1][15] = round;
147
0
  if (!aes256_ecb_encrypt(key, tmp[1], tmp[2]))
148
0
    return 0;
149
0
  memset(tmp[1], 0, AES_BLOCK_SIZE);
150
0
  memcpy(tmp[1], &input[AES_BLOCK_SIZE], 8);
151
0
  tmp[1][8] = 0x80;
152
0
  for (i = 0; i < AES_BLOCK_SIZE; i++)
153
0
    tmp[0][i] = tmp[0][i] ^ tmp[1][i] ^ tmp[2][i];
154
0
  if (!aes256_ecb_encrypt(key, tmp[0], output))
155
0
    return 0;
156
0
  return 1;
157
0
}
158
159
#define AES256_KEY_LEN 32
160
161
0
static int eoi_decrypt_can(struct sc_pkcs15_u8 *enc_can, char *can) {
162
  /* Magic key that is used to decrypt CAN */
163
0
  const u8 magic_key[AES256_KEY_LEN] = {0xC8, 0x12, 0x0F, 0xD8, 0x21, 0x20, 0x1F, 0x77, 0xF1, 0x83, 0x9D, 0xD8, 0x86, 0xB0, 0x5C, 0xF2, 0x4F, 0x7E, 0x52, 0x66, 0xE5, 0x87, 0x89, 0x2B, 0xF4, 0xC5, 0xE5, 0x4C, 0x54, 0xA1, 0x55, 0x30};
164
0
  u8 can_key[AES256_KEY_LEN] = { 0 };
165
166
0
  if (!can || !enc_can || !enc_can->value || enc_can->len != 24)
167
0
    return SC_ERROR_INVALID_ARGUMENTS;
168
169
0
  if (!get_can_key(magic_key, 0x01, enc_can->value, &can_key[0]))
170
0
    return SC_ERROR_INTERNAL;
171
0
  if (!get_can_key(magic_key, 0x02, enc_can->value, &can_key[AES_BLOCK_SIZE]))
172
0
    return SC_ERROR_INTERNAL;
173
174
0
  if (!aes256_ecb_decrypt(can_key, enc_can->value, (u8 *)can))
175
0
    return SC_ERROR_INTERNAL;
176
0
  can[AES_BLOCK_SIZE - 1] = 0;
177
178
0
  return SC_SUCCESS;
179
0
}
180
181
static int eoi_sm_open(struct sc_card *card)
182
0
{
183
0
  int r;
184
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
185
0
  struct establish_pace_channel_input pace_input;
186
0
  struct establish_pace_channel_output pace_output;
187
188
0
  if (!privdata)
189
0
    return SC_ERROR_INTERNAL;
190
191
0
  if (!privdata->can[0]) {
192
    /* If no CAN is specified in conf, try to decrypt it from enc_can file */
193
0
    r = eoi_decrypt_can(&privdata->enc_can, privdata->can);
194
0
    sc_log_openssl(card->ctx);
195
0
    LOG_TEST_RET(card->ctx, r, "Cannot decrypt CAN");
196
0
  }
197
  /* CAN should be 6 chars long */
198
0
  if (strlen(privdata->can) != 6)
199
0
    return SC_ERROR_DECRYPT_FAILED;
200
201
0
  memset(&pace_input, 0, sizeof pace_input);
202
0
  memset(&pace_output, 0, sizeof pace_output);
203
204
0
  pace_input.pin_id = PACE_PIN_ID_CAN;
205
0
  pace_input.pin = (u8 *)privdata->can;
206
0
  pace_input.pin_length = strlen(privdata->can);
207
208
  /* EF.CardAccess can only be read from MF */
209
0
  r = sc_select_file(card, sc_get_mf_path(), NULL);
210
0
  LOG_TEST_RET(card->ctx, r, "sc_select_file failed");
211
212
0
  r = perform_pace(card, pace_input, &pace_output, EAC_TR_VERSION_2_02);
213
0
  LOG_TEST_RET(card->ctx, r, "Error verifying CAN");
214
215
0
  return SC_SUCCESS;
216
0
}
217
218
static int eoi_get_data(sc_card_t *card, u8 data_id, u8 *buf, size_t len)
219
0
{
220
0
  int r;
221
0
  sc_apdu_t apdu;
222
223
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, data_id);
224
0
  apdu.resp = buf;
225
0
  apdu.resplen = len;
226
0
  apdu.le = len;
227
228
0
  r = sc_transmit_apdu(card, &apdu);
229
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
230
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
231
0
  return r;
232
0
}
233
234
#define ATR_MATCH 1
235
236
2.42k
static int eoi_match_card(sc_card_t* card) {
237
2.42k
  LOG_FUNC_CALLED(card->ctx);
238
2.42k
  if (_sc_match_atr(card, eoi_atrs, &card->type) >= 0) {
239
0
    sc_log(card->ctx, "ATR recognized as Slovenian eID card");
240
0
    LOG_FUNC_RETURN(card->ctx, ATR_MATCH);
241
0
  }
242
2.42k
  LOG_FUNC_RETURN(card->ctx, !ATR_MATCH);
243
2.42k
}
244
245
0
static int eoi_init(sc_card_t* card) {
246
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
247
0
  u8 version[6];
248
0
  size_t i, j;
249
0
  scconf_block **found_blocks, *block;
250
0
  int r;
251
0
  char *can;
252
253
0
  LOG_FUNC_CALLED(card->ctx);
254
255
0
  if (eoi_get_data(card, 0x16, version, sizeof(version)) != SC_SUCCESS)
256
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_CARD);
257
258
0
  if (privdata)
259
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
260
0
  privdata = sc_mem_secure_alloc(sizeof(struct eoi_privdata));
261
0
  if (!privdata)
262
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
263
  /* sc_mem_secure_alloc()-ed memory may not be zeroized */
264
0
  memset(privdata, 0, sizeof(struct eoi_privdata));
265
0
  card->drv_data = privdata;
266
267
0
  sprintf(privdata->version, "%X%02X.%02X%02X", version[0], version[1], version[2], version[3]);
268
0
  sc_log(card->ctx, "App version: %s", privdata->version);
269
270
0
  memset(&card->sm_ctx, 0, sizeof card->sm_ctx);
271
0
  card->sm_ctx.ops.open = eoi_sm_open;
272
273
0
  card->max_send_size = SC_MAX_APDU_DATA_SIZE;
274
0
  card->max_recv_size = SC_MAX_APDU_RESP_SIZE;
275
276
0
  for (i = 0; i < sizeof eoi_curves / sizeof * eoi_curves; ++i) {
277
0
    r = _sc_card_add_ec_alg(card, eoi_curves[i].len, SC_ALGORITHM_ECDSA_RAW | SC_ALGORITHM_ECDSA_HASH_NONE, 0, &eoi_curves[i].oid);
278
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Add EC alg failed");
279
0
  }
280
281
0
  can = getenv("EOI_CAN");
282
0
  if (can)
283
0
    strlcpy(privdata->can, can, sizeof(privdata->can));
284
0
  for (i = 0; card->ctx->conf_blocks[i]; i++) {
285
0
    found_blocks = scconf_find_blocks(card->ctx->conf, card->ctx->conf_blocks[i],
286
0
          "card_driver", "eoi");
287
0
    if (!found_blocks)
288
0
      continue;
289
290
0
    for (j = 0, block = found_blocks[j]; block; j++, block = found_blocks[j]) {
291
0
      if (!privdata->can[0]) {
292
0
        const char *can = scconf_get_str(block, "can", NULL);
293
0
        if (can)
294
0
          strlcpy(privdata->can, can, sizeof(privdata->can));
295
0
      }
296
0
    }
297
0
    free(found_blocks);
298
0
  }
299
300
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
301
302
0
err:
303
0
  if (privdata) {
304
0
    sc_mem_clear(privdata, sizeof(struct eoi_privdata));
305
0
    sc_mem_secure_free(privdata, sizeof(struct eoi_privdata));
306
0
  }
307
0
  card->drv_data = NULL;
308
309
0
  LOG_FUNC_RETURN(card->ctx, r);
310
0
}
311
312
static int eoi_finish(sc_card_t* card)
313
0
{
314
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
315
316
0
  LOG_FUNC_CALLED(card->ctx);
317
318
0
  if (privdata) {
319
0
    sc_mem_clear(privdata, sizeof(struct eoi_privdata));
320
0
    sc_mem_secure_free(privdata, sizeof(struct eoi_privdata));
321
0
  }
322
323
0
  card->drv_data = NULL;
324
325
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
326
0
}
327
328
static int eoi_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
329
0
{
330
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
331
0
  int i;
332
333
0
  LOG_FUNC_CALLED(card->ctx);
334
335
0
  if (!privdata)
336
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
337
338
0
  for (i = 0; i < MAX_OBJECTS && privdata->pin_paths[i]; i++) {
339
0
    if (privdata->pin_paths[i] && sc_compare_path(privdata->pin_paths[i], in_path)) {
340
0
      LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
341
0
    }
342
0
  }
343
344
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->select_file(card, in_path, file_out));
345
0
}
346
347
static int eoi_logout(struct sc_card *card)
348
0
{
349
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
350
0
  struct sc_apdu apdu;
351
0
  u8 buf[256];
352
0
  int r = SC_SUCCESS;
353
354
0
  LOG_FUNC_CALLED(card->ctx);
355
356
0
  if (!privdata)
357
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
358
359
0
  iso_sm_close(card);
360
0
  card->sm_ctx.sm_mode = SM_MODE_NONE;
361
362
0
  if (card->reader->flags & SC_READER_ENABLE_ESCAPE) {
363
    /*
364
     * Get the UID of the ISO 14443 A card. (see PCSC Part 3)
365
     * The "official" PKCS#11 does it and we do the same.
366
     */
367
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x00, 0x00);
368
0
    apdu.cla = 0xFF;
369
0
    apdu.resp = buf;
370
0
    apdu.resplen = 256;
371
0
    apdu.lc = 0;
372
0
    apdu.le = 256;
373
374
0
    r = sc_transmit_apdu(card, &apdu);
375
0
  }
376
377
0
  LOG_FUNC_RETURN(card->ctx, r);
378
0
}
379
380
static int eoi_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data, int *tries_left)
381
0
{
382
0
  int r;
383
384
0
  LOG_FUNC_CALLED(card->ctx);
385
386
0
  if (data->cmd == SC_PIN_CMD_VERIFY && card->sm_ctx.sm_mode == SM_MODE_NONE) {
387
    /* Establish SM before any PIN VERIFY command */
388
0
    r = eoi_sm_open(card);
389
0
    if (r != SC_SUCCESS)
390
0
      LOG_FUNC_RETURN(card->ctx, r);
391
0
  }
392
393
0
  if (data->cmd == SC_PIN_CMD_UNBLOCK) {
394
0
    int pin_reference = data->pin_reference;
395
0
    size_t pin2_len = data->pin2.len;
396
    /* Verify PUK, establish SM if necessary */
397
0
    data->cmd = SC_PIN_CMD_VERIFY;
398
0
    data->pin_reference = data->puk_reference;
399
0
    r = eoi_pin_cmd(card, data, tries_left);
400
0
    if (r != SC_SUCCESS)
401
0
      LOG_FUNC_RETURN(card->ctx, r);
402
    /* RESET RETRY COUNTER */
403
0
    data->cmd = SC_PIN_CMD_UNBLOCK;
404
0
    data->pin_reference = 0x80|pin_reference;
405
0
    data->pin1.len = 0;
406
0
    data->pin2.len = 0;
407
0
    r = sc_get_iso7816_driver()->ops->pin_cmd(card, data, tries_left);
408
0
    if (r != SC_SUCCESS)
409
0
      LOG_FUNC_RETURN(card->ctx, r);
410
    /* Continue as CHANGE PIN */
411
0
    data->cmd = SC_PIN_CMD_CHANGE;
412
0
    data->pin2.len = pin2_len;
413
0
  }
414
415
  /* CHANGE PIN command does not send the old PIN as it should already be verified */
416
0
  if (data->cmd == SC_PIN_CMD_CHANGE)
417
0
    data->pin1.len = 0;
418
419
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->pin_cmd(card, data, tries_left));
420
0
}
421
422
static int
423
eoi_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
424
0
{
425
0
  struct sc_card_driver *iso_driver = NULL;
426
0
  int r = SC_ERROR_NOT_SUPPORTED;
427
428
0
  LOG_FUNC_CALLED(card->ctx);
429
0
  switch (cmd) {
430
0
  case SC_CARDCTL_GET_MODEL:
431
0
    if (!ptr) {
432
0
      r = SC_ERROR_INVALID_ARGUMENTS;
433
0
    } else {
434
0
      *(char **)ptr = eoi_model;
435
0
      r = SC_SUCCESS;
436
0
    }
437
0
    break;
438
0
  default:
439
0
    iso_driver = sc_get_iso7816_driver();
440
0
    if (iso_driver->ops->card_ctl != NULL) {
441
0
      r = sc_get_iso7816_driver()->ops->card_ctl(card, cmd, ptr);
442
0
    }
443
0
  }
444
0
  LOG_FUNC_RETURN(card->ctx, r);
445
0
}
446
447
0
#define ALREADY_PROCESSED 0x80000000
448
449
static int eoi_set_security_env(struct sc_card *card, const struct sc_security_env *env, int se_num)
450
0
{
451
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
452
0
  struct sc_apdu apdu;
453
0
  u8 sbuf[4];
454
0
  int i, r, locked = 0;
455
456
0
  LOG_FUNC_CALLED(card->ctx);
457
458
0
  if (!privdata)
459
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
460
461
0
  if (!card || !env)
462
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
463
464
  /* We don't know yet which hash is used. So just store the security_env data and return */
465
0
  if (!(env->algorithm_flags & ALREADY_PROCESSED)) {
466
0
    privdata->key_len = BYTES4BITS(env->algorithm_ref);
467
0
    memcpy(&privdata->sec_env, env, sizeof(struct sc_security_env));
468
0
    privdata->se_num = se_num;
469
0
    LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
470
0
  }
471
472
0
  if (env->operation != SC_SEC_OPERATION_SIGN)
473
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
474
0
  if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT))
475
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
476
0
  if (env->key_ref_len != 1)
477
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
478
0
  if (env->algorithm != SC_ALGORITHM_EC)
479
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
480
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xB6);
481
0
  sbuf[0] = 0x91;
482
0
  sbuf[1] = 0x02;
483
0
  if (env->algorithm_flags & SC_ALGORITHM_ECDSA_HASH_SHA1)
484
0
    sbuf[2] = 0x11;
485
0
  else if (env->algorithm_flags & SC_ALGORITHM_ECDSA_HASH_SHA256)
486
0
    sbuf[2] = 0x21;
487
0
  else if (env->algorithm_flags & (SC_ALGORITHM_ECDSA_RAW|SC_ALGORITHM_ECDSA_HASH_NONE))
488
0
    sbuf[2] = 0x22;
489
0
  else
490
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
491
0
  for (i = 0; i < MAX_OBJECTS && privdata->prkey_mappings[i][1]; i++) {
492
0
    if (privdata->prkey_mappings[i][0] == env->key_ref[0])
493
0
      break;
494
0
  }
495
0
  if (i == MAX_OBJECTS)
496
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
497
0
  sbuf[3] = privdata->prkey_mappings[i][1];
498
0
  apdu.lc = 4;
499
0
  apdu.datalen = 4;
500
0
  apdu.data = sbuf;
501
0
  if (se_num > 0) {
502
0
    r = sc_lock(card);
503
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
504
0
    locked = 1;
505
0
  }
506
0
  if (apdu.datalen) {
507
0
    r = sc_transmit_apdu(card, &apdu);
508
0
    if (r) {
509
0
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
510
0
      goto err;
511
0
    }
512
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
513
0
    if (r) {
514
0
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
515
0
      goto err;
516
0
    }
517
0
  }
518
0
  if (se_num <= 0) {
519
0
    r = SC_SUCCESS;
520
0
    goto err;
521
0
  }
522
0
  sc_unlock(card);
523
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
524
525
0
  LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
526
0
err:
527
0
  if (locked)
528
0
    sc_unlock(card);
529
0
  LOG_FUNC_RETURN(card->ctx, r);
530
0
}
531
532
static int eoi_compute_signature(struct sc_card *card, const u8 * data, size_t data_len, u8 *out, size_t outlen)
533
0
{
534
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
535
0
  int r;
536
537
0
  LOG_FUNC_CALLED(card->ctx);
538
539
0
  if (!privdata)
540
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
541
542
  /*
543
   * Guess the correct mode. If the size is less than the full-key-len, it must be a hash then
544
   */
545
0
  if (privdata->key_len != data_len) {
546
0
    switch (data_len) {
547
0
      case SHA_DIGEST_LENGTH:
548
0
        privdata->sec_env.algorithm_flags = SC_ALGORITHM_ECDSA_HASH_SHA1;
549
0
        break;
550
0
      case SHA256_DIGEST_LENGTH:
551
0
        privdata->sec_env.algorithm_flags = SC_ALGORITHM_ECDSA_HASH_SHA256;
552
0
        break;
553
0
    }
554
0
  }
555
  /* Now we know which hash is used */
556
0
  privdata->sec_env.algorithm_flags |= ALREADY_PROCESSED;
557
558
  /* Perform the true set_security_env */
559
0
  r = eoi_set_security_env(card, &privdata->sec_env, privdata->se_num);
560
0
  LOG_TEST_RET(card->ctx, r, "set_security_env failed");
561
562
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->compute_signature(card, data, data_len, out, outlen));
563
0
}
564
565
struct sc_card_driver *sc_get_eoi_driver(void)
566
18.4k
{
567
18.4k
  eoi_ops = *sc_get_iso7816_driver()->ops;
568
569
18.4k
  eoi_ops.match_card = eoi_match_card;
570
18.4k
  eoi_ops.init = eoi_init;
571
18.4k
  eoi_ops.finish = eoi_finish;
572
18.4k
  eoi_ops.select_file = eoi_select_file;
573
18.4k
  eoi_ops.logout = eoi_logout;
574
18.4k
  eoi_ops.pin_cmd = eoi_pin_cmd;
575
18.4k
  eoi_ops.card_ctl = eoi_card_ctl;
576
18.4k
  eoi_ops.set_security_env = eoi_set_security_env;
577
18.4k
  eoi_ops.compute_signature = eoi_compute_signature;
578
579
18.4k
  return &eoi_drv;
580
18.4k
}
581
582
#else
583
584
struct sc_card_driver* sc_get_eoi_driver(void) {
585
  return NULL;
586
}
587
588
#endif