Coverage Report

Created: 2026-06-06 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-entersafe.c
Line
Count
Source
1
/*
2
 * This library is free software; you can redistribute it and/or
3
 * modify it under the terms of the GNU Lesser General Public
4
 * License as published by the Free Software Foundation; either
5
 * version 2.1 of the License, or (at your option) any later version.
6
 *
7
 * This library is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10
 * Lesser General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU Lesser General Public
13
 * License along with this library; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
 */
16
17
/* Initially written by Weitao Sun (weitao@ftsafe.com) 2008 */
18
19
#ifdef HAVE_CONFIG_H
20
#include "config.h"
21
#endif
22
#ifdef ENABLE_OPENSSL /* empty file without openssl */
23
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include <openssl/evp.h>
28
29
#include "internal.h"
30
#include "asn1.h"
31
#include "cardctl.h"
32
33
static const struct sc_atr_table entersafe_atrs[] = {
34
  {
35
    "3b:0f:00:65:46:53:05:19:05:71:df:00:00:00:00:00:00",
36
    "ff:ff:ff:ff:ff:ff:ff:00:ff:ff:ff:00:00:00:00:00:00",
37
    "ePass3000", SC_CARD_TYPE_ENTERSAFE_3K, 0, NULL },
38
  {
39
    "3b:9f:95:81:31:fe:9f:00:65:46:53:05:30:06:71:df:00:00:00:80:6a:82:5e",
40
    "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:00:00:00:00",
41
    "FTCOS/PK-01C", SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, 0, NULL },
42
  {
43
    "3b:fc:18:00:00:81:31:80:45:90:67:46:4a:00:64:18:14:00:00:00:00:02",
44
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
45
    "EJAVA/PK-01C", SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C, 0, NULL },
46
  {
47
    "3b:7c:18:00:00:90:67:46:4a:20:28:8c:58:00:00:00:00",
48
    "ff:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff",
49
    "EJAVA/PK-01C-T0",SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0,0,NULL},
50
  {
51
    "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:21:28:8C:58:00:00:00:00:B7",
52
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
53
    "EJAVA/H10CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1,0,NULL},
54
  {
55
    "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:20:25:c3:30:00:00:00:00",
56
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:00:00:00:00",
57
    "EJAVA/D11CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1,0,NULL},
58
  {
59
    "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:00:6A:04:24:00:00:00:00:20",
60
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
61
    "EJAVA/C21C/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1,0,NULL},
62
  {
63
    "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:00:68:08:04:00:00:00:00:0E",
64
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
65
    "EJAVA/A22CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1,0,NULL},
66
  {
67
    "3B:FC:18:00:00:81:31:80:45:90:67:46:4A:10:27:61:30:00:00:00:00:0C",
68
    "ff:00:00:00:00:00:00:00:00:ff:ff:ff:ff:00:00:00:00:ff:ff:ff:ff:00",
69
    "EJAVA/A40CR/PK-01C-T1",SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1,0,NULL},
70
  {
71
    "3b:fc:18:00:00:81:31:80:45:90:67:46:4a:00:68:08:06:00:00:00:00:0c",
72
    "FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:00:FF:FF:FF:FF:FF:FF:00:00:00",
73
    "FTCOS/PK-01C", SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C, 0, NULL },
74
  { NULL, NULL, NULL, 0, 0, NULL }
75
};
76
77
static struct sc_card_operations entersafe_ops;
78
static struct sc_card_operations *iso_ops = NULL;
79
80
static struct sc_card_driver entersafe_drv = {
81
  "entersafe",
82
  "entersafe",
83
  &entersafe_ops,
84
  NULL, 0, NULL
85
};
86
87
static u8 trans_code_3k[] =
88
{
89
  0x01, 0x02, 0x03, 0x04,
90
  0x05, 0x06, 0x07, 0x08,
91
};
92
93
static u8 trans_code_ftcos_pk_01c[] =
94
{
95
  0x92, 0x34, 0x2E, 0xEF,
96
  0x23, 0x40, 0x4F, 0xD1,
97
};
98
99
static u8 init_key[] =
100
{
101
  1,  2,  3,  4,
102
  5,  6,  7,  8,
103
  9,  10, 11, 12,
104
  13, 14, 15, 16,
105
};
106
107
static u8 key_maintain[] =
108
{
109
  0x12, 0x34, 0x56, 0x78,
110
  0x21, 0x43, 0x65, 0x87,
111
  0x11, 0x22, 0xaa, 0xbb,
112
  0x33, 0x44, 0xcd, 0xef
113
};
114
115
static void entersafe_reverse_buffer(u8* buff, size_t size)
116
0
{
117
0
  u8 t;
118
0
  u8 *end = buff + size - 1;
119
120
0
  while (buff < end) {
121
0
    t = *buff;
122
0
    *buff = *end;
123
0
    *end = t;
124
0
    ++buff;
125
0
    --end;
126
0
  }
127
0
}
128
129
static int entersafe_select_file(sc_card_t *card,
130
                 const sc_path_t *in_path,
131
                 sc_file_t **file_out);
132
133
/* the entersafe part */
134
static int entersafe_match_card(sc_card_t *card)
135
0
{
136
0
  int i;
137
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
138
139
0
  i = _sc_match_atr(card, entersafe_atrs, &card->type);
140
0
  if (i < 0)
141
0
    return 0;
142
143
0
  return 1;
144
0
}
145
146
static int entersafe_init(sc_card_t *card)
147
0
{
148
0
  unsigned int flags;
149
150
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
151
152
0
  card->name = "entersafe";
153
0
  card->cla  = 0x00;
154
0
  card->drv_data = NULL;
155
156
0
  flags = SC_ALGORITHM_ONBOARD_KEY_GEN | SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_HASH_NONE;
157
158
0
  _sc_card_add_rsa_alg(card, 512, flags, 0);
159
0
  _sc_card_add_rsa_alg(card, 768, flags, 0);
160
0
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
161
0
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
162
163
0
  card->caps = SC_CARD_CAP_RNG;
164
165
  /* we need read_binary&friends with max 224 bytes per read */
166
0
  card->max_send_size = 224;
167
0
  card->max_recv_size = 224;
168
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
169
0
}
170
171
static int entersafe_gen_random(sc_card_t *card, u8 *buff, size_t size)
172
0
{
173
0
  int r = SC_SUCCESS;
174
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = {0};
175
0
  sc_apdu_t apdu;
176
177
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
178
179
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x84, 0x00, 0x00);
180
0
  apdu.resp = rbuf;
181
0
  apdu.le = size;
182
0
  apdu.resplen = sizeof(rbuf);
183
184
0
  r = sc_transmit_apdu(card, &apdu);
185
0
  LOG_TEST_RET(card->ctx, r, "entersafe gen random failed");
186
187
0
  if (apdu.resplen != size)
188
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
189
0
  memcpy(buff, rbuf, size);
190
191
0
  LOG_FUNC_RETURN(card->ctx, r);
192
0
}
193
194
static int entersafe_cipher_apdu(sc_card_t *card, sc_apdu_t *apdu,
195
                 u8 *key, size_t keylen,
196
                 u8 *buff, size_t buffsize)
197
0
{
198
0
  EVP_CIPHER_CTX *ctx = NULL;
199
0
  EVP_CIPHER *alg = NULL;
200
201
0
  u8 iv[8] = {0};
202
0
  int len;
203
204
0
  if (card == NULL || apdu == NULL || key == NULL || buff == NULL)
205
0
    return SC_ERROR_INTERNAL;
206
207
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
208
209
  /* padding as 0x80 0x00 0x00...... */
210
0
  memset(buff, 0, buffsize);
211
0
  buff[0] = apdu->lc;
212
0
  memcpy(buff + 1, apdu->data, apdu->lc);
213
0
  buff[apdu->lc + 1] = 0x80;
214
215
0
  ctx = EVP_CIPHER_CTX_new();
216
0
  if (ctx == NULL) {
217
0
    sc_log_openssl(card->ctx);
218
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
219
0
  }
220
0
  EVP_CIPHER_CTX_set_padding(ctx, 0);
221
222
0
  if (keylen == 8) {
223
0
    alg = sc_evp_cipher(card->ctx, "DES-ECB");
224
0
  } else if (keylen == 16) {
225
0
    alg = sc_evp_cipher(card->ctx, "DES-EDE");
226
0
  } else {
227
0
    EVP_CIPHER_CTX_free(ctx);
228
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
229
0
  }
230
231
0
  if (EVP_EncryptInit_ex(ctx, alg, NULL, key, iv) != 1) {
232
0
    sc_log_openssl(card->ctx);
233
0
    sc_evp_cipher_free(alg);
234
0
    EVP_CIPHER_CTX_free(ctx);
235
0
    sc_log(card->ctx, "entersafe encryption error.");
236
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
237
0
  }
238
239
0
  len = (int)apdu->lc;
240
0
  if (!EVP_EncryptUpdate(ctx, buff, &len, buff, (int)buffsize)) {
241
0
    sc_log_openssl(card->ctx);
242
0
    sc_evp_cipher_free(alg);
243
0
    EVP_CIPHER_CTX_free(ctx);
244
0
    sc_log(card->ctx, "entersafe encryption error.");
245
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INTERNAL);
246
0
  }
247
0
  apdu->lc = len;
248
249
0
  sc_evp_cipher_free(alg);
250
0
  EVP_CIPHER_CTX_free(ctx);
251
252
0
  if (apdu->lc != buffsize) {
253
0
    sc_log(card->ctx, "entersafe build cipher apdu failed.");
254
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INTERNAL);
255
0
  }
256
257
0
  apdu->data = buff;
258
0
  apdu->datalen = apdu->lc;
259
260
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
261
0
}
262
263
static int entersafe_mac_apdu(sc_card_t *card, sc_apdu_t *apdu,
264
                u8 * key,size_t keylen,
265
                u8 * buff,size_t buffsize)
266
0
{
267
0
  int r;
268
0
  u8 iv[8];
269
0
  u8 *tmp = NULL, *tmp_rounded = NULL;
270
0
  size_t tmpsize = 0, tmpsize_rounded = 0;
271
0
  int outl = 0;
272
0
  EVP_CIPHER_CTX *ctx = NULL;
273
0
  EVP_CIPHER *alg = NULL;
274
275
0
  if (card == NULL || apdu == NULL || key == NULL || buff == NULL)
276
0
    return SC_ERROR_INTERNAL;
277
278
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
279
280
0
  if (apdu->cse != SC_APDU_CASE_3_SHORT)
281
0
    return SC_ERROR_INTERNAL;
282
0
  if (keylen != 8 && keylen != 16)
283
0
    return SC_ERROR_INTERNAL;
284
285
0
  r = entersafe_gen_random(card, iv, sizeof(iv));
286
0
  LOG_TEST_RET(card->ctx, r, "entersafe gen random failed");
287
288
  /* encode the APDU in the buffer */
289
0
  if ((r = sc_apdu_get_octets(card->ctx, apdu, &tmp, &tmpsize, SC_PROTO_RAW)) != SC_SUCCESS)
290
0
    goto out;
291
292
  /* round to 8 */
293
0
  tmpsize_rounded = (tmpsize / 8 + 1) * 8;
294
295
0
  tmp_rounded = malloc(tmpsize_rounded);
296
0
  if (tmp_rounded == NULL) {
297
0
    r = SC_ERROR_OUT_OF_MEMORY;
298
0
    goto out;
299
0
  }
300
301
  /* build content and padded buffer by 0x80 0x00 0x00..... */
302
0
  memset(tmp_rounded, 0, tmpsize_rounded);
303
0
  memcpy(tmp_rounded, tmp, tmpsize);
304
0
  tmp_rounded[4] += 4;
305
0
  tmp_rounded[tmpsize] = 0x80;
306
307
  /* block_size-1 blocks*/
308
0
  ctx = EVP_CIPHER_CTX_new();
309
0
  if (ctx == NULL) {
310
0
    r = SC_ERROR_OUT_OF_MEMORY;
311
0
    sc_log_openssl(card->ctx);
312
0
    goto out;
313
0
  }
314
0
  EVP_CIPHER_CTX_set_padding(ctx, 0);
315
0
  alg = sc_evp_cipher(card->ctx, "DES-CBC");
316
0
  if (!alg ||
317
0
      EVP_EncryptInit_ex(ctx, alg, NULL, key, iv) != 1) {
318
0
    r = SC_ERROR_INTERNAL;
319
0
    sc_log_openssl(card->ctx);
320
0
    goto out;
321
0
  }
322
323
0
  if (tmpsize_rounded > 8) {
324
0
    if (!EVP_EncryptUpdate(ctx, tmp_rounded, &outl, tmp_rounded, (int)tmpsize_rounded - 8)) {
325
0
      r = SC_ERROR_INTERNAL;
326
0
      sc_log_openssl(card->ctx);
327
0
      goto out;
328
0
    }
329
0
  }
330
  /* last block */
331
0
  if (keylen == 8) {
332
0
    if (!EVP_EncryptUpdate(ctx, tmp_rounded + outl, &outl, tmp_rounded + outl, 8)) {
333
0
      r = SC_ERROR_INTERNAL;
334
0
      sc_log_openssl(card->ctx);
335
0
      goto out;
336
0
    }
337
0
  } else {
338
0
    if (EVP_EncryptInit_ex(ctx, EVP_des_ede_cbc(), NULL, key, tmp_rounded + outl - 8) != 1 ||
339
0
        !EVP_EncryptUpdate(ctx, tmp_rounded + outl, &outl, tmp_rounded + outl, 8)) {
340
0
      r = SC_ERROR_INTERNAL;
341
0
      sc_log_openssl(card->ctx);
342
0
      goto out;
343
0
    }
344
0
  }
345
346
0
  if (apdu->lc + 4 > buffsize) {
347
0
    r = SC_ERROR_INVALID_DATA;
348
0
    goto out;
349
0
  }
350
351
0
  memcpy(buff, apdu->data, apdu->lc);
352
  /* use first 4 bytes of last block as mac value */
353
0
  memcpy(buff + apdu->lc, tmp_rounded + tmpsize_rounded - 8, 4);
354
0
  apdu->data = buff;
355
0
  apdu->lc += 4;
356
0
  apdu->datalen = apdu->lc;
357
358
0
out:
359
0
  free(tmp);
360
0
  free(tmp_rounded);
361
0
  sc_evp_cipher_free(alg);
362
0
  EVP_CIPHER_CTX_free(ctx);
363
364
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
365
0
}
366
367
static int entersafe_transmit_apdu(sc_card_t *card, sc_apdu_t *apdu,
368
                   u8 * key, size_t keylen,
369
                   int cipher, int mac)
370
0
{
371
0
  u8 *cipher_data = NULL, *mac_data = NULL;
372
0
  size_t cipher_data_size, mac_data_size, blocks;
373
0
  int r = SC_SUCCESS;
374
0
  u8 *sbuf = NULL;
375
0
  size_t ssize = 0;
376
377
0
  if (card == NULL || apdu == NULL)
378
0
    return SC_ERROR_INTERNAL;
379
380
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
381
382
0
  if ((cipher || mac) && (!key || (keylen != 8 && keylen != 16)))
383
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
384
385
0
  r = sc_apdu_get_octets(card->ctx, apdu, &sbuf, &ssize, SC_PROTO_RAW);
386
0
  if (r == SC_SUCCESS)
387
0
    sc_apdu_log(card->ctx, sbuf, ssize, 1);
388
0
  if (sbuf)
389
0
    free(sbuf);
390
391
0
  if (cipher) {
392
0
    blocks = (apdu->lc + 2) / 8 + 1;
393
0
    cipher_data_size = blocks * 8;
394
0
    cipher_data = malloc(cipher_data_size);
395
0
    if (!cipher_data) {
396
0
      r = SC_ERROR_OUT_OF_MEMORY;
397
0
      goto out;
398
0
    }
399
400
0
    if ((r = entersafe_cipher_apdu(card, apdu, key, keylen, cipher_data, cipher_data_size)) < 0)
401
0
      goto out;
402
0
  }
403
0
  if (mac) {
404
0
    mac_data_size = apdu->lc + 4;
405
0
    mac_data = malloc(mac_data_size);
406
0
    if (!mac_data) {
407
0
      r = SC_ERROR_OUT_OF_MEMORY;
408
0
      goto out;
409
0
    }
410
0
    r = entersafe_mac_apdu(card, apdu, key, keylen, mac_data, mac_data_size);
411
0
    if (r < 0)
412
0
      goto out;
413
0
  }
414
415
0
  r = sc_transmit_apdu(card, apdu);
416
417
0
out:
418
0
  free(cipher_data);
419
0
  free(mac_data);
420
421
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
422
0
}
423
424
static int entersafe_read_binary(sc_card_t *card,
425
                 unsigned int idx, u8 *buf, size_t count,
426
                 unsigned long *flags)
427
0
{
428
0
  sc_apdu_t apdu;
429
0
  u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
430
0
  int r;
431
432
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
433
434
0
  if (count > card->max_recv_size)
435
0
    return SC_ERROR_INTERNAL;
436
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0, (idx >> 8) & 0xFF, idx & 0xFF);
437
438
0
  apdu.cla = idx > 0x7fff ? 0x80 : 0x00;
439
0
  apdu.le = count;
440
0
  apdu.resplen = count;
441
0
  apdu.resp = recvbuf;
442
443
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
444
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
445
0
  if (apdu.resplen == 0)
446
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
447
0
  memcpy(buf, recvbuf, apdu.resplen);
448
449
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)apdu.resplen);
450
0
}
451
452
static int entersafe_update_binary(sc_card_t *card,
453
                   unsigned int idx, const u8 *buf,
454
                   size_t count, unsigned long flags)
