Coverage Report

Created: 2026-01-10 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-isoApplet.c
Line
Count
Source
1
/*
2
 * Support for the IsoApplet JavaCard Applet.
3
 *
4
 * Copyright (C) 2014 Philip Wendland <wendlandphilip@gmail.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
#include "asn1.h"
25
#include "cardctl.h"
26
#include "internal.h"
27
#include "log.h"
28
#include "opensc.h"
29
#include "pkcs15.h"
30
#include "types.h"
31
32
0
#define ISOAPPLET_ALG_REF_ECDSA 0x21
33
0
#define ISOAPPLET_ALG_REF_RSA_PAD_PKCS1 0x11
34
0
#define ISOAPPLET_ALG_REF_RSA_PAD_PSS 0x12
35
36
263
#define ISOAPPLET_VERSION_V0 0x0006
37
120
#define ISOAPPLET_VERSION_V1 0x0100
38
39
52
#define ISOAPPLET_API_FEATURE_EXT_APDU 0x01
40
52
#define ISOAPPLET_API_FEATURE_SECURE_RANDOM 0x02
41
14
#define ISOAPPLET_API_FEATURE_ECC 0x04
42
52
#define ISOAPPLET_API_FEATURE_RSA_PSS 0x08
43
52
#define ISOAPPLET_API_FEATURE_RSA_4096 0x20
44
45
static const u8 isoApplet_aid[] = {0xf2,0x76,0xa2,0x88,0xbc,0xfb,0xa6,0x9d,0x34,0xf3,0x10,0x01};
46
47
struct isoApplet_drv_data
48
{
49
  /* Save the current algorithm reference
50
   * (ISOAPPLET_ALG_REF_ECDSA, ISOAPPLET_ALG_REF_RSA_PAD_PKCS1)
51
   * to be able to distinguish between RSA and ECC operations.
52
   * If ECC is being used, the signatures generated by the card
53
   * have to be modified. */
54
  unsigned int sec_env_alg_ref;
55
  unsigned long sec_env_ec_field_length;
56
  unsigned int isoapplet_version;
57
  unsigned int isoapplet_features;
58
};
59
52
#define DRVDATA(card) ((struct isoApplet_drv_data *) ((card)->drv_data))
60
61
/* Operations supported by the applet. */
62
static struct sc_card_operations isoApplet_ops;
63
64
/* A reference to the iso7816_* functions.
65
 * Initialized in sc_get_driver. */
66
static const struct sc_card_operations *iso_ops = NULL;
67
68
/* The description of the driver. */
69
static struct sc_card_driver isoApplet_drv =
70
{
71
  "Javacard with IsoApplet",
72
  "isoApplet",
73
  &isoApplet_ops,
74
  NULL, 0, NULL
75
};
76
77
static struct isoapplet_supported_ec_curves {
78
    struct sc_object_id oid;
79
    size_t size;
80
    unsigned int min_applet_version;
81
} ec_curves[] = {
82
  {{{1, 2, 840, 10045, 3, 1, 1, -1}},     192, 0x0000}, /* secp192r1, nistp192, prime192v1, ansiX9p192r1 */
83
  {{{1, 3, 132, 0, 33, -1}},              224, 0x0000}, /* secp224r1, nistp224 */
84
  {{{1, 2, 840, 10045, 3, 1, 7, -1}},     256, 0x0000}, /* secp256r1, nistp256, prime256v1, ansiX9p256r1 */
85
  {{{1, 3, 132, 0, 34, -1}},              384, 0x0000}, /* secp384r1, nistp384, prime384v1, ansiX9p384r1 */
86
  {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 3, -1}}, 192, 0x0000}, /* brainpoolP192r1 */
87
  {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 5, -1}}, 224, 0x0000}, /* brainpoolP224r1 */
88
  {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 7, -1}}, 256, 0x0000}, /* brainpoolP256r1 */
89
  {{{1, 3, 36, 3, 3, 2, 8, 1, 1, 9, -1}}, 320, 0x0000}, /* brainpoolP320r1 */
90
  {{{1, 3, 132, 0, 31, -1}},              192, 0x0006}, /* secp192k1 */
91
  {{{1, 3, 132, 0, 10, -1}},              256, 0x0006}, /* secp256k1 */
92
  {{{-1}}, 0, 0} /* This entry must not be touched. */
