From b56e848eaa40d5582e2b0242771209e0fb45b76a Mon Sep 17 00:00:00 2001 From: Christian Reitter Date: Fri, 12 Aug 2022 14:04:15 +0200 Subject: [PATCH] feat(crypto): mark uninteresting fuzzer inputs --- crypto/fuzzer/fuzzer.c | 176 +++++++++++++++++++++-------------------- 1 file changed, 91 insertions(+), 85 deletions(-) diff --git a/crypto/fuzzer/fuzzer.c b/crypto/fuzzer/fuzzer.c index d7454aa333..975200cf6d 100644 --- a/crypto/fuzzer/fuzzer.c +++ b/crypto/fuzzer/fuzzer.c @@ -144,7 +144,7 @@ int fuzz_bn_format(void) { bignum256 target_bignum; // we need some amount of initial data if (fuzzer_length < sizeof(target_bignum) + 1 + 1) { - return 0; + return -1; } #define FUZZ_BN_FORMAT_OUTPUT_BUFFER_SIZE 512 @@ -166,7 +166,7 @@ int fuzz_bn_format(void) { // check for the second half of the data if (fuzzer_length < prefixlen + suffixlen + 4 + 4 + 1 - 2) { - return 0; + return -1; } memcpy(&decimals, fuzzer_input(4), 4); memcpy(&exponent, fuzzer_input(4), 4); @@ -206,7 +206,7 @@ int fuzz_bn_format(void) { int fuzz_base32_decode(void) { if (fuzzer_length < 2 || fuzzer_length > BASE32_DECODE_MAX_INPUT_LEN) { - return 0; + return -1; } char *in_buffer = malloc(fuzzer_length); @@ -239,7 +239,7 @@ int fuzz_base32_decode(void) { int fuzz_base32_encode(void) { if (fuzzer_length > BASE32_ENCODE_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t *in_buffer = malloc(fuzzer_length); @@ -273,7 +273,7 @@ int fuzz_base32_encode(void) { int fuzz_base58_encode_check(void) { if (fuzzer_length > BASE58_ENCODE_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t *in_buffer = malloc(fuzzer_length); @@ -315,7 +315,7 @@ int fuzz_base58_encode_check(void) { int fuzz_base58_decode_check(void) { if (fuzzer_length > BASE58_DECODE_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t *in_buffer = malloc(fuzzer_length + 1); @@ -349,7 +349,7 @@ int fuzz_base58_decode_check(void) { int fuzz_xmr_base58_addr_decode_check(void) { if (fuzzer_length > XMR_BASE58_ADDR_DECODE_MAX_INPUT_LEN) { - return 0; + return -1; } // TODO no null termination used !? @@ -388,7 +388,7 @@ int fuzz_xmr_base58_addr_decode_check(void) { int fuzz_xmr_base58_decode(void) { if (fuzzer_length > XMR_BASE58_DECODE_MAX_INPUT_LEN) { - return 0; + return -1; } char *in_buffer = malloc(fuzzer_length); @@ -421,7 +421,7 @@ int fuzz_xmr_base58_addr_encode_check(void) { size_t tag_size = sizeof(tag_in); if (fuzzer_length < tag_size + 1 || fuzzer_length > XMR_BASE58_ADDR_ENCODE_MAX_INPUT_LEN) { - return 0; + return -1; } // mutate tag_in @@ -468,7 +468,7 @@ int fuzz_xmr_base58_addr_encode_check(void) { int fuzz_xmr_base58_encode(void) { if (fuzzer_length > XMR_BASE58_ENCODE_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t *in_buffer = malloc(fuzzer_length); @@ -499,7 +499,7 @@ int fuzz_xmr_serialize_varint(void) { size_t varint_in_size = sizeof(varint_in); if (fuzzer_length <= varint_in_size || fuzzer_length > XMR_SERIALIZE_VARINT_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t out_buffer[XMR_SERIALIZE_VARINT_MAX_INPUT_LEN] = {0}; @@ -535,7 +535,7 @@ int fuzz_xmr_serialize_varint(void) { int fuzz_nem_validate_address(void) { if (fuzzer_length < 1 || fuzzer_length > NEM_VALIDATE_ADDRESS_MAX_INPUT_LEN) { - return 0; + return -1; } uint8_t network = fuzzer_input(1)[0]; @@ -562,7 +562,7 @@ int fuzz_nem_get_address(void) { // TODO switch to < comparison? if (fuzzer_length != (sizeof(ed25519_public_key_fuzz) + sizeof(version))) { - return 0; + return -1; } char address[NEM_ADDRESS_SIZE + 1] = {0}; @@ -582,7 +582,7 @@ int fuzz_xmr_get_subaddress_secret_key(void) { uint32_t major = 0; uint32_t minor = 0; if (fuzzer_length != (sizeof(bignum256modm) + 2 * sizeof(uint32_t))) { - return 0; + return -1; } bignum256modm output = {0}; @@ -604,7 +604,7 @@ int fuzz_xmr_derive_private_key(void) { if (fuzzer_length != (sizeof(bignum256modm) + sizeof(ge25519) + sizeof(uint32_t))) { - return 0; + return -1; } memcpy(base, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm)); @@ -624,7 +624,7 @@ int fuzz_xmr_derive_public_key(void) { uint32_t idx = 0; if (fuzzer_length != (2 * sizeof(ge25519) + sizeof(uint32_t))) { - return 0; + return -1; } memcpy(&base, fuzzer_input(sizeof(ge25519)), sizeof(ge25519)); @@ -643,7 +643,7 @@ int fuzz_xmr_derive_public_key(void) { int fuzz_shamir_interpolate(void) { if (fuzzer_length != (2 * sizeof(uint8_t) + SHAMIR_MAX_SHARE_COUNT + SHAMIR_MAX_DATA_LEN + sizeof(size_t))) { - return 0; + return -1; } uint8_t result[SHAMIR_MAX_LEN] = {0}; @@ -690,7 +690,7 @@ int fuzz_ecdsa_sign_digest_functions(void) { uint8_t sig2[64] = {0}; uint8_t pby1, pby2 = 0; if (fuzzer_length < 1 + sizeof(priv_key) + sizeof(digest)) { - return 0; + return -1; } const ecdsa_curve *curve; @@ -751,7 +751,7 @@ int fuzz_ecdsa_verify_digest_functions(void) { uint8_t pub_key[65] = {0}; if (fuzzer_length < 1 + sizeof(hash) + sizeof(sig) + sizeof(pub_key)) { - return 0; + return -1; } memcpy(&curve_decider, fuzzer_input(1), 1); @@ -797,7 +797,7 @@ int fuzz_word_index(void) { #define MAX_WORD_LENGTH 12 if (fuzzer_length < MAX_WORD_LENGTH) { - return 0; + return -1; } char word[MAX_WORD_LENGTH + 1] = {0}; @@ -812,7 +812,7 @@ int fuzz_word_index(void) { int fuzz_slip39_word_completion_mask(void) { if (fuzzer_length != 2) { - return 0; + return -1; } uint16_t sequence = (fuzzer_ptr[0] << 8) + fuzzer_ptr[1]; fuzzer_input(2); @@ -826,7 +826,7 @@ int fuzz_slip39_word_completion_mask(void) { #define MAX_MNEMONIC_FUZZ_LENGTH 256 int fuzz_mnemonic_check(void) { if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH) { - return 0; + return -1; } char mnemonic[MAX_MNEMONIC_FUZZ_LENGTH + 1] = {0}; @@ -848,7 +848,7 @@ int fuzz_mnemonic_check(void) { int fuzz_mnemonic_from_data(void) { if (fuzzer_length < 16 || fuzzer_length > 32) { - return 0; + return -1; } const char *mnemo_result = mnemonic_from_data(fuzzer_ptr, fuzzer_length); @@ -873,7 +873,7 @@ int fuzz_mnemonic_from_data(void) { #define MAX_PASSPHRASE_FUZZ_LENGTH 257 int fuzz_mnemonic_to_seed(void) { if (fuzzer_length < MAX_MNEMONIC_FUZZ_LENGTH + MAX_PASSPHRASE_FUZZ_LENGTH) { - return 0; + return -1; } char mnemonic[MAX_PASSPHRASE_FUZZ_LENGTH + 1] = {0}; @@ -897,7 +897,7 @@ int fuzz_ethereum_address_checksum(void) { bool rskip60 = false; if (fuzzer_length < sizeof(addr) + sizeof(address) + sizeof(chain_id) + 1) { - return 0; + return -1; } memcpy(addr, fuzzer_input(sizeof(addr)), sizeof(addr)); @@ -913,7 +913,7 @@ int fuzz_ethereum_address_checksum(void) { int fuzz_aes(void) { if (fuzzer_length < 1 + 16 + 16 + 32) { - return 0; + return -1; } aes_encrypt_ctx ctxe; @@ -991,7 +991,7 @@ int fuzz_chacha_drbg(void) { if (fuzzer_length < CHACHA_DRBG_ENTROPY_LENGTH + CHACHA_DRBG_RESEED_LENGTH + CHACHA_DRBG_NONCE_LENGTH) { - return 0; + return -1; } uint8_t entropy[CHACHA_DRBG_ENTROPY_LENGTH] = {0}; @@ -1026,7 +1026,7 @@ int fuzz_ed25519_sign_verify(void) { if (fuzzer_length < sizeof(secret_key) + sizeof(signature) + sizeof(message)) { - return 0; + return -1; } memcpy(&secret_key, fuzzer_input(sizeof(secret_key)), sizeof(secret_key)); @@ -1058,7 +1058,7 @@ int fuzz_zkp_bip340_sign_digest(void) { if (fuzzer_length < sizeof(priv_key) + sizeof(aux_input) + sizeof(digest) + sizeof(sig)) { - return 0; + return -1; } memcpy(priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key)); memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest)); @@ -1085,7 +1085,7 @@ int fuzz_zkp_bip340_verify_digest(void) { uint8_t sig[64] = {0}; if (fuzzer_length < sizeof(digest) + sizeof(pub_key) + sizeof(sig)) { - return 0; + return -1; } memcpy(pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key)); memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest)); @@ -1111,7 +1111,7 @@ int fuzz_zkp_bip340_tweak_keys(void) { if (fuzzer_length < sizeof(internal_priv) + sizeof(root_hash) + sizeof(internal_pub)) { - return 0; + return -1; } memcpy(internal_priv, fuzzer_input(sizeof(internal_priv)), sizeof(internal_priv)); @@ -1137,7 +1137,7 @@ int fuzz_ecdsa_get_public_key_functions(void) { const ecdsa_curve *curve = &secp256k1; if (fuzzer_length < sizeof(privkey)) { - return 0; + return -1; } memcpy(privkey, fuzzer_input(sizeof(privkey)), sizeof(privkey)); @@ -1181,7 +1181,7 @@ int fuzz_ecdsa_recover_pub_from_sig_functions(void) { uint8_t pubkey2[65] = {0}; if (fuzzer_length < sizeof(digest) + sizeof(sig) + sizeof(recid)) { - return 0; + return -1; } memcpy(digest, fuzzer_input(sizeof(digest)), sizeof(digest)); memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig)); @@ -1216,7 +1216,7 @@ int fuzz_ecdsa_sig_from_der(void) { uint8_t out[72] = {0}; if (fuzzer_length < sizeof(der)) { - return 0; + return -1; } memcpy(der, fuzzer_input(sizeof(der)), sizeof(der)); // null-terminate @@ -1236,7 +1236,7 @@ int fuzz_ecdsa_sig_to_der(void) { uint8_t der[72] = {0}; if (fuzzer_length < sizeof(sig)) { - return 0; + return -1; } memcpy(sig, fuzzer_input(sizeof(sig)), sizeof(sig)); @@ -1247,24 +1247,24 @@ int fuzz_ecdsa_sig_to_der(void) { return 0; } -void fuzz_button_sequence_to_word(void) { +int fuzz_button_sequence_to_word(void) { uint16_t input = 0; if (fuzzer_length < sizeof(input)) { - return; + return -1; } memcpy(&input, fuzzer_input(sizeof(input)), sizeof(input)); button_sequence_to_word(input); - return; + return 0; } -void fuzz_xmr_add_keys(void) { +int fuzz_xmr_add_keys(void) { bignum256modm a, b; ge25519 A, B; if (fuzzer_length < sizeof(bignum256modm) * 2 + sizeof(ge25519) * 2 ) { - return; + return -1; } memcpy(&a, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm)); memcpy(&b, fuzzer_input(sizeof(bignum256modm)), sizeof(bignum256modm)); @@ -1285,17 +1285,17 @@ void fuzz_xmr_add_keys(void) { xmr_add_keys3_vartime(&r, a, &A, b, &B); check_msan(&r, sizeof(r)); - return; + return 0; } -void fuzz_ecdh_multiply(void) { +int fuzz_ecdh_multiply(void) { uint8_t priv_key[32]; // 33 or 65 bytes content uint8_t pub_key[65]; uint8_t decider; if (fuzzer_length < sizeof(priv_key) + sizeof(pub_key) + sizeof(decider)) { - return; + return -1; } memcpy(&priv_key, fuzzer_input(sizeof(priv_key)), sizeof(priv_key)); memcpy(&pub_key, fuzzer_input(sizeof(pub_key)), sizeof(pub_key)); @@ -1322,7 +1322,7 @@ void fuzz_ecdh_multiply(void) { // failure case } - return; + return 0; } void zkp_initialize_context_or_crash(void) { @@ -1341,7 +1341,7 @@ void zkp_initialize_context_or_crash(void) { int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // reject input that is too short if (size < META_HEADER_SIZE) { - return 0; + return -1; } fuzzer_reset_state(); @@ -1362,142 +1362,148 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { // this is helpful for directing the fuzzing focus on a specific case #ifdef FUZZER_EXCLUSIVE_TARGET if (target_decision != FUZZER_EXCLUSIVE_TARGET) { - return 0; + return -1; } #endif + // recent libFuzzer implementations support marking inputs as non-interesting + // via return -1; instead of the regular return 0; + // see https://github.com/llvm/llvm-project/commit/92fb310151d2b1e349695fc0f1c5d5d50afb3b52 + int target_result = 0; + // TODO reorder and regroup target functions switch (target_decision) { case 0: - fuzz_bn_format(); + target_result = fuzz_bn_format(); break; case 1: - fuzz_base32_decode(); + target_result = fuzz_base32_decode(); break; case 2: - fuzz_base32_encode(); + target_result = fuzz_base32_encode(); break; case 3: - fuzz_base58_encode_check(); + target_result = fuzz_base58_encode_check(); break; case 4: - fuzz_base58_decode_check(); + target_result = fuzz_base58_decode_check(); break; case 5: - fuzz_xmr_base58_addr_decode_check(); + target_result = fuzz_xmr_base58_addr_decode_check(); break; case 6: - fuzz_xmr_base58_addr_encode_check(); + target_result = fuzz_xmr_base58_addr_encode_check(); break; case 7: - fuzz_xmr_serialize_varint(); + target_result = fuzz_xmr_serialize_varint(); break; case 8: - fuzz_nem_validate_address(); + target_result = fuzz_nem_validate_address(); break; case 9: - fuzz_nem_get_address(); + target_result = fuzz_nem_get_address(); break; case 10: - fuzz_xmr_get_subaddress_secret_key(); + target_result = fuzz_xmr_get_subaddress_secret_key(); break; case 11: - fuzz_xmr_derive_private_key(); + target_result = fuzz_xmr_derive_private_key(); break; case 12: - fuzz_xmr_derive_public_key(); + target_result = fuzz_xmr_derive_public_key(); break; case 13: - fuzz_shamir_interpolate(); + target_result = fuzz_shamir_interpolate(); break; case 14: #ifdef FUZZ_ALLOW_SLOW zkp_initialize_context_or_crash(); // slow through expensive bignum operations - fuzz_ecdsa_verify_digest_functions(); + target_result = fuzz_ecdsa_verify_digest_functions(); #endif break; case 15: - fuzz_word_index(); + target_result = fuzz_word_index(); break; case 16: - fuzz_slip39_word_completion_mask(); + target_result = fuzz_slip39_word_completion_mask(); break; case 17: - fuzz_mnemonic_check(); + target_result = fuzz_mnemonic_check(); break; case 18: #ifdef FUZZ_ALLOW_SLOW - fuzz_aes(); + target_result = fuzz_aes(); #endif break; case 22: - fuzz_chacha_drbg(); + target_result = fuzz_chacha_drbg(); break; case 23: #ifdef FUZZ_ALLOW_SLOW zkp_initialize_context_or_crash(); // slow through expensive bignum operations - fuzz_ecdsa_sign_digest_functions(); + target_result = fuzz_ecdsa_sign_digest_functions(); #endif break; case 24: - fuzz_ed25519_sign_verify(); + target_result = fuzz_ed25519_sign_verify(); break; case 25: - fuzz_mnemonic_from_data(); + target_result = fuzz_mnemonic_from_data(); break; case 26: - fuzz_mnemonic_to_seed(); + target_result = fuzz_mnemonic_to_seed(); break; case 27: - fuzz_button_sequence_to_word(); + target_result = fuzz_button_sequence_to_word(); break; case 30: - fuzz_ethereum_address_checksum(); + target_result = fuzz_ethereum_address_checksum(); break; case 41: zkp_initialize_context_or_crash(); - fuzz_zkp_bip340_sign_digest(); + target_result = fuzz_zkp_bip340_sign_digest(); break; case 42: zkp_initialize_context_or_crash(); - fuzz_zkp_bip340_verify_digest(); + target_result = fuzz_zkp_bip340_verify_digest(); break; case 43: zkp_initialize_context_or_crash(); - fuzz_zkp_bip340_tweak_keys(); + target_result = fuzz_zkp_bip340_tweak_keys(); break; case 50: zkp_initialize_context_or_crash(); - fuzz_ecdsa_get_public_key_functions(); + target_result = fuzz_ecdsa_get_public_key_functions(); break; case 51: zkp_initialize_context_or_crash(); - fuzz_ecdsa_recover_pub_from_sig_functions(); + target_result = fuzz_ecdsa_recover_pub_from_sig_functions(); break; case 52: - fuzz_ecdsa_sig_from_der(); + target_result = fuzz_ecdsa_sig_from_der(); break; case 53: - fuzz_ecdsa_sig_to_der(); + target_result = fuzz_ecdsa_sig_to_der(); break; case 60: - fuzz_xmr_base58_encode(); + target_result = fuzz_xmr_base58_encode(); break; case 61: - fuzz_xmr_base58_decode(); + target_result = fuzz_xmr_base58_decode(); break; case 63: - fuzz_xmr_add_keys(); + target_result = fuzz_xmr_add_keys(); break; case 64: - fuzz_ecdh_multiply(); + target_result = fuzz_ecdh_multiply(); break; default: - // do nothing + // mark as uninteresting input + return -1; break; } - return 0; + return target_result; }