blob: 257f60ac14ddba19a55cbb6a72d0b30a846ee468 [file] [log] [blame]
/*
*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "security/record/security_record_storage.h"
#include "storage/mutation.h"
namespace bluetooth {
namespace security {
namespace record {
namespace {
void SetClassicData(
storage::Mutation& mutation, std::shared_ptr<record::SecurityRecord> record, storage::Device& device) {
if (*device.GetDeviceType() == hci::DeviceType::LE) {
return;
}
if (record->IsClassicLinkKeyValid()) {
LOG_WARN("Type: %d", static_cast<int>(*device.GetDeviceType()));
mutation.Add(device.Classic().SetLinkKey(record->GetLinkKey()));
mutation.Add(device.Classic().SetLinkKeyType(record->GetKeyType()));
}
}
void SetLeData(storage::Mutation& mutation, std::shared_ptr<record::SecurityRecord> record, storage::Device& device) {
if (*device.GetDeviceType() == hci::DeviceType::BR_EDR) {
return;
}
auto le_device = device.Le();
if (record->identity_address_) {
mutation.Add(le_device.SetAddressType(record->identity_address_->GetAddressType()));
}
if (record->remote_irk) {
std::array<uint8_t, 23> peerid;
std::copy_n(record->remote_irk->data(), record->remote_irk->size(), peerid.data());
peerid[16] = static_cast<uint8_t>(record->identity_address_->GetAddressType());
std::copy_n(record->identity_address_->GetAddress().data(), 6, peerid.data() + 17);
common::ByteArray<23> byte_array(peerid);
mutation.Add(le_device.SetPeerId(byte_array.ToString()));
}
if (record->pseudo_address_) {
mutation.Add(le_device.SetLegacyPseudoAddress(record->pseudo_address_->GetAddress()));
}
if (record->remote_ltk) {
std::array<uint8_t, 28> penc_keys;
std::copy_n(record->remote_ltk->data(), record->remote_ltk->size(), penc_keys.data());
std::copy_n(record->remote_rand->data(), record->remote_rand->size(), penc_keys.data() + 16);
uint16_t* ediv_location = (uint16_t*)(penc_keys.data() + 24);
*ediv_location = *record->remote_ediv;
penc_keys[26] = record->security_level;
penc_keys[27] = record->key_size;
common::ByteArray<28> byte_array(penc_keys);
mutation.Add(le_device.SetPeerEncryptionKeys(byte_array.ToString()));
}
if (record->remote_signature_key) {
std::array<uint8_t, 21> psrk_keys;
// four bytes counter, all zeros
*psrk_keys.data() = 0;
*(psrk_keys.data() + 1) = 0;
*(psrk_keys.data() + 2) = 0;
*(psrk_keys.data() + 3) = 0;
std::copy_n(record->remote_signature_key->data(), record->remote_signature_key->size(), psrk_keys.data() + 4);
*(psrk_keys.data() + 20) = record->security_level;
common::ByteArray<21> byte_array(psrk_keys);
mutation.Add(le_device.SetPeerSignatureResolvingKeys(byte_array.ToString()));
}
}
void SetAuthenticationData(storage::Mutation& mutation, std::shared_ptr<record::SecurityRecord> record, storage::Device& device) {
device.SetIsAuthenticated((record->IsAuthenticated() ? 1 : 0));
device.SetIsEncryptionRequired((record->IsEncryptionRequired() ? 1 : 0));
device.SetRequiresMitmProtection(record->RequiresMitmProtection() ? 1 : 0);
}
} // namespace
SecurityRecordStorage::SecurityRecordStorage(storage::StorageModule* storage_module, os::Handler* handler)
: storage_module_(storage_module), handler_(handler) {}
void SecurityRecordStorage::SaveSecurityRecords(std::set<std::shared_ptr<record::SecurityRecord>>* records) {
for (auto record : *records) {
if (record->IsTemporary()) continue;
storage::Device device = storage_module_->GetDeviceByClassicMacAddress(record->GetPseudoAddress()->GetAddress());
auto mutation = storage_module_->Modify();
if (record->IsClassicLinkKeyValid() && !record->identity_address_) {
mutation.Add(device.SetDeviceType(hci::DeviceType::BR_EDR));
} else if (record->IsClassicLinkKeyValid() && record->remote_ltk) {
mutation.Add(device.SetDeviceType(hci::DeviceType::DUAL));
} else if (!record->IsClassicLinkKeyValid() && record->remote_ltk) {
mutation.Add(device.SetDeviceType(hci::DeviceType::LE));
} else {
LOG_ERROR(
"Cannot determine device type from security record for '%s'; dropping!",
record->GetPseudoAddress()->ToString().c_str());
continue;
}
mutation.Commit();
SetClassicData(mutation, record, device);
SetLeData(mutation, record, device);
SetAuthenticationData(mutation, record, device);
mutation.Commit();
}
}
void SecurityRecordStorage::LoadSecurityRecords(std::set<std::shared_ptr<record::SecurityRecord>>* records) {
for (auto device : storage_module_->GetBondedDevices()) {
auto address_type = (device.GetDeviceType() == hci::DeviceType::BR_EDR) ? hci::AddressType::PUBLIC_DEVICE_ADDRESS
: device.Le().GetAddressType();
auto address_with_type = hci::AddressWithType(device.GetAddress(), *address_type);
auto record = std::make_shared<record::SecurityRecord>(address_with_type);
if (device.GetDeviceType() != hci::DeviceType::LE) {
record->SetLinkKey(device.Classic().GetLinkKey()->bytes, *device.Classic().GetLinkKeyType());
}
if (device.GetDeviceType() != hci::DeviceType::BR_EDR) {
record->pseudo_address_ = std::make_optional<hci::AddressWithType>(
*device.Le().GetLegacyPseudoAddress(), *device.Le().GetAddressType());
if (device.Le().GetPeerId()) {
auto peerid = common::ByteArray<23>::FromString(*device.Le().GetPeerId());
record->remote_irk = std::make_optional<std::array<uint8_t, 16>>();
std::copy_n(peerid->data(), record->remote_irk->size(), record->remote_irk->data());
uint8_t idaddress_type;
hci::Address idaddress;
std::copy_n(peerid->data() + 16, 1, &idaddress_type);
std::copy_n(peerid->data() + 17, 6, idaddress.data());
record->identity_address_ =
std::make_optional<hci::AddressWithType>(idaddress, static_cast<hci::AddressType>(idaddress_type));
}
if (device.Le().GetPeerEncryptionKeys()) {
auto peer_encryption_keys = common::ByteArray<28>::FromString(*device.Le().GetPeerEncryptionKeys());
record->remote_ltk = std::make_optional<std::array<uint8_t, 16>>();
record->remote_rand = std::make_optional<std::array<uint8_t, 8>>();
record->remote_ediv = std::make_optional(0);
std::copy_n(peer_encryption_keys->data(), 16, record->remote_ltk->data());
std::copy_n(peer_encryption_keys->data() + 16, 8, record->remote_rand->data());
std::copy_n(peer_encryption_keys->data() + 24, 2, &(*record->remote_ediv));
record->security_level = peer_encryption_keys->data()[26];
record->key_size = peer_encryption_keys->data()[27];
}
if (device.Le().GetPeerSignatureResolvingKeys()) {
auto peer_signature_resolving_keys =
common::ByteArray<21>::FromString(*device.Le().GetPeerSignatureResolvingKeys());
record->remote_signature_key = std::make_optional<std::array<uint8_t, 16>>();
std::copy_n(peer_signature_resolving_keys->data() + 4, 16, record->remote_signature_key->data());
record->security_level = peer_signature_resolving_keys->data()[20];
}
}
record->SetIsEncryptionRequired(device.GetIsEncryptionRequired() == 1 ? true : false);
record->SetAuthenticated(device.GetIsAuthenticated() == 1 ? true : false);
record->SetRequiresMitmProtection(device.GetRequiresMitmProtection() == 1 ? true : false);
records->insert(record);
}
}
void SecurityRecordStorage::RemoveDevice(hci::AddressWithType address) {
storage::Device device = storage_module_->GetDeviceByClassicMacAddress(address.GetAddress());
auto mutation = storage_module_->Modify();
mutation.Add(device.RemoveFromConfig());
mutation.Commit();
}
} // namespace record
} // namespace security
} // namespace bluetooth