Coverage Report

Created: 2025-08-24 06:59

/src/opensc/src/libopensc/pkcs15-iasecc.c
Line
Count
Source (jump to first uncovered line)
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
  offs = 0;
66
0
  if (*(ddata->data + offs++) != 0x01)   {
67
0
    sc_pkcs15_free_data_object(ddata);
68
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
69
0
  }
70
71
0
  id.len = *(ddata->data + offs++);
72
0
  memcpy(id.value, ddata->data + offs, id.len);
73
0
  offs += (int) id.len;
74
75
0
  if (*(ddata->data + offs++) != 0x02)  {
76
0
    sc_pkcs15_free_data_object(ddata);
77
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
78
0
  }
79
0
  if (*(ddata->data + offs++) != 0x01)  {
80
0
    sc_pkcs15_free_data_object(ddata);
81
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
82
0
  }
83
84
0
  flags = *(ddata->data + offs);
85
0
  if (default_cont)
86
0
    flags |= SC_MD_CONTAINER_MAP_DEFAULT_CONTAINER;
87
88
0
  sc_pkcs15_free_data_object(ddata);
89
90
0
  rv = sc_pkcs15_find_prkey_by_id(p15card, &id, &prkey_object);
91
0
  LOG_TEST_RET(ctx, rv, "Find related PrKey error");
92
93
0
  prkey_info = (struct sc_pkcs15_prkey_info *)prkey_object->data;
94
0
  if (prkey_info->aux_data == NULL)   {
95
0
    rv = sc_aux_data_allocate(ctx, &prkey_info->aux_data, NULL);
96
0
    LOG_TEST_RET(ctx, rv, "Cannot allocate MD auxiliary data");
97
0
  }
98
99
0
  rv = sc_aux_data_set_md_guid(ctx, prkey_info->aux_data, dobj->label);
100
0
  LOG_TEST_RET(ctx, rv, "Cannot set MD CMAP Guid");
101
102
0
  rv = sc_aux_data_set_md_flags(ctx, prkey_info->aux_data, flags);
103
0
  LOG_TEST_RET(ctx, rv, "Cannot set MD CMAP record flags");
104
105
0
  LOG_FUNC_RETURN(ctx, rv);
106
0
}
107
108
109
/*
110
 * CPx cards have an undocumented issue: they lack of
111
 * Algorithm's reference into their PKCS's ASN1 encoding.
112
 */
113
static int
114
_iasecc_cpx_fixup_prkdf(struct sc_pkcs15_card *p15card)
115
0
{
116
0
  struct sc_context * const ctx = p15card->card->ctx;
117
0
  struct sc_pkcs15_object *pkobjs[32];
118
0
  int ii, count;
119
0
  int rv = SC_SUCCESS;
120
121
0
  LOG_FUNC_CALLED(ctx);
122
123
0
  rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, pkobjs, sizeof(pkobjs)/sizeof(pkobjs[0]));
124
0
  LOG_TEST_RET(ctx, rv, "Cannot get PRKEY objects list");
125
126
0
  count = rv;
127
0
  for(ii=0; ii<count; ii++)   {
128
0
    rv = iasecc_pkcs15_encode_supported_algos(p15card, pkobjs[ii]);
129
0
    LOG_TEST_RET(ctx, rv, "Cannot fix suported_algos");
130
0
  }
131
132
0
  LOG_FUNC_RETURN(ctx, rv);
133
0
}
134
135
136
/*
137
 * It is the entry point for 2 models of cards that need some hot patching
138
 * - Gemalto cards
139
 * - CPx: fixup algo_refs from the prkey
140
 */
141
static int
142
_iasecc_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
143
0
{
144
0
  struct sc_context *ctx = p15card->card->ctx;
145
0
  struct sc_pkcs15_object *dobjs[32];
146
0
  struct sc_pkcs15_data *default_guid = NULL;
147
0
  int rv, ii, count;
148
149
0
  LOG_FUNC_CALLED(ctx);
150
151
0
  if (!df)
152
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
153
154
0
  if (df->enumerated)
155
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
156
157
0
  rv = sc_pkcs15_parse_df(p15card, df);
158
0
  LOG_TEST_RET(ctx, rv, "DF parse error");
159
160
0
  switch(p15card->card->type) {
161
    /* enumerate the IASECC cards that need a fixup of the keyInfo */
162
0
    case SC_CARD_TYPE_IASECC_GEMALTO:
163
0
    case SC_CARD_TYPE_IASECC_CPX:
164
0
    case SC_CARD_TYPE_IASECC_CPXCL:
165
0
      sc_log(ctx, "Warning: the %d card has an invalid DF, hot patch to be applied",
166
0
        p15card->card->type);
167
0
      break;
168
0
    default:
169
0
      sc_log(ctx, "the %d card has a proper DF, no need for a hot patch",
170
0
        p15card->card->type);
171
0
      LOG_FUNC_RETURN(ctx, SC_SUCCESS);
172
0
      break;
173
0
  }
174
175
0
  if (df->type != SC_PKCS15_PRKDF)
176
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
177
178
0
  sc_log(ctx, "parse of SC_PKCS15_PRKDF");
179
180
0
  rv = _iasecc_cpx_fixup_prkdf(p15card);
181
0
  LOG_TEST_RET(ctx, rv, "Cannot fixup PrKDF");
182
183
0
  rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_DATA_OBJECT, dobjs, sizeof(dobjs)/sizeof(dobjs[0]));
