Coverage Report

Created: 2026-09-14 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-gids.c
Line
Count
Source
1
/*
2
 * pkcs15-gids.c: Support for GIDS smart cards.
3
 *
4
 * Copyright (C) 2015 Vincent Le Toux (My Smart Logon) <vincent.letoux@mysmartlogon.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
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#include <stdlib.h>
27
#include <string.h>
28
#include <stdio.h>
29
30
#include "internal.h"
31
#include "pkcs15.h"
32
#include "common/compat_strlcpy.h"
33
#include "cardctl.h"
34
35
#ifdef ENABLE_ZLIB
36
37
#include "card-gids.h"
38
39
/*
40
 * Add a key from a minidriver container
41
 */
42
0
static int sc_pkcs15emu_gids_add_prkey(sc_pkcs15_card_t * p15card, sc_cardctl_gids_get_container_t *container) {
43
44
0
  sc_card_t *card = p15card->card;
45
0
  sc_pkcs15_prkey_info_t prkey_info;
46
0
  sc_pkcs15_object_t     prkey_obj;
47
0
  sc_pkcs15_pubkey_info_t pubkey_info;
48
0
  sc_pkcs15_object_t     pubkey_obj;
49
0
  sc_pkcs15_cert_info_t cert_info;
50
0
  sc_pkcs15_object_t cert_obj;
51
0
  int r;
52
0
  char ch_tmp[10];
53
0
  sc_log(card->ctx, "Got args: containerIndex=%zx\n", container->containernum);
54
55
0
  memset(&prkey_info, 0, sizeof(prkey_info));
56
0
  memset(&prkey_obj,  0, sizeof(prkey_obj));
57
58
0
  prkey_info.id.len = 1;
59
0
  prkey_info.id.value[0] = container->containernum;
60
0
  prkey_info.modulus_length    = container->module_length;
61
0
  prkey_info.usage             = container->prvusage;
62
0
  prkey_info.native            = 1;
63
0
  prkey_info.key_reference     = (int)(0x81 + container->containernum);
64
65
0
  strlcpy(prkey_obj.label, container->label, sizeof(prkey_obj.label));
66
0
  prkey_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
67
0
  prkey_obj.auth_id.len = 1;
68
0
  prkey_obj.auth_id.value[0] = 0x80;
69
70
0
  r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
71
0
  LOG_TEST_RET(card->ctx, r, "unable to sc_pkcs15emu_add_rsa_prkey");
72
73
0
  memset(&pubkey_info, 0, sizeof(pubkey_info));
74
0
  memset(&pubkey_obj,  0, sizeof(pubkey_obj));
75
76
0
  strlcpy(pubkey_obj.label, container->label, sizeof(pubkey_obj.label));
77
78
0
  snprintf(ch_tmp, sizeof(ch_tmp), "3FFFB0%02X", prkey_info.key_reference);
79
0
  sc_format_path(ch_tmp, &pubkey_info.path);
80
0
  pubkey_info.native = 1;
81
0
  pubkey_info.key_reference = prkey_info.key_reference;
82
0
  pubkey_info.modulus_length = prkey_info.modulus_length;
83
0
  pubkey_info.usage = container->pubusage;
84
0
  pubkey_info.id = prkey_info.id;
85
86
0
  r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info);
87
0
  LOG_TEST_RET(card->ctx, r, "unable to sc_pkcs15emu_add_rsa_pubkey");
88
89
0
  if (container->certificatepath.len > 0) {
90
0
    memset(&cert_info, 0, sizeof(cert_info));
91
0
    memset(&cert_obj, 0, sizeof(cert_obj));
92
93
0
    cert_info.id = prkey_info.id;
94
0
    cert_info.path.count = -1;
95
0
    cert_info.path = container->certificatepath;
96
97
0
    strlcpy(cert_obj.label, container->label, sizeof(cert_obj.label));
98
0
    r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
99
0
    LOG_TEST_RET(card->ctx, r, "Could not add certificate");
100
0
  } else {
101
0
    sc_log(card->ctx,  "No certificate found");
102
0
  }
103
104
0
  return SC_SUCCESS;
105
0
}
106
107
/*
108
 * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects
109
 *
110
 */
111
static int sc_pkcs15emu_gids_init (sc_pkcs15_card_t * p15card)
112
117
{
113
117
  sc_card_t *card = p15card->card;
114
117
  int r;
115
117
  size_t i;
116
117
  struct sc_pkcs15_auth_info pin_info;
117
117
  struct sc_pkcs15_object pin_obj;
118
117
  struct sc_pin_cmd_data pin_cmd_data;
119
117
  size_t recordsnum;
120
117
  int has_puk;
121
122
117
  r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_ALL_CONTAINERS, &recordsnum);
123
117
  LOG_TEST_RET(card->ctx, r, "unable to get the containers. Uninitialized card ?");
124
125
0
  r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, NULL);
126
0
  LOG_TEST_RET(card->ctx, r, "unable to get the serial number. Uninitialized card ?");
127
128
0
  free(p15card->tokeninfo->serial_number);
129
0
  p15card->tokeninfo->serial_number = (char*) malloc(card->serialnr.len *2 +1);
130
0
  if (!p15card->tokeninfo->serial_number) {
131
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
132
0
  }
133
0
  sc_bin_to_hex(card->serialnr.value, card->serialnr.len, p15card->tokeninfo->serial_number, card->serialnr.len *2 +1, 0);
134
135
0
  if (p15card->tokeninfo->label == NULL) {
136
0
    p15card->tokeninfo->label = strdup("GIDS card");
137
0
    if (p15card->tokeninfo->label == NULL) {
138
0
      free(p15card->tokeninfo->serial_number);
139
0
      p15card->tokeninfo->serial_number = NULL;
140
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
141
0
    }
142
0
  }
