Coverage Report

Created: 2025-11-23 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-jpki.c
Line
Count
Source
1
/*
2
 * card-jpki.c: Support for JPKI(Japanese Individual Number Cards).
3
 *
4
 * Copyright (C) 2016, HAMANO Tsukasa <hamano@osstech.co.jp>
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
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <string.h>
26
#include <stdlib.h>
27
28
#include "internal.h"
29
#include "jpki.h"
30
31
static const struct sc_atr_table jpki_atrs[] = {
32
  {"3b:e0:00:ff:81:31:fe:45:14", NULL, NULL,
33
   SC_CARD_TYPE_JPKI_BASE, 0, NULL},
34
  {NULL, NULL, NULL, 0, 0, NULL}
35
};
36
37
static struct sc_card_operations jpki_ops;
38
static struct sc_card_driver jpki_drv = {
39
  "JPKI(Japanese Individual Number Cards)",
40
  "jpki",
41
  &jpki_ops,
42
  NULL, 0, NULL
43
};
44
45
int jpki_select_ap(struct sc_card *card)
46
2.42k
{
47
2.42k
  int rc;
48
2.42k
  sc_path_t path;
49
50
2.42k
  LOG_FUNC_CALLED(card->ctx);
51
52
  /* Select JPKI application */
53
2.42k
  sc_format_path(AID_JPKI, &path);
54
2.42k
  path.type = SC_PATH_TYPE_DF_NAME;
55
2.42k
  rc = sc_select_file(card, &path, NULL);
56
2.42k
  LOG_TEST_RET(card->ctx, rc, "select JPKI AP failed");
57
58
70
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
59
70
}
60
61
static int
62
jpki_match_card(struct sc_card *card)
63
2.38k
{
64
2.38k
  int i, rc;
65
66
2.38k
  i = _sc_match_atr(card, jpki_atrs, &card->type);
67
2.38k
  if (i >= 0) {
68
3
    return 1;
69
3
  }
70
71
2.38k
  rc = jpki_select_ap(card);
72
2.38k
  if (rc == SC_SUCCESS) {
73
40
    card->type = SC_CARD_TYPE_JPKI_BASE;
74
40
    return 1;
75
40
  }
76
2.34k
  return 0;
77
2.38k
}
78
79
static int
80
jpki_finish(sc_card_t * card)
81
43
{
82
43
  struct jpki_private_data *drvdata = JPKI_DRVDATA(card);
83
84
43
  LOG_FUNC_CALLED(card->ctx);
85
43
  if (drvdata) {
86
43
    if (drvdata->mf) {
87
43
      free(drvdata->mf);
88
43
    }
89
43
    free(drvdata);
90
43
    card->drv_data = NULL;
91
43
  }
92
43
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
93
43
}
94
95
static int
96
jpki_init(struct sc_card *card)
97
43
{
98
43
  struct jpki_private_data *drvdata;
99
43
  sc_file_t *mf;
100
43
  int flags;
101
102
43
  LOG_FUNC_CALLED(card->ctx);
103
104
43
  drvdata = malloc(sizeof (struct jpki_private_data));
105
43
  if (!drvdata)
106
43
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
107
108
43
  memset(drvdata, 0, sizeof (struct jpki_private_data));
109
110
  /* create virtual MF */
111
43
  mf = sc_file_new();
112
43
  if (!mf) {
113
0
    free(drvdata);
114
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
115
0
  }
116
43
  sc_format_path("3f00", &mf->path);
117
43
  mf->type = SC_FILE_TYPE_DF;
118
43
  mf->shareable = 0;
119
43
  mf->ef_structure = SC_FILE_EF_UNKNOWN;
120
43
  mf->size = 0;
121
43
  mf->id = 0x3f00;
122
43
  mf->status = SC_FILE_STATUS_ACTIVATED;
123
43
  sc_file_add_acl_entry(mf, SC_AC_OP_SELECT, SC_AC_NONE, 0);
124
43
  sc_file_add_acl_entry(mf, SC_AC_OP_LIST_FILES, SC_AC_NONE, 0);
125
43
  sc_file_add_acl_entry(mf, SC_AC_OP_LOCK, SC_AC_NEVER, 0);
126
43
  sc_file_add_acl_entry(mf, SC_AC_OP_DELETE, SC_AC_NEVER, 0);
127
43
  sc_file_add_acl_entry(mf, SC_AC_OP_CREATE, SC_AC_NEVER, 0);
128
43
  drvdata->mf = mf;
129
43
  drvdata->selected = SELECT_MF;
130
131
43
  card->name = "jpki";
132
43
  card->drv_data = drvdata;
133
134
43
  flags = SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_PAD_PKCS1;
135
43
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
136
137
43
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
138
43
}
139
140
static int
141
jpki_select_file(struct sc_card *card,
142
     const struct sc_path *path, struct sc_file **file_out)
