// 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.

#include "bin/secure_socket.h"

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>

#include <key.h>
#include <keyt.h>
#include <nss.h>
#include <pk11pub.h>
#include <prerror.h>
#include <prinit.h>
#include <prnetdb.h>
#include <secmod.h>
#include <ssl.h>
#include <sslproto.h>

#include "bin/builtin.h"
#include "bin/dartutils.h"
#include "bin/lockers.h"
#include "bin/net/nss_memio.h"
#include "bin/socket.h"
#include "bin/thread.h"
#include "bin/utils.h"
#include "platform/utils.h"

#include "include/dart_api.h"


namespace dart {
namespace bin {

bool SSLFilter::library_initialized_ = false;
// To protect library initialization.
Mutex* SSLFilter::mutex_ = new Mutex();
// The password is needed when creating secure server sockets.  It can
// be null if only secure client sockets are used.
const char* SSLFilter::password_ = NULL;

static const int kSSLFilterNativeFieldIndex = 0;


/* Handle an error reported from the NSS library. */
static void ThrowPRException(const char* exception_type,
                             const char* message,
                             bool free_message = false) {
  PRErrorCode error_code = PR_GetError();
  const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN);
  OSError os_error_struct(error_code, error_message, OSError::kNSS);
  Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
  Dart_Handle exception =
      DartUtils::NewDartIOException(exception_type, message, os_error);
  if (free_message) {
    free(const_cast<char*>(message));
  }
  Dart_ThrowException(exception);
}


static void ThrowCertificateException(const char* format,
                                      const char* certificate_name) {
  int length = strlen(certificate_name);
  length += strlen(format);
  char* message = reinterpret_cast<char*>(malloc(length + 1));
  if (message == NULL) {
    FATAL("Out of memory formatting CertificateException for throwing");
  }
  snprintf(message, length + 1, format, certificate_name);
  message[length] = '\0';
  ThrowPRException("CertificateException", message, true);
}


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 SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
  ASSERT(Dart_IsInstance(dart_this));
  ThrowIfError(Dart_SetNativeInstanceField(
      dart_this,
      kSSLFilterNativeFieldIndex,
      reinterpret_cast<intptr_t>(filter)));
}


void FUNCTION_NAME(SecureSocket_Init)(Dart_NativeArguments args) {
  Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
  SSLFilter* filter = new SSLFilter;
  SetFilter(args, filter);
  filter->Init(dart_this);
}


void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
  Dart_Handle host_name_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
  Dart_Handle host_sockaddr_storage_object =
      ThrowIfError(Dart_GetNativeArgument(args, 2));
  Dart_Handle port_object = ThrowIfError(Dart_GetNativeArgument(args, 3));
  bool is_server = DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 4));
  Dart_Handle certificate_name_object =
      ThrowIfError(Dart_GetNativeArgument(args, 5));
  bool request_client_certificate =
      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 6));
  bool require_client_certificate =
      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 7));
  bool send_client_certificate =
      DartUtils::GetBooleanValue(Dart_GetNativeArgument(args, 8));

  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));

  RawAddr raw_addr;
  SocketAddress::GetSockAddr(host_sockaddr_storage_object, &raw_addr);

  int64_t port;
  if (!DartUtils::GetInt64Value(port_object, &port)) {
    FATAL("The range of port_object was checked in Dart - it cannot fail here");
  }

  const char* certificate_name = NULL;
  if (Dart_IsString(certificate_name_object)) {
    ThrowIfError(Dart_StringToCString(certificate_name_object,
                                      &certificate_name));
  }
  // If this is a server connection, it must have a certificate to connect with.
  ASSERT(!is_server || certificate_name != NULL);

  GetFilter(args)->Connect(host_name,
                           &raw_addr,
                           static_cast<int>(port),
                           is_server,
                           certificate_name,
                           request_client_certificate,
                           require_client_certificate,
                           send_client_certificate);
}


void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
  SSLFilter* filter = GetFilter(args);
  SetFilter(args, NULL);
  filter->Destroy();
  delete filter;
}


