Coverage Report

Created: 2025-08-24 06:59

/src/opensc/src/libopensc/pkcs15-starcert.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * partial PKCS15 emulation for G&D Starcert V2.2 cards
3
 *
4
 * Copyright (C) 2004, Nils <larsch@trustcenter.de>
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 <stdlib.h>
26
#include <string.h>
27
#include <stdio.h>
28
29
#include "internal.h"
30
#include "common/compat_strlcpy.h"
31
#include "pkcs15.h"
32
#include "cardctl.h"
33
34
411
#define MANU_ID   "Giesecke & Devrient GmbH"
35
962
#define STARCERT  "StarCertV2201"
36
37
typedef struct cdata_st {
38
  const char *label;
39
  int     authority;
40
  const char *path;
41
  const char *id;
42
  int         obj_flags;
43
} cdata;
44
45
typedef struct pdata_st {
46
  const char *id;
47
  const char *label;
48
  const char *path;
49
  int         ref;
50
  int         type;
51
  unsigned int maxlen;
52
  unsigned int minlen;
53
  unsigned int storedlen;
54
  int         flags;
55
  int         tries_left;
56
  const char  pad_char;
57
  int         obj_flags;
58
} pindata;
59
60
typedef struct prdata_st {
61
  const char *id;
62
  const char *label;
63
  unsigned int modulus_len;
64
  int         usage;
65
  const char *path;
66
  int         ref;
67
  const char *auth_id;
68
  int         obj_flags;
69
} prdata;
70
71
447
#define USAGE_NONREP  SC_PKCS15_PRKEY_USAGE_NONREPUDIATION
72
447
#define USAGE_KE  SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
73
447
      SC_PKCS15_PRKEY_USAGE_DECRYPT | \
74
447
      SC_PKCS15_PRKEY_USAGE_WRAP    | \
75
447
      SC_PKCS15_PRKEY_USAGE_UNWRAP
76
447
#define USAGE_AUT SC_PKCS15_PRKEY_USAGE_ENCRYPT | \
77
447
      SC_PKCS15_PRKEY_USAGE_DECRYPT | \
78
447
      SC_PKCS15_PRKEY_USAGE_WRAP    | \
79
447
      SC_PKCS15_PRKEY_USAGE_UNWRAP  | \
80
447
      SC_PKCS15_PRKEY_USAGE_SIGN
