Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add fuzzing test #7

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,9 @@ target
.idea/
/specs/cells
.vscode/
webauthn_coverage
webauthn_fuzzer
tests/pw_webauthn_lib/corpus
tests/pw_webauthn_lib/crash-*
tests/pw_webauthn_lib/fuzz-*
tests/pw_webauthn_lib/coverage/*
19 changes: 19 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
cmake_minimum_required(VERSION 3.12)
project(pw-lock C)
set(CMAKE_C_STANDARD 11)
# uncomment it for sanitize
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize=undefined")
add_compile_options(-Wno-macro-redefined)

include_directories(deps/libecc/src)
# deps/ckb-c-std-lib
include_directories(c)
include_directories(tests/pw_webauthn_lib)
add_definitions(-DWORDSIZE=64)
add_definitions(-DWITH_STDLIB)
add_definitions(-D__unix__)
add_definitions(-DCKB_SIMULATOR)
add_definitions(-DNN_CONSISTENCY_CHECK)

add_executable(pw_webauthn_lib tests/pw_webauthn_lib/main_test.c)

63 changes: 63 additions & 0 deletions tests/pw_webauthn_lib/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
OS = Unknown
ifneq ($(shell uname -a | grep -i Darwin),)
OS = MacOS
endif
ifneq ($(shell uname -a | grep -i Linux),)
OS = Linux
endif
ifeq ($(OS),Unknown)
echo "error: unsupported OS"; exit 1
endif

NPROC?=4
CC=clang
LLVM_PROFDATA=llvm-profdata
LLVM_COV=llvm-cov

CORPUS_DIR=corpus
FLAGS=-I../../deps/libecc/src -I../../c -I. -DWORDSIZE=64 -DWITH_STDLIB -D__unix__ -DCKB_SIMULATOR -DNN_CONSISTENCY_CHECK -Wno-macro-redefined

FUZZER_FLAGS=-g -O1 -fsanitize=fuzzer,address,undefined $(FLAGS)

COVERAGE_DIR=coverage
COVERAGE_FLAGS=-fprofile-instr-generate -fcoverage-mapping $(FLAGS)

ifeq ($(OS),MacOS)
COVERAGE_FLAGS+=-Wl,-U,_LLVMFuzzerCustomMutator -Wl,-U,_LLVMFuzzerInitialize
endif

EXTERNAL_HEADERS=../../c/webauthn/pw_webauthn.h

all: fuzzer coverage

show: $(COVERAGE_DIR)/fuzzer.profdata
$(LLVM_COV) show --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata webauthn_coverage

report: $(COVERAGE_DIR)/fuzzer.profdata coverage $(EXTERNAL_HEADERS)
$(LLVM_COV) report --show-functions --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata webauthn_coverage $(EXTERNAL_HEADERS)

fuzzer:
clang $(FUZZER_FLAGS) fuzzer.c -o webauthn_fuzzer

coverage: $(EXTERNAL_HEADERS)
clang $(COVERAGE_FLAGS) coverage.c fuzzer.c -o webauthn_coverage

start-fuzzer: fuzzer
./webauthn_fuzzer -workers=$(NPROC) -jobs=$(NPROC) -max_len=700 corpus

clean:
rm -rf webauthn_fuzzer webauthn_coverage webauthn_fuzzer.dSYM

#%.h:export
# ln -s $(CURDIR)/../$@ $(CURDIR)/$@

%.profraw: coverage
echo "start webauthn_coverage"
LLVM_PROFILE_FILE=$@ ./webauthn_coverage $(CORPUS_DIR)/*

%.profdata: %.profraw
$(LLVM_PROFDATA) merge --sparse $< -o $@

.PHONY: all fuzzer coverage report

.PRECIOUS: $(COVERAGE_DIR)/fuzzer.profraw $(COVERAGE_DIR)/fuzzer.profdata
11 changes: 11 additions & 0 deletions tests/pw_webauthn_lib/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
### Fuzzing test
```bash
make
make start-fuzzer
```

Get code coverage by:
```bash
make report
make show
```
194 changes: 194 additions & 0 deletions tests/pw_webauthn_lib/ckb_syscalls.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#ifndef CKB_C_STDLIB_CKB_SYSCALLS_H_
#define CKB_C_STDLIB_CKB_SYSCALLS_H_

#include <stddef.h>
#include <stdint.h>
#include <string.h>


#define SYS_exit 93
#define SYS_ckb_load_transaction 2051
#define SYS_ckb_load_script 2052
#define SYS_ckb_load_tx_hash 2061
#define SYS_ckb_load_script_hash 2062
#define SYS_ckb_load_cell 2071
#define SYS_ckb_load_header 2072
#define SYS_ckb_load_input 2073
#define SYS_ckb_load_witness 2074
#define SYS_ckb_load_cell_by_field 2081
#define SYS_ckb_load_header_by_field 2082
#define SYS_ckb_load_input_by_field 2083
#define SYS_ckb_load_cell_data_as_code 2091
#define SYS_ckb_load_cell_data 2092
#define SYS_ckb_debug 2177

#define CKB_SUCCESS 0
#define CKB_INDEX_OUT_OF_BOUND 1
#define CKB_ITEM_MISSING 2
#define CKB_LENGTH_NOT_ENOUGH 3

#define CKB_SOURCE_INPUT 1
#define CKB_SOURCE_OUTPUT 2
#define CKB_SOURCE_CELL_DEP 3
#define CKB_SOURCE_HEADER_DEP 4
#define CKB_SOURCE_GROUP_INPUT 0x0100000000000001
#define CKB_SOURCE_GROUP_OUTPUT 0x0100000000000002

#define CKB_CELL_FIELD_CAPACITY 0
#define CKB_CELL_FIELD_DATA_HASH 1
#define CKB_CELL_FIELD_LOCK 2
#define CKB_CELL_FIELD_LOCK_HASH 3
#define CKB_CELL_FIELD_TYPE 4
#define CKB_CELL_FIELD_TYPE_HASH 5
#define CKB_CELL_FIELD_OCCUPIED_CAPACITY 6

#define CKB_HEADER_FIELD_EPOCH_NUMBER 0
#define CKB_HEADER_FIELD_EPOCH_START_BLOCK_NUMBER 1
#define CKB_HEADER_FIELD_EPOCH_LENGTH 2

#define CKB_INPUT_FIELD_OUT_POINT 0
#define CKB_INPUT_FIELD_SINCE 1

int ckb_exit(int8_t code) { return 0;}

int ckb_load_tx_hash(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_checked_load_tx_hash(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_load_script_hash(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_checked_load_script_hash(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_load_cell(void* addr, uint64_t* len, size_t offset, size_t index,
size_t source) {
return 0;
}

int ckb_checked_load_cell(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source) {
return 0;
}

int ckb_load_input(void* addr, uint64_t* len, size_t offset, size_t index,
size_t source) {
return 0;
}

int ckb_checked_load_input(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source) {
return 0;
}

int ckb_load_header(void* addr, uint64_t* len, size_t offset, size_t index,
size_t source) {
return 0;
}

int ckb_checked_load_header(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source) {
return 0;
}

int ckb_load_witness(void* addr, uint64_t* len, size_t offset, size_t index,
size_t source) {
return 0;
}

int ckb_checked_load_witness(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source) {
return 0;
}

int ckb_load_script(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_checked_load_script(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_load_transaction(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_checked_load_transaction(void* addr, uint64_t* len, size_t offset) {
return 0;
}

int ckb_load_cell_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source, size_t field) {
return 0;
}

int ckb_checked_load_cell_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source, size_t field) {
return 0;
}

int ckb_load_header_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source, size_t field) {
return 0;
}

int ckb_checked_load_header_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source,
size_t field) {
return 0;
}

int ckb_load_input_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source, size_t field) {
return 0;
}

int ckb_checked_load_input_by_field(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source, size_t field) {
return 0;
}

int ckb_load_cell_code(void* addr, size_t memory_size, size_t content_offset,
size_t content_size, size_t index, size_t source) {
return 0;
}

int ckb_load_cell_data(void* addr, uint64_t* len, size_t offset, size_t index,
size_t source) {
return 0;
}

int ckb_checked_load_cell_data(void* addr, uint64_t* len, size_t offset,
size_t index, size_t source) {
return 0;
}

int ckb_debug(const char* s) {
return 0;
}

int ckb_load_actual_type_witness(uint8_t* buf, uint64_t* len, size_t index,
size_t* type_source) {
return 0;
}

/* calculate inputs length */
int ckb_calculate_inputs_len() {
return 0;
}