455
0
{
456
0
  sc_apdu_t apdu;
457
0
  int r;
458
459
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
460
461
0
  if (count > card->max_send_size)
462
0
    return SC_ERROR_INTERNAL;
463
464
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6, (idx >> 8) & 0xFF, idx & 0xFF);
465
0
  apdu.cla = idx > 0x7fff ? 0x80 : 0x00;
466
0
  apdu.lc = count;
467
0
  apdu.datalen = count;
468
0
  apdu.data = buf;
469
470
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
471
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
472
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
473
0
        "Card returned error");
474
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)count);
475
0
}
476
477
static int entersafe_process_fci(struct sc_card *card, struct sc_file *file,
478
                 const u8 *buf, size_t buflen)
479
0
{
480
0
  int r;
481
482
0
  if (file == NULL)
483
0
    return SC_ERROR_INTERNAL;
484
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
485
486
0
  r = iso_ops->process_fci(card, file, buf, buflen);
487
0
  LOG_TEST_RET(card->ctx, r, "Process fci failed");
488
489
0
  if (file->namelen) {
490
0
    file->type = SC_FILE_TYPE_DF;
491
0
    file->ef_structure = SC_FILE_EF_UNKNOWN;
492
0
  } else {
493
0
    file->type = SC_FILE_TYPE_WORKING_EF;
494
0
    file->ef_structure = SC_FILE_EF_TRANSPARENT;
495
0
  }
496
497
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
498
0
}
499
500
static int entersafe_select_fid(sc_card_t *card,
501
                unsigned int id_hi, unsigned int id_lo,
502
                sc_file_t **file_out)
