Coverage Report

Created: 2026-10-17 06:30

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
/* Decrypt the 24-byte encrypted CAN blob (16 enc || 8 SN) into its 16-byte
162
 * plaintext block. Exposed for card-chipdocit: same chip, same key. */
163
int
164
chipdoc_decrypt_can_block(const u8 *enc_can, size_t enc_can_len, u8 out[AES_BLOCK_SIZE])
165
0
{
166
  /* Magic key that is used to decrypt CAN */
167
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};
168
0
  u8 can_key[AES256_KEY_LEN] = { 0 };
169
170
0
  if (!enc_can || !out || enc_can_len != 24)
171
0
    return SC_ERROR_INVALID_ARGUMENTS;
172
0
  if (!get_can_key(magic_key, 0x01, enc_can, &can_key[0]))
173
0
    return SC_ERROR_INTERNAL;
174
0
  if (!get_can_key(magic_key, 0x02, enc_can, &can_key[AES_BLOCK_SIZE]))
175
0
    return SC_ERROR_INTERNAL;
176
0
  if (!aes256_ecb_decrypt(can_key, enc_can, out))
177
0
    return SC_ERROR_INTERNAL;
178
0
  return SC_SUCCESS;
179
0
}
180
181
static int
182
eoi_decrypt_can(struct sc_pkcs15_u8 *enc_can, char *can)
183
0
{
184
0
  int r;
185
186
0
  if (!can || !enc_can || !enc_can->value)
187
0
    return SC_ERROR_INVALID_ARGUMENTS;
188
0
  r = chipdoc_decrypt_can_block(enc_can->value, enc_can->len, (u8 *)can);
189
0
  if (r != SC_SUCCESS)
190
0
    return r;
191
0
  can[AES_BLOCK_SIZE - 1] = 0;
192
0
  return SC_SUCCESS;
193
0
}
194
195
static int eoi_sm_open(struct sc_card *card)
196
0
{
197
0
  int r;
198
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
199
0
  struct establish_pace_channel_input pace_input;
200
0
  struct establish_pace_channel_output pace_output;
201
202
0
  if (!privdata)
203
0
    return SC_ERROR_INTERNAL;
204
205
0
  if (!privdata->can[0]) {
206
    /* If no CAN is specified in conf, try to decrypt it from enc_can file */
207
0
    r = eoi_decrypt_can(&privdata->enc_can, privdata->can);
208
0
    sc_log_openssl(card->ctx);
209
0
    LOG_TEST_RET(card->ctx, r, "Cannot decrypt CAN");
210
0
  }
211
  /* CAN should be 6 chars long */
212
0
  if (strlen(privdata->can) != 6)
213
0
    return SC_ERROR_DECRYPT_FAILED;
214
215
0
  memset(&pace_input, 0, sizeof pace_input);
216
0
  memset(&pace_output, 0, sizeof pace_output);
217
218
0
  pace_input.pin_id = PACE_PIN_ID_CAN;
219
0
  pace_input.pin = (u8 *)privdata->can;
220
0
  pace_input.pin_length = strlen(privdata->can);
221
222
  /* EF.CardAccess can only be read from MF */
223
0
  r = sc_select_file(card, sc_get_mf_path(), NULL);
224
0
  LOG_TEST_RET(card->ctx, r, "sc_select_file failed");
225
226
0
  r = perform_pace(card, pace_input, &pace_output, EAC_TR_VERSION_2_02);
227
0
  LOG_TEST_RET(card->ctx, r, "Error verifying CAN");
228
229
0
  return SC_SUCCESS;
230
0
}
231
232
static int eoi_get_data(sc_card_t *card, u8 data_id, u8 *buf, size_t len)
233
0
{
234
0
  int r;
235
0
  sc_apdu_t apdu;
236
237
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x01, data_id);
238
0
  apdu.resp = buf;
239
0
  apdu.resplen = len;
240
0
  apdu.le = len;
241
242
0
  r = sc_transmit_apdu(card, &apdu);
243
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
244
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
245
0
  return r;
246
0
}
247
248
#define ATR_MATCH 1
249
250
2.46k
static int eoi_match_card(sc_card_t* card) {
251
2.46k
  LOG_FUNC_CALLED(card->ctx);
252
2.46k
  if (_sc_match_atr(card, eoi_atrs, &card->type) >= 0) {
253
0
    sc_log(card->ctx, "ATR recognized as Slovenian eID card");
254
0
    LOG_FUNC_RETURN(card->ctx, ATR_MATCH);
255
0
  }
256
2.46k
  LOG_FUNC_RETURN(card->ctx, !ATR_MATCH);
257
2.46k
}
258
259
0
static int eoi_init(sc_card_t* card) {
260
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
261
0
  u8 version[6];
262
0
  size_t i, j;
263
0
  scconf_block **found_blocks, *block;
264
0
  int r;
265
0
  char *can;
266
267
0
  LOG_FUNC_CALLED(card->ctx);
268
269
0
  if (eoi_get_data(card, 0x16, version, sizeof(version)) != SC_SUCCESS)
270
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_WRONG_CARD);
271
272
0
  if (privdata)