/*
* Look for dep cell with specific data hash, data_hash should a buffer with
* 32 bytes.
*/
int ckb_look_for_dep_with_hash(const uint8_t* data_hash, size_t* index) {
return 0;
}

#endif /* CKB_C_STDLIB_CKB_SYSCALLS_H_ */
41 changes: 41 additions & 0 deletions tests/pw_webauthn_lib/coverage.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*===- StandaloneFuzzTargetMain.c - standalone main() for fuzz targets. ---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// This main() function can be linked to a fuzz target (i.e. a library
// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize())
// instead of libFuzzer. This main() function will not perform any fuzzing
// but will simply feed all input files one by one to the fuzz target.
//
// Use this file to provide reproducers for bugs when linking against libFuzzer
// or other fuzzing engine is undesirable.
//===----------------------------------------------------------------------===*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size);
__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv);

int main(int argc, char **argv) {
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv);
for (int i = 1; i < argc; i++) {
fprintf(stderr, "Running: %s\n", argv[i]);
FILE *f = fopen(argv[i], "r");
assert(f);
fseek(f, 0, SEEK_END);
size_t len = ftell(f);
fseek(f, 0, SEEK_SET);
unsigned char *buf = (unsigned char *)malloc(len);
size_t n_read = fread(buf, 1, len, f);
fclose(f);
assert(n_read == len);
LLVMFuzzerTestOneInput(buf, len);
free(buf);
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
}
}
23 changes: 23 additions & 0 deletions tests/pw_webauthn_lib/fuzzer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "ckb_syscalls.h"
#include "webauthn/pw_webauthn_lib.c"
#include "stubs.h"


/**
* @param message: transaction message digest, size is 32 bytes
* @param lock_args: last 20 bytes sha256 hash of pubkey, used to shield
* the real pubkey. size is 20 bytes
* @param lock_bytes: transaction signature in witness.lock, size is 500 bytes
*
*/
int validate_webauthn(unsigned char* message, unsigned char* lock_args,
unsigned char* lock_bytes, uint64_t lock_bytes_size);


int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
if (size < (564+20+32)) {
return 0;
}
validate_webauthn(data, data+32, data+32+20, 564);
return 0;
}
13 changes: 13 additions & 0 deletions tests/pw_webauthn_lib/main_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

#include "ckb_syscalls.h"
#include "webauthn/pw_webauthn_lib.c"
#include "stubs.h"


int verify_challenge_in_client_data(const u8* digest_message,
const u8* client_data,
int client_data_len);
int main() {

}

Loading