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