• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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"
42 
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;
49 
50 #define GotoState(s) next_handshake_state_ = s
51 
52 namespace net {
53 
54 namespace {
55 
56 bool g_nss_server_sockets_init = false;
57 
58 class NSSSSLServerInitSingleton {
59  public:
NSSSSLServerInitSingleton()60   NSSSSLServerInitSingleton() {
61     EnsureNSSSSLInit();
62 
63     SSL_ConfigServerSessionIDCache(1024, 5, 5, NULL);
64     g_nss_server_sockets_init = true;
65   }
66 
~NSSSSLServerInitSingleton()67   ~NSSSSLServerInitSingleton() {
68     SSL_ShutdownServerSessionIDCache();
69     g_nss_server_sockets_init = false;
70   }
71 };
72 
73 static base::LazyInstance<NSSSSLServerInitSingleton>
74     g_nss_ssl_server_init_singleton = LAZY_INSTANCE_INITIALIZER;
75 
76 }  // namespace
77 
EnableSSLServerSockets()78 void EnableSSLServerSockets() {
79   g_nss_ssl_server_init_singleton.Get();
80 }
81 
CreateSSLServerSocket(scoped_ptr<StreamSocket> socket,X509Certificate * cert,crypto::RSAPrivateKey * key,const SSLConfig & ssl_config)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!";
89 
90   return scoped_ptr<SSLServerSocket>(
91       new SSLServerSocketNSS(socket.Pass(), cert, key, ssl_config));
92 }
93 
SSLServerSocketNSS(scoped_ptr<StreamSocket> transport_socket,scoped_refptr<X509Certificate> cert,crypto::RSAPrivateKey * key,const SSLConfig & 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());
115 }
116 
~SSLServerSocketNSS()117 SSLServerSocketNSS::~SSLServerSocketNSS() {
118   if (nss_fd_ != NULL) {
119     PR_Close(nss_fd_);
120     nss_fd_ = NULL;
121   }
122 }
123 
Handshake(const CompletionCallback & callback)124 int SSLServerSocketNSS::Handshake(const CompletionCallback& callback) {
125   net_log_.BeginEvent(NetLog::TYPE_SSL_SERVER_HANDSHAKE);
126 
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;
132   }
133 
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;
139   }
140 
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);
146 
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);
153   }
154 
155   return rv > OK ? OK : rv;
156 }
157 
ExportKeyingMaterial(const base::StringPiece & label,bool has_context,const base::StringPiece & context,unsigned char * out,unsigned int outlen)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());
172   }
173   return OK;
174 }
175 
GetTLSUniqueChannelBinding(std::string * out)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());
187   }
188   out->assign(reinterpret_cast<char*>(buf), len);
189   return OK;
190 }
191 
Connect(const CompletionCallback & callback)192 int SSLServerSocketNSS::Connect(const CompletionCallback& callback) {
193   NOTIMPLEMENTED();
194   return ERR_NOT_IMPLEMENTED;
195 }
196 
Read(IOBuffer * buf,int buf_len,const CompletionCallback & callback)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());
204 
205   user_read_buf_ = buf;
206   user_read_buf_len_ = buf_len;
207 
208   DCHECK(completed_handshake_);
209 
210   int rv = DoReadLoop(OK);
211 
212   if (rv == ERR_IO_PENDING) {
213     user_read_callback_ = callback;
214   } else {
215     user_read_buf_ = NULL;
216     user_read_buf_len_ = 0;
217   }
218   return rv;
219 }
220 
Write(IOBuffer * buf,int buf_len,const CompletionCallback & callback)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());
227 
228   user_write_buf_ = buf;
229   user_write_buf_len_ = buf_len;
230 
231   int rv = DoWriteLoop(OK);
232 
233   if (rv == ERR_IO_PENDING) {
234     user_write_callback_ = callback;
235   } else {
236     user_write_buf_ = NULL;
237     user_write_buf_len_ = 0;
238   }
239   return rv;
240 }
241 
SetReceiveBufferSize(int32 size)242 int SSLServerSocketNSS::SetReceiveBufferSize(int32 size) {
243   return transport_socket_->SetReceiveBufferSize(size);
244 }
245 
SetSendBufferSize(int32 size)246 int SSLServerSocketNSS::SetSendBufferSize(int32 size) {
247   return transport_socket_->SetSendBufferSize(size);
248 }
249 
IsConnected() const250 bool SSLServerSocketNSS::IsConnected() const {
251   // TODO(wtc): Find out if we should check transport_socket_->IsConnected()
252   // as well.
253   return completed_handshake_;
254 }
255 
Disconnect()256 void SSLServerSocketNSS::Disconnect() {
257   transport_socket_->Disconnect();
258 }
259 
IsConnectedAndIdle() const260 bool SSLServerSocketNSS::IsConnectedAndIdle() const {
261   return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
262 }
263 
GetPeerAddress(IPEndPoint * address) const264 int SSLServerSocketNSS::GetPeerAddress(IPEndPoint* address) const {
265   if (!IsConnected())
266     return ERR_SOCKET_NOT_CONNECTED;
267   return transport_socket_->GetPeerAddress(address);
268 }
269 
GetLocalAddress(IPEndPoint * address) const270 int SSLServerSocketNSS::GetLocalAddress(IPEndPoint* address) const {
271   if (!IsConnected())
272     return ERR_SOCKET_NOT_CONNECTED;
273   return transport_socket_->GetLocalAddress(address);
274 }
275 
NetLog() const276 const BoundNetLog& SSLServerSocketNSS::NetLog() const {
277   return net_log_;
278 }
279 
SetSubresourceSpeculation()280 void SSLServerSocketNSS::SetSubresourceSpeculation() {
281   transport_socket_->SetSubresourceSpeculation();
282 }
283 
SetOmniboxSpeculation()284 void SSLServerSocketNSS::SetOmniboxSpeculation() {
285   transport_socket_->SetOmniboxSpeculation();
286 }
287 
WasEverUsed() const288 bool SSLServerSocketNSS::WasEverUsed() const {
289   return transport_socket_->WasEverUsed();
290 }
291 
UsingTCPFastOpen() const292 bool SSLServerSocketNSS::UsingTCPFastOpen() const {
293   return transport_socket_->UsingTCPFastOpen();
294 }
295 
WasNpnNegotiated() const296 bool SSLServerSocketNSS::WasNpnNegotiated() const {
297   NOTIMPLEMENTED();
298   return false;
299 }
300 
GetNegotiatedProtocol() const301 NextProto SSLServerSocketNSS::GetNegotiatedProtocol() const {
302   // NPN is not supported by this class.
303   return kProtoUnknown;
304 }
305 
GetSSLInfo(SSLInfo * ssl_info)306 bool SSLServerSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
307   NOTIMPLEMENTED();
308   return false;
309 }
310 
InitializeSSLOptions()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.
316   }
317 
318   // Grab pointer to buffers
319   nss_bufs_ = memio_GetSecret(nss_fd_);
320 
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.
327   }
328   // TODO(port): set more ssl options!  Check errors!
329 
330   int rv;
331 
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;
336   }
337 
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;
342   }
343 
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;
351   }
352 
353   if (ssl_config_.require_forward_secrecy) {
354     const PRUint16* const ssl_ciphers = SSL_GetImplementedCiphers();
355     const PRUint16 num_ciphers = SSL_GetNumImplementedCiphers();
356 
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);
365         }
366       }
367     }
368   }
369 
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);
376   }
377 
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");
383   }
384 
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;
390   }
391 
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;
396   }
397 
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;
402   }
403 
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;
408   }
409 
410   rv = SSL_AuthCertificateHook(nss_fd_, OwnAuthCertHandler, this);
411   if (rv != SECSuccess) {
412     LogFailedNSSFunction(net_log_, "SSL_AuthCertificateHook", "");
413     return ERR_UNEXPECTED;
414   }
415 
416   rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
417   if (rv != SECSuccess) {
418     LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
419     return ERR_UNEXPECTED;
420   }
421 
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;
426 
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;
432 
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());
439   }
440 
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;
446   }
447 
448   SECKEYPrivateKeyStr* private_key = NULL;
449   PK11SlotInfo* slot = crypto::GetPrivateNSSKeySlot();
450   if (!slot) {
451     CERT_DestroyCertificate(cert);
452     return ERR_UNEXPECTED;
453   }
454 
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;
472   }
473 
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);
479 
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;
485   }
486 
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;
492   }
493 
494   return OK;
495 }
496 
OnSendComplete(int result)497 void SSLServerSocketNSS::OnSendComplete(int result) {
498   if (next_handshake_state_ == STATE_HANDSHAKE) {
499     // In handshake phase.
500     OnHandshakeIOComplete(result);
501     return;
502   }
503 
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;
508 
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();
516   }
517 }
518 
OnRecvComplete(int result)519 void SSLServerSocketNSS::OnRecvComplete(int result) {
520   if (next_handshake_state_ == STATE_HANDSHAKE) {
521     // In handshake phase.
522     OnHandshakeIOComplete(result);
523     return;
524   }
525 
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;
530 
531   int rv = DoReadLoop(result);
532   if (rv != ERR_IO_PENDING)
533     DoReadCallback(rv);
534 }
535 
OnHandshakeIOComplete(int result)536 void SSLServerSocketNSS::OnHandshakeIOComplete(int result) {
537   int rv = DoHandshakeLoop(result);
538   if (rv == ERR_IO_PENDING)
539     return;
540 
541   net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_SERVER_HANDSHAKE, rv);
542   if (!user_handshake_callback_.is_null())
543     DoHandshakeCallback(rv);
544 }
545 
546 // Return 0 for EOF,
547 // > 0 for bytes transferred immediately,
548 // < 0 for error (or the non-error ERR_IO_PENDING).
BufferSend(void)549 int SSLServerSocketNSS::BufferSend(void) {
550   if (transport_send_busy_)
551     return ERR_IO_PENDING;
552 
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;
559   }
560   const unsigned int len = len1 + len2;
561 
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));
576     }
577   }
578 
579   return rv;
580 }
581 
BufferSendComplete(int result)582 void SSLServerSocketNSS::BufferSendComplete(int result) {
583   memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
584   transport_send_busy_ = false;
585   OnSendComplete(result);
586 }
587 
BufferRecv(void)588 int SSLServerSocketNSS::BufferRecv(void) {
589   if (transport_recv_busy_) return ERR_IO_PENDING;
590 
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(),
601         nb,
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;
611     }
612   }
613   return rv;
614 }
615 
BufferRecvComplete(int result)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);
621   }
622   recv_buffer_ = NULL;
623   memio_PutReadResult(nss_bufs_, MapErrorToNSS(result));
624   transport_recv_busy_ = false;
625   OnRecvComplete(result);
626 }
627 
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).
DoTransportIO()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;
644   }
645   return network_moved;
646 }
647 
DoPayloadRead()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;
657   }
658   rv = MapNSSError(prerr);
659   net_log_.AddEvent(NetLog::TYPE_SSL_READ_ERROR,
660                     CreateNetLogSSLErrorCallback(rv, prerr));
661   return rv;
662 }
663 
DoPayloadWrite()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;
672   }
673   rv = MapNSSError(prerr);
674   net_log_.AddEvent(NetLog::TYPE_SSL_WRITE_ERROR,
675                     CreateNetLogSSLErrorCallback(rv, prerr));
676   return rv;
677 }
678 
DoHandshakeLoop(int last_io_result)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;
698     }
699 
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.
707     }
708   } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
709   return rv;
710 }
711 
DoReadLoop(int result)712 int SSLServerSocketNSS::DoReadLoop(int result) {
713   DCHECK(completed_handshake_);
714   DCHECK(next_handshake_state_ == STATE_NONE);
715 
716   if (result < 0)
717     return result;
718 
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;
725   }
726 
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;
734 }
735 
DoWriteLoop(int result)736 int SSLServerSocketNSS::DoWriteLoop(int result) {
737   DCHECK(completed_handshake_);
738   DCHECK_EQ(next_handshake_state_, STATE_NONE);
739 
740   if (result < 0)
741     return result;
742 
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;
749   }
750 
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;
758 }
759 
DoHandshake()760 int SSLServerSocketNSS::DoHandshake() {
761   int net_error = OK;
762   SECStatus rv = SSL_ForceHandshake(nss_fd_);
763 
764   if (rv == SECSuccess) {
765     completed_handshake_ = true;
766   } else {
767     PRErrorCode prerr = PR_GetError();
768     net_error = MapNSSError(prerr);
769 
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));
778     }
779   }
780   return net_error;
781 }
782 
DoHandshakeCallback(int rv)783 void SSLServerSocketNSS::DoHandshakeCallback(int rv) {
784   DCHECK_NE(rv, ERR_IO_PENDING);
785   ResetAndReturn(&user_handshake_callback_).Run(rv > OK ? OK : rv);
786 }
787 
DoReadCallback(int rv)788 void SSLServerSocketNSS::DoReadCallback(int rv) {
789   DCHECK(rv != ERR_IO_PENDING);
790   DCHECK(!user_read_callback_.is_null());
791 
792   user_read_buf_ = NULL;
793   user_read_buf_len_ = 0;
794   ResetAndReturn(&user_read_callback_).Run(rv);
795 }
796 
DoWriteCallback(int rv)797 void SSLServerSocketNSS::DoWriteCallback(int rv) {
798   DCHECK(rv != ERR_IO_PENDING);
799   DCHECK(!user_write_callback_.is_null());
800 
801   user_write_buf_ = NULL;
802   user_write_buf_len_ = 0;
803   ResetAndReturn(&user_write_callback_).Run(rv);
804 }
805 
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.
OwnAuthCertHandler(void * arg,PRFileDesc * socket,PRBool checksig,PRBool is_server)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;
819 }
820 
821 // static
822 // NSS calls this when handshake is completed.
823 // After the SSL handshake is finished we need to verify the certificate.
HandshakeCallback(PRFileDesc * socket,void * arg)824 void SSLServerSocketNSS::HandshakeCallback(PRFileDesc* socket,
825                                            void* arg) {
826   // TODO(hclam): Implement.
827 }
828 
Init()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;
835 
836   EnableSSLServerSockets();
837   return OK;
838 }
839 
840 }  // namespace net
841