Convert raw pointers to scoped_ptr in net module.
[chromium-blink-merge.git] / net / socket / ssl_server_socket_nss.cc
blob4483c9111345b938667ec3b77194b7a4044ac230
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/nss_util_internal.h"
36 #include "crypto/rsa_private_key.h"
37 #include "net/base/io_buffer.h"
38 #include "net/base/net_errors.h"
39 #include "net/log/net_log.h"
40 #include "net/socket/nss_ssl_util.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(64, 28800, 28800, 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 scoped_ptr<SSLServerSocket> CreateSSLServerSocket(
82 scoped_ptr<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 scoped_ptr<SSLServerSocket>(
90 new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config));
93 SSLServerSocketNSS::SSLServerSocketNSS(
94 scoped_ptr<StreamSocket> transport_socket,
95 scoped_refptr<X509Certificate> cert,
96 crypto::RSAPrivateKey* key,
97 const SSLConfig& ssl_config)
98 : transport_send_busy_(false),
99 transport_recv_busy_(false),
100 user_read_buf_len_(0),
101 user_write_buf_len_(0),
102 nss_fd_(NULL),
103 nss_bufs_(NULL),
104 transport_socket_(transport_socket.Pass()),
105 ssl_config_(ssl_config),
106 cert_(cert),
107 next_handshake_state_(STATE_NONE),
108 completed_handshake_(false) {
109 // TODO(hclam): Need a better way to clone a key.
110 std::vector<uint8> key_bytes;
111 CHECK(key->ExportPrivateKey(&key_bytes));
112 key_.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_bytes));
113 CHECK(key_.get());
116 SSLServerSocketNSS::~SSLServerSocketNSS() {
117 if (nss_fd_ != NULL) {
118 PR_Close(nss_fd_);
119 nss_fd_ = NULL;
123 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
124 net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
126 int rv = Init();
127 if (rv != OK) {
128 LOG(ERROR) << "Failed to initialize NSS";
129 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
130 return rv;
133 rv = InitializeSSLOptions();
134 if (rv != OK) {
135 LOG(ERROR) << "Failed to initialize SSL options";
136 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
137 return rv;
140 // Set peer address. TODO(hclam): This should be in a separate method.
141 PRNetAddr peername;
142 memset(&peername, 0, sizeof(peername));
143 peername.raw.family = AF_INET;
144 memio_SetPeerName(nss_fd_, &peername);
146 GotoState(STATE_HANDSHAKE);
147 rv = DoHandshakeLoop(OK);
148 if (rv == ERR_IO_PENDING) {
149 user_handshake_callback_ = callback;
150 } else {
151 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
154 return rv > OK ? OK : rv;
157 int SSLServerSocketNSS::ExportKeyingMaterial(const base::StringPiece& label,
158 bool has_context,
159 const base::StringPiece& context,
160 unsigned char* out,
161 unsigned int outlen) {
162 if (!IsConnected())
163 return ERR_SOCKET_NOT_CONNECTED;
164 SECStatus result = SSL_ExportKeyingMaterial(
165 nss_fd_, label.data(), label.size(), has_context,
166 reinterpret_cast<const unsigned char*>(context.data()),
167 context.length(), out, outlen);
168 if (result != SECSuccess) {
169 LogFailedNSSFunction(net_log_, "SSL_ExportKeyingMaterial", "");
170 return MapNSSError(PORT_GetError());
172 return OK;
175 int SSLServerSocketNSS::GetTLSUniqueChannelBinding(std::string* out) {
176 if (!IsConnected())
177 return ERR_SOCKET_NOT_CONNECTED;
178 unsigned char buf[64];
179 unsigned int len;
180 SECStatus result = SSL_GetChannelBinding(nss_fd_,
181 SSL_CHANNEL_BINDING_TLS_UNIQUE,
182 buf, &len, arraysize(buf));
183 if (result != SECSuccess) {
184 LogFailedNSSFunction(net_log_, "SSL_GetChannelBinding", "");
185 return MapNSSError(PORT_GetError());
187 out->assign(reinterpret_cast<char*>(buf), len);
188 return OK;
191 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
192 NOTIMPLEMENTED();
193 return ERR_NOT_IMPLEMENTED;
196 int SSLServerSocketNSS::Read(IOBuffer* buf, int buf_len,
197 const CompletionCallback& callback) {
198 DCHECK(user_read_callback_.is_null());
199 DCHECK(user_handshake_callback_.is_null());
200 DCHECK(!user_read_buf_.get());
201 DCHECK(nss_bufs_);
202 DCHECK(!callback.is_null());
204 user_read_buf_ = buf;
205 user_read_buf_len_ = buf_len;
207 DCHECK(completed_handshake_);
209 int rv = DoReadLoop(OK);
211 if (rv == ERR_IO_PENDING) {
212 user_read_callback_ = callback;
213 } else {
214 user_read_buf_ = NULL;
215 user_read_buf_len_ = 0;
217 return rv;
220 int SSLServerSocketNSS::Write(IOBuffer* buf, int buf_len,
221 const CompletionCallback& callback) {
222 DCHECK(user_write_callback_.is_null());
223 DCHECK(!user_write_buf_.get());
224 DCHECK(nss_bufs_);
225 DCHECK(!callback.is_null());
227 user_write_buf_ = buf;
228 user_write_buf_len_ = buf_len;
230 int rv = DoWriteLoop(OK);
232 if (rv == ERR_IO_PENDING) {
233 user_write_callback_ = callback;
234 } else {
235 user_write_buf_ = NULL;
236 user_write_buf_len_ = 0;
238 return rv;
241 int SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
242 return transport_socket_->SetReceiveBufferSize(size);
245 int SSLServerSocketNSS::SetSendBufferSize(int32 size) {
246 return transport_socket_->SetSendBufferSize(size);
249 bool SSLServerSocketNSS::IsConnected() const {
250 // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
251 // as well.
252 return completed_handshake_;
255 void SSLServerSocketNSS::Disconnect() {
256 transport_socket_->Disconnect();
259 bool SSLServerSocketNSS::IsConnectedAndIdle() const {
260 return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
263 int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
264 if (!IsConnected())
265 return ERR_SOCKET_NOT_CONNECTED;
266 return transport_socket_->GetPeerAddress(address);
269 int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
270 if (!IsConnected())
271 return ERR_SOCKET_NOT_CONNECTED;
272 return transport_socket_->GetLocalAddress(address);
275 const BoundNetLog& SSLServerSocketNSS::NetLog() const {
276 return net_log_;
279 void SSLServerSocketNSS::SetSubresourceSpeculation() {
280 transport_socket_->SetSubresourceSpeculation();
283 void SSLServerSocketNSS::SetOmniboxSpeculation() {
284 transport_socket_->SetOmniboxSpeculation();
287 bool SSLServerSocketNSS::WasEverUsed() const {
288 return transport_socket_->WasEverUsed();
291 bool SSLServerSocketNSS::UsingTCPFastOpen() const {
292 return transport_socket_->UsingTCPFastOpen();
295 bool SSLServerSocketNSS::WasNpnNegotiated() const {
296 NOTIMPLEMENTED();
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 void SSLServerSocketNSS::GetConnectionAttempts(ConnectionAttempts* out) const {
311 out->clear();
314 int SSLServerSocketNSS::InitializeSSLOptions() {
315 // Transport connected, now hook it up to nss
316 nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
317 if (nss_fd_ == NULL) {
318 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
321 // Grab pointer to buffers
322 nss_bufs_ = memio_GetSecret(nss_fd_);
324 /* Create SSL state machine */
325 /* Push SSL onto our fake I/O socket */
326 nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
327 if (nss_fd_ == NULL) {
328 LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
329 return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR/NSS error code.
331 // TODO(port): set more ssl options! Check errors!
333 int rv;
335 rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
336 if (rv != SECSuccess) {
337 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
338 return ERR_UNEXPECTED;
341 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
342 if (rv != SECSuccess) {
343 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
344 return ERR_UNEXPECTED;
347 SSLVersionRange version_range;
348 version_range.min = ssl_config_.version_min;
349 version_range.max = ssl_config_.version_max;
350 rv = SSL_VersionRangeSet(nss_fd_, &version_range);
351 if (rv != SECSuccess) {
352 LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
353 return ERR_NO_SSL_VERSIONS_ENABLED;
356 if (ssl_config_.require_ecdhe) {
357 const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
358 const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
360 // Require forward security by iterating over the cipher suites and
361 // disabling all those that don't use ECDHE.
362 for (unsigned i = 0; i < num_ciphers; i++) {
363 SSLCipherSuiteInfo info;
364 if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
365 SECSuccess) {
366 if (strcmp(info.keaTypeName, "ECDHE") != 0) {
367 SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
373 for (std::vector<uint16>::const_iterator it =
374 ssl_config_.disabled_cipher_suites.begin();
375 it != ssl_config_.disabled_cipher_suites.end(); ++it) {
376 // This will fail if the specified cipher is not implemented by NSS, but
377 // the failure is harmless.
378 SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
381 // Server socket doesn't need session tickets.
382 rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
383 if (rv != SECSuccess) {
384 LogFailedNSSFunction(
385 net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
388 // Doing this will force PR_Accept perform handshake as server.
389 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
390 if (rv != SECSuccess) {
391 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
392 return ERR_UNEXPECTED;
395 rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
396 if (rv != SECSuccess) {
397 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
398 return ERR_UNEXPECTED;
401 rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
402 if (rv != SECSuccess) {
403 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
404 return ERR_UNEXPECTED;
407 rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
408 if (rv != SECSuccess) {
409 LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
410 return ERR_UNEXPECTED;
413 rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
414 if (rv != SECSuccess) {
415 LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
416 return ERR_UNEXPECTED;
419 rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
420 if (rv != SECSuccess) {
421 LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
422 return ERR_UNEXPECTED;
425 // Get a certificate of CERTCertificate structure.
426 std::string der_string;
427 if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
428 return ERR_UNEXPECTED;
430 SECItem der_cert;
431 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
432 der_string.data()));
433 der_cert.len = der_string.length();
434 der_cert.type = siDERCertBuffer;
436 // Parse into a CERTCertificate structure.
437 CERTCertificate* cert = CERT_NewTempCertificate(
438 CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
439 if (!cert) {
440 LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
441 return MapNSSError(PORT_GetError());
444 // Get a key of SECKEYPrivateKey* structure.
445 std::vector<uint8> key_vector;
446 if (!key_->ExportPrivateKey(&key_vector)) {
447 CERT_DestroyCertificate(cert);
448 return ERR_UNEXPECTED;
451 SECKEYPrivateKeyStr* private_key = NULL;
452 PK11SlotInfo* slot = PK11_GetInternalSlot();
453 if (!slot) {
454 CERT_DestroyCertificate(cert);
455 return ERR_UNEXPECTED;
458 SECItem der_private_key_info;
459 der_private_key_info.data =
460 const_cast<unsigned char*>(&key_vector.front());
461 der_private_key_info.len = key_vector.size();
462 // The server's RSA private key must be imported into NSS with the
463 // following key usage bits:
464 // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
465 // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
466 // exchange algorithms.
467 const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
468 rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
469 slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
470 key_usage, &private_key, NULL);
471 PK11_FreeSlot(slot);
472 if (rv != SECSuccess) {
473 CERT_DestroyCertificate(cert);
474 return ERR_UNEXPECTED;
477 // Assign server certificate and private key.
478 SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
479 rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
480 CERT_DestroyCertificate(cert);
481 SECKEY_DestroyPrivateKey(private_key);
483 if (rv != SECSuccess) {
484 PRErrorCode prerr = PR_GetError();
485 LOG(ERROR) << "Failed to config SSL server: " << prerr;
486 LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
487 return ERR_UNEXPECTED;
490 // Tell SSL we're a server; needed if not letting NSPR do socket I/O
491 rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
492 if (rv != SECSuccess) {
493 LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
494 return ERR_UNEXPECTED;
497 return OK;
500 void SSLServerSocketNSS::OnSendComplete(int result) {
501 if (next_handshake_state_ == STATE_HANDSHAKE) {
502 // In handshake phase.
503 OnHandshakeIOComplete(result);
504 return;
507 // TODO(byungchul): This state machine is not correct. Copy the state machine
508 // of SSLClientSocketNSS::OnSendComplete() which handles it better.
509 if (!completed_handshake_)
510 return;
512 if (user_write_buf_.get()) {
513 int rv = DoWriteLoop(result);
514 if (rv != ERR_IO_PENDING)
515 DoWriteCallback(rv);
516 } else {
517 // Ensure that any queued ciphertext is flushed.
518 DoTransportIO();
522 void SSLServerSocketNSS::OnRecvComplete(int result) {
523 if (next_handshake_state_ == STATE_HANDSHAKE) {
524 // In handshake phase.
525 OnHandshakeIOComplete(result);
526 return;
529 // Network layer received some data, check if client requested to read
530 // decrypted data.
531 if (!user_read_buf_.get() || !completed_handshake_)
532 return;
534 int rv = DoReadLoop(result);
535 if (rv != ERR_IO_PENDING)
536 DoReadCallback(rv);
539 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
540 int rv = DoHandshakeLoop(result);
541 if (rv == ERR_IO_PENDING)
542 return;
544 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
545 if (!user_handshake_callback_.is_null())
546 DoHandshakeCallback(rv);
549 // Return 0 for EOF,
550 // > 0 for bytes transferred immediately,
551 // < 0 for error (or the non-error ERR_IO_PENDING).
552 int SSLServerSocketNSS::BufferSend(void) {
553 if (transport_send_busy_)
554 return ERR_IO_PENDING;
556 const char* buf1;
557 const char* buf2;
558 unsigned int len1, len2;
559 if (memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2)) {
560 // The error code itself is ignored, so just return ERR_ABORTED.
561 return ERR_ABORTED;
563 const size_t len = len1 + len2;
565 int rv = 0;
566 if (len) {
567 scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
568 memcpy(send_buffer->data(), buf1, len1);
569 memcpy(send_buffer->data() + len1, buf2, len2);
570 rv = transport_socket_->Write(
571 send_buffer.get(),
572 len,
573 base::Bind(&SSLServerSocketNSS::BufferSendComplete,
574 base::Unretained(this)));
575 if (rv == ERR_IO_PENDING) {
576 transport_send_busy_ = true;
577 } else {
578 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
582 return rv;
585 void SSLServerSocketNSS::BufferSendComplete(int result) {
586 memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
587 transport_send_busy_ = false;
588 OnSendComplete(result);
591 int SSLServerSocketNSS::BufferRecv(void) {
592 if (transport_recv_busy_) return ERR_IO_PENDING;
594 char* buf;
595 int nb = memio_GetReadParams(nss_bufs_, &buf);
596 int rv;
597 if (!nb) {
598 // buffer too full to read into, so no I/O possible at moment
599 rv = ERR_IO_PENDING;
600 } else {
601 recv_buffer_ = new IOBuffer(nb);
602 rv = transport_socket_->Read(
603 recv_buffer_.get(),
605 base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
606 base::Unretained(this)));
607 if (rv == ERR_IO_PENDING) {
608 transport_recv_busy_ = true;
609 } else {
610 if (rv > 0)
611 memcpy(buf, recv_buffer_->data(), rv);
612 memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
613 recv_buffer_ = NULL;
616 return rv;
619 void SSLServerSocketNSS::BufferRecvComplete(int result) {
620 if (result > 0) {
621 char* buf;
622 memio_GetReadParams(nss_bufs_, &buf);
623 memcpy(buf, recv_buffer_->data(), result);
625 recv_buffer_ = NULL;
626 memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
627 transport_recv_busy_ = false;
628 OnRecvComplete(result);
631 // Do as much network I/O as possible between the buffer and the
632 // transport socket. Return true if some I/O performed, false
633 // otherwise (error or ERR_IO_PENDING).
634 bool SSLServerSocketNSS::DoTransportIO() {
635 bool network_moved = false;
636 if (nss_bufs_ != NULL) {
637 int rv;
638 // Read and write as much data as we can. The loop is neccessary
639 // because Write() may return synchronously.
640 do {
641 rv = BufferSend();
642 if (rv > 0)
643 network_moved = true;
644 } while (rv > 0);
645 if (BufferRecv() >= 0)
646 network_moved = true;
648 return network_moved;
651 int SSLServerSocketNSS::DoPayloadRead() {
652 DCHECK(user_read_buf_.get());
653 DCHECK_GT(user_read_buf_len_, 0);
654 int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_buf_len_);
655 if (rv >= 0)
656 return rv;
657 PRErrorCode prerr = PR_GetError();
658 if (prerr == PR_WOULD_BLOCK_ERROR) {
659 return ERR_IO_PENDING;
661 rv = MapNSSError(prerr);
662 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
663 CreateNetLogSSLErrorCallback(rv, prerr));
664 return rv;
667 int SSLServerSocketNSS::DoPayloadWrite() {
668 DCHECK(user_write_buf_.get());
669 int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
670 if (rv >= 0)
671 return rv;
672 PRErrorCode prerr = PR_GetError();
673 if (prerr == PR_WOULD_BLOCK_ERROR) {
674 return ERR_IO_PENDING;
676 rv = MapNSSError(prerr);
677 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
678 CreateNetLogSSLErrorCallback(rv, prerr));
679 return rv;
682 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
683 int rv = last_io_result;
684 do {
685 // Default to STATE_NONE for next state.
686 // (This is a quirk carried over from the windows
687 // implementation. It makes reading the logs a bit harder.)
688 // State handlers can and often do call GotoState just
689 // to stay in the current state.
690 State state = next_handshake_state_;
691 GotoState(STATE_NONE);
692 switch (state) {
693 case STATE_HANDSHAKE:
694 rv = DoHandshake();
695 break;
696 case STATE_NONE:
697 default:
698 rv = ERR_UNEXPECTED;
699 LOG(DFATAL) << "unexpected state " << state;
700 break;
703 // Do the actual network I/O
704 bool network_moved = DoTransportIO();
705 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
706 // In general we exit the loop if rv is ERR_IO_PENDING. In this
707 // special case we keep looping even if rv is ERR_IO_PENDING because
708 // the transport IO may allow DoHandshake to make progress.
709 rv = OK; // This causes us to stay in the loop.
711 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
712 return rv;
715 int SSLServerSocketNSS::DoReadLoop(int result) {
716 DCHECK(completed_handshake_);
717 DCHECK(next_handshake_state_ == STATE_NONE);
719 if (result < 0)
720 return result;
722 if (!nss_bufs_) {
723 LOG(DFATAL) << "!nss_bufs_";
724 int rv = ERR_UNEXPECTED;
725 net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
726 CreateNetLogSSLErrorCallback(rv, 0));
727 return rv;
730 bool network_moved;
731 int rv;
732 do {
733 rv = DoPayloadRead();
734 network_moved = DoTransportIO();
735 } while (rv == ERR_IO_PENDING && network_moved);
736 return rv;
739 int SSLServerSocketNSS::DoWriteLoop(int result) {
740 DCHECK(completed_handshake_);
741 DCHECK_EQ(next_handshake_state_, STATE_NONE);
743 if (result < 0)
744 return result;
746 if (!nss_bufs_) {
747 LOG(DFATAL) << "!nss_bufs_";
748 int rv = ERR_UNEXPECTED;
749 net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
750 CreateNetLogSSLErrorCallback(rv, 0));
751 return rv;
754 bool network_moved;
755 int rv;
756 do {
757 rv = DoPayloadWrite();
758 network_moved = DoTransportIO();
759 } while (rv == ERR_IO_PENDING && network_moved);
760 return rv;
763 int SSLServerSocketNSS::DoHandshake() {
764 int net_error = OK;
765 SECStatus rv = SSL_ForceHandshake(nss_fd_);
767 if (rv == SECSuccess) {
768 completed_handshake_ = true;
769 } else {
770 PRErrorCode prerr = PR_GetError();
771 net_error = MapNSSError(prerr);
773 // If not done, stay in this state
774 if (net_error == ERR_IO_PENDING) {
775 GotoState(STATE_HANDSHAKE);
776 } else {
777 LOG(ERROR) << "handshake failed; NSS error code " << prerr
778 << ", net_error " << net_error;
779 net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
780 CreateNetLogSSLErrorCallback(net_error, prerr));
783 return net_error;
786 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
787 DCHECK_NE(rv, ERR_IO_PENDING);
788 ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
791 void SSLServerSocketNSS::DoReadCallback(int rv) {
792 DCHECK(rv != ERR_IO_PENDING);
793 DCHECK(!user_read_callback_.is_null());
795 user_read_buf_ = NULL;
796 user_read_buf_len_ = 0;
797 ResetAndReturn(&user_read_callback_).Run(rv);
800 void SSLServerSocketNSS::DoWriteCallback(int rv) {
801 DCHECK(rv != ERR_IO_PENDING);
802 DCHECK(!user_write_callback_.is_null());
804 user_write_buf_ = NULL;
805 user_write_buf_len_ = 0;
806 ResetAndReturn(&user_write_callback_).Run(rv);
809 // static
810 // NSS calls this if an incoming certificate needs to be verified.
811 // Do nothing but return SECSuccess.
812 // This is called only in full handshake mode.
813 // Peer certificate is retrieved in HandshakeCallback() later, which is called
814 // in full handshake mode or in resumption handshake mode.
815 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
816 PRFileDesc* socket,
817 PRBool checksig,
818 PRBool is_server) {
819 // TODO(hclam): Implement.
820 // Tell NSS to not verify the certificate.
821 return SECSuccess;
824 // static
825 // NSS calls this when handshake is completed.
826 // After the SSL handshake is finished we need to verify the certificate.
827 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
828 void* arg) {
829 // TODO(hclam): Implement.
832 int SSLServerSocketNSS::Init() {
833 // Initialize the NSS SSL library in a threadsafe way. This also
834 // initializes the NSS base library.
835 EnsureNSSSSLInit();
836 if (!NSS_IsInitialized())
837 return ERR_UNEXPECTED;
839 EnableSSLServerSockets();
840 return OK;
843 } // namespace net