503
0
{
504
0
  int r;
505
0
  sc_file_t *file = NULL;
506
0
  sc_path_t path;
507
508
0
  memset(&path, 0, sizeof(sc_path_t));
509
510
0
  path.type = SC_PATH_TYPE_FILE_ID;
511
0
  path.value[0] = id_hi;
512
0
  path.value[1] = id_lo;
513
0
  path.len = 2;
514
515
0
  r = iso_ops->select_file(card, &path, &file);
516
0
  if (r < 0)
517
0
    sc_file_free(file);
518
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
519
520
0
  if (file_out)
521
0
    *file_out = file;
522
0
  else
523
0
    sc_file_free(file);
524
525
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
526
0
}
527
528
static int entersafe_select_aid(sc_card_t *card,
529
                const sc_path_t *in_path,
530
                sc_file_t **file_out)
531
0
{
532
0
  int r;
533
534
0
  r = iso_ops->select_file(card, in_path, file_out);
535
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
536
537
0
  if (file_out) {
538
0
    sc_file_t *file = *file_out;
539
0
    if (file == NULL)
540
0
      return SC_ERROR_INTERNAL;
541
542
0
    file->type = SC_FILE_TYPE_DF;
543
0
    file->ef_structure = SC_FILE_EF_UNKNOWN;
544
0
    file->path.len = 0;
545
0
    file->size = 0;
546
    /* AID */
547
0
    memcpy(file->name, in_path->value, in_path->len);
548
0
    file->namelen = in_path->len;
549
0
    file->id = 0x0000;
550
0
  }
551
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
552
0
}
553
554
static int entersafe_select_path(sc_card_t *card,
555
                const u8 pathbuf[16], const size_t len,
556
                sc_file_t **file_out)
557
0
{
558
0
  u8 n_pathbuf[SC_MAX_PATH_SIZE];
559
0
  const u8 *path = pathbuf;
560
0
  size_t pathlen = len;
561
0
  unsigned int i;
562
0
  int r;
563
564
0
  if (pathlen % 2 != 0 || pathlen > 6 || pathlen <= 0)
565
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
566
567
  /* if pathlen == 6 then the first FID must be MF (== 3F00) */
568
0
  if (pathlen == 6 && (path[0] != 0x3f || path[1] != 0x00))
569
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
570
571
  /* unify path (the first FID should be MF) */
572
0
  if (path[0] != 0x3f || path[1] != 0x00) {
573
0
    n_pathbuf[0] = 0x3f;
574
0
    n_pathbuf[1] = 0x00;
575
0
    memcpy(n_pathbuf + 2, path, pathlen);
576
0
    path = n_pathbuf;
577
0
    pathlen += 2;
578
0
  }
579
580
0
  for (i = 0; i < pathlen - 2; i += 2) {
581
0
    r = entersafe_select_fid(card, path[i], path[i + 1], NULL);
582
0
    LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
583
0
  }
584
0
  return entersafe_select_fid(card, path[pathlen - 2], path[pathlen - 1], file_out);
585
0
}
586
587
static int entersafe_select_file(sc_card_t *card,
588
                const sc_path_t *in_path,
589
                sc_file_t **file_out)
