Coverage Report

Created: 2025-12-14 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/tests/fuzzing/fuzz_pkcs15init.c
Line
Count
Source
1
/*
2
 * fuzz_pkcs15init.c: Fuzzer for functions processing pkcs15 init
3
 *
4
 * Copyright (C) 2022 Red Hat, Inc.
5
 *
6
 * Author: Veronika Hanulikova <vhanulik@redhat.com>
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
 */
21
22
#ifdef HAVE_CONFIG_H
23
#include "config.h"
24
#endif
25
26
#include "fuzzer_reader.h"
27
#include "pkcs15init/pkcs15-lib.c"
28
#include "scconf/scconf.h"
29
#include "pkcs15init/pkcs15-init.h"
30
#include "pkcs15init/profile.c"
31
#include "pkcs15init/profile.h"
32
33
int fuzz_profile_load(struct sc_profile *profile, const uint8_t *data, size_t size)
34
13.8k
{
35
13.8k
    int rv = 0;
36
13.8k
    scconf_context  *conf = NULL;
37
13.8k
    conf = scconf_new(NULL);
38
13.8k
    if (!conf)
39
0
        return 0;
40
41
13.8k
    if ((rv = scconf_parse_string(conf, (char *)data)) < 0) {
42
0
        scconf_free(conf);
43
0
        return rv;
44
0
    }
45
46
13.8k
    rv = process_conf(profile, conf);
47
13.8k
    scconf_free(conf);
48
13.8k
    return rv;
49
13.8k
}
50
51
void fuzz_pkcs15init_bind(struct sc_card *card, struct sc_profile **result,
52
                          const uint8_t *data, size_t size)
53
15.1k
{
54
15.1k
    struct sc_profile *profile = NULL;
55
15.1k
    const char        *driver;
56
15.1k
    struct sc_pkcs15init_operations * (* func)(void) = NULL;
57
15.1k
    int r = 0;
58
59
15.1k
    if (!card || !card->driver || !result)
60
0
        return;
61
62
15.1k
    *result = NULL;
63
64
15.1k
    r = sc_pkcs15init_set_lifecycle(card, SC_CARDCTRL_LIFECYCLE_ADMIN);
65
15.1k
    if (r < 0 && r != SC_ERROR_NOT_SUPPORTED) {
66
49
        return;
67
49
    }
68
69
15.1k
  profile = sc_profile_new();
70
15.1k
    if (!profile)
71
0
        return;
72
15.1k
    profile->card = card;
73
15.1k
    driver = card->driver->short_name;
74
75
176k
    for (int i = 0; profile_operations[i].name; i++) {
76
176k
    if (!strcasecmp(driver, profile_operations[i].name)) {
77
14.2k
      func = (struct sc_pkcs15init_operations *(*)(void)) profile_operations[i].func;
78
14.2k
      break;
79
14.2k
    }
80
176k
  }
81
15.1k
    if (func) {
82
14.2k
        profile->ops = func();
83
14.2k
    } else {
84
932
        sc_profile_free(profile);
85
932
        return;
86
932
    }
87
14.2k
    profile->name = strdup("Fuzz profile");
88
89
14.2k
    r = sc_pkcs15init_read_info(card, profile);
90
14.2k
    if (r < 0) {
91
338
    sc_profile_free(profile);
92
338
        return;
93
338
  }
94
95
13.8k
    if (fuzz_profile_load(profile, data, size) < 0) {
96
1.75k
        sc_profile_free(profile);
97
1.75k
        return;
98
1.75k
    }
99
100
12.1k
    if (sc_profile_finish(profile, NULL) < 0) {
101
4.00k
        sc_profile_free(profile);
102
4.00k
        return;
103
4.00k
    }
104
8.11k
    *result = profile;
105
8.11k
}
106
107
int fuzz_get_reader_data(const uint8_t *from, size_t from_size, const uint8_t **to, size_t *to_size)
108
18.3k
{
109
18.3k
    size_t i = 0;
110
14.7M
    while(i < from_size - 1 && from[i] != '\0')
111
14.7M
        i++;
112
113
18.3k
    if (from[i] != '\0')
114
20
        return 0;
115
116
18.3k
    *to_size = from_size - (i + 1);
117
18.3k
    *to = from + (i + 1);
118
18.3k
    return 1;
119
18.3k
}
120
121
void do_init_app(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card,
122
                 unsigned char *so_pin, unsigned char *so_puk)
