Coverage Report

Created: 2026-04-09 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/fuzz/provider.c
Line
Count
Source
1
/*
2
 * Copyright 2023-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 * https://www.openssl.org/source/license.html
8
 * or in the file LICENSE in the source distribution.
9
 */
10
#include <string.h>
11
#include <openssl/types.h>
12
#include <openssl/crypto.h>
13
#include <openssl/core_names.h>
14
#include <openssl/kdf.h>
15
#include <openssl/evp.h>
16
#include <openssl/provider.h>
17
#include "fuzzer.h"
18
19
#define DEFINE_ALGORITHMS(name, evp)                                     \
20
    DEFINE_STACK_OF(evp)                                                 \
21
    static int cmp_##evp(const evp *const *a, const evp *const *b);      \
22
    static void collect_##evp(evp *obj, void *stack);                    \
23
    static void init_##name(OSSL_LIB_CTX *libctx);                       \
24
    static void cleanup_##name(void);                                    \
25
    static STACK_OF(evp) *name##_collection;                             \
26
    static int cmp_##evp(const evp *const *a, const evp *const *b)       \
27
616
    {                                                                    \
28
616
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
616
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
616
    }                                                                    \
provider.c:cmp_EVP_MD
Line
Count
Source
27
58
    {                                                                    \
28
58
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
58
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
58
    }                                                                    \
provider.c:cmp_EVP_KDF
Line
Count
Source
27
42
    {                                                                    \
28
42
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
42
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
42
    }                                                                    \
provider.c:cmp_EVP_CIPHER
Line
Count
Source
27
258
    {                                                                    \
28
258
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
258
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
258
    }                                                                    \
provider.c:cmp_EVP_KEM
Line
Count
Source
27
22
    {                                                                    \
28
22
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
22
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
22
    }                                                                    \
provider.c:cmp_EVP_KEYEXCH
Line
Count
Source
27
12
    {                                                                    \
28
12
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
12
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
12
    }                                                                    \
provider.c:cmp_EVP_RAND
Line
Count
Source
27
8
    {                                                                    \
28
8
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
8
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
8
    }                                                                    \
provider.c:cmp_EVP_MAC
Line
Count
Source
27
16
    {                                                                    \
28
16
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
16
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
16
    }                                                                    \
provider.c:cmp_EVP_KEYMGMT
Line
Count
Source
27
82
    {                                                                    \
28
82
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
82
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
82
    }                                                                    \
provider.c:cmp_EVP_SIGNATURE
Line
Count
Source
27
116
    {                                                                    \
28
116
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
116
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
116
    }                                                                    \
