diff --git a/presence/implementation/BUILD b/presence/implementation/BUILD index bea094ed..ffc3cedb 100644 --- a/presence/implementation/BUILD +++ b/presence/implementation/BUILD @@ -45,7 +45,6 @@ cc_library( "base_broadcast_request.cc", "broadcast_manager.cc", "credential_manager_impl.cc", - "encryption.cc", "ldt.cc", "scan_manager.cc", "service_controller_impl.cc", @@ -58,7 +57,6 @@ cc_library( "broadcast_manager.h", "credential_manager.h", "credential_manager_impl.h", - "encryption.h", "ldt.h", "scan_manager.h", "service_controller.h", @@ -187,19 +185,6 @@ cc_test( ], ) -cc_test( - name = "encryption_test", - size = "small", - srcs = ["encryption_test.cc"], - deps = [ - ":internal", - "//internal/platform/implementation/g3", # build_cleaner: keep - "@com_github_protobuf_matchers//protobuf-matchers", - "@com_google_absl//absl/strings", - "@com_google_googletest//:gtest_main", - ], -) - cc_test( name = "ldt_test", size = "small", diff --git a/presence/implementation/base_broadcast_request.cc b/presence/implementation/base_broadcast_request.cc index fbb72c70..2171c8f5 100644 --- a/presence/implementation/base_broadcast_request.cc +++ b/presence/implementation/base_broadcast_request.cc @@ -19,10 +19,10 @@ #include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "internal/crypto/random.h" #include "internal/platform/logging.h" #include "presence/broadcast_request.h" #include "presence/implementation/action_factory.h" -#include "presence/implementation/encryption.h" namespace nearby { namespace presence { @@ -74,9 +74,7 @@ BasePresenceRequestBuilder::operator BaseBroadcastRequest() const { .action = action_}; BaseBroadcastRequest broadcast_request{ .variant = presence, - .salt = salt_.size() == kSaltSize - ? salt_ - : Encryption::GenerateRandomByteArray(kSaltSize), + .salt = salt_.size() == kSaltSize ? salt_ : crypto::RandBytes(kSaltSize), .tx_power = tx_power_, .power_mode = power_mode_}; return broadcast_request; diff --git a/presence/implementation/credential_manager_impl.cc b/presence/implementation/credential_manager_impl.cc index 80f1f242..11264d5b 100644 --- a/presence/implementation/credential_manager_impl.cc +++ b/presence/implementation/credential_manager_impl.cc @@ -35,7 +35,7 @@ #include "internal/platform/implementation/crypto.h" #include "internal/platform/logging.h" #include "internal/proto/credential.pb.h" -#include "presence/implementation/encryption.h" +#include "presence/implementation/base_broadcast_request.h" #include "presence/implementation/ldt.h" namespace nearby { @@ -60,6 +60,13 @@ absl::Duration RandomDuration(absl::Duration max_duration) { return max_duration * random / std::numeric_limits::max(); } +std::string CustomizeBytesSize(absl::string_view bytes, size_t len) { + return ::crypto::HkdfSha256( + /*ikm=*/bytes, + /*salt=*/std::string(CredentialManagerImpl::kAuthenticityKeyByteSize, 0), + /*info=*/"", /*derived_key_size=*/len); +} + } // namespace void CredentialManagerImpl::GenerateCredentials( @@ -157,8 +164,7 @@ CredentialManagerImpl::CreateLocalCredential( private_credential.set_identity_type(identity_type); // Creates an AES key to encrypt the whole broadcast. - std::string secret_key = - Encryption::GenerateRandomByteArray(kAuthenticityKeyByteSize); + std::string secret_key = crypto::RandBytes(kAuthenticityKeyByteSize); private_credential.set_authenticity_key(secret_key); // Uses SHA-256 algorithm to generate the credential ID from the @@ -181,8 +187,7 @@ CredentialManagerImpl::CreateLocalCredential( std::string(private_key.begin(), private_key.end())); // Create an AES key to encrypt the device metadata. - auto metadata_key = - Encryption::GenerateRandomByteArray(kAuthenticityKeyByteSize); + auto metadata_key = crypto::RandBytes(kBaseMetadataSize); private_credential.set_metadata_encryption_key(metadata_key); // set device meta data @@ -252,8 +257,8 @@ std::string CredentialManagerImpl::DecryptDeviceMetadata( ExtendMetadataEncryptionKey(device_metadata_encryption_key); aead.Init(derived_key); - auto iv = Encryption::CustomizeBytesSize( - authenticity_key, CredentialManagerImpl::kAesGcmIVSize); + auto iv = CustomizeBytesSize(authenticity_key, + CredentialManagerImpl::kAesGcmIVSize); std::vector iv_bytes(iv.begin(), iv.end()); std::vector encrypted_device_metadata_bytes( device_metadata_string.begin(), device_metadata_string.end()); @@ -277,7 +282,7 @@ std::string CredentialManagerImpl::EncryptDeviceMetadata( aead.Init(derived_key); - auto iv = Encryption::CustomizeBytesSize(authenticity_key, kAesGcmIVSize); + auto iv = CustomizeBytesSize(authenticity_key, kAesGcmIVSize); std::vector iv_bytes(iv.begin(), iv.end()); std::vector device_metadata_bytes(device_metadata_string.begin(), diff --git a/presence/implementation/credential_manager_impl.h b/presence/implementation/credential_manager_impl.h index cf475faf..4cd80b5e 100644 --- a/presence/implementation/credential_manager_impl.h +++ b/presence/implementation/credential_manager_impl.h @@ -53,7 +53,7 @@ class CredentialManagerImpl : public CredentialManager { credential_storage_ptr_(std::move(credential_storage_ptr)) {} // AES only supports key sizes of 16, 24 or 32 bytes. - static constexpr int kAuthenticityKeyByteSize = 16; + static constexpr int kAuthenticityKeyByteSize = 32; // Length of key in bytes required by AES-GCM encryption. static constexpr size_t kNearbyPresenceNumBytesAesGcmKeySize = 32; diff --git a/presence/implementation/credential_manager_impl_test.cc b/presence/implementation/credential_manager_impl_test.cc index c9ea742a..38144202 100644 --- a/presence/implementation/credential_manager_impl_test.cc +++ b/presence/implementation/credential_manager_impl_test.cc @@ -32,6 +32,7 @@ #include "internal/platform/logging.h" #include "internal/platform/medium_environment.h" #include "internal/proto/credential.pb.h" +#include "presence/implementation/base_broadcast_request.h" namespace nearby { namespace presence { @@ -159,7 +160,7 @@ TEST_F(CredentialManagerImplTest, CreateOneCredentialSuccessfully) { CredentialManagerImpl::kAuthenticityKeyByteSize); EXPECT_FALSE(private_credential.verification_key().empty()); EXPECT_EQ(private_credential.metadata_encryption_key().size(), - CredentialManagerImpl::kAuthenticityKeyByteSize); + kBaseMetadataSize); SharedCredential public_credential = credentials.second; // Verify the public credential. diff --git a/presence/implementation/encryption.cc b/presence/implementation/encryption.cc deleted file mode 100644 index 56eb2c52..00000000 --- a/presence/implementation/encryption.cc +++ /dev/null @@ -1,106 +0,0 @@ -// 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/encryption.h" - -#include -#include -#include - -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/str_format.h" -#include "internal/crypto/hkdf.h" -#include "internal/crypto/random.h" -#include // NOLINT -#include // NOLINT - -namespace nearby { -namespace presence { - -constexpr int kAuthenticityKeyByteSize = 16; -constexpr int kMetadataKeyMaxSize = 16; -constexpr int kAesCtrIvSize = 16; -constexpr int kSaltSize = 2; - -std::string Encryption::CustomizeBytesSize(absl::string_view bytes, - size_t len) { - return ::crypto::HkdfSha256(/*ikm=*/bytes, - /*salt=*/std::string(kAuthenticityKeyByteSize, 0), - /*info=*/"", /*derived_key_size=*/len); -} - -std::string Encryption::GenerateRandomByteArray(size_t len) { - std::string buffer(len, 0); - ::crypto::RandBytes( - absl::MakeSpan(reinterpret_cast(buffer.data()), buffer.size())); - return buffer; -} - -absl::StatusOr Encryption::RunMetadataEncryption( - absl::string_view metadata, absl::string_view key, absl::string_view salt, - bool encrypt) { - if (metadata.size() > kMetadataKeyMaxSize) { - return absl::InvalidArgumentError( - absl::StrFormat("Metadata key length %d greater than %d", - metadata.size(), kMetadataKeyMaxSize)); - } - if (key.size() != kAuthenticityKeyByteSize) { - return absl::InvalidArgumentError( - absl::StrFormat("Invalid authenticity key length %d. Expected %d", - key.size(), kAuthenticityKeyByteSize)); - } - if (salt.size() != kSaltSize) { - return absl::InvalidArgumentError(absl::StrFormat( - "Invalid salt length %d, Expected %d.", salt.size(), kSaltSize)); - } - auto output = std::string(metadata.size(), 0); - int output_size; - std::string iv = CustomizeBytesSize(salt, kAesCtrIvSize); - - // AES-CTR is used without authentication because it's used as a PRF. - auto ctx = - std::unique_ptr>( - EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free); - if (1 != EVP_CipherInit_ex(ctx.get(), EVP_aes_128_ctr(), nullptr, - reinterpret_cast(key.data()), - reinterpret_cast(iv.data()), - encrypt ? 1 : 0)) { - return absl::InvalidArgumentError("Failed to initialize AES encryption."); - } - - int input_size = metadata.size(); - if (1 != EVP_CipherUpdate( - ctx.get(), reinterpret_cast(output.data()), - &output_size, reinterpret_cast(metadata.data()), - input_size)) { - return absl::InvalidArgumentError("AES error in EVP_CipherUpdate"); - } - int tmp_size = 0; - if (1 != EVP_EncryptFinal_ex( - ctx.get(), - reinterpret_cast(output.data() + output_size), - &tmp_size)) { - return absl::InvalidArgumentError("AES errorin EVP_EncryptFinal_ex"); - } - output_size += tmp_size; - if (output_size != input_size) { - return absl::InvalidArgumentError(absl::StrFormat( - "Invalid output size %d. Expected %d", output_size, input_size)); - } - return output; -} - -} // namespace presence -} // namespace nearby diff --git a/presence/implementation/encryption.h b/presence/implementation/encryption.h deleted file mode 100644 index cd8e9cc8..00000000 --- a/presence/implementation/encryption.h +++ /dev/null @@ -1,74 +0,0 @@ -// 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_ENCRYPTION_H_ -#define THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_ENCRYPTION_H_ - -#include - -#include "absl/status/statusor.h" -#include "absl/strings/string_view.h" - -namespace nearby { -namespace presence { - -/** Utilities for encryption and decryption of presence advertisements. */ -class Encryption { - public: - /** - * Uses a HMAC based HKDF algorithm to generate and return a - * new byte array of given length based on input bytes and a zero-initialized - * salt. - */ - static std::string CustomizeBytesSize(absl::string_view bytes, size_t len); - - /** Generates a random byte array of given size. */ - static std::string GenerateRandomByteArray(size_t len); - - /** Generates encrypted metadata key. `metadata_encryption_key` must be 14 or - * 16 bytes long. `authenticity_key` is the AES key and must be 128 bit (16 - * bytes) long. `salt` must be 2 bytes long. - * - * Note, because the salt is ony 16 bit long, the caller should not reuse - * salts. Reusing salts will expose the encrypted metadata key. The solution - * in NP is to store all used salts and rotate the autheticity key when we run - * out of salts. - */ - static absl::StatusOr GenerateEncryptedMetadataKey( - absl::string_view metadata_encryption_key, - absl::string_view authenticity_key, absl::string_view salt) { - return RunMetadataEncryption(metadata_encryption_key, authenticity_key, - salt, /*encrypt= */ true); - } - - /** Generates decrypted metadata key. `encrypted_metadata_key` must be 14 or - * 16 bytes long. `authenticity_key` is the AES key and must be 128 bit (16 - * bytes) long. `salt` must be 2 bytes long.*/ - static absl::StatusOr GenerateDecryptedMetadataKey( - absl::string_view encrypted_metadata_key, - absl::string_view authenticity_key, absl::string_view salt) { - return RunMetadataEncryption(encrypted_metadata_key, authenticity_key, salt, - /*encrypt= */ false); - } - - private: - static absl::StatusOr RunMetadataEncryption( - absl::string_view metadata, absl::string_view key, absl::string_view salt, - bool encrypt); -}; - -} // namespace presence -} // namespace nearby - -#endif // THIRD_PARTY_NEARBY_PRESENCE_IMPLEMENTATION_ENCRYPTION_H_ diff --git a/presence/implementation/encryption_test.cc b/presence/implementation/encryption_test.cc deleted file mode 100644 index f66b39bb..00000000 --- a/presence/implementation/encryption_test.cc +++ /dev/null @@ -1,131 +0,0 @@ -// 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/encryption.h" - -#include - -#include "gmock/gmock.h" -#include "protobuf-matchers/protocol-buffer-matchers.h" -#include "gtest/gtest.h" -#include "absl/strings/escaping.h" - -namespace nearby { -namespace presence { -namespace { - -TEST(EncryptionTest, CustomizeBytesSize) { - std::string ikm = "Input data"; - std::string kExpectedOutputHex = "51d2c0506732febbccf093066db66f269682137e"; - - std::string result = Encryption::CustomizeBytesSize(ikm, 20); - - EXPECT_EQ(absl::BytesToHexString(result), kExpectedOutputHex); -} - -TEST(EncryptionTest, GenerateRandomByteArray) { - std::string random1 = Encryption::GenerateRandomByteArray(10); - std::string random2 = Encryption::GenerateRandomByteArray(10); - - EXPECT_NE(random1, random2); -} - -TEST(EncryptionTest, GenerateEncryptedMetadataKeyFor14bytes) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("20212223242526272829303132333435"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKey = - absl::HexStringToBytes("4041424344454647484950515253"); - const std::string kExpectedOutputHex = "637b4868fcbcb3d8a67c47481807"; - - auto result = Encryption::GenerateEncryptedMetadataKey( - kMetadataKey, kAuthenticityKey, kSalt); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(absl::BytesToHexString(result.value()), kExpectedOutputHex); -} - -TEST(EncryptionTest, GenerateEncryptedMetadataKeyFor16bytes) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("20212223242526272829303132333435"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKey = - absl::HexStringToBytes("40414243444546474849505152535455"); - const std::string kExpectedOutputHex = "637b4868fcbcb3d8a67c47481807d139"; - - auto result = Encryption::GenerateEncryptedMetadataKey( - kMetadataKey, kAuthenticityKey, kSalt); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(absl::BytesToHexString(result.value()), kExpectedOutputHex); -} - -TEST(EncryptionTest, GenerateDecryptedMetadataKeyFor14bytes) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("20212223242526272829303132333435"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKeyHex = "4041424344454647484950515253"; - const std::string kEncryptedMetadata = - absl::HexStringToBytes("637b4868fcbcb3d8a67c47481807"); - - auto result = Encryption::GenerateDecryptedMetadataKey( - kEncryptedMetadata, kAuthenticityKey, kSalt); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(absl::BytesToHexString(result.value()), kMetadataKeyHex); -} - -TEST(EncryptionTest, GenerateDecryptedMetadataKeyFor16bytes) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("20212223242526272829303132333435"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKeyHex = "40414243444546474849505152535455"; - const std::string kEncryptedMetadata = - absl::HexStringToBytes("637b4868fcbcb3d8a67c47481807d139"); - - auto result = Encryption::GenerateDecryptedMetadataKey( - kEncryptedMetadata, kAuthenticityKey, kSalt); - - EXPECT_TRUE(result.ok()); - EXPECT_EQ(absl::BytesToHexString(result.value()), kMetadataKeyHex); -} - -TEST(EncryptionTest, RejectTooLongMetadataKey) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("20212223242526272829303132333435"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKey = - absl::HexStringToBytes("4041424344454647484950515253545566"); - - auto result = Encryption::GenerateEncryptedMetadataKey( - kMetadataKey, kAuthenticityKey, kSalt); - - EXPECT_FALSE(result.ok()); -} - -TEST(EncryptionTest, RejectInvalidAuthenticityKeySize) { - const std::string kAuthenticityKey = - absl::HexStringToBytes("2021222324252627282930313233343546"); - const std::string kSalt = absl::HexStringToBytes("0102"); - const std::string kMetadataKey = - absl::HexStringToBytes("40414243444546474849505152535455"); - - auto result = Encryption::GenerateEncryptedMetadataKey( - kMetadataKey, kAuthenticityKey, kSalt); - - EXPECT_FALSE(result.ok()); -} -} // namespace -} // namespace presence -} // namespace nearby