273
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
274
0
  privdata = sc_mem_secure_alloc(sizeof(struct eoi_privdata));
275
0
  if (!privdata)
276
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
277
  /* sc_mem_secure_alloc()-ed memory may not be zeroized */
278
0
  memset(privdata, 0, sizeof(struct eoi_privdata));
279
0
  card->drv_data = privdata;
280
281
0
  sprintf(privdata->version, "%X%02X.%02X%02X", version[0], version[1], version[2], version[3]);
282
0
  sc_log(card->ctx, "App version: %s", privdata->version);
283
284
0
  memset(&card->sm_ctx, 0, sizeof card->sm_ctx);
285
0
  card->sm_ctx.ops.open = eoi_sm_open;
286
287
0
  card->max_send_size = SC_MAX_APDU_DATA_SIZE;
288
0
  card->max_recv_size = SC_MAX_APDU_RESP_SIZE;
289
290
0
  for (i = 0; i < sizeof eoi_curves / sizeof * eoi_curves; ++i) {
291
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);
292
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "Add EC alg failed");
293
0
  }
294
295
0
  can = getenv("EOI_CAN");
296
0
  if (can)
297
0
    strlcpy(privdata->can, can, sizeof(privdata->can));
298
0
  for (i = 0; card->ctx->conf_blocks[i]; i++) {
299
0
    found_blocks = scconf_find_blocks(card->ctx->conf, card->ctx->conf_blocks[i],
300
0
          "card_driver", "eoi");
301
0
    if (!found_blocks)
302
0
      continue;
303
304
0
    for (j = 0, block = found_blocks[j]; block; j++, block = found_blocks[j]) {
305
0
      if (!privdata->can[0]) {
306
0
        const char *can = scconf_get_str(block, "can", NULL);
307
0
        if (can)
308
0
          strlcpy(privdata->can, can, sizeof(privdata->can));
309
0
      }
310
0
    }
311
0
    free(found_blocks);
312
0
  }
313
314
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
315
316
0
err:
317
0
  if (privdata) {
318
0
    sc_mem_clear(privdata, sizeof(struct eoi_privdata));
319
0
    sc_mem_secure_free(privdata, sizeof(struct eoi_privdata));
320
0
  }
321
0
  card->drv_data = NULL;
322
323
0
  LOG_FUNC_RETURN(card->ctx, r);
324
0
}
325
326
static int eoi_finish(sc_card_t* card)
327
0
{
328
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
329
330
0
  LOG_FUNC_CALLED(card->ctx);
331
332
0
  if (privdata) {
333
0
    sc_mem_clear(privdata, sizeof(struct eoi_privdata));
334
0
    sc_mem_secure_free(privdata, sizeof(struct eoi_privdata));
335
0
  }
336
337
0
  card->drv_data = NULL;
338
339
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
340
0
}
341
342
static int eoi_select_file(sc_card_t *card, const sc_path_t *in_path, sc_file_t **file_out)
343
0
{
344
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
345
0
  int i;
346
347
0
  LOG_FUNC_CALLED(card->ctx);
348
349
0
  if (!privdata)
350
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
351
352
0
  for (i = 0; i < MAX_OBJECTS && privdata->pin_paths[i]; i++) {
353
0
    if (privdata->pin_paths[i] && sc_compare_path(privdata->pin_paths[i], in_path)) {
354
0
      LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
355
0
    }
356
0
  }
357
358
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->select_file(card, in_path, file_out));
359
0
}
360
361
static int eoi_logout(struct sc_card *card)
362
0
{
363
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
364
0
  struct sc_apdu apdu;
365
0
  u8 buf[256];
366
0
  int r = SC_SUCCESS;
367
368
0
  LOG_FUNC_CALLED(card->ctx);
369
370
0
  if (!privdata)
371
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
372
373
0
  iso_sm_close(card);
374
0
  card->sm_ctx.sm_mode = SM_MODE_NONE;
375
376
0
  if (card->reader->flags & SC_READER_ENABLE_ESCAPE) {
377
    /*
378
     * Get the UID of the ISO 14443 A card. (see PCSC Part 3)
379
     * The "official" PKCS#11 does it and we do the same.
380
     */
381
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0x00, 0x00);
382
0
    apdu.cla = 0xFF;
383
0
    apdu.resp = buf;
384
0
    apdu.resplen = 256;
385
0
    apdu.lc = 0;
386
0
    apdu.le = 256;
387
388
0
    r = sc_transmit_apdu(card, &apdu);
389
0
  }
