Skip to content

Commit

Permalink
Add a basic fuzz testing harness
Browse files Browse the repository at this point in the history
  • Loading branch information
silvergasp committed Aug 27, 2024
1 parent a6e0bfc commit a4c5fc5
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 0 deletions.
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: MIT

cmake_minimum_required (VERSION 3.15)
include(CMakeDependentOption)

# option() honors normal variables.
# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
if(POLICY CMP0077)
Expand All @@ -27,6 +29,11 @@ option(OQS_LIBJADE_BUILD "Enable formally verified implementation of supported a
option(OQS_PERMIT_UNSUPPORTED_ARCHITECTURE "Permit compilation on an an unsupported architecture." OFF)
option(OQS_STRICT_WARNINGS "Enable all compiler warnings." OFF)
option(OQS_EMBEDDED_BUILD "Compile liboqs for an Embedded environment without a full standard library." OFF)
# Libfuzzer isn't supported on gcc
if('${CMAKE_CXX_COMPILER_ID}' STREQUAL 'Clang')
option(OQS_BUILD_FUZZ_TESTS "Build fuzz test suite" OFF)
endif()


set(OQS_OPT_TARGET auto CACHE STRING "The target microarchitecture for optimization.")

Expand All @@ -39,6 +46,16 @@ set(OQS_COMPILE_BUILD_TARGET "${CMAKE_SYSTEM_PROCESSOR}-${CMAKE_HOST_SYSTEM}")
set(OQS_MINIMAL_GCC_VERSION "7.1.0")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Determine the flags for fuzzing. Use OSS-Fuzz's configuration if available, otherwise fall back to defaults.
if(DEFINED ENV{LIB_FUZZING_ENGINE})
set(FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE})
set(FUZZING_COMPILE_FLAGS "")
set(FUZZING_LINK_FLAGS "${FUZZING_ENGINE}")
else()
set(FUZZING_COMPILE_FLAGS "-fsanitize=fuzzer,address")
set(FUZZING_LINK_FLAGS "-fsanitize=fuzzer,address")
endif()

# heuristic check to see whether we're running on a RaspberryPi
if(EXISTS "/opt/vc/include/bcm_host.h")
add_definitions( -DOQS_USE_RASPBERRY_PI )
Expand Down
21 changes: 21 additions & 0 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
let
pkgs = import <nixpkgs> {};
in
with pkgs;
stdenv.mkDerivation {
name = "clang-env-with-nightly-rust";
buildInputs = [
clang
llvmPackages.libclang
openssl
cmake
ninja
];
shellHook = ''
export LIBCLANG_PATH="${pkgs.llvmPackages.libclang}/lib";
export CC=clang;
export CXX=clang++;
export CFLAGS=-fsanitize=fuzzer-no-link,address
export LDFLAGS=-fsanitize=address
'';
}
9 changes: 9 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,15 @@ set(KEM_TESTS example_kem kat_kem test_kem test_kem_mem speed_kem vectors_kem)
add_executable(example_sig example_sig.c)
target_link_libraries(example_sig PRIVATE ${TEST_DEPS})

if(OQS_BUILD_FUZZ_TESTS)
add_executable(fuzz_test_sig fuzz_test_sig.c)
target_link_libraries(fuzz_test_sig PRIVATE ${TEST_DEPS})
set_target_properties(fuzz_test_sig PROPERTIES
COMPILE_FLAGS "${FUZZING_COMPILE_FLAGS}"
LINK_FLAGS "${FUZZING_LINK_FLAGS}"
)
endif()

# Stateful SIG API tests
add_executable(example_sig_stfl example_sig_stfl.c)
target_link_libraries(example_sig_stfl PRIVATE ${TEST_DEPS})
Expand Down
94 changes: 94 additions & 0 deletions tests/fuzz_test_sig.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* fuzz_test_sig.c
*
* Minimal fuzz test for liboqs.
*
* SPDX-License-Identifier: MIT
*/

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <oqs/oqs.h>

void cleanup_heap(uint8_t *public_key, uint8_t *secret_key,
uint8_t *signature,
OQS_SIG *sig);

static OQS_STATUS fuzz_dilithium_2(const uint8_t *message, size_t message_len) {

#ifdef OQS_ENABLE_SIG_dilithium_2

OQS_SIG *sig = NULL;
uint8_t *public_key = NULL;
uint8_t *secret_key = NULL;
uint8_t *signature = NULL;
size_t signature_len;
OQS_STATUS rc;

sig = OQS_SIG_new(OQS_SIG_alg_dilithium_2);
if (sig == NULL) {
printf("[example_heap] OQS_SIG_alg_dilithium_2 was not enabled at compile-time.\n");
return OQS_ERROR;
}

public_key = malloc(sig->length_public_key);
secret_key = malloc(sig->length_secret_key);
signature = malloc(sig->length_signature);
if ((public_key == NULL) || (secret_key == NULL) || (message == NULL) || (signature == NULL)) {
fprintf(stderr, "ERROR: malloc failed!\n");
cleanup_heap(public_key, secret_key, signature, sig);
return OQS_ERROR;
}

rc = OQS_SIG_keypair(sig, public_key, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_keypair failed!\n");
cleanup_heap(public_key, secret_key, signature, sig);
return OQS_ERROR;
}
rc = OQS_SIG_sign(sig, signature, &signature_len, message, message_len, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_sign failed!\n");
cleanup_heap(public_key, secret_key, signature, sig);
return OQS_ERROR;
}
rc = OQS_SIG_verify(sig, message, message_len, signature, signature_len, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_SIG_verify failed!\n");
cleanup_heap(public_key, secret_key, signature, sig);
return OQS_ERROR;
}

cleanup_heap(public_key, secret_key, signature, sig);
return OQS_SUCCESS; // success
#else

printf("[example_heap] OQS_SIG_dilithium_2 was not enabled at compile-time.\n");
return OQS_SUCCESS;

#endif
}

int LLVMFuzzerTestOneInput(const char* data, size_t size) {
OQS_init();
if (OQS_ERROR == fuzz_dilithium_2((const uint8_t*)data, size)) {
return -1;
}
OQS_destroy();
return 0;
}


void cleanup_heap(uint8_t *public_key, uint8_t *secret_key,
uint8_t *signature,
OQS_SIG *sig) {
if (sig != NULL) {
OQS_MEM_secure_free(secret_key, sig->length_secret_key);
}
OQS_MEM_insecure_free(public_key);
OQS_MEM_insecure_free(signature);
OQS_SIG_free(sig);
}

0 comments on commit a4c5fc5

Please sign in to comment.