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