Coverage Report

Created: 2025-08-26 06:43

/src/opensc/src/tests/fuzzing/fuzz_piv_tool.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * fuzz_piv_tool.c: Fuzz target for piv-tool
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 "libopensc/internal.h"
27
#include <stdlib.h>
28
#include <string.h>
29
#include <stdbool.h>
30
#include "fuzzer_reader.h"
31
#include "fuzzer_tool.h"
32
#undef stderr
33
7.54k
#define stderr stdout
34
35
/* Rename main for calling in fuzz target */
36
#define main _main
37
/* Connect to virtual reader instead of real card*/
38
3.19k
#define util_connect_card(ctx, card, id, do_wait) fuzz_util_connect_card(ctx, card)
39
# include "tools/piv-tool.c"
40
#undef main
41
42
static const uint8_t *reader_data = NULL;
43
static size_t reader_data_size = 0;
44
45
/* Use instead of util_connect_card() */
46
int fuzz_util_connect_card(struct sc_context *ctx, struct sc_card **card)
47
18.0k
{
48
18.0k
  return fuzz_connect_card(ctx, card, NULL, reader_data, reader_data_size);
49
18.0k
}
50
51
void initilize_global()
52
3.31k
{
53
  /* Global variables need to be reser between runs,
54
     fuzz target is called repetitively in one execution */
55
3.31k
  reader_data = NULL;
56
3.31k
  reader_data_size = 0;
57
3.31k
  ctx = NULL;
58
3.31k
  card = NULL;
59
3.31k
  bp = NULL;
60
3.31k
  opt_reader = NULL;
61
3.31k
  opt_apdus = NULL;
62
3.31k
  opt_apdu_count = 0;
63
64
3.31k
  optind = 0;
65
3.31k
  opterr = 0; /* do not print out error messages */
66
3.31k
  optopt = 0;
67
3.31k
}
68
69
void test_load(char *op, const uint8_t *data, size_t size)
70
14
{
71
14
  char *filename = NULL;
72
14
  char *argv[] = {"./fuzz_piv", op, NULL /*ref*/, "-i", NULL /*filename*/, "-A", NULL /*admin*/, NULL};
73
14
  int argc = 7;
74
14
  char *opt_ref = NULL, *opt_admin = NULL;
75
76
14
  if (!(opt_ref = extract_word(&data, &size)))
77
5
    return;
78
9
  argv[2] = opt_ref;
79
80
9
  if (!(opt_admin = extract_word(&data, &size))) {
81
3
    free(opt_ref);
82
3
    return;
83
3
  }
84
6
  argv[6] = opt_admin;
85
86
6
  if (create_input_file(&filename, &data, &size) != 0) {
87
3
    free(opt_ref);
88
3
    free(opt_admin);
89
3
    remove_file(filename);
90
3
    return;
91
3
  }
92
3
  argv[4] = filename;
93
94
3
  reader_data = data;
95
3
  reader_data_size = size;
96
3
  _main(argc, argv);
97
98
3
  free(opt_ref);
99
3
  free(opt_admin);
100
3
  remove_file(filename);
101
3
}
102
103
/* Skip argv with option for output file */
104
int present_outfile(int argc, char *argv[])
105
3.26k
{
106
3.26k
  const struct option _options[] = {
107
3.26k
    { "out",1, NULL,'o' },
108
3.26k
    { NULL, 0, NULL, 0 }
109
3.26k
  };
110
3.26k
  int c;
111
2.00M
  while ((c = getopt_long(argc, argv, "o:", _options, (int *) 0)) != -1) {
112
2.00M
    switch (c) {
113
2
      case 'o':
114
2
        return 1;
115
2.00M
      default:
116
2.00M
        continue;
117
2.00M
    }
118
2.00M
  }
119
3.26k
  optind = 0;
120
3.26k
  optopt = 0;
121
3.26k
  return 0;
122
3.26k
}
123
124
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
125
3.32k
{
126
3.32k
  uint8_t operation = 0;
127
3.32k
  char *filename = NULL;
128
3.32k
  char **argv = NULL;
129
3.32k
  int argc = 0;
130
3.32k
  char auth_path[50] = {0};
131
132
3.32k
#ifdef FUZZING_ENABLED
133
3.32k
  fclose(stdout);
134
3.32k
#endif
135
3.32k
  if (size < 10)
136
6
    return 0;
137
138
3.31k
  initilize_global();
139
3.31k
  operation = data[0];
140
3.31k
  data++;
141
3.31k
  size--;
142
143
  /* extract admin argument and set file with admin key */
144
3.31k
  if (create_input_file(&filename, &data, &size) != 0 || size < 3)
145
33
    goto err;
146
3.28k
  sprintf(auth_path, "PIV_EXT_AUTH_KEY=%s", filename);
147
3.28k
  putenv(auth_path);
148
149
3.28k
  switch (operation) {
150
8
    case 0:
151
8
      test_load("-O", data, size);
152
8
      break;
153
3
    case 1:
154
3
      test_load("-C", data, size);
155
3
      break;
156
3
    case 2:
157
3
      test_load("-Z", data, size);
158
3
      break;
159
3.26k
    default:
160
3.26k
      if (get_fuzzed_argv("./fuzz_piv", data, size, &argv, &argc, &reader_data, &reader_data_size) != 0)
161
6
        goto err;
162
3.26k
      if (present_outfile(argc, argv)) {
163
2
        free_arguments(argc, argv);
164
2
        goto err;
165
2
      }
166
3.26k
      _main(argc, argv);
167
3.26k
      free_arguments(argc, argv);
168
3.28k
  }
169
3.31k
err:
170
3.31k
  reader_data = NULL;
171
3.31k
  reader_data_size = 0;
172
3.31k
  remove_file(filename);
173
3.31k
  return 0;
174
3.28k
}