diff --git a/fuzzing/extra/nfc_ndef.cmake b/fuzzing/extra/nfc_ndef.cmake new file mode 100644 index 000000000..c6770fc3d --- /dev/null +++ b/fuzzing/extra/nfc_ndef.cmake @@ -0,0 +1,11 @@ +include_guard() + +add_executable(fuzz_nfc_ndef + ${BOLOS_SDK}/fuzzing/harness/fuzzer_nfc_ndef.c + ${BOLOS_SDK}/lib_nfc/src/nfc_ndef.c) +target_compile_options(fuzz_nfc_ndef PUBLIC ${COMPILATION_FLAGS}) +target_link_options(fuzz_nfc_ndef PUBLIC ${LINK_FLAGS}) +target_compile_definitions(fuzz_nfc_ndef PUBLIC HAVE_NFC HAVE_NDEF_SUPPORT) +target_include_directories(fuzz_nfc_ndef PUBLIC "${BOLOS_SDK}/include/" + "${BOLOS_SDK}/lib_nfc/include/") +target_link_libraries(fuzz_nfc_ndef PUBLIC nbgl_shared) diff --git a/fuzzing/harness/fuzzer_nfc_ndef.c b/fuzzing/harness/fuzzer_nfc_ndef.c new file mode 100644 index 000000000..50c49a14a --- /dev/null +++ b/fuzzing/harness/fuzzer_nfc_ndef.c @@ -0,0 +1,32 @@ +#include +#include +#include +#include + +#include "nfc_ndef.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + ndef_struct_t parsed; + char out_string[NFC_NDEF_MAX_SIZE + 1]; + uint8_t *in_buffer; + + if (size == 0) { + return 0; + } + + in_buffer = (uint8_t *) malloc(size); + if (in_buffer == NULL) { + return 0; + } + + memset(&parsed, 0, sizeof(parsed)); + memset(out_string, 0, sizeof(out_string)); + memcpy(in_buffer, data, size); + + os_parse_ndef(in_buffer, (uint16_t) size, &parsed); + os_ndef_to_string(&parsed, out_string); + free(in_buffer); + + return 0; +} diff --git a/lib_nfc/include/nfc_ndef.h b/lib_nfc/include/nfc_ndef.h index b3c176a84..3f43c8180 100644 --- a/lib_nfc/include/nfc_ndef.h +++ b/lib_nfc/include/nfc_ndef.h @@ -110,7 +110,7 @@ typedef struct __attribute__((packed)) ndef_struct_s { * GLOBAL PROTOTYPES **********************/ uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header); -uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed); +uint8_t os_parse_ndef(uint8_t *in_buffer, uint16_t in_buffer_length, ndef_struct_t *parsed); uint16_t os_ndef_to_string(ndef_struct_t *ndef_message, char *out_string); #endif diff --git a/lib_nfc/src/nfc_ndef.c b/lib_nfc/src/nfc_ndef.c index 6e3eca6a7..b902164ef 100644 --- a/lib_nfc/src/nfc_ndef.c +++ b/lib_nfc/src/nfc_ndef.c @@ -134,24 +134,43 @@ uint16_t os_get_uri_header(uint8_t uri_id, char *uri_header) * @brief deserializes an encoded NDEF message to an ndef_struct_t * * @param in_buffer input buffer to deseialize + * @param in_buffer_length input buffer length * @param parsed deserialized output * @return bolos error */ -uint8_t os_parse_ndef(uint8_t *in_buffer, ndef_struct_t *parsed) +uint8_t os_parse_ndef(uint8_t *in_buffer, uint16_t in_buffer_length, ndef_struct_t *parsed) { uint8_t text_length, info_length; + + if (in_buffer == NULL || parsed == NULL) { + return 1; + } + if (in_buffer_length <= APDU_OFF_DATA) { + return 1; + } + parsed->ndef_type = in_buffer[APDU_OFF_P1]; parsed->uri_id = in_buffer[APDU_OFF_P2]; text_length = in_buffer[APDU_OFF_DATA]; if (text_length > NFC_TEXT_MAX_LEN) { return 1; } + + if (in_buffer_length < (uint16_t) (APDU_OFF_DATA + 1 + text_length + 1)) { + return 1; + } + memcpy(parsed->text, &in_buffer[APDU_OFF_DATA + 1], text_length); parsed->text[text_length] = '\0'; info_length = in_buffer[APDU_OFF_DATA + 1 + text_length]; if (info_length > NFC_INFO_MAX_LEN) { return 1; } + + if (in_buffer_length < (uint16_t) (APDU_OFF_DATA + 1 + text_length + 1 + info_length)) { + return 1; + } + if (info_length) { memcpy(parsed->info, &in_buffer[APDU_OFF_DATA + 1 + text_length + 1], info_length); parsed->info[info_length] = '\0';