93
};
94
95
static int
96
isoApplet_finish(sc_card_t *card)
97
52
{
98
52
  struct isoApplet_drv_data *drvdata=DRVDATA(card);
99
100
52
  LOG_FUNC_CALLED(card->ctx);
101
52
  if (drvdata)
102
52
  {
103
52
    free(drvdata);
104
52
    card->drv_data=NULL;
105
52
  }
106
52
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
107
52
}
108
109
static int
110
isoApplet_match_card(sc_card_t *card)
111
3.71k
{
112
3.71k
  int rv;
113
114
3.71k
  rv = iso7816_select_aid(card, isoApplet_aid, sizeof(isoApplet_aid), NULL, NULL);
115
3.71k
  if(rv != SC_SUCCESS)
116
3.65k
  {
117
3.65k
    return 0;
118
3.65k
  }
119
120
68
  return 1;
121
3.71k
}
122
123
static int
124
68
isoApplet_get_info(sc_card_t * card, struct isoApplet_drv_data * drvdata) {
125
68
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
126
68
  int rv;
127
68
  sc_context_t * ctx = card->ctx;
128
129
68
  rv = sc_get_data(card, 0x0101, rbuf, 3);
130
68
  if(rv == SC_ERROR_INS_NOT_SUPPORTED) {
131
    /* INS not supported. This is an older IsoApplet that might return the
132
     * applet information upon selection. For backward compatibility, try this. */
133
5
    size_t rlen = sizeof(rbuf);
134
5
    rv = iso7816_select_aid(card, isoApplet_aid, sizeof(isoApplet_aid), rbuf, &rlen);
135
5
    LOG_TEST_RET(ctx, rv, "Error selecting applet.");
136
3
    rv = (int)rlen;
137
3
  }
138
139
66
  if (rv < 0) {
140
8
    LOG_TEST_RET(ctx, rv, "Card returned error.");
141
8
  }
142
143
  /* Fill up drvdata */
144
58
  if(rv >= 3)
145
21
  {
146
21
    drvdata->isoapplet_version = rbuf[0] << 8 | rbuf[1];
147
21
    drvdata->isoapplet_features = rbuf[2];
148
21
  }
149
150
58
  return SC_SUCCESS;
151
66
}
152
153
static int
154
isoApplet_init(sc_card_t *card)
155
68
{
156
68
  int i, r;
157
68
  unsigned int major_version = 0;
158
68
  unsigned long flags = 0;
159
68
  unsigned long ext_flags = 0;
160
68
  struct isoApplet_drv_data *drvdata;
161
162
68
  LOG_FUNC_CALLED(card->ctx);
163
164
68
  drvdata=calloc(1, sizeof(*drvdata));
165
68
  if (!drvdata)
166
68
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
167
168
68
  card->drv_data = drvdata;
169
68
  card->cla = 0x00;
170
171
  /* Obtain applet version and specific features */
172
68
  r = isoApplet_get_info(card, drvdata);
173
68
  LOG_TEST_GOTO_ERR(card->ctx, r, "Error obtaining information about applet.");
174
175
58
  major_version = drvdata->isoapplet_version & 0xFF00;
176
58
  if(major_version != (ISOAPPLET_VERSION_V0 & 0xFF00) && major_version != (ISOAPPLET_VERSION_V1 & 0xFF00))
177
6
  {
178
6
    sc_log(card->ctx, "IsoApplet: Mismatching major API version. Not proceeding. "
179
6
         "API versions: Driver (%04X or %04X), applet (%04X). Please update accordingly.",
180
6
         ISOAPPLET_VERSION_V0, ISOAPPLET_VERSION_V1, drvdata->isoapplet_version);
181
6
    r = SC_ERROR_INVALID_CARD;
182
6
    goto err;
183
6
  }
184
52
  else if(drvdata->isoapplet_version != ISOAPPLET_VERSION_V0 && drvdata->isoapplet_version != ISOAPPLET_VERSION_V1)
185
50
  {
186
50
    sc_log(card->ctx, "IsoApplet: Mismatching minor version. Proceeding anyway. "
187
50
         "API versions: Driver (%04X or %04X), applet (%04X). "
188
50
         "Please update accordingly whenever possible.",
189
50
         ISOAPPLET_VERSION_V0, ISOAPPLET_VERSION_V1, drvdata->isoapplet_version);
190
50
  }
191
192
52
  if(drvdata->isoapplet_features & ISOAPPLET_API_FEATURE_EXT_APDU)
193
6
    card->caps |=  SC_CARD_CAP_APDU_EXT;
194
52
  if(drvdata->isoapplet_features & ISOAPPLET_API_FEATURE_SECURE_RANDOM)
195
7
    card->caps |=  SC_CARD_CAP_RNG;
196
52
  if(drvdata->isoapplet_version <= 0x0005
197
14
      || drvdata->isoapplet_features & ISOAPPLET_API_FEATURE_ECC)
198
45
  {
199
    /* There are Java Cards that do not support ECDSA at all. The IsoApplet
200
     * started to report this with version 00.06.
201
     *
202
     * Curves supported by the pkcs15-init driver are indicated per curve. This
203
     * should be kept in sync with the explicit parameters in the pkcs15-init
204
     * driver. */
205
45
    flags = 0;
206
45
    if (major_version == (ISOAPPLET_VERSION_V0 & 0xFF00)) {
207
40
      flags |= SC_ALGORITHM_ECDSA_HASH_SHA1;
208
40
    } else { // ISOAPPLET_VERSION_V1
209
5
      flags |= SC_ALGORITHM_ECDSA_RAW;
210
5
      flags |= SC_ALGORITHM_ECDSA_HASH_NONE;
211
5
    }
212
45
    flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
213
45
    ext_flags = SC_ALGORITHM_EXT_EC_UNCOMPRESES;
214
45
    ext_flags |=  SC_ALGORITHM_EXT_EC_NAMEDCURVE;
215
45
    ext_flags |= SC_ALGORITHM_EXT_EC_F_P;
216
495
    for (i=0; ec_curves[i].oid.value[0] >= 0; i++)
217
450
    {
218
450
      if(drvdata->isoapplet_version >= ec_curves[i].min_applet_version)
219
374
        _sc_card_add_ec_alg(card, ec_curves[i].size, flags, ext_flags, &ec_curves[i].oid);
220
450
    }
221
45
  }
222
223
  /* RSA */
224
52
  flags = 0;
225
52
  flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
226
52
  flags |= SC_ALGORITHM_RSA_HASH_NONE;
227
52
  if(drvdata->isoapplet_features & ISOAPPLET_API_FEATURE_RSA_PSS) {
228
6
    flags |= SC_ALGORITHM_RSA_PAD_PSS;
229
6
  }
230
  /* Key-generation: */
231
52
  flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
232
  /* Modulus lengths: */
233
52
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
234
52
  if (drvdata->isoapplet_features & ISOAPPLET_API_FEATURE_RSA_4096) {
235
7
    _sc_card_add_rsa_alg(card, 4096, flags, 0);
236
7
  }
237
238
52
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
239
16
err:
240
16
  free(drvdata);
241
16
  LOG_FUNC_RETURN(card->ctx, r);
242
16
}
243
244
/*
245
 * @brief convert an OpenSC ACL entry to the security condition
246
 * byte used by the IsoApplet.
247
 *
248
 * Used by IsoApplet_create_file to parse OpenSC ACL entries
249
 * into ISO 7816-4 Table 20 security condition bytes.
250
 *
251
 * @param entry The OpenSC ACL entry.
252
 *
253
 * @return The security condition byte. No restriction (0x00)
254
 *         if unknown operation.
255
 */
256
static u8
257
isoApplet_acl_to_security_condition_byte(const sc_acl_entry_t *entry)
258
0
{
259
0
  if(!entry)
260
0
    return 0x00;
261
0
  switch(entry->method)
262
0
  {
263
0
  case SC_AC_CHV:
264
0
    return 0x90;
265
0
  case SC_AC_NEVER:
266
0
    return 0xFF;
267
0
  case SC_AC_NONE:
268
0
  default:
269
0
    return 0x00;
270
0
  }
271
0
}
272
273
/*
274
 * The reason for this function is that OpenSC doesn't set any
275
 * Security Attribute Tag in the FCI upon file creation if there
276
 * is no file->sec_attr. I set the file->sec_attr to a format
277
 * understood by the applet (ISO 7816-4 tables 16, 17 and 20).
278
 * The iso7816_create_file will then set this as Tag 86 - Sec.
279
 * Attr. Prop. Format.
280
 * The applet will then be able to set and enforce access rights
281
 * for any file created by OpenSC. Without this function, the
282
 * applet would not know where to enforce security rules and
283
 * when.
284
 *
285
 * Note: IsoApplet currently only supports a "onepin" option.
286
 *
287
 * Format of the sec_attr: 8 Bytes:
288
 *  7      - ISO 7816-4 table 16 or 17
289
 *  6 to 0 - ISO 7816-4 table 20
290
 */
