• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "fuzz.h"
2 
3 #define MODULE_NAME "Type4 Emulator:"
4 
5 enum {
6   SUB_TYPE_READONLY,
7   SUB_TYPE_READWRITE,
8 
9   SUB_TYPE_MAX
10 };
11 
ce_cback(tCE_EVENT event,tCE_DATA * p_ce_data)12 static void ce_cback(tCE_EVENT event, tCE_DATA* p_ce_data) {
13   FUZZLOG(MODULE_NAME ": event=0x%02x, p_ce_data=%p", event, p_ce_data);
14 
15   if (event == CE_T4T_RAW_FRAME_EVT) {
16     if (p_ce_data->raw_frame.p_data) {
17       GKI_freebuf(p_ce_data->raw_frame.p_data);
18       p_ce_data->raw_frame.p_data = nullptr;
19     }
20   }
21 }
22 
Init(Fuzz_Context &)23 static bool Init(Fuzz_Context& /*ctx*/) {
24   tNFC_ACTIVATE_DEVT activate_params = {
25       .protocol = NFC_PROTOCOL_ISO_DEP,
26   };
27 
28   ce_init();
29   if (NFC_STATUS_OK != CE_SetActivatedTagType(&activate_params, 0, ce_cback)) {
30     FUZZLOG(MODULE_NAME ": CE_SetActivatedTagType failed");
31     return false;
32   }
33 
34   if (CE_T4T_AID_HANDLE_INVALID == CE_T4tRegisterAID(0, nullptr, ce_cback)) {
35     return false;
36   }
37 
38   uint8_t AID[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
39   if (CE_T4T_AID_HANDLE_INVALID ==
40       CE_T4tRegisterAID(sizeof(AID), AID, ce_cback)) {
41     return false;
42   }
43 
44   return true;
45 }
46 
Init_ReadOnly(Fuzz_Context & ctx)47 static bool Init_ReadOnly(Fuzz_Context& ctx) {
48   const uint16_t size_max = 1024;
49   const uint16_t ndef_len = 256;
50 
51   auto ndef_msg = ctx.GetBuffer(size_max);
52 
53   return NFC_STATUS_OK ==
54          CE_T4tSetLocalNDEFMsg(true, size_max, ndef_len, ndef_msg, nullptr);
55 }
56 
Init_ReadWrite(Fuzz_Context & ctx)57 static bool Init_ReadWrite(Fuzz_Context& ctx) {
58   const uint16_t size_max = 1024;
59   const uint16_t ndef_len = 256;
60 
61   auto ndef_msg = ctx.GetBuffer(size_max);
62   auto scratch_buf = ctx.GetBuffer(size_max);
63 
64   return NFC_STATUS_OK == CE_T4tSetLocalNDEFMsg(false, size_max, ndef_len,
65                                                 ndef_msg, scratch_buf);
66 }
67 
Fuzz_Init(Fuzz_Context & ctx)68 static bool Fuzz_Init(Fuzz_Context& ctx) {
69   if (!Init(ctx)) {
70     FUZZLOG(MODULE_NAME ": initialization failed");
71     return false;
72   }
73 
74   bool result = true;
75   switch (ctx.SubType) {
76     case SUB_TYPE_READONLY:
77       result = Init_ReadOnly(ctx);
78       break;
79     case SUB_TYPE_READWRITE:
80       result = Init_ReadWrite(ctx);
81       break;
82     default:
83       FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType);
84       result = false;
85       break;
86   }
87 
88   if (!result) {
89     FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType);
90   }
91 
92   return result;
93 }
94 
Fuzz_Run(Fuzz_Context & ctx)95 static void Fuzz_Run(Fuzz_Context& ctx) {
96   for (auto it = ctx.Data.cbegin(); it != ctx.Data.cend(); ++it) {
97     NFC_HDR* p_msg;
98     p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
99     if (p_msg == nullptr) {
100       FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
101       return;
102     }
103 
104     /* Initialize NFC_HDR */
105     p_msg->len = it->size();
106     p_msg->offset = 0;
107 
108     uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
109     memcpy(p, it->data(), it->size());
110 
111     tNFC_CONN conn = {.data = {
112                           .status = NFC_STATUS_OK,
113                           .p_data = p_msg,
114                       }};
115 
116     FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zu]=%s", ctx.SubType,
117             it - ctx.Data.cbegin() + 1, ctx.Data.size(),
118             BytesToHex(*it).c_str());
119 
120     rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
121   }
122 }
123 
Type4_FixPackets(uint8_t,std::vector<bytes_t> & Packets)124 void Type4_FixPackets(uint8_t /*SubType*/, std::vector<bytes_t>& Packets) {
125   const uint8_t valid_cmds[] = {T4T_CMD_INS_SELECT, T4T_CMD_INS_READ_BINARY,
126                                 T4T_CMD_INS_UPDATE_BINARY};
127 
128   for (auto it = Packets.begin() + 1; it != Packets.end(); ++it) {
129     if (it->size() < T4T_CMD_MIN_HDR_SIZE) {
130       it->resize(T4T_CMD_MIN_HDR_SIZE);
131     }
132 
133     auto p = it->data();
134     p[0] = T4T_CMD_CLASS;
135     p[1] = valid_cmds[p[1] % sizeof(valid_cmds)];
136   }
137 }
138 
Type4_Fuzz(uint8_t SubType,const std::vector<bytes_t> & Packets)139 void Type4_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Packets) {
140   Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Packets);
141   if (Fuzz_Init(ctx)) {
142     Fuzz_Run(ctx);
143   }
144 }
145