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