184
0
  LOG_TEST_RET(ctx, rv, "Cannot get DATA objects list");
185
186
0
  count = rv;
187
0
  for(ii=0; ii<count; ii++)   {
188
0
    struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
189
0
    int private_obj = dobjs[ii]->flags & SC_PKCS15_CO_FLAG_PRIVATE;
190
191
0
    if (strcmp(dinfo->app_label, IASECC_GEMALTO_MD_APPLICATION_NAME))
192
0
      continue;
193
194
0
    if (!strcmp(dobjs[ii]->label, IASECC_GEMALTO_MD_DEFAULT_CONT_LABEL))   {
195
0
      rv = sc_pkcs15_read_data_object(p15card, (struct sc_pkcs15_data_info *)dobjs[ii]->data, private_obj, &default_guid);
196
0
      LOG_TEST_RET(ctx, rv, "Failed to read 'default container' DATA object data");
197
0
      break;
198
0
    }
199
0
  }
200
201
0
  for(ii=0; ii<count; ii++)   {
202
0
    struct sc_pkcs15_data_info *dinfo = (struct sc_pkcs15_data_info *)dobjs[ii]->data;
203
0
    int default_cont = 0;
204
205
0
    if (strcmp(dinfo->app_label, IASECC_GEMALTO_MD_APPLICATION_NAME))
206
0
      continue;
207
208
0
    if (!strcmp(dobjs[ii]->label, IASECC_GEMALTO_MD_DEFAULT_CONT_LABEL))
209
0
      continue;
210
211
0
    if (default_guid)
212
0
      if (strlen(dobjs[ii]->label) == default_guid->data_len)
213
0
        if (!memcmp(dobjs[ii]->label, default_guid->data, default_guid->data_len))
214
0
          default_cont = 1;
215
216
0
    rv = _iasecc_md_update_keyinfo(p15card, dobjs[ii], default_cont);
217
0
    LOG_TEST_RET(ctx, rv, "Cannot update key MD info");
218
0
  }
219
220
0
  sc_pkcs15_free_data_object(default_guid);
221
222
0
  LOG_FUNC_RETURN(ctx, rv);
223
0
}
224
225
226
static int
227
iasecc_pkcs15emu_detect_card(sc_pkcs15_card_t *p15card)
228
3
{
229
3
  if (p15card->card->type < SC_CARD_TYPE_IASECC_BASE)
230
3
    return SC_ERROR_WRONG_CARD;
231
232
0
  if (p15card->card->type > SC_CARD_TYPE_IASECC_BASE + 10)
233
0
    return SC_ERROR_WRONG_CARD;
234
235
0
  return SC_SUCCESS;
236
0
}
237
238
239
static int
240
sc_pkcs15emu_iasecc_init (struct sc_pkcs15_card *p15card, struct sc_aid *aid)
241
0
{
242
0
  struct sc_context *ctx = p15card->card->ctx;
243
0
  int rv;
244
245
0
  LOG_FUNC_CALLED(ctx);
246
247
0
  rv = sc_pkcs15_bind_internal(p15card, aid);
248
249
0
  p15card->ops.parse_df = _iasecc_parse_df;
250
251
0
  LOG_FUNC_RETURN(ctx, rv);
252
0
}
253
254
255
int
256
sc_pkcs15emu_iasecc_init_ex(struct sc_pkcs15_card *p15card, struct sc_aid *aid)
257
3
{
258
3
  if (iasecc_pkcs15emu_detect_card(p15card))
259
3
    return SC_ERROR_WRONG_CARD;
260
261
0
  return sc_pkcs15emu_iasecc_init(p15card, aid);
262
3
}