media/mtransport/transportlayerdtls.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

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

mercurial