Coverage Report

Created: 2025-10-10 06:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-tccardos.c
Line
Count
Source
1
/*
2
 * pkcs15-tccardos.c: PKCS#15 profile for TC CardOS M4 cards
3
 *
4
 * Copyright (C) 2005  Nils Larsch <nils@larsch.net> 
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
28
#include "internal.h"
29
#include "log.h"
30
#include "pkcs15.h"
31
32
0
#define MANU_ID     "SIEMENS AG"
33
0
#define TC_CARDOS_APP_DF  "3F001002"
34
0
#define TC_CARDOS_LABEL   "TC CardOS M4"
35
36
0
#define TC_CARDOS_SIGN    0x0020
37
0
#define TC_CARDOS_AUTH    0x0040
38
0
#define TC_CARDOS_DEC   0x0080
39
0
#define TC_CARDOS_NOPIN   0x1000
40
0
#define TC_CARDOS_LOCALPIN  0x2000
41
#define TC_CARDOS_GLOBALPIN 0x3000
42
0
#define TC_CARDOS_PIN_MASK  0x3000
43
44
static int read_file(struct sc_card *card, const char *file, u8 *buf,
45
  size_t *len)
46
0
{
47
0
  int r;
48
0
  struct sc_path path;
49
0
  struct sc_file *fid = NULL;
50
51
0
  sc_format_path(file, &path);
52
0
  r = sc_select_file(card, &path, &fid);
53
0
  if (r != SC_SUCCESS)
54
0
    return r;
55
0
  if (!fid)
56
0
    return SC_ERROR_INTERNAL;
57
0
  if (fid->size < *len)
58
0
    *len = fid->size;
59
0
  r = sc_read_binary(card, 0, buf, *len, 0);
60
0
  sc_file_free(fid);
61
0
  if ((size_t)r < *len)
62
0
    return SC_ERROR_INTERNAL;
63
64
0
  return SC_SUCCESS;
65
0
}
66
67
static const char *get_keyholder(int fileId)
68
0
{
69
0
  u8 tmp = fileId & 0x0f;
70
71
0
  if (tmp < 0x08)
72
0
    return "CH";
73
0
  else if (tmp < 0x0d)
74
0
    return "CA";
75
0
  else if (tmp == 0x0e)
76
0
    return "RCA";
77
0
  else  
78
0
    return "error";
79
0
}
80
81
static const char *get_service(int fileId)
82
0
{
83
0
  u8 tmp = (fileId >> 8) & 0x0f;
84
85
0
  if (tmp == 0)
86
0
    return "DS";
87
0
  else if (tmp == 2 || tmp == 3)
88
0
    return "KE";
89
0
  else if (tmp == 5)
90
0
    return "AUT"; 
91
0
  else
92
0
    return "error";
93
0
}
94
95
static int create_cert_obj(sc_pkcs15_card_t *p15card, int fileId)
96
0
{
97
0
  sc_pkcs15_object_t    p15obj;
98
0
  sc_pkcs15_cert_info_t cinfo;
99
100
0
  memset(&p15obj, 0, sizeof(p15obj));
101
0
  memset(&cinfo,  0, sizeof(cinfo));
102
  /* the certificate attributes */
103
0
  cinfo.id.value[0] = (fileId >> 8) & 0xff;
104
0
  cinfo.id.value[1] = fileId & 0xff;
105
0
  cinfo.id.len = 2;
106
0
  cinfo.authority = fileId & 0x08 ? 1 : 0;
107
0
  cinfo.path.value[0] = (fileId >> 8) & 0xff;
108
0
  cinfo.path.value[1] = fileId & 0xff;
109
0
  cinfo.path.len   = 2;
110
0
  cinfo.path.type  = SC_PATH_TYPE_FILE_ID;
111
0
  cinfo.path.index =  0;
112
0
  cinfo.path.count = -1;
113
114
  /* compose the certificate name from the fileID */
115
0
  sprintf(p15obj.label, "C.%s.%s", get_keyholder(fileId), get_service(fileId));
116
0
  p15obj.flags        = 0; /* XXX */
117
0
  p15obj.user_consent = 0;