291
static int
292
isoApplet_create_file(sc_card_t *card, sc_file_t *file)
293
0
{
294
0
  int r = 0;
295
296
0
  LOG_FUNC_CALLED(card->ctx);
297
298
0
  if(file->sec_attr_len == 0)
299
0
  {
300
0
    u8 access_buf[8];
301
0
    int idx[8], i;
302
303
0
    if(file->type == SC_FILE_TYPE_DF)
304
0
    {
305
0
      const int df_idx[8] = /* These are the SC operations. */
306
0
      {
307
0
        0, /* Reserved. */
308
0
        SC_AC_OP_DELETE_SELF, /* b6 */
309
0
        SC_AC_OP_LOCK,        /* b5 */
310
0
        SC_AC_OP_ACTIVATE,    /* b4 */
311
0
        SC_AC_OP_DEACTIVATE,  /* b3 */
312
0
        SC_AC_OP_CREATE_DF,   /* b2 */
313
0
        SC_AC_OP_CREATE_EF,   /* b1 */
314
0
        SC_AC_OP_DELETE       /* b0 */
315
0
      };
316
0
      for(i=0; i<8; i++)
317
0
      {
318
0
        idx[i] = df_idx[i];
319
0
      }
320
0
    }
321
0
    else   /* EF */
322
0
    {
323
0
      const int ef_idx[8] =
324
0
      {
325
0
        0, /* Reserved. */
326
0
        SC_AC_OP_DELETE_SELF, /* b6 */
327
0
        SC_AC_OP_LOCK,        /* b5 */
328
0
        SC_AC_OP_ACTIVATE,    /* b4 */
329
0
        SC_AC_OP_DEACTIVATE,  /* b3 */
330
0
        SC_AC_OP_WRITE,       /* b2 */
331
0
        SC_AC_OP_UPDATE,      /* b1 */
332
0
        SC_AC_OP_READ         /* b0 */
333
0
      };
334
0
      for(i=0; i<8; i++)
335
0
      {
336
0
        idx[i] = ef_idx[i];
337
0
      }
338
0
    }
339
    /* Now idx contains the operation identifiers.
340
     * We now search for the OPs. */
341
0
    access_buf[0] = 0xFF; /* A security condition byte is present for every OP. (Table 19) */
342
0
    for(i=1; i<8; i++)
343
0
    {
344
0
      const sc_acl_entry_t *entry;
345
0
      entry = sc_file_get_acl_entry(file, idx[i]);
346
0
      access_buf[i] = isoApplet_acl_to_security_condition_byte(entry);
347
0
    }
348
349
0
    r = sc_file_set_sec_attr(file, access_buf, 8);
350
0
    LOG_TEST_RET(card->ctx, r, "Error adding security attribute.");
351
0
  }
352
353
0
  r = iso_ops->create_file(card, file);
354
0
  LOG_FUNC_RETURN(card->ctx, r);
355
0
}
356
357
/*
358
 * Add an ACL entry to the OpenSC file struct, according to the operation
359
 * and the saByte (Encoded according to IsoApplet FCI proprietary security
360
 * information, see also ISO 7816-4 table 20).
361
 *
362
 * @param[in,out] file
363
 * @param[in]     operation The OpenSC operation.
364
 * @param[in]     saByte    The security condition byte returned by the applet.
365
 */
366
static int
367
isoApplet_add_sa_to_acl(sc_file_t *file, unsigned int operation, u8 saByte)
368
119
{
369
119
  int r;
370
371
119
  switch(saByte)
372
119
  {
373
16
  case 0x90:
374
16
    r = sc_file_add_acl_entry(file, operation, SC_AC_CHV, 1);
375
16
    if(r < 0)
376
0
      return r;
377
16
    break;
378
30
  case 0xFF:
379
30
    r = sc_file_add_acl_entry(file, operation, SC_AC_NEVER, SC_AC_KEY_REF_NONE);
380
30
    if(r < 0)
381
0
      return r;
382
30
    break;
383
30
  case 0x00:
384
23
    r = sc_file_add_acl_entry(file, operation, SC_AC_NONE, SC_AC_KEY_REF_NONE);
385
23
    if(r < 0)
386
0
      return r;
387
23
    break;
388
50
  default:
389
50
    r = sc_file_add_acl_entry(file, operation, SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE);
390
50
    if(r < 0)
391
0
      return r;
392
119
  }
393
119
  return SC_SUCCESS;
394
119
}
395
396
397
/*
398
 * This function first calls the iso7816.c process_fci() for any other FCI
399
 * information and then updates the ACL of the OpenSC file struct according
400
 * to the FCI from the applet.
401
 */
402
static int
403
isoApplet_process_fci(sc_card_t *card, sc_file_t *file,
404
                      const u8 *buf, size_t buflen)
405
44
{
406
44
  int r;
407
44
  u8 *sa = NULL;
408
409
44
  LOG_FUNC_CALLED(card->ctx);
410
411
44
  r = iso_ops->process_fci(card, file, buf, buflen);
412
44
  LOG_TEST_RET(card->ctx, r, "Error while processing the FCI.");
413
  /* Construct the ACL from the sec_attr. */
414
44
  if(file->sec_attr && file->sec_attr_len == 8)
415
32
  {
416
32
    sa = file->sec_attr;
417
32
    if(sa[0] != 0xFF)
418
12
    {
419
12
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA,
420
12
                   "File security attribute does not contain a ACL byte for every operation.");
421
12
    }
422
20
    if(file->type == SC_FILE_TYPE_DF)
423
7
    {
424
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]);
425
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
426
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_LOCK, sa[2]);
427
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
428
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]);
429
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
430
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]);
431
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
432
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_CREATE_DF, sa[5]);
433
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
434
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_CREATE_EF, sa[6]);
435
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
436
7
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE, sa[7]);
437
7
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
438
7
    }
439
13
    else if(file->type == SC_FILE_TYPE_INTERNAL_EF
440
9
            || file->type == SC_FILE_TYPE_WORKING_EF)
441
10
    {
442
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DELETE_SELF, sa[1]);
443
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
444
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_LOCK, sa[2]);
445
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
446
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_ACTIVATE, sa[3]);
447
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
448
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_DEACTIVATE, sa[4]);
449
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
450
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_WRITE, sa[5]);
451
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
452
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_UPDATE, sa[6]);
453
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
454
10
      r = isoApplet_add_sa_to_acl(file, SC_AC_OP_READ, sa[7]);
455
10
      LOG_TEST_RET(card->ctx, r, "Error adding ACL entry.");
456
10
    }
457
458
20
  }
459
460
32
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
461
32
}
462
463
/*
464
 * @brief Encode the EC parameters as a concatenation of TLV entries.
465
 *
466
 * The format is:
467
 *  81 - prime
468
 *  82 - coefficient A
469
 *  83 - coefficient B
470
 *  84 - base point G
471
 *  85 - order
472
 *  87 - cofactor
473
 *
474
 *  @param[in]  card
475
 *  @param[in]  params  The ECparameters containing the information of the curve.
476
 *  @param[out] out     The array the encoded parameters are written to.
477
 *  @param[in]  out_len The size of out
478
 *  @param[out] ptr     A pointer pointing to the end of the parameters in out
479
 *                      (the first untouched byte behind the parameters).
480
 */
