QUIC - enable persisting of QUICServerInfo (server config) to disk
[chromium-blink-merge.git] / net / socket / ssl_server_socket_nss.cc
blob3911f67644039006289cb9accba9b2e424f28fdc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/socket/ssl_server_socket_nss.h"
7 #if defined(OS_WIN)
8 #include <winsock2.h>
9 #endif
11 #if defined(USE_SYSTEM_SSL)
12 #include <dlfcn.h>
13 #endif
14 #if defined(OS_MACOSX)
15 #include <Security/Security.h>
16 #endif
17 #include <certdb.h>
18 #include <cryptohi.h>
19 #include <hasht.h>
20 #include <keyhi.h>
21 #include <nspr.h>
22 #include <nss.h>
23 #include <pk11pub.h>
24 #include <secerr.h>
25 #include <sechash.h>
26 #include <ssl.h>
27 #include <sslerr.h>
28 #include <sslproto.h>
30 #include <limits>
32 #include "base/callback_helpers.h"
33 #include "base/lazy_instance.h"
34 #include "base/memory/ref_counted.h"
35 #include "crypto/rsa_private_key.h"
36 #include "crypto/nss_util_internal.h"
37 #include "net/base/io_buffer.h"
38 #include "net/base/net_errors.h"
39 #include "net/base/net_log.h"
40 #include "net/socket/nss_ssl_util.h"
41 #include "net/socket/ssl_error_params.h"
43 // SSL plaintext fragments are shorter than 16KB. Although the record layer
44 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
45 // smaller than 1KB. So a 17KB buffer should be large enough to hold an
46 // entire SSL record.
47 static const int kRecvBufferSize = 17 * 1024;
48 static const int kSendBufferSize = 17 * 1024;
50 #define GotoState(s) next_handshake_state_ = s
52 namespace net {
54 namespace {
56 bool g_nss_server_sockets_init = false;
58 class NSSSSLServerInitSingleton {
59 public:
60 NSSSSLServerInitSingleton() {
61 EnsureNSSSSLInit();
63 SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
64 g_nss_server_sockets_init = true;
67 ~NSSSSLServerInitSingleton() {
68 SSL_ShutdownServerSessionIDCache();
69 g_nss_server_sockets_init = false;
73 static base::LazyInstance<NSSSSLServerInitSingleton>
74 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
76 } // namespace
78 void EnableSSLServerSockets() {
79 g_nss_ssl_server_init_singleton.Get();
82 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
83 scoped_ptr<StreamSocket> socket,
84 X509Certificate* cert,
85 crypto::RSAPrivateKey* key,
86 const SSLConfig& ssl_config) {
87 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
88 << "called yet!";
90 return scoped_ptr<SSLServerSocket>(
91 new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config));
94 SSLServerSocketNSS::SSLServerSocketNSS(
95 scoped_ptr<StreamSocket> transport_socket,
96 scoped_refptr<X509Certificate> cert,
97 crypto::RSAPrivateKey* key,
98 const SSLConfig& ssl_config)
99 : transport_send_busy_(false),
100 transport_recv_busy_(false),
101 user_read_buf_len_(0),
102 user_write_buf_len_(0),
103 nss_fd_(NULL),
104 nss_bufs_(NULL),
105 transport_socket_(transport_socket.Pass()),
106 ssl_config_(ssl_config),
107 cert_(cert),
108 next_handshake_state_(STATE_NONE),
109 completed_handshake_(false) {
110 // TODO(hclam): Need a better way to clone a key.
111 std::vector<uint8> key_bytes;
112 CHECK(key->ExportPrivateKey(&key_bytes));
113 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
114 CHECK(key_.get());
117 SSLServerSocketNSS::~SSLServerSocketNSS() {
118 if (nss_fd_ != NULL) {
119 PR_Close(nss_fd_);
120 nss_fd_ = NULL;
124 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
125 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
127 int rv = Init();
128 if (rv != OK) {
129 LOG(ERROR) << "Failed to initialize NSS";
130 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
131 return rv;
134 rv = InitializeSSLOptions();
135 if (rv != OK) {
136 LOG(ERROR) << "Failed to initialize SSL options";
137 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
138 return rv;
141 // Set peer address. TODO(hclam): This should be in a separate method.
142 PRNetAddr peername;
143 memset(&peername, 0, sizeof(peername));
144 peername.raw.family = AF_INET;
145 memio_SetPeerName(nss_fd_, &peername);
147 GotoState(STATE_HANDSHAKE);
148 rv = DoHandshakeLoop(OK);
149 if (rv == ERR_IO_PENDING) {
150 user_handshake_callback_ = callback;
151 } else {
152 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
155 return rv > OK ? OK : rv;
158 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
159 bool has_context,
160 const base::StringPiece& context,
161 unsigned char* out,
162 unsigned int outlen) {
163 if (!IsConnected())
164 return ERR_SOCKET_NOT_CONNECTED;
165 SECStatus result = SSL_ExportKeyingMaterial(
166 nss_fd_, label.data(), label.size(), has_context,
167 reinterpret_cast<const unsigned char*>(context.data()),
168 context.length(), out, outlen);
169 if (result != SECSuccess) {
170 LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
171 return MapNSSError(PORT_GetError());
173 return OK;
176 int SSLServerSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
177 if (!IsConnected())
178 return ERR_SOCKET_NOT_CONNECTED;
179 unsigned char buf[64];
180 unsigned int len;
181 SECStatus result = SSL_GetChannelBinding(nss_fd_,
182 SSL_CHANNEL_BINDING_TLS_UNIQUE,
183 buf, &len, arraysize(buf));
184 if (result != SECSuccess) {
185 LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
186 return MapNSSError(PORT_GetError());
188 out->assign(reinterpret_cast<char*>(buf), len);
189 return OK;
192 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
193 NOTIMPLEMENTED();
194 return ERR_NOT_IMPLEMENTED;
197 int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
198 const CompletionCallback& callback) {
199 DCHECK(user_read_callback_.is_null());
200 DCHECK(user_handshake_callback_.is_null());
201 DCHECK(!user_read_buf_.get());
202 DCHECK(nss_bufs_);
203 DCHECK(!callback.is_null());
205 user_read_buf_ = buf;
206 user_read_buf_len_ = buf_len;
208 DCHECK(completed_handshake_);
210 int rv = DoReadLoop(OK);
212 if (rv == ERR_IO_PENDING) {
213 user_read_callback_ = callback;
214 } else {
215 user_read_buf_ = NULL;
216 user_read_buf_len_ = 0;
218 return rv;
221 int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
222 const CompletionCallback& callback) {
223 DCHECK(user_write_callback_.is_null());
224 DCHECK(!user_write_buf_.get());
225 DCHECK(nss_bufs_);
226 DCHECK(!callback.is_null());
228 user_write_buf_ = buf;
229 user_write_buf_len_ = buf_len;
231 int rv = DoWriteLoop(OK);
233 if (rv == ERR_IO_PENDING) {
234 user_write_callback_ = callback;
235 } else {
236 user_write_buf_ = NULL;
237 user_write_buf_len_ = 0;
239 return rv;
242 int SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
243 return transport_socket_->SetReceiveBufferSize(size);
246 int SSLServerSocketNSS::SetSendBufferSize(int32 size) {
247 return transport_socket_->SetSendBufferSize(size);
250 bool SSLServerSocketNSS::IsConnected() const {
251 // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
252 // as well.
253 return completed_handshake_;
256 void SSLServerSocketNSS::Disconnect() {
257 transport_socket_->Disconnect();
260 bool SSLServerSocketNSS::IsConnectedAndIdle() const {
261 return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
264 int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
265 if (!IsConnected())
266 return ERR_SOCKET_NOT_CONNECTED;
267 return transport_socket_->GetPeerAddress(address);
270 int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
271 if (!IsConnected())
272 return ERR_SOCKET_NOT_CONNECTED;
273 return transport_socket_->GetLocalAddress(address);
276 const BoundNetLog& SSLServerSocketNSS::NetLog() const {
277 return net_log_;
280 void SSLServerSocketNSS::SetSubresourceSpeculation() {
281 transport_socket_->SetSubresourceSpeculation();
284 void SSLServerSocketNSS::SetOmniboxSpeculation() {
285 transport_socket_->SetOmniboxSpeculation();
288 bool SSLServerSocketNSS::WasEverUsed() const {
289 return transport_socket_->WasEverUsed();
292 bool SSLServerSocketNSS::UsingTCPFastOpen() const {
293 return transport_socket_->UsingTCPFastOpen();
296 bool SSLServerSocketNSS::WasNpnNegotiated() const {
297 NOTIMPLEMENTED();
298 return false;
301 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
302 // NPN is not supported by this class.
303 return kProtoUnknown;
306 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
307 NOTIMPLEMENTED();
308 return false;
311 int SSLServerSocketNSS::InitializeSSLOptions() {
312 // Transport connected, now hook it up to nss
313 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
314 if (nss_fd_ == NULL) {
315 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
318 // Grab pointer to buffers
319 nss_bufs_ = memio_GetSecret(nss_fd_);
321 /* Create SSL state machine */
322 /* Push SSL onto our fake I/O socket */
323 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
324 if (nss_fd_ == NULL) {
325 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
326 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
328 // TODO(port): set more ssl options! Check errors!
330 int rv;
332 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
333 if (rv != SECSuccess) {
334 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
335 return ERR_UNEXPECTED;
338 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
339 if (rv != SECSuccess) {
340 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
341 return ERR_UNEXPECTED;
344 SSLVersionRange version_range;
345 version_range.min = ssl_config_.version_min;
346 version_range.max = ssl_config_.version_max;
347 rv = SSL_VersionRangeSet(nss_fd_, &version_range);
348 if (rv != SECSuccess) {
349 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
350 return ERR_NO_SSL_VERSIONS_ENABLED;
353 if (ssl_config_.require_forward_secrecy) {
354 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
355 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
357 // Require forward security by iterating over the cipher suites and
358 // disabling all those that don't use ECDHE.
359 for (unsigned i = 0; i < num_ciphers; i++) {
360 SSLCipherSuiteInfo info;
361 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
362 SECSuccess) {
363 if (strcmp(info.keaTypeName, "ECDHE") != 0) {
364 SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
370 for (std::vector<uint16>::const_iterator it =
371 ssl_config_.disabled_cipher_suites.begin();
372 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
373 // This will fail if the specified cipher is not implemented by NSS, but
374 // the failure is harmless.
375 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
378 // Server socket doesn't need session tickets.
379 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
380 if (rv != SECSuccess) {
381 LogFailedNSSFunction(
382 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
385 // Doing this will force PR_Accept perform handshake as server.
386 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
387 if (rv != SECSuccess) {
388 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
389 return ERR_UNEXPECTED;
392 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
393 if (rv != SECSuccess) {
394 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
395 return ERR_UNEXPECTED;
398 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
399 if (rv != SECSuccess) {
400 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
401 return ERR_UNEXPECTED;
404 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
405 if (rv != SECSuccess) {
406 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
407 return ERR_UNEXPECTED;
410 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
411 if (rv != SECSuccess) {
412 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
413 return ERR_UNEXPECTED;
416 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
417 if (rv != SECSuccess) {
418 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
419 return ERR_UNEXPECTED;
422 // Get a certificate of CERTCertificate structure.
423 std::string der_string;
424 if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
425 return ERR_UNEXPECTED;
427 SECItem der_cert;
428 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
429 der_string.data()));
430 der_cert.len = der_string.length();
431 der_cert.type = siDERCertBuffer;
433 // Parse into a CERTCertificate structure.
434 CERTCertificate* cert = CERT_NewTempCertificate(
435 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
436 if (!cert) {
437 LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
438 return MapNSSError(PORT_GetError());
441 // Get a key of SECKEYPrivateKey* structure.
442 std::vector<uint8> key_vector;
443 if (!key_->ExportPrivateKey(&key_vector)) {
444 CERT_DestroyCertificate(cert);
445 return ERR_UNEXPECTED;
448 SECKEYPrivateKeyStr* private_key = NULL;
449 PK11SlotInfo* slot = PK11_GetInternalSlot();
450 if (!slot) {
451 CERT_DestroyCertificate(cert);
452 return ERR_UNEXPECTED;
455 SECItem der_private_key_info;
456 der_private_key_info.data =
457 const_cast<unsigned char*>(&key_vector.front());
458 der_private_key_info.len = key_vector.size();
459 // The server's RSA private key must be imported into NSS with the
460 // following key usage bits:
461 // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
462 // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
463 // exchange algorithms.
464 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
465 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
466 slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
467 key_usage, &private_key, NULL);
468 PK11_FreeSlot(slot);
469 if (rv != SECSuccess) {
470 CERT_DestroyCertificate(cert);
471 return ERR_UNEXPECTED;
474 // Assign server certificate and private key.
475 SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
476 rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
477 CERT_DestroyCertificate(cert);
478 SECKEY_DestroyPrivateKey(private_key);
480 if (rv != SECSuccess) {
481 PRErrorCode prerr = PR_GetError();
482 LOG(ERROR) << "Failed to config SSL server: " << prerr;
483 LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
484 return ERR_UNEXPECTED;
487 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
488 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
489 if (rv != SECSuccess) {
490 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
491 return ERR_UNEXPECTED;
494 return OK;
497 void SSLServerSocketNSS::OnSendComplete(int result) {
498 if (next_handshake_state_ == STATE_HANDSHAKE) {
499 // In handshake phase.
500 OnHandshakeIOComplete(result);
501 return;
504 // TODO(byungchul): This state machine is not correct. Copy the state machine
505 // of SSLClientSocketNSS::OnSendComplete() which handles it better.
506 if (!completed_handshake_)
507 return;
509 if (user_write_buf_.get()) {
510 int rv = DoWriteLoop(result);
511 if (rv != ERR_IO_PENDING)
512 DoWriteCallback(rv);
513 } else {
514 // Ensure that any queued ciphertext is flushed.
515 DoTransportIO();
519 void SSLServerSocketNSS::OnRecvComplete(int result) {
520 if (next_handshake_state_ == STATE_HANDSHAKE) {
521 // In handshake phase.
522 OnHandshakeIOComplete(result);
523 return;
526 // Network layer received some data, check if client requested to read
527 // decrypted data.
528 if (!user_read_buf_.get() || !completed_handshake_)
529 return;
531 int rv = DoReadLoop(result);
532 if (rv != ERR_IO_PENDING)
533 DoReadCallback(rv);
536 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
537 int rv = DoHandshakeLoop(result);
538 if (rv == ERR_IO_PENDING)
539 return;
541 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
542 if (!user_handshake_callback_.is_null())
543 DoHandshakeCallback(rv);
546 // Return 0 for EOF,
547 // > 0 for bytes transferred immediately,
548 // < 0 for error (or the non-error ERR_IO_PENDING).
549 int SSLServerSocketNSS::BufferSend(void) {
550 if (transport_send_busy_)
551 return ERR_IO_PENDING;
553 const char* buf1;
554 const char* buf2;
555 unsigned int len1, len2;
556 if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
557 // The error code itself is ignored, so just return ERR_ABORTED.
558 return ERR_ABORTED;
560 const unsigned int len = len1 + len2;
562 int rv = 0;
563 if (len) {
564 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
565 memcpy(send_buffer->data(), buf1, len1);
566 memcpy(send_buffer->data() + len1, buf2, len2);
567 rv = transport_socket_->Write(
568 send_buffer.get(),
569 len,
570 base::Bind(&SSLServerSocketNSS::BufferSendComplete,
571 base::Unretained(this)));
572 if (rv == ERR_IO_PENDING) {
573 transport_send_busy_ = true;
574 } else {
575 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
579 return rv;
582 void SSLServerSocketNSS::BufferSendComplete(int result) {
583 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
584 transport_send_busy_ = false;
585 OnSendComplete(result);
588 int SSLServerSocketNSS::BufferRecv(void) {
589 if (transport_recv_busy_) return ERR_IO_PENDING;
591 char* buf;
592 int nb = memio_GetReadParams(nss_bufs_, &buf);
593 int rv;
594 if (!nb) {
595 // buffer too full to read into, so no I/O possible at moment
596 rv = ERR_IO_PENDING;
597 } else {
598 recv_buffer_ = new IOBuffer(nb);
599 rv = transport_socket_->Read(
600 recv_buffer_.get(),
602 base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
603 base::Unretained(this)));
604 if (rv == ERR_IO_PENDING) {
605 transport_recv_busy_ = true;
606 } else {
607 if (rv > 0)
608 memcpy(buf, recv_buffer_->data(), rv);
609 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
610 recv_buffer_ = NULL;
613 return rv;
616 void SSLServerSocketNSS::BufferRecvComplete(int result) {
617 if (result > 0) {
618 char* buf;
619 memio_GetReadParams(nss_bufs_, &buf);
620 memcpy(buf, recv_buffer_->data(), result);
622 recv_buffer_ = NULL;
623 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
624 transport_recv_busy_ = false;
625 OnRecvComplete(result);
628 // Do as much network I/O as possible between the buffer and the
629 // transport socket. Return true if some I/O performed, false
630 // otherwise (error or ERR_IO_PENDING).
631 bool SSLServerSocketNSS::DoTransportIO() {
632 bool network_moved = false;
633 if (nss_bufs_ != NULL) {
634 int rv;
635 // Read and write as much data as we can. The loop is neccessary
636 // because Write() may return synchronously.
637 do {
638 rv = BufferSend();
639 if (rv > 0)
640 network_moved = true;
641 } while (rv > 0);
642 if (BufferRecv() >= 0)
643 network_moved = true;
645 return network_moved;
648 int SSLServerSocketNSS::DoPayloadRead() {
649 DCHECK(user_read_buf_.get());
650 DCHECK_GT(user_read_buf_len_, 0);
651 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
652 if (rv >= 0)
653 return rv;
654 PRErrorCode prerr = PR_GetError();
655 if (prerr == PR_WOULD_BLOCK_ERROR) {
656 return ERR_IO_PENDING;
658 rv = MapNSSError(prerr);
659 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
660 CreateNetLogSSLErrorCallback(rv, prerr));
661 return rv;
664 int SSLServerSocketNSS::DoPayloadWrite() {
665 DCHECK(user_write_buf_.get());
666 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
667 if (rv >= 0)
668 return rv;
669 PRErrorCode prerr = PR_GetError();
670 if (prerr == PR_WOULD_BLOCK_ERROR) {
671 return ERR_IO_PENDING;
673 rv = MapNSSError(prerr);
674 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
675 CreateNetLogSSLErrorCallback(rv, prerr));
676 return rv;
679 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
680 int rv = last_io_result;
681 do {
682 // Default to STATE_NONE for next state.
683 // (This is a quirk carried over from the windows
684 // implementation. It makes reading the logs a bit harder.)
685 // State handlers can and often do call GotoState just
686 // to stay in the current state.
687 State state = next_handshake_state_;
688 GotoState(STATE_NONE);
689 switch (state) {
690 case STATE_HANDSHAKE:
691 rv = DoHandshake();
692 break;
693 case STATE_NONE:
694 default:
695 rv = ERR_UNEXPECTED;
696 LOG(DFATAL) << "unexpected state " << state;
697 break;
700 // Do the actual network I/O
701 bool network_moved = DoTransportIO();
702 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
703 // In general we exit the loop if rv is ERR_IO_PENDING. In this
704 // special case we keep looping even if rv is ERR_IO_PENDING because
705 // the transport IO may allow DoHandshake to make progress.
706 rv = OK; // This causes us to stay in the loop.
708 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
709 return rv;
712 int SSLServerSocketNSS::DoReadLoop(int result) {
713 DCHECK(completed_handshake_);
714 DCHECK(next_handshake_state_ == STATE_NONE);
716 if (result < 0)
717 return result;
719 if (!nss_bufs_) {
720 LOG(DFATAL) << "!nss_bufs_";
721 int rv = ERR_UNEXPECTED;
722 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
723 CreateNetLogSSLErrorCallback(rv, 0));
724 return rv;
727 bool network_moved;
728 int rv;
729 do {
730 rv = DoPayloadRead();
731 network_moved = DoTransportIO();
732 } while (rv == ERR_IO_PENDING && network_moved);
733 return rv;
736 int SSLServerSocketNSS::DoWriteLoop(int result) {
737 DCHECK(completed_handshake_);
738 DCHECK_EQ(next_handshake_state_, STATE_NONE);
740 if (result < 0)
741 return result;
743 if (!nss_bufs_) {
744 LOG(DFATAL) << "!nss_bufs_";
745 int rv = ERR_UNEXPECTED;
746 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
747 CreateNetLogSSLErrorCallback(rv, 0));
748 return rv;
751 bool network_moved;
752 int rv;
753 do {
754 rv = DoPayloadWrite();
755 network_moved = DoTransportIO();
756 } while (rv == ERR_IO_PENDING && network_moved);
757 return rv;
760 int SSLServerSocketNSS::DoHandshake() {
761 int net_error = OK;
762 SECStatus rv = SSL_ForceHandshake(nss_fd_);
764 if (rv == SECSuccess) {
765 completed_handshake_ = true;
766 } else {
767 PRErrorCode prerr = PR_GetError();
768 net_error = MapNSSError(prerr);
770 // If not done, stay in this state
771 if (net_error == ERR_IO_PENDING) {
772 GotoState(STATE_HANDSHAKE);
773 } else {
774 LOG(ERROR) << "handshake failed; NSS error code " << prerr
775 << ", net_error " << net_error;
776 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
777 CreateNetLogSSLErrorCallback(net_error, prerr));
780 return net_error;
783 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
784 DCHECK_NE(rv, ERR_IO_PENDING);
785 ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
788 void SSLServerSocketNSS::DoReadCallback(int rv) {
789 DCHECK(rv != ERR_IO_PENDING);
790 DCHECK(!user_read_callback_.is_null());
792 user_read_buf_ = NULL;
793 user_read_buf_len_ = 0;
794 ResetAndReturn(&user_read_callback_).Run(rv);
797 void SSLServerSocketNSS::DoWriteCallback(int rv) {
798 DCHECK(rv != ERR_IO_PENDING);
799 DCHECK(!user_write_callback_.is_null());
801 user_write_buf_ = NULL;
802 user_write_buf_len_ = 0;
803 ResetAndReturn(&user_write_callback_).Run(rv);
806 // static
807 // NSS calls this if an incoming certificate needs to be verified.
808 // Do nothing but return SECSuccess.
809 // This is called only in full handshake mode.
810 // Peer certificate is retrieved in HandshakeCallback() later, which is called
811 // in full handshake mode or in resumption handshake mode.
812 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
813 PRFileDesc* socket,
814 PRBool checksig,
815 PRBool is_server) {
816 // TODO(hclam): Implement.
817 // Tell NSS to not verify the certificate.
818 return SECSuccess;
821 // static
822 // NSS calls this when handshake is completed.
823 // After the SSL handshake is finished we need to verify the certificate.
824 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
825 void* arg) {
826 // TODO(hclam): Implement.
829 int SSLServerSocketNSS::Init() {
830 // Initialize the NSS SSL library in a threadsafe way. This also
831 // initializes the NSS base library.
832 EnsureNSSSSLInit();
833 if (!NSS_IsInitialized())
834 return ERR_UNEXPECTED;
836 EnableSSLServerSockets();
837 return OK;
840 } // namespace net