mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Use LDT for advertisement encryption.
We are still missing the real LDT implementation, so the code is linked with a placeholder code that doesn't do the actual encryption. We also needed to pass the `account_name` to credential manager to choose the correct credentials. PiperOrigin-RevId: 483801163
This commit is contained in:
committed by
Copybara-Service
parent
41ba8c8a14
commit
53c504be9d
@@ -45,10 +45,10 @@ struct PresenceBroadcast {
|
||||
// Nearby SDK encrypts Data ELements before broadcasting if a non-public
|
||||
// `PresenceIdentity` is provided.
|
||||
std::vector<DataElement> extended_properties;
|
||||
};
|
||||
|
||||
// Account name used to select private credentials.
|
||||
std::string account_name;
|
||||
// Account name used to select private credentials.
|
||||
std::string account_name;
|
||||
};
|
||||
|
||||
std::vector<BroadcastSection> sections;
|
||||
};
|
||||
|
||||
@@ -22,6 +22,8 @@ cc_library(
|
||||
"base_broadcast_request.cc",
|
||||
"credential_manager_impl.cc",
|
||||
"encryption.cc",
|
||||
"ldt.cc",
|
||||
"np_ldt.c",
|
||||
"service_controller_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
@@ -33,6 +35,8 @@ cc_library(
|
||||
"credential_manager.h",
|
||||
"credential_manager_impl.h",
|
||||
"encryption.h",
|
||||
"ldt.h",
|
||||
"np_ldt.h",
|
||||
"scan_manager.h",
|
||||
"service_controller.h",
|
||||
"service_controller_impl.h",
|
||||
@@ -45,6 +49,7 @@ cc_library(
|
||||
"//internal/platform:base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform:uuid",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/platform/implementation:types",
|
||||
@@ -57,6 +62,7 @@ cc_library(
|
||||
"@com_google_absl//absl/status:statusor",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_absl//absl/strings:str_format",
|
||||
"@com_google_absl//absl/time",
|
||||
"@com_google_absl//absl/types:optional",
|
||||
"@com_google_absl//absl/types:variant",
|
||||
],
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace presence {
|
||||
|
||||
using ::nearby::internal::IdentityType;
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uint8_t kBaseVersion = 0;
|
||||
@@ -133,8 +132,9 @@ AdvertisementFactory::CreateBaseNpAdvertisement(
|
||||
return result;
|
||||
}
|
||||
absl::StatusOr<std::string> encrypted =
|
||||
credential_manager_.EncryptDataElements(presence.identity, request.salt,
|
||||
unencrypted);
|
||||
credential_manager_.EncryptDataElements(presence.identity,
|
||||
presence.account_name,
|
||||
request.salt, unencrypted);
|
||||
if (!encrypted.ok()) {
|
||||
return encrypted.status();
|
||||
}
|
||||
|
||||
@@ -39,12 +39,13 @@ using ::testing::status::StatusIs;
|
||||
class MockCredentialManager : public CredentialManagerImpl {
|
||||
public:
|
||||
MOCK_METHOD(absl::StatusOr<std::string>, EncryptDataElements,
|
||||
(IdentityType identity, absl::string_view salt,
|
||||
absl::string_view data_elements),
|
||||
(IdentityType identity, absl::string_view account_name,
|
||||
absl::string_view salt, absl::string_view data_elements),
|
||||
(override));
|
||||
};
|
||||
|
||||
TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) {
|
||||
std::string account_name = "Test account";
|
||||
std::string salt = "AB";
|
||||
std::string metadata_key =
|
||||
absl::HexStringToBytes("1011121314151617181920212223");
|
||||
@@ -55,12 +56,13 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) {
|
||||
Action action = ActionFactory::CreateAction(data_elements);
|
||||
BaseBroadcastRequest request =
|
||||
BaseBroadcastRequest(BasePresenceRequestBuilder(kIdentity)
|
||||
.SetAccountName(account_name)
|
||||
.SetSalt(salt)
|
||||
.SetTxPower(5)
|
||||
.SetAction(action));
|
||||
EXPECT_CALL(
|
||||
credential_manager,
|
||||
EncryptDataElements(kIdentity, salt, absl::HexStringToBytes("36050080")))
|
||||
EXPECT_CALL(credential_manager,
|
||||
EncryptDataElements(kIdentity, account_name, salt,
|
||||
absl::HexStringToBytes("36050080")))
|
||||
.WillOnce(Return(metadata_key + absl::HexStringToBytes("50515253")));
|
||||
|
||||
AdvertisementFactory factory(&credential_manager);
|
||||
@@ -105,6 +107,7 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPublicIdentity) {
|
||||
}
|
||||
|
||||
TEST(AdvertisementFactory, CreateAdvertisementFailsWhenEncryptionFails) {
|
||||
std::string account_name = "Test account";
|
||||
std::string salt = "AB";
|
||||
NiceMock<MockCredentialManager> credential_manager;
|
||||
constexpr IdentityType kIdentity = internal::IDENTITY_TYPE_PRIVATE;
|
||||
@@ -113,12 +116,13 @@ TEST(AdvertisementFactory, CreateAdvertisementFailsWhenEncryptionFails) {
|
||||
Action action = ActionFactory::CreateAction(data_elements);
|
||||
BaseBroadcastRequest request =
|
||||
BaseBroadcastRequest(BasePresenceRequestBuilder(kIdentity)
|
||||
.SetAccountName(account_name)
|
||||
.SetSalt(salt)
|
||||
.SetTxPower(5)
|
||||
.SetAction(action));
|
||||
EXPECT_CALL(
|
||||
credential_manager,
|
||||
EncryptDataElements(kIdentity, salt, absl::HexStringToBytes("36050080")))
|
||||
EXPECT_CALL(credential_manager,
|
||||
EncryptDataElements(kIdentity, account_name, salt,
|
||||
absl::HexStringToBytes("36050080")))
|
||||
.WillOnce(Return(absl::OutOfRangeError("failed")));
|
||||
|
||||
AdvertisementFactory factory(&credential_manager);
|
||||
@@ -128,6 +132,7 @@ TEST(AdvertisementFactory, CreateAdvertisementFailsWhenEncryptionFails) {
|
||||
|
||||
TEST(AdvertisementFactory,
|
||||
CreateAdvertisementFailsWhenEncryptionReturnsTooMuchData) {
|
||||
std::string account_name = "Test account";
|
||||
std::string salt = "AB";
|
||||
NiceMock<MockCredentialManager> credential_manager;
|
||||
constexpr IdentityType kIdentity = internal::IDENTITY_TYPE_PRIVATE;
|
||||
@@ -136,12 +141,13 @@ TEST(AdvertisementFactory,
|
||||
Action action = ActionFactory::CreateAction(data_elements);
|
||||
BaseBroadcastRequest request =
|
||||
BaseBroadcastRequest(BasePresenceRequestBuilder(kIdentity)
|
||||
.SetAccountName(account_name)
|
||||
.SetSalt(salt)
|
||||
.SetTxPower(5)
|
||||
.SetAction(action));
|
||||
EXPECT_CALL(
|
||||
credential_manager,
|
||||
EncryptDataElements(kIdentity, salt, absl::HexStringToBytes("36050080")))
|
||||
EXPECT_CALL(credential_manager,
|
||||
EncryptDataElements(kIdentity, account_name, salt,
|
||||
absl::HexStringToBytes("36050080")))
|
||||
.WillOnce(Return(absl::HexStringToBytes(
|
||||
"deaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddeaddead"
|
||||
"deaddeaddeaddeaddeaddeaddead")));
|
||||
@@ -153,6 +159,7 @@ TEST(AdvertisementFactory,
|
||||
|
||||
TEST(AdvertisementFactory,
|
||||
CreateAdvertisementFailsWhenEncryptionReturnsTooLittleData) {
|
||||
std::string account_name = "Test account";
|
||||
std::string salt = "AB";
|
||||
std::string metadata_key =
|
||||
absl::HexStringToBytes("1011121314151617181920212223");
|
||||
@@ -164,12 +171,13 @@ TEST(AdvertisementFactory,
|
||||
Action action = ActionFactory::CreateAction(data_elements);
|
||||
BaseBroadcastRequest request =
|
||||
BaseBroadcastRequest(BasePresenceRequestBuilder(kIdentity)
|
||||
.SetAccountName(account_name)
|
||||
.SetSalt(salt)
|
||||
.SetTxPower(5)
|
||||
.SetAction(action));
|
||||
EXPECT_CALL(
|
||||
credential_manager,
|
||||
EncryptDataElements(kIdentity, salt, absl::HexStringToBytes("36050080")))
|
||||
EXPECT_CALL(credential_manager,
|
||||
EncryptDataElements(kIdentity, account_name, salt,
|
||||
absl::HexStringToBytes("36050080")))
|
||||
.WillOnce(Return(metadata_key));
|
||||
|
||||
AdvertisementFactory factory(&credential_manager);
|
||||
|
||||
@@ -54,9 +54,15 @@ BasePresenceRequestBuilder& BasePresenceRequestBuilder::SetPowerMode(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasePresenceRequestBuilder& BasePresenceRequestBuilder::SetAccountName(
|
||||
absl::string_view account_name) {
|
||||
account_name_ = account_name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
BasePresenceRequestBuilder::operator BaseBroadcastRequest() const {
|
||||
BaseBroadcastRequest::BasePresence presence{.identity = identity_,
|
||||
.action = action_};
|
||||
BaseBroadcastRequest::BasePresence presence{
|
||||
.identity = identity_, .action = action_, .account_name = account_name_};
|
||||
BaseBroadcastRequest broadcast_request{
|
||||
.variant = presence,
|
||||
.salt = salt_.size() == kSaltSize
|
||||
@@ -85,7 +91,8 @@ absl::StatusOr<BaseBroadcastRequest> BaseBroadcastRequest::Create(
|
||||
BasePresenceRequestBuilder(section.identity)
|
||||
.SetTxPower(request.tx_power)
|
||||
.SetAction(ActionFactory::CreateAction(section.extended_properties))
|
||||
.SetPowerMode(request.power_mode));
|
||||
.SetPowerMode(request.power_mode)
|
||||
.SetAccountName(section.account_name));
|
||||
}
|
||||
return absl::UnimplementedError("Request not supported");
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ struct BaseBroadcastRequest {
|
||||
struct BasePresence {
|
||||
nearby::internal::IdentityType identity;
|
||||
Action action;
|
||||
std::string account_name;
|
||||
};
|
||||
struct BaseFastPair {
|
||||
struct Discoverable {
|
||||
@@ -80,6 +81,7 @@ class BasePresenceRequestBuilder {
|
||||
BasePresenceRequestBuilder& SetTxPower(int8_t tx_power);
|
||||
BasePresenceRequestBuilder& SetAction(const Action& action);
|
||||
BasePresenceRequestBuilder& SetPowerMode(PowerMode power_mode);
|
||||
BasePresenceRequestBuilder& SetAccountName(absl::string_view account_name);
|
||||
|
||||
explicit operator BaseBroadcastRequest() const;
|
||||
|
||||
@@ -89,6 +91,7 @@ class BasePresenceRequestBuilder {
|
||||
int8_t tx_power_ = kUnspecifiedTxPower;
|
||||
Action action_;
|
||||
PowerMode power_mode_ = PowerMode::kNoPower;
|
||||
std::string account_name_;
|
||||
};
|
||||
|
||||
} // namespace presence
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "presence/implementation/base_broadcast_request.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "protobuf-matchers/protocol-buffer-matchers.h"
|
||||
#include "gtest/gtest.h"
|
||||
@@ -46,15 +48,14 @@ TEST(BroadcastRequestTest, CreateFromPresenceRequest) {
|
||||
constexpr int8_t kTxPower = 30;
|
||||
constexpr uint32_t kExpectedAction =
|
||||
(1 << 23); // encoded kActiveUnlockAction
|
||||
std::string account_name = "Test account";
|
||||
PresenceBroadcast::BroadcastSection section = {
|
||||
.identity = internal::IDENTITY_TYPE_PUBLIC,
|
||||
.extended_properties = {
|
||||
DataElement(DataElement(ActionBit::kActiveUnlockAction))}};
|
||||
.extended_properties = {DataElement(
|
||||
DataElement(ActionBit::kActiveUnlockAction))},
|
||||
.account_name = account_name};
|
||||
PresenceBroadcast presence_request = {.sections = {section}};
|
||||
BroadcastRequest input = {
|
||||
.tx_power = kTxPower,
|
||||
.variant = presence_request,
|
||||
};
|
||||
BroadcastRequest input = {.tx_power = kTxPower, .variant = presence_request};
|
||||
|
||||
absl::StatusOr<BaseBroadcastRequest> request =
|
||||
BaseBroadcastRequest::Create(input);
|
||||
@@ -67,6 +68,9 @@ TEST(BroadcastRequestTest, CreateFromPresenceRequest) {
|
||||
EXPECT_THAT(absl::get<BaseBroadcastRequest::BasePresence>(request->variant)
|
||||
.action.action,
|
||||
kExpectedAction);
|
||||
EXPECT_THAT(absl::get<BaseBroadcastRequest::BasePresence>(request->variant)
|
||||
.account_name,
|
||||
account_name);
|
||||
}
|
||||
|
||||
TEST(BroadcastRequestTest, CreateFromEmptyPresenceRequestFails) {
|
||||
|
||||
@@ -81,11 +81,11 @@ class CredentialManager {
|
||||
virtual absl::StatusOr<std::string> DecryptDataElements(
|
||||
absl::string_view salt, absl::string_view data_elements) = 0;
|
||||
|
||||
// Encrypts `data_elements` using certificate associated with `identity` and
|
||||
// `salt`.
|
||||
// Encrypts `data_elements` using certificate associated with `identity`,
|
||||
// `account_name` and `salt`.
|
||||
virtual absl::StatusOr<std::string> EncryptDataElements(
|
||||
nearby::internal::IdentityType identity, absl::string_view salt,
|
||||
absl::string_view data_elements) = 0;
|
||||
nearby::internal::IdentityType identity, absl::string_view account_name,
|
||||
absl::string_view salt, absl::string_view data_elements) = 0;
|
||||
};
|
||||
|
||||
} // namespace presence
|
||||
|
||||
@@ -19,21 +19,29 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/time/time.h"
|
||||
#include "internal/crypto/aead.h"
|
||||
#include "internal/crypto/ec_private_key.h"
|
||||
#include "internal/crypto/hkdf.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/future.h"
|
||||
#include "internal/platform/implementation/credential_callbacks.h"
|
||||
#include "internal/platform/implementation/crypto.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "internal/proto/credential.proto.h"
|
||||
#include "presence/implementation/encryption.h"
|
||||
#include "presence/implementation/ldt.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
namespace {
|
||||
using ::location::nearby::Base64Utils;
|
||||
using ::location::nearby::Crypto;
|
||||
using ::location::nearby::Exception;
|
||||
using ::location::nearby::ExceptionOr;
|
||||
using ::location::nearby::Future;
|
||||
using ::nearby::internal::DeviceMetadata;
|
||||
using ::nearby::internal::IdentityType;
|
||||
using ::nearby::internal::PrivateCredential;
|
||||
@@ -42,6 +50,8 @@ using ::nearby::internal::PublicCredential;
|
||||
// Key to retrieve local device's Private/Public Key Credentials from key store.
|
||||
constexpr char kPairedKeyAliasPrefix[] = "nearby_presence_paired_key_alias_";
|
||||
|
||||
constexpr absl::Duration kTimeout = absl::Seconds(3);
|
||||
|
||||
} // namespace
|
||||
|
||||
void CredentialManagerImpl::GenerateCredentials(
|
||||
@@ -238,5 +248,51 @@ void CredentialManagerImpl::GetPublicCredentials(
|
||||
credential_selector, public_credential_type, std::move(callback));
|
||||
}
|
||||
|
||||
ExceptionOr<std::vector<PrivateCredential>>
|
||||
CredentialManagerImpl::GetPrivateCredentialsSync(
|
||||
const CredentialSelector& credential_selector, absl::Duration timeout) {
|
||||
Future<std::vector<PrivateCredential>> result;
|
||||
GetPrivateCredentials(
|
||||
credential_selector,
|
||||
{
|
||||
.credentials_fetched_cb =
|
||||
[result](std::vector<PrivateCredential> credentials) mutable {
|
||||
result.Set(credentials);
|
||||
},
|
||||
.get_credentials_failed_cb =
|
||||
[result](CredentialOperationStatus status) mutable {
|
||||
result.SetException({Exception::kFailed});
|
||||
},
|
||||
});
|
||||
return result.Get(timeout);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> CredentialManagerImpl::EncryptDataElements(
|
||||
nearby::internal::IdentityType identity, absl::string_view account_name,
|
||||
absl::string_view salt, absl::string_view data_elements) {
|
||||
CredentialSelector selector = {
|
||||
.manager_app_id = "",
|
||||
.account_name = std::string(account_name),
|
||||
.identity_type = identity,
|
||||
};
|
||||
ExceptionOr<std::vector<PrivateCredential>> credentials =
|
||||
GetPrivateCredentialsSync(selector, kTimeout);
|
||||
if (!credentials.ok()) {
|
||||
return absl::UnavailableError("Failed to fetch credentials");
|
||||
}
|
||||
if (credentials.result().empty()) {
|
||||
return absl::UnavailableError("No credentials");
|
||||
}
|
||||
PrivateCredential& credential = credentials.result().front();
|
||||
|
||||
// HMAC is not used during encryption, so we can pass an empty value.
|
||||
absl::StatusOr<LdtEncryptor> encryptor =
|
||||
LdtEncryptor::Create(credential.authenticity_key(), /*known_hmac=*/"");
|
||||
if (!encryptor.ok()) {
|
||||
return encryptor.status();
|
||||
}
|
||||
return encryptor->Encrypt(data_elements, salt);
|
||||
}
|
||||
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
@@ -70,6 +70,12 @@ class CredentialManagerImpl : public CredentialManager {
|
||||
const CredentialSelector& credential_selector,
|
||||
GetPrivateCredentialsResultCallback callback) override;
|
||||
|
||||
// Blocking version of `GetPrivateCredentials`
|
||||
location::nearby::ExceptionOr<
|
||||
std::vector<nearby::internal::PrivateCredential>>
|
||||
GetPrivateCredentialsSync(const CredentialSelector& credential_selector,
|
||||
absl::Duration timeout);
|
||||
|
||||
// Used to fetch remote public creds when scanning.
|
||||
void GetPublicCredentials(
|
||||
const CredentialSelector& credential_selector,
|
||||
@@ -87,10 +93,8 @@ class CredentialManagerImpl : public CredentialManager {
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> EncryptDataElements(
|
||||
nearby::internal::IdentityType identity, absl::string_view salt,
|
||||
absl::string_view data_elements) override {
|
||||
return absl::UnimplementedError("EncryptDataElements unimplemented");
|
||||
}
|
||||
nearby::internal::IdentityType identity, absl::string_view account_name,
|
||||
absl::string_view salt, absl::string_view data_elements) override;
|
||||
|
||||
std::pair<nearby::internal::PrivateCredential,
|
||||
nearby::internal::PublicCredential>
|
||||
|
||||
@@ -346,15 +346,29 @@ TEST(CredentialManagerImpl, PublicCredentialsFailEncryption) {
|
||||
EXPECT_TRUE(publicCredentials.empty());
|
||||
}
|
||||
|
||||
TEST(CredentialManagerImpl, EncryptDataElements) {
|
||||
absl::string_view salt = "AB";
|
||||
absl::string_view data_elements = "data_elements";
|
||||
DeviceMetadata device_metadata = CreateTestDeviceMetadata();
|
||||
CredentialManagerImpl credential_manager;
|
||||
std::vector<IdentityType> identity_types{IDENTITY_TYPE_PRIVATE};
|
||||
credential_manager.GenerateCredentials(
|
||||
device_metadata, "", identity_types, 1, 1,
|
||||
{
|
||||
.credentials_generated_cb =
|
||||
[](std::vector<nearby::internal::PublicCredential>) {},
|
||||
});
|
||||
|
||||
EXPECT_THAT(credential_manager.EncryptDataElements(
|
||||
IDENTITY_TYPE_PRIVATE, "test_account", salt, data_elements),
|
||||
absl::Status(absl::StatusCode::kUnavailable,
|
||||
"Failed to create LDT encryptor"));
|
||||
}
|
||||
|
||||
TEST(CredentialManagerImpl, UnimplementedFunctions) {
|
||||
CredentialManagerImpl credential_manager;
|
||||
constexpr absl::string_view salt = "salt";
|
||||
constexpr absl::string_view data_elements = "data_elements";
|
||||
IdentityType identity = IDENTITY_TYPE_PRIVATE;
|
||||
EXPECT_THAT(
|
||||
credential_manager.EncryptDataElements(identity, salt, data_elements),
|
||||
absl::Status(absl::StatusCode::kUnimplemented,
|
||||
"EncryptDataElements unimplemented"));
|
||||
EXPECT_THAT(credential_manager.DecryptDataElements(salt, data_elements),
|
||||
absl::Status(absl::StatusCode::kUnimplemented,
|
||||
"DecryptDataElements unimplemented"));
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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 "presence/implementation/ldt.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "absl/status/status.h"
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "presence/implementation/np_ldt.h"
|
||||
#include <openssl/aes.h>
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
|
||||
namespace {
|
||||
template <class T>
|
||||
T FromStringView(absl::string_view data) {
|
||||
T result{
|
||||
.bytes = {0},
|
||||
};
|
||||
memcpy(result.bytes, data.data(),
|
||||
std::min(sizeof(result.bytes), data.size()));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct AesContext {
|
||||
AES_KEY encryption_key;
|
||||
AES_KEY decryption_key;
|
||||
};
|
||||
|
||||
NpLdtAesCipherHandle AesCreateCipher(NpLdtAes128Key key) {
|
||||
AesContext* ctx = new AesContext();
|
||||
AES_set_encrypt_key(key.bytes, 128, &ctx->encryption_key);
|
||||
AES_set_decrypt_key(key.bytes, 128, &ctx->decryption_key);
|
||||
// The caller takes ownership and they must call `AesCloseCipher` eventually.
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int32_t AesCloseCipher(NpLdtAesCipherHandle handle) {
|
||||
AesContext* ctx = reinterpret_cast<AesContext*>(handle);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AesEncrypt(NpLdtAesCipherHandle handle, NpLdtAesBlock* block) {
|
||||
AesContext* ctx = reinterpret_cast<AesContext*>(handle);
|
||||
AES_encrypt(block->bytes, block->bytes, &ctx->encryption_key);
|
||||
}
|
||||
|
||||
void AesDecrypt(NpLdtAesCipherHandle handle, NpLdtAesBlock* block) {
|
||||
AesContext* ctx = reinterpret_cast<AesContext*>(handle);
|
||||
AES_decrypt(block->bytes, block->bytes, &ctx->decryption_key);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
absl::StatusOr<LdtEncryptor> LdtEncryptor::Create(
|
||||
absl::string_view key_seed, absl::string_view known_hmac) {
|
||||
NpLdtHandle handle =
|
||||
NpLdtCreate({.create_cipher = AesCreateCipher,
|
||||
.close_cipher = AesCloseCipher,
|
||||
.encrypt = AesEncrypt,
|
||||
.decrypt = AesDecrypt},
|
||||
FromStringView<NpLdtKeySeed>(key_seed),
|
||||
FromStringView<NpMetadataKeyHmac>(known_hmac));
|
||||
if (handle == nullptr) {
|
||||
return absl::UnavailableError("Failed to create LDT encryptor");
|
||||
}
|
||||
|
||||
return LdtEncryptor(handle);
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> LdtEncryptor::Encrypt(absl::string_view data,
|
||||
absl::string_view salt) {
|
||||
std::string encrypted = std::string(data);
|
||||
NP_LDT_RESULT result =
|
||||
NpLdtEncrypt(ldt_handle_, reinterpret_cast<uint8_t*>(encrypted.data()),
|
||||
encrypted.size(), FromStringView<NpLdtSalt>(salt));
|
||||
if (result == NP_LDT_SUCCESS) {
|
||||
return encrypted;
|
||||
}
|
||||
return absl::InternalError(
|
||||
absl::StrFormat("LDT encryption failed, errorcode %d", result));
|
||||
}
|
||||
|
||||
absl::StatusOr<std::string> LdtEncryptor::DecryptAndVerify(
|
||||
absl::string_view data, absl::string_view salt) {
|
||||
std::string encrypted = std::string(data);
|
||||
NP_LDT_RESULT result = NpLdtDecryptAndVerify(
|
||||
ldt_handle_, reinterpret_cast<uint8_t*>(encrypted.data()),
|
||||
encrypted.size(), FromStringView<NpLdtSalt>(salt));
|
||||
if (result == NP_LDT_SUCCESS) {
|
||||
return encrypted;
|
||||
}
|
||||
return absl::InternalError(
|
||||
absl::StrFormat("LDT encryption failed, errorcode %d", result));
|
||||
}
|
||||
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_LDT_H_
|
||||
#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_LDT_H_
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/status/statusor.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "presence/implementation/np_ldt.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace presence {
|
||||
|
||||
// C++ abstraction on top of LDT C API.
|
||||
class LdtEncryptor {
|
||||
public:
|
||||
LdtEncryptor(const LdtEncryptor&) = delete;
|
||||
LdtEncryptor(LdtEncryptor&& other) : ldt_handle_(other.ldt_handle_) {
|
||||
other.ldt_handle_ = nullptr;
|
||||
}
|
||||
LdtEncryptor& operator=(const LdtEncryptor&) = delete;
|
||||
LdtEncryptor& operator=(LdtEncryptor&& other) {
|
||||
std::swap(ldt_handle_, other.ldt_handle_);
|
||||
return *this;
|
||||
}
|
||||
~LdtEncryptor() {
|
||||
if (ldt_handle_ != nullptr) {
|
||||
NpLdtClose(ldt_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates an instance of `LdtEncryptor`.
|
||||
// `key_seed` is used to generate LDT encryption and decryption keys.
|
||||
// `known_hmac` is used during decryption to verify if the message was
|
||||
// encrypted with the expected key.
|
||||
static absl::StatusOr<LdtEncryptor> Create(absl::string_view key_seed,
|
||||
absl::string_view known_hmac);
|
||||
|
||||
// Encrypts `data`, which must be 16 - 31 bytes long.
|
||||
absl::StatusOr<std::string> Encrypt(absl::string_view data,
|
||||
absl::string_view salt);
|
||||
|
||||
// Decrypts `data` and verifies if it was encrypted with a key generated from
|
||||
// `key_seed`.
|
||||
absl::StatusOr<std::string> DecryptAndVerify(absl::string_view data,
|
||||
absl::string_view salt);
|
||||
|
||||
private:
|
||||
explicit LdtEncryptor(NpLdtHandle ldt_handle) : ldt_handle_(ldt_handle) {}
|
||||
// An opaque handle to the underlying LDT implementation. It can be null iff
|
||||
// this object has already been destroyed.
|
||||
NpLdtHandle ldt_handle_;
|
||||
};
|
||||
|
||||
} // namespace presence
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_LDT_H_
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright 2022 Google LLC
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// https://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 "third_party/nearby/presence/implementation/np_ldt.h"
|
||||
|
||||
// Placeholder, empty implementations of LDT utilities. They will be replaced
|
||||
// with implementations in Rust.
|
||||
|
||||
NpLdtHandle NpLdtCreate(NpLdtAesConfig aes_config, NpLdtKeySeed key_seed,
|
||||
NpMetadataKeyHmac known_hmac) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
NP_LDT_RESULT NpLdtClose(NpLdtHandle handle) { return NP_LDT_SUCCESS; }
|
||||
|
||||
NP_LDT_RESULT NpLdtEncrypt(NpLdtHandle handle, uint8_t* buffer,
|
||||
size_t buffer_len, NpLdtSalt salt) {
|
||||
return NP_LDT_SUCCESS;
|
||||
}
|
||||
|
||||
NP_LDT_RESULT NpLdtDecryptAndVerify(NpLdtHandle handle, uint8_t* buffer,
|
||||
size_t buffer_len, NpLdtSalt salt) {
|
||||
return NP_LDT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user