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