#include "fuzz.h" #define MODULE_NAME "Type1 Read/Write" enum { SUB_TYPE_PRESENCE_CHECK, SUB_TYPE_RID, SUB_TYPE_READ_ALL, SUB_TYPE_READ, SUB_TYPE_WRITE_ERASE, SUB_TYPE_WRITE_NO_ERASE, SUB_TYPE_READ_SEG, SUB_TYPE_READ_8, SUB_TYPE_WRITE_ERASE_8, SUB_TYPE_WRITE_NO_ERASE_8, SUB_TYPE_FORMAT_NDEF, SUB_TYPE_LOCATE_TLV, SUB_TYPE_READ_NDEF, SUB_TYPE_WRITE_NDEF, SUB_TYPE_SET_READONLY, SUB_TYPE_MAX }; static void rw_cback(tRW_EVENT event, tRW_DATA* p_rw_data) { FUZZLOG(MODULE_NAME ": rw_cback: event=0x%02x, p_rw_data=%p", event, p_rw_data); if (event == RW_T1T_RAW_FRAME_EVT || event == RW_T1T_RID_EVT || event == RW_T1T_RALL_CPLT_EVT || event == RW_T1T_READ_CPLT_EVT || event == RW_T1T_RSEG_CPLT_EVT || event == RW_T1T_READ8_CPLT_EVT) { if (p_rw_data->data.p_data) { GKI_freebuf(p_rw_data->data.p_data); p_rw_data->data.p_data = nullptr; } } } #define TEST_NFCID_VALUE \ { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 } static bool Init(Fuzz_Context& /*ctx*/) { tNFC_ACTIVATE_DEVT activate_params = { .protocol = NFC_PROTOCOL_T1T, .rf_tech_param = {.mode = NFC_DISCOVERY_TYPE_POLL_A, .param = {.pa = { .hr = {T1T_NDEF_SUPPORTED, 0x01}, .nfcid1 = TEST_NFCID_VALUE, }}}}; rw_init(); if (NFC_STATUS_OK != RW_SetActivatedTagType(&activate_params, rw_cback)) { FUZZLOG(MODULE_NAME ": RW_SetActivatedTagType failed"); return false; } return true; } static bool Init_PresenceCheck(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tPresenceCheck(); } static bool Init_Rid(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tRid(); } static bool Init_ReadAll(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tReadAll(); } static bool Init_Read(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tRead(0, 0x10); } static bool Init_WriteErase(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tWriteErase(0, 0x10, 0x20); } static bool Init_WriteNoErase(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tWriteNoErase(0, 0x10, 0x20); } static bool Init_ReadSeg(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tReadSeg(0); } static bool Init_Read8(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tRead8(0); } static bool Init_WriteErase8(Fuzz_Context& ctx) { const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}; auto scratch = ctx.GetBuffer(sizeof(data), data); return NFC_STATUS_OK == RW_T1tWriteErase8(0, scratch); } static bool Init_WriteNoErase8(Fuzz_Context& ctx) { const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}; auto scratch = ctx.GetBuffer(sizeof(data), data); return NFC_STATUS_OK == RW_T1tWriteNoErase8(0, scratch); } static bool Init_FormatNdef(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tFormatNDef(); } static bool Init_LocateTlv(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tLocateTlv(TAG_NDEF_TLV); } static bool Init_ReadNdef(Fuzz_Context& ctx) { tRW_T1T_CB* p_t1t = &rw_cb.tcb.t1t; p_t1t->tag_attribute = RW_T1_TAG_ATTRB_READ_WRITE; p_t1t->ndef_msg_len = 256; auto scratch = ctx.GetBuffer(4096); return NFC_STATUS_OK == RW_T1tReadNDef(scratch, 4096); } static bool Init_WriteNdef(Fuzz_Context& ctx) { const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04}; auto scratch = ctx.GetBuffer(sizeof(data), data); return NFC_STATUS_OK == RW_T1tWriteNDef(sizeof(data), scratch); } static bool Init_SetReadOnly(Fuzz_Context& /*ctx*/) { return NFC_STATUS_OK == RW_T1tSetTagReadOnly(true); } static bool Fuzz_Init(Fuzz_Context& ctx) { if (!Init(ctx)) { FUZZLOG(MODULE_NAME ": initialization failed"); return false; } bool result = false; switch (ctx.SubType) { case SUB_TYPE_PRESENCE_CHECK: result = Init_PresenceCheck(ctx); break; case SUB_TYPE_RID: result = Init_Rid(ctx); break; case SUB_TYPE_READ_ALL: result = Init_ReadAll(ctx); break; case SUB_TYPE_READ: result = Init_Read(ctx); break; case SUB_TYPE_WRITE_ERASE: result = Init_WriteErase(ctx); break; case SUB_TYPE_WRITE_NO_ERASE: result = Init_WriteNoErase(ctx); break; case SUB_TYPE_READ_SEG: result = Init_ReadSeg(ctx); break; case SUB_TYPE_READ_8: result = Init_Read8(ctx); break; case SUB_TYPE_WRITE_ERASE_8: result = Init_WriteErase8(ctx); break; case SUB_TYPE_WRITE_NO_ERASE_8: result = Init_WriteNoErase8(ctx); break; case SUB_TYPE_FORMAT_NDEF: result = Init_FormatNdef(ctx); break; case SUB_TYPE_LOCATE_TLV: result = Init_LocateTlv(ctx); break; case SUB_TYPE_READ_NDEF: result = Init_ReadNdef(ctx); break; case SUB_TYPE_WRITE_NDEF: result = Init_WriteNdef(ctx); break; case SUB_TYPE_SET_READONLY: result = Init_SetReadOnly(ctx); break; default: FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType); result = false; break; } if (!result) { FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType); } return result; } static void Fuzz_Deinit(Fuzz_Context& /*ctx*/) { if (rf_cback) { tNFC_CONN conn = { .deactivate = {.status = NFC_STATUS_OK, .type = NFC_DEACTIVATE_TYPE_IDLE, .is_ntf = true, .reason = NFC_DEACTIVATE_REASON_DH_REQ_FAILED}}; rf_cback(NFC_RF_CONN_ID, NFC_DEACTIVATE_CEVT, &conn); } } static void Fuzz_Run(Fuzz_Context& ctx) { for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) { NFC_HDR* p_msg; p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size()); if (p_msg == nullptr || it->size() < 1) { FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size()); return; } /* Initialize NFC_HDR */ p_msg->len = it->size() - 1; p_msg->offset = 0; uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset; memcpy(p, it->data(), it->size()); tNFC_CONN conn = {.data = { .status = NFC_STATUS_OK, .p_data = p_msg, }}; FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zd]=%s", ctx.SubType, it - ctx.Data.cbegin(), ctx.Data.size() - 1, BytesToHex(*it).c_str()); rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn); } } void Type1_FixPackets(uint8_t /*SubType*/, std::vector<bytes_t>& /*Data*/) {} void Type1_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Data) { Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Data); if (Fuzz_Init(ctx)) { Fuzz_Run(ctx); } Fuzz_Deinit(ctx); }