481
static int
482
isoApplet_put_ec_params(sc_card_t *card, sc_cardctl_isoApplet_ec_parameters_t *params, u8 *out, size_t out_len, u8 **ptr)
483
0
{
484
0
  u8 *p = out;
485
0
  int r;
486
487
0
  LOG_FUNC_CALLED(card->ctx);
488
489
0
  if(!params
490
0
          || !params->prime.value
491
0
          || !params->coefficientA.value
492
0
          || !params->coefficientB.value
493
0
          || !params->basePointG.value
494
0
          || !params->order.value
495
0
          || !params->coFactor.value)
496
0
  {
497
0
    LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Error: EC params not present.");
498
0
  }
499
500
0
  if(out == NULL || out_len == 0)
501
0
  {
502
0
    LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Error: Parameter out is NULL or outlen is zero.");
503
0
  }
504
505
0
  r = sc_asn1_put_tag(0x81, params->prime.value, params->prime.len, p, out_len - (p - out), &p);
506
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
507
0
  r = sc_asn1_put_tag(0x82, params->coefficientA.value, params->coefficientA.len, p, out_len - (p - out), &p);
508
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
509
0
  r = sc_asn1_put_tag(0x83, params->coefficientB.value, params->coefficientB.len, p, out_len - (p - out), &p);
510
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
511
0
  r = sc_asn1_put_tag(0x84, params->basePointG.value, params->basePointG.len, p, out_len - (p - out), &p);
512
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
513
0
  r = sc_asn1_put_tag(0x85, params->order.value, params->order.len, p, out_len - (p - out), &p);
514
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
515
0
  r = sc_asn1_put_tag(0x87, params->coFactor.value, params->coFactor.len, p, out_len - (p - out), &p);
516
0
  LOG_TEST_RET(card->ctx, r, "Error in handling TLV.");
517
518
0
  if (ptr != NULL)
519
0
    *ptr = p;
520
0
  LOG_FUNC_RETURN(card->ctx, r);
521
0
}
522
523
/*
524
 * @brief Generate a private key on the card.
525
 */
526
static int
527
isoApplet_ctl_generate_key(sc_card_t *card, sc_cardctl_isoApplet_genkey_t *args)
528
0
{
529
0
  int r;
530
0
  sc_apdu_t apdu;
531
0
  u8 rbuf[SC_MAX_EXT_APDU_RESP_SIZE];
532
0
  u8 sbuf[SC_MAX_EXT_APDU_DATA_SIZE];
533
0
  u8 *p;
534
0
  const u8 *inner_tag_value;
535
0
  const u8 *outer_tag_value;
536
0
  unsigned int tag;
537
0
  size_t outer_tag_len;
538
0
  size_t inner_tag_len;
539
0
  unsigned int cla;
540
0
  size_t sz;
541
542
0
  LOG_FUNC_CALLED(card->ctx);
543
544
  /* MANAGE SECURITY ENVIRONMENT (SET). Set the algorithm and key references. */
545
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0x00);
546
547
0
  p = sbuf;
548
0
  *p++ = 0x80; /* algorithm reference */
549
0
  *p++ = 0x01;
550
0
  *p++ = args->algorithm_ref;
551
552
0
  *p++ = 0x84; /* Private key reference */
553
0
  *p++ = 0x01;
554
0
  *p++ = args->priv_key_ref;
555
556
0
  sz = p - sbuf;
557
0
  p = NULL;
558
559
0
  apdu.lc = sz;
560
0
  apdu.datalen = sz;
561
0
  apdu.data = sbuf;
562
563
0
  r = sc_transmit_apdu(card, &apdu);
564
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
565
566
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
567
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
568
569
570
  /* GENERATE ASYMMETRIC KEY PAIR
571
   * We use a larger buffer here, even if the card does not support extended apdus.
572
   * There are two cases:
573
   *  1) The card can do ext. apdus: The data fits in one apdu.
574
   *  2) The card can't do ext. apdus: sc_transmit_apdu will handle that - the
575
   *     card will send SW_BYTES_REMAINING, OpenSC will automatically do a
576
   *     GET RESPONSE to get the remaining data, and will append it to the data
577
   *     buffer. */
578
0
  if(args->algorithm_ref == SC_ISOAPPLET_ALG_REF_EC_GEN)
579
0
  {
580
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x46, 0x00, 0x00);
581
0
    apdu.data = sbuf;
582
0
    p = sbuf;
583
0
    r = isoApplet_put_ec_params(card, &args->pubkey.ec.params, p, sizeof(sbuf), &p);
584
0
    LOG_TEST_RET(card->ctx, r, "Error composing EC params.");
585
0
    apdu.datalen = p - sbuf;
586
0
    apdu.lc = p - sbuf;
587
    /* Use APDU chaining if the card does not support extended apdus
588
     * and the data does not fit in one short apdu. */
589
0
    if ((apdu.datalen > 255) && !(card->caps & SC_CARD_CAP_APDU_EXT))
590
0
    {
591
0
      apdu.flags |= SC_APDU_FLAGS_CHAINING;
592
0
    }
593
0
  }
594
0
  else
595
0
  {
596
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2, 0x46, 0x42, 0x00);
597
0
  }
598
599
0
  apdu.resp = rbuf;
600
0
  apdu.resplen = sizeof(rbuf);
601
0
  if (card->caps & SC_CARD_CAP_APDU_EXT) {
602
0
    apdu.le = apdu.resplen;
603
0
  } else {
604
0
    apdu.le = 256;
605
0
  }
606
0
  r = sc_transmit_apdu(card, &apdu);
607
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
608
609
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
610
0
  if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81)
611
0
  {
612
0
    sc_log(card->ctx, "Key generation not supported by the card with that particular key type. "
613
0
           "Your card may not support the specified algorithm used by the applet / specified by you. "
614
0
           "In most cases, this happens when trying to generate EC keys not supported by your java card. "
615
0
           "In this case, look for supported field lengths and whether FP and/or F2M are supported.");
616
0
  }
617
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
618
619
  /* Parse the public key / response. */
620
0
  outer_tag_value = apdu.resp;
621
0
  r = sc_asn1_read_tag(&outer_tag_value, apdu.resplen, &cla, &tag, &outer_tag_len);
622
0
  LOG_TEST_RET(card->ctx, r, "Error in ASN1 handling.");
623
  /* Interindustry template for nesting one set of public key data objects */
624
0
  if((tag != 0x1F49) || (cla != 0x60))
625
0
  {
626
0
    LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA,
627
0
                 "The data returned by the card is unexpected.");
628
0
  }
629
630
0
  switch(args->algorithm_ref)
631
0
  {
632
633
0
  case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048:
634
0
  case SC_ISOAPPLET_ALG_REF_RSA_GEN_4096:
635
    /* Search for the modulus tag (81). */
636
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x81, &inner_tag_len);
637
0
    const size_t expected_modulus_len = args->algorithm_ref == SC_ISOAPPLET_ALG_REF_RSA_GEN_2048 ? 256 : 512;
638
0
    if(inner_tag_value == NULL || inner_tag_len != expected_modulus_len)
639
0
    {
640
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid modulus.");
641
0
    }
642
0
    if(inner_tag_len > args->pubkey.rsa.modulus.len)
643
0
    {
644
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);
645
0
    }
646
0
    memcpy(args->pubkey.rsa.modulus.value, inner_tag_value, inner_tag_len);
647
0
    args->pubkey.rsa.modulus.len = inner_tag_len;
648
649
    /* Exponent tag (82) */
650
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x82, &inner_tag_len);
651
0
    if(inner_tag_value == NULL || inner_tag_len != 3)
652
0
    {
653
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid exponent.");
654
0
    }
655
0
    if(inner_tag_len > args->pubkey.rsa.exponent.len)
656
0
    {
657
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_BUFFER_TOO_SMALL);
658
0
    }
659
0
    if(memcmp(inner_tag_value, "\x01\x00\x01", 3) != 0)
660
0
    {
661
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INCOMPATIBLE_KEY,
662
0
                   "Key generation error: Unexpected public key exponent.");
