1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 // Original author: ekr@rtfm.com
12 #include "mozilla/UniquePtr.h"
21 #include "nsComponentManagerUtils.h"
22 #include "nsIEventTarget.h"
24 #include "nsComponentManagerUtils.h"
25 #include "nsServiceManagerUtils.h"
27 #include "dtlsidentity.h"
28 #include "transportflow.h"
29 #include "transportlayerdtls.h"
33 MOZ_MTLOG_MODULE("mtransport")
35 static PRDescIdentity transport_layer_identity
= PR_INVALID_IO_LAYER
;
37 // TODO: Implement a mode for this where
38 // the channel is not ready until confirmed externally
39 // (e.g., after cert check).
41 #define UNIMPLEMENTED \
43 "Call to unimplemented function "<< __FUNCTION__); \
45 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0)
48 // We need to adapt the NSPR/libssl model to the TransportFlow model.
49 // The former wants pull semantics and TransportFlow wants push.
51 // - A TransportLayerDtls assumes it is sitting on top of another
52 // TransportLayer, which means that events come in asynchronously.
53 // - NSS (libssl) wants to sit on top of a PRFileDesc and poll.
54 // - The TransportLayerNSPRAdapter is a PRFileDesc containing a
56 // - When TransportLayerDtls.PacketReceived() is called, we insert
57 // the packets in the FIFO and then do a PR_Recv() on the NSS
58 // PRFileDesc, which eventually reads off the FIFO.
60 // All of this stuff is assumed to happen solely in a single thread
61 // (generally the SocketTransportService thread)
63 Packet() : data_(nullptr), len_(0) {}
65 void Assign(const void *data
, int32_t len
) {
66 data_
.reset(new uint8_t[len
]);
67 memcpy(data_
.get(), data
, len
);
71 UniquePtr
<uint8_t[]> data_
;
75 void TransportLayerNSPRAdapter::PacketReceived(const void *data
, int32_t len
) {
76 input_
.push(new Packet());
77 input_
.back()->Assign(data
, len
);
80 int32_t TransportLayerNSPRAdapter::Recv(void *buf
, int32_t buflen
) {
82 PR_SetError(PR_WOULD_BLOCK_ERROR
, 0);
86 Packet
* front
= input_
.front();
87 if (buflen
< front
->len_
) {
88 MOZ_ASSERT(false, "Not enough buffer space to receive into");
89 PR_SetError(PR_BUFFER_OVERFLOW_ERROR
, 0);
93 int32_t count
= front
->len_
;
94 memcpy(buf
, front
->data_
.get(), count
);
102 int32_t TransportLayerNSPRAdapter::Write(const void *buf
, int32_t length
) {
103 TransportResult r
= output_
->SendPacket(
104 static_cast<const unsigned char *>(buf
), length
);
109 if (r
== TE_WOULDBLOCK
) {
110 PR_SetError(PR_WOULD_BLOCK_ERROR
, 0);
112 PR_SetError(PR_IO_ERROR
, 0);
119 // Implementation of NSPR methods
120 static PRStatus
TransportLayerClose(PRFileDesc
*f
) {
125 static int32_t TransportLayerRead(PRFileDesc
*f
, void *buf
, int32_t length
) {
130 static int32_t TransportLayerWrite(PRFileDesc
*f
, const void *buf
, int32_t length
) {
131 TransportLayerNSPRAdapter
*io
= reinterpret_cast<TransportLayerNSPRAdapter
*>(f
->secret
);
132 return io
->Write(buf
, length
);
135 static int32_t TransportLayerAvailable(PRFileDesc
*f
) {
140 int64_t TransportLayerAvailable64(PRFileDesc
*f
) {
145 static PRStatus
TransportLayerSync(PRFileDesc
*f
) {
150 static int32_t TransportLayerSeek(PRFileDesc
*f
, int32_t offset
,
156 static int64_t TransportLayerSeek64(PRFileDesc
*f
, int64_t offset
,
162 static PRStatus
TransportLayerFileInfo(PRFileDesc
*f
, PRFileInfo
*info
) {
167 static PRStatus
TransportLayerFileInfo64(PRFileDesc
*f
, PRFileInfo64
*info
) {
172 static int32_t TransportLayerWritev(PRFileDesc
*f
, const PRIOVec
*iov
,
173 int32_t iov_size
, PRIntervalTime to
) {
178 static PRStatus
TransportLayerConnect(PRFileDesc
*f
, const PRNetAddr
*addr
,
184 static PRFileDesc
*TransportLayerAccept(PRFileDesc
*sd
, PRNetAddr
*addr
,
190 static PRStatus
TransportLayerBind(PRFileDesc
*f
, const PRNetAddr
*addr
) {
195 static PRStatus
TransportLayerListen(PRFileDesc
*f
, int32_t depth
) {
200 static PRStatus
TransportLayerShutdown(PRFileDesc
*f
, int32_t how
) {
205 // This function does not support peek, or waiting until `to`
206 static int32_t TransportLayerRecv(PRFileDesc
*f
, void *buf
, int32_t buflen
,
207 int32_t flags
, PRIntervalTime to
) {
208 MOZ_ASSERT(flags
== 0);
210 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
214 TransportLayerNSPRAdapter
*io
= reinterpret_cast<TransportLayerNSPRAdapter
*>(f
->secret
);
215 return io
->Recv(buf
, buflen
);
218 // Note: this is always nonblocking and assumes a zero timeout.
219 static int32_t TransportLayerSend(PRFileDesc
*f
, const void *buf
, int32_t amount
,
220 int32_t flags
, PRIntervalTime to
) {
221 int32_t written
= TransportLayerWrite(f
, buf
, amount
);
225 static int32_t TransportLayerRecvfrom(PRFileDesc
*f
, void *buf
, int32_t amount
,
226 int32_t flags
, PRNetAddr
*addr
, PRIntervalTime to
) {
231 static int32_t TransportLayerSendto(PRFileDesc
*f
, const void *buf
, int32_t amount
,
232 int32_t flags
, const PRNetAddr
*addr
, PRIntervalTime to
) {
237 static int16_t TransportLayerPoll(PRFileDesc
*f
, int16_t in_flags
, int16_t *out_flags
) {
242 static int32_t TransportLayerAcceptRead(PRFileDesc
*sd
, PRFileDesc
**nd
,
244 void *buf
, int32_t amount
, PRIntervalTime t
) {
249 static int32_t TransportLayerTransmitFile(PRFileDesc
*sd
, PRFileDesc
*f
,
250 const void *headers
, int32_t hlen
,
251 PRTransmitFileFlags flags
, PRIntervalTime t
) {
256 static PRStatus
TransportLayerGetpeername(PRFileDesc
*f
, PRNetAddr
*addr
) {
257 // TODO: Modify to return unique names for each channel
258 // somehow, as opposed to always the same static address. The current
259 // implementation messes up the session cache, which is why it's off
261 addr
->inet
.family
= PR_AF_INET
;
268 static PRStatus
TransportLayerGetsockname(PRFileDesc
*f
, PRNetAddr
*addr
) {
273 static PRStatus
TransportLayerGetsockoption(PRFileDesc
*f
, PRSocketOptionData
*opt
) {
274 switch (opt
->option
) {
275 case PR_SockOpt_Nonblocking
:
276 opt
->value
.non_blocking
= PR_TRUE
;
286 // Imitate setting socket options. These are mostly noops.
287 static PRStatus
TransportLayerSetsockoption(PRFileDesc
*f
,
288 const PRSocketOptionData
*opt
) {
289 switch (opt
->option
) {
290 case PR_SockOpt_Nonblocking
:
292 case PR_SockOpt_NoDelay
:
302 static int32_t TransportLayerSendfile(PRFileDesc
*out
, PRSendFileData
*in
,
303 PRTransmitFileFlags flags
, PRIntervalTime to
) {
308 static PRStatus
TransportLayerConnectContinue(PRFileDesc
*f
, int16_t flags
) {
313 static int32_t TransportLayerReserved(PRFileDesc
*f
) {
318 static const struct PRIOMethods TransportLayerMethods
= {
323 TransportLayerAvailable
,
324 TransportLayerAvailable64
,
327 TransportLayerSeek64
,
328 TransportLayerFileInfo
,
329 TransportLayerFileInfo64
,
330 TransportLayerWritev
,
331 TransportLayerConnect
,
332 TransportLayerAccept
,
334 TransportLayerListen
,
335 TransportLayerShutdown
,
338 TransportLayerRecvfrom
,
339 TransportLayerSendto
,
341 TransportLayerAcceptRead
,
342 TransportLayerTransmitFile
,
343 TransportLayerGetsockname
,
344 TransportLayerGetpeername
,
345 TransportLayerReserved
,
346 TransportLayerReserved
,
347 TransportLayerGetsockoption
,
348 TransportLayerSetsockoption
,
349 TransportLayerSendfile
,
350 TransportLayerConnectContinue
,
351 TransportLayerReserved
,
352 TransportLayerReserved
,
353 TransportLayerReserved
,
354 TransportLayerReserved
357 TransportLayerDtls::~TransportLayerDtls() {
363 nsresult
TransportLayerDtls::InitInternal() {
364 // Get the transport service as an event target
366 target_
= do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID
, &rv
);
369 MOZ_MTLOG(ML_ERROR
, "Couldn't get socket transport service");
373 timer_
= do_CreateInstance(NS_TIMER_CONTRACTID
, &rv
);
375 MOZ_MTLOG(ML_ERROR
, "Couldn't get timer");
383 void TransportLayerDtls::WasInserted() {
384 // Connect to the lower layers
386 TL_SET_STATE(TS_ERROR
);
391 nsresult
TransportLayerDtls::SetVerificationAllowAll() {
392 // Defensive programming
393 if (verification_mode_
!= VERIFY_UNSET
)
394 return NS_ERROR_ALREADY_INITIALIZED
;
396 verification_mode_
= VERIFY_ALLOW_ALL
;
402 TransportLayerDtls::SetVerificationDigest(const std::string digest_algorithm
,
403 const unsigned char *digest_value
,
405 // Defensive programming
406 if (verification_mode_
!= VERIFY_UNSET
&&
407 verification_mode_
!= VERIFY_DIGEST
) {
408 return NS_ERROR_ALREADY_INITIALIZED
;
411 // Note that we do not sanity check these values for length.
412 // We merely ensure they will fit into the buffer.
413 // TODO: is there a Data construct we could use?
414 if (digest_len
> kMaxDigestLength
)
415 return NS_ERROR_INVALID_ARG
;
417 digests_
.push_back(new VerificationDigest(
418 digest_algorithm
, digest_value
, digest_len
));
420 verification_mode_
= VERIFY_DIGEST
;
425 // TODO: make sure this is called from STS. Otherwise
426 // we have thread safety issues
427 bool TransportLayerDtls::Setup() {
432 MOZ_MTLOG(ML_ERROR
, "DTLS layer with nothing below. This is useless");
435 nspr_io_adapter_
= new TransportLayerNSPRAdapter(downward_
);
438 MOZ_MTLOG(ML_ERROR
, "Can't start DTLS without an identity");
442 if (verification_mode_
== VERIFY_UNSET
) {
444 "Can't start DTLS without specifying a verification mode");
448 if (transport_layer_identity
== PR_INVALID_IO_LAYER
) {
449 transport_layer_identity
= PR_GetUniqueIdentity("nssstreamadapter");
452 ScopedPRFileDesc
pr_fd(PR_CreateIOLayerStub(transport_layer_identity
,
453 &TransportLayerMethods
));
454 MOZ_ASSERT(pr_fd
!= nullptr);
457 pr_fd
->secret
= reinterpret_cast<PRFilePrivate
*>(nspr_io_adapter_
.get());
459 ScopedPRFileDesc
ssl_fd(DTLS_ImportFD(nullptr, pr_fd
));
460 MOZ_ASSERT(ssl_fd
!= nullptr); // This should never happen
465 pr_fd
.forget(); // ownership transfered to ssl_fd;
467 if (role_
== CLIENT
) {
468 MOZ_MTLOG(ML_DEBUG
, "Setting up DTLS as client");
469 rv
= SSL_GetClientAuthDataHook(ssl_fd
, GetClientAuthDataHook
,
471 if (rv
!= SECSuccess
) {
472 MOZ_MTLOG(ML_ERROR
, "Couldn't set identity");
476 MOZ_MTLOG(ML_DEBUG
, "Setting up DTLS as server");
478 rv
= SSL_ConfigSecureServer(ssl_fd
, identity_
->cert(),
479 identity_
->privkey(),
481 if (rv
!= SECSuccess
) {
482 MOZ_MTLOG(ML_ERROR
, "Couldn't set identity");
486 // Insist on a certificate from the client
487 rv
= SSL_OptionSet(ssl_fd
, SSL_REQUEST_CERTIFICATE
, PR_TRUE
);
488 if (rv
!= SECSuccess
) {
489 MOZ_MTLOG(ML_ERROR
, "Couldn't request certificate");
493 rv
= SSL_OptionSet(ssl_fd
, SSL_REQUIRE_CERTIFICATE
, PR_TRUE
);
494 if (rv
!= SECSuccess
) {
495 MOZ_MTLOG(ML_ERROR
, "Couldn't require certificate");
500 // Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS
501 // 1.0 for stream modes.
502 SSLVersionRange version_range
= {
503 SSL_LIBRARY_VERSION_TLS_1_1
,
504 SSL_LIBRARY_VERSION_TLS_1_1
// version intolerance; bug 1052610
507 rv
= SSL_VersionRangeSet(ssl_fd
, &version_range
);
508 if (rv
!= SECSuccess
) {
509 MOZ_MTLOG(ML_ERROR
, "Can't disable SSLv3");
513 rv
= SSL_OptionSet(ssl_fd
, SSL_ENABLE_SESSION_TICKETS
, PR_FALSE
);
514 if (rv
!= SECSuccess
) {
515 MOZ_MTLOG(ML_ERROR
, "Couldn't disable session tickets");
519 rv
= SSL_OptionSet(ssl_fd
, SSL_NO_CACHE
, PR_TRUE
);
520 if (rv
!= SECSuccess
) {
521 MOZ_MTLOG(ML_ERROR
, "Couldn't disable session caching");
525 rv
= SSL_OptionSet(ssl_fd
, SSL_ENABLE_DEFLATE
, PR_FALSE
);
526 if (rv
!= SECSuccess
) {
527 MOZ_MTLOG(ML_ERROR
, "Couldn't disable deflate");
531 rv
= SSL_OptionSet(ssl_fd
, SSL_ENABLE_RENEGOTIATION
, SSL_RENEGOTIATE_NEVER
);
532 if (rv
!= SECSuccess
) {
533 MOZ_MTLOG(ML_ERROR
, "Couldn't disable renegotiation");
537 rv
= SSL_OptionSet(ssl_fd
, SSL_ENABLE_FALSE_START
, PR_FALSE
);
538 if (rv
!= SECSuccess
) {
539 MOZ_MTLOG(ML_ERROR
, "Couldn't disable false start");
543 rv
= SSL_OptionSet(ssl_fd
, SSL_NO_LOCKS
, PR_TRUE
);
544 if (rv
!= SECSuccess
) {
545 MOZ_MTLOG(ML_ERROR
, "Couldn't disable locks");
549 rv
= SSL_OptionSet(ssl_fd
, SSL_REUSE_SERVER_ECDHE_KEY
, PR_FALSE
);
550 if (rv
!= SECSuccess
) {
551 MOZ_MTLOG(ML_ERROR
, "Couldn't disable ECDHE key reuse");
555 if (!SetupCipherSuites(ssl_fd
)) {
559 // Certificate validation
560 rv
= SSL_AuthCertificateHook(ssl_fd
, AuthCertificateHook
,
561 reinterpret_cast<void *>(this));
562 if (rv
!= SECSuccess
) {
563 MOZ_MTLOG(ML_ERROR
, "Couldn't set certificate validation hook");
567 // Now start the handshake
568 rv
= SSL_ResetHandshake(ssl_fd
, role_
== SERVER
? PR_TRUE
: PR_FALSE
);
569 if (rv
!= SECSuccess
) {
570 MOZ_MTLOG(ML_ERROR
, "Couldn't reset handshake");
573 ssl_fd_
= ssl_fd
.forget();
575 // Finally, get ready to receive data
576 downward_
->SignalStateChange
.connect(this, &TransportLayerDtls::StateChange
);
577 downward_
->SignalPacketReceived
.connect(this, &TransportLayerDtls::PacketReceived
);
579 if (downward_
->state() == TS_OPEN
) {
586 // Ciphers we need to enable. These are on by default in standard firefox
587 // builds, but can be disabled with prefs and they aren't on in our unit tests
588 // since that uses NSS default configuration.
589 // Only override prefs to comply with MUST statements in the security-arch.
590 static const uint32_t EnabledCiphers
[] = {
591 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
,
592 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
595 // Don't remove suites; TODO(mt@mozilla.com) restore; bug 1052610
597 // Disable all NSS suites modes without PFS or with old and rusty ciphersuites.
598 // Anything outside this list is governed by the usual combination of policy
599 // and user preferences.
600 static const uint32_t DisabledCiphers
[] = {
601 TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
,
602 TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
,
603 TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
,
604 TLS_ECDHE_RSA_WITH_RC4_128_SHA
,
606 TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
,
607 TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
,
608 TLS_DHE_DSS_WITH_RC4_128_SHA
,
610 TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
,
611 TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
,
612 TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
,
613 TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
,
614 TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
,
615 TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
,
616 TLS_ECDH_ECDSA_WITH_RC4_128_SHA
,
617 TLS_ECDH_RSA_WITH_RC4_128_SHA
,
619 TLS_RSA_WITH_AES_128_GCM_SHA256
,
620 TLS_RSA_WITH_AES_128_CBC_SHA
,
621 TLS_RSA_WITH_AES_128_CBC_SHA256
,
622 TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
,
623 TLS_RSA_WITH_AES_256_CBC_SHA
,
624 TLS_RSA_WITH_AES_256_CBC_SHA256
,
625 TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
,
626 TLS_RSA_WITH_SEED_CBC_SHA
,
627 SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA
,
628 TLS_RSA_WITH_3DES_EDE_CBC_SHA
,
629 TLS_RSA_WITH_RC4_128_SHA
,
630 TLS_RSA_WITH_RC4_128_MD5
,
632 TLS_DHE_RSA_WITH_DES_CBC_SHA
,
633 TLS_DHE_DSS_WITH_DES_CBC_SHA
,
634 SSL_RSA_FIPS_WITH_DES_CBC_SHA
,
635 TLS_RSA_WITH_DES_CBC_SHA
,
637 TLS_RSA_EXPORT1024_WITH_RC4_56_SHA
,
638 TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA
,
640 TLS_RSA_EXPORT_WITH_RC4_40_MD5
,
641 TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
,
643 TLS_ECDHE_ECDSA_WITH_NULL_SHA
,
644 TLS_ECDHE_RSA_WITH_NULL_SHA
,
645 TLS_ECDH_ECDSA_WITH_NULL_SHA
,
646 TLS_ECDH_RSA_WITH_NULL_SHA
,
648 TLS_RSA_WITH_NULL_SHA
,
649 TLS_RSA_WITH_NULL_SHA256
,
650 TLS_RSA_WITH_NULL_MD5
,
652 #endif // bug 1052610
654 bool TransportLayerDtls::SetupCipherSuites(PRFileDesc
* ssl_fd
) const {
657 // Set the SRTP ciphers
658 if (!srtp_ciphers_
.empty()) {
659 // Note: std::vector is guaranteed to contiguous
660 rv
= SSL_SetSRTPCiphers(ssl_fd
, &srtp_ciphers_
[0], srtp_ciphers_
.size());
662 if (rv
!= SECSuccess
) {
663 MOZ_MTLOG(ML_ERROR
, "Couldn't set SRTP cipher suite");
668 for (size_t i
= 0; i
< PR_ARRAY_SIZE(EnabledCiphers
); ++i
) {
669 MOZ_MTLOG(ML_INFO
, LAYER_INFO
<< "Enabling: " << EnabledCiphers
[i
]);
670 rv
= SSL_CipherPrefSet(ssl_fd
, EnabledCiphers
[i
], PR_TRUE
);
671 if (rv
!= SECSuccess
) {
672 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<<
673 "Unable to enable suite: " << EnabledCiphers
[i
]);
678 // Don't remove suites; TODO(mt@mozilla.com) restore; bug 1052610
680 for (size_t i
= 0; i
< PR_ARRAY_SIZE(DisabledCiphers
); ++i
) {
681 MOZ_MTLOG(ML_INFO
, LAYER_INFO
<< "Disabling: " << DisabledCiphers
[i
]);
683 PRBool enabled
= false;
684 rv
= SSL_CipherPrefGet(ssl_fd
, DisabledCiphers
[i
], &enabled
);
685 if (rv
!= SECSuccess
) {
686 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<<
687 "Unable to check if suite is enabled: " << DisabledCiphers
[i
]);
691 rv
= SSL_CipherPrefSet(ssl_fd
, DisabledCiphers
[i
], PR_FALSE
);
692 if (rv
!= SECSuccess
) {
693 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<<
694 "Unable to disable suite: " << DisabledCiphers
[i
]);
703 nsresult
TransportLayerDtls::GetCipherSuite(uint16_t* cipherSuite
) const {
706 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "GetCipherSuite passed a nullptr");
707 return NS_ERROR_NULL_POINTER
;
709 if (state_
!= TS_OPEN
) {
710 return NS_ERROR_NOT_AVAILABLE
;
713 SECStatus rv
= SSL_GetChannelInfo(ssl_fd_
, &info
, sizeof(info
));
714 if (rv
!= SECSuccess
) {
715 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<< "GetCipherSuite can't get channel info");
716 return NS_ERROR_FAILURE
;
718 *cipherSuite
= info
.cipherSuite
;
722 void TransportLayerDtls::StateChange(TransportLayer
*layer
, State state
) {
723 if (state
<= state_
) {
724 MOZ_MTLOG(ML_ERROR
, "Lower layer state is going backwards from ours");
725 TL_SET_STATE(TS_ERROR
);
731 MOZ_ASSERT(false); // Can't happen
736 LAYER_INFO
<< "State change of lower layer to INIT forbidden");
737 TL_SET_STATE(TS_ERROR
);
741 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Lower layer is connecting.");
746 LAYER_INFO
<< "Lower layer is now open; starting TLS");
751 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Lower layer is now closed");
752 TL_SET_STATE(TS_CLOSED
);
756 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Lower layer experienced an error");
757 TL_SET_STATE(TS_ERROR
);
762 void TransportLayerDtls::Handshake() {
763 TL_SET_STATE(TS_CONNECTING
);
765 // Clear the retransmit timer
768 SECStatus rv
= SSL_ForceHandshake(ssl_fd_
);
770 if (rv
== SECSuccess
) {
772 LAYER_INFO
<< "****** SSL handshake completed ******");
774 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Certificate check never occurred");
775 TL_SET_STATE(TS_ERROR
);
778 TL_SET_STATE(TS_OPEN
);
780 int32_t err
= PR_GetError();
782 case SSL_ERROR_RX_MALFORMED_HANDSHAKE
:
783 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Malformed DTLS message; ignoring");
784 // If this were TLS (and not DTLS), this would be fatal, but
785 // here we're required to ignore bad messages, so fall through
786 case PR_WOULD_BLOCK_ERROR
:
787 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<< "Handshake would have blocked");
788 PRIntervalTime timeout
;
789 rv
= DTLS_GetHandshakeTimeout(ssl_fd_
, &timeout
);
790 if (rv
== SECSuccess
) {
791 uint32_t timeout_ms
= PR_IntervalToMilliseconds(timeout
);
794 LAYER_INFO
<< "Setting DTLS timeout to " << timeout_ms
);
795 timer_
->SetTarget(target_
);
796 timer_
->InitWithFuncCallback(TimerCallback
,
798 nsITimer::TYPE_ONE_SHOT
);
802 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "SSL handshake error "<< err
);
803 TL_SET_STATE(TS_ERROR
);
809 void TransportLayerDtls::PacketReceived(TransportLayer
* layer
,
810 const unsigned char *data
,
813 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "PacketReceived(" << len
<< ")");
815 if (state_
!= TS_CONNECTING
&& state_
!= TS_OPEN
) {
817 LAYER_INFO
<< "Discarding packet in inappropriate state");
821 nspr_io_adapter_
->PacketReceived(data
, len
);
823 // If we're still connecting, try to handshake
824 if (state_
== TS_CONNECTING
) {
828 // Now try a recv if we're open, since there might be data left
829 if (state_
== TS_OPEN
) {
830 unsigned char buf
[2000];
832 int32_t rv
= PR_Recv(ssl_fd_
, buf
, sizeof(buf
), 0, PR_INTERVAL_NO_WAIT
);
835 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "Read " << rv
<< " bytes from NSS");
836 SignalPacketReceived(this, buf
, rv
);
837 } else if (rv
== 0) {
838 TL_SET_STATE(TS_CLOSED
);
840 int32_t err
= PR_GetError();
842 if (err
== PR_WOULD_BLOCK_ERROR
) {
844 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "Receive would have blocked");
846 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<< "NSS Error " << err
);
847 TL_SET_STATE(TS_ERROR
);
853 TransportResult
TransportLayerDtls::SendPacket(const unsigned char *data
,
856 if (state_
!= TS_OPEN
) {
857 MOZ_MTLOG(ML_ERROR
, LAYER_INFO
<< "Can't call SendPacket() in state "
862 int32_t rv
= PR_Send(ssl_fd_
, data
, len
, 0, PR_INTERVAL_NO_WAIT
);
866 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "Wrote " << rv
<< " bytes to SSL Layer");
871 TL_SET_STATE(TS_CLOSED
);
875 int32_t err
= PR_GetError();
877 if (err
== PR_WOULD_BLOCK_ERROR
) {
879 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "Send would have blocked");
880 return TE_WOULDBLOCK
;
883 MOZ_MTLOG(ML_NOTICE
, LAYER_INFO
<< "NSS Error " << err
);
884 TL_SET_STATE(TS_ERROR
);
888 SECStatus
TransportLayerDtls::GetClientAuthDataHook(void *arg
, PRFileDesc
*fd
,
889 CERTDistNames
*caNames
,
890 CERTCertificate
**pRetCert
,
891 SECKEYPrivateKey
**pRetKey
) {
892 MOZ_MTLOG(ML_DEBUG
, "Server requested client auth");
894 TransportLayerDtls
*stream
= reinterpret_cast<TransportLayerDtls
*>(arg
);
895 stream
->CheckThread();
897 if (!stream
->identity_
) {
898 MOZ_MTLOG(ML_ERROR
, "No identity available");
899 PR_SetError(SSL_ERROR_NO_CERTIFICATE
, 0);
903 *pRetCert
= CERT_DupCertificate(stream
->identity_
->cert());
905 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
909 *pRetKey
= SECKEY_CopyPrivateKey(stream
->identity_
->privkey());
911 CERT_DestroyCertificate(*pRetCert
);
913 PR_SetError(PR_OUT_OF_MEMORY_ERROR
, 0);
920 nsresult
TransportLayerDtls::SetSrtpCiphers(std::vector
<uint16_t> ciphers
) {
921 // TODO: We should check these
922 srtp_ciphers_
= ciphers
;
927 nsresult
TransportLayerDtls::GetSrtpCipher(uint16_t *cipher
) const {
929 SECStatus rv
= SSL_GetSRTPCipher(ssl_fd_
, cipher
);
930 if (rv
!= SECSuccess
) {
931 MOZ_MTLOG(ML_DEBUG
, "No SRTP cipher negotiated");
932 return NS_ERROR_FAILURE
;
938 nsresult
TransportLayerDtls::ExportKeyingMaterial(const std::string
& label
,
940 const std::string
& context
,
942 unsigned int outlen
) {
944 SECStatus rv
= SSL_ExportKeyingMaterial(ssl_fd_
,
948 reinterpret_cast<const unsigned char *>(
953 if (rv
!= SECSuccess
) {
954 MOZ_MTLOG(ML_ERROR
, "Couldn't export SSL keying material");
955 return NS_ERROR_FAILURE
;
961 SECStatus
TransportLayerDtls::AuthCertificateHook(void *arg
,
965 TransportLayerDtls
*stream
= reinterpret_cast<TransportLayerDtls
*>(arg
);
966 stream
->CheckThread();
967 return stream
->AuthCertificateHook(fd
, checksig
, isServer
);
971 TransportLayerDtls::CheckDigest(const RefPtr
<VerificationDigest
>&
973 CERTCertificate
*peer_cert
) {
974 unsigned char computed_digest
[kMaxDigestLength
];
975 size_t computed_digest_len
;
977 MOZ_MTLOG(ML_DEBUG
, LAYER_INFO
<< "Checking digest, algorithm="
978 << digest
->algorithm_
);
980 DtlsIdentity::ComputeFingerprint(peer_cert
,
983 sizeof(computed_digest
),
984 &computed_digest_len
);
985 if (NS_FAILED(res
)) {
986 MOZ_MTLOG(ML_ERROR
, "Could not compute peer fingerprint for digest " <<
989 PR_SetError(SSL_ERROR_BAD_CERTIFICATE
, 0);
993 if (computed_digest_len
!= digest
->len_
) {
994 MOZ_MTLOG(ML_ERROR
, "Digest is wrong length " << digest
->len_
<<
995 " should be " << computed_digest_len
<< " for algorithm " <<
997 PR_SetError(SSL_ERROR_BAD_CERTIFICATE
, 0);
1001 if (memcmp(digest
->value_
, computed_digest
, computed_digest_len
) != 0) {
1002 MOZ_MTLOG(ML_ERROR
, "Digest does not match");
1003 PR_SetError(SSL_ERROR_BAD_CERTIFICATE
, 0);
1011 SECStatus
TransportLayerDtls::AuthCertificateHook(PRFileDesc
*fd
,
1015 ScopedCERTCertificate peer_cert
;
1016 peer_cert
= SSL_PeerCertificate(fd
);
1019 // We are not set up to take this being called multiple
1020 // times. Change this if we ever add renegotiation.
1021 MOZ_ASSERT(!auth_hook_called_
);
1022 if (auth_hook_called_
) {
1023 PR_SetError(PR_UNKNOWN_ERROR
, 0);
1026 auth_hook_called_
= true;
1028 MOZ_ASSERT(verification_mode_
!= VERIFY_UNSET
);
1029 MOZ_ASSERT(peer_cert_
== nullptr);
1031 switch (verification_mode_
) {
1033 // Break out to error exit
1034 PR_SetError(PR_UNKNOWN_ERROR
, 0);
1037 case VERIFY_ALLOW_ALL
:
1038 peer_cert_
= peer_cert
.forget();
1044 MOZ_ASSERT(digests_
.size() != 0);
1045 // Check all the provided digests
1047 // Checking functions call PR_SetError()
1048 SECStatus rv
= SECFailure
;
1049 for (size_t i
= 0; i
< digests_
.size(); i
++) {
1050 RefPtr
<VerificationDigest
> digest
= digests_
[i
];
1051 rv
= CheckDigest(digest
, peer_cert
);
1053 if (rv
!= SECSuccess
)
1057 if (rv
== SECSuccess
) {
1058 // Matches all digests, we are good to go
1060 peer_cert
= peer_cert
.forget();
1066 MOZ_CRASH(); // Can't happen
1072 void TransportLayerDtls::TimerCallback(nsITimer
*timer
, void *arg
) {
1073 TransportLayerDtls
*dtls
= reinterpret_cast<TransportLayerDtls
*>(arg
);
1075 MOZ_MTLOG(ML_DEBUG
, "DTLS timer expired");
1080 } // close namespace