143
2.67k
{
144
2.67k
  struct jpki_private_data *drvdata = JPKI_DRVDATA(card);
145
2.67k
  int rc;
146
2.67k
  sc_apdu_t apdu;
147
2.67k
  struct sc_file *file = NULL;
148
149
2.67k
  LOG_FUNC_CALLED(card->ctx);
150
2.67k
  sc_log(card->ctx,
151
2.67k
         "jpki_select_file: path=%s, len=%"SC_FORMAT_LEN_SIZE_T"u",
152
2.67k
         sc_print_path(path), path->len);
153
2.67k
  if (path->len == 2 && memcmp(path->value, "\x3F\x00", 2) == 0) {
154
0
    drvdata->selected = SELECT_MF;
155
0
    if (file_out) {
156
0
      sc_file_dup(file_out, drvdata->mf);
157
0
      if (*file_out == NULL) {
158
0
        LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
159
0
      }
160
0
    }
161
0
    return 0;
162
0
  }
163
164
2.67k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0);
165
2.67k
  switch (path->type) {
166
72
  case SC_PATH_TYPE_FILE_ID:
167
72
    apdu.p1 = 2;
168
72
    break;
169
2.47k
  case SC_PATH_TYPE_DF_NAME:
170
2.47k
    apdu.p1 = 4;
171
2.47k
    break;
172
129
  default:
173
129
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
174
2.67k
  }
175
2.54k
  apdu.p2 = 0x0C;
176
2.54k
  apdu.data = path->value;
177
2.54k
  apdu.datalen = path->len;
178
2.54k
  apdu.lc = path->len;
179
180
2.54k
  rc = sc_transmit_apdu(card, &apdu);
181
2.54k
  LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
182
2.53k
  rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
183
2.53k
  LOG_TEST_RET(card->ctx, rc, "SW Check failed");
184
149
  if (!file_out) {
185
149
    LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
186
149
  }
187
188
  /* read certificate file size */
189
0
  if (path->len == 2 && (
190
0
        memcmp(path->value, "\x00\x0A", 2) == 0 ||
191
0
        memcmp(path->value, "\x00\x01", 2) == 0 ||
192
0
        memcmp(path->value, "\x00\x0B", 2) == 0 ||
193
0
        memcmp(path->value, "\x00\x02", 2) == 0 )
194
0
    ) {
195
0
    u8 buf[4];
196
0
    rc = sc_read_binary(card, 0, buf, 4, 0);
197
0
    LOG_TEST_RET(card->ctx, rc, "SW Check failed");
198
0
    if (rc < 4)
199
0
      LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Received data too short");
200
0
    file = sc_file_new();
201
0
    if (!file) {
202
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
203
0
    }
204
0
    file->path = *path;
205
0
    file->size = (buf[2] << 8 | buf[3]) + 4;
206
0
    *file_out = file;
207
0
  }
208
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
209
0
}
210
211
static int
212
jpki_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data, int *tries_left)
213
63
{
214
63
  int rc;
215
63
  sc_path_t path;
216
63
  sc_apdu_t apdu;
217
63
  struct jpki_private_data *priv = JPKI_DRVDATA(card);
218
63
  int max_tries = 0;
219
220
63
  LOG_FUNC_CALLED(card->ctx);
221
222
63
  if (tries_left) {
223
56
    *tries_left = -1;
224
56
  }
225
226
63
  switch (data->pin_reference) {
227
40
  case 1:
228
40
    sc_format_path(JPKI_AUTH_PIN, &path);
229
40
    path.type = SC_PATH_TYPE_FILE_ID;
230
40
    rc = sc_select_file(card, &path, NULL);
231
40
    max_tries = JPKI_AUTH_PIN_MAX_TRIES;
232
40
    break;
233
23
  case 2:
234
23
    sc_format_path(JPKI_SIGN_PIN, &path);
235
23
    path.type = SC_PATH_TYPE_FILE_ID;
236
23
    rc = sc_select_file(card, &path, NULL);
237
23
    max_tries = JPKI_SIGN_PIN_MAX_TRIES;
238
23
    break;
239
0
  default:
240
0
    sc_log(card->ctx, "Unknown PIN reference: %d", data->pin_reference);
241
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
242
63
  }
243
63
  LOG_TEST_RET(card->ctx, rc, "SELECT_FILE error");
244
245
52
  switch (data->cmd) {
246
10
  case SC_PIN_CMD_VERIFY:
247
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
248
10
    if (data->pin1.len == 0 && !(data->flags & SC_PIN_CMD_USE_PINPAD))
249
10
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_LENGTH);
250
10
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0x20, 0x00, 0x80);
251
10
    apdu.data = data->pin1.data;
252
10
    apdu.datalen = data->pin1.len;
253
10
    apdu.lc = data->pin1.len;
254
10
    rc = sc_transmit_apdu(card, &apdu);
255
10
    LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
256
9
    rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
257
9
    if (rc == SC_SUCCESS) {
258
7
      data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
259
7
      data->pin1.tries_left = max_tries;
260
7
    } else {
261
2
      data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
262
2
      data->pin1.tries_left = apdu.sw2 & 0xF;
263
2
    }
264
9
    priv->logged_in = data->pin1.logged_in;
265
9
    LOG_TEST_RET(card->ctx, rc, "VERIFY failed");
