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