590
0
{
591
0
  if (card == NULL || in_path == NULL)
592
0
    return SC_ERROR_INTERNAL;
593
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
594
595
0
  switch (in_path->type) {
596
0
    case SC_PATH_TYPE_FILE_ID:
597
0
      if (in_path->len != 2)
598
0
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
599
0
      return entersafe_select_fid(card,in_path->value[0], in_path->value[1], file_out);
600
0
    case SC_PATH_TYPE_DF_NAME:
601
0
      return entersafe_select_aid(card, in_path, file_out);
602
0
    case SC_PATH_TYPE_PATH:
603
0
      return entersafe_select_path(card, in_path->value, in_path->len, file_out);
604
0
    default:
605
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
606
0
  }
607
0
}
608
609
static int entersafe_create_mf(sc_card_t *card, sc_entersafe_create_data *data)
610
0
{
611
0
  int r;
612
0
  sc_apdu_t apdu;
613
614
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
615
616
0
  memcpy(data->data.df.init_key, init_key, sizeof(init_key));
617
618
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
619
0
  apdu.cla = 0x84;
620
0
  apdu.data = (u8 *)&data->data.df;
621
0
  apdu.datalen = apdu.lc = sizeof(data->data.df);
622
623
0
  switch(card->type) {
624
0
    case SC_CARD_TYPE_ENTERSAFE_3K:
625
0
      r = entersafe_transmit_apdu(card, &apdu, trans_code_3k, sizeof(trans_code_3k), 0, 1);
626
0
      break;
627
0
    case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C:
628
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C:
629
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0:
630
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1:
631
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1:
632
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1:
633
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1:
634
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1:
635
0
      r = entersafe_transmit_apdu(card, &apdu, trans_code_ftcos_pk_01c, sizeof(trans_code_ftcos_pk_01c), 0, 1);
636
0
      break;
637
0
    default:
638
0
      r = SC_ERROR_INTERNAL;
639
0
      break;
640
0
  }
641
642
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
643
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
644
0
}
645
646
static int entersafe_create_df(sc_card_t *card, sc_entersafe_create_data *data)
647
0
{
648
0
  int r;
649
0
  sc_apdu_t apdu;
650
651
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
652
653
0
  memcpy(data->data.df.init_key, init_key, sizeof(init_key));
654
655
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x01, 0x00);
656
0
  apdu.cla = 0x84;
657
0
  apdu.data = (u8 *)&data->data.df;
658
0
  apdu.lc = apdu.datalen = sizeof(data->data.df);
659
660
0
  r = entersafe_transmit_apdu(card, &apdu,init_key,sizeof(init_key),0,1);
661
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
662
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
663
0
}
664
665
static int entersafe_create_ef(sc_card_t *card, sc_entersafe_create_data *data)
666
0
{
667
0
  int r;
668
0
  sc_apdu_t apdu;
669
670
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
671
672
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x02, 0x00);
673
0
  apdu.cla = 0x84;
674
0
  apdu.data = (u8*)&data->data.ef;
675
0
  apdu.lc = apdu.datalen = sizeof(data->data.ef);
676
677
0
  r = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
678
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
679
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
680
0
}
681
682
static u8 process_acl_entry(sc_file_t *in, unsigned int method, unsigned int in_def)
683
0
{
684
0
  u8 def = (u8)in_def;
685
0
  const sc_acl_entry_t *entry = sc_file_get_acl_entry(in, method);
686
0
  if (!entry) {
687
0
    return def;
688
0
  } else if (entry->method & SC_AC_CHV) {
689
0
    unsigned int key_ref = entry->key_ref;
690
0
    if (key_ref == SC_AC_KEY_REF_NONE)
691
0
      return def;
692
0
    else
693
0
      return ENTERSAFE_AC_ALWAYS&0x04;
694
0
  } else if (entry->method & SC_AC_NEVER) {
695
0
    return ENTERSAFE_AC_NEVER;
696
0
  }
697
0
  return def;
698
0
}
699
700
static int entersafe_create_file(sc_card_t *card, sc_file_t *file)
701
0
{
702
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
703
704
0
  if (file->type == SC_FILE_TYPE_WORKING_EF) {
705
0
    sc_entersafe_create_data data;
706
0
    memset(&data, 0, sizeof(data));
707
708
0
    data.data.ef.file_id[0] = (file->id >> 8) & 0xFF;
709
0
    data.data.ef.file_id[1] = file->id & 0xFF;
710
0
    data.data.ef.size[0] = (file->size >> 8) & 0xFF;
711
0
    data.data.ef.size[1] = file->size & 0xFF;
712
0
    memset(data.data.ef.ac, ENTERSAFE_AC_ALWAYS, sizeof(data.data.ef.ac));
713
0
    data.data.ef.ac[0] = process_acl_entry(file, SC_AC_OP_READ, ENTERSAFE_AC_ALWAYS);
714
0
    data.data.ef.ac[1] = process_acl_entry(file, SC_AC_OP_UPDATE, ENTERSAFE_AC_ALWAYS);
715
716
0
    return entersafe_create_ef(card, &data);
717
0
  } else {
718
0
    return SC_ERROR_INVALID_ARGUMENTS;
719
0
  }
720
0
}
721
722
static int entersafe_internal_set_security_env(sc_card_t *card,
723
                         const sc_security_env_t *env,
724
                         u8 ** data,size_t* size)
725
0
{
726
0
  sc_apdu_t apdu;
727
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
728
0
  u8 *p = sbuf;
729
0
  int r;
730
731
0
  if (card == NULL || env == NULL)
732
0
    return SC_ERROR_INTERNAL;
733
734
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
735
736
0
  switch (env->operation) {
737
0
    case SC_SEC_OPERATION_DECIPHER:
738
0
    case SC_SEC_OPERATION_SIGN:
739
0
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
740
0
      apdu.p1 = 0x41;
741
0
      apdu.p2 = 0xB8;
742
0
      *p++ = 0x80;
743
0
      *p++ = 0x01;
744
0
      *p++ = 0x80;
745
0
      *p++ = 0x83;
746
0
      *p++ = 0x02;
747
0
      *p++ = env->key_ref[0];
748
0
      *p++ = 0x22;
749
0
      if (*size > 1024 / 8) {
750
0
        if (*size == 2048 / 8) {
751
0
          *p++ = 0x89;
752
0
          *p++ = 0x40;
753
0
          memcpy(p, *data, 0x40);
754
0
          p += 0x40;
755
0
          *data += 0x40;
756
0
          *size -= 0x40;
757
0
        } else {
758
0
          SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
759
0
        }
760
0
      }
761
0
      break;
762
0
    default:
763
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
764
0
  }
765
766
0
  apdu.le = 0;
767
0
  apdu.lc = apdu.datalen = p - sbuf;
768
0
  apdu.data = sbuf;
769
0
  apdu.resplen = 0;
770
771
0
  r = sc_transmit_apdu(card, &apdu);
772
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
773
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
774
0
}
775
776
/**
777
 * We don't really set the security environment,but cache it.It will be set when
778
 * security operation is performed later.Because we may transport partial of
779
 * the sign/decipher data within the security environment apdu.
780
 */
781
static int entersafe_set_security_env(sc_card_t *card,
782
                    const sc_security_env_t *env,
783
                    int se_num)
784
0
{
785
0
  if (card == NULL || env == NULL)
786
0
    return SC_ERROR_INTERNAL;
787
788
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
789
790
0
  if (card->drv_data) {
791
0
    free(card->drv_data);
792
0
    card->drv_data = 0;
793
0
  }
794
795
0
  card->drv_data = calloc(1, sizeof(*env));
796
0
  if (!card->drv_data)
797
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
798
799
0
  memcpy(card->drv_data, env, sizeof(*env));
800
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
801
0
}
802
803
static int entersafe_restore_security_env(sc_card_t *card, int se_num)
804
0
{
805
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
806
0
  return SC_SUCCESS;
807
0
}
808
809
810
static int entersafe_compute_with_prkey(sc_card_t *card,
811
                    const u8 *data, size_t datalen,
812
                    u8 *out, size_t outlen)
813
0
{
814
0
  int r;
815
0
  sc_apdu_t apdu;
816
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
817
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
818
0
  u8 *p = sbuf;
819
0
  size_t size = datalen;
820
821
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
822
823
0
  if (!data || datalen > SC_MAX_APDU_BUFFER_SIZE)
824
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
825
826
0
  memcpy(p,data,size);
827
828
0
  if (!card->drv_data)
829
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INTERNAL);
830
831
0
  r = entersafe_internal_set_security_env(card, card->drv_data, &p, &size);
832
0
  LOG_TEST_RET(card->ctx, r, "internal set security env failed");
833
834
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x86, 0x80);
835
0
  apdu.data = p;
836
0
  apdu.lc = size;
837
0
  apdu.datalen = size;
838
0
  apdu.resp = rbuf;
839
0
  apdu.resplen = sizeof(rbuf);
840
0
  apdu.le = 256;
841
842
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
843
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
844
845
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
846
0
    size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
