| // 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 <stddef.h> |
| #include <stdint.h> |
| |
| #include <vector> |
| |
| #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<const char*>(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<const uint8_t*>(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<EasyUnlockClientImpl> 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 |