1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be
321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file.
421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/socket/ssl_server_socket_nss.h"
621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(OS_WIN)
821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <winsock2.h>
921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(USE_SYSTEM_SSL)
1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <dlfcn.h>
1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#if defined(OS_MACOSX)
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <Security/Security.h>
1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#endif
1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <certdb.h>
1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <cryptohi.h>
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <hasht.h>
2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <keyhi.h>
2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <nspr.h>
2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <nss.h>
2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <pk11pub.h>
2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <secerr.h>
2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <sechash.h>
2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <ssl.h>
2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <sslerr.h>
2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <sslproto.h>
2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <limits>
3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/ref_counted.h"
33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/rsa_private_key.h"
34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util_internal.h"
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/io_buffer.h"
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/net_errors.h"
3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/net_log.h"
3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/ocsp/nss_ocsp.h"
3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/socket/nss_ssl_util.h"
4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/socket/ssl_error_params.h"
4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenstatic const int kRecvBufferSize = 4096;
4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#define GotoState(s) next_handshake_state_ = s
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net {
4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSSLServerSocket* CreateSSLServerSocket(
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    Socket* socket, X509Certificate* cert, crypto::RSAPrivateKey* key,
5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const SSLConfig& ssl_config) {
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return new SSLServerSocketNSS(socket, cert, key, ssl_config);
5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSSLServerSocketNSS::SSLServerSocketNSS(
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    Socket* transport_socket,
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    scoped_refptr<X509Certificate> cert,
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    crypto::RSAPrivateKey* key,
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    const SSLConfig& ssl_config)
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          this, &SSLServerSocketNSS::BufferSendComplete)),
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          this, &SSLServerSocketNSS::BufferRecvComplete)),
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      transport_send_busy_(false),
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      transport_recv_busy_(false),
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      user_accept_callback_(NULL),
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      user_read_callback_(NULL),
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      user_write_callback_(NULL),
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      nss_fd_(NULL),
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      nss_bufs_(NULL),
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      transport_socket_(transport_socket),
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ssl_config_(ssl_config),
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      cert_(cert),
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      next_handshake_state_(STATE_NONE),
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      completed_handshake_(false) {
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ssl_config_.false_start_enabled = false;
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ssl_config_.ssl3_enabled = true;
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ssl_config_.tls1_enabled = true;
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // TODO(hclam): Need a better way to clone a key.
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::vector<uint8> key_bytes;
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CHECK(key->ExportPrivateKey(&key_bytes));
82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CHECK(key_.get());
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenSSLServerSocketNSS::~SSLServerSocketNSS() {
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (nss_fd_ != NULL) {
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PR_Close(nss_fd_);
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    nss_fd_ = NULL;
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::Accept(CompletionCallback* callback) {
9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net_log_.BeginEvent(NetLog::TYPE_SSL_ACCEPT, NULL);
9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = Init();
9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != OK) {
9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(ERROR) << "Failed to initialize NSS";
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = InitializeSSLOptions();
10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != OK) {
10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(ERROR) << "Failed to initialize SSL options";
10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Set peer address. TODO(hclam): This should be in a separate method.
11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  PRNetAddr peername;
11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  memset(&peername, 0, sizeof(peername));
11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  peername.raw.family = AF_INET;
11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  memio_SetPeerName(nss_fd_, &peername);
11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
11621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  GotoState(STATE_HANDSHAKE);
11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = DoHandshakeLoop(net::OK);
11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv == ERR_IO_PENDING) {
11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_accept_callback_ = callback;
12021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_ACCEPT, rv);
12221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
12321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv > OK ? OK : rv;
12521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
12621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
12721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
12821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                             CompletionCallback* callback) {
12921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!user_read_callback_);
13021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!user_accept_callback_);
13121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!user_read_buf_);
13221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(nss_bufs_);
13321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  user_read_buf_ = buf;
13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  user_read_buf_len_ = buf_len;
13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(completed_handshake_);
13821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
13921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = DoReadLoop(OK);
14021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
14121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv == ERR_IO_PENDING) {
14221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_read_callback_ = callback;
14321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
14421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_read_buf_ = NULL;
14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_read_buf_len_ = 0;
14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
14921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
15121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                              CompletionCallback* callback) {
15221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!user_write_callback_);
15321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(!user_write_buf_);
15421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(nss_bufs_);
15521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  user_write_buf_ = buf;
15721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  user_write_buf_len_ = buf_len;
15821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
15921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = DoWriteLoop(OK);
16021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
16121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv == ERR_IO_PENDING) {
16221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_write_callback_ = callback;
16321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
16421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_write_buf_ = NULL;
16521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    user_write_buf_len_ = 0;
16621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
16721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
16821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
17321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SSLServerSocketNSS::SetSendBufferSize(int32 size) {
17572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
17621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
17821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::InitializeSSLOptions() {
17921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Transport connected, now hook it up to nss
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // TODO(port): specify rx and tx buffer sizes separately
18121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  nss_fd_ = memio_CreateIOLayer(kRecvBufferSize);
18221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (nss_fd_ == NULL) {
18321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
18421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
18521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
18621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Grab pointer to buffers
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  nss_bufs_ = memio_GetSecret(nss_fd_);
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  /* Create SSL state machine */
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  /* Push SSL onto our fake I/O socket */
19121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
19221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (nss_fd_ == NULL) {
19321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
19421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
19521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
19621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // TODO(port): set more ssl options!  Check errors!
19721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
19821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv;
19921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
20021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
20121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
20221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
20321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
20421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
20521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
20621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
20721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
20821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
21121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
21221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL3, PR_TRUE);
21321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL3");
21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_TLS, ssl_config_.tls1_enabled);
21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_TLS");
22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  for (std::vector<uint16>::const_iterator it =
22521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen           ssl_config_.disabled_cipher_suites.begin();
22621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen       it != ssl_config_.disabled_cipher_suites.end(); ++it) {
22721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // This will fail if the specified cipher is not implemented by NSS, but
22821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // the failure is harmless.
22921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
23021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Server socket doesn't need session tickets.
23321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
23421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
23521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(
23621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
23721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
23821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
23921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Doing this will force PR_Accept perform handshake as server.
24021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
24121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
24221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
24321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
24421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
24521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
24621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
24721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
24821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
24921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
25021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
25121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
25221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
25321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
25421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
25521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
25621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
25721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
25821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
25921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
26021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
26121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
26221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
26321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
26421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
26521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
26621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_ConfigureServerSessionIDCache", "");
26721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
26821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
26921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
27021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
27121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
27221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
27321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
27421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
27521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
27621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
27721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
27821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
27921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
28021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
28121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
28221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Get a certificate of CERTCertificate structure.
28321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::string der_string;
28421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!cert_->GetDEREncoded(&der_string))
28521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
28621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
28721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SECItem der_cert;
28821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
28921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      der_string.data()));
29021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  der_cert.len  = der_string.length();
29121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  der_cert.type = siDERCertBuffer;
29221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
29321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Parse into a CERTCertificate structure.
29421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CERTCertificate* cert = CERT_NewTempCertificate(
29521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
29621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
29721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Get a key of SECKEYPrivateKey* structure.
29821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  std::vector<uint8> key_vector;
29921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!key_->ExportPrivateKey(&key_vector)) {
30021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CERT_DestroyCertificate(cert);
30121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
30221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
30321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
30421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SECKEYPrivateKeyStr* private_key = NULL;
305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  PK11SlotInfo* slot = crypto::GetPrivateNSSKeySlot();
30621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!slot) {
30721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CERT_DestroyCertificate(cert);
30821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
30921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
31021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
31121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SECItem der_private_key_info;
31221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  der_private_key_info.data =
31321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      const_cast<unsigned char*>(&key_vector.front());
31421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  der_private_key_info.len = key_vector.size();
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The server's RSA private key must be imported into NSS with the
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // following key usage bits:
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //   exchange algorithms.
32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
32121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
32221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      key_usage, &private_key, NULL);
32421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  PK11_FreeSlot(slot);
32521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
32621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    CERT_DestroyCertificate(cert);
32721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
32821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
32921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
33021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Assign server certificate and private key.
33121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
33221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
33321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  CERT_DestroyCertificate(cert);
33421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SECKEY_DestroyPrivateKey(private_key);
33521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
33621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
33721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PRErrorCode prerr = PR_GetError();
33821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(ERROR) << "Failed to config SSL server: " << prerr;
33921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
34021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
34121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
34221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
34321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  // Tell SSL we're a server; needed if not letting NSPR do socket I/O
34421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
34521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv != SECSuccess) {
34621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
34721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_UNEXPECTED;
34821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
34921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
35021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return OK;
35121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
35221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::OnSendComplete(int result) {
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (next_handshake_state_ == STATE_HANDSHAKE) {
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // In handshake phase.
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    OnHandshakeIOComplete(result);
35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!user_write_buf_ || !completed_handshake_)
36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = DoWriteLoop(result);
36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv != ERR_IO_PENDING)
36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DoWriteCallback(rv);
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::OnRecvComplete(int result) {
36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (next_handshake_state_ == STATE_HANDSHAKE) {
37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // In handshake phase.
37172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    OnHandshakeIOComplete(result);
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Network layer received some data, check if client requested to read
37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // decrypted data.
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!user_read_buf_ || !completed_handshake_)
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = DoReadLoop(result);
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv != ERR_IO_PENDING)
38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DoReadCallback(rv);
38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = DoHandshakeLoop(result);
38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv != ERR_IO_PENDING) {
38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    net_log_.EndEventWithNetErrorCode(net::NetLog::TYPE_SSL_ACCEPT, rv);
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (user_accept_callback_)
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      DoAcceptCallback(rv);
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
39421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Return 0 for EOF,
39521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// > 0 for bytes transferred immediately,
39621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// < 0 for error (or the non-error ERR_IO_PENDING).
39721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::BufferSend(void) {
39821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (transport_send_busy_)
39921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_IO_PENDING;
40021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const char* buf1;
40221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const char* buf2;
40321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  unsigned int len1, len2;
40421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
40521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const unsigned int len = len1 + len2;
40621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
40721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = 0;
40821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (len) {
40921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
41021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    memcpy(send_buffer->data(), buf1, len1);
41121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    memcpy(send_buffer->data() + len1, buf2, len2);
41221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    rv = transport_socket_->Write(send_buffer, len,
41321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                  &buffer_send_callback_);
41421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (rv == ERR_IO_PENDING) {
41521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      transport_send_busy_ = true;
41621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
41721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
41821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
41921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
42021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
42221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
42321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
42421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SSLServerSocketNSS::BufferSendComplete(int result) {
42521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
42621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  transport_send_busy_ = false;
42721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  OnSendComplete(result);
42821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
42921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
43021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::BufferRecv(void) {
43121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (transport_recv_busy_) return ERR_IO_PENDING;
43221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
43321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  char *buf;
43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int nb = memio_GetReadParams(nss_bufs_, &buf);
43521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv;
43621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!nb) {
43721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // buffer too full to read into, so no I/O possible at moment
43821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    rv = ERR_IO_PENDING;
43921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
44021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    recv_buffer_ = new IOBuffer(nb);
44121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    rv = transport_socket_->Read(recv_buffer_, nb, &buffer_recv_callback_);
44221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (rv == ERR_IO_PENDING) {
44321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      transport_recv_busy_ = true;
44421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
44521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (rv > 0)
44621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        memcpy(buf, recv_buffer_->data(), rv);
44721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
44821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      recv_buffer_ = NULL;
44921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
45021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
45121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
45221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
45321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
45421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SSLServerSocketNSS::BufferRecvComplete(int result) {
45521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (result > 0) {
45621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    char *buf;
45721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    memio_GetReadParams(nss_bufs_, &buf);
45821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    memcpy(buf, recv_buffer_->data(), result);
45921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  recv_buffer_ = NULL;
46121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
46221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  transport_recv_busy_ = false;
46321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  OnRecvComplete(result);
46421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
46521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
46621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Do network I/O between the given buffer and the given socket.
46721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Return true if some I/O performed, false otherwise (error or ERR_IO_PENDING)
46821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool SSLServerSocketNSS::DoTransportIO() {
46921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool network_moved = false;
47021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (nss_bufs_ != NULL) {
47121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int nsent = BufferSend();
47221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int nreceived = BufferRecv();
47321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    network_moved = (nsent > 0 || nreceived >= 0);
47421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
47521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return network_moved;
47621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
47721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
47821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoPayloadRead() {
47921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(user_read_buf_);
48021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK_GT(user_read_buf_len_, 0);
48121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
48221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv >= 0)
48321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
48421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  PRErrorCode prerr = PR_GetError();
48521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (prerr == PR_WOULD_BLOCK_ERROR) {
48621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_IO_PENDING;
48721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
48821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = MapNSSError(prerr);
48921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
49121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
49221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
49321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoPayloadWrite() {
49521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(user_write_buf_);
49621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
49721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv >= 0)
49821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
49921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  PRErrorCode prerr = PR_GetError();
50021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (prerr == PR_WOULD_BLOCK_ERROR) {
50121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return ERR_IO_PENDING;
50221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
50321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  rv = MapNSSError(prerr);
50421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
50521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                    make_scoped_refptr(new SSLErrorParams(rv, prerr)));
50621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
50721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
50821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
50921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
51021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool network_moved;
51121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv = last_io_result;
51221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  do {
51321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Default to STATE_NONE for next state.
51421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // (This is a quirk carried over from the windows
51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // implementation.  It makes reading the logs a bit harder.)
51621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // State handlers can and often do call GotoState just
51721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // to stay in the current state.
51821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    State state = next_handshake_state_;
51921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    GotoState(STATE_NONE);
52021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    switch (state) {
52121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case STATE_NONE:
52221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        // we're just pumping data between the buffer and the network
52321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
52421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      case STATE_HANDSHAKE:
52521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        rv = DoHandshake();
52621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
52721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      default:
52821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        rv = ERR_UNEXPECTED;
52921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        LOG(DFATAL) << "unexpected state " << state;
53021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        break;
53121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
53221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
53321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // Do the actual network I/O
53421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    network_moved = DoTransportIO();
53521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } while ((rv != ERR_IO_PENDING || network_moved) &&
53621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen           next_handshake_state_ != STATE_NONE);
53721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
53821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
53921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
54021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoReadLoop(int result) {
54121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(completed_handshake_);
54221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(next_handshake_state_ == STATE_NONE);
54321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
54421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (result < 0)
54521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return result;
54621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
54721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!nss_bufs_) {
54821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(DFATAL) << "!nss_bufs_";
54921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int rv = ERR_UNEXPECTED;
55021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
55121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      make_scoped_refptr(new SSLErrorParams(rv, 0)));
55221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
55321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
55421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
55521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool network_moved;
55621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv;
55721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  do {
55821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    rv = DoPayloadRead();
55921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    network_moved = DoTransportIO();
56021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } while (rv == ERR_IO_PENDING && network_moved);
56121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
56221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
56321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
56421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoWriteLoop(int result) {
56521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(completed_handshake_);
56621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  DCHECK(next_handshake_state_ == STATE_NONE);
56721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
56821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (result < 0)
56921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return result;
57021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
57121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!nss_bufs_) {
57221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    LOG(DFATAL) << "!nss_bufs_";
57321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    int rv = ERR_UNEXPECTED;
57421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
57521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                      make_scoped_refptr(new SSLErrorParams(rv, 0)));
57621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return rv;
57721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  bool network_moved;
58021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int rv;
58121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  do {
58221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    rv = DoPayloadWrite();
58321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    network_moved = DoTransportIO();
58421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } while (rv == ERR_IO_PENDING && network_moved);
58521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return rv;
58621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
58721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
58821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint SSLServerSocketNSS::DoHandshake() {
58921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  int net_error = net::OK;
59021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  SECStatus rv = SSL_ForceHandshake(nss_fd_);
59121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
59221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (rv == SECSuccess) {
59321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    completed_handshake_ = true;
59421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else {
59521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    PRErrorCode prerr = PR_GetError();
59621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    net_error = MapNSSHandshakeError(prerr);
59721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
59821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    // If not done, stay in this state
59921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (net_error == ERR_IO_PENDING) {
60021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      GotoState(STATE_HANDSHAKE);
60121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    } else {
60221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      LOG(ERROR) << "handshake failed; NSS error code " << prerr
60321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                 << ", net_error " << net_error;
60421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      net_log_.AddEvent(
60521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          NetLog::TYPE_SSL_HANDSHAKE_ERROR,
60621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          make_scoped_refptr(new SSLErrorParams(net_error, prerr)));
60721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
60821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
60921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return net_error;
61021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
61272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::DoAcceptCallback(int rv) {
61372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_NE(rv, ERR_IO_PENDING);
61472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
61572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CompletionCallback* c = user_accept_callback_;
61672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_accept_callback_ = NULL;
61772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  c->Run(rv > OK ? OK : rv);
61872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
61972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
62072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::DoReadCallback(int rv) {
62172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(rv != ERR_IO_PENDING);
62272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(user_read_callback_);
62372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
62472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Since Run may result in Read being called, clear |user_read_callback_|
62572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // up front.
62672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CompletionCallback* c = user_read_callback_;
62772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_read_callback_ = NULL;
62872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_read_buf_ = NULL;
62972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_read_buf_len_ = 0;
63072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  c->Run(rv);
63172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
63272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
63372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::DoWriteCallback(int rv) {
63472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(rv != ERR_IO_PENDING);
63572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(user_write_callback_);
63672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
63772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Since Run may result in Write being called, clear |user_write_callback_|
63872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // up front.
63972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  CompletionCallback* c = user_write_callback_;
64072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_write_callback_ = NULL;
64172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_write_buf_ = NULL;
64272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  user_write_buf_len_ = 0;
64372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  c->Run(rv);
64472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
64572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
64672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
64772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this if an incoming certificate needs to be verified.
64872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Do nothing but return SECSuccess.
64972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// This is called only in full handshake mode.
65072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Peer certificate is retrieved in HandshakeCallback() later, which is called
65172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// in full handshake mode or in resumption handshake mode.
65272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
65372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 PRFileDesc* socket,
65472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 PRBool checksig,
65572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                 PRBool is_server) {
65672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(hclam): Implement.
65772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Tell NSS to not verify the certificate.
65872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return SECSuccess;
65972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
66072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
66172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static
66272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// NSS calls this when handshake is completed.
66372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// After the SSL handshake is finished we need to verify the certificate.
66472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
66572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                           void* arg) {
66672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(hclam): Implement.
66772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
66872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
66972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint SSLServerSocketNSS::Init() {
67072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Initialize the NSS SSL library in a threadsafe way.  This also
67172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // initializes the NSS base library.
67272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EnsureNSSSSLInit();
67372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!NSS_IsInitialized())
67472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return ERR_UNEXPECTED;
67572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if !defined(OS_MACOSX) && !defined(OS_WIN)
67672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // We must call EnsureOCSPInit() here, on the IO thread, to get the IO loop
67772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // by MessageLoopForIO::current().
67872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // X509Certificate::Verify() runs on a worker thread of CertVerifier.
67972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  EnsureOCSPInit();
68072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif
68172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
68272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return OK;
68372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
68472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
68521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace net
686