blob: 93cfe854cec18640c0d591550ca3d9f157495300 [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/components/multidevice/secure_message_delegate_impl.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/easy_unlock_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace multidevice {
namespace {
// Converts encryption type to a string representation used by EasyUnlock dbus
// client.
std::string EncSchemeToString(securemessage::EncScheme scheme) {
switch (scheme) {
case securemessage::AES_256_CBC:
return easy_unlock::kEncryptionTypeAES256CBC;
case securemessage::NONE:
return easy_unlock::kEncryptionTypeNone;
}
NOTREACHED();
return std::string();
}
// Converts signature type to a string representation used by EasyUnlock dbus
// client.
std::string SigSchemeToString(securemessage::SigScheme scheme) {
switch (scheme) {
case securemessage::ECDSA_P256_SHA256:
return easy_unlock::kSignatureTypeECDSAP256SHA256;
case securemessage::HMAC_SHA256:
return easy_unlock::kSignatureTypeHMACSHA256;
case securemessage::RSA2048_SHA256:
// RSA2048_SHA256 is not supported by the daemon.
NOTREACHED();
return std::string();
}
NOTREACHED();
return std::string();
}
// Parses the serialized HeaderAndBody string returned by the DBus client, and
// calls the corresponding SecureMessageDelegate unwrap callback.
void HandleUnwrapResult(
const SecureMessageDelegate::UnwrapSecureMessageCallback& callback,
const std::string& unwrap_result) {
securemessage::HeaderAndBody header_and_body;
if (!header_and_body.ParseFromString(unwrap_result)) {
callback.Run(false, std::string(), securemessage::Header());
} else {
callback.Run(true, header_and_body.body(), header_and_body.header());
}
}
// The SecureMessageDelegate expects the keys in the reverse order returned by
// the DBus client.
void HandleKeyPairResult(
const SecureMessageDelegate::GenerateKeyPairCallback& callback,
const std::string& private_key,
const std::string& public_key) {
callback.Run(public_key, private_key);
}
} // namespace
// static
SecureMessageDelegateImpl::Factory*
SecureMessageDelegateImpl::Factory::test_factory_instance_ = nullptr;
// static
std::unique_ptr<SecureMessageDelegate>
SecureMessageDelegateImpl::Factory::NewInstance() {
if (test_factory_instance_)
return test_factory_instance_->BuildInstance();
static base::NoDestructor<SecureMessageDelegateImpl::Factory> factory;
return factory->BuildInstance();
}
// static
void SecureMessageDelegateImpl::Factory::SetInstanceForTesting(
Factory* test_factory) {
test_factory_instance_ = test_factory;
}
SecureMessageDelegateImpl::Factory::~Factory() = default;
std::unique_ptr<SecureMessageDelegate>
SecureMessageDelegateImpl::Factory::BuildInstance() {
return base::WrapUnique(new SecureMessageDelegateImpl());
}
SecureMessageDelegateImpl::SecureMessageDelegateImpl()
: dbus_client_(chromeos::DBusThreadManager::Get()->GetEasyUnlockClient()) {}
SecureMessageDelegateImpl::~SecureMessageDelegateImpl() {}
void SecureMessageDelegateImpl::GenerateKeyPair(
const GenerateKeyPairCallback& callback) {
dbus_client_->GenerateEcP256KeyPair(
base::BindOnce(HandleKeyPairResult, callback));
}
void SecureMessageDelegateImpl::DeriveKey(const std::string& private_key,
const std::string& public_key,
const DeriveKeyCallback& callback) {
dbus_client_->PerformECDHKeyAgreement(private_key, public_key, callback);
}
void SecureMessageDelegateImpl::CreateSecureMessage(
const std::string& payload,
const std::string& key,
const CreateOptions& create_options,
const CreateSecureMessageCallback& callback) {
if (create_options.signature_scheme == securemessage::RSA2048_SHA256) {
PA_LOG(ERROR) << "Unable to create message: RSA2048_SHA256 not supported "
<< "by the ChromeOS daemon.";
callback.Run(std::string());
return;
}
chromeos::EasyUnlockClient::CreateSecureMessageOptions options;
options.key.assign(key);
if (!create_options.associated_data.empty())
options.associated_data.assign(create_options.associated_data);
if (!create_options.public_metadata.empty())
options.public_metadata.assign(create_options.public_metadata);
if (!create_options.verification_key_id.empty())
options.verification_key_id.assign(create_options.verification_key_id);
if (!create_options.decryption_key_id.empty())
options.decryption_key_id.assign(create_options.decryption_key_id);
options.encryption_type = EncSchemeToString(create_options.encryption_scheme);
options.signature_type = SigSchemeToString(create_options.signature_scheme);
dbus_client_->CreateSecureMessage(payload, options, callback);
}
void SecureMessageDelegateImpl::UnwrapSecureMessage(
const std::string& serialized_message,
const std::string& key,
const UnwrapOptions& unwrap_options,
const UnwrapSecureMessageCallback& callback) {
if (unwrap_options.signature_scheme == securemessage::RSA2048_SHA256) {
PA_LOG(ERROR) << "Unable to unwrap message: RSA2048_SHA256 not supported "
<< "by the ChromeOS daemon.";
callback.Run(false, std::string(), securemessage::Header());
return;
}
chromeos::EasyUnlockClient::UnwrapSecureMessageOptions options;
options.key.assign(key);
if (!unwrap_options.associated_data.empty())
options.associated_data.assign(unwrap_options.associated_data);
options.encryption_type = EncSchemeToString(unwrap_options.encryption_scheme);
options.signature_type = SigSchemeToString(unwrap_options.signature_scheme);
dbus_client_->UnwrapSecureMessage(
serialized_message, options,
base::BindOnce(&HandleUnwrapResult, callback));
}
} // namespace multidevice
} // namespace chromeos