Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / libjingle / source / talk / base / nssstreamadapter.cc
1 /*
2  * libjingle
3  * Copyright 2004--2008, Google Inc.
4  * Copyright 2004--2011, RTFM, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  *  1. Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright notice,
12  *     this list of conditions and the following disclaimer in the documentation
13  *     and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *     derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <vector>
30
31 #if HAVE_CONFIG_H
32 #include "config.h"
33 #endif  // HAVE_CONFIG_H
34
35 #if HAVE_NSS_SSL_H
36
37 #include "talk/base/nssstreamadapter.h"
38
39 #include "keyhi.h"
40 #include "nspr.h"
41 #include "nss.h"
42 #include "pk11pub.h"
43 #include "secerr.h"
44
45 #ifdef NSS_SSL_RELATIVE_PATH
46 #include "ssl.h"
47 #include "sslerr.h"
48 #include "sslproto.h"
49 #else
50 #include "net/third_party/nss/ssl/ssl.h"
51 #include "net/third_party/nss/ssl/sslerr.h"
52 #include "net/third_party/nss/ssl/sslproto.h"
53 #endif
54
55 #include "talk/base/nssidentity.h"
56 #include "talk/base/thread.h"
57
58 namespace talk_base {
59
60 PRDescIdentity NSSStreamAdapter::nspr_layer_identity = PR_INVALID_IO_LAYER;
61
62 #define UNIMPLEMENTED \
63   PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); \
64   LOG(LS_ERROR) \
65   << "Call to unimplemented function "<< __FUNCTION__; ASSERT(false)
66
67 #ifdef SRTP_AES128_CM_HMAC_SHA1_80
68 #define HAVE_DTLS_SRTP
69 #endif
70
71 #ifdef HAVE_DTLS_SRTP
72 // SRTP cipher suite table
73 struct SrtpCipherMapEntry {
74   const char* external_name;
75   PRUint16 cipher_id;
76 };
77
78 // This isn't elegant, but it's better than an external reference
79 static const SrtpCipherMapEntry kSrtpCipherMap[] = {
80   {"AES_CM_128_HMAC_SHA1_80", SRTP_AES128_CM_HMAC_SHA1_80 },
81   {"AES_CM_128_HMAC_SHA1_32", SRTP_AES128_CM_HMAC_SHA1_32 },
82   {NULL, 0}
83 };
84 #endif
85
86
87 // Implementation of NSPR methods
88 static PRStatus StreamClose(PRFileDesc *socket) {
89   // Noop
90   return PR_SUCCESS;
91 }
92
93 static PRInt32 StreamRead(PRFileDesc *socket, void *buf, PRInt32 length) {
94   StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret);
95   size_t read;
96   int error;
97   StreamResult result = stream->Read(buf, length, &read, &error);
98   if (result == SR_SUCCESS) {
99     return read;
100   }
101
102   if (result == SR_EOS) {
103     return 0;
104   }
105
106   if (result == SR_BLOCK) {
107     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
108     return -1;
109   }
110
111   PR_SetError(PR_UNKNOWN_ERROR, error);
112   return -1;
113 }
114
115 static PRInt32 StreamWrite(PRFileDesc *socket, const void *buf,
116                            PRInt32 length) {
117   StreamInterface *stream = reinterpret_cast<StreamInterface *>(socket->secret);
118   size_t written;
119   int error;
120   StreamResult result = stream->Write(buf, length, &written, &error);
121   if (result == SR_SUCCESS) {
122     return written;
123   }
124
125   if (result == SR_BLOCK) {
126     LOG(LS_INFO) <<
127         "NSSStreamAdapter: write to underlying transport would block";
128     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
129     return -1;
130   }
131
132   LOG(LS_ERROR) << "Write error";
133   PR_SetError(PR_UNKNOWN_ERROR, error);
134   return -1;
135 }
136
137 static PRInt32 StreamAvailable(PRFileDesc *socket) {
138   UNIMPLEMENTED;
139   return -1;
140 }
141
142 PRInt64 StreamAvailable64(PRFileDesc *socket) {
143   UNIMPLEMENTED;
144   return -1;
145 }
146
147 static PRStatus StreamSync(PRFileDesc *socket) {
148   UNIMPLEMENTED;
149   return PR_FAILURE;
150 }
151
152 static PROffset32 StreamSeek(PRFileDesc *socket, PROffset32 offset,
153                              PRSeekWhence how) {
154   UNIMPLEMENTED;
155   return -1;
156 }
157
158 static PROffset64 StreamSeek64(PRFileDesc *socket, PROffset64 offset,
159                                PRSeekWhence how) {
160   UNIMPLEMENTED;
161   return -1;
162 }
163
164 static PRStatus StreamFileInfo(PRFileDesc *socket, PRFileInfo *info) {
165   UNIMPLEMENTED;
166   return PR_FAILURE;
167 }
168
169 static PRStatus StreamFileInfo64(PRFileDesc *socket, PRFileInfo64 *info) {
170   UNIMPLEMENTED;
171   return PR_FAILURE;
172 }
173
174 static PRInt32 StreamWritev(PRFileDesc *socket, const PRIOVec *iov,
175                      PRInt32 iov_size, PRIntervalTime timeout) {
176   UNIMPLEMENTED;
177   return -1;
178 }
179
180 static PRStatus StreamConnect(PRFileDesc *socket, const PRNetAddr *addr,
181                               PRIntervalTime timeout) {
182   UNIMPLEMENTED;
183   return PR_FAILURE;
184 }
185
186 static PRFileDesc *StreamAccept(PRFileDesc *sd, PRNetAddr *addr,
187                                 PRIntervalTime timeout) {
188   UNIMPLEMENTED;
189   return NULL;
190 }
191
192 static PRStatus StreamBind(PRFileDesc *socket, const PRNetAddr *addr) {
193   UNIMPLEMENTED;
194   return PR_FAILURE;
195 }
196
197 static PRStatus StreamListen(PRFileDesc *socket, PRIntn depth) {
198   UNIMPLEMENTED;
199   return PR_FAILURE;
200 }
201
202 static PRStatus StreamShutdown(PRFileDesc *socket, PRIntn how) {
203   UNIMPLEMENTED;
204   return PR_FAILURE;
205 }
206
207 // Note: this is always nonblocking and ignores the timeout.
208 // TODO(ekr@rtfm.com): In future verify that the socket is
209 // actually in non-blocking mode.
210 // This function does not support peek.
211 static PRInt32 StreamRecv(PRFileDesc *socket, void *buf, PRInt32 amount,
212                    PRIntn flags, PRIntervalTime to) {
213   ASSERT(flags == 0);
214
215   if (flags != 0) {
216     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
217     return -1;
218   }
219
220   return StreamRead(socket, buf, amount);
221 }
222
223 // Note: this is always nonblocking and assumes a zero timeout.
224 // This function does not support peek.
225 static PRInt32 StreamSend(PRFileDesc *socket, const void *buf,
226                           PRInt32 amount, PRIntn flags,
227                           PRIntervalTime to) {
228   ASSERT(flags == 0);
229
230   return StreamWrite(socket, buf, amount);
231 }
232
233 static PRInt32 StreamRecvfrom(PRFileDesc *socket, void *buf,
234                               PRInt32 amount, PRIntn flags,
235                               PRNetAddr *addr, PRIntervalTime to) {
236   UNIMPLEMENTED;
237   return -1;
238 }
239
240 static PRInt32 StreamSendto(PRFileDesc *socket, const void *buf,
241                             PRInt32 amount, PRIntn flags,
242                             const PRNetAddr *addr, PRIntervalTime to) {
243   UNIMPLEMENTED;
244   return -1;
245 }
246
247 static PRInt16 StreamPoll(PRFileDesc *socket, PRInt16 in_flags,
248                           PRInt16 *out_flags) {
249   UNIMPLEMENTED;
250   return -1;
251 }
252
253 static PRInt32 StreamAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
254                                 PRNetAddr **raddr,
255                                 void *buf, PRInt32 amount, PRIntervalTime t) {
256   UNIMPLEMENTED;
257   return -1;
258 }
259
260 static PRInt32 StreamTransmitFile(PRFileDesc *sd, PRFileDesc *socket,
261                                   const void *headers, PRInt32 hlen,
262                                   PRTransmitFileFlags flags, PRIntervalTime t) {
263   UNIMPLEMENTED;
264   return -1;
265 }
266
267 static PRStatus StreamGetPeerName(PRFileDesc *socket, PRNetAddr *addr) {
268   // TODO(ekr@rtfm.com): Modify to return unique names for each channel
269   // somehow, as opposed to always the same static address. The current
270   // implementation messes up the session cache, which is why it's off
271   // elsewhere
272   addr->inet.family = PR_AF_INET;
273   addr->inet.port = 0;
274   addr->inet.ip = 0;
275
276   return PR_SUCCESS;
277 }
278
279 static PRStatus StreamGetSockName(PRFileDesc *socket, PRNetAddr *addr) {
280   UNIMPLEMENTED;
281   return PR_FAILURE;
282 }
283
284 static PRStatus StreamGetSockOption(PRFileDesc *socket, PRSocketOptionData *opt) {
285   switch (opt->option) {
286     case PR_SockOpt_Nonblocking:
287       opt->value.non_blocking = PR_TRUE;
288       return PR_SUCCESS;
289     default:
290       UNIMPLEMENTED;
291       break;
292   }
293
294   return PR_FAILURE;
295 }
296
297 // Imitate setting socket options. These are mostly noops.
298 static PRStatus StreamSetSockOption(PRFileDesc *socket,
299                                     const PRSocketOptionData *opt) {
300   switch (opt->option) {
301     case PR_SockOpt_Nonblocking:
302       return PR_SUCCESS;
303     case PR_SockOpt_NoDelay:
304       return PR_SUCCESS;
305     default:
306       UNIMPLEMENTED;
307       break;
308   }
309
310   return PR_FAILURE;
311 }
312
313 static PRInt32 StreamSendfile(PRFileDesc *out, PRSendFileData *in,
314                               PRTransmitFileFlags flags, PRIntervalTime to) {
315   UNIMPLEMENTED;
316   return -1;
317 }
318
319 static PRStatus StreamConnectContinue(PRFileDesc *socket, PRInt16 flags) {
320   UNIMPLEMENTED;
321   return PR_FAILURE;
322 }
323
324 static PRIntn StreamReserved(PRFileDesc *socket) {
325   UNIMPLEMENTED;
326   return -1;
327 }
328
329 static const struct PRIOMethods nss_methods = {
330   PR_DESC_LAYERED,
331   StreamClose,
332   StreamRead,
333   StreamWrite,
334   StreamAvailable,
335   StreamAvailable64,
336   StreamSync,
337   StreamSeek,
338   StreamSeek64,
339   StreamFileInfo,
340   StreamFileInfo64,
341   StreamWritev,
342   StreamConnect,
343   StreamAccept,
344   StreamBind,
345   StreamListen,
346   StreamShutdown,
347   StreamRecv,
348   StreamSend,
349   StreamRecvfrom,
350   StreamSendto,
351   StreamPoll,
352   StreamAcceptRead,
353   StreamTransmitFile,
354   StreamGetSockName,
355   StreamGetPeerName,
356   StreamReserved,
357   StreamReserved,
358   StreamGetSockOption,
359   StreamSetSockOption,
360   StreamSendfile,
361   StreamConnectContinue,
362   StreamReserved,
363   StreamReserved,
364   StreamReserved,
365   StreamReserved
366 };
367
368 NSSStreamAdapter::NSSStreamAdapter(StreamInterface *stream)
369     : SSLStreamAdapterHelper(stream),
370       ssl_fd_(NULL),
371       cert_ok_(false) {
372 }
373
374 bool NSSStreamAdapter::Init() {
375   if (nspr_layer_identity == PR_INVALID_IO_LAYER) {
376     nspr_layer_identity = PR_GetUniqueIdentity("nssstreamadapter");
377   }
378   PRFileDesc *pr_fd = PR_CreateIOLayerStub(nspr_layer_identity, &nss_methods);
379   if (!pr_fd)
380     return false;
381   pr_fd->secret = reinterpret_cast<PRFilePrivate *>(stream());
382
383   PRFileDesc *ssl_fd;
384   if (ssl_mode_ == SSL_MODE_DTLS) {
385     ssl_fd = DTLS_ImportFD(NULL, pr_fd);
386   } else {
387     ssl_fd = SSL_ImportFD(NULL, pr_fd);
388   }
389   ASSERT(ssl_fd != NULL);  // This should never happen
390   if (!ssl_fd) {
391     PR_Close(pr_fd);
392     return false;
393   }
394
395   SECStatus rv;
396   // Turn on security.
397   rv = SSL_OptionSet(ssl_fd, SSL_SECURITY, PR_TRUE);
398   if (rv != SECSuccess) {
399     LOG(LS_ERROR) << "Error enabling security on SSL Socket";
400     return false;
401   }
402
403   // Disable SSLv2.
404   rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SSL2, PR_FALSE);
405   if (rv != SECSuccess) {
406     LOG(LS_ERROR) << "Error disabling SSL2";
407     return false;
408   }
409
410   // Disable caching.
411   // TODO(ekr@rtfm.com): restore this when I have the caching
412   // identity set.
413   rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE);
414   if (rv != SECSuccess) {
415     LOG(LS_ERROR) << "Error disabling cache";
416     return false;
417   }
418
419   // Disable session tickets.
420   rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
421   if (rv != SECSuccess) {
422     LOG(LS_ERROR) << "Error enabling tickets";
423     return false;
424   }
425
426   // Disable renegotiation.
427   rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION,
428                      SSL_RENEGOTIATE_NEVER);
429   if (rv != SECSuccess) {
430     LOG(LS_ERROR) << "Error disabling renegotiation";
431     return false;
432   }
433
434   // Disable false start.
435   rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE);
436   if (rv != SECSuccess) {
437     LOG(LS_ERROR) << "Error disabling false start";
438     return false;
439   }
440           
441   ssl_fd_ = ssl_fd;
442
443   return true;
444 }
445
446 NSSStreamAdapter::~NSSStreamAdapter() {
447   if (ssl_fd_)
448     PR_Close(ssl_fd_);
449 };
450
451
452 int NSSStreamAdapter::BeginSSL() {
453   SECStatus rv;
454
455   if (!Init()) {
456     Error("Init", -1, false);
457     return -1;
458   }
459
460   ASSERT(state_ == SSL_CONNECTING);
461   // The underlying stream has been opened. If we are in peer-to-peer mode
462   // then a peer certificate must have been specified by now.
463   ASSERT(!ssl_server_name_.empty() ||
464          peer_certificate_.get() != NULL ||
465          !peer_certificate_digest_algorithm_.empty());
466   LOG(LS_INFO) << "BeginSSL: "
467                << (!ssl_server_name_.empty() ? ssl_server_name_ :
468                                                "with peer");
469
470   if (role_ == SSL_CLIENT) {
471     LOG(LS_INFO) << "BeginSSL: as client";
472
473     rv = SSL_GetClientAuthDataHook(ssl_fd_, GetClientAuthDataHook,
474                                    this);
475     if (rv != SECSuccess) {
476       Error("BeginSSL", -1, false);
477       return -1;
478     }
479   } else {
480     LOG(LS_INFO) << "BeginSSL: as server";
481     NSSIdentity *identity;
482
483     if (identity_.get()) {
484       identity = static_cast<NSSIdentity *>(identity_.get());
485     } else {
486       LOG(LS_ERROR) << "Can't be an SSL server without an identity";
487       Error("BeginSSL", -1, false);
488       return -1;
489     }
490     rv = SSL_ConfigSecureServer(ssl_fd_, identity->certificate().certificate(),
491                                 identity->keypair()->privkey(),
492                                 kt_rsa);
493     if (rv != SECSuccess) {
494       Error("BeginSSL", -1, false);
495       return -1;
496     }
497
498     // Insist on a certificate from the client
499     rv = SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE);
500     if (rv != SECSuccess) {
501       Error("BeginSSL", -1, false);
502       return -1;
503     }
504
505     rv = SSL_OptionSet(ssl_fd_, SSL_REQUIRE_CERTIFICATE, PR_TRUE);
506     if (rv != SECSuccess) {
507       Error("BeginSSL", -1, false);
508       return -1;
509     }
510   }
511
512   // Set the version range.
513   SSLVersionRange vrange;
514   vrange.min =  (ssl_mode_ == SSL_MODE_DTLS) ?
515       SSL_LIBRARY_VERSION_TLS_1_1 :
516       SSL_LIBRARY_VERSION_TLS_1_0;
517   vrange.max = SSL_LIBRARY_VERSION_TLS_1_1;
518   
519   rv = SSL_VersionRangeSet(ssl_fd_, &vrange);
520   if (rv != SECSuccess) {
521     Error("BeginSSL", -1, false);
522     return -1;
523   }
524
525   // SRTP
526 #ifdef HAVE_DTLS_SRTP
527   if (!srtp_ciphers_.empty()) {
528     rv = SSL_SetSRTPCiphers(ssl_fd_, &srtp_ciphers_[0], srtp_ciphers_.size());
529     if (rv != SECSuccess) {
530       Error("BeginSSL", -1, false);
531       return -1;
532     }
533   }
534 #endif
535
536   // Certificate validation
537   rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this);
538   if (rv != SECSuccess) {
539     Error("BeginSSL", -1, false);
540     return -1;
541   }
542
543   // Now start the handshake
544   rv = SSL_ResetHandshake(ssl_fd_, role_ == SSL_SERVER ? PR_TRUE : PR_FALSE);
545   if (rv != SECSuccess) {
546     Error("BeginSSL", -1, false);
547     return -1;
548   }
549
550   return ContinueSSL();
551 }
552
553 int NSSStreamAdapter::ContinueSSL() {
554   LOG(LS_INFO) << "ContinueSSL";
555   ASSERT(state_ == SSL_CONNECTING);
556
557   // Clear the DTLS timer
558   Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT);
559
560   SECStatus rv = SSL_ForceHandshake(ssl_fd_);
561
562   if (rv == SECSuccess) {
563     LOG(LS_INFO) << "Handshake complete";
564
565     ASSERT(cert_ok_);
566     if (!cert_ok_) {
567       Error("ContinueSSL", -1, true);
568       return -1;
569     }
570
571     state_ = SSL_CONNECTED;
572     StreamAdapterInterface::OnEvent(stream(), SE_OPEN|SE_READ|SE_WRITE, 0);
573     return 0;
574   }
575
576   PRInt32 err = PR_GetError();
577   switch (err) {
578     case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
579       if (ssl_mode_ != SSL_MODE_DTLS) {
580         Error("ContinueSSL", -1, true);
581         return -1;
582       } else {
583         LOG(LS_INFO) << "Malformed DTLS message. Ignoring.";
584         // Fall through
585       }
586     case PR_WOULD_BLOCK_ERROR:
587       LOG(LS_INFO) << "Would have blocked";
588       if (ssl_mode_ == SSL_MODE_DTLS) {
589         PRIntervalTime timeout;
590
591         SECStatus rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout);
592         if (rv == SECSuccess) {
593           LOG(LS_INFO) << "Timeout is " << timeout << " ms";
594           Thread::Current()->PostDelayed(PR_IntervalToMilliseconds(timeout),
595                                          this, MSG_DTLS_TIMEOUT, 0);
596         }
597       }
598
599       return 0;
600     default:
601       LOG(LS_INFO) << "Error " << err;
602       break;
603   }
604
605   Error("ContinueSSL", -1, true);
606   return -1;
607 }
608
609 void NSSStreamAdapter::Cleanup() {
610   if (state_ != SSL_ERROR) {
611     state_ = SSL_CLOSED;
612   }
613
614   if (ssl_fd_) {
615     PR_Close(ssl_fd_);
616     ssl_fd_ = NULL;
617   }
618
619   identity_.reset();
620   peer_certificate_.reset();
621
622   Thread::Current()->Clear(this, MSG_DTLS_TIMEOUT);
623 }
624
625 StreamResult NSSStreamAdapter::Read(void* data, size_t data_len,
626                                     size_t* read, int* error) {
627   // SSL_CONNECTED sanity check.
628   switch (state_) {
629     case SSL_NONE:
630     case SSL_WAIT:
631     case SSL_CONNECTING:
632       return SR_BLOCK;
633
634     case SSL_CONNECTED:
635       break;
636
637     case SSL_CLOSED:
638       return SR_EOS;
639
640     case SSL_ERROR:
641     default:
642       if (error)
643         *error = ssl_error_code_;
644       return SR_ERROR;
645   }
646
647   PRInt32 rv = PR_Read(ssl_fd_, data, data_len);
648
649   if (rv == 0) {
650     return SR_EOS;
651   }
652
653   // Error
654   if (rv < 0) {
655     PRInt32 err = PR_GetError();
656
657     switch (err) {
658       case PR_WOULD_BLOCK_ERROR:
659         return SR_BLOCK;
660       default:
661         Error("Read", -1, false);
662         *error = err;  // libjingle semantics are that this is impl-specific
663         return SR_ERROR;
664     }
665   }
666
667   // Success
668   *read = rv;
669
670   return SR_SUCCESS;
671 }
672
673 StreamResult NSSStreamAdapter::Write(const void* data, size_t data_len,
674                                      size_t* written, int* error) {
675   // SSL_CONNECTED sanity check.
676   switch (state_) {
677     case SSL_NONE:
678     case SSL_WAIT:
679     case SSL_CONNECTING:
680       return SR_BLOCK;
681
682     case SSL_CONNECTED:
683       break;
684       
685     case SSL_ERROR:
686     case SSL_CLOSED:
687     default:
688       if (error)
689         *error = ssl_error_code_;
690       return SR_ERROR;
691   }
692
693   PRInt32 rv = PR_Write(ssl_fd_, data, data_len);
694
695   // Error
696   if (rv < 0) {
697     PRInt32 err = PR_GetError();
698
699     switch (err) {
700       case PR_WOULD_BLOCK_ERROR:
701         return SR_BLOCK;
702       default:
703         Error("Write", -1, false);
704         *error = err;  // libjingle semantics are that this is impl-specific
705         return SR_ERROR;
706     }
707   }
708
709   // Success
710   *written = rv;
711
712   return SR_SUCCESS;
713 }
714
715 void NSSStreamAdapter::OnEvent(StreamInterface* stream, int events,
716                                int err) {
717   int events_to_signal = 0;
718   int signal_error = 0;
719   ASSERT(stream == this->stream());
720   if ((events & SE_OPEN)) {
721     LOG(LS_INFO) << "NSSStreamAdapter::OnEvent SE_OPEN";
722     if (state_ != SSL_WAIT) {
723       ASSERT(state_ == SSL_NONE);
724       events_to_signal |= SE_OPEN;
725     } else {
726       state_ = SSL_CONNECTING;
727       if (int err = BeginSSL()) {
728         Error("BeginSSL", err, true);
729         return;
730       }
731     }
732   }
733   if ((events & (SE_READ|SE_WRITE))) {
734     LOG(LS_INFO) << "NSSStreamAdapter::OnEvent"
735                  << ((events & SE_READ) ? " SE_READ" : "")
736                  << ((events & SE_WRITE) ? " SE_WRITE" : "");
737     if (state_ == SSL_NONE) {
738       events_to_signal |= events & (SE_READ|SE_WRITE);
739     } else if (state_ == SSL_CONNECTING) {
740       if (int err = ContinueSSL()) {
741         Error("ContinueSSL", err, true);
742         return;
743       }
744     } else if (state_ == SSL_CONNECTED) {
745       if (events & SE_WRITE) {
746         LOG(LS_INFO) << " -- onStreamWriteable";
747         events_to_signal |= SE_WRITE;
748       }
749       if (events & SE_READ) {
750         LOG(LS_INFO) << " -- onStreamReadable";
751         events_to_signal |= SE_READ;
752       }
753     }
754   }
755   if ((events & SE_CLOSE)) {
756     LOG(LS_INFO) << "NSSStreamAdapter::OnEvent(SE_CLOSE, " << err << ")";
757     Cleanup();
758     events_to_signal |= SE_CLOSE;
759     // SE_CLOSE is the only event that uses the final parameter to OnEvent().
760     ASSERT(signal_error == 0);
761     signal_error = err;
762   }
763   if (events_to_signal)
764     StreamAdapterInterface::OnEvent(stream, events_to_signal, signal_error);
765 }
766
767 void NSSStreamAdapter::OnMessage(Message* msg) {
768   // Process our own messages and then pass others to the superclass
769   if (MSG_DTLS_TIMEOUT == msg->message_id) {
770     LOG(LS_INFO) << "DTLS timeout expired";
771     ContinueSSL();
772   } else {
773     StreamInterface::OnMessage(msg);
774   }
775 }
776
777 // Certificate verification callback. Called to check any certificate
778 SECStatus NSSStreamAdapter::AuthCertificateHook(void *arg,
779                                                 PRFileDesc *fd,
780                                                 PRBool checksig,
781                                                 PRBool isServer) {
782   LOG(LS_INFO) << "NSSStreamAdapter::AuthCertificateHook";
783   NSSCertificate peer_cert(SSL_PeerCertificate(fd));
784   NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg);
785   stream->cert_ok_ = false;
786
787   // Read the peer's certificate chain.
788   CERTCertList* cert_list = SSL_PeerCertificateChain(fd);
789   ASSERT(cert_list != NULL);
790
791   // If the peer provided multiple certificates, check that they form a valid
792   // chain as defined by RFC 5246 Section 7.4.2: "Each following certificate
793   // MUST directly certify the one preceding it.".  This check does NOT
794   // verify other requirements, such as whether the chain reaches a trusted
795   // root, self-signed certificates have valid signatures, certificates are not
796   // expired, etc.
797   // Even if the chain is valid, the leaf certificate must still match a
798   // provided certificate or digest.
799   if (!NSSCertificate::IsValidChain(cert_list)) {
800     CERT_DestroyCertList(cert_list);
801     PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
802     return SECFailure;
803   }
804
805   if (stream->peer_certificate_.get()) {
806     LOG(LS_INFO) << "Checking against specified certificate";
807
808     // The peer certificate was specified
809     if (reinterpret_cast<NSSCertificate *>(stream->peer_certificate_.get())->
810         Equals(&peer_cert)) {
811       LOG(LS_INFO) << "Accepted peer certificate";
812       stream->cert_ok_ = true;
813     }
814   } else if (!stream->peer_certificate_digest_algorithm_.empty()) {
815     LOG(LS_INFO) << "Checking against specified digest";
816     // The peer certificate digest was specified
817     unsigned char digest[64];  // Maximum size
818     std::size_t digest_length;
819
820     if (!peer_cert.ComputeDigest(
821             stream->peer_certificate_digest_algorithm_,
822             digest, sizeof(digest), &digest_length)) {
823       LOG(LS_ERROR) << "Digest computation failed";
824     } else {
825       Buffer computed_digest(digest, digest_length);
826       if (computed_digest == stream->peer_certificate_digest_value_) {
827         LOG(LS_INFO) << "Accepted peer certificate";
828         stream->cert_ok_ = true;
829       }
830     }
831   } else {
832     // Other modes, but we haven't implemented yet
833     // TODO(ekr@rtfm.com): Implement real certificate validation
834     UNIMPLEMENTED;
835   }
836
837   if (!stream->cert_ok_ && stream->ignore_bad_cert()) {
838     LOG(LS_WARNING) << "Ignoring cert error while verifying cert chain";
839     stream->cert_ok_ = true;
840   }
841
842   if (stream->cert_ok_)
843     stream->peer_certificate_.reset(new NSSCertificate(cert_list));
844
845   CERT_DestroyCertList(cert_list);
846
847   if (stream->cert_ok_)
848     return SECSuccess;
849
850   PORT_SetError(SEC_ERROR_UNTRUSTED_CERT);
851   return SECFailure;
852 }
853
854
855 SECStatus NSSStreamAdapter::GetClientAuthDataHook(void *arg, PRFileDesc *fd,
856                                                   CERTDistNames *caNames,
857                                                   CERTCertificate **pRetCert,
858                                                   SECKEYPrivateKey **pRetKey) {
859   LOG(LS_INFO) << "Client cert requested";
860   NSSStreamAdapter *stream = reinterpret_cast<NSSStreamAdapter *>(arg);
861
862   if (!stream->identity_.get()) {
863     LOG(LS_ERROR) << "No identity available";
864     return SECFailure;
865   }
866
867   NSSIdentity *identity = static_cast<NSSIdentity *>(stream->identity_.get());
868   // Destroyed internally by NSS
869   *pRetCert = CERT_DupCertificate(identity->certificate().certificate());
870   *pRetKey = SECKEY_CopyPrivateKey(identity->keypair()->privkey());
871
872   return SECSuccess;
873 }
874
875 // RFC 5705 Key Exporter
876 bool NSSStreamAdapter::ExportKeyingMaterial(const std::string& label,
877                                             const uint8* context,
878                                             size_t context_len,
879                                             bool use_context,
880                                             uint8* result,
881                                             size_t result_len) {
882   SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_,
883                                           label.c_str(), label.size(),
884                                           use_context,
885                                           context, context_len,
886                                           result, result_len);
887
888   return rv == SECSuccess;
889 }
890
891 bool NSSStreamAdapter::SetDtlsSrtpCiphers(
892     const std::vector<std::string>& ciphers) {
893 #ifdef HAVE_DTLS_SRTP
894   std::vector<PRUint16> internal_ciphers;
895   if (state_ != SSL_NONE)
896     return false;
897
898   for (std::vector<std::string>::const_iterator cipher = ciphers.begin();
899        cipher != ciphers.end(); ++cipher) {
900     bool found = false;
901     for (const SrtpCipherMapEntry *entry = kSrtpCipherMap; entry->cipher_id;
902          ++entry) {
903       if (*cipher == entry->external_name) {
904         found = true;
905         internal_ciphers.push_back(entry->cipher_id);
906         break;
907       }
908     }
909
910     if (!found) {
911       LOG(LS_ERROR) << "Could not find cipher: " << *cipher;
912       return false;
913     }
914   }
915
916   if (internal_ciphers.empty())
917     return false;
918
919   srtp_ciphers_ = internal_ciphers;
920
921   return true;
922 #else
923   return false;
924 #endif
925 }
926
927 bool NSSStreamAdapter::GetDtlsSrtpCipher(std::string* cipher) {
928 #ifdef HAVE_DTLS_SRTP
929   ASSERT(state_ == SSL_CONNECTED);
930   if (state_ != SSL_CONNECTED)
931     return false;
932
933   PRUint16 selected_cipher;
934
935   SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, &selected_cipher);
936   if (rv == SECFailure)
937     return false;
938
939   for (const SrtpCipherMapEntry *entry = kSrtpCipherMap;
940        entry->cipher_id; ++entry) {
941     if (selected_cipher == entry->cipher_id) {
942       *cipher = entry->external_name;
943       return true;
944     }
945   }
946
947   ASSERT(false);  // This should never happen
948 #endif
949   return false;
950 }
951
952
953 bool NSSContext::initialized;
954 NSSContext *NSSContext::global_nss_context;
955
956 // Static initialization and shutdown
957 NSSContext *NSSContext::Instance() {
958   if (!global_nss_context) {
959     NSSContext *new_ctx = new NSSContext();
960
961     if (!(new_ctx->slot_ = PK11_GetInternalSlot())) {
962       delete new_ctx;
963       goto fail;
964     }
965
966     global_nss_context = new_ctx;
967   }
968
969  fail:
970   return global_nss_context;
971 }
972
973
974
975 bool NSSContext::InitializeSSL(VerificationCallback callback) {
976   ASSERT(!callback);
977
978   if (!initialized) {
979     SECStatus rv;
980
981     rv = NSS_NoDB_Init(NULL);
982     if (rv != SECSuccess) {
983       LOG(LS_ERROR) << "Couldn't initialize NSS error=" <<
984           PORT_GetError();
985       return false;
986     }
987
988     NSS_SetDomesticPolicy();
989
990     initialized = true;
991   }
992
993   return true;
994 }
995
996 bool NSSContext::InitializeSSLThread() {
997   // Not needed
998   return true;
999 }
1000
1001 bool NSSContext::CleanupSSL() {
1002   // Not needed
1003   return true;
1004 }
1005
1006 bool NSSStreamAdapter::HaveDtls() {
1007   return true;
1008 }
1009
1010 bool NSSStreamAdapter::HaveDtlsSrtp() {
1011 #ifdef HAVE_DTLS_SRTP
1012   return true;
1013 #else
1014   return false;
1015 #endif
1016 }
1017
1018 bool NSSStreamAdapter::HaveExporter() {
1019   return true;
1020 }
1021
1022 }  // namespace talk_base
1023
1024 #endif  // HAVE_NSS_SSL_H