1 #include "fuzz.h"
2 
3 #define MODULE_NAME "Type3 Read/Write"
4 
5 enum {
6   SUB_TYPE_CHECK_NDEF,
7   SUB_TYPE_UPDATE_NDEF,
8   SUB_TYPE_CHECK,
9   SUB_TYPE_UPDATE,
10   SUB_TYPE_SEND_RAW_FRAME,
11 
12   SUB_TYPE_NCI_CMD_FIRST,
13   SUB_TYPE_DETECT_NDEF = SUB_TYPE_NCI_CMD_FIRST,
14   SUB_TYPE_PRESENCE_CHECK,
15   SUB_TYPE_POLL,
16   SUB_TYPE_GET_SYSTEM_CODES,
17   SUB_TYPE_FORMAT_NDEF,
18   SUB_TYPE_SET_READ_ONLY_SOFT,
19   SUB_TYPE_SET_READ_ONLY_HARD,
20 
21   SUB_TYPE_MAX
22 };
23 
24 // The following definition are copied from rw_t3t.cc
25 // ============================================================================
26 
27 /* Default NDEF attribute information block (used when formatting Felica-Lite
28  * tags) */
29 /* NBr (max block reads per cmd)*/
30 #define RW_T3T_DEFAULT_FELICALITE_NBR 4
31 /* NBw (max block write per cmd)*/
32 #define RW_T3T_DEFAULT_FELICALITE_NBW 1
33 #define RW_T3T_DEFAULT_FELICALITE_NMAXB (T3T_FELICALITE_NMAXB)
34 #define RW_T3T_DEFAULT_FELICALITE_ATTRIB_INFO_CHECKSUM                       \
35   ((T3T_MSG_NDEF_VERSION + RW_T3T_DEFAULT_FELICALITE_NBR +                   \
36     RW_T3T_DEFAULT_FELICALITE_NBW + (RW_T3T_DEFAULT_FELICALITE_NMAXB >> 8) + \
37     (RW_T3T_DEFAULT_FELICALITE_NMAXB & 0xFF) + T3T_MSG_NDEF_WRITEF_OFF +     \
38     T3T_MSG_NDEF_RWFLAG_RW) &                                                \
39    0xFFFF)
40 // ============================================================================
41 
rw_cback(tRW_EVENT event,tRW_DATA * p_rw_data)42 static void rw_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
43   FUZZLOG(MODULE_NAME ": rw_cback: event=0x%02x, p_rw_data=%p", event,
44           p_rw_data);
45 
46   if (event == RW_T3T_RAW_FRAME_EVT) {
47     if (p_rw_data->data.p_data) {
48       GKI_freebuf(p_rw_data->data.p_data);
49       p_rw_data->data.p_data = nullptr;
50     }
51   }
52 }
53 
54 #define TEST_NFCID_VALUE \
55   { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }
56 const uint8_t TEST_NFCID[] = TEST_NFCID_VALUE;
57 
Init(Fuzz_Context &)58 static bool Init(Fuzz_Context& /*ctx*/) {
59   tNFC_ACTIVATE_DEVT activate_params = {
60       .protocol = NFC_PROTOCOL_T3T,
61       .rf_tech_param = {.mode = NFC_DISCOVERY_TYPE_POLL_F,
62                         .param = {.pf = {
63                                       .nfcid2 = TEST_NFCID_VALUE,
64                                       .bit_rate = NFC_BIT_RATE_212,
65                                       .sensf_res_len = NFC_MAX_SENSF_RES_LEN,
66                                       .mrti_check = 1,
67                                       .mrti_update = 1,
68                                   }}}};
69 
70   rw_init();
71   if (NFC_STATUS_OK != RW_SetActivatedTagType(&activate_params, rw_cback)) {
72     FUZZLOG(MODULE_NAME ": RW_SetActivatedTagType failed");
73     return false;
74   }
75 
76   // A workaround to initialize Type3 tag attribute
77   tRW_T3T_DETECT t3t_detect = {
78       NFC_STATUS_OK,         // tNFC_STATUS status;
79       T3T_MSG_NDEF_VERSION,  // uint8_t version; /* Ver: peer version */
80       RW_T3T_DEFAULT_FELICALITE_NBR,  // uint8_t
81                                       // nbr; /* NBr: number of blocks that can
82                                       // be read using one Check command */
83       RW_T3T_DEFAULT_FELICALITE_NBW,  // uint8_t nbw;    /* Nbw: number of
84                                       // blocks that can be written using one
85                                       // Update command */
86       RW_T3T_DEFAULT_FELICALITE_NMAXB,  // uint16_t nmaxb; /* Nmaxb: maximum
87                                         // number of blocks available for NDEF
88                                         // data */
89       T3T_MSG_NDEF_WRITEF_OFF,  // uint8_t writef; /* WriteFlag: 00h if writing
90                                 // data finished; 0Fh if writing data in
91                                 // progress */
92       T3T_MSG_NDEF_RWFLAG_RW,   // uint8_t
93                                // rwflag;  /* RWFlag: 00h NDEF is read-only; 01h
94                                // if read/write available */
95       0x100 * 16,  // uint32_t ln; /* Ln: actual size of stored NDEF data (in
96                    // bytes) */
97   };
98 
99   tRW_T3T_CB* p_cb = &rw_cb.tcb.t3t;
100   memcpy(&p_cb->ndef_attrib, &t3t_detect, sizeof(t3t_detect));
101 
102   // workaround of issue b/139424089
103   p_cb->p_cur_cmd_buf->offset = 1;
104   p_cb->p_cur_cmd_buf->len = 0;
105   return true;
106 }
107 
Init_CheckNDef(Fuzz_Context &)108 static bool Init_CheckNDef(Fuzz_Context& /*ctx*/) {
109   return NFC_STATUS_OK == RW_T3tCheckNDef();
110 }
111 
Init_UpdateNDef(Fuzz_Context & ctx)112 static bool Init_UpdateNDef(Fuzz_Context& ctx) {
113   const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
114                           0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
115 
116   auto scratch = ctx.GetBuffer(sizeof(data), data);
117   return NFC_STATUS_OK == RW_T3tUpdateNDef(sizeof(data), scratch);
118 }
119 
Init_Check(Fuzz_Context &)120 static bool Init_Check(Fuzz_Context& /*ctx*/) {
121   tT3T_BLOCK_DESC t3t_blocks = {0x000B, 5};
122   return NFC_STATUS_OK == RW_T3tCheck(1, &t3t_blocks);
123 }
124 
Init_Update(Fuzz_Context & ctx)125 static bool Init_Update(Fuzz_Context& ctx) {
126   const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
127                           0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
128   auto scratch = ctx.GetBuffer(sizeof(data), data);
129   tT3T_BLOCK_DESC t3t_blocks = {0x000B, 5};
130   return NFC_STATUS_OK == RW_T3tUpdate(1, &t3t_blocks, scratch);
131 }
132 
Init_SendRawFrame(Fuzz_Context &)133 static bool Init_SendRawFrame(Fuzz_Context& /*ctx*/) {
134   uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
135                     0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
136 
137   return NFC_STATUS_OK == RW_T3tSendRawFrame(sizeof(data), data);
138 }
139 
Init_DetectNDef(Fuzz_Context &)140 static bool Init_DetectNDef(Fuzz_Context& /*ctx*/) {
141   return NFC_STATUS_OK == RW_T3tDetectNDef();
142 }
143 
Init_PresenceCheck(Fuzz_Context &)144 static bool Init_PresenceCheck(Fuzz_Context& /*ctx*/) {
145   return NFC_STATUS_OK == RW_T3tPresenceCheck();
146 }
147 
Init_Poll(Fuzz_Context &)148 static bool Init_Poll(Fuzz_Context& /*ctx*/) {
149   return NFC_STATUS_OK == RW_T3tPoll(0, 1, 0);
150 }
151 
Init_GetSystemCode(Fuzz_Context &)152 static bool Init_GetSystemCode(Fuzz_Context& /*ctx*/) {
153   return NFC_STATUS_OK == RW_T3tGetSystemCodes();
154 }
155 
Init_FormatNDef(Fuzz_Context &)156 static bool Init_FormatNDef(Fuzz_Context& /*ctx*/) {
157   return NFC_STATUS_OK == RW_T3tFormatNDef();
158 }
159 
Init_SetReadonly(Fuzz_Context &)160 static bool Init_SetReadonly(Fuzz_Context& /*ctx*/) {
161   return NFC_STATUS_OK == RW_T3tSetReadOnly(true);
162 }
163 
Fuzz_Init(Fuzz_Context & ctx)164 static bool Fuzz_Init(Fuzz_Context& ctx) {
165   if (!Init(ctx)) {
166     FUZZLOG(MODULE_NAME ": initialization failed");
167     return false;
168   }
169 
170   bool result = false;
171   switch (ctx.SubType) {
172     case SUB_TYPE_CHECK_NDEF:
173       result = Init_CheckNDef(ctx);
174       break;
175     case SUB_TYPE_UPDATE_NDEF:
176       result = Init_UpdateNDef(ctx);
177       break;
178     case SUB_TYPE_CHECK:
179       result = Init_Check(ctx);
180       break;
181     case SUB_TYPE_UPDATE:
182       result = Init_Update(ctx);
183       break;
184     case SUB_TYPE_SEND_RAW_FRAME:
185       result = Init_SendRawFrame(ctx);
186       break;
187     case SUB_TYPE_DETECT_NDEF:
188       result = Init_DetectNDef(ctx);
189       break;
190     case SUB_TYPE_PRESENCE_CHECK:
191       result = Init_PresenceCheck(ctx);
192       break;
193     case SUB_TYPE_POLL:
194       result = Init_Poll(ctx);
195       break;
196     case SUB_TYPE_GET_SYSTEM_CODES:
197       result = Init_GetSystemCode(ctx);
198       break;
199     case SUB_TYPE_FORMAT_NDEF:
200       result = Init_FormatNDef(ctx);
201       break;
202     case SUB_TYPE_SET_READ_ONLY_SOFT:
203     case SUB_TYPE_SET_READ_ONLY_HARD:
204       result = Init_SetReadonly(ctx);
205       break;
206     default:
207       FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType);
208       result = false;
209       break;
210   }
211 
212   if (!result) {
213     FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType);
214   }
215 
216   return result;
217 }
218 
Fuzz_Deinit(Fuzz_Context &)219 static void Fuzz_Deinit(Fuzz_Context& /*ctx*/) {
220   if (rf_cback) {
221     tNFC_CONN conn = {
222         .deactivate = {.status = NFC_STATUS_OK,
223                        .type = NFC_DEACTIVATE_TYPE_IDLE,
224                        .is_ntf = true,
225                        .reason = NFC_DEACTIVATE_REASON_DH_REQ_FAILED}};
226 
227     rf_cback(NFC_RF_CONN_ID, NFC_DEACTIVATE_CEVT, &conn);
228   }
229 }
230 
t3t_nci_msg(NFC_HDR * p_msg)231 static void t3t_nci_msg(NFC_HDR* p_msg) {
232   uint8_t status;
233   uint8_t num_responses;
234 
235   uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
236   uint8_t plen = p_msg->len;
237 
238   if (plen >= 2) {
239     /* Pass result to RW_T3T for processing */
240     STREAM_TO_UINT8(status, p);
241     STREAM_TO_UINT8(num_responses, p);
242     plen -= NFC_TL_SIZE;
243     rw_t3t_handle_nci_poll_ntf(status, num_responses, (uint8_t)plen, p);
244   }
245 
246   GKI_freebuf(p_msg);
247 }
248 
t3t_data_msg(NFC_HDR * p_msg)249 static void t3t_data_msg(NFC_HDR* p_msg) {
250   tNFC_CONN conn = {.data = {
251                         .status = NFC_STATUS_OK,
252                         .p_data = p_msg,
253                     }};
254   if (p_msg->len < 1) {
255     FUZZLOG(MODULE_NAME ": Ivalid message length=%hu", p_msg->len);
256     return;
257   }
258   p_msg->len--;
259 
260   rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
261 }
262 
Fuzz_Run(Fuzz_Context & ctx)263 static void Fuzz_Run(Fuzz_Context& ctx) {
264   for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
265     NFC_HDR* p_msg;
266     p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
267     if (p_msg == nullptr) {
268       FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
269       return;
270     }
271 
272     /* Initialize NFC_HDR */
273     p_msg->len = it->size();
274     p_msg->offset = 0;
275 
276     uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
277     memcpy(p, it->data(), it->size());
278 
279     FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zd]=%s", ctx.SubType,
280             it - ctx.Data.cbegin(), ctx.Data.size() - 1,
281             BytesToHex(*it).c_str());
282 
283     if (ctx.SubType >= SUB_TYPE_NCI_CMD_FIRST) {
284       t3t_nci_msg(p_msg);
285     } else {
286       t3t_data_msg(p_msg);
287     }
288   }
289 }
290 
Type3_FixPackets(uint8_t SubType,std::vector<bytes_t> & Packets)291 void Type3_FixPackets(uint8_t SubType, std::vector<bytes_t>& Packets) {
292   for (auto it = Packets.begin() + 1; it != Packets.end(); ++it) {
293     if (SubType >= SUB_TYPE_NCI_CMD_FIRST) {
294       if (it->size() < 3) {
295         it->resize(3);
296         memset(it->data(), 0, it->size());
297       }
298     } else {
299       if (it->size() <= T3T_MSG_RSP_COMMON_HDR_LEN) {
300         it->resize(T3T_MSG_RSP_COMMON_HDR_LEN + 1);
301         memset(it->data(), 0, it->size());
302       }
303 
304       uint8_t* p = it->data();
305       p[0] = it->size();
306       p[it->size() - 1] = NFC_STATUS_OK;
307 
308       auto rsp = &p[1];
309       rsp[T3T_MSG_RSP_OFFSET_STATUS1] = T3T_MSG_RSP_STATUS_OK;
310       memcpy(&rsp[T3T_MSG_RSP_OFFSET_IDM], TEST_NFCID, sizeof(TEST_NFCID));
311     }
312   }
313 }
314 
Type3_Fuzz(uint8_t SubType,const std::vector<bytes_t> & Packets)315 void Type3_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Packets) {
316   Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Packets);
317   if (Fuzz_Init(ctx)) {
318     Fuzz_Run(ctx);
319   }
320   Fuzz_Deinit(ctx);
321 }
322