1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chromeos/dbus/easy_unlock_client.h" 6 7 #include <vector> 8 9 #include "base/bind.h" 10 #include "base/compiler_specific.h" 11 #include "dbus/bus.h" 12 #include "dbus/message.h" 13 #include "dbus/object_path.h" 14 #include "dbus/object_proxy.h" 15 #include "third_party/cros_system_api/dbus/service_constants.h" 16 17 namespace chromeos { 18 19 namespace { 20 21 // Reads array of bytes from a dbus message reader and converts it to string. 22 std::string PopResponseData(dbus::MessageReader* reader) { 23 const uint8* bytes = NULL; 24 size_t length = 0; 25 if (!reader->PopArrayOfBytes(&bytes, &length)) 26 return ""; 27 28 return std::string(reinterpret_cast<const char*>(bytes), length); 29 } 30 31 // Converts string to array of bytes and writes it using dbus meddage writer. 32 void AppendStringAsByteArray(const std::string& data, 33 dbus::MessageWriter* writer) { 34 writer->AppendArrayOfBytes(reinterpret_cast<const uint8*>(data.data()), 35 data.length()); 36 } 37 38 // The EasyUnlockClient used in production (and returned by 39 // EasyUnlockClient::Create). 40 class EasyUnlockClientImpl : public EasyUnlockClient { 41 public: 42 EasyUnlockClientImpl() : proxy_(NULL), weak_ptr_factory_(this) {} 43 44 virtual ~EasyUnlockClientImpl() {} 45 46 // EasyUnlockClient override. 47 virtual void PerformECDHKeyAgreement(const std::string& private_key, 48 const std::string& public_key, 49 const DataCallback& callback) OVERRIDE { 50 dbus::MethodCall method_call( 51 easy_unlock::kEasyUnlockServiceInterface, 52 easy_unlock::kPerformECDHKeyAgreementMethod); 53 dbus::MessageWriter writer(&method_call); 54 // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is 55 // not guaranteed here, so the method uses byte arrays. 56 AppendStringAsByteArray(private_key, &writer); 57 AppendStringAsByteArray(public_key, &writer); 58 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 59 base::Bind(&EasyUnlockClientImpl::OnData, 60 weak_ptr_factory_.GetWeakPtr(), 61 callback)); 62 } 63 64 // EasyUnlockClient override. 65 virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) OVERRIDE { 66 dbus::MethodCall method_call( 67 easy_unlock::kEasyUnlockServiceInterface, 68 easy_unlock::kGenerateEcP256KeyPairMethod); 69 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 70 base::Bind(&EasyUnlockClientImpl::OnKeyPair, 71 weak_ptr_factory_.GetWeakPtr(), 72 callback)); 73 } 74 75 // EasyUnlockClient override. 76 virtual void CreateSecureMessage(const std::string& payload, 77 const CreateSecureMessageOptions& options, 78 const DataCallback& callback) OVERRIDE { 79 dbus::MethodCall method_call( 80 easy_unlock::kEasyUnlockServiceInterface, 81 easy_unlock::kCreateSecureMessageMethod); 82 dbus::MessageWriter writer(&method_call); 83 // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is 84 // not guaranteed here, so the method uses byte arrays. 85 AppendStringAsByteArray(payload, &writer); 86 AppendStringAsByteArray(options.key, &writer); 87 AppendStringAsByteArray(options.associated_data, &writer); 88 AppendStringAsByteArray(options.public_metadata, &writer); 89 AppendStringAsByteArray(options.verification_key_id, &writer); 90 AppendStringAsByteArray(options.decryption_key_id, &writer); 91 writer.AppendString(options.encryption_type); 92 writer.AppendString(options.signature_type); 93 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 94 base::Bind(&EasyUnlockClientImpl::OnData, 95 weak_ptr_factory_.GetWeakPtr(), 96 callback)); 97 } 98 99 // EasyUnlockClient override. 100 virtual void UnwrapSecureMessage(const std::string& message, 101 const UnwrapSecureMessageOptions& options, 102 const DataCallback& callback) OVERRIDE { 103 dbus::MethodCall method_call( 104 easy_unlock::kEasyUnlockServiceInterface, 105 easy_unlock::kUnwrapSecureMessageMethod); 106 dbus::MessageWriter writer(&method_call); 107 // NOTE: DBus expects that data sent as string is UTF-8 encoded. This is 108 // not guaranteed here, so the method uses byte arrays. 109 AppendStringAsByteArray(message, &writer); 110 AppendStringAsByteArray(options.key, &writer); 111 AppendStringAsByteArray(options.associated_data, &writer); 112 writer.AppendString(options.encryption_type); 113 writer.AppendString(options.signature_type); 114 proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, 115 base::Bind(&EasyUnlockClientImpl::OnData, 116 weak_ptr_factory_.GetWeakPtr(), 117 callback)); 118 } 119 120 protected: 121 virtual void Init(dbus::Bus* bus) OVERRIDE { 122 proxy_ = 123 bus->GetObjectProxy( 124 easy_unlock::kEasyUnlockServiceName, 125 dbus::ObjectPath(easy_unlock::kEasyUnlockServicePath)); 126 } 127 128 private: 129 void OnData(const DataCallback& callback, dbus::Response* response) { 130 if (!response) { 131 callback.Run(""); 132 return; 133 } 134 135 dbus::MessageReader reader(response); 136 callback.Run(PopResponseData(&reader)); 137 } 138 139 void OnKeyPair(const KeyPairCallback& callback, dbus::Response* response) { 140 if (!response) { 141 callback.Run("", ""); 142 return; 143 } 144 145 dbus::MessageReader reader(response); 146 std::string private_key = PopResponseData(&reader); 147 std::string public_key = PopResponseData(&reader); 148 149 if (public_key.empty() || private_key.empty()) { 150 callback.Run("", ""); 151 return; 152 } 153 154 callback.Run(private_key, public_key); 155 } 156 157 dbus::ObjectProxy* proxy_; 158 159 // Note: This should remain the last member so it'll be destroyed and 160 // invalidate its weak pointers before any other members are destroyed. 161 base::WeakPtrFactory<EasyUnlockClientImpl> weak_ptr_factory_; 162 163 DISALLOW_COPY_AND_ASSIGN(EasyUnlockClientImpl); 164 }; 165 166 } // namespace 167 168 EasyUnlockClient::CreateSecureMessageOptions::CreateSecureMessageOptions() {} 169 170 EasyUnlockClient::CreateSecureMessageOptions::~CreateSecureMessageOptions() {} 171 172 EasyUnlockClient::UnwrapSecureMessageOptions::UnwrapSecureMessageOptions() {} 173 174 EasyUnlockClient::UnwrapSecureMessageOptions::~UnwrapSecureMessageOptions() {} 175 176 EasyUnlockClient::EasyUnlockClient() { 177 } 178 179 EasyUnlockClient::~EasyUnlockClient() { 180 } 181 182 // static 183 EasyUnlockClient* EasyUnlockClient::Create() { 184 return new EasyUnlockClientImpl(); 185 } 186 187 } // namespace chromeos 188