143
144
0
  if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) {
145
0
    free(p15card->tokeninfo->manufacturer_id);
146
0
    p15card->tokeninfo->manufacturer_id = NULL;
147
0
  }
148
149
0
  if (p15card->tokeninfo->manufacturer_id == NULL) {
150
0
    p15card->tokeninfo->manufacturer_id = strdup("www.mysmartlogon.com");
151
0
    if (p15card->tokeninfo->manufacturer_id == NULL) {
152
0
      sc_pkcs15_card_clear(p15card);
153
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
154
0
    }
155
0
  }
156
0
  if (p15card->card->type == SC_CARD_TYPE_GIDS_V2) {
157
0
    p15card->tokeninfo->version = 2;
158
0
  } else if (p15card->card->type == SC_CARD_TYPE_GIDS_V1) {
159
0
    p15card->tokeninfo->version = 1;
160
0
  }
161
162
0
  memset(&pin_info, 0, sizeof(pin_info));
163
0
  memset(&pin_obj, 0, sizeof(pin_obj));
164
165
0
  pin_info.auth_id.len = 1;
166
0
  pin_info.auth_id.value[0] = 0x80;
167
0
  pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
168
0
  pin_info.attrs.pin.reference = 0x80;
169
0
  pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED;
170
0
  pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
171
0
  pin_info.attrs.pin.min_length = 4;
172
0
  pin_info.attrs.pin.stored_length = 0;
173
0
  pin_info.attrs.pin.max_length = 15;
174
0
  pin_info.attrs.pin.pad_char = '\0';
175
0
  pin_info.tries_left = -1;
176
0
  pin_info.max_tries = -1;
177
178
0
  memset(&pin_cmd_data, 0, sizeof(pin_cmd_data));
179
0
  pin_cmd_data.cmd = SC_PIN_CMD_GET_INFO;
180
0
  pin_cmd_data.pin_type = SC_AC_CHV;
181
0
  pin_cmd_data.pin_reference = pin_info.attrs.pin.reference;
182
183
0
  r = sc_pin_cmd(card, &pin_cmd_data);
184
0
  if (r == SC_SUCCESS) {
185
0
    pin_info.max_tries = pin_cmd_data.pin1.max_tries;
186
0
    pin_info.tries_left = pin_cmd_data.pin1.tries_left;
187
0
  }
188
189
0
  strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label));
190
0
  pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE;
191
192
  /*
193
   * check whether PUK is available on this card and then optionally
194
   * link PIN with PUK.
195
   */
196
0
  pin_cmd_data.pin_reference = 0x81;
197
0
  has_puk = sc_pin_cmd(card, &pin_cmd_data) == SC_SUCCESS;
198
0
  if (has_puk) {
199
0
    pin_obj.auth_id.len = 1;
200
0
    pin_obj.auth_id.value[0] = 0x81;
201
0
  }
202
203
0
  r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
204
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "unable to sc_pkcs15emu_add_pin_obj");
205
206
0
  if (has_puk) {
207
0
    pin_info.auth_id.value[0] = 0x81;
208
0
    pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED | SC_PKCS15_PIN_FLAG_UNBLOCKING_PIN;
209
0
    pin_info.attrs.pin.reference = 0x81;
210
0
    pin_info.max_tries = pin_cmd_data.pin1.max_tries;
211
0
    pin_info.tries_left = pin_cmd_data.pin1.tries_left;
212
0
    strlcpy(pin_obj.label, "PUK", sizeof(pin_obj.label));
213
0
    pin_obj.auth_id.len = 0;
214
0
    r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
215
0
    LOG_TEST_GOTO_ERR(card->ctx, r, "unable to sc_pkcs15emu_add_pin_obj with PUK");
216
0
  }
217
218
0
  r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_ALL_CONTAINERS, &recordsnum);
219
0
  LOG_TEST_GOTO_ERR(card->ctx, r, "sc_card_ctl SC_CARDCTL_GIDS_GET_ALL_CONTAINERS");
220
221
0
  for (i = 0; i < recordsnum; i++) {
222
0
    sc_cardctl_gids_get_container_t container;
223
0
    memset(&container, 0, sizeof(sc_cardctl_gids_get_container_t));
224
0
    container.containernum = i;
225
0
    r = sc_card_ctl(card, SC_CARDCTL_GIDS_GET_CONTAINER_DETAIL, &container);
226
0
    if (r < 0) {
227
      // one of the container information couldn't be retrieved
228
      // ignore it
229
0
      continue;
230
0
    }
231
0
    sc_pkcs15emu_gids_add_prkey(p15card, &container);
232
0
  }
233
0
  return SC_SUCCESS;
234
0
err:
235
0
  sc_pkcs15_card_clear(p15card);
236
0
  LOG_FUNC_RETURN(card->ctx, r);
237
0
}
238
239
int sc_pkcs15emu_gids_init_ex(sc_pkcs15_card_t *p15card,
240
        struct sc_aid *aid)
241
9.24k
{
242
9.24k
  if (p15card->card->type != SC_CARD_TYPE_GIDS_GENERIC && p15card->card->type != SC_CARD_TYPE_GIDS_V1 && p15card->card->type != SC_CARD_TYPE_GIDS_V2) {
243
9.12k
    return SC_ERROR_WRONG_CARD;
244
9.12k
  }
245
117
  return sc_pkcs15emu_gids_init(p15card);
246
9.24k
}
247
248
#else
249
250
int sc_pkcs15emu_gids_init_ex(sc_pkcs15_card_t *p15card,
251
        struct sc_aid *aid)
252
{
253
  return SC_ERROR_WRONG_CARD;
254
}
255
256
#endif