• Home
  • History
  • Annotate
  • 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 #include <base/logging.h>
26 #include <string.h>
27 
28 #include "bt_target.h"
29 #include "bt_utils.h"
30 #include "stack_config.h"
31 
32 #include "gd/os/log.h"
33 #include "gd/os/rand.h"
34 #include "hcimsgs.h"
35 #include "l2c_api.h"
36 #include "l2cdefs.h"
37 #include "main/shim/shim.h"
38 #include "smp_api.h"
39 #include "smp_int.h"
40 #include "stack/btm/btm_dev.h"
41 
42 #include "p_256_ecc_pp.h"
43 
44 /*******************************************************************************
45  *
46  * Function         SMP_Init
47  *
48  * Description      This function initializes the SMP unit.
49  *
50  * Returns          void
51  *
52  ******************************************************************************/
53 void SMP_Init(void) {
54   if (bluetooth::shim::is_gd_shim_enabled()) {
55     LOG(INFO) << "Skipping legacy SMP_Init because GD is enabled";
56     return;
57   }
58 
59   memset(&smp_cb, 0, sizeof(tSMP_CB));
60   smp_cb.smp_rsp_timer_ent = alarm_new("smp.smp_rsp_timer_ent");
61   smp_cb.delayed_auth_timer_ent = alarm_new("smp.delayed_auth_timer_ent");
62 
63 #if defined(SMP_INITIAL_TRACE_LEVEL)
64   smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
65 #else
66   smp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */
67 #endif
68   SMP_TRACE_EVENT("%s", __func__);
69 
70   smp_l2cap_if_init();
71   /* initialization of P-256 parameters */
72   p_256_init_curve();
73 
74   /* Initialize failure case for certification */
75   smp_cb.cert_failure = static_cast<tSMP_STATUS>(
76       stack_config_get_interface()->get_pts_smp_failure_case());
77   if (smp_cb.cert_failure)
78     SMP_TRACE_ERROR("%s PTS FAILURE MODE IN EFFECT (CASE %d)", __func__,
79                     smp_cb.cert_failure);
80 }
81 
82 /*******************************************************************************
83  *
84  * Function         SMP_SetTraceLevel
85  *
86  * Description      This function sets the trace level for SMP.  If called with
87  *                  a value of 0xFF, it simply returns the current trace level.
88  *
89  *                  Input Parameters:
90  *                      level:  The level to set the GATT tracing to:
91  *                      0xff-returns the current setting.
92  *                      0-turns off tracing.
93  *                      >= 1-Errors.
94  *                      >= 2-Warnings.
95  *                      >= 3-APIs.
96  *                      >= 4-Events.
97  *                      >= 5-Debug.
98  *
99  * Returns          The new or current trace level
100  *
101  ******************************************************************************/
102 uint8_t SMP_SetTraceLevel(uint8_t new_level) {
103   if (new_level != 0xFF) smp_cb.trace_level = new_level;
104 
105   return (smp_cb.trace_level);
106 }
107 
108 /*******************************************************************************
109  *
110  * Function         SMP_Register
111  *
112  * Description      This function register for the SMP services callback.
113  *
114  * Returns          void
115  *
116  ******************************************************************************/
117 bool SMP_Register(tSMP_CALLBACK* p_cback) {
118   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
119       << "Legacy SMP API should not be invoked when GD Security is used";
120 
121   SMP_TRACE_EVENT("SMP_Register state=%d", smp_cb.state);
122 
123   if (smp_cb.p_callback != NULL) {
124     SMP_TRACE_ERROR("SMP_Register: duplicate registration, overwrite it");
125   }
126   smp_cb.p_callback = p_cback;
127 
128   return (true);
129 }
130 
131 /*******************************************************************************
132  *
133  * Function         SMP_Pair
134  *
135  * Description      This function call to perform a SMP pairing with peer
136  *                  device. Device support one SMP pairing at one time.
137  *
138  * Parameters       bd_addr - peer device bd address.
139  *
140  * Returns          None
141  *
142  ******************************************************************************/
143 tSMP_STATUS SMP_Pair(const RawAddress& bd_addr) {
144   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
145       << "Legacy SMP API should not be invoked when GD Security is used";
146   tSMP_CB* p_cb = &smp_cb;
147 
148   SMP_TRACE_EVENT("%s: state=%d br_state=%d flag=0x%x, bd_addr=%s", __func__,
149                   p_cb->state, p_cb->br_state, p_cb->flags,
150                   bd_addr.ToString().c_str());
151 
152   if (p_cb->state != SMP_STATE_IDLE ||
153       p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD || p_cb->smp_over_br) {
154     /* pending security on going, reject this one */
155     return SMP_BUSY;
156   } else {
157     p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
158     p_cb->pairing_bda = bd_addr;
159 
160     if (!L2CA_ConnectFixedChnl(L2CAP_SMP_CID, bd_addr)) {
161       tSMP_INT_DATA smp_int_data;
162       smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
163       p_cb->status = SMP_PAIR_INTERNAL_ERR;
164       SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __func__);
165       smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
166       return SMP_PAIR_INTERNAL_ERR;
167     }
168 
169     return SMP_STARTED;
170   }
171 }
172 
173 /*******************************************************************************
174  *
175  * Function         SMP_BR_PairWith
176  *
177  * Description      This function is called to start a SMP pairing over BR/EDR.
178  *                  Device support one SMP pairing at one time.
179  *
180  * Parameters       bd_addr - peer device bd address.
181  *
182  * Returns          SMP_STARTED if pairing started, otherwise the reason for
183  *                  failure.
184  *
185  ******************************************************************************/
186 tSMP_STATUS SMP_BR_PairWith(const RawAddress& bd_addr) {
187   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
188       << "Legacy SMP API should not be invoked when GD Security is used";
189 
190   tSMP_CB* p_cb = &smp_cb;
191 
192   SMP_TRACE_EVENT("%s: state=%d br_state=%d flag=0x%x, bd_addr=%s", __func__,
193                   p_cb->state, p_cb->br_state, p_cb->flags,
194                   bd_addr.ToString().c_str());
195 
196   if (p_cb->state != SMP_STATE_IDLE || p_cb->smp_over_br ||
197       p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD) {
198     /* pending security on going, reject this one */
199     return SMP_BUSY;
200   }
201 
202   p_cb->role = HCI_ROLE_CENTRAL;
203   p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
204   p_cb->smp_over_br = true;
205   p_cb->pairing_bda = bd_addr;
206 
207   if (!L2CA_ConnectFixedChnl(L2CAP_SMP_BR_CID, bd_addr)) {
208     SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __func__);
209     tSMP_INT_DATA smp_int_data;
210     smp_int_data.status = SMP_PAIR_INTERNAL_ERR;
211     p_cb->status = SMP_PAIR_INTERNAL_ERR;
212     smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
213     return SMP_PAIR_INTERNAL_ERR;
214   }
215 
216   return SMP_STARTED;
217 }
218 
219 /*******************************************************************************
220  *
221  * Function         SMP_PairCancel
222  *
223  * Description      This function call to cancel a SMP pairing with peer device.
224  *
225  * Parameters       bd_addr - peer device bd address.
226  *
227  * Returns          true - Pairining is cancelled
228  *
229  ******************************************************************************/
230 bool SMP_PairCancel(const RawAddress& bd_addr) {
231   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
232       << "Legacy SMP API should not be invoked when GD Security is used";
233 
234   tSMP_CB* p_cb = &smp_cb;
235   uint8_t err_code = SMP_PAIR_FAIL_UNKNOWN;
236 
237   // PTS SMP failure test cases
238   if (p_cb->cert_failure == SMP_PASSKEY_ENTRY_FAIL ||
239       p_cb->cert_failure == SMP_NUMERIC_COMPAR_FAIL)
240     err_code = p_cb->cert_failure;
241 
242   SMP_TRACE_EVENT("SMP_CancelPair state=%d flag=0x%x ", p_cb->state,
243                   p_cb->flags);
244   if (p_cb->state != SMP_STATE_IDLE && p_cb->pairing_bda == bd_addr) {
245     p_cb->is_pair_cancel = true;
246     SMP_TRACE_DEBUG("Cancel Pairing: set fail reason Unknown");
247     tSMP_INT_DATA smp_int_data;
248     smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
249     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
250     return true;
251   }
252 
253   return false;
254 }
255 /*******************************************************************************
256  *
257  * Function         SMP_SecurityGrant
258  *
259  * Description      This function is called to grant security process.
260  *
261  * Parameters       bd_addr - peer device bd address.
262  *                  res     - result of the operation SMP_SUCCESS if success.
263  *                            Otherwise, SMP_REPEATED_ATTEMPTS if too many
264  *                            attempts.
265  *
266  * Returns          None
267  *
268  ******************************************************************************/
269 void SMP_SecurityGrant(const RawAddress& bd_addr, tSMP_STATUS res) {
270   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
271       << "Legacy SMP API should not be invoked when GD Security is used";
272 
273   SMP_TRACE_EVENT("SMP_SecurityGrant ");
274 
275   // If just showing consent dialog, send response
276   if (smp_cb.cb_evt == SMP_CONSENT_REQ_EVT) {
277     // If JUSTWORKS, this is used to display the consent dialog
278     if (smp_cb.selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS) {
279       if (res == SMP_SUCCESS) {
280         smp_sm_event(&smp_cb, SMP_SC_NC_OK_EVT, NULL);
281       } else {
282         SMP_TRACE_WARNING("%s() - Consent dialog fails for JUSTWORKS",
283                           __func__);
284         /* send pairing failure */
285         tSMP_INT_DATA smp_int_data;
286         smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
287         smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
288       }
289     } else if (smp_cb.selected_association_model == SMP_MODEL_ENCRYPTION_ONLY) {
290       if (res == SMP_SUCCESS) {
291         smp_cb.sec_level = SMP_SEC_UNAUTHENTICATE;
292 
293         tSMP_KEY key;
294         tSMP_INT_DATA smp_int_data;
295         key.key_type = SMP_KEY_TYPE_TK;
296         key.p_data = smp_cb.tk.data();
297         smp_int_data.key = key;
298 
299         smp_cb.tk = {0};
300         smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
301       } else {
302         SMP_TRACE_WARNING("%s() - Consent dialog fails for ENCRYPTION_ONLY",
303                           __func__);
304         /* send pairing failure */
305         tSMP_INT_DATA smp_int_data;
306         smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
307         smp_sm_event(&smp_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
308       }
309     }
310     return;
311   }
312 
313   if (smp_cb.smp_over_br) {
314     if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
315         smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || smp_cb.pairing_bda != bd_addr) {
316       return;
317     }
318 
319     /* clear the SMP_SEC_REQUEST_EVT event after get grant */
320     /* avoid generating duplicate pair request */
321     smp_cb.cb_evt = SMP_EVT_NONE;
322     tSMP_INT_DATA smp_int_data;
323     smp_int_data.status = res;
324     smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT,
325                                &smp_int_data);
326     return;
327   }
328 
329   if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
330       smp_cb.cb_evt != SMP_SEC_REQUEST_EVT || smp_cb.pairing_bda != bd_addr)
331     return;
332   /* clear the SMP_SEC_REQUEST_EVT event after get grant */
333   /* avoid generate duplicate pair request */
334   smp_cb.cb_evt = SMP_EVT_NONE;
335   tSMP_INT_DATA smp_int_data;
336   smp_int_data.status = res;
337   smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &smp_int_data);
338 }
339 
340 /*******************************************************************************
341  *
342  * Function         SMP_PasskeyReply
343  *
344  * Description      This function is called after Security Manager submitted
345  *                  passkey request to the application.
346  *
347  * Parameters:      bd_addr - Address of the device for which passkey was
348  *                            requested
349  *                  res     - result of the operation SMP_SUCCESS if success
350  *                  passkey - numeric value in the range of
351  *                            BTM_MIN_PASSKEY_VAL(0) -
352  *                            BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
353  *
354  ******************************************************************************/
355 void SMP_PasskeyReply(const RawAddress& bd_addr, uint8_t res,
356                       uint32_t passkey) {
357   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
358       << "Legacy SMP API should not be invoked when GD Security is used";
359 
360   tSMP_CB* p_cb = &smp_cb;
361 
362   SMP_TRACE_EVENT("SMP_PasskeyReply: Key: %d  Result:%d", passkey, res);
363 
364   /* If timeout already expired or has been canceled, ignore the reply */
365   if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT) {
366     SMP_TRACE_WARNING("SMP_PasskeyReply() - Wrong State: %d", p_cb->state);
367     return;
368   }
369 
370   if (bd_addr != p_cb->pairing_bda) {
371     SMP_TRACE_ERROR("SMP_PasskeyReply() - Wrong BD Addr");
372     return;
373   }
374 
375   if (btm_find_dev(bd_addr) == NULL) {
376     SMP_TRACE_ERROR("SMP_PasskeyReply() - no dev CB");
377     return;
378   }
379 
380   if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS) {
381     SMP_TRACE_WARNING(
382         "SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail",
383         passkey);
384     /* send pairing failure */
385     tSMP_INT_DATA smp_int_data;
386     smp_int_data.status = SMP_PASSKEY_ENTRY_FAIL;
387     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
388 
389   } else if (p_cb->selected_association_model ==
390              SMP_MODEL_SEC_CONN_PASSKEY_ENT) {
391     tSMP_INT_DATA smp_int_data;
392     smp_int_data.passkey = passkey;
393     smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
394   } else {
395     smp_convert_string_to_tk(&p_cb->tk, passkey);
396   }
397 
398   return;
399 }
400 
401 /*******************************************************************************
402  *
403  * Function         SMP_ConfirmReply
404  *
405  * Description      This function is called after Security Manager submitted
406  *                  numeric comparison request to the application.
407  *
408  * Parameters:      bd_addr      - Address of the device with which numeric
409  *                                 comparison was requested
410  *                  res          - comparison result SMP_SUCCESS if success
411  *
412  ******************************************************************************/
413 void SMP_ConfirmReply(const RawAddress& bd_addr, uint8_t res) {
414   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
415       << "Legacy SMP API should not be invoked when GD Security is used";
416 
417   tSMP_CB* p_cb = &smp_cb;
418 
419   SMP_TRACE_EVENT("%s: Result:%d", __func__, res);
420 
421   /* If timeout already expired or has been canceled, ignore the reply */
422   if (p_cb->cb_evt != SMP_NC_REQ_EVT) {
423     SMP_TRACE_WARNING("%s() - Wrong State: %d", __func__, p_cb->state);
424     return;
425   }
426 
427   if (bd_addr != p_cb->pairing_bda) {
428     SMP_TRACE_ERROR("%s() - Wrong BD Addr", __func__);
429     return;
430   }
431 
432   if (btm_find_dev(bd_addr) == NULL) {
433     SMP_TRACE_ERROR("%s() - no dev CB", __func__);
434     return;
435   }
436 
437   if (res != SMP_SUCCESS) {
438     SMP_TRACE_WARNING("%s() - Numeric Comparison fails", __func__);
439     /* send pairing failure */
440     tSMP_INT_DATA smp_int_data;
441     smp_int_data.status = SMP_NUMERIC_COMPAR_FAIL;
442     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
443   } else {
444     smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
445   }
446 }
447 
448 /*******************************************************************************
449  *
450  * Function         SMP_OobDataReply
451  *
452  * Description      This function is called to provide the OOB data for
453  *                  SMP in response to SMP_OOB_REQ_EVT
454  *
455  * Parameters:      bd_addr     - Address of the peer device
456  *                  res         - result of the operation SMP_SUCCESS if success
457  *                  p_data      - simple pairing Randomizer  C.
458  *
459  ******************************************************************************/
460 void SMP_OobDataReply(const RawAddress& bd_addr, tSMP_STATUS res, uint8_t len,
461                       uint8_t* p_data) {
462   LOG_ASSERT(!bluetooth::shim::is_gd_shim_enabled())
463       << "Legacy SMP API should not be invoked when GD Security is used";
464 
465   tSMP_CB* p_cb = &smp_cb;
466   tSMP_KEY key;
467 
468   SMP_TRACE_EVENT("%s State: %d  res:%d", __func__, smp_cb.state, res);
469 
470   /* If timeout already expired or has been canceled, ignore the reply */
471   if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
472     return;
473 
474   if (res != SMP_SUCCESS || len == 0 || !p_data) {
475     tSMP_INT_DATA smp_int_data;
476     smp_int_data.status = SMP_OOB_FAIL;
477     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
478   } else {
479     if (len > OCTET16_LEN) len = OCTET16_LEN;
480 
481     memcpy(p_cb->tk.data(), p_data, len);
482 
483     key.key_type = SMP_KEY_TYPE_TK;
484     key.p_data = p_cb->tk.data();
485 
486     tSMP_INT_DATA smp_int_data;
487     smp_int_data.key = key;
488     smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
489   }
490 }
491 
492 /*******************************************************************************
493  *
494  * Function         SMP_SecureConnectionOobDataReply
495  *
496  * Description      This function is called to provide the SC OOB data for
497  *                  SMP in response to SMP_SC_OOB_REQ_EVT
498  *
499  * Parameters:      p_data      - pointer to the data
500  *
501  ******************************************************************************/
502 void SMP_SecureConnectionOobDataReply(uint8_t* p_data) {
503   tSMP_CB* p_cb = &smp_cb;
504 
505   tSMP_SC_OOB_DATA* p_oob = (tSMP_SC_OOB_DATA*)p_data;
506   if (!p_oob) {
507     SMP_TRACE_ERROR("%s received no data", __func__);
508     tSMP_INT_DATA smp_int_data;
509     smp_int_data.status = SMP_OOB_FAIL;
510     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
511     return;
512   }
513 
514   SMP_TRACE_EVENT(
515       "%s req_oob_type: %d, loc_oob_data.present: %d, "
516       "peer_oob_data.present: %d",
517       __func__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
518       p_oob->peer_oob_data.present);
519 
520   if (p_cb->state != SMP_STATE_WAIT_APP_RSP ||
521       p_cb->cb_evt != SMP_SC_OOB_REQ_EVT)
522     return;
523 
524   bool data_missing = false;
525   switch (p_cb->req_oob_type) {
526     case SMP_OOB_PEER:
527       if (!p_oob->peer_oob_data.present) data_missing = true;
528       break;
529     case SMP_OOB_LOCAL:
530       if (!p_oob->loc_oob_data.present) data_missing = true;
531       break;
532     case SMP_OOB_BOTH:
533       // Check for previous local OOB data in cache
534       // This would be in the case data was generated BEFORE pairing was
535       // attempted and this instance is the connector or pairing initiator.
536       // [NOTICE]: Overridding data present here if the data exists so state
537       // machine asks for it later
538       p_oob->loc_oob_data.present = smp_has_local_oob_data();
539       if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present)
540         data_missing = true;
541       break;
542     default:
543       SMP_TRACE_EVENT("Unexpected OOB data type requested. Fail OOB");
544       data_missing = true;
545       break;
546   }
547 
548   tSMP_INT_DATA smp_int_data;
549   if (data_missing) {
550     smp_int_data.status = SMP_OOB_FAIL;
551     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
552     return;
553   }
554 
555   p_cb->sc_oob_data = *p_oob;
556 
557   smp_int_data.p_data = p_data;
558   smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, &smp_int_data);
559 }
560 
561 /*******************************************************************************
562  *
563  * Function         SMP_CrLocScOobData
564  *
565  * Description      This function is called to generate a public key to be
566  *                  passed to a remote device via Out of Band transport.
567  *
568  ******************************************************************************/
569 void SMP_CrLocScOobData() {
570   tSMP_INT_DATA smp_int_data;
571   smp_sm_event(&smp_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, &smp_int_data);
572 }
573 
574 /*******************************************************************************
575  *
576  * Function         SMP_ClearLocScOobData
577  *
578  * Description      This function is called to clear out the OOB stored locally.
579  *
580  ******************************************************************************/
581 void SMP_ClearLocScOobData() { smp_clear_local_oob_data(); }
582