Coverage Report

Created: 2026-08-13 06:08

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-iasecc.c
Line
Count
Source
1
/*
2
 * PKCS15 emulation layer for IAS/ECC card.
3
 *
4
 * Copyright (C) 2016, Viktor Tarasov <viktor.tarasov@gmail.com>
5
 * Copyright (C) 2004, Bud P. Bruegger <bud@comune.grosseto.it>
6
 * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
7
 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
28
#include <stdlib.h>
29
#include <string.h>
30
#include <stdio.h>
31
#ifdef ENABLE_OPENSSL
32
#include <openssl/x509v3.h>
33
#endif
34
35
#include "internal.h"
36
#include "pkcs15.h"
37
#include "../pkcs15init/pkcs15-iasecc.h"
38
#include "iasecc.h"
39
#include "aux-data.h"
40
41
0
#define IASECC_GEMALTO_MD_APPLICATION_NAME "CSP"
42
0
#define IASECC_GEMALTO_MD_DEFAULT_CONT_LABEL "Default Key Container"
43
44
static int
45
_iasecc_md_update_keyinfo(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *dobj, int default_cont)
46
0
{
47
0
  struct sc_context *ctx = p15card->card->ctx;
48
0
  struct sc_pkcs15_prkey_info *prkey_info = NULL;
49
0
  struct sc_pkcs15_object *prkey_object = NULL;
50
0
  struct sc_pkcs15_data *ddata = NULL;
51
0
  struct sc_pkcs15_id id;
52
0
  int rv, offs;
53
0
  unsigned flags;
54
0
  int private_obj;
55
56
0
  LOG_FUNC_CALLED(ctx);
57
58
0
  if (!dobj)
59
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
60
61
0
  private_obj = dobj->flags & SC_PKCS15_CO_FLAG_PRIVATE;
62
0
  rv = sc_pkcs15_read_data_object(p15card, (struct sc_pkcs15_data_info *)dobj->data, private_obj, &ddata);
63
0
  LOG_TEST_RET(ctx, rv, "Failed to read container DATA object data");
64
65
  /* [0] = 0x01
66
   * [1] = length
67
   * [2 .. 2 + length] = ID
68
   * [2 + length] = 0x02
69
   * [2 + length + 1] = 0x01
70
   * [3 + length + 2] = flags
71
   */
72
0
  offs = 0;
73
0
  if (ddata->data_len < 2 || *(ddata->data + offs++) != 0x01)   {
74
0
    sc_pkcs15_free_data_object(ddata);
75
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
76
0
  }
77
78
0
  id.len = *(ddata->data + offs++);
79
0
  if (id.len > sizeof(id.value) || ddata->data_len < offs + id.len + 3) {
80
0
    sc_pkcs15_free_data_object(ddata);
81
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
82
0
  }
83
0
  memcpy(id.value, ddata->data + offs, id.len);
84
0
  offs += (int)id.len;
85
86
0
  if (*(ddata->data + offs++) != 0x02)  {
87
0
    sc_pkcs15_free_data_object(ddata);
88
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
89
0
  }
90
0
  if (*(ddata->data + offs++) != 0x01)  {
91
0
    sc_pkcs15_free_data_object(ddata);
92
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
93
0
  }
94
95
0
  flags = *(ddata->data + offs);
96
0
  if (default_cont)
97
0
    flags |= SC_MD_CONTAINER_MAP_DEFAULT_CONTAINER;
98
99
0
  sc_pkcs15_free_data_object(ddata);
100
101
0
  rv = sc_pkcs15_find_prkey_by_id(p15card, &id, &prkey_object);
102
0
  LOG_TEST_RET(ctx, rv, "Find related PrKey error");
103
104
0
  prkey_info = (struct sc_pkcs15_prkey_info *)prkey_object->data;
105
0
  if (prkey_info->aux_data == NULL)   {
106
0
    rv = sc_aux_data_allocate(ctx, &prkey_info->aux_data, NULL);
107
0
    LOG_TEST_RET(ctx, rv, "Cannot allocate MD auxiliary data");
108
0
  }
109
110
0
  rv = sc_aux_data_set_md_guid(ctx, prkey_info->aux_data, dobj->label);
111
0
  LOG_TEST_RET(ctx, rv, "Cannot set MD CMAP Guid");
112
113
0
  rv = sc_aux_data_set_md_flags(ctx, prkey_info->aux_data, flags);
114
0
  LOG_TEST_RET(ctx, rv, "Cannot set MD CMAP record flags");
115
116
0
  LOG_FUNC_RETURN(ctx, rv);
117
0
}
118
119
120
/*
121
 * CPx cards have an undocumented issue: they lack of
122
 * Algorithm's reference into their PKCS's ASN1 encoding.
123
 */
124
static int
125
_iasecc_cpx_fixup_prkdf(struct sc_pkcs15_card *p15card)
126
0
{
127
0
  struct sc_context * const ctx = p15card->card->ctx;
128
0
  struct sc_pkcs15_object *pkobjs[32];
129
0
  int ii, count;
130
0
  int rv = SC_SUCCESS;
131
132
0
  LOG_FUNC_CALLED(ctx);
133
134
0
  rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, pkobjs, sizeof(pkobjs)/sizeof(pkobjs[0]));
135
0
  LOG_TEST_RET(ctx, rv, "Cannot get PRKEY objects list");
136
137
0
  count = rv;
138
0
  for(ii=0; ii<count; ii++)   {
139
0
    rv = iasecc_pkcs15_encode_supported_algos(p15card, pkobjs[ii]);
140
0
    LOG_TEST_RET(ctx, rv, "Cannot fix suported_algos");
141
0
  }
