xref: /openssl/fuzz/provider.c (revision f3b988dc)
1 /*
2  * Copyright 2023 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 
FuzzerInitialize(int * argc,char *** argv)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 
FuzzerCleanup(void)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 
read_uint(const uint8_t ** buf,size_t * len,uint64_t ** res)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 
read_int(const uint8_t ** buf,size_t * len,int64_t ** res)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 
read_double(const uint8_t ** buf,size_t * len,double ** res)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 
read_utf8_string(const uint8_t ** buf,size_t * len,char ** res)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 = 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 
read_utf8_ptr(const uint8_t ** buf,size_t * len,char ** res)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 
read_octet_string(const uint8_t ** buf,size_t * len,char ** res)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 
read_octet_ptr(const uint8_t ** buf,size_t * len,char ** res)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 
free_params(OSSL_PARAM * param)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 
fuzz_params(OSSL_PARAM * param,const uint8_t ** buf,size_t * len)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 
do_evp_cipher(const EVP_CIPHER * evp_cipher,const OSSL_PARAM param[])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 
do_evp_kdf(EVP_KDF * evp_kdf,const OSSL_PARAM params[])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 
do_evp_mac(EVP_MAC * evp_mac,const OSSL_PARAM params[])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 
do_evp_rand(EVP_RAND * evp_rand,const OSSL_PARAM params[])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 
do_evp_sig(EVP_SIGNATURE * evp_sig,const OSSL_PARAM params[])526 static int do_evp_sig(EVP_SIGNATURE *evp_sig, const OSSL_PARAM params[])
527 {
528     return 0;
529 }
530 
do_evp_asym_cipher(EVP_ASYM_CIPHER * evp_asym_cipher,const OSSL_PARAM params[])531 static int do_evp_asym_cipher(EVP_ASYM_CIPHER *evp_asym_cipher, const OSSL_PARAM params[])
532 {
533     return 0;
534 }
535 
do_evp_kem(EVP_KEM * evp_kem,const OSSL_PARAM params[])536 static int do_evp_kem(EVP_KEM *evp_kem, const OSSL_PARAM params[])
537 {
538     return 0;
539 }
540 
do_evp_key_exch(EVP_KEYEXCH * evp_kdf,const OSSL_PARAM params[])541 static int do_evp_key_exch(EVP_KEYEXCH *evp_kdf, const OSSL_PARAM params[])
542 {
543     return 0;
544 }
545 
do_evp_md(EVP_MD * evp_md,const OSSL_PARAM params[])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 
FuzzerTestOneInput(const uint8_t * buf,size_t len)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