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