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