118
119
0
  return sc_pkcs15emu_add_x509_cert(p15card, &p15obj, &cinfo);
120
0
}
121
122
static int create_pkey_obj(sc_pkcs15_card_t *p15card, int cert, int key_descr,
123
  unsigned int keyId, unsigned int pinId)
124
0
{
125
0
  sc_pkcs15_object_t     p15obj;
126
0
  sc_pkcs15_prkey_info_t pinfo;
127
128
  /* init data objects */
129
0
  memset(&p15obj, 0, sizeof(p15obj));
130
0
  memset(&pinfo,  0, sizeof(pinfo));
131
  /* the private key attributes */
132
0
  pinfo.id.value[0] = (cert >> 8) & 0xff;
133
0
  pinfo.id.value[1] = cert & 0xff;
134
0
  pinfo.id.len = 2;
135
0
  pinfo.native   = 1;
136
0
  pinfo.key_reference  = (u8)keyId;
137
0
  pinfo.modulus_length = 1024; /* XXX */
138
0
  pinfo.access_flags = SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE;
139
0
  pinfo.usage    = 0;
140
0
  if (key_descr & TC_CARDOS_SIGN)
141
0
    pinfo.usage = SC_PKCS15_PRKEY_USAGE_SIGN |
142
0
                  SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
143
0
  if (key_descr & TC_CARDOS_AUTH)
144
0
    pinfo.usage |= SC_PKCS15_PRKEY_USAGE_SIGN;
145
0
  if (key_descr & TC_CARDOS_DEC)
146
0
    pinfo.usage = SC_PKCS15_PRKEY_USAGE_ENCRYPT |
147
0
            SC_PKCS15_PRKEY_USAGE_DECRYPT |
148
0
            SC_PKCS15_PRKEY_USAGE_WRAP    |
149
0
            SC_PKCS15_PRKEY_USAGE_UNWRAP;
150
0
  sc_format_path(TC_CARDOS_APP_DF, &pinfo.path);
151
0
  pinfo.path.index = 0;
152
0
  pinfo.path.count = 0;
153
  /* the common object attributes */
154
0
  sprintf(p15obj.label, "SK.CH.%s", get_service(cert));
155
0
  if (pinId && (key_descr & TC_CARDOS_PIN_MASK)) {
156
0
    p15obj.auth_id.value[0] = (u8)pinId;
157
0
    p15obj.auth_id.len      = 1;
158
0
  }
159
0
  p15obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
160
0
  p15obj.user_consent = 0;
161
0
  p15obj.type = SC_PKCS15_TYPE_PRKEY_RSA;
162
163
0
  return sc_pkcs15emu_add_rsa_prkey(p15card, &p15obj, &pinfo);
164
0
}
165
  
166
static int create_pin_obj(sc_pkcs15_card_t *p15card, int cert,
167
  int key_descr, unsigned int pinId)