provider.c:cmp_EVP_ASYM_CIPHER
Line
Count
Source
27
2
    {                                                                    \
28
2
        return strcmp(OSSL_PROVIDER_get0_name(evp##_get0_provider(*a)),  \
29
2
            OSSL_PROVIDER_get0_name(evp##_get0_provider(*b)));           \
30
2
    }                                                                    \
31
    static void collect_##evp(evp *obj, void *stack)                     \
32
2.39k
    {                                                                    \
33
2.39k
        STACK_OF(evp) *obj_stack = stack;                                \
34
2.39k
                                                                         \
35
2.39k
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
2.39k
            evp##_up_ref(obj);                                           \
37
2.39k
    }                                                                    \
provider.c:collect_EVP_MD
Line
Count
Source
32
222
    {                                                                    \
33
222
        STACK_OF(evp) *obj_stack = stack;                                \
34
222
                                                                         \
35
222
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
222
            evp##_up_ref(obj);                                           \
37
222
    }                                                                    \
provider.c:collect_EVP_KDF
Line
Count
Source
32
146
    {                                                                    \
33
146
        STACK_OF(evp) *obj_stack = stack;                                \
34
146
                                                                         \
35
146
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
146
            evp##_up_ref(obj);                                           \
37
146
    }                                                                    \
provider.c:collect_EVP_CIPHER
Line
Count
Source
32
1.04k
    {                                                                    \
33
1.04k
        STACK_OF(evp) *obj_stack = stack;                                \
34
1.04k
                                                                         \
35
1.04k
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
1.04k
            evp##_up_ref(obj);                                           \
37
1.04k
    }                                                                    \
provider.c:collect_EVP_KEM
Line
Count
Source
32
76
    {                                                                    \
33
76
        STACK_OF(evp) *obj_stack = stack;                                \
34
76
                                                                         \
35
76
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
76
            evp##_up_ref(obj);                                           \
37
76
    }                                                                    \
provider.c:collect_EVP_KEYEXCH
Line
Count
Source
32
56
    {                                                                    \
33
56
        STACK_OF(evp) *obj_stack = stack;                                \
34
56
                                                                         \
35
56
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
56
            evp##_up_ref(obj);                                           \
37
56
    }                                                                    \
provider.c:collect_EVP_RAND
Line
Count
Source
32
40
    {                                                                    \
33
40
        STACK_OF(evp) *obj_stack = stack;                                \
34
40
                                                                         \
35
40
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
40
            evp##_up_ref(obj);                                           \
37
40
    }                                                                    \
provider.c:collect_EVP_MAC
Line
Count
Source
32
72
    {                                                                    \
33
72
        STACK_OF(evp) *obj_stack = stack;                                \
34
72
                                                                         \
35
72
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
72
            evp##_up_ref(obj);                                           \
37
72
    }                                                                    \
provider.c:collect_EVP_KEYMGMT
Line
Count
Source
32
280
    {                                                                    \
33
280
        STACK_OF(evp) *obj_stack = stack;                                \
34
280
                                                                         \
35
280
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
280
            evp##_up_ref(obj);                                           \
37
280
    }                                                                    \
provider.c:collect_EVP_SIGNATURE
Line
Count
Source
32
442
    {                                                                    \
33
442
        STACK_OF(evp) *obj_stack = stack;                                \
34
442
                                                                         \
35
442
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
442
            evp##_up_ref(obj);                                           \
37
442
    }                                                                    \
provider.c:collect_EVP_ASYM_CIPHER
Line
Count
Source
32
16
    {                                                                    \
33
16
        STACK_OF(evp) *obj_stack = stack;                                \
34
16
                                                                         \
35
16
        if (sk_##evp##_push(obj_stack, obj) > 0)                         \
36
16
            evp##_up_ref(obj);                                           \
37
16
    }                                                                    \
38
    static void init_##name(OSSL_LIB_CTX *libctx)                        \
39
80
    {                                                                    \
40
80
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
80
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
80
    }                                                                    \
provider.c:init_digests
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_kdf
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_cipher
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_kem
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_keyexch
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_rand
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_mac
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_keymgmt
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_signature
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
provider.c:init_asym_ciphers
Line
Count
Source
39
8
    {                                                                    \
40
8
        name##_collection = sk_##evp##_new(cmp_##evp);                   \
41
8
        evp##_do_all_provided(libctx, collect_##evp, name##_collection); \
42
8
    }                                                                    \
43
    static void cleanup_##name(void)                                     \
44
0
    {                                                                    \
45
0
        sk_##evp##_pop_free(name##_collection, evp##_free);              \
46
0
    }
Unexecuted instantiation: provider.c:cleanup_digests
Unexecuted instantiation: provider.c:cleanup_kdf
Unexecuted instantiation: provider.c:cleanup_cipher
Unexecuted instantiation: provider.c:cleanup_kem
Unexecuted instantiation: provider.c:cleanup_keyexch
Unexecuted instantiation: provider.c:cleanup_rand
Unexecuted instantiation: provider.c:cleanup_mac
Unexecuted instantiation: provider.c:cleanup_keymgmt
Unexecuted instantiation: provider.c:cleanup_signature
Unexecuted instantiation: provider.c:cleanup_asym_ciphers
47
48
DEFINE_ALGORITHMS(digests, EVP_MD)
49
50
DEFINE_ALGORITHMS(kdf, EVP_KDF)
51
52
DEFINE_ALGORITHMS(cipher, EVP_CIPHER)
53
54
DEFINE_ALGORITHMS(kem, EVP_KEM)
55
56
DEFINE_ALGORITHMS(keyexch, EVP_KEYEXCH)
57
58
DEFINE_ALGORITHMS(rand, EVP_RAND)
59
60
DEFINE_ALGORITHMS(mac, EVP_MAC)
61
62
DEFINE_ALGORITHMS(keymgmt, EVP_KEYMGMT)
63
64
DEFINE_ALGORITHMS(signature, EVP_SIGNATURE)
65
66
DEFINE_ALGORITHMS(asym_ciphers, EVP_ASYM_CIPHER)
67
68
static OSSL_LIB_CTX *libctx = NULL;
69
70
int FuzzerInitialize(int *argc, char ***argv)
71
20
{
72
20
    libctx = OSSL_LIB_CTX_new();
73
20
    if (libctx == NULL)
74
0
        return 0;
75
76
20
    init_digests(libctx);
77
20
    init_kdf(libctx);
78
20
    init_cipher(libctx);
79
20
    init_kem(libctx);
80
20
    init_keyexch(libctx);
81
20
    init_rand(libctx);
82
20
    init_mac(libctx);
83
20
    init_keymgmt(libctx);
84
20
    init_signature(libctx);
85
20
    init_asym_ciphers(libctx);
86
20
    return 1;
87
20
}
88
89
void FuzzerCleanup(void)
90
0
{
91
0
    cleanup_digests();
92
0
    cleanup_kdf();
93
0
    cleanup_cipher();
94
0
    cleanup_kem();
95
0
    cleanup_keyexch();
96
0
    cleanup_rand();
97
0
    cleanup_mac();
98
0
    cleanup_keymgmt();
99
0
    cleanup_signature();
100
0
    cleanup_asym_ciphers();
101
102
0
    OSSL_LIB_CTX_free(libctx);
103
0
}
104
105
static int read_uint(const uint8_t **buf, size_t *len, uint64_t **res)
106
3.72k
{
107
3.72k
    int r = 1;
108
109
3.72k
    if (*len < sizeof(uint64_t)) {
110
76
        r = 0;
111
76
        goto end;
112
76
    }
113
114
3.64k
    *res = OPENSSL_malloc(sizeof(uint64_t));
115
3.64k
    if (*res == NULL) {
116
0
        r = 0;
117
0
        goto end;
118
0
    }
119
3.64k
    **res = (uint64_t)**buf;
120
121
3.64k
    *buf += sizeof(uint64_t);
122
3.64k
    *len -= sizeof(uint64_t);
123
3.72k
end:
124
3.72k
    return r;
125
3.64k
}
126
127
static int read_int(const uint8_t **buf, size_t *len, int64_t **res)
128
15.8k
{
129
15.8k
    int r = 1;
130
131
15.8k
    if (*len < sizeof(int64_t)) {
132
3.83k
        r = 0;
133
3.83k
        goto end;
134
3.83k
    }
135
136
12.0k
    *res = OPENSSL_malloc(sizeof(int64_t));
137
12.0k
    if (*res == NULL) {
138
0
        r = 0;
139
0
        goto end;
140
0
    }
141
12.0k
    **res = (int64_t)**buf;
142
143
12.0k
    *buf += sizeof(int64_t);
144
12.0k
    *len -= sizeof(int64_t);
145
15.8k
end:
146
15.8k
    return r;
147
12.0k
}
148
149
static int read_double(const uint8_t **buf, size_t *len, double **res)
150
0
{
151
0
    int r = 1;
152
153
0
    if (*len < sizeof(double)) {
154
0
        r = 0;
155
0
        goto end;
156
0
    }
157
158
0
    *res = OPENSSL_malloc(sizeof(double));
159
0
    if (*res == NULL) {
160
0
        r = 0;
161
0
        goto end;
162
0
    }
163
0
    **res = (double)**buf;
164
165
0
    *buf += sizeof(double);
166
0
    *len -= sizeof(double);
167
0
end:
168
0
    return r;
169
0
}
170
171
static int read_utf8_string(const uint8_t **buf, size_t *len, char **res)
172
14.5k
{
173
14.5k
    size_t found_len;
174
14.5k
    int r;
175
176
14.5k
    found_len = OPENSSL_strnlen((const char *)*buf, *len);
177
178
14.5k
    if (found_len == *len) {
179
1.01k
        r = -1;
180
1.01k
        goto end;
181
1.01k
    }
182
183
13.5k
    found_len++; /* skip over the \0 byte */
184
185
13.5k
    r = (int)found_len;
186
187
13.5k
    *res = (char *)*buf;
188
13.5k
    *len -= found_len;
189
13.5k
    *buf = *buf + found_len; /* continue after the \0 byte */
190
14.5k
end:
191
14.5k
    return r;
192
13.5k
}
193
194
static int read_utf8_ptr(const uint8_t **buf, size_t *len, char **res)
195
0
{
196
0
    if (*len > 0 && **buf == 0xFF) {
197
        /* represent NULL somehow */
198
0
        *res = NULL;
199
0
        *buf += 1;
200
0
        *len -= 1;
201
0
        return 0;
202
0
    }
203
0
    return read_utf8_string(buf, len, res);
204
0
}
205
206
static int read_octet_string(const uint8_t **buf, size_t *len, char **res)
207
14.0k
{
208
14.0k
    int r;
209
14.0k
    size_t i;
210
14.0k
    const uint8_t *ptr = *buf;
211
14.0k
    int found = 0;
212
213
185M
    for (i = 0; i < *len; ++i) {
214
185M
        if (*ptr == 0xFF && (i + 1 < *len && *(ptr + 1) == 0xFF)) {
215
10.4k
            ptr++;
216
10.4k
            found = 1;
217
10.4k
            break;
218
10.4k
        }
219
185M
        ptr++;
220
185M
    }
221
222
14.0k
    if (!found) {
223
3.63k
        r = -1;
224
3.63k
        goto end;
225
3.63k
    }
226
227
10.4k
    *res = (char *)*buf;
228
229
10.4k
    r = (int)(ptr - *buf);
230
10.4k
    *len -= r;
231
10.4k
    *buf = ptr;
232
233
14.0k
end:
234
14.0k
    return r;
235
10.4k
}
236
237
static int read_octet_ptr(const uint8_t **buf, size_t *len, char **res)
238
0
{
239
    /* TODO: This representation could need an improvement potentially. */
240
0
    if (*len > 1 && **buf == 0xFF && *(*buf + 1) == 0xFF) {
241
        /* represent NULL somehow */
242
0
        *res = NULL;
243
0
        *buf += 2;
244
0
        *len -= 2;
245
0
        return 0;
246
0
    }
247
0
    return read_octet_string(buf, len, res);
248
0
}
249
250
static char *DFLT_STR = "";
251
static char *DFLT_UTF8_PTR = NULL;
252
static char *DFLT_OCTET_STRING = "";
253
static char *DFLT_OCTET_PTR = NULL;
254
255
static int64_t ITERS = 1;
256
static uint64_t UITERS = 1;
257
static int64_t BLOCKSIZE = 8;
258
static uint64_t UBLOCKSIZE = 8;
259
260
static void free_params(OSSL_PARAM *param)
261
10.2k
{
262
67.2k
    for (; param != NULL && param->key != NULL; param++) {
263
57.0k
        switch (param->data_type) {
264
4.01k
        case OSSL_PARAM_INTEGER:
265
16.4k
        case OSSL_PARAM_UNSIGNED_INTEGER:
266
16.4k
        case OSSL_PARAM_REAL:
267
16.4k
            if (param->data != NULL) {
268
16.4k
                OPENSSL_free(param->data);
269
16.4k
            }
270
16.4k
            break;
271
57.0k
        }
272
57.0k
    }
273
10.2k
}
274
275
static OSSL_PARAM *fuzz_params(OSSL_PARAM *param, const uint8_t **buf, size_t *len)
276
2.45k
{
277
2.45k
    OSSL_PARAM *p;
278
2.45k
    OSSL_PARAM *fuzzed_parameters;
279
2.45k
    int p_num = 0;
280
281
15.5k
    for (p = param; p != NULL && p->key != NULL; p++)
282
13.0k
        p_num++;
283
284
2.45k
    fuzzed_parameters = OPENSSL_calloc(p_num + 1, sizeof(OSSL_PARAM));
285
2.45k
    if (fuzzed_parameters == NULL)
286
0
        return NULL;
287
2.45k
    p = fuzzed_parameters;
288
289
15.5k
    for (; param != NULL && param->key != NULL; param++) {
290
13.0k
        int64_t *use_param = NULL;
291
13.0k
        int64_t *p_value_int = NULL;
292
13.0k
        uint64_t *p_value_uint = NULL;
293
13.0k
        double *p_value_double = NULL;
294
13.0k
        char *p_value_utf8_str = DFLT_STR;
295
13.0k
        char *p_value_octet_str = DFLT_OCTET_STRING;
296
13.0k
        char *p_value_utf8_ptr = DFLT_UTF8_PTR;
297
13.0k
        char *p_value_octet_ptr = DFLT_OCTET_PTR;
298
299
13.0k
        int data_len = 0;
300
301
13.0k
        if (!read_int(buf, len, &use_param)) {
302
3.81k
            use_param = OPENSSL_malloc(sizeof(uint64_t));
303
3.81k
            if (use_param == NULL) {
304
0
                OPENSSL_free(fuzzed_parameters);
305
0
                return NULL;
306
0
            }
307
3.81k
            *use_param = 0;
308
3.81k
        }
309
310
13.0k
        switch (param->data_type) {
311
845
        case OSSL_PARAM_INTEGER:
312
845
            if (strcmp(param->key, OSSL_KDF_PARAM_ITER) == 0) {
313
0
                p_value_int = OPENSSL_malloc(sizeof(ITERS));
314
0
                if (p_value_int == NULL) {
315
0
                    OPENSSL_free(fuzzed_parameters);
316
0
                    OPENSSL_free(use_param);
317
0
                    return NULL;
318
0
                }
319
0
                *p_value_int = ITERS;
320
845
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_N) == 0) {
321
0
                p_value_int = OPENSSL_malloc(sizeof(ITERS));
322
0
                if (p_value_int == NULL) {
323
0
                    OPENSSL_free(fuzzed_parameters);
324
0
                    OPENSSL_free(use_param);
325
0
                    return NULL;
326
0
                }
327
0
                *p_value_int = ITERS;
328
845
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_R) == 0) {
329
102
                p_value_int = OPENSSL_malloc(sizeof(BLOCKSIZE));
330
102
                if (p_value_int == NULL) {
331
0
                    OPENSSL_free(fuzzed_parameters);
332
0
                    OPENSSL_free(use_param);
333
0
                    return NULL;
334
0
                }
335
102
                *p_value_int = BLOCKSIZE;
336
743
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_P) == 0) {
337
0
                p_value_int = OPENSSL_malloc(sizeof(BLOCKSIZE));
338
0
                if (p_value_int == NULL) {
339
0
                    OPENSSL_free(fuzzed_parameters);
340
0
                    OPENSSL_free(use_param);
341
0
                    return NULL;
342
0
                }
343
0
                *p_value_int = BLOCKSIZE;
344
743
            } else if (!*use_param || !read_int(buf, len, &p_value_int)) {
345
432
                p_value_int = OPENSSL_malloc(sizeof(int64_t));
346
432
                if (p_value_int == NULL) {
347
0
                    OPENSSL_free(fuzzed_parameters);
348
0
                    OPENSSL_free(use_param);
349
0
                    return NULL;
350
0
                }
351
432
                *p_value_int = 0;
352
432
            }
353
354
845
            *p = *param;
355
845
            p->data = p_value_int;
356
845
            p++;
357
845
            break;
358
3.42k
        case OSSL_PARAM_UNSIGNED_INTEGER:
359
3.42k
            if (strcmp(param->key, OSSL_KDF_PARAM_ITER) == 0) {
360
356
                p_value_uint = OPENSSL_malloc(sizeof(UITERS));
361
356
                if (p_value_uint == NULL) {
362
0
                    OPENSSL_free(fuzzed_parameters);
363
0
                    OPENSSL_free(use_param);
364
0
                    return NULL;
365
0
                }
366
356
                *p_value_uint = UITERS;
367
3.06k
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_N) == 0) {
368
17
                p_value_uint = OPENSSL_malloc(sizeof(UITERS));
369
17
                if (p_value_uint == NULL) {
370
0
                    OPENSSL_free(fuzzed_parameters);
371
0
                    OPENSSL_free(use_param);
372
0
                    return NULL;
373
0
                }
374
17
                *p_value_uint = UITERS;
375
3.05k
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_R) == 0) {
376
17
                p_value_uint = OPENSSL_malloc(sizeof(UBLOCKSIZE));
377
17
                if (p_value_uint == NULL) {
378
0
                    OPENSSL_free(fuzzed_parameters);
379
0
                    OPENSSL_free(use_param);
380
0
                    return NULL;
381
0
                }
382
17
                *p_value_uint = UBLOCKSIZE;
383
3.03k
            } else if (strcmp(param->key, OSSL_KDF_PARAM_SCRYPT_P) == 0) {
384
17
                p_value_uint = OPENSSL_malloc(sizeof(UBLOCKSIZE));
385
17
                if (p_value_uint == NULL) {
386
0
                    OPENSSL_free(fuzzed_parameters);
387
0
                    OPENSSL_free(use_param);
388
0
                    return NULL;
389
0
                }
390
17
                *p_value_uint = UBLOCKSIZE;
391
3.01k
            } else if (!*use_param || !read_uint(buf, len, &p_value_uint)) {
392
1.83k
                p_value_uint = OPENSSL_malloc(sizeof(uint64_t));
393
1.83k
                if (p_value_uint == NULL) {
394
0
                    OPENSSL_free(fuzzed_parameters);
395
0
                    OPENSSL_free(use_param);
396
0
                    return NULL;
397
0
                }
398
1.83k
                *p_value_uint = 0;
399
1.83k
            }
400
401
3.42k
            *p = *param;
402
3.42k
            p->data = p_value_uint;
403
3.42k
            p++;
404
3.42k
            break;
405
0
        case OSSL_PARAM_REAL:
406
0
            if (!*use_param || !read_double(buf, len, &p_value_double)) {
407
0
                p_value_double = OPENSSL_malloc(sizeof(double));
408
0
                if (p_value_double == NULL) {
409
0
                    OPENSSL_free(fuzzed_parameters);
410
0
                    OPENSSL_free(use_param);
411
0
                    return NULL;
412
0
                }
413
0
                *p_value_double = 0;
414
0
            }
415
416
0
            *p = *param;
417
0
            p->data = p_value_double;
418
0
            p++;
419
0
            break;
420
4.29k
        case OSSL_PARAM_UTF8_STRING:
421
4.29k
            if (*use_param && (data_len = read_utf8_string(buf, len, &p_value_utf8_str)) < 0)
422
222
                data_len = 0;
423
4.29k
            *p = *param;
424
4.29k
            p->data = p_value_utf8_str;
425
4.29k
            p->data_size = data_len;
426
4.29k
            p++;
427
4.29k
            break;
428
4.52k
        case OSSL_PARAM_OCTET_STRING:
429
4.52k
            if (*use_param && (data_len = read_octet_string(buf, len, &p_value_octet_str)) < 0)
430
650
                data_len = 0;
431
4.52k
            *p = *param;
432
4.52k
            p->data = p_value_octet_str;
433
4.52k
            p->data_size = data_len;
434
4.52k
            p++;
435
4.52k
            break;
436
0
        case OSSL_PARAM_UTF8_PTR:
437
0
            if (*use_param && (data_len = read_utf8_ptr(buf, len, &p_value_utf8_ptr)) < 0)
438
0
                data_len = 0;
439
0
            *p = *param;
440
0
            p->data = p_value_utf8_ptr;
441
0
            p->data_size = data_len;
442
0
            p++;
443
0
            break;
444
0
        case OSSL_PARAM_OCTET_PTR:
445
0
            if (*use_param && (data_len = read_octet_ptr(buf, len, &p_value_octet_ptr)) < 0)
446
0
                data_len = 0;
447
0
            *p = *param;
448
0
            p->data = p_value_octet_ptr;
449
0
            p->data_size = data_len;
450
0
            p++;
451
0
            break;
452
0
        default:
453
0
            break;
454
13.0k
        }
455
456
13.0k
        OPENSSL_free(use_param);
457
13.0k
    }