123
8.11k
{
124
8.11k
    struct sc_pkcs15init_initargs init_args;
125
8.11k
    sc_pkcs15_auth_info_t         info;
126
8.11k
    int                           so_puk_disabled = 0;
127
128
8.11k
    memset(&init_args, 0, sizeof(init_args));
129
8.11k
    memset(&info, 0, sizeof(info));
130
8.11k
    sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_SO_PIN, &info);
131
8.11k
    if ((info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED) &&
132
214
        (info.attrs.pin.flags & SC_PKCS15_PIN_FLAG_SO_PIN))
133
210
        so_puk_disabled = 1;
134
135
8.11k
    sc_pkcs15init_get_pin_info(profile, SC_PKCS15INIT_SO_PUK, &info);
136
137
8.11k
    init_args.so_pin = so_pin;
138
8.11k
    init_args.so_pin_len = 8;
139
140
8.11k
    if (!so_puk_disabled) {
141
7.90k
        init_args.so_puk = so_puk;
142
7.90k
        init_args.so_puk_len = 8;
143
7.90k
    }
144
145
8.11k
    sc_pkcs15init_add_app(card, profile, &init_args);
146
8.11k
}
147
148
void do_store_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card,
149
                  unsigned char *pin, unsigned char *so_pin)
150
5.66k
{
151
5.66k
    struct sc_pkcs15init_pinargs pin_args;
152
5.66k
    char   pin_id[SC_PKCS15_MAX_ID_SIZE] = "1\0";
153
5.66k
    sc_pkcs15init_set_p15card(profile, p15card);
154
155
5.66k
    memcpy(pin, "1234555678\0", 11); /* Set new pin */
156
5.66k
    memset(&pin_args, 0, sizeof(pin_args));
157
158
5.66k
    sc_pkcs15_format_id(pin_id, &pin_args.auth_id);
159
5.66k
    pin_args.pin = pin;
160
5.66k
    pin_args.pin_len = 6;
161
5.66k
    pin_args.label = "Basic PIN";
162
163
5.66k
    pin_args.puk = so_pin;
164
5.66k
    pin_args.puk_len = 8;
165
166
5.66k
    sc_pkcs15init_store_pin(p15card, profile, &pin_args);
167
5.66k
}
168
169
void do_store_data_object(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card,
170
                          uint8_t *buf, size_t len)