663
0
    }
664
0
    memcpy(args->pubkey.rsa.exponent.value, inner_tag_value, inner_tag_len);
665
0
    args->pubkey.rsa.exponent.len = inner_tag_len;
666
0
    p = NULL;
667
0
    break;
668
669
0
  case SC_ISOAPPLET_ALG_REF_EC_GEN:
670
    /* Compare the parameters received from the card to the ones sent to the card. */
671
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x81, &inner_tag_len);
672
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.prime.len
673
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.prime.value, inner_tag_len) != 0)
674
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid prime.");
675
676
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x82, &inner_tag_len);
677
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coefficientA.len
678
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.coefficientA.value, inner_tag_len) != 0)
679
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid coefficient A.");
680
681
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x83, &inner_tag_len);
682
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coefficientB.len
683
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.coefficientB.value, inner_tag_len) != 0)
684
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid coefficient B.");
685
686
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x84, &inner_tag_len);
687
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.basePointG.len
688
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.basePointG.value, inner_tag_len) != 0)
689
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid base point G.");
690
691
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x85, &inner_tag_len);
692
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.order.len
693
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.order.value, inner_tag_len) != 0)
694
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid order.");
695
696
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x87, &inner_tag_len);
697
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.params.coFactor.len
698
0
            || memcmp(inner_tag_value, args->pubkey.ec.params.coFactor.value, inner_tag_len) != 0)
699
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid cofactor.");
700
701
    /* Extract public key */
702
0
    inner_tag_value = sc_asn1_find_tag(card->ctx, outer_tag_value, outer_tag_len, (unsigned int) 0x86, &inner_tag_len);
703
0
    if(inner_tag_value == NULL || inner_tag_len != args->pubkey.ec.ecPointQ.len)
704
0
      LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_DATA, "Card returned no or a invalid EC point Q.");
705
0
    memcpy(args->pubkey.ec.ecPointQ.value, inner_tag_value, inner_tag_len);
706
707
0
    break;
708
0
  default:
709
0
    LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unable to parse public key: Unsupported algorithm.");
710
0
  }/* switch */
711
712
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
713
0
}
714
715
/*
716
 * @brief Use PUT DATA to import a private RSA key.
717
 *
718
 * For simplicity, command chaining has to be used. One chunk (apdu) must contain
719
 * one RSA field (P, Q, etc.). The first apdu must contain the outer tag (7F48).
720
 *
721
 * @param card
722
 * @param rsa The RSA private key to import.
723
 *
724
 * @return SC_ERROR_INVALID_ARGUMENTS: The RSA key does not contain CRT fields.
725
 *       other errors:               Transmit errors / errors returned by card.
726
 */
727
static int
728
isoApplet_put_data_prkey_rsa(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args)
729
0
{
730
0
  sc_apdu_t apdu;
731
0
  u8 sbuf[SC_MAX_EXT_APDU_DATA_SIZE];
732
0
  u8 *p = NULL;
733
0
  int r;
734
0
  size_t tags_len;
735
736
0
  LOG_FUNC_CALLED(card->ctx);
737
738
0
  if(!args->privkey.rsa.p.value
739
0
          || !args->privkey.rsa.q.value
740
0
          || !args->privkey.rsa.iqmp.value
741
0
          || !args->privkey.rsa.dmp1.value
742
0
          || !args->privkey.rsa.dmq1.value)
743
0
  {
744
0
    LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "RSA key is missing information.");
745
0
  }
746
747
  /* Note: The format is according to ISO 2-byte tag 7F48
748
   * "T-L pair to indicate a private key data object" */
749
750
  /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */
751
0
  tags_len = 0;
752
0
  r = sc_asn1_put_tag(0x92, NULL, args->privkey.rsa.p.len, NULL, 0, NULL);
753
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
754
0
  tags_len += r;
755
0
  r = sc_asn1_put_tag(0x93, NULL, args->privkey.rsa.q.len, NULL, 0, NULL);
756
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
757
0
  tags_len += r;
758
0
  r = sc_asn1_put_tag(0x94, NULL, args->privkey.rsa.iqmp.len, NULL, 0, NULL);
759
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
760
0
  tags_len += r;
761
0
  r = sc_asn1_put_tag(0x95, NULL, args->privkey.rsa.dmp1.len, NULL, 0, NULL);
762
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
763
0
  tags_len += r;
764
0
  r = sc_asn1_put_tag(0x96, NULL, args->privkey.rsa.dmq1.len, NULL, 0, NULL);
765
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
766
0
  tags_len += r;
767
768
  /* Write the outer tag and length information. */
769
0
  p = sbuf;
770
0
  r = sc_asn1_put_tag(0x7F48, NULL, tags_len, p, sizeof(sbuf), &p);
771
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
772
773
  /* Write inner tags. */
774
  /* p */
775
0
  r = sc_asn1_put_tag(0x92, args->privkey.rsa.p.value, args->privkey.rsa.p.len, p, sizeof(sbuf) - (p - sbuf), &p);
776
0
  if(r < 0)
777
0
    goto out;
778
  /* q */
779
0
  r = sc_asn1_put_tag(0x93, args->privkey.rsa.q.value, args->privkey.rsa.q.len, p, sizeof(sbuf) - (p - sbuf), &p);
780
0
  if(r < 0)
781
0
    goto out;
782
  /* 1/q mod p */
783
0
  r = sc_asn1_put_tag(0x94, args->privkey.rsa.iqmp.value, args->privkey.rsa.iqmp.len, p, sizeof(sbuf) - (p - sbuf), &p);
784
0
  if(r < 0)
785
0
    goto out;
786
  /* d mod (p-1) */
787
0
  r = sc_asn1_put_tag(0x95, args->privkey.rsa.dmp1.value, args->privkey.rsa.dmp1.len, p, sizeof(sbuf) - (p - sbuf), &p);
788
0
  if(r < 0)
789
0
    goto out;
790
  /* d mod (q-1) */
791
0
  r = sc_asn1_put_tag(0x96, args->privkey.rsa.dmq1.value, args->privkey.rsa.dmq1.len, p, sizeof(sbuf) - (p - sbuf), &p);
792
0
  if(r < 0)
793
0
    goto out;
794
795
  /* Send to card, using chaining or extended APDUs. */
796
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF);
797
0
  apdu.data = sbuf;
798
0
  apdu.datalen = p - sbuf;
799
0
  apdu.lc = p - sbuf;
800
0
  if ((card->caps & SC_CARD_CAP_APDU_EXT) == 0)
801
0
  {
802
    /* The lower layers will automatically do chaining */
803
0
    apdu.flags |= SC_APDU_FLAGS_CHAINING;
804
0
  }
805
0
  r = sc_transmit_apdu(card, &apdu);
806
0
  if(r < 0)
807
0
    goto out;
808
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
809
0
  if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81)
810
0
  {
811
0
    sc_log(card->ctx, "Key import not supported by the card with that particular key type. "
812
0
           "Your card may not support the specified algorithm used by the applet / specified by you. "
813
0
           "In most cases, this happens when trying to import EC keys not supported by your java card. "
814
0
           "In this case, look for supported field lengths and whether FP and/or F2M are supported. "
815
0
           "If you tried to import a private RSA key, check the key length.");
816
0
  }
