- add sources.
[platform/framework/web/crosswalk.git] / src / net / socket / ssl_server_socket_nss.cc
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.
4
5 #include "net/socket/ssl_server_socket_nss.h"
6
7 #if defined(OS_WIN)
8 #include <winsock2.h>
9 #endif
10
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>
29
30 #include <limits>
31
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"
41
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;
48
49 #define GotoState(s) next_handshake_state_ = s
50
51 namespace net {
52
53 namespace {
54
55 bool g_nss_server_sockets_init = false;
56
57 class NSSSSLServerInitSingleton {
58  public:
59   NSSSSLServerInitSingleton() {
60     EnsureNSSSSLInit();
61
62     SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
63     g_nss_server_sockets_init = true;
64   }
65
66   ~NSSSSLServerInitSingleton() {
67     SSL_ShutdownServerSessionIDCache();
68     g_nss_server_sockets_init = false;
69   }
70 };
71
72 static base::LazyInstance<NSSSSLServerInitSingleton>
73     g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
74
75 }  // namespace
76
77 void EnableSSLServerSockets() {
78   g_nss_ssl_server_init_singleton.Get();
79 }
80
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!";
88
89   return scoped_ptr<SSLServerSocket>(
90       new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config));
91 }
92
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());
114 }
115
116 SSLServerSocketNSS::~SSLServerSocketNSS() {
117   if (nss_fd_ != NULL) {
118     PR_Close(nss_fd_);
119     nss_fd_ = NULL;
120   }
121 }
122
123 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
124   net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
125
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;
131   }
132
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;
138   }
139
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);
145
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);
152   }
153
154   return rv > OK ? OK : rv;
155 }
156
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());
171   }
172   return OK;
173 }
174
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());
186   }
187   out->assign(reinterpret_cast<char*>(buf), len);
188   return OK;
189 }
190
191 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
192   NOTIMPLEMENTED();
193   return ERR_NOT_IMPLEMENTED;
194 }
195
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());
203
204   user_read_buf_ = buf;
205   user_read_buf_len_ = buf_len;
206
207   DCHECK(completed_handshake_);
208
209   int rv = DoReadLoop(OK);
210
211   if (rv == ERR_IO_PENDING) {
212     user_read_callback_ = callback;
213   } else {
214     user_read_buf_ = NULL;
215     user_read_buf_len_ = 0;
216   }
217   return rv;
218 }
219
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());
226
227   user_write_buf_ = buf;
228   user_write_buf_len_ = buf_len;
229
230   int rv = DoWriteLoop(OK);
231
232   if (rv == ERR_IO_PENDING) {
233     user_write_callback_ = callback;
234   } else {
235     user_write_buf_ = NULL;
236     user_write_buf_len_ = 0;
237   }
238   return rv;
239 }
240
241 bool SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
242   return transport_socket_->SetReceiveBufferSize(size);
243 }
244
245 bool SSLServerSocketNSS::SetSendBufferSize(int32 size) {
246   return transport_socket_->SetSendBufferSize(size);
247 }
248
249 bool SSLServerSocketNSS::IsConnected() const {
250   return completed_handshake_;
251 }
252
253 void SSLServerSocketNSS::Disconnect() {
254   transport_socket_->Disconnect();
255 }
256
257 bool SSLServerSocketNSS::IsConnectedAndIdle() const {
258   return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
259 }
260
261 int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
262   if (!IsConnected())
263     return ERR_SOCKET_NOT_CONNECTED;
264   return transport_socket_->GetPeerAddress(address);
265 }
266
267 int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
268   if (!IsConnected())
269     return ERR_SOCKET_NOT_CONNECTED;
270   return transport_socket_->GetLocalAddress(address);
271 }
272
273 const BoundNetLog& SSLServerSocketNSS::NetLog() const {
274   return net_log_;
275 }
276
277 void SSLServerSocketNSS::SetSubresourceSpeculation() {
278   transport_socket_->SetSubresourceSpeculation();
279 }
280
281 void SSLServerSocketNSS::SetOmniboxSpeculation() {
282   transport_socket_->SetOmniboxSpeculation();
283 }
284
285 bool SSLServerSocketNSS::WasEverUsed() const {
286   return transport_socket_->WasEverUsed();
287 }
288
289 bool SSLServerSocketNSS::UsingTCPFastOpen() const {
290   return transport_socket_->UsingTCPFastOpen();
291 }
292
293 bool SSLServerSocketNSS::WasNpnNegotiated() const {
294   return false;
295 }
296
297 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
298   // NPN is not supported by this class.
299   return kProtoUnknown;
300 }
301
302 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
303   NOTIMPLEMENTED();
304   return false;
305 }
306
307 int SSLServerSocketNSS::InitializeSSLOptions() {
308   // Transport connected, now hook it up to nss
309   nss_fd_ = memio_CreateIOLayer(kRecvBufferSize, kSendBufferSize);
310   if (nss_fd_ == NULL) {
311     return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR error code.
312   }
313
314   // Grab pointer to buffers
315   nss_bufs_ = memio_GetSecret(nss_fd_);
316
317   /* Create SSL state machine */
318   /* Push SSL onto our fake I/O socket */
319   nss_fd_ = SSL_ImportFD(NULL, nss_fd_);
320   if (nss_fd_ == NULL) {
321     LogFailedNSSFunction(net_log_, "SSL_ImportFD", "");
322     return ERR_OUT_OF_MEMORY;  // TODO(port): map NSPR/NSS error code.
323   }
324   // TODO(port): set more ssl options!  Check errors!
325
326   int rv;
327
328   rv = SSL_OptionSet(nss_fd_, SSL_SECURITY, PR_TRUE);
329   if (rv != SECSuccess) {
330     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_SECURITY");
331     return ERR_UNEXPECTED;
332   }
333
334   rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SSL2, PR_FALSE);
335   if (rv != SECSuccess) {
336     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_ENABLE_SSL2");
337     return ERR_UNEXPECTED;
338   }
339
340   SSLVersionRange version_range;
341   version_range.min = ssl_config_.version_min;
342   version_range.max = ssl_config_.version_max;
343   rv = SSL_VersionRangeSet(nss_fd_, &version_range);
344   if (rv != SECSuccess) {
345     LogFailedNSSFunction(net_log_, "SSL_VersionRangeSet", "");
346     return ERR_NO_SSL_VERSIONS_ENABLED;
347   }
348
349   if (ssl_config_.require_forward_secrecy) {
350     const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
351     const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
352
353     // Require forward security by iterating over the cipher suites and
354     // disabling all those that don't use either DHE or ECDHE.
355     for (unsigned i = 0; i < num_ciphers; i++) {
356       SSLCipherSuiteInfo info;
357       if (SSL_GetCipherSuiteInfo(ssl_ciphers[i], &info, sizeof(info)) ==
358           SECSuccess) {
359         if (strcmp(info.keaTypeName, "ECDHE") != 0 &&
360             strcmp(info.keaTypeName, "DHE") != 0) {
361           SSL_CipherPrefSet(nss_fd_, ssl_ciphers[i], PR_FALSE);
362         }
363       }
364     }
365   }
366
367   for (std::vector<uint16>::const_iterator it =
368            ssl_config_.disabled_cipher_suites.begin();
369        it != ssl_config_.disabled_cipher_suites.end(); ++it) {
370     // This will fail if the specified cipher is not implemented by NSS, but
371     // the failure is harmless.
372     SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
373   }
374
375   // Server socket doesn't need session tickets.
376   rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
377   if (rv != SECSuccess) {
378     LogFailedNSSFunction(
379         net_log_, "SSL_OptionSet", "SSL_ENABLE_SESSION_TICKETS");
380   }
381
382   // Doing this will force PR_Accept perform handshake as server.
383   rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_FALSE);
384   if (rv != SECSuccess) {
385     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT");
386     return ERR_UNEXPECTED;
387   }
388
389   rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_SERVER, PR_TRUE);
390   if (rv != SECSuccess) {
391     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_SERVER");
392     return ERR_UNEXPECTED;
393   }
394
395   rv = SSL_OptionSet(nss_fd_, SSL_REQUEST_CERTIFICATE, PR_FALSE);
396   if (rv != SECSuccess) {
397     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUEST_CERTIFICATE");
398     return ERR_UNEXPECTED;
399   }
400
401   rv = SSL_OptionSet(nss_fd_, SSL_REQUIRE_CERTIFICATE, PR_FALSE);
402   if (rv != SECSuccess) {
403     LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_REQUIRE_CERTIFICATE");
404     return ERR_UNEXPECTED;
405   }
406
407   rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
408   if (rv != SECSuccess) {
409     LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
410     return ERR_UNEXPECTED;
411   }
412
413   rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
414   if (rv != SECSuccess) {
415     LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
416     return ERR_UNEXPECTED;
417   }
418
419   // Get a certificate of CERTCertificate structure.
420   std::string der_string;
421   if (!X509Certificate::GetDEREncoded(cert_->os_cert_handle(), &der_string))
422     return ERR_UNEXPECTED;
423
424   SECItem der_cert;
425   der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(
426       der_string.data()));
427   der_cert.len  = der_string.length();
428   der_cert.type = siDERCertBuffer;
429
430   // Parse into a CERTCertificate structure.
431   CERTCertificate* cert = CERT_NewTempCertificate(
432       CERT_GetDefaultCertDB(), &der_cert, NULL, PR_FALSE, PR_TRUE);
433   if (!cert) {
434     LogFailedNSSFunction(net_log_, "CERT_NewTempCertificate", "");
435     return MapNSSError(PORT_GetError());
436   }
437
438   // Get a key of SECKEYPrivateKey* structure.
439   std::vector<uint8> key_vector;
440   if (!key_->ExportPrivateKey(&key_vector)) {
441     CERT_DestroyCertificate(cert);
442     return ERR_UNEXPECTED;
443   }
444
445   SECKEYPrivateKeyStr* private_key = NULL;
446   PK11SlotInfo* slot = crypto::GetPrivateNSSKeySlot();
447   if (!slot) {
448     CERT_DestroyCertificate(cert);
449     return ERR_UNEXPECTED;
450   }
451
452   SECItem der_private_key_info;
453   der_private_key_info.data =
454       const_cast<unsigned char*>(&key_vector.front());
455   der_private_key_info.len = key_vector.size();
456   // The server's RSA private key must be imported into NSS with the
457   // following key usage bits:
458   // - KU_KEY_ENCIPHERMENT, required for the RSA key exchange algorithm.
459   // - KU_DIGITAL_SIGNATURE, required for the DHE_RSA and ECDHE_RSA key
460   //   exchange algorithms.
461   const unsigned int key_usage = KU_KEY_ENCIPHERMENT | KU_DIGITAL_SIGNATURE;
462   rv =  PK11_ImportDERPrivateKeyInfoAndReturnKey(
463       slot, &der_private_key_info, NULL, NULL, PR_FALSE, PR_FALSE,
464       key_usage, &private_key, NULL);
465   PK11_FreeSlot(slot);
466   if (rv != SECSuccess) {
467     CERT_DestroyCertificate(cert);
468     return ERR_UNEXPECTED;
469   }
470
471   // Assign server certificate and private key.
472   SSLKEAType cert_kea = NSS_FindCertKEAType(cert);
473   rv = SSL_ConfigSecureServer(nss_fd_, cert, private_key, cert_kea);
474   CERT_DestroyCertificate(cert);
475   SECKEY_DestroyPrivateKey(private_key);
476
477   if (rv != SECSuccess) {
478     PRErrorCode prerr = PR_GetError();
479     LOG(ERROR) << "Failed to config SSL server: " << prerr;
480     LogFailedNSSFunction(net_log_, "SSL_ConfigureSecureServer", "");
481     return ERR_UNEXPECTED;
482   }
483
484   // Tell SSL we're a server; needed if not letting NSPR do socket I/O
485   rv = SSL_ResetHandshake(nss_fd_, PR_TRUE);
486   if (rv != SECSuccess) {
487     LogFailedNSSFunction(net_log_, "SSL_ResetHandshake", "");
488     return ERR_UNEXPECTED;
489   }
490
491   return OK;
492 }
493
494 void SSLServerSocketNSS::OnSendComplete(int result) {
495   if (next_handshake_state_ == STATE_HANDSHAKE) {
496     // In handshake phase.
497     OnHandshakeIOComplete(result);
498     return;
499   }
500
501   if (!completed_handshake_)
502     return;
503
504   if (user_write_buf_.get()) {
505     int rv = DoWriteLoop(result);
506     if (rv != ERR_IO_PENDING)
507       DoWriteCallback(rv);
508   } else {
509     // Ensure that any queued ciphertext is flushed.
510     DoTransportIO();
511   }
512 }
513
514 void SSLServerSocketNSS::OnRecvComplete(int result) {
515   if (next_handshake_state_ == STATE_HANDSHAKE) {
516     // In handshake phase.
517     OnHandshakeIOComplete(result);
518     return;
519   }
520
521   // Network layer received some data, check if client requested to read
522   // decrypted data.
523   if (!user_read_buf_.get() || !completed_handshake_)
524     return;
525
526   int rv = DoReadLoop(result);
527   if (rv != ERR_IO_PENDING)
528     DoReadCallback(rv);
529 }
530
531 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
532   int rv = DoHandshakeLoop(result);
533   if (rv != ERR_IO_PENDING) {
534     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
535     if (!user_handshake_callback_.is_null())
536       DoHandshakeCallback(rv);
537   }
538 }
539
540 // Return 0 for EOF,
541 // > 0 for bytes transferred immediately,
542 // < 0 for error (or the non-error ERR_IO_PENDING).
543 int SSLServerSocketNSS::BufferSend(void) {
544   if (transport_send_busy_)
545     return ERR_IO_PENDING;
546
547   const char* buf1;
548   const char* buf2;
549   unsigned int len1, len2;
550   memio_GetWriteParams(nss_bufs_, &buf1, &len1, &buf2, &len2);
551   const unsigned int len = len1 + len2;
552
553   int rv = 0;
554   if (len) {
555     scoped_refptr<IOBuffer> send_buffer(new IOBuffer(len));
556     memcpy(send_buffer->data(), buf1, len1);
557     memcpy(send_buffer->data() + len1, buf2, len2);
558     rv = transport_socket_->Write(
559         send_buffer.get(),
560         len,
561         base::Bind(&SSLServerSocketNSS::BufferSendComplete,
562                    base::Unretained(this)));
563     if (rv == ERR_IO_PENDING) {
564       transport_send_busy_ = true;
565     } else {
566       memio_PutWriteResult(nss_bufs_, MapErrorToNSS(rv));
567     }
568   }
569
570   return rv;
571 }
572
573 void SSLServerSocketNSS::BufferSendComplete(int result) {
574   memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
575   transport_send_busy_ = false;
576   OnSendComplete(result);
577 }
578
579 int SSLServerSocketNSS::BufferRecv(void) {
580   if (transport_recv_busy_) return ERR_IO_PENDING;
581
582   char* buf;
583   int nb = memio_GetReadParams(nss_bufs_, &buf);
584   int rv;
585   if (!nb) {
586     // buffer too full to read into, so no I/O possible at moment
587     rv = ERR_IO_PENDING;
588   } else {
589     recv_buffer_ = new IOBuffer(nb);
590     rv = transport_socket_->Read(
591         recv_buffer_.get(),
592         nb,
593         base::Bind(&SSLServerSocketNSS::BufferRecvComplete,
594                    base::Unretained(this)));
595     if (rv == ERR_IO_PENDING) {
596       transport_recv_busy_ = true;
597     } else {
598       if (rv > 0)
599         memcpy(buf, recv_buffer_->data(), rv);
600       memio_PutReadResult(nss_bufs_, MapErrorToNSS(rv));
601       recv_buffer_ = NULL;
602     }
603   }
604   return rv;
605 }
606
607 void SSLServerSocketNSS::BufferRecvComplete(int result) {
608   if (result > 0) {
609     char* buf;
610     memio_GetReadParams(nss_bufs_, &buf);
611     memcpy(buf, recv_buffer_->data(), result);
612   }
613   recv_buffer_ = NULL;
614   memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
615   transport_recv_busy_ = false;
616   OnRecvComplete(result);
617 }
618
619 // Do as much network I/O as possible between the buffer and the
620 // transport socket. Return true if some I/O performed, false
621 // otherwise (error or ERR_IO_PENDING).
622 bool SSLServerSocketNSS::DoTransportIO() {
623   bool network_moved = false;
624   if (nss_bufs_ != NULL) {
625     int rv;
626     // Read and write as much data as we can. The loop is neccessary
627     // because Write() may return synchronously.
628     do {
629       rv = BufferSend();
630       if (rv > 0)
631         network_moved = true;
632     } while (rv > 0);
633     if (BufferRecv() >= 0)
634       network_moved = true;
635   }
636   return network_moved;
637 }
638
639 int SSLServerSocketNSS::DoPayloadRead() {
640   DCHECK(user_read_buf_.get());
641   DCHECK_GT(user_read_buf_len_, 0);
642   int rv = PR_Read(nss_fd_, user_read_buf_->data(), user_read_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;
648   }
649   rv = MapNSSError(prerr);
650   net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
651                     CreateNetLogSSLErrorCallback(rv, prerr));
652   return rv;
653 }
654
655 int SSLServerSocketNSS::DoPayloadWrite() {
656   DCHECK(user_write_buf_.get());
657   int rv = PR_Write(nss_fd_, user_write_buf_->data(), user_write_buf_len_);
658   if (rv >= 0)
659     return rv;
660   PRErrorCode prerr = PR_GetError();
661   if (prerr == PR_WOULD_BLOCK_ERROR) {
662     return ERR_IO_PENDING;
663   }
664   rv = MapNSSError(prerr);
665   net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
666                     CreateNetLogSSLErrorCallback(rv, prerr));
667   return rv;
668 }
669
670 int SSLServerSocketNSS::DoHandshakeLoop(int last_io_result) {
671   int rv = last_io_result;
672   do {
673     // Default to STATE_NONE for next state.
674     // (This is a quirk carried over from the windows
675     // implementation.  It makes reading the logs a bit harder.)
676     // State handlers can and often do call GotoState just
677     // to stay in the current state.
678     State state = next_handshake_state_;
679     GotoState(STATE_NONE);
680     switch (state) {
681       case STATE_HANDSHAKE:
682         rv = DoHandshake();
683         break;
684       case STATE_NONE:
685       default:
686         rv = ERR_UNEXPECTED;
687         LOG(DFATAL) << "unexpected state " << state;
688         break;
689     }
690
691     // Do the actual network I/O
692     bool network_moved = DoTransportIO();
693     if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
694       // In general we exit the loop if rv is ERR_IO_PENDING.  In this
695       // special case we keep looping even if rv is ERR_IO_PENDING because
696       // the transport IO may allow DoHandshake to make progress.
697       rv = OK;  // This causes us to stay in the loop.
698     }
699   } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
700   return rv;
701 }
702
703 int SSLServerSocketNSS::DoReadLoop(int result) {
704   DCHECK(completed_handshake_);
705   DCHECK(next_handshake_state_ == STATE_NONE);
706
707   if (result < 0)
708     return result;
709
710   if (!nss_bufs_) {
711     LOG(DFATAL) << "!nss_bufs_";
712     int rv = ERR_UNEXPECTED;
713     net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
714                       CreateNetLogSSLErrorCallback(rv, 0));
715     return rv;
716   }
717
718   bool network_moved;
719   int rv;
720   do {
721     rv = DoPayloadRead();
722     network_moved = DoTransportIO();
723   } while (rv == ERR_IO_PENDING && network_moved);
724   return rv;
725 }
726
727 int SSLServerSocketNSS::DoWriteLoop(int result) {
728   DCHECK(completed_handshake_);
729   DCHECK(next_handshake_state_ == STATE_NONE);
730
731   if (result < 0)
732     return result;
733
734   if (!nss_bufs_) {
735     LOG(DFATAL) << "!nss_bufs_";
736     int rv = ERR_UNEXPECTED;
737     net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
738                       CreateNetLogSSLErrorCallback(rv, 0));
739     return rv;
740   }
741
742   bool network_moved;
743   int rv;
744   do {
745     rv = DoPayloadWrite();
746     network_moved = DoTransportIO();
747   } while (rv == ERR_IO_PENDING && network_moved);
748   return rv;
749 }
750
751 int SSLServerSocketNSS::DoHandshake() {
752   int net_error = OK;
753   SECStatus rv = SSL_ForceHandshake(nss_fd_);
754
755   if (rv == SECSuccess) {
756     completed_handshake_ = true;
757   } else {
758     PRErrorCode prerr = PR_GetError();
759     net_error = MapNSSError(prerr);
760
761     // If not done, stay in this state
762     if (net_error == ERR_IO_PENDING) {
763       GotoState(STATE_HANDSHAKE);
764     } else {
765       LOG(ERROR) << "handshake failed; NSS error code " << prerr
766                  << ", net_error " << net_error;
767       net_log_.AddEvent(NetLog::TYPE_SSL_HANDSHAKE_ERROR,
768                         CreateNetLogSSLErrorCallback(net_error, prerr));
769     }
770   }
771   return net_error;
772 }
773
774 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
775   DCHECK_NE(rv, ERR_IO_PENDING);
776
777   CompletionCallback c = user_handshake_callback_;
778   user_handshake_callback_.Reset();
779   c.Run(rv > OK ? OK : rv);
780 }
781
782 void SSLServerSocketNSS::DoReadCallback(int rv) {
783   DCHECK(rv != ERR_IO_PENDING);
784   DCHECK(!user_read_callback_.is_null());
785
786   // Since Run may result in Read being called, clear |user_read_callback_|
787   // up front.
788   CompletionCallback c = user_read_callback_;
789   user_read_callback_.Reset();
790   user_read_buf_ = NULL;
791   user_read_buf_len_ = 0;
792   c.Run(rv);
793 }
794
795 void SSLServerSocketNSS::DoWriteCallback(int rv) {
796   DCHECK(rv != ERR_IO_PENDING);
797   DCHECK(!user_write_callback_.is_null());
798
799   // Since Run may result in Write being called, clear |user_write_callback_|
800   // up front.
801   CompletionCallback c = user_write_callback_;
802   user_write_callback_.Reset();
803   user_write_buf_ = NULL;
804   user_write_buf_len_ = 0;
805   c.Run(rv);
806 }
807
808 // static
809 // NSS calls this if an incoming certificate needs to be verified.
810 // Do nothing but return SECSuccess.
811 // This is called only in full handshake mode.
812 // Peer certificate is retrieved in HandshakeCallback() later, which is called
813 // in full handshake mode or in resumption handshake mode.
814 SECStatus SSLServerSocketNSS::OwnAuthCertHandler(void* arg,
815                                                  PRFileDesc* socket,
816                                                  PRBool checksig,
817                                                  PRBool is_server) {
818   // TODO(hclam): Implement.
819   // Tell NSS to not verify the certificate.
820   return SECSuccess;
821 }
822
823 // static
824 // NSS calls this when handshake is completed.
825 // After the SSL handshake is finished we need to verify the certificate.
826 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
827                                            void* arg) {
828   // TODO(hclam): Implement.
829 }
830
831 int SSLServerSocketNSS::Init() {
832   // Initialize the NSS SSL library in a threadsafe way.  This also
833   // initializes the NSS base library.
834   EnsureNSSSSLInit();
835   if (!NSS_IsInitialized())
836     return ERR_UNEXPECTED;
837
838   EnableSSLServerSockets();
839   return OK;
840 }
841
842 }  // namespace net