Coverage Report

Created: 2025-11-09 06:38

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.45k
{
47
2.45k
  int rc;
48
2.45k
  sc_path_t path;
49
50
2.45k
  LOG_FUNC_CALLED(card->ctx);
51
52
  /* Select JPKI application */
53
2.45k
  sc_format_path(AID_JPKI, &path);
54
2.45k
  path.type = SC_PATH_TYPE_DF_NAME;
55
2.45k
  rc = sc_select_file(card, &path, NULL);
56
2.45k
  LOG_TEST_RET(card->ctx, rc, "select JPKI AP failed");
57
58
6
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
59
6
}
60
61
static int
62
jpki_match_card(struct sc_card *card)
63
2.45k
{
64
2.45k
  int i, rc;
65
66
2.45k
  i = _sc_match_atr(card, jpki_atrs, &card->type);
67
2.45k
  if (i >= 0) {
68
1
    return 1;
69
1
  }
70
71
2.45k
  rc = jpki_select_ap(card);
72
2.45k
  if (rc == SC_SUCCESS) {
73
6
    card->type = SC_CARD_TYPE_JPKI_BASE;
74
6
    return 1;
75
6
  }
76
2.44k
  return 0;
77
2.45k
}
78
79
static int
80
jpki_finish(sc_card_t * card)
81
7
{
82
7
  struct jpki_private_data *drvdata = JPKI_DRVDATA(card);
83
84
7
  LOG_FUNC_CALLED(card->ctx);
85
7
  if (drvdata) {
86
7
    if (drvdata->mf) {
87
7
      free(drvdata->mf);
88
7
    }
89
7
    free(drvdata);
90
7
    card->drv_data = NULL;
91
7
  }
92
7
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
93
7
}
94
95
static int
96
jpki_init(struct sc_card *card)
97
7
{
98
7
  struct jpki_private_data *drvdata;
99
7
  sc_file_t *mf;
100
7
  int flags;
101
102
7
  LOG_FUNC_CALLED(card->ctx);
103
104
7
  drvdata = malloc(sizeof (struct jpki_private_data));
105
7
  if (!drvdata)
106
7
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
107
108
7
  memset(drvdata, 0, sizeof (struct jpki_private_data));
109
110
  /* create virtual MF */
111
7
  mf = sc_file_new();
112
7
  if (!mf) {
113
0
    free(drvdata);
114
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
115
0
  }
116
7
  sc_format_path("3f00", &mf->path);
117
7
  mf->type = SC_FILE_TYPE_DF;
118
7
  mf->shareable = 0;
119
7
  mf->ef_structure = SC_FILE_EF_UNKNOWN;
120
7
  mf->size = 0;
121
7
  mf->id = 0x3f00;
122
7
  mf->status = SC_FILE_STATUS_ACTIVATED;
123
7
  sc_file_add_acl_entry(mf, SC_AC_OP_SELECT, SC_AC_NONE, 0);
124
7
  sc_file_add_acl_entry(mf, SC_AC_OP_LIST_FILES, SC_AC_NONE, 0);
125
7
  sc_file_add_acl_entry(mf, SC_AC_OP_LOCK, SC_AC_NEVER, 0);
126
7
  sc_file_add_acl_entry(mf, SC_AC_OP_DELETE, SC_AC_NEVER, 0);
127
7
  sc_file_add_acl_entry(mf, SC_AC_OP_CREATE, SC_AC_NEVER, 0);
128
7
  drvdata->mf = mf;
129
7
  drvdata->selected = SELECT_MF;
130
131
7
  card->name = "jpki";
132
7
  card->drv_data = drvdata;
133
134
7
  flags = SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_PAD_PKCS1;
135
7
  _sc_card_add_rsa_alg(card, 2048, flags, 0);
136
137
7
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
138
7
}
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.45k
{
144
2.45k
  struct jpki_private_data *drvdata = JPKI_DRVDATA(card);
145
2.45k
  int rc;
146
2.45k
  sc_apdu_t apdu;
147
2.45k
  struct sc_file *file = NULL;
148
149
2.45k
  LOG_FUNC_CALLED(card->ctx);
150
2.45k
  sc_log(card->ctx,
151
2.45k
         "jpki_select_file: path=%s, len=%"SC_FORMAT_LEN_SIZE_T"u",
152
2.45k
         sc_print_path(path), path->len);
153
2.45k
  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.45k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0, 0);
