Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / networking_private / crypto_verify_impl.cc
blob2385a3e311faa62fbf8753785b94e00c3a06304e
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.
5 #include "chrome/browser/extensions/api/networking_private/crypto_verify_impl.h"
7 #include "base/base64.h"
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
10 #include "base/sequenced_task_runner.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/sequenced_worker_pool.h"
15 #include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
16 #include "chrome/common/extensions/api/networking_private/networking_private_crypto.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "extensions/browser/api/networking_private/networking_private_api.h"
19 #include "extensions/browser/api/networking_private/networking_private_service_client.h"
20 #include "extensions/common/api/networking_private.h"
22 namespace extensions {
24 namespace {
26 const char kCryptoVerifySequenceTokenName[] = "CryptoVerify";
28 // Called from a blocking pool task runner. Returns true and sets |verified| if
29 // able to decode the credentials, otherwise sets |verified| to false and
30 // returns false.
31 bool DecodeAndVerifyCredentials(
32 const CryptoVerifyImpl::Credentials& credentials,
33 bool* verified) {
34 std::string decoded_signed_data;
35 if (!base::Base64Decode(credentials.signed_data, &decoded_signed_data)) {
36 LOG(ERROR) << "Failed to decode signed data";
37 *verified = false;
38 return false;
40 *verified = networking_private_crypto::VerifyCredentials(
41 credentials.certificate, credentials.intermediate_certificates,
42 decoded_signed_data, credentials.unsigned_data, credentials.device_bssid);
43 return true;
46 void VerifyDestinationCompleted(
47 const CryptoVerifyImpl::BoolCallback& success_callback,
48 const CryptoVerifyImpl::FailureCallback& failure_callback,
49 bool* verified,
50 bool success) {
51 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
52 if (!success)
53 failure_callback.Run(networking_private::kErrorEncryptionError);
54 else
55 success_callback.Run(*verified);
58 // Called from a blocking pool task runner. Returns |data| encoded using
59 // |credentials| on success, or an empty string on failure.
60 std::string DoVerifyAndEncryptData(
61 const CryptoVerifyImpl::Credentials& credentials,
62 const std::string& data) {
63 bool verified;
64 if (!DecodeAndVerifyCredentials(credentials, &verified) || !verified)
65 return std::string();
67 std::string decoded_public_key;
68 if (!base::Base64Decode(credentials.public_key, &decoded_public_key)) {
69 LOG(ERROR) << "Failed to decode public key";
70 return std::string();
73 std::vector<uint8_t> public_key_data(decoded_public_key.begin(),
74 decoded_public_key.end());
75 std::vector<uint8_t> ciphertext;
76 if (!networking_private_crypto::EncryptByteString(public_key_data, data,
77 &ciphertext)) {
78 LOG(ERROR) << "Failed to encrypt data";
79 return std::string();
82 std::string base64_encoded_ciphertext;
83 base::Base64Encode(std::string(ciphertext.begin(), ciphertext.end()),
84 &base64_encoded_ciphertext);
85 return base64_encoded_ciphertext;
88 void VerifyAndEncryptDataCompleted(
89 const CryptoVerifyImpl::StringCallback& success_callback,
90 const CryptoVerifyImpl::FailureCallback& failure_callback,
91 const std::string& encrypted_data) {
92 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
93 if (encrypted_data.empty())
94 failure_callback.Run(networking_private::kErrorEncryptionError);
95 else
96 success_callback.Run(encrypted_data);
99 // Called when NetworkingPrivateCredentialsGetter completes (from an arbitrary
100 // thread). Posts the result to the UI thread.
101 void CredentialsGetterCompleted(
102 const CryptoVerifyImpl::StringCallback& success_callback,
103 const CryptoVerifyImpl::FailureCallback& failure_callback,
104 const std::string& key_data,
105 const std::string& error) {
106 if (!error.empty()) {
107 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
108 base::Bind(failure_callback, error));
109 } else {
110 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
111 base::Bind(success_callback, key_data));
115 // Called from a blocking pool task runner. Returns true if
116 // NetworkingPrivateCredentialsGetter is successfully started (which will
117 // invoke the appropriate callback when completed), or false if unable
118 // to start the getter (credentials or public key decode failed).
119 bool DoVerifyAndEncryptCredentials(
120 const std::string& guid,
121 const CryptoVerifyImpl::Credentials& credentials,
122 const CryptoVerifyImpl::StringCallback& success_callback,
123 const CryptoVerifyImpl::FailureCallback& failure_callback) {
124 bool verified;
125 if (!DecodeAndVerifyCredentials(credentials, &verified) || !verified)
126 return false;
128 std::string decoded_public_key;
129 if (!base::Base64Decode(credentials.public_key, &decoded_public_key)) {
130 LOG(ERROR) << "Failed to decode public key";
131 return false;
134 // Start getting credentials. CredentialsGetterCompleted will be called on
135 // completion. On Windows it will be called from a different thread after
136 // |credentials_getter| is deleted.
137 scoped_ptr<NetworkingPrivateCredentialsGetter> credentials_getter(
138 NetworkingPrivateCredentialsGetter::Create());
139 credentials_getter->Start(guid, decoded_public_key,
140 base::Bind(&CredentialsGetterCompleted,
141 success_callback, failure_callback));
142 return true;
145 void VerifyAndEncryptCredentialsCompleted(
146 const CryptoVerifyImpl::FailureCallback& failure_callback,
147 bool succeeded) {
148 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
149 // If VerifyAndEncryptCredentials succeeded, then the appropriate callback
150 // will be triggered from CredentialsGetterCompleted.
151 if (succeeded)
152 return;
153 failure_callback.Run(networking_private::kErrorEncryptionError);
156 } // namespace
158 CryptoVerifyImpl::Credentials::Credentials(
159 const VerificationProperties& properties) {
160 certificate = properties.certificate;
161 if (properties.intermediate_certificates.get())
162 intermediate_certificates = *properties.intermediate_certificates;
163 signed_data = properties.signed_data;
165 std::vector<std::string> data_parts;
166 data_parts.push_back(properties.device_ssid);
167 data_parts.push_back(properties.device_serial);
168 data_parts.push_back(properties.device_bssid);
169 data_parts.push_back(properties.public_key);
170 data_parts.push_back(properties.nonce);
171 unsigned_data = base::JoinString(data_parts, ",");
173 device_bssid = properties.device_bssid;
174 public_key = properties.public_key;
177 CryptoVerifyImpl::Credentials::~Credentials() {
180 CryptoVerifyImpl::CryptoVerifyImpl() {
181 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
182 base::SequencedWorkerPool::SequenceToken sequence_token =
183 content::BrowserThread::GetBlockingPool()->GetNamedSequenceToken(
184 kCryptoVerifySequenceTokenName);
185 blocking_pool_task_runner_ =
186 content::BrowserThread::GetBlockingPool()
187 ->GetSequencedTaskRunnerWithShutdownBehavior(
188 sequence_token, base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
191 CryptoVerifyImpl::~CryptoVerifyImpl() {
192 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
195 void CryptoVerifyImpl::VerifyDestination(
196 const VerificationProperties& verification_properties,
197 const BoolCallback& success_callback,
198 const FailureCallback& failure_callback) {
199 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
200 Credentials credentials(verification_properties);
201 bool* verified = new bool;
202 base::PostTaskAndReplyWithResult(
203 blocking_pool_task_runner_.get(), FROM_HERE,
204 base::Bind(&DecodeAndVerifyCredentials, credentials, verified),
205 base::Bind(&VerifyDestinationCompleted, success_callback,
206 failure_callback, base::Owned(verified)));
209 void CryptoVerifyImpl::VerifyAndEncryptCredentials(
210 const std::string& guid,
211 const VerificationProperties& verification_properties,
212 const StringCallback& success_callback,
213 const FailureCallback& failure_callback) {
214 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
215 Credentials credentials(verification_properties);
216 base::PostTaskAndReplyWithResult(
217 blocking_pool_task_runner_.get(), FROM_HERE,
218 base::Bind(&DoVerifyAndEncryptCredentials, guid, credentials,
219 success_callback, failure_callback),
220 base::Bind(&VerifyAndEncryptCredentialsCompleted, failure_callback));
223 void CryptoVerifyImpl::VerifyAndEncryptData(
224 const VerificationProperties& verification_properties,
225 const std::string& data,
226 const StringCallback& success_callback,
227 const FailureCallback& failure_callback) {
228 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
229 Credentials credentials(verification_properties);
230 base::PostTaskAndReplyWithResult(
231 blocking_pool_task_runner_.get(), FROM_HERE,
232 base::Bind(&DoVerifyAndEncryptData, credentials, data),
233 base::Bind(&VerifyAndEncryptDataCompleted, success_callback,
234 failure_callback));
237 } // namespace extensions