Coverage Report

Created: 2026-03-01 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-gemsafeV1.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 David Mattes (david.mattes@boeing.com) */
18
/* Portuguese eID card support by Joao Poupino (joao.poupino@ist.utl.pt) */
19
20
#ifdef HAVE_CONFIG_H
21
#include "config.h"
22
#endif
23
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "internal.h"
28
#include "asn1.h"
29
#include "cardctl.h"
30
31
85
#define GEMSAFEV1_ALG_REF_FREEFORM  0x12
32
462
#define GEMSAFEV3_ALG_REF_FREEFORM  0x02
33
#define GEMSAFEV3_ALG_REF_SHA1    0x12
34
290
#define GEMSAFEV3_ALG_REF_SHA256  0x42
35
#define MAX_RESP_BUFFER_SIZE 2048
36
37
static struct sc_card_operations gemsafe_ops;
38
static struct sc_card_operations *iso_ops = NULL;
39
40
static struct sc_card_driver gemsafe_drv = {
41
  "Gemalto GemSafe V1 applet",
42
  "gemsafeV1",
43
  &gemsafe_ops,
44
  NULL, 0, NULL
45
};
46
47
/* Known ATRs */
48
static const struct sc_atr_table gemsafe_atrs[] = {
49
  /* standard version */
50
    {"3B:7B:94:00:00:80:65:B0:83:01:01:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
51
    {"3B:6B:00:00:80:65:B0:83:01:01:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
52
    /* GemSafeXpresso 32K */
53
    {"3b:6d:00:00:80:31:80:65:b0:83:01:02:90:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
54
    /* fips 140 version */
55
    {"3B:6B:00:00:80:65:B0:83:01:03:74:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
56
    /* Undefined */
57
    {"3B:7A:94:00:00:80:65:A2:01:01:01:3D:72:D6:43", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
58
    {"3B:7D:94:00:00:80:31:80:65:B0:83:01:01:90:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
59
    {"3B:7D:96:00:00:80:31:80:65:B0:83:11:48:C8:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_GENERIC, 0, NULL},
60
    /* Portuguese eID cards */
61
    {"3B:7D:95:00:00:80:31:80:65:B0:83:11:C0:A9:83:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
62
    {"3B:7D:95:00:00:80:31:80:65:B0:83:11:C0:A9:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
63
    {"3B:7D:95:00:00:80:31:80:65:B0:83:11:00:C8:83:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
64
    {"3B:7D:95:00:00:80:31:80:65:B0:83:11:00:C8:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
65
    {"3B:FF:96:00:00:81:31:80:43:80:31:80:65:B0:85:03:00:EF:12:0F:FF:82:90:00:67", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
66
    {"3B:FF:96:00:00:81:31:FE:43:80:31:80:65:B0:85:04:01:20:12:0F:FF:82:90:00:D0", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_PTEID, 0, NULL},
67
    /* Swedish eID card */
68
    {"3B:7D:96:00:00:80:31:80:65:B0:83:11:00:C8:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_SEEID, 0, NULL},
69
    /* European Patent Office epoline card*/
70
    {"3b:7d:96:00:00:80:31:80:65:b0:83:02:01:f3:83:00:90:00", NULL, NULL, SC_CARD_TYPE_GEMSAFEV1_SEEID, 0, NULL},
71
    {NULL, NULL, NULL, 0, 0, NULL}
72
};
73
74
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x18, 0x0A,
75
  0x00, 0x00, 0x01, 0x63, 0x42, 0x00};
76
77
static const u8 gemsafe_pteid_aid[] = {0x60, 0x46, 0x32, 0xFF, 0x00, 0x00, 0x02};
78
79
static const u8 gemsafe_seeid_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x18, 0x0C,
80
                                       0x00, 0x00, 0x01, 0x63, 0x42, 0x00};
81
82
/*
83
static const u8 gemsafe_def_aid[] = {0xA0, 0x00, 0x00, 0x00, 0x63, 0x50,
84
  0x4B, 0x43, 0x53, 0x2D, 0x31, 0x35};
85
*/
86
87
typedef struct gemsafe_exdata_st {
88
  u8  aid[16];
89
  size_t  aid_len;
90
} gemsafe_exdata;
91
92
static int get_conf_aid(sc_card_t *card, u8 *aid, size_t *len)
93
144
{
94
144
  sc_context_t    *ctx = card->ctx;
95
144
  scconf_block    *conf_block, **blocks;
96
144
  int     i;
97
144
  const char    *str_aid;
98
99
144
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
100
101
144
  conf_block = NULL;
102
288
  for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
103
144
    blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
104
144
            "card", "gemsafeV1");
105
144
    if (blocks != NULL && blocks[0] != NULL)
106
0
      conf_block = blocks[0];
107
144
    free(blocks);
108
144
  }
109
110
144
  if (!conf_block) {
111
144
    sc_log(ctx,  "no card specific options configured, trying default AID\n");
112
144
    return SC_ERROR_INTERNAL;
113
144
  }
114
115
0
  str_aid = scconf_get_str(conf_block, "aid", NULL);
116
0
  if (!str_aid) {
117
0
    sc_log(ctx,  "no aid configured, trying default AID\n");
118
0
    return SC_ERROR_INTERNAL;
119
0
  }
120
0
  return sc_hex_to_bin(str_aid, aid, len);
121
0
}
122
123
static int gemsafe_match_card(sc_card_t *card)
124
81.5k
{
125
81.5k
  int i;
126
127
81.5k
  i = _sc_match_atr(card, gemsafe_atrs, &card->type);
128
81.5k
  if (i < 0)
129
78.7k
    return 0;
130
131
2.72k
  return 1;
132
81.5k
}
133
134
static int gemsafe_init(struct sc_card *card)
135
2.72k
{
136
2.72k
  int r;
137
2.72k
  gemsafe_exdata *exdata = NULL;
138
139
2.72k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
140
141
2.72k
  card->name = "GemSAFE V1";
142
2.72k
  card->cla  = 0x00;
143
144
2.72k
  exdata = (gemsafe_exdata *)calloc(1, sizeof(gemsafe_exdata));
145
2.72k
  if (!exdata)
146
0
    return SC_ERROR_OUT_OF_MEMORY;
147
2.72k
  exdata->aid_len = sizeof(exdata->aid);
148
2.72k
  if(card->type == SC_CARD_TYPE_GEMSAFEV1_GENERIC) {
149
    /* try to get a AID from the config file */
150
144
    r = get_conf_aid(card, exdata->aid, &exdata->aid_len);
151
144
    if (r < 0) {
152
      /* failed, use default value */
153
144
      memcpy(exdata->aid, gemsafe_def_aid, sizeof(gemsafe_def_aid));
154
144
      exdata->aid_len = sizeof(gemsafe_def_aid);
155
144
    }
156
2.58k
  } else if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
157
2.55k
    memcpy(exdata->aid, gemsafe_pteid_aid, sizeof(gemsafe_pteid_aid));
158
2.55k
    exdata->aid_len = sizeof(gemsafe_pteid_aid);
159
2.55k
  } else if (card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) {
160
29
    memcpy(exdata->aid, gemsafe_seeid_aid, sizeof(gemsafe_seeid_aid));
161
29
    exdata->aid_len = sizeof(gemsafe_seeid_aid);
162
29
  }
163
164
  /* increase lock_count here to prevent sc_unlock to select
165
   * applet twice in gp_select_applet */
166
2.72k
  card->lock_count++;
167
  /* SELECT applet */
168
2.72k
  r = iso7816_select_aid(card, exdata->aid, exdata->aid_len, NULL, NULL);
169
2.72k
  if (r < 0) {
170
33
    free(exdata);
171
33
    sc_log(card->ctx,  "applet selection failed\n");
172
33
    return SC_ERROR_INVALID_CARD;
173
33
  }
174
2.69k
  card->lock_count--;
175
176
  /* set the supported algorithm */
177
2.69k
  unsigned long flags;
178
179
2.69k
  flags  = SC_ALGORITHM_RSA_PAD_PKCS1;
180
2.69k
  flags |= SC_ALGORITHM_RSA_PAD_ISO9796;
181
2.69k
  flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
182
2.69k
  flags |= SC_ALGORITHM_RSA_HASH_NONE;
183
184
  /* GemSAFE V3 cards support SHA256 */
185
2.69k
  if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
186
156
      card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID)
187
2.55k
    flags |= SC_ALGORITHM_RSA_HASH_SHA256;
188
189
2.69k
  _sc_card_add_rsa_alg(card,  512, flags, 0);
190
2.69k
  _sc_card_add_rsa_alg(card,  768, flags, 0);
191
2.69k
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
192
2.69k
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
193
2.69k
  _sc_card_add_rsa_alg(card, 3072, flags, 0);
194
2.69k
  _sc_card_add_rsa_alg(card, 4096, flags, 0);
195
196
  /* fake algorithm to persuade register_mechanisms()
197
   * to register these hashes */
198
2.69k
  if (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
199
2.55k
      card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) {
200
2.55k
    flags  = SC_ALGORITHM_RSA_HASH_SHA1;
201
2.55k
    flags |= SC_ALGORITHM_RSA_HASH_MD5;
202
2.55k
    flags |= SC_ALGORITHM_RSA_HASH_MD5_SHA1;
203
2.55k
    flags |= SC_ALGORITHM_RSA_HASH_RIPEMD160;
204
205
2.55k
    _sc_card_add_rsa_alg(card,  512, flags, 0);
206
2.55k
  }
207
208
2.69k
  card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
209
2.69k
  card->drv_data = exdata;
210
211
2.69k
  return SC_SUCCESS;
212
2.72k
}
213
214
static int gemsafe_finish(sc_card_t *card)
215
2.69k
{
216
2.69k
  gemsafe_exdata *exdata = (gemsafe_exdata *)card->drv_data;
217
218
2.69k
  if (exdata)
219
2.69k
    free(exdata);
220
2.69k
  return SC_SUCCESS;
221
2.69k
}
222
223
static int gemsafe_select_file(struct sc_card *card, const struct sc_path *path,
224
     struct sc_file **file_out)
225
20.2k
{
226
  /* so far just call the iso select file (but this will change) */
227
20.2k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
228
229
20.2k
  return iso_ops->select_file(card, path, file_out);
230
20.2k
}
231
232
static int gemsafe_sc2acl(sc_file_t *file, unsigned ops, u8 sc_byte)
233
1.17k
{
234
1.17k
  int r;
235
1.17k
  unsigned int meth = 0;
236
237
1.17k
  if (sc_byte == 0xff) {
238
417
    r = sc_file_add_acl_entry(file, ops, SC_AC_NEVER, 0);
239
417
    return r;
240
417
  }
241
759
  if (sc_byte == 0x00) {
242
164
    r = sc_file_add_acl_entry(file, ops, SC_AC_NONE, 0);
243
164
    return r;
244
164
  }
245
246
  /* XXX: OR combination of access rights are currently not supported
247
   * hence ignored */
248
595
  if (sc_byte & 0x40)
249
309
    meth |= SC_AC_PRO;
250
595
  if (sc_byte & 0x20)
251
331
    meth |= SC_AC_AUT | SC_AC_TERM;
252
595
  if (sc_byte & 0x10)
253
215
    meth |= SC_AC_CHV;
254
255
595
  return sc_file_add_acl_entry(file, ops, meth, sc_byte & 0x0f);
256
759
}
257
258
static int gemsafe_setacl(sc_card_t *card, sc_file_t *file, const u8 *data,
259
  int is_df)
260
393
{
261
393
  int       r;
262
393
  u8        cond;
263
393
  const u8 *p = data + 1;
264
393
  struct sc_context *ctx = card->ctx;
265
266
393
  if (is_df) {
267
198
    if (*data & 0x04)  /* CREATE DF */
268
112
      cond = *p++;
269
86
    else
270
86
      cond = 0xff;
271
198
    sc_log(ctx,
272
198
      "DF security byte CREATE DF: %02x\n", cond);
273
198
    r = gemsafe_sc2acl(file, SC_AC_OP_CREATE, cond);
274
198
    if (r < 0)
275
0
      return r;
276
198
    if (*data & 0x02)  /* CREATE EF */
277
132
      cond = *p;
278
66
    else
279
66
      cond = 0xff;
280
198
    sc_log(ctx,
281
198
      "DF security byte CREATE EF: %02x\n", cond);
282
    /* XXX: opensc doesn't currently separate access conditions for
283
     * CREATE EF and CREATE DF, this should be changed */
284
198
    r = gemsafe_sc2acl(file, SC_AC_OP_CREATE, cond);
285
198
    if (r < 0)
286
0
      return r;
287
198
  } else {
288
    /* XXX: ACTIVATE FILE and DEACTIVATE FILE ac are currently not
289
     * supported => ignore them */
290
195
    if (*data & 0x02)  /* UPDATE BINARY, ERASE BINARY */
291
136
      cond = *p++;
292
59
    else
293
59
      cond = 0xff;
294
195
    sc_log(ctx,
295
195
      "EF security byte UPDATE/ERASE BINARY: %02x\n", cond);
296
195
    r = gemsafe_sc2acl(file, SC_AC_OP_UPDATE, cond);
297
195
    if (r < 0)
298
0
      return r;
299
195
    r = gemsafe_sc2acl(file, SC_AC_OP_WRITE, cond);
300
195
    if (r < 0)
301
0
      return r;
302
195
    r = gemsafe_sc2acl(file, SC_AC_OP_ERASE, cond);
303
195
    if (r < 0)
304
0
      return r;
305
195
    if (*data & 0x01)  /* READ BINARY */
306
126
      cond = *p;
307
69
    else
308
69
      cond = 0xff;
309
195
    sc_log(ctx,
310
195
      "EF security byte READ BINARY: %02x\n", cond);
311
195
    r = gemsafe_sc2acl(file, SC_AC_OP_READ, cond);
312
195
    if (r < 0)
313
0
      return r;
314
195
  }
315
316
393
  return SC_SUCCESS;
317
393
}
318
319
static int gemsafe_process_fci(struct sc_card *card, struct sc_file *file,
320
  const u8 *buf, size_t len)
321
3.42k
{
322
3.42k
  int        r;
323
3.42k
  size_t     tlen;
324
3.42k
  const u8   *tag = NULL, *p = buf;
325
3.42k
  const char *type;
326
3.42k
  struct sc_context *ctx = card->ctx;
327
328
3.42k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
329
330
3.42k
  r = iso_ops->process_fci(card, file, buf, len);
331
3.42k
  if (r < 0)
332
0
    return r;
333
3.42k
  sc_log(ctx,
334
3.42k
    "processing GemSAFE V1 specific FCI information\n");
335
336
337
3.42k
  tag = sc_asn1_find_tag(ctx, p, len, 0x82, &tlen);
338
3.42k
  if (!tag) {
339
    /* no FDB => we have a DF */
340
2.59k
    type = "DF";
341
2.59k
    file->type = SC_FILE_TYPE_DF;
342
2.59k
  } else {
343
836
    type = "EF";
344
836
    file->type = SC_FILE_TYPE_WORKING_EF;
345
836
  }
346
347
3.42k
  sc_log(ctx,  "file type: %s\n", type);
348
349
3.42k
  tag = sc_asn1_find_tag(ctx, p, len, 0x8C, &tlen);
350
3.42k
  if (tag && tlen > 1) {
351
393
    r = gemsafe_setacl(card, file, tag, strcmp(type, "DF") ? 0 : 1);
352
393
    if (r < 0) {
353
0
      sc_log(ctx,  "unable to set ACL\n");
354
0
      return SC_ERROR_INTERNAL;
355
0
    }
356
393
  } else
357
3.03k
    sc_log(ctx,  "error: AM and SC bytes missing\n");
358
359
3.42k
  return SC_SUCCESS;
360
3.42k
}
361
362
static u8 gemsafe_flags2algref(struct sc_card *card, const struct sc_security_env *env)
363
1.51k
{
364
1.51k
  u8 ret = 0;
365
366
1.51k
  if (env->operation == SC_SEC_OPERATION_SIGN) {
367
1.07k
    if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA256)
368
290
      ret = GEMSAFEV3_ALG_REF_SHA256;
369
782
    else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01)
370
285
      ret = (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
371
54
             card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) ?
372
242
            GEMSAFEV3_ALG_REF_FREEFORM :
373
285
            GEMSAFEV1_ALG_REF_FREEFORM;
374
497
    else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)
375
249
      ret = 0x11;
376
1.07k
  } else if (env->operation == SC_SEC_OPERATION_DECIPHER) {
377
441
    if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02)
378
262
      ret = (card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
379
46
             card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) ?
380
220
            GEMSAFEV3_ALG_REF_FREEFORM :
381
262
            GEMSAFEV1_ALG_REF_FREEFORM;
382
441
  }
383
384
1.51k
  return ret;
385
1.51k
}
386
387
static int gemsafe_restore_security_env(struct sc_card *card, int se_num)
388
0
{
389
0
  int r;
390
0
  struct sc_apdu apdu;
391
392
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
393
394
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0x73, (u8) se_num);
395
396
0
  r = sc_transmit_apdu(card, &apdu);
397
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
398
399
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
400
0
}
401
402
403
static int gemsafe_set_security_env(struct sc_card *card,
404
            const struct sc_security_env *env,
405
            int se_num)
406
1.51k
{
407
1.51k
  u8 alg_ref;
408
1.51k
  struct sc_security_env se_env = *env;
409
1.51k
  struct sc_context *ctx = card->ctx;
410
411
1.51k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
412
413
1.51k
  if (!(se_env.flags & SC_SEC_ENV_ALG_REF_PRESENT)) {
414
    /* set the algorithm reference */
415
1.51k
    alg_ref = gemsafe_flags2algref(card, &se_env);
416
1.51k
    if (alg_ref) {
417
1.08k
      se_env.algorithm_ref = alg_ref;
418
1.08k
      se_env.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
419
1.08k
    }
420
1.51k
  }
421
1.51k
  if (!(se_env.flags & SC_SEC_ENV_ALG_REF_PRESENT))
422
427
    sc_log(ctx, "unknown algorithm flags '%lx'\n", se_env.algorithm_flags);
423
424
1.51k
  se_env.flags &= ~SC_SEC_ENV_FILE_REF_PRESENT;
425
1.51k
  return iso_ops->set_security_env(card, &se_env, se_num);
426
1.51k
}
427
428
static int gemsafe_compute_signature(struct sc_card *card, const u8 * data,
429
  size_t data_len, u8 * out, size_t outlen)
430
287
{
431
287
  int r;
432
287
  size_t len;
433
287
  struct sc_apdu apdu;
434
287
  u8 rbuf[MAX_RESP_BUFFER_SIZE];
435
287
  u8 sbuf[MAX_RESP_BUFFER_SIZE];
436
287
  sc_context_t *ctx = card->ctx;
437
438
287
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
439
440
  /* the card can sign 36 bytes of free form data */
441
287
  if (data_len > 36) {
442
36
    sc_log(ctx,
443
36
       "error: input data too long: %"SC_FORMAT_LEN_SIZE_T"u bytes\n",
444
36
       data_len);
445
36
    return SC_ERROR_INVALID_ARGUMENTS;
446
36
  }
447
448
  /* the Portuguese eID card requires a two-phase exchange */
449
  /* and so does the Swedish one */
450
251
  if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
451
213
     card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) {
452
213
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A, 0x90, 0xA0);
453
213
  } else {
454
38
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E, 0xAC);
455
38
    apdu.cla |= 0x80;
456
38
    apdu.resp = rbuf;
457
38
    apdu.resplen = sizeof(rbuf);
458
38
    apdu.le      = 256;
459
38
  }
