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