1 /* 2 * Copyright 2021 HIMSA II K/S - www.himsa.com. 3 * Represented by EHIMA - www.ehima.com 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 #pragma once 19 #include <base/logging.h> 20 #include <base/strings/string_number_conversions.h> 21 22 #include <algorithm> 23 #include <map> 24 #include <vector> 25 26 #include "bta_csis_api.h" 27 #include "bta_gatt_api.h" 28 #include "bta_groups.h" 29 #include "btif_storage.h" 30 #include "gap_api.h" 31 #include "gd/common/init_flags.h" 32 #include "gd/common/strings.h" 33 #include "stack/crypto_toolbox/crypto_toolbox.h" 34 35 namespace bluetooth { 36 namespace csis { 37 38 using bluetooth::csis::CsisLockCb; 39 40 // CSIP additions 41 /* Generic UUID is used when CSIS is not included in any context */ 42 static const bluetooth::Uuid kCsisServiceUuid = bluetooth::Uuid::From16Bit(0x1846); 43 static const bluetooth::Uuid kCsisSirkUuid = bluetooth::Uuid::From16Bit(0x2B84); 44 static const bluetooth::Uuid kCsisSizeUuid = bluetooth::Uuid::From16Bit(0x2B85); 45 static const bluetooth::Uuid kCsisLockUuid = bluetooth::Uuid::From16Bit(0x2B86); 46 static const bluetooth::Uuid kCsisRankUuid = bluetooth::Uuid::From16Bit(0x2B87); 47 48 static constexpr uint8_t kCsisErrorCodeLockDenied = 0x80; 49 static constexpr uint8_t kCsisErrorCodeReleaseNotAllowed = 0x81; 50 static constexpr uint8_t kCsisErrorCodeInvalidValue = 0x82; 51 static constexpr uint8_t kCsisErrorCodeLockAccessSirkRejected = 0x83; 52 static constexpr uint8_t kCsisErrorCodeLockOobSirkOnly = 0x84; 53 static constexpr uint8_t kCsisErrorCodeLockAlreadyGranted = 0x85; 54 55 static constexpr uint8_t kCsisSirkTypeEncrypted = 0x00; 56 static constexpr uint8_t kCsisSirkCharLen = 17; 57 58 struct hdl_pair { hdl_pairhdl_pair59 hdl_pair() {} hdl_pairhdl_pair60 hdl_pair(uint16_t val_hdl, uint16_t ccc_hdl) : val_hdl(val_hdl), ccc_hdl(ccc_hdl) {} 61 62 uint16_t val_hdl; 63 uint16_t ccc_hdl; 64 }; 65 66 /* CSIS Types */ 67 static constexpr uint8_t kDefaultScanDurationS = 5; 68 static constexpr uint8_t kDefaultCsisSetSize = 1; 69 static constexpr uint8_t kUnknownRank = 0xff; 70 71 /* Enums */ 72 enum class CsisLockState : uint8_t { 73 CSIS_STATE_UNSET = 0x00, 74 CSIS_STATE_UNLOCKED, 75 CSIS_STATE_LOCKED 76 }; 77 78 enum class CsisDiscoveryState : uint8_t { 79 CSIS_DISCOVERY_IDLE = 0x00, 80 CSIS_DISCOVERY_ONGOING, 81 CSIS_DISCOVERY_COMPLETED, 82 }; 83 84 class GattServiceDevice { 85 public: 86 RawAddress addr; 87 /* 88 * This is true only during first connection to profile, until we store the 89 * device. 90 */ 91 bool first_connection; 92 93 /* 94 * We are making active attempt to connect to this device, 'direct connect'. 95 */ 96 bool connecting_actively = false; 97 98 uint16_t conn_id = GATT_INVALID_CONN_ID; 99 uint16_t service_handle = GAP_INVALID_HANDLE; 100 bool is_gatt_service_valid = false; 101 GattServiceDevice(const RawAddress & addr,bool first_connection)102 GattServiceDevice(const RawAddress& addr, bool first_connection) 103 : addr(addr), first_connection(first_connection) {} 104 GattServiceDevice()105 GattServiceDevice() : GattServiceDevice(RawAddress::kEmpty, false) {} 106 IsConnected()107 bool IsConnected() const { return (conn_id != GATT_INVALID_CONN_ID); } 108 109 class MatchAddress { 110 private: 111 RawAddress addr; 112 113 public: MatchAddress(const RawAddress & addr)114 MatchAddress(const RawAddress& addr) : addr(addr) {} operator()115 bool operator()(const std::shared_ptr<GattServiceDevice>& other) const { 116 return (addr == other->addr); 117 } 118 }; 119 120 class MatchConnId { 121 private: 122 uint16_t conn_id; 123 124 public: MatchConnId(uint16_t conn_id)125 MatchConnId(uint16_t conn_id) : conn_id(conn_id) {} operator()126 bool operator()(const std::shared_ptr<GattServiceDevice>& other) const { 127 return (conn_id == other->conn_id); 128 } 129 }; 130 }; 131 132 /* 133 * CSIS instance represents single CSIS service on the remote device 134 * along with the handle in database and specific data to control CSIS like: 135 * rank, lock state. 136 * 137 * It also inclues UUID of the primary service which includes that CSIS 138 * instance. If this is 0x0000 it means CSIS is per device and not for specific 139 * service. 140 */ 141 class CsisInstance { 142 public: 143 bluetooth::Uuid coordinated_service = bluetooth::groups::kGenericContextUuid; 144 145 struct SvcData { 146 uint16_t start_handle; 147 uint16_t end_handle; 148 struct hdl_pair sirk_handle; 149 struct hdl_pair lock_handle; 150 uint16_t rank_handle; 151 struct hdl_pair size_handle; 152 } svc_data = { 153 GAP_INVALID_HANDLE, 154 GAP_INVALID_HANDLE, 155 {GAP_INVALID_HANDLE, GAP_INVALID_HANDLE}, 156 {GAP_INVALID_HANDLE, GAP_INVALID_HANDLE}, 157 GAP_INVALID_HANDLE, 158 {GAP_INVALID_HANDLE, GAP_INVALID_HANDLE}, 159 }; 160 CsisInstance(uint16_t start_handle,uint16_t end_handle,const bluetooth::Uuid & uuid)161 CsisInstance(uint16_t start_handle, uint16_t end_handle, const bluetooth::Uuid& uuid) 162 : coordinated_service(uuid), 163 group_id_(bluetooth::groups::kGroupUnknown), 164 rank_(kUnknownRank), 165 lock_state_(CsisLockState::CSIS_STATE_UNSET) { 166 svc_data.start_handle = start_handle; 167 svc_data.end_handle = end_handle; 168 } 169 SetLockState(CsisLockState state)170 void SetLockState(CsisLockState state) { 171 DLOG(INFO) << __func__ << " current lock state: " << (int)(lock_state_) 172 << " new lock state: " << (int)(state); 173 lock_state_ = state; 174 } GetLockState(void)175 CsisLockState GetLockState(void) const { return lock_state_; } GetRank(void)176 uint8_t GetRank(void) const { return rank_; } SetRank(uint8_t rank)177 void SetRank(uint8_t rank) { 178 DLOG(INFO) << __func__ << " current rank state: " << loghex(rank_) 179 << " new rank state: " << loghex(rank); 180 rank_ = rank; 181 } 182 SetGroupId(int group_id)183 void SetGroupId(int group_id) { 184 LOG(INFO) << __func__ << " set group id: " << group_id 185 << " instance handle: " << loghex(svc_data.start_handle); 186 group_id_ = group_id; 187 } 188 GetGroupId(void)189 int GetGroupId(void) const { return group_id_; } 190 HasSameUuid(const CsisInstance & csis_instance)191 bool HasSameUuid(const CsisInstance& csis_instance) const { 192 return (csis_instance.coordinated_service == coordinated_service); 193 } 194 GetUuid(void)195 const bluetooth::Uuid& GetUuid(void) const { return coordinated_service; } IsForUuid(const bluetooth::Uuid & uuid)196 bool IsForUuid(const bluetooth::Uuid& uuid) const { return coordinated_service == uuid; } 197 198 private: 199 int group_id_; 200 uint8_t rank_; 201 CsisLockState lock_state_; 202 }; 203 204 /* 205 * Csis Device represents remote device and its all CSIS instances. 206 * It can happen that device can have more than one CSIS service instance 207 * if those instances are included in other services. In this way, coordinated 208 * set is within the context of the primary service which includes the instance. 209 * 210 * CsisDevice contains vector of the instances. 211 */ 212 class CsisDevice : public GattServiceDevice { 213 public: 214 using GattServiceDevice::GattServiceDevice; 215 ClearSvcData()216 void ClearSvcData() { 217 GattServiceDevice::service_handle = GAP_INVALID_HANDLE; 218 GattServiceDevice::is_gatt_service_valid = false; 219 220 csis_instances_.clear(); 221 } 222 GetCsisInstanceByOwningHandle(uint16_t handle)223 std::shared_ptr<CsisInstance> GetCsisInstanceByOwningHandle(uint16_t handle) { 224 uint16_t hdl = 0; 225 for (const auto& [h, inst] : csis_instances_) { 226 if (handle >= inst->svc_data.start_handle && handle <= inst->svc_data.end_handle) { 227 hdl = h; 228 DLOG(INFO) << __func__ << " found " << loghex(hdl); 229 break; 230 } 231 } 232 return (hdl > 0) ? csis_instances_.at(hdl) : nullptr; 233 } 234 GetCsisInstanceByGroupId(int group_id)235 std::shared_ptr<CsisInstance> GetCsisInstanceByGroupId(int group_id) { 236 uint16_t hdl = 0; 237 for (const auto& [handle, inst] : csis_instances_) { 238 if (inst->GetGroupId() == group_id) { 239 hdl = handle; 240 break; 241 } 242 } 243 return (hdl > 0) ? csis_instances_.at(hdl) : nullptr; 244 } 245 SetCsisInstance(uint16_t handle,std::shared_ptr<CsisInstance> csis_instance)246 void SetCsisInstance(uint16_t handle, std::shared_ptr<CsisInstance> csis_instance) { 247 if (csis_instances_.count(handle)) { 248 DLOG(INFO) << __func__ << " instance is already here: " << csis_instance->GetUuid(); 249 return; 250 } 251 252 csis_instances_.insert({handle, csis_instance}); 253 DLOG(INFO) << __func__ << " instance added: " << loghex(handle) 254 << "device: " << ADDRESS_TO_LOGGABLE_STR(addr); 255 } 256 RemoveCsisInstance(int group_id)257 void RemoveCsisInstance(int group_id) { 258 for (auto it = csis_instances_.begin(); it != csis_instances_.end(); it++) { 259 if (it->second->GetGroupId() == group_id) { 260 csis_instances_.erase(it); 261 return; 262 } 263 } 264 } 265 GetNumberOfCsisInstances(void)266 int GetNumberOfCsisInstances(void) { return csis_instances_.size(); } 267 ForEachCsisInstance(std::function<void (const std::shared_ptr<CsisInstance> &)> cb)268 void ForEachCsisInstance(std::function<void(const std::shared_ptr<CsisInstance>&)> cb) { 269 for (auto const& kv_pair : csis_instances_) { 270 cb(kv_pair.second); 271 } 272 } 273 274 private: 275 /* Instances per start handle */ 276 std::map<uint16_t, std::shared_ptr<CsisInstance>> csis_instances_; 277 }; 278 279 /* 280 * CSIS group gathers devices which belongs to specific group. 281 * It also contains methond to decode encrypted SIRK and also to 282 * resolve PRSI in order to find out if device belongs to given group 283 */ 284 class CsisGroup { 285 public: CsisGroup(int group_id,const bluetooth::Uuid & uuid)286 CsisGroup(int group_id, const bluetooth::Uuid& uuid) 287 : group_id_(group_id), 288 size_(kDefaultCsisSetSize), 289 uuid_(uuid), 290 member_discovery_state_(CsisDiscoveryState::CSIS_DISCOVERY_IDLE), 291 lock_state_(CsisLockState::CSIS_STATE_UNSET), 292 target_lock_state_(CsisLockState::CSIS_STATE_UNSET), 293 lock_transition_cnt_(0) { 294 devices_.clear(); 295 BTIF_STORAGE_FILL_PROPERTY(&model_name, BT_PROPERTY_REMOTE_MODEL_NUM, 296 sizeof(model_name_val), &model_name_val); 297 } 298 299 bt_property_t model_name; 300 bt_bdname_t model_name_val = {0}; 301 AddDevice(std::shared_ptr<CsisDevice> csis_device)302 void AddDevice(std::shared_ptr<CsisDevice> csis_device) { 303 auto it = 304 find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(csis_device->addr)); 305 if (it != devices_.end()) return; 306 307 devices_.push_back(std::move(csis_device)); 308 } 309 RemoveDevice(const RawAddress & bd_addr)310 void RemoveDevice(const RawAddress& bd_addr) { 311 auto it = find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(bd_addr)); 312 if (it != devices_.end()) devices_.erase(it); 313 } 314 GetCurrentSize(void)315 int GetCurrentSize(void) const { return devices_.size(); } GetUuid()316 bluetooth::Uuid GetUuid() const { return uuid_; } SetUuid(const bluetooth::Uuid & uuid)317 void SetUuid(const bluetooth::Uuid& uuid) { uuid_ = uuid; } GetGroupId(void)318 int GetGroupId(void) const { return group_id_; } GetDesiredSize(void)319 int GetDesiredSize(void) const { return size_; } SetDesiredSize(int size)320 void SetDesiredSize(int size) { size_ = size; } IsGroupComplete(void)321 bool IsGroupComplete(void) const { return size_ == (int)devices_.size(); } IsEmpty(void)322 bool IsEmpty(void) const { return devices_.empty(); } 323 IsDeviceInTheGroup(std::shared_ptr<CsisDevice> & csis_device)324 bool IsDeviceInTheGroup(std::shared_ptr<CsisDevice>& csis_device) { 325 auto it = 326 find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(csis_device->addr)); 327 return (it != devices_.end()); 328 } IsRsiMatching(const RawAddress & rsi)329 bool IsRsiMatching(const RawAddress& rsi) const { return is_rsi_match_sirk(rsi, GetSirk()); } IsSirkBelongsToGroup(Octet16 sirk)330 bool IsSirkBelongsToGroup(Octet16 sirk) const { return (sirk_available_ && sirk_ == sirk); } GetSirk(void)331 Octet16 GetSirk(void) const { return sirk_; } SetSirk(Octet16 & sirk)332 void SetSirk(Octet16& sirk) { 333 if (sirk_available_) { 334 DLOG(INFO) << __func__ << " Updating SIRK"; 335 } 336 sirk_available_ = true; 337 sirk_ = sirk; 338 } 339 GetNumOfConnectedDevices(void)340 int GetNumOfConnectedDevices(void) { 341 return std::count_if(devices_.begin(), devices_.end(), 342 [](auto& d) { return d->IsConnected(); }); 343 } 344 GetDiscoveryState(void)345 CsisDiscoveryState GetDiscoveryState(void) const { return member_discovery_state_; } SetDiscoveryState(CsisDiscoveryState state)346 void SetDiscoveryState(CsisDiscoveryState state) { 347 DLOG(INFO) << __func__ << " current discovery state: " << (int)(member_discovery_state_) 348 << " new discovery state: " << (int)(state); 349 member_discovery_state_ = state; 350 } 351 SetCurrentLockState(CsisLockState state)352 void SetCurrentLockState(CsisLockState state) { lock_state_ = state; } 353 354 void SetTargetLockState(CsisLockState state, CsisLockCb cb = base::DoNothing()) { 355 target_lock_state_ = state; 356 cb_ = std::move(cb); 357 switch (state) { 358 case CsisLockState::CSIS_STATE_LOCKED: 359 lock_transition_cnt_ = GetNumOfConnectedDevices(); 360 break; 361 case CsisLockState::CSIS_STATE_UNLOCKED: 362 case CsisLockState::CSIS_STATE_UNSET: 363 lock_transition_cnt_ = 0; 364 break; 365 } 366 } 367 GetLockCb(void)368 CsisLockCb GetLockCb(void) { return std::move(cb_); } 369 GetCurrentLockState(void)370 CsisLockState GetCurrentLockState(void) const { return lock_state_; } GetTargetLockState(void)371 CsisLockState GetTargetLockState(void) const { return target_lock_state_; } 372 IsAvailableForCsisLockOperation(void)373 bool IsAvailableForCsisLockOperation(void) { 374 int id = group_id_; 375 int number_of_connected = 0; 376 auto iter = std::find_if( 377 devices_.begin(), devices_.end(), [id, &number_of_connected](auto& d) { 378 if (!d->IsConnected()) { 379 LOG_DEBUG("Device %s is not connected in group %d", 380 ADDRESS_TO_LOGGABLE_CSTR(d->addr), id); 381 return false; 382 } 383 auto inst = d->GetCsisInstanceByGroupId(id); 384 if (!inst) { 385 LOG_DEBUG("Instance not available for group %d", id); 386 return false; 387 } 388 number_of_connected++; 389 LOG_DEBUG("Device %s, lock state: %d", 390 ADDRESS_TO_LOGGABLE_CSTR(d->addr), 391 (int)inst->GetLockState()); 392 return inst->GetLockState() == CsisLockState::CSIS_STATE_LOCKED; 393 }); 394 395 LOG_DEBUG("Locked set: %d, number of connected %d", iter != devices_.end(), 396 number_of_connected); 397 /* If there is no locked device, we are good to go */ 398 if (iter != devices_.end()) { 399 LOG_WARN("Device %s is locked ", ADDRESS_TO_LOGGABLE_CSTR((*iter)->addr)); 400 return false; 401 } 402 403 return (number_of_connected > 0); 404 } 405 SortByCsisRank(void)406 void SortByCsisRank(void) { 407 int id = group_id_; 408 std::sort(devices_.begin(), devices_.end(), [id](auto& dev1, auto& dev2) { 409 auto inst1 = dev1->GetCsisInstanceByGroupId(id); 410 auto inst2 = dev2->GetCsisInstanceByGroupId(id); 411 if (!inst1 || !inst2) { 412 /* One of the device is not connected */ 413 DLOG(INFO) << __func__ << " one of the device is not connected: inst1: " << inst1 414 << " inst2: " << inst2; 415 return dev1->IsConnected(); 416 } 417 return (inst1->GetRank() < inst2->GetRank()); 418 }); 419 } 420 GetFirstDevice(void)421 std::shared_ptr<CsisDevice> GetFirstDevice(void) { return (devices_.front()); } GetLastDevice(void)422 std::shared_ptr<CsisDevice> GetLastDevice(void) { return (devices_.back()); } GetNextDevice(std::shared_ptr<CsisDevice> & device)423 std::shared_ptr<CsisDevice> GetNextDevice(std::shared_ptr<CsisDevice>& device) { 424 auto iter = 425 std::find_if(devices_.begin(), devices_.end(), CsisDevice::MatchAddress(device->addr)); 426 427 /* If reference device not found */ 428 if (iter == devices_.end()) return nullptr; 429 430 iter++; 431 /* If reference device is last in group */ 432 if (iter == devices_.end()) return nullptr; 433 434 return (*iter); 435 } GetPrevDevice(std::shared_ptr<CsisDevice> & device)436 std::shared_ptr<CsisDevice> GetPrevDevice(std::shared_ptr<CsisDevice>& device) { 437 auto iter = 438 std::find_if(devices_.rbegin(), devices_.rend(), CsisDevice::MatchAddress(device->addr)); 439 440 /* If reference device not found */ 441 if (iter == devices_.rend()) return nullptr; 442 443 iter++; 444 445 if (iter == devices_.rend()) return nullptr; 446 return (*iter); 447 } 448 GetLockTransitionCnt(void)449 int GetLockTransitionCnt(void) const { return lock_transition_cnt_; } UpdateLockTransitionCnt(int i)450 int UpdateLockTransitionCnt(int i) { 451 lock_transition_cnt_ += i; 452 return lock_transition_cnt_; 453 } 454 455 /* Return true if given Autoset Private Address |srpa| matches Set Identity 456 * Resolving Key |sirk| */ is_rsi_match_sirk(const RawAddress & rsi,const Octet16 & sirk)457 static bool is_rsi_match_sirk(const RawAddress& rsi, const Octet16& sirk) { 458 /* use the 3 MSB of bd address as prand */ 459 uint8_t rand[3]; 460 rand[0] = rsi.address[2]; 461 rand[1] = rsi.address[1]; 462 rand[2] = rsi.address[0]; 463 DLOG(INFO) << "Prand " << base::HexEncode(rand, 3); 464 465 DLOG(INFO) << "SIRK " << base::HexEncode(sirk.data(), 16); 466 /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ 467 Octet16 x = crypto_toolbox::aes_128(sirk, &rand[0], 3); 468 469 DLOG(INFO) << "X" << base::HexEncode(x.data(), 16); 470 471 rand[0] = rsi.address[5]; 472 rand[1] = rsi.address[4]; 473 rand[2] = rsi.address[3]; 474 475 DLOG(INFO) << "Hash " << base::HexEncode(rand, 3); 476 477 if (memcmp(x.data(), &rand[0], 3) == 0) { 478 // match 479 return true; 480 } 481 // not a match 482 return false; 483 } 484 485 private: 486 int group_id_; 487 Octet16 sirk_ = {0}; 488 bool sirk_available_ = false; 489 int size_; 490 bluetooth::Uuid uuid_; 491 492 std::vector<std::shared_ptr<CsisDevice>> devices_; 493 CsisDiscoveryState member_discovery_state_; 494 495 CsisLockState lock_state_; 496 CsisLockState target_lock_state_; 497 int lock_transition_cnt_; 498 499 CsisLockCb cb_; 500 }; 501 502 } // namespace csis 503 } // namespace bluetooth 504