460
  /* we sign a digestInfo object => tag 0x90 */
461
251
  sbuf[0] = 0x90;
462
251
  sbuf[1] = (u8)data_len;
463
251
  memcpy(sbuf + 2, data, data_len);
464
251
  apdu.data = sbuf;
465
251
  apdu.lc   = data_len + 2;
466
251
  apdu.datalen = data_len + 2;
467
468
251
  r = sc_transmit_apdu(card, &apdu);
469
251
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
470
237
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
471
166
    if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID ||
472
143
       card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) {
473
      /* finalize the exchange */
474
143
      sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A, 0x9E, 0x9A);
475
143
      apdu.le = 128; /* 1024 bit keys */
476
143
      apdu.resp = rbuf;
477
143
      apdu.resplen = sizeof(rbuf);
478
143
      if(card->type == SC_CARD_TYPE_GEMSAFEV1_SEEID) {
479
        /* cla 0x80 not supported */
480
22
        apdu.cla = 0x00;
481
22
      }
482
143
      r = sc_transmit_apdu(card, &apdu);
483
143
      LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
484
120
      if(apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
485
56
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
486
120
    }
487
87
    len = apdu.resplen > outlen ? outlen : apdu.resplen;
488
489
87
    memcpy(out, apdu.resp, len);
