diff --git a/presence/implementation/credential_manager.h b/presence/implementation/credential_manager.h index 37129466..869f728d 100644 --- a/presence/implementation/credential_manager.h +++ b/presence/implementation/credential_manager.h @@ -77,6 +77,12 @@ class CredentialManager { location::nearby::api::CredentialSelector credential_selector, location::nearby::api::GetPublicCredentialsResultCallback callback) = 0; + // Decrypts the device metadata from a public credential. + // Returns an empty string if decryption fails. + virtual std::string DecryptDeviceMetadata( + std::string device_metadata_encryption_key, std::string authenticity_key, + std::string device_metadata_string) = 0; + // Decrypts Data Elements from an NP advertisement. // Returns an error if `metadata_key` is not associated with any known // credentials (identity). diff --git a/presence/implementation/credential_manager_impl.cc b/presence/implementation/credential_manager_impl.cc index 1447b1a3..23a4806b 100644 --- a/presence/implementation/credential_manager_impl.cc +++ b/presence/implementation/credential_manager_impl.cc @@ -19,9 +19,9 @@ #include #include +#include "internal/crypto/aead.h" #include "internal/crypto/ec_private_key.h" -#include "internal/crypto/encryptor.h" -#include "internal/crypto/symmetric_key.h" +#include "internal/crypto/hkdf.h" #include "internal/platform/base64_utils.h" #include "internal/platform/implementation/crypto.h" #include "internal/platform/logging.h" @@ -151,23 +151,76 @@ CredentialManagerImpl::CreatePublicCredential( metadata_encryption_key_tag.AsStringView()); // Encrypt the device metadata - crypto::Encryptor encryptor; - auto sym_key = crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, private_credential->metadata_encryption_key()); + auto encrypted_meta_data = EncryptDeviceMetadata( + private_credential->metadata_encryption_key(), + private_credential->authenticity_key(), + private_credential->device_metadata().SerializeAsString()); - auto iv = Encryption::CustomizeBytesSize( - private_credential->authenticity_key(), kAesGcmIVSize); - // It is GCM in the spec. Here we use CBC instead since GCM is not supported - // now. - if (!encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv)) { - NEARBY_LOG(ERROR, "Fails to initialize the encryptor"); + if (encrypted_meta_data.empty()) { + NEARBY_LOG(ERROR, "Fails to encrypt the device metadata."); return std::unique_ptr(nullptr); } - encryptor.Encrypt(private_credential->device_metadata().SerializeAsString(), - public_credential_ptr->mutable_encrypted_metadata_bytes()); + public_credential_ptr->set_encrypted_metadata_bytes(encrypted_meta_data); return public_credential_ptr; } +std::string CredentialManagerImpl::DecryptDeviceMetadata( + std::string device_metadata_encryption_key, std::string authenticity_key, + std::string device_metadata_string) { + crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM); + + std::vector derived_key = + ExtendMetadataEncryptionKey(device_metadata_encryption_key); + aead.Init(derived_key); + + auto iv = Encryption::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()); + + auto result = aead.Open(encrypted_device_metadata_bytes, + /*nonce=*/ + iv_bytes, + /*additional_data=*/absl::Span()); + + return std::string(result.value().begin(), result.value().end()); +} + +std::string CredentialManagerImpl::EncryptDeviceMetadata( + std::string device_metadata_encryption_key, std::string authenticity_key, + std::string device_metadata_string) { + crypto::Aead aead(crypto::Aead::AeadAlgorithm::AES_256_GCM); + + std::vector derived_key = + ExtendMetadataEncryptionKey(device_metadata_encryption_key); + + aead.Init(derived_key); + + auto iv = Encryption::CustomizeBytesSize(authenticity_key, kAesGcmIVSize); + std::vector iv_bytes(iv.begin(), iv.end()); + + std::vector device_metadata_bytes(device_metadata_string.begin(), + device_metadata_string.end()); + device_metadata_bytes.resize(device_metadata_string.size()); + + auto encrypted = aead.Seal(device_metadata_bytes, + /*nonce=*/ + iv_bytes, + /*additional_data=*/absl::Span()); + + return std::string(encrypted.begin(), encrypted.end()); +} + +std::vector CredentialManagerImpl::ExtendMetadataEncryptionKey( + std::string device_metadata_encryption_key) { + return crypto::HkdfSha256( + std::vector(device_metadata_encryption_key.begin(), + device_metadata_encryption_key.end()), + /*salt=*/absl::Span(), + /*info=*/absl::Span(), kNearbyPresenceNumBytesAesGcmKeySize); +} + } // namespace presence } // namespace nearby diff --git a/presence/implementation/credential_manager_impl.h b/presence/implementation/credential_manager_impl.h index e10e671a..35e4f20c 100644 --- a/presence/implementation/credential_manager_impl.h +++ b/presence/implementation/credential_manager_impl.h @@ -38,14 +38,17 @@ class CredentialManagerImpl : public CredentialManager { // AES only supports key sizes of 16, 24 or 32 bytes. static constexpr int kAuthenticityKeyByteSize = 16; + // Length of key in bytes required by AES-GCM encryption. + static constexpr size_t kNearbyPresenceNumBytesAesGcmKeySize = 32; + // Modify this to 12 after use real AES. - static constexpr int kAesGcmIVSize = 16; + static constexpr int kAesGcmIVSize = 12; void GenerateCredentials( proto::DeviceMetadata device_metadata, std::vector identity_types, int credential_life_cycle_days, int contiguous_copy_of_credentials, - GenerateCredentialsCallback credentials_generated_cb); + GenerateCredentialsCallback credentials_generated_cb) override; void UpdateRemotePublicCredentials( std::string account_name, @@ -63,6 +66,10 @@ class CredentialManagerImpl : public CredentialManager { location::nearby::api::GetPublicCredentialsResultCallback callback) override {} + std::string DecryptDeviceMetadata( + std::string device_metadata_encryption_key, std::string authenticity_key, + std::string device_metadata_string) override; + absl::StatusOr DecryptDataElements( absl::string_view metadata_key, absl::string_view salt, absl::string_view data_elements) override { @@ -93,6 +100,14 @@ class CredentialManagerImpl : public CredentialManager { std::unique_ptr CreatePublicCredential( proto::PrivateCredential* private_credential_ptr, std::vector* public_key); + + std::string EncryptDeviceMetadata(std::string device_metadata_encryption_key, + std::string authenticity_key, + std::string device_metadata_string); + + // Extend the key from 16 bytes to 32 bytes. + std::vector ExtendMetadataEncryptionKey( + std::string device_metadata_encryption_key); }; } // namespace presence diff --git a/presence/implementation/credential_manager_impl_test.cc b/presence/implementation/credential_manager_impl_test.cc index 0a4e3a7a..759742f7 100644 --- a/presence/implementation/credential_manager_impl_test.cc +++ b/presence/implementation/credential_manager_impl_test.cc @@ -20,8 +20,8 @@ #include "gmock/gmock.h" #include "protobuf-matchers/protocol-buffer-matchers.h" #include "gtest/gtest.h" -#include "internal/crypto/encryptor.h" -#include "internal/crypto/symmetric_key.h" +#include "internal/crypto/aead.h" +#include "internal/crypto/hkdf.h" #include "internal/platform/implementation/crypto.h" #include "presence/encryption.h" @@ -80,19 +80,14 @@ TEST(CredentialManagerImpl, CreateOneCredentialSuccessfully) { EXPECT_FALSE(public_credential->encrypted_metadata_bytes().empty()); // Decrypt the device metadata - crypto::Encryptor encryptor; - auto sym_key = crypto::SymmetricKey::Import( - crypto::SymmetricKey::AES, private_credential->metadata_encryption_key()); - EXPECT_TRUE(sym_key.get() != nullptr); - auto iv = - Encryption::CustomizeBytesSize(private_credential->authenticity_key(), - CredentialManagerImpl::kAesGcmIVSize); - encryptor.Init(sym_key.get(), crypto::Encryptor::CBC, iv); - std::string decrypted_metadata; - EXPECT_TRUE(encryptor.Decrypt(public_credential->encrypted_metadata_bytes(), - &decrypted_metadata)); + + auto decrypted_device_metadata = credential_manager.DecryptDeviceMetadata( + private_credential->metadata_encryption_key(), + public_credential->authenticity_key(), + public_credential->encrypted_metadata_bytes()); + EXPECT_EQ(private_credential->device_metadata().SerializeAsString(), - decrypted_metadata); + decrypted_device_metadata); } } // namespace presence } // namespace nearby