// 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 "base/bind.h" #include "base/compiler_specific.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* 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) {} virtual ~EasyUnlockClientImpl() {} // EasyUnlockClient override. virtual 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. virtual 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. virtual void CreateSecureMessage(const std::string& payload, const std::string& secret_key, const std::string& associated_data, const std::string& public_metadata, const std::string& verification_key_id, const std::string& decryption_key_id, const std::string& encryption_type, const std::string& signature_type, 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(secret_key, &writer); AppendStringAsByteArray(associated_data, &writer); AppendStringAsByteArray(public_metadata, &writer); AppendStringAsByteArray(verification_key_id, &writer); AppendStringAsByteArray(decryption_key_id, &writer); writer.AppendString(encryption_type); writer.AppendString(signature_type); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } // EasyUnlockClient override. virtual void UnwrapSecureMessage(const std::string& message, const std::string& secret_key, const std::string& associated_data, const std::string& encryption_type, const std::string& signature_type, 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(secret_key, &writer); AppendStringAsByteArray(associated_data, &writer); writer.AppendString(encryption_type); writer.AppendString(signature_type); proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::Bind(&EasyUnlockClientImpl::OnData, weak_ptr_factory_.GetWeakPtr(), callback)); } protected: virtual 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::EasyUnlockClient() { } EasyUnlockClient::~EasyUnlockClient() { } // static EasyUnlockClient* EasyUnlockClient::Create() { return new EasyUnlockClientImpl(); } } // namespace chromeos