// 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(TARGET_OS_MACOS) && !TARGET_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(TARGET_OS_MACOS) && !TARGET_OS_IOS

#endif  // !defined(DART_IO_DISABLED) &&
        // !defined(DART_IO_SECURE_SOCKET_DISABLED)
