Skip to content

Commit 3f0d4d6

Browse files
test: add eip7702 fuzzer
1 parent fc7bafd commit 3f0d4d6

3 files changed

Lines changed: 150 additions & 1 deletion

File tree

tests/fuzzing/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,8 @@ set(DEFINES
159159
HAVE_NFT_SUPPORT
160160
HAVE_DYNAMIC_NETWORKS
161161
HAVE_WEB3_CHECKS
162+
HAVE_EIP7702
163+
HAVE_EIP7702_WHITELIST
162164
explicit_bzero=bzero # Fix for https://github.com/google/sanitizers/issues/1507
163165
)
164166
@@ -190,6 +192,7 @@ include_directories(
190192
${CMAKE_SOURCE_DIR}/../../src_features/signMessageEIP712/
191193
${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/
192194
${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/
195+
${CMAKE_SOURCE_DIR}/../../src_features/signAuthorizationEIP7702/
193196
${BOLOS_SDK}/include
194197
${BOLOS_SDK}/target/${TARGET_DEVICE}/include
195198
${BOLOS_SDK}/lib_cxng/include
@@ -209,6 +212,7 @@ FILE(GLOB_RECURSE SOURCES
209212
${CMAKE_SOURCE_DIR}/../../src_features/provideNFTInformation/*.c
210213
${CMAKE_SOURCE_DIR}/../../src_features/provide_proxy_info/*.c
211214
${CMAKE_SOURCE_DIR}/../../src_features/provide_tx_simulation/*.c
215+
${CMAKE_SOURCE_DIR}/../../src_features/signAuthorizationEIP7702/*.c
212216
${CMAKE_SOURCE_DIR}/../../src/mem.c
213217
${CMAKE_SOURCE_DIR}/../../src/mem_utils.c
214218
${CMAKE_SOURCE_DIR}/../../src/network.c

tests/fuzzing/src/fuzzer.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include "gtp_tx_info.h"
1818
#include "enum_value.h"
1919

20+
#include "auth_7702.h"
21+
#include "commands_7702.h"
22+
2023
#include "shared_context.h"
2124
#include "tlv.h"
2225
#include "mem.h"
@@ -26,6 +29,7 @@
2629
typedef int (*harness)(const uint8_t *data, size_t size);
2730

2831
// Global state required by the app features
32+
cx_sha3_t global_sha3;
2933
cx_sha3_t sha3;
3034
unsigned char G_io_apdu_buffer[260];
3135
tmpContent_t tmpContent;
@@ -39,7 +43,12 @@ const chain_config_t *chainConfig = &config;
3943
uint8_t appState;
4044
tmpCtx_t tmpCtx;
4145
strings_t strings;
42-
const internalStorage_t N_storage_real = {.w3c_enable = true, .w3c_opt_in = true};
46+
// Mock the storage to enable wanted features
47+
const internalStorage_t N_storage_real = {
48+
.w3c_enable = true,
49+
.w3c_opt_in = true,
50+
.eip7702_enable = true,
51+
};
4352

4453
int fuzzGenericParserFieldCmd(const uint8_t *data, size_t size) {
4554
s_field field = {0};
@@ -160,6 +169,33 @@ int fuzzCalldata(const uint8_t *data, size_t size) {
160169
return 0;
161170
}
162171

172+
int fuzzEIP7702Parser(const uint8_t *data, size_t size) {
173+
s_auth_7702_ctx ctx = {0};
174+
175+
if (!tlv_parse(data, size, (f_tlv_data_handler) handle_auth_7702_struct, &ctx)) return 1;
176+
177+
if (!verify_auth_7702_struct(&ctx)) return 1;
178+
179+
return 0;
180+
}
181+
182+
int fuzzEIP7702(const uint8_t *data, size_t size) {
183+
size_t offset = 0;
184+
size_t len = 0;
185+
uint8_t p1;
186+
unsigned int flags;
187+
188+
while (size - offset > 3) {
189+
if (data[offset++] == 0) break;
190+
p1 = data[offset++];
191+
len = data[offset++];
192+
if (size - offset < len) return 0;
193+
if (handleSignEIP7702Authorization(p1, data + offset, len, &flags) != APDU_RESPONSE_OK) return 1;
194+
offset += len;
195+
}
196+
return 0;
197+
}
198+
163199
// Array of fuzzing harness functions
164200
harness harnesses[] = {
165201
fuzzGenericParserFieldCmd,
@@ -171,6 +207,7 @@ harness harnesses[] = {
171207
fuzzProxyInfo,
172208
fuzzTxSimulation,
173209
fuzzCalldata,
210+
fuzzEIP7702,
174211
};
175212

176213
/* Main fuzzing handler called by libfuzzer */
@@ -183,6 +220,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
183220
explicit_bzero(&strings, sizeof(strings_t));
184221
explicit_bzero(&G_io_apdu_buffer, 260);
185222
explicit_bzero(&sha3, sizeof(sha3));
223+
explicit_bzero(&global_sha3, sizeof(global_sha3));
186224

187225
calldata_cleanup();
188226
mem_reset();

tests/fuzzing/src/mock.c

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "buffer.h"
88
#include "lcx_ecfp.h"
99

10+
#include "bip32_utils.h"
11+
1012
/** MemorySanitizer does not wrap explicit_bzero https://github.com/google/sanitizers/issues/1507
1113
* which results in false positives when running MemorySanitizer.
1214
*/
@@ -184,16 +186,121 @@ int io_send_response_buffers(const buffer_t *rdatalist, size_t count, uint16_t s
184186
}
185187

186188
uint16_t io_seproxyhal_send_status(uint16_t sw, uint32_t tx, bool reset, bool idle) {
189+
UNUSED(sw);
190+
UNUSED(tx);
191+
UNUSED(reset);
192+
UNUSED(idle);
187193
return 0;
188194
}
189195

190196
uint32_t os_pki_get_info(uint8_t *key_usage,
191197
uint8_t *trusted_name,
192198
size_t *trusted_name_len,
193199
cx_ecfp_384_public_key_t *public_key) {
200+
UNUSED(key_usage);
201+
UNUSED(trusted_name_len);
202+
UNUSED(public_key);
194203
memcpy(trusted_name, "trusted name", sizeof("trusted name"));
195204
return 0;
196205
}
197206

198207
void ui_tx_simulation_opt_in(bool response_expected) {
208+
UNUSED(response_expected);
209+
}
210+
211+
void ui_error_no_7702(void) {
212+
}
213+
214+
void ui_error_no_7702_whitelist(void) {
215+
}
216+
217+
void ui_sign_7702_auth(void) {
218+
}
219+
220+
void ui_sign_7702_revocation(void) {
221+
}
222+
223+
cx_err_t cx_keccak_init_no_throw(cx_sha3_t *hash PLENGTH(sizeof(cx_sha3_t)), size_t size)
224+
{
225+
UNUSED(size);
226+
memset_s(hash, 0, sizeof(cx_sha3_t));
227+
return CX_OK;
228+
}
229+
230+
cx_err_t bip32_derive_with_seed_get_pubkey_256(unsigned int derivation_mode,
231+
cx_curve_t curve,
232+
const uint32_t *path,
233+
size_t path_len,
234+
uint8_t raw_pubkey[static 65],
235+
uint8_t *chain_code,
236+
cx_md_t hashID,
237+
unsigned char *seed,
238+
size_t seed_len) {
239+
UNUSED(derivation_mode);
240+
UNUSED(curve);
241+
UNUSED(path);
242+
UNUSED(path_len);
243+
UNUSED(chain_code);
244+
UNUSED(hashID);
245+
UNUSED(seed);
246+
UNUSED(seed_len);
247+
memset(raw_pubkey, 0, 65);
248+
return CX_OK;
249+
}
250+
251+
cx_err_t bip32_derive_with_seed_ecdsa_sign_rs_hash_256(unsigned int derivation_mode,
252+
cx_curve_t curve,
253+
const uint32_t *path,
254+
size_t path_len,
255+
uint32_t sign_mode,
256+
cx_md_t hashID,
257+
const uint8_t *hash,
258+
size_t hash_len,
259+
uint8_t sig_r[static 32],
260+
uint8_t sig_s[static 32],
261+
uint32_t *info,
262+
unsigned char *seed,
263+
size_t seed_len) {
264+
UNUSED(derivation_mode);
265+
UNUSED(curve);
266+
UNUSED(path);
267+
UNUSED(path_len);
268+
UNUSED(sign_mode);
269+
UNUSED(hashID);
270+
UNUSED(hash);
271+
UNUSED(hash_len);
272+
UNUSED(info);
273+
UNUSED(seed);
274+
UNUSED(seed_len);
275+
memset(sig_r, 0, 32);
276+
memset(sig_s, 0, 32);
277+
return CX_OK;
278+
}
279+
280+
// Duplicate from main.c...
281+
const uint8_t *parseBip32(const uint8_t *dataBuffer, uint8_t *dataLength, bip32_path_t *bip32) {
282+
if (*dataLength < 1) {
283+
PRINTF("Invalid data\n");
284+
return NULL;
285+
}
286+
287+
bip32->length = *dataBuffer;
288+
289+
dataBuffer++;
290+
(*dataLength)--;
291+
292+
if (*dataLength < sizeof(uint32_t) * (bip32->length)) {
293+
PRINTF("Invalid data\n");
294+
return NULL;
295+
}
296+
297+
if (bip32_path_read(dataBuffer, (size_t) dataLength, bip32->path, (size_t) bip32->length) ==
298+
false) {
299+
PRINTF("Invalid Path data\n");
300+
return NULL;
301+
}
302+
dataBuffer += bip32->length * sizeof(uint32_t);
303+
*dataLength -= bip32->length * sizeof(uint32_t);
304+
305+
return dataBuffer;
199306
}

0 commit comments

Comments
 (0)