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