void FUNCTION_NAME(SecureSocket_Handshake)(Dart_NativeArguments args) {
  GetFilter(args)->Handshake();
}


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_InitializeLibrary)
    (Dart_NativeArguments args) {
  Dart_Handle certificate_database_object =
      ThrowIfError(Dart_GetNativeArgument(args, 0));
  // Check that the type is string, and get the UTF-8 C string value from it.
  const char* certificate_database = NULL;
  if (Dart_IsString(certificate_database_object)) {
    ThrowIfError(Dart_StringToCString(certificate_database_object,
                                      &certificate_database));
  } else if (!Dart_IsNull(certificate_database_object)) {
    Dart_ThrowException(DartUtils::NewDartArgumentError(
        "Non-String certificate directory argument to SetCertificateDatabase"));
  }
  // Leave certificate_database as NULL if no value was provided.

  Dart_Handle password_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
  // Check that the type is string or null,
  // and get the UTF-8 C string value from it.
  const char* password = NULL;
  if (Dart_IsString(password_object)) {
    ThrowIfError(Dart_StringToCString(password_object, &password));
  } else if (Dart_IsNull(password_object)) {
    // Pass the empty string as the password.
    password = "";
  } else {
    Dart_ThrowException(DartUtils::NewDartArgumentError(
        "Password argument to SetCertificateDatabase is not a String or null"));
  }

  Dart_Handle builtin_roots_object =
      ThrowIfError(Dart_GetNativeArgument(args, 2));
  // Check that the type is boolean, and get the boolean value from it.
  bool builtin_roots = true;
  if (Dart_IsBoolean(builtin_roots_object)) {
    ThrowIfError(Dart_BooleanValue(builtin_roots_object, &builtin_roots));
  } else {
    Dart_ThrowException(DartUtils::NewDartArgumentError(
        "UseBuiltinRoots argument to SetCertificateDatabase is not a bool"));
  }

  SSLFilter::InitializeLibrary(certificate_database, password, builtin_roots);
}


void FUNCTION_NAME(SecureSocket_PeerCertificate)
    (Dart_NativeArguments args) {
  Dart_SetReturnValue(args, GetFilter(args)->PeerCertificate());
}


void FUNCTION_NAME(SecureSocket_FilterPointer)(Dart_NativeArguments args) {
  intptr_t filter_pointer = reinterpret_cast<intptr_t>(GetFilter(args));
  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());
  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 {
    PRErrorCode error_code = PR_GetError();
    const char* error_message = PR_ErrorToString(error_code, PR_LANGUAGE_EN);
    CObjectArray* result = new CObjectArray(CObject::NewArray(2));
    result->SetAt(0, new CObjectInt32(CObject::NewInt32(error_code)));
    result->SetAt(1, new CObjectString(CObject::NewString(error_message)));
    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:
        // Read data from circular buffer.
        if (end < start) {
          // Data may be split into two segments.  In this case,
          // the first is [start, size).
          int bytes = ProcessReadEncryptedBuffer(start, size);
          if (bytes < 0) return false;
          start += bytes;
          ASSERT(start <= size);
          if (start == size) start = 0;
        }
        if (start < end) {
          int bytes = ProcessReadEncryptedBuffer(start, end);
          if (bytes < 0) return false;
          start += bytes;
          ASSERT(start <= end);
        }
        starts[i] = start;
        break;
      case kWritePlaintext:
        if (end < start) {
          // Data is split into two segments, [start, size) and [0, end).
          int bytes = ProcessWritePlaintextBuffer(start, size, 0, end);
          if (bytes < 0) return false;
          start += bytes;
          if (start >= size) start -= size;
        } else {
          int bytes = ProcessWritePlaintextBuffer(start, end, 0, 0);
          if (bytes < 0) return false;
          start += bytes;
          ASSERT(start <= end);
        }
        starts[i] = start;
        break;
      default:
        UNREACHABLE();
    }
  }
  return true;
}


