/src/liboqs/tests/fuzz_test_sig.c
Line | Count | Source |
1 | | /* |
2 | | * fuzz_test_sig.c |
3 | | * |
4 | | * Minimal fuzz test for liboqs. |
5 | | * |
6 | | * SPDX-License-Identifier: MIT |
7 | | */ |
8 | | |
9 | | #include "oqs/sig.h" |
10 | | #include <stdbool.h> |
11 | | #include <stdio.h> |
12 | | #include <stdlib.h> |
13 | | #include <string.h> |
14 | | |
15 | | #include <oqs/oqs.h> |
16 | | |
17 | | |
18 | | typedef struct { |
19 | | uint32_t random_seed; |
20 | | uint32_t algorithm_index; |
21 | | } fuzz_init_ctx_t; |
22 | | |
23 | | typedef struct { |
24 | | fuzz_init_ctx_t init; |
25 | | const uint8_t *data; |
26 | | size_t data_len; |
27 | | } fuzz_ctx_t; |
28 | | |
29 | | fuzz_ctx_t init_fuzz_context(const uint8_t *data, size_t data_len); |
30 | | void fuzz_rand(uint8_t *random_array, size_t bytes_to_read); |
31 | | |
32 | 0 | void fuzz_rand(uint8_t *random_array, size_t bytes_to_read) { |
33 | 0 | for (size_t i = 0; i < bytes_to_read; i++) { |
34 | 0 | random_array[i] = (uint8_t)rand(); |
35 | 0 | } |
36 | 0 | } |
37 | | |
38 | 0 | fuzz_ctx_t init_fuzz_context(const uint8_t *data, size_t data_len) { |
39 | |
|
40 | 0 | fuzz_ctx_t ctx = {{0, 0}, NULL, 0}; |
41 | 0 | if (data_len > sizeof(fuzz_init_ctx_t)) { |
42 | 0 | memcpy(&ctx.init, data, sizeof(fuzz_init_ctx_t)); |
43 | 0 | ctx.data = data + sizeof(fuzz_init_ctx_t); |
44 | 0 | ctx.data_len = data_len - sizeof(fuzz_init_ctx_t); |
45 | |
|
46 | 0 | ctx.init.algorithm_index %= OQS_SIG_algs_length; |
47 | 0 | } else { |
48 | 0 | ctx.data = data; |
49 | 0 | ctx.data_len = data_len; |
50 | 0 | } |
51 | |
|
52 | 0 | srand(ctx.init.random_seed); |
53 | 0 | OQS_randombytes_custom_algorithm(&fuzz_rand); |
54 | |
|
55 | 0 | return ctx; |
56 | 0 | } |
57 | | |
58 | | void cleanup_heap(uint8_t *public_key, uint8_t *secret_key, uint8_t *signature, |
59 | | OQS_SIG *sig); |
60 | | |
61 | 0 | static OQS_STATUS fuzz_sig(const uint8_t *data, size_t data_len) { |
62 | 0 | OQS_SIG *sig = NULL; |
63 | 0 | uint8_t *public_key = NULL; |
64 | 0 | uint8_t *secret_key = NULL; |
65 | 0 | uint8_t *signature = NULL; |
66 | 0 | size_t signature_len; |
67 | 0 | OQS_STATUS rc; |
68 | |
|
69 | 0 | fuzz_ctx_t ctx = init_fuzz_context(data, data_len); |
70 | |
|
71 | 0 | const char *algorithm = OQS_SIG_alg_identifier(ctx.init.algorithm_index); |
72 | |
|
73 | 0 | sig = OQS_SIG_new(algorithm); |
74 | 0 | if (sig == NULL) { |
75 | 0 | printf("%s was not enabled at compile-time.\n", algorithm); |
76 | 0 | return OQS_ERROR; |
77 | 0 | } |
78 | | |
79 | 0 | public_key = malloc(sig->length_public_key); |
80 | 0 | secret_key = malloc(sig->length_secret_key); |
81 | 0 | signature = malloc(sig->length_signature); |
82 | 0 | if ((public_key == NULL) || (secret_key == NULL) || (ctx.data == NULL) || |
83 | 0 | (signature == NULL)) { |
84 | 0 | fprintf(stderr, "ERROR: malloc failed!\n"); |
85 | 0 | cleanup_heap(public_key, secret_key, signature, sig); |
86 | 0 | return OQS_ERROR; |
87 | 0 | } |
88 | | |
89 | 0 | rc = OQS_SIG_keypair(sig, public_key, secret_key); |
90 | 0 | if (rc != OQS_SUCCESS) { |
91 | 0 | fprintf(stderr, "ERROR: OQS_SIG_keypair failed!\n"); |
92 | 0 | cleanup_heap(public_key, secret_key, signature, sig); |
93 | 0 | return OQS_ERROR; |
94 | 0 | } |
95 | 0 | rc = OQS_SIG_sign(sig, signature, &signature_len, ctx.data, ctx.data_len, |
96 | 0 | secret_key); |
97 | 0 | if (rc != OQS_SUCCESS) { |
98 | 0 | fprintf(stderr, "ERROR: OQS_SIG_sign failed!\n"); |
99 | 0 | cleanup_heap(public_key, secret_key, signature, sig); |
100 | 0 | return OQS_ERROR; |
101 | 0 | } |
102 | 0 | rc = OQS_SIG_verify(sig, ctx.data, ctx.data_len, signature, signature_len, |
103 | 0 | public_key); |
104 | 0 | if (rc != OQS_SUCCESS) { |
105 | 0 | fprintf(stderr, "ERROR: OQS_SIG_verify failed!\n"); |
106 | 0 | cleanup_heap(public_key, secret_key, signature, sig); |
107 | 0 | exit(1); |
108 | 0 | } |
109 | | |
110 | 0 | cleanup_heap(public_key, secret_key, signature, sig); |
111 | 0 | return OQS_SUCCESS; // success |
112 | 0 | } |
113 | | |
114 | | void cleanup_heap(uint8_t *public_key, uint8_t *secret_key, uint8_t *signature, |
115 | 0 | OQS_SIG *sig) { |
116 | 0 | if (sig != NULL) { |
117 | 0 | OQS_MEM_secure_free(secret_key, sig->length_secret_key); |
118 | 0 | } |
119 | 0 | OQS_MEM_insecure_free(public_key); |
120 | 0 | OQS_MEM_insecure_free(signature); |
121 | 0 | OQS_SIG_free(sig); |
122 | 0 | } |
123 | | |
124 | 0 | int LLVMFuzzerTestOneInput(const char *data, size_t size) { |
125 | 0 | OQS_init(); |
126 | 0 | if (OQS_ERROR == fuzz_sig((const uint8_t *)data, size)) { |
127 | | // If we get an error prune testcase from corpus. |
128 | 0 | return -1; |
129 | 0 | } |
130 | 0 | OQS_destroy(); |
131 | 0 | return 0; |
132 | 0 | } |