// Copyright 2014 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/dbus/easy_unlock_client.h" #include #include #include #include "base/bind.h" #include "base/compiler_specific.h" #include "base/macros.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_path.h" #include "dbus/object_proxy.h" #include "third_party/cros_system_api/dbus/service_constants.h" namespace chromeos { namespace { // Reads array of bytes from a dbus message reader and converts it to string. std::string PopResponseData(dbus::MessageReader* reader) { const uint8_t* bytes = NULL; size_t length = 0; if (!reader->PopArrayOfBytes(&bytes, &length)) return ""; return std::string(reinterpret_cast(bytes), length); } // Converts string to array of bytes and writes it using dbus meddage writer. void AppendStringAsByteArray(const std::string& data, dbus::MessageWriter* writer) { writer->AppendArrayOfBytes(reinterpret_cast(data.data()), data.length()); } // The EasyUnlockClient used in production (and returned by // EasyUnlockClient::Create). class EasyUnlockClientImpl : public EasyUnlockClient { public: EasyUnlockClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {} ~EasyUnlockClientImpl() override {} // EasyUnlockClient override. void GenerateEcP256KeyPair(const KeyPairCallback& callback) override { dbus::MethodCall method_call( easy_unlock::kEasyUnlockServiceInterface, easy_unlock::kGenerateEcP256KeyPairMethod); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnKeyPair, weak_ptr_factory_.GetWeakPtr(), callback)); } // EasyUnlockClient override. void WrapPublicKey(const std::string& key_algorithm, const std::string& public_key, const DataCallback& callback) override { dbus::MethodCall method_call( easy_unlock::kEasyUnlockServiceInterface, easy_unlock::kWrapPublicKeyMethod); dbus::MessageWriter writer(&method_call); writer.AppendString(key_algorithm); AppendStringAsByteArray(public_key, &writer); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } // EasyUnlockClient override. void PerformECDHKeyAgreement(const std::string& private_key, const std::string& public_key, const DataCallback& callback) override { dbus::MethodCall method_call( easy_unlock::kEasyUnlockServiceInterface, easy_unlock::kPerformECDHKeyAgreementMethod); dbus::MessageWriter writer(&method_call); // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is // not guaranteed here, so the method uses byte arrays. AppendStringAsByteArray(private_key, &writer); AppendStringAsByteArray(public_key, &writer); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } // EasyUnlockClient override. void CreateSecureMessage(const std::string& payload, const CreateSecureMessageOptions& options, const DataCallback& callback) override { dbus::MethodCall method_call( easy_unlock::kEasyUnlockServiceInterface, easy_unlock::kCreateSecureMessageMethod); dbus::MessageWriter writer(&method_call); // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is // not guaranteed here, so the method uses byte arrays. AppendStringAsByteArray(payload, &writer); AppendStringAsByteArray(options.key, &writer); AppendStringAsByteArray(options.associated_data, &writer); AppendStringAsByteArray(options.public_metadata, &writer); AppendStringAsByteArray(options.verification_key_id, &writer); AppendStringAsByteArray(options.decryption_key_id, &writer); writer.AppendString(options.encryption_type); writer.AppendString(options.signature_type); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } // EasyUnlockClient override. void UnwrapSecureMessage(const std::string& message, const UnwrapSecureMessageOptions& options, const DataCallback& callback) override { dbus::MethodCall method_call( easy_unlock::kEasyUnlockServiceInterface, easy_unlock::kUnwrapSecureMessageMethod); dbus::MessageWriter writer(&method_call); // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is // not guaranteed here, so the method uses byte arrays. AppendStringAsByteArray(message, &writer); AppendStringAsByteArray(options.key, &writer); AppendStringAsByteArray(options.associated_data, &writer); writer.AppendString(options.encryption_type); writer.AppendString(options.signature_type); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } protected: void Init(dbus::Bus* bus) override { proxy_ = bus->GetObjectProxy( easy_unlock::kEasyUnlockServiceName, dbus::ObjectPath(easy_unlock::kEasyUnlockServicePath)); } private: void OnData(const DataCallback& callback, dbus::Response* response) { if (!response) { callback.Run(""); return; } dbus::MessageReader reader(response); callback.Run(PopResponseData(&reader)); } void OnKeyPair(const KeyPairCallback& callback, dbus::Response* response) { if (!response) { callback.Run("", ""); return; } dbus::MessageReader reader(response); std::string private_key = PopResponseData(&reader); std::string public_key = PopResponseData(&reader); if (public_key.empty() || private_key.empty()) { callback.Run("", ""); return; } callback.Run(private_key, public_key); } dbus::ObjectProxy* proxy_; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed. base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(EasyUnlockClientImpl); }; } // namespace EasyUnlockClient::CreateSecureMessageOptions::CreateSecureMessageOptions() {} EasyUnlockClient::CreateSecureMessageOptions::~CreateSecureMessageOptions() {} EasyUnlockClient::UnwrapSecureMessageOptions::UnwrapSecureMessageOptions() {} EasyUnlockClient::UnwrapSecureMessageOptions::~UnwrapSecureMessageOptions() {} EasyUnlockClient::EasyUnlockClient() { } EasyUnlockClient::~EasyUnlockClient() { } // static EasyUnlockClient* EasyUnlockClient::Create() { return new EasyUnlockClientImpl(); } } // namespace chromeos