165
2.45k
  switch (path->type) {
166
0
  case SC_PATH_TYPE_FILE_ID:
167
0
    apdu.p1 = 2;
168
0
    break;
169
2.45k
  case SC_PATH_TYPE_DF_NAME:
170
2.45k
    apdu.p1 = 4;
171
2.45k
    break;
172
0
  default:
173
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
174
2.45k
  }
175
2.45k
  apdu.p2 = 0x0C;
176
2.45k
  apdu.data = path->value;
177
2.45k
  apdu.datalen = path->len;
178
2.45k
  apdu.lc = path->len;
179
180
2.45k
  rc = sc_transmit_apdu(card, &apdu);
181
2.45k
  LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
182
2.44k
  rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
183
2.44k
  LOG_TEST_RET(card->ctx, rc, "SW Check failed");
184
6
  if (!file_out) {
185
6
    LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
186
6
  }
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
0
{
214
0
  int rc;
215
0
  sc_path_t path;
216
0
  sc_apdu_t apdu;
217
0
  struct jpki_private_data *priv = JPKI_DRVDATA(card);
218
0
  int max_tries = 0;
219
220
0
  LOG_FUNC_CALLED(card->ctx);
221
222
0
  if (tries_left) {
223
0
    *tries_left = -1;
224
0
  }
225
226
0
  switch (data->pin_reference) {
227
0
  case 1:
228
0
    sc_format_path(JPKI_AUTH_PIN, &path);
229
0
    path.type = SC_PATH_TYPE_FILE_ID;
230
0
    rc = sc_select_file(card, &path, NULL);
231
0
    max_tries = JPKI_AUTH_PIN_MAX_TRIES;
232
0
    break;
233
0
  case 2:
234
0
    sc_format_path(JPKI_SIGN_PIN, &path);
235
0
    path.type = SC_PATH_TYPE_FILE_ID;
236
0
    rc = sc_select_file(card, &path, NULL);
237
0
    max_tries = JPKI_SIGN_PIN_MAX_TRIES;
238
0
    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
0
  }
243
0
  LOG_TEST_RET(card->ctx, rc, "SELECT_FILE error");
244
245
0
  switch (data->cmd) {
246
0
  case SC_PIN_CMD_VERIFY:
247
    /* detect overloaded APDU with SC_PIN_CMD_GET_INFO */
248
0
    if (data->pin1.len == 0 && !(data->flags & SC_PIN_CMD_USE_PINPAD))
249
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_PIN_LENGTH);
250
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3, 0x20, 0x00, 0x80);
251
0
    apdu.data = data->pin1.data;
252
0
    apdu.datalen = data->pin1.len;
253
0
    apdu.lc = data->pin1.len;
254
0
    rc = sc_transmit_apdu(card, &apdu);
255
0
    LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
256
0
    rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
257
0
    if (rc == SC_SUCCESS) {
258
0
      data->pin1.logged_in = SC_PIN_STATE_LOGGED_IN;
259
0
      data->pin1.tries_left = max_tries;
260
0
    } else {
261
0
      data->pin1.logged_in = SC_PIN_STATE_LOGGED_OUT;
262
0
      data->pin1.tries_left = apdu.sw2 & 0xF;
263
0
    }
264
0
    priv->logged_in = data->pin1.logged_in;
265
0
    LOG_TEST_RET(card->ctx, rc, "VERIFY failed");
266
0
    break;
267
0
  case SC_PIN_CMD_GET_INFO:
268
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x20, 0x00, 0x80);
269
0
    rc = sc_transmit_apdu(card, &apdu);
270
0
    LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
271
0
    if (apdu.sw1 != 0x63) {
272
0
      sc_log(card->ctx, "VERIFY GET_INFO error");
273
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_CARD_CMD_FAILED);
274
0
    }
275
0
    data->pin1.logged_in = priv->logged_in;
276
0
    data->pin1.tries_left = apdu.sw2 & 0xF;
