1 /*
2 * Copyright (C) 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* 'system/nfc/src/fuzzers/rw/t4t.cc' is used as reference to come up with file */
18
19 #include "fuzz.h"
20
21 #include "../includes/memutils.h"
22 char enable_selective_overload = ENABLE_NONE;
23 extern bool testInProgress;
24 extern char* vulnPtr;
25
26 #define MODULE_NAME "Type4 Read/Write"
27
28 enum {
29 SUB_TYPE_DETECT_NDEF,
30 SUB_TYPE_READ_NDEF,
31 SUB_TYPE_UPDATE_NDEF,
32 SUB_TYPE_PRESENCE_CHECK,
33 SUB_TYPE_SET_READ_ONLY,
34 SUB_TYPE_FORMAT_NDEF,
35
36 SUB_TYPE_MAX
37 };
38
rw_cback(tRW_EVENT event,tRW_DATA * p_rw_data)39 static void rw_cback(tRW_EVENT event, tRW_DATA* p_rw_data) {
40 FUZZLOG(MODULE_NAME ": rw_cback: event=0x%02x, p_rw_data=%p", event, p_rw_data);
41
42 if (event == RW_T4T_RAW_FRAME_EVT) {
43 if (p_rw_data->raw_frame.p_data) {
44 GKI_freebuf(p_rw_data->raw_frame.p_data);
45 p_rw_data->raw_frame.p_data = nullptr;
46 }
47 } else if (event == RW_T4T_NDEF_READ_EVT || event == RW_T4T_NDEF_READ_CPLT_EVT) {
48 if (p_rw_data->data.p_data) {
49 GKI_freebuf(p_rw_data->data.p_data);
50 p_rw_data->data.p_data = nullptr;
51 }
52 }
53 }
54
55 #define TEST_NFCID_VALUE \
56 { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 }
57
Init(Fuzz_Context &)58 static bool Init(Fuzz_Context& /*ctx*/) {
59 tNFC_ACTIVATE_DEVT activate_params = {.protocol = NFC_PROTOCOL_ISO_DEP,
60 .rf_tech_param = {
61 .mode = NFC_DISCOVERY_TYPE_POLL_A,
62 }};
63
64 rw_init();
65 if (NFC_STATUS_OK != RW_SetActivatedTagType(&activate_params, rw_cback)) {
66 FUZZLOG(MODULE_NAME ": RW_SetActivatedTagType failed");
67 return false;
68 }
69
70 return true;
71 }
72
Init_PresenceCheck(Fuzz_Context &)73 static bool Init_PresenceCheck(Fuzz_Context& /*ctx*/) {
74 return NFC_STATUS_OK == RW_T4tPresenceCheck(1);
75 }
76
Init_DetectNDef(Fuzz_Context &)77 static bool Init_DetectNDef(Fuzz_Context& /*ctx*/) {
78 return NFC_STATUS_OK == RW_T4tDetectNDef();
79 }
80
Init_ReadNDef(Fuzz_Context &)81 static bool Init_ReadNDef(Fuzz_Context& /*ctx*/) {
82 return NFC_STATUS_OK == RW_T4tReadNDef();
83 }
84
Init_UpdateNDef(Fuzz_Context & ctx)85 static bool Init_UpdateNDef(Fuzz_Context& ctx) {
86 const uint8_t data[] = {0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04,
87 0x01, 0x02, 0x03, 0x04, 0x01, 0x02, 0x03, 0x04};
88
89 auto scratch = ctx.GetBuffer(sizeof(data), data);
90 return NFC_STATUS_OK == RW_T4tUpdateNDef(sizeof(data), scratch);
91 }
92
Init_FormatNDef(Fuzz_Context &)93 static bool Init_FormatNDef(Fuzz_Context& /*ctx*/) {
94 return NFC_STATUS_OK == RW_T4tFormatNDef();
95 }
96
Init_SetNDefReadOnly(Fuzz_Context &)97 static bool Init_SetNDefReadOnly(Fuzz_Context& /*ctx*/) {
98 return NFC_STATUS_OK == RW_T4tSetNDefReadOnly();
99 }
100
Fuzz_Init(Fuzz_Context & ctx)101 static bool Fuzz_Init(Fuzz_Context& ctx) {
102 if (!Init(ctx)) {
103 FUZZLOG(MODULE_NAME ": initialization failed");
104 return false;
105 }
106
107 bool result = false;
108 switch (ctx.SubType) {
109 case SUB_TYPE_DETECT_NDEF:
110 result = Init_DetectNDef(ctx);
111 break;
112 case SUB_TYPE_UPDATE_NDEF:
113 result = Init_UpdateNDef(ctx);
114 break;
115 case SUB_TYPE_PRESENCE_CHECK:
116 result = Init_PresenceCheck(ctx);
117 break;
118 case SUB_TYPE_READ_NDEF:
119 result = Init_ReadNDef(ctx);
120 break;
121 case SUB_TYPE_FORMAT_NDEF:
122 result = Init_FormatNDef(ctx);
123 break;
124 case SUB_TYPE_SET_READ_ONLY:
125 result = Init_SetNDefReadOnly(ctx);
126 break;
127 default:
128 FUZZLOG(MODULE_NAME ": Unknown command %d", ctx.SubType);
129 result = false;
130 break;
131 }
132
133 if (!result) {
134 FUZZLOG(MODULE_NAME ": Initializing command %02X failed", ctx.SubType);
135 }
136
137 return result;
138 }
139
Fuzz_Deinit(Fuzz_Context &)140 static void Fuzz_Deinit(Fuzz_Context& /*ctx*/) {
141 if (rf_cback) {
142 tNFC_CONN conn = {.deactivate = {.status = NFC_STATUS_OK,
143 .type = NFC_DEACTIVATE_TYPE_IDLE,
144 .is_ntf = true,
145 .reason = NFC_DEACTIVATE_REASON_DH_REQ_FAILED}};
146
147 rf_cback(NFC_RF_CONN_ID, NFC_DEACTIVATE_CEVT, &conn);
148 }
149 }
150
Fuzz_Run(Fuzz_Context & ctx)151 static void Fuzz_Run(Fuzz_Context& ctx) {
152 for (auto it = ctx.Data.cbegin() + 1; it != ctx.Data.cend(); ++it) {
153 NFC_HDR* p_msg;
154
155 /* CVE-2021-0925 starts */
156 enable_selective_overload = ENABLE_ALL;
157 /* CVE-2021-0925 ends */
158
159 p_msg = (NFC_HDR*)GKI_getbuf(sizeof(NFC_HDR) + it->size());
160
161 /* CVE-2021-0925 starts */
162 vulnPtr = (char*)p_msg;
163 enable_selective_overload = ENABLE_FREE_CHECK | ENABLE_REALLOC_CHECK;
164 /* CVE-2021-0925 ends */
165
166 if (p_msg == nullptr) {
167 FUZZLOG(MODULE_NAME ": GKI_getbuf returns null, size=%zu", it->size());
168 return;
169 }
170
171 /* Initialize NFC_HDR */
172 p_msg->len = it->size();
173 p_msg->offset = 0;
174
175 uint8_t* p = (uint8_t*)(p_msg + 1) + p_msg->offset;
176 memcpy(p, it->data(), it->size());
177
178 tNFC_CONN conn = {.data = {
179 .status = NFC_STATUS_OK,
180 .p_data = p_msg,
181 }};
182
183 FUZZLOG(MODULE_NAME ": SubType=%02X, Response[%zd/%zd]", ctx.SubType,
184 it - ctx.Data.cbegin(), ctx.Data.size() - 1);
185
186 /* CVE-2021-0925 starts */
187 testInProgress = true;
188 /* CVE-2021-0925 ends */
189
190 rf_cback(NFC_RF_CONN_ID, NFC_DATA_CEVT, &conn);
191
192 /* CVE-2021-0925 starts */
193 testInProgress = false;
194 /* CVE-2021-0925 ends */
195 }
196 }
197
Type4_FixPackets(uint8_t,std::vector<bytes_t> &)198 void Type4_FixPackets(uint8_t /*SubType*/, std::vector<bytes_t>& /*Data*/) {}
199
Type4_Fuzz(uint8_t SubType,const std::vector<bytes_t> & Data)200 void Type4_Fuzz(uint8_t SubType, const std::vector<bytes_t>& Data) {
201 Fuzz_Context ctx(SubType % SUB_TYPE_MAX, Data);
202 if (Fuzz_Init(ctx)) {
203 Fuzz_Run(ctx);
204 }
205
206 Fuzz_Deinit(ctx);
207 }
208