xref: /aosp_15_r20/system/nfc/src/fuzzers/integration/nfc_integration_fuzzer_impl.cc (revision 7eba2f3b06c51ae21384f6a4f14577b668a869b3)
1 #include "nfc_integration_fuzzer_impl.h"
2 
3 #include <android-base/logging.h>
4 #include <android-base/stringprintf.h>
5 #include <fuzzer/FuzzedDataProvider.h>
6 
7 #include "nfa_ce_api.h"
8 #include "nfa_ee_api.h"
9 #include "nfa_rw_api.h"
10 #include "nfa_sys.h"
11 #include "nfc_api.h"
12 #include "nfc_int.h"
13 #include "nfc_task_helpers.h"
14 #include "rw_int.h"
15 
16 extern uint32_t g_tick_count;
17 extern tRW_CB rw_cb;
18 
19 FuzzedDataProvider* g_fuzzed_data;
20 
21 static bool g_saw_event = false;
22 static tNFA_EE_DISCOVER_REQ g_ee_info;
23 
fuzz_cback(tRW_EVENT event,tRW_DATA * p_rw_data)24 void fuzz_cback(tRW_EVENT event, tRW_DATA *p_rw_data) {
25   (void)event;
26   (void)p_rw_data;
27 }
28 constexpr int32_t kMaxFramesSize =
29     USHRT_MAX - NFC_HDR_SIZE - NCI_MSG_OFFSET_SIZE - NCI_DATA_HDR_SIZE - 3;
30 
nfa_dm_callback(uint8_t event,tNFA_DM_CBACK_DATA *)31 static void nfa_dm_callback(uint8_t event, tNFA_DM_CBACK_DATA*) {
32   g_saw_event = true;
33   LOG(INFO) << android::base::StringPrintf("nfa_dm_callback got event %d",
34                                            event);
35 }
36 
nfa_conn_callback(uint8_t event,tNFA_CONN_EVT_DATA *)37 static void nfa_conn_callback(uint8_t event, tNFA_CONN_EVT_DATA*) {
38   LOG(INFO) << android::base::StringPrintf("nfa_conn_callback got event %d",
39                                            event);
40   g_saw_event = true;
41 }
42 
nfa_ee_callback(tNFA_EE_EVT event,tNFA_EE_CBACK_DATA * p_data)43 static void nfa_ee_callback(tNFA_EE_EVT event, tNFA_EE_CBACK_DATA* p_data) {
44   switch (event) {
45     case NFA_EE_DISCOVER_REQ_EVT: {
46       memcpy(&g_ee_info, &p_data->discover_req, sizeof(g_ee_info));
47       break;
48     }
49   }
50 }
51 
52 // From packages/apps/Nfc/nci/jni/PeerToPeer.cpp
53 #define LLCP_DATA_LINK_TIMEOUT 2000
54 
55 void nfc_process_timer_evt(void);
56 
GetProtocol(const Protocol & protocol)57 static tNFC_PROTOCOL GetProtocol(const Protocol& protocol) {
58   switch (protocol.value()) {
59     case Protocol::FUZZER_PROTOCOL_UNKNOWN: {
60       return NFC_PROTOCOL_UNKNOWN;
61     }
62     case Protocol::FUZZER_PROTOCOL_T1T: {
63       return NFC_PROTOCOL_T1T;
64     }
65     case Protocol::FUZZER_PROTOCOL_T2T: {
66       return NFC_PROTOCOL_T2T;
67     }
68     case Protocol::FUZZER_PROTOCOL_T3T: {
69       return NFC_PROTOCOL_T3T;
70     }
71     case Protocol::FUZZER_PROTOCOL_T5T: {
72       return NFC_PROTOCOL_T5T;
73     }
74     case Protocol::FUZZER_PROTOCOL_ISO_DEP: {
75       return NFC_PROTOCOL_ISO_DEP;
76     }
77     case Protocol::FUZZER_PROTOCOL_NFC_DEP: {
78       return NFC_PROTOCOL_NFC_DEP;
79     }
80     case Protocol::FUZZER_PROTOCOL_MIFARE: {
81       return NFC_PROTOCOL_MIFARE;
82     }
83     case Protocol::FUZZER_PROTOCOL_ISO15693: {
84       return NFC_PROTOCOL_ISO15693;
85     }
86     case Protocol::FUZZER_PROTOCOL_B_PRIME: {
87       return NFC_PROTOCOL_B_PRIME;
88     }
89     case Protocol::FUZZER_PROTOCOL_KOVIO: {
90       return NFC_PROTOCOL_KOVIO;
91     }
92   }
93 }
94 
GetDiscovery(const DiscoveryType & type)95 static tNFC_DISCOVERY_TYPE GetDiscovery(const DiscoveryType& type) {
96   switch (type.value()) {
97     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_A: {
98       return NFC_DISCOVERY_TYPE_POLL_A;
99     }
100     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_B: {
101       return NFC_DISCOVERY_TYPE_POLL_B;
102     }
103     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_F: {
104       return NFC_DISCOVERY_TYPE_POLL_F;
105     }
106     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_V: {
107       return NFC_DISCOVERY_TYPE_POLL_V;
108     }
109     case DiscoveryType::FUZZER_DISCOVERY_TYPE_LISTEN_A: {
110       return NFC_DISCOVERY_TYPE_LISTEN_A;
111     }
112     case DiscoveryType::FUZZER_DISCOVERY_TYPE_LISTEN_B: {
113       return NFC_DISCOVERY_TYPE_LISTEN_B;
114     }
115     case DiscoveryType::FUZZER_DISCOVERY_TYPE_LISTEN_F: {
116       return NFC_DISCOVERY_TYPE_LISTEN_F;
117     }
118     case DiscoveryType::FUZZER_DISCOVERY_TYPE_LISTEN_ISO15693: {
119       return NFC_DISCOVERY_TYPE_LISTEN_ISO15693;
120     }
121     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_B_PRIME: {
122       return NFC_DISCOVERY_TYPE_POLL_B_PRIME;
123     }
124     case DiscoveryType::FUZZER_DISCOVERY_TYPE_POLL_KOVIO: {
125       return NFC_DISCOVERY_TYPE_POLL_KOVIO;
126     }
127     case DiscoveryType::FUZZER_DISCOVERY_TYPE_LISTEN_B_PRIME: {
128       return NFC_DISCOVERY_TYPE_LISTEN_B_PRIME;
129     }
130   }
131 }
132 
SerializeTechParameters(const tNFC_RF_TECH_PARAMS & params)133 std::vector<uint8_t> SerializeTechParameters(
134     const tNFC_RF_TECH_PARAMS& params) {
135   std::vector<uint8_t> vec;
136 
137   switch (params.mode) {
138     case NCI_DISCOVERY_TYPE_POLL_A: {
139       const tNFC_RF_PA_PARAMS* pa = &params.param.pa;
140       vec.push_back(pa->sens_res[0]);
141       vec.push_back(pa->sens_res[1]);
142       vec.push_back(pa->nfcid1_len);
143       vec.insert(vec.end(), pa->nfcid1, pa->nfcid1 + pa->nfcid1_len);
144 
145       // sel_rsp of 0 is the same as not having it, so we just always send it
146       vec.push_back(1);
147       vec.push_back(pa->sel_rsp);
148 
149       vec.push_back(pa->hr_len);
150       vec.insert(vec.end(), pa->hr, pa->hr + pa->hr_len);
151       break;
152     }
153     default: {
154       abort();
155     }
156   }
157 
158   return vec;
159 }
160 
161 // Serialize an NFC Activation event back to the spec wire format
SerializeNfcActivate(const tNFC_ACTIVATE_DEVT & activate,uint8_t buff_size,uint8_t num_buff,const std::string & rf_tech_param_buffer,const std::string & intf_param_buffer)162 std::vector<uint8_t> SerializeNfcActivate(
163     const tNFC_ACTIVATE_DEVT& activate, uint8_t buff_size, uint8_t num_buff,
164     const std::string& rf_tech_param_buffer,
165     const std::string& intf_param_buffer) {
166   std::vector<uint8_t> packet;
167   packet.push_back(activate.rf_disc_id);
168   packet.push_back(activate.intf_param.type);
169   packet.push_back(activate.protocol);
170   packet.push_back(activate.rf_tech_param.mode);
171   packet.push_back(buff_size);
172   packet.push_back(num_buff);
173 
174   std::vector<uint8_t> tech_parameters(
175       rf_tech_param_buffer.begin(),
176       rf_tech_param_buffer
177           .end());  // = SerializeTechParameters(activate.rf_tech_param);
178   if (tech_parameters.size() > 256) {
179     tech_parameters.resize(256);
180   }
181   packet.push_back(tech_parameters.size());
182   packet.insert(packet.end(), tech_parameters.begin(), tech_parameters.end());
183 
184   packet.push_back(activate.data_mode);
185   packet.push_back(activate.tx_bitrate);
186   packet.push_back(activate.rx_bitrate);
187 
188   std::vector<uint8_t> activation_parameters(intf_param_buffer.begin(),
189                                              intf_param_buffer.end());
190   if (activation_parameters.size() > 256) {
191     activation_parameters.resize(256);
192   }
193 
194   packet.push_back(activation_parameters.size());
195   packet.insert(packet.end(), activation_parameters.begin(),
196                 activation_parameters.end());
197   return packet;
198 }
199 
DoRfManageIntfActivated(const RfManageIntfActivated & activated)200 void DoRfManageIntfActivated(const RfManageIntfActivated& activated) {
201   // The event we want to generate
202   tNFC_ACTIVATE_DEVT activate_event = {};
203   activate_event.rf_disc_id = activated.rf_discovery_id();
204   activate_event.protocol = GetProtocol(activated.rf_protocol());
205   activate_event.data_mode = GetDiscovery(activated.data_mode());
206   activate_event.tx_bitrate = activated.tx_bitrate();
207   activate_event.rx_bitrate = activated.rx_bitrate();
208   uint8_t buff_size = activated.buff_size();
209   uint8_t num_buff = activated.num_buff();
210 
211   std::vector<uint8_t> packet = SerializeNfcActivate(
212       activate_event, buff_size, num_buff, activated.rf_tech_param_buffer(),
213       activated.intf_param_buffer());
214 
215   g_fake_hal->SimulatePacketArrival(NCI_MT_NTF, 0, NCI_GID_RF_MANAGE,
216                                     NCI_MSG_RF_INTF_ACTIVATED, packet.data(),
217                                     packet.size());
218 }
219 
DoRfManagementNtf(const RfManagementNtf & ntf)220 void DoRfManagementNtf(const RfManagementNtf& ntf) {
221   switch (ntf.opcode_case()) {
222     case RfManagementNtf::kIntfActivated: {
223       DoRfManageIntfActivated(ntf.intf_activated());
224       break;
225     }
226     case RfManagementNtf::OPCODE_NOT_SET: {
227       break;
228     }
229   }
230 }
231 
DoMtNtf(const MtNtf & ntf)232 void DoMtNtf(const MtNtf& ntf) {
233   switch (ntf.gid_case()) {
234     case MtNtf::kRfManage: {
235       DoRfManagementNtf(ntf.rf_manage());
236       break;
237     }
238     case MtNtf::GID_NOT_SET: {
239       break;
240     }
241   }
242 }
243 
DoStructuredPacket(const SimulateStructuredPacket & packet)244 void DoStructuredPacket(const SimulateStructuredPacket& packet) {
245   switch (packet.packet_case()) {
246     case SimulateStructuredPacket::kNtf: {
247       DoMtNtf(packet.ntf());
248       break;
249     }
250     case SimulateStructuredPacket::PACKET_NOT_SET: {
251       break;
252     }
253   }
254 }
255 
DoPacket(const SimulatePacketArrival & packet)256 void DoPacket(const SimulatePacketArrival& packet) {
257   uint8_t mt = packet.mt();
258   uint8_t pbf = packet.pbf();
259   uint8_t gid = packet.gid();
260   uint8_t opcode = static_cast<uint8_t>(packet.opcode());
261   bool need_flush = false;
262   if (mt == NCI_MT_DATA) {
263     // The gid field will be used as the connection ID. We should handle this
264     // a lot better but for now we let the existing gid enum get interpreted
265     // as a connection ID.
266     // gid = 0;
267     opcode = 0;
268   }
269 
270   g_fake_hal->SimulatePacketArrival(mt, pbf, gid, opcode,
271                                     (unsigned char*)packet.packet().data(),
272                                     packet.packet().size());
273   if (need_flush) {
274     DoAllTasks(false);
275   }
276 }
277 
DoOneCommand(std::vector<std::vector<uint8_t>> & bytes_container,const Command & command)278 void NfcIntegrationFuzzer::DoOneCommand(
279     std::vector<std::vector<uint8_t>>& bytes_container,
280     const Command& command) {
281   switch (command.command_case()) {
282     case Command::kSimulatePacketArrival: {
283       DoPacket(command.simulate_packet_arrival());
284       break;
285     }
286     case Command::kSimulateHalEvent: {
287       g_fake_hal->SimulateHALEvent(command.simulate_hal_event().hal_event(),
288                                    command.simulate_hal_event().hal_status());
289       break;
290     }
291     case Command::kSimulateStructuredPacket: {
292       DoStructuredPacket(command.simulate_structured_packet());
293       break;
294     }
295     case Command::kSendRawFrame: {
296       std::vector<uint8_t> frame(
297           command.send_raw_frame().data(),
298           command.send_raw_frame().data() + command.send_raw_frame().size());
299       uint16_t frameSize =
300           frame.size() <= kMaxFramesSize ? frame.size() : kMaxFramesSize;
301       NFA_SendRawFrame(frame.data(), frameSize,
302                        /*presence check start delay*/ 0);
303       break;
304     }
305     case Command::kDoNciMessages: {
306       nfc_process_nci_messages();
307       break;
308     }
309     case Command::kDoNfaTasks: {
310       nfc_process_nfa_messages();
311       break;
312     }
313     case Command::kSimulateTimerEvent: {
314       nfc_process_timer_evt();
315       break;
316     }
317     case Command::kSimulateQuickTimerEvent: {
318       nfc_process_quick_timer_evt();
319       break;
320     }
321     case Command::kSelect: {
322       NFA_Select(command.select().rf_select_id(),
323                  GetProtocol(command.select().protocol()),
324                  command.select().rf_interface());
325       break;
326     }
327     case Command::kConfigureUiccListenTech: {
328       if (g_ee_info.num_ee > 0) {
329         uint8_t handle = command.configure_uicc_listen_tech().ee_handle();
330         handle = g_ee_info.ee_disc_info[handle % g_ee_info.num_ee].ee_handle;
331         NFA_CeConfigureUiccListenTech(
332             handle, command.configure_uicc_listen_tech().tech_mask());
333         NFA_EeClearDefaultTechRouting(handle, 0xFF);
334         NFA_EeSetDefaultTechRouting(handle, 0xFF, 0, 0, 0, 0, 0);
335       }
336       break;
337     }
338     case Command::kRegisterT3T: {
339       uint8_t nfcid2[NCI_RF_F_UID_LEN] = {};
340       uint8_t t3tPmm[NCI_T3T_PMM_LEN] = {};
341       NFA_CeRegisterFelicaSystemCodeOnDH(0, nfcid2, t3tPmm, nfa_conn_callback);
342       const uint8_t SYS_CODE_PWR_STATE_HOST = 0x01;
343       NFA_EeAddSystemCodeRouting(0, NCI_DH_ID, SYS_CODE_PWR_STATE_HOST);
344       break;
345     }
346     case Command::kStartRfDiscovery: {
347       NFA_StartRfDiscovery();
348       break;
349     }
350     case Command::kStopRfDiscovery: {
351       NFA_StopRfDiscovery();
352       break;
353     }
354     case Command::kSetIsoListenTech: {
355       NFA_CeSetIsoDepListenTech(
356           fuzzed_data_.ConsumeIntegralInRange<uint8_t>(0, 0xFF));
357       NFA_CeRegisterAidOnDH(nullptr, 0, nfa_conn_callback);
358       break;
359     }
360     case Command::kRwFormatTag: {
361       NFA_RwFormatTag();
362       break;
363     }
364     case Command::kRwPresenceCheck: {
365       NFA_RwPresenceCheck(command.rw_presence_check().option());
366       break;
367     }
368     case Command::kRwSetTagReadOnly: {
369       NFA_RwSetTagReadOnly(command.rw_set_tag_read_only());
370       break;
371     }
372     case Command::kEeUpdateNow: {
373       NFA_EeUpdateNow();
374       break;
375     }
376     case Command::kEeAddAidRouting: {
377       uint8_t handle = command.ee_add_aid_routing().ee_handle();
378       if (g_ee_info.num_ee) {
379         handle = g_ee_info.ee_disc_info[handle % g_ee_info.num_ee].ee_handle;
380       }
381       std::vector<uint8_t> aid(command.ee_add_aid_routing().aid().data(),
382                                command.ee_add_aid_routing().aid().data() +
383                                    command.ee_add_aid_routing().aid().size());
384       tNFA_EE_PWR_STATE power_state =
385           command.ee_add_aid_routing().power_state();
386       uint8_t aidInfo = command.ee_add_aid_routing().aid_info();
387       NFA_EeAddAidRouting(handle, aid.size(), aid.data(), power_state, aidInfo);
388       break;
389     }
390     case Command::kReadNdef: {
391       NFA_RwReadNDef();
392       break;
393     }
394     case Command::kDetectNdef: {
395       NFA_RwDetectNDef();
396       break;
397     }
398     case Command::kWriteNdef: {
399       bytes_container.emplace_back(command.write_ndef().size() % 1024);
400       NFA_RwWriteNDef(bytes_container.back().data(),
401                       bytes_container.back().size());
402       break;
403     }
404     case Command::COMMAND_NOT_SET: {
405       break;
406     }
407   }
408 }
409 
NfcIntegrationFuzzer(const Session * session)410 NfcIntegrationFuzzer::NfcIntegrationFuzzer(const Session* session)
411     : session_(session),
412       fuzzed_data_(
413           reinterpret_cast<const uint8_t*>(session->data_provider().data()),
414           session->data_provider().size()) {
415   g_fuzzed_data = &fuzzed_data_;
416 }
417 
Setup()418 bool NfcIntegrationFuzzer::Setup() {
419   g_tick_count = 0;
420   memset(&g_ee_info, 0, sizeof(g_ee_info));
421   NFA_Init(&fuzzed_hal_entry);
422 
423   rw_cb.p_cback = &fuzz_cback;
424   NFA_Enable(nfa_dm_callback, nfa_conn_callback);
425   DoAllTasks(false);
426 
427   NFA_EeRegister(nfa_ee_callback);
428   NFA_EeSetDefaultProtoRouting(NFC_DH_ID, NFA_PROTOCOL_MASK_ISO_DEP, 0, 0, 0, 0,
429                                0);
430 
431   DoPacket(session_->setup_packet());
432   g_saw_event = false;
433   DoAllTasks(false);
434   if (!g_saw_event) {
435     return false;
436   }
437 
438   NFA_EnableListening();
439   NFA_EnablePolling(NFA_TECHNOLOGY_MASK_A | NFA_TECHNOLOGY_MASK_B |
440                     NFA_TECHNOLOGY_MASK_F | NFA_TECHNOLOGY_MASK_V |
441                     NFA_TECHNOLOGY_MASK_B_PRIME | NFA_TECHNOLOGY_MASK_A_ACTIVE |
442                     NFA_TECHNOLOGY_MASK_F_ACTIVE | NFA_TECHNOLOGY_MASK_KOVIO);
443 
444   NFA_EnableDtamode(static_cast<tNFA_eDtaModes>(session_->dta_mode()));
445   NFA_StartRfDiscovery();
446 
447   DoAllTasks(false);
448   return true;
449 }
450 
RunCommands()451 void NfcIntegrationFuzzer::RunCommands() {
452   for (const Command& command : session_->commands()) {
453     DoOneCommand(bytes_container_, command);
454   }
455 }
456 
TearDown()457 void NfcIntegrationFuzzer::TearDown() {
458   // Do any remaining tasks including pending timers
459   DoAllTasks(true);
460 
461   // Issue a disable command then clear pending tasks
462   // and timers again
463   NFA_Disable(false);
464   DoAllTasks(true);
465 }
466