static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
  PRTime start_validity;
  PRTime end_validity;
  SECStatus status =
      CERT_GetCertTimes(certificate, &start_validity, &end_validity);
  if (status != SECSuccess) {
    ThrowPRException("CertificateException",
                     "Cannot get validity times from certificate");
  }
  int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
  int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
  Dart_Handle subject_name_object =
      DartUtils::NewString(certificate->subjectName);
  Dart_Handle issuer_name_object =
      DartUtils::NewString(certificate->issuerName);
  Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
  Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);

  Dart_Handle date_type =
      DartUtils::GetDartType(DartUtils::kCoreLibURL, "DateTime");
  Dart_Handle from_milliseconds =
      DartUtils::NewString("fromMillisecondsSinceEpoch");

  Dart_Handle start_validity_date =
      Dart_New(date_type, from_milliseconds, 1, &start_epoch_ms_int);
  Dart_Handle end_validity_date =
      Dart_New(date_type, from_milliseconds, 1, &end_epoch_ms_int);

  Dart_Handle x509_type =
      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
  Dart_Handle arguments[] = { subject_name_object,
                              issuer_name_object,
                              start_validity_date,
                              end_validity_date };
  return Dart_New(x509_type, Dart_Null(), 4, arguments);
}


void SSLFilter::Init(Dart_Handle dart_this) {
  if (!library_initialized_) {
    InitializeLibrary(NULL, "", true, false);
  }
  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);

  InitializeBuffers(dart_this);
  filter_ = memio_CreateIOLayer(kMemioBufferSize, kMemioBufferSize);
}


void SSLFilter::InitializeBuffers(Dart_Handle dart_this) {
  // Create SSLFilter buffers as ExternalUint8Array objects.
  Dart_Handle dart_buffers_object = ThrowIfError(
      Dart_GetField(dart_this, DartUtils::NewString("buffers")));
  Dart_Handle secure_filter_impl_type =
      Dart_InstanceGetType(dart_this);
  Dart_Handle dart_buffer_size = ThrowIfError(
      Dart_GetField(secure_filter_impl_type, DartUtils::NewString("SIZE")));
  int64_t buffer_size = DartUtils::GetIntegerValue(dart_buffer_size);
  Dart_Handle dart_encrypted_buffer_size = ThrowIfError(
      Dart_GetField(secure_filter_impl_type,
                    DartUtils::NewString("ENCRYPTED_SIZE")));
  int64_t encrypted_buffer_size =
      DartUtils::GetIntegerValue(dart_encrypted_buffer_size);
  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");
  for (int i = 0; i < kNumBuffers; ++i) {
    int size = isBufferEncrypted(i) ? encrypted_buffer_size_ : buffer_size_;
    dart_buffer_objects_[i] =
        Dart_NewPersistentHandle(Dart_ListGetAt(dart_buffers_object, i));
    ASSERT(dart_buffer_objects_[i] != NULL);
    buffers_[i] = new uint8_t[size];
    Dart_Handle data = ThrowIfError(
        Dart_NewExternalTypedData(Dart_TypedData_kUint8, buffers_[i], size));
    ThrowIfError(
        Dart_SetField(Dart_HandleFromPersistent(dart_buffer_objects_[i]),
                      data_identifier,
                      data));
  }
}


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);
}


char* PasswordCallback(PK11SlotInfo* slot, PRBool retry, void* arg) {
  if (!retry) {
    return PL_strdup(static_cast<char*>(arg));  // Freed by NSS internals.
  }
  return NULL;
}


static const char* builtin_roots_module =
#if defined(TARGET_OS_LINUX) || defined(TARGET_OS_ANDROID)
    "name=\"Root Certs\" library=\"libnssckbi.so\"";
#elif defined(TARGET_OS_MACOS)
    "name=\"Root Certs\" library=\"libnssckbi.dylib\"";
#elif defined(TARGET_OS_WINDOWS)
    "name=\"Root Certs\" library=\"nssckbi.dll\"";
#else
#error Automatic target os detection failed.
#endif



