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