817
0
  if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00)
818
0
  {
819
0
    sc_log(card->ctx, "Key import not allowed by the applet's security policy. "
820
0
           "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet,"
821
0
           " rebuild and reinstall the applet.");
822
0
  }
823
0
  if(r < 0)
824
0
    goto out;
825
826
0
  r = SC_SUCCESS;
827
0
out:
828
0
  sc_mem_clear(sbuf, sizeof(sbuf));
829
0
  LOG_FUNC_RETURN(card->ctx, r);
830
0
}
831
832
/*
833
 * @brief Use PUT DATA to import a private EC key.
834
 *
835
 * Format of transmitted data:
836
 *  0xE0 - Private class, constructed encoding, number one.
837
 *  0x81 - prime
838
 *  0x82 - coefficient A
839
 *  0x83 - coefficient B
840
 *  0x84 - base point G
841
 *  0x85 - order
842
 *  0x87 - cofactor
843
 *  0x88 - private D (private key)
844
 *
845
 * @param card
846
 * @param ec   The EC private key to import.
847
 *
848
 * @return SC_ERROR_INVALID_ARGUMENTS: Curve parameters or private component is missing.
849
 *         other errors:               Transmit errors / errors returned by card.
850
 *                                     ASN1 errors.
851
 */
852
static int
853
isoApplet_put_data_prkey_ec(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args)
854
0
{
855
0
  sc_apdu_t apdu;
856
0
  u8 sbuf[SC_MAX_EXT_APDU_DATA_SIZE];
857
0
  int r;
858
0
  u8 *p;
859
0
  size_t tags_len;
860
861
0
  LOG_FUNC_CALLED(card->ctx);
862
863
0
  if(!args->privkey.ec.privateD.value
864
0
          || !args->privkey.ec.params.prime.value
865
0
          || !args->privkey.ec.params.coefficientA.value
866
0
          || !args->privkey.ec.params.coefficientB.value
867
0
          || !args->privkey.ec.params.basePointG.value
868
0
          || !args->privkey.ec.params.order.value
869
0
          || !args->privkey.ec.params.coFactor.value
870
0
    )
871
0
  {
872
0
    LOG_TEST_RET(card->ctx, SC_ERROR_INVALID_ARGUMENTS, "Missing information about EC private key.");
873
0
  }
874
875
  /* Calculate the length of all inner tag-length-value entries, but do not write anything yet. */
876
0
  tags_len = 0;
877
0
  r = sc_asn1_put_tag(0x81, NULL, args->privkey.ec.params.prime.len, NULL, 0, NULL);
878
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
879
0
  tags_len += r;
880
0
  r = sc_asn1_put_tag(0x82, NULL, args->privkey.ec.params.coefficientA.len, NULL, 0, NULL);
881
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
882
0
  tags_len += r;
883
0
  r = sc_asn1_put_tag(0x83, NULL, args->privkey.ec.params.coefficientB.len, NULL, 0, NULL);
884
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
885
0
  tags_len += r;
886
0
  r = sc_asn1_put_tag(0x84, NULL, args->privkey.ec.params.basePointG.len, NULL, 0, NULL);
887
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
888
0
  tags_len += r;
889
0
  r = sc_asn1_put_tag(0x85, NULL, args->privkey.ec.params.order.len, NULL, 0, NULL);
890
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
891
0
  tags_len += r;
892
0
  r = sc_asn1_put_tag(0x87, NULL, args->privkey.ec.params.coFactor.len, NULL, 0, NULL);
893
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
894
0
  tags_len += r;
895
0
  r = sc_asn1_put_tag(0x88, NULL, args->privkey.ec.privateD.len, NULL, 0, NULL);
896
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
897
0
  tags_len += r;
898
899
  /* Write the outer tag and length information. */
900
0
  p = sbuf;
901
0
  r = sc_asn1_put_tag(0xE0, NULL, tags_len, p, sizeof(sbuf), &p);
902
0
  LOG_TEST_RET(card->ctx, r, "Error handling TLV.");
903
904
  /* Write inner tags. */
905
0
  r = isoApplet_put_ec_params(card, &args->privkey.ec.params, p, sizeof(sbuf) - (p - sbuf), &p);
906
0
  if(r < 0)
907
0
  {
908
0
    sc_log(card->ctx, "Error composing EC params.");
909
0
    goto out;
910
0
  }
911
0
  r = sc_asn1_put_tag(0x88, args->privkey.ec.privateD.value, args->privkey.ec.privateD.len, p, sizeof(sbuf) - (p - sbuf), &p);
912
0
  if(r < 0)
913
0
    goto out;
914
915
  /* Send to card. */
916
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0xDB, 0x3F, 0xFF);
917
0
  apdu.lc = p - sbuf;
918
0
  apdu.datalen = p - sbuf;
919
0
  apdu.data = sbuf;
920
0
  if ((apdu.datalen > 255) && !(card->caps & SC_CARD_CAP_APDU_EXT))
921
0
  {
922
0
    apdu.flags |= SC_APDU_FLAGS_CHAINING;
923
0
  }
924
0
  r = sc_transmit_apdu(card, &apdu);
925
0
  if(r < 0)
926
0
  {
927
0
    sc_log(card->ctx, "APDU transmit failed");
928
0
    goto out;
929
0
  }
930
931
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
932
0
  if(apdu.sw1 == 0x6D && apdu.sw2 == 0x00)
933
0
  {
934
0
    sc_log(card->ctx, "The applet returned that the PUT DATA instruction byte is not supported. "
935
0
           "If you are using an older applet version and are trying to import keys, please update your applet first.");
936
0
  }
937
0
  else if(apdu.sw1 == 0x6A && apdu.sw2 == 0x81)
938
0
  {
939
0
    sc_log(card->ctx, "Key import not supported by the card with that particular key type. "
940
0
           "Your card may not support the specified algorithm used by the applet / specified by you. "
941
0
           "In most cases, this happens when trying to import EC keys not supported by your java card. "
942
0
           "In this case, look for supported field lengths and whether FP and/or F2M are supported. "
943
0
           "If you tried to import a private RSA key, check the key length.");
944
0
  }
945
0
  else if(apdu.sw1 == 0x69 && apdu.sw2 == 0x00)
946
0
  {
947
0
    sc_log(card->ctx, "Key import not allowed by the applet's security policy. "
948
0
           "If you want to allow key import, set DEF_PRIVATE_KEY_IMPORT_ALLOWED in the IsoApplet,"
949
0
           " rebuild and reinstall the applet.");
950
0
  }
951
0
  if(r < 0)
952
0
  {
953
0
    sc_log(card->ctx, "Card returned error");
954
0
    goto out;
955
0
  }
956
957
0
  r = SC_SUCCESS;
958
0
out:
959
0
  sc_mem_clear(sbuf, sizeof(sbuf));
960
0
  LOG_FUNC_RETURN(card->ctx, r);
961
0
}
962
963
/*
964
 * @brief Import a private key.
965
 */
