1 /*
2 * Copyright 2022 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 #include <fuzzer/FuzzedDataProvider.h>
18
19 #include <cstdint>
20 #include <functional>
21 #include <vector>
22
23 #include "common/message_loop_thread.h"
24 #include "osi/include/allocator.h"
25 #include "stack/include/bt_hdr.h"
26 #include "stack/include/smp_api.h"
27 #include "stack/smp/smp_int.h"
28 #include "test/fake/fake_osi.h"
29 #include "test/mock/mock_btif_config.h"
30 #include "test/mock/mock_stack_acl.h"
31 #include "test/mock/mock_stack_btm_dev.h"
32 #include "test/mock/mock_stack_l2cap_api.h"
33 #include "test/mock/mock_stack_l2cap_ble.h"
34
35 bluetooth::common::MessageLoopThread* main_thread_ptr = nullptr;
36
get_main_thread()37 bluetooth::common::MessageLoopThread* get_main_thread() {
38 return main_thread_ptr;
39 }
40 namespace {
41
42 #define SDP_DB_SIZE 0x10000
43
44 constexpr uint8_t kDummyAddr[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
45 constexpr uint8_t kDummyRemoteAddr[] = {0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC};
46
47 // Set up default callback structure
48 tL2CAP_FIXED_CHNL_REG fixed_chnl_reg = {
49 .pL2CA_FixedConn_Cb = [](uint16_t, const RawAddress&, bool, uint16_t,
__anon109b80c40202() 50 tBT_TRANSPORT) {},
__anon109b80c40302() 51 .pL2CA_FixedData_Cb = [](uint16_t, const RawAddress&, BT_HDR*) {},
52 };
53
54 tL2CAP_FIXED_CHNL_REG fixed_chnl_br_reg = {
55 .pL2CA_FixedConn_Cb = [](uint16_t, const RawAddress&, bool, uint16_t,
__anon109b80c40402() 56 tBT_TRANSPORT) {},
__anon109b80c40502() 57 .pL2CA_FixedData_Cb = [](uint16_t, const RawAddress&, BT_HDR*) {},
58 };
59
60 tBTM_SEC_DEV_REC dev_rec;
61 bool is_peripheral;
62
63 class FakeBtStack {
64 public:
FakeBtStack()65 FakeBtStack() {
66 test::mock::stack_acl::BTM_ReadConnectionAddr.body =
67 [](const RawAddress& remote_bda, RawAddress& local_conn_addr,
68 tBLE_ADDR_TYPE* p_addr_type, bool ota_address) {
69 local_conn_addr = kDummyAddr;
70 *p_addr_type = BLE_ADDR_PUBLIC;
71 };
72 test::mock::stack_acl::BTM_ReadRemoteConnectionAddr.body =
73 [](const RawAddress& pseudo_addr, RawAddress& conn_addr,
74 tBLE_ADDR_TYPE* p_addr_type, bool ota_address) {
75 conn_addr = kDummyRemoteAddr;
76 *p_addr_type = BLE_ADDR_PUBLIC;
77 return true;
78 };
79 test::mock::stack_btm_dev::btm_find_dev.body = [](const RawAddress&) {
80 return &dev_rec;
81 };
82
83 test::mock::stack_l2cap_ble::L2CA_GetBleConnRole.body =
84 [](const RawAddress&) {
85 return is_peripheral ? HCI_ROLE_PERIPHERAL : HCI_ROLE_CENTRAL;
86 };
87
88 test::mock::stack_l2cap_api::L2CA_SetIdleTimeoutByBdAddr.body =
89 [](const RawAddress&, uint16_t, uint8_t) { return true; };
90 test::mock::stack_l2cap_api::L2CA_RemoveFixedChnl.body =
91 [](uint16_t, const RawAddress&) { return true; };
92 test::mock::stack_l2cap_api::L2CA_ConnectFixedChnl.body =
93 [](uint16_t, const RawAddress&) { return true; };
94 test::mock::stack_l2cap_api::L2CA_SendFixedChnlData.body =
95 [](uint16_t cid, const RawAddress& addr, BT_HDR* hdr) {
96 osi_free(hdr);
97 return L2CAP_DW_SUCCESS;
98 };
99 test::mock::stack_l2cap_api::L2CA_RegisterFixedChannel.body =
100 [](uint16_t fixed_cid, tL2CAP_FIXED_CHNL_REG* p_freg) {
101 if (fixed_cid == L2CAP_SMP_CID) {
102 fixed_chnl_reg = *p_freg;
103 } else if (fixed_cid == L2CAP_SMP_BR_CID) {
104 fixed_chnl_br_reg = *p_freg;
105 } else {
106 abort();
107 }
108 return true;
109 };
110 main_thread_ptr =
111 new bluetooth::common::MessageLoopThread("smp_fuzz_main_thread");
112 main_thread_ptr->StartUp();
113 }
114
~FakeBtStack()115 ~FakeBtStack() {
116 test::mock::stack_acl::BTM_ReadConnectionAddr = {};
117 test::mock::stack_acl::BTM_ReadRemoteConnectionAddr = {};
118
119 test::mock::stack_btm_dev::btm_find_dev = {};
120
121 test::mock::stack_l2cap_ble::L2CA_GetBleConnRole = {};
122
123 test::mock::stack_l2cap_api::L2CA_SetIdleTimeoutByBdAddr = {};
124 test::mock::stack_l2cap_api::L2CA_RemoveFixedChnl = {};
125 test::mock::stack_l2cap_api::L2CA_ConnectFixedChnl = {};
126 test::mock::stack_l2cap_api::L2CA_SendFixedChnlData = {};
127 test::mock::stack_l2cap_api::L2CA_RegisterFixedChannel = {};
128 main_thread_ptr->ShutDown();
129 delete main_thread_ptr;
130 main_thread_ptr = nullptr;
131 }
132 };
133
134 class Fakes {
135 public:
136 test::fake::FakeOsi fake_osi;
137 FakeBtStack fake_stack;
138 };
139
140 } // namespace
141
142 uint8_t oob_data[] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
143 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00};
144 tSMP_IO_REQ io_req = {};
145
smp_callback(tSMP_EVT event,const RawAddress & bd_addr,const tSMP_EVT_DATA * p_data)146 tBTM_STATUS smp_callback(tSMP_EVT event, const RawAddress& bd_addr,
147 const tSMP_EVT_DATA* p_data) {
148 switch (event) {
149 case SMP_IO_CAP_REQ_EVT:
150 case SMP_BR_KEYS_REQ_EVT: {
151 tSMP_IO_REQ* p_req = (tSMP_IO_REQ*)p_data;
152 memcpy(p_req, &io_req, sizeof(io_req));
153 } break;
154
155 case SMP_PASSKEY_REQ_EVT: {
156 SMP_PasskeyReply(kDummyAddr, SMP_SUCCESS, 1234);
157 } break;
158
159 case SMP_NC_REQ_EVT: {
160 SMP_ConfirmReply(kDummyAddr, SMP_SUCCESS);
161 } break;
162
163 case SMP_OOB_REQ_EVT: {
164 SMP_OobDataReply(kDummyAddr, SMP_SUCCESS, sizeof(oob_data), oob_data);
165 } break;
166
167 case SMP_SC_OOB_REQ_EVT: {
168 tSMP_SC_OOB_DATA oob_data = {};
169 SMP_SecureConnectionOobDataReply((uint8_t*)&oob_data);
170 } break;
171 case SMP_CONSENT_REQ_EVT: {
172 SMP_SecurityGrant(kDummyAddr, SMP_SUCCESS);
173 } break;
174 default:
175 break;
176 }
177 return BTM_SUCCESS;
178 }
179
Fuzz(const uint8_t * data,size_t size)180 void Fuzz(const uint8_t* data, size_t size) {
181 FuzzedDataProvider fdp(data, size);
182 uint16_t cid;
183 tBT_TRANSPORT transport;
184 tL2CAP_FIXED_CHNL_REG* chnl_reg;
185
186 SMP_Init(BTM_SEC_MODE_SP);
187 SMP_Register(smp_callback);
188 SMP_ClearLocScOobData();
189
190 auto is_br = fdp.ConsumeBool();
191 auto is_initiator = fdp.ConsumeBool();
192 is_peripheral = fdp.ConsumeBool();
193 fdp.ConsumeData(&io_req, sizeof(io_req));
194
195 if (is_br) {
196 cid = L2CAP_SMP_BR_CID;
197 chnl_reg = &fixed_chnl_br_reg;
198 transport = BT_TRANSPORT_BR_EDR;
199 if (is_initiator) SMP_BR_PairWith(kDummyAddr);
200 } else {
201 cid = L2CAP_SMP_CID;
202 chnl_reg = &fixed_chnl_reg;
203 transport = BT_TRANSPORT_LE;
204 if (is_initiator) SMP_Pair(kDummyAddr);
205 }
206
207 // Simulating connection establaishing event
208 chnl_reg->pL2CA_FixedConn_Cb(cid, kDummyAddr, true, 0, transport);
209
210 constexpr uint16_t kMaxPacketSize = 1024;
211 while (fdp.remaining_bytes() > 0) {
212 auto size = fdp.ConsumeIntegralInRange<uint16_t>(0, kMaxPacketSize);
213 auto bytes = fdp.ConsumeBytes<uint8_t>(size);
214 BT_HDR* hdr = (BT_HDR*)osi_calloc(sizeof(BT_HDR) + bytes.size());
215 hdr->len = bytes.size();
216 std::copy(bytes.cbegin(), bytes.cend(), hdr->data);
217
218 // Simulating incoming data packet event
219 chnl_reg->pL2CA_FixedData_Cb(cid, kDummyAddr, hdr);
220 }
221
222 // Simulating disconnecting event
223 chnl_reg->pL2CA_FixedConn_Cb(cid, kDummyAddr, false, 0, transport);
224
225 // Final cleanups to avoid memory leak
226 alarm_free(smp_cb.smp_rsp_timer_ent);
227 alarm_free(smp_cb.delayed_auth_timer_ent);
228 }
229
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)230 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
231 auto fakes = std::make_unique<Fakes>();
232 Fuzz(Data, Size);
233 return 0;
234 }
235