81
82
static int get_cert_len(sc_card_t *card, sc_path_t *path)
83
1.64k
{
84
1.64k
  int r;
85
1.64k
  u8  buf[8];
86
87
1.64k
  r = sc_select_file(card, path, NULL);
88
1.64k
  if (r < 0)
89
1.37k
    return 0;
90
271
  r = sc_read_binary(card, 0, buf, sizeof(buf), 0);
91
271
  if (r < 0)
92
80
    return 0;
93
191
  if (buf[0] != 0x30 || buf[1] != 0x82)
94
172
    return 0;
95
19
  path->index = 0;
96
19
  path->count = ((buf[2] << 8) | buf[3]) + 4;
97
19
  return 1;
98
191
}
99
100
static int starcert_detect_card(sc_pkcs15_card_t *p15card)
101
69.2k
{
102
69.2k
  int       r;
103
69.2k
  u8        buf[128];
104
69.2k
  sc_path_t path;
105
69.2k
  sc_card_t *card = p15card->card;
106
107
  /* check if we have the correct card OS */
108
69.2k
  if (strcmp(card->name, "STARCOS"))
109
67.6k
    return SC_ERROR_WRONG_CARD;
110
  /* read EF_Info file */
111
1.60k
  sc_format_path("3F00FE13", &path);
112
1.60k
  r = sc_select_file(card, &path, NULL);
113
1.60k
  if (r != SC_SUCCESS)
114
1.06k
    return SC_ERROR_WRONG_CARD;
115
532
  r = sc_read_binary(card, 0, buf, 64, 0);
116
532
  if (r != 64)
117
51
    return SC_ERROR_WRONG_CARD;
118
481
  if (memcmp(buf + 24, STARCERT, strlen(STARCERT)))
119
34
    return SC_ERROR_WRONG_CARD;
120
121
447
  return SC_SUCCESS;
122
481
}
123
124
static int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card)
125
447
{
126
447
  const cdata certs[] = {
127
447
    {"DS certificate", 0, "3F00DF01C000","1",
128
447
      SC_PKCS15_CO_FLAG_MODIFIABLE},
129
447
    {"CA certificate", 1, "3F00DF01C008","2",
130
447
      SC_PKCS15_CO_FLAG_MODIFIABLE},
131
447
    {"KE certificate", 0, "3F00DF01C200","3",
132
447
      SC_PKCS15_CO_FLAG_MODIFIABLE},
133
447
    {"AUT certificate",0, "3F00DF01C500","4",
134
447
      SC_PKCS15_CO_FLAG_MODIFIABLE},
135
447
    {NULL, 0, NULL, NULL, 0}
136
447
  };
137
138
447
  const pindata pins[] = {
139
447
    { "99", "DS pin", "3F00DF01", 0x99,
140
447
      SC_PKCS15_PIN_TYPE_ASCII_NUMERIC,
141
447
      8, 8, 8, SC_PKCS15_PIN_FLAG_NEEDS_PADDING |
142
447
      SC_PKCS15_PIN_FLAG_LOCAL, -1, 0x00,
143
447
      SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE },
144
447
    { NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0}
145
447
  };
146
147
447
  const prdata prkeys[] = {
148
447
    { "01", "DS key", 1024, USAGE_NONREP, "3F00DF01",
149
447
      0x84, "99", SC_PKCS15_CO_FLAG_PRIVATE},
150
447
    { "03", "KE key", 1024, USAGE_KE, "3F00DF01",
151
447
      0x85, NULL, SC_PKCS15_CO_FLAG_PRIVATE},
152
447
    { "04", "AUT key", 1024, USAGE_AUT, "3F00DF01",
153
447
      0x82, NULL, SC_PKCS15_CO_FLAG_PRIVATE},
154
447
    { NULL, NULL, 0, 0, NULL, 0, NULL, 0}
155
447
  };
156
157
447
  int    r, i;
158
447
  char   buf[256];
159
447
  sc_path_t path;
160
447
  sc_file_t *file = NULL;
161
447
  sc_card_t *card = p15card->card;
162
447
  sc_serial_number_t serial;
163
164
  /* get serial number */
165
447
  r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
166
447
  if (r != SC_SUCCESS)
167
36
    return SC_ERROR_INTERNAL;
168
411
  r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
169
411
  if (r != SC_SUCCESS)
170
0
    return SC_ERROR_INTERNAL;
171
172
411
  set_string(&p15card->tokeninfo->serial_number, buf);
173
411
  if (!p15card->tokeninfo->serial_number)
174
0
    return SC_ERROR_INTERNAL;
175
  /* the manufacturer ID, in this case Giesecke & Devrient GmbH */
176
411
  set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
177
411
  if (!p15card->tokeninfo->manufacturer_id)
178
0
    goto err;
179
180
  /* set certs */
181
2.05k
  for (i = 0; certs[i].label; i++) {
182
1.64k
    struct sc_pkcs15_cert_info cert_info;
183
1.64k
    struct sc_pkcs15_object    cert_obj;
184
185
1.64k
    memset(&cert_info, 0, sizeof(cert_info));
186
1.64k
    memset(&cert_obj,  0, sizeof(cert_obj));
187
188
1.64k
    sc_pkcs15_format_id(certs[i].id, &cert_info.id);
189
1.64k
    cert_info.authority = certs[i].authority;
190
1.64k
    sc_format_path(certs[i].path, &cert_info.path);
191
1.64k
    if (!get_cert_len(card, &cert_info.path))
192
      /* skip errors */
193
1.62k
      continue;
194
195
19
    strlcpy(cert_obj.label, certs[i].label, sizeof(cert_obj.label));
196
19
    cert_obj.flags = certs[i].obj_flags;
197
198
19
    r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info);
199
19
    if (r < 0)
200
0
      goto err;
201
19
  }