966
static int
967
isoApplet_ctl_import_key(sc_card_t *card, sc_cardctl_isoApplet_import_key_t *args)
968
0
{
969
0
  int r;
970
0
  size_t sz;
971
0
  sc_apdu_t apdu;
972
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
973
0
  u8 *p;
974
975
0
  LOG_FUNC_CALLED(card->ctx);
976
977
  /*
978
   * Private keys are not stored in the filesystem.
979
   * ISO 7816-8 - section C.2  describes:
980
   * "Usage of the PUT DATA command for private key import"
981
   * The applet uses this PUT DATA to import private keys, if private key import is allowed.
982
   *
983
   * The first step is to perform a MANAGE SECURITY ENVIRONMENT as it would be done
984
   * with on-card key generation. The second step is PUT DATA (instead of
985
   * GENERATE ASYMMETRIC KEY PAIR).
986
   */
987
988
  /* MANAGE SECURITY ENVIRONMENT (SET). Set the algorithm and key references. */
989
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0x00);
990
991
0
  p = sbuf;
992
0
  *p++ = 0x80; /* algorithm reference */
993
0
  *p++ = 0x01;
994
0
  *p++ = args->algorithm_ref;
995
996
0
  *p++ = 0x84; /* Private key reference */
997
0
  *p++ = 0x01;
998
0
  *p++ = args->priv_key_ref;
999
1000
0
  sz = p - sbuf;
1001
0
  p = NULL;
1002
1003
0
  apdu.lc = sz;
1004
0
  apdu.datalen = sz;
1005
0
  apdu.data = sbuf;
1006
1007
0
  r = sc_transmit_apdu(card, &apdu);
1008
0
  LOG_TEST_RET(card->ctx, r, "%s: APDU transmit failed");
1009
1010
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1011
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1012
1013
1014
  /* PUT DATA */
1015
0
  switch(args->algorithm_ref)
1016
0
  {
1017
1018
0
  case SC_ISOAPPLET_ALG_REF_RSA_GEN_2048:
1019
0
    r = isoApplet_put_data_prkey_rsa(card, args);
1020
0
    LOG_TEST_RET(card->ctx, r, "Error in PUT DATA.");
1021
0
    break;
1022
1023
0
  case SC_ISOAPPLET_ALG_REF_EC_GEN:
1024
0
    r = isoApplet_put_data_prkey_ec(card, args);
1025
0
    LOG_TEST_RET(card->ctx, r, "Error in PUT DATA.");
1026
0
    break;
1027
1028
0
  default:
1029
0
    LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unknown algorithm reference.");
1030
0
  }
1031
1032
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
1033
0
}
1034
1035
static int
1036
isoApplet_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
1037
1
{
1038
1
  int r = 0;
1039
1040
1
  LOG_FUNC_CALLED(card->ctx);
1041
1
  switch (cmd)
1042
1
  {
1043
0
  case SC_CARDCTL_ISOAPPLET_GENERATE_KEY:
1044
0
    r = isoApplet_ctl_generate_key(card,
1045
0
                                   (sc_cardctl_isoApplet_genkey_t *) ptr);
1046
0
    break;
1047
0
  case SC_CARDCTL_ISOAPPLET_IMPORT_KEY:
1048
0
    r = isoApplet_ctl_import_key(card,
1049
0
                                 (sc_cardctl_isoApplet_import_key_t *) ptr);
1050
0
    break;
1051
1
  default:
1052
1
    r = SC_ERROR_NOT_SUPPORTED;
1053
1
  }
1054
1
  LOG_FUNC_RETURN(card->ctx, r);
1055
1
}
1056
1057
static int
1058
isoApplet_set_security_env(sc_card_t *card,
1059
                           const sc_security_env_t *env, int se_num)
1060
0
{
1061
0
  sc_apdu_t apdu;
1062
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1063
0
  u8 *p;
1064
0
  int r;
1065
0
  size_t sz;
1066
0
  struct isoApplet_drv_data *drvdata = DRVDATA(card);
1067
1068
0
  LOG_FUNC_CALLED(card->ctx);
1069
1070
0
  if(se_num != 0)
1071
0
  {
1072
0
    LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED,
1073
0
                 "IsoApplet does not support storing of security environments.");
1074
0
  }
1075
0
  assert(card != NULL && env != NULL);
1076
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0);
1077
0
  switch (env->operation)
1078
0
  {
1079
0
  case SC_SEC_OPERATION_DECIPHER:
1080
0
    apdu.p2 = 0xB8;
1081
0
    break;
1082
0
  case SC_SEC_OPERATION_SIGN:
1083
0
    apdu.p2 = 0xB6;
1084
0
    break;
1085
0
  default:
1086
0
    return SC_ERROR_INVALID_ARGUMENTS;
1087
0
  }
1088
0
  p = sbuf;
1089
1090
0
  if (env->flags & SC_SEC_ENV_ALG_PRESENT)
1091
0
  {
1092
1093
0
    switch(env->algorithm)
1094
0
    {
1095
1096
0
    case SC_ALGORITHM_RSA:
1097
0
      if( env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1 )
1098
0
      {
1099
0
        drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_RSA_PAD_PKCS1;
1100
0
      }
1101
0
      else if( env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PSS )
1102
0
      {
1103
0
        drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_RSA_PAD_PSS;
1104
0
      }
1105
0
      else
1106
0
      {
1107
0
        LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "IsoApplet does not support requested padding/hash combination");
1108
0
      }
1109
0
      break;
1110
1111
0
    case SC_ALGORITHM_EC:
1112
0
      drvdata->sec_env_alg_ref = ISOAPPLET_ALG_REF_ECDSA;
1113
0
      drvdata->sec_env_ec_field_length = env->algorithm_ref;
1114
0
      break;
1115
1116
0
    default:
1117
0
      LOG_TEST_RET(card->ctx, SC_ERROR_NOT_SUPPORTED, "Unsupported algorithm.");
1118
0
    }
1119
1120
0
    *p++ = 0x80; /* algorithm reference */
1121
0
    *p++ = 0x01;
1122
0
    *p++ = drvdata->sec_env_alg_ref;
1123
0
  }
1124
1125
0
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
1126
0
  {
1127
0
    *p++ = 0x81;
1128
0
    *p++ = env->file_ref.len;
1129
0
    assert(sizeof(sbuf) - (p - sbuf) >= env->file_ref.len);
1130
0
    memcpy(p, env->file_ref.value, env->file_ref.len);
1131
0
    p += env->file_ref.len;
1132
0
  }
1133
1134
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
1135
0
  {
1136
0
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
1137
0
      *p++ = 0x83;
1138
0
    else
1139
0
      *p++ = 0x84;
1140
0
    *p++ = env->key_ref_len;
1141
0
    assert(sizeof(sbuf) - (p - sbuf) >= env->key_ref_len);
1142
0
    memcpy(p, env->key_ref, env->key_ref_len);
1143
0
    p += env->key_ref_len;
1144
0
  }
1145
0
  sz = p - sbuf;
1146
0
  apdu.lc = sz;
1147
0
  apdu.datalen = sz;
1148
0
  apdu.data = sbuf;
1149
0
  r = (int)sz;
1150
1151
0
  if (apdu.datalen != 0)