void SSLFilter::InitializeLibrary(const char* certificate_database,
                                  const char* password,
                                  bool use_builtin_root_certificates,
                                  bool report_duplicate_initialization) {
  MutexLocker locker(mutex_);
  SECStatus status;
  if (!library_initialized_) {
    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    // TODO(whesse): Verify there are no UTF-8 issues here.
    if (certificate_database == NULL || certificate_database[0] == '\0') {
      status = NSS_NoDB_Init(NULL);
      if (status != SECSuccess) {
        mutex_->Unlock();  // MutexLocker destructor not called when throwing.
        ThrowPRException("TlsException",
                         "Failed NSS_NoDB_Init call.");
      }
      if (use_builtin_root_certificates) {
        SECMODModule* module = SECMOD_LoadUserModule(
            const_cast<char*>(builtin_roots_module), NULL, PR_FALSE);
        if (!module) {
          mutex_->Unlock();  // MutexLocker destructor not called when throwing.
          ThrowPRException("TlsException",
                           "Failed to load builtin root certificates.");
        }
      }
    } else {
      PRUint32 init_flags = NSS_INIT_READONLY;
      if (!use_builtin_root_certificates) {
        init_flags |= NSS_INIT_NOMODDB;
      }
      status = NSS_Initialize(certificate_database,
                              "",
                              "",
                              SECMOD_DB,
                              init_flags);
      if (status != SECSuccess) {
        mutex_->Unlock();  // MutexLocker destructor not called when throwing.
        ThrowPRException("TlsException",
                         "Failed NSS_Init call.");
      }
      password_ = strdup(password);  // This one copy persists until Dart exits.
      PK11_SetPasswordFunc(PasswordCallback);
    }
    library_initialized_ = true;

    status = NSS_SetDomesticPolicy();
    if (status != SECSuccess) {
      mutex_->Unlock();  // MutexLocker destructor not called when throwing.
      ThrowPRException("TlsException",
                       "Failed NSS_SetDomesticPolicy call.");
    }

    // Enable the same additional ciphers that Chromium does.
    // See NSSSSLInitSingleton() in Chromium's net/socket/nss_ssl_util.cc.
    // Explicitly enable exactly those ciphers with keys of at least 80 bits.
    const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
    const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
    for (int i = 0; i < num_ciphers; i++) {
      SSLCipherSuiteInfo info;
      if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
          SECSuccess) {
        bool enabled = (info.effectiveKeyBits >= 80);
        // Trim the list of cipher suites in order to keep the size of the
        // ClientHello down. DSS, ECDH, CAMELLIA, SEED, ECC+3DES, and
        // HMAC-SHA256 cipher suites are disabled.
        if (info.symCipher == ssl_calg_camellia ||
            info.symCipher == ssl_calg_seed ||
            (info.symCipher == ssl_calg_3des && info.keaType != ssl_kea_rsa) ||
            info.authAlgorithm == ssl_auth_dsa ||
            info.macAlgorithm == ssl_hmac_sha256 ||
            info.nonStandard ||
            strcmp(info.keaTypeName, "ECDH") == 0) {
          enabled = false;
        }

        if (ssl_ciphers[i] == TLS_DHE_DSS_WITH_AES_128_CBC_SHA) {
          // Enabled to allow servers with only a DSA certificate to function.
          enabled = true;
        }
        SSL_CipherPrefSetDefault(ssl_ciphers[i], enabled);
      }
    }

    status = SSL_ConfigServerSessionIDCache(0, 0, 0, NULL);
    if (status != SECSuccess) {
      mutex_->Unlock();  // MutexLocker destructor not called when throwing.
      ThrowPRException("TlsException",
                       "Failed SSL_ConfigServerSessionIDCache call.");
    }

  } else if (report_duplicate_initialization) {
    mutex_->Unlock();  // MutexLocker destructor not called when throwing.
    // Like ThrowPRException, without adding an OSError.
    Dart_ThrowException(DartUtils::NewDartIOException("TlsException",
        "Called SecureSocket.initialize more than once",
        Dart_Null()));
  }
}