847
0
    memcpy(out, apdu.resp, len);
848
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
849
0
  }
850
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
851
0
}
852
853
static int entersafe_compute_signature(sc_card_t *card,
854
                     const u8 * data, size_t datalen,
855
                     u8 * out, size_t outlen)
856
0
{
857
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
858
0
  return entersafe_compute_with_prkey(card, data, datalen, out, outlen);
859
0
}
860
861
static int entersafe_decipher(sc_card_t *card,
862
                const u8 *crgram, size_t crgram_len,
863
                u8 *out, size_t outlen)
864
0
{
865
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
866
0
  return entersafe_compute_with_prkey(card, crgram, crgram_len, out, outlen);
867
0
}
868
869
static void entersafe_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
870
0
{
871
0
  pin->encoding   = SC_PIN_ENCODING_ASCII;
872
0
  pin->min_length = 4;
873
0
  pin->max_length = 16;
874
0
  pin->pad_length = 16;
875
0
  pin->offset     = 5 + num * 16;
876
0
  pin->pad_char   = 0x00;
877
0
}
878
879
static int entersafe_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data)
880
0
{
881
0
  int r;
882
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
883
0
  entersafe_init_pin_info(&data->pin1, 0);
884
0
  entersafe_init_pin_info(&data->pin2, 1);
885
0
  data->flags |= SC_PIN_CMD_NEED_PADDING;
886
887
0
  if (data->cmd != SC_PIN_CMD_UNBLOCK) {
888
0
    r = iso_ops->pin_cmd(card, data);
889
0
    sc_log(card->ctx, "Verify rv:%i", r);
890
0
  } else {
891
0
    { /*verify*/
892
0
      sc_apdu_t apdu;
893
0
      u8 sbuf[0x10] = {0};
894
895
0
      if (data->pin1.len > sizeof(sbuf)) {
896
0
        return SC_ERROR_INVALID_DATA;
897
0
      }
898
899
0
      memcpy(sbuf, data->pin1.data, data->pin1.len);
900
0
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x20, 0x00, data->pin_reference + 1);
901
0
      apdu.lc = apdu.datalen = sizeof(sbuf);
902
0
      apdu.data = sbuf;
903
904
0
      r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
905
0
      LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
906
0
    }
907
908
0
    { /*change*/
909
0
      sc_apdu_t apdu;
910
0
      u8 sbuf[0x12] = {0};
911
912
0
      if (data->pin2.len + 2 > sizeof(sbuf)) {
913
0
        return SC_ERROR_INVALID_DATA;
914
0
      }
915
916
0
      sbuf[0] = 0x33;
917
0
      sbuf[1] = 0x00;
918
0
      memcpy(sbuf + 2, data->pin2.data, data->pin2.len);
919
0
      sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF4, 0x0B, data->pin_reference);
920
0
      apdu.cla = 0x84;
921
0
      apdu.lc = apdu.datalen = sizeof(sbuf);
922
0
      apdu.data = sbuf;
923
924
0
      r = entersafe_transmit_apdu(card, &apdu, key_maintain, sizeof(key_maintain), 1, 1);
925
0
      LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
926
0
    }
927
0
  }
928
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
929
0
}
930
931
static int entersafe_erase_card(sc_card_t *card)
932
0
{
933
0
  int r;
934
0
  u8  sbuf[2];
935
0
  sc_apdu_t apdu;
936
937
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
938
939
0
  sbuf[0] = 0x3f;
940
0
  sbuf[1] = 0x00;
941
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x00);
942
0
  apdu.lc = 2;
943
0
  apdu.datalen = 2;
944
0
  apdu.data = sbuf;
945
946
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
947
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
948
949
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xEE, 0x00, 0x00);
950
0
  apdu.cla = 0x84;
951
0
  apdu.lc = 2;
952
0
  apdu.datalen = 2;
953
0
  apdu.data = sbuf;
954
955
0
  switch(card->type) {
956
0
    case SC_CARD_TYPE_ENTERSAFE_3K:
957
0
      r = entersafe_transmit_apdu(card, &apdu, trans_code_3k, sizeof(trans_code_3k), 0, 1);
958
0
      break;
959
0
    case SC_CARD_TYPE_ENTERSAFE_FTCOS_PK_01C:
960
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C:
961
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_PK_01C_T0:
962
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_H10CR_PK_01C_T1:
963
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_D11CR_PK_01C_T1:
964
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_C21C_PK_01C_T1:
965
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_A22CR_PK_01C_T1:
966
0
    case SC_CARD_TYPE_ENTERSAFE_EJAVA_A40CR_PK_01C_T1:
967
0
      r = entersafe_transmit_apdu(card, &apdu, trans_code_ftcos_pk_01c, sizeof(trans_code_ftcos_pk_01c), 0, 1);
968
0
      break;
969
0
    default:
970
0
      r = SC_ERROR_INTERNAL;
971
0
      break;
972
0
  }
973
974
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
975
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
976
0
}
977
978
static int
979
entersafe_encode_bignum(u8 tag, sc_pkcs15_bignum_t bignum, u8 **ptr, size_t *ptrlen)
980
0
{
981
0
  u8 *p = *ptr;
982
983
  /* lower bound for 1B length encoding */
984
0
  if (*ptrlen < bignum.len + 2) {
985
0
    return SC_ERROR_INVALID_DATA;
986
0
  }
987
988
0
  *p++ = tag;
989
0
  *ptrlen -= 1;
990
0
  if (bignum.len < 128) {
991
0
    *p++ = (u8)bignum.len;
992
0
    *ptrlen -= 1;
993
0
  } else {
994
0
    u8 bytes = 1;
995
0
    size_t len = bignum.len;
996
0
    while (len) {
997
0
      len = len >> 8;
998
0
      ++bytes;
999
0
    }
1000
0
    bytes &= 0x0F;
1001
0
    *p++ = 0x80 | bytes;
1002
0
    *ptrlen -= 1;
1003
0
    while (bytes) {
1004
0
      *p++ = bignum.len >> ((bytes - 1) * 8);
1005
0
      *ptrlen -= 1;
1006
0
      --bytes;
1007
0
    }
1008
0
  }
1009
  /* Tag and length bytes already counted and checked */
1010
0
  if (*ptrlen < bignum.len) {
1011
0
    return SC_ERROR_INVALID_DATA;
1012
0
  }
1013
1014
0
  memcpy(p, bignum.data, bignum.len);
1015
0
  entersafe_reverse_buffer(p, bignum.len);
1016
0
  p += bignum.len;
1017
0
  *ptr = p;
1018
0
  *ptrlen -= bignum.len;
1019
1020
0
  return SC_SUCCESS;
1021
0
}
1022
1023
static int entersafe_write_small_rsa_key(sc_card_t *card, u8 key_id, struct sc_pkcs15_prkey_rsa *rsa)
1024
0
{
1025
0
  sc_apdu_t apdu;
1026
0
  u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
1027
0
  int r;
1028
0
  u8 *p = sbuff;
1029
0
  size_t buflen = sizeof(sbuff);
1030
1031
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1032
1033
0
  { /* write prkey */
1034
0
    *p++ = 0x00;      /* EC */
1035
0
    *p++ = 0x00;      /* ver */
1036
0
    r = entersafe_encode_bignum('E', rsa->exponent, &p, &buflen);
1037
0
    LOG_TEST_RET(card->ctx, r, "Failed to encode bignum. Buffer too small?");
1038
0
    r = entersafe_encode_bignum('D', rsa->d, &p, &buflen);
1039
0
    LOG_TEST_RET(card->ctx, r, "Failed to encode bignum. Buffer too small?");
1040
1041
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF4, 0x22, key_id);
1042
0
    apdu.cla = 0x84;
1043
0
    apdu.data = sbuff;
1044
0
    apdu.lc = apdu.datalen = p - sbuff;
1045
1046
0
    r = entersafe_transmit_apdu(card, &apdu, key_maintain, sizeof(key_maintain), 1, 1);
1047
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1048
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write prkey failed");
1049
0
  }
