Version 1.24.3

Cherry-pick 0af5298845574517862e0a4cfabace1488ec2196 to stable
Cherry-pick 644862bf966e6c079460258807ab3364b7e3759a to stable
Cherry-pick 0e164c043f1007e8b3124a152ac9783f821e038c to stable
Cherry-pick 9cf7ba4f842a126b581eeac0197c269a204ecd78 to stable
diff --git a/CHANGELOG.md b/CHANGELOG.md
index befe4a0..cf29c44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+## 1.24.3 - 14-12-2017
+
+* Fix for constructing a new SecurityContext that contains the built-in
+  certificate authority roots
+    (https://github.com/dart-lang/sdk/issues/24693).
+
+### Core library changes
+
+* `dart:io`
+  * Unified backends for `SecureSocket`, `SecurityContext`, and 
+    `X509Certificate` to be consistent across all platforms. All
+    `SecureSocket`, `SecurityContext`, and `X509Certificate` properties and
+    methods are now supported on iOS and OSX.
+
 ## 1.24.2 - 22-06-2017
 
 * Fixes for debugging in Dartium.
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
index 59aa7ff..688cf4a 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/io_patch.dart
@@ -451,7 +451,7 @@
 @patch
 class SecurityContext {
   @patch
-  factory SecurityContext() {
+  factory SecurityContext({bool withTrustedRoots: false}) {
     throw new UnsupportedError("SecurityContext constructor");
   }
 
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index cde7664..f0ac8d9 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -408,10 +408,10 @@
       if (is_mac) {
         libs += [ "CoreServices.framework" ]
       }
-    } else {
-      deps += [ "//third_party/boringssl" ]
     }
 
+    deps += [ "//third_party/boringssl" ]
+
     if (is_fuchsia) {
       libs = [ "launchpad" ]
     }
diff --git a/runtime/bin/io_impl_sources.gypi b/runtime/bin/io_impl_sources.gypi
index 5a7df0e..d3bce7e 100644
--- a/runtime/bin/io_impl_sources.gypi
+++ b/runtime/bin/io_impl_sources.gypi
@@ -53,14 +53,18 @@
     'process_win.cc',
     'reference_counting.h',
     'root_certificates_unsupported.cc',
-    'secure_socket.h',
-    'secure_socket_boringssl.cc',
-    'secure_socket_boringssl.h',
-    'secure_socket_ios.cc',
-    'secure_socket_ios.h',
-    'secure_socket_macos.cc',
-    'secure_socket_macos.h',
+    'secure_socket_filter.cc',
+    'secure_socket_filter.h',
     'secure_socket_unsupported.cc',
+    'secure_socket_utils.cc',
+    'secure_socket_utils.h',
+    'security_context.cc',
+    'security_context.h',
+    'security_context_android.cc',
+    'security_context_fuchsia.cc',
+    'security_context_linux.cc',
+    'security_context_macos.cc',
+    'security_context_win.cc',
     'socket.cc',
     'socket.h',
     'socket_android.cc',
diff --git a/runtime/bin/io_service.cc b/runtime/bin/io_service.cc
index 2a685f1..c5e5628 100644
--- a/runtime/bin/io_service.cc
+++ b/runtime/bin/io_service.cc
@@ -10,7 +10,8 @@
 #include "bin/directory.h"
 #include "bin/file.h"
 #include "bin/io_buffer.h"
-#include "bin/secure_socket.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/security_context.h"
 #include "bin/socket.h"
 #include "bin/utils.h"
 
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 412a2fb2..647490e 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -518,7 +518,6 @@
 }
 
 
-#if !defined(HOST_OS_MACOS)
 extern const char* commandline_root_certs_file;
 extern const char* commandline_root_certs_cache;
 
@@ -554,7 +553,6 @@
   commandline_root_certs_cache = arg;
   return true;
 }
