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 = ¶ms.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