390
391
0
  LOG_FUNC_RETURN(card->ctx, r);
392
0
}
393
394
static int eoi_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data)
395
0
{
396
0
  int r;
397
398
0
  LOG_FUNC_CALLED(card->ctx);
399
400
0
  if (data->cmd == SC_PIN_CMD_VERIFY && card->sm_ctx.sm_mode == SM_MODE_NONE) {
401
    /* Establish SM before any PIN VERIFY command */
402
0
    r = eoi_sm_open(card);
403
0
    if (r != SC_SUCCESS)
404
0
      LOG_FUNC_RETURN(card->ctx, r);
405
0
  }
406
407
0
  if (data->cmd == SC_PIN_CMD_UNBLOCK) {
408
0
    int pin_reference = data->pin_reference;
409
0
    size_t pin2_len = data->pin2.len;
410
    /* Verify PUK, establish SM if necessary */
411
0
    data->cmd = SC_PIN_CMD_VERIFY;
412
0
    data->pin_reference = data->puk_reference;
413
0
    r = eoi_pin_cmd(card, data);
414
0
    if (r != SC_SUCCESS)
415
0
      LOG_FUNC_RETURN(card->ctx, r);
416
    /* RESET RETRY COUNTER */
417
0
    data->cmd = SC_PIN_CMD_UNBLOCK;
418
0
    data->pin_reference = 0x80|pin_reference;
419
0
    data->pin1.len = 0;
420
0
    data->pin2.len = 0;
421
0
    r = sc_get_iso7816_driver()->ops->pin_cmd(card, data);
422
0
    if (r != SC_SUCCESS)
423
0
      LOG_FUNC_RETURN(card->ctx, r);
424
    /* Continue as CHANGE PIN */
425
0
    data->cmd = SC_PIN_CMD_CHANGE;
426
0
    data->pin2.len = pin2_len;
427
0
  }
428
429
  /* CHANGE PIN command does not send the old PIN as it should already be verified */
430
0
  if (data->cmd == SC_PIN_CMD_CHANGE)
431
0
    data->pin1.len = 0;
432
433
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->pin_cmd(card, data));
434
0
}
435
436
static int
437
eoi_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
438
0
{
439
0
  struct sc_card_driver *iso_driver = NULL;
440
0
  int r = SC_ERROR_NOT_SUPPORTED;
441
442
0
  LOG_FUNC_CALLED(card->ctx);
443
0
  switch (cmd) {
444
0
  case SC_CARDCTL_GET_MODEL:
445
0
    if (!ptr) {
446
0
      r = SC_ERROR_INVALID_ARGUMENTS;
447
0
    } else {
448
0
      *(char **)ptr = eoi_model;
449
0
      r = SC_SUCCESS;
450
0
    }
451
0
    break;
452
0
  default:
453
0
    iso_driver = sc_get_iso7816_driver();
454
0
    if (iso_driver->ops->card_ctl != NULL) {
455
0
      r = sc_get_iso7816_driver()->ops->card_ctl(card, cmd, ptr);
456
0
    }
457
0
  }
458
0
  LOG_FUNC_RETURN(card->ctx, r);
459
0
}
460
461
0
#define ALREADY_PROCESSED 0x80000000
462
463
static int eoi_set_security_env(struct sc_card *card, const struct sc_security_env *env, int se_num)
464
0
{
465
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
466
0
  struct sc_apdu apdu;
467
0
  u8 sbuf[4];
468
0
  int i, r, locked = 0;
469
470
0
  LOG_FUNC_CALLED(card->ctx);
471
472
0
  if (!privdata)
473
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
474
475
0
  if (!card || !env)
476
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
477
478
  /* We don't know yet which hash is used. So just store the security_env data and return */
479
0
  if (!(env->algorithm_flags & ALREADY_PROCESSED)) {
480
0
    privdata->key_len = BYTES4BITS(env->algorithm_ref);
481
0
    memcpy(&privdata->sec_env, env, sizeof(struct sc_security_env));
482
0
    privdata->se_num = se_num;
483
0
    LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
484
0
  }
485
486
0
  if (env->operation != SC_SEC_OPERATION_SIGN)
487
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
488
0
  if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT))
489
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
490
0
  if (env->key_ref_len != 1)
491
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
492
0
  if (env->algorithm != SC_ALGORITHM_EC)
493
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
494
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81, 0xB6);
495
0
  sbuf[0] = 0x91;
496
0
  sbuf[1] = 0x02;
