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