15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_server_socket_nss.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winsock2.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_SSL)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dlfcn.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <Security/Security.h>
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <certdb.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cryptohi.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <hasht.h>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <keyhi.h>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nspr.h>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h>
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pk11pub.h>
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secerr.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sechash.h>
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ssl.h>
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslerr.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslproto.h>
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/callback_helpers.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/rsa_private_key.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util_internal.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/nss_ssl_util.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSL plaintext fragments are shorter than 16KB. Although the record layer
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// smaller than 1KB. So a 17KB buffer should be large enough to hold an
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// entire SSL record.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRecvBufferSize = 17 * 1024;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSendBufferSize = 17 * 1024;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GotoState(s) next_handshake_state_ = s
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool g_nss_server_sockets_init = false;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NSSSSLServerInitSingleton {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSSSSLServerInitSingleton() {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnsureNSSSSLInit();
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_nss_server_sockets_init = true;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~NSSSSLServerInitSingleton() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_ShutdownServerSessionIDCache();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_nss_server_sockets_init = false;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<NSSSSLServerInitSingleton>
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void EnableSSLServerSockets() {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_nss_ssl_server_init_singleton.Get();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<StreamSocket> socket,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    X509Certificate* cert,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::RSAPrivateKey* key,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    << "called yet!";
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return scoped_ptr<SSLServerSocket>(
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config));
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLServerSocketNSS::SSLServerSocketNSS(
943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    scoped_ptr<StreamSocket> transport_socket,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<X509Certificate> cert,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    crypto::RSAPrivateKey* key,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SSLConfig& ssl_config)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : transport_send_busy_(false),
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_(false),
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_read_buf_len_(0),
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_write_buf_len_(0),
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_(NULL),
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_bufs_(NULL),
1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      transport_socket_(transport_socket.Pass()),
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_config_(ssl_config),
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cert_(cert),
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_handshake_state_(STATE_NONE),
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      completed_handshake_(false) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Need a better way to clone a key.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8> key_bytes;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(key->ExportPrivateKey(&key_bytes));
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(key_.get());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLServerSocketNSS::~SSLServerSocketNSS() {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ != NULL) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PR_Close(nss_fd_);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nss_fd_ = NULL;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = Init();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to initialize NSS";
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = InitializeSSLOptions();
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK) {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to initialize SSL options";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set peer address. TODO(hclam): This should be in a separate method.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRNetAddr peername;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&peername, 0, sizeof(peername));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  peername.raw.family = AF_INET;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_SetPeerName(nss_fd_, &peername);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GotoState(STATE_HANDSHAKE);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoHandshakeLoop(OK);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_handshake_callback_ = callback;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv > OK ? OK : rv;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool has_context,
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const base::StringPiece& context,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned char* out,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             unsigned int outlen) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_ExportKeyingMaterial(
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nss_fd_, label.data(), label.size(), has_context,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<const unsigned char*>(context.data()),
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context.length(), out, outlen);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char buf[64];
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus result = SSL_GetChannelBinding(nss_fd_,
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           SSL_CHANNEL_BINDING_TLS_UNIQUE,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           buf, &len, arraysize(buf));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != SECSuccess) {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  out->assign(reinterpret_cast<char*>(buf), len);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ERR_NOT_IMPLEMENTED;
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const CompletionCallback& callback) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_read_callback_.is_null());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_handshake_callback_.is_null());
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_read_buf_.get());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = buf;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = buf_len;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(completed_handshake_);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(OK);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_callback_ = callback;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_ = NULL;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_read_buf_len_ = 0;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const CompletionCallback& callback) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_write_callback_.is_null());
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!user_write_buf_.get());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nss_bufs_);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!callback.is_null());
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = buf;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = buf_len;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoWriteLoop(OK);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_callback_ = callback;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_ = NULL;
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_write_buf_len_ = 0;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
241c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->SetReceiveBufferSize(size);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SSLServerSocketNSS::SetSendBufferSize(int32 size) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->SetSendBufferSize(size);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::IsConnected() const {
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // as well.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return completed_handshake_;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::Disconnect() {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_->Disconnect();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::IsConnectedAndIdle() const {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->GetPeerAddress(address);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsConnected())
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_SOCKET_NOT_CONNECTED;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->GetLocalAddress(address);
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLServerSocketNSS::NetLog() const {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::SetSubresourceSpeculation() {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_->SetSubresourceSpeculation();
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::SetOmniboxSpeculation() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_socket_->SetOmniboxSpeculation();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::WasEverUsed() const {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->WasEverUsed();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::UsingTCPFastOpen() const {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_socket_->UsingTCPFastOpen();
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::WasNpnNegotiated() const {
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  NOTIMPLEMENTED();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NPN is not supported by this class.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kProtoUnknown;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::InitializeSSLOptions() {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transport connected, now hook it up to nss
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ == NULL) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Grab pointer to buffers
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_bufs_ = memio_GetSecret(nss_fd_);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Create SSL state machine */
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  /* Push SSL onto our fake I/O socket */
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_fd_ == NULL) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(port): set more ssl options!  Check errors!
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLVersionRange version_range;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.min = ssl_config_.version_min;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version_range.max = ssl_config_.version_max;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_VersionRangeSet(nss_fd_, &version_range);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_NO_SSL_VERSIONS_ENABLED;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (ssl_config_.require_forward_secrecy) {
3530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
3540f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
3550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // Require forward security by iterating over the cipher suites and
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // disabling all those that don't use ECDHE.
3580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    for (unsigned i = 0; i < num_ciphers; i++) {
3590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      SSLCipherSuiteInfo info;
3600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
3610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          SECSuccess) {
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (strcmp(info.keaTypeName, "ECDHE") != 0) {
3630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)          SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
3640f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        }
3650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      }
3660f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    }
3670f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
3680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::vector<uint16>::const_iterator it =
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           ssl_config_.disabled_cipher_suites.begin();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will fail if the specified cipher is not implemented by NSS, but
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // the failure is harmless.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Server socket doesn't need session tickets.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Doing this will force PR_Accept perform handshake as server.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a certificate of CERTCertificate structure.
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string der_string;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem der_cert;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      der_string.data()));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  der_cert.len  = der_string.length();
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  der_cert.type = siDERCertBuffer;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse into a CERTCertificate structure.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERTCertificate* cert = CERT_NewTempCertificate(
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cert) {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return MapNSSError(PORT_GetError());
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a key of SECKEYPrivateKey* structure.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<uint8> key_vector;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!key_->ExportPrivateKey(&key_vector)) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(cert);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEYPrivateKeyStr* private_key = NULL;
448116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PK11SlotInfo* slot = PK11_GetInternalSlot();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!slot) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(cert);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECItem der_private_key_info;
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  der_private_key_info.data =
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const_cast<unsigned char*>(&key_vector.front());
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  der_private_key_info.len = key_vector.size();
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The server's RSA private key must be imported into NSS with the
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // following key usage bits:
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   exchange algorithms.
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      key_usage, &private_key, NULL);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PK11_FreeSlot(slot);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CERT_DestroyCertificate(cert);
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Assign server certificate and private key.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CERT_DestroyCertificate(cert);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECKEY_DestroyPrivateKey(private_key);
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRErrorCode prerr = PR_GetError();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Failed to config SSL server: " << prerr;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell SSL we're a server; needed if not letting NSPR do socket I/O
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != SECSuccess) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::OnSendComplete(int result) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In handshake phase.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
503cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // TODO(byungchul): This state machine is not correct. Copy the state machine
504cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // of SSLClientSocketNSS::OnSendComplete() which handles it better.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!completed_handshake_)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (user_write_buf_.get()) {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = DoWriteLoop(result);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != ERR_IO_PENDING)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DoWriteCallback(rv);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ensure that any queued ciphertext is flushed.
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoTransportIO();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::OnRecvComplete(int result) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_handshake_state_ == STATE_HANDSHAKE) {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In handshake phase.
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnHandshakeIOComplete(result);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Network layer received some data, check if client requested to read
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decrypted data.
527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!user_read_buf_.get() || !completed_handshake_)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoReadLoop(result);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoReadCallback(rv);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoHandshakeLoop(result);
537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!user_handshake_callback_.is_null())
542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DoHandshakeCallback(rv);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return 0 for EOF,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// > 0 for bytes transferred immediately,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// < 0 for error (or the non-error ERR_IO_PENDING).
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::BufferSend(void) {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_send_busy_)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf1;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* buf2;
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int len1, len2;
555f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
556f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // The error code itself is ignored, so just return ERR_ABORTED.
557f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return ERR_ABORTED;
558f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const unsigned int len = len1 + len2;
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = 0;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data(), buf1, len1);
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(send_buffer->data() + len1, buf2, len2);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = transport_socket_->Write(
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        send_buffer.get(),
568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        len,
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&SSLServerSocketNSS::BufferSendComplete,
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_send_busy_ = true;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::BufferSendComplete(int result) {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_send_busy_ = false;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnSendComplete(result);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::BufferRecv(void) {
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_recv_busy_) return ERR_IO_PENDING;
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buf;
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nb = memio_GetReadParams(nss_bufs_, &buf);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nb) {
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // buffer too full to read into, so no I/O possible at moment
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = ERR_IO_PENDING;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    recv_buffer_ = new IOBuffer(nb);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = transport_socket_->Read(
599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        recv_buffer_.get(),
600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        nb,
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(this)));
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv == ERR_IO_PENDING) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_recv_busy_ = true;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv > 0)
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(buf, recv_buffer_->data(), rv);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      recv_buffer_ = NULL;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::BufferRecvComplete(int result) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result > 0) {
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* buf;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memio_GetReadParams(nss_bufs_, &buf);
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    memcpy(buf, recv_buffer_->data(), result);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  recv_buffer_ = NULL;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  transport_recv_busy_ = false;
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OnRecvComplete(result);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do as much network I/O as possible between the buffer and the
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// transport socket. Return true if some I/O performed, false
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise (error or ERR_IO_PENDING).
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLServerSocketNSS::DoTransportIO() {
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved = false;
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (nss_bufs_ != NULL) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv;
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Read and write as much data as we can. The loop is neccessary
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because Write() may return synchronously.
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = BufferSend();
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (rv > 0)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        network_moved = true;
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (rv > 0);
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (BufferRecv() >= 0)
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      network_moved = true;
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return network_moved;
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoPayloadRead() {
648868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_read_buf_.get());
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GT(user_read_buf_len_, 0);
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRErrorCode prerr = PR_GetError();
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerr == PR_WOULD_BLOCK_ERROR) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = MapNSSError(prerr);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    CreateNetLogSSLErrorCallback(rv, prerr));
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoPayloadWrite() {
664868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(user_write_buf_.get());
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv >= 0)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PRErrorCode prerr = PR_GetError();
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prerr == PR_WOULD_BLOCK_ERROR) {
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_IO_PENDING;
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = MapNSSError(prerr);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    CreateNetLogSSLErrorCallback(rv, prerr));
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Default to STATE_NONE for next state.
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This is a quirk carried over from the windows
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // implementation.  It makes reading the logs a bit harder.)
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // State handlers can and often do call GotoState just
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to stay in the current state.
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_handshake_state_;
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GotoState(STATE_NONE);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_HANDSHAKE:
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoHandshake();
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_NONE:
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(DFATAL) << "unexpected state " << state;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Do the actual network I/O
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool network_moved = DoTransportIO();
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // In general we exit the loop if rv is ERR_IO_PENDING.  In this
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // special case we keep looping even if rv is ERR_IO_PENDING because
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the transport IO may allow DoHandshake to make progress.
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rv = OK;  // This causes us to stay in the loop.
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoReadLoop(int result) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(completed_handshake_);
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(next_handshake_state_ == STATE_NONE);
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CreateNetLogSSLErrorCallback(rv, 0));
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadRead();
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoWriteLoop(int result) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(completed_handshake_);
737cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK_EQ(next_handshake_state_, STATE_NONE);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nss_bufs_) {
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(DFATAL) << "!nss_bufs_";
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = ERR_UNEXPECTED;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      CreateNetLogSSLErrorCallback(rv, 0));
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool network_moved;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = DoPayloadWrite();
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    network_moved = DoTransportIO();
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv == ERR_IO_PENDING && network_moved);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::DoHandshake() {
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int net_error = OK;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SECStatus rv = SSL_ForceHandshake(nss_fd_);
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == SECSuccess) {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    completed_handshake_ = true;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PRErrorCode prerr = PR_GetError();
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_error = MapNSSError(prerr);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If not done, stay in this state
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net_error == ERR_IO_PENDING) {
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GotoState(STATE_HANDSHAKE);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(ERROR) << "handshake failed; NSS error code " << prerr
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 << ", net_error " << net_error;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        CreateNetLogSSLErrorCallback(net_error, prerr));
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_error;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(rv, ERR_IO_PENDING);
784cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::DoReadCallback(int rv) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_read_callback_.is_null());
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_ = NULL;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_read_buf_len_ = 0;
793cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_read_callback_).Run(rv);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::DoWriteCallback(int rv) {
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(rv != ERR_IO_PENDING);
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_write_callback_.is_null());
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_ = NULL;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_write_buf_len_ = 0;
802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ResetAndReturn(&user_write_callback_).Run(rv);
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSS calls this if an incoming certificate needs to be verified.
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Do nothing but return SECSuccess.
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is called only in full handshake mode.
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Peer certificate is retrieved in HandshakeCallback() later, which is called
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in full handshake mode or in resumption handshake mode.
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 PRFileDesc* socket,
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 PRBool checksig,
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 PRBool is_server) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Implement.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell NSS to not verify the certificate.
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SECSuccess;
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NSS calls this when handshake is completed.
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// After the SSL handshake is finished we need to verify the certificate.
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           void* arg) {
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(hclam): Implement.
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLServerSocketNSS::Init() {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the NSS SSL library in a threadsafe way.  This also
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initializes the NSS base library.
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureNSSSSLInit();
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!NSS_IsInitialized())
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_UNEXPECTED;
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnableSSLServerSockets();
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
840