-#endif  // !defined(HOST_OS_MACOS)
 
 
 static struct {
@@ -590,10 +588,8 @@
     {"--hot-reload-rollback-test-mode", ProcessHotReloadRollbackTestModeOption},
     {"--short_socket_read", ProcessShortSocketReadOption},
     {"--short_socket_write", ProcessShortSocketWriteOption},
-#if !defined(HOST_OS_MACOS)
     {"--root-certs-file=", ProcessRootCertsFileOption},
     {"--root-certs-cache=", ProcessRootCertsCacheOption},
-#endif  // !defined(HOST_OS_MACOS)
     {NULL, NULL}};
 
 
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
deleted file mode 100644
index 83bf34d..0000000
--- a/runtime/bin/secure_socket.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_BIN_SECURE_SOCKET_H_
-#define RUNTIME_BIN_SECURE_SOCKET_H_
-
-#if defined(DART_IO_DISABLED) || defined(DART_IO_SECURE_SOCKET_DISABLED)
-#error "secure_socket.h can only be included on builds with SSL enabled"
-#endif
-
-#include "platform/globals.h"
-#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) ||                      \
-    defined(HOST_OS_WINDOWS) || defined(HOST_OS_FUCHSIA)
-#include "bin/secure_socket_boringssl.h"
-#elif defined(HOST_OS_MACOS)
-#if HOST_OS_IOS
-#include "bin/secure_socket_ios.h"
-#else  // HOST_OS_IOS
-#include "bin/secure_socket_macos.h"
-#endif  // HOST_OS_IOS
-#else
-#error Unknown target os.
-#endif
-
-#endif  // RUNTIME_BIN_SECURE_SOCKET_H_
diff --git a/runtime/bin/secure_socket_boringssl.cc b/runtime/bin/secure_socket_boringssl.cc
deleted file mode 100644
index a3740a8..0000000
--- a/runtime/bin/secure_socket_boringssl.cc
+++ /dev/null
@@ -1,1807 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
-
-#include "platform/globals.h"
-#if defined(HOST_OS_ANDROID) || defined(HOST_OS_LINUX) ||                      \
-    defined(HOST_OS_WINDOWS) || defined(HOST_OS_FUCHSIA)
-
-#include "bin/secure_socket.h"
-#include "bin/secure_socket_boringssl.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/pkcs12.h>
-#include <openssl/safestack.h>
-#include <openssl/ssl.h>
-#include <openssl/tls1.h>
-#include <openssl/x509.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/directory.h"
-#include "bin/file.h"
-#include "bin/lockers.h"
-#include "bin/log.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-#include "platform/text_buffer.h"
-#include "platform/utils.h"
-
-#include "include/dart_api.h"
-
-// Return the error from the containing function if handle is an error handle.
-#define RETURN_IF_ERROR(handle)                                                \
-  {                                                                            \
-    Dart_Handle __handle = handle;                                             \
-    if (Dart_IsError((__handle))) {                                            \
-      return __handle;                                                         \
-    }                                                                          \
-  }
-
-namespace dart {
-namespace bin {
-
-bool SSLFilter::library_initialized_ = false;
-// To protect library initialization.
-Mutex* SSLFilter::mutex_ = new Mutex();
-int SSLFilter::filter_ssl_index;
-
-const intptr_t SSLFilter::kInternalBIOSize = 10 * KB;
-const intptr_t SSLFilter::kApproximateSize =
-    sizeof(SSLFilter) + (2 * SSLFilter::kInternalBIOSize);
-
-// The security context won't necessarily use the compiled-in root certificates,
-// but since there is no way to update the size of the allocation after creating
-// the weak persistent handle, we assume that it will. Note that when the
-// root certs aren't compiled in, |root_certificates_pem_length| is 0.
-const intptr_t SSLContext::kApproximateSize =
-    sizeof(SSLContext) + root_certificates_pem_length;
-
-static const int kSSLFilterNativeFieldIndex = 0;
-static const int kSecurityContextNativeFieldIndex = 0;
-static const int kX509NativeFieldIndex = 0;
-
-static const bool SSL_LOG_STATUS = false;
-static const bool SSL_LOG_DATA = false;
-
-static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
-
-const char* commandline_root_certs_file = NULL;
-const char* commandline_root_certs_cache = NULL;
-
-// Get the error messages from BoringSSL, and put them in buffer as a
-// null-terminated string.
-static void FetchErrorString(const SSL* ssl, TextBuffer* text_buffer) {
-  const char* sep = File::PathSeparator();
-  while (true) {
-    const char* path = NULL;
-    int line = -1;
-    uint32_t error = ERR_get_error_line(&path, &line);
-    if (error == 0) {
-      break;
-    }
-    text_buffer->Printf("\n\t%s", ERR_reason_error_string(error));
-    if ((ssl != NULL) && (ERR_GET_LIB(error) == ERR_LIB_SSL) &&
-        (ERR_GET_REASON(error) == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
-      intptr_t result = SSL_get_verify_result(ssl);
-      text_buffer->Printf(": %s", X509_verify_cert_error_string(result));
-    }
-    if ((path != NULL) && (line >= 0)) {
-      const char* file = strrchr(path, sep[0]);
-      path = file ? file + 1 : path;
-      text_buffer->Printf("(%s:%d)", path, line);
-    }
-  }
-}
-
-
-// Handle an error reported from the BoringSSL library.
-static void ThrowIOException(int status,
-                             const char* exception_type,
-                             const char* message,
-                             const SSL* ssl) {
-  Dart_Handle exception;
-  {
-    TextBuffer error_string(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    FetchErrorString(ssl, &error_string);
-    OSError os_error_struct(status, error_string.buf(), OSError::kBoringSSL);
-    Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
-    exception =
-        DartUtils::NewDartIOException(exception_type, message, os_error);
-    ASSERT(!Dart_IsError(exception));
-  }
-  Dart_ThrowException(exception);
-  UNREACHABLE();
-}
-
-
-static SSLFilter* GetFilter(Dart_NativeArguments args) {
-  SSLFilter* filter;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&filter)));
-  return filter;
-}
-
-
-static void DeleteFilter(void* isolate_data,
-                         Dart_WeakPersistentHandle handle,
-                         void* context_pointer) {
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  filter->Release();
-}
-
-
-static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
-  ASSERT(filter != NULL);
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(filter));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, reinterpret_cast<void*>(filter),
-                               SSLFilter::kApproximateSize, DeleteFilter);
-  return Dart_Null();
-}
-
-
-static SSLContext* GetSecurityContext(Dart_NativeArguments args) {
-  SSLContext* context;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&context)));
-  return context;
-}
-
-
-static void DeleteSecurityContext(void* isolate_data,
-                                  Dart_WeakPersistentHandle handle,
-                                  void* context_pointer) {
-  SSLContext* context = static_cast<SSLContext*>(context_pointer);
-  delete context;
-}
-
-
-static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
-                                      SSLContext* context) {
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(context));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, context, SSLContext::kApproximateSize,
-                               DeleteSecurityContext);
-  return Dart_Null();
-}
-
-
-static X509* GetX509Certificate(Dart_NativeArguments args) {
-  X509* certificate;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kX509NativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&certificate)));
-  return certificate;
-}
-
-
-// Forward declaration.
-static void SetAlpnProtocolList(Dart_Handle protocols_handle,
-                                SSL* ssl,
-                                SSLContext* context,
-                                bool is_server);
-
-
-void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  SSLFilter* filter = new SSLFilter();
-  Dart_Handle err = SetFilter(args, filter);
-  if (Dart_IsError(err)) {
-    filter->Release();
-    Dart_PropagateError(err);
-  }
-  err = filter->Init(dart_this);
-  if (Dart_IsError(err)) {
-    // The finalizer was set up by SetFilter. It will delete `filter` if there
-    // is an error.
-    filter->Destroy();
-    Dart_PropagateError(err);
-  }
-}
-
-
-void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
-  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
-  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
-  Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 6));
-
-  const char* host_name = NULL;
-  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
-  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
-
-  SSLContext* context = NULL;
-  if (!Dart_IsNull(context_object)) {
-    ThrowIfError(Dart_GetNativeInstanceField(
-        context_object, kSecurityContextNativeFieldIndex,
-        reinterpret_cast<intptr_t*>(&context)));
-  }
-
-  // The protocols_handle is guaranteed to be a valid Uint8List.
-  // It will have the correct length encoding of the protocols array.
-  ASSERT(!Dart_IsNull(protocols_handle));
-
-  GetFilter(args)->Connect(host_name, context->context(), is_server,
-                           request_client_certificate,
-                           require_client_certificate, protocols_handle);
-}
-
-
-void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // There are two paths that can clean up an SSLFilter object. First,
-  // there is this explicit call to Destroy(), called from
-  // _SecureFilter.destroy() in Dart code. After a call to destroy(), the Dart
-  // code maintains the invariant that there will be no futher SSLFilter
-  // requests sent to the IO Service. Therefore, the internals of the SSLFilter
-  // are safe to deallocate, but not the SSLFilter itself, which is already
-  // set up to be cleaned up by the finalizer.
-  //
-  // The second path is through the finalizer, which we have to do in case
-  // some mishap prevents a call to _SecureFilter.destroy().
-  filter->Destroy();
-}
-
-
-void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
-  GetFilter(args)->Handshake();
-}
-
-
-void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
-    Dart_NativeArguments args) {
-  GetFilter(args)->GetSelectedProtocol(args);
-}
-
-
-void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
-  bool use_session_cache =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  GetFilter(args)->Renegotiate(use_session_cache, request_client_certificate,
-                               require_client_certificate);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle handshake_complete =
-      ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(handshake_complete)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterHandshakeCompleteCallback"));
-  }
-  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle callback = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterBadCertificateCallback"));
-  }
-  GetFilter(args)->RegisterBadCertificateCallback(callback);
-}
-
-
-void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
-  Dart_Handle cert = ThrowIfError(GetFilter(args)->PeerCertificate());
-  Dart_SetReturnValue(args, cert);
-}
-
-
-void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // This filter pointer is passed to the IO Service thread. The IO Service
-  // thread must Release() the pointer when it is done with it.
-  filter->Retain();
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
-  Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
-}
-
-
-static void ReleaseCertificate(void* isolate_data,
-                               Dart_WeakPersistentHandle handle,
-                               void* context_pointer) {
-  X509* cert = reinterpret_cast<X509*>(context_pointer);
-  X509_free(cert);
-}
-
-
-static intptr_t EstimateX509Size(X509* certificate) {
-  intptr_t length = i2d_X509(certificate, NULL);
-  return length > 0 ? length : 0;
-}
-
-
-// Returns the handle for a Dart object wrapping the X509 certificate object.
-// The caller should own a reference to the X509 object whose reference count
-// won't drop to zero before the ReleaseCertificate finalizer runs.
-static Dart_Handle WrappedX509Certificate(X509* certificate) {
-  if (certificate == NULL) {
-    return Dart_Null();
-  }
-  Dart_Handle x509_type =
-      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
-  if (Dart_IsError(x509_type)) {
-    X509_free(certificate);
-    return x509_type;
-  }
-  Dart_Handle arguments[] = {NULL};
-  Dart_Handle result =
-      Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
-  if (Dart_IsError(result)) {
-    X509_free(certificate);
-    return result;
-  }
-  ASSERT(Dart_IsInstance(result));
-  Dart_Handle status = Dart_SetNativeInstanceField(
-      result, kX509NativeFieldIndex, reinterpret_cast<intptr_t>(certificate));
-  if (Dart_IsError(status)) {
-    X509_free(certificate);
-    return status;
-  }
-  const intptr_t approximate_size_of_certificate =
-      sizeof(*certificate) + EstimateX509Size(certificate);
-  ASSERT(approximate_size_of_certificate > 0);
-  Dart_NewWeakPersistentHandle(result, reinterpret_cast<void*>(certificate),
-                               approximate_size_of_certificate,
-                               ReleaseCertificate);
-  return result;
-}
-
-
-int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) {
-  if (preverify_ok == 1) {
-    return 1;
-  }
-  Dart_Isolate isolate = Dart_CurrentIsolate();
-  if (isolate == NULL) {
-    FATAL("CertificateCallback called with no current isolate\n");
-  }
-  X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx);
-  int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
-  SSL* ssl =
-      static_cast<SSL*>(X509_STORE_CTX_get_ex_data(store_ctx, ssl_index));
-  SSLFilter* filter = static_cast<SSLFilter*>(
-      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
-  Dart_Handle callback = filter->bad_certificate_callback();
-  if (Dart_IsNull(callback)) {
-    return 0;
-  }
-
-  // Upref since the Dart X509 object may outlive the SecurityContext.
-  if (certificate != NULL) {
-    X509_up_ref(certificate);
-  }
-  Dart_Handle args[1];
-  args[0] = WrappedX509Certificate(certificate);
-  if (Dart_IsError(args[0])) {
-    filter->callback_error = args[0];
-    return 0;
-  }
-  Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
-  if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
-    result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
-        "HandshakeException",
-        "BadCertificateCallback returned a value that was not a boolean",
-        Dart_Null()));
-  }
-  if (Dart_IsError(result)) {
-    filter->callback_error = result;
-    return 0;
-  }
-  return DartUtils::GetBooleanValue(result);
-}
-
-
-void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
-  SSLFilter::InitializeLibrary();
-  SSL_CTX* ctx = SSL_CTX_new(TLS_method());
-  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, CertificateCallback);
-  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
-  SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM");
-  SSLContext* context = new SSLContext(ctx);
-  Dart_Handle err = SetSecurityContext(args, context);
-  if (Dart_IsError(err)) {
-    delete context;
-    Dart_PropagateError(err);
-  }
-}
-
-
-int PasswordCallback(char* buf, int size, int rwflag, void* userdata) {
-  char* password = static_cast<char*>(userdata);
-  ASSERT(size == PEM_BUFSIZE);
-  strncpy(buf, password, size);
-  return strlen(password);
-}
-
-
-void CheckStatusSSL(int status,
-                    const char* type,
-                    const char* message,
-                    const SSL* ssl) {
-  // TODO(24183): Take appropriate action on failed calls,
-  // throw exception that includes all messages from the error stack.
-  if (status == 1) {
-    return;
-  }
-  if (SSL_LOG_STATUS) {
-    int error = ERR_get_error();
-    Log::PrintErr("Failed: %s status %d", message, status);
-    char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
-    ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    Log::PrintErr("ERROR: %d %s\n", error, error_string);
-  }
-  ThrowIOException(status, type, message, ssl);
-}
-
-
-void CheckStatus(int status, const char* type, const char* message) {
-  CheckStatusSSL(status, type, message, NULL);
-}
-
-
-// Where the argument to the constructor is the handle for an object
-// implementing List<int>, this class creates a scope in which a memory-backed
-// BIO is allocated. Leaving the scope cleans up the BIO and the buffer that
-// was used to create it.
-//
-// Do not make Dart_ API calls while in a ScopedMemBIO.
-// Do not call Dart_PropagateError while in a ScopedMemBIO.
-class ScopedMemBIO {
- public:
-  explicit ScopedMemBIO(Dart_Handle object) {
-    if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
-      Dart_ThrowException(
-          DartUtils::NewDartArgumentError("Argument is not a List<int>"));
-    }
-
-    uint8_t* bytes = NULL;
-    intptr_t bytes_len = 0;
-    bool is_typed_data = false;
-    if (Dart_IsTypedData(object)) {
-      is_typed_data = true;
-      Dart_TypedData_Type typ;
-      ThrowIfError(Dart_TypedDataAcquireData(
-          object, &typ, reinterpret_cast<void**>(&bytes), &bytes_len));
-    } else {
-      ASSERT(Dart_IsList(object));
-      ThrowIfError(Dart_ListLength(object, &bytes_len));
-      bytes = Dart_ScopeAllocate(bytes_len);
-      ASSERT(bytes != NULL);
-      ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
-    }
-
-    object_ = object;
-    bytes_ = bytes;
-    bytes_len_ = bytes_len;
-    bio_ = BIO_new_mem_buf(bytes, bytes_len);
-    ASSERT(bio_ != NULL);
-    is_typed_data_ = is_typed_data;
-  }
-
-  ~ScopedMemBIO() {
-    ASSERT(bio_ != NULL);
-    if (is_typed_data_) {
-      BIO_free(bio_);
-      ThrowIfError(Dart_TypedDataReleaseData(object_));
-    } else {
-      BIO_free(bio_);
-    }
-  }
-
-  BIO* bio() {
-    ASSERT(bio_ != NULL);
-    return bio_;
-  }
-
- private:
-  Dart_Handle object_;
-  uint8_t* bytes_;
-  intptr_t bytes_len_;
-  BIO* bio_;
-  bool is_typed_data_;
-
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO);
-};
-
-template <typename T, void (*free_func)(T*)>
-class ScopedSSLType {
- public:
-  explicit ScopedSSLType(T* obj) : obj_(obj) {}
-
-  ~ScopedSSLType() {
-    if (obj_ != NULL) {
-      free_func(obj_);
-    }
-  }
-
-  T* get() { return obj_; }
-  const T* get() const { return obj_; }
-
-  T* release() {
-    T* result = obj_;
-    obj_ = NULL;
-    return result;
-  }
-
- private:
-  T* obj_;
-
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(ScopedSSLType);
-};
-
-template <typename T, typename E, void (*func)(E*)>
-class ScopedSSLStackType {
- public:
-  explicit ScopedSSLStackType(T* obj) : obj_(obj) {}
-
-  ~ScopedSSLStackType() {
-    if (obj_ != NULL) {
-      sk_pop_free(reinterpret_cast<_STACK*>(obj_),
-                  reinterpret_cast<void (*)(void*)>(func));
-    }
-  }
-
-  T* get() { return obj_; }
-  const T* get() const { return obj_; }
-
-  T* release() {
-    T* result = obj_;
-    obj_ = NULL;
-    return result;
-  }
-
- private:
-  T* obj_;
-
-  DISALLOW_ALLOCATION();
-  DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType);
-};
-
-typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12;
-typedef ScopedSSLType<X509, X509_free> ScopedX509;
-typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack;
-
-static bool NoPEMStartLine() {
-  uint32_t last_error = ERR_peek_last_error();
-  return (ERR_GET_LIB(last_error) == ERR_LIB_PEM) &&
-         (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE);
-}
-
-
-static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return NULL;
-  }
-
-  EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
-  if (status == 0) {
-    return NULL;
-  }
-
-  // We only care about the private key.
-  ScopedX509 delete_cert(cert);
-  ScopedX509Stack delete_ca_certs(ca_certs);
-  return key;
-}
-
-
-static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) {
-  EVP_PKEY* key = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallback,
-                                          const_cast<char*>(password));
-  if (key == NULL) {
-    // We try reading data as PKCS12 only if reading as PEM was unsuccessful and
-    // if there is no indication that the data is malformed PEM. We assume the
-    // data is malformed PEM if it contains the start line, i.e. a line
-    // with ----- BEGIN.
-    if (NoPEMStartLine()) {
-      // Reset the bio, and clear the error from trying to read as PEM.
-      ERR_clear_error();
-      BIO_reset(bio);
-
-      // Try to decode as PKCS12.
-      key = GetPrivateKeyPKCS12(bio, password);
-    }
-  }
-  return key;
-}
-
-
-static const char* GetPasswordArgument(Dart_NativeArguments args,
-                                       intptr_t index) {
-  Dart_Handle password_object =
-      ThrowIfError(Dart_GetNativeArgument(args, index));
-  const char* password = NULL;
-  if (Dart_IsString(password_object)) {
-    ThrowIfError(Dart_StringToCString(password_object, &password));
-    if (strlen(password) > PEM_BUFSIZE - 1) {
-      Dart_ThrowException(DartUtils::NewDartArgumentError(
-          "Password length is greater than 1023 (PEM_BUFSIZE)"));
-    }
-  } else if (Dart_IsNull(password_object)) {
-    password = "";
-  } else {
-    Dart_ThrowException(
-        DartUtils::NewDartArgumentError("Password is not a String or null"));
-  }
-  return password;
-}
-
-
-void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  int status;
-  {
-    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    EVP_PKEY* key = GetPrivateKey(bio.bio(), password);
-    status = SSL_CTX_use_PrivateKey(context->context(), key);
-    // SSL_CTX_use_PrivateKey increments the reference count of key on success,
-    // so we have to call EVP_PKEY_free on both success and failure.
-    EVP_PKEY_free(key);
-  }
-
-  // TODO(24184): Handle different expected errors here - file missing,
-  // incorrect password, file not a PEM, and throw exceptions.
-  // CheckStatus should also throw an exception in uncaught cases.
-  CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
-}
-
-
-static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context,
-                                             BIO* bio,
-                                             const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
-
-  EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
-  if (status == 0) {
-    return status;
-  }
-
-  ScopedX509Stack cert_stack(ca_certs);
-  X509_STORE* store = SSL_CTX_get_cert_store(context);
-  status = X509_STORE_add_cert(store, cert);
-  // X509_STORE_add_cert increments the reference count of cert on success.
-  X509_free(cert);
-  if (status == 0) {
-    return status;
-  }
-
-  X509* ca;
-  while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
-    status = X509_STORE_add_cert(store, ca);
-    // X509_STORE_add_cert increments the reference count of cert on success.
-    X509_free(ca);
-    if (status == 0) {
-      return status;
-    }
-  }
-
-  return status;
-}
-
-
-static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) {
-  X509_STORE* store = SSL_CTX_get_cert_store(context);
-
-  int status = 0;
-  X509* cert = NULL;
-  while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
-    status = X509_STORE_add_cert(store, cert);
-    // X509_STORE_add_cert increments the reference count of cert on success.
-    X509_free(cert);
-    if (status == 0) {
-      return status;
-    }
-  }
-
-  // If no PEM start line is found, it means that we read to the end of the
-  // file, or that the file isn't PEM. In the first case, status will be
-  // non-zero indicating success. In the second case, status will be 0,
-  // indicating that we should try to read as PKCS12. If there is some other
-  // error, we return it up to the caller.
-  return NoPEMStartLine() ? status : 0;
-}
-
-
-static int SetTrustedCertificatesBytes(SSL_CTX* context,
-                                       BIO* bio,
-                                       const char* password) {
-  int status = SetTrustedCertificatesBytesPEM(context, bio);
-  if (status == 0) {
-    if (NoPEMStartLine()) {
-      ERR_clear_error();
-      BIO_reset(bio);
-      status = SetTrustedCertificatesBytesPKCS12(context, bio, password);
-    }
-  } else {
-    // The PEM file was successfully parsed.
-    ERR_clear_error();
-  }
-  return status;
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-  int status;
-  {
-    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status =
-        SetTrustedCertificatesBytes(context->context(), bio.bio(), password);
-  }
-  CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, Dart_NewBoolean(true));
-}
-
-
-static void AddCompiledInCerts(SSLContext* context) {
-  if (root_certificates_pem == NULL) {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Missing compiled-in roots\n");
-    }
-    return;
-  }
-  X509_STORE* store = SSL_CTX_get_cert_store(context->context());
-  BIO* roots_bio =
-      BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem),
-                      root_certificates_pem_length);
-  X509* root_cert;
-  // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case,
-  // backed by a memory buffer), and returns X509 objects, one by one.
-  // When the end of the bio is reached, it returns null.
-  while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) {
-    int status = X509_STORE_add_cert(store, root_cert);
-    // X509_STORE_add_cert increments the reference count of cert on success.
-    X509_free(root_cert);
-    if (status == 0) {
-      break;
-    }
-  }
-  BIO_free(roots_bio);
-  // If there is an error here, it must be the error indicating that we are done
-  // reading PEM certificates.
-  ASSERT((ERR_peek_error() == 0) || NoPEMStartLine());
-  ERR_clear_error();
-}
-
-
-static void LoadRootCertFile(SSLContext* context, const char* file) {
-  if (SSL_LOG_STATUS) {
-    Log::Print("Looking for trusted roots in %s\n", file);
-  }
-  if (!File::Exists(file)) {
-    ThrowIOException(-1, "TlsException", "Failed to find root cert file", NULL);
-  }
-  int status = SSL_CTX_load_verify_locations(context->context(), file, NULL);
-  CheckStatus(status, "TlsException", "Failure trusting builtin roots");
-  if (SSL_LOG_STATUS) {
-    Log::Print("Trusting roots from: %s\n", file);
-  }
-}
-
-
-static void LoadRootCertCache(SSLContext* context, const char* cache) {
-  if (SSL_LOG_STATUS) {
-    Log::Print("Looking for trusted roots in %s\n", cache);
-  }
-  if (Directory::Exists(cache) != Directory::EXISTS) {
-    ThrowIOException(-1, "TlsException", "Failed to find root cert cache",
-                     NULL);
-  }
-  int status = SSL_CTX_load_verify_locations(context->context(), NULL, cache);
-  CheckStatus(status, "TlsException", "Failure trusting builtin roots");
-  if (SSL_LOG_STATUS) {
-    Log::Print("Trusting roots from: %s\n", cache);
-  }
-}
-
-
-void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-
-  // First, try to use locations specified on the command line.
-  if (commandline_root_certs_file != NULL) {
-    LoadRootCertFile(context, commandline_root_certs_file);
-    return;
-  }
-
-  if (commandline_root_certs_cache != NULL) {
-    LoadRootCertCache(context, commandline_root_certs_cache);
-    return;
-  }
-
-#if defined(HOST_OS_ANDROID)
-  // On Android, we don't compile in the trusted root certificates. Insead,
-  // we use the directory of trusted certificates already present on the device.
-  // This saves ~240KB from the size of the binary. This has the drawback that
-  // SSL_do_handshake will synchronously hit the filesystem looking for root
-  // certs during its trust evaluation. We call SSL_do_handshake directly from
-  // the Dart thread so that Dart code can be invoked from the "bad certificate"
-  // callback called by SSL_do_handshake.
-  const char* android_cacerts = "/system/etc/security/cacerts";
-  LoadRootCertCache(context, android_cacerts);
-  return;
-#elif defined(HOST_OS_LINUX)
-  // On Linux, we use the compiled-in trusted certs as a last resort. First,
-  // we try to find the trusted certs in various standard locations. A good
-  // discussion of the complexities of this endeavor can be found here:
-  //
-  // https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/
-  const char* bundle = "/etc/pki/tls/certs/ca-bundle.crt";
-  const char* cachedir = "/etc/ssl/certs";
-  if (File::Exists(bundle)) {
-    LoadRootCertFile(context, bundle);
-    return;
-  }
-
-  if (Directory::Exists(cachedir) == Directory::EXISTS) {
-    LoadRootCertCache(context, cachedir);
-    return;
-  }
-#endif  // defined(HOST_OS_ANDROID)
-
-  // Fall back on the compiled-in certs if the standard locations don't exist,
-  // or we aren't on Linux.
-  if (SSL_LOG_STATUS) {
-    Log::Print("Trusting compiled-in roots\n");
-  }
-  AddCompiledInCerts(context);
-}
-
-
-static int UseChainBytesPKCS12(SSL_CTX* context,
-                               BIO* bio,
-                               const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
-
-  EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
-  if (status == 0) {
-    return status;
-  }
-
-  ScopedX509 x509(cert);
-  ScopedX509Stack certs(ca_certs);
-  status = SSL_CTX_use_certificate(context, x509.get());
-  if (ERR_peek_error() != 0) {
-    // Key/certificate mismatch doesn't imply status is 0.
-    status = 0;
-  }
-  if (status == 0) {
-    return status;
-  }
-
-  SSL_CTX_clear_chain_certs(context);
-
-  X509* ca;
-  while ((ca = sk_X509_shift(certs.get())) != NULL) {
-    status = SSL_CTX_add0_chain_cert(context, ca);
-    // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
-    // call fails.
-    if (status == 0) {
-      X509_free(ca);
-      return status;
-    }
-  }
-
-  return status;
-}
-
-
-static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) {
-  int status = 0;
-  ScopedX509 x509(PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL));
-  if (x509.get() == NULL) {
-    return 0;
-  }
-
-  status = SSL_CTX_use_certificate(context, x509.get());
-  if (ERR_peek_error() != 0) {
-    // Key/certificate mismatch doesn't imply status is 0.
-    status = 0;
-  }
-  if (status == 0) {
-    return status;
-  }
-
-  SSL_CTX_clear_chain_certs(context);
-
-  X509* ca;
-  while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
-    status = SSL_CTX_add0_chain_cert(context, ca);
-    // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
-    // call fails.
-    if (status == 0) {
-      X509_free(ca);
-      return status;
-    }
-    // Note that we must not free `ca` if it was successfully added to the
-    // chain. We must free the main certificate x509, though since its reference
-    // count is increased by SSL_CTX_use_certificate.
-  }
-
-  return NoPEMStartLine() ? status : 0;
-}
-
-
-static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) {
-  int status = UseChainBytesPEM(context, bio);
-  if (status == 0) {
-    if (NoPEMStartLine()) {
-      ERR_clear_error();
-      BIO_reset(bio);
-      status = UseChainBytesPKCS12(context, bio, password);
-    }
-  } else {
-    // The PEM file was successfully read.
-    ERR_clear_error();
-  }
-  return status;
-}
-
-
-void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-  int status;
-  {
-    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = UseChainBytes(context->context(), bio.bio(), password);
-  }
-  CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes");
-}
-
-
-static int SetClientAuthoritiesPKCS12(SSL_CTX* context,
-                                      BIO* bio,
-                                      const char* password) {
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
-  if (p12.get() == NULL) {
-    return 0;
-  }
-
-  EVP_PKEY* key = NULL;
-  X509* cert = NULL;
-  STACK_OF(X509)* ca_certs = NULL;
-  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
-  if (status == 0) {
-    return status;
-  }
-
-  ScopedX509Stack cert_stack(ca_certs);
-  status = SSL_CTX_add_client_CA(context, cert);
-  // SSL_CTX_add_client_CA increments the reference count of cert on success.
-  X509_free(cert);
-  if (status == 0) {
-    return status;
-  }
-
-  X509* ca;
-  while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
-    status = SSL_CTX_add_client_CA(context, ca);
-    // SSL_CTX_add_client_CA increments the reference count of ca on success.
-    X509_free(ca);  // The name has been extracted.
-    if (status == 0) {
-      return status;
-    }
-  }
-
-  return status;
-}
-
-
-static int SetClientAuthoritiesPEM(SSL_CTX* context, BIO* bio) {
-  int status = 0;
-  X509* cert = NULL;
-  while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
-    status = SSL_CTX_add_client_CA(context, cert);
-    X509_free(cert);  // The name has been extracted.
-    if (status == 0) {
-      return status;
-    }
-  }
-  return NoPEMStartLine() ? status : 0;
-}
-
-
-static int SetClientAuthorities(SSL_CTX* context,
-                                BIO* bio,
-                                const char* password) {
-  int status = SetClientAuthoritiesPEM(context, bio);
-  if (status == 0) {
-    if (NoPEMStartLine()) {
-      ERR_clear_error();
-      BIO_reset(bio);
-      status = SetClientAuthoritiesPKCS12(context, bio, password);
-    }
-  } else {
-    // The PEM file was successfully parsed.
-    ERR_clear_error();
-  }
-  return status;
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  int status;
-  {
-    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = SetClientAuthorities(context->context(), bio.bio(), password);
-  }
-
-  CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
-    Dart_NativeArguments args) {
-  SSLContext* context = GetSecurityContext(args);
-  Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  Dart_Handle is_server_handle = ThrowIfError(Dart_GetNativeArgument(args, 2));
-  if (Dart_IsBoolean(is_server_handle)) {
-    bool is_server = DartUtils::GetBooleanValue(is_server_handle);
-    SetAlpnProtocolList(protocols_handle, NULL, context, is_server);
-  } else {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Non-boolean is_server argument passed to SetAlpnProtocols"));
-  }
-}
-
-
-void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
-  X509* certificate = GetX509Certificate(args);
-  X509_NAME* subject = X509_get_subject_name(certificate);
-  char* subject_string = X509_NAME_oneline(subject, NULL, 0);
-  Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_string));
-  OPENSSL_free(subject_string);
-}
-
-
-void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
-  X509* certificate = GetX509Certificate(args);
-  X509_NAME* issuer = X509_get_issuer_name(certificate);
-  char* issuer_string = X509_NAME_oneline(issuer, NULL, 0);
-  Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_string));
-  OPENSSL_free(issuer_string);
-}
-
-static Dart_Handle ASN1TimeToMilliseconds(ASN1_TIME* aTime) {
-  ASN1_UTCTIME* epoch_start = M_ASN1_UTCTIME_new();
-  ASN1_UTCTIME_set_string(epoch_start, "700101000000Z");
-  int days;
-  int seconds;
-  int result = ASN1_TIME_diff(&days, &seconds, epoch_start, aTime);
-  M_ASN1_UTCTIME_free(epoch_start);
-  if (result != 1) {
-    // TODO(whesse): Propagate an error to Dart.
-    Log::PrintErr("ASN1Time error %d\n", result);
-  }
-  return Dart_NewInteger((86400LL * days + seconds) * 1000LL);
-}
-
-void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
-  X509* certificate = GetX509Certificate(args);
-  ASN1_TIME* not_before = X509_get_notBefore(certificate);
-  Dart_SetReturnValue(args, ASN1TimeToMilliseconds(not_before));
-}
-
-
-void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
-  X509* certificate = GetX509Certificate(args);
-  ASN1_TIME* not_after = X509_get_notAfter(certificate);
-  Dart_SetReturnValue(args, ASN1TimeToMilliseconds(not_after));
-}
-
-
-/**
- * Pushes data through the SSL filter, reading and writing from circular
- * buffers shared with Dart.
- *
- * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
- * pass encrypted and plaintext data to and from the C++ SSLFilter object.
- *
- * ProcessFilter is called with a CObject array containing the pointer to
- * the SSLFilter, encoded as an int, and the start and end positions of the
- * valid data in the four circular buffers.  The function only reads from
- * the valid data area of the input buffers, and only writes to the free
- * area of the output buffers.  The function returns the new start and end
- * positions in the buffers, but it only updates start for input buffers, and
- * end for output buffers.  Therefore, the Dart thread can simultaneously
- * write to the free space and end pointer of input buffers, and read from
- * the data space of output buffers, and modify the start pointer.
- *
- * When ProcessFilter returns, the Dart thread is responsible for combining
- * the updated pointers from Dart and C++, to make the new valid state of
- * the circular buffer.
- */
-CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
-  CObjectIntptr filter_object(request[0]);
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
-  RefCntReleaseScope<SSLFilter> rs(filter);
-
-  bool in_handshake = CObjectBool(request[1]).Value();
-  int starts[SSLFilter::kNumBuffers];
-  int ends[SSLFilter::kNumBuffers];
-  for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
-    starts[i] = CObjectInt32(request[2 * i + 2]).Value();
-    ends[i] = CObjectInt32(request[2 * i + 3]).Value();
-  }
-
-  if (filter->ProcessAllBuffers(starts, ends, in_handshake)) {
-    CObjectArray* result =
-        new CObjectArray(CObject::NewArray(SSLFilter::kNumBuffers * 2));
-    for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
-      result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
-      result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
-    }
-    return result;
-  } else {
-    int32_t error_code = static_cast<int32_t>(ERR_peek_error());
-    TextBuffer error_string(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    FetchErrorString(filter->ssl_, &error_string);
-    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
-    result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
-    result->SetAt(1, new CObjectString(CObject::NewString(error_string.buf())));
-    return result;
-  }
-}
-
-
-bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
-                                  int ends[kNumBuffers],
-                                  bool in_handshake) {
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (in_handshake && (i == kReadPlaintext || i == kWritePlaintext)) continue;
-    int start = starts[i];
-    int end = ends[i];
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    if (start < 0 || end < 0 || start >= size || end >= size) {
-      FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
-    }
-    switch (i) {
-      case kReadPlaintext:
-      case kWriteEncrypted:
-        // Write data to the circular buffer's free space.  If the buffer
-        // is full, neither if statement is executed and nothing happens.
-        if (start <= end) {
-          // If the free space may be split into two segments,
-          // then the first is [end, size), unless start == 0.
-          // Then, since the last free byte is at position start - 2,
-          // the interval is [end, size - 1).
-          int buffer_end = (start == 0) ? size - 1 : size;
-          int bytes = (i == kReadPlaintext)
-                          ? ProcessReadPlaintextBuffer(end, buffer_end)
-                          : ProcessWriteEncryptedBuffer(end, buffer_end);
-          if (bytes < 0) return false;
-          end += bytes;
-          ASSERT(end <= size);
-          if (end == size) end = 0;
-        }
-        if (start > end + 1) {
-          int bytes = (i == kReadPlaintext)
-                          ? ProcessReadPlaintextBuffer(end, start - 1)
-                          : ProcessWriteEncryptedBuffer(end, start - 1);
-          if (bytes < 0) return false;
-          end += bytes;
-          ASSERT(end < start);
-        }
-        ends[i] = end;
-        break;
-      case kReadEncrypted:
-      case kWritePlaintext:
-        // Read/Write data from circular buffer.  If the buffer is empty,
-        // neither if statement's condition is true.
-        if (end < start) {
-          // Data may be split into two segments.  In this case,
-          // the first is [start, size).
-          int bytes = (i == kReadEncrypted)
-                          ? ProcessReadEncryptedBuffer(start, size)
-                          : ProcessWritePlaintextBuffer(start, size);
-          if (bytes < 0) return false;
-          start += bytes;
-          ASSERT(start <= size);
-          if (start == size) start = 0;
-        }
-        if (start < end) {
-          int bytes = (i == kReadEncrypted)
-                          ? ProcessReadEncryptedBuffer(start, end)
-                          : ProcessWritePlaintextBuffer(start, end);
-          if (bytes < 0) return false;
-          start += bytes;
-          ASSERT(start <= end);
-        }
-        starts[i] = start;
-        break;
-      default:
-        UNREACHABLE();
-    }
-  }
-  return true;
-}
-
-
-Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
-  if (!library_initialized_) {
-    InitializeLibrary();
-  }
-  ASSERT(string_start_ == NULL);
-  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
-  ASSERT(string_start_ != NULL);
-  ASSERT(string_length_ == NULL);
-  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
-  ASSERT(string_length_ != NULL);
-  ASSERT(bad_certificate_callback_ == NULL);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
-  ASSERT(bad_certificate_callback_ != NULL);
-
-  // Caller handles cleanup on an error.
-  return InitializeBuffers(dart_this);
-}
-
-
-Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
-  // Create SSLFilter buffers as ExternalUint8Array objects.
-  Dart_Handle buffers_string = DartUtils::NewString("buffers");
-  RETURN_IF_ERROR(buffers_string);
-  Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
-  RETURN_IF_ERROR(dart_buffers_object);
-  Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
-  RETURN_IF_ERROR(secure_filter_impl_type);
-  Dart_Handle size_string = DartUtils::NewString("SIZE");
-  RETURN_IF_ERROR(size_string);
-  Dart_Handle dart_buffer_size =
-      Dart_GetField(secure_filter_impl_type, size_string);
-  RETURN_IF_ERROR(dart_buffer_size);
-
-  int64_t buffer_size = 0;
-  Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
-  RETURN_IF_ERROR(err);
-
-  Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
-  RETURN_IF_ERROR(encrypted_size_string);
-
-  Dart_Handle dart_encrypted_buffer_size =
-      Dart_GetField(secure_filter_impl_type, encrypted_size_string);
-  RETURN_IF_ERROR(dart_encrypted_buffer_size);
-
-  int64_t encrypted_buffer_size = 0;
-  err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
-  RETURN_IF_ERROR(err);
-
-  if (buffer_size <= 0 || buffer_size > 1 * MB) {
-    FATAL("Invalid buffer size in _ExternalBuffer");
-  }
-  if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
-    FATAL("Invalid encrypted buffer size in _ExternalBuffer");
-  }
-  buffer_size_ = static_cast<int>(buffer_size);
-  encrypted_buffer_size_ = static_cast<int>(encrypted_buffer_size);
-
-  Dart_Handle data_identifier = DartUtils::NewString("data");
-  RETURN_IF_ERROR(data_identifier);
-
-  for (int i = 0; i < kNumBuffers; i++) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    buffers_[i] = new uint8_t[size];
-    ASSERT(buffers_[i] != NULL);
-    dart_buffer_objects_[i] = NULL;
-  }
-
-  Dart_Handle result = Dart_Null();
-  for (int i = 0; i < kNumBuffers; ++i) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    result = Dart_ListGetAt(dart_buffers_object, i);
-    if (Dart_IsError(result)) {
-      break;
-    }
-
-    dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
-    ASSERT(dart_buffer_objects_[i] != NULL);
-    Dart_Handle data =
-        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
-    if (Dart_IsError(data)) {
-      result = data;
-      break;
-    }
-    result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
-    if (Dart_IsError(result)) {
-      break;
-    }
-    result = Dart_SetField(result, data_identifier, data);
-    if (Dart_IsError(result)) {
-      break;
-    }
-  }
-
-  // Caller handles cleanup on an error.
-  return result;
-}
-
-
-void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
-  ASSERT(NULL == handshake_complete_);
-  handshake_complete_ = Dart_NewPersistentHandle(complete);
-
-  ASSERT(handshake_complete_ != NULL);
-}
-
-
-void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
-  ASSERT(bad_certificate_callback_ != NULL);
-  Dart_DeletePersistentHandle(bad_certificate_callback_);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
-  ASSERT(bad_certificate_callback_ != NULL);
-}
-
-
-void SSLFilter::InitializeLibrary() {
-  MutexLocker locker(mutex_);
-  if (!library_initialized_) {
-    SSL_library_init();
-    filter_ssl_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
-    ASSERT(filter_ssl_index >= 0);
-    library_initialized_ = true;
-  }
-}
-
-
-Dart_Handle SSLFilter::PeerCertificate() {
-  // SSL_get_peer_certificate incs the refcount of certificate. X509_free is
-  // called by the finalizer set up by WrappedX509Certificate.
-  X509* certificate = SSL_get_peer_certificate(ssl_);
-  return WrappedX509Certificate(certificate);
-}
-
-
-int AlpnCallback(SSL* ssl,
-                 const uint8_t** out,
-                 uint8_t* outlen,
-                 const uint8_t* in,
-                 unsigned int inlen,
-                 void* arg) {
-  // 'in' and 'arg' are sequences of (length, data) strings with 1-byte lengths.
-  // 'arg' is 0-terminated. Finds the first string in 'arg' that is in 'in'.
-  uint8_t* server_list = static_cast<uint8_t*>(arg);
-  while (*server_list != 0) {
-    uint8_t protocol_length = *server_list++;
-    const uint8_t* client_list = in;
-    while (client_list < in + inlen) {
-      uint8_t client_protocol_length = *client_list++;
-      if (client_protocol_length == protocol_length) {
-        if (0 == memcmp(server_list, client_list, protocol_length)) {
-          *out = client_list;
-          *outlen = client_protocol_length;
-          return SSL_TLSEXT_ERR_OK;  // Success
-        }
-      }
-      client_list += client_protocol_length;
-    }
-    server_list += protocol_length;
-  }
-  // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN.
-  return SSL_TLSEXT_ERR_NOACK;
-}
-
-
-// Sets the protocol list for ALPN on a SSL object or a context.
-static void SetAlpnProtocolList(Dart_Handle protocols_handle,
-                                SSL* ssl,
-                                SSLContext* context,
-                                bool is_server) {
-  // Enable ALPN (application layer protocol negotiation) if the caller provides
-  // a valid list of supported protocols.
-  Dart_TypedData_Type protocols_type;
-  uint8_t* protocol_string = NULL;
-  uint8_t* protocol_string_copy = NULL;
-  intptr_t protocol_string_len = 0;
-  int status;
-
-  Dart_Handle result = Dart_TypedDataAcquireData(
-      protocols_handle, &protocols_type,
-      reinterpret_cast<void**>(&protocol_string), &protocol_string_len);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-
-  if (protocols_type != Dart_TypedData_kUint8) {
-    Dart_TypedDataReleaseData(protocols_handle);
-    Dart_PropagateError(Dart_NewApiError(
-        "Unexpected type for protocols (expected valid Uint8List)."));
-  }
-
-  if (protocol_string_len > 0) {
-    if (is_server) {
-      // ALPN on server connections must be set on an SSL_CTX object,
-      // not on the SSL object of the individual connection.
-      ASSERT(context != NULL);
-      ASSERT(ssl == NULL);
-      // Because it must be passed as a single void*, terminate
-      // the list of (length, data) strings with a length 0 string.
-      protocol_string_copy =
-          static_cast<uint8_t*>(malloc(protocol_string_len + 1));
-      memmove(protocol_string_copy, protocol_string, protocol_string_len);
-      protocol_string_copy[protocol_string_len] = '\0';
-      SSL_CTX_set_alpn_select_cb(context->context(), AlpnCallback,
-                                 protocol_string_copy);
-      context->set_alpn_protocol_string(protocol_string_copy);
-    } else {
-      // The function makes a local copy of protocol_string, which it owns.
-      if (ssl != NULL) {
-        ASSERT(context == NULL);
-        status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len);
-      } else {
-        ASSERT(context != NULL);
-        ASSERT(ssl == NULL);
-        status = SSL_CTX_set_alpn_protos(context->context(), protocol_string,
-                                         protocol_string_len);
-      }
-      ASSERT(status == 0);  // The function returns a non-standard status.
-    }
-  }
-  Dart_TypedDataReleaseData(protocols_handle);
-}
-
-
-void SSLFilter::Connect(const char* hostname,
-                        SSL_CTX* context,
-                        bool is_server,
-                        bool request_client_certificate,
-                        bool require_client_certificate,
-                        Dart_Handle protocols_handle) {
-  is_server_ = is_server;
-  if (in_handshake_) {
-    FATAL("Connect called twice on the same _SecureFilter.");
-  }
-
-  int status;
-  int error;
-  BIO* ssl_side;
-  status = BIO_new_bio_pair(&ssl_side, kInternalBIOSize, &socket_side_,
-                            kInternalBIOSize);
-  CheckStatusSSL(status, "TlsException", "BIO_new_bio_pair", ssl_);
-
-  assert(context != NULL);
-  ssl_ = SSL_new(context);
-  SSL_set_bio(ssl_, ssl_side, ssl_side);
-  SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY);  // TODO(whesse): Is this right?
-  SSL_set_ex_data(ssl_, filter_ssl_index, this);
-
-  if (is_server_) {
-    int certificate_mode =
-        request_client_certificate ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
-    if (require_client_certificate) {
-      certificate_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
-    }
-    SSL_set_verify(ssl_, certificate_mode, NULL);
-  } else {
-    SetAlpnProtocolList(protocols_handle, ssl_, NULL, false);
-    status = SSL_set_tlsext_host_name(ssl_, hostname);
-    CheckStatusSSL(status, "TlsException", "Set SNI host name", ssl_);
-    // Sets the hostname in the certificate-checking object, so it is checked
-    // against the certificate presented by the server.
-    X509_VERIFY_PARAM* certificate_checking_parameters = SSL_get0_param(ssl_);
-    hostname_ = strdup(hostname);
-    X509_VERIFY_PARAM_set_flags(
-        certificate_checking_parameters,
-        X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST);
-    X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0);
-    status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters,
-                                         hostname_, strlen(hostname_));
-    CheckStatusSSL(status, "TlsException",
-                   "Set hostname for certificate checking", ssl_);
-  }
-  // Make the connection:
-  if (is_server_) {
-    status = SSL_accept(ssl_);
-    if (SSL_LOG_STATUS) {
-      Log::Print("SSL_accept status: %d\n", status);
-    }
-    if (status != 1) {
-      // TODO(whesse): expect a needs-data error here.  Handle other errors.
-      error = SSL_get_error(ssl_, status);
-      if (SSL_LOG_STATUS) {
-        Log::Print("SSL_accept error: %d\n", error);
-      }
-    }
-  } else {
-    status = SSL_connect(ssl_);
-    if (SSL_LOG_STATUS) {
-      Log::Print("SSL_connect status: %d\n", status);
-    }
-    if (status != 1) {
-      // TODO(whesse): expect a needs-data error here.  Handle other errors.
-      error = SSL_get_error(ssl_, status);
-      if (SSL_LOG_STATUS) {
-        Log::Print("SSL_connect error: %d\n", error);
-      }
-    }
-  }
-  Handshake();
-}
-
-
-int printErrorCallback(const char* str, size_t len, void* ctx) {
-  Log::PrintErr("%.*s\n", static_cast<int>(len), str);
-  return 1;
-}
-
-
-void SSLFilter::Handshake() {
-  // Try and push handshake along.
-  int status;
-  status = SSL_do_handshake(ssl_);
-  if (callback_error != NULL) {
-    // The SSL_do_handshake will try performing a handshake and might call
-    // a CertificateCallback. If the certificate validation
-    // failed the 'callback_error" will be set by the certificateCallback
-    // logic and we propagate the error"
-    Dart_PropagateError(callback_error);
-  }
-  if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
-    in_handshake_ = true;
-    return;
-  }
-  CheckStatusSSL(
-      status, "HandshakeException",
-      is_server_ ? "Handshake error in server" : "Handshake error in client",
-      ssl_);
-  // Handshake succeeded.
-  if (in_handshake_) {
-    // TODO(24071): Check return value of SSL_get_verify_result, this
-    //    should give us the hostname check.
-    int result = SSL_get_verify_result(ssl_);
-    if (SSL_LOG_STATUS) {
-      Log::Print("Handshake verification status: %d\n", result);
-      X509* peer_certificate = SSL_get_peer_certificate(ssl_);
-      if (peer_certificate == NULL) {
-        Log::Print("No peer certificate received\n");
-      } else {
-        X509_NAME* s_name = X509_get_subject_name(peer_certificate);
-        printf("Peer certificate SN: ");
-        X509_NAME_print_ex_fp(stdout, s_name, 4, 0);
-        printf("\n");
-      }
-    }
-    ThrowIfError(Dart_InvokeClosure(
-        Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
-    in_handshake_ = false;
-  }
-}
-
-
-void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
-  const uint8_t* protocol;
-  unsigned length;
-  SSL_get0_alpn_selected(ssl_, &protocol, &length);
-  if (length == 0) {
-    Dart_SetReturnValue(args, Dart_Null());
-  } else {
-    Dart_SetReturnValue(args, Dart_NewStringFromUTF8(protocol, length));
-  }
-}
-
-
-void SSLFilter::Renegotiate(bool use_session_cache,
-                            bool request_client_certificate,
-                            bool require_client_certificate) {
-  // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
-  // SSL_REQUEST_CERTIFICATE option is also set, so set it.
-  request_client_certificate =
-      request_client_certificate || require_client_certificate;
-  // TODO(24070, 24069): Implement setting the client certificate parameters,
-  //   and triggering rehandshake.
-}
-
-
-void SSLFilter::FreeResources() {
-  if (ssl_ != NULL) {
-    SSL_free(ssl_);
-    ssl_ = NULL;
-  }
-  if (socket_side_ != NULL) {
-    BIO_free(socket_side_);
-    socket_side_ = NULL;
-  }
-  if (hostname_ != NULL) {
-    free(hostname_);
-    hostname_ = NULL;
-  }
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (buffers_[i] != NULL) {
-      delete[] buffers_[i];
-      buffers_[i] = NULL;
-    }
-  }
-}
-
-
-SSLFilter::~SSLFilter() {
-  FreeResources();
-}
-
-
-void SSLFilter::Destroy() {
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (dart_buffer_objects_[i] != NULL) {
-      Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
-      dart_buffer_objects_[i] = NULL;
-    }
-  }
-  if (string_start_ != NULL) {
-    Dart_DeletePersistentHandle(string_start_);
-    string_start_ = NULL;
-  }
-  if (string_length_ != NULL) {
-    Dart_DeletePersistentHandle(string_length_);
-    string_length_ = NULL;
-  }
-  if (handshake_complete_ != NULL) {
-    Dart_DeletePersistentHandle(handshake_complete_);
-    handshake_complete_ = NULL;
-  }
-  if (bad_certificate_callback_ != NULL) {
-    Dart_DeletePersistentHandle(bad_certificate_callback_);
-    bad_certificate_callback_ = NULL;
-  }
-  FreeResources();
-}
-
-
-/* Read decrypted data from the filter to the circular buffer */
-int SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
-  int length = end - start;
-  int bytes_processed = 0;
-  if (length > 0) {
-    bytes_processed = SSL_read(
-        ssl_, reinterpret_cast<char*>((buffers_[kReadPlaintext] + start)),
-        length);
-    if (bytes_processed < 0) {
-      int error = SSL_get_error(ssl_, bytes_processed);
-      USE(error);
-      bytes_processed = 0;
-    }
-  }
-  return bytes_processed;
-}
-
-
-int SSLFilter::ProcessWritePlaintextBuffer(int start, int end) {
-  int length = end - start;
-  int bytes_processed =
-      SSL_write(ssl_, buffers_[kWritePlaintext] + start, length);
-  if (bytes_processed < 0) {
-    if (SSL_LOG_DATA) {
-      Log::Print("SSL_write returned error %d\n", bytes_processed);
-    }
-    return 0;
-  }
-  return bytes_processed;
-}
-
-
-/* Read encrypted data from the circular buffer to the filter */
-int SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
-  int length = end - start;
-  if (SSL_LOG_DATA)
-    Log::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n", length);
-  int bytes_processed = 0;
-  if (length > 0) {
-    bytes_processed =
-        BIO_write(socket_side_, buffers_[kReadEncrypted] + start, length);
-    if (bytes_processed <= 0) {
-      bool retry = BIO_should_retry(socket_side_);
-      if (!retry) {
-        if (SSL_LOG_DATA)
-          Log::Print("BIO_write failed in ReadEncryptedBuffer\n");
-      }
-      bytes_processed = 0;
-    }
-  }
-  if (SSL_LOG_DATA)
-    Log::Print("Leaving ProcessReadEncryptedBuffer wrote %d bytes\n",
-               bytes_processed);
-  return bytes_processed;
-}
-
-
-int SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
-  int length = end - start;
-  int bytes_processed = 0;
-  if (length > 0) {
-    bytes_processed =
-        BIO_read(socket_side_, buffers_[kWriteEncrypted] + start, length);
-    if (bytes_processed < 0) {
-      if (SSL_LOG_DATA)
-        Log::Print("WriteEncrypted BIO_read returned error %d\n",
-                   bytes_processed);
-      return 0;
-    } else {
-      if (SSL_LOG_DATA)
-        Log::Print("WriteEncrypted  BIO_read wrote %d bytes\n",
-                   bytes_processed);
-    }
-  }
-  return bytes_processed;
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_LINUX)
-
-#endif  // !defined(DART_IO_DISABLED) &&
-        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/secure_socket_filter.cc b/runtime/bin/secure_socket_filter.cc
new file mode 100644
index 0000000..c07eaad
--- /dev/null
+++ b/runtime/bin/secure_socket_filter.cc
@@ -0,0 +1,745 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "bin/secure_socket_filter.h"
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/lockers.h"
+#include "bin/log.h"
+#include "bin/secure_socket_utils.h"
+#include "bin/security_context.h"
+#include "platform/text_buffer.h"
+
+
+// Return the error from the containing function if handle is an error handle.
+#define RETURN_IF_ERROR(handle)                                                \
+  {                                                                            \
+    Dart_Handle __handle = handle;                                             \
+    if (Dart_IsError((__handle))) {                                            \
+      return __handle;                                                         \
+    }                                                                          \
+  }
+
+namespace dart {
+namespace bin {
+
+bool SSLFilter::library_initialized_ = false;
+// To protect library initialization.
+Mutex* SSLFilter::mutex_ = new Mutex();
+int SSLFilter::filter_ssl_index;
+
+const intptr_t SSLFilter::kInternalBIOSize = 10 * KB;
+const intptr_t SSLFilter::kApproximateSize =
+    sizeof(SSLFilter) + (2 * SSLFilter::kInternalBIOSize);
+
+static SSLFilter* GetFilter(Dart_NativeArguments args) {
+  SSLFilter* filter;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this, SSLFilter::kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&filter)));
+  return filter;
+}
+
+
+static void DeleteFilter(void* isolate_data,
+                         Dart_WeakPersistentHandle handle,
+                         void* context_pointer) {
+  SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
+  filter->Release();
+}
+
+
+static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
+  ASSERT(filter != NULL);
+  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+  RETURN_IF_ERROR(dart_this);
+  ASSERT(Dart_IsInstance(dart_this));
+  Dart_Handle err = Dart_SetNativeInstanceField(
+      dart_this, SSLFilter::kSSLFilterNativeFieldIndex,
+      reinterpret_cast<intptr_t>(filter));
+  RETURN_IF_ERROR(err);
+  Dart_NewWeakPersistentHandle(dart_this, reinterpret_cast<void*>(filter),
+                               SSLFilter::kApproximateSize, DeleteFilter);
+  return Dart_Null();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  SSLFilter* filter = new SSLFilter();
+  Dart_Handle err = SetFilter(args, filter);
+  if (Dart_IsError(err)) {
+    filter->Release();
+    Dart_PropagateError(err);
+  }
+  err = filter->Init(dart_this);
+  if (Dart_IsError(err)) {
+    // The finalizer was set up by SetFilter. It will delete `filter` if there
+    // is an error.
+    filter->Destroy();
+    Dart_PropagateError(err);
+  }
+}
+
+
+void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
+  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
+  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+  bool request_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
+  bool require_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
+  Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 6));
+
+  const char* host_name = NULL;
+  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
+  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
+
+  SSLCertContext* context = NULL;
+  if (!Dart_IsNull(context_object)) {
+    ThrowIfError(Dart_GetNativeInstanceField(
+        context_object, SSLCertContext::kSecurityContextNativeFieldIndex,
+        reinterpret_cast<intptr_t*>(&context)));
+  }
+
+  // The protocols_handle is guaranteed to be a valid Uint8List.
+  // It will have the correct length encoding of the protocols array.
+  ASSERT(!Dart_IsNull(protocols_handle));
+  GetFilter(args)->Connect(host_name, context, is_server,
+                           request_client_certificate,
+                           require_client_certificate, protocols_handle);
+}
+
+
+void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
+  SSLFilter* filter = GetFilter(args);
+  // There are two paths that can clean up an SSLFilter object. First,
+  // there is this explicit call to Destroy(), called from
+  // _SecureFilter.destroy() in Dart code. After a call to destroy(), the Dart
+  // code maintains the invariant that there will be no futher SSLFilter
+  // requests sent to the IO Service. Therefore, the internals of the SSLFilter
+  // are safe to deallocate, but not the SSLFilter itself, which is already
+  // set up to be cleaned up by the finalizer.
+  //
+  // The second path is through the finalizer, which we have to do in case
+  // some mishap prevents a call to _SecureFilter.destroy().
+  filter->Destroy();
+}
+
+
+void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
+  GetFilter(args)->Handshake();
+}
+
+
+void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
+    Dart_NativeArguments args) {
+  GetFilter(args)->GetSelectedProtocol(args);
+}
+
+
+void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
+  bool use_session_cache =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
+  bool request_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
+  bool require_client_certificate =
+      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
+  GetFilter(args)->Renegotiate(use_session_cache, request_client_certificate,
+                               require_client_certificate);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
+    Dart_NativeArguments args) {
+  Dart_Handle handshake_complete =
+      ThrowIfError(Dart_GetNativeArgument(args, 1));
+  if (!Dart_IsClosure(handshake_complete)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to RegisterHandshakeCompleteCallback"));
+  }
+  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
+}
+
+
+void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
+    Dart_NativeArguments args) {
+  Dart_Handle callback = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Illegal argument to RegisterBadCertificateCallback"));
+  }
+  GetFilter(args)->RegisterBadCertificateCallback(callback);
+}
+
+
+void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
+  Dart_Handle cert = ThrowIfError(GetFilter(args)->PeerCertificate());
+  Dart_SetReturnValue(args, cert);
+}
+
+
+void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
+  SSLFilter* filter = GetFilter(args);
+  // This filter pointer is passed to the IO Service thread. The IO Service
+  // thread must Release() the pointer when it is done with it.
+  filter->Retain();
+  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
+  Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
+}
+
+
+/**
+ * Pushes data through the SSL filter, reading and writing from circular
+ * buffers shared with Dart.
+ *
+ * The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
+ * pass encrypted and plaintext data to and from the C++ SSLFilter object.
+ *
+ * ProcessFilter is called with a CObject array containing the pointer to
+ * the SSLFilter, encoded as an int, and the start and end positions of the
+ * valid data in the four circular buffers.  The function only reads from
+ * the valid data area of the input buffers, and only writes to the free
+ * area of the output buffers.  The function returns the new start and end
+ * positions in the buffers, but it only updates start for input buffers, and
+ * end for output buffers.  Therefore, the Dart thread can simultaneously
+ * write to the free space and end pointer of input buffers, and read from
+ * the data space of output buffers, and modify the start pointer.
+ *
+ * When ProcessFilter returns, the Dart thread is responsible for combining
+ * the updated pointers from Dart and C++, to make the new valid state of
+ * the circular buffer.
+ */
+CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
+  CObjectIntptr filter_object(request[0]);
+  SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
+  RefCntReleaseScope<SSLFilter> rs(filter);
+
+  bool in_handshake = CObjectBool(request[1]).Value();
+  int starts[SSLFilter::kNumBuffers];
+  int ends[SSLFilter::kNumBuffers];
+  for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
+    starts[i] = CObjectInt32(request[2 * i + 2]).Value();
+    ends[i] = CObjectInt32(request[2 * i + 3]).Value();
+  }
+
+  if (filter->ProcessAllBuffers(starts, ends, in_handshake)) {
+    CObjectArray* result =
+        new CObjectArray(CObject::NewArray(SSLFilter::kNumBuffers * 2));
+    for (int i = 0; i < SSLFilter::kNumBuffers; ++i) {
+      result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
+      result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
+    }
+    return result;
+  } else {
+    int32_t error_code = static_cast<int32_t>(ERR_peek_error());
+    TextBuffer error_string(SecureSocketUtils::SSL_ERROR_MESSAGE_BUFFER_SIZE);
+    SecureSocketUtils::FetchErrorString(filter->ssl_, &error_string);
+    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
+    result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
+    result->SetAt(1, new CObjectString(CObject::NewString(error_string.buf())));
+    return result;
+  }
+}
+
+
+bool SSLFilter::ProcessAllBuffers(int starts[kNumBuffers],
+                                  int ends[kNumBuffers],
+                                  bool in_handshake) {
+  for (int i = 0; i < kNumBuffers; ++i) {
+    if (in_handshake && (i == kReadPlaintext || i == kWritePlaintext)) continue;
+    int start = starts[i];
+    int end = ends[i];
+    int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+    if (start < 0 || end < 0 || start >= size || end >= size) {
+      FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
+    }
+    switch (i) {
+      case kReadPlaintext:
+      case kWriteEncrypted:
+        // Write data to the circular buffer's free space.  If the buffer
+        // is full, neither if statement is executed and nothing happens.
+        if (start <= end) {
+          // If the free space may be split into two segments,
+          // then the first is [end, size), unless start == 0.
+          // Then, since the last free byte is at position start - 2,
+          // the interval is [end, size - 1).
+          int buffer_end = (start == 0) ? size - 1 : size;
+          int bytes = (i == kReadPlaintext)
+                          ? ProcessReadPlaintextBuffer(end, buffer_end)
+                          : ProcessWriteEncryptedBuffer(end, buffer_end);
+          if (bytes < 0) return false;
+          end += bytes;
+          ASSERT(end <= size);
+          if (end == size) end = 0;
+        }
+        if (start > end + 1) {
+          int bytes = (i == kReadPlaintext)
+                          ? ProcessReadPlaintextBuffer(end, start - 1)
+                          : ProcessWriteEncryptedBuffer(end, start - 1);
+          if (bytes < 0) return false;
+          end += bytes;
+          ASSERT(end < start);
+        }
+        ends[i] = end;
+        break;
+      case kReadEncrypted:
+      case kWritePlaintext:
+        // Read/Write data from circular buffer.  If the buffer is empty,
+        // neither if statement's condition is true.
+        if (end < start) {
+          // Data may be split into two segments.  In this case,
+          // the first is [start, size).
+          int bytes = (i == kReadEncrypted)
+                          ? ProcessReadEncryptedBuffer(start, size)
+                          : ProcessWritePlaintextBuffer(start, size);
+          if (bytes < 0) return false;
+          start += bytes;
+          ASSERT(start <= size);
+          if (start == size) start = 0;
+        }
+        if (start < end) {
+          int bytes = (i == kReadEncrypted)
+                          ? ProcessReadEncryptedBuffer(start, end)
+                          : ProcessWritePlaintextBuffer(start, end);
+          if (bytes < 0) return false;
+          start += bytes;
+          ASSERT(start <= end);
+        }
+        starts[i] = start;
+        break;
+      default:
+        UNREACHABLE();
+    }
+  }
+  return true;
+}
+
+
+Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
+  if (!library_initialized_) {
+    InitializeLibrary();
+  }
+  ASSERT(string_start_ == NULL);
+  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
+  ASSERT(string_start_ != NULL);
+  ASSERT(string_length_ == NULL);
+  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
+  ASSERT(string_length_ != NULL);
+  ASSERT(bad_certificate_callback_ == NULL);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
+  ASSERT(bad_certificate_callback_ != NULL);
+  // Caller handles cleanup on an error.
+  return InitializeBuffers(dart_this);
+}
+
+
+Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
+  // Create SSLFilter buffers as ExternalUint8Array objects.
+  Dart_Handle buffers_string = DartUtils::NewString("buffers");
+  RETURN_IF_ERROR(buffers_string);
+  Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
+  RETURN_IF_ERROR(dart_buffers_object);
+  Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
+  RETURN_IF_ERROR(secure_filter_impl_type);
+  Dart_Handle size_string = DartUtils::NewString("SIZE");
+  RETURN_IF_ERROR(size_string);
+  Dart_Handle dart_buffer_size =
+      Dart_GetField(secure_filter_impl_type, size_string);
+  RETURN_IF_ERROR(dart_buffer_size);
+
+  int64_t buffer_size = 0;
+  Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
+  RETURN_IF_ERROR(err);
+
+  Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
+  RETURN_IF_ERROR(encrypted_size_string);
+
+  Dart_Handle dart_encrypted_buffer_size =
+      Dart_GetField(secure_filter_impl_type, encrypted_size_string);
+  RETURN_IF_ERROR(dart_encrypted_buffer_size);
+
+  int64_t encrypted_buffer_size = 0;
+  err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
+  RETURN_IF_ERROR(err);
+
+  if (buffer_size <= 0 || buffer_size > 1 * MB) {
+    FATAL("Invalid buffer size in _ExternalBuffer");
+  }
+  if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
+    FATAL("Invalid encrypted buffer size in _ExternalBuffer");
+  }
+  buffer_size_ = static_cast<int>(buffer_size);
+  encrypted_buffer_size_ = static_cast<int>(encrypted_buffer_size);
+
+  Dart_Handle data_identifier = DartUtils::NewString("data");
+  RETURN_IF_ERROR(data_identifier);
+
+  for (int i = 0; i < kNumBuffers; i++) {
+    int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+    buffers_[i] = new uint8_t[size];
+    ASSERT(buffers_[i] != NULL);
+    dart_buffer_objects_[i] = NULL;
+  }
+
+  Dart_Handle result = Dart_Null();
+  for (int i = 0; i < kNumBuffers; ++i) {
+    int size = IsBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
+    result = Dart_ListGetAt(dart_buffers_object, i);
+    if (Dart_IsError(result)) {
+      break;
+    }
+
+    dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
+    ASSERT(dart_buffer_objects_[i] != NULL);
+    Dart_Handle data =
+        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
+    if (Dart_IsError(data)) {
+      result = data;
+      break;
+    }
+    result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
+    if (Dart_IsError(result)) {
+      break;
+    }
+    result = Dart_SetField(result, data_identifier, data);
+    if (Dart_IsError(result)) {
+      break;
+    }
+  }
+
+  // Caller handles cleanup on an error.
+  return result;
+}
+
+
+void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
+  ASSERT(NULL == handshake_complete_);
+  handshake_complete_ = Dart_NewPersistentHandle(complete);
+
+  ASSERT(handshake_complete_ != NULL);
+}
+
+
+void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
+  ASSERT(bad_certificate_callback_ != NULL);
+  Dart_DeletePersistentHandle(bad_certificate_callback_);
+  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
+  ASSERT(bad_certificate_callback_ != NULL);
+}
+
+
+Dart_Handle SSLFilter::PeerCertificate() {
+  X509* ca = SSL_get_peer_certificate(ssl_);
+  if (ca == NULL) {
+    return Dart_Null();
+  }
+  return X509Helper::WrappedX509Certificate(ca);
+}
+
+
+void SSLFilter::InitializeLibrary() {
+  MutexLocker locker(mutex_);
+  if (!library_initialized_) {
+    SSL_library_init();
+    filter_ssl_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
+    ASSERT(filter_ssl_index >= 0);
+    library_initialized_ = true;
+  }
+}
+
+
+void SSLFilter::Connect(const char* hostname,
+                        SSLCertContext* context,
+                        bool is_server,
+                        bool request_client_certificate,
+                        bool require_client_certificate,
+                        Dart_Handle protocols_handle) {
+  is_server_ = is_server;
+  if (in_handshake_) {
+    FATAL("Connect called twice on the same _SecureFilter.");
+  }
+
+  int status;
+  int error;
+  BIO* ssl_side;
+  status = BIO_new_bio_pair(&ssl_side, kInternalBIOSize, &socket_side_,
+                            kInternalBIOSize);
+  SecureSocketUtils::CheckStatusSSL(status, "TlsException", "BIO_new_bio_pair",
+                                    ssl_);
+
+  ASSERT(context != NULL);
+  ASSERT(context->context() != NULL);
+  ssl_ = SSL_new(context->context());
+  SSL_set_bio(ssl_, ssl_side, ssl_side);
+  SSL_set_mode(ssl_, SSL_MODE_AUTO_RETRY);  // TODO(whesse): Is this right?
+  SSL_set_ex_data(ssl_, filter_ssl_index, this);
+  context->RegisterCallbacks(ssl_);
+
+  if (is_server_) {
+    int certificate_mode =
+        request_client_certificate ? SSL_VERIFY_PEER : SSL_VERIFY_NONE;
+    if (require_client_certificate) {
+      certificate_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+    }
+    SSL_set_verify(ssl_, certificate_mode, NULL);
+  } else {
+    SSLCertContext::SetAlpnProtocolList(protocols_handle, ssl_, NULL, false);
+    status = SSL_set_tlsext_host_name(ssl_, hostname);
+    SecureSocketUtils::CheckStatusSSL(status, "TlsException",
+                                      "Set SNI host name", ssl_);
+    // Sets the hostname in the certificate-checking object, so it is checked
+    // against the certificate presented by the server.
+    X509_VERIFY_PARAM* certificate_checking_parameters = SSL_get0_param(ssl_);
+    hostname_ = strdup(hostname);
+    X509_VERIFY_PARAM_set_flags(
+        certificate_checking_parameters,
+        X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_TRUSTED_FIRST);
+    X509_VERIFY_PARAM_set_hostflags(certificate_checking_parameters, 0);
+    status = X509_VERIFY_PARAM_set1_host(certificate_checking_parameters,
+                                         hostname_, strlen(hostname_));
+    SecureSocketUtils::CheckStatusSSL(
+        status, "TlsException", "Set hostname for certificate checking", ssl_);
+  }
+  // Make the connection:
+  if (is_server_) {
+    status = SSL_accept(ssl_);
+    if (SSL_LOG_STATUS) {
+      Log::Print("SSL_accept status: %d\n", status);
+    }
+    if (status != 1) {
+      // TODO(whesse): expect a needs-data error here.  Handle other errors.
+      error = SSL_get_error(ssl_, status);
+      if (SSL_LOG_STATUS) {
+        Log::Print("SSL_accept error: %d\n", error);
+      }
+    }
+  } else {
+    status = SSL_connect(ssl_);
+    if (SSL_LOG_STATUS) {
+      Log::Print("SSL_connect status: %d\n", status);
+    }
+    if (status != 1) {
+      // TODO(whesse): expect a needs-data error here.  Handle other errors.
+      error = SSL_get_error(ssl_, status);
+      if (SSL_LOG_STATUS) {
+        Log::Print("SSL_connect error: %d\n", error);
+      }
+    }
+  }
+  Handshake();
+}
+
+
+void SSLFilter::Handshake() {
+  // Try and push handshake along.
+  int status;
+  status = SSL_do_handshake(ssl_);
+  if (callback_error != NULL) {
+    // The SSL_do_handshake will try performing a handshake and might call
+    // a CertificateCallback. If the certificate validation
+    // failed the 'callback_error" will be set by the certificateCallback
+    // logic and we propagate the error"
+    Dart_PropagateError(callback_error);
+  }
+  if (SSL_want_write(ssl_) || SSL_want_read(ssl_)) {
+    in_handshake_ = true;
+    return;
+  }
+  SecureSocketUtils::CheckStatusSSL(
+      status, "HandshakeException",
+      is_server_ ? "Handshake error in server" : "Handshake error in client",
+      ssl_);
+  // Handshake succeeded.
+  if (in_handshake_) {
+    // TODO(24071): Check return value of SSL_get_verify_result, this
+    //    should give us the hostname check.
+    int result = SSL_get_verify_result(ssl_);
+    if (SSL_LOG_STATUS) {
+      Log::Print("Handshake verification status: %d\n", result);
+      X509* peer_certificate = SSL_get_peer_certificate(ssl_);
+      if (peer_certificate == NULL) {
+        Log::Print("No peer certificate received\n");
+      } else {
+        X509_NAME* s_name = X509_get_subject_name(peer_certificate);
+        printf("Peer certificate SN: ");
+        X509_NAME_print_ex_fp(stdout, s_name, 4, 0);
+        printf("\n");
+      }
+    }
+    ThrowIfError(Dart_InvokeClosure(
+        Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
+    in_handshake_ = false;
+  }
+}
+
+
+void SSLFilter::GetSelectedProtocol(Dart_NativeArguments args) {
+  const uint8_t* protocol;
+  unsigned length;
+  SSL_get0_alpn_selected(ssl_, &protocol, &length);
+  if (length == 0) {
+    Dart_SetReturnValue(args, Dart_Null());
+  } else {
+    Dart_SetReturnValue(args, Dart_NewStringFromUTF8(protocol, length));
+  }
+}
+
+
+void SSLFilter::Renegotiate(bool use_session_cache,
+                            bool request_client_certificate,
+                            bool require_client_certificate) {
+  // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
+  // SSL_REQUEST_CERTIFICATE option is also set, so set it.
+  request_client_certificate =
+      request_client_certificate || require_client_certificate;
+  // TODO(24070, 24069): Implement setting the client certificate parameters,
+  //   and triggering rehandshake.
+}
+
+
+void SSLFilter::FreeResources() {
+  if (ssl_ != NULL) {
+    SSL_free(ssl_);
+    ssl_ = NULL;
+  }
+  if (socket_side_ != NULL) {
+    BIO_free(socket_side_);
+    socket_side_ = NULL;
+  }
+  if (hostname_ != NULL) {
+    free(hostname_);
+    hostname_ = NULL;
+  }
+  for (int i = 0; i < kNumBuffers; ++i) {
+    if (buffers_[i] != NULL) {
+      delete[] buffers_[i];
+      buffers_[i] = NULL;
+    }
+  }
+}
+
+
+SSLFilter::~SSLFilter() {
+  FreeResources();
+}
+
+
+void SSLFilter::Destroy() {
+  for (int i = 0; i < kNumBuffers; ++i) {
+    if (dart_buffer_objects_[i] != NULL) {
+      Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
+      dart_buffer_objects_[i] = NULL;
+    }
+  }
+  if (string_start_ != NULL) {
+    Dart_DeletePersistentHandle(string_start_);
+    string_start_ = NULL;
+  }
+  if (string_length_ != NULL) {
+    Dart_DeletePersistentHandle(string_length_);
+    string_length_ = NULL;
+  }
+  if (handshake_complete_ != NULL) {
+    Dart_DeletePersistentHandle(handshake_complete_);
+    handshake_complete_ = NULL;
+  }
+  if (bad_certificate_callback_ != NULL) {
+    Dart_DeletePersistentHandle(bad_certificate_callback_);
+    bad_certificate_callback_ = NULL;
+  }
+  FreeResources();
+}
+
+
+/* Read decrypted data from the filter to the circular buffer */
+int SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
+  int length = end - start;
+  int bytes_processed = 0;
+  if (length > 0) {
+    bytes_processed = SSL_read(
+        ssl_, reinterpret_cast<char*>((buffers_[kReadPlaintext] + start)),
+        length);
+    if (bytes_processed < 0) {
+      int error = SSL_get_error(ssl_, bytes_processed);
+      USE(error);
+      bytes_processed = 0;
+    }
+  }
+  return bytes_processed;
+}
+
+
+int SSLFilter::ProcessWritePlaintextBuffer(int start, int end) {
+  int length = end - start;
+  int bytes_processed =
+      SSL_write(ssl_, buffers_[kWritePlaintext] + start, length);
+  if (bytes_processed < 0) {
+    if (SSL_LOG_DATA) {
+      Log::Print("SSL_write returned error %d\n", bytes_processed);
+    }
+    return 0;
+  }
+  return bytes_processed;
+}
+
+
+/* Read encrypted data from the circular buffer to the filter */
+int SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
+  int length = end - start;
+  if (SSL_LOG_DATA)
+    Log::Print("Entering ProcessReadEncryptedBuffer with %d bytes\n", length);
+  int bytes_processed = 0;
+  if (length > 0) {
+    bytes_processed =
+        BIO_write(socket_side_, buffers_[kReadEncrypted] + start, length);
+    if (bytes_processed <= 0) {
+      bool retry = BIO_should_retry(socket_side_);
+      if (!retry) {
+        if (SSL_LOG_DATA)
+          Log::Print("BIO_write failed in ReadEncryptedBuffer\n");
+      }
+      bytes_processed = 0;
+    }
+  }
+  if (SSL_LOG_DATA)
+    Log::Print("Leaving ProcessReadEncryptedBuffer wrote %d bytes\n",
+               bytes_processed);
+  return bytes_processed;
+}
+
+
+int SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
+  int length = end - start;
+  int bytes_processed = 0;
+  if (length > 0) {
+    bytes_processed =
+        BIO_read(socket_side_, buffers_[kWriteEncrypted] + start, length);
+    if (bytes_processed < 0) {
+      if (SSL_LOG_DATA)
+        Log::Print("WriteEncrypted BIO_read returned error %d\n",
+                   bytes_processed);
+      return 0;
+    } else {
+      if (SSL_LOG_DATA)
+        Log::Print("WriteEncrypted  BIO_read wrote %d bytes\n",
+                   bytes_processed);
+    }
+  }
+  return bytes_processed;
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/secure_socket_boringssl.h b/runtime/bin/secure_socket_filter.h
similarity index 66%
rename from runtime/bin/secure_socket_boringssl.h
rename to runtime/bin/secure_socket_filter.h
index e14171d..dda69eb 100644
--- a/runtime/bin/secure_socket_boringssl.h
+++ b/runtime/bin/secure_socket_filter.h
@@ -1,30 +1,18 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#ifndef RUNTIME_BIN_SECURE_SOCKET_BORINGSSL_H_
-#define RUNTIME_BIN_SECURE_SOCKET_BORINGSSL_H_
-
-#if !defined(RUNTIME_BIN_SECURE_SOCKET_H_)
-#error Do not include secure_socket_boringssl.h directly. Use secure_socket.h.
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
+#ifndef RUNTIME_BIN_SECURE_SOCKET_FILTER_H_
+#define RUNTIME_BIN_SECURE_SOCKET_FILTER_H_
 
 #include <openssl/bio.h>
