1/****************************************************************************** 2 * 3 * Copyright (C) 2009-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 database building and query functions 22 * 23 ******************************************************************************/ 24 25#include "bt_target.h" 26 27#include "bt_trace.h" 28#include "bt_utils.h" 29 30#include <stdio.h> 31#include <string.h> 32#include "btm_int.h" 33#include "gatt_int.h" 34#include "l2c_api.h" 35#include "osi/include/osi.h" 36 37using base::StringPrintf; 38/******************************************************************************* 39 * L O C A L F U N C T I O N P R O T O T Y P E S * 40 ******************************************************************************/ 41static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid, 42 tGATT_PERM perm); 43static tGATT_STATUS gatts_send_app_read_request( 44 tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, 45 uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type); 46 47/** 48 * Initialize a memory space to be a service database. 49 */ 50void gatts_init_service_db(tGATT_SVC_DB& db, tBT_UUID* p_service, bool is_pri, 51 uint16_t s_hdl, uint16_t num_handle) { 52 db.attr_list.reserve(num_handle); 53 54 VLOG(1) << StringPrintf("%s: s_hdl= %d num_handle= %d", __func__, s_hdl, 55 num_handle); 56 57 /* update service database information */ 58 db.next_handle = s_hdl; 59 db.end_handle = s_hdl + num_handle; 60 61 /* add service declration record */ 62 tBT_UUID uuid = {LEN_UUID_16, {0}}; 63 uuid.uu.uuid16 = is_pri ? GATT_UUID_PRI_SERVICE : GATT_UUID_SEC_SERVICE; 64 tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 65 attr.p_value.reset((tGATT_ATTR_VALUE*)(new tBT_UUID)); 66 memcpy(&attr.p_value->uuid, p_service, sizeof(tBT_UUID)); 67} 68 69tBT_UUID* gatts_get_service_uuid(tGATT_SVC_DB* p_db) { 70 if (!p_db || p_db->attr_list.empty()) { 71 LOG(ERROR) << "service DB empty"; 72 return NULL; 73 } else { 74 return &p_db->attr_list[0].p_value->uuid; 75 } 76} 77 78/** Check attribute readability. Returns status of operation. */ 79static tGATT_STATUS gatts_check_attr_readability(const tGATT_ATTR& attr, 80 UNUSED_ATTR uint16_t offset, 81 bool read_long, 82 tGATT_SEC_FLAG sec_flag, 83 uint8_t key_size) { 84 uint16_t min_key_size; 85 tGATT_PERM perm = attr.permission; 86 87 min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12)); 88 if (min_key_size != 0) { 89 min_key_size += 6; 90 } 91 92 if (!(perm & GATT_READ_ALLOWED)) { 93 LOG(ERROR) << __func__ << ": GATT_READ_NOT_PERMIT"; 94 return GATT_READ_NOT_PERMIT; 95 } 96 97 if ((perm & GATT_READ_AUTH_REQUIRED) && 98 !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) && 99 !(sec_flag & BTM_SEC_FLAG_ENCRYPTED)) { 100 LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION"; 101 return GATT_INSUF_AUTHENTICATION; 102 } 103 104 if ((perm & GATT_READ_MITM_REQUIRED) && 105 !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { 106 LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION: MITM Required"; 107 return GATT_INSUF_AUTHENTICATION; 108 } 109 110 if ((perm & GATT_READ_ENCRYPTED_REQUIRED) && 111 !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 112 LOG(ERROR) << __func__ << ": GATT_INSUF_ENCRYPTION"; 113 return GATT_INSUF_ENCRYPTION; 114 } 115 116 if ((perm & GATT_READ_ENCRYPTED_REQUIRED) && 117 (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && (key_size < min_key_size)) { 118 LOG(ERROR) << __func__ << ": GATT_INSUF_KEY_SIZE"; 119 return GATT_INSUF_KEY_SIZE; 120 } 121 122 if (read_long && attr.uuid.len == LEN_UUID_16) { 123 switch (attr.uuid.uu.uuid16) { 124 case GATT_UUID_PRI_SERVICE: 125 case GATT_UUID_SEC_SERVICE: 126 case GATT_UUID_CHAR_DECLARE: 127 case GATT_UUID_INCLUDE_SERVICE: 128 case GATT_UUID_CHAR_EXT_PROP: 129 case GATT_UUID_CHAR_CLIENT_CONFIG: 130 case GATT_UUID_CHAR_SRVR_CONFIG: 131 case GATT_UUID_CHAR_PRESENT_FORMAT: 132 LOG(ERROR) << __func__ << ": GATT_NOT_LONG"; 133 return GATT_NOT_LONG; 134 135 default: 136 break; 137 } 138 } 139 140 return GATT_SUCCESS; 141} 142 143/******************************************************************************* 144 * 145 * Function read_attr_value 146 * 147 * Description Utility function to read an attribute value. 148 * 149 * Parameter p_attr: pointer to the attribute to read. 150 * offset: read offset. 151 * p_value: output parameter to carry out the attribute value. 152 * p_len: output parameter to carry out the attribute length. 153 * read_long: this is a read blob request. 154 * mtu: MTU 155 * sec_flag: current link security status. 156 * key_size: encryption key size. 157 * 158 * Returns status of operation. 159 * 160 ******************************************************************************/ 161static tGATT_STATUS read_attr_value(tGATT_ATTR& attr16, uint16_t offset, 162 uint8_t** p_data, bool read_long, 163 uint16_t mtu, uint16_t* p_len, 164 tGATT_SEC_FLAG sec_flag, uint8_t key_size) { 165 uint16_t len = 0, uuid16 = 0; 166 uint8_t* p = *p_data; 167 168 VLOG(1) 169 << __func__ 170 << StringPrintf( 171 " uuid=0x%04x perm=0x%02x sec_flag=0x%x offset=%d read_long=%d", 172 attr16.uuid.uu.uuid16, attr16.permission, sec_flag, offset, 173 read_long); 174 175 tGATT_STATUS status = gatts_check_attr_readability(attr16, offset, read_long, 176 sec_flag, key_size); 177 178 if (status != GATT_SUCCESS) return status; 179 180 if (attr16.uuid.len == LEN_UUID_16) uuid16 = attr16.uuid.uu.uuid16; 181 182 status = GATT_NO_RESOURCES; 183 184 if (uuid16 == GATT_UUID_PRI_SERVICE || uuid16 == GATT_UUID_SEC_SERVICE) { 185 len = attr16.p_value->uuid.len; 186 if (mtu >= attr16.p_value->uuid.len) { 187 gatt_build_uuid_to_stream(&p, attr16.p_value->uuid); 188 status = GATT_SUCCESS; 189 } 190 } else if (uuid16 == GATT_UUID_CHAR_DECLARE) { 191 tGATT_ATTR* val_attr = &attr16 + 1; 192 len = (val_attr->uuid.len == LEN_UUID_16) ? 5 : 19; 193 194 if (mtu >= len) { 195 UINT8_TO_STREAM(p, attr16.p_value->char_decl.property); 196 UINT16_TO_STREAM(p, attr16.p_value->char_decl.char_val_handle); 197 198 if (val_attr->uuid.len == LEN_UUID_16) { 199 UINT16_TO_STREAM(p, val_attr->uuid.uu.uuid16); 200 } 201 /* convert a 32bits UUID to 128 bits */ 202 else if (val_attr->uuid.len == LEN_UUID_32) { 203 gatt_convert_uuid32_to_uuid128(p, val_attr->uuid.uu.uuid32); 204 p += LEN_UUID_128; 205 } else { 206 ARRAY_TO_STREAM(p, val_attr->uuid.uu.uuid128, LEN_UUID_128); 207 } 208 status = GATT_SUCCESS; 209 } 210 211 } else if (uuid16 == GATT_UUID_INCLUDE_SERVICE) { 212 if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) 213 len = 6; 214 else 215 len = 4; 216 217 if (mtu >= len) { 218 UINT16_TO_STREAM(p, attr16.p_value->incl_handle.s_handle); 219 UINT16_TO_STREAM(p, attr16.p_value->incl_handle.e_handle); 220 221 if (attr16.p_value->incl_handle.service_type.len == LEN_UUID_16) { 222 UINT16_TO_STREAM(p, attr16.p_value->incl_handle.service_type.uu.uuid16); 223 } 224 status = GATT_SUCCESS; 225 } 226 } else /* characteristic description or characteristic value */ 227 { 228 status = GATT_PENDING; 229 } 230 231 *p_len = len; 232 *p_data = p; 233 return status; 234} 235 236/******************************************************************************* 237 * 238 * Function gatts_db_read_attr_value_by_type 239 * 240 * Description Query attribute value by attribute type. 241 * 242 * Parameter p_db: pointer to the attribute database. 243 * p_rsp: Read By type response data. 244 * s_handle: starting handle of the range we are looking for. 245 * e_handle: ending handle of the range we are looking for. 246 * type: Attribute type. 247 * mtu: MTU. 248 * sec_flag: current link security status. 249 * key_size: encryption key size. 250 * 251 * Returns Status of the operation. 252 * 253 ******************************************************************************/ 254tGATT_STATUS gatts_db_read_attr_value_by_type( 255 tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, BT_HDR* p_rsp, 256 uint16_t s_handle, uint16_t e_handle, tBT_UUID type, uint16_t* p_len, 257 tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id, 258 uint16_t* p_cur_handle) { 259 tGATT_STATUS status = GATT_NOT_FOUND; 260 uint16_t len = 0; 261 uint8_t* p = (uint8_t*)(p_rsp + 1) + p_rsp->len + L2CAP_MIN_OFFSET; 262 263 if (p_db) { 264 for (tGATT_ATTR& attr : p_db->attr_list) { 265 tBT_UUID attr_uuid = attr.uuid; 266 267 if (attr.handle >= s_handle && gatt_uuid_compare(type, attr_uuid)) { 268 if (*p_len <= 2) { 269 status = GATT_NO_RESOURCES; 270 break; 271 } 272 273 UINT16_TO_STREAM(p, attr.handle); 274 275 status = read_attr_value(attr, 0, &p, false, (uint16_t)(*p_len - 2), 276 &len, sec_flag, key_size); 277 278 if (status == GATT_PENDING) { 279 status = gatts_send_app_read_request(tcb, op_code, attr.handle, 0, 280 trans_id, attr.gatt_type); 281 282 /* one callback at a time */ 283 break; 284 } else if (status == GATT_SUCCESS) { 285 if (p_rsp->offset == 0) p_rsp->offset = len + 2; 286 287 if (p_rsp->offset == len + 2) { 288 p_rsp->len += (len + 2); 289 *p_len -= (len + 2); 290 } else { 291 LOG(ERROR) << "format mismatch"; 292 status = GATT_NO_RESOURCES; 293 break; 294 } 295 } else { 296 *p_cur_handle = attr.handle; 297 break; 298 } 299 } 300 } 301 } 302 303#if (BLE_DELAY_REQUEST_ENC == TRUE) 304 uint8_t flag = 0; 305 if (BTM_GetSecurityFlags(tcb.peer_bda, &flag)) { 306 if ((tcb.att_lcid == L2CAP_ATT_CID) && (status == GATT_PENDING) && 307 (type.uu.uuid16 == GATT_UUID_GAP_DEVICE_NAME)) { 308 if ((flag & (BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_FLAG_ENCRYPTED)) == 309 BTM_SEC_LINK_KEY_KNOWN) { 310 tACL_CONN* p = btm_bda_to_acl(tcb.peer_bda, BT_TRANSPORT_LE); 311 if ((p != NULL) && (p->link_role == BTM_ROLE_MASTER)) 312 btm_ble_set_encryption(tcb.peer_bda, BTM_BLE_SEC_ENCRYPT, 313 p->link_role); 314 } 315 } 316 } 317#endif 318 return status; 319} 320 321/** 322 * This function adds an included service into a database. 323 * 324 * Parameter db: database pointer. 325 * inc_srvc_type: included service type. 326 * 327 * Returns Status of the operation. 328 * 329 */ 330uint16_t gatts_add_included_service(tGATT_SVC_DB& db, uint16_t s_handle, 331 uint16_t e_handle, tBT_UUID service) { 332 tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_INCLUDE_SERVICE}}; 333 334 VLOG(1) << StringPrintf("%s: s_hdl = 0x%04x e_hdl = 0x%04x uuid = 0x%04x", 335 __func__, s_handle, e_handle, service.uu.uuid16); 336 337 if (service.len == 0 || s_handle == 0 || e_handle == 0) { 338 LOG(ERROR) << __func__ << ": Illegal Params."; 339 return 0; 340 } 341 342 tGATT_ATTR& attr = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 343 344 attr.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_INCL_SRVC)); 345 attr.p_value->incl_handle.s_handle = s_handle; 346 attr.p_value->incl_handle.e_handle = e_handle; 347 memcpy(&attr.p_value->incl_handle.service_type, &service, sizeof(tBT_UUID)); 348 349 return attr.handle; 350} 351 352/******************************************************************************* 353 * 354 * Function gatts_add_characteristic 355 * 356 * Description This function add a characteristics and its descriptor into 357 * a servce identified by the service database pointer. 358 * 359 * Parameter db: database. 360 * perm: permission (authentication and key size requirements) 361 * property: property of the characteristic. 362 * p_char: characteristic value information. 363 * 364 * Returns Status of te operation. 365 * 366 ******************************************************************************/ 367uint16_t gatts_add_characteristic(tGATT_SVC_DB& db, tGATT_PERM perm, 368 tGATT_CHAR_PROP property, 369 tBT_UUID& char_uuid) { 370 tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_DECLARE}}; 371 372 VLOG(1) << StringPrintf("%s: perm=0x%0x property=0x%0x", __func__, perm, 373 property); 374 375 tGATT_ATTR& char_decl = allocate_attr_in_db(db, uuid, GATT_PERM_READ); 376 tGATT_ATTR& char_val = allocate_attr_in_db(db, char_uuid, perm); 377 378 char_decl.p_value.reset((tGATT_ATTR_VALUE*)(new tGATT_CHAR_DECL)); 379 char_decl.p_value->char_decl.property = property; 380 char_decl.p_value->char_decl.char_val_handle = char_val.handle; 381 char_val.gatt_type = BTGATT_DB_CHARACTERISTIC; 382 return char_val.handle; 383} 384 385/******************************************************************************* 386 * 387 * Function gatt_convertchar_descr_type 388 * 389 * Description Convert a char descript UUID into descriptor type. 390 * 391 * Returns descriptor type. 392 * 393 ******************************************************************************/ 394uint8_t gatt_convertchar_descr_type(tBT_UUID* p_descr_uuid) { 395 tBT_UUID std_descr = {LEN_UUID_16, {GATT_UUID_CHAR_EXT_PROP}}; 396 397 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 398 return GATT_DESCR_EXT_DSCPTOR; 399 400 std_descr.uu.uuid16++; 401 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 402 return GATT_DESCR_USER_DSCPTOR; 403 404 std_descr.uu.uuid16++; 405 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_CLT_CONFIG; 406 407 std_descr.uu.uuid16++; 408 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) return GATT_DESCR_SVR_CONFIG; 409 410 std_descr.uu.uuid16++; 411 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 412 return GATT_DESCR_PRES_FORMAT; 413 414 std_descr.uu.uuid16++; 415 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 416 return GATT_DESCR_AGGR_FORMAT; 417 418 std_descr.uu.uuid16++; 419 if (gatt_uuid_compare(std_descr, *p_descr_uuid)) 420 return GATT_DESCR_VALID_RANGE; 421 422 return GATT_DESCR_UNKNOWN; 423} 424 425/******************************************************************************* 426 * 427 * Function gatts_add_char_descr 428 * 429 * Description This function add a characteristics descriptor. 430 * 431 * Parameter p_db: database pointer. 432 * perm: characteristic descriptor permission type. 433 * char_dscp_tpye: the characteristic descriptor masks. 434 * p_dscp_params: characteristic descriptors values. 435 * 436 * Returns Status of the operation. 437 * 438 ******************************************************************************/ 439uint16_t gatts_add_char_descr(tGATT_SVC_DB& db, tGATT_PERM perm, 440 tBT_UUID& descr_uuid) { 441 VLOG(1) << StringPrintf("gatts_add_char_descr uuid=0x%04x", 442 descr_uuid.uu.uuid16); 443 444 /* Add characteristic descriptors */ 445 tGATT_ATTR& char_dscptr = allocate_attr_in_db(db, descr_uuid, perm); 446 char_dscptr.gatt_type = BTGATT_DB_DESCRIPTOR; 447 return char_dscptr.handle; 448} 449 450/******************************************************************************/ 451/* Service Attribute Database Query Utility Functions */ 452/******************************************************************************/ 453tGATT_ATTR* find_attr_by_handle(tGATT_SVC_DB* p_db, uint16_t handle) { 454 if (!p_db) return nullptr; 455 456 for (auto& attr : p_db->attr_list) { 457 if (attr.handle == handle) return &attr; 458 if (attr.handle > handle) return nullptr; 459 } 460 461 return nullptr; 462} 463 464/******************************************************************************* 465 * 466 * Function gatts_read_attr_value_by_handle 467 * 468 * Description Query attribute value by attribute handle. 469 * 470 * Parameter p_db: pointer to the attribute database. 471 * handle: Attribute handle to read. 472 * offset: Read offset. 473 * p_value: output parameter to carry out the attribute value. 474 * p_len: output parameter as attribute length read. 475 * read_long: this is a read blob request. 476 * mtu: MTU. 477 * sec_flag: current link security status. 478 * key_size: encryption key size 479 * 480 * Returns Status of operation. 481 * 482 ******************************************************************************/ 483tGATT_STATUS gatts_read_attr_value_by_handle( 484 tGATT_TCB& tcb, tGATT_SVC_DB* p_db, uint8_t op_code, uint16_t handle, 485 uint16_t offset, uint8_t* p_value, uint16_t* p_len, uint16_t mtu, 486 tGATT_SEC_FLAG sec_flag, uint8_t key_size, uint32_t trans_id) { 487 tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 488 if (!p_attr) return GATT_NOT_FOUND; 489 490 uint8_t* pp = p_value; 491 tGATT_STATUS status = read_attr_value(*p_attr, offset, &pp, 492 (bool)(op_code == GATT_REQ_READ_BLOB), 493 mtu, p_len, sec_flag, key_size); 494 495 if (status == GATT_PENDING) { 496 status = gatts_send_app_read_request(tcb, op_code, p_attr->handle, offset, 497 trans_id, p_attr->gatt_type); 498 } 499 return status; 500} 501 502/******************************************************************************* 503 * 504 * Function gatts_read_attr_perm_check 505 * 506 * Description Check attribute readability. 507 * 508 * Parameter p_db: pointer to the attribute database. 509 * handle: Attribute handle to read. 510 * offset: Read offset. 511 * p_value: output parameter to carry out the attribute value. 512 * p_len: output parameter as attribute length read. 513 * read_long: this is a read blob request. 514 * mtu: MTU. 515 * sec_flag: current link security status. 516 * key_size: encryption key size 517 * 518 * Returns Status of operation. 519 * 520 ******************************************************************************/ 521tGATT_STATUS gatts_read_attr_perm_check(tGATT_SVC_DB* p_db, bool is_long, 522 uint16_t handle, 523 tGATT_SEC_FLAG sec_flag, 524 uint8_t key_size) { 525 tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 526 if (!p_attr) return GATT_NOT_FOUND; 527 528 return gatts_check_attr_readability(*p_attr, 0, is_long, sec_flag, key_size); 529} 530 531/******************************************************************************* 532 * 533 * Function gatts_write_attr_perm_check 534 * 535 * Description Write attribute value into database. 536 * 537 * Parameter p_db: pointer to the attribute database. 538 * op_code:op code of this write. 539 * handle: handle of the attribute to write. 540 * offset: Write offset if write op code is write blob. 541 * p_data: Attribute value to write. 542 * len: attribute data length. 543 * sec_flag: current link security status. 544 * key_size: encryption key size 545 * 546 * Returns Status of the operation. 547 * 548 ******************************************************************************/ 549tGATT_STATUS gatts_write_attr_perm_check(tGATT_SVC_DB* p_db, uint8_t op_code, 550 uint16_t handle, uint16_t offset, 551 uint8_t* p_data, uint16_t len, 552 tGATT_SEC_FLAG sec_flag, 553 uint8_t key_size) { 554 VLOG(1) << StringPrintf( 555 "%s: op_code=0x%0x handle=0x%04x offset=%d len=%d sec_flag=0x%0x " 556 "key_size=%d", 557 __func__, op_code, handle, offset, len, sec_flag, key_size); 558 559 tGATT_ATTR* p_attr = find_attr_by_handle(p_db, handle); 560 if (!p_attr) return GATT_NOT_FOUND; 561 562 tGATT_PERM perm = p_attr->permission; 563 uint16_t min_key_size = (((perm & GATT_ENCRYPT_KEY_SIZE_MASK) >> 12)); 564 if (min_key_size != 0) { 565 min_key_size += 6; 566 } 567 VLOG(1) << StringPrintf("%s: p_attr->permission =0x%04x min_key_size==0x%04x", 568 __func__, p_attr->permission, min_key_size); 569 570 if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE) && 571 (perm & GATT_WRITE_SIGNED_PERM)) { 572 /* use the rules for the mixed security see section 10.2.3*/ 573 /* use security mode 1 level 2 when the following condition follows */ 574 /* LE security mode 2 level 1 and LE security mode 1 level 2 */ 575 if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED)) { 576 perm = GATT_PERM_WRITE_ENCRYPTED; 577 } 578 /* use security mode 1 level 3 when the following condition follows */ 579 /* LE security mode 2 level 2 and security mode 1 and LE */ 580 else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) && 581 (perm & GATT_PERM_WRITE_ENCRYPTED)) || 582 /* LE security mode 2 and security mode 1 level 3 */ 583 ((perm & GATT_WRITE_SIGNED_PERM) && 584 (perm & GATT_PERM_WRITE_ENC_MITM))) { 585 perm = GATT_PERM_WRITE_ENC_MITM; 586 } 587 } 588 589 tGATT_STATUS status = GATT_NOT_FOUND; 590 if ((op_code == GATT_SIGN_CMD_WRITE) && !(perm & GATT_WRITE_SIGNED_PERM)) { 591 status = GATT_WRITE_NOT_PERMIT; 592 VLOG(1) << __func__ << ": sign cmd write not allowed"; 593 } 594 if ((op_code == GATT_SIGN_CMD_WRITE) && 595 (sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 596 status = GATT_INVALID_PDU; 597 LOG(ERROR) << __func__ 598 << ": Error!! sign cmd write sent on a encypted link"; 599 } else if (!(perm & GATT_WRITE_ALLOWED)) { 600 status = GATT_WRITE_NOT_PERMIT; 601 LOG(ERROR) << __func__ << ": GATT_WRITE_NOT_PERMIT"; 602 } 603 /* require authentication, but not been authenticated */ 604 else if ((perm & GATT_WRITE_AUTH_REQUIRED) && 605 !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED)) { 606 status = GATT_INSUF_AUTHENTICATION; 607 LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION"; 608 } else if ((perm & GATT_WRITE_MITM_REQUIRED) && 609 !(sec_flag & GATT_SEC_FLAG_LKEY_AUTHED)) { 610 status = GATT_INSUF_AUTHENTICATION; 611 LOG(ERROR) << __func__ << ": GATT_INSUF_AUTHENTICATION: MITM required"; 612 } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) && 613 !(sec_flag & GATT_SEC_FLAG_ENCRYPTED)) { 614 status = GATT_INSUF_ENCRYPTION; 615 LOG(ERROR) << __func__ << ": GATT_INSUF_ENCRYPTION"; 616 } else if ((perm & GATT_WRITE_ENCRYPTED_PERM) && 617 (sec_flag & GATT_SEC_FLAG_ENCRYPTED) && 618 (key_size < min_key_size)) { 619 status = GATT_INSUF_KEY_SIZE; 620 LOG(ERROR) << __func__ << ": GATT_INSUF_KEY_SIZE"; 621 } 622 /* LE security mode 2 attribute */ 623 else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && 624 !(sec_flag & GATT_SEC_FLAG_ENCRYPTED) && 625 (perm & GATT_WRITE_ALLOWED) == 0) { 626 status = GATT_INSUF_AUTHENTICATION; 627 LOG(ERROR) << __func__ 628 << ": GATT_INSUF_AUTHENTICATION: LE security mode 2 required"; 629 } else /* writable: must be char value declaration or char descritpors 630 */ 631 { 632 uint16_t max_size = 0; 633 634 if (p_attr->uuid.len == LEN_UUID_16) { 635 switch (p_attr->uuid.uu.uuid16) { 636 case GATT_UUID_CHAR_PRESENT_FORMAT: /* should be readable only */ 637 case GATT_UUID_CHAR_EXT_PROP: /* should be readable only */ 638 case GATT_UUID_CHAR_AGG_FORMAT: /* should be readable only */ 639 case GATT_UUID_CHAR_VALID_RANGE: 640 status = GATT_WRITE_NOT_PERMIT; 641 break; 642 643 case GATT_UUID_CHAR_CLIENT_CONFIG: 644 /* fall through */ 645 case GATT_UUID_CHAR_SRVR_CONFIG: 646 max_size = 2; 647 /* fall through */ 648 case GATT_UUID_CHAR_DESCRIPTION: 649 default: /* any other must be character value declaration */ 650 status = GATT_SUCCESS; 651 break; 652 } 653 } else if (p_attr->uuid.len == LEN_UUID_128 || 654 p_attr->uuid.len == LEN_UUID_32) { 655 status = GATT_SUCCESS; 656 } else { 657 status = GATT_INVALID_PDU; 658 } 659 660 if (p_data == NULL && len > 0) { 661 status = GATT_INVALID_PDU; 662 } 663 /* these attribute does not allow write blob */ 664 else if ((p_attr->uuid.len == LEN_UUID_16) && 665 (p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_CLIENT_CONFIG || 666 p_attr->uuid.uu.uuid16 == GATT_UUID_CHAR_SRVR_CONFIG)) { 667 if (op_code == GATT_REQ_PREPARE_WRITE && 668 offset != 0) /* does not allow write blob */ 669 { 670 status = GATT_NOT_LONG; 671 LOG(ERROR) << __func__ << ": GATT_NOT_LONG"; 672 } else if (len != max_size) /* data does not match the required format */ 673 { 674 status = GATT_INVALID_ATTR_LEN; 675 LOG(ERROR) << __func__ << ": GATT_INVALID_PDU"; 676 } else { 677 status = GATT_SUCCESS; 678 } 679 } 680 } 681 682 return status; 683} 684 685static void uuid_to_str(const tBT_UUID bt_uuid, char* str_buf, size_t buf_len) { 686 if (bt_uuid.len == LEN_UUID_16) { 687 snprintf(str_buf, buf_len, "0x%04x", bt_uuid.uu.uuid16); 688 } else if (bt_uuid.len == LEN_UUID_32) { 689 snprintf(str_buf, buf_len, "0x%08x", bt_uuid.uu.uuid32); 690 } else if (bt_uuid.len == LEN_UUID_128) { 691 int x = snprintf(str_buf, buf_len, "%02x%02x%02x%02x-%02x%02x-%02x%02x-", 692 bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14], 693 bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12], 694 bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10], 695 bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]); 696 snprintf(&str_buf[x], buf_len - x, "%02x%02x-%02x%02x%02x%02x%02x%02x", 697 bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6], 698 bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4], 699 bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2], 700 bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]); 701 } else 702 snprintf(str_buf, buf_len, "Unknown (len=%d)", bt_uuid.len); 703} 704 705/** 706 * Description Allocate a memory space for a new attribute, and link this 707 * attribute into the database attribute list. 708 * 709 * 710 * Parameter p_db : database pointer. 711 * uuid: attribute UUID 712 * 713 * Returns pointer to the newly allocated attribute. 714 * 715 */ 716static tGATT_ATTR& allocate_attr_in_db(tGATT_SVC_DB& db, const tBT_UUID& uuid, 717 tGATT_PERM perm) { 718 if (db.next_handle >= db.end_handle) { 719 LOG(FATAL) << __func__ 720 << " wrong number of handles! handle_max = " << +db.end_handle 721 << ", next_handle = " << +db.next_handle; 722 } 723 724 db.attr_list.emplace_back(); 725 tGATT_ATTR& attr = db.attr_list.back(); 726 attr.handle = db.next_handle++; 727 attr.uuid = uuid; 728 attr.permission = perm; 729 730 char uuid_str[37]; 731 uuid_to_str(attr.uuid, uuid_str, sizeof(uuid_str)); 732 733 return attr; 734} 735 736/******************************************************************************* 737 * 738 * Function gatts_send_app_read_request 739 * 740 * Description Send application read request callback 741 * 742 * Returns status of operation. 743 * 744 ******************************************************************************/ 745static tGATT_STATUS gatts_send_app_read_request( 746 tGATT_TCB& tcb, uint8_t op_code, uint16_t handle, uint16_t offset, 747 uint32_t trans_id, bt_gatt_db_attribute_type_t gatt_type) { 748 tGATT_SRV_LIST_ELEM& el = *gatt_sr_find_i_rcb_by_handle(handle); 749 uint16_t conn_id = GATT_CREATE_CONN_ID(tcb.tcb_idx, el.gatt_if); 750 751 if (trans_id == 0) { 752 trans_id = gatt_sr_enqueue_cmd(tcb, op_code, handle); 753 gatt_sr_update_cback_cnt(tcb, el.gatt_if, true, true); 754 } 755 756 if (trans_id != 0) { 757 tGATTS_DATA sr_data; 758 memset(&sr_data, 0, sizeof(tGATTS_DATA)); 759 760 sr_data.read_req.handle = handle; 761 sr_data.read_req.is_long = (bool)(op_code == GATT_REQ_READ_BLOB); 762 sr_data.read_req.offset = offset; 763 764 uint8_t opcode; 765 if (gatt_type == BTGATT_DB_DESCRIPTOR) { 766 opcode = GATTS_REQ_TYPE_READ_DESCRIPTOR; 767 } else if (gatt_type == BTGATT_DB_CHARACTERISTIC) { 768 opcode = GATTS_REQ_TYPE_READ_CHARACTERISTIC; 769 } else { 770 LOG(ERROR) << __func__ 771 << ": Attempt to read attribute that's not tied with " 772 "characteristic or descriptor value."; 773 return GATT_ERROR; 774 } 775 776 gatt_sr_send_req_callback(conn_id, trans_id, opcode, &sr_data); 777 return (tGATT_STATUS)GATT_PENDING; 778 } else 779 return (tGATT_STATUS)GATT_BUSY; /* max pending command, application error */ 780} 781