1050
1051
0
  p = sbuff;
1052
0
  { /* write pukey */
1053
0
    *p++ = 0x00;      /* EC */
1054
0
    *p++ = 0x00;      /* ver */
1055
0
    r = entersafe_encode_bignum('E', rsa->exponent, &p, &buflen);
1056
0
    LOG_TEST_RET(card->ctx, r, "Failed to encode bignum. Buffer too small?");
1057
0
    r = entersafe_encode_bignum('N', rsa->modulus, &p, &buflen);
1058
0
    LOG_TEST_RET(card->ctx, r, "Failed to encode bignum. Buffer too small?");
1059
1060
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF4, 0x2A, key_id);
1061
0
    apdu.cla = 0x84;
1062
0
    apdu.data = sbuff;
1063
0
    apdu.lc = apdu.datalen = p - sbuff;
1064
1065
0
    r = entersafe_transmit_apdu(card, &apdu, key_maintain, sizeof(key_maintain), 1, 1);
1066
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1067
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write pukey failed");
1068
0
  }
1069
1070
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1071
0
}
1072
1073
static int entersafe_write_rsa_key_factor(sc_card_t *card,
1074
                      u8 key_id,u8 usage,
1075
                      u8 factor,
1076
                      sc_pkcs15_bignum_t data)
1077
0
{
1078
0
  int r;
1079
0
  sc_apdu_t apdu;
1080
1081
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1082
1083
0
  { /* MSE */
1084
0
    u8 sbuff[4];
1085
0
    sbuff[0] = 0x84;
1086
0
    sbuff[1] = 0x02;
1087
0
    sbuff[2] = key_id;
1088
0
    sbuff[3] = usage;
1089
1090
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x01, 0xB8);
1091
0
    apdu.data = sbuff;
1092
0
    apdu.lc = apdu.datalen = 4;
1093
1094
0
    r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1095
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1096
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write prkey factor failed(MSE)");
1097
0
  }
1098
1099
0
  { /* Write 'x'; */
1100
0
    u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
1101
1102
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, factor, 0x00);
1103
1104
0
    memcpy(sbuff, data.data, data.len);
1105
0
    entersafe_reverse_buffer(sbuff, data.len);
1106
/*
1107
 *  PK01C and PK13C smart card only support 1024 or 2048bit key .
1108
 *  Size of exponent1 exponent2 coefficient of RSA private key keep the same as size of prime1
1109
 *  So check factor is padded with zero or not
1110
 */
1111
0
    switch(factor) {
1112
0
      case 0x3:
1113
0
      case 0x4:
1114
0
      case 0x5: {
1115
0
          size_t i;
1116
0
          if (data.len > 32 && data.len < 64) {
1117
0
            for (i = data.len; i < 64; i++)
1118
0
              sbuff[i] = 0;
1119
0
            data.len = 64;
1120
0
          } else if( data.len > 64 && data.len < 128 ) {
1121
0
            for (i = data.len; i < 128; i++)
1122
0
              sbuff[i] = 0;
1123
0
            data.len = 128;
1124
0
          }
1125
0
        }
1126
0
        break;
1127
0
      default:
1128
0
        break;
1129
0
    }
1130
1131
0
    apdu.data = sbuff;
1132
0
    apdu.lc = apdu.datalen = data.len;
1133
1134
0
    r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1135
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1136
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write prkey factor failed");
1137
0
  }
1138
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1139
0
}
1140
1141
static int entersafe_write_large_rsa_key(sc_card_t *card,u8 key_id,struct sc_pkcs15_prkey_rsa *rsa)
1142
0
{
1143
0
  int r;
1144
1145
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1146
1147
0
  { /* write prkey */
1148
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x22, 0x01, rsa->p);
1149
0
    LOG_TEST_RET(card->ctx, r, "write p failed");
1150
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x22, 0x02, rsa->q);
1151
0
    LOG_TEST_RET(card->ctx, r, "write q failed");
1152
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x22, 0x03, rsa->dmp1);
1153
0
    LOG_TEST_RET(card->ctx, r, "write dmp1 failed");
1154
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x22, 0x04, rsa->dmq1);
1155
0
    LOG_TEST_RET(card->ctx, r, "write dmq1 failed");
1156
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x22, 0x05, rsa->iqmp);
1157
0
    LOG_TEST_RET(card->ctx, r, "write iqmp failed");
1158
0
  }
1159
1160
0
  { /* write pukey */
1161
0
    u8 sbuff[SC_MAX_APDU_BUFFER_SIZE];
1162
0
    sc_apdu_t apdu;
1163
1164
    /* first 64(0x40) bytes of N */
1165
0
    sbuff[0] = 0x83;
1166
0
    sbuff[1] = 0x02;
1167
0
    sbuff[2] = key_id;
1168
0
    sbuff[3] = 0x2A;
1169
0
    sbuff[4] = 0x89;
1170
0
    sbuff[5] = 0x40;
1171
0
    memcpy(sbuff + 6, rsa->modulus.data, 0x40);
1172
1173
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x01, 0xB8);
1174
0
    apdu.data = sbuff;
1175
0
    apdu.lc = apdu.datalen = 0x46;
1176
1177
0
    r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1178
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1179
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write pukey N(1) failed");
1180
1181
    /* left 192(0xC0) bytes of N */
1182
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x0B, 0x00);
1183
0
    apdu.data = rsa->modulus.data + 0x40;
1184
0
    apdu.lc = apdu.datalen = 0xC0;
1185
1186
0
    r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1187
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1188
0
    LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write pukey N(2) failed");
1189
1190
    /* E */
1191
0
    r = entersafe_write_rsa_key_factor(card, key_id, 0x2A, 0x0D, rsa->exponent);
1192
0
    LOG_TEST_RET(card->ctx, r, "write exponent failed");
1193
0
  }
1194
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1195
0
}
1196
1197
static int entersafe_write_symmetric_key(sc_card_t *card,
1198
                     u8 key_id, u8 usage,
1199
                     u8 EC, u8 ver,
1200
                     u8 *data, size_t len)
1201
0
{
1202
0
  sc_apdu_t apdu;
1203
0
  u8 sbuff[SC_MAX_APDU_BUFFER_SIZE] = {0};
1204
0
  int r;
1205
1206
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1207
1208
0
  if (len > 240)
1209
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INCORRECT_PARAMETERS);
1210
1211
0
  sbuff[0] = EC;
1212
0
  sbuff[1] = ver;
1213
0
  memcpy(&sbuff[2], data, len);
1214
1215
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF4, usage, key_id);
1216
0
  apdu.cla = 0x84;
1217
0
  apdu.data = sbuff;
1218
0
  apdu.lc = apdu.datalen = len + 2;
1219
1220
0
  r = entersafe_transmit_apdu(card, &apdu, key_maintain, sizeof(key_maintain), 1, 1);
1221
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1222
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "Write prkey failed");
1223
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
1224
0
}
1225
1226
static int entersafe_write_key(sc_card_t *card, sc_entersafe_wkey_data *data)
1227
0
{
1228
0
  struct sc_pkcs15_prkey_rsa *rsa = data->key_data.rsa;
1229
1230
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1231
1232
0
  switch(data->usage) {
1233
0
    case 0x22:
1234
0
      if(rsa->modulus.len < 256)
1235
0
        return entersafe_write_small_rsa_key(card,data->key_id, rsa);
1236
0
      else
1237
0
        return entersafe_write_large_rsa_key(card,data->key_id, rsa);
1238
0
      break;
1239
0
    case 0x2A:
1240
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_NOT_SUPPORTED);
1241
0
      break;
1242
0
    default:
1243
0
      return entersafe_write_symmetric_key(card,data->key_id,data->usage,
1244
0
                        data->key_data.symmetric.EC,
1245
0
                        data->key_data.symmetric.ver,
1246
0
                        data->key_data.symmetric.key_val,
1247
0
                        data->key_data.symmetric.key_len);
1248
0
      break;
1249
0
  }