497
0
  if (env->algorithm_flags & SC_ALGORITHM_ECDSA_HASH_SHA1)
498
0
    sbuf[2] = 0x11;
499
0
  else if (env->algorithm_flags & SC_ALGORITHM_ECDSA_HASH_SHA256)
500
0
    sbuf[2] = 0x21;
501
0
  else if (env->algorithm_flags & (SC_ALGORITHM_ECDSA_RAW|SC_ALGORITHM_ECDSA_HASH_NONE))
502
0
    sbuf[2] = 0x22;
503
0
  else
504
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
505
0
  for (i = 0; i < MAX_OBJECTS && privdata->prkey_mappings[i][1]; i++) {
506
0
    if (privdata->prkey_mappings[i][0] == env->key_ref[0])
507
0
      break;
508
0
  }
509
0
  if (i == MAX_OBJECTS)
510
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
511
0
  sbuf[3] = privdata->prkey_mappings[i][1];
512
0
  apdu.lc = 4;
513
0
  apdu.datalen = 4;
514
0
  apdu.data = sbuf;
515
0
  if (se_num > 0) {
516
0
    r = sc_lock(card);
517
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
518
0
    locked = 1;
519
0
  }
520
0
  if (apdu.datalen) {
521
0
    r = sc_transmit_apdu(card, &apdu);
522
0
    if (r) {
523
0
      sc_log(card->ctx, "%s: APDU transmit failed", sc_strerror(r));
524
0
      goto err;
525
0
    }
526
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
527
0
    if (r) {
528
0
      sc_log(card->ctx, "%s: Card returned error", sc_strerror(r));
529
0
      goto err;
530
0
    }
531
0
  }
532
0
  if (se_num <= 0) {
533
0
    r = SC_SUCCESS;
534
0
    goto err;
535
0
  }
536
0
  sc_unlock(card);
537
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
538
539
0
  LOG_FUNC_RETURN(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2));
540
0
err:
541
0
  if (locked)
542
0
    sc_unlock(card);
543
0
  LOG_FUNC_RETURN(card->ctx, r);
544
0
}
545
546
static int eoi_compute_signature(struct sc_card *card, const u8 * data, size_t data_len, u8 *out, size_t outlen)
547
0
{
548
0
  struct eoi_privdata *privdata = (struct eoi_privdata *)card->drv_data;
549
0
  int r;
550
551
0
  LOG_FUNC_CALLED(card->ctx);
552
553
0
  if (!privdata)
554
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
555
556
  /*
557
   * Guess the correct mode. If the size is less than the full-key-len, it must be a hash then
558
   */
559
0
  if (privdata->key_len != data_len) {
560
0
    switch (data_len) {
561
0
      case SHA_DIGEST_LENGTH:
562
0
        privdata->sec_env.algorithm_flags = SC_ALGORITHM_ECDSA_HASH_SHA1;
563
0
        break;
564
0
      case SHA256_DIGEST_LENGTH:
565
0
        privdata->sec_env.algorithm_flags = SC_ALGORITHM_ECDSA_HASH_SHA256;
566
0
        break;
567
0
    }
568
0
  }
569
  /* Now we know which hash is used */
570
0
  privdata->sec_env.algorithm_flags |= ALREADY_PROCESSED;
571
572
  /* Perform the true set_security_env */
573
0
  r = eoi_set_security_env(card, &privdata->sec_env, privdata->se_num);
574
0
  LOG_TEST_RET(card->ctx, r, "set_security_env failed");
575
576
0
  LOG_FUNC_RETURN(card->ctx, sc_get_iso7816_driver()->ops->compute_signature(card, data, data_len, out, outlen));
577
0
}
578
579
struct sc_card_driver *sc_get_eoi_driver(void)
580
11.9k
{
581
11.9k
  eoi_ops = *sc_get_iso7816_driver()->ops;
582
583
11.9k
  eoi_ops.match_card = eoi_match_card;
584
11.9k
  eoi_ops.init = eoi_init;
585
11.9k
  eoi_ops.finish = eoi_finish;
586
11.9k
  eoi_ops.select_file = eoi_select_file;
587
11.9k
  eoi_ops.logout = eoi_logout;
588
11.9k
  eoi_ops.pin_cmd = eoi_pin_cmd;
589
11.9k
  eoi_ops.card_ctl = eoi_card_ctl;
590
11.9k
  eoi_ops.set_security_env = eoi_set_security_env;
591
11.9k
  eoi_ops.compute_signature = eoi_compute_signature;
592
593
11.9k
  return &eoi_drv;
594
11.9k
}
595
596
#else
597
598
struct sc_card_driver* sc_get_eoi_driver(void) {
599
  return NULL;
600
}
601
602
#endif