Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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
9 #include <queue>
10 #include <algorithm>
12 #include "logging.h"
13 #include "ssl.h"
14 #include "sslerr.h"
15 #include "sslproto.h"
16 #include "keyhi.h"
18 #include "nsCOMPtr.h"
19 #include "nsComponentManagerUtils.h"
20 #include "nsIEventTarget.h"
21 #include "nsNetCID.h"
22 #include "nsComponentManagerUtils.h"
23 #include "nsServiceManagerUtils.h"
25 #include "dtlsidentity.h"
26 #include "transportflow.h"
27 #include "transportlayerdtls.h"
29 namespace mozilla {
31 MOZ_MTLOG_MODULE("mtransport")
33 static PRDescIdentity transport_layer_identity = PR_INVALID_IO_LAYER;
35 // TODO: Implement a mode for this where
36 // the channel is not ready until confirmed externally
37 // (e.g., after cert check).
39 #define UNIMPLEMENTED \
40 MOZ_MTLOG(ML_ERROR, \
41 "Call to unimplemented function "<< __FUNCTION__); \
42 MOZ_ASSERT(false); \
43 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0)
46 // We need to adapt the NSPR/libssl model to the TransportFlow model.
47 // The former wants pull semantics and TransportFlow wants push.
48 //
49 // - A TransportLayerDtls assumes it is sitting on top of another
50 // TransportLayer, which means that events come in asynchronously.
51 // - NSS (libssl) wants to sit on top of a PRFileDesc and poll.
52 // - The TransportLayerNSPRAdapter is a PRFileDesc containing a
53 // FIFO.
54 // - When TransportLayerDtls.PacketReceived() is called, we insert
55 // the packets in the FIFO and then do a PR_Recv() on the NSS
56 // PRFileDesc, which eventually reads off the FIFO.
57 //
58 // All of this stuff is assumed to happen solely in a single thread
59 // (generally the SocketTransportService thread)
60 struct Packet {
61 Packet() : data_(nullptr), len_(0), offset_(0) {}
63 void Assign(const void *data, int32_t len) {
64 data_ = new uint8_t[len];
65 memcpy(data_, data, len);
66 len_ = len;
67 }
69 ScopedDeleteArray<uint8_t> data_;
70 int32_t len_;
71 int32_t offset_;
72 };
74 void TransportLayerNSPRAdapter::PacketReceived(const void *data, int32_t len) {
75 input_.push(new Packet());
76 input_.back()->Assign(data, len);
77 }
79 int32_t TransportLayerNSPRAdapter::Read(void *data, int32_t len) {
80 if (input_.empty()) {
81 PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
82 return TE_WOULDBLOCK;
83 }
85 Packet* front = input_.front();
86 int32_t to_read = std::min(len, front->len_ - front->offset_);
87 memcpy(data, front->data_, to_read);
88 front->offset_ += to_read;
90 if (front->offset_ == front->len_) {
91 input_.pop();
92 delete front;
93 }
95 return to_read;
96 }
98 int32_t TransportLayerNSPRAdapter::Write(const void *buf, int32_t length) {
99 TransportResult r = output_->SendPacket(
100 static_cast<const unsigned char *>(buf), length);
101 if (r >= 0) {
102 return r;
103 }
105 if (r == TE_WOULDBLOCK) {
106 PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
107 } else {
108 PR_SetError(PR_IO_ERROR, 0);
109 }
111 return -1;
112 }
115 // Implementation of NSPR methods
116 static PRStatus TransportLayerClose(PRFileDesc *f) {
117 f->secret = nullptr;
118 return PR_SUCCESS;
119 }
121 static int32_t TransportLayerRead(PRFileDesc *f, void *buf, int32_t length) {
122 TransportLayerNSPRAdapter *io = reinterpret_cast<TransportLayerNSPRAdapter *>(f->secret);
123 return io->Read(buf, length);
124 }
126 static int32_t TransportLayerWrite(PRFileDesc *f, const void *buf, int32_t length) {
127 TransportLayerNSPRAdapter *io = reinterpret_cast<TransportLayerNSPRAdapter *>(f->secret);
128 return io->Write(buf, length);
129 }
131 static int32_t TransportLayerAvailable(PRFileDesc *f) {
132 UNIMPLEMENTED;
133 return -1;
134 }
136 int64_t TransportLayerAvailable64(PRFileDesc *f) {
137 UNIMPLEMENTED;
138 return -1;
139 }
141 static PRStatus TransportLayerSync(PRFileDesc *f) {
142 UNIMPLEMENTED;
143 return PR_FAILURE;
144 }
146 static int32_t TransportLayerSeek(PRFileDesc *f, int32_t offset,
147 PRSeekWhence how) {
148 UNIMPLEMENTED;
149 return -1;
150 }
152 static int64_t TransportLayerSeek64(PRFileDesc *f, int64_t offset,
153 PRSeekWhence how) {
154 UNIMPLEMENTED;
155 return -1;
156 }
158 static PRStatus TransportLayerFileInfo(PRFileDesc *f, PRFileInfo *info) {
159 UNIMPLEMENTED;
160 return PR_FAILURE;
161 }
163 static PRStatus TransportLayerFileInfo64(PRFileDesc *f, PRFileInfo64 *info) {
164 UNIMPLEMENTED;
165 return PR_FAILURE;
166 }
168 static int32_t TransportLayerWritev(PRFileDesc *f, const PRIOVec *iov,
169 int32_t iov_size, PRIntervalTime to) {
170 UNIMPLEMENTED;
171 return -1;
172 }
174 static PRStatus TransportLayerConnect(PRFileDesc *f, const PRNetAddr *addr,
175 PRIntervalTime to) {
176 UNIMPLEMENTED;
177 return PR_FAILURE;
178 }
180 static PRFileDesc *TransportLayerAccept(PRFileDesc *sd, PRNetAddr *addr,
181 PRIntervalTime to) {
182 UNIMPLEMENTED;
183 return nullptr;
184 }
186 static PRStatus TransportLayerBind(PRFileDesc *f, const PRNetAddr *addr) {
187 UNIMPLEMENTED;
188 return PR_FAILURE;
189 }
191 static PRStatus TransportLayerListen(PRFileDesc *f, int32_t depth) {
192 UNIMPLEMENTED;
193 return PR_FAILURE;
194 }
196 static PRStatus TransportLayerShutdown(PRFileDesc *f, int32_t how) {
197 UNIMPLEMENTED;
198 return PR_FAILURE;
199 }
201 // This function does not support peek.
202 static int32_t TransportLayerRecv(PRFileDesc *f, void *buf, int32_t amount,
203 int32_t flags, PRIntervalTime to) {
204 MOZ_ASSERT(flags == 0);
205 if (flags != 0) {
206 PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
207 return -1;
208 }
210 return TransportLayerRead(f, buf, amount);
211 }
213 // Note: this is always nonblocking and assumes a zero timeout.
214 static int32_t TransportLayerSend(PRFileDesc *f, const void *buf, int32_t amount,
215 int32_t flags, PRIntervalTime to) {
216 int32_t written = TransportLayerWrite(f, buf, amount);
217 return written;
218 }
220 static int32_t TransportLayerRecvfrom(PRFileDesc *f, void *buf, int32_t amount,
221 int32_t flags, PRNetAddr *addr, PRIntervalTime to) {
222 UNIMPLEMENTED;
223 return -1;
224 }
226 static int32_t TransportLayerSendto(PRFileDesc *f, const void *buf, int32_t amount,
227 int32_t flags, const PRNetAddr *addr, PRIntervalTime to) {
228 UNIMPLEMENTED;
229 return -1;
230 }
232 static int16_t TransportLayerPoll(PRFileDesc *f, int16_t in_flags, int16_t *out_flags) {
233 UNIMPLEMENTED;
234 return -1;
235 }
237 static int32_t TransportLayerAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
238 PRNetAddr **raddr,
239 void *buf, int32_t amount, PRIntervalTime t) {
240 UNIMPLEMENTED;
241 return -1;
242 }
244 static int32_t TransportLayerTransmitFile(PRFileDesc *sd, PRFileDesc *f,
245 const void *headers, int32_t hlen,
246 PRTransmitFileFlags flags, PRIntervalTime t) {
247 UNIMPLEMENTED;
248 return -1;
249 }
251 static PRStatus TransportLayerGetpeername(PRFileDesc *f, PRNetAddr *addr) {
252 // TODO: 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;
260 return PR_SUCCESS;
261 }
263 static PRStatus TransportLayerGetsockname(PRFileDesc *f, PRNetAddr *addr) {
264 UNIMPLEMENTED;
265 return PR_FAILURE;
266 }
268 static PRStatus TransportLayerGetsockoption(PRFileDesc *f, 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 }
278 return PR_FAILURE;
279 }
281 // Imitate setting socket options. These are mostly noops.
282 static PRStatus TransportLayerSetsockoption(PRFileDesc *f,
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 }
294 return PR_FAILURE;
295 }
297 static int32_t TransportLayerSendfile(PRFileDesc *out, PRSendFileData *in,
298 PRTransmitFileFlags flags, PRIntervalTime to) {
299 UNIMPLEMENTED;
300 return -1;
301 }
303 static PRStatus TransportLayerConnectContinue(PRFileDesc *f, int16_t flags) {
304 UNIMPLEMENTED;
305 return PR_FAILURE;
306 }
308 static int32_t TransportLayerReserved(PRFileDesc *f) {
309 UNIMPLEMENTED;
310 return -1;
311 }
313 static const struct PRIOMethods TransportLayerMethods = {
314 PR_DESC_LAYERED,
315 TransportLayerClose,
316 TransportLayerRead,
317 TransportLayerWrite,
318 TransportLayerAvailable,
319 TransportLayerAvailable64,
320 TransportLayerSync,
321 TransportLayerSeek,
322 TransportLayerSeek64,
323 TransportLayerFileInfo,
324 TransportLayerFileInfo64,
325 TransportLayerWritev,
326 TransportLayerConnect,
327 TransportLayerAccept,
328 TransportLayerBind,
329 TransportLayerListen,
330 TransportLayerShutdown,
331 TransportLayerRecv,
332 TransportLayerSend,
333 TransportLayerRecvfrom,
334 TransportLayerSendto,
335 TransportLayerPoll,
336 TransportLayerAcceptRead,
337 TransportLayerTransmitFile,
338 TransportLayerGetsockname,
339 TransportLayerGetpeername,
340 TransportLayerReserved,
341 TransportLayerReserved,
342 TransportLayerGetsockoption,
343 TransportLayerSetsockoption,
344 TransportLayerSendfile,
345 TransportLayerConnectContinue,
346 TransportLayerReserved,
347 TransportLayerReserved,
348 TransportLayerReserved,
349 TransportLayerReserved
350 };
352 TransportLayerDtls::~TransportLayerDtls() {
353 if (timer_) {
354 timer_->Cancel();
355 }
356 }
358 nsresult TransportLayerDtls::InitInternal() {
359 // Get the transport service as an event target
360 nsresult rv;
361 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
363 if (NS_FAILED(rv)) {
364 MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service");
365 return rv;
366 }
368 timer_ = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
369 if (NS_FAILED(rv)) {
370 MOZ_MTLOG(ML_ERROR, "Couldn't get timer");
371 return rv;
372 }
374 return NS_OK;
375 }
378 void TransportLayerDtls::WasInserted() {
379 // Connect to the lower layers
380 if (!Setup()) {
381 TL_SET_STATE(TS_ERROR);
382 }
383 }
386 nsresult TransportLayerDtls::SetVerificationAllowAll() {
387 // Defensive programming
388 if (verification_mode_ != VERIFY_UNSET)
389 return NS_ERROR_ALREADY_INITIALIZED;
391 verification_mode_ = VERIFY_ALLOW_ALL;
393 return NS_OK;
394 }
396 nsresult
397 TransportLayerDtls::SetVerificationDigest(const std::string digest_algorithm,
398 const unsigned char *digest_value,
399 size_t digest_len) {
400 // Defensive programming
401 if (verification_mode_ != VERIFY_UNSET &&
402 verification_mode_ != VERIFY_DIGEST) {
403 return NS_ERROR_ALREADY_INITIALIZED;
404 }
406 // Note that we do not sanity check these values for length.
407 // We merely ensure they will fit into the buffer.
408 // TODO: is there a Data construct we could use?
409 if (digest_len > kMaxDigestLength)
410 return NS_ERROR_INVALID_ARG;
412 digests_.push_back(new VerificationDigest(
413 digest_algorithm, digest_value, digest_len));
415 verification_mode_ = VERIFY_DIGEST;
417 return NS_OK;
418 }
420 // TODO: make sure this is called from STS. Otherwise
421 // we have thread safety issues
422 bool TransportLayerDtls::Setup() {
423 CheckThread();
424 SECStatus rv;
426 if (!downward_) {
427 MOZ_MTLOG(ML_ERROR, "DTLS layer with nothing below. This is useless");
428 return false;
429 }
430 nspr_io_adapter_ = new TransportLayerNSPRAdapter(downward_);
432 if (!identity_) {
433 MOZ_MTLOG(ML_ERROR, "Can't start DTLS without an identity");
434 return false;
435 }
437 if (verification_mode_ == VERIFY_UNSET) {
438 MOZ_MTLOG(ML_ERROR,
439 "Can't start DTLS without specifying a verification mode");
440 return false;
441 }
443 if (transport_layer_identity == PR_INVALID_IO_LAYER) {
444 transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter");
445 }
447 ScopedPRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity,
448 &TransportLayerMethods));
449 MOZ_ASSERT(pr_fd != nullptr);
450 if (!pr_fd)
451 return false;
452 pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get());
454 ScopedPRFileDesc ssl_fd;
455 if (mode_ == DGRAM) {
456 ssl_fd = DTLS_ImportFD(nullptr, pr_fd);
457 } else {
458 ssl_fd = SSL_ImportFD(nullptr, pr_fd);
459 }
461 MOZ_ASSERT(ssl_fd != nullptr); // This should never happen
462 if (!ssl_fd) {
463 return false;
464 }
466 pr_fd.forget(); // ownership transfered to ssl_fd;
468 if (role_ == CLIENT) {
469 MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as client");
470 rv = SSL_GetClientAuthDataHook(ssl_fd, GetClientAuthDataHook,
471 this);
472 if (rv != SECSuccess) {
473 MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
474 return false;
475 }
476 } else {
477 MOZ_MTLOG(ML_DEBUG, "Setting up DTLS as server");
478 // Server side
479 rv = SSL_ConfigSecureServer(ssl_fd, identity_->cert(),
480 identity_->privkey(),
481 kt_rsa);
482 if (rv != SECSuccess) {
483 MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
484 return false;
485 }
487 // Insist on a certificate from the client
488 rv = SSL_OptionSet(ssl_fd, SSL_REQUEST_CERTIFICATE, PR_TRUE);
489 if (rv != SECSuccess) {
490 MOZ_MTLOG(ML_ERROR, "Couldn't request certificate");
491 return false;
492 }
494 rv = SSL_OptionSet(ssl_fd, SSL_REQUIRE_CERTIFICATE, PR_TRUE);
495 if (rv != SECSuccess) {
496 MOZ_MTLOG(ML_ERROR, "Couldn't require certificate");
497 return false;
498 }
499 }
501 // Require TLS 1.1. Perhaps some day in the future we will allow
502 // TLS 1.0 for stream modes.
503 SSLVersionRange version_range = {
504 SSL_LIBRARY_VERSION_TLS_1_1,
505 SSL_LIBRARY_VERSION_TLS_1_1
506 };
508 rv = SSL_VersionRangeSet(ssl_fd, &version_range);
509 if (rv != SECSuccess) {
510 MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3");
511 return false;
512 }
514 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
515 if (rv != SECSuccess) {
516 MOZ_MTLOG(ML_ERROR, "Couldn't disable session tickets");
517 return false;
518 }
520 rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE);
521 if (rv != SECSuccess) {
522 MOZ_MTLOG(ML_ERROR, "Couldn't disable session caching");
523 return false;
524 }
526 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_DEFLATE, PR_FALSE);
527 if (rv != SECSuccess) {
528 MOZ_MTLOG(ML_ERROR, "Couldn't disable deflate");
529 return false;
530 }
532 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER);
533 if (rv != SECSuccess) {
534 MOZ_MTLOG(ML_ERROR, "Couldn't disable renegotiation");
535 return false;
536 }
538 rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE);
539 if (rv != SECSuccess) {
540 MOZ_MTLOG(ML_ERROR, "Couldn't disable false start");
541 return false;
542 }
544 rv = SSL_OptionSet(ssl_fd, SSL_NO_LOCKS, PR_TRUE);
545 if (rv != SECSuccess) {
546 MOZ_MTLOG(ML_ERROR, "Couldn't disable locks");
547 return false;
548 }
550 // Set the SRTP ciphers
551 if (srtp_ciphers_.size()) {
552 // Note: std::vector is guaranteed to contiguous
553 rv = SSL_SetSRTPCiphers(ssl_fd, &srtp_ciphers_[0],
554 srtp_ciphers_.size());
556 if (rv != SECSuccess) {
557 MOZ_MTLOG(ML_ERROR, "Couldn't set SRTP cipher suite");
558 return false;
559 }
560 }
562 // Certificate validation
563 rv = SSL_AuthCertificateHook(ssl_fd, AuthCertificateHook,
564 reinterpret_cast<void *>(this));
565 if (rv != SECSuccess) {
566 MOZ_MTLOG(ML_ERROR, "Couldn't set certificate validation hook");
567 return false;
568 }
570 // Now start the handshake
571 rv = SSL_ResetHandshake(ssl_fd, role_ == SERVER ? PR_TRUE : PR_FALSE);
572 if (rv != SECSuccess) {
573 MOZ_MTLOG(ML_ERROR, "Couldn't reset handshake");
574 return false;
575 }
576 ssl_fd_ = ssl_fd.forget();
578 // Finally, get ready to receive data
579 downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange);
580 downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived);
582 if (downward_->state() == TS_OPEN) {
583 Handshake();
584 }
586 return true;
587 }
590 void TransportLayerDtls::StateChange(TransportLayer *layer, State state) {
591 if (state <= state_) {
592 MOZ_MTLOG(ML_ERROR, "Lower layer state is going backwards from ours");
593 TL_SET_STATE(TS_ERROR);
594 return;
595 }
597 switch (state) {
598 case TS_NONE:
599 MOZ_ASSERT(false); // Can't happen
600 break;
602 case TS_INIT:
603 MOZ_MTLOG(ML_ERROR,
604 LAYER_INFO << "State change of lower layer to INIT forbidden");
605 TL_SET_STATE(TS_ERROR);
606 break;
608 case TS_CONNECTING:
609 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower lower is connecting.");
610 break;
612 case TS_OPEN:
613 MOZ_MTLOG(ML_ERROR,
614 LAYER_INFO << "Lower lower is now open; starting TLS");
615 Handshake();
616 break;
618 case TS_CLOSED:
619 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower lower is now closed");
620 TL_SET_STATE(TS_CLOSED);
621 break;
623 case TS_ERROR:
624 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower lower experienced an error");
625 TL_SET_STATE(TS_ERROR);
626 break;
627 }
628 }
630 void TransportLayerDtls::Handshake() {
631 TL_SET_STATE(TS_CONNECTING);
633 // Clear the retransmit timer
634 timer_->Cancel();
636 SECStatus rv = SSL_ForceHandshake(ssl_fd_);
638 if (rv == SECSuccess) {
639 MOZ_MTLOG(ML_NOTICE,
640 LAYER_INFO << "****** SSL handshake completed ******");
641 if (!cert_ok_) {
642 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Certificate check never occurred");
643 TL_SET_STATE(TS_ERROR);
644 return;
645 }
646 TL_SET_STATE(TS_OPEN);
647 } else {
648 int32_t err = PR_GetError();
649 switch(err) {
650 case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
651 if (mode_ != DGRAM) {
652 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Malformed TLS message");
653 TL_SET_STATE(TS_ERROR);
654 } else {
655 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Malformed DTLS message; ignoring");
656 }
657 // Fall through
658 case PR_WOULD_BLOCK_ERROR:
659 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Would have blocked");
660 if (mode_ == DGRAM) {
661 PRIntervalTime timeout;
662 rv = DTLS_GetHandshakeTimeout(ssl_fd_, &timeout);
663 if (rv == SECSuccess) {
664 uint32_t timeout_ms = PR_IntervalToMilliseconds(timeout);
666 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Setting DTLS timeout to " <<
667 timeout_ms);
668 timer_->SetTarget(target_);
669 timer_->InitWithFuncCallback(TimerCallback,
670 this, timeout_ms,
671 nsITimer::TYPE_ONE_SHOT);
672 }
673 }
674 break;
675 default:
676 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "SSL handshake error "<< err);
677 TL_SET_STATE(TS_ERROR);
678 break;
679 }
680 }
681 }
683 void TransportLayerDtls::PacketReceived(TransportLayer* layer,
684 const unsigned char *data,
685 size_t len) {
686 CheckThread();
687 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << len << ")");
689 if (state_ != TS_CONNECTING && state_ != TS_OPEN) {
690 MOZ_MTLOG(ML_DEBUG,
691 LAYER_INFO << "Discarding packet in inappropriate state");
692 return;
693 }
695 nspr_io_adapter_->PacketReceived(data, len);
697 // If we're still connecting, try to handshake
698 if (state_ == TS_CONNECTING) {
699 Handshake();
700 }
702 // Now try a recv if we're open, since there might be data left
703 if (state_ == TS_OPEN) {
704 unsigned char buf[2000];
706 int32_t rv = PR_Recv(ssl_fd_, buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
707 if (rv > 0) {
708 // We have data
709 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS");
710 SignalPacketReceived(this, buf, rv);
711 } else if (rv == 0) {
712 TL_SET_STATE(TS_CLOSED);
713 } else {
714 int32_t err = PR_GetError();
716 if (err == PR_WOULD_BLOCK_ERROR) {
717 // This gets ignored
718 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Would have blocked");
719 } else {
720 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err);
721 TL_SET_STATE(TS_ERROR);
722 }
723 }
724 }
725 }
727 TransportResult TransportLayerDtls::SendPacket(const unsigned char *data,
728 size_t len) {
729 CheckThread();
730 if (state_ != TS_OPEN) {
731 MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Can't call SendPacket() in state "
732 << state_);
733 return TE_ERROR;
734 }
736 int32_t rv = PR_Send(ssl_fd_, data, len, 0, PR_INTERVAL_NO_WAIT);
738 if (rv > 0) {
739 // We have data
740 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << rv << " bytes to SSL Layer");
741 return rv;
742 }
744 if (rv == 0) {
745 TL_SET_STATE(TS_CLOSED);
746 return 0;
747 }
749 int32_t err = PR_GetError();
751 if (err == PR_WOULD_BLOCK_ERROR) {
752 // This gets ignored
753 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Would have blocked");
754 return TE_WOULDBLOCK;
755 }
757 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err);
758 TL_SET_STATE(TS_ERROR);
759 return TE_ERROR;
760 }
762 SECStatus TransportLayerDtls::GetClientAuthDataHook(void *arg, PRFileDesc *fd,
763 CERTDistNames *caNames,
764 CERTCertificate **pRetCert,
765 SECKEYPrivateKey **pRetKey) {
766 MOZ_MTLOG(ML_DEBUG, "Server requested client auth");
768 TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg);
769 stream->CheckThread();
771 if (!stream->identity_) {
772 MOZ_MTLOG(ML_ERROR, "No identity available");
773 PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);
774 return SECFailure;
775 }
777 *pRetCert = CERT_DupCertificate(stream->identity_->cert());
778 if (!*pRetCert) {
779 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
780 return SECFailure;
781 }
783 *pRetKey = SECKEY_CopyPrivateKey(stream->identity_->privkey());
784 if (!*pRetKey) {
785 CERT_DestroyCertificate(*pRetCert);
786 *pRetCert = nullptr;
787 PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
788 return SECFailure;
789 }
791 return SECSuccess;
792 }
794 nsresult TransportLayerDtls::SetSrtpCiphers(std::vector<uint16_t> ciphers) {
795 // TODO: We should check these
796 srtp_ciphers_ = ciphers;
798 return NS_OK;
799 }
801 nsresult TransportLayerDtls::GetSrtpCipher(uint16_t *cipher) {
802 CheckThread();
803 SECStatus rv = SSL_GetSRTPCipher(ssl_fd_, cipher);
804 if (rv != SECSuccess) {
805 MOZ_MTLOG(ML_DEBUG, "No SRTP cipher negotiated");
806 return NS_ERROR_FAILURE;
807 }
809 return NS_OK;
810 }
812 nsresult TransportLayerDtls::ExportKeyingMaterial(const std::string& label,
813 bool use_context,
814 const std::string& context,
815 unsigned char *out,
816 unsigned int outlen) {
817 CheckThread();
818 SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_,
819 label.c_str(),
820 label.size(),
821 use_context,
822 reinterpret_cast<const unsigned char *>(
823 context.c_str()),
824 context.size(),
825 out,
826 outlen);
827 if (rv != SECSuccess) {
828 MOZ_MTLOG(ML_ERROR, "Couldn't export SSL keying material");
829 return NS_ERROR_FAILURE;
830 }
832 return NS_OK;
833 }
835 SECStatus TransportLayerDtls::AuthCertificateHook(void *arg,
836 PRFileDesc *fd,
837 PRBool checksig,
838 PRBool isServer) {
839 TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg);
840 stream->CheckThread();
841 return stream->AuthCertificateHook(fd, checksig, isServer);
842 }
844 SECStatus
845 TransportLayerDtls::CheckDigest(const RefPtr<VerificationDigest>&
846 digest,
847 CERTCertificate *peer_cert) {
848 unsigned char computed_digest[kMaxDigestLength];
849 size_t computed_digest_len;
851 MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Checking digest, algorithm="
852 << digest->algorithm_);
853 nsresult res =
854 DtlsIdentity::ComputeFingerprint(peer_cert,
855 digest->algorithm_,
856 computed_digest,
857 sizeof(computed_digest),
858 &computed_digest_len);
859 if (NS_FAILED(res)) {
860 MOZ_MTLOG(ML_ERROR, "Could not compute peer fingerprint for digest " <<
861 digest->algorithm_);
862 // Go to end
863 PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
864 return SECFailure;
865 }
867 if (computed_digest_len != digest->len_) {
868 MOZ_MTLOG(ML_ERROR, "Digest is wrong length " << digest->len_ <<
869 " should be " << computed_digest_len << " for algorithm " <<
870 digest->algorithm_);
871 PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
872 return SECFailure;
873 }
875 if (memcmp(digest->value_, computed_digest, computed_digest_len) != 0) {
876 MOZ_MTLOG(ML_ERROR, "Digest does not match");
877 PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
878 return SECFailure;
879 }
881 return SECSuccess;
882 }
885 SECStatus TransportLayerDtls::AuthCertificateHook(PRFileDesc *fd,
886 PRBool checksig,
887 PRBool isServer) {
888 CheckThread();
889 ScopedCERTCertificate peer_cert;
890 peer_cert = SSL_PeerCertificate(fd);
893 // We are not set up to take this being called multiple
894 // times. Change this if we ever add renegotiation.
895 MOZ_ASSERT(!auth_hook_called_);
896 if (auth_hook_called_) {
897 PR_SetError(PR_UNKNOWN_ERROR, 0);
898 return SECFailure;
899 }
900 auth_hook_called_ = true;
902 MOZ_ASSERT(verification_mode_ != VERIFY_UNSET);
903 MOZ_ASSERT(peer_cert_ == nullptr);
905 switch (verification_mode_) {
906 case VERIFY_UNSET:
907 // Break out to error exit
908 PR_SetError(PR_UNKNOWN_ERROR, 0);
909 break;
911 case VERIFY_ALLOW_ALL:
912 peer_cert_ = peer_cert.forget();
913 cert_ok_ = true;
914 return SECSuccess;
916 case VERIFY_DIGEST:
917 {
918 MOZ_ASSERT(digests_.size() != 0);
919 // Check all the provided digests
921 // Checking functions call PR_SetError()
922 SECStatus rv = SECFailure;
923 for (size_t i = 0; i < digests_.size(); i++) {
924 RefPtr<VerificationDigest> digest = digests_[i];
925 rv = CheckDigest(digest, peer_cert);
927 if (rv != SECSuccess)
928 break;
929 }
931 if (rv == SECSuccess) {
932 // Matches all digests, we are good to go
933 cert_ok_ = true;
934 peer_cert = peer_cert.forget();
935 return SECSuccess;
936 }
937 }
938 break;
939 default:
940 MOZ_CRASH(); // Can't happen
941 }
943 return SECFailure;
944 }
946 void TransportLayerDtls::TimerCallback(nsITimer *timer, void *arg) {
947 TransportLayerDtls *dtls = reinterpret_cast<TransportLayerDtls *>(arg);
949 MOZ_MTLOG(ML_DEBUG, "DTLS timer expired");
951 dtls->Handshake();
952 }
954 } // close namespace