458
459
2.45k
    return fuzzed_parameters;
460
2.45k
}
461
462
static int do_evp_cipher(const EVP_CIPHER *evp_cipher, const OSSL_PARAM param[])
463
265
{
464
265
    unsigned char outbuf[1024];
465
265
    int outlen, tmplen;
466
265
    int key_len = EVP_CIPHER_get_key_length(evp_cipher);
467
265
    int iv_len = EVP_CIPHER_get_iv_length(evp_cipher);
468
265
    unsigned char *key = NULL, *iv = NULL;
469
265
    const char intext[] = "text";
470
265
    EVP_CIPHER_CTX *ctx = NULL;
471
265
    int i;
472
473
265
    if (key_len <= 0)
474
1
        key_len = 16;
475
265
    if (iv_len <= 0)
476
29
        iv_len = 16;
477
478
265
    key = OPENSSL_zalloc(key_len);
479
265
    iv = OPENSSL_zalloc(iv_len);
480
265
    if (key == NULL || iv == NULL)
481
0
        goto err;
482
7.08k
    for (i = 0; i < key_len; i++)
483
6.82k
        key[i] = (unsigned char)i;
484
3.90k
    for (i = 0; i < iv_len; i++)
485
3.64k
        iv[i] = (unsigned char)(i + 1);
486
487
265
    ctx = EVP_CIPHER_CTX_new();
488
265
    if (ctx == NULL)
489
0
        goto err;
490
491
265
    if (!EVP_EncryptInit_ex2(ctx, evp_cipher, key, iv, NULL))
492
0
        goto err;
493
494
265
    if (!EVP_CIPHER_CTX_set_params(ctx, param))
495
153
        goto err;
496
497
112
    if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, (const unsigned char *)intext,
498
112
            (int)strlen(intext)))
