Coverage Report

Created: 2026-01-10 06:05

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