1250
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1251
0
}
1252
1253
static int entersafe_gen_key(sc_card_t *card, sc_entersafe_gen_key_data *data)
1254
0
{
1255
0
  int r;
1256
0
  size_t len = data->key_length >> 3;
1257
0
  sc_apdu_t apdu;
1258
0
  u8 rbuf[300] = {0};
1259
0
  u8 sbuf[4], *p;
1260
0
  size_t plen = 0;
1261
1262
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1263
1264
  /* MSE */
1265
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x01, 0xB8);
1266
0
  apdu.lc = 0x04;
1267
0
  sbuf[0] = 0x83;
1268
0
  sbuf[1] = 0x02;
1269
0
  sbuf[2] = data->key_id;
1270
0
  sbuf[3] = 0x2A;
1271
0
  apdu.data = sbuf;
1272
0
  apdu.datalen = 4;
1273
0
  apdu.lc = 4;
1274
0
  apdu.le = 0;
1275
1276
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1277
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1278
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "EnterSafe set MSE failed");
1279
1280
  /* generate key */
1281
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
1282
0
  apdu.le = 0;
1283
0
  sbuf[0] = (u8)(data->key_length >> 8);
1284
0
  sbuf[1] = (u8)(data->key_length);
1285
0
  apdu.data = sbuf;
1286
0
  apdu.lc = 2;
1287
0
  apdu.datalen = 2;
1288
1289
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1290
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1291
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "EnterSafe generate key pair failed");
1292
1293
  /* read public key via READ PUBLIC KEY */
1294
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xE6, 0x2A, data->key_id);
1295
0
  apdu.cla     = 0x80;
1296
0
  apdu.resp    = rbuf;
1297
0
  apdu.resplen = sizeof(rbuf);
1298
0
  apdu.le      = 256;
1299
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1300
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1301
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "EnterSafe get pukey failed");
1302
1303
0
  p = rbuf;
1304
0
  plen = apdu.resplen;
1305
0
  if (*p != 'E') {
1306
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1307
0
  }
1308
0
  if ((size_t)(p - rbuf) + 2 + p[1] >= plen) {
1309
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1310
0
  }
1311
0
  p += 2 + p[1];
1312
  /* N */
1313
0
  if (*p != 'N') {
1314
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1315
0
  }
1316
0
  if ((size_t)(p - rbuf) + 2 >= plen) {
1317
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1318
0
  }
1319
0
  ++p;
1320
0
  if (*p++ > 0x80) {
1321
0
    u8 len_bytes = (*(p - 1)) & 0x0f;
1322
0
    size_t module_len = 0;
1323
0
    if ((size_t)(p - rbuf) + len_bytes >= plen) {
1324
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1325
0
    }
1326
0
    while (len_bytes != 0) {
1327
0
      module_len = module_len << 8;
1328
0
      module_len += *p++;
1329
0
      --len_bytes;
1330
0
    }
1331
0
  }
1332
1333
0
  if ((p - rbuf) + len >= plen) {
1334
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_DATA);
1335
0
  }
1336
1337
0
  data->modulus = malloc(len);
1338
0
  if (!data->modulus)
1339
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_OUT_OF_MEMORY);
1340
0
  entersafe_reverse_buffer(p, len);
1341
0
  memcpy(data->modulus, p, len);
1342
1343
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1344
0
}
1345
1346
static int entersafe_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
1347
0
{
1348
0
  int r;
1349
0
  sc_apdu_t apdu;
1350
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
1351
1352
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1353
0
  if (serial == NULL)
1354
0
    return SC_ERROR_INTERNAL;
1355
1356
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xEA, 0x00, 0x00);
1357
0
  apdu.cla = 0x80;
1358
0
  apdu.resp = rbuf;
1359
0
  apdu.resplen = sizeof(rbuf);
1360
0
  apdu.le = 0x08;
1361
1362
0
  r = entersafe_transmit_apdu(card, &apdu, 0, 0, 0, 0);
1363
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1364
0
  LOG_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2), "EnterSafe get SN failed");
1365
0
  if (apdu.resplen != 8)
1366
0
    LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of SN");
1367
1368
0
  card->serialnr.len = serial->len = 8;
1369
0
  memcpy(card->serialnr.value, rbuf, 8);
1370
0
  memcpy(serial->value, rbuf, 8);
1371
1372
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1373
0
}
1374
1375
static int entersafe_preinstall_rsa_2048(sc_card_t *card, u8 key_id)
1376
0
{
1377
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1378
0
  sc_apdu_t apdu;
1379
0
  int ret = 0;
1380
0
  static u8 const rsa_key_e[] =
1381
0
  {
1382
0
    'E', 0x04, 0x01, 0x00, 0x01, 0x00
1383
0
  };
1384
1385
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1386
1387
  /* create rsa item in IKF */
1388
0
  sbuf[0] = 0x04; /* key len extern */
1389
0
  sbuf[1] = 0x0a; /* key len */
1390
0
  sbuf[2] = 0x22; /* USAGE */
1391
0
  sbuf[3] = 0x34; /* user ac */
1392
0
  sbuf[4] = 0x04; /* change ac */
1393
0
  sbuf[5] = 0x34; /* UPDATE AC */
1394
0
  sbuf[6] = 0x40; /* ALGO */
1395
0
  sbuf[7] = 0x00; /* EC */
1396
0
  sbuf[8] = 0x00; /* VER */
1397
0
  memcpy(&sbuf[9], rsa_key_e, sizeof(rsa_key_e));
1398
0
  sbuf[9 + sizeof(rsa_key_e) + 0] = 'C'+'R'+'T';
1399
0
  sbuf[9 + sizeof(rsa_key_e) + 1] = 0x82;
1400
0
  sbuf[9 + sizeof(rsa_key_e) + 2] = 0x04;
1401
0
  sbuf[9 + sizeof(rsa_key_e) + 3] = 0x00;
1402
1403
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF0, 0x00, key_id);
1404
0
  apdu.cla = 0x84;
1405
0
  apdu.data = sbuf;
1406
0
  apdu.lc = apdu.datalen = 9 + sizeof(rsa_key_e) + 4;
1407
1408
0
  ret = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
1409
0
  LOG_TEST_RET(card->ctx, ret, "Preinstall rsa failed");
1410
1411
  /* create rsa item in PKF */
1412
0
  sbuf[0] = 0x01; /* key len extern */
1413
0
  sbuf[1] = 0x0A; /* key len */
1414
0
  sbuf[2] = 0x2A; /* USAGE */
1415
0
  sbuf[3] = ENTERSAFE_AC_ALWAYS; /* user ac */
1416
0
  sbuf[4] = 0x04; /* change ac */
1417
0
  sbuf[5] = ENTERSAFE_AC_ALWAYS; /* UPDATE AC */
1418
0
  sbuf[6] = 0x40; /* ALGO */
1419
0
  sbuf[7] = 0x00; /* EC */
1420
0
  sbuf[8] = 0x00; /* VER */
1421
0
  memcpy(&sbuf[9], rsa_key_e, sizeof(rsa_key_e));
1422
0
  sbuf[9 + sizeof(rsa_key_e) + 0] = 'N';
1423
0
  sbuf[9 + sizeof(rsa_key_e) + 1] = 0x82;
1424
0
  sbuf[9 + sizeof(rsa_key_e) + 2] = 0x01;
1425
0
  sbuf[9 + sizeof(rsa_key_e) + 3] = 0x00;
1426
1427
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF0, 0x00, key_id);
1428
0
  apdu.cla = 0x84;
1429
0
  apdu.data = sbuf;
1430
0
  apdu.lc = apdu.datalen = 9 + sizeof(rsa_key_e) + 4;
1431
1432
0
  ret = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
1433
0
  LOG_TEST_RET(card->ctx, ret, "Preinstall rsa failed");