168
0
{
169
0
  sc_pkcs15_object_t   p15obj;
170
0
  sc_pkcs15_auth_info_t ainfo;
171
172
  /* init data objects */
173
0
  memset(&p15obj, 0, sizeof(p15obj));
174
0
  memset(&ainfo,  0, sizeof(ainfo));
175
  /* the authentication object attributes */
176
0
  ainfo.auth_id.value[0] = (u8)pinId;
177
0
  ainfo.auth_id.len   = 1;
178
0
  ainfo.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
179
0
  ainfo.attrs.pin.reference = (u8)pinId;
180
0
  ainfo.attrs.pin.flags = SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA;
181
0
  if ((key_descr & TC_CARDOS_PIN_MASK) == TC_CARDOS_LOCALPIN)
182
0
    ainfo.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_LOCAL;
183
0
  ainfo.attrs.pin.type  = SC_PKCS15_PIN_TYPE_BCD; /* XXX */
184
0
  ainfo.attrs.pin.min_length = 6;    /* XXX */
185
0
  ainfo.attrs.pin.stored_length = 8; /* XXX */
186
0
  ainfo.attrs.pin.max_length = 8;
187
0
  ainfo.attrs.pin.pad_char   = 0;
188
0
  ainfo.tries_left = 3;    /* XXX */
189
0
  ainfo.logged_in = SC_PIN_STATE_UNKNOWN;
190
0
  sc_format_path(TC_CARDOS_APP_DF, &ainfo.path);
191
0
  ainfo.path.index = 0;
192
0
  ainfo.path.count = 0;
193
  /* the common object attributes */
194
0
  sprintf(p15obj.label, "PIN.CH.%s", get_service(cert));
195
0
  p15obj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
196
0
  p15obj.user_consent = 0;
197
0
  p15obj.type = SC_PKCS15_TYPE_AUTH_PIN;
198
199
0
  return sc_pkcs15emu_add_pin_obj(p15card, &p15obj, &ainfo);
200
0
}
201
202
0
#define MAX_INFO1_SIZE    256
203
0
#define MAX_INFO2_SIZE    256
204
205
static int parse_EF_CardInfo(sc_pkcs15_card_t *p15card)
206
0
{
207
0
  int    r;
208
0
  u8     info1[MAX_INFO1_SIZE];
209
0
  size_t info1_len = MAX_INFO1_SIZE;
210
0
  u8     info2[MAX_INFO2_SIZE];
211
0
  size_t info2_len = MAX_INFO2_SIZE;
212
0
  u8     *p1, *p2;
213
0
  size_t i;
214
0
  unsigned int key_num;
215
0
  struct sc_context *ctx = p15card->card->ctx;
216
0
  size_t offset;
217
218
  /* read EF_CardInfo1 */
219
0
  r = read_file(p15card->card, "3F001003b200", info1, &info1_len);
220
0
  if (r != SC_SUCCESS || info1_len < 4)
221
0
    return SC_ERROR_WRONG_CARD;
222
  /* read EF_CardInfo2 */
223
0
  r = read_file(p15card->card, "3F001003b201", info2, &info2_len);
224
0
  if (r != SC_SUCCESS)
225
0
    return SC_ERROR_WRONG_CARD;
226
  /* get the number of private keys */
227
0
  key_num = ((unsigned int) info1[info1_len-1])
228
0
    | (((unsigned int) info1[info1_len-2]) << 8)
229
0
      | (((unsigned int) info1[info1_len-3]) << 16)
230
0
      | (((unsigned int) info1[info1_len-4]) << 24);
231
0
  sc_log(ctx, 
232
0
    "found %d private keys\n", (int)key_num);
233
  /* set p1 to the address of the first key descriptor */
234
0
  offset = info1_len - 4 - key_num * 2;
235
0
  if (offset >= info1_len)
236
0
    return SC_ERROR_INVALID_DATA;
237
0
  p1 = info1 + offset;
238
0
  p2 = info2;
239
240
  /* This is the minimum amount of data expected by the following code without
241
   * overunning the buffer without additional condition for cert_count == 4 */
242
0
  if (info2_len < key_num * 14)
243
0
    return SC_ERROR_INVALID_DATA;
244
0
  for (i=0; i<key_num; i++) {
245
0
    u8   pinId, keyId, cert_count;
246
0
    int  ch_cert, ca_cert, r1_cert, r2_cert = 0;
247
0
    int  key_descr;
248
    /* evaluate CertInfo2 */
249
0
    cert_count = *p2++;
250
0
    p2 += 2; /* ignore cert DF (it's always 1002) */
251
0
    keyId = *p2++;
252
0
    p2++; /* ignore transport pin XXX */
253
0
    pinId = *p2++;
254
0
    p2 += 2; /* RFU */
255
0
    ch_cert = (p2[0] << 8) | p2[1];
256
0
    p2 += 2;
257
0
    ca_cert = (p2[0] << 8) | p2[1];
258
0
    p2 += 2;
259
0
    r1_cert = (p2[0] << 8) | p2[1];
260
0
    p2 += 2;
261
0
    if (cert_count == 4) {
262
0
      r2_cert = (p2[0] << 8) | p2[1];
263
0
      p2 += 2;
264
0
    }
265
    /* evaluate CertInfo1 */
266
0
    key_descr = (p1[0] << 8) | p1[1];
267
0
    p1 += 2;
268
    /* create and add certificates */
269
0
    if (ch_cert) {
270
0
      r = create_cert_obj(p15card, ch_cert);
271
0
      if (r < 0)
272
0
        return r;
273
0
    }
274
0
    if (ca_cert) {
275
0
      r = create_cert_obj(p15card, ca_cert);
276
0
      if (r < 0)
277
0
        return r;
278
0
    }
279
0
    if (r1_cert) {
280
0
      r = create_cert_obj(p15card, r1_cert);
281
0
      if (r < 0)
282
0
        return r;
283
0
    }
284
0
    if (r2_cert) {
285
0
      r = create_cert_obj(p15card, r2_cert);
286
0
      if (r < 0)
287
0
        return r;
288
0
    }
289
    /* create and add pin object */
290
0
    if ((key_descr & TC_CARDOS_PIN_MASK) != TC_CARDOS_NOPIN) {
291
0
      r = create_pin_obj(p15card, ch_cert, key_descr, pinId);
292
0
      if (r < 0)
293
0
        return r;
294
0
    } else
295
0
      pinId = 0;
296
    /* create and add private key */
297
0
    r = create_pkey_obj(p15card, ch_cert, key_descr, keyId, pinId);
298
0
    if (r < 0)
299
0
      return r;
300
0
  }
301
0
  return SC_SUCCESS;
302
0
}
303
304
305
static int sc_pkcs15_tccardos_init_func(sc_pkcs15_card_t *p15card)
306
0
{
307
0
  int    r;
308
0
  struct sc_path path;
309
0
  struct sc_file *file = NULL;
310
0
  char   hex_buf[256];
311
0
  struct sc_card *card = p15card->card;
312
0
  sc_serial_number_t iccsn;
313
0
  iccsn.len = sizeof iccsn.value;
314
315
  /* check if we have the correct card OS */
316
0
  if (strcmp(card->name, "CardOS M4"))
317
0
    return SC_ERROR_WRONG_CARD;
318
  /* create pkcs15 objects */
319
0
  r = parse_EF_CardInfo(p15card);
320
0
  if (r != SC_SUCCESS)
321
0
    return r;
322
  /* set card label */
323
0
  set_string(&p15card->tokeninfo->label, TC_CARDOS_LABEL);
324
0
  if (p15card->tokeninfo->label == NULL)
325
0
    return SC_ERROR_OUT_OF_MEMORY;
326
  /* set the manufacturer ID */
327
0
  set_string(&p15card->tokeninfo->manufacturer_id, MANU_ID);
328
0
  if (p15card->tokeninfo->manufacturer_id == NULL) {
329
0
    r = SC_ERROR_OUT_OF_MEMORY;
330
0
    goto err;
331
0
  }
332
  /* set the serial number */
333
0
  r = sc_parse_ef_gdo(card, iccsn.value, &iccsn.len, NULL, 0);
334
0
  if (r != SC_SUCCESS || iccsn.len < 5+8) {
335
0
    r = SC_ERROR_INTERNAL;
336
0
    goto err;
337
0
  }
338
0
  sc_bin_to_hex(iccsn.value + 5, 8, hex_buf, sizeof(hex_buf), 0);
339
0
  set_string(&p15card->tokeninfo->serial_number, hex_buf);
340
0
  if (p15card->tokeninfo->serial_number == NULL) {
341
0
    r = SC_ERROR_OUT_OF_MEMORY;
342
0
    goto err;
343
0
  }
344
  /* select the application DF */
345
0
  sc_format_path(TC_CARDOS_APP_DF, &path);
346
0
  r = sc_select_file(card, &path, &file);
347
0
  if (r != SC_SUCCESS || file == NULL) {
348
0
    r = SC_ERROR_INTERNAL;
349
0
    goto err;
350
0
  }
351
  /* set the application DF */
352
0
  sc_file_free(p15card->file_app);
353
0
  p15card->file_app = file;
354
355
0
  return SC_SUCCESS;
356
357
0
err:
358
0
  sc_pkcs15_card_clear(p15card);
359
0
  return r;
360
0
}
361
362
int sc_pkcs15emu_tccardos_init_ex(sc_pkcs15_card_t *p15card,
363
          struct sc_aid *aid)
364
0
{
365
0
  return sc_pkcs15_tccardos_init_func(p15card);
366
0
}