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