Skip to content

Commit

Permalink
add fuzzer
Browse files Browse the repository at this point in the history
  • Loading branch information
yhql committed Mar 29, 2021
1 parent e81b065 commit c71a462
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fuzz/build/
fuzz/corpus/
18 changes: 18 additions & 0 deletions fuzz/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.10)

project(essence_fuzzer)

set(CMAKE_C_STANDARD 99)

include_directories(. ../src ../src/iota)

add_definitions(-DFUZZING)

add_executable(essence_fuzzer fuzztest.c ../src/iota/essence.c)
add_executable(essence_fuzzer_coverage fuzztest.c ../src/iota/essence.c)

target_compile_options(essence_fuzzer PRIVATE -fsanitize=fuzzer,address -g -ggdb2 -O1)
target_compile_options(essence_fuzzer_coverage PRIVATE -fsanitize=fuzzer,address -g -ggdb2 -O1 -fprofile-instr-generate -fcoverage-mapping)

target_link_options(essence_fuzzer PRIVATE -fsanitize=fuzzer,address)
target_link_options(essence_fuzzer_coverage PRIVATE -fsanitize=fuzzer,address)
36 changes: 36 additions & 0 deletions fuzz/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Fuzzing

This fuzzer should reach a reasonable coverage (>85%) of `essence.c` with no test cases to start with and in a very short time, but this could always be improved by starting from a real testcase.

### On Linux:

- `cmake -Bbuild -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++`

Fuzzing (from `./build/`):

- `./essence_fuzzer ../corpus/`

Running coverage:

- `./essence_fuzzer_coverage ../corpus/*`

### On Windows:

- `cmake -Bbuild -GNinja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++`

Fuzzing (from `./build/`):

- `.\essence_fuzzer.exe ../corpus/`

Running coverage:
- `.\essence_fuzzer_coverage.exe $(ls ../corpus/* | % {$_.FullName})`

## Monitoring coverage

```
llvm-profdata merge -sparse *.profraw -o default.profdata
llvm-cov report essence_fuzzer_coverage -instr-profile="default.profdata"
llvm-cov show essence_fuzzer_coverage -instr-profile="default.profdata" --format=html > report.html
```

Will output a file `report.html` containing coverage information by line in the source file.
15 changes: 15 additions & 0 deletions fuzz/fuzztest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <stdint.h>
#include <string.h>

#include "api.h"
#include "essence.h"

int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
if (Size >= API_BUFFER_SIZE_BYTES) {
API_CTX api = {0};
memcpy(api.data.buffer, Data, API_BUFFER_SIZE_BYTES);
// api.essence.has_remainder = 1;
essence_parse_and_validate(&api);
}
return 0;
}
7 changes: 7 additions & 0 deletions fuzz/os.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#pragma once

#define os_memcpy memcpy
#define os_memcmp memcmp
#define os_memset memset
#define explicit_bzero(addr, size) memset((addr), 0, (size))

21 changes: 17 additions & 4 deletions src/iota/essence.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@

#include "os.h"
#include "api.h"
#include "iota_io.h"
#include "iota/ed25519.h"

#ifndef FUZZING
#include "iota_io.h"
#include "iota/ed25519.h"
#endif

// gcc doesn't know this and ledger's SDK cannot be compiled with Werror!
//#pragma GCC diagnostic error "-Werror"
Expand Down Expand Up @@ -360,23 +363,32 @@ static uint8_t essence_verify_remainder_address(
bip32_path[BIP32_ADDRESS_INDEX] = remainder_bip32->bip32_index;
bip32_path[BIP32_CHANGE_INDEX] = remainder_bip32->bip32_change;

// Block below cannot be fuzzed without going through crypto APIs
#ifndef FUZZING
// address generate generates with address
MUST(address_generate(bip32_path, BIP32_PATH_LEN, &tmp.address_type));

// verify, the address is the same
// relies on packed struct
MUST(!os_memcmp(&outputs[remainder_index].address_type, &tmp.address_type,
ADDRESS_WITH_TYPE_SIZE_BYTES));

#else
(void)outputs;
#endif
return 1;
}

static void essence_hash(API_CTX *api)
{
// Block below cannot be fuzzed without going through crypto APIs
#ifndef FUZZING
cx_blake2b_t blake2b;
cx_blake2b_init(&blake2b, BLAKE2B_SIZE_BYTES * 8);
cx_hash(&blake2b.header, CX_LAST, api->data.buffer, api->essence.length,
api->essence.hash, ADDRESS_SIZE_BYTES);
#else
(void)api;
#endif
}

uint8_t essence_parse_and_validate(API_CTX *api)
Expand Down Expand Up @@ -446,7 +458,7 @@ uint8_t essence_parse_and_validate(API_CTX *api)
return 1;
}


#ifndef FUZZING
static uint16_t essence_sign_signature_unlock_block(
SIGNATURE_UNLOCK_BLOCK *pBlock, uint16_t output_max_len,
const uint8_t *essence_hash, uint32_t *bip32_path,
Expand Down Expand Up @@ -584,3 +596,4 @@ uint8_t essence_sign(API_CTX *api)

return 1;
}
#endif // FUZZING

0 comments on commit c71a462

Please sign in to comment.