MONGOCRYPT-834 fuzzing for oss-fuzz#1152
Conversation
There was a problem hiding this comment.
How were these binary files generated? Consider documenting in a new doc/fuzzing.md to describe how we can regenerate these if needed.
There was a problem hiding this comment.
Though it may not be strictly needed for OSS-Fuzz, suggest adding a CMake target to help test locally:
option (ENABLE_FUZZING "Build fuzzing targets. Requires a compiler supporting -fsanitize=fuzzer." OFF)
# ...
if (ENABLE_FUZZING)
include (CheckCCompilerFlag)
check_c_compiler_flag ("-fsanitize=fuzzer" COMPILER_SUPPORTS_FUZZER)
if (NOT COMPILER_SUPPORTS_FUZZER)
message (FATAL_ERROR
"ENABLE_FUZZING is ON but the compiler does not support -fsanitize=fuzzer. "
)
endif ()
add_executable (fuzz_mongocrypt EXCLUDE_FROM_ALL test/fuzz_mongocrypt.c)
target_include_directories (fuzz_mongocrypt PRIVATE ./src)
target_link_libraries (fuzz_mongocrypt PRIVATE mongocrypt_static _mongocrypt::libbson_for_static)
target_compile_options (fuzz_mongocrypt PRIVATE -fsanitize=fuzzer)
target_link_options (fuzz_mongocrypt PRIVATE -fsanitize=fuzzer)
endif ()Tip: I can run this locally on macOS by using the compilers included in brew install llvm:
cmake \
-DCMAKE_C_COMPILER="/opt/homebrew/opt/llvm/bin/clang" \
-DCMAKE_CXX_COMPILER="/opt/homebrew/opt/llvm/bin/clang++" \
-DENABLE_FUZZING=ON \
-Bcmake-build| /* Set up key encryption key for local provider. */ | ||
| uint8_t kek_bson[] = { | ||
| /* {"provider": "local"} as BSON */ | ||
| 0x1b, 0x00, 0x00, 0x00, /* doc len = 27 */ |
There was a problem hiding this comment.
| 0x1b, 0x00, 0x00, 0x00, /* doc len = 27 */ | |
| 0x19, 0x00, 0x00, 0x00, /* doc len = 27 */ |
Careful. Length appears incorrect. Contents can be checked with PyMongo using bson.decode:
bson.decode(bytearray([
0x19, 0x00, 0x00, 0x00,
0x02,
ord('p'), ord('r'), ord('o'), ord('v'), ord('i'), ord('d'), ord('e'), ord('r'), 0x00,
0x06, 0x00, 0x00, 0x00,
ord('l'), ord('o'), ord('c'), ord('a'), ord('l'), 0x00,
0x00
]))
# {'provider': 'local'}| 0x1b, 0x00, 0x00, 0x00, /* doc len = 27 */ | ||
| 0x02, /* type: string */ | ||
| 'p', 'r', 'o', 'v', 'i', 'd', 'e', 'r', 0x00, /* key */ | ||
| 0x06, 0x00, 0x00, 0x00, /* string len = 6 */ |
There was a problem hiding this comment.
Suggest running file through clang-format to align comments.
| mongocrypt_ctx_setopt_key_id(ctx, kid_bin); | ||
| mongocrypt_binary_destroy(kid_bin); | ||
| } | ||
| mongocrypt_ctx_setopt_algorithm(ctx, "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic", -1); |
There was a problem hiding this comment.
Set algorithm and queryType to "range".
I expect the call to mongocrypt_ctx_explicit_encrypt_expression_init always fails. Encrypt expression requires algorithm and queryType both be set to range.
libmongocrypt checks the queryType for encryptExpression is "range" (1) and later that queryType matches algorithm (2).
Background
Libmongocrypt will be added to OSS-Fuzz for continuous fuzz testing. On our end we only have to provide the fuzzing entry point:
LLVMFuzzerTestOneInputwhich is linked into the fuzzing binary.Design
The fuzzing engine which accepts binary inputs uses the first byte to decide on the target state. It provides some defaults (local encryption keys, etc.) until the state machine is ready to accept input and feeds the fuzzer generated data. A corpus of starting data derived from test inputs improves fuzzing efficiency.
Coverage
The fuzzing added here covers 14.33% of libmongocrypt's functions.