171
5.66k
{
172
5.66k
    struct sc_pkcs15init_dataargs args;
173
5.66k
    char value[SC_MAX_OBJECT_ID_OCTETS];
174
175
5.66k
    memcpy(value, buf, SC_MAX_OBJECT_ID_OCTETS);
176
5.66k
    value[len < SC_MAX_OBJECT_ID_OCTETS ? len : SC_MAX_OBJECT_ID_OCTETS - 1] = '\0';
177
178
5.66k
    memset(&args, 0, sizeof(args));
179
5.66k
    sc_init_oid(&args.app_oid);
180
5.66k
    args.label = "label";
181
5.66k
    args.app_label = "pkcs15-init";
182
183
5.66k
    sc_format_oid(&args.app_oid, value);
184
185
5.66k
    args.der_encoded.value = buf;
186
5.66k
    args.der_encoded.len = len;
187
5.66k
    sc_pkcs15init_store_data_object(p15card, profile, &args, NULL);
188
5.66k
}
189
190
void do_generate_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card)
191
5.66k
{
192
5.66k
    struct sc_pkcs15init_keygen_args keygen_args;
193
5.66k
    int algorithms[] = { SC_ALGORITHM_RSA, SC_ALGORITHM_EC };
194
5.66k
    unsigned int keybits[] = { 1024, 0 };
195
196
5.66k
    memset(&keygen_args, 0, sizeof(keygen_args));
197
5.66k
    sc_pkcs15_format_id("01", &(keygen_args.prkey_args.auth_id));
198
5.66k
    keygen_args.prkey_args.access_flags |=
199
5.66k
                    SC_PKCS15_PRKEY_ACCESS_SENSITIVE
200
5.66k
                | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
201
5.66k
                | SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
202
5.66k
                | SC_PKCS15_PRKEY_ACCESS_LOCAL;
203
204
16.9k
    for (int i = 0; i < 2; i++) {
205
11.3k
        keygen_args.prkey_args.key.algorithm = algorithms[i];
206
11.3k
        if (algorithms[i] == SC_ALGORITHM_EC) /* strdup called also in parse_alg_spec() */
207
5.66k
            keygen_args.prkey_args.key.u.ec.params.named_curve = strdup("prime256v1");
208
11.3k
        sc_pkcs15init_generate_key(p15card, profile, &keygen_args, keybits[i], NULL);
209
  /* clear the keygen prkey by algorithms which includes the pubkey and ec_params */
210
11.3k
  sc_pkcs15_erase_prkey(&keygen_args.prkey_args.key);
211
11.3k
    }
212
5.66k
}
213
214
void do_generate_skey(struct sc_profile *profile, struct sc_pkcs15_card *p15card, sc_card_t *card)
215
5.66k
{
216
5.66k
    struct sc_pkcs15init_skeyargs skey_args;
217
5.66k
    int algorithms[] = { SC_ALGORITHM_DES, SC_ALGORITHM_3DES, SC_ALGORITHM_AES };
218
5.66k
    unsigned int keybits[] = { 64, 192, 128 };
219
220
    /* init keygen_args*/
221
5.66k
    memset(&skey_args, 0, sizeof(skey_args));
222
5.66k
    skey_args.label = "label";
223
5.66k
    skey_args.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT;
224
5.66k
    skey_args.user_consent = 0;
225
226
22.6k
    for (int i = 0; i < 3; i++) {
227
16.9k
        skey_args.algorithm = algorithms[i];
228
16.9k
        skey_args.value_len = keybits[i];
229
16.9k
        sc_pkcs15init_generate_secret_key(p15card, profile, &skey_args, NULL);
230
16.9k
    }
231
5.66k
}
232
233
void do_store_secret_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
234
                         sc_card_t *card, uint8_t *buf)
