• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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