Skip to content

Commit 40c1dde

Browse files
committed
Add fuzz tests for the automotive example
1 parent fa09244 commit 40c1dde

File tree

3 files changed

+302
-1
lines changed

3 files changed

+302
-1
lines changed

src/automotive/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,13 @@ target_include_directories(automotive PUBLIC
1111
${CMAKE_CURRENT_SOURCE_DIR}/gps
1212
${CMAKE_CURRENT_SOURCE_DIR}/key_management
1313
${CMAKE_CURRENT_SOURCE_DIR}/time
14-
)
14+
)
15+
16+
add_fuzz_test(automotive_fuzzer
17+
fuzz_test.cpp
18+
mocks.cpp
19+
)
20+
21+
target_link_libraries(automotive_fuzzer
22+
automotive
23+
)

src/automotive/fuzz_test.cpp

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
2+
#include <stddef.h>
3+
#include <stdint.h>
4+
5+
#include <cifuzz/cifuzz.h>
6+
#include <fuzzer/FuzzedDataProvider.h>
7+
8+
#ifdef __cplusplus
9+
extern "C" {
10+
#endif
11+
12+
#include "crypto_1.h"
13+
#include "crypto_2.h"
14+
#include "gps_1.h"
15+
#include "key_management_1.h"
16+
#include "time_1.h"
17+
18+
#ifdef __cplusplus
19+
}
20+
#endif
21+
22+
void SetFDP(FuzzedDataProvider *fuzzed_data_provider);
23+
FuzzedDataProvider *GetFDP();
24+
void ConsumeDataAndFillRestWithZeros(void *destination, size_t num_bytes);
25+
26+
FUZZ_TEST_SETUP() {}
27+
28+
FUZZ_TEST(const uint8_t *data, size_t size) {
29+
30+
// Ensure a minimum data length
31+
if (size < 100)
32+
return;
33+
34+
// Setup FuzzedDataProvider and initialize the mocklib
35+
FuzzedDataProvider fdp(data, size);
36+
SetFDP(&fdp);
37+
38+
int number_of_functions = GetFDP()->ConsumeIntegralInRange<int>(1, 100);
39+
for (int i = 0; i < number_of_functions; i++) {
40+
int function_id = GetFDP()->ConsumeIntegralInRange<int>(0, 15);
41+
switch (function_id) {
42+
43+
case 0: {
44+
crypto_get_state();
45+
break;
46+
}
47+
48+
case 1: {
49+
get_destination_position();
50+
break;
51+
}
52+
53+
case 2: {
54+
crypto_key key = {};
55+
ConsumeDataAndFillRestWithZeros(key.key, 64);
56+
57+
crypto_verify_key(key);
58+
break;
59+
}
60+
61+
case 3: {
62+
current_time();
63+
break;
64+
}
65+
66+
case 4: {
67+
crypto_nonce nonce_tmp = {};
68+
ConsumeDataAndFillRestWithZeros(nonce_tmp.nonce, 64);
69+
nonce_tmp.time_of_creation = GetFDP()->ConsumeIntegral<int>();
70+
crypto_nonce *nonce = &nonce_tmp;
71+
72+
crypto_verify_nonce(nonce);
73+
break;
74+
}
75+
76+
case 5: {
77+
std::vector<uint8_t> message_vec = GetFDP()->ConsumeBytes<uint8_t>(
78+
sizeof(uint8_t) * GetFDP()->ConsumeIntegral<uint16_t>());
79+
const uint8_t *message = (const uint8_t *)message_vec.data();
80+
81+
// The parameter "len" seems to represent the length of a buffer/array. In
82+
// this case, we usually don't want to provide fuzzer-generated lengths
83+
// that differ from the actual length of the buffer. If you confirm that
84+
// the parameter is a length parameter, you can get the length of the
85+
// fuzzer-generated buffer as follows (replace "buffer" with the actual
86+
// variable):
87+
// int len = buffer.size();
88+
int len = message_vec.size();
89+
crypto_hmac hmac_tmp = {};
90+
ConsumeDataAndFillRestWithZeros(hmac_tmp.hmac, 64);
91+
crypto_hmac *hmac = &hmac_tmp;
92+
93+
crypto_verify_hmac(message, len, hmac);
94+
break;
95+
}
96+
97+
case 6: {
98+
crypto_nonce nonce = {};
99+
ConsumeDataAndFillRestWithZeros(nonce.nonce, 64);
100+
nonce.time_of_creation = GetFDP()->ConsumeIntegral<int>();
101+
102+
crypto_set_nonce(nonce);
103+
break;
104+
}
105+
106+
case 7: {
107+
std::vector<uint8_t> message_vec = GetFDP()->ConsumeBytes<uint8_t>(
108+
sizeof(uint8_t) * GetFDP()->ConsumeIntegral<uint16_t>());
109+
const uint8_t *message = (const uint8_t *)message_vec.data();
110+
111+
// The parameter "len" seems to represent the length of a buffer/array. In
112+
// this case, we usually don't want to provide fuzzer-generated lengths
113+
// that differ from the actual length of the buffer. If you confirm that
114+
// the parameter is a length parameter, you can get the length of the
115+
// fuzzer-generated buffer as follows (replace "buffer" with the actual
116+
// variable):
117+
// int len = buffer.size();
118+
int len = message_vec.size();
119+
crypto_hmac hmac_tmp = {};
120+
ConsumeDataAndFillRestWithZeros(hmac_tmp.hmac, 64);
121+
crypto_hmac *hmac = &hmac_tmp;
122+
123+
crypto_calculate_hmac(message, len, hmac);
124+
break;
125+
}
126+
127+
case 8: {
128+
GPS_position position = {};
129+
position.longitude_degree = GetFDP()->ConsumeIntegral<uint8_t>();
130+
position.longitude_minute = GetFDP()->ConsumeIntegral<uint8_t>();
131+
position.longitude_second = GetFDP()->ConsumeIntegral<uint8_t>();
132+
position.latitude_degree = GetFDP()->ConsumeIntegral<uint8_t>();
133+
position.latitude_minute = GetFDP()->ConsumeIntegral<uint8_t>();
134+
position.latitude_second = GetFDP()->ConsumeIntegral<uint8_t>();
135+
136+
set_destination_postition(position);
137+
break;
138+
}
139+
140+
case 9: {
141+
crypto_key key = {};
142+
ConsumeDataAndFillRestWithZeros(key.key, 64);
143+
144+
crypto_set_key(key);
145+
break;
146+
}
147+
148+
case 10: {
149+
GPS_position position_tmp = {};
150+
position_tmp.longitude_degree = GetFDP()->ConsumeIntegral<uint8_t>();
151+
position_tmp.longitude_minute = GetFDP()->ConsumeIntegral<uint8_t>();
152+
position_tmp.longitude_second = GetFDP()->ConsumeIntegral<uint8_t>();
153+
position_tmp.latitude_degree = GetFDP()->ConsumeIntegral<uint8_t>();
154+
position_tmp.latitude_minute = GetFDP()->ConsumeIntegral<uint8_t>();
155+
position_tmp.latitude_second = GetFDP()->ConsumeIntegral<uint8_t>();
156+
GPS_position *position = &position_tmp;
157+
158+
get_current_position(position);
159+
break;
160+
}
161+
162+
case 11: {
163+
init_crypto_module();
164+
break;
165+
}
166+
167+
case 12: {
168+
std::vector<uint8_t> key_vec = GetFDP()->ConsumeBytes<uint8_t>(
169+
sizeof(uint8_t) * GetFDP()->ConsumeIntegral<uint16_t>());
170+
uint8_t *key = (uint8_t *)key_vec.data();
171+
172+
// The parameter "length" seems to represent the length of a buffer/array.
173+
// In this case, we usually don't want to provide fuzzer-generated lengths
174+
// that differ from the actual length of the buffer. If you confirm that
175+
// the parameter is a length parameter, you can get the length of the
176+
// fuzzer-generated buffer as follows (replace "buffer" with the actual
177+
// variable):
178+
// uint8_t length = buffer.size();
179+
uint8_t length = key_vec.size();
180+
181+
key_management_create_key(key, length);
182+
break;
183+
}
184+
185+
case 13: {
186+
std::vector<uint8_t> nonce_vec = GetFDP()->ConsumeBytes<uint8_t>(
187+
sizeof(uint8_t) * GetFDP()->ConsumeIntegral<uint16_t>());
188+
uint8_t *nonce = (uint8_t *)nonce_vec.data();
189+
190+
// The parameter "length" seems to represent the length of a buffer/array.
191+
// In this case, we usually don't want to provide fuzzer-generated lengths
192+
// that differ from the actual length of the buffer. If you confirm that
193+
// the parameter is a length parameter, you can get the length of the
194+
// fuzzer-generated buffer as follows (replace "buffer" with the actual
195+
// variable):
196+
// uint8_t length = buffer.size();
197+
uint8_t length = nonce_vec.size();
198+
199+
key_management_create_nonce(nonce, length);
200+
break;
201+
}
202+
203+
case 14: {
204+
crypto_init();
205+
break;
206+
}
207+
}
208+
}
209+
}

