1 /******************************************************************************
2 *
3 * Copyright 2008-2012 Broadcom Corporation
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 /******************************************************************************
20 *
21 * This file contains the implementation of the SMP interface used by
22 * applications that can run over an SMP.
23 *
24 ******************************************************************************/
25 #define LOG_TAG "smp"
26
27 #include "smp_api.h"
28
29 #include <bluetooth/log.h>
30 #include <string.h>
31
32 #include "smp_int.h"
33 #include "stack/include/bt_octets.h"
34 #include "stack/include/btm_sec_api_types.h"
35 #include "stack/include/l2cap_interface.h"
36 #include "types/raw_address.h"
37
38 using namespace bluetooth;
39
40 /*******************************************************************************
41 *
42 * Function SMP_Init
43 *
44 * Description This function initializes the SMP unit.
45 *
46 * Returns void
47 *
48 ******************************************************************************/
SMP_Init(uint8_t init_security_mode)49 void SMP_Init(uint8_t init_security_mode) { smp_cb.init(init_security_mode); }
50
51 /*******************************************************************************
52 *
53 * Function SMP_Register
54 *
55 * Description This function register for the SMP services callback.
56 *
57 * Returns void
58 *
59 ******************************************************************************/
SMP_Register(tSMP_CALLBACK * p_cback)60 bool SMP_Register(tSMP_CALLBACK* p_cback) {
61 log::verbose("state={}", smp_cb.state);
62
63 if (smp_cb.p_callback != NULL) {
64 log::error("duplicate registration, overwrite it");
65 }
66 smp_cb.p_callback = p_cback;
67
68 return true;
69 }
70
71 /*******************************************************************************
72 *
73 * Function SMP_Pair
74 *
75 * Description This function call to perform a SMP pairing with peer
76 * device. Device support one SMP pairing at one time.
77 *
78 * Parameters bd_addr - peer device bd address.
79 *
80 * Returns None
81 *
82 ******************************************************************************/
SMP_Pair(const RawAddress & bd_addr,tBLE_ADDR_TYPE addr_type)83 tSMP_STATUS SMP_Pair(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type) {
84 tSMP_CB* p_cb = &smp_cb;
85
86 log::verbose("state={} br_state={} flag=0x{:x}, bd_addr={}", p_cb->state, p_cb->br_state,
87 p_cb->flags, bd_addr);
88
89 if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
90 p_cb->smp_over_br) {
91 /* pending security on going, reject this one */
92 return SMP_BUSY;
93 } else {
94 p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
95 p_cb->pairing_bda = bd_addr;
96
97 p_cb->pairing_ble_bd_addr = {
98 .type = addr_type,
99 .bda = bd_addr,
100 };
101 if (!stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_SMP_CID, bd_addr)) {
102 tSMP_INT_DATA smp_int_data;
103 smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
104 p_cb->status = SMP_PAIR_INTERNAL_ERR;
105 log::error("L2C connect fixed channel failed.");
106 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
107 return SMP_PAIR_INTERNAL_ERR;
108 }
109
110 return SMP_STARTED;
111 }
112 }
113
SMP_Pair(const RawAddress & bd_addr)114 tSMP_STATUS SMP_Pair(const RawAddress& bd_addr) { return SMP_Pair(bd_addr, BLE_ADDR_PUBLIC); }
115
116 /*******************************************************************************
117 *
118 * Function SMP_BR_PairWith
119 *
120 * Description This function is called to start a SMP pairing over BR/EDR.
121 * Device support one SMP pairing at one time.
122 *
123 * Parameters bd_addr - peer device bd address.
124 *
125 * Returns SMP_STARTED if pairing started, otherwise the reason for
126 * failure.
127 *
128 ******************************************************************************/
SMP_BR_PairWith(const RawAddress & bd_addr)129 tSMP_STATUS SMP_BR_PairWith(const RawAddress& bd_addr) {
130 tSMP_CB* p_cb = &smp_cb;
131
132 log::verbose("state={} br_state={} flag=0x{:x}, bd_addr={}", p_cb->state, p_cb->br_state,
133 p_cb->flags, bd_addr);
134
135 if (p_cb->state != SMP_STATE_IDLE || p_cb->smp_over_br ||
136 p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
137 /* pending security on going, reject this one */
138 return SMP_BUSY;
139 }
140
141 p_cb->role = HCI_ROLE_CENTRAL;
142 p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
143 p_cb->smp_over_br = true;
144 p_cb->pairing_bda = bd_addr;
145
146 if (!stack::l2cap::get_interface().L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, bd_addr)) {
147 log::error("L2C connect fixed channel failed.");
148 tSMP_INT_DATA smp_int_data;
149 smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
150 p_cb->status = SMP_PAIR_INTERNAL_ERR;
151 smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
152 return SMP_PAIR_INTERNAL_ERR;
153 }
154
155 return SMP_STARTED;
156 }
157
158 /*******************************************************************************
159 *
160 * Function SMP_PairCancel
161 *
162 * Description This function call to cancel a SMP pairing with peer device.
163 *
164 * Parameters bd_addr - peer device bd address.
165 *
166 * Returns true - Pairining is cancelled
167 *
168 ******************************************************************************/
SMP_PairCancel(const RawAddress & bd_addr)169 bool SMP_PairCancel(const RawAddress& bd_addr) {
170 tSMP_CB* p_cb = &smp_cb;
171
172 log::verbose("state={} flag=0x{:x}", p_cb->state, p_cb->flags);
173 if (p_cb->state != SMP_STATE_IDLE && p_cb->pairing_bda == bd_addr) {
174 p_cb->is_pair_cancel = true;
175 log::verbose("set fail reason Unknown");
176 tSMP_INT_DATA smp_int_data;
177 smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
178 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
179 return true;
180 }
181
182 return false;
183 }
184 /*******************************************************************************
185 *
186 * Function SMP_SecurityGrant
187 *
188 * Description This function is called to grant security process.
189 *
190 * Parameters bd_addr - peer device bd address.
191 * res - result of the operation SMP_SUCCESS if success.
192 * Otherwise, SMP_REPEATED_ATTEMPTS if too many
193 * attempts.
194 *
195 * Returns None
196 *
197 ******************************************************************************/
SMP_SecurityGrant(const RawAddress & bd_addr,tSMP_STATUS res)198 void SMP_SecurityGrant(const RawAddress& bd_addr, tSMP_STATUS res) {
199 log::verbose("addr:{}", bd_addr);
200
201 // If just showing consent dialog, send response
202 if (smp_cb.cb_evt == SMP_CONSENT_REQ_EVT) {
203 // If JUSTWORKS, this is used to display the consent dialog
204 if (smp_cb.selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
205 if (res == SMP_SUCCESS) {
206 smp_sm_event(&smp_cb, SMP_SC_NC_OK_EVT, NULL);
207 } else {
208 log::warn("Consent dialog fails for JUSTWORKS");
209 /* send pairing failure */
210 tSMP_INT_DATA smp_int_data;
211 smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
212 smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
213 }
214 } else if (smp_cb.selected_association_model == SMP_MODEL_ENCRYPTION_ONLY) {
215 if (res == SMP_SUCCESS) {
216 smp_cb.sec_level = SMP_SEC_UNAUTHENTICATE;
217
218 tSMP_KEY key;
219 tSMP_INT_DATA smp_int_data;
220 key.key_type = SMP_KEY_TYPE_TK;
221 key.p_data = smp_cb.tk.data();
222 smp_int_data.key = key;
223
224 smp_cb.tk = {0};
225 smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
226 } else {
227 log::warn("Consent dialog fails for ENCRYPTION_ONLY");
228 /* send pairing failure */
229 tSMP_INT_DATA smp_int_data;
230 smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
231 smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
232 }
233 }
234 return;
235 }
236
237 if (smp_cb.smp_over_br) {
238 if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP || smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
239 smp_cb.pairing_bda != bd_addr) {
240 return;
241 }
242
243 /* clear the SMP_SEC_REQUEST_EVT event after get grant */
244 /* avoid generating duplicate pair request */
245 smp_cb.cb_evt = SMP_EVT_NONE;
246 tSMP_INT_DATA smp_int_data;
247 smp_int_data.status = res;
248 smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &smp_int_data);
249 return;
250 }
251
252 if (smp_cb.state != SMP_STATE_WAIT_APP_RSP || smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
253 smp_cb.pairing_bda != bd_addr) {
254 return;
255 }
256 /* clear the SMP_SEC_REQUEST_EVT event after get grant */
257 /* avoid generate duplicate pair request */
258 smp_cb.cb_evt = SMP_EVT_NONE;
259 tSMP_INT_DATA smp_int_data;
260 smp_int_data.status = res;
261 smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &smp_int_data);
262 }
263
264 /*******************************************************************************
265 *
266 * Function SMP_PasskeyReply
267 *
268 * Description This function is called when the user replies
269 * passkey after being requested.
270 *
271 * Parameters: bd_addr - Address of the device for which passkey was
272 * requested
273 * res - result of the operation SMP_SUCCESS if success
274 * passkey - numeric value in the range of
275 * BTM_MIN_PASSKEY_VAL(0) -
276 * BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
277 *
278 ******************************************************************************/
SMP_PasskeyReply(const RawAddress & bd_addr,uint8_t res,uint32_t passkey)279 void SMP_PasskeyReply(const RawAddress& bd_addr, uint8_t res, uint32_t passkey) {
280 tSMP_CB* p_cb = &smp_cb;
281
282 log::verbose("Key:{} Result:{}", passkey, res);
283
284 /* If timeout already expired or has been canceled, ignore the reply */
285 if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT) {
286 log::warn("Wrong State:{}", p_cb->state);
287 return;
288 }
289
290 if (bd_addr != p_cb->pairing_bda) {
291 log::error("Wrong BD Addr");
292 return;
293 }
294
295 if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS) {
296 log::warn("Invalid passkey value:{} or passkey entry fail", passkey);
297 /* send pairing failure */
298 tSMP_INT_DATA smp_int_data;
299 smp_int_data.status = SMP_PASSKEY_ENTRY_FAIL;
300 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
301 } else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
302 tSMP_INT_DATA smp_int_data;
303 smp_int_data.passkey = passkey;
304 smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
305 } else {
306 smp_convert_string_to_tk(&p_cb->tk, passkey);
307 }
308 }
309
310 /*******************************************************************************
311 *
312 * Function SMP_ConfirmReply
313 *
314 * Description This function is called after Security Manager submitted
315 * numeric comparison request to the application.
316 *
317 * Parameters: bd_addr - Address of the device with which numeric
318 * comparison was requested
319 * res - comparison result SMP_SUCCESS if success
320 *
321 ******************************************************************************/
SMP_ConfirmReply(const RawAddress & bd_addr,uint8_t res)322 void SMP_ConfirmReply(const RawAddress& bd_addr, uint8_t res) {
323 tSMP_CB* p_cb = &smp_cb;
324
325 log::verbose("addr:{}, Result:{}", bd_addr, res);
326
327 /* If timeout already expired or has been canceled, ignore the reply */
328 if (p_cb->cb_evt != SMP_NC_REQ_EVT) {
329 log::warn("Wrong State:{}", p_cb->state);
330 return;
331 }
332
333 if (bd_addr != p_cb->pairing_bda) {
334 log::error("Wrong BD Addr");
335 return;
336 }
337
338 if (res != SMP_SUCCESS) {
339 log::warn("Numeric Comparison fails");
340 /* send pairing failure */
341 tSMP_INT_DATA smp_int_data;
342 smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
343 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
344 } else {
345 smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
346 }
347 }
348
349 /*******************************************************************************
350 *
351 * Function SMP_OobDataReply
352 *
353 * Description This function is called to provide the OOB data for
354 * SMP in response to SMP_OOB_REQ_EVT
355 *
356 * Parameters: bd_addr - Address of the peer device
357 * res - result of the operation SMP_SUCCESS if success
358 * p_data - simple pairing Randomizer C.
359 *
360 ******************************************************************************/
SMP_OobDataReply(const RawAddress &,tSMP_STATUS res,uint8_t len,uint8_t * p_data)361 void SMP_OobDataReply(const RawAddress& /* bd_addr */, tSMP_STATUS res, uint8_t len,
362 uint8_t* p_data) {
363 tSMP_CB* p_cb = &smp_cb;
364 tSMP_KEY key;
365
366 log::verbose("State:{} res:{}", smp_cb.state, res);
367
368 /* If timeout already expired or has been canceled, ignore the reply */
369 if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT) {
370 return;
371 }
372
373 if (res != SMP_SUCCESS || len == 0 || !p_data) {
374 tSMP_INT_DATA smp_int_data;
375 smp_int_data.status = SMP_OOB_FAIL;
376 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
377 } else {
378 if (len > OCTET16_LEN) {
379 len = OCTET16_LEN;
380 }
381
382 memcpy(p_cb->tk.data(), p_data, len);
383
384 key.key_type = SMP_KEY_TYPE_TK;
385 key.p_data = p_cb->tk.data();
386
387 tSMP_INT_DATA smp_int_data;
388 smp_int_data.key = key;
389 smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
390 }
391 }
392
393 /*******************************************************************************
394 *
395 * Function SMP_SecureConnectionOobDataReply
396 *
397 * Description This function is called to provide the SC OOB data for
398 * SMP in response to SMP_SC_OOB_REQ_EVT
399 *
400 * Parameters: p_data - pointer to the data
401 *
402 ******************************************************************************/
SMP_SecureConnectionOobDataReply(uint8_t * p_data)403 void SMP_SecureConnectionOobDataReply(uint8_t* p_data) {
404 tSMP_CB* p_cb = &smp_cb;
405
406 tSMP_SC_OOB_DATA* p_oob = (tSMP_SC_OOB_DATA*)p_data;
407 if (!p_oob) {
408 log::error("received no data");
409 tSMP_INT_DATA smp_int_data;
410 smp_int_data.status = SMP_OOB_FAIL;
411 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
412 return;
413 }
414
415 log::verbose("req_oob_type:{}, loc_oob_data.present:{}, peer_oob_data.present:{}",
416 p_cb->req_oob_type, p_oob->loc_oob_data.present, p_oob->peer_oob_data.present);
417
418 if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT) {
419 return;
420 }
421
422 bool data_missing = false;
423 switch (p_cb->req_oob_type) {
424 case SMP_OOB_PEER:
425 if (!p_oob->peer_oob_data.present) {
426 data_missing = true;
427 }
428 break;
429 case SMP_OOB_LOCAL:
430 if (!p_oob->loc_oob_data.present) {
431 data_missing = true;
432 }
433 break;
434 case SMP_OOB_BOTH:
435 // Check for previous local OOB data in cache
436 // This would be in the case data was generated BEFORE pairing was
437 // attempted and this instance is the connector or pairing initiator.
438 // [NOTICE]: Overridding data present here if the data exists so state
439 // machine asks for it later
440 p_oob->loc_oob_data.present = smp_has_local_oob_data();
441 if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present) {
442 data_missing = true;
443 }
444 break;
445 default:
446 log::verbose("Unexpected OOB data type requested. Fail OOB");
447 data_missing = true;
448 break;
449 }
450
451 tSMP_INT_DATA smp_int_data;
452 if (data_missing) {
453 smp_int_data.status = SMP_OOB_FAIL;
454 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
455 return;
456 }
457
458 p_cb->sc_oob_data = *p_oob;
459
460 smp_int_data.p_data = p_data;
461 smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, &smp_int_data);
462 }
463
464 /*******************************************************************************
465 *
466 * Function SMP_CrLocScOobData
467 *
468 * Description This function is called to generate a public key to be
469 * passed to a remote device via Out of Band transport.
470 *
471 * Returns true if the request is successfully sent and executed by the
472 * state machine, false otherwise
473 *
474 ******************************************************************************/
SMP_CrLocScOobData()475 bool SMP_CrLocScOobData() {
476 tSMP_INT_DATA smp_int_data;
477 return smp_sm_event(&smp_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, &smp_int_data);
478 }
479
480 /*******************************************************************************
481 *
482 * Function SMP_ClearLocScOobData
483 *
484 * Description This function is called to clear out the OOB stored locally.
485 *
486 ******************************************************************************/
SMP_ClearLocScOobData()487 void SMP_ClearLocScOobData() { smp_clear_local_oob_data(); }
488
489 /*******************************************************************************
490 *
491 * Function SMP_SirkConfirmDeviceReply
492 *
493 * Description This function is called after Security Manager submitted
494 * verification of device with CSIP.
495 *
496 * Parameters: bd_addr - Address of the device with which verification
497 * was requested
498 * res - comparison result SMP_SUCCESS if success
499 *
500 ******************************************************************************/
SMP_SirkConfirmDeviceReply(const RawAddress & bd_addr,uint8_t res)501 void SMP_SirkConfirmDeviceReply(const RawAddress& bd_addr, uint8_t res) {
502 tSMP_CB* p_cb = &smp_cb;
503
504 log::info("Result:{}", res);
505
506 /* If timeout already expired or has been canceled, ignore the reply */
507 if (p_cb->cb_evt != SMP_SIRK_VERIFICATION_REQ_EVT) {
508 log::warn("Wrong State:{}", p_cb->state);
509 return;
510 }
511
512 if (bd_addr != p_cb->pairing_bda) {
513 log::warn("Wrong confirmation BD Addr: {} vs expected {}", bd_addr, p_cb->pairing_bda);
514 return;
515 }
516
517 tSMP_INT_DATA smp_int_data;
518 if (res != SMP_SUCCESS) {
519 log::warn("Verification fails");
520 /* send pairing failure */
521 smp_int_data.status = SMP_SIRK_DEVICE_INVALID;
522 smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
523 } else {
524 smp_int_data.status = SMP_SUCCESS;
525 smp_sm_event(p_cb, SMP_SIRK_DEVICE_VALID_EVT, &smp_int_data);
526 }
527 }
528