SECStatus BadCertificateCallback(void* filter, PRFileDesc* fd) {
  SSLFilter* ssl_filter = static_cast<SSLFilter*>(filter);
  Dart_Handle callback = ssl_filter->bad_certificate_callback();
  if (Dart_IsNull(callback)) return SECFailure;
  Dart_Handle x509_object = ssl_filter->PeerCertificate();
  Dart_Handle result = Dart_InvokeClosure(callback, 1, &x509_object);
  if (Dart_IsError(result)) {
    ssl_filter->callback_error = result;
    return SECFailure;
  }
  // Our wrapper is guaranteed to return a boolean.
  bool c_result = DartUtils::GetBooleanValue(result);
  return c_result ? SECSuccess : SECFailure;
}


Dart_Handle SSLFilter::PeerCertificate() {
  CERTCertificate* certificate = SSL_PeerCertificate(filter_);
  if (certificate == NULL) return Dart_Null();
  Dart_Handle x509_object = X509FromCertificate(certificate);
  CERT_DestroyCertificate(certificate);
  return x509_object;
}


void SSLFilter::Connect(const char* host_name,
                        RawAddr* raw_addr,
                        int port,
                        bool is_server,
                        const char* certificate_name,
                        bool request_client_certificate,
                        bool require_client_certificate,
                        bool send_client_certificate) {
  is_server_ = is_server;
  if (in_handshake_) {
    FATAL("Connect called twice on the same _SecureFilter.");
  }

  if (!is_server && certificate_name != NULL) {
    client_certificate_name_ = strdup(certificate_name);
  }

  filter_ = SSL_ImportFD(NULL, filter_);
  if (filter_ == NULL) {
    ThrowPRException("TlsException", "Failed SSL_ImportFD call");
  }

  SSLVersionRange vrange;
  vrange.min = SSL_LIBRARY_VERSION_3_0;
  vrange.max = SSL_LIBRARY_VERSION_TLS_1_2;
  SSL_VersionRangeSet(filter_, &vrange);

  SECStatus status;
  if (is_server) {
    CERTCertificate* certificate = NULL;
    if (strstr(certificate_name, "CN=") != NULL) {
      // Look up certificate using the distinguished name (DN) certificate_name.
      CERTCertDBHandle* certificate_database = CERT_GetDefaultCertDB();
      if (certificate_database == NULL) {
        ThrowPRException("CertificateException",
                         "Certificate database cannot be loaded");
      }
      certificate = CERT_FindCertByNameString(certificate_database,
          const_cast<char*>(certificate_name));
      if (certificate == NULL) {
        ThrowCertificateException(
            "Cannot find server certificate by distinguished name: %s",
            certificate_name);
      }
    } else {
      // Look up certificate using the nickname certificate_name.
      certificate = PK11_FindCertFromNickname(
          const_cast<char*>(certificate_name),
          static_cast<void*>(const_cast<char*>(password_)));
      if (certificate == NULL) {
        ThrowCertificateException(
            "Cannot find server certificate by nickname: %s",
            certificate_name);
      }
    }
    SECKEYPrivateKey* key = PK11_FindKeyByAnyCert(
        certificate,
        static_cast<void*>(const_cast<char*>(password_)));
    if (key == NULL) {
      CERT_DestroyCertificate(certificate);
      if (PR_GetError() == -8177) {
        ThrowPRException("CertificateException",
                         "Certificate database password incorrect");
      } else {
        ThrowCertificateException(
            "Cannot find private key for certificate %s",
            certificate_name);
      }
    }
    // kt_rsa (key type RSA) is an enum constant from the NSS libraries.
    // TODO(whesse): Allow different key types.
    status = SSL_ConfigSecureServer(filter_, certificate, key, kt_rsa);
    CERT_DestroyCertificate(certificate);
    SECKEY_DestroyPrivateKey(key);
    if (status != SECSuccess) {
      ThrowCertificateException(
          "Failed SSL_ConfigSecureServer call with certificate %s",
          certificate_name);
    }

    if (request_client_certificate) {
      status = SSL_OptionSet(filter_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
      if (status != SECSuccess) {
        ThrowPRException("TlsException",
                         "Failed SSL_OptionSet(REQUEST_CERTIFICATE) call");
      }
      status = SSL_OptionSet(filter_,
                             SSL_REQUIRE_CERTIFICATE,
                             require_client_certificate);
      if (status != SECSuccess) {
        ThrowPRException("TlsException",
                         "Failed SSL_OptionSet(REQUIRE_CERTIFICATE) call");
      }
    }
  } else {  // Client.
    if (SSL_SetURL(filter_, host_name) == -1) {
      ThrowPRException("TlsException", "Failed SetURL call");
    }
    if (send_client_certificate) {
      SSL_SetPKCS11PinArg(filter_, const_cast<char*>(password_));
      status = SSL_GetClientAuthDataHook(
          filter_,
          NSS_GetClientAuthData,
          static_cast<void*>(client_certificate_name_));
      if (status != SECSuccess) {
        ThrowPRException("TlsException",
                         "Failed SSL_GetClientAuthDataHook call");
      }
    }
  }

  // Install bad certificate callback, and pass 'this' to it if it is called.
  status = SSL_BadCertHook(filter_,
                           BadCertificateCallback,
                           static_cast<void*>(this));

  status = SSL_ResetHandshake(filter_, is_server);
  if (status != SECSuccess) {
    ThrowPRException("TlsException",
                     "Failed SSL_ResetHandshake call");
  }

  // Set the peer address from the address passed. The DNS has already
  // been done in Dart code, so just use that address. This relies on
  // following about PRNetAddr: "The raw member of the union is
  // equivalent to struct sockaddr", which is stated in the NSS
  // documentation.
  PRNetAddr peername;
  memset(&peername, 0, sizeof(peername));
  intptr_t len = SocketAddress::GetAddrLength(raw_addr);
  ASSERT(static_cast<size_t>(len) <= sizeof(peername));
  memmove(&peername, &raw_addr->addr, len);

  // Adjust the address family field for BSD, whose sockaddr
  // structure has a one-byte length and one-byte address family
  // field at the beginning.  PRNetAddr has a two-byte address
  // family field at the beginning.
  peername.raw.family = raw_addr->addr.sa_family;

  memio_SetPeerName(filter_, &peername);
}


void SSLFilter::Handshake() {
  SECStatus status = SSL_ForceHandshake(filter_);
  if (status == SECSuccess) {
    if (in_handshake_) {
      ThrowIfError(Dart_InvokeClosure(
          Dart_HandleFromPersistent(handshake_complete_), 0, NULL));
      in_handshake_ = false;
    }
  } else {
    if (callback_error != NULL) {
      Dart_PropagateError(callback_error);
    }
    PRErrorCode error = PR_GetError();
    if (error == PR_WOULD_BLOCK_ERROR) {
      if (!in_handshake_) {
        in_handshake_ = true;
      }
    } else {
      if (is_server_) {
        ThrowPRException("HandshakeException",
                         "Handshake error in server");
      } else {
        ThrowPRException("HandshakeException",
                         "Handshake error in client");
      }
    }
  }
}


void SSLFilter::Renegotiate(bool use_session_cache,
                            bool request_client_certificate,
                            bool require_client_certificate) {
  SECStatus status;
  // 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;

  status = SSL_OptionSet(filter_,
                         SSL_REQUEST_CERTIFICATE,
                         request_client_certificate);
  if (status != SECSuccess) {
    ThrowPRException("TlsException",
       "Failure in (Raw)SecureSocket.renegotiate request_client_certificate");
  }
  status = SSL_OptionSet(filter_,
                         SSL_REQUIRE_CERTIFICATE,
                         require_client_certificate);
  if (status != SECSuccess) {
    ThrowPRException("TlsException",
       "Failure in (Raw)SecureSocket.renegotiate require_client_certificate");
  }
  bool flush_cache = !use_session_cache;
  status = SSL_ReHandshake(filter_, flush_cache);
  if (status != SECSuccess) {
    if (is_server_) {
      ThrowPRException("HandshakeException",
                       "Failure in (Raw)SecureSocket.renegotiate in server");
    } else {
      ThrowPRException("HandshakeException",
                       "Failure in (Raw)SecureSocket.renegotiate in client");
    }
  }
}


void SSLFilter::Destroy() {
  for (int i = 0; i < kNumBuffers; ++i) {
    Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
    delete[] buffers_[i];
  }
  Dart_DeletePersistentHandle(string_start_);
  Dart_DeletePersistentHandle(string_length_);
  Dart_DeletePersistentHandle(handshake_complete_);
  Dart_DeletePersistentHandle(bad_certificate_callback_);
  free(client_certificate_name_);

  PR_Close(filter_);
}


intptr_t SSLFilter::ProcessReadPlaintextBuffer(int start, int end) {
  int length = end - start;
  int bytes_processed = 0;
  if (length > 0) {
    bytes_processed = PR_Read(filter_,
                              buffers_[kReadPlaintext] + start,
                              length);
    if (bytes_processed < 0) {
      ASSERT(bytes_processed == -1);
      PRErrorCode pr_error = PR_GetError();
      if (PR_WOULD_BLOCK_ERROR != pr_error) {
        return -1;
      }
      bytes_processed = 0;
    }
  }
  return bytes_processed;
}


intptr_t SSLFilter::ProcessWritePlaintextBuffer(int start1, int end1,
                                                int start2, int end2) {
  PRIOVec ranges[2];
  uint8_t* buffer = buffers_[kWritePlaintext];
  ranges[0].iov_base = reinterpret_cast<char*>(buffer + start1);
  ranges[0].iov_len = end1 - start1;
  ranges[1].iov_base = reinterpret_cast<char*>(buffer + start2);
  ranges[1].iov_len = end2 - start2;
  int bytes_processed = PR_Writev(filter_, ranges, 2, PR_INTERVAL_NO_TIMEOUT);
  if (bytes_processed < 0) {
    ASSERT(bytes_processed == -1);
    PRErrorCode pr_error = PR_GetError();
    if (PR_WOULD_BLOCK_ERROR != pr_error) {
      return -1;
    }
    bytes_processed = 0;
  }
  return bytes_processed;
}


intptr_t SSLFilter::ProcessReadEncryptedBuffer(int start, int end) {
  int length = end - start;
  int bytes_processed = 0;
  if (length > 0) {
    memio_Private* secret = memio_GetSecret(filter_);
    uint8_t* filter_buf;
    int free_bytes = memio_GetReadParams(secret, &filter_buf);
    bytes_processed = dart::Utils::Minimum(length, free_bytes);
    memmove(filter_buf, buffers_[kReadEncrypted] + start, bytes_processed);
    memio_PutReadResult(secret, bytes_processed);
  }
  return bytes_processed;
}


intptr_t SSLFilter::ProcessWriteEncryptedBuffer(int start, int end) {
  int length = end - start;
  int bytes_processed = 0;
  if (length > 0) {
    uint8_t* buffer = buffers_[kWriteEncrypted];
    const uint8_t* buf1;
    const uint8_t* buf2;
    unsigned int len1;
    unsigned int len2;
    memio_Private* secret = memio_GetSecret(filter_);
    int status = memio_GetWriteParams(secret, &buf1, &len1, &buf2, &len2);
    if (status != 0) {
      return -1;
    }
    int bytes_to_send =
        dart::Utils::Minimum(len1, static_cast<unsigned>(length));
    if (bytes_to_send > 0) {
      memmove(buffer + start, buf1, bytes_to_send);
      bytes_processed = bytes_to_send;
    }
    bytes_to_send = dart::Utils::Minimum(len2,
        static_cast<unsigned>(length - bytes_processed));
    if (bytes_to_send > 0) {
      memmove(buffer + start + bytes_processed, buf2, bytes_to_send);
      bytes_processed += bytes_to_send;
    }
    if (bytes_processed > 0) {
      memio_PutWriteResult(secret, bytes_processed);
    }
  }
  return bytes_processed;
}

}  // namespace bin
}  // namespace dart