src/automotive/mocks.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
2+
#include <cstdint>
3+
#include <iomanip>
4+
#include <iostream>
5+
#include <vector>
6+
7+
#include <fuzzer/FuzzedDataProvider.h>
8+
9+
#ifdef __cplusplus
10+
extern "C" {
11+
#endif
12+
13+
#include "crypto_1.h"
14+
#include "gps_1.h"
15+
#include "key_management_1.h"
16+
#include "time_1.h"
17+
18+
#ifdef __cplusplus
19+
}
20+
#endif
21+
22+
static FuzzedDataProvider *gFDP;
23+
24+
// This function received the fuzzer generated data from the fuzz target.
25+
// It needs to be called at the beginning of the LLVMFuzzerTestOneInput
26+
// function.
27+
void SetFDP(FuzzedDataProvider *fuzzed_data_provider) {
28+
gFDP = fuzzed_data_provider;
29+
}
30+
31+
FuzzedDataProvider *GetFDP() { return gFDP; }
32+
33+
// Wrapper function for FuzzedDataProvider.h
34+
// Writes |num_bytes| of input data to the given destination pointer. If there
35+
// is not enough data left, writes all remaining bytes and fills the rest with
36+
// zeros. Return value is the number of bytes written.
37+
void ConsumeDataAndFillRestWithZeros(void *destination, size_t num_bytes) {
38+
if (destination != nullptr) {
39+
size_t num_consumed_bytes = GetFDP()->ConsumeData(destination, num_bytes);
40+
if (num_bytes > num_consumed_bytes) {
41+
size_t num_zero_bytes = num_bytes - num_consumed_bytes;
42+
std::memset((char *)destination + num_consumed_bytes, 0, num_zero_bytes);
43+
}
44+
}
45+
}
46+
47+
#ifdef __cplusplus
48+
extern "C" {
49+
#endif
50+
51+
int driver_get_current_time() {
52+
int cifuzz_var_0 = GetFDP()->ConsumeIntegral<int>();
53+
return cifuzz_var_0;
54+
}
55+
56+
uint8_t GPS_driver_obtain_current_position(uint8_t *position_as_bytes,
57+
uint8_t *hmac_as_bytes) {
58+
unsigned int position_as_bytes_length = 12;
59+
ConsumeDataAndFillRestWithZeros((void *)position_as_bytes,
60+
position_as_bytes_length);
61+
unsigned int hmac_as_bytes_length = 64;
62+
ConsumeDataAndFillRestWithZeros((void *)hmac_as_bytes, hmac_as_bytes_length);
63+
uint8_t cifuzz_var_1 = GetFDP()->ConsumeIntegral<uint8_t>();
64+
return cifuzz_var_1;
65+
}
66+
67+
uint8_t HSM_get_random_byte() {
68+
uint8_t cifuzz_var_2 = GetFDP()->ConsumeIntegral<uint8_t>();
69+
return cifuzz_var_2;
70+
}
71+
72+
uint8_t third_party_library_calc_hmac(const uint8_t *message, int len,
73+
const char *key, const char *nonce,
74+
uint8_t *hmac) {
75+
unsigned int hmac_length = 64;
76+
ConsumeDataAndFillRestWithZeros((void *)hmac, hmac_length);
77+
uint8_t cifuzz_var_3 = GetFDP()->ConsumeIntegral<uint8_t>();
78+
return cifuzz_var_3;
79+
}
80+
81+
#ifdef __cplusplus
82+
}
83+
#endif

0 commit comments

Comments
 (0)