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