277
0
    if (tries_left) {
278
0
      *tries_left = data->pin1.tries_left;
279
0
    }
280
0
    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
0
  }
285
286
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
287
0
}
288
289
static int
290
jpki_set_security_env(sc_card_t * card,
291
    const sc_security_env_t * env, int se_num)
292
0
{
293
0
  int rc;
294
0
  sc_path_t path;
295
296
0
  LOG_FUNC_CALLED(card->ctx);
297
0
  sc_log(card->ctx,
298
0
         "flags=%08lx op=%d alg=%lu algf=%08lx algr=%08lx kr0=%02x, krfl=%"SC_FORMAT_LEN_SIZE_T"u",
299
0
         env->flags, env->operation, env->algorithm,
300
0
         env->algorithm_flags, env->algorithm_ref, env->key_ref[0],
301
0
         env->key_ref_len);
302
303
0
  switch (env->operation) {
304
0
  case SC_SEC_OPERATION_SIGN:
305
0
    break;
306
0
  default:
307
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_NOT_SUPPORTED);
308
0
  }
309
310
0
  switch (env->key_ref[0]) {
311
0
  case 1:
312
0
    sc_format_path(JPKI_AUTH_KEY, &path);
313
0
    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
0
  }
320
0
  path.type = SC_PATH_TYPE_FILE_ID;
321
0
  rc = sc_select_file(card, &path, NULL);
322
0
  LOG_TEST_RET(card->ctx, rc, "select key failed");
323
324
0
  LOG_FUNC_RETURN(card->ctx, SC_SUCCESS);
325
0
}
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
0
{
331
0
  int rc;
332
0
  sc_apdu_t apdu;
333
0
  unsigned char resp[SC_MAX_APDU_BUFFER_SIZE];
334
335
0
  LOG_FUNC_CALLED(card->ctx);
336
337
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x00, 0x80);
338
0
  apdu.cla = 0x80;
339
0
  apdu.data = data;
340
0
  apdu.datalen = datalen;
341
0
  apdu.lc = datalen;
342
0
  apdu.resp = resp;
343
0
  apdu.resplen = sizeof(resp);
344
0
  apdu.le = 0;
345
0
  rc = sc_transmit_apdu(card, &apdu);
346
0
  LOG_TEST_RET(card->ctx, rc, "APDU transmit failed");
347
0
  rc = sc_check_sw(card, apdu.sw1, apdu.sw2);
348
0
  LOG_TEST_RET(card->ctx, rc, "SW Check failed");
349
0
  if (apdu.resplen > outlen) {
350
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
351
0
  }
352
0
  memcpy(out, resp, apdu.resplen);
353
0
  LOG_FUNC_RETURN(card->ctx, (int)apdu.resplen);
354
0
}
355
356
static int jpki_card_reader_lock_obtained(sc_card_t *card, int was_reset)
357
2.45k
{
358
2.45k
  int r = SC_SUCCESS;
359
360
2.45k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
361
362
2.45k
  if (was_reset > 0) {
363
0
    r = jpki_select_ap(card);
364
0
  }
365
366
2.45k
  LOG_FUNC_RETURN(card->ctx, r);
367
2.45k
}
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
18.4k
{
377
18.4k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
378
379
18.4k
  jpki_ops = *iso_drv->ops;
380
18.4k
  jpki_ops.match_card = jpki_match_card;
381
18.4k
  jpki_ops.init = jpki_init;
382
18.4k
  jpki_ops.finish = jpki_finish;
383
18.4k
  jpki_ops.select_file = jpki_select_file;
384
18.4k
  jpki_ops.pin_cmd = jpki_pin_cmd;
385
18.4k
  jpki_ops.set_security_env = jpki_set_security_env;
386
18.4k
  jpki_ops.compute_signature = jpki_compute_signature;
387
18.4k
  jpki_ops.card_reader_lock_obtained = jpki_card_reader_lock_obtained;
388
18.4k
  jpki_ops.logout = jpki_logout;
389
390
18.4k
  return &jpki_drv;
391
18.4k
}
392
393
struct sc_card_driver *
394
sc_get_jpki_driver(void)
395
18.4k
{
396
18.4k
  return sc_get_driver();
397
18.4k
}