1 #include "fuzz.h"
2 
3 #define MODULE_NAME "Type4 Read/Write"
4 
5 enum {
6   SUB_TYPE_DETECT_NDEF,
7   SUB_TYPE_READ_NDEF,
8   SUB_TYPE_UPDATE_NDEF,
9   SUB_TYPE_PRESENCE_CHECK,
10   SUB_TYPE_SET_READ_ONLY,
11   SUB_TYPE_FORMAT_NDEF,
12 
13   SUB_TYPE_MAX
14 };
15 
rw_cback(tRW_EVENT event,tRW_DATA * p_rw_data)16 static void rw_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
17   FUZZLOG(MODULE_NAME ": rw_cback: event=0x%02x, p_rw_data=%p", event,
18           p_rw_data);
19 
20   if (event == RW_T4T_RAW_FRAME_EVT) {
21     if (p_rw_data->raw_frame.p_data) {
22       GKI_freebuf(p_rw_data->raw_frame.p_data);
23       p_rw_data->raw_frame.p_data = nullptr;
24     }
25   } else if (event == RW_T4T_NDEF_READ_EVT ||
26              event == RW_T4T_NDEF_READ_CPLT_EVT) {
27     if (p_rw_data->data.p_data) {
28       GKI_freebuf(p_rw_data->data.p_data);
29       p_rw_data->data.p_data = nullptr;
30     }
31   }
32 }
33 
34 #define TEST_NFCID_VALUE \
35   { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }
36 
Init(Fuzz_Context &)37 static bool Init(Fuzz_Context& /*ctx*/) {
38   tNFC_ACTIVATE_DEVT activate_params = {.protocol = NFC_PROTOCOL_ISO_DEP,
39                                         .rf_tech_param = {
40                                             .mode = NFC_DISCOVERY_TYPE_POLL_A,
41                                         }};
42 
43   rw_init();
44   if (NFC_STATUS_OK != RW_SetActivatedTagType(&activate_params, rw_cback)) {
45     FUZZLOG(MODULE_NAME ": RW_SetActivatedTagType failed");
46     return false;
47   }
48 
49   return true;
50 }
51 
Init_PresenceCheck(Fuzz_Context &)52 static bool Init_PresenceCheck(Fuzz_Context& /*ctx*/) {
53   return NFC_STATUS_OK == RW_T4tPresenceCheck(1);
54 }
55 
Init_DetectNDef(Fuzz_Context &)56 static bool Init_DetectNDef(Fuzz_Context& /*ctx*/) {
57   return NFC_STATUS_OK == RW_T4tDetectNDef();
58 }
59 
Init_ReadNDef(Fuzz_Context &)60 static bool Init_ReadNDef(Fuzz_Context& /*ctx*/) {
61   return NFC_STATUS_OK == RW_T4tReadNDef();
62 }
63 
Init_UpdateNDef(Fuzz_Context & ctx)64 static bool Init_UpdateNDef(Fuzz_Context& ctx) {
65   const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
66                           0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
67 
68   auto scratch = ctx.GetBuffer(sizeof(data), data);
69   return NFC_STATUS_OK == RW_T4tUpdateNDef(sizeof(data), scratch);
70 }
71 
Init_FormatNDef(Fuzz_Context &)72 static bool Init_FormatNDef(Fuzz_Context& /*ctx*/) {
73   return NFC_STATUS_OK == RW_T4tFormatNDef();
74 }
75 
Init_SetNDefReadOnly(Fuzz_Context &)76 static bool Init_SetNDefReadOnly(Fuzz_Context& /*ctx*/) {
77   return NFC_STATUS_OK == RW_T4tSetNDefReadOnly();
78 }
79 
Fuzz_Init(Fuzz_Context & ctx)80 static bool Fuzz_Init(Fuzz_Context& ctx) {
81   if (!Init(ctx)) {
82     FUZZLOG(MODULE_NAME ": initialization failed");
83     return false;
84   }
85 
86   bool result = false;
87   switch (ctx.SubType) {
88     case SUB_TYPE_DETECT_NDEF:
89       result = Init_DetectNDef(ctx);
90       break;
91     case SUB_TYPE_UPDATE_NDEF:
92       result = Init_UpdateNDef(ctx);
93       break;
94     case SUB_TYPE_PRESENCE_CHECK:
95       result = Init_PresenceCheck(ctx);
96       break;
97     case SUB_TYPE_READ_NDEF:
98       result = Init_ReadNDef(ctx);
99       break;
100     case SUB_TYPE_FORMAT_NDEF:
101       result = Init_FormatNDef(ctx);
102       break;
103     case SUB_TYPE_SET_READ_ONLY:
104       result = Init_SetNDefReadOnly(ctx);
105       break;
106     default:
107       FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType);
108       result = false;
109       break;
110   }
111 
112   if (!result) {
113     FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType);
114   }
115 
116   return result;
117 }
118 
Fuzz_Deinit(Fuzz_Context &)119 static void Fuzz_Deinit(Fuzz_Context& /*ctx*/) {
120   if (rf_cback) {
121     tNFC_CONN conn = {
122         .deactivate = {.status = NFC_STATUS_OK,
123                        .type = NFC_DEACTIVATE_TYPE_IDLE,
124                        .is_ntf = true,
125                        .reason = NFC_DEACTIVATE_REASON_DH_REQ_FAILED}};
126 
127     rf_cback(NFC_RF_CONN_ID, NFC_DEACTIVATE_CEVT, &conn);
128   }
129 }
130 
Fuzz_Run(Fuzz_Context & ctx)131 static void Fuzz_Run(Fuzz_Context& ctx) {
132   for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
133     NFC_HDR* p_msg;
134     p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
135     if (p_msg == nullptr) {
136       FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
137       return;
138     }
139 
140     /* Initialize NFC_HDR */
141     p_msg->len = it->size();
142     p_msg->offset = 0;
143 
144     uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
145     memcpy(p, it->data(), it->size());
146 
147     tNFC_CONN conn = {.data = {
148                           .status = NFC_STATUS_OK,
149                           .p_data = p_msg,
150                       }};
151 
152     FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zd]=%s", ctx.SubType,
153             it - ctx.Data.cbegin(), ctx.Data.size() - 1,
154             BytesToHex(*it).c_str());
155 
156     rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
157   }
158 }
159 
Type4_FixPackets(uint8_t,std::vector<bytes_t> &)160 void Type4_FixPackets(uint8_t /*SubType*/, std::vector<bytes_t>& /*Data*/) {}
161 
Type4_Fuzz(uint8_t SubType,const std::vector<bytes_t> & Data)162 void Type4_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Data) {
163   Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Data);
164   if (Fuzz_Init(ctx)) {
165     Fuzz_Run(ctx);
166   }
167 
168   Fuzz_Deinit(ctx);
169 }
170