1 /****************************************************************************** 2 * 3 * Copyright (C) 1999-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 GATT authentication handling functions 22 * 23 ******************************************************************************/ 24 #include "bt_target.h" 25 #include "bt_utils.h" 26 27 #include <string.h> 28 #include "bt_common.h" 29 30 #include "btm_int.h" 31 #include "gatt_api.h" 32 #include "gatt_int.h" 33 #include "osi/include/osi.h" 34 35 /******************************************************************************* 36 * 37 * Function gatt_sign_data 38 * 39 * Description This function sign the data for write command. 40 * 41 * Returns true if encrypted, otherwise false. 42 * 43 ******************************************************************************/ 44 static bool gatt_sign_data(tGATT_CLCB* p_clcb) { 45 tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf; 46 uint8_t *p_data = NULL, *p; 47 uint16_t payload_size = p_clcb->p_tcb->payload_size; 48 bool status = false; 49 uint8_t* p_signature; 50 51 /* do not need to mark channel securoty activity for data signing */ 52 gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_OK); 53 54 p_data = 55 (uint8_t*)osi_malloc(p_attr->len + 3); /* 3 = 2 byte handle + opcode */ 56 57 p = p_data; 58 UINT8_TO_STREAM(p, GATT_SIGN_CMD_WRITE); 59 UINT16_TO_STREAM(p, p_attr->handle); 60 ARRAY_TO_STREAM(p, p_attr->value, p_attr->len); 61 62 /* sign data length should be attribulte value length plus 2B handle + 1B op 63 * code */ 64 if ((payload_size - GATT_AUTH_SIGN_LEN - 3) < p_attr->len) 65 p_attr->len = payload_size - GATT_AUTH_SIGN_LEN - 3; 66 67 p_signature = p_attr->value + p_attr->len; 68 if (BTM_BleDataSignature( 69 p_clcb->p_tcb->peer_bda, p_data, 70 (uint16_t)(p_attr->len + 3), /* 3 = 2 byte handle + opcode */ 71 p_signature)) { 72 p_attr->len += BTM_BLE_AUTH_SIGN_LEN; 73 gatt_set_ch_state(p_clcb->p_tcb, GATT_CH_OPEN); 74 gatt_act_write(p_clcb, GATT_SEC_SIGN_DATA); 75 } else { 76 gatt_end_operation(p_clcb, GATT_INTERNAL_ERROR, NULL); 77 } 78 79 osi_free(p_data); 80 81 return status; 82 } 83 84 /******************************************************************************* 85 * 86 * Function gatt_verify_signature 87 * 88 * Description This function start to verify the sign data when receiving 89 * the data from peer device. 90 * 91 * Returns 92 * 93 ******************************************************************************/ 94 void gatt_verify_signature(tGATT_TCB* p_tcb, BT_HDR* p_buf) { 95 uint16_t cmd_len; 96 uint8_t op_code; 97 uint8_t *p, *p_orig = (uint8_t *)(p_buf + 1) + p_buf->offset; 98 uint32_t counter; 99 100 if (p_buf->len < GATT_AUTH_SIGN_LEN + 4) { 101 GATT_TRACE_ERROR("%s: Data length %u less than expected %u", __func__, 102 p_buf->len, GATT_AUTH_SIGN_LEN + 4); 103 return; 104 } 105 cmd_len = p_buf->len - GATT_AUTH_SIGN_LEN + 4; 106 p = p_orig + cmd_len - 4; 107 STREAM_TO_UINT32(counter, p); 108 109 if (BTM_BleVerifySignature(p_tcb->peer_bda, p_orig, cmd_len, counter, p)) { 110 STREAM_TO_UINT8(op_code, p_orig); 111 gatt_server_handle_client_req(p_tcb, op_code, (uint16_t)(p_buf->len - 1), 112 p_orig); 113 } else { 114 /* if this is a bad signature, assume from attacker, ignore it */ 115 GATT_TRACE_ERROR("Signature Verification Failed, data ignored"); 116 } 117 118 return; 119 } 120 /******************************************************************************* 121 * 122 * Function gatt_sec_check_complete 123 * 124 * Description security check complete and proceed to data sending action. 125 * 126 * Returns void. 127 * 128 ******************************************************************************/ 129 void gatt_sec_check_complete(bool sec_check_ok, tGATT_CLCB* p_clcb, 130 uint8_t sec_act) { 131 if (p_clcb && p_clcb->p_tcb && 132 fixed_queue_is_empty(p_clcb->p_tcb->pending_enc_clcb)) { 133 gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE); 134 } 135 136 if (!sec_check_ok) { 137 gatt_end_operation(p_clcb, GATT_AUTH_FAIL, NULL); 138 } else if (p_clcb->operation == GATTC_OPTYPE_WRITE) { 139 gatt_act_write(p_clcb, sec_act); 140 } else if (p_clcb->operation == GATTC_OPTYPE_READ) { 141 gatt_act_read(p_clcb, p_clcb->counter); 142 } 143 } 144 /******************************************************************************* 145 * 146 * Function gatt_enc_cmpl_cback 147 * 148 * Description link encryption complete callback. 149 * 150 * Returns 151 * 152 ******************************************************************************/ 153 void gatt_enc_cmpl_cback(BD_ADDR bd_addr, tBT_TRANSPORT transport, 154 UNUSED_ATTR void* p_ref_data, tBTM_STATUS result) { 155 tGATT_TCB* p_tcb; 156 uint8_t sec_flag; 157 bool status = false; 158 159 GATT_TRACE_DEBUG("gatt_enc_cmpl_cback"); 160 p_tcb = gatt_find_tcb_by_addr(bd_addr, transport); 161 if (p_tcb != NULL) { 162 if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) return; 163 164 tGATT_PENDING_ENC_CLCB* p_buf = 165 (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue( 166 p_tcb->pending_enc_clcb); 167 if (p_buf != NULL) { 168 if (result == BTM_SUCCESS) { 169 if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM) { 170 BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, transport); 171 172 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) { 173 status = true; 174 } 175 } else { 176 status = true; 177 } 178 } 179 gatt_sec_check_complete(status, p_buf->p_clcb, p_tcb->sec_act); 180 osi_free(p_buf); 181 /* start all other pending operation in queue */ 182 for (size_t count = fixed_queue_length(p_tcb->pending_enc_clcb); 183 count > 0; count--) { 184 p_buf = (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue( 185 p_tcb->pending_enc_clcb); 186 if (p_buf != NULL) { 187 gatt_security_check_start(p_buf->p_clcb); 188 osi_free(p_buf); 189 } else 190 break; 191 } 192 } else { 193 GATT_TRACE_ERROR("Unknown operation encryption completed"); 194 } 195 } else { 196 GATT_TRACE_ERROR("enc callback for unknown bd_addr"); 197 } 198 } 199 200 /******************************************************************************* 201 * 202 * Function gatt_notify_enc_cmpl 203 * 204 * Description link encryption complete notification for all encryption 205 * process initiated outside GATT. 206 * 207 * Returns 208 * 209 ******************************************************************************/ 210 void gatt_notify_enc_cmpl(BD_ADDR bd_addr) { 211 tGATT_TCB* p_tcb; 212 uint8_t i = 0; 213 214 p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE); 215 if (p_tcb != NULL) { 216 for (i = 0; i < GATT_MAX_APPS; i++) { 217 if (gatt_cb.cl_rcb[i].in_use && gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb) { 218 (*gatt_cb.cl_rcb[i].app_cb.p_enc_cmpl_cb)(gatt_cb.cl_rcb[i].gatt_if, 219 bd_addr); 220 } 221 } 222 223 if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) { 224 gatt_set_sec_act(p_tcb, GATT_SEC_NONE); 225 226 size_t count = fixed_queue_length(p_tcb->pending_enc_clcb); 227 for (; count > 0; count--) { 228 tGATT_PENDING_ENC_CLCB* p_buf = 229 (tGATT_PENDING_ENC_CLCB*)fixed_queue_try_dequeue( 230 p_tcb->pending_enc_clcb); 231 if (p_buf != NULL) { 232 gatt_security_check_start(p_buf->p_clcb); 233 osi_free(p_buf); 234 } else 235 break; 236 } 237 } 238 } else { 239 GATT_TRACE_DEBUG("notify GATT for encryption completion of unknown device"); 240 } 241 return; 242 } 243 /******************************************************************************* 244 * 245 * Function gatt_set_sec_act 246 * 247 * Description This function set the sec_act in clcb 248 * 249 * Returns none 250 * 251 ******************************************************************************/ 252 void gatt_set_sec_act(tGATT_TCB* p_tcb, tGATT_SEC_ACTION sec_act) { 253 if (p_tcb) { 254 p_tcb->sec_act = sec_act; 255 } 256 } 257 /******************************************************************************* 258 * 259 * Function gatt_get_sec_act 260 * 261 * Description This function get the sec_act in clcb 262 * 263 * Returns none 264 * 265 ******************************************************************************/ 266 tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb) { 267 tGATT_SEC_ACTION sec_act = GATT_SEC_NONE; 268 if (p_tcb) { 269 sec_act = p_tcb->sec_act; 270 } 271 return sec_act; 272 } 273 /******************************************************************************* 274 * 275 * Function gatt_determine_sec_act 276 * 277 * Description This routine determine the security action based on 278 * auth_request and current link status 279 * 280 * Returns tGATT_SEC_ACTION security action 281 * 282 ******************************************************************************/ 283 tGATT_SEC_ACTION gatt_determine_sec_act(tGATT_CLCB* p_clcb) { 284 tGATT_SEC_ACTION act = GATT_SEC_OK; 285 uint8_t sec_flag; 286 tGATT_TCB* p_tcb = p_clcb->p_tcb; 287 tGATT_AUTH_REQ auth_req = p_clcb->auth_req; 288 bool is_link_encrypted = false; 289 bool is_link_key_known = false; 290 bool is_key_mitm = false; 291 uint8_t key_type; 292 tBTM_BLE_SEC_REQ_ACT sec_act = BTM_LE_SEC_NONE; 293 294 if (auth_req == GATT_AUTH_REQ_NONE) return act; 295 296 BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, 297 p_clcb->p_tcb->transport); 298 299 btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act); 300 301 /* if a encryption is pending, need to wait */ 302 if (sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD && auth_req != GATT_AUTH_REQ_NONE) 303 return GATT_SEC_ENC_PENDING; 304 305 if (sec_flag & (BTM_SEC_FLAG_ENCRYPTED | BTM_SEC_FLAG_LKEY_KNOWN)) { 306 if (sec_flag & BTM_SEC_FLAG_ENCRYPTED) is_link_encrypted = true; 307 308 is_link_key_known = true; 309 310 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) is_key_mitm = true; 311 } 312 313 /* first check link key upgrade required or not */ 314 switch (auth_req) { 315 case GATT_AUTH_REQ_MITM: 316 case GATT_AUTH_REQ_SIGNED_MITM: 317 if (!is_key_mitm) act = GATT_SEC_ENCRYPT_MITM; 318 break; 319 320 case GATT_AUTH_REQ_NO_MITM: 321 case GATT_AUTH_REQ_SIGNED_NO_MITM: 322 if (!is_link_key_known) act = GATT_SEC_ENCRYPT_NO_MITM; 323 break; 324 default: 325 break; 326 } 327 328 /* now check link needs to be encrypted or not if the link key upgrade is not 329 * required */ 330 if (act == GATT_SEC_OK) { 331 if (p_tcb->transport == BT_TRANSPORT_LE && 332 (p_clcb->operation == GATTC_OPTYPE_WRITE) && 333 (p_clcb->op_subtype == GATT_WRITE_NO_RSP)) { 334 /* this is a write command request 335 check data signing required or not */ 336 if (!is_link_encrypted) { 337 btm_ble_get_enc_key_type(p_tcb->peer_bda, &key_type); 338 339 if ((key_type & BTM_LE_KEY_LCSRK) && 340 ((auth_req == GATT_AUTH_REQ_SIGNED_NO_MITM) || 341 (auth_req == GATT_AUTH_REQ_SIGNED_MITM))) { 342 act = GATT_SEC_SIGN_DATA; 343 } else { 344 act = GATT_SEC_ENCRYPT; 345 } 346 } 347 } else { 348 if (!is_link_encrypted) { 349 act = GATT_SEC_ENCRYPT; 350 } 351 } 352 } 353 354 return act; 355 } 356 357 /******************************************************************************* 358 * 359 * Function gatt_get_link_encrypt_status 360 * 361 * Description This routine get the encryption status of the specified link 362 * 363 * 364 * Returns tGATT_STATUS link encryption status 365 * 366 ******************************************************************************/ 367 tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB* p_tcb) { 368 tGATT_STATUS encrypt_status = GATT_NOT_ENCRYPTED; 369 uint8_t sec_flag = 0; 370 371 BTM_GetSecurityFlagsByTransport(p_tcb->peer_bda, &sec_flag, p_tcb->transport); 372 373 if ((sec_flag & BTM_SEC_FLAG_ENCRYPTED) && 374 (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)) { 375 encrypt_status = GATT_ENCRYPED_NO_MITM; 376 if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED) 377 encrypt_status = GATT_ENCRYPED_MITM; 378 } 379 380 GATT_TRACE_DEBUG("gatt_get_link_encrypt_status status=0x%x", encrypt_status); 381 return encrypt_status; 382 } 383 384 /******************************************************************************* 385 * 386 * Function gatt_convert_sec_action 387 * 388 * Description Convert GATT security action enum into equivalent 389 * BTM BLE security action enum 390 * 391 * Returns bool true - conversation is successful 392 * 393 ******************************************************************************/ 394 static bool gatt_convert_sec_action(tGATT_SEC_ACTION gatt_sec_act, 395 tBTM_BLE_SEC_ACT* p_btm_sec_act) { 396 bool status = true; 397 switch (gatt_sec_act) { 398 case GATT_SEC_ENCRYPT: 399 *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT; 400 break; 401 case GATT_SEC_ENCRYPT_NO_MITM: 402 *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT_NO_MITM; 403 break; 404 case GATT_SEC_ENCRYPT_MITM: 405 *p_btm_sec_act = BTM_BLE_SEC_ENCRYPT_MITM; 406 break; 407 default: 408 status = false; 409 break; 410 } 411 412 return status; 413 } 414 /******************************************************************************* 415 * 416 * Function gatt_check_enc_req 417 * 418 * Description check link security. 419 * 420 * Returns true if encrypted, otherwise false. 421 * 422 ******************************************************************************/ 423 bool gatt_security_check_start(tGATT_CLCB* p_clcb) { 424 tGATT_TCB* p_tcb = p_clcb->p_tcb; 425 tGATT_SEC_ACTION gatt_sec_act; 426 tBTM_BLE_SEC_ACT btm_ble_sec_act; 427 bool status = true; 428 tBTM_STATUS btm_status; 429 tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb); 430 431 gatt_sec_act = gatt_determine_sec_act(p_clcb); 432 433 if (sec_act_old == GATT_SEC_NONE) gatt_set_sec_act(p_tcb, gatt_sec_act); 434 435 switch (gatt_sec_act) { 436 case GATT_SEC_SIGN_DATA: 437 GATT_TRACE_DEBUG("gatt_security_check_start: Do data signing"); 438 gatt_sign_data(p_clcb); 439 break; 440 case GATT_SEC_ENCRYPT: 441 case GATT_SEC_ENCRYPT_NO_MITM: 442 case GATT_SEC_ENCRYPT_MITM: 443 if (sec_act_old < GATT_SEC_ENCRYPT) { 444 GATT_TRACE_DEBUG( 445 "gatt_security_check_start: Encrypt now or key upgreade first"); 446 gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act); 447 btm_status = 448 BTM_SetEncryption(p_tcb->peer_bda, p_tcb->transport, 449 gatt_enc_cmpl_cback, NULL, btm_ble_sec_act); 450 if ((btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED)) { 451 GATT_TRACE_ERROR( 452 "gatt_security_check_start BTM_SetEncryption failed " 453 "btm_status=%d", 454 btm_status); 455 status = false; 456 } 457 } 458 if (status) gatt_add_pending_enc_channel_clcb(p_tcb, p_clcb); 459 break; 460 case GATT_SEC_ENC_PENDING: 461 gatt_add_pending_enc_channel_clcb(p_tcb, p_clcb); 462 /* wait for link encrypotion to finish */ 463 break; 464 default: 465 gatt_sec_check_complete(true, p_clcb, gatt_sec_act); 466 break; 467 } 468 469 if (status == false) { 470 gatt_set_sec_act(p_tcb, GATT_SEC_NONE); 471 gatt_set_ch_state(p_tcb, GATT_CH_OPEN); 472 } 473 474 return status; 475 } 476