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