Fix Telemetry media seek action flakiness.
[chromium-blink-merge.git] / net / socket / ssl_server_socket_nss.cc
blobc2681d3ee14436d6d9c3b33ee575aef62e02398d
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/lazy_instance.h"
33 #include "base/memory/ref_counted.h"
34 #include "crypto/rsa_private_key.h"
35 #include "crypto/nss_util_internal.h"
36 #include "net/base/io_buffer.h"
37 #include "net/base/net_errors.h"
38 #include "net/base/net_log.h"
39 #include "net/socket/nss_ssl_util.h"
40 #include "net/socket/ssl_error_params.h"
42 // SSL plaintext fragments are shorter than 16KB. Although the record layer
43 // overhead is allowed to be 2K + 5 bytes, in practice the overhead is much
44 // smaller than 1KB. So a 17KB buffer should be large enough to hold an
45 // entire SSL record.
46 static const int kRecvBufferSize = 17 * 1024;
47 static const int kSendBufferSize = 17 * 1024;
49 #define GotoState(s) next_handshake_state_ = s
51 namespace net {
53 namespace {
55 bool g_nss_server_sockets_init = false;
57 class NSSSSLServerInitSingleton {
58 public:
59 NSSSSLServerInitSingleton() {
60 EnsureNSSSSLInit();
62 SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
63 g_nss_server_sockets_init = true;
66 ~NSSSSLServerInitSingleton() {
67 SSL_ShutdownServerSessionIDCache();
68 g_nss_server_sockets_init = false;
72 static base::LazyInstance<NSSSSLServerInitSingleton>
73 g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
75 } // namespace
77 void EnableSSLServerSockets() {
78 g_nss_ssl_server_init_singleton.Get();
81 SSLServerSocket* CreateSSLServerSocket(
82 StreamSocket* socket,
83 X509Certificate* cert,
84 crypto::RSAPrivateKey* key,
85 const SSLConfig& ssl_config) {
86 DCHECK(g_nss_server_sockets_init) << "EnableSSLServerSockets() has not been"
87 << "called yet!";
89 return new SSLServerSocketNSS(socket, cert, key, ssl_config);
92 SSLServerSocketNSS::SSLServerSocketNSS(
93 StreamSocket* transport_socket,
94 scoped_refptr<X509Certificate> cert,
95 crypto::RSAPrivateKey* key,
96 const SSLConfig& ssl_config)
97 : transport_send_busy_(false),
98 transport_recv_busy_(false),
99 user_read_buf_len_(0),
100 user_write_buf_len_(0),
101 nss_fd_(NULL),
102 nss_bufs_(NULL),
103 transport_socket_(transport_socket),
104 ssl_config_(ssl_config),
105 cert_(cert),
106 next_handshake_state_(STATE_NONE),
107 completed_handshake_(false) {
108 ssl_config_.false_start_enabled = false;
109 ssl_config_.version_min = SSL_PROTOCOL_VERSION_SSL3;
110 ssl_config_.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
112 // TODO(hclam): Need a better way to clone a key.
113 std::vector<uint8> key_bytes;
114 CHECK(key->ExportPrivateKey(&key_bytes));
115 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
116 CHECK(key_.get());
119 SSLServerSocketNSS::~SSLServerSocketNSS() {
120 if (nss_fd_ != NULL) {
121 PR_Close(nss_fd_);
122 nss_fd_ = NULL;
126 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
127 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
129 int rv = Init();
130 if (rv != OK) {
131 LOG(ERROR) << "Failed to initialize NSS";
132 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
133 return rv;
136 rv = InitializeSSLOptions();
137 if (rv != OK) {
138 LOG(ERROR) << "Failed to initialize SSL options";
139 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
140 return rv;
143 // Set peer address. TODO(hclam): This should be in a separate method.
144 PRNetAddr peername;
145 memset(&peername, 0, sizeof(peername));
146 peername.raw.family = AF_INET;
147 memio_SetPeerName(nss_fd_, &peername);
149 GotoState(STATE_HANDSHAKE);
150 rv = DoHandshakeLoop(OK);
151 if (rv == ERR_IO_PENDING) {
152 user_handshake_callback_ = callback;
153 } else {
154 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
157 return rv > OK ? OK : rv;
160 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
161 bool has_context,
162 const base::StringPiece& context,
163 unsigned char* out,
164 unsigned int outlen) {
165 if (!IsConnected())
166 return ERR_SOCKET_NOT_CONNECTED;
167 SECStatus result = SSL_ExportKeyingMaterial(
168 nss_fd_, label.data(), label.size(), has_context,
169 reinterpret_cast<const unsigned char*>(context.data()),
170 context.length(), out, outlen);
171 if (result != SECSuccess) {
172 LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
173 return MapNSSError(PORT_GetError());
175 return OK;
178 int SSLServerSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
179 if (!IsConnected())
180 return ERR_SOCKET_NOT_CONNECTED;
181 unsigned char buf[64];
182 unsigned int len;
183 SECStatus result = SSL_GetChannelBinding(nss_fd_,
184 SSL_CHANNEL_BINDING_TLS_UNIQUE,
185 buf, &len, arraysize(buf));
186 if (result != SECSuccess) {
187 LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
188 return MapNSSError(PORT_GetError());
190 out->assign(reinterpret_cast<char*>(buf), len);
191 return OK;
194 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
195 NOTIMPLEMENTED();
196 return ERR_NOT_IMPLEMENTED;
199 int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
200 const CompletionCallback& callback) {
201 DCHECK(user_read_callback_.is_null());
202 DCHECK(user_handshake_callback_.is_null());
203 DCHECK(!user_read_buf_.get());
204 DCHECK(nss_bufs_);
205 DCHECK(!callback.is_null());
207 user_read_buf_ = buf;
208 user_read_buf_len_ = buf_len;
210 DCHECK(completed_handshake_);
212 int rv = DoReadLoop(OK);
214 if (rv == ERR_IO_PENDING) {
215 user_read_callback_ = callback;
216 } else {
217 user_read_buf_ = NULL;
218 user_read_buf_len_ = 0;
220 return rv;
223 int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
224 const CompletionCallback& callback) {
225 DCHECK(user_write_callback_.is_null());
226 DCHECK(!user_write_buf_.get());
227 DCHECK(nss_bufs_);
228 DCHECK(!callback.is_null());
230 user_write_buf_ = buf;
231 user_write_buf_len_ = buf_len;
233 int rv = DoWriteLoop(OK);
235 if (rv == ERR_IO_PENDING) {
236 user_write_callback_ = callback;
237 } else {
238 user_write_buf_ = NULL;
239 user_write_buf_len_ = 0;
241 return rv;
244 bool SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
245 return transport_socket_->SetReceiveBufferSize(size);
248 bool SSLServerSocketNSS::SetSendBufferSize(int32 size) {
249 return transport_socket_->SetSendBufferSize(size);
252 bool SSLServerSocketNSS::IsConnected() const {
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 return false;
300 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
301 // NPN is not supported by this class.
302 return kProtoUnknown;
305 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
306 NOTIMPLEMENTED();
307 return false;
310 int SSLServerSocketNSS::InitializeSSLOptions() {
311 // Transport connected, now hook it up to nss
312 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
313 if (nss_fd_ == NULL) {
314 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
317 // Grab pointer to buffers
318 nss_bufs_ = memio_GetSecret(nss_fd_);
320 /* Create SSL state machine */
321 /* Push SSL onto our fake I/O socket */
322 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
323 if (nss_fd_ == NULL) {
324 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
325 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
327 // TODO(port): set more ssl options! Check errors!
329 int rv;
331 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
332 if (rv != SECSuccess) {
333 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
334 return ERR_UNEXPECTED;
337 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
338 if (rv != SECSuccess) {
339 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
340 return ERR_UNEXPECTED;
343 SSLVersionRange version_range;
344 version_range.min = ssl_config_.version_min;
345 version_range.max = ssl_config_.version_max;
346 rv = SSL_VersionRangeSet(nss_fd_, &version_range);
347 if (rv != SECSuccess) {
348 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
349 return ERR_NO_SSL_VERSIONS_ENABLED;
352 for (std::vector<uint16>::const_iterator it =
353 ssl_config_.disabled_cipher_suites.begin();
354 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
355 // This will fail if the specified cipher is not implemented by NSS, but
356 // the failure is harmless.
357 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
360 // Server socket doesn't need session tickets.
361 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
362 if (rv != SECSuccess) {
363 LogFailedNSSFunction(
364 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
367 // Doing this will force PR_Accept perform handshake as server.
368 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
369 if (rv != SECSuccess) {
370 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
371 return ERR_UNEXPECTED;
374 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
375 if (rv != SECSuccess) {
376 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
377 return ERR_UNEXPECTED;
380 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
381 if (rv != SECSuccess) {
382 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
383 return ERR_UNEXPECTED;
386 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
387 if (rv != SECSuccess) {
388 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
389 return ERR_UNEXPECTED;
392 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
393 if (rv != SECSuccess) {
394 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
395 return ERR_UNEXPECTED;
398 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
399 if (rv != SECSuccess) {
400 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
401 return ERR_UNEXPECTED;
404 // Get a certificate of CERTCertificate structure.
405 std::string der_string;
406 if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
407 return ERR_UNEXPECTED;
409 SECItem der_cert;
410 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
411 der_string.data()));
412 der_cert.len = der_string.length();
413 der_cert.type = siDERCertBuffer;
415 // Parse into a CERTCertificate structure.
416 CERTCertificate* cert = CERT_NewTempCertificate(
417 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
418 if (!cert) {
419 LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
420 return MapNSSError(PORT_GetError());
423 // Get a key of SECKEYPrivateKey* structure.
424 std::vector<uint8> key_vector;
425 if (!key_->ExportPrivateKey(&key_vector)) {
426 CERT_DestroyCertificate(cert);
427 return ERR_UNEXPECTED;
430 SECKEYPrivateKeyStr* private_key = NULL;
431 PK11SlotInfo* slot = crypto::GetPrivateNSSKeySlot();
432 if (!slot) {
433 CERT_DestroyCertificate(cert);
434 return ERR_UNEXPECTED;
437 SECItem der_private_key_info;
438 der_private_key_info.data =
439 const_cast<unsigned char*>(&key_vector.front());
440 der_private_key_info.len = key_vector.size();
441 // The server's RSA private key must be imported into NSS with the
442 // following key usage bits:
443 // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
444 // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
445 // exchange algorithms.
446 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
447 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
448 slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
449 key_usage, &private_key, NULL);
450 PK11_FreeSlot(slot);
451 if (rv != SECSuccess) {
452 CERT_DestroyCertificate(cert);
453 return ERR_UNEXPECTED;
456 // Assign server certificate and private key.
457 SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
458 rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
459 CERT_DestroyCertificate(cert);
460 SECKEY_DestroyPrivateKey(private_key);
462 if (rv != SECSuccess) {
463 PRErrorCode prerr = PR_GetError();
464 LOG(ERROR) << "Failed to config SSL server: " << prerr;
465 LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
466 return ERR_UNEXPECTED;
469 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
470 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
471 if (rv != SECSuccess) {
472 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
473 return ERR_UNEXPECTED;
476 return OK;
479 void SSLServerSocketNSS::OnSendComplete(int result) {
480 if (next_handshake_state_ == STATE_HANDSHAKE) {
481 // In handshake phase.
482 OnHandshakeIOComplete(result);
483 return;
486 if (!completed_handshake_)
487 return;
489 if (user_write_buf_.get()) {
490 int rv = DoWriteLoop(result);
491 if (rv != ERR_IO_PENDING)
492 DoWriteCallback(rv);
493 } else {
494 // Ensure that any queued ciphertext is flushed.
495 DoTransportIO();
499 void SSLServerSocketNSS::OnRecvComplete(int result) {
500 if (next_handshake_state_ == STATE_HANDSHAKE) {
501 // In handshake phase.
502 OnHandshakeIOComplete(result);
503 return;
506 // Network layer received some data, check if client requested to read
507 // decrypted data.
508 if (!user_read_buf_.get() || !completed_handshake_)
509 return;
511 int rv = DoReadLoop(result);
512 if (rv != ERR_IO_PENDING)
513 DoReadCallback(rv);
516 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
517 int rv = DoHandshakeLoop(result);
518 if (rv != ERR_IO_PENDING) {
519 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
520 if (!user_handshake_callback_.is_null())
521 DoHandshakeCallback(rv);
525 // Return 0 for EOF,
526 // > 0 for bytes transferred immediately,
527 // < 0 for error (or the non-error ERR_IO_PENDING).
528 int SSLServerSocketNSS::BufferSend(void) {
529 if (transport_send_busy_)
530 return ERR_IO_PENDING;
532 const char* buf1;
533 const char* buf2;
534 unsigned int len1, len2;
535 memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
536 const unsigned int len = len1 + len2;
538 int rv = 0;
539 if (len) {
540 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
541 memcpy(send_buffer->data(), buf1, len1);
542 memcpy(send_buffer->data() + len1, buf2, len2);
543 rv = transport_socket_->Write(
544 send_buffer.get(),
545 len,
546 base::Bind(&SSLServerSocketNSS::BufferSendComplete,
547 base::Unretained(this)));
548 if (rv == ERR_IO_PENDING) {
549 transport_send_busy_ = true;
550 } else {
551 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
555 return rv;
558 void SSLServerSocketNSS::BufferSendComplete(int result) {
559 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
560 transport_send_busy_ = false;
561 OnSendComplete(result);
564 int SSLServerSocketNSS::BufferRecv(void) {
565 if (transport_recv_busy_) return ERR_IO_PENDING;
567 char* buf;
568 int nb = memio_GetReadParams(nss_bufs_, &buf);
569 int rv;
570 if (!nb) {
571 // buffer too full to read into, so no I/O possible at moment
572 rv = ERR_IO_PENDING;
573 } else {
574 recv_buffer_ = new IOBuffer(nb);
575 rv = transport_socket_->Read(
576 recv_buffer_.get(),
578 base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
579 base::Unretained(this)));
580 if (rv == ERR_IO_PENDING) {
581 transport_recv_busy_ = true;
582 } else {
583 if (rv > 0)
584 memcpy(buf, recv_buffer_->data(), rv);
585 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
586 recv_buffer_ = NULL;
589 return rv;
592 void SSLServerSocketNSS::BufferRecvComplete(int result) {
593 if (result > 0) {
594 char* buf;
595 memio_GetReadParams(nss_bufs_, &buf);
596 memcpy(buf, recv_buffer_->data(), result);
598 recv_buffer_ = NULL;
599 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
600 transport_recv_busy_ = false;
601 OnRecvComplete(result);
604 // Do as much network I/O as possible between the buffer and the
605 // transport socket. Return true if some I/O performed, false
606 // otherwise (error or ERR_IO_PENDING).
607 bool SSLServerSocketNSS::DoTransportIO() {
608 bool network_moved = false;
609 if (nss_bufs_ != NULL) {
610 int rv;
611 // Read and write as much data as we can. The loop is neccessary
612 // because Write() may return synchronously.
613 do {
614 rv = BufferSend();
615 if (rv > 0)
616 network_moved = true;
617 } while (rv > 0);
618 if (BufferRecv() >= 0)
619 network_moved = true;
621 return network_moved;
624 int SSLServerSocketNSS::DoPayloadRead() {
625 DCHECK(user_read_buf_.get());
626 DCHECK_GT(user_read_buf_len_, 0);
627 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
628 if (rv >= 0)
629 return rv;
630 PRErrorCode prerr = PR_GetError();
631 if (prerr == PR_WOULD_BLOCK_ERROR) {
632 return ERR_IO_PENDING;
634 rv = MapNSSError(prerr);
635 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
636 CreateNetLogSSLErrorCallback(rv, prerr));
637 return rv;
640 int SSLServerSocketNSS::DoPayloadWrite() {
641 DCHECK(user_write_buf_.get());
642 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
643 if (rv >= 0)
644 return rv;
645 PRErrorCode prerr = PR_GetError();
646 if (prerr == PR_WOULD_BLOCK_ERROR) {
647 return ERR_IO_PENDING;
649 rv = MapNSSError(prerr);
650 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
651 CreateNetLogSSLErrorCallback(rv, prerr));
652 return rv;
655 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
656 int rv = last_io_result;
657 do {
658 // Default to STATE_NONE for next state.
659 // (This is a quirk carried over from the windows
660 // implementation. It makes reading the logs a bit harder.)
661 // State handlers can and often do call GotoState just
662 // to stay in the current state.
663 State state = next_handshake_state_;
664 GotoState(STATE_NONE);
665 switch (state) {
666 case STATE_HANDSHAKE:
667 rv = DoHandshake();
668 break;
669 case STATE_NONE:
670 default:
671 rv = ERR_UNEXPECTED;
672 LOG(DFATAL) << "unexpected state " << state;
673 break;
676 // Do the actual network I/O
677 bool network_moved = DoTransportIO();
678 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
679 // In general we exit the loop if rv is ERR_IO_PENDING. In this
680 // special case we keep looping even if rv is ERR_IO_PENDING because
681 // the transport IO may allow DoHandshake to make progress.
682 rv = OK; // This causes us to stay in the loop.
684 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
685 return rv;
688 int SSLServerSocketNSS::DoReadLoop(int result) {
689 DCHECK(completed_handshake_);
690 DCHECK(next_handshake_state_ == STATE_NONE);
692 if (result < 0)
693 return result;
695 if (!nss_bufs_) {
696 LOG(DFATAL) << "!nss_bufs_";
697 int rv = ERR_UNEXPECTED;
698 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
699 CreateNetLogSSLErrorCallback(rv, 0));
700 return rv;
703 bool network_moved;
704 int rv;
705 do {
706 rv = DoPayloadRead();
707 network_moved = DoTransportIO();
708 } while (rv == ERR_IO_PENDING && network_moved);
709 return rv;
712 int SSLServerSocketNSS::DoWriteLoop(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_WRITE_ERROR,
723 CreateNetLogSSLErrorCallback(rv, 0));
724 return rv;
727 bool network_moved;
728 int rv;
729 do {
730 rv = DoPayloadWrite();
731 network_moved = DoTransportIO();
732 } while (rv == ERR_IO_PENDING && network_moved);
733 return rv;
736 int SSLServerSocketNSS::DoHandshake() {
737 int net_error = OK;
738 SECStatus rv = SSL_ForceHandshake(nss_fd_);
740 if (rv == SECSuccess) {
741 completed_handshake_ = true;
742 } else {
743 PRErrorCode prerr = PR_GetError();
744 net_error = MapNSSError(prerr);
746 // If not done, stay in this state
747 if (net_error == ERR_IO_PENDING) {
748 GotoState(STATE_HANDSHAKE);
749 } else {
750 LOG(ERROR) << "handshake failed; NSS error code " << prerr
751 << ", net_error " << net_error;
752 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
753 CreateNetLogSSLErrorCallback(net_error, prerr));
756 return net_error;
759 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
760 DCHECK_NE(rv, ERR_IO_PENDING);
762 CompletionCallback c = user_handshake_callback_;
763 user_handshake_callback_.Reset();
764 c.Run(rv > OK ? OK : rv);
767 void SSLServerSocketNSS::DoReadCallback(int rv) {
768 DCHECK(rv != ERR_IO_PENDING);
769 DCHECK(!user_read_callback_.is_null());
771 // Since Run may result in Read being called, clear |user_read_callback_|
772 // up front.
773 CompletionCallback c = user_read_callback_;
774 user_read_callback_.Reset();
775 user_read_buf_ = NULL;
776 user_read_buf_len_ = 0;
777 c.Run(rv);
780 void SSLServerSocketNSS::DoWriteCallback(int rv) {
781 DCHECK(rv != ERR_IO_PENDING);
782 DCHECK(!user_write_callback_.is_null());
784 // Since Run may result in Write being called, clear |user_write_callback_|
785 // up front.
786 CompletionCallback c = user_write_callback_;
787 user_write_callback_.Reset();
788 user_write_buf_ = NULL;
789 user_write_buf_len_ = 0;
790 c.Run(rv);
793 // static
794 // NSS calls this if an incoming certificate needs to be verified.
795 // Do nothing but return SECSuccess.
796 // This is called only in full handshake mode.
797 // Peer certificate is retrieved in HandshakeCallback() later, which is called
798 // in full handshake mode or in resumption handshake mode.
799 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
800 PRFileDesc* socket,
801 PRBool checksig,
802 PRBool is_server) {
803 // TODO(hclam): Implement.
804 // Tell NSS to not verify the certificate.
805 return SECSuccess;
808 // static
809 // NSS calls this when handshake is completed.
810 // After the SSL handshake is finished we need to verify the certificate.
811 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
812 void* arg) {
813 // TODO(hclam): Implement.
816 int SSLServerSocketNSS::Init() {
817 // Initialize the NSS SSL library in a threadsafe way. This also
818 // initializes the NSS base library.
819 EnsureNSSSSLInit();
820 if (!NSS_IsInitialized())
821 return ERR_UNEXPECTED;
823 EnableSSLServerSockets();
824 return OK;
827 } // namespace net