235
5.66k
{
236
5.66k
    struct sc_pkcs15init_skeyargs args;
237
5.66k
    int algorithms[] = { SC_ALGORITHM_AES, SC_ALGORITHM_DES, SC_ALGORITHM_3DES };
238
5.66k
    unsigned int keybits[] = { 128, 64, 192 };
239
240
5.66k
    memset(&args, 0, sizeof(args));
241
5.66k
    args.access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE | SC_PKCS15_PRKEY_ACCESS_SENSITIVE;
242
5.66k
    args.usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT;
243
5.66k
    sc_pkcs15_format_id("02", &(args.auth_id));
244
245
22.6k
    for (int i = 0; i < 3; i++) {
246
16.9k
  size_t keybytes = BYTES4BITS(keybits[i]);
247
16.9k
  args.key.data = malloc(keybytes);
248
16.9k
  memcpy(args.key.data, buf, keybytes);
249
16.9k
  args.key.data_len = keybytes;
250
16.9k
  args.algorithm = algorithms[i];
251
16.9k
  args.value_len = keybits[i];
252
253
16.9k
  sc_pkcs15init_store_secret_key(p15card, profile, &args, NULL);
254
16.9k
  if (args.key.data)
255
16.9k
    free(args.key.data);
256
16.9k
    }
257
5.66k
}
258
259
void do_erase(struct sc_profile *profile, sc_card_t *card)
260
5.66k
{
261
5.66k
    struct sc_pkcs15_card *p15card;
262
263
5.66k
    p15card = sc_pkcs15_card_new();
264
5.66k
    p15card->card = card;
265
266
5.66k
    sc_pkcs15init_erase_card(p15card, profile, NULL);
267
5.66k
    sc_pkcs15_card_free(p15card);
268
5.66k
}
269
270
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
271
18.3k
{
272
18.3k
    sc_context_t          *ctx = NULL;
273
18.3k
    sc_card_t             *card = NULL;
274
18.3k
    struct sc_pkcs15_card *p15card = NULL;
275
18.3k
    struct sc_profile     *profile = NULL;
276
18.3k
    struct sc_reader      *reader = NULL;
277
18.3k
    const uint8_t         *reader_data = NULL;
278
18.3k
    size_t                 reader_data_size = 0;
279
18.3k
    uint8_t               *buf = NULL;
280
18.3k
    uint16_t               len = size < 256 ? size : 256;
281
18.3k
    unsigned char         *pin = NULL;
282
18.3k
    unsigned char         *so_pin = NULL;
283
18.3k
    unsigned char         *puk = NULL;
284
18.3k
    unsigned char         *so_puk = NULL;
285
18.3k
    struct sc_pkcs15_card *tmp_p15_data = NULL;
286
287
18.3k
#ifdef FUZZING_ENABLED
288
18.3k
    fclose(stdout);
289
18.3k
#endif
290
291
18.3k
    if (size == 0)
292
0
        return 0;
293
294
18.3k
    if (!fuzz_get_reader_data(data, size, &reader_data, &reader_data_size)) {
295
20
        return 0;
296
20
    }
297
298
    /* Establish context for fuzz app*/
299
18.3k
    sc_establish_context(&ctx, "fuzz");
300
18.3k
    if (!ctx)
301
0
        return 0;
302
303
18.3k
    if (fuzz_connect_card(ctx, &card, &reader, reader_data, reader_data_size) != SC_SUCCESS)
304
3.15k
        goto end;
305
306
    /* Load profile and bind with card */
307
15.1k
    fuzz_pkcs15init_bind(card, &profile, data, size - reader_data_size);
308
309
15.1k
    if(!profile)
310
7.07k
        goto end;
311
312
8.11k
    pin = malloc(11);
313
8.11k
    so_pin = malloc(9);
314
8.11k
    puk = malloc(9);
315
8.11k
    so_puk = malloc(9);
316
8.11k
    buf = malloc(len * sizeof(char));
317
8.11k
    if (!pin || !so_pin || !puk || !so_puk || !buf)
318
0
        goto end_release;
319
320
8.11k
    memcpy(pin, "123456\0", 7);
321
8.11k
    memcpy(so_pin, "12345678\0", 9);
322
8.11k
    memcpy(puk, "12345678\0", 9);
323
8.11k
    memcpy(so_puk, "12345678\0", 9);
324
8.11k
    memcpy(buf, data, len);
325
326
    /* test pkcs15-init functionality*/
327
8.11k
    do_init_app(profile, p15card, card, so_pin, so_puk);
328
329
8.11k
    if (!sc_pkcs15_bind(card, NULL, &p15card)) { /* First and only sc_pkcs15_bind calling, is omitted in next cases*/
330
5.66k
        do_store_pin(profile, p15card, card, pin, so_pin);
331
5.66k
    }
332
333
    /* sc_pkcs15_bind failed, no point in testing next cases */
334
8.11k
    if (!p15card)
335
2.45k
        goto end_release;
336
337
5.66k
    do_store_data_object(profile, p15card, card, buf, len);
338
5.66k
    do_generate_key(profile, p15card, card);
339
5.66k
    do_generate_skey(profile, p15card, card);
340
5.66k
    do_store_secret_key(profile, p15card, card, buf);
341
342
5.66k
    sc_pkcs15init_finalize_card(card, profile);
343
5.66k
    sc_pkcs15init_sanity_check(p15card, profile);
344
345
5.66k
    do_erase(profile, card);
346
347
8.11k
end_release:
348
8.11k
    free(pin);
349
8.11k
    free(puk);
350
8.11k
    free(so_pin);
351
8.11k
    free(so_puk);
352
8.11k
    free(buf);
353
354
18.3k
end:
355
18.3k
  if (profile) {
356
8.11k
    tmp_p15_data = profile->p15_data;
357
8.11k
    sc_pkcs15init_unbind(profile);
358
8.11k
    if (tmp_p15_data != p15card)
359
1.19k
      sc_pkcs15_unbind(tmp_p15_data);
360
8.11k
  }
361
18.3k
  if (p15card) {
362
5.66k
    sc_pkcs15_unbind(p15card);
363
5.66k
  }
364
18.3k
    if (card)
365
15.1k
      sc_disconnect_card(card);
366
18.3k
    sc_release_context(ctx);
367
368
18.3k
    return 0;
369
8.11k
}