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