1152
0
  {
1153
0
    r = sc_transmit_apdu(card, &apdu);
1154
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1155
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1156
0
    LOG_TEST_RET(card->ctx, r, "Card returned error");
1157
0
  }
1158
1159
0
  LOG_FUNC_RETURN(card->ctx, r);
1160
0
}
1161
1162
static int
1163
isoApplet_compute_signature(struct sc_card *card,
1164
                            const u8 *data, size_t datalen,
1165
                            u8 *out, size_t outlen)
1166
0
{
1167
0
  struct sc_context *ctx = card->ctx;
1168
0
  struct isoApplet_drv_data *drvdata = DRVDATA(card);
1169
0
  int r;
1170
1171
0
  LOG_FUNC_CALLED(ctx);
1172
1173
0
  if (drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_RSA_PAD_PSS) {
1174
    // For RSA-PSS signature schemes the IsoApplet expects only the hash.
1175
0
    u8 tmp[64]; // large enough for SHA512
1176
0
    size_t tmplen = sizeof(tmp);
1177
0
    r = sc_pkcs1_strip_digest_info_prefix(NULL, data, datalen, tmp, &tmplen);
1178
0
    if (r == SC_SUCCESS) {
1179
0
      r = iso_ops->compute_signature(card, tmp, tmplen, out, outlen);
1180
0
    } else {
1181
      /* No digest info present? Use the value as it is */
1182
0
      r = iso_ops->compute_signature(card, data, datalen, out, outlen);
1183
0
    }
1184
0
  } else if (drvdata->sec_env_alg_ref == ISOAPPLET_ALG_REF_ECDSA) {
1185
    /*
1186
    * The card returns ECDSA signatures as an ASN.1 sequence of integers R,S
1187
    * while PKCS#11 expects the raw concatenation of R,S for PKCS#11.
1188
    * We cannot expect the caller to provide an out buffer that is large enough for the ASN.1 sequence.
1189
    * Therefore, we allocate a temporary buffer for the card output, and then convert it to raw R,S.
1190
    * The card supports no curves with field sizes larger than 384bit (EC:secp384r1 which yields an ASN.1
1191
    * encoded signature of 104 byte:
1192
    *  R and S = 384 bit = 48 byte + 1 zero byte if the first bit is set (otherwise they are interpreted as negative).
1193
    *  Seq-Tag&Len (2 bytes) + R-Tag&Len (2 bytes) + R (49 bytes) + S-Tag&Len (2 bytes) + S (49 bytes)
1194
    */
1195
0
    u8 seqbuf[104];
1196
0
    size_t seqlen = sizeof(seqbuf);
1197
0
    r = iso_ops->compute_signature(card, data, datalen, seqbuf, seqlen);
1198
1199
0
    if (r < 0) {
1200
0
      LOG_FUNC_RETURN(ctx, r);
1201
0
    }
1202
1203
    /* Convert ASN.1 sequence of integers R,S to the raw concatenation of R,S for PKCS#11. */
1204
0
    size_t len = BYTES4BITS(drvdata->sec_env_ec_field_length) * 2;
1205
0
    if (len > outlen)
1206
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_BUFFER_TOO_SMALL);
1207
1208
0
    r = sc_asn1_sig_value_sequence_to_rs(ctx, seqbuf, r, out, len);
1209
0
    LOG_TEST_RET(ctx, r, "Failed to convert ASN.1 signature to raw RS");
1210
0
    r = (int)len;
1211
0
  } else {
1212
0
    r = iso_ops->compute_signature(card, data, datalen, out, outlen);
1213
0
  }
1214
0
  LOG_FUNC_RETURN(ctx, r);
1215
0
}
1216
1217
static int
1218
isoApplet_get_challenge(struct sc_card *card, u8 *rnd, size_t len)
1219
0
{
1220
0
  int r;
1221
1222
0
  LOG_FUNC_CALLED(card->ctx);
1223
1224
0
  if(card->caps & SC_CARD_CAP_RNG) {
1225
0
    r = iso_ops->get_challenge(card, rnd, len);
1226
0
  } else   {
1227
0
    r = SC_ERROR_NOT_SUPPORTED;
1228
0
  }
1229
1230
0
  LOG_FUNC_RETURN(card->ctx, r);
1231
0
}
1232
1233
static int isoApplet_card_reader_lock_obtained(sc_card_t *card, int was_reset)
1234
3.84k
{
1235
3.84k
  int r = SC_SUCCESS;
1236
1237
3.84k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1238
1239
3.84k
  if (was_reset > 0) {
1240
0
    r = iso7816_select_aid(card, isoApplet_aid, sizeof(isoApplet_aid), NULL, NULL);
1241
0
  }
1242
1243
3.84k
  LOG_FUNC_RETURN(card->ctx, r);
1244
3.84k
}
1245
1246
static int isoApplet_logout(sc_card_t *card)
1247
0
{
1248
0
  return iso7816_select_aid(card, isoApplet_aid, sizeof(isoApplet_aid), NULL, NULL);
1249
0
}
1250
1251
static struct sc_card_driver *sc_get_driver(void)
1252
15.2k
{
1253
15.2k
  sc_card_driver_t *iso_drv = sc_get_iso7816_driver();
1254
1255
15.2k
  if(iso_ops == NULL)
1256
1
  {
1257
1
    iso_ops = iso_drv->ops;
1258
1
  }
1259
1260
15.2k
  isoApplet_ops = *iso_drv->ops;
1261
1262
15.2k
  isoApplet_ops.match_card = isoApplet_match_card;
1263
15.2k
  isoApplet_ops.init = isoApplet_init;
1264
15.2k
  isoApplet_ops.finish = isoApplet_finish;
1265
1266
15.2k
  isoApplet_ops.card_ctl = isoApplet_card_ctl;
1267
1268
15.2k
  isoApplet_ops.create_file = isoApplet_create_file;
1269
15.2k
  isoApplet_ops.process_fci = isoApplet_process_fci;
1270
15.2k
  isoApplet_ops.set_security_env = isoApplet_set_security_env;
1271
15.2k
  isoApplet_ops.compute_signature = isoApplet_compute_signature;
1272
15.2k
  isoApplet_ops.get_challenge = isoApplet_get_challenge;
1273
15.2k
  isoApplet_ops.card_reader_lock_obtained = isoApplet_card_reader_lock_obtained;
1274
15.2k
  isoApplet_ops.logout = isoApplet_logout;
1275
1276
  /* unsupported functions */
1277
15.2k
  isoApplet_ops.write_binary = NULL;
1278
15.2k
  isoApplet_ops.read_record = NULL;
1279
15.2k
  isoApplet_ops.write_record = NULL;
1280
15.2k
  isoApplet_ops.append_record = NULL;
1281
15.2k
  isoApplet_ops.update_record = NULL;
1282
15.2k
  isoApplet_ops.restore_security_env = NULL;
1283
1284
15.2k
  return &isoApplet_drv;
1285
15.2k
}
1286
1287
struct sc_card_driver * sc_get_isoApplet_driver(void)
1288
15.2k
{
1289
15.2k
  return sc_get_driver();
1290
15.2k
}