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