1434
1435
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1436
0
}
1437
1438
static int entersafe_preinstall_keys(sc_card_t *card, int (*install_rsa)(sc_card_t *, u8))
1439
0
{
1440
0
  int r;
1441
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1442
0
  sc_apdu_t apdu;
1443
1444
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1445
1446
0
  { /* RSA */
1447
0
    u8 rsa_index;
1448
0
    for (rsa_index = ENTERSAFE_MIN_KEY_ID; rsa_index <= ENTERSAFE_MAX_KEY_ID; ++rsa_index) {
1449
0
      r = install_rsa(card, rsa_index);
1450
0
      LOG_TEST_RET(card->ctx, r, "Preinstall rsa key failed");
1451
0
    }
1452
0
  }
1453
1454
0
  { /* key maintain */
1455
    /* create key maintain*/
1456
0
    sbuf[0] = 0;  /* key len extern */
1457
0
    sbuf[1] = sizeof(key_maintain); /* key len */
1458
0
    sbuf[2] = 0x03; /* USAGE */
1459
0
    sbuf[3] = ENTERSAFE_AC_ALWAYS; /* use AC */
1460
0
    sbuf[4] = ENTERSAFE_AC_ALWAYS; /* CHANGE AC */
1461
0
    sbuf[5] = ENTERSAFE_AC_NEVER; /* UPDATE AC */
1462
0
    sbuf[6] = 0x01; /* ALGO */
1463
0
    sbuf[7] = 0x00; /* EC */
1464
0
    sbuf[8] = 0x00; /* VER */
1465
0
    memcpy(&sbuf[9], key_maintain, sizeof(key_maintain));
1466
1467
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF0, 0x00, 0x00);
1468
0
    apdu.cla = 0x84;
1469
0
    apdu.data = sbuf;
1470
0
    apdu.lc = apdu.datalen = 0x19;
1471
1472
0
    r = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
1473
0
    LOG_TEST_RET(card->ctx, r, "Preinstall key maintain failed");
1474
0
  }
1475
1476
0
  { /* user PIN */
1477
0
    memset(sbuf, 0, sizeof(sbuf));
1478
0
    sbuf[0] = 0;  /* key len extern */
1479
0
    sbuf[1] = 16; /* key len */
1480
0
    sbuf[2] = 0x0B; /* USAGE */
1481
0
    sbuf[3] = ENTERSAFE_AC_ALWAYS; /* use AC */
1482
0
    sbuf[4] = 0X04; /* CHANGE AC */
1483
0
    sbuf[5] = 0x38; /* UPDATE AC */
1484
0
    sbuf[6] = 0x01; /* ALGO */
1485
0
    sbuf[7] = 0xFF; /* EC */
1486
0
    sbuf[8] = 0x00; /* VER */
1487
1488
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF0, 0x00, ENTERSAFE_USER_PIN_ID);
1489
0
    apdu.cla = 0x84;
1490
0
    apdu.data = sbuf;
1491
0
    apdu.lc = apdu.datalen = 0x19;
1492
1493
0
    r = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
1494
0
    LOG_TEST_RET(card->ctx, r, "Preinstall user PIN failed");
1495
0
  }
1496
1497
0
  { /* user PUK */
1498
0
    memset(sbuf, 0, sizeof(sbuf));
1499
0
    sbuf[0] = 0;  /* key len extern */
1500
0
    sbuf[1] = 16; /* key len */
1501
0
    sbuf[2] = 0x0B; /* USAGE */
1502
0
    sbuf[3] = ENTERSAFE_AC_ALWAYS; /* use AC */
1503
0
    sbuf[4] = 0X08; /* CHANGE AC */
1504
0
    sbuf[5] = 0xC0; /* UPDATE AC */
1505
0
    sbuf[6] = 0x01; /* ALGO */
1506
0
    sbuf[7] = 0xFF; /* EC */
1507
0
    sbuf[8] = 0x00; /* VER */
1508
1509
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xF0, 0x00, ENTERSAFE_USER_PIN_ID + 1);
1510
0
    apdu.cla = 0x84;
1511
0
    apdu.data = sbuf;
1512
0
    apdu.lc = apdu.datalen = 0x19;
1513
1514
0
    r = entersafe_transmit_apdu(card, &apdu, init_key, sizeof(init_key), 0, 1);
1515
0
    LOG_TEST_RET(card->ctx, r, "Preinstall user PUK failed");
1516
0
  }
1517
1518
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
1519
0
}
1520
1521
static int entersafe_card_ctl_2048(sc_card_t *card, unsigned long cmd, void *ptr)
1522
0
{
1523
0
  sc_entersafe_create_data *tmp = (sc_entersafe_create_data *)ptr;
1524
1525
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1526
1527
0
  switch (cmd) {
1528
0
    case SC_CARDCTL_ENTERSAFE_CREATE_FILE:
1529
0
      if (tmp->type == SC_ENTERSAFE_MF_DATA)
1530
0
        return entersafe_create_mf(card, tmp);
1531
0
      else if (tmp->type == SC_ENTERSAFE_DF_DATA)
1532
0
        return entersafe_create_df(card, tmp);
1533
0
      else if (tmp->type == SC_ENTERSAFE_EF_DATA)
1534
0
        return entersafe_create_ef(card, tmp);
1535
0
      else
1536
0
        return SC_ERROR_INTERNAL;
1537
0
    case SC_CARDCTL_ENTERSAFE_WRITE_KEY:
1538
0
      return entersafe_write_key(card, (sc_entersafe_wkey_data *)ptr);
1539
0
    case SC_CARDCTL_ENTERSAFE_GENERATE_KEY:
1540
0
      return entersafe_gen_key(card, (sc_entersafe_gen_key_data *)ptr);
1541
0
    case SC_CARDCTL_ERASE_CARD:
1542
0
      return entersafe_erase_card(card);
1543
0
    case SC_CARDCTL_GET_SERIALNR:
1544
0
      return entersafe_get_serialnr(card, (sc_serial_number_t *)ptr);
1545
0
    case SC_CARDCTL_ENTERSAFE_PREINSTALL_KEYS:
1546
0
      return entersafe_preinstall_keys(card, entersafe_preinstall_rsa_2048);
1547
0
    default:
1548
0
      return SC_ERROR_NOT_SUPPORTED;
1549
0
  }
1550
0
}
1551
1552
static struct sc_card_driver * sc_get_driver(void)
1553
0
{
1554
0
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
1555
1556
0
  if (iso_ops == NULL)
1557
0
    iso_ops = iso_drv->ops;
1558
1559
0
  entersafe_ops = *iso_drv->ops;
1560
0
  entersafe_ops.match_card = entersafe_match_card;
1561
0
  entersafe_ops.init = entersafe_init;
1562
0
  entersafe_ops.read_binary = entersafe_read_binary;
1563
0
  entersafe_ops.write_binary = NULL;
1564
0
  entersafe_ops.update_binary = entersafe_update_binary;
1565
0
  entersafe_ops.select_file = entersafe_select_file;
1566
0
  entersafe_ops.restore_security_env = entersafe_restore_security_env;
1567
0
  entersafe_ops.set_security_env = entersafe_set_security_env;
1568
0
  entersafe_ops.decipher = entersafe_decipher;
1569
0
  entersafe_ops.compute_signature = entersafe_compute_signature;
1570
0
  entersafe_ops.create_file = entersafe_create_file;
1571
0
  entersafe_ops.delete_file = NULL;
1572
0
  entersafe_ops.pin_cmd = entersafe_pin_cmd;
1573
0
  entersafe_ops.card_ctl = entersafe_card_ctl_2048;
1574
0
  entersafe_ops.process_fci = entersafe_process_fci;
1575
0
  return &entersafe_drv;
1576
0
}
1577
1578
struct sc_card_driver * sc_get_entersafe_driver(void)
1579
0
{
1580
0
  return sc_get_driver();
1581
0
}
1582
#endif