1 /*
2  * Copyright 2020 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 "hal/fuzz/fuzz_hci_hal.h"
18 
19 #include "fuzz/helpers.h"
20 #include "hci/fuzz/status_vs_complete_commands.h"
21 
22 namespace bluetooth {
23 namespace hal {
24 namespace fuzz {
25 using bluetooth::fuzz::GetArbitraryBytes;
26 
registerIncomingPacketCallback(HciHalCallbacks * callbacks)27 void FuzzHciHal::registerIncomingPacketCallback(HciHalCallbacks* callbacks) {
28   callbacks_ = callbacks;
29 }
30 
unregisterIncomingPacketCallback()31 void FuzzHciHal::unregisterIncomingPacketCallback() { callbacks_ = nullptr; }
32 
injectArbitrary(FuzzedDataProvider & fdp)33 void FuzzHciHal::injectArbitrary(FuzzedDataProvider& fdp) {
34   const uint8_t action = fdp.ConsumeIntegralInRange(0, 4);
35   switch (action) {
36     case 1:
37       injectAclData(GetArbitraryBytes(&fdp));
38       break;
39     case 2:
40       injectHciEvent(GetArbitraryBytes(&fdp));
41       break;
42     case 3:
43       injectScoData(GetArbitraryBytes(&fdp));
44       break;
45     case 4:
46       injectIsoData(GetArbitraryBytes(&fdp));
47       break;
48   }
49 }
50 
sendHciCommand(HciPacket packet)51 void FuzzHciHal::sendHciCommand(HciPacket packet) {
52   hci::CommandView command = hci::CommandView::FromBytes(packet);
53   if (!command.IsValid()) {
54     return;
55   }
56 
57   waiting_opcode_ = command.GetOpCode();
58   waiting_for_status_ = hci::fuzz::uses_command_status(waiting_opcode_);
59   waiting_for_complete_ = !waiting_for_status_;
60 }
61 
injectHciEvent(std::vector<uint8_t> data)62 void FuzzHciHal::injectHciEvent(std::vector<uint8_t> data) {
63   hci::EventView event = hci::EventView::FromBytes(data);
64   if (!event.IsValid()) {
65     return;
66   }
67 
68   hci::CommandCompleteView complete = hci::CommandCompleteView::Create(event);
69   if (complete.IsValid()) {
70     if (!waiting_for_complete_ || complete.GetCommandOpCode() != waiting_opcode_) {
71       return;
72     }
73     waiting_for_complete_ = false;
74   }
75 
76   hci::CommandStatusView status = hci::CommandStatusView::Create(event);
77   if (status.IsValid()) {
78     if (!waiting_for_status_ || status.GetCommandOpCode() != waiting_opcode_) {
79       return;
80     }
81     waiting_for_status_ = false;
82   }
83 
84   callbacks_->hciEventReceived(data);
85 }
86 
injectAclData(std::vector<uint8_t> data)87 void FuzzHciHal::injectAclData(std::vector<uint8_t> data) {
88   hci::AclView aclPacket = hci::AclView::FromBytes(data);
89   if (!aclPacket.IsValid()) {
90     return;
91   }
92 
93   callbacks_->aclDataReceived(data);
94 }
95 
injectScoData(std::vector<uint8_t> data)96 void FuzzHciHal::injectScoData(std::vector<uint8_t> data) {
97   hci::ScoView scoPacket = hci::ScoView::FromBytes(data);
98   if (!scoPacket.IsValid()) {
99     return;
100   }
101 
102   callbacks_->scoDataReceived(data);
103 }
104 
injectIsoData(std::vector<uint8_t> data)105 void FuzzHciHal::injectIsoData(std::vector<uint8_t> data) {
106   hci::IsoView isoPacket = hci::IsoView::FromBytes(data);
107   if (!isoPacket.IsValid()) {
108     return;
109   }
110 
111   callbacks_->isoDataReceived(data);
112 }
113 
__anon80a66a2a0102() 114 const ModuleFactory FuzzHciHal::Factory = ModuleFactory([]() { return new FuzzHciHal(); });
115 
116 }  // namespace fuzz
117 }  // namespace hal
118 }  // namespace bluetooth
119