499
9
        goto err;
500
    /*
501
     * Buffer passed to EVP_EncryptFinal() must be after data just
502
     * encrypted to avoid overwriting it.
503
     */
504
103
    if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen))
505
20
        goto err;
506
83
    outlen += tmplen;
507
83
    EVP_CIPHER_CTX_free(ctx);
508
83
    OPENSSL_free(key);
509
83
    OPENSSL_free(iv);
510
83
    return 1;
511
512
182
err:
513
182
    EVP_CIPHER_CTX_free(ctx);
514
182
    OPENSSL_free(key);
515
182
    OPENSSL_free(iv);
516
182
    return 0;
517
103
}
518
519
static int do_evp_kdf(EVP_KDF *evp_kdf, const OSSL_PARAM params[])
520
6.22k
{
521
6.22k
    int r = 1;
522
6.22k
    EVP_KDF_CTX *kctx = NULL;
523
6.22k
    unsigned char derived[32];
524
525
6.22k
    kctx = EVP_KDF_CTX_new(evp_kdf);
526
527
6.22k
    if (kctx == NULL) {
528
0
        r = 0;
529
0
        goto end;
530
0
    }
531
532
6.22k
    if (EVP_KDF_CTX_set_params(kctx, params) <= 0) {
533
2.56k
        r = 0;
534
2.56k
        goto end;
535
2.56k
    }
536
537
3.66k
    if (EVP_KDF_derive(kctx, derived, sizeof(derived), NULL) <= 0) {
538
1.07k
        r = 0;
539
1.07k
        goto end;
540
1.07k
    }
541
542
6.22k
end:
543
6.22k
    EVP_KDF_CTX_free(kctx);
544
6.22k
    return r;
545
3.66k
}
546
547
static int do_evp_mac(EVP_MAC *evp_mac, const OSSL_PARAM params[])
548
2.01k
{
549
2.01k
    int r = 1;
550
2.01k
    const char *key = "mac_key";
551
2.01k
    char text[] = "Some Crypto Text";
552
2.01k
    EVP_MAC_CTX *ctx = NULL;
553
2.01k
    unsigned char buf[4096];
554
2.01k
    size_t final_l;
555
556
2.01k
    if ((ctx = EVP_MAC_CTX_new(evp_mac)) == NULL
557
2.01k
        || !EVP_MAC_init(ctx, (const unsigned char *)key, strlen(key),
558
2.01k
            params)) {
559
1.20k
        r = 0;
560
1.20k
        goto end;
561
1.20k
    }
562
563
808
    if (EVP_MAC_CTX_set_params(ctx, params) <= 0) {
564
0
        r = 0;
565
0
        goto end;
566
0
    }
567
568
808
    if (!EVP_MAC_update(ctx, (unsigned char *)text, sizeof(text))) {
569
98
        r = 0;
570
98
        goto end;
571
98
    }
572
573
710
    if (!EVP_MAC_final(ctx, buf, &final_l, sizeof(buf))) {
574
0
        r = 0;
575
0
        goto end;
576
0
    }
577
578
2.01k
end:
579
2.01k
    EVP_MAC_CTX_free(ctx);
580
2.01k
    return r;
581
710
}
582
583
static int do_evp_rand(EVP_RAND *evp_rand, const OSSL_PARAM params[])
584
1.17k
{
585
1.17k
    int r = 1;
586
1.17k
    EVP_RAND_CTX *ctx = NULL;
587
1.17k
    unsigned char buf[4096];
588
589
1.17k
    if (!(ctx = EVP_RAND_CTX_new(evp_rand, NULL))) {
590
0
        r = 0;
591
0
        goto end;
592
0
    }
593
594
1.17k
    if (EVP_RAND_CTX_set_params(ctx, params) <= 0) {
595
337
        r = 0;
596
337
        goto end;
597
337
    }
598
599
839
    if (!EVP_RAND_generate(ctx, buf, sizeof(buf), 0, 0, NULL, 0)) {
600
197
        r = 0;
601
197
        goto end;
602
197
    }
603
604
642
    if (!EVP_RAND_reseed(ctx, 0, 0, 0, NULL, 0)) {
605
0
        r = 0;
606
0
        goto end;
607
0
    }
608
609
1.17k
end:
610
1.17k
    EVP_RAND_CTX_free(ctx);
611
1.17k
    return r;
612
642
}
613
614
static int do_evp_sig(EVP_SIGNATURE *evp_sig, const OSSL_PARAM params[])
615
121
{
616
121
    return 0;
617
121
}
618
619
static int do_evp_asym_cipher(EVP_ASYM_CIPHER *evp_asym_cipher, const OSSL_PARAM params[])
620
23
{
621
23
    return 0;
622
23
}
623
624
static int do_evp_kem(EVP_KEM *evp_kem, const OSSL_PARAM params[])
625
52
{
626
52
    return 0;
627
52
}
628
629
static int do_evp_key_exch(EVP_KEYEXCH *evp_kdf, const OSSL_PARAM params[])
630
92
{
631
92
    return 0;
632
92
}
633
634
static int do_evp_md(EVP_MD *evp_md, const OSSL_PARAM params[])
635
147
{
636
147
    int r = 1;
637
147
    unsigned char md_value[EVP_MAX_MD_SIZE];
638
147
    unsigned int md_len;
639
147
    EVP_MD_CTX *mdctx = NULL;
640
641
147
    if (!(mdctx = EVP_MD_CTX_new())) {
642
0
        r = 0;
643
0
        goto end;
644
0
    }
645
646
147
    if (!EVP_DigestInit_ex2(mdctx, evp_md, NULL)) {
647
66
        r = 0;
648
66
        goto end;
649
66
    }
650
651
81
    if (!EVP_MD_CTX_set_params(mdctx, params)) {
652
63
        r = 0;
653
63
        goto end;
654
63
    }
655
18
    if (!EVP_DigestUpdate(mdctx, "Test", strlen("Test"))) {
656
0
        r = 0;
657
0
        goto end;
658
0
    }
659
18
    if (!EVP_DigestFinal_ex(mdctx, md_value, &md_len)) {
660
14
        r = 0;
661
14
        goto end;
662
14
    }
663
664
147
end:
665
147
    EVP_MD_CTX_free(mdctx);
666
147
    return r;
667
18
}
668
669
#define EVP_FUZZ(source, evp, f)                                                               \
670
10.2k
    do {                                                                                       \
671
10.2k
        evp *alg = sk_##evp##_value(source, *algorithm % sk_##evp##_num(source));              \
672
10.2k
        OSSL_PARAM *fuzzed_params;                                                             \
673
10.2k
                                                                                               \
674
10.2k
        if (alg == NULL)                                                                       \
675
10.2k
            break;                                                                             \
676
10.2k
        fuzzed_params = fuzz_params((OSSL_PARAM *)evp##_settable_ctx_params(alg), &buf, &len); \
677
10.2k
        if (fuzzed_params != NULL)                                                             \
678
10.2k
            f(alg, fuzzed_params);                                                             \
679
10.2k
        free_params(fuzzed_params);                                                            \
680
10.2k
        OSSL_PARAM_free(fuzzed_params);                                                        \
681
10.2k
    } while (0);
682
683
int FuzzerTestOneInput(const uint8_t *buf, size_t len)
684
10.2k
{
685
10.2k
    int r = 1;
686
10.2k
    uint64_t *operation = NULL;
687
10.2k
    int64_t *algorithm = NULL;
688
689
10.2k
    if (!read_uint(&buf, &len, &operation)) {
690
16
        r = 0;
691
16
        goto end;
692
16
    }
693
694
10.2k
    if (!read_int(&buf, &len, &algorithm)) {
695
20
        r = 0;
696
20
        goto end;
697
20
    }
698
699
10.2k
    switch (*operation % 10) {
700
147
    case 0:
701
147
        EVP_FUZZ(digests_collection, EVP_MD, do_evp_md);
702
147
        break;
703
352
    case 1:
704
352
        EVP_FUZZ(cipher_collection, EVP_CIPHER, do_evp_cipher);
705
352
        break;
706
6.22k
    case 2:
707
6.22k
        EVP_FUZZ(kdf_collection, EVP_KDF, do_evp_kdf);
708
6.22k
        break;
709
2.01k
    case 3:
710
2.01k
        EVP_FUZZ(mac_collection, EVP_MAC, do_evp_mac);
711
2.01k
        break;
712
52
    case 4:
713
52
        EVP_FUZZ(kem_collection, EVP_KEM, do_evp_kem);
714
52
        break;
715
1.17k
    case 5:
716
1.17k
        EVP_FUZZ(rand_collection, EVP_RAND, do_evp_rand);
717
1.17k
        break;
718
23
    case 6:
719
23
        EVP_FUZZ(asym_ciphers_collection, EVP_ASYM_CIPHER, do_evp_asym_cipher);
720
23
        break;
721
121
    case 7:
722
121
        EVP_FUZZ(signature_collection, EVP_SIGNATURE, do_evp_sig);
723
121
        break;
724
92
    case 8:
725
92
        EVP_FUZZ(keyexch_collection, EVP_KEYEXCH, do_evp_key_exch);
726
92
        break;
727
4
    case 9:
728
        /*
729
        Implement and call:
730
        static int do_evp_keymgmt(EVP_KEYMGMT *evp_kdf, const OSSL_PARAM params[])
731
        {
732
            return 0;
733
        }
734
        */
735
        /* not yet implemented */
736
4
        break;
737
0
    default:
738
0
        r = 0;
739
0
        goto end;
740
10.2k
    }
741
742
10.2k
end:
743
10.2k
    OPENSSL_free(operation);
744
10.2k
    OPENSSL_free(algorithm);
745
10.2k
    return r;
746
10.2k
}