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