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