Coverage Report

Created: 2026-02-26 06:59

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