blob: ac116a4ae7e00d9a0d81a6aca3b50ff43c8943fe [file] [log] [blame]
Alex Vakulenko0155b392015-05-06 15:30:58 -07001// Copyright 2015 The Chromium OS 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
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -07005#include <brillo/streams/tls_stream.h>
Alex Vakulenko0155b392015-05-06 15:30:58 -07006
7#include <algorithm>
8#include <limits>
9#include <string>
10#include <vector>
11
12#include <openssl/err.h>
13#include <openssl/ssl.h>
14
15#include <base/bind.h>
16#include <base/memory/weak_ptr.h>
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070017#include <brillo/message_loops/message_loop.h>
18#include <brillo/secure_blob.h>
19#include <brillo/streams/openssl_stream_bio.h>
20#include <brillo/streams/stream_utils.h>
21#include <brillo/strings/string_utils.h>
Alex Vakulenko0155b392015-05-06 15:30:58 -070022
23namespace {
24
25// SSL info callback which is called by OpenSSL when we enable logging level of
26// at least 3. This logs the information about the internal TLS handshake.
Christopher Wiley2fd46ba2016-01-04 08:59:09 -080027void TlsInfoCallback(const SSL* /* ssl */, int where, int ret) {
Alex Vakulenko0155b392015-05-06 15:30:58 -070028 std::string reason;
29 std::vector<std::string> info;
30 if (where & SSL_CB_LOOP)
31 info.push_back("loop");
32 if (where & SSL_CB_EXIT)
33 info.push_back("exit");
34 if (where & SSL_CB_READ)
35 info.push_back("read");
36 if (where & SSL_CB_WRITE)
37 info.push_back("write");
38 if (where & SSL_CB_ALERT) {
39 info.push_back("alert");
40 reason = ", reason: ";
41 reason += SSL_alert_type_string_long(ret);
42 reason += "/";
43 reason += SSL_alert_desc_string_long(ret);
44 }
45 if (where & SSL_CB_HANDSHAKE_START)
46 info.push_back("handshake_start");
47 if (where & SSL_CB_HANDSHAKE_DONE)
48 info.push_back("handshake_done");
49
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070050 VLOG(3) << "TLS progress info: " << brillo::string_utils::Join(",", info)
Alex Vakulenko0155b392015-05-06 15:30:58 -070051 << ", with status: " << ret << reason;
52}
53
Alex Vakulenkof76c6822015-05-11 15:45:25 -070054// Static variable to store the index of TlsStream private data in SSL context
55// used to store custom data for OnCertVerifyResults().
56int ssl_ctx_private_data_index = -1;
57
58// Default trusted certificate store location.
Alex Vakulenko3703d372015-08-19 12:02:02 -070059const char kCACertificatePath[] =
60#ifdef __ANDROID__
Bertrand SIMONNETbccdc4c2015-11-25 15:36:51 -080061 "/system/etc/security/cacerts_google";
Alex Vakulenko3703d372015-08-19 12:02:02 -070062#else
63 "/usr/share/chromeos-ca-certificates";
64#endif
Alex Vakulenkof76c6822015-05-11 15:45:25 -070065
Alex Vakulenko0155b392015-05-06 15:30:58 -070066} // anonymous namespace
67
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070068namespace brillo {
Alex Vakulenko0155b392015-05-06 15:30:58 -070069
70// Helper implementation of TLS stream used to hide most of OpenSSL inner
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -070071// workings from the users of brillo::TlsStream.
Alex Vakulenko0155b392015-05-06 15:30:58 -070072class TlsStream::TlsStreamImpl {
73 public:
74 TlsStreamImpl();
75 ~TlsStreamImpl();
76
77 bool Init(StreamPtr socket,
Alex Vakulenkof76c6822015-05-11 15:45:25 -070078 const std::string& host,
Alex Vakulenko0155b392015-05-06 15:30:58 -070079 const base::Closure& success_callback,
80 const Stream::ErrorCallback& error_callback,
81 ErrorPtr* error);
82
83 bool ReadNonBlocking(void* buffer,
84 size_t size_to_read,
85 size_t* size_read,
86 bool* end_of_stream,
87 ErrorPtr* error);
88
89 bool WriteNonBlocking(const void* buffer,
90 size_t size_to_write,
91 size_t* size_written,
92 ErrorPtr* error);
93
94 bool Flush(ErrorPtr* error);
95 bool Close(ErrorPtr* error);
96 bool WaitForData(AccessMode mode,
97 const base::Callback<void(AccessMode)>& callback,
98 ErrorPtr* error);
99 bool WaitForDataBlocking(AccessMode in_mode,
Alex Vakulenko1b792392015-06-03 12:06:53 -0700100 base::TimeDelta timeout,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700101 AccessMode* out_mode,
102 ErrorPtr* error);
Alex Vakulenko8cb41342015-05-15 16:00:14 -0700103 void CancelPendingAsyncOperations();
Alex Vakulenko0155b392015-05-06 15:30:58 -0700104
105 private:
106 bool ReportError(ErrorPtr* error,
107 const tracked_objects::Location& location,
108 const std::string& message);
109 void DoHandshake(const base::Closure& success_callback,
110 const Stream::ErrorCallback& error_callback);
111 void RetryHandshake(const base::Closure& success_callback,
112 const Stream::ErrorCallback& error_callback,
113 Stream::AccessMode mode);
114
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700115 int OnCertVerifyResults(int ok, X509_STORE_CTX* ctx);
116 static int OnCertVerifyResultsStatic(int ok, X509_STORE_CTX* ctx);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700117
118 StreamPtr socket_;
119 std::unique_ptr<SSL_CTX, decltype(&SSL_CTX_free)> ctx_{nullptr, SSL_CTX_free};
120 std::unique_ptr<SSL, decltype(&SSL_free)> ssl_{nullptr, SSL_free};
121 BIO* stream_bio_{nullptr};
122 bool need_more_read_{false};
123 bool need_more_write_{false};
124
Alex Vakulenko0155b392015-05-06 15:30:58 -0700125 base::WeakPtrFactory<TlsStreamImpl> weak_ptr_factory_{this};
126 DISALLOW_COPY_AND_ASSIGN(TlsStreamImpl);
127};
128
129TlsStream::TlsStreamImpl::TlsStreamImpl() {
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700130 SSL_load_error_strings();
131 SSL_library_init();
132 if (ssl_ctx_private_data_index < 0) {
133 ssl_ctx_private_data_index =
134 SSL_CTX_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
135 }
Alex Vakulenko0155b392015-05-06 15:30:58 -0700136}
137
138TlsStream::TlsStreamImpl::~TlsStreamImpl() {
139 ssl_.reset();
140 ctx_.reset();
141}
142
143bool TlsStream::TlsStreamImpl::ReadNonBlocking(void* buffer,
144 size_t size_to_read,
145 size_t* size_read,
146 bool* end_of_stream,
147 ErrorPtr* error) {
148 const size_t max_int = std::numeric_limits<int>::max();
149 int size_int = static_cast<int>(std::min(size_to_read, max_int));
150 int ret = SSL_read(ssl_.get(), buffer, size_int);
151 if (ret > 0) {
152 *size_read = static_cast<size_t>(ret);
153 if (end_of_stream)
154 *end_of_stream = false;
155 return true;
156 }
157
158 int err = SSL_get_error(ssl_.get(), ret);
159 if (err == SSL_ERROR_ZERO_RETURN) {
160 *size_read = 0;
161 if (end_of_stream)
162 *end_of_stream = true;
163 return true;
164 }
165
166 if (err == SSL_ERROR_WANT_READ) {
167 need_more_read_ = true;
168 } else if (err == SSL_ERROR_WANT_WRITE) {
169 // Writes might be required for SSL_read() because of possible TLS
170 // re-negotiations which can happen at any time.
171 need_more_write_ = true;
172 } else {
173 return ReportError(error, FROM_HERE, "Error reading from TLS socket");
174 }
175 *size_read = 0;
176 if (end_of_stream)
177 *end_of_stream = false;
178 return true;
179}
180
181bool TlsStream::TlsStreamImpl::WriteNonBlocking(const void* buffer,
182 size_t size_to_write,
183 size_t* size_written,
184 ErrorPtr* error) {
185 const size_t max_int = std::numeric_limits<int>::max();
186 int size_int = static_cast<int>(std::min(size_to_write, max_int));
187 int ret = SSL_write(ssl_.get(), buffer, size_int);
188 if (ret > 0) {
189 *size_written = static_cast<size_t>(ret);
190 return true;
191 }
192
193 int err = SSL_get_error(ssl_.get(), ret);
194 if (err == SSL_ERROR_WANT_READ) {
195 // Reads might be required for SSL_write() because of possible TLS
196 // re-negotiations which can happen at any time.
197 need_more_read_ = true;
198 } else if (err == SSL_ERROR_WANT_WRITE) {
199 need_more_write_ = true;
200 } else {
201 return ReportError(error, FROM_HERE, "Error writing to TLS socket");
202 }
203 *size_written = 0;
204 return true;
205}
206
207bool TlsStream::TlsStreamImpl::Flush(ErrorPtr* error) {
208 return socket_->FlushBlocking(error);
209}
210
211bool TlsStream::TlsStreamImpl::Close(ErrorPtr* error) {
Alex Vakulenko1b792392015-06-03 12:06:53 -0700212 // 2 seconds should be plenty here.
213 const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(2);
Alex Vakulenkof1f06b42015-06-03 12:20:15 -0700214 // The retry count of 4 below is just arbitrary, to ensure we don't get stuck
215 // here forever. We should rarely need to repeat SSL_shutdown anyway.
216 for (int retry_count = 0; retry_count < 4; retry_count++) {
Alex Vakulenko0155b392015-05-06 15:30:58 -0700217 int ret = SSL_shutdown(ssl_.get());
Alex Vakulenkof1f06b42015-06-03 12:20:15 -0700218 // We really don't care for bi-directional shutdown here.
219 // Just make sure we only send the "close notify" alert to the remote peer.
220 if (ret >= 0)
Alex Vakulenko0155b392015-05-06 15:30:58 -0700221 break;
222
223 int err = SSL_get_error(ssl_.get(), ret);
224 if (err == SSL_ERROR_WANT_READ) {
Alex Vakulenko1b792392015-06-03 12:06:53 -0700225 if (!socket_->WaitForDataBlocking(AccessMode::READ, kTimeout, nullptr,
226 error)) {
Alex Vakulenko0155b392015-05-06 15:30:58 -0700227 break;
Alex Vakulenko1b792392015-06-03 12:06:53 -0700228 }
Alex Vakulenko0155b392015-05-06 15:30:58 -0700229 } else if (err == SSL_ERROR_WANT_WRITE) {
Alex Vakulenko1b792392015-06-03 12:06:53 -0700230 if (!socket_->WaitForDataBlocking(AccessMode::WRITE, kTimeout, nullptr,
231 error)) {
Alex Vakulenko0155b392015-05-06 15:30:58 -0700232 break;
Alex Vakulenko1b792392015-06-03 12:06:53 -0700233 }
Alex Vakulenko0155b392015-05-06 15:30:58 -0700234 } else {
Alex Vakulenkof1f06b42015-06-03 12:20:15 -0700235 LOG(ERROR) << "SSL_shutdown returned error #" << err;
Alex Vakulenko0155b392015-05-06 15:30:58 -0700236 ReportError(error, FROM_HERE, "Failed to shut down TLS socket");
237 break;
238 }
239 }
240 return socket_->CloseBlocking(error);
241}
242
243bool TlsStream::TlsStreamImpl::WaitForData(
244 AccessMode mode,
245 const base::Callback<void(AccessMode)>& callback,
246 ErrorPtr* error) {
Alex Vakulenko38bb5d62015-05-07 13:12:54 -0700247 bool is_read = stream_utils::IsReadAccessMode(mode);
248 bool is_write = stream_utils::IsWriteAccessMode(mode);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700249 is_read |= need_more_read_;
250 is_write |= need_more_write_;
251 need_more_read_ = false;
252 need_more_write_ = false;
253 if (is_read && SSL_pending(ssl_.get()) > 0) {
254 callback.Run(AccessMode::READ);
255 return true;
256 }
Alex Vakulenko38bb5d62015-05-07 13:12:54 -0700257 mode = stream_utils::MakeAccessMode(is_read, is_write);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700258 return socket_->WaitForData(mode, callback, error);
259}
260
261bool TlsStream::TlsStreamImpl::WaitForDataBlocking(AccessMode in_mode,
Alex Vakulenko1b792392015-06-03 12:06:53 -0700262 base::TimeDelta timeout,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700263 AccessMode* out_mode,
264 ErrorPtr* error) {
Alex Vakulenko38bb5d62015-05-07 13:12:54 -0700265 bool is_read = stream_utils::IsReadAccessMode(in_mode);
266 bool is_write = stream_utils::IsWriteAccessMode(in_mode);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700267 is_read |= need_more_read_;
268 is_write |= need_more_write_;
269 need_more_read_ = need_more_write_ = false;
270 if (is_read && SSL_pending(ssl_.get()) > 0) {
271 if (out_mode)
272 *out_mode = AccessMode::READ;
273 return true;
274 }
Alex Vakulenko38bb5d62015-05-07 13:12:54 -0700275 in_mode = stream_utils::MakeAccessMode(is_read, is_write);
Alex Vakulenko1b792392015-06-03 12:06:53 -0700276 return socket_->WaitForDataBlocking(in_mode, timeout, out_mode, error);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700277}
278
Alex Vakulenko8cb41342015-05-15 16:00:14 -0700279void TlsStream::TlsStreamImpl::CancelPendingAsyncOperations() {
280 socket_->CancelPendingAsyncOperations();
281 weak_ptr_factory_.InvalidateWeakPtrs();
282}
283
Alex Vakulenko0155b392015-05-06 15:30:58 -0700284bool TlsStream::TlsStreamImpl::ReportError(
285 ErrorPtr* error,
286 const tracked_objects::Location& location,
287 const std::string& message) {
288 const char* file = nullptr;
289 int line = 0;
290 const char* data = 0;
291 int flags = 0;
292 while (auto errnum = ERR_get_error_line_data(&file, &line, &data, &flags)) {
293 char buf[256];
294 ERR_error_string_n(errnum, buf, sizeof(buf));
295 tracked_objects::Location ssl_location{"Unknown", file, line, nullptr};
296 std::string ssl_message = buf;
297 if (flags & ERR_TXT_STRING) {
298 ssl_message += ": ";
299 ssl_message += data;
300 }
301 Error::AddTo(error, ssl_location, "openssl", std::to_string(errnum),
302 ssl_message);
303 }
304 Error::AddTo(error, location, "tls_stream", "failed", message);
305 return false;
306}
307
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700308int TlsStream::TlsStreamImpl::OnCertVerifyResults(int ok, X509_STORE_CTX* ctx) {
309 // OpenSSL already performs a comprehensive check of the certificate chain
310 // (using X509_verify_cert() function) and calls back with the result of its
311 // verification.
312 // |ok| is set to 1 if the verification passed and 0 if an error was detected.
313 // Here we can perform some additional checks if we need to, or simply log
314 // the issues found.
315
316 // For now, just log an error if it occurred.
317 if (!ok) {
318 LOG(ERROR) << "Server certificate validation failed: "
319 << X509_verify_cert_error_string(X509_STORE_CTX_get_error(ctx));
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700320 }
321 return ok;
322}
323
324int TlsStream::TlsStreamImpl::OnCertVerifyResultsStatic(int ok,
325 X509_STORE_CTX* ctx) {
326 // Obtain the pointer to the instance of TlsStream::TlsStreamImpl from the
327 // SSL CTX object referenced by |ctx|.
328 SSL* ssl = static_cast<SSL*>(X509_STORE_CTX_get_ex_data(
329 ctx, SSL_get_ex_data_X509_STORE_CTX_idx()));
330 SSL_CTX* ssl_ctx = ssl ? SSL_get_SSL_CTX(ssl) : nullptr;
331 TlsStream::TlsStreamImpl* self = nullptr;
332 if (ssl_ctx) {
333 self = static_cast<TlsStream::TlsStreamImpl*>(SSL_CTX_get_ex_data(
334 ssl_ctx, ssl_ctx_private_data_index));
335 }
336 return self ? self->OnCertVerifyResults(ok, ctx) : ok;
Alex Vakulenko0155b392015-05-06 15:30:58 -0700337}
338
339bool TlsStream::TlsStreamImpl::Init(StreamPtr socket,
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700340 const std::string& host,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700341 const base::Closure& success_callback,
342 const Stream::ErrorCallback& error_callback,
343 ErrorPtr* error) {
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700344 ctx_.reset(SSL_CTX_new(TLSv1_2_client_method()));
Alex Vakulenko0155b392015-05-06 15:30:58 -0700345 if (!ctx_)
346 return ReportError(error, FROM_HERE, "Cannot create SSL_CTX");
347
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700348 // Top cipher suites supported by both Google GFEs and OpenSSL (in server
349 // preferred order).
Alex Vakulenko0155b392015-05-06 15:30:58 -0700350 int res = SSL_CTX_set_cipher_list(ctx_.get(),
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700351 "ECDHE-ECDSA-AES128-GCM-SHA256:"
352 "ECDHE-ECDSA-AES256-GCM-SHA384:"
353 "ECDHE-RSA-AES128-GCM-SHA256:"
354 "ECDHE-RSA-AES256-GCM-SHA384");
Alex Vakulenko0155b392015-05-06 15:30:58 -0700355 if (res != 1)
356 return ReportError(error, FROM_HERE, "Cannot set the cipher list");
357
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -0700358 res = SSL_CTX_load_verify_locations(ctx_.get(), nullptr, kCACertificatePath);
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700359 if (res != 1) {
360 return ReportError(error, FROM_HERE,
361 "Failed to specify trusted certificate location");
362 }
Alex Vakulenko0155b392015-05-06 15:30:58 -0700363
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700364 // Store a pointer to "this" into SSL_CTX instance.
365 SSL_CTX_set_ex_data(ctx_.get(), ssl_ctx_private_data_index, this);
Alex Vakulenkobe6a3bb2015-05-26 18:16:56 -0700366
367 // Ask OpenSSL to validate the server host from the certificate to match
368 // the expected host name we are given:
369 X509_VERIFY_PARAM* param = SSL_CTX_get0_param(ctx_.get());
370 X509_VERIFY_PARAM_set1_host(param, host.c_str(), host.size());
371
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700372 SSL_CTX_set_verify(ctx_.get(), SSL_VERIFY_PEER,
373 &TlsStreamImpl::OnCertVerifyResultsStatic);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700374
375 socket_ = std::move(socket);
376 ssl_.reset(SSL_new(ctx_.get()));
377
378 // Enable TLS progress callback if VLOG level is >=3.
379 if (VLOG_IS_ON(3))
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700380 SSL_set_info_callback(ssl_.get(), TlsInfoCallback);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700381
382 stream_bio_ = BIO_new_stream(socket_.get());
383 SSL_set_bio(ssl_.get(), stream_bio_, stream_bio_);
384 SSL_set_connect_state(ssl_.get());
385
386 // We might have no message loop (e.g. we are in unit tests).
Alex Deymo00072602015-08-03 21:14:07 -0700387 if (MessageLoop::ThreadHasCurrent()) {
388 MessageLoop::current()->PostTask(
Alex Vakulenko0155b392015-05-06 15:30:58 -0700389 FROM_HERE,
390 base::Bind(&TlsStreamImpl::DoHandshake,
391 weak_ptr_factory_.GetWeakPtr(),
392 success_callback,
393 error_callback));
394 } else {
395 DoHandshake(success_callback, error_callback);
396 }
397 return true;
398}
399
400void TlsStream::TlsStreamImpl::RetryHandshake(
401 const base::Closure& success_callback,
402 const Stream::ErrorCallback& error_callback,
Christopher Wiley2fd46ba2016-01-04 08:59:09 -0800403 Stream::AccessMode /* mode */) {
Alex Vakulenko0155b392015-05-06 15:30:58 -0700404 VLOG(1) << "Retrying TLS handshake";
405 DoHandshake(success_callback, error_callback);
406}
407
408void TlsStream::TlsStreamImpl::DoHandshake(
409 const base::Closure& success_callback,
410 const Stream::ErrorCallback& error_callback) {
411 VLOG(1) << "Begin TLS handshake";
412 int res = SSL_do_handshake(ssl_.get());
413 if (res == 1) {
414 VLOG(1) << "Handshake successful";
415 success_callback.Run();
416 return;
417 }
418 ErrorPtr error;
419 int err = SSL_get_error(ssl_.get(), res);
420 if (err == SSL_ERROR_WANT_READ) {
421 VLOG(1) << "Waiting for read data...";
422 bool ok = socket_->WaitForData(
423 Stream::AccessMode::READ,
424 base::Bind(&TlsStreamImpl::RetryHandshake,
425 weak_ptr_factory_.GetWeakPtr(),
426 success_callback, error_callback),
427 &error);
428 if (ok)
429 return;
430 } else if (err == SSL_ERROR_WANT_WRITE) {
431 VLOG(1) << "Waiting for write data...";
432 bool ok = socket_->WaitForData(
433 Stream::AccessMode::WRITE,
434 base::Bind(&TlsStreamImpl::RetryHandshake,
435 weak_ptr_factory_.GetWeakPtr(),
436 success_callback, error_callback),
437 &error);
438 if (ok)
439 return;
440 } else {
441 ReportError(&error, FROM_HERE, "TLS handshake failed.");
442 }
443 error_callback.Run(error.get());
444}
445
446/////////////////////////////////////////////////////////////////////////////
447TlsStream::TlsStream(std::unique_ptr<TlsStreamImpl> impl)
448 : impl_{std::move(impl)} {}
449
Alex Vakulenkod66669e2015-05-26 16:47:40 -0700450TlsStream::~TlsStream() {
451 if (impl_) {
452 impl_->Close(nullptr);
453 }
454}
Alex Vakulenko0155b392015-05-06 15:30:58 -0700455
456void TlsStream::Connect(StreamPtr socket,
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700457 const std::string& host,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700458 const base::Callback<void(StreamPtr)>& success_callback,
459 const Stream::ErrorCallback& error_callback) {
460 std::unique_ptr<TlsStreamImpl> impl{new TlsStreamImpl};
461 std::unique_ptr<TlsStream> stream{new TlsStream{std::move(impl)}};
462
463 TlsStreamImpl* pimpl = stream->impl_.get();
464 ErrorPtr error;
Alex Vakulenkof76c6822015-05-11 15:45:25 -0700465 bool success = pimpl->Init(std::move(socket), host,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700466 base::Bind(success_callback,
467 base::Passed(std::move(stream))),
468 error_callback, &error);
469
470 if (!success)
471 error_callback.Run(error.get());
472}
473
474bool TlsStream::IsOpen() const {
475 return impl_ ? true : false;
476}
477
Christopher Wiley2fd46ba2016-01-04 08:59:09 -0800478bool TlsStream::SetSizeBlocking(uint64_t /* size */, ErrorPtr* error) {
Alex Vakulenko0155b392015-05-06 15:30:58 -0700479 return stream_utils::ErrorOperationNotSupported(FROM_HERE, error);
480}
481
Christopher Wiley2fd46ba2016-01-04 08:59:09 -0800482bool TlsStream::Seek(int64_t /* offset */,
483 Whence /* whence */,
484 uint64_t* /* new_position*/,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700485 ErrorPtr* error) {
486 return stream_utils::ErrorOperationNotSupported(FROM_HERE, error);
487}
488
489bool TlsStream::ReadNonBlocking(void* buffer,
490 size_t size_to_read,
491 size_t* size_read,
492 bool* end_of_stream,
493 ErrorPtr* error) {
494 if (!impl_)
495 return stream_utils::ErrorStreamClosed(FROM_HERE, error);
496 return impl_->ReadNonBlocking(buffer, size_to_read, size_read, end_of_stream,
497 error);
498}
499
500bool TlsStream::WriteNonBlocking(const void* buffer,
501 size_t size_to_write,
502 size_t* size_written,
503 ErrorPtr* error) {
504 if (!impl_)
505 return stream_utils::ErrorStreamClosed(FROM_HERE, error);
506 return impl_->WriteNonBlocking(buffer, size_to_write, size_written, error);
507}
508
509bool TlsStream::FlushBlocking(ErrorPtr* error) {
510 if (!impl_)
511 return stream_utils::ErrorStreamClosed(FROM_HERE, error);
512 return impl_->Flush(error);
513}
514
515bool TlsStream::CloseBlocking(ErrorPtr* error) {
516 if (impl_ && !impl_->Close(error))
517 return false;
518 impl_.reset();
519 return true;
520}
521
522bool TlsStream::WaitForData(AccessMode mode,
523 const base::Callback<void(AccessMode)>& callback,
524 ErrorPtr* error) {
525 if (!impl_)
526 return stream_utils::ErrorStreamClosed(FROM_HERE, error);
527 return impl_->WaitForData(mode, callback, error);
528}
529
530bool TlsStream::WaitForDataBlocking(AccessMode in_mode,
Alex Vakulenko1b792392015-06-03 12:06:53 -0700531 base::TimeDelta timeout,
Alex Vakulenko0155b392015-05-06 15:30:58 -0700532 AccessMode* out_mode,
533 ErrorPtr* error) {
534 if (!impl_)
535 return stream_utils::ErrorStreamClosed(FROM_HERE, error);
Alex Vakulenko1b792392015-06-03 12:06:53 -0700536 return impl_->WaitForDataBlocking(in_mode, timeout, out_mode, error);
Alex Vakulenko0155b392015-05-06 15:30:58 -0700537}
538
Alex Vakulenko8cb41342015-05-15 16:00:14 -0700539void TlsStream::CancelPendingAsyncOperations() {
540 if (impl_)
541 impl_->CancelPendingAsyncOperations();
Alex Vakulenko9988ee02015-05-19 13:38:48 -0700542 Stream::CancelPendingAsyncOperations();
Alex Vakulenko8cb41342015-05-15 16:00:14 -0700543}
544
Alex Vakulenko9ed0cab2015-10-12 15:21:28 -0700545} // namespace brillo