-#include <openssl/err.h>
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 
 #include "bin/builtin.h"
-#include "bin/dartutils.h"
 #include "bin/reference_counting.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
+#include "bin/security_context.h"
+#include "platform/utils.h"
 
 namespace dart {
 namespace bin {
@@ -33,44 +21,6 @@
 extern const unsigned char* root_certificates_pem;
 extern unsigned int root_certificates_pem_length;
 
-class SSLContext {
- public:
-  static const intptr_t kApproximateSize;
-
-  explicit SSLContext(SSL_CTX* context)
-      : context_(context), alpn_protocol_string_(NULL) {}
-
-  ~SSLContext() {
-    SSL_CTX_free(context_);
-    if (alpn_protocol_string_ != NULL) {
-      free(alpn_protocol_string_);
-    }
-  }
-
-  SSL_CTX* context() const { return context_; }
-
-  uint8_t* alpn_protocol_string() const { return alpn_protocol_string_; }
-  void set_alpn_protocol_string(uint8_t* protocol_string) {
-    if (alpn_protocol_string_ != NULL) {
-      free(alpn_protocol_string_);
-    }
-    alpn_protocol_string_ = protocol_string;
-  }
-
- private:
-  SSL_CTX* context_;
-  uint8_t* alpn_protocol_string_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLContext);
-};
-
-/*
- * SSLFilter encapsulates the SSL(TLS) code in a filter, that communicates
- * with the containing _SecureFilterImpl Dart object through four shared
- * ExternalByteArray buffers, for reading and writing plaintext, and
- * reading and writing encrypted text.  The filter handles handshaking
- * and certificate verification.
- */
 class SSLFilter : public ReferenceCounted<SSLFilter> {
  public:
   // These enums must agree with those in sdk/lib/io/secure_socket.dart.
@@ -84,6 +34,7 @@
   };
 
   static const intptr_t kApproximateSize;
+  static const int kSSLFilterNativeFieldIndex = 0;
 
   SSLFilter()
       : callback_error(NULL),
@@ -100,7 +51,7 @@
 
   Dart_Handle Init(Dart_Handle dart_this);
   void Connect(const char* hostname,
-               SSL_CTX* context,
+               SSLCertContext* context,
                bool is_server,
                bool request_client_certificate,
                bool require_client_certificate,
@@ -133,15 +84,14 @@
   // The index of the external data field in _ssl that points to the SSLFilter.
   static int filter_ssl_index;
 
-  // TODO(whesse): make private:
-  SSL* ssl_;
-  BIO* socket_side_;
-
  private:
   static const intptr_t kInternalBIOSize;
   static bool library_initialized_;
   static Mutex* mutex_;  // To protect library initialization.
 
+  SSL* ssl_;
+  BIO* socket_side_;
+
   uint8_t* buffers_[kNumBuffers];
   int buffer_size_;
   int encrypted_buffer_size_;
@@ -154,7 +104,7 @@
   bool is_server_;
   char* hostname_;
 
-  static bool isBufferEncrypted(int i) {
+  static bool IsBufferEncrypted(int i) {
     return static_cast<BufferIndex>(i) >= kFirstEncrypted;
   }
   Dart_Handle InitializeBuffers(Dart_Handle dart_this);
@@ -166,4 +116,4 @@
 }  // namespace bin
 }  // namespace dart
 
-#endif  // RUNTIME_BIN_SECURE_SOCKET_BORINGSSL_H_
+#endif  // RUNTIME_BIN_SECURE_SOCKET_FILTER_H_
diff --git a/runtime/bin/secure_socket_ios.cc b/runtime/bin/secure_socket_ios.cc
deleted file mode 100644
index e2d9abc..0000000
--- a/runtime/bin/secure_socket_ios.cc
+++ /dev/null
@@ -1,1507 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
-
-#include "platform/globals.h"
-#if HOST_OS_IOS
-
-#include "bin/secure_socket.h"
-#include "bin/secure_socket_ios.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/lockers.h"
-#include "bin/log.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-#include "platform/text_buffer.h"
-#include "platform/utils.h"
-
-#include "include/dart_api.h"
-
-// Return the error from the containing function if handle is an error handle.
-#define RETURN_IF_ERROR(handle)                                                \
-  {                                                                            \
-    Dart_Handle __handle = handle;                                             \
-    if (Dart_IsError((__handle))) {                                            \
-      return __handle;                                                         \
-    }                                                                          \
-  }
-
-namespace dart {
-namespace bin {
-
-static const int kSSLFilterNativeFieldIndex = 0;
-static const int kSecurityContextNativeFieldIndex = 0;
-static const int kX509NativeFieldIndex = 0;
-
-static const bool SSL_LOG_STATUS = false;
-static const bool SSL_LOG_DATA = false;
-static const bool SSL_LOG_CERTS = false;
-static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
-static const intptr_t PEM_BUFSIZE = 1024;
-
-static char* CFStringRefToCString(CFStringRef cfstring) {
-  CFIndex len = CFStringGetLength(cfstring);
-  CFIndex max_len =
-      CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
-  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len));
-  ASSERT(result != NULL);
-  bool success =
-      CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8);
-  return success ? result : NULL;
-}
-
-
-// Handle an error reported from the SecureTransport library.
-static void ThrowIOException(OSStatus status,
-                             const char* exception_type,
-                             const char* message) {
-  TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-  status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
-                        static_cast<intptr_t>(status));
-  OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL);
-  Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
-  Dart_Handle exception =
-      DartUtils::NewDartIOException(exception_type, message, os_error);
-  ASSERT(!Dart_IsError(exception));
-  Dart_ThrowException(exception);
-  UNREACHABLE();
-}
-
-
-static void CheckStatus(OSStatus status,
-                        const char* type,
-                        const char* message) {
-  if (status == noErr) {
-    return;
-  }
-  ThrowIOException(status, type, message);
-}
-
-
-static SSLFilter* GetFilter(Dart_NativeArguments args) {
-  SSLFilter* filter;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&filter)));
-  return filter;
-}
-
-
-static void DeleteFilter(void* isolate_data,
-                         Dart_WeakPersistentHandle handle,
-                         void* context_pointer) {
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  filter->Release();
-}
-
-
-static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
-  ASSERT(filter != NULL);
-  const int approximate_size_of_filter = 1500;
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(filter));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, reinterpret_cast<void*>(filter),
-                               approximate_size_of_filter, DeleteFilter);
-  return Dart_Null();
-}
-
-
-static SSLCertContext* GetSecurityContext(Dart_NativeArguments args) {
-  SSLCertContext* context;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&context)));
-  return context;
-}
-
-
-static void DeleteCertContext(void* isolate_data,
-                              Dart_WeakPersistentHandle handle,
-                              void* context_pointer) {
-  SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
-  context->Release();
-}
-
-
-static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
-                                      SSLCertContext* context) {
-  const int approximate_size_of_context = 1500;
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(context));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, context, approximate_size_of_context,
-                               DeleteCertContext);
-  return Dart_Null();
-}
-
-
-static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) {
-  SecCertificateRef certificate;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kX509NativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&certificate)));
-  return certificate;
-}
-
-
-static void ReleaseCertificate(void* isolate_data,
-                               Dart_WeakPersistentHandle handle,
-                               void* context_pointer) {
-  SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer);
-  CFRelease(cert);
-}
-
-
-static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) {
-  const intptr_t approximate_size_of_certificate = 1500;
-  if (certificate == NULL) {
-    return Dart_Null();
-  }
-  Dart_Handle x509_type =
-      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
-  if (Dart_IsError(x509_type)) {
-    return x509_type;
-  }
-  Dart_Handle arguments[] = {NULL};
-
-  Dart_Handle result =
-      Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  ASSERT(Dart_IsInstance(result));
-
-  // CFRetain in case the returned Dart object outlives the SecurityContext.
-  // CFRelease is in the Dart object's finalizer
-  CFRetain(certificate);
-  Dart_NewWeakPersistentHandle(result, reinterpret_cast<void*>(certificate),
-                               approximate_size_of_certificate,
-                               ReleaseCertificate);
-
-  Dart_Handle status = Dart_SetNativeInstanceField(
-      result, kX509NativeFieldIndex, reinterpret_cast<intptr_t>(certificate));
-  if (Dart_IsError(status)) {
-    return status;
-  }
-  return result;
-}
-
-
-static const char* GetPasswordArgument(Dart_NativeArguments args,
-                                       intptr_t index) {
-  Dart_Handle password_object =
-      ThrowIfError(Dart_GetNativeArgument(args, index));
-  const char* password = NULL;
-  if (Dart_IsString(password_object)) {
-    ThrowIfError(Dart_StringToCString(password_object, &password));
-    if (strlen(password) > PEM_BUFSIZE - 1) {
-      Dart_ThrowException(DartUtils::NewDartArgumentError(
-          "Password length is greater than 1023 bytes."));
-    }
-  } else if (Dart_IsNull(password_object)) {
-    password = "";
-  } else {
-    Dart_ThrowException(
-        DartUtils::NewDartArgumentError("Password is not a String or null"));
-  }
-  return password;
-}
-
-
-static OSStatus TryPKCS12Import(CFDataRef cfdata,
-                                CFStringRef password,
-                                CFArrayRef* out_certs,
-                                SecIdentityRef* out_identity) {
-  const void* keys[] = {kSecImportExportPassphrase};
-  const void* values[] = {password};
-  CFDictionaryRef params =
-      CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
-  CFArrayRef items = NULL;
-  OSStatus status = SecPKCS12Import(cfdata, params, &items);
-  CFRelease(params);
-
-  if (status != noErr) {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("SecPKCS12Import: status = %ld",
-                    static_cast<intptr_t>(status));
-      return status;
-    }
-  }
-
-  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
-  if (SSL_LOG_CERTS) {
-    Log::PrintErr("TryPKCS12Import succeeded, count = %ld\n", items_length);
-  }
-
-  // Empty list indicates a decoding failure of some sort.
-  if ((items != NULL) && (items_length == 0)) {
-    CFRelease(items);
-    return errSSLBadCert;
-  }
-
-  CFMutableArrayRef result_certs =
-      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-  SecIdentityRef result_identity = NULL;
-
-  for (CFIndex i = 0; i < items_length; i++) {
-    CFTypeRef item =
-        reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
-    ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
-    CFDictionaryRef dict = reinterpret_cast<CFDictionaryRef>(item);
-
-    //  Trust.
-    CFTypeRef trust_item = CFDictionaryGetValue(dict, kSecImportItemTrust);
-    if (trust_item != NULL) {
-      ASSERT(CFGetTypeID(trust_item) == SecTrustGetTypeID());
-      if (SSL_LOG_CERTS) {
-        Log::PrintErr("\titem %ld has a trust object\n", i);
-      }
-      // TODO(zra): Is this useful for anything?
-    }
-
-    // Identity.
-    CFTypeRef identity_item =
-        CFDictionaryGetValue(dict, kSecImportItemIdentity);
-    if (identity_item != NULL) {
-      ASSERT(CFGetTypeID(identity_item) == SecIdentityGetTypeID());
-      if (SSL_LOG_CERTS) {
-        Log::PrintErr("\titem %ld has an identity object\n", i);
-      }
-      // Only extract the first identity we find.
-      if (result_identity == NULL) {
-        result_identity =
-            reinterpret_cast<SecIdentityRef>(const_cast<void*>(identity_item));
-        CFRetain(result_identity);
-      }
-    }
-
-    // Certificates.
-    CFTypeRef cert_items = CFDictionaryGetValue(dict, kSecImportItemCertChain);
-    if (cert_items != NULL) {
-      ASSERT(CFGetTypeID(cert_items) == CFArrayGetTypeID());
-      CFArrayRef certs = reinterpret_cast<CFArrayRef>(cert_items);
-      if (SSL_LOG_CERTS) {
-        CFIndex count = CFArrayGetCount(certs);
-        Log::PrintErr("\titem %ld has a cert chain %ld certs long\n", i, count);
-      }
-      CFArrayAppendArray(result_certs, certs,
-                         CFRangeMake(0, CFArrayGetCount(certs)));
-    }
-  }
-
-  if (out_certs == NULL) {
-    if (result_certs != NULL) {
-      CFRelease(result_certs);
-    }
-  } else {
-    *out_certs = result_certs;
-  }
-
-  if (out_identity == NULL) {
-    if (result_identity != NULL) {
-      CFRelease(result_identity);
-    }
-  } else {
-    *out_identity = result_identity;
-  }
-
-  // On failure, don't return any objects.
-  ASSERT((status == noErr) ||
-         ((result_certs == NULL) && (result_identity == NULL)));
-  return status;
-}
-
-
-static OSStatus ExtractSecItems(uint8_t* buffer,
-                                intptr_t length,
-                                const char* password,
-                                CFArrayRef* out_certs,
-                                SecIdentityRef* out_identity) {
-  ASSERT(buffer != NULL);
-  ASSERT(password != NULL);
-  OSStatus status = noErr;
-
-  CFDataRef cfdata =
-      CFDataCreateWithBytesNoCopy(NULL, buffer, length, kCFAllocatorNull);
-  CFStringRef cfpassword = CFStringCreateWithCStringNoCopy(
-      NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull);
-  ASSERT(cfdata != NULL);
-  ASSERT(cfpassword != NULL);
-
-  status = TryPKCS12Import(cfdata, cfpassword, out_certs, out_identity);
-
-  CFRelease(cfdata);
-  CFRelease(cfpassword);
-  return status;
-}
-
-
-void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  SSLFilter* filter = new SSLFilter();  // Deleted in DeleteFilter finalizer.
-  Dart_Handle err = SetFilter(args, filter);
-  if (Dart_IsError(err)) {
-    filter->Release();
-    Dart_PropagateError(err);
-  }
-  err = filter->Init(dart_this);
-  if (Dart_IsError(err)) {
-    // The finalizer was set up by SetFilter. It will delete `filter` if there
-    // is an error.
-    filter->Destroy();
-    Dart_PropagateError(err);
-  }
-}
-
-
-void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
-  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
-
-  const char* host_name = NULL;
-  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
-  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
-
-  SSLCertContext* context = NULL;
-  if (!Dart_IsNull(context_object)) {
-    ThrowIfError(Dart_GetNativeInstanceField(
-        context_object, kSecurityContextNativeFieldIndex,
-        reinterpret_cast<intptr_t*>(&context)));
-  }
-
-  GetFilter(args)->Connect(dart_this, host_name, context, is_server,
-                           request_client_certificate,
-                           require_client_certificate);
-}
-
-
-void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // The SSLFilter is deleted in the finalizer for the Dart object created by
-  // SetFilter. There is no need to NULL-out the native field for the SSLFilter
-  // here because the SSLFilter won't be deleted until the finalizer for the
-  // Dart object runs while the Dart object is being GCd. This approach avoids a
-  // leak if Destroy isn't called, and avoids a NULL-dereference if Destroy is
-  // called more than once.
-  filter->Destroy();
-}
-
-
-void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
-  OSStatus status = GetFilter(args)->CheckHandshake();
-  CheckStatus(status, "HandshakeException", "Handshake error");
-}
-
-
-void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
-    Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, Dart_Null());
-}
-
-
-void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
-  bool use_session_cache =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  GetFilter(args)->Renegotiate(use_session_cache, request_client_certificate,
-                               require_client_certificate);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle handshake_complete =
-      ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(handshake_complete)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterHandshakeCompleteCallback"));
-  }
-  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle callback = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterBadCertificateCallback"));
-  }
-  GetFilter(args)->RegisterBadCertificateCallback(callback);
-}
-
-
-void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
-}
-
-
-void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // This filter pointer is passed to the IO Service thread. The IO Service
-  // thread must Release() the pointer when it is done with it.
-  filter->Retain();
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
-  Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
-}
-
-
-void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
-  SSLCertContext* cert_context = new SSLCertContext();
-  // cert_context deleted in DeleteCertContext finalizer.
-  Dart_Handle err = SetSecurityContext(args, cert_context);
-  if (Dart_IsError(err)) {
-    cert_context->Release();
-    Dart_PropagateError(err);
-  }
-}
-
-
-void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  OSStatus status;
-  CFArrayRef cert_chain = NULL;
-  SecIdentityRef identity = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = ExtractSecItems(buffer.get(), buffer.length(), password,
-                             &cert_chain, &identity);
-  }
-
-  // Set the context fields. Repeated calls to usePrivateKeyBytes are an error.
-  bool set_failure = false;
-  if ((identity != NULL) && !context->set_identity(identity)) {
-    CFRelease(identity);
-    if (cert_chain != NULL) {
-      CFRelease(cert_chain);
-    }
-    set_failure = true;
-  }
-
-  // We can't have set a cert_chain without also having set an identity.
-  // That is, if context->set_identity() succeeds, then it is impossible for
-  // context->set_cert_chain() to fail. This is because SecPKCS12Import never
-  // returns a cert chain without also returning a private key.
-  ASSERT(set_failure || (context->cert_chain() == NULL));
-  if (!set_failure && (cert_chain != NULL)) {
-    context->set_cert_chain(cert_chain);
-  }
-
-  if (set_failure) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "usePrivateKeyBytes has already been called on the given context."));
-  }
-  CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-
-  OSStatus status = noErr;
-  SecCertificateRef cert = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    CFDataRef cfdata = CFDataCreateWithBytesNoCopy(
-        NULL, buffer.get(), buffer.length(), kCFAllocatorNull);
-    cert = SecCertificateCreateWithData(NULL, cfdata);
-    CFRelease(cfdata);
-  }
-
-  // Add the certs to the context.
-  if (cert != NULL) {
-    context->add_trusted_cert(cert);
-  } else {
-    status = errSSLBadCert;
-  }
-  CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, Dart_NewBoolean(false));
-}
-
-
-void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  context->set_trust_builtin(true);
-}
-
-
-void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
-    Dart_NativeArguments args) {
-  // This is a no-op on iOS. We get the cert chain along with the private key
-  // in UsePrivateyKeyBytes().
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
-    Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "SecurityContext.setClientAuthoritiesBytes is not supported on this "
-      "platform."));
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
-    Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "ALPN is not supported on this platform"));
-}
-
-
-void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
-  SecCertificateRef certificate = GetX509Certificate(args);
-  CFStringRef cfsubject = SecCertificateCopySubjectSummary(certificate);
-  if (cfsubject != NULL) {
-    char* csubject = CFStringRefToCString(cfsubject);
-    CFRelease(cfsubject);
-    Dart_SetReturnValue(args, Dart_NewStringFromCString(csubject));
-  } else {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.subject failed to find subject's common name."));
-  }
-}
-
-
-void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "X509Certificate.issuer is not supported on this platform."));
-}
-
-
-void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "X509Certificate.startValidity is not supported on this platform."));
-}
-
-
-void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "X509Certificate.endValidity is not supported on this platform."));
-}
-
-
-// Pushes data through the SSL filter, reading and writing from circular
-// buffers shared with Dart. Called from the IOService thread.
-//
-// The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
-// pass encrypted and plaintext data to and from the C++ SSLFilter object.
-//
-// ProcessFilter is called with a CObject array containing the pointer to
-// the SSLFilter, encoded as an int, and the start and end positions of the
-// valid data in the four circular buffers.  The function only reads from
-// the valid data area of the input buffers, and only writes to the free
-// area of the output buffers.  The function returns the new start and end
-// positions in the buffers, but it only updates start for input buffers, and
-// end for output buffers.  Therefore, the Dart thread can simultaneously
-// write to the free space and end pointer of input buffers, and read from
-// the data space of output buffers, and modify the start pointer.
-//
-// When ProcessFilter returns, the Dart thread is responsible for combining
-// the updated pointers from Dart and C++, to make the new valid state of
-// the circular buffer.
-CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
-  CObjectIntptr filter_object(request[0]);
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
-  RefCntReleaseScope<SSLFilter> rs(filter);
-
-  bool in_handshake = CObjectBool(request[1]).Value();
-  intptr_t starts[SSLFilter::kNumBuffers];
-  intptr_t ends[SSLFilter::kNumBuffers];
-  for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
-    starts[i] = CObjectInt32(request[2 * i + 2]).Value();
-    ends[i] = CObjectInt32(request[2 * i + 3]).Value();
-  }
-
-  OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake);
-  if (status == noErr) {
-    CObjectArray* result =
-        new CObjectArray(CObject::NewArray(SSLFilter::kNumBuffers * 2));
-    for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
-      result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
-      result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
-    }
-    return result;
-  } else {
-    TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
-                          static_cast<intptr_t>(status));
-    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
-    result->SetAt(0, new CObjectInt32(CObject::NewInt32(status)));
-    result->SetAt(1,
-                  new CObjectString(CObject::NewString(status_message.buf())));
-    return result;
-  }
-}
-
-
-// Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers,
-// called from ProcessFilterRequest, called from the IOService thread.
-// However, the first call to SSLHandshake comes from the Dart thread, and so
-// doesn't go through there. This results in calls to SSLReadCallback and
-// SSLWriteCallback in which buffer_starts_ and buffer_ends_ haven't been set
-// up. In that case, since we're coming from Dart anyway, we can access the
-// fieds directly from the Dart objects.
-intptr_t SSLFilter::GetBufferStart(intptr_t idx) const {
-  if (buffer_starts_[idx] != NULL) {
-    return *buffer_starts_[idx];
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  Dart_Handle start_handle =
-      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("start")));
-  int64_t start = DartUtils::GetIntegerValue(start_handle);
-  return static_cast<intptr_t>(start);
-}
-
-
-intptr_t SSLFilter::GetBufferEnd(intptr_t idx) const {
-  if (buffer_ends_[idx] != NULL) {
-    return *buffer_ends_[idx];
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  Dart_Handle end_handle =
-      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("end")));
-  int64_t end = DartUtils::GetIntegerValue(end_handle);
-  return static_cast<intptr_t>(end);
-}
-
-
-void SSLFilter::SetBufferStart(intptr_t idx, intptr_t value) {
-  if (buffer_starts_[idx] != NULL) {
-    *buffer_starts_[idx] = value;
-    return;
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  ThrowIfError(DartUtils::SetIntegerField(buffer_handle, "start",
-                                          static_cast<int64_t>(value)));
-}
-
-
-void SSLFilter::SetBufferEnd(intptr_t idx, intptr_t value) {
-  if (buffer_ends_[idx] != NULL) {
-    *buffer_ends_[idx] = value;
-    return;
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  ThrowIfError(DartUtils::SetIntegerField(buffer_handle, "end",
-                                          static_cast<int64_t>(value)));
-}
-
-
-OSStatus SSLFilter::ProcessAllBuffers(intptr_t starts[kNumBuffers],
-                                      intptr_t ends[kNumBuffers],
-                                      bool in_handshake) {
-  for (intptr_t i = 0; i < kNumBuffers; ++i) {
-    buffer_starts_[i] = &starts[i];
-    buffer_ends_[i] = &ends[i];
-  }
-
-  if (in_handshake) {
-    OSStatus status = Handshake();
-    if (status != noErr) {
-      return status;
-    }
-  } else {
-    for (intptr_t i = 0; i < kNumBuffers; ++i) {
-      intptr_t start = starts[i];
-      intptr_t end = ends[i];
-      intptr_t size =
-          isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-      if (start < 0 || end < 0 || start >= size || end >= size) {
-        FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
-      }
-      switch (i) {
-        case kReadPlaintext:
-          // Write data to the circular buffer's free space.  If the buffer
-          // is full, neither if statement is executed and nothing happens.
-          if (start <= end) {
-            // If the free space may be split into two segments,
-            // then the first is [end, size), unless start == 0.
-            // Then, since the last free byte is at position start - 2,
-            // the interval is [end, size - 1).
-            intptr_t buffer_end = (start == 0) ? size - 1 : size;
-            intptr_t bytes = 0;
-            OSStatus status =
-                ProcessReadPlaintextBuffer(end, buffer_end, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            end += bytes;
-            ASSERT(end <= size);
-            if (end == size) {
-              end = 0;
-            }
-          }
-          if (start > end + 1) {
-            intptr_t bytes = 0;
-            OSStatus status =
-                ProcessReadPlaintextBuffer(end, start - 1, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            end += bytes;
-            ASSERT(end < start);
-          }
-          ends[i] = end;
-          break;
-        case kWritePlaintext:
-          // Read/Write data from circular buffer.  If the buffer is empty,
-          // neither if statement's condition is true.
-          if (end < start) {
-            // Data may be split into two segments.  In this case,
-            // the first is [start, size).
-            intptr_t bytes = 0;
-            OSStatus status = ProcessWritePlaintextBuffer(start, size, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            start += bytes;
-            ASSERT(start <= size);
-            if (start == size) {
-              start = 0;
-            }
-          }
-          if (start < end) {
-            intptr_t bytes = 0;
-            OSStatus status = ProcessWritePlaintextBuffer(start, end, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            start += bytes;
-            ASSERT(start <= end);
-          }
-          starts[i] = start;
-          break;
-        case kReadEncrypted:
-        case kWriteEncrypted:
-          // These buffers are advanced through SSLReadCallback and
-          // SSLWriteCallback, which are called from SSLRead, SSLWrite, and
-          // SSLHandshake.
-          break;
-        default:
-          UNREACHABLE();
-      }
-    }
-  }
-
-  for (intptr_t i = 0; i < kNumBuffers; ++i) {
-    buffer_starts_[i] = NULL;
-    buffer_ends_[i] = NULL;
-  }
-  return noErr;
-}
-
-
-Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
-  ASSERT(string_start_ == NULL);
-  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
-  ASSERT(string_start_ != NULL);
-  ASSERT(string_length_ == NULL);
-  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
-  ASSERT(string_length_ != NULL);
-  ASSERT(bad_certificate_callback_ == NULL);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
-  ASSERT(bad_certificate_callback_ != NULL);
-
-  // Caller handles cleanup on an error.
-  return InitializeBuffers(dart_this);
-}
-
-
-Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
-  // Create SSLFilter buffers as ExternalUint8Array objects.
-  Dart_Handle buffers_string = DartUtils::NewString("buffers");
-  RETURN_IF_ERROR(buffers_string);
-  Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
-  RETURN_IF_ERROR(dart_buffers_object);
-  Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
-  RETURN_IF_ERROR(secure_filter_impl_type);
-  Dart_Handle size_string = DartUtils::NewString("SIZE");
-  RETURN_IF_ERROR(size_string);
-  Dart_Handle dart_buffer_size =
-      Dart_GetField(secure_filter_impl_type, size_string);
-  RETURN_IF_ERROR(dart_buffer_size);
-
-  int64_t buffer_size = 0;
-  Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
-  RETURN_IF_ERROR(err);
-
-  Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
-  RETURN_IF_ERROR(encrypted_size_string);
-
-  Dart_Handle dart_encrypted_buffer_size =
-      Dart_GetField(secure_filter_impl_type, encrypted_size_string);
-  RETURN_IF_ERROR(dart_encrypted_buffer_size);
-
-  int64_t encrypted_buffer_size = 0;
-  err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
-  RETURN_IF_ERROR(err);
-
-  if (buffer_size <= 0 || buffer_size > 1 * MB) {
-    FATAL("Invalid buffer size in _ExternalBuffer");
-  }
-  if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
-    FATAL("Invalid encrypted buffer size in _ExternalBuffer");
-  }
-  buffer_size_ = static_cast<intptr_t>(buffer_size);
-  encrypted_buffer_size_ = static_cast<intptr_t>(encrypted_buffer_size);
-
-  Dart_Handle data_identifier = DartUtils::NewString("data");
-  RETURN_IF_ERROR(data_identifier);
-
-  for (int i = 0; i < kNumBuffers; i++) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    buffers_[i] = new uint8_t[size];
-    ASSERT(buffers_[i] != NULL);
-    buffer_starts_[i] = NULL;
-    buffer_ends_[i] = NULL;
-    dart_buffer_objects_[i] = NULL;
-  }
-
-  Dart_Handle result = Dart_Null();
-  for (int i = 0; i < kNumBuffers; ++i) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    result = Dart_ListGetAt(dart_buffers_object, i);
-    if (Dart_IsError(result)) {
-      break;
-    }
-
-    dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
-    ASSERT(dart_buffer_objects_[i] != NULL);
-    Dart_Handle data =
-        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
-    if (Dart_IsError(data)) {
-      result = data;
-      break;
-    }
-    result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
-    if (Dart_IsError(result)) {
-      break;
-    }
-    result = Dart_SetField(result, data_identifier, data);
-    if (Dart_IsError(result)) {
-      break;
-    }
-  }
-
-  // Caller handles cleanup on an error.
-  return result;
-}
-
-
-void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
-  ASSERT(NULL == handshake_complete_);
-  handshake_complete_ = Dart_NewPersistentHandle(complete);
-  ASSERT(handshake_complete_ != NULL);
-}
-
-
-void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
-  ASSERT(bad_certificate_callback_ != NULL);
-  Dart_DeletePersistentHandle(bad_certificate_callback_);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
-  ASSERT(bad_certificate_callback_ != NULL);
-}
-
-
-Dart_Handle SSLFilter::PeerCertificate() {
-  if (peer_certs_ == NULL) {
-    return Dart_Null();
-  }
-
-  CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, 0);
-  ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
-  SecCertificateRef cert =
-      reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
-  if (cert == NULL) {
-    return Dart_Null();
-  }
-
-  return WrappedX509Certificate(cert);
-}
-
-
-void SSLFilter::Connect(Dart_Handle dart_this,
-                        const char* hostname,
-                        SSLCertContext* context,
-                        bool is_server,
-                        bool request_client_certificate,
-                        bool require_client_certificate) {
-  if (in_handshake_) {
-    FATAL("Connect called twice on the same _SecureFilter.");
-  }
-
-  // Create the underlying context
-  SSLContextRef ssl_context = SSLCreateContext(
-      NULL, is_server ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
-
-  // Configure the context.
-  OSStatus status;
-  status = SSLSetPeerDomainName(ssl_context, hostname, strlen(hostname));
-  CheckStatus(status, "TlsException", "Failed to set peer domain name");
-
-  status = SSLSetIOFuncs(ssl_context, SSLFilter::SSLReadCallback,
-                         SSLFilter::SSLWriteCallback);
-  CheckStatus(status, "TlsException", "Failed to set IO Callbacks");
-
-  status =
-      SSLSetConnection(ssl_context, reinterpret_cast<SSLConnectionRef>(this));
-  CheckStatus(status, "TlsException", "Failed to set connection object");
-
-  // Always evaluate the certs manually so that we can cache the peer
-  // certificates in the context for calls to peerCertificate.
-  status = SSLSetSessionOption(ssl_context, kSSLSessionOptionBreakOnServerAuth,
-                               true);
-  CheckStatus(status, "TlsException", "Failed to set BreakOnServerAuth option");
-
-  status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1);
-  CheckStatus(status, "TlsException",
-              "Failed to set minimum protocol version to kTLSProtocol1");
-
-  // If the context has an identity pass it to SSLSetCertificate().
-  if (context->identity() != NULL) {
-    CFMutableArrayRef chain =
-        CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    CFArrayAppendValue(chain, context->identity());
-
-    // Append the certificate chain if there is one.
-    if (context->cert_chain() != NULL) {
-      // Skip the first one, it's already included in the identity.
-      CFIndex chain_length = CFArrayGetCount(context->cert_chain());
-      if (chain_length > 1) {
-        CFArrayAppendArray(chain, context->cert_chain(),
-                           CFRangeMake(1, chain_length));
-      }
-    }
-
-    status = SSLSetCertificate(ssl_context, chain);
-    CFRelease(chain);
-    CheckStatus(status, "TlsException", "SSLSetCertificate failed");
-  }
-
-  if (is_server) {
-    SSLAuthenticate auth =
-        require_client_certificate
-            ? kAlwaysAuthenticate
-            : (request_client_certificate ? kTryAuthenticate
-                                          : kNeverAuthenticate);
-    status = SSLSetClientSideAuthenticate(ssl_context, auth);
-    CheckStatus(status, "TlsException",
-                "Failed to set client authentication mode");
-
-    // If we're at least trying client authentication, then break handshake
-    // for client authentication.
-    if (auth != kNeverAuthenticate) {
-      status = SSLSetSessionOption(ssl_context,
-                                   kSSLSessionOptionBreakOnClientAuth, true);
-      CheckStatus(status, "TlsException",
-                  "Failed to set client authentication mode");
-    }
-  }
-
-  // Add the contexts to our wrapper.
-  cert_context_.set(context);
-  ssl_context_ = ssl_context;
-  is_server_ = is_server;
-
-  // Kick-off the handshake. Expect the handshake to need more data.
-  // SSLHandshake calls our SSLReadCallback and SSLWriteCallback.
-  status = SSLHandshake(ssl_context);
-  ASSERT(status != noErr);
-  if (status == errSSLWouldBlock) {
-    status = noErr;
-    in_handshake_ = true;
-  }
-  CheckStatus(status, "HandshakeException", is_server_
-                                                ? "Handshake error in server"
-                                                : "Handshake error in client");
-}
-
-
-OSStatus SSLFilter::EvaluatePeerTrust() {
-  OSStatus status = noErr;
-
-  if (SSL_LOG_STATUS) {
-    Log::PrintErr("Handshake evaluating trust.\n");
-  }
-  SecTrustRef peer_trust = NULL;
-  status = SSLCopyPeerTrust(ssl_context_, &peer_trust);
-  if (status != noErr) {
-    if (is_server_ && (status == errSSLBadCert)) {
-      // A client certificate was requested, but not required, and wasn't sent.
-      return noErr;
-    }
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Handshake error from SSLCopyPeerTrust(): %ld.\n",
-                    static_cast<intptr_t>(status));
-    }
-    return status;
-  }
-
-  CFArrayRef trusted_certs = NULL;
-  if (cert_context_.get()->trusted_certs() != NULL) {
-    trusted_certs =
-        CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs());
-  } else {
-    trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
-  }
-
-  status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
-  if (status != noErr) {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
-                    static_cast<intptr_t>(status));
-    }
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  if (SSL_LOG_STATUS) {
-    Log::PrintErr(
-        "Handshake %s built in root certs\n",
-        cert_context_.get()->trust_builtin() ? "trusting" : "not trusting");
-  }
-
-  status = SecTrustSetAnchorCertificatesOnly(
-      peer_trust, !cert_context_.get()->trust_builtin());
-  if (status != noErr) {
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  SecTrustResultType trust_result;
-  status = SecTrustEvaluate(peer_trust, &trust_result);
-  if (status != noErr) {
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  // Grab the peer's certificate chain.
-  CFIndex peer_chain_length = SecTrustGetCertificateCount(peer_trust);
-  CFMutableArrayRef peer_certs =
-      CFArrayCreateMutable(NULL, peer_chain_length, &kCFTypeArrayCallBacks);
-  for (CFIndex i = 0; i < peer_chain_length; ++i) {
-    CFArrayAppendValue(peer_certs,
-                       SecTrustGetCertificateAtIndex(peer_trust, i));
-  }
-  peer_certs_ = peer_certs;
-
-  CFRelease(trusted_certs);
-  CFRelease(peer_trust);
-
-  if ((trust_result == kSecTrustResultProceed) ||
-      (trust_result == kSecTrustResultUnspecified)) {
-    // Trusted.
-    return noErr;
-  } else {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Trust eval failed: trust_result = %d\n", trust_result);
-    }
-    bad_cert_ = true;
-    return errSSLBadCert;
-  }
-}
-
-
-OSStatus SSLFilter::Handshake() {
-  ASSERT(cert_context_.get() != NULL);
-  ASSERT(ssl_context_ != NULL);
-  // Try and push handshake along.
-  if (SSL_LOG_STATUS) {
-    Log::PrintErr("Doing SSLHandshake\n");
-  }
-  OSStatus status = SSLHandshake(ssl_context_);
-  if (SSL_LOG_STATUS) {
-    Log::PrintErr("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
-  }
-
-  if ((status == errSSLServerAuthCompleted) ||
-      (status == errSSLClientAuthCompleted)) {
-    status = EvaluatePeerTrust();
-    if (status == errSSLBadCert) {
-      // Need to invoke the bad certificate callback.
-      return noErr;
-    } else if (status != noErr) {
-      return status;
-    }
-    // When trust evaluation succeeds, we can call SSLHandshake again
-    // immediately.
-    status = SSLHandshake(ssl_context_);
-  }
-
-  if (status == errSSLWouldBlock) {
-    in_handshake_ = true;
-    return noErr;
-  }
-
-  // Handshake succeeded.
-  if ((in_handshake_) && (status == noErr)) {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Finished with the Handshake\n");
-    }
-    connected_ = true;
-  }
-  return status;
-}
-
-
-// Returns false if Handshake should fail, and true if Handshake should
-// proceed.
-Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) {
-  Dart_Handle callback = bad_certificate_callback_;
-  if (Dart_IsNull(callback)) {
-    return callback;
-  }
-  Dart_Handle args[1];
-  args[0] = WrappedX509Certificate(peer_cert);
-  if (Dart_IsError(args[0])) {
-    return args[0];
-  }
-  Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
-  if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
-    result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
-        "HandshakeException",
-        "BadCertificateCallback returned a value that was not a boolean",
-        Dart_Null()));
-  }
-  return result;
-}
-
-
-OSStatus SSLFilter::CheckHandshake() {
-  if (bad_cert_ && in_handshake_) {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Invoking bad certificate callback\n");
-    }
-    ASSERT(peer_certs_ != NULL);
-    CFIndex peer_certs_len = CFArrayGetCount(peer_certs_);
-    ASSERT(peer_certs_len > 0);
-    CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1);
-    ASSERT(item != NULL);
-    ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
-    SecCertificateRef peer_cert =
-        reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
-    Dart_Handle result = InvokeBadCertCallback(peer_cert);
-    ThrowIfError(result);
-    if (Dart_IsNull(result)) {
-      return errSSLBadCert;
-    } else {
-      bool good_cert = DartUtils::GetBooleanValue(result);
-      bad_cert_ = !good_cert;
-      return good_cert ? noErr : errSSLBadCert;
-    }
-  }
-
-  if (connected_ && in_handshake_) {
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("Invoking handshake complete callback\n");
-    }
-    ThrowIfError(Dart_InvokeClosure(
-        Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
-    in_handshake_ = false;
-  }
-  return noErr;
-}
-
-
-void SSLFilter::Renegotiate(bool use_session_cache,
-                            bool request_client_certificate,
-                            bool require_client_certificate) {
-  // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
-  // SSL_REQUEST_CERTIFICATE option is also set, so set it.
-  request_client_certificate =
-      request_client_certificate || require_client_certificate;
-  // TODO(24070, 24069): Implement setting the client certificate parameters,
-  //   and triggering rehandshake.
-}
-
-
-SSLFilter::~SSLFilter() {
-  if (ssl_context_ != NULL) {
-    CFRelease(ssl_context_);
-    ssl_context_ = NULL;
-  }
-  if (peer_certs_ != NULL) {
-    CFRelease(peer_certs_);
-    peer_certs_ = NULL;
-  }
-  if (hostname_ != NULL) {
-    free(hostname_);
-    hostname_ = NULL;
-  }
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (buffers_[i] != NULL) {
-      delete[] buffers_[i];
-      buffers_[i] = NULL;
-    }
-  }
-}
-
-
-void SSLFilter::Destroy() {
-  if (ssl_context_ != NULL) {
-    SSLClose(ssl_context_);
-  }
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (dart_buffer_objects_[i] != NULL) {
-      Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
-      dart_buffer_objects_[i] = NULL;
-    }
-  }
-  if (string_start_ != NULL) {
-    Dart_DeletePersistentHandle(string_start_);
-    string_start_ = NULL;
-  }
-  if (string_length_ != NULL) {
-    Dart_DeletePersistentHandle(string_length_);
-    string_length_ = NULL;
-  }
-  if (handshake_complete_ != NULL) {
-    Dart_DeletePersistentHandle(handshake_complete_);
-    handshake_complete_ = NULL;
-  }
-  if (bad_certificate_callback_ != NULL) {
-    Dart_DeletePersistentHandle(bad_certificate_callback_);
-    bad_certificate_callback_ = NULL;
-  }
-}
-
-
-OSStatus SSLFilter::SSLReadCallback(SSLConnectionRef connection,
-                                    void* data,
-                                    size_t* data_requested) {
-  // Copy at most `data_requested` bytes from `buffers_[kReadEncrypted]` into
-  // `data`
-  ASSERT(connection != NULL);
-  ASSERT(data != NULL);
-  ASSERT(data_requested != NULL);
-
-  SSLFilter* filter =
-      const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
-  uint8_t* datap = reinterpret_cast<uint8_t*>(data);
-  uint8_t* buffer = filter->buffers_[kReadEncrypted];
-  intptr_t start = filter->GetBufferStart(kReadEncrypted);
-  intptr_t end = filter->GetBufferEnd(kReadEncrypted);
-  intptr_t size = filter->encrypted_buffer_size_;
-  intptr_t requested = static_cast<intptr_t>(*data_requested);
-  intptr_t data_read = 0;
-
-  if (end < start) {
-    // Data may be split into two segments.  In this case,
-    // the first is [start, size).
-    intptr_t buffer_end = (start == 0) ? size - 1 : size;
-    intptr_t available = buffer_end - start;
-    intptr_t bytes = requested < available ? requested : available;
-    memmove(datap, &buffer[start], bytes);
-    start += bytes;
-    datap += bytes;
-    data_read += bytes;
-    requested -= bytes;
-    ASSERT(start <= size);
-    if (start == size) {
-      start = 0;
-    }
-  }
-  if ((requested > 0) && (start < end)) {
-    intptr_t available = end - start;
-    intptr_t bytes = requested < available ? requested : available;
-    memmove(datap, &buffer[start], bytes);
-    start += bytes;
-    datap += bytes;
-    data_read += bytes;
-    requested -= bytes;
-    ASSERT(start <= end);
-  }
-
-  if (SSL_LOG_DATA) {
-    Log::PrintErr("SSLReadCallback: requested: %ld, read %ld bytes\n",
-                  *data_requested, data_read);
-  }
-
-  filter->SetBufferStart(kReadEncrypted, start);
-  bool short_read = data_read < static_cast<intptr_t>(*data_requested);
-  *data_requested = data_read;
-  return short_read ? errSSLWouldBlock : noErr;
-}
-
-
-// Read decrypted data from the filter to the circular buffer.
-OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start,
-                                               intptr_t end,
-                                               intptr_t* bytes_processed) {
-  ASSERT(bytes_processed != NULL);
-  intptr_t length = end - start;
-  OSStatus status = noErr;
-  size_t bytes = 0;
-  if (length > 0) {
-    status =
-        SSLRead(ssl_context_,
-                reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)),
-                length, &bytes);
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("SSLRead: status = %ld\n", static_cast<intptr_t>(status));
-    }
-    if ((status != noErr) && (status != errSSLWouldBlock)) {
-      *bytes_processed = 0;
-      return status;
-    }
-  }
-  if (SSL_LOG_DATA) {
-    Log::PrintErr(
-        "ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n", length,
-        bytes);
-  }
-  *bytes_processed = static_cast<intptr_t>(bytes);
-  return status;
-}
-
-
-OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection,
-                                     const void* data,
-                                     size_t* data_provided) {
-  // Copy at most `data_provided` bytes from data into
-  // `buffers_[kWriteEncrypted]`.
-  ASSERT(connection != NULL);
-  ASSERT(data != NULL);
-  ASSERT(data_provided != NULL);
-
-  SSLFilter* filter =
-      const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
-  const uint8_t* datap = reinterpret_cast<const uint8_t*>(data);
-  uint8_t* buffer = filter->buffers_[kWriteEncrypted];
-  intptr_t start = filter->GetBufferStart(kWriteEncrypted);
-  intptr_t end = filter->GetBufferEnd(kWriteEncrypted);
-  intptr_t size = filter->encrypted_buffer_size_;
-  intptr_t provided = static_cast<intptr_t>(*data_provided);
-  intptr_t data_written = 0;
-
-  // is full, neither if statement is executed and nothing happens.
-  if (start <= end) {
-    // If the free space may be split into two segments,
-    // then the first is [end, size), unless start == 0.
-    // Then, since the last free byte is at position start - 2,
-    // the interval is [end, size - 1).
-    intptr_t buffer_end = (start == 0) ? size - 1 : size;
-    intptr_t available = buffer_end - end;
-    intptr_t bytes = provided < available ? provided : available;
-    memmove(&buffer[end], datap, bytes);
-    end += bytes;
-    datap += bytes;
-    data_written += bytes;
-    provided -= bytes;
-    ASSERT(end <= size);
-    if (end == size) {
-      end = 0;
-    }
-  }
-  if ((provided > 0) && (start > end + 1)) {
-    intptr_t available = (start - 1) - end;
-    intptr_t bytes = provided < available ? provided : available;
-    memmove(&buffer[end], datap, bytes);
-    end += bytes;
-    datap += bytes;
-    data_written += bytes;
-    provided -= bytes;
-    ASSERT(end < start);
-  }
-
-  if (SSL_LOG_DATA) {
-    Log::PrintErr("SSLWriteCallback: provided: %ld, written %ld bytes\n",
-                  *data_provided, data_written);
-  }
-
-  filter->SetBufferEnd(kWriteEncrypted, end);
-  *data_provided = data_written;
-  return (data_written == 0) ? errSSLWouldBlock : noErr;
-}
-
-
-OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start,
-                                                intptr_t end,
-                                                intptr_t* bytes_processed) {
-  ASSERT(bytes_processed != NULL);
-  intptr_t length = end - start;
-  OSStatus status = noErr;
-  size_t bytes = 0;
-  if (length > 0) {
-    status =
-        SSLWrite(ssl_context_,
-                 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start),
-                 length, &bytes);
-    if (SSL_LOG_STATUS) {
-      Log::PrintErr("SSLWrite: status = %ld\n", static_cast<intptr_t>(status));
-    }
-    if ((status != noErr) && (status != errSSLWouldBlock)) {
-      *bytes_processed = 0;
-      return status;
-    }
-  }
-  if (SSL_LOG_DATA) {
-    Log::PrintErr("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n",
-                  length, bytes);
-  }
-  *bytes_processed = static_cast<intptr_t>(bytes);
-  return status;
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // HOST_OS_IOS
-
-#endif  // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/secure_socket_ios.h b/runtime/bin/secure_socket_ios.h
deleted file mode 100644
index 8a59cb7..0000000
--- a/runtime/bin/secure_socket_ios.h
+++ /dev/null
@@ -1,239 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_BIN_SECURE_SOCKET_IOS_H_
-#define RUNTIME_BIN_SECURE_SOCKET_IOS_H_
-
-#if !defined(RUNTIME_BIN_SECURE_SOCKET_H_)
-#error Do not include secure_socket_macos.h directly. Use secure_socket.h.
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/lockers.h"
-#include "bin/reference_counting.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-namespace dart {
-namespace bin {
-
-// SSLCertContext wraps the certificates needed for a SecureTransport
-// connection. Fields are protected by the mutex_ field, and may only be set
-// once. This is to allow access by both the Dart thread and the IOService
-// thread. Setters return false if the field was already set.
-class SSLCertContext : public ReferenceCounted<SSLCertContext> {
- public:
-  SSLCertContext()
-      : ReferenceCounted(),
-        mutex_(new Mutex()),
-        trusted_certs_(NULL),
-        identity_(NULL),
-        cert_chain_(NULL),
-        trust_builtin_(false) {}
-
-  ~SSLCertContext() {
-    {
-      MutexLocker m(mutex_);
-      if (trusted_certs_ != NULL) {
-        CFRelease(trusted_certs_);
-      }
-      if (identity_ != NULL) {
-        CFRelease(identity_);
-      }
-      if (cert_chain_ != NULL) {
-        CFRelease(cert_chain_);
-      }
-    }
-    delete mutex_;
-  }
-
-  CFMutableArrayRef trusted_certs() {
-    MutexLocker m(mutex_);
-    return trusted_certs_;
-  }
-  void add_trusted_cert(SecCertificateRef trusted_cert) {
-    // Takes ownership of trusted_cert.
-    MutexLocker m(mutex_);
-    if (trusted_certs_ == NULL) {
-      trusted_certs_ = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-    }
-    CFArrayAppendValue(trusted_certs_, trusted_cert);
-    CFRelease(trusted_cert);  // trusted_cert is retained by the array.
-  }
-
-  SecIdentityRef identity() {
-    MutexLocker m(mutex_);
-    return identity_;
-  }
-  bool set_identity(SecIdentityRef identity) {
-    MutexLocker m(mutex_);
-    if (identity_ == NULL) {
-      identity_ = identity;
-      return true;
-    }
-    return false;
-  }
-
-  CFArrayRef cert_chain() {
-    MutexLocker m(mutex_);
-    return cert_chain_;
-  }
-  bool set_cert_chain(CFArrayRef cert_chain) {
-    MutexLocker m(mutex_);
-    if (cert_chain_ == NULL) {
-      cert_chain_ = cert_chain;
-      return true;
-    }
-    return false;
-  }
-
-  bool trust_builtin() {
-    MutexLocker m(mutex_);
-    return trust_builtin_;
-  }
-  void set_trust_builtin(bool trust_builtin) {
-    MutexLocker m(mutex_);
-    trust_builtin_ = trust_builtin;
-  }
-
- private:
-  // The context is accessed both by Dart code and the IOService. This mutex
-  // protects all fields.
-  Mutex* mutex_;
-  CFMutableArrayRef trusted_certs_;
-  SecIdentityRef identity_;
-  CFArrayRef cert_chain_;
-  bool trust_builtin_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
-};
-
-// SSLFilter encapsulates the SecureTransport code in a filter that communicates
-// with the containing _SecureFilterImpl Dart object through four shared
-// ExternalByteArray buffers, for reading and writing plaintext, and
-// reading and writing encrypted text.  The filter handles handshaking
-// and certificate verification.
-class SSLFilter : public ReferenceCounted<SSLFilter> {
- public:
-  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
-  enum BufferIndex {
-    kReadPlaintext,
-    kWritePlaintext,
-    kReadEncrypted,
-    kWriteEncrypted,
-    kNumBuffers,
-    kFirstEncrypted = kReadEncrypted
-  };
-
-  SSLFilter()
-      : ReferenceCounted(),
-        cert_context_(NULL),
-        ssl_context_(NULL),
-        peer_certs_(NULL),
-        string_start_(NULL),
-        string_length_(NULL),
-        handshake_complete_(NULL),
-        bad_certificate_callback_(NULL),
-        in_handshake_(false),
-        connected_(false),
-        bad_cert_(false),
-        is_server_(false),
-        hostname_(NULL) {}
-
-  ~SSLFilter();
-
-  // Callback called by the IOService.
-  static CObject* ProcessFilterRequest(const CObjectArray& request);
-
-  Dart_Handle Init(Dart_Handle dart_this);
-  void Connect(Dart_Handle dart_this,
-               const char* hostname,
-               SSLCertContext* context,
-               bool is_server,
-               bool request_client_certificate,
-               bool require_client_certificate);
-  void Destroy();
-  OSStatus CheckHandshake();
-  void Renegotiate(bool use_session_cache,
-                   bool request_client_certificate,
-                   bool require_client_certificate);
-  void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
-  void RegisterBadCertificateCallback(Dart_Handle callback);
-  Dart_Handle PeerCertificate();
-
- private:
-  static OSStatus SSLReadCallback(SSLConnectionRef connection,
-                                  void* data,
-                                  size_t* data_length);
-  static OSStatus SSLWriteCallback(SSLConnectionRef connection,
-                                   const void* data,
-                                   size_t* data_length);
-
-  static bool isBufferEncrypted(intptr_t i) {
-    return static_cast<BufferIndex>(i) >= kFirstEncrypted;
-  }
-  Dart_Handle InitializeBuffers(Dart_Handle dart_this);
-
-  intptr_t GetBufferStart(intptr_t idx) const;
-  intptr_t GetBufferEnd(intptr_t idx) const;
-  void SetBufferStart(intptr_t idx, intptr_t value);
-  void SetBufferEnd(intptr_t idx, intptr_t value);
-
-  OSStatus ProcessAllBuffers(intptr_t starts[kNumBuffers],
-                             intptr_t ends[kNumBuffers],
-                             bool in_handshake);
-  OSStatus ProcessReadPlaintextBuffer(intptr_t start,
-                                      intptr_t end,
-                                      intptr_t* bytes_processed);
-  OSStatus ProcessWritePlaintextBuffer(intptr_t start,
-                                       intptr_t end,
-                                       intptr_t* bytes_processed);
-
-  // These calls can block on IO, and should only be invoked from
-  // from ProcessAllBuffers from ProcessFilterRequest.
-  OSStatus EvaluatePeerTrust();
-  OSStatus Handshake();
-  Dart_Handle InvokeBadCertCallback(SecCertificateRef peer_cert);
-
-  RetainedPointer<SSLCertContext> cert_context_;
-  SSLContextRef ssl_context_;
-  CFArrayRef peer_certs_;
-
-  // starts and ends filled in at the start of ProcessAllBuffers.
-  // If these are NULL, then try to get the pointers out of
-  // dart_buffer_objects_.
-  uint8_t* buffers_[kNumBuffers];
-  intptr_t* buffer_starts_[kNumBuffers];
-  intptr_t* buffer_ends_[kNumBuffers];
-  intptr_t buffer_size_;
-  intptr_t encrypted_buffer_size_;
-  Dart_PersistentHandle string_start_;
-  Dart_PersistentHandle string_length_;
-  Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
-  Dart_PersistentHandle handshake_complete_;
-  Dart_PersistentHandle bad_certificate_callback_;
-  bool in_handshake_;
-  bool connected_;
-  bool bad_cert_;
-  bool is_server_;
-  char* hostname_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
-};
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // RUNTIME_BIN_SECURE_SOCKET_IOS_H_
diff --git a/runtime/bin/secure_socket_macos.cc b/runtime/bin/secure_socket_macos.cc
deleted file mode 100644
index 520f2c9..0000000
--- a/runtime/bin/secure_socket_macos.cc
+++ /dev/null
@@ -1,1815 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
-
-#include "platform/globals.h"
-#if defined(HOST_OS_MACOS) && !HOST_OS_IOS
-
-#include "bin/secure_socket.h"
-#include "bin/secure_socket_macos.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/lockers.h"
-#include "bin/log.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-#include "platform/text_buffer.h"
-#include "platform/utils.h"
-
-#include "include/dart_api.h"
-
-// Return the error from the containing function if handle is an error handle.
-#define RETURN_IF_ERROR(handle)                                                \
-  {                                                                            \
-    Dart_Handle __handle = handle;                                             \
-    if (Dart_IsError((__handle))) {                                            \
-      return __handle;                                                         \
-    }                                                                          \
-  }
-
-// We need to access this private API function to create a SecIdentityRef
-// without writing a custom keychain to the filesystem. This is the approach
-// taken in WebKit:
-// https://webkit.googlesource.com/WebKit/+/master/Source/WebKit2/Shared/cf/ArgumentCodersCF.cpp
-extern "C" {
-SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator,
-                                 SecCertificateRef certificate,
-                                 SecKeyRef private_key);
-}
-
-namespace dart {
-namespace bin {
-
-static const int kSSLFilterNativeFieldIndex = 0;
-static const int kSecurityContextNativeFieldIndex = 0;
-static const int kX509NativeFieldIndex = 0;
-
-static const bool SSL_LOG_STATUS = false;
-static const bool SSL_LOG_DATA = false;
-static const bool SSL_LOG_CERTS = false;
-static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
-static const intptr_t PEM_BUFSIZE = 1024;
-
-static char* CFStringRefToCString(CFStringRef cfstring) {
-  CFIndex len = CFStringGetLength(cfstring);
-  CFIndex max_len =
-      CFStringGetMaximumSizeForEncoding(len, kCFStringEncodingUTF8) + 1;
-  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(max_len));
-  ASSERT(result != NULL);
-  bool success =
-      CFStringGetCString(cfstring, result, max_len, kCFStringEncodingUTF8);
-  return success ? result : NULL;
-}
-
-
-// Handle an error reported from the SecureTransport library.
-static void ThrowIOException(OSStatus status,
-                             const char* exception_type,
-                             const char* message) {
-  TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-  CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
-  if (error_string == NULL) {
-    status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
-                          static_cast<intptr_t>(status));
-  } else {
-    char* error = CFStringRefToCString(error_string);
-    status_message.Printf("OSStatus = %ld: %s", static_cast<intptr_t>(status),
-                          error);
-    CFRelease(error_string);
-  }
-  OSError os_error_struct(status, status_message.buf(), OSError::kBoringSSL);
-  Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
-  Dart_Handle exception =
-      DartUtils::NewDartIOException(exception_type, message, os_error);
-  ASSERT(!Dart_IsError(exception));
-  Dart_ThrowException(exception);
-  UNREACHABLE();
-}
-
-
-static void CheckStatus(OSStatus status,
-                        const char* type,
-                        const char* message) {
-  if (status == noErr) {
-    return;
-  }
-  ThrowIOException(status, type, message);
-}
-
-
-static SSLFilter* GetFilter(Dart_NativeArguments args) {
-  SSLFilter* filter;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&filter)));
-  return filter;
-}
-
-
-static void DeleteFilter(void* isolate_data,
-                         Dart_WeakPersistentHandle handle,
-                         void* context_pointer) {
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(context_pointer);
-  filter->Release();
-}
-
-
-static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
-  ASSERT(filter != NULL);
-  const int approximate_size_of_filter = 1500;
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSSLFilterNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(filter));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, reinterpret_cast<void*>(filter),
-                               approximate_size_of_filter, DeleteFilter);
-  return Dart_Null();
-}
-
-
-static SSLCertContext* GetSecurityContext(Dart_NativeArguments args) {
-  SSLCertContext* context;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&context)));
-  return context;
-}
-
-
-static void DeleteCertContext(void* isolate_data,
-                              Dart_WeakPersistentHandle handle,
-                              void* context_pointer) {
-  SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
-  context->Release();
-}
-
-
-static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
-                                      SSLCertContext* context) {
-  const int approximate_size_of_context = 1500;
-  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
-  RETURN_IF_ERROR(dart_this);
-  ASSERT(Dart_IsInstance(dart_this));
-  Dart_Handle err =
-      Dart_SetNativeInstanceField(dart_this, kSecurityContextNativeFieldIndex,
-                                  reinterpret_cast<intptr_t>(context));
-  RETURN_IF_ERROR(err);
-  Dart_NewWeakPersistentHandle(dart_this, context, approximate_size_of_context,
-                               DeleteCertContext);
-  return Dart_Null();
-}
-
-
-static SecCertificateRef GetX509Certificate(Dart_NativeArguments args) {
-  SecCertificateRef certificate;
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  ASSERT(Dart_IsInstance(dart_this));
-  ThrowIfError(
-      Dart_GetNativeInstanceField(dart_this, kX509NativeFieldIndex,
-                                  reinterpret_cast<intptr_t*>(&certificate)));
-  return certificate;
-}
-
-
-static void ReleaseCertificate(void* isolate_data,
-                               Dart_WeakPersistentHandle handle,
-                               void* context_pointer) {
-  SecCertificateRef cert = reinterpret_cast<SecCertificateRef>(context_pointer);
-  CFRelease(cert);
-}
-
-
-static Dart_Handle WrappedX509Certificate(SecCertificateRef certificate) {
-  const intptr_t approximate_size_of_certificate = 1500;
-  if (certificate == NULL) {
-    return Dart_Null();
-  }
-  Dart_Handle x509_type =
-      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
-  if (Dart_IsError(x509_type)) {
-    return x509_type;
-  }
-  Dart_Handle arguments[] = {NULL};
-
-  Dart_Handle result =
-      Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  ASSERT(Dart_IsInstance(result));
-
-  // CFRetain in case the returned Dart object outlives the SecurityContext.
-  // CFRelease is in the Dart object's finalizer
-  CFRetain(certificate);
-  Dart_NewWeakPersistentHandle(result, reinterpret_cast<void*>(certificate),
-                               approximate_size_of_certificate,
-                               ReleaseCertificate);
-
-  Dart_Handle status = Dart_SetNativeInstanceField(
-      result, kX509NativeFieldIndex, reinterpret_cast<intptr_t>(certificate));
-  if (Dart_IsError(status)) {
-    return status;
-  }
-  return result;
-}
-
-
-static const char* GetPasswordArgument(Dart_NativeArguments args,
-                                       intptr_t index) {
-  Dart_Handle password_object =
-      ThrowIfError(Dart_GetNativeArgument(args, index));
-  const char* password = NULL;
-  if (Dart_IsString(password_object)) {
-    ThrowIfError(Dart_StringToCString(password_object, &password));
-    if (strlen(password) > PEM_BUFSIZE - 1) {
-      Dart_ThrowException(DartUtils::NewDartArgumentError(
-          "Password length is greater than 1023 bytes."));
-    }
-  } else if (Dart_IsNull(password_object)) {
-    password = "";
-  } else {
-    Dart_ThrowException(
-        DartUtils::NewDartArgumentError("Password is not a String or null"));
-  }
-  return password;
-}
-
-
-static OSStatus GetKeyAndCerts(CFArrayRef items,
-                               CFIndex items_length,
-                               CFArrayRef* out_certs,
-                               SecKeyRef* out_key) {
-  OSStatus status = noErr;
-
-  // Loop through the items, take only the first private key/identity, ignore
-  // any others, populate out_certs.
-  CFMutableArrayRef certs =
-      CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-  SecKeyRef key = NULL;
-
-  for (CFIndex i = 0; i < items_length; ++i) {
-    CFTypeRef item =
-        reinterpret_cast<CFTypeRef>(CFArrayGetValueAtIndex(items, i));
-    CFTypeID item_type = CFGetTypeID(item);
-    if (item_type == SecCertificateGetTypeID()) {
-      if (SSL_LOG_CERTS) {
-        Log::Print("\titem %ld: Certificate\n", i);
-      }
-      CFArrayAppendValue(certs, item);
-    } else if ((item_type == SecKeyGetTypeID()) && (key == NULL)) {
-      if (SSL_LOG_CERTS) {
-        Log::Print("\titem %ld: Key\n", i);
-      }
-      key = reinterpret_cast<SecKeyRef>(const_cast<void*>(item));
-      CFRetain(key);
-    } else if ((item_type == SecIdentityGetTypeID()) && (key == NULL)) {
-      if (SSL_LOG_CERTS) {
-        Log::Print("\titem %ld: Identity\n", i);
-      }
-      SecIdentityRef identity =
-          reinterpret_cast<SecIdentityRef>(const_cast<void*>(item));
-      SecCertificateRef cert = NULL;
-
-      status = SecIdentityCopyPrivateKey(identity, &key);
-      if (status != noErr) {
-        CFRelease(certs);
-        return status;
-      }
-
-      status = SecIdentityCopyCertificate(identity, &cert);
-      if (status != noErr) {
-        CFRelease(key);
-        CFRelease(certs);
-        return status;
-      }
-      CFArrayAppendValue(certs, cert);
-      CFRelease(cert);
-    }
-    // Other item types are ignored.
-  }
-
-  if (out_key == NULL) {
-    if (key != NULL) {
-      CFRelease(key);
-    }
-  } else {
-    *out_key = key;
-  }
-
-  if (out_certs == NULL) {
-    if (certs != NULL) {
-      CFRelease(certs);
-    }
-  } else {
-    *out_certs = certs;
-  }
-  return status;
-}
-
-
-static OSStatus TryPEMImport(CFDataRef cfdata,
-                             CFStringRef password,
-                             CFArrayRef* out_certs,
-                             SecKeyRef* out_key) {
-  OSStatus status = noErr;
-
-  SecExternalFormat format = kSecFormatPEMSequence;
-  SecExternalItemType sitem_type = kSecItemTypeAggregate;
-
-  SecItemImportExportKeyParameters params;
-  memset(&params, 0, sizeof(params));
-  params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
-  params.flags = kSecKeyNoAccessControl;
-  params.passphrase = password;
-
-  CFArrayRef items = NULL;
-  status = SecItemImport(cfdata, NULL, &format, &sitem_type, 0, &params, NULL,
-                         &items);
-
-  if (status != noErr) {
-    if (SSL_LOG_CERTS) {
-      Log::Print("TrySecItemImport failed with: %ld, type = %d, format = %d\n",
-                 static_cast<intptr_t>(status), sitem_type, format);
-    }
-    return status;
-  }
-
-  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
-  if (SSL_LOG_CERTS) {
-    Log::Print(
-        "TrySecItemImport succeeded, type = %d, format = %d, count = %ld\n",
-        sitem_type, format, items_length);
-  }
-
-  // Empty list indicates a decoding failure of some sort.
-  if ((items != NULL) && (items_length == 0)) {
-    CFRelease(items);
-    return errSSLBadCert;
-  }
-
-  status = GetKeyAndCerts(items, items_length, out_certs, out_key);
-  CFRelease(items);
-  return status;
-}
-
-
-static char* TempKeychainPath() {
-  const char* exes = "keychaindir.XXXX";
-  const char* fname = "keychain";
-  const char* temp_dir = getenv("TMPDIR");
-  if (temp_dir == NULL) {
-    temp_dir = getenv("TMP");
-  }
-  if (temp_dir == NULL) {
-    temp_dir = "/tmp/";
-  }
-  ASSERT(temp_dir != NULL);
-
-  TextBuffer path(PATH_MAX);
-  path.Printf("%s/%s", temp_dir, exes);
-  char* ret = mkdtemp(path.buf());
-  ASSERT(ret != NULL);
-  path.Printf("/%s", fname);
-
-  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(path.length() + 1));
-  return strncpy(result, path.buf(), path.length() + 1);
-}
-
-
-static OSStatus CreateKeychain(SecKeychainRef* keychain) {
-  ASSERT(keychain != NULL);
-  OSStatus status = noErr;
-  const char* temp_keychain_pwd = "dartdart";
-  char* temp_file_path = TempKeychainPath();
-  ASSERT(temp_file_path != NULL);
-  if (SSL_LOG_CERTS) {
-    Log::Print("Temporary keychain at: '%s'\n", temp_file_path);
-  }
-  status = SecKeychainCreate(temp_file_path, strlen(temp_keychain_pwd) + 1,
-                             reinterpret_cast<const void*>(temp_keychain_pwd),
-                             FALSE,  // Prompt user? Definitely no.
-                             NULL,   // Default access rights.
-                             keychain);
-  if (status != noErr) {
-    return status;
-  }
-  ASSERT(*keychain != NULL);
-  return status;
-}
-
-
-static OSStatus TryPKCS12Import(CFDataRef cfdata,
-                                CFStringRef password,
-                                CFArrayRef* out_certs,
-                                SecKeyRef* out_key,
-                                SecKeychainRef* out_keychain) {
-  OSStatus status = noErr;
-
-  SecExternalFormat format = kSecFormatPKCS12;
-  SecExternalItemType sitem_type = kSecItemTypeAggregate;
-
-  SecItemImportExportKeyParameters params;
-  memset(&params, 0, sizeof(params));
-  params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
-  params.flags = kSecKeyNoAccessControl;
-  params.passphrase = password;
-
-  CFArrayRef items = NULL;
-  if (SSL_LOG_CERTS) {
-    Log::Print("Trying PKCS12 import with: type = %d, format = %d\n",
-               sitem_type, format);
-  }
-
-  // The documentation for SecKeychainItemImport here:
-  //
-  // https://developer.apple.com/library/mac/documentation/Security/Reference/keychainservices/index.html
-  //
-  // states that when the SecKeychainRef argument is NULL, the CFArrayRef*
-  // argument will be populated by an array containing all keys, identities,
-  // and certificates from the data in the CFDataRef argument.
-  //
-  // Unfortunately, this is not true. The code to populate the CFArrayRef with
-  // keys and identities from PKCS12 data has been skipped and/or commented out,
-  // here:
-  //
-  // https://github.com/Apple-FOSS-Mirror/Security/blob/master/libsecurity_keychain/lib/SecImportExportAgg.cpp#L636
-  //
-  // as "floating" SecKeyRefs from the PKCS12 decoder haven't been implemented.
-  // That is, each private key instance coming from the PKCS12 decoder has to be
-  // associated with a keychain instance. Thus, as a workaround, we create a
-  // temporary keychain here if one is needed, and stash it below in a
-  // SecurityContext. This has the drawbacks:
-  // 1.) We need to make a temporary directory to hold the keychain file, and
-  // 2.) SecKeychainItemImport() probably does blocking IO to create and
-  //     manipulate the keychain file.
-  // So if the API is updated, this keychain should not be used.
-  SecKeychainRef keychain = NULL;
-  if (out_key != NULL) {
-    ASSERT(out_keychain != NULL);
-    status = CreateKeychain(&keychain);
-    if (status != noErr) {
-      return status;
-    }
-    *out_keychain = keychain;
-  }
-
-  status = SecItemImport(cfdata, NULL, &format, &sitem_type, 0, &params,
-                         keychain, &items);
-  if (status != noErr) {
-    if (SSL_LOG_CERTS) {
-      Log::Print("TrySecItemImport failed with: %ld, it = %d, format = %d\n",
-                 static_cast<intptr_t>(status), sitem_type, format);
-    }
-    return status;
-  }
-
-  CFIndex items_length = (items == NULL) ? 0 : CFArrayGetCount(items);
-  if (SSL_LOG_CERTS) {
-    Log::Print("TrySecItemImport succeeded, count = %ld\n", items_length);
-  }
-
-  // Empty list indicates a decoding failure of some sort.
-  if ((items != NULL) && (items_length == 0)) {
-    CFRelease(items);
-    return errSSLBadCert;
-  }
-
-  status = GetKeyAndCerts(items, items_length, out_certs, out_key);
-  CFRelease(items);
-  return status;
-}
-
-
-static OSStatus ExtractSecItems(uint8_t* buffer,
-                                intptr_t length,
-                                const char* password,
-                                CFArrayRef* out_certs,
-                                SecKeyRef* out_key,
-                                SecKeychainRef* out_keychain) {
-  ASSERT(buffer != NULL);
-  ASSERT(password != NULL);
-  OSStatus status = noErr;
-
-  CFDataRef cfdata =
-      CFDataCreateWithBytesNoCopy(NULL, buffer, length, kCFAllocatorNull);
-  CFStringRef cfpassword = CFStringCreateWithCStringNoCopy(
-      NULL, password, kCFStringEncodingUTF8, kCFAllocatorNull);
-  ASSERT(cfdata != NULL);
-  ASSERT(cfpassword != NULL);
-
-  status = TryPEMImport(cfdata, cfpassword, out_certs, out_key);
-  if (status != noErr) {
-    status =
-        TryPKCS12Import(cfdata, cfpassword, out_certs, out_key, out_keychain);
-  }
-
-  CFRelease(cfdata);
-  CFRelease(cfpassword);
-  return status;
-}
-
-
-void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  SSLFilter* filter = new SSLFilter();  // Deleted in DeleteFilter finalizer.
-  Dart_Handle err = SetFilter(args, filter);
-  if (Dart_IsError(err)) {
-    filter->Release();
-    Dart_PropagateError(err);
-  }
-  err = filter->Init(dart_this);
-  if (Dart_IsError(err)) {
-    // The finalizer was set up by SetFilter. It will delete `filter` if there
-    // is an error.
-    filter->Destroy();
-    Dart_PropagateError(err);
-  }
-}
-
-
-void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
-  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
-  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  Dart_Handle context_object = ThrowIfError(Dart_GetNativeArgument(args, 2));
-  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 5));
-
-  const char* host_name = NULL;
-  // TODO(whesse): Is truncating a Dart string containing \0 what we want?
-  ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
-
-  SSLCertContext* context = NULL;
-  if (!Dart_IsNull(context_object)) {
-    ThrowIfError(Dart_GetNativeInstanceField(
-        context_object, kSecurityContextNativeFieldIndex,
-        reinterpret_cast<intptr_t*>(&context)));
-  }
-
-  GetFilter(args)->Connect(dart_this, host_name, context, is_server,
-                           request_client_certificate,
-                           require_client_certificate);
-}
-
-
-void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // The SSLFilter is deleted in the finalizer for the Dart object created by
-  // SetFilter. There is no need to NULL-out the native field for the SSLFilter
-  // here because the SSLFilter won't be deleted until the finalizer for the
-  // Dart object runs while the Dart object is being GCd. This approach avoids a
-  // leak if Destroy isn't called, and avoids a NULL-dereference if Destroy is
-  // called more than once.
-  filter->Destroy();
-}
-
-
-void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
-  OSStatus status = GetFilter(args)->CheckHandshake();
-  CheckStatus(status, "HandshakeException", "Handshake error");
-}
-
-
-void FUNCTION_NAME(SecureSocket_GetSelectedProtocol)(
-    Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, Dart_Null());
-}
-
-
-void FUNCTION_NAME(SecureSocket_Renegotiate)(Dart_NativeArguments args) {
-  bool use_session_cache =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 1));
-  bool request_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 2));
-  bool require_client_certificate =
-      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 3));
-  GetFilter(args)->Renegotiate(use_session_cache, request_client_certificate,
-                               require_client_certificate);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterHandshakeCompleteCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle handshake_complete =
-      ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(handshake_complete)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterHandshakeCompleteCallback"));
-  }
-  GetFilter(args)->RegisterHandshakeCompleteCallback(handshake_complete);
-}
-
-
-void FUNCTION_NAME(SecureSocket_RegisterBadCertificateCallback)(
-    Dart_NativeArguments args) {
-  Dart_Handle callback = ThrowIfError(Dart_GetNativeArgument(args, 1));
-  if (!Dart_IsClosure(callback) && !Dart_IsNull(callback)) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "Illegal argument to RegisterBadCertificateCallback"));
-  }
-  GetFilter(args)->RegisterBadCertificateCallback(callback);
-}
-
-
-void FUNCTION_NAME(SecureSocket_PeerCertificate)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
-}
-
-
-void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
-  SSLFilter* filter = GetFilter(args);
-  // This filter pointer is passed to the IO Service thread. The IO Service
-  // thread must Release() the pointer when it is done with it.
-  filter->Retain();
-  intptr_t filter_pointer = reinterpret_cast<intptr_t>(filter);
-  Dart_SetReturnValue(args, Dart_NewInteger(filter_pointer));
-}
-
-
-void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
-  SSLCertContext* cert_context = new SSLCertContext();
-  // cert_context deleted in DeleteCertContext finalizer.
-  Dart_Handle err = SetSecurityContext(args, cert_context);
-  if (Dart_IsError(err)) {
-    cert_context->Release();
-    Dart_PropagateError(err);
-  }
-}
-
-
-void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  OSStatus status;
-  SecKeyRef key = NULL;
-  SecKeychainRef keychain = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = ExtractSecItems(buffer.get(), buffer.length(), password, NULL,
-                             &key, &keychain);
-  }
-
-  // Set the context fields. If there's a failure, release the items.
-  bool set_failure = false;
-  if ((key != NULL) && !context->set_private_key(key)) {
-    CFRelease(key);
-    SecKeychainDelete(keychain);
-    CFRelease(keychain);
-    set_failure = true;
-  }
-  if (!set_failure && (keychain != NULL) && !context->set_keychain(keychain)) {
-    SecKeychainDelete(keychain);
-    CFRelease(keychain);
-  }
-
-  if (set_failure) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "usePrivateKeyBytes has already been called on the given context."));
-  }
-  CheckStatus(status, "TlsException", "Failure in usePrivateKeyBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  OSStatus status;
-  CFArrayRef certs = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = ExtractSecItems(buffer.get(), buffer.length(), password, &certs,
-                             NULL, NULL);
-  }
-
-  // Set the field in the context. If there's a failure, release the certs,
-  // and throw an exception.
-  if ((certs != NULL) && !context->set_trusted_certs(certs)) {
-    CFRelease(certs);
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "setTrustedCertificatesBytes has already been called "
-        "on the given context."));
-  }
-
-  CheckStatus(status, "TlsException", "Failure in setTrustedCertificatesBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
-  Dart_SetReturnValue(args, Dart_NewBoolean(false));
-}
-
-
-void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  context->set_trust_builtin(true);
-}
-
-
-void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-
-  const char* password = GetPasswordArgument(args, 2);
-  OSStatus status;
-  CFArrayRef certs = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = ExtractSecItems(buffer.get(), buffer.length(), password, &certs,
-                             NULL, NULL);
-  }
-
-  // Set the field in the context. If there's a failure, release the certs,
-  // and throw an exception.
-  if ((certs != NULL) && !context->set_cert_chain(certs)) {
-    CFRelease(certs);
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "useCertificateChainBytes has already been called "
-        "on the given context."));
-  }
-
-  CheckStatus(status, "TlsException", "Failure in useCertificateChainBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
-    Dart_NativeArguments args) {
-  SSLCertContext* context = GetSecurityContext(args);
-  const char* password = GetPasswordArgument(args, 2);
-
-  OSStatus status;
-  CFArrayRef certs = NULL;
-  {
-    ScopedMemBuffer buffer(ThrowIfError(Dart_GetNativeArgument(args, 1)));
-    status = ExtractSecItems(buffer.get(), buffer.length(), password, &certs,
-                             NULL, NULL);
-  }
-
-  // Set the field in the context. If there's a failure, release the certs,
-  // and throw an exception.
-  if ((certs != NULL) && !context->set_cert_authorities(certs)) {
-    CFRelease(certs);
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "setClientAuthoritiesBytes has already been called "
-        "on the given context."));
-  }
-
-  CheckStatus(status, "TlsException", "Failure in setClientAuthoritiesBytes");
-}
-
-
-void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
-    Dart_NativeArguments args) {
-  Dart_ThrowException(DartUtils::NewDartUnsupportedError(
-      "ALPN is not supported on this platform"));
-}
-
-
-static char* GetNameFromCert(SecCertificateRef certificate,
-                             CFTypeRef field,
-                             CFStringRef name) {
-  char* issuer_name = NULL;
-
-  CFTypeRef keys[] = {field};
-  CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
-  CFErrorRef error = NULL;
-  CFDictionaryRef cert_dict =
-      SecCertificateCopyValues(certificate, key_array, &error);
-  if (cert_dict == NULL) {
-    CFRelease(key_array);
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.issuer failed to copy issuer field out of certificate"));
-  }
-
-  CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
-  ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
-  CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
-
-  item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
-  ASSERT(CFGetTypeID(item) == CFArrayGetTypeID());
-  CFArrayRef val_array = reinterpret_cast<CFArrayRef>(item);
-
-  for (intptr_t i = 0; i < CFArrayGetCount(val_array); i++) {
-    item = CFArrayGetValueAtIndex(val_array, i);
-    ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
-    CFDictionaryRef val_dict2 = reinterpret_cast<CFDictionaryRef>(item);
-
-    item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyLabel);
-    ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
-    CFStringRef label = reinterpret_cast<CFStringRef>(item);
-
-    if (CFStringCompare(label, name, 0) == kCFCompareEqualTo) {
-      item = CFDictionaryGetValue(val_dict2, kSecPropertyKeyValue);
-      ASSERT(CFGetTypeID(item) == CFStringGetTypeID());
-      CFStringRef value = reinterpret_cast<CFStringRef>(item);
-      issuer_name = CFStringRefToCString(value);
-      break;
-    }
-  }
-
-  CFRelease(cert_dict);
-  CFRelease(key_array);
-  return issuer_name;
-}
-
-
-void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
-  SecCertificateRef certificate = GetX509Certificate(args);
-  char* subject_name =
-      GetNameFromCert(certificate, kSecOIDX509V1SubjectName,
-                      reinterpret_cast<CFStringRef>(kSecOIDCommonName));
-  if (subject_name == NULL) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.subject failed to find subject's common name."));
-  } else {
-    Dart_SetReturnValue(args, Dart_NewStringFromCString(subject_name));
-  }
-}
-
-
-void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
-  SecCertificateRef certificate = GetX509Certificate(args);
-  char* issuer_name =
-      GetNameFromCert(certificate, kSecOIDX509V1IssuerName,
-                      reinterpret_cast<CFStringRef>(kSecOIDCommonName));
-  if (issuer_name == NULL) {
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.issuer failed to find issuer's common name."));
-  } else {
-    Dart_SetReturnValue(args, Dart_NewStringFromCString(issuer_name));
-  }
-}
-
-
-// Returns the number of seconds since the epoch from 'field'.
-static int64_t GetTimeFromCert(SecCertificateRef certificate, CFTypeRef field) {
-  CFTypeRef keys[] = {field};
-  CFArrayRef key_array = CFArrayCreate(NULL, keys, 1, &kCFTypeArrayCallBacks);
-  CFErrorRef error = NULL;
-  CFDictionaryRef cert_dict =
-      SecCertificateCopyValues(certificate, key_array, &error);
-  if (cert_dict == NULL) {
-    CFRelease(key_array);
-    Dart_ThrowException(DartUtils::NewDartArgumentError(
-        "X509.startValidity: failed to copy issuer field out of certificate"));
-  }
-
-  CFTypeRef item = CFDictionaryGetValue(cert_dict, keys[0]);
-  ASSERT(CFGetTypeID(item) == CFDictionaryGetTypeID());
-  CFDictionaryRef val_dict = reinterpret_cast<CFDictionaryRef>(item);
-
-  item = CFDictionaryGetValue(val_dict, kSecPropertyKeyValue);
-  ASSERT(CFGetTypeID(item) == CFNumberGetTypeID());
-  CFNumberRef date_number = reinterpret_cast<CFNumberRef>(item);
-
-  CFAbsoluteTime date_abs_time;
-  CFNumberGetValue(date_number, kCFNumberDoubleType, &date_abs_time);
-  CFAbsoluteTime seconds_since_epoch =
-      date_abs_time + kCFAbsoluteTimeIntervalSince1970;
-  return static_cast<int64_t>(seconds_since_epoch) * 1000LL;
-}
-
-
-void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
-  SecCertificateRef certificate = GetX509Certificate(args);
-  int64_t seconds_since_epoch =
-      GetTimeFromCert(certificate, kSecOIDX509V1ValidityNotBefore);
-  Dart_SetReturnValue(
-      args,
-      Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
-}
-
-
-void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
-  SecCertificateRef certificate = GetX509Certificate(args);
-  int64_t seconds_since_epoch =
-      GetTimeFromCert(certificate, kSecOIDX509V1ValidityNotAfter);
-  Dart_SetReturnValue(
-      args,
-      Dart_NewInteger(static_cast<int64_t>(seconds_since_epoch) * 1000LL));
-}
-
-
-// Pushes data through the SSL filter, reading and writing from circular
-// buffers shared with Dart. Called from the IOService thread.
-//
-// The Dart _SecureFilterImpl class contains 4 ExternalByteArrays used to
-// pass encrypted and plaintext data to and from the C++ SSLFilter object.
-//
-// ProcessFilter is called with a CObject array containing the pointer to
-// the SSLFilter, encoded as an int, and the start and end positions of the
-// valid data in the four circular buffers.  The function only reads from
-// the valid data area of the input buffers, and only writes to the free
-// area of the output buffers.  The function returns the new start and end
-// positions in the buffers, but it only updates start for input buffers, and
-// end for output buffers.  Therefore, the Dart thread can simultaneously
-// write to the free space and end pointer of input buffers, and read from
-// the data space of output buffers, and modify the start pointer.
-//
-// When ProcessFilter returns, the Dart thread is responsible for combining
-// the updated pointers from Dart and C++, to make the new valid state of
-// the circular buffer.
-CObject* SSLFilter::ProcessFilterRequest(const CObjectArray& request) {
-  CObjectIntptr filter_object(request[0]);
-  SSLFilter* filter = reinterpret_cast<SSLFilter*>(filter_object.Value());
-  RefCntReleaseScope<SSLFilter> rs(filter);
-
-  bool in_handshake = CObjectBool(request[1]).Value();
-  intptr_t starts[SSLFilter::kNumBuffers];
-  intptr_t ends[SSLFilter::kNumBuffers];
-  for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
-    starts[i] = CObjectInt32(request[2 * i + 2]).Value();
-    ends[i] = CObjectInt32(request[2 * i + 3]).Value();
-  }
-
-  OSStatus status = filter->ProcessAllBuffers(starts, ends, in_handshake);
-  if (status == noErr) {
-    CObjectArray* result =
-        new CObjectArray(CObject::NewArray(SSLFilter::kNumBuffers * 2));
-    for (intptr_t i = 0; i < SSLFilter::kNumBuffers; ++i) {
-      result->SetAt(2 * i, new CObjectInt32(CObject::NewInt32(starts[i])));
-      result->SetAt(2 * i + 1, new CObjectInt32(CObject::NewInt32(ends[i])));
-    }
-    return result;
-  } else {
-    TextBuffer status_message(SSL_ERROR_MESSAGE_BUFFER_SIZE);
-    CFStringRef error_string = SecCopyErrorMessageString(status, NULL);
-    if (error_string == NULL) {
-      status_message.Printf("OSStatus = %ld: https://www.osstatus.com",
-                            static_cast<intptr_t>(status));
-    } else {
-      char* error = CFStringRefToCString(error_string);
-      status_message.Printf("OSStatus = %ld: %s", static_cast<intptr_t>(status),
-                            error);
-      CFRelease(error_string);
-    }
-    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
-    result->SetAt(0, new CObjectInt32(CObject::NewInt32(status)));
-    result->SetAt(1,
-                  new CObjectString(CObject::NewString(status_message.buf())));
-    return result;
-  }
-}
-
-
-// Usually buffer_starts_ and buffer_ends_ are populated by ProcessAllBuffers,
-// called from ProcessFilterRequest, called from the IOService thread.
-// However, the first call to SSLHandshake comes from the Dart thread, and so
-// doesn't go through there. This results in calls to SSLReadCallback and
-// SSLWriteCallback in which buffer_starts_ and buffer_ends_ haven't been set
-// up. In that case, since we're coming from Dart anyway, we can access the
-// fieds directly from the Dart objects.
-intptr_t SSLFilter::GetBufferStart(intptr_t idx) const {
-  if (buffer_starts_[idx] != NULL) {
-    return *buffer_starts_[idx];
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  Dart_Handle start_handle =
-      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("start")));
-  int64_t start = DartUtils::GetIntegerValue(start_handle);
-  return static_cast<intptr_t>(start);
-}
-
-
-intptr_t SSLFilter::GetBufferEnd(intptr_t idx) const {
-  if (buffer_ends_[idx] != NULL) {
-    return *buffer_ends_[idx];
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  Dart_Handle end_handle =
-      ThrowIfError(Dart_GetField(buffer_handle, DartUtils::NewString("end")));
-  int64_t end = DartUtils::GetIntegerValue(end_handle);
-  return static_cast<intptr_t>(end);
-}
-
-
-void SSLFilter::SetBufferStart(intptr_t idx, intptr_t value) {
-  if (buffer_starts_[idx] != NULL) {
-    *buffer_starts_[idx] = value;
-    return;
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  ThrowIfError(DartUtils::SetIntegerField(buffer_handle, "start",
-                                          static_cast<int64_t>(value)));
-}
-
-
-void SSLFilter::SetBufferEnd(intptr_t idx, intptr_t value) {
-  if (buffer_ends_[idx] != NULL) {
-    *buffer_ends_[idx] = value;
-    return;
-  }
-  Dart_Handle buffer_handle =
-      ThrowIfError(Dart_HandleFromPersistent(dart_buffer_objects_[idx]));
-  ThrowIfError(DartUtils::SetIntegerField(buffer_handle, "end",
-                                          static_cast<int64_t>(value)));
-}
-
-
-OSStatus SSLFilter::ProcessAllBuffers(intptr_t starts[kNumBuffers],
-                                      intptr_t ends[kNumBuffers],
-                                      bool in_handshake) {
-  for (intptr_t i = 0; i < kNumBuffers; ++i) {
-    buffer_starts_[i] = &starts[i];
-    buffer_ends_[i] = &ends[i];
-  }
-
-  if (in_handshake) {
-    OSStatus status = Handshake();
-    if (status != noErr) {
-      return status;
-    }
-  } else {
-    for (intptr_t i = 0; i < kNumBuffers; ++i) {
-      intptr_t start = starts[i];
-      intptr_t end = ends[i];
-      intptr_t size =
-          isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-      if (start < 0 || end < 0 || start >= size || end >= size) {
-        FATAL("Out-of-bounds internal buffer access in dart:io SecureSocket");
-      }
-      switch (i) {
-        case kReadPlaintext:
-          // Write data to the circular buffer's free space.  If the buffer
-          // is full, neither if statement is executed and nothing happens.
-          if (start <= end) {
-            // If the free space may be split into two segments,
-            // then the first is [end, size), unless start == 0.
-            // Then, since the last free byte is at position start - 2,
-            // the interval is [end, size - 1).
-            intptr_t buffer_end = (start == 0) ? size - 1 : size;
-            intptr_t bytes = 0;
-            OSStatus status =
-                ProcessReadPlaintextBuffer(end, buffer_end, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            end += bytes;
-            ASSERT(end <= size);
-            if (end == size) {
-              end = 0;
-            }
-          }
-          if (start > end + 1) {
-            intptr_t bytes = 0;
-            OSStatus status =
-                ProcessReadPlaintextBuffer(end, start - 1, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            end += bytes;
-            ASSERT(end < start);
-          }
-          ends[i] = end;
-          break;
-        case kWritePlaintext:
-          // Read/Write data from circular buffer.  If the buffer is empty,
-          // neither if statement's condition is true.
-          if (end < start) {
-            // Data may be split into two segments.  In this case,
-            // the first is [start, size).
-            intptr_t bytes = 0;
-            OSStatus status = ProcessWritePlaintextBuffer(start, size, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            start += bytes;
-            ASSERT(start <= size);
-            if (start == size) {
-              start = 0;
-            }
-          }
-          if (start < end) {
-            intptr_t bytes = 0;
-            OSStatus status = ProcessWritePlaintextBuffer(start, end, &bytes);
-            if ((status != noErr) && (status != errSSLWouldBlock)) {
-              return status;
-            }
-            start += bytes;
-            ASSERT(start <= end);
-          }
-          starts[i] = start;
-          break;
-        case kReadEncrypted:
-        case kWriteEncrypted:
-          // These buffers are advanced through SSLReadCallback and
-          // SSLWriteCallback, which are called from SSLRead, SSLWrite, and
-          // SSLHandshake.
-          break;
-        default:
-          UNREACHABLE();
-      }
-    }
-  }
-
-  for (intptr_t i = 0; i < kNumBuffers; ++i) {
-    buffer_starts_[i] = NULL;
-    buffer_ends_[i] = NULL;
-  }
-  return noErr;
-}
-
-
-Dart_Handle SSLFilter::Init(Dart_Handle dart_this) {
-  ASSERT(string_start_ == NULL);
-  string_start_ = Dart_NewPersistentHandle(DartUtils::NewString("start"));
-  ASSERT(string_start_ != NULL);
-  ASSERT(string_length_ == NULL);
-  string_length_ = Dart_NewPersistentHandle(DartUtils::NewString("length"));
-  ASSERT(string_length_ != NULL);
-  ASSERT(bad_certificate_callback_ == NULL);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(Dart_Null());
-  ASSERT(bad_certificate_callback_ != NULL);
-
-  // Caller handles cleanup on an error.
-  return InitializeBuffers(dart_this);
-}
-
-
-Dart_Handle SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
-  // Create SSLFilter buffers as ExternalUint8Array objects.
-  Dart_Handle buffers_string = DartUtils::NewString("buffers");
-  RETURN_IF_ERROR(buffers_string);
-  Dart_Handle dart_buffers_object = Dart_GetField(dart_this, buffers_string);
-  RETURN_IF_ERROR(dart_buffers_object);
-  Dart_Handle secure_filter_impl_type = Dart_InstanceGetType(dart_this);
-  RETURN_IF_ERROR(secure_filter_impl_type);
-  Dart_Handle size_string = DartUtils::NewString("SIZE");
-  RETURN_IF_ERROR(size_string);
-  Dart_Handle dart_buffer_size =
-      Dart_GetField(secure_filter_impl_type, size_string);
-  RETURN_IF_ERROR(dart_buffer_size);
-
-  int64_t buffer_size = 0;
-  Dart_Handle err = Dart_IntegerToInt64(dart_buffer_size, &buffer_size);
-  RETURN_IF_ERROR(err);
-
-  Dart_Handle encrypted_size_string = DartUtils::NewString("ENCRYPTED_SIZE");
-  RETURN_IF_ERROR(encrypted_size_string);
-
-  Dart_Handle dart_encrypted_buffer_size =
-      Dart_GetField(secure_filter_impl_type, encrypted_size_string);
-  RETURN_IF_ERROR(dart_encrypted_buffer_size);
-
-  int64_t encrypted_buffer_size = 0;
-  err = Dart_IntegerToInt64(dart_encrypted_buffer_size, &encrypted_buffer_size);
-  RETURN_IF_ERROR(err);
-
-  if (buffer_size <= 0 || buffer_size > 1 * MB) {
-    FATAL("Invalid buffer size in _ExternalBuffer");
-  }
-  if (encrypted_buffer_size <= 0 || encrypted_buffer_size > 1 * MB) {
-    FATAL("Invalid encrypted buffer size in _ExternalBuffer");
-  }
-  buffer_size_ = static_cast<intptr_t>(buffer_size);
-  encrypted_buffer_size_ = static_cast<intptr_t>(encrypted_buffer_size);
-
-  Dart_Handle data_identifier = DartUtils::NewString("data");
-  RETURN_IF_ERROR(data_identifier);
-
-  for (int i = 0; i < kNumBuffers; i++) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    buffers_[i] = new uint8_t[size];
-    ASSERT(buffers_[i] != NULL);
-    buffer_starts_[i] = NULL;
-    buffer_ends_[i] = NULL;
-    dart_buffer_objects_[i] = NULL;
-  }
-
-  Dart_Handle result = Dart_Null();
-  for (int i = 0; i < kNumBuffers; ++i) {
-    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
-    result = Dart_ListGetAt(dart_buffers_object, i);
-    if (Dart_IsError(result)) {
-      break;
-    }
-
-    dart_buffer_objects_[i] = Dart_NewPersistentHandle(result);
-    ASSERT(dart_buffer_objects_[i] != NULL);
-    Dart_Handle data =
-        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size);
-    if (Dart_IsError(data)) {
-      result = data;
-      break;
-    }
-    result = Dart_HandleFromPersistent(dart_buffer_objects_[i]);
-    if (Dart_IsError(result)) {
-      break;
-    }
-    result = Dart_SetField(result, data_identifier, data);
-    if (Dart_IsError(result)) {
-      break;
-    }
-  }
-
-  // Caller handles cleanup on an error.
-  return result;
-}
-
-
-void SSLFilter::RegisterHandshakeCompleteCallback(Dart_Handle complete) {
-  ASSERT(NULL == handshake_complete_);
-  handshake_complete_ = Dart_NewPersistentHandle(complete);
-  ASSERT(handshake_complete_ != NULL);
-}
-
-
-void SSLFilter::RegisterBadCertificateCallback(Dart_Handle callback) {
-  ASSERT(bad_certificate_callback_ != NULL);
-  Dart_DeletePersistentHandle(bad_certificate_callback_);
-  bad_certificate_callback_ = Dart_NewPersistentHandle(callback);
-  ASSERT(bad_certificate_callback_ != NULL);
-}
-
-
-Dart_Handle SSLFilter::PeerCertificate() {
-  if (peer_certs_ == NULL) {
-    return Dart_Null();
-  }
-
-  CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, 0);
-  ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
-  SecCertificateRef cert =
-      reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
-  if (cert == NULL) {
-    return Dart_Null();
-  }
-
-  return WrappedX509Certificate(cert);
-}
-
-
-void SSLFilter::Connect(Dart_Handle dart_this,
-                        const char* hostname,
-                        SSLCertContext* context,
-                        bool is_server,
-                        bool request_client_certificate,
-                        bool require_client_certificate) {
-  if (in_handshake_) {
-    FATAL("Connect called twice on the same _SecureFilter.");
-  }
-
-  // Create the underlying context
-  SSLContextRef ssl_context = SSLCreateContext(
-      NULL, is_server ? kSSLServerSide : kSSLClientSide, kSSLStreamType);
-
-  // Configure the context.
-  OSStatus status;
-  status = SSLSetPeerDomainName(ssl_context, hostname, strlen(hostname));
-  CheckStatus(status, "TlsException", "Failed to set peer domain name");
-
-  status = SSLSetIOFuncs(ssl_context, SSLFilter::SSLReadCallback,
-                         SSLFilter::SSLWriteCallback);
-  CheckStatus(status, "TlsException", "Failed to set IO Callbacks");
-
-  status =
-      SSLSetConnection(ssl_context, reinterpret_cast<SSLConnectionRef>(this));
-  CheckStatus(status, "TlsException", "Failed to set connection object");
-
-  // Always evaluate the certs manually so that we can cache the peer
-  // certificates in the context for calls to peerCertificate.
-  status = SSLSetSessionOption(ssl_context, kSSLSessionOptionBreakOnServerAuth,
-                               true);
-  CheckStatus(status, "TlsException", "Failed to set BreakOnServerAuth option");
-
-  status = SSLSetProtocolVersionMin(ssl_context, kTLSProtocol1);
-  CheckStatus(status, "TlsException",
-              "Failed to set minimum protocol version to kTLSProtocol1");
-
-  // If the context has a private key and certificate chain, combine the
-  // private key and first certificate into a SecIdentityRef, and place that
-  // and the remaining certs in an array to pass to SSLSetCertificate().
-  if ((context->private_key() != NULL) && (context->cert_chain() != NULL)) {
-    CFIndex chain_length = CFArrayGetCount(context->cert_chain());
-    CFMutableArrayRef certs =
-        CFArrayCreateMutable(NULL, chain_length, &kCFTypeArrayCallBacks);
-    CFTypeRef item = CFArrayGetValueAtIndex(context->cert_chain(), 0);
-    ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
-    SecCertificateRef first_cert =
-        reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
-    SecIdentityRef identity =
-        SecIdentityCreate(NULL, first_cert, context->private_key());
-    CFArrayAppendValue(certs, identity);
-    for (CFIndex i = 0; i < chain_length; i++) {
-      CFArrayAppendValue(certs,
-                         CFArrayGetValueAtIndex(context->cert_chain(), i));
-    }
-    CFRelease(identity);
-    status = SSLSetCertificate(ssl_context, certs);
-    CFRelease(certs);
-    CheckStatus(status, "TlsException", "SSLSetCertificate failed");
-  }
-
-  if (context->cert_authorities() != NULL) {
-    status = SSLSetCertificateAuthorities(ssl_context,
-                                          context->cert_authorities(), true);
-    CheckStatus(status, "TlsException",
-                "Failed to set certificate authorities");
-  }
-
-  if (is_server) {
-    SSLAuthenticate auth =
-        require_client_certificate
-            ? kAlwaysAuthenticate
-            : (request_client_certificate ? kTryAuthenticate
-                                          : kNeverAuthenticate);
-    status = SSLSetClientSideAuthenticate(ssl_context, auth);
-    CheckStatus(status, "TlsException",
-                "Failed to set client authentication mode");
-
-    // If we're at least trying client authentication, then break handshake
-    // for client authentication.
-    if (auth != kNeverAuthenticate) {
-      status = SSLSetSessionOption(ssl_context,
-                                   kSSLSessionOptionBreakOnClientAuth, true);
-      CheckStatus(status, "TlsException",
-                  "Failed to set client authentication mode");
-    }
-  }
-
-  // Add the contexts to our wrapper.
-  cert_context_.set(context);
-  ssl_context_ = ssl_context;
-  is_server_ = is_server;
-
-  // Kick-off the handshake. Expect the handshake to need more data.
-  // SSLHandshake calls our SSLReadCallback and SSLWriteCallback.
-  status = SSLHandshake(ssl_context);
-  ASSERT(status != noErr);
-  if (status == errSSLWouldBlock) {
-    status = noErr;
-    in_handshake_ = true;
-  }
-  CheckStatus(status, "HandshakeException", is_server_
-                                                ? "Handshake error in server"
-                                                : "Handshake error in client");
-}
-
-
-OSStatus SSLFilter::EvaluatePeerTrust() {
-  OSStatus status = noErr;
-
-  if (SSL_LOG_STATUS) {
-    Log::Print("Handshake evaluating trust.\n");
-  }
-  SecTrustRef peer_trust = NULL;
-  status = SSLCopyPeerTrust(ssl_context_, &peer_trust);
-  if (status != noErr) {
-    if (is_server_ && (status == errSSLBadCert)) {
-      // A client certificate was requested, but not required, and wasn't sent.
-      return noErr;
-    }
-    if (SSL_LOG_STATUS) {
-      Log::Print("Handshake error from SSLCopyPeerTrust(): %ld.\n",
-                 static_cast<intptr_t>(status));
-    }
-    return status;
-  }
-
-  CFArrayRef trusted_certs = NULL;
-  if (cert_context_.get()->trusted_certs() != NULL) {
-    trusted_certs =
-        CFArrayCreateCopy(NULL, cert_context_.get()->trusted_certs());
-  } else {
-    trusted_certs = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
-  }
-
-  status = SecTrustSetAnchorCertificates(peer_trust, trusted_certs);
-  if (status != noErr) {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Handshake error from SecTrustSetAnchorCertificates: %ld\n",
-                 static_cast<intptr_t>(status));
-    }
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  if (SSL_LOG_STATUS) {
-    Log::Print(
-        "Handshake %s built in root certs\n",
-        cert_context_.get()->trust_builtin() ? "trusting" : "not trusting");
-  }
-
-  status = SecTrustSetAnchorCertificatesOnly(
-      peer_trust, !cert_context_.get()->trust_builtin());
-  if (status != noErr) {
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  SecTrustResultType trust_result;
-  status = SecTrustEvaluate(peer_trust, &trust_result);
-  if (status != noErr) {
-    CFRelease(trusted_certs);
-    CFRelease(peer_trust);
-    return status;
-  }
-
-  // Grab the peer's certificate chain.
-  CFIndex peer_chain_length = SecTrustGetCertificateCount(peer_trust);
-  CFMutableArrayRef peer_certs =
-      CFArrayCreateMutable(NULL, peer_chain_length, &kCFTypeArrayCallBacks);
-  for (CFIndex i = 0; i < peer_chain_length; ++i) {
-    CFArrayAppendValue(peer_certs,
-                       SecTrustGetCertificateAtIndex(peer_trust, i));
-  }
-  peer_certs_ = peer_certs;
-
-  CFRelease(trusted_certs);
-  CFRelease(peer_trust);
-
-  if ((trust_result == kSecTrustResultProceed) ||
-      (trust_result == kSecTrustResultUnspecified)) {
-    // Trusted.
-    return noErr;
-  } else {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Trust eval failed: trust_restul = %d\n", trust_result);
-    }
-    bad_cert_ = true;
-    return errSSLBadCert;
-  }
-}
-
-
-OSStatus SSLFilter::Handshake() {
-  ASSERT(cert_context_.get() != NULL);
-  ASSERT(ssl_context_ != NULL);
-  // Try and push handshake along.
-  if (SSL_LOG_STATUS) {
-    Log::Print("Doing SSLHandshake\n");
-  }
-  OSStatus status = SSLHandshake(ssl_context_);
-  if (SSL_LOG_STATUS) {
-    Log::Print("SSLHandshake returned %ld\n", static_cast<intptr_t>(status));
-  }
-
-  if ((status == errSSLServerAuthCompleted) ||
-      (status == errSSLClientAuthCompleted)) {
-    status = EvaluatePeerTrust();
-    if (status == errSSLBadCert) {
-      // Need to invoke the bad certificate callback.
-      return noErr;
-    } else if (status != noErr) {
-      return status;
-    }
-    // When trust evaluation succeeds, we can call SSLHandshake again
-    // immediately.
-    status = SSLHandshake(ssl_context_);
-  }
-
-  if (status == errSSLWouldBlock) {
-    in_handshake_ = true;
-    return noErr;
-  }
-
-  // Handshake succeeded.
-  if ((in_handshake_) && (status == noErr)) {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Finished with the Handshake\n");
-    }
-    connected_ = true;
-  }
-  return status;
-}
-
-
-// Returns false if Handshake should fail, and true if Handshake should
-// proceed.
-Dart_Handle SSLFilter::InvokeBadCertCallback(SecCertificateRef peer_cert) {
-  Dart_Handle callback = bad_certificate_callback_;
-  if (Dart_IsNull(callback)) {
-    return callback;
-  }
-  Dart_Handle args[1];
-  args[0] = WrappedX509Certificate(peer_cert);
-  if (Dart_IsError(args[0])) {
-    return args[0];
-  }
-  Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
-  if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
-    result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
-        "HandshakeException",
-        "BadCertificateCallback returned a value that was not a boolean",
-        Dart_Null()));
-  }
-  return result;
-}
-
-
-OSStatus SSLFilter::CheckHandshake() {
-  if (bad_cert_ && in_handshake_) {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Invoking bad certificate callback\n");
-    }
-    ASSERT(peer_certs_ != NULL);
-    CFIndex peer_certs_len = CFArrayGetCount(peer_certs_);
-    ASSERT(peer_certs_len > 0);
-    CFTypeRef item = CFArrayGetValueAtIndex(peer_certs_, peer_certs_len - 1);
-    ASSERT(item != NULL);
-    ASSERT(CFGetTypeID(item) == SecCertificateGetTypeID());
-    SecCertificateRef peer_cert =
-        reinterpret_cast<SecCertificateRef>(const_cast<void*>(item));
-    Dart_Handle result = InvokeBadCertCallback(peer_cert);
-    ThrowIfError(result);
-    if (Dart_IsNull(result)) {
-      return errSSLBadCert;
-    } else {
-      bool good_cert = DartUtils::GetBooleanValue(result);
-      bad_cert_ = !good_cert;
-      return good_cert ? noErr : errSSLBadCert;
-    }
-  }
-
-  if (connected_ && in_handshake_) {
-    if (SSL_LOG_STATUS) {
-      Log::Print("Invoking handshake complete callback\n");
-    }
-    ThrowIfError(Dart_InvokeClosure(
-        Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
-    in_handshake_ = false;
-  }
-  return noErr;
-}
-
-
-void SSLFilter::Renegotiate(bool use_session_cache,
-                            bool request_client_certificate,
-                            bool require_client_certificate) {
-  // The SSL_REQUIRE_CERTIFICATE option only takes effect if the
-  // SSL_REQUEST_CERTIFICATE option is also set, so set it.
-  request_client_certificate =
-      request_client_certificate || require_client_certificate;
-  // TODO(24070, 24069): Implement setting the client certificate parameters,
-  //   and triggering rehandshake.
-}
-
-
-SSLFilter::~SSLFilter() {
-  if (ssl_context_ != NULL) {
-    CFRelease(ssl_context_);
-    ssl_context_ = NULL;
-  }
-  if (peer_certs_ != NULL) {
-    CFRelease(peer_certs_);
-    peer_certs_ = NULL;
-  }
-  if (hostname_ != NULL) {
-    free(hostname_);
-    hostname_ = NULL;
-  }
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (buffers_[i] != NULL) {
-      delete[] buffers_[i];
-      buffers_[i] = NULL;
-    }
-  }
-}
-
-
-void SSLFilter::Destroy() {
-  if (ssl_context_ != NULL) {
-    SSLClose(ssl_context_);
-  }
-  for (int i = 0; i < kNumBuffers; ++i) {
-    if (dart_buffer_objects_[i] != NULL) {
-      Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
-      dart_buffer_objects_[i] = NULL;
-    }
-  }
-  if (string_start_ != NULL) {
-    Dart_DeletePersistentHandle(string_start_);
-    string_start_ = NULL;
-  }
-  if (string_length_ != NULL) {
-    Dart_DeletePersistentHandle(string_length_);
-    string_length_ = NULL;
-  }
-  if (handshake_complete_ != NULL) {
-    Dart_DeletePersistentHandle(handshake_complete_);
-    handshake_complete_ = NULL;
-  }
-  if (bad_certificate_callback_ != NULL) {
-    Dart_DeletePersistentHandle(bad_certificate_callback_);
-    bad_certificate_callback_ = NULL;
-  }
-}
-
-
-OSStatus SSLFilter::SSLReadCallback(SSLConnectionRef connection,
-                                    void* data,
-                                    size_t* data_requested) {
-  // Copy at most `data_requested` bytes from `buffers_[kReadEncrypted]` into
-  // `data`
-  ASSERT(connection != NULL);
-  ASSERT(data != NULL);
-  ASSERT(data_requested != NULL);
-
-  SSLFilter* filter =
-      const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
-  uint8_t* datap = reinterpret_cast<uint8_t*>(data);
-  uint8_t* buffer = filter->buffers_[kReadEncrypted];
-  intptr_t start = filter->GetBufferStart(kReadEncrypted);
-  intptr_t end = filter->GetBufferEnd(kReadEncrypted);
-  intptr_t size = filter->encrypted_buffer_size_;
-  intptr_t requested = static_cast<intptr_t>(*data_requested);
-  intptr_t data_read = 0;
-
-  if (end < start) {
-    // Data may be split into two segments.  In this case,
-    // the first is [start, size).
-    intptr_t buffer_end = (start == 0) ? size - 1 : size;
-    intptr_t available = buffer_end - start;
-    intptr_t bytes = requested < available ? requested : available;
-    memmove(datap, &buffer[start], bytes);
-    start += bytes;
-    datap += bytes;
-    data_read += bytes;
-    requested -= bytes;
-    ASSERT(start <= size);
-    if (start == size) {
-      start = 0;
-    }
-  }
-  if ((requested > 0) && (start < end)) {
-    intptr_t available = end - start;
-    intptr_t bytes = requested < available ? requested : available;
-    memmove(datap, &buffer[start], bytes);
-    start += bytes;
-    datap += bytes;
-    data_read += bytes;
-    requested -= bytes;
-    ASSERT(start <= end);
-  }
-
-  if (SSL_LOG_DATA) {
-    Log::Print("SSLReadCallback: requested: %ld, read %ld bytes\n",
-               *data_requested, data_read);
-  }
-
-  filter->SetBufferStart(kReadEncrypted, start);
-  bool short_read = data_read < static_cast<intptr_t>(*data_requested);
-  *data_requested = data_read;
-  return short_read ? errSSLWouldBlock : noErr;
-}
-
-
-// Read decrypted data from the filter to the circular buffer.
-OSStatus SSLFilter::ProcessReadPlaintextBuffer(intptr_t start,
-                                               intptr_t end,
-                                               intptr_t* bytes_processed) {
-  ASSERT(bytes_processed != NULL);
-  intptr_t length = end - start;
-  OSStatus status = noErr;
-  size_t bytes = 0;
-  if (length > 0) {
-    status =
-        SSLRead(ssl_context_,
-                reinterpret_cast<void*>((buffers_[kReadPlaintext] + start)),
-                length, &bytes);
-    if (SSL_LOG_STATUS) {
-      Log::Print("SSLRead: status = %ld\n", static_cast<intptr_t>(status));
-    }
-    if ((status != noErr) && (status != errSSLWouldBlock)) {
-      *bytes_processed = 0;
-      return status;
-    }
-  }
-  if (SSL_LOG_DATA) {
-    Log::Print("ProcessReadPlaintextBuffer: requested: %ld, read %ld bytes\n",
-               length, bytes);
-  }
-  *bytes_processed = static_cast<intptr_t>(bytes);
-  return status;
-}
-
-
-OSStatus SSLFilter::SSLWriteCallback(SSLConnectionRef connection,
-                                     const void* data,
-                                     size_t* data_provided) {
-  // Copy at most `data_provided` bytes from data into
-  // `buffers_[kWriteEncrypted]`.
-  ASSERT(connection != NULL);
-  ASSERT(data != NULL);
-  ASSERT(data_provided != NULL);
-
-  SSLFilter* filter =
-      const_cast<SSLFilter*>(reinterpret_cast<const SSLFilter*>(connection));
-  const uint8_t* datap = reinterpret_cast<const uint8_t*>(data);
-  uint8_t* buffer = filter->buffers_[kWriteEncrypted];
-  intptr_t start = filter->GetBufferStart(kWriteEncrypted);
-  intptr_t end = filter->GetBufferEnd(kWriteEncrypted);
-  intptr_t size = filter->encrypted_buffer_size_;
-  intptr_t provided = static_cast<intptr_t>(*data_provided);
-  intptr_t data_written = 0;
-
-  // is full, neither if statement is executed and nothing happens.
-  if (start <= end) {
-    // If the free space may be split into two segments,
-    // then the first is [end, size), unless start == 0.
-    // Then, since the last free byte is at position start - 2,
-    // the interval is [end, size - 1).
-    intptr_t buffer_end = (start == 0) ? size - 1 : size;
-    intptr_t available = buffer_end - end;
-    intptr_t bytes = provided < available ? provided : available;
-    memmove(&buffer[end], datap, bytes);
-    end += bytes;
-    datap += bytes;
-    data_written += bytes;
-    provided -= bytes;
-    ASSERT(end <= size);
-    if (end == size) {
-      end = 0;
-    }
-  }
-  if ((provided > 0) && (start > end + 1)) {
-    intptr_t available = (start - 1) - end;
-    intptr_t bytes = provided < available ? provided : available;
-    memmove(&buffer[end], datap, bytes);
-    end += bytes;
-    datap += bytes;
-    data_written += bytes;
-    provided -= bytes;
-    ASSERT(end < start);
-  }
-
-  if (SSL_LOG_DATA) {
-    Log::Print("SSLWriteCallback: provided: %ld, written %ld bytes\n",
-               *data_provided, data_written);
-  }
-
-  filter->SetBufferEnd(kWriteEncrypted, end);
-  *data_provided = data_written;
-  return (data_written == 0) ? errSSLWouldBlock : noErr;
-}
-
-
-OSStatus SSLFilter::ProcessWritePlaintextBuffer(intptr_t start,
-                                                intptr_t end,
-                                                intptr_t* bytes_processed) {
-  ASSERT(bytes_processed != NULL);
-  intptr_t length = end - start;
-  OSStatus status = noErr;
-  size_t bytes = 0;
-  if (length > 0) {
-    status =
-        SSLWrite(ssl_context_,
-                 reinterpret_cast<void*>(buffers_[kWritePlaintext] + start),
-                 length, &bytes);
-    if (SSL_LOG_STATUS) {
-      Log::Print("SSLWrite: status = %ld\n", static_cast<intptr_t>(status));
-    }
-    if ((status != noErr) && (status != errSSLWouldBlock)) {
-      *bytes_processed = 0;
-      return status;
-    }
-  }
-  if (SSL_LOG_DATA) {
-    Log::Print("ProcessWritePlaintextBuffer: requested: %ld, written: %ld\n",
-               length, bytes);
-  }
-  *bytes_processed = static_cast<intptr_t>(bytes);
-  return status;
-}
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // defined(HOST_OS_MACOS) && !HOST_OS_IOS
-
-#endif  // !defined(DART_IO_DISABLED) &&
-        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/secure_socket_macos.h b/runtime/bin/secure_socket_macos.h
deleted file mode 100644
index f84cc42..0000000
--- a/runtime/bin/secure_socket_macos.h
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#ifndef RUNTIME_BIN_SECURE_SOCKET_MACOS_H_
-#define RUNTIME_BIN_SECURE_SOCKET_MACOS_H_
-
-#if !defined(RUNTIME_BIN_SECURE_SOCKET_H_)
-#error Do not include secure_socket_macos.h directly. Use secure_socket.h.
-#endif
-
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#include <sys/types.h>
-
-#include <CoreFoundation/CoreFoundation.h>
-#include <Security/SecureTransport.h>
-#include <Security/Security.h>
-
-#include "bin/builtin.h"
-#include "bin/dartutils.h"
-#include "bin/lockers.h"
-#include "bin/reference_counting.h"
-#include "bin/socket.h"
-#include "bin/thread.h"
-#include "bin/utils.h"
-
-namespace dart {
-namespace bin {
-
-// SSLCertContext wraps the certificates needed for a SecureTransport
-// connection. Fields are protected by the mutex_ field, and may only be set
-// once. This is to allow access by both the Dart thread and the IOService
-// thread. Setters return false if the field was already set.
-class SSLCertContext : public ReferenceCounted<SSLCertContext> {
- public:
-  SSLCertContext()
-      : ReferenceCounted(),
-        mutex_(new Mutex()),
-        private_key_(NULL),
-        keychain_(NULL),
-        cert_chain_(NULL),
-        trusted_certs_(NULL),
-        cert_authorities_(NULL),
-        trust_builtin_(false) {}
-
-  ~SSLCertContext() {
-    {
-      MutexLocker m(mutex_);
-      if (private_key_ != NULL) {
-        CFRelease(private_key_);
-      }
-      if (keychain_ != NULL) {
-        SecKeychainDelete(keychain_);
-        CFRelease(keychain_);
-      }
-      if (cert_chain_ != NULL) {
-        CFRelease(cert_chain_);
-      }
-      if (trusted_certs_ != NULL) {
-        CFRelease(trusted_certs_);
-      }
-      if (cert_authorities_ != NULL) {
-        CFRelease(cert_authorities_);
-      }
-    }
-    delete mutex_;
-  }
-
-  SecKeyRef private_key() {
-    MutexLocker m(mutex_);
-    return private_key_;
-  }
-  bool set_private_key(SecKeyRef private_key) {
-    MutexLocker m(mutex_);
-    if (private_key_ != NULL) {
-      return false;
-    }
-    private_key_ = private_key;
-    return true;
-  }
-
-  SecKeychainRef keychain() {
-    MutexLocker m(mutex_);
-    return keychain_;
-  }
-  bool set_keychain(SecKeychainRef keychain) {
-    MutexLocker m(mutex_);
-    if (keychain_ != NULL) {
-      return false;
-    }
-    keychain_ = keychain;
-    return true;
-  }
-
-  CFArrayRef cert_chain() {
-    MutexLocker m(mutex_);
-    return cert_chain_;
-  }
-  bool set_cert_chain(CFArrayRef cert_chain) {
-    MutexLocker m(mutex_);
-    if (cert_chain_ != NULL) {
-      return false;
-    }
-    cert_chain_ = cert_chain;
-    return true;
-  }
-
-  CFArrayRef trusted_certs() {
-    MutexLocker m(mutex_);
-    return trusted_certs_;
-  }
-  bool set_trusted_certs(CFArrayRef trusted_certs) {
-    MutexLocker m(mutex_);
-    if (trusted_certs_ != NULL) {
-      return false;
-    }
-    trusted_certs_ = trusted_certs;
-    return true;
-  }
-
-  CFArrayRef cert_authorities() {
-    MutexLocker m(mutex_);
-    return cert_authorities_;
-  }
-  bool set_cert_authorities(CFArrayRef cert_authorities) {
-    MutexLocker m(mutex_);
-    if (cert_authorities_ != NULL) {
-      return false;
-    }
-    cert_authorities_ = cert_authorities;
-    return true;
-  }
-
-  bool trust_builtin() {
-    MutexLocker m(mutex_);
-    return trust_builtin_;
-  }
-  void set_trust_builtin(bool trust_builtin) {
-    MutexLocker m(mutex_);
-    trust_builtin_ = trust_builtin;
-  }
-
- private:
-  // The context is accessed both by Dart code and the IOService. This mutex
-  // protects all fields.
-  Mutex* mutex_;
-
-  SecKeyRef private_key_;
-  SecKeychainRef keychain_;
-
-  // CFArrays of SecCertificateRef.
-  CFArrayRef cert_chain_;
-  CFArrayRef trusted_certs_;
-  CFArrayRef cert_authorities_;
-
-  bool trust_builtin_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
-};
-
-// SSLFilter encapsulates the SecureTransport code in a filter that communicates
-// with the containing _SecureFilterImpl Dart object through four shared
-// ExternalByteArray buffers, for reading and writing plaintext, and
-// reading and writing encrypted text.  The filter handles handshaking
-// and certificate verification.
-class SSLFilter : public ReferenceCounted<SSLFilter> {
- public:
-  // These enums must agree with those in sdk/lib/io/secure_socket.dart.
-  enum BufferIndex {
-    kReadPlaintext,
-    kWritePlaintext,
-    kReadEncrypted,
-    kWriteEncrypted,
-    kNumBuffers,
-    kFirstEncrypted = kReadEncrypted
-  };
-
-  SSLFilter()
-      : ReferenceCounted(),
-        cert_context_(NULL),
-        ssl_context_(NULL),
-        peer_certs_(NULL),
-        string_start_(NULL),
-        string_length_(NULL),
-        handshake_complete_(NULL),
-        bad_certificate_callback_(NULL),
-        in_handshake_(false),
-        connected_(false),
-        bad_cert_(false),
-        is_server_(false),
-        hostname_(NULL) {}
-
-  ~SSLFilter();
-
-  // Callback called by the IOService.
-  static CObject* ProcessFilterRequest(const CObjectArray& request);
-
-  Dart_Handle Init(Dart_Handle dart_this);
-  void Connect(Dart_Handle dart_this,
-               const char* hostname,
-               SSLCertContext* context,
-               bool is_server,
-               bool request_client_certificate,
-               bool require_client_certificate);
-  void Destroy();
-  OSStatus CheckHandshake();
-  void Renegotiate(bool use_session_cache,
-                   bool request_client_certificate,
-                   bool require_client_certificate);
-  void RegisterHandshakeCompleteCallback(Dart_Handle handshake_complete);
-  void RegisterBadCertificateCallback(Dart_Handle callback);
-  Dart_Handle PeerCertificate();
-
- private:
-  static OSStatus SSLReadCallback(SSLConnectionRef connection,
-                                  void* data,
-                                  size_t* data_length);
-  static OSStatus SSLWriteCallback(SSLConnectionRef connection,
-                                   const void* data,
-                                   size_t* data_length);
-
-  static bool isBufferEncrypted(intptr_t i) {
-    return static_cast<BufferIndex>(i) >= kFirstEncrypted;
-  }
-  Dart_Handle InitializeBuffers(Dart_Handle dart_this);
-
-  intptr_t GetBufferStart(intptr_t idx) const;
-  intptr_t GetBufferEnd(intptr_t idx) const;
-  void SetBufferStart(intptr_t idx, intptr_t value);
-  void SetBufferEnd(intptr_t idx, intptr_t value);
-
-  OSStatus ProcessAllBuffers(intptr_t starts[kNumBuffers],
-                             intptr_t ends[kNumBuffers],
-                             bool in_handshake);
-  OSStatus ProcessReadPlaintextBuffer(intptr_t start,
-                                      intptr_t end,
-                                      intptr_t* bytes_processed);
-  OSStatus ProcessWritePlaintextBuffer(intptr_t start,
-                                       intptr_t end,
-                                       intptr_t* bytes_processed);
-
-  // These calls can block on IO, and should only be invoked from
-  // from ProcessAllBuffers from ProcessFilterRequest.
-  OSStatus EvaluatePeerTrust();
-  OSStatus Handshake();
-  Dart_Handle InvokeBadCertCallback(SecCertificateRef peer_cert);
-
-  RetainedPointer<SSLCertContext> cert_context_;
-  SSLContextRef ssl_context_;
-  CFArrayRef peer_certs_;
-
-  // starts and ends filled in at the start of ProcessAllBuffers.
-  // If these are NULL, then try to get the pointers out of
-  // dart_buffer_objects_.
-  uint8_t* buffers_[kNumBuffers];
-  intptr_t* buffer_starts_[kNumBuffers];
-  intptr_t* buffer_ends_[kNumBuffers];
-  intptr_t buffer_size_;
-  intptr_t encrypted_buffer_size_;
-  Dart_PersistentHandle string_start_;
-  Dart_PersistentHandle string_length_;
-  Dart_PersistentHandle dart_buffer_objects_[kNumBuffers];
-  Dart_PersistentHandle handshake_complete_;
-  Dart_PersistentHandle bad_certificate_callback_;
-  bool in_handshake_;
-  bool connected_;
-  bool bad_cert_;
-  bool is_server_;
-  char* hostname_;
-
-  DISALLOW_COPY_AND_ASSIGN(SSLFilter);
-};
-
-}  // namespace bin
-}  // namespace dart
-
-#endif  // RUNTIME_BIN_SECURE_SOCKET_MACOS_H_
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 735ba3b..012aee9 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -121,8 +121,8 @@
 @patch
 class SecurityContext {
   @patch
-  factory SecurityContext() {
-    return new _SecurityContext();
+  factory SecurityContext({bool withTrustedRoots: false}) {
+    return new _SecurityContext(withTrustedRoots);
   }
 
   @patch
@@ -138,14 +138,16 @@
 
 class _SecurityContext extends NativeFieldWrapperClass1
     implements SecurityContext {
-  _SecurityContext() {
+  _SecurityContext(bool withTrustedRoots) {
     _createNativeContext();
+    if (withTrustedRoots) {
+      _trustBuiltinRoots();
+    }
   }
 
   void _createNativeContext() native "SecurityContext_Allocate";
 
-  static final SecurityContext defaultContext = new _SecurityContext()
-    .._trustBuiltinRoots();
+  static final SecurityContext defaultContext = new _SecurityContext(true);
 
   void usePrivateKey(String file, {String password}) {
     List<int> bytes = (new File(file)).readAsBytesSync();
diff --git a/runtime/bin/secure_socket_utils.cc b/runtime/bin/secure_socket_utils.cc
new file mode 100644
index 0000000..4ed1a67
--- /dev/null
+++ b/runtime/bin/secure_socket_utils.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "bin/secure_socket_utils.h"
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+
+#include "platform/globals.h"
+
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/security_context.h"
+
+namespace dart {
+namespace bin {
+
+// Get the error messages from BoringSSL, and put them in buffer as a
+// null-terminated string.
+void SecureSocketUtils::FetchErrorString(const SSL* ssl,
+                                         TextBuffer* text_buffer) {
+  const char* sep = File::PathSeparator();
+  while (true) {
+    const char* path = NULL;
+    int line = -1;
+    uint32_t error = ERR_get_error_line(&path, &line);
+    if (error == 0) {
+      break;
+    }
+    text_buffer->Printf("\n\t%s", ERR_reason_error_string(error));
+    if ((ssl != NULL) && (ERR_GET_LIB(error) == ERR_LIB_SSL) &&
+        (ERR_GET_REASON(error) == SSL_R_CERTIFICATE_VERIFY_FAILED)) {
+      intptr_t result = SSL_get_verify_result(ssl);
+      text_buffer->Printf(": %s", X509_verify_cert_error_string(result));
+    }
+    if ((path != NULL) && (line >= 0)) {
+      const char* file = strrchr(path, sep[0]);
+      path = file ? file + 1 : path;
+      text_buffer->Printf("(%s:%d)", path, line);
+    }
+  }
+}
+
+
+// Handle an error reported from the BoringSSL library.
+void SecureSocketUtils::ThrowIOException(int status,
+                                         const char* exception_type,
+                                         const char* message,
+                                         const SSL* ssl) {
+  Dart_Handle exception;
+  {
+    TextBuffer error_string(SSL_ERROR_MESSAGE_BUFFER_SIZE);
+    SecureSocketUtils::FetchErrorString(ssl, &error_string);
+    OSError os_error_struct(status, error_string.buf(), OSError::kBoringSSL);
+    Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
+    exception =
+        DartUtils::NewDartIOException(exception_type, message, os_error);
+    ASSERT(!Dart_IsError(exception));
+  }
+  Dart_ThrowException(exception);
+  UNREACHABLE();
+}
+
+
+void SecureSocketUtils::CheckStatusSSL(int status,
+                                       const char* type,
+                                       const char* message,
+                                       const SSL* ssl) {
+  // TODO(24183): Take appropriate action on failed calls,
+  // throw exception that includes all messages from the error stack.
+  if (status == 1) {
+    return;
+  }
+  if (SSL_LOG_STATUS) {
+    int error = ERR_get_error();
+    Log::PrintErr("Failed: %s status %d", message, status);
+    char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
+    ERR_error_string_n(error, error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
+    Log::PrintErr("ERROR: %d %s\n", error, error_string);
+  }
+  SecureSocketUtils::ThrowIOException(status, type, message, ssl);
+}
+
+
+void SecureSocketUtils::CheckStatus(int status,
+                                    const char* type,
+                                    const char* message) {
+  SecureSocketUtils::CheckStatusSSL(status, type, message, NULL);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/secure_socket_utils.h b/runtime/bin/secure_socket_utils.h
new file mode 100644
index 0000000..50a8ad5
--- /dev/null
+++ b/runtime/bin/secure_socket_utils.h
@@ -0,0 +1,180 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_SECURE_SOCKET_UTILS_H_
+#define RUNTIME_BIN_SECURE_SOCKET_UTILS_H_
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "platform/globals.h"
+
+#include "bin/dartutils.h"
+#include "platform/text_buffer.h"
+
+namespace dart {
+namespace bin {
+
+const bool SSL_LOG_STATUS = false;
+const bool SSL_LOG_DATA = false;
+const bool SSL_LOG_CERTS = false;
+
+class SecureSocketUtils : public AllStatic {
+ public:
+  static const int SSL_ERROR_MESSAGE_BUFFER_SIZE = 1000;
+
+  static void ThrowIOException(int status,
+                               const char* exception_type,
+                               const char* message,
+                               const SSL* ssl);
+
+  static void CheckStatusSSL(int status,
+                             const char* type,
+                             const char* message,
+                             const SSL* ssl);
+
+  static void CheckStatus(int status, const char* type, const char* message);
+
+  static bool NoPEMStartLine() {
+    uint32_t last_error = ERR_peek_last_error();
+    return (ERR_GET_LIB(last_error) == ERR_LIB_PEM) &&
+           (ERR_GET_REASON(last_error) == PEM_R_NO_START_LINE);
+  }
+
+  static void FetchErrorString(const SSL* ssl, TextBuffer* text_buffer);
+};
+
+
+// Where the argument to the constructor is the handle for an object
+// implementing List<int>, this class creates a scope in which a memory-backed
+// BIO is allocated. Leaving the scope cleans up the BIO and the buffer that
+// was used to create it.
+//
+// Do not make Dart_ API calls while in a ScopedMemBIO.
+// Do not call Dart_PropagateError while in a ScopedMemBIO.
+class ScopedMemBIO {
+ public:
+  explicit ScopedMemBIO(Dart_Handle object) {
+    if (!Dart_IsTypedData(object) && !Dart_IsList(object)) {
+      Dart_ThrowException(
+          DartUtils::NewDartArgumentError("Argument is not a List<int>"));
+    }
+
+    uint8_t* bytes = NULL;
+    intptr_t bytes_len = 0;
+    bool is_typed_data = false;
+    if (Dart_IsTypedData(object)) {
+      is_typed_data = true;
+      Dart_TypedData_Type typ;
+      ThrowIfError(Dart_TypedDataAcquireData(
+          object, &typ, reinterpret_cast<void**>(&bytes), &bytes_len));
+    } else {
+      ASSERT(Dart_IsList(object));
+      ThrowIfError(Dart_ListLength(object, &bytes_len));
+      bytes = Dart_ScopeAllocate(bytes_len);
+      ASSERT(bytes != NULL);
+      ThrowIfError(Dart_ListGetAsBytes(object, 0, bytes, bytes_len));
+    }
+
+    object_ = object;
+    bytes_ = bytes;
+    bytes_len_ = bytes_len;
+    bio_ = BIO_new_mem_buf(bytes, bytes_len);
+    ASSERT(bio_ != NULL);
+    is_typed_data_ = is_typed_data;
+  }
+
+  ~ScopedMemBIO() {
+    ASSERT(bio_ != NULL);
+    if (is_typed_data_) {
+      BIO_free(bio_);
+      ThrowIfError(Dart_TypedDataReleaseData(object_));
+    } else {
+      BIO_free(bio_);
+    }
+  }
+
+  BIO* bio() {
+    ASSERT(bio_ != NULL);
+    return bio_;
+  }
+
+ private:
+  Dart_Handle object_;
+  uint8_t* bytes_;
+  intptr_t bytes_len_;
+  BIO* bio_;
+  bool is_typed_data_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedMemBIO);
+};
+
+template <typename T, void (*free_func)(T*)>
+class ScopedSSLType {
+ public:
+  explicit ScopedSSLType(T* obj) : obj_(obj) {}
+
+  ~ScopedSSLType() {
+    if (obj_ != NULL) {
+      free_func(obj_);
+    }
+  }
+
+  T* get() { return obj_; }
+  const T* get() const { return obj_; }
+
+  T* release() {
+    T* result = obj_;
+    obj_ = NULL;
+    return result;
+  }
+
+ private:
+  T* obj_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedSSLType);
+};
+
+template <typename T, typename E, void (*func)(E*)>
+class ScopedSSLStackType {
+ public:
+  explicit ScopedSSLStackType(T* obj) : obj_(obj) {}
+
+  ~ScopedSSLStackType() {
+    if (obj_ != NULL) {
+      sk_pop_free(reinterpret_cast<_STACK*>(obj_),
+                  reinterpret_cast<void (*)(void*)>(func));
+    }
+  }
+
+  T* get() { return obj_; }
+  const T* get() const { return obj_; }
+
+  T* release() {
+    T* result = obj_;
+    obj_ = NULL;
+    return result;
+  }
+
+ private:
+  T* obj_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedSSLStackType);
+};
+
+
+typedef ScopedSSLType<PKCS12, PKCS12_free> ScopedPKCS12;
+typedef ScopedSSLType<X509, X509_free> ScopedX509;
+typedef ScopedSSLStackType<STACK_OF(X509), X509, X509_free> ScopedX509Stack;
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_SECURE_SOCKET_UTILS_H_
diff --git a/runtime/bin/security_context.cc b/runtime/bin/security_context.cc
new file mode 100644
index 0000000..f394c3b
--- /dev/null
+++ b/runtime/bin/security_context.cc
@@ -0,0 +1,866 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "bin/security_context.h"
+
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "platform/globals.h"
+
+#include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/secure_socket_utils.h"
+
+// Return the error from the containing function if handle is an error handle.
+#define RETURN_IF_ERROR(handle)                                                \
+  {                                                                            \
+    Dart_Handle __handle = handle;                                             \
+    if (Dart_IsError((__handle))) {                                            \
+      return __handle;                                                         \
+    }                                                                          \
+  }
+
+namespace dart {
+namespace bin {
+
+int SSLCertContext::CertificateCallback(int preverify_ok,
+                                        X509_STORE_CTX* store_ctx) {
+  if (preverify_ok == 1) {
+    return 1;
+  }
+  Dart_Isolate isolate = Dart_CurrentIsolate();
+  if (isolate == NULL) {
+    FATAL("CertificateCallback called with no current isolate\n");
+  }
+  X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx);
+  int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
+  SSL* ssl =
+      static_cast<SSL*>(X509_STORE_CTX_get_ex_data(store_ctx, ssl_index));
+  SSLFilter* filter = static_cast<SSLFilter*>(
+      SSL_get_ex_data(ssl, SSLFilter::filter_ssl_index));
+  Dart_Handle callback = filter->bad_certificate_callback();
+  if (Dart_IsNull(callback)) {
+    return 0;
+  }
+
+  // Upref since the Dart X509 object may outlive the SecurityContext.
+  if (certificate != NULL) {
+    X509_up_ref(certificate);
+  }
+  Dart_Handle args[1];
+  args[0] = X509Helper::WrappedX509Certificate(certificate);
+  if (Dart_IsError(args[0])) {
+    filter->callback_error = args[0];
+    return 0;
+  }
+  Dart_Handle result = Dart_InvokeClosure(callback, 1, args);
+  if (!Dart_IsError(result) && !Dart_IsBoolean(result)) {
+    result = Dart_NewUnhandledExceptionError(DartUtils::NewDartIOException(
+        "HandshakeException",
+        "BadCertificateCallback returned a value that was not a boolean",
+        Dart_Null()));
+  }
+  if (Dart_IsError(result)) {
+    filter->callback_error = result;
+    return 0;
+  }
+  return DartUtils::GetBooleanValue(result);
+}
+
+
+SSLCertContext* SSLCertContext::GetSecurityContext(Dart_NativeArguments args) {
+  SSLCertContext* context;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this, SSLCertContext::kSecurityContextNativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&context)));
+  return context;
+}
+
+
+static void DeleteSecurityContext(void* isolate_data,
+                                  Dart_WeakPersistentHandle handle,
+                                  void* context_pointer) {
+  SSLCertContext* context = static_cast<SSLCertContext*>(context_pointer);
+  context->Release();
+}
+
+
+static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
+                                      SSLCertContext* context) {
+  Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
+  RETURN_IF_ERROR(dart_this);
+  ASSERT(Dart_IsInstance(dart_this));
+  Dart_Handle err = Dart_SetNativeInstanceField(
+      dart_this, SSLCertContext::kSecurityContextNativeFieldIndex,
+      reinterpret_cast<intptr_t>(context));
+  RETURN_IF_ERROR(err);
+  Dart_NewWeakPersistentHandle(dart_this, context,
+                               SSLCertContext::kApproximateSize,
+                               DeleteSecurityContext);
+  return Dart_Null();
+}
+
+
+static void ReleaseCertificate(void* isolate_data,
+                               Dart_WeakPersistentHandle handle,
+                               void* context_pointer) {
+  X509* cert = reinterpret_cast<X509*>(context_pointer);
+  X509_free(cert);
+}
+
+
+static intptr_t EstimateX509Size(X509* certificate) {
+  intptr_t length = i2d_X509(certificate, NULL);
+  return length > 0 ? length : 0;
+}
+
+
+// Returns the handle for a Dart object wrapping the X509 certificate object.
+// The caller should own a reference to the X509 object whose reference count
+// won't drop to zero before the ReleaseCertificate finalizer runs.
+Dart_Handle X509Helper::WrappedX509Certificate(X509* certificate) {
+  if (certificate == NULL) {
+    return Dart_Null();
+  }
+  Dart_Handle x509_type =
+      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
+  if (Dart_IsError(x509_type)) {
+    X509_free(certificate);
+    return x509_type;
+  }
+  Dart_Handle arguments[] = {NULL};
+  Dart_Handle result =
+      Dart_New(x509_type, DartUtils::NewString("_"), 0, arguments);
+  if (Dart_IsError(result)) {
+    X509_free(certificate);
+    return result;
+  }
+  ASSERT(Dart_IsInstance(result));
+  Dart_Handle status =
+      Dart_SetNativeInstanceField(result, SSLCertContext::kX509NativeFieldIndex,
+                                  reinterpret_cast<intptr_t>(certificate));
+  if (Dart_IsError(status)) {
+    X509_free(certificate);
+    return status;
+  }
+  const intptr_t approximate_size_of_certificate =
+      sizeof(*certificate) + EstimateX509Size(certificate);
+  ASSERT(approximate_size_of_certificate > 0);
+  Dart_NewWeakPersistentHandle(result, reinterpret_cast<void*>(certificate),
+                               approximate_size_of_certificate,
+                               ReleaseCertificate);
+  return result;
+}
+
+
+static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context,
+                                             BIO* bio,
+                                             const char* password) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return 0;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509* cert = NULL;
+  STACK_OF(X509)* ca_certs = NULL;
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  if (status == 0) {
+    return status;
+  }
+
+  ScopedX509Stack cert_stack(ca_certs);
+  X509_STORE* store = SSL_CTX_get_cert_store(context);
+  status = X509_STORE_add_cert(store, cert);
+  // X509_STORE_add_cert increments the reference count of cert on success.
+  X509_free(cert);
+  if (status == 0) {
+    return status;
+  }
+
+  X509* ca;
+  while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
+    status = X509_STORE_add_cert(store, ca);
+    // X509_STORE_add_cert increments the reference count of cert on success.
+    X509_free(ca);
+    if (status == 0) {
+      return status;
+    }
+  }
+
+  return status;
+}
+
+
+static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) {
+  X509_STORE* store = SSL_CTX_get_cert_store(context);
+
+  int status = 0;
+  X509* cert = NULL;
+  while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+    status = X509_STORE_add_cert(store, cert);
+    // X509_STORE_add_cert increments the reference count of cert on success.
+    X509_free(cert);
+    if (status == 0) {
+      return status;
+    }
+  }
+
+  // If no PEM start line is found, it means that we read to the end of the
+  // file, or that the file isn't PEM. In the first case, status will be
+  // non-zero indicating success. In the second case, status will be 0,
+  // indicating that we should try to read as PKCS12. If there is some other
+  // error, we return it up to the caller.
+  return SecureSocketUtils::NoPEMStartLine() ? status : 0;
+}
+
+
+void SSLCertContext::SetTrustedCertificatesBytes(Dart_Handle cert_bytes,
+                                                 const char* password) {
+  int status = 0;
+  {
+    ScopedMemBIO bio(cert_bytes);
+    status = SetTrustedCertificatesBytesPEM(context(), bio.bio());
+    if (status == 0) {
+      if (SecureSocketUtils::NoPEMStartLine()) {
+        ERR_clear_error();
+        BIO_reset(bio.bio());
+        status =
+            SetTrustedCertificatesBytesPKCS12(context(), bio.bio(), password);
+      }
+    } else {
+      // The PEM file was successfully parsed.
+      ERR_clear_error();
+    }
+  }
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure trusting builtin roots");
+}
+
+
+static int SetClientAuthoritiesPKCS12(SSL_CTX* context,
+                                      BIO* bio,
+                                      const char* password) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return 0;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509* cert = NULL;
+  STACK_OF(X509)* ca_certs = NULL;
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  if (status == 0) {
+    return status;
+  }
+
+  ScopedX509Stack cert_stack(ca_certs);
+  status = SSL_CTX_add_client_CA(context, cert);
+  // SSL_CTX_add_client_CA increments the reference count of cert on success.
+  X509_free(cert);
+  if (status == 0) {
+    return status;
+  }
+
+  X509* ca;
+  while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
+    status = SSL_CTX_add_client_CA(context, ca);
+    // SSL_CTX_add_client_CA increments the reference count of ca on success.
+    X509_free(ca);  // The name has been extracted.
+    if (status == 0) {
+      return status;
+    }
+  }
+
+  return status;
+}
+
+
+static int SetClientAuthoritiesPEM(SSL_CTX* context, BIO* bio) {
+  int status = 0;
+  X509* cert = NULL;
+  while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+    status = SSL_CTX_add_client_CA(context, cert);
+    X509_free(cert);  // The name has been extracted.
+    if (status == 0) {
+      return status;
+    }
+  }
+  return SecureSocketUtils::NoPEMStartLine() ? status : 0;
+}
+
+
+static int SetClientAuthorities(SSL_CTX* context,
+                                BIO* bio,
+                                const char* password) {
+  int status = SetClientAuthoritiesPEM(context, bio);
+  if (status == 0) {
+    if (SecureSocketUtils::NoPEMStartLine()) {
+      ERR_clear_error();
+      BIO_reset(bio);
+      status = SetClientAuthoritiesPKCS12(context, bio, password);
+    }
+  } else {
+    // The PEM file was successfully parsed.
+    ERR_clear_error();
+  }
+  return status;
+}
+
+
+void SSLCertContext::SetClientAuthoritiesBytes(
+    Dart_Handle client_authorities_bytes,
+    const char* password) {
+  int status;
+  {
+    ScopedMemBIO bio(client_authorities_bytes);
+    status = SetClientAuthorities(context(), bio.bio(), password);
+  }
+
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure in setClientAuthoritiesBytes");
+}
+
+void SSLCertContext::LoadRootCertFile(const char* file) {
+  if (SSL_LOG_STATUS) {
+    Log::Print("Looking for trusted roots in %s\n", file);
+  }
+  if (!File::Exists(file)) {
+    SecureSocketUtils::ThrowIOException(-1, "TlsException",
+                                        "Failed to find root cert file", NULL);
+  }
+  int status = SSL_CTX_load_verify_locations(context(), file, NULL);
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure trusting builtin roots");
+  if (SSL_LOG_STATUS) {
+    Log::Print("Trusting roots from: %s\n", file);
+  }
+}
+
+
+void SSLCertContext::AddCompiledInCerts() {
+  if (root_certificates_pem == NULL) {
+    if (SSL_LOG_STATUS) {
+      Log::Print("Missing compiled-in roots\n");
+    }
+    return;
+  }
+  X509_STORE* store = SSL_CTX_get_cert_store(context());
+  BIO* roots_bio =
+      BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem),
+                      root_certificates_pem_length);
+  X509* root_cert;
+  // PEM_read_bio_X509 reads PEM-encoded certificates from a bio (in our case,
+  // backed by a memory buffer), and returns X509 objects, one by one.
+  // When the end of the bio is reached, it returns null.
+  while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) {
+    int status = X509_STORE_add_cert(store, root_cert);
+    // X509_STORE_add_cert increments the reference count of cert on success.
+    X509_free(root_cert);
+    if (status == 0) {
+      break;
+    }
+  }
+  BIO_free(roots_bio);
+  // If there is an error here, it must be the error indicating that we are done
+  // reading PEM certificates.
+  ASSERT((ERR_peek_error() == 0) || SecureSocketUtils::NoPEMStartLine());
+  ERR_clear_error();
+}
+
+
+void SSLCertContext::LoadRootCertCache(const char* cache) {
+  if (SSL_LOG_STATUS) {
+    Log::Print("Looking for trusted roots in %s\n", cache);
+  }
+  if (Directory::Exists(cache) != Directory::EXISTS) {
+    SecureSocketUtils::ThrowIOException(-1, "TlsException",
+                                        "Failed to find root cert cache", NULL);
+  }
+  int status = SSL_CTX_load_verify_locations(context(), NULL, cache);
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure trusting builtin roots");
+  if (SSL_LOG_STATUS) {
+    Log::Print("Trusting roots from: %s\n", cache);
+  }
+}
+
+
+int PasswordCallback(char* buf, int size, int rwflag, void* userdata) {
+  char* password = static_cast<char*>(userdata);
+  ASSERT(size == PEM_BUFSIZE);
+  strncpy(buf, password, size);
+  return strlen(password);
+}
+
+
+static EVP_PKEY* GetPrivateKeyPKCS12(BIO* bio, const char* password) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return NULL;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509* cert = NULL;
+  STACK_OF(X509)* ca_certs = NULL;
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  if (status == 0) {
+    return NULL;
+  }
+
+  // We only care about the private key.
+  ScopedX509 delete_cert(cert);
+  ScopedX509Stack delete_ca_certs(ca_certs);
+  return key;
+}
+
+
+static EVP_PKEY* GetPrivateKey(BIO* bio, const char* password) {
+  EVP_PKEY* key = PEM_read_bio_PrivateKey(bio, NULL, PasswordCallback,
+                                          const_cast<char*>(password));
+  if (key == NULL) {
+    // We try reading data as PKCS12 only if reading as PEM was unsuccessful and
+    // if there is no indication that the data is malformed PEM. We assume the
+    // data is malformed PEM if it contains the start line, i.e. a line
+    // with ----- BEGIN.
+    if (SecureSocketUtils::NoPEMStartLine()) {
+      // Reset the bio, and clear the error from trying to read as PEM.
+      ERR_clear_error();
+      BIO_reset(bio);
+
+      // Try to decode as PKCS12.
+      key = GetPrivateKeyPKCS12(bio, password);
+    }
+  }
+  return key;
+}
+
+
+const char* SSLCertContext::GetPasswordArgument(Dart_NativeArguments args,
+                                                intptr_t index) {
+  Dart_Handle password_object =
+      ThrowIfError(Dart_GetNativeArgument(args, index));
+  const char* password = NULL;
+  if (Dart_IsString(password_object)) {
+    ThrowIfError(Dart_StringToCString(password_object, &password));
+    if (strlen(password) > PEM_BUFSIZE - 1) {
+      Dart_ThrowException(DartUtils::NewDartArgumentError(
+          "Password length is greater than 1023 (PEM_BUFSIZE)"));
+    }
+  } else if (Dart_IsNull(password_object)) {
+    password = "";
+  } else {
+    Dart_ThrowException(
+        DartUtils::NewDartArgumentError("Password is not a String or null"));
+  }
+  return password;
+}
+
+
+int AlpnCallback(SSL* ssl,
+                 const uint8_t** out,
+                 uint8_t* outlen,
+                 const uint8_t* in,
+                 unsigned int inlen,
+                 void* arg) {
+  // 'in' and 'arg' are sequences of (length, data) strings with 1-byte lengths.
+  // 'arg' is 0-terminated. Finds the first string in 'arg' that is in 'in'.
+  uint8_t* server_list = static_cast<uint8_t*>(arg);
+  while (*server_list != 0) {
+    uint8_t protocol_length = *server_list++;
+    const uint8_t* client_list = in;
+    while (client_list < in + inlen) {
+      uint8_t client_protocol_length = *client_list++;
+      if (client_protocol_length == protocol_length) {
+        if (0 == memcmp(server_list, client_list, protocol_length)) {
+          *out = client_list;
+          *outlen = client_protocol_length;
+          return SSL_TLSEXT_ERR_OK;  // Success
+        }
+      }
+      client_list += client_protocol_length;
+    }
+    server_list += protocol_length;
+  }
+  // TODO(23580): Make failure send a fatal alert instead of ignoring ALPN.
+  return SSL_TLSEXT_ERR_NOACK;
+}
+
+
+// Sets the protocol list for ALPN on a SSL object or a context.
+void SSLCertContext::SetAlpnProtocolList(Dart_Handle protocols_handle,
+                                         SSL* ssl,
+                                         SSLCertContext* context,
+                                         bool is_server) {
+  // Enable ALPN (application layer protocol negotiation) if the caller provides
+  // a valid list of supported protocols.
+  Dart_TypedData_Type protocols_type;
+  uint8_t* protocol_string = NULL;
+  uint8_t* protocol_string_copy = NULL;
+  intptr_t protocol_string_len = 0;
+  int status;
+
+  Dart_Handle result = Dart_TypedDataAcquireData(
+      protocols_handle, &protocols_type,
+      reinterpret_cast<void**>(&protocol_string), &protocol_string_len);
+  if (Dart_IsError(result)) {
+    Dart_PropagateError(result);
+  }
+
+  if (protocols_type != Dart_TypedData_kUint8) {
+    Dart_TypedDataReleaseData(protocols_handle);
+    Dart_PropagateError(Dart_NewApiError(
+        "Unexpected type for protocols (expected valid Uint8List)."));
+  }
+
+  if (protocol_string_len > 0) {
+    if (is_server) {
+      // ALPN on server connections must be set on an SSL_CTX object,
+      // not on the SSL object of the individual connection.
+      ASSERT(context != NULL);
+      ASSERT(ssl == NULL);
+      // Because it must be passed as a single void*, terminate
+      // the list of (length, data) strings with a length 0 string.
+      protocol_string_copy =
+          static_cast<uint8_t*>(malloc(protocol_string_len + 1));
+      memmove(protocol_string_copy, protocol_string, protocol_string_len);
+      protocol_string_copy[protocol_string_len] = '\0';
+      SSL_CTX_set_alpn_select_cb(context->context(), AlpnCallback,
+                                 protocol_string_copy);
+      context->set_alpn_protocol_string(protocol_string_copy);
+    } else {
+      // The function makes a local copy of protocol_string, which it owns.
+      if (ssl != NULL) {
+        ASSERT(context == NULL);
+        status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len);
+      } else {
+        ASSERT(context != NULL);
+        ASSERT(ssl == NULL);
+        status = SSL_CTX_set_alpn_protos(context->context(), protocol_string,
+                                         protocol_string_len);
+      }
+      ASSERT(status == 0);  // The function returns a non-standard status.
+    }
+  }
+  Dart_TypedDataReleaseData(protocols_handle);
+}
+
+
+static int UseChainBytesPKCS12(SSL_CTX* context,
+                               BIO* bio,
+                               const char* password) {
+  ScopedPKCS12 p12(d2i_PKCS12_bio(bio, NULL));
+  if (p12.get() == NULL) {
+    return 0;
+  }
+
+  EVP_PKEY* key = NULL;
+  X509* cert = NULL;
+  STACK_OF(X509)* ca_certs = NULL;
+  int status = PKCS12_parse(p12.get(), password, &key, &cert, &ca_certs);
+  if (status == 0) {
+    return status;
+  }
+
+  ScopedX509 x509(cert);
+  ScopedX509Stack certs(ca_certs);
+  status = SSL_CTX_use_certificate(context, x509.get());
+  if (ERR_peek_error() != 0) {
+    // Key/certificate mismatch doesn't imply status is 0.
+    status = 0;
+  }
+  if (status == 0) {
+    return status;
+  }
+
+  SSL_CTX_clear_chain_certs(context);
+
+  X509* ca;
+  while ((ca = sk_X509_shift(certs.get())) != NULL) {
+    status = SSL_CTX_add0_chain_cert(context, ca);
+    // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
+    // call fails.
+    if (status == 0) {
+      X509_free(ca);
+      return status;
+    }
+  }
+
+  return status;
+}
+
+
+static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) {
+  int status = 0;
+  ScopedX509 x509(PEM_read_bio_X509_AUX(bio, NULL, NULL, NULL));
+  if (x509.get() == NULL) {
+    return 0;
+  }
+
+  status = SSL_CTX_use_certificate(context, x509.get());
+  if (ERR_peek_error() != 0) {
+    // Key/certificate mismatch doesn't imply status is 0.
+    status = 0;
+  }
+  if (status == 0) {
+    return status;
+  }
+
+  SSL_CTX_clear_chain_certs(context);
+
+  X509* ca;
+  while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
+    status = SSL_CTX_add0_chain_cert(context, ca);
+    // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
+    // call fails.
+    if (status == 0) {
+      X509_free(ca);
+      return status;
+    }
+    // Note that we must not free `ca` if it was successfully added to the
+    // chain. We must free the main certificate x509, though since its reference
+    // count is increased by SSL_CTX_use_certificate.
+  }
+
+  return SecureSocketUtils::NoPEMStartLine() ? status : 0;
+}
+
+
+static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) {
+  int status = UseChainBytesPEM(context, bio);
+  if (status == 0) {
+    if (SecureSocketUtils::NoPEMStartLine()) {
+      ERR_clear_error();
+      BIO_reset(bio);
+      status = UseChainBytesPKCS12(context, bio, password);
+    }
+  } else {
+    // The PEM file was successfully read.
+    ERR_clear_error();
+  }
+  return status;
+}
+
+
+int SSLCertContext::UseCertificateChainBytes(Dart_Handle cert_chain_bytes,
+                                             const char* password) {
+  ScopedMemBIO bio(cert_chain_bytes);
+  return UseChainBytes(context(), bio.bio(), password);
+}
+
+
+static X509* GetX509Certificate(Dart_NativeArguments args) {
+  X509* certificate = NULL;
+  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
+  ASSERT(Dart_IsInstance(dart_this));
+  ThrowIfError(Dart_GetNativeInstanceField(
+      dart_this, SSLCertContext::kX509NativeFieldIndex,
+      reinterpret_cast<intptr_t*>(&certificate)));
+  return certificate;
+}
+
+
+Dart_Handle X509Helper::GetSubject(Dart_NativeArguments args) {
+  X509* certificate = GetX509Certificate(args);
+  X509_NAME* subject = X509_get_subject_name(certificate);
+  char* subject_string = X509_NAME_oneline(subject, NULL, 0);
+  if (subject_string == NULL) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.subject failed to find subject's common name."));
+  }
+  Dart_Handle subject_handle = Dart_NewStringFromCString(subject_string);
+  OPENSSL_free(subject_string);
+  return subject_handle;
+}
+
+
+Dart_Handle X509Helper::GetIssuer(Dart_NativeArguments args) {
+  fprintf(stdout, "Getting issuer!\n");
+  X509* certificate = GetX509Certificate(args);
+  X509_NAME* issuer = X509_get_issuer_name(certificate);
+  char* issuer_string = X509_NAME_oneline(issuer, NULL, 0);
+  if (issuer_string == NULL) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "X509.issuer failed to find issuer's common name."));
+  }
+  Dart_Handle issuer_handle = Dart_NewStringFromCString(issuer_string);
+  OPENSSL_free(issuer_string);
+  return issuer_handle;
+}
+
+
+static Dart_Handle ASN1TimeToMilliseconds(ASN1_TIME* aTime) {
+  ASN1_UTCTIME* epoch_start = M_ASN1_UTCTIME_new();
+  ASN1_UTCTIME_set_string(epoch_start, "700101000000Z");
+  int days;
+  int seconds;
+  int result = ASN1_TIME_diff(&days, &seconds, epoch_start, aTime);
+  M_ASN1_UTCTIME_free(epoch_start);
+  if (result != 1) {
+    // TODO(whesse): Propagate an error to Dart.
+    Log::PrintErr("ASN1Time error %d\n", result);
+  }
+  return Dart_NewInteger((86400LL * days + seconds) * 1000LL);
+}
+
+
+Dart_Handle X509Helper::GetStartValidity(Dart_NativeArguments args) {
+  X509* certificate = GetX509Certificate(args);
+  ASN1_TIME* not_before = X509_get_notBefore(certificate);
+  return ASN1TimeToMilliseconds(not_before);
+}
+
+
+Dart_Handle X509Helper::GetEndValidity(Dart_NativeArguments args) {
+  X509* certificate = GetX509Certificate(args);
+  ASN1_TIME* not_after = X509_get_notAfter(certificate);
+  return ASN1TimeToMilliseconds(not_after);
+}
+
+void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+  const char* password = SSLCertContext::GetPasswordArgument(args, 2);
+
+  int status;
+  {
+    ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
+    EVP_PKEY* key = GetPrivateKey(bio.bio(), password);
+    status = SSL_CTX_use_PrivateKey(context->context(), key);
+    // SSL_CTX_use_PrivateKey increments the reference count of key on success,
+    // so we have to call EVP_PKEY_free on both success and failure.
+    EVP_PKEY_free(key);
+  }
+
+  // TODO(24184): Handle different expected errors here - file missing,
+  // incorrect password, file not a PEM, and throw exceptions.
+  // SecureSocketUtils::CheckStatus should also throw an exception in uncaught
+  // cases.
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure in usePrivateKeyBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
+  SSLFilter::InitializeLibrary();
+  SSL_CTX* ctx = SSL_CTX_new(TLS_method());
+  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLCertContext::CertificateCallback);
+  SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
+  SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM");
+  SSLCertContext* context = new SSLCertContext(ctx);
+  Dart_Handle err = SetSecurityContext(args, context);
+  if (Dart_IsError(err)) {
+    delete context;
+    Dart_PropagateError(err);
+  }
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+  Dart_Handle cert_bytes = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  const char* password = SSLCertContext::GetPasswordArgument(args, 2);
+
+  ASSERT(context != NULL);
+  ASSERT(password != NULL);
+  context->SetTrustedCertificatesBytes(cert_bytes, password);
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+  Dart_Handle client_authorities_bytes =
+      ThrowIfError(Dart_GetNativeArgument(args, 1));
+  const char* password = SSLCertContext::GetPasswordArgument(args, 2);
+
+  ASSERT(context != NULL);
+  ASSERT(password != NULL);
+
+  context->SetClientAuthoritiesBytes(client_authorities_bytes, password);
+}
+
+
+void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+  Dart_Handle cert_chain_bytes = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  const char* password = SSLCertContext::GetPasswordArgument(args, 2);
+
+  ASSERT(context != NULL);
+  ASSERT(password != NULL);
+
+  int status = context->UseCertificateChainBytes(cert_chain_bytes, password);
+
+  SecureSocketUtils::CheckStatus(status, "TlsException",
+                                 "Failure in useCertificateChainBytes");
+}
+
+
+void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, Dart_NewBoolean(true));
+}
+
+
+void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+
+  ASSERT(context != NULL);
+
+  context->TrustBuiltinRoots();
+}
+
+
+void FUNCTION_NAME(X509_Subject)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, X509Helper::GetSubject(args));
+}
+
+
+void FUNCTION_NAME(X509_Issuer)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, X509Helper::GetIssuer(args));
+}
+
+
+void FUNCTION_NAME(X509_StartValidity)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, X509Helper::GetStartValidity(args));
+}
+
+
+void FUNCTION_NAME(X509_EndValidity)(Dart_NativeArguments args) {
+  Dart_SetReturnValue(args, X509Helper::GetEndValidity(args));
+}
+
+
+void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
+    Dart_NativeArguments args) {
+  SSLCertContext* context = SSLCertContext::GetSecurityContext(args);
+  Dart_Handle protocols_handle = ThrowIfError(Dart_GetNativeArgument(args, 1));
+  Dart_Handle is_server_handle = ThrowIfError(Dart_GetNativeArgument(args, 2));
+  if (Dart_IsBoolean(is_server_handle)) {
+    bool is_server = DartUtils::GetBooleanValue(is_server_handle);
+    SSLCertContext::SetAlpnProtocolList(protocols_handle, NULL, context,
+                                        is_server);
+  } else {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Non-boolean is_server argument passed to SetAlpnProtocols"));
+  }
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/security_context.h b/runtime/bin/security_context.h
new file mode 100644
index 0000000..eaba5a5
--- /dev/null
+++ b/runtime/bin/security_context.h
@@ -0,0 +1,104 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_BIN_SECURITY_CONTEXT_H_
+#define RUNTIME_BIN_SECURITY_CONTEXT_H_
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/lockers.h"
+#include "bin/reference_counting.h"
+#include "bin/socket.h"
+
+namespace dart {
+namespace bin {
+
+// Forward declaration
+class SSLFilter;
+
+class SSLCertContext : public ReferenceCounted<SSLCertContext> {
+ public:
+  static const intptr_t kApproximateSize;
+  static const int kSecurityContextNativeFieldIndex = 0;
+  static const int kX509NativeFieldIndex = 0;
+
+  explicit SSLCertContext(SSL_CTX* context)
+      : ReferenceCounted(),
+        context_(context),
+        alpn_protocol_string_(NULL),
+        trust_builtin_(false) {}
+
+  ~SSLCertContext() {
+    SSL_CTX_free(context_);
+    if (alpn_protocol_string_ != NULL) {
+      free(alpn_protocol_string_);
+    }
+  }
+
+  static int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx);
+
+  static SSLCertContext* GetSecurityContext(Dart_NativeArguments args);
+  static const char* GetPasswordArgument(Dart_NativeArguments args,
+                                         intptr_t index);
+  static void SetAlpnProtocolList(Dart_Handle protocols_handle,
+                                  SSL* ssl,
+                                  SSLCertContext* context,
+                                  bool is_server);
+
+  void SetTrustedCertificatesBytes(Dart_Handle cert_bytes,
+                                   const char* password);
+
+  void SetClientAuthoritiesBytes(Dart_Handle client_authorities_bytes,
+                                 const char* password);
+
+  int UseCertificateChainBytes(Dart_Handle cert_chain_bytes,
+                               const char* password);
+
+  void TrustBuiltinRoots();
+
+  SSL_CTX* context() const { return context_; }
+
+  uint8_t* alpn_protocol_string() const { return alpn_protocol_string_; }
+
+  void set_alpn_protocol_string(uint8_t* protocol_string) {
+    if (alpn_protocol_string_ != NULL) {
+      free(alpn_protocol_string_);
+    }
+    alpn_protocol_string_ = protocol_string;
+  }
+
+  bool trust_builtin() const { return trust_builtin_; }
+
+  void set_trust_builtin(bool trust_builtin) { trust_builtin_ = trust_builtin; }
+
+  void RegisterCallbacks(SSL* ssl);
+
+ private:
+  void AddCompiledInCerts();
+  void LoadRootCertFile(const char* file);
+  void LoadRootCertCache(const char* cache);
+
+  SSL_CTX* context_;
+  uint8_t* alpn_protocol_string_;
+
+  bool trust_builtin_;
+
+  DISALLOW_COPY_AND_ASSIGN(SSLCertContext);
+};
+
+
+class X509Helper : public AllStatic {
+ public:
+  static Dart_Handle GetSubject(Dart_NativeArguments args);
+  static Dart_Handle GetIssuer(Dart_NativeArguments args);
+  static Dart_Handle GetStartValidity(Dart_NativeArguments args);
+  static Dart_Handle GetEndValidity(Dart_NativeArguments args);
+  static Dart_Handle WrappedX509Certificate(X509* certificate);
+};
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // RUNTIME_BIN_SECURITY_CONTEXT_H_
diff --git a/runtime/bin/security_context_android.cc b/runtime/bin/security_context_android.cc
new file mode 100644
index 0000000..dc4eaf8
--- /dev/null
+++ b/runtime/bin/security_context_android.cc
@@ -0,0 +1,71 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "platform/globals.h"
+#if defined(HOST_OS_ANDROID)
+
+#include "bin/security_context.h"
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/secure_socket_utils.h"
+
+namespace dart {
+namespace bin {
+
+// The security context won't necessarily use the compiled-in root certificates,
+// but since there is no way to update the size of the allocation after creating
+// the weak persistent handle, we assume that it will. Note that when the
+// root certs aren't compiled in, |root_certificates_pem_length| is 0.
+const intptr_t SSLCertContext::kApproximateSize =
+    sizeof(SSLCertContext) + root_certificates_pem_length;
+
+const char* commandline_root_certs_file = NULL;
+const char* commandline_root_certs_cache = NULL;
+
+void SSLCertContext::TrustBuiltinRoots() {
+  // First, try to use locations specified on the command line.
+  if (commandline_root_certs_file != NULL) {
+    LoadRootCertFile(commandline_root_certs_file);
+    return;
+  }
+
+  if (commandline_root_certs_cache != NULL) {
+    LoadRootCertCache(commandline_root_certs_cache);
+    return;
+  }
+
+  // On Android, we don't compile in the trusted root certificates. Insead,
+  // we use the directory of trusted certificates already present on the device.
+  // This saves ~240KB from the size of the binary. This has the drawback that
+  // SSL_do_handshake will synchronously hit the filesystem looking for root
+  // certs during its trust evaluation. We call SSL_do_handshake directly from
+  // the Dart thread so that Dart code can be invoked from the "bad certificate"
+  // callback called by SSL_do_handshake.
+  const char* android_cacerts = "/system/etc/security/cacerts";
+  LoadRootCertCache(android_cacerts);
+  return;
+}
+
+
+void SSLCertContext::RegisterCallbacks(SSL* ssl) {
+  // No callbacks to register for implementations using BoringSSL's built-in
+  // verification mechanism.
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(HOST_OS_ANDROID)
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/security_context_fuchsia.cc b/runtime/bin/security_context_fuchsia.cc
new file mode 100644
index 0000000..c49476b
--- /dev/null
+++ b/runtime/bin/security_context_fuchsia.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "platform/globals.h"
+#if defined(HOST_OS_FUCHSIA)
+
+#include "bin/security_context.h"
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/secure_socket_utils.h"
+
+namespace dart {
+namespace bin {
+
+// The security context won't necessarily use the compiled-in root certificates,
+// but since there is no way to update the size of the allocation after creating
+// the weak persistent handle, we assume that it will. Note that when the
+// root certs aren't compiled in, |root_certificates_pem_length| is 0.
+const intptr_t SSLCertContext::kApproximateSize =
+    sizeof(SSLCertContext) + root_certificates_pem_length;
+
+const char* commandline_root_certs_file = NULL;
+const char* commandline_root_certs_cache = NULL;
+
+void SSLCertContext::TrustBuiltinRoots() {
+  // First, try to use locations specified on the command line.
+  if (commandline_root_certs_file != NULL) {
+    LoadRootCertFile(commandline_root_certs_file);
+    return;
+  }
+
+  if (commandline_root_certs_cache != NULL) {
+    LoadRootCertCache(commandline_root_certs_cache);
+    return;
+  }
+
+  // Fall back on the compiled-in certs if the standard locations don't exist,
+  // or we aren't on Linux.
+  if (SSL_LOG_STATUS) {
+    Log::Print("Trusting compiled-in roots\n");
+  }
+  AddCompiledInCerts();
+}
+
+
+void SSLCertContext::RegisterCallbacks(SSL* ssl) {
+  // No callbacks to register for implementations using BoringSSL's built-in
+  // verification mechanism.
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(HOST_OS_FUCHSIA)
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/security_context_linux.cc b/runtime/bin/security_context_linux.cc
new file mode 100644
index 0000000..2985fff
--- /dev/null
+++ b/runtime/bin/security_context_linux.cc
@@ -0,0 +1,84 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "platform/globals.h"
+#if defined(HOST_OS_LINUX)
+
+#include "bin/security_context.h"
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/secure_socket_utils.h"
+
+namespace dart {
+namespace bin {
+
+// The security context won't necessarily use the compiled-in root certificates,
+// but since there is no way to update the size of the allocation after creating
+// the weak persistent handle, we assume that it will. Note that when the
+// root certs aren't compiled in, |root_certificates_pem_length| is 0.
+const intptr_t SSLCertContext::kApproximateSize =
+    sizeof(SSLCertContext) + root_certificates_pem_length;
+
+const char* commandline_root_certs_file = NULL;
+const char* commandline_root_certs_cache = NULL;
+
+void SSLCertContext::TrustBuiltinRoots() {
+  // First, try to use locations specified on the command line.
+  if (commandline_root_certs_file != NULL) {
+    LoadRootCertFile(commandline_root_certs_file);
+    return;
+  }
+
+  if (commandline_root_certs_cache != NULL) {
+    LoadRootCertCache(commandline_root_certs_cache);
+    return;
+  }
+
+  // On Linux, we use the compiled-in trusted certs as a last resort. First,
+  // we try to find the trusted certs in various standard locations. A good
+  // discussion of the complexities of this endeavor can be found here:
+  //
+  // https://www.happyassassin.net/2015/01/12/a-note-about-ssltls-trusted-certificate-stores-and-platforms/
+  const char* bundle = "/etc/pki/tls/certs/ca-bundle.crt";
+  const char* cachedir = "/etc/ssl/certs";
+  if (File::Exists(bundle)) {
+    LoadRootCertFile(bundle);
+    return;
+  }
+
+  if (Directory::Exists(cachedir) == Directory::EXISTS) {
+    LoadRootCertCache(cachedir);
+    return;
+  }
+
+  // Fall back on the compiled-in certs if the standard locations don't exist,
+  // or we aren't on Linux.
+  if (SSL_LOG_STATUS) {
+    Log::Print("Trusting compiled-in roots\n");
+  }
+  AddCompiledInCerts();
+}
+
+
+void SSLCertContext::RegisterCallbacks(SSL* ssl) {
+  // No callbacks to register for implementations using BoringSSL's built-in
+  // verification mechanism.
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(HOST_OS_LINUX)
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/security_context_macos.cc b/runtime/bin/security_context_macos.cc
new file mode 100644
index 0000000..3ae88f7
--- /dev/null
+++ b/runtime/bin/security_context_macos.cc
@@ -0,0 +1,191 @@
+// Copyright (c) 2017 the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "platform/globals.h"
+#if defined(HOST_OS_MACOS)
+
+#include "bin/security_context.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <Security/SecureTransport.h>
+#include <Security/Security.h>
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/secure_socket_filter.h"
+
+namespace dart {
+namespace bin {
+
+const intptr_t SSLCertContext::kApproximateSize = sizeof(SSLCertContext);
+
+const char* commandline_root_certs_file = NULL;
+const char* commandline_root_certs_cache = NULL;
+
+template <typename T>
+class ScopedCFType {
+ public:
+  explicit ScopedCFType(T obj) : obj_(obj) {}
+
+  ~ScopedCFType() { CFRelease(obj_); }
+
+  T get() { return obj_; }
+  T* ptr() { return &obj_; }
+  const T get() const { return obj_; }
+
+  void set(T obj) { obj_ = obj; }
+
+ private:
+  T obj_;
+
+  DISALLOW_ALLOCATION();
+  DISALLOW_COPY_AND_ASSIGN(ScopedCFType);
+};
+
+typedef ScopedCFType<CFMutableArrayRef> ScopedCFMutableArrayRef;
+typedef ScopedCFType<CFDataRef> ScopedCFDataRef;
+typedef ScopedCFType<SecPolicyRef> ScopedSecPolicyRef;
+typedef ScopedCFType<SecCertificateRef> ScopedSecCertificateRef;
+typedef ScopedCFType<SecTrustRef> ScopedSecTrustRef;
+
+static SecCertificateRef CreateSecCertificateFromX509(X509* cert) {
+  if (cert == NULL) {
+    return NULL;
+  }
+  unsigned char* deb_cert = NULL;
+  int length = i2d_X509(cert, &deb_cert);
+  if (length < 0) {
+    return 0;
+  }
+  ASSERT(deb_cert != NULL);
+  ScopedCFDataRef cert_buf(
+      CFDataCreateWithBytesNoCopy(NULL, deb_cert, length, kCFAllocatorNull));
+  SecCertificateRef auth_cert =
+      SecCertificateCreateWithData(NULL, cert_buf.get());
+  if (auth_cert == NULL) {
+    return NULL;
+  }
+  return auth_cert;
+}
+
+
+static int CertificateVerificationCallback(X509_STORE_CTX* ctx, void* arg) {
+  SSLCertContext* context = static_cast<SSLCertContext*>(arg);
+
+  // Convert BoringSSL formatted certificates to SecCertificate certificates.
+  ScopedCFMutableArrayRef cert_chain(NULL);
+  X509* root_cert = NULL;
+  if (ctx->untrusted != NULL) {
+    STACK_OF(X509)* user_provided_certs = ctx->untrusted;
+    int num_certs = sk_X509_num(user_provided_certs);
+    int current_cert = 0;
+    cert_chain.set(CFArrayCreateMutable(NULL, num_certs, NULL));
+    X509* ca;
+    while ((ca = sk_X509_shift(user_provided_certs)) != NULL) {
+      SecCertificateRef cert = CreateSecCertificateFromX509(ca);
+      if (cert == NULL) {
+        return ctx->verify_cb(0, ctx);
+      }
+      CFArrayAppendValue(cert_chain.get(), cert);
+      ++current_cert;
+
+      if (current_cert == num_certs) {
+        root_cert = ca;
+      }
+    }
+  }
+
+  // Convert all trusted certificates provided by the user via
+  // setTrustedCertificatesBytes or the command line into SecCertificates.
+  ScopedCFMutableArrayRef trusted_certs(CFArrayCreateMutable(NULL, 0, NULL));
+  X509_STORE* store = ctx->ctx;
+  ASSERT(store != NULL);
+
+  if (store->objs != NULL) {
+    for (uintptr_t i = 0; i < sk_X509_OBJECT_num(store->objs); ++i) {
+      X509* ca = sk_X509_OBJECT_value(store->objs, i)->data.x509;
+      SecCertificateRef cert = CreateSecCertificateFromX509(ca);
+      if (cert == NULL) {
+        return ctx->verify_cb(0, ctx);
+      }
+      CFArrayAppendValue(trusted_certs.get(), cert);
+    }
+  }
+
+  // Generate a generic X509 verification policy.
+  ScopedSecPolicyRef policy(SecPolicyCreateBasicX509());
+
+  // Create the trust object with the certificates provided by the user.
+  ScopedSecTrustRef trust(NULL);
+  OSStatus status = SecTrustCreateWithCertificates(cert_chain.get(),
+                                                   policy.get(), trust.ptr());
+  if (status != noErr) {
+    return ctx->verify_cb(0, ctx);
+  }
+
+  // If the user provided any additional CA certificates, add them to the trust
+  // object.
+  if (CFArrayGetCount(trusted_certs.get()) > 0) {
+    status = SecTrustSetAnchorCertificates(trust.get(), trusted_certs.get());
+    if (status != noErr) {
+      return ctx->verify_cb(0, ctx);
+    }
+  }
+
+  // Specify whether or not to use the built-in CA certificates for
+  // verification.
+  status =
+      SecTrustSetAnchorCertificatesOnly(trust.get(), !context->trust_builtin());
+  if (status != noErr) {
+    return ctx->verify_cb(0, ctx);
+  }
+
+  // Perform the certificate verification.
+  SecTrustResultType trust_result;
+  status = SecTrustEvaluate(trust.get(), &trust_result);
+  if (status != noErr) {
+    return ctx->verify_cb(0, ctx);
+  }
+
+  if ((trust_result == kSecTrustResultProceed) ||
+      (trust_result == kSecTrustResultUnspecified)) {
+    // Successfully verified certificate!
+    return ctx->verify_cb(1, ctx);
+  }
+
+  // Set current_cert to the root of the certificate chain. This will be passed
+  // to the callback provided by the user for additional verification steps.
+  ctx->current_cert = root_cert;
+  return ctx->verify_cb(0, ctx);
+}
+
+
+void SSLCertContext::RegisterCallbacks(SSL* ssl) {
+  SSL_CTX* ctx = SSL_get_SSL_CTX(ssl);
+  SSL_CTX_set_cert_verify_callback(ctx, CertificateVerificationCallback, this);
+}
+
+
+void SSLCertContext::TrustBuiltinRoots() {
+  // First, try to use locations specified on the command line.
+  if (commandline_root_certs_file != NULL) {
+    LoadRootCertFile(commandline_root_certs_file);
+    return;
+  }
+  if (commandline_root_certs_cache != NULL) {
+    LoadRootCertCache(commandline_root_certs_cache);
+    return;
+  }
+  set_trust_builtin(true);
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(HOST_OS_MACOS)
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/runtime/bin/security_context_win.cc b/runtime/bin/security_context_win.cc
new file mode 100644
index 0000000..2c228c3
--- /dev/null
+++ b/runtime/bin/security_context_win.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(DART_IO_DISABLED) && !defined(DART_IO_SECURE_SOCKET_DISABLED)
+
+#include "platform/globals.h"
+#if defined(HOST_OS_WINDOWS)
+
+#include "bin/security_context.h"
+
+#include <openssl/bio.h>
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include "bin/directory.h"
+#include "bin/file.h"
+#include "bin/log.h"
+#include "bin/secure_socket_filter.h"
+#include "bin/secure_socket_utils.h"
+
+namespace dart {
+namespace bin {
+
+// The security context won't necessarily use the compiled-in root certificates,
+// but since there is no way to update the size of the allocation after creating
+// the weak persistent handle, we assume that it will. Note that when the
+// root certs aren't compiled in, |root_certificates_pem_length| is 0.
+const intptr_t SSLCertContext::kApproximateSize =
+    sizeof(SSLCertContext) + root_certificates_pem_length;
+
+const char* commandline_root_certs_file = NULL;
+const char* commandline_root_certs_cache = NULL;
+
+void SSLCertContext::TrustBuiltinRoots() {
+  // First, try to use locations specified on the command line.
+  if (commandline_root_certs_file != NULL) {
+    LoadRootCertFile(commandline_root_certs_file);
+    return;
+  }
+
+  if (commandline_root_certs_cache != NULL) {
+    LoadRootCertCache(commandline_root_certs_cache);
+    return;
+  }
+
+  // Fall back on the compiled-in certs if the standard locations don't exist,
+  // or we aren't on Linux.
+  if (SSL_LOG_STATUS) {
+    Log::Print("Trusting compiled-in roots\n");
+  }
+  AddCompiledInCerts();
+}
+
+
+void SSLCertContext::RegisterCallbacks(SSL* ssl) {
+  // No callbacks to register for implementations using BoringSSL's built-in
+  // verification mechanism.
+}
+
+}  // namespace bin
+}  // namespace dart
+
+#endif  // defined(HOST_OS_WINDOWS)
+
+#endif  // !defined(DART_IO_DISABLED) &&
+        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 59aa7ff..688cf4a 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -451,7 +451,7 @@
 @patch
 class SecurityContext {
   @patch
-  factory SecurityContext() {
+  factory SecurityContext({bool withTrustedRoots: false}) {
     throw new UnsupportedError("SecurityContext constructor");
   }
 
diff --git a/sdk/lib/io/security_context.dart b/sdk/lib/io/security_context.dart
index 8d55c19..7169370 100644
--- a/sdk/lib/io/security_context.dart
+++ b/sdk/lib/io/security_context.dart
@@ -20,7 +20,21 @@
  * be used, by way of [SecurityContext.defaultContext].
  */
 abstract class SecurityContext {
-  external factory SecurityContext();
+  /**
+   * Creates a new [SecurityContext].
+   *
+   * By default, the created [SecurityContext] contains no keys or certificates.
+   * These can be added by calling the methods of this class.
+   *
+   * If `withTrustedRoots` is passed as `true`, the [SecurityContext] will be
+   * seeded by the trusted root certificates provided as explained below. To
+   * obtain a [SecurityContext] containing trusted root certificates,
+   * [SecurityContext.defaultContext] is usually sufficient, and should
+   * be used instead. However, if the [SecurityContext] containing the trusted
+   * root certificates must be modified per-connection, then `withTrustedRoots`
+   * should be used.
+   */
+  external factory SecurityContext({bool withTrustedRoots: false});
 
   /**
    * Secure networking classes with an optional `context` parameter
diff --git a/tests/standalone/io/secure_builtin_roots_test.dart b/tests/standalone/io/secure_builtin_roots_test.dart
index e1c5321..2b1ddee 100644
--- a/tests/standalone/io/secure_builtin_roots_test.dart
+++ b/tests/standalone/io/secure_builtin_roots_test.dart
@@ -35,6 +35,8 @@
   asyncStart();
   await testGoogleUrl(null, "pass");
   await testGoogleUrl(SecurityContext.defaultContext, "pass");
+  await testGoogleUrl(new SecurityContext(withTrustedRoots: true), "pass");
+  await testGoogleUrl(new SecurityContext(withTrustedRoots: false), "fail");
   await testGoogleUrl(new SecurityContext(), "fail");
   asyncEnd();
 }
diff --git a/tools/VERSION b/tools/VERSION
index 123dfeb..7be09ef 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -26,6 +26,6 @@
 CHANNEL stable
 MAJOR 1
 MINOR 24
-PATCH 2
+PATCH 3
 PRERELEASE 0
 PRERELEASE_PATCH 0