142
143
0
  LOG_FUNC_RETURN(ctx, rv);
144
0
}
145
146
147
/*
148
 * It is the entry point for 2 models of cards that need some hot patching
149
 * - Gemalto cards
150
 * - CPx: fixup algo_refs from the prkey
151
 */
152
static int
153
_iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
154
0
{
155
0
  struct sc_context *ctx = p15card->card->ctx;
156
0
  struct sc_pkcs15_object *dobjs[32];
157
0
  struct sc_pkcs15_data *default_guid = NULL;
158
0
  int rv, ii, count;
159
160
0
  LOG_FUNC_CALLED(ctx);
161
162
0
  if (!df)
163
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
164
165
0
  if (df->enumerated)
166
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
167
168
0
  rv = sc_pkcs15_parse_df(p15card, df);
169
0
  LOG_TEST_RET(ctx, rv, "DF parse error");
170
171
0
  switch(p15card->card->type) {
172
    /* enumerate the IASECC cards that need a fixup of the keyInfo */
173
0
    case SC_CARD_TYPE_IASECC_GEMALTO:
174
0
    case SC_CARD_TYPE_IASECC_CPX:
175
0
    case SC_CARD_TYPE_IASECC_CPXCL:
176
0
      sc_log(ctx, "Warning: the %d card has an invalid DF, hot patch to be applied",
177
0
        p15card->card->type);
178
0
      break;
179
0
    default:
180
0
      sc_log(ctx, "the %d card has a proper DF, no need for a hot patch",
181
0
        p15card->card->type);
182
0
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
183
0
      break;
184
0
  }
185
186
0
  if (df->type != SC_PKCS15_PRKDF)
187
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
188
189
0
  sc_log(ctx, "parse of SC_PKCS15_PRKDF");
190
191
0
  rv = _iasecc_cpx_fixup_prkdf(p15card);
192
0
  LOG_TEST_RET(ctx, rv, "Cannot fixup PrKDF");
193
194
0
  rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, sizeof(dobjs)/sizeof(dobjs[0]));
195
0
  LOG_TEST_RET(ctx, rv, "Cannot get DATA objects list");
196
197
0
  count = rv;
198
0
  for(ii=0; ii<count; ii++)   {
199
0
    struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
200
0
    int private_obj = dobjs[ii]->flags & SC_PKCS15_CO_FLAG_PRIVATE;
201
202
0
    if (strcmp(dinfo->app_label, IASECC_GEMALTO_MD_APPLICATION_NAME))
203
0
      continue;
204
205
0
    if (!strcmp(dobjs[ii]->label, IASECC_GEMALTO_MD_DEFAULT_CONT_LABEL))   {
206
0
      rv = sc_pkcs15_read_data_object(p15card, (struct sc_pkcs15_data_info *)dobjs[ii]->data, private_obj, &default_guid);
207
0
      LOG_TEST_RET(ctx, rv, "Failed to read 'default container' DATA object data");
208
0
      break;
209
0
    }
210
0
  }
211
212
0
  for(ii=0; ii<count; ii++)   {
213
0
    struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
214
0
    int default_cont = 0;
215
216
0
    if (strcmp(dinfo->app_label, IASECC_GEMALTO_MD_APPLICATION_NAME))
217
0
      continue;
218
219
0
    if (!strcmp(dobjs[ii]->label, IASECC_GEMALTO_MD_DEFAULT_CONT_LABEL))
220
0
      continue;
221
222
0
    if (default_guid)
223
0
      if (strlen(dobjs[ii]->label) == default_guid->data_len)
224
0
        if (!memcmp(dobjs[ii]->label, default_guid->data, default_guid->data_len))
225
0
          default_cont = 1;
226
227
0
    rv = _iasecc_md_update_keyinfo(p15card, dobjs[ii], default_cont);
228
0
    LOG_TEST_RET(ctx, rv, "Cannot update key MD info");
229
0
  }
230
231
0
  sc_pkcs15_free_data_object(default_guid);
232
233
0
  LOG_FUNC_RETURN(ctx, rv);
234
0
}
235
236
237
static int
238
iasecc_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card)
239
111
{
240
111
  if (p15card->card->type < SC_CARD_TYPE_IASECC_BASE)
241
0
    return SC_ERROR_WRONG_CARD;
242
243
111
  if (p15card->card->type > SC_CARD_TYPE_IASECC_BASE + 10)
244
111
    return SC_ERROR_WRONG_CARD;
245
246
0
  return SC_SUCCESS;
247
111
}
248
249
250
static int
251
sc_pkcs15emu_iasecc_init (struct sc_pkcs15_card *p15card, struct sc_aid *aid)
252
0
{
253
0
  struct sc_context *ctx = p15card->card->ctx;
254
0
  int rv;
255
256
0
  LOG_FUNC_CALLED(ctx);
257
258
0
  rv = sc_pkcs15_bind_internal(p15card, aid);
259
260
0
  p15card->ops.parse_df = _iasecc_parse_df;
261
262
0
  LOG_FUNC_RETURN(ctx, rv);
263
0
}
264
265
266
int
267
sc_pkcs15emu_iasecc_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
268
111
{
269
111
  if (iasecc_pkcs15emu_detect_card(p15card))
270
111
    return SC_ERROR_WRONG_CARD;
271
272
0
  return sc_pkcs15emu_iasecc_init(p15card, aid);
273
111
}