202
  /* set pins */
203
822
  for (i = 0; pins[i].label; i++) {
204
411
    struct sc_pkcs15_auth_info pin_info;
205
411
    struct sc_pkcs15_object   pin_obj;
206
207
411
    memset(&pin_info, 0, sizeof(pin_info));
208
411
    memset(&pin_obj,  0, sizeof(pin_obj));
209
210
211
411
    sc_pkcs15_format_id(pins[i].id, &pin_info.auth_id);
212
411
    pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
213
411
    pin_info.attrs.pin.reference     = pins[i].ref;
214
411
    pin_info.attrs.pin.flags         = pins[i].flags;
215
411
    pin_info.attrs.pin.type          = pins[i].type;
216
411
    pin_info.attrs.pin.min_length    = pins[i].minlen;
217
411
    pin_info.attrs.pin.stored_length = pins[i].storedlen;
218
411
    pin_info.attrs.pin.max_length    = pins[i].maxlen;
219
411
    pin_info.attrs.pin.pad_char      = pins[i].pad_char;
220
411
    sc_format_path(pins[i].path, &pin_info.path);
221
411
    pin_info.tries_left    = -1;
222
411
    pin_info.logged_in = SC_PIN_STATE_UNKNOWN;
223
224
411
    strlcpy(pin_obj.label, pins[i].label, sizeof(pin_obj.label));
225
411
    pin_obj.flags = pins[i].obj_flags;
226
227
411
    r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info);
228
411
    if (r < 0)
229
0
      goto err;
230
411
  }
231
  /* set private keys */
232
1.64k
  for (i = 0; prkeys[i].label; i++) {
233
1.23k
    struct sc_pkcs15_prkey_info prkey_info;
234
1.23k
    struct sc_pkcs15_object     prkey_obj;
235
236
1.23k
    memset(&prkey_info, 0, sizeof(prkey_info));
237
1.23k
    memset(&prkey_obj,  0, sizeof(prkey_obj));
238
239
1.23k
    sc_pkcs15_format_id(prkeys[i].id, &prkey_info.id);
240
1.23k
    prkey_info.usage         = prkeys[i].usage;
241
1.23k
    prkey_info.native        = 1;
242
1.23k
    prkey_info.key_reference = prkeys[i].ref;
243
1.23k
    prkey_info.modulus_length= prkeys[i].modulus_len;
244
1.23k
    sc_format_path(prkeys[i].path, &prkey_info.path);
245
246
1.23k
    strlcpy(prkey_obj.label, prkeys[i].label, sizeof(prkey_obj.label));
247
1.23k
    prkey_obj.flags = prkeys[i].obj_flags;
248
1.23k
    if (prkeys[i].auth_id)
249
411
      sc_pkcs15_format_id(prkeys[i].auth_id, &prkey_obj.auth_id);
250
251
1.23k
    r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkey_obj, &prkey_info);
252
1.23k
    if (r < 0)
253
0
      goto err;
254
1.23k
  }
255
256
  /* select the application DF */
257
411
  sc_format_path("3F00DF01", &path);
258
411
  r = sc_select_file(card, &path, &file);
259
411
  if (r != SC_SUCCESS || !file)
260
183
    goto err;
261
  /* set the application DF */
262
228
  sc_file_free(p15card->file_app);
263
228
  p15card->file_app = file;
264
265
228
  return SC_SUCCESS;
266
267
183
err:
268
183
  sc_pkcs15_card_clear(p15card);
269
183
  return SC_ERROR_INTERNAL;
270
411
}
271
272
int sc_pkcs15emu_starcert_init_ex(sc_pkcs15_card_t *p15card,
273
          struct sc_aid *aid)
274
69.2k
{
275
69.2k
  if (starcert_detect_card(p15card))
276
68.8k
    return SC_ERROR_WRONG_CARD;
277
447
  return sc_pkcs15emu_starcert_init(p15card);
278
69.2k
}