266
7
    break;
267
42
  case SC_PIN_CMD_GET_INFO:
268
42
    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x80);
269
42
    rc = sc_transmit_apdu(card, &apdu);
270
42
    LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
271
39
    if (apdu.sw1 != 0x63) {
272
9
      sc_log(card->ctx, "VERIFY GET_INFO error");
273
9
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
274
9
    }
275
30
    data->pin1.logged_in = priv->logged_in;
276
30
    data->pin1.tries_left = apdu.sw2 & 0xF;
277
30
    if (tries_left) {
278
29
      *tries_left = data->pin1.tries_left;
279
29
    }
280
30
    break;
281
0
  default:
282
0
    sc_log(card->ctx, "Card does not support PIN command: %d", data->cmd);
283
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
284
52
  }
285
286
37
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
287
37
}
288
289
static int
290
jpki_set_security_env(sc_card_t * card,
291
    const sc_security_env_t * env, int se_num)
292
9
{
293
9
  int rc;
294
9
  sc_path_t path;
295
296
9
  LOG_FUNC_CALLED(card->ctx);
297
9
  sc_log(card->ctx,
298
9
         "flags=%08lx op=%d alg=%lu algf=%08lx algr=%08lx kr0=%02x, krfl=%"SC_FORMAT_LEN_SIZE_T"u",
299
9
         env->flags, env->operation, env->algorithm,
300
9
         env->algorithm_flags, env->algorithm_ref, env->key_ref[0],
301
9
         env->key_ref_len);
302
303
9
  switch (env->operation) {
304
9
  case SC_SEC_OPERATION_SIGN:
305
9
    break;
306
0
  default:
307
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
308
9
  }
309
310
9
  switch (env->key_ref[0]) {
311
9
  case 1:
312
9
    sc_format_path(JPKI_AUTH_KEY, &path);
313
9
    break;
314
0
  case 2:
315
0
    sc_format_path(JPKI_SIGN_KEY, &path);
316
0
    break;
317
0
  default:
318
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
319
9
  }
320
9
  path.type = SC_PATH_TYPE_FILE_ID;
321
9
  rc = sc_select_file(card, &path, NULL);
322
9
  LOG_TEST_RET(card->ctx, rc, "select key failed");
323
324
5
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
325
5
}
326
327
static int
328
jpki_compute_signature(sc_card_t * card,
329
    const u8 * data, size_t datalen, u8 * out, size_t outlen)
330
5
{
331
5
  int rc;
332
5
  sc_apdu_t apdu;
333
5
  unsigned char resp[SC_MAX_APDU_BUFFER_SIZE];
334
335
5
  LOG_FUNC_CALLED(card->ctx);
336
337
5
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, 0x80);
338
5
  apdu.cla = 0x80;
339
5
  apdu.data = data;
340
5
  apdu.datalen = datalen;
341
5
  apdu.lc = datalen;
342
5
  apdu.resp = resp;
343
5
  apdu.resplen = sizeof(resp);
344
5
  apdu.le = 0;
345
5
  rc = sc_transmit_apdu(card, &apdu);
346
5
  LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
347
4
  rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
348
4
  LOG_TEST_RET(card->ctx, rc, "SW Check failed");
349
4
  if (apdu.resplen > outlen) {
350
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
351
0
  }
352
4
  memcpy(out, resp, apdu.resplen);
353
4
  LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
354
4
}
355
356
static int jpki_card_reader_lock_obtained(sc_card_t *card, int was_reset)
357
2.43k
{
358
2.43k
  int r = SC_SUCCESS;
359
360
2.43k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
361
362
2.43k
  if (was_reset > 0) {
363
0
    r = jpki_select_ap(card);
364
0
  }
365
366
2.43k
  LOG_FUNC_RETURN(card->ctx, r);
367
2.43k
}
368
369
static int jpki_logout(sc_card_t *card)
370
0
{
371
0
  return jpki_select_ap(card);
372
0
}
373
374
static struct sc_card_driver *
375
sc_get_driver(void)
376
13.2k
{
377
13.2k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
378
379
13.2k
  jpki_ops = *iso_drv->ops;
380
13.2k
  jpki_ops.match_card = jpki_match_card;
381
13.2k
  jpki_ops.init = jpki_init;
382
13.2k
  jpki_ops.finish = jpki_finish;
383
13.2k
  jpki_ops.select_file = jpki_select_file;
384
13.2k
  jpki_ops.pin_cmd = jpki_pin_cmd;
385
13.2k
  jpki_ops.set_security_env = jpki_set_security_env;
386
13.2k
  jpki_ops.compute_signature = jpki_compute_signature;
387
13.2k
  jpki_ops.card_reader_lock_obtained = jpki_card_reader_lock_obtained;
388
13.2k
  jpki_ops.logout = jpki_logout;
389
390
13.2k
  return &jpki_drv;
391
13.2k
}
392
393
struct sc_card_driver *
394
sc_get_jpki_driver(void)
395
13.2k
{
396
13.2k
  return sc_get_driver();
397
13.2k
}