490
87
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
491
87
  }
492
71
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
493
71
}
494
495
static int gemsafe_decipher(struct sc_card *card, const u8 * crgram,
496
  size_t crgram_len, u8 *out, size_t outlen)
497
159
{
498
159
  int r;
499
159
  struct sc_apdu apdu;
500
159
  u8 rbuf[MAX_RESP_BUFFER_SIZE];
501
159
  sc_context_t *ctx = card->ctx;
502
503
159
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
504
159
  if (crgram_len > 255)
505
12
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
506
507
147
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x84);
508
147
  apdu.cla |= 0x80;
509
147
  apdu.resp = rbuf;
510
147
  apdu.resplen = sizeof(rbuf);
511
147
  apdu.le      = crgram_len;
512
513
147
  apdu.data = crgram;
514
147
  apdu.lc   = crgram_len;
515
147
  apdu.datalen = crgram_len;
516
147
  r = sc_transmit_apdu(card, &apdu);
517
147
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
518
139
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
519
95
    size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
520
521
95
    memcpy(out, apdu.resp, len);
522
95
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
523
95
  }
524
44
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
525
44
}
526
527
static int gemsafe_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
528
607
{
529
607
  int prev_cla, r;
530
531
607
  prev_cla = card->cla;
532
607
  if(card->type == SC_CARD_TYPE_GEMSAFEV1_PTEID) {
533
    /* Warning: this depends on iso7816_get_challenge not
534
     * changing the value of the card's CLA
535
     */
536
342
    card->cla = 0x80;
537
342
  }
538
607
  r = iso_ops->get_challenge(card, rnd, len);
539
  /* Restore the CLA value if needed */
540
607
  if(card->cla != prev_cla)
541
342
    card->cla = prev_cla;
542
543
607
  return r;
544
607
}
545
546
static int gemsafe_card_reader_lock_obtained(sc_card_t *card, int was_reset)
547
5.86k
{
548
5.86k
  int r = SC_SUCCESS;
549
5.86k
  gemsafe_exdata *exdata = (gemsafe_exdata *)card->drv_data;
550
551
5.86k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
552
553
5.86k
  if (was_reset > 0 && exdata) {
554
0
    r = iso7816_select_aid(card, exdata->aid, exdata->aid_len, NULL, NULL);
555
0
  }
556
557
5.86k
  LOG_FUNC_RETURN(card->ctx, r);
558
5.86k
}
559
560
static int gemsafe_logout(sc_card_t *card)
561
0
{
562
0
  gemsafe_exdata *exdata = (gemsafe_exdata *)card->drv_data;
563
564
0
  return iso7816_select_aid(card, exdata->aid, exdata->aid_len, NULL, NULL);
565
0
}
566
567
static struct sc_card_driver *sc_get_driver(void)
568
91.7k
{
569
91.7k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
570
91.7k
  if (!iso_ops)
571
10
    iso_ops = iso_drv->ops;
572
  /* use the standard iso operations as default */
573
91.7k
  gemsafe_ops = *iso_drv->ops;
574
  /* gemsafe specific functions */
575
91.7k
  gemsafe_ops.match_card  = gemsafe_match_card;
576
91.7k
  gemsafe_ops.init  = gemsafe_init;
577
91.7k
  gemsafe_ops.finish  = gemsafe_finish;
578
91.7k
  gemsafe_ops.select_file = gemsafe_select_file;
579
91.7k
  gemsafe_ops.restore_security_env = gemsafe_restore_security_env;
580
91.7k
  gemsafe_ops.set_security_env     = gemsafe_set_security_env;
581
91.7k
  gemsafe_ops.decipher             = gemsafe_decipher;
582
91.7k
  gemsafe_ops.compute_signature    = gemsafe_compute_signature;
583
91.7k
  gemsafe_ops.get_challenge      = gemsafe_get_challenge;
584
91.7k
  gemsafe_ops.process_fci = gemsafe_process_fci;
585
91.7k
  gemsafe_ops.pin_cmd    = iso_ops->pin_cmd;
586
91.7k
  gemsafe_ops.card_reader_lock_obtained = gemsafe_card_reader_lock_obtained;
587
91.7k
  gemsafe_ops.logout = gemsafe_logout;
588
589
91.7k
  return &gemsafe_drv;
590
91.7k
}
591
592
struct sc_card_driver *sc_get_gemsafeV1_driver(void)
593
91.7k
{
594
91.7k
  return sc_get_driver();
595
91.7k
}
596