1 /******************************************************************************
2 *
3 * Copyright 2019 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 #include "security/pairing_handler_le.h"
20
21 #include "os/rand.h"
22
23 #include <base/logging.h>
24
25 using bluetooth::os::GenerateRandom;
26
27 namespace bluetooth {
28 namespace security {
29
DoLegacyStage1(const InitialInformations & i,const PairingRequestView & pairing_request,const PairingResponseView & pairing_response)30 LegacyStage1ResultOrFailure PairingHandlerLe::DoLegacyStage1(const InitialInformations& i,
31 const PairingRequestView& pairing_request,
32 const PairingResponseView& pairing_response) {
33 if (((pairing_request.GetAuthReq() | pairing_response.GetAuthReq()) & AuthReqMaskMitm) == 0) {
34 // If both devices have not set MITM option, Just Works shall be used
35 return LegacyJustWorks();
36 }
37
38 if (pairing_request.GetOobDataFlag() == OobDataFlag::PRESENT &&
39 pairing_response.GetOobDataFlag() == OobDataFlag::PRESENT) {
40 // OobDataFlag remote_oob_flag = IAmCentral(i) ? pairing_response.GetOobDataFlag() :
41 // pairing_request.GetOobDataFlag(); OobDataFlag my_oob_flag = IAmCentral(i) ? pairing_request.GetOobDataFlag() :
42 // pairing_response.GetOobDataFlag();
43 return LegacyOutOfBand(i);
44 }
45
46 const auto& iom = pairing_request.GetIoCapability();
47 const auto& ios = pairing_response.GetIoCapability();
48
49 if (iom == IoCapability::NO_INPUT_NO_OUTPUT || ios == IoCapability::NO_INPUT_NO_OUTPUT) {
50 return LegacyJustWorks();
51 }
52
53 if ((iom == IoCapability::DISPLAY_ONLY || iom == IoCapability::DISPLAY_YES_NO) &&
54 (ios == IoCapability::DISPLAY_ONLY || ios == IoCapability::DISPLAY_YES_NO)) {
55 return LegacyJustWorks();
56 }
57
58 // This if() should not be needed, these are only combinations left.
59 if (iom == IoCapability::KEYBOARD_DISPLAY || iom == IoCapability::KEYBOARD_ONLY ||
60 ios == IoCapability::KEYBOARD_DISPLAY || ios == IoCapability::KEYBOARD_ONLY) {
61 IoCapability my_iocaps = IAmCentral(i) ? iom : ios;
62 IoCapability remote_iocaps = IAmCentral(i) ? ios : iom;
63 return LegacyPasskeyEntry(i, my_iocaps, remote_iocaps);
64 }
65
66 // We went through all possble combinations.
67 LOG_ALWAYS_FATAL("This should never happen");
68 }
69
LegacyJustWorks()70 LegacyStage1ResultOrFailure PairingHandlerLe::LegacyJustWorks() {
71 LOG_INFO("Legacy Just Works start");
72 return Octet16{0};
73 }
74
LegacyPasskeyEntry(const InitialInformations & i,const IoCapability & my_iocaps,const IoCapability & remote_iocaps)75 LegacyStage1ResultOrFailure PairingHandlerLe::LegacyPasskeyEntry(const InitialInformations& i,
76 const IoCapability& my_iocaps,
77 const IoCapability& remote_iocaps) {
78 bool i_am_displaying = false;
79 if (my_iocaps == IoCapability::DISPLAY_ONLY || my_iocaps == IoCapability::DISPLAY_YES_NO) {
80 i_am_displaying = true;
81 } else if (
82 IAmCentral(i) && remote_iocaps == IoCapability::KEYBOARD_DISPLAY && my_iocaps == IoCapability::KEYBOARD_DISPLAY) {
83 i_am_displaying = true;
84 } else if (my_iocaps == IoCapability::KEYBOARD_DISPLAY && remote_iocaps == IoCapability::KEYBOARD_ONLY) {
85 i_am_displaying = true;
86 }
87
88 LOG_INFO("Passkey Entry start %s", i_am_displaying ? "displaying" : "accepting");
89
90 uint32_t passkey;
91 if (i_am_displaying) {
92 // generate passkey in a valid range
93 passkey = GenerateRandom();
94 passkey &= 0x0fffff; /* maximum 20 significant bits */
95 constexpr uint32_t PASSKEY_MAX = 999999;
96 if (passkey > PASSKEY_MAX) passkey >>= 1;
97
98 ConfirmationData data(i.remote_connection_address, i.remote_name, passkey);
99 i.user_interface_handler->Post(
100 common::BindOnce(&UI::DisplayConfirmValue, common::Unretained(i.user_interface), data));
101 } else {
102 ConfirmationData data(i.remote_connection_address, i.remote_name);
103 i.user_interface_handler->Post(
104 common::BindOnce(&UI::DisplayEnterPasskeyDialog, common::Unretained(i.user_interface), data));
105 std::optional<PairingEvent> response = WaitUiPasskey();
106 if (!response) return PairingFailure("Passkey did not arrive!");
107
108 passkey = response->ui_value;
109 }
110
111 Octet16 tk{0};
112 tk[0] = (uint8_t)(passkey);
113 tk[1] = (uint8_t)(passkey >> 8);
114 tk[2] = (uint8_t)(passkey >> 16);
115 tk[3] = (uint8_t)(passkey >> 24);
116
117 LOG_INFO("Passkey Entry finish");
118 return tk;
119 }
120
LegacyOutOfBand(const InitialInformations & i)121 LegacyStage1ResultOrFailure PairingHandlerLe::LegacyOutOfBand(const InitialInformations& i) {
122 return i.remote_oob_data->security_manager_tk_value;
123 }
124
DoLegacyStage2(const InitialInformations & i,const PairingRequestView & pairing_request,const PairingResponseView & pairing_response,const Octet16 & tk)125 StkOrFailure PairingHandlerLe::DoLegacyStage2(const InitialInformations& i, const PairingRequestView& pairing_request,
126 const PairingResponseView& pairing_response, const Octet16& tk) {
127 LOG_INFO("Legacy Step 2 start");
128 std::vector<uint8_t> preq(pairing_request.begin(), pairing_request.end());
129 std::vector<uint8_t> pres(pairing_response.begin(), pairing_response.end());
130
131 Octet16 mrand, srand;
132 if (IAmCentral(i)) {
133 mrand = GenerateRandom<16>();
134
135 // LOG(INFO) << +(IAmCentral(i)) << " tk = " << base::HexEncode(tk.data(), tk.size());
136 // LOG(INFO) << +(IAmCentral(i)) << " mrand = " << base::HexEncode(mrand.data(), mrand.size());
137 // LOG(INFO) << +(IAmCentral(i)) << " pres = " << base::HexEncode(pres.data(), pres.size());
138 // LOG(INFO) << +(IAmCentral(i)) << " preq = " << base::HexEncode(preq.data(), preq.size());
139
140 Octet16 mconfirm = crypto_toolbox::c1(
141 tk,
142 mrand,
143 preq.data(),
144 pres.data(),
145 (uint8_t)i.my_connection_address.GetAddressType(),
146 i.my_connection_address.GetAddress().data(),
147 (uint8_t)i.remote_connection_address.GetAddressType(),
148 i.remote_connection_address.GetAddress().data());
149
150 // LOG(INFO) << +(IAmCentral(i)) << " mconfirm = " << base::HexEncode(mconfirm.data(), mconfirm.size());
151
152 LOG_INFO("Central sends Mconfirm");
153 SendL2capPacket(i, PairingConfirmBuilder::Create(mconfirm));
154
155 LOG_INFO("Central waits for the Sconfirm");
156 auto sconfirm_pkt = WaitPairingConfirm();
157 if (std::holds_alternative<PairingFailure>(sconfirm_pkt)) {
158 return std::get<PairingFailure>(sconfirm_pkt);
159 }
160 Octet16 sconfirm = std::get<PairingConfirmView>(sconfirm_pkt).GetConfirmValue();
161
162 LOG_INFO("Central sends Mrand");
163 SendL2capPacket(i, PairingRandomBuilder::Create(mrand));
164
165 LOG_INFO("Central waits for Srand");
166 auto random_pkt = WaitPairingRandom();
167 if (std::holds_alternative<PairingFailure>(random_pkt)) {
168 return std::get<PairingFailure>(random_pkt);
169 }
170 srand = std::get<PairingRandomView>(random_pkt).GetRandomValue();
171
172 // LOG(INFO) << +(IAmCentral(i)) << " srand = " << base::HexEncode(srand.data(), srand.size());
173
174 Octet16 sconfirm_generated = crypto_toolbox::c1(
175 tk,
176 srand,
177 preq.data(),
178 pres.data(),
179 (uint8_t)i.my_connection_address.GetAddressType(),
180 i.my_connection_address.GetAddress().data(),
181 (uint8_t)i.remote_connection_address.GetAddressType(),
182 i.remote_connection_address.GetAddress().data());
183
184 if (sconfirm != sconfirm_generated) {
185 LOG_INFO("sconfirm does not match generated value");
186
187 SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED));
188 return PairingFailure("sconfirm does not match generated value");
189 }
190 } else {
191 srand = GenerateRandom<16>();
192
193 std::vector<uint8_t> preq(pairing_request.begin(), pairing_request.end());
194 std::vector<uint8_t> pres(pairing_response.begin(), pairing_response.end());
195
196 Octet16 sconfirm = crypto_toolbox::c1(
197 tk,
198 srand,
199 preq.data(),
200 pres.data(),
201 (uint8_t)i.remote_connection_address.GetAddressType(),
202 i.remote_connection_address.GetAddress().data(),
203 (uint8_t)i.my_connection_address.GetAddressType(),
204 i.my_connection_address.GetAddress().data());
205
206 LOG_INFO("Peripheral waits for the Mconfirm");
207 auto mconfirm_pkt = WaitPairingConfirm();
208 if (std::holds_alternative<PairingFailure>(mconfirm_pkt)) {
209 return std::get<PairingFailure>(mconfirm_pkt);
210 }
211 Octet16 mconfirm = std::get<PairingConfirmView>(mconfirm_pkt).GetConfirmValue();
212
213 LOG_INFO("Peripheral sends Sconfirm");
214 SendL2capPacket(i, PairingConfirmBuilder::Create(sconfirm));
215
216 LOG_INFO("Peripheral waits for Mrand");
217 auto random_pkt = WaitPairingRandom();
218 if (std::holds_alternative<PairingFailure>(random_pkt)) {
219 return std::get<PairingFailure>(random_pkt);
220 }
221 mrand = std::get<PairingRandomView>(random_pkt).GetRandomValue();
222
223 Octet16 mconfirm_generated = crypto_toolbox::c1(
224 tk,
225 mrand,
226 preq.data(),
227 pres.data(),
228 (uint8_t)i.remote_connection_address.GetAddressType(),
229 i.remote_connection_address.GetAddress().data(),
230 (uint8_t)i.my_connection_address.GetAddressType(),
231 i.my_connection_address.GetAddress().data());
232
233 if (mconfirm != mconfirm_generated) {
234 LOG_INFO("mconfirm does not match generated value");
235 SendL2capPacket(i, PairingFailedBuilder::Create(PairingFailedReason::CONFIRM_VALUE_FAILED));
236 return PairingFailure("mconfirm does not match generated value");
237 }
238
239 LOG_INFO("Peripheral sends Srand");
240 SendL2capPacket(i, PairingRandomBuilder::Create(srand));
241 }
242
243 LOG_INFO("Legacy stage 2 finish");
244
245 /* STK */
246 return crypto_toolbox::s1(tk, mrand, srand);
247 }
248 } // namespace security
249 } // namespace bluetooth
250