LCOV - code coverage report
Current view: top level - media/mtransport - transportlayerdtls.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 582 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 63 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       6             : 
       7             : // Original author: ekr@rtfm.com
       8             : 
       9             : #include "transportlayerdtls.h"
      10             : 
      11             : #include <algorithm>
      12             : #include <queue>
      13             : #include <sstream>
      14             : 
      15             : #include "dtlsidentity.h"
      16             : #include "keyhi.h"
      17             : #include "logging.h"
      18             : #include "mozilla/Move.h"
      19             : #include "mozilla/Telemetry.h"
      20             : #include "mozilla/UniquePtr.h"
      21             : #include "mozilla/Unused.h"
      22             : #include "nsCOMPtr.h"
      23             : #include "nsComponentManagerUtils.h"
      24             : #include "nsComponentManagerUtils.h"
      25             : #include "nsIEventTarget.h"
      26             : #include "nsNetCID.h"
      27             : #include "nsServiceManagerUtils.h"
      28             : #include "ssl.h"
      29             : #include "sslerr.h"
      30             : #include "sslproto.h"
      31             : #include "transportflow.h"
      32             : 
      33             : 
      34             : namespace mozilla {
      35             : 
      36           0 : MOZ_MTLOG_MODULE("mtransport")
      37             : 
      38             : static PRDescIdentity transport_layer_identity = PR_INVALID_IO_LAYER;
      39             : 
      40             : // TODO: Implement a mode for this where
      41             : // the channel is not ready until confirmed externally
      42             : // (e.g., after cert check).
      43             : 
      44             : #define UNIMPLEMENTED                                           \
      45             :   MOZ_MTLOG(ML_ERROR,                                           \
      46             :        "Call to unimplemented function "<< __FUNCTION__);       \
      47             :   MOZ_ASSERT(false);                                            \
      48             :   PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0)
      49             : 
      50             : #define MAX_ALPN_LENGTH 255
      51             : 
      52             : // We need to adapt the NSPR/libssl model to the TransportFlow model.
      53             : // The former wants pull semantics and TransportFlow wants push.
      54             : //
      55             : // - A TransportLayerDtls assumes it is sitting on top of another
      56             : //   TransportLayer, which means that events come in asynchronously.
      57             : // - NSS (libssl) wants to sit on top of a PRFileDesc and poll.
      58             : // - The TransportLayerNSPRAdapter is a PRFileDesc containing a
      59             : //   FIFO.
      60             : // - When TransportLayerDtls.PacketReceived() is called, we insert
      61             : //   the packets in the FIFO and then do a PR_Recv() on the NSS
      62             : //   PRFileDesc, which eventually reads off the FIFO.
      63             : //
      64             : // All of this stuff is assumed to happen solely in a single thread
      65             : // (generally the SocketTransportService thread)
      66           0 : struct Packet {
      67           0 :   Packet() : data_(nullptr), len_(0) {}
      68             : 
      69           0 :   void Assign(const void *data, int32_t len) {
      70           0 :     data_.reset(new uint8_t[len]);
      71           0 :     memcpy(data_.get(), data, len);
      72           0 :     len_ = len;
      73           0 :   }
      74             : 
      75             :   UniquePtr<uint8_t[]> data_;
      76             :   int32_t len_;
      77             : };
      78             : 
      79           0 : void TransportLayerNSPRAdapter::PacketReceived(const void *data, int32_t len) {
      80           0 :   if (enabled_) {
      81           0 :     input_.push(new Packet());
      82           0 :     input_.back()->Assign(data, len);
      83             :   }
      84           0 : }
      85             : 
      86           0 : int32_t TransportLayerNSPRAdapter::Recv(void *buf, int32_t buflen) {
      87           0 :   if (input_.empty()) {
      88           0 :     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
      89           0 :     return -1;
      90             :   }
      91             : 
      92           0 :   Packet* front = input_.front();
      93           0 :   if (buflen < front->len_) {
      94           0 :     MOZ_ASSERT(false, "Not enough buffer space to receive into");
      95             :     PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
      96             :     return -1;
      97             :   }
      98             : 
      99           0 :   int32_t count = front->len_;
     100           0 :   memcpy(buf, front->data_.get(), count);
     101             : 
     102           0 :   input_.pop();
     103           0 :   delete front;
     104             : 
     105           0 :   return count;
     106             : }
     107             : 
     108           0 : int32_t TransportLayerNSPRAdapter::Write(const void *buf, int32_t length) {
     109           0 :   if (!enabled_) {
     110           0 :     MOZ_MTLOG(ML_WARNING, "Writing to disabled transport layer");
     111           0 :     return -1;
     112             :   }
     113             : 
     114           0 :   TransportResult r = output_->SendPacket(
     115           0 :       static_cast<const unsigned char *>(buf), length);
     116           0 :   if (r >= 0) {
     117           0 :     return r;
     118             :   }
     119             : 
     120           0 :   if (r == TE_WOULDBLOCK) {
     121           0 :     PR_SetError(PR_WOULD_BLOCK_ERROR, 0);
     122             :   } else {
     123           0 :     PR_SetError(PR_IO_ERROR, 0);
     124             :   }
     125             : 
     126           0 :   return -1;
     127             : }
     128             : 
     129             : 
     130             : // Implementation of NSPR methods
     131           0 : static PRStatus TransportLayerClose(PRFileDesc *f) {
     132           0 :   f->dtor(f);
     133           0 :   return PR_SUCCESS;
     134             : }
     135             : 
     136           0 : static int32_t TransportLayerRead(PRFileDesc *f, void *buf, int32_t length) {
     137           0 :   UNIMPLEMENTED;
     138             :   return -1;
     139             : }
     140             : 
     141           0 : static int32_t TransportLayerWrite(PRFileDesc *f, const void *buf, int32_t length) {
     142           0 :   TransportLayerNSPRAdapter *io = reinterpret_cast<TransportLayerNSPRAdapter *>(f->secret);
     143           0 :   return io->Write(buf, length);
     144             : }
     145             : 
     146           0 : static int32_t TransportLayerAvailable(PRFileDesc *f) {
     147           0 :   UNIMPLEMENTED;
     148             :   return -1;
     149             : }
     150             : 
     151           0 : int64_t TransportLayerAvailable64(PRFileDesc *f) {
     152           0 :   UNIMPLEMENTED;
     153             :   return -1;
     154             : }
     155             : 
     156           0 : static PRStatus TransportLayerSync(PRFileDesc *f) {
     157           0 :   UNIMPLEMENTED;
     158             :   return PR_FAILURE;
     159             : }
     160             : 
     161           0 : static int32_t TransportLayerSeek(PRFileDesc *f, int32_t offset,
     162             :                                   PRSeekWhence how) {
     163           0 :   UNIMPLEMENTED;
     164             :   return -1;
     165             : }
     166             : 
     167           0 : static int64_t TransportLayerSeek64(PRFileDesc *f, int64_t offset,
     168             :                                     PRSeekWhence how) {
     169           0 :   UNIMPLEMENTED;
     170             :   return -1;
     171             : }
     172             : 
     173           0 : static PRStatus TransportLayerFileInfo(PRFileDesc *f, PRFileInfo *info) {
     174           0 :   UNIMPLEMENTED;
     175             :   return PR_FAILURE;
     176             : }
     177             : 
     178           0 : static PRStatus TransportLayerFileInfo64(PRFileDesc *f, PRFileInfo64 *info) {
     179           0 :   UNIMPLEMENTED;
     180             :   return PR_FAILURE;
     181             : }
     182             : 
     183           0 : static int32_t TransportLayerWritev(PRFileDesc *f, const PRIOVec *iov,
     184             :                                     int32_t iov_size, PRIntervalTime to) {
     185           0 :   UNIMPLEMENTED;
     186             :   return -1;
     187             : }
     188             : 
     189           0 : static PRStatus TransportLayerConnect(PRFileDesc *f, const PRNetAddr *addr,
     190             :                                       PRIntervalTime to) {
     191           0 :   UNIMPLEMENTED;
     192             :   return PR_FAILURE;
     193             : }
     194             : 
     195           0 : static PRFileDesc *TransportLayerAccept(PRFileDesc *sd, PRNetAddr *addr,
     196             :                                         PRIntervalTime to) {
     197           0 :   UNIMPLEMENTED;
     198             :   return nullptr;
     199             : }
     200             : 
     201           0 : static PRStatus TransportLayerBind(PRFileDesc *f, const PRNetAddr *addr) {
     202           0 :   UNIMPLEMENTED;
     203             :   return PR_FAILURE;
     204             : }
     205             : 
     206           0 : static PRStatus TransportLayerListen(PRFileDesc *f, int32_t depth) {
     207           0 :   UNIMPLEMENTED;
     208             :   return PR_FAILURE;
     209             : }
     210             : 
     211           0 : static PRStatus TransportLayerShutdown(PRFileDesc *f, int32_t how) {
     212             :   // This is only called from NSS when we are the server and the client refuses
     213             :   // to provide a certificate.  In this case, the handshake is destined for
     214             :   // failure, so we will just let this pass.
     215           0 :   TransportLayerNSPRAdapter *io = reinterpret_cast<TransportLayerNSPRAdapter *>(f->secret);
     216           0 :   io->SetEnabled(false);
     217           0 :   return PR_SUCCESS;
     218             : }
     219             : 
     220             : // This function does not support peek, or waiting until `to`
     221           0 : static int32_t TransportLayerRecv(PRFileDesc *f, void *buf, int32_t buflen,
     222             :                                   int32_t flags, PRIntervalTime to) {
     223           0 :   MOZ_ASSERT(flags == 0);
     224           0 :   if (flags != 0) {
     225           0 :     PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
     226           0 :     return -1;
     227             :   }
     228             : 
     229           0 :   TransportLayerNSPRAdapter *io = reinterpret_cast<TransportLayerNSPRAdapter *>(f->secret);
     230           0 :   return io->Recv(buf, buflen);
     231             : }
     232             : 
     233             : // Note: this is always nonblocking and assumes a zero timeout.
     234           0 : static int32_t TransportLayerSend(PRFileDesc *f, const void *buf, int32_t amount,
     235             :                                   int32_t flags, PRIntervalTime to) {
     236           0 :   int32_t written = TransportLayerWrite(f, buf, amount);
     237           0 :   return written;
     238             : }
     239             : 
     240           0 : static int32_t TransportLayerRecvfrom(PRFileDesc *f, void *buf, int32_t amount,
     241             :                                       int32_t flags, PRNetAddr *addr, PRIntervalTime to) {
     242           0 :   UNIMPLEMENTED;
     243             :   return -1;
     244             : }
     245             : 
     246           0 : static int32_t TransportLayerSendto(PRFileDesc *f, const void *buf, int32_t amount,
     247             :                                     int32_t flags, const PRNetAddr *addr, PRIntervalTime to) {
     248           0 :   UNIMPLEMENTED;
     249             :   return -1;
     250             : }
     251             : 
     252           0 : static int16_t TransportLayerPoll(PRFileDesc *f, int16_t in_flags, int16_t *out_flags) {
     253           0 :   UNIMPLEMENTED;
     254             :   return -1;
     255             : }
     256             : 
     257           0 : static int32_t TransportLayerAcceptRead(PRFileDesc *sd, PRFileDesc **nd,
     258             :                                         PRNetAddr **raddr,
     259             :                                         void *buf, int32_t amount, PRIntervalTime t) {
     260           0 :   UNIMPLEMENTED;
     261             :   return -1;
     262             : }
     263             : 
     264           0 : static int32_t TransportLayerTransmitFile(PRFileDesc *sd, PRFileDesc *f,
     265             :                                           const void *headers, int32_t hlen,
     266             :                                           PRTransmitFileFlags flags, PRIntervalTime t) {
     267           0 :   UNIMPLEMENTED;
     268             :   return -1;
     269             : }
     270             : 
     271           0 : static PRStatus TransportLayerGetpeername(PRFileDesc *f, PRNetAddr *addr) {
     272             :   // TODO: Modify to return unique names for each channel
     273             :   // somehow, as opposed to always the same static address. The current
     274             :   // implementation messes up the session cache, which is why it's off
     275             :   // elsewhere
     276           0 :   addr->inet.family = PR_AF_INET;
     277           0 :   addr->inet.port = 0;
     278           0 :   addr->inet.ip = 0;
     279             : 
     280           0 :   return PR_SUCCESS;
     281             : }
     282             : 
     283           0 : static PRStatus TransportLayerGetsockname(PRFileDesc *f, PRNetAddr *addr) {
     284           0 :   UNIMPLEMENTED;
     285             :   return PR_FAILURE;
     286             : }
     287             : 
     288           0 : static PRStatus TransportLayerGetsockoption(PRFileDesc *f, PRSocketOptionData *opt) {
     289           0 :   switch (opt->option) {
     290             :     case PR_SockOpt_Nonblocking:
     291           0 :       opt->value.non_blocking = PR_TRUE;
     292           0 :       return PR_SUCCESS;
     293             :     default:
     294           0 :       UNIMPLEMENTED;
     295             :       break;
     296             :   }
     297             : 
     298             :   return PR_FAILURE;
     299             : }
     300             : 
     301             : // Imitate setting socket options. These are mostly noops.
     302           0 : static PRStatus TransportLayerSetsockoption(PRFileDesc *f,
     303             :                                             const PRSocketOptionData *opt) {
     304           0 :   switch (opt->option) {
     305             :     case PR_SockOpt_Nonblocking:
     306           0 :       return PR_SUCCESS;
     307             :     case PR_SockOpt_NoDelay:
     308           0 :       return PR_SUCCESS;
     309             :     default:
     310           0 :       UNIMPLEMENTED;
     311             :       break;
     312             :   }
     313             : 
     314             :   return PR_FAILURE;
     315             : }
     316             : 
     317           0 : static int32_t TransportLayerSendfile(PRFileDesc *out, PRSendFileData *in,
     318             :                                       PRTransmitFileFlags flags, PRIntervalTime to) {
     319           0 :   UNIMPLEMENTED;
     320             :   return -1;
     321             : }
     322             : 
     323           0 : static PRStatus TransportLayerConnectContinue(PRFileDesc *f, int16_t flags) {
     324           0 :   UNIMPLEMENTED;
     325             :   return PR_FAILURE;
     326             : }
     327             : 
     328           0 : static int32_t TransportLayerReserved(PRFileDesc *f) {
     329           0 :   UNIMPLEMENTED;
     330             :   return -1;
     331             : }
     332             : 
     333             : static const struct PRIOMethods TransportLayerMethods = {
     334             :   PR_DESC_LAYERED,
     335             :   TransportLayerClose,
     336             :   TransportLayerRead,
     337             :   TransportLayerWrite,
     338             :   TransportLayerAvailable,
     339             :   TransportLayerAvailable64,
     340             :   TransportLayerSync,
     341             :   TransportLayerSeek,
     342             :   TransportLayerSeek64,
     343             :   TransportLayerFileInfo,
     344             :   TransportLayerFileInfo64,
     345             :   TransportLayerWritev,
     346             :   TransportLayerConnect,
     347             :   TransportLayerAccept,
     348             :   TransportLayerBind,
     349             :   TransportLayerListen,
     350             :   TransportLayerShutdown,
     351             :   TransportLayerRecv,
     352             :   TransportLayerSend,
     353             :   TransportLayerRecvfrom,
     354             :   TransportLayerSendto,
     355             :   TransportLayerPoll,
     356             :   TransportLayerAcceptRead,
     357             :   TransportLayerTransmitFile,
     358             :   TransportLayerGetsockname,
     359             :   TransportLayerGetpeername,
     360             :   TransportLayerReserved,
     361             :   TransportLayerReserved,
     362             :   TransportLayerGetsockoption,
     363             :   TransportLayerSetsockoption,
     364             :   TransportLayerSendfile,
     365             :   TransportLayerConnectContinue,
     366             :   TransportLayerReserved,
     367             :   TransportLayerReserved,
     368             :   TransportLayerReserved,
     369             :   TransportLayerReserved
     370             : };
     371             : 
     372           0 : TransportLayerDtls::~TransportLayerDtls() {
     373             :   // Destroy the NSS instance first so it can still send out an alert before
     374             :   // we disable the nspr_io_adapter_.
     375           0 :   ssl_fd_ = nullptr;
     376           0 :   nspr_io_adapter_->SetEnabled(false);
     377           0 :   if (timer_) {
     378           0 :     timer_->Cancel();
     379             :   }
     380           0 : }
     381             : 
     382           0 : nsresult TransportLayerDtls::InitInternal() {
     383             :   // Get the transport service as an event target
     384             :   nsresult rv;
     385           0 :   target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv);
     386             : 
     387           0 :   if (NS_FAILED(rv)) {
     388           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't get socket transport service");
     389           0 :     return rv;
     390             :   }
     391             : 
     392           0 :   timer_ = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
     393           0 :   if (NS_FAILED(rv)) {
     394           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't get timer");
     395           0 :     return rv;
     396             :   }
     397             : 
     398           0 :   return NS_OK;
     399             : }
     400             : 
     401             : 
     402           0 : void TransportLayerDtls::WasInserted() {
     403             :   // Connect to the lower layers
     404           0 :   if (!Setup()) {
     405           0 :     TL_SET_STATE(TS_ERROR);
     406             :   }
     407           0 : }
     408             : 
     409             : 
     410             : // Set the permitted and default ALPN identifiers.
     411             : // The default is here to allow for peers that don't want to negotiate ALPN
     412             : // in that case, the default string will be reported from GetNegotiatedAlpn().
     413             : // Setting the default to the empty string causes the transport layer to fail
     414             : // if ALPN is not negotiated.
     415             : // Note: we only support Unicode strings here, which are encoded into UTF-8,
     416             : // even though ALPN ostensibly allows arbitrary octet sequences.
     417           0 : nsresult TransportLayerDtls::SetAlpn(
     418             :   const std::set<std::string>& alpn_allowed,
     419             :   const std::string& alpn_default) {
     420             : 
     421           0 :   alpn_allowed_ = alpn_allowed;
     422           0 :   alpn_default_ = alpn_default;
     423             : 
     424           0 :   return NS_OK;
     425             : }
     426             : 
     427             : 
     428           0 : nsresult TransportLayerDtls::SetVerificationAllowAll() {
     429             :   // Defensive programming
     430           0 :   if (verification_mode_ != VERIFY_UNSET)
     431           0 :     return NS_ERROR_ALREADY_INITIALIZED;
     432             : 
     433           0 :   verification_mode_ = VERIFY_ALLOW_ALL;
     434             : 
     435           0 :   return NS_OK;
     436             : }
     437             : 
     438             : nsresult
     439           0 : TransportLayerDtls::SetVerificationDigest(const std::string digest_algorithm,
     440             :                                           const unsigned char *digest_value,
     441             :                                           size_t digest_len) {
     442             :   // Defensive programming
     443           0 :   if (verification_mode_ != VERIFY_UNSET &&
     444           0 :       verification_mode_ != VERIFY_DIGEST) {
     445           0 :     return NS_ERROR_ALREADY_INITIALIZED;
     446             :   }
     447             : 
     448             :   // Note that we do not sanity check these values for length.
     449             :   // We merely ensure they will fit into the buffer.
     450             :   // TODO: is there a Data construct we could use?
     451           0 :   if (digest_len > kMaxDigestLength)
     452           0 :     return NS_ERROR_INVALID_ARG;
     453             : 
     454           0 :   digests_.push_back(new VerificationDigest(
     455           0 :       digest_algorithm, digest_value, digest_len));
     456             : 
     457           0 :   verification_mode_ = VERIFY_DIGEST;
     458             : 
     459           0 :   return NS_OK;
     460             : }
     461             : 
     462             : // These are the named groups that we will allow.
     463             : static const SSLNamedGroup NamedGroupPreferences[] = {
     464             :   ssl_grp_ec_curve25519,
     465             :   ssl_grp_ec_secp256r1,
     466             :   ssl_grp_ec_secp384r1,
     467             :   ssl_grp_ffdhe_2048,
     468             :   ssl_grp_ffdhe_3072
     469             : };
     470             : 
     471             : // TODO: make sure this is called from STS. Otherwise
     472             : // we have thread safety issues
     473           0 : bool TransportLayerDtls::Setup() {
     474           0 :   CheckThread();
     475             :   SECStatus rv;
     476             : 
     477           0 :   if (!downward_) {
     478           0 :     MOZ_MTLOG(ML_ERROR, "DTLS layer with nothing below. This is useless");
     479           0 :     return false;
     480             :   }
     481           0 :   nspr_io_adapter_ = MakeUnique<TransportLayerNSPRAdapter>(downward_);
     482             : 
     483           0 :   if (!identity_) {
     484           0 :     MOZ_MTLOG(ML_ERROR, "Can't start DTLS without an identity");
     485           0 :     return false;
     486             :   }
     487             : 
     488           0 :   if (verification_mode_ == VERIFY_UNSET) {
     489           0 :     MOZ_MTLOG(ML_ERROR,
     490             :               "Can't start DTLS without specifying a verification mode");
     491           0 :     return false;
     492             :   }
     493             : 
     494           0 :   if (transport_layer_identity == PR_INVALID_IO_LAYER) {
     495           0 :     transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter");
     496             :   }
     497             : 
     498             :   UniquePRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity,
     499           0 :                                               &TransportLayerMethods));
     500           0 :   MOZ_ASSERT(pr_fd != nullptr);
     501           0 :   if (!pr_fd)
     502           0 :     return false;
     503           0 :   pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get());
     504             : 
     505           0 :   UniquePRFileDesc ssl_fd(DTLS_ImportFD(nullptr, pr_fd.get()));
     506           0 :   MOZ_ASSERT(ssl_fd != nullptr);  // This should never happen
     507           0 :   if (!ssl_fd) {
     508           0 :     return false;
     509             :   }
     510             : 
     511           0 :   Unused << pr_fd.release(); // ownership transfered to ssl_fd;
     512             : 
     513           0 :   if (role_ == CLIENT) {
     514           0 :     MOZ_MTLOG(ML_INFO, "Setting up DTLS as client");
     515           0 :     rv = SSL_GetClientAuthDataHook(ssl_fd.get(), GetClientAuthDataHook,
     516           0 :                                    this);
     517           0 :     if (rv != SECSuccess) {
     518           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
     519           0 :       return false;
     520             :     }
     521             :   } else {
     522           0 :     MOZ_MTLOG(ML_INFO, "Setting up DTLS as server");
     523             :     // Server side
     524           0 :     rv = SSL_ConfigSecureServer(ssl_fd.get(), identity_->cert().get(),
     525           0 :                                 identity_->privkey().get(),
     526           0 :                                 identity_->auth_type());
     527           0 :     if (rv != SECSuccess) {
     528           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't set identity");
     529           0 :       return false;
     530             :     }
     531             : 
     532           0 :     UniqueCERTCertList zero_certs(CERT_NewCertList());
     533           0 :     rv = SSL_SetTrustAnchors(ssl_fd.get(), zero_certs.get());
     534           0 :     if (rv != SECSuccess) {
     535           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't set trust anchors");
     536           0 :       return false;
     537             :     }
     538             : 
     539             :     // Insist on a certificate from the client
     540           0 :     rv = SSL_OptionSet(ssl_fd.get(), SSL_REQUEST_CERTIFICATE, PR_TRUE);
     541           0 :     if (rv != SECSuccess) {
     542           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't request certificate");
     543           0 :       return false;
     544             :     }
     545             : 
     546           0 :     rv = SSL_OptionSet(ssl_fd.get(), SSL_REQUIRE_CERTIFICATE, PR_TRUE);
     547           0 :     if (rv != SECSuccess) {
     548           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't require certificate");
     549           0 :       return false;
     550             :     }
     551             :   }
     552             : 
     553             :   // Require TLS 1.1 or 1.2. Perhaps some day in the future we will allow TLS
     554             :   // 1.0 for stream modes.
     555             :   SSLVersionRange version_range = {
     556             :     SSL_LIBRARY_VERSION_TLS_1_1,
     557             :     SSL_LIBRARY_VERSION_TLS_1_2
     558           0 :   };
     559             : 
     560           0 :   rv = SSL_VersionRangeSet(ssl_fd.get(), &version_range);
     561           0 :   if (rv != SECSuccess) {
     562           0 :     MOZ_MTLOG(ML_ERROR, "Can't disable SSLv3");
     563           0 :     return false;
     564             :   }
     565             : 
     566           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_SESSION_TICKETS, PR_FALSE);
     567           0 :   if (rv != SECSuccess) {
     568           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable session tickets");
     569           0 :     return false;
     570             :   }
     571             : 
     572           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_NO_CACHE, PR_TRUE);
     573           0 :   if (rv != SECSuccess) {
     574           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable session caching");
     575           0 :     return false;
     576             :   }
     577             : 
     578           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_DEFLATE, PR_FALSE);
     579           0 :   if (rv != SECSuccess) {
     580           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable deflate");
     581           0 :     return false;
     582             :   }
     583             : 
     584           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_RENEGOTIATION,
     585           0 :                      SSL_RENEGOTIATE_NEVER);
     586           0 :   if (rv != SECSuccess) {
     587           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable renegotiation");
     588           0 :     return false;
     589             :   }
     590             : 
     591           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_FALSE_START, PR_FALSE);
     592           0 :   if (rv != SECSuccess) {
     593           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable false start");
     594           0 :     return false;
     595             :   }
     596             : 
     597           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_NO_LOCKS, PR_TRUE);
     598           0 :   if (rv != SECSuccess) {
     599           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable locks");
     600           0 :     return false;
     601             :   }
     602             : 
     603           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
     604           0 :   if (rv != SECSuccess) {
     605           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable ECDHE key reuse");
     606           0 :     return false;
     607             :   }
     608             : 
     609           0 :   if (!SetupCipherSuites(ssl_fd)) {
     610           0 :     return false;
     611             :   }
     612             : 
     613           0 :   rv = SSL_NamedGroupConfig(ssl_fd.get(), NamedGroupPreferences,
     614           0 :                             mozilla::ArrayLength(NamedGroupPreferences));
     615           0 :   if (rv != SECSuccess) {
     616           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't set named groups");
     617           0 :     return false;
     618             :   }
     619             : 
     620             :   // Certificate validation
     621           0 :   rv = SSL_AuthCertificateHook(ssl_fd.get(), AuthCertificateHook,
     622           0 :                                reinterpret_cast<void *>(this));
     623           0 :   if (rv != SECSuccess) {
     624           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't set certificate validation hook");
     625           0 :     return false;
     626             :   }
     627             : 
     628           0 :   if (!SetupAlpn(ssl_fd)) {
     629           0 :     return false;
     630             :   }
     631             : 
     632             :   // Now start the handshake
     633           0 :   rv = SSL_ResetHandshake(ssl_fd.get(), role_ == SERVER ? PR_TRUE : PR_FALSE);
     634           0 :   if (rv != SECSuccess) {
     635           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't reset handshake");
     636           0 :     return false;
     637             :   }
     638           0 :   ssl_fd_ = Move(ssl_fd);
     639             : 
     640             :   // Finally, get ready to receive data
     641           0 :   downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange);
     642           0 :   downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived);
     643             : 
     644           0 :   if (downward_->state() == TS_OPEN) {
     645           0 :     TL_SET_STATE(TS_CONNECTING);
     646           0 :     Handshake();
     647             :   }
     648             : 
     649           0 :   return true;
     650             : }
     651             : 
     652           0 : bool TransportLayerDtls::SetupAlpn(UniquePRFileDesc& ssl_fd) const {
     653           0 :   if (alpn_allowed_.empty()) {
     654           0 :     return true;
     655             :   }
     656             : 
     657           0 :   SECStatus rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_NPN, PR_FALSE);
     658           0 :   if (rv != SECSuccess) {
     659           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't disable NPN");
     660           0 :     return false;
     661             :   }
     662             : 
     663           0 :   rv = SSL_OptionSet(ssl_fd.get(), SSL_ENABLE_ALPN, PR_TRUE);
     664           0 :   if (rv != SECSuccess) {
     665           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't enable ALPN");
     666           0 :     return false;
     667             :   }
     668             : 
     669             :   unsigned char buf[MAX_ALPN_LENGTH];
     670           0 :   size_t offset = 0;
     671           0 :   for (const auto& tag : alpn_allowed_) {
     672           0 :     if ((offset + 1 + tag.length()) >= sizeof(buf)) {
     673           0 :       MOZ_MTLOG(ML_ERROR, "ALPN too long");
     674           0 :       return false;
     675             :     }
     676           0 :     buf[offset++] = tag.length();
     677           0 :     memcpy(buf + offset, tag.c_str(), tag.length());
     678           0 :     offset += tag.length();
     679             :   }
     680           0 :   rv = SSL_SetNextProtoNego(ssl_fd.get(), buf, offset);
     681           0 :   if (rv != SECSuccess) {
     682           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't set ALPN string");
     683           0 :     return false;
     684             :   }
     685           0 :   return true;
     686             : }
     687             : 
     688             : // Ciphers we need to enable.  These are on by default in standard firefox
     689             : // builds, but can be disabled with prefs and they aren't on in our unit tests
     690             : // since that uses NSS default configuration.
     691             : //
     692             : // Only override prefs to comply with MUST statements in the security-arch doc.
     693             : // Anything outside this list is governed by the usual combination of policy
     694             : // and user preferences.
     695             : static const uint32_t EnabledCiphers[] = {
     696             :   TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
     697             :   TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
     698             : };
     699             : 
     700             : // Disable all NSS suites modes without PFS or with old and rusty ciphersuites.
     701             : // Anything outside this list is governed by the usual combination of policy
     702             : // and user preferences.
     703             : static const uint32_t DisabledCiphers[] = {
     704             :   // Bug 1310061: disable all SHA384 ciphers until fixed
     705             :   TLS_AES_256_GCM_SHA384,
     706             :   TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
     707             :   TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
     708             :   TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
     709             :   TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
     710             :   TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
     711             :   TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,
     712             : 
     713             :   TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
     714             :   TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
     715             :   TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
     716             :   TLS_ECDHE_RSA_WITH_RC4_128_SHA,
     717             : 
     718             :   TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
     719             :   TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
     720             :   TLS_DHE_DSS_WITH_RC4_128_SHA,
     721             : 
     722             :   TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
     723             :   TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
     724             :   TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
     725             :   TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
     726             :   TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
     727             :   TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
     728             :   TLS_ECDH_ECDSA_WITH_RC4_128_SHA,
     729             :   TLS_ECDH_RSA_WITH_RC4_128_SHA,
     730             : 
     731             :   TLS_RSA_WITH_AES_128_GCM_SHA256,
     732             :   TLS_RSA_WITH_AES_256_GCM_SHA384,
     733             :   TLS_RSA_WITH_AES_128_CBC_SHA,
     734             :   TLS_RSA_WITH_AES_128_CBC_SHA256,
     735             :   TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
     736             :   TLS_RSA_WITH_AES_256_CBC_SHA,
     737             :   TLS_RSA_WITH_AES_256_CBC_SHA256,
     738             :   TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
     739             :   TLS_RSA_WITH_SEED_CBC_SHA,
     740             :   TLS_RSA_WITH_3DES_EDE_CBC_SHA,
     741             :   TLS_RSA_WITH_RC4_128_SHA,
     742             :   TLS_RSA_WITH_RC4_128_MD5,
     743             : 
     744             :   TLS_DHE_RSA_WITH_DES_CBC_SHA,
     745             :   TLS_DHE_DSS_WITH_DES_CBC_SHA,
     746             :   TLS_RSA_WITH_DES_CBC_SHA,
     747             : 
     748             :   TLS_ECDHE_ECDSA_WITH_NULL_SHA,
     749             :   TLS_ECDHE_RSA_WITH_NULL_SHA,
     750             :   TLS_ECDH_ECDSA_WITH_NULL_SHA,
     751             :   TLS_ECDH_RSA_WITH_NULL_SHA,
     752             :   TLS_RSA_WITH_NULL_SHA,
     753             :   TLS_RSA_WITH_NULL_SHA256,
     754             :   TLS_RSA_WITH_NULL_MD5,
     755             : };
     756             : 
     757           0 : bool TransportLayerDtls::SetupCipherSuites(UniquePRFileDesc& ssl_fd) const {
     758             :   SECStatus rv;
     759             : 
     760             :   // Set the SRTP ciphers
     761           0 :   if (!srtp_ciphers_.empty()) {
     762             :     // Note: std::vector is guaranteed to contiguous
     763           0 :     rv = SSL_SetSRTPCiphers(ssl_fd.get(), &srtp_ciphers_[0],
     764           0 :                             srtp_ciphers_.size());
     765           0 :     if (rv != SECSuccess) {
     766           0 :       MOZ_MTLOG(ML_ERROR, "Couldn't set SRTP cipher suite");
     767           0 :       return false;
     768             :     }
     769             :   }
     770             : 
     771           0 :   for (const auto& cipher : EnabledCiphers) {
     772           0 :     MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Enabling: " << cipher);
     773           0 :     rv = SSL_CipherPrefSet(ssl_fd.get(), cipher, PR_TRUE);
     774           0 :     if (rv != SECSuccess) {
     775           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO <<
     776             :                 "Unable to enable suite: " << cipher);
     777           0 :       return false;
     778             :     }
     779             :   }
     780             : 
     781           0 :   for (const auto& cipher : DisabledCiphers) {
     782           0 :     MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Disabling: " << cipher);
     783             : 
     784           0 :     PRBool enabled = false;
     785           0 :     rv = SSL_CipherPrefGet(ssl_fd.get(), cipher, &enabled);
     786           0 :     if (rv != SECSuccess) {
     787           0 :       MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
     788             :                 "Unable to check if suite is enabled: " << cipher);
     789           0 :       return false;
     790             :     }
     791           0 :     if (enabled) {
     792           0 :       rv = SSL_CipherPrefSet(ssl_fd.get(), cipher, PR_FALSE);
     793           0 :       if (rv != SECSuccess) {
     794           0 :         MOZ_MTLOG(ML_NOTICE, LAYER_INFO <<
     795             :                   "Unable to disable suite: " << cipher);
     796           0 :         return false;
     797             :       }
     798             :     }
     799             :   }
     800             : 
     801           0 :   return true;
     802             : }
     803             : 
     804           0 : nsresult TransportLayerDtls::GetCipherSuite(uint16_t* cipherSuite) const {
     805           0 :   CheckThread();
     806           0 :   if (!cipherSuite) {
     807           0 :     MOZ_MTLOG(ML_ERROR, LAYER_INFO << "GetCipherSuite passed a nullptr");
     808           0 :     return NS_ERROR_NULL_POINTER;
     809             :   }
     810           0 :   if (state_ != TS_OPEN) {
     811           0 :     return NS_ERROR_NOT_AVAILABLE;
     812             :   }
     813             :   SSLChannelInfo info;
     814           0 :   SECStatus rv = SSL_GetChannelInfo(ssl_fd_.get(), &info, sizeof(info));
     815           0 :   if (rv != SECSuccess) {
     816           0 :     MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "GetCipherSuite can't get channel info");
     817           0 :     return NS_ERROR_FAILURE;
     818             :   }
     819           0 :   *cipherSuite = info.cipherSuite;
     820           0 :   return NS_OK;
     821             : }
     822             : 
     823           0 : void TransportLayerDtls::StateChange(TransportLayer *layer, State state) {
     824           0 :   if (state <= state_) {
     825           0 :     MOZ_MTLOG(ML_ERROR, "Lower layer state is going backwards from ours");
     826           0 :     TL_SET_STATE(TS_ERROR);
     827           0 :     return;
     828             :   }
     829             : 
     830           0 :   switch (state) {
     831             :     case TS_NONE:
     832           0 :       MOZ_ASSERT(false);  // Can't happen
     833             :       break;
     834             : 
     835             :     case TS_INIT:
     836           0 :       MOZ_MTLOG(ML_ERROR,
     837             :                 LAYER_INFO << "State change of lower layer to INIT forbidden");
     838           0 :       TL_SET_STATE(TS_ERROR);
     839           0 :       break;
     840             : 
     841             :     case TS_CONNECTING:
     842           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower layer is connecting.");
     843           0 :       break;
     844             : 
     845             :     case TS_OPEN:
     846           0 :       MOZ_MTLOG(ML_ERROR,
     847             :                 LAYER_INFO << "Lower layer is now open; starting TLS");
     848             :       // Async, since the ICE layer might need to send a STUN response, and we
     849             :       // don't want the handshake to start until that is sent.
     850           0 :       TL_SET_STATE(TS_CONNECTING);
     851           0 :       timer_->Cancel();
     852           0 :       timer_->SetTarget(target_);
     853           0 :       timer_->InitWithNamedFuncCallback(TimerCallback,
     854             :                                         this,
     855             :                                         0,
     856             :                                         nsITimer::TYPE_ONE_SHOT,
     857           0 :                                         "TransportLayerDtls::TimerCallback");
     858           0 :       break;
     859             : 
     860             :     case TS_CLOSED:
     861           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower layer is now closed");
     862           0 :       TL_SET_STATE(TS_CLOSED);
     863           0 :       break;
     864             : 
     865             :     case TS_ERROR:
     866           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Lower layer experienced an error");
     867           0 :       TL_SET_STATE(TS_ERROR);
     868           0 :       break;
     869             :   }
     870             : }
     871             : 
     872           0 : void TransportLayerDtls::Handshake() {
     873             :   // Clear the retransmit timer
     874           0 :   timer_->Cancel();
     875             : 
     876           0 :   MOZ_ASSERT(state_ == TS_CONNECTING);
     877             : 
     878           0 :   SECStatus rv = SSL_ForceHandshake(ssl_fd_.get());
     879             : 
     880           0 :   if (rv == SECSuccess) {
     881           0 :     MOZ_MTLOG(ML_NOTICE,
     882             :               LAYER_INFO << "****** SSL handshake completed ******");
     883           0 :     if (!cert_ok_) {
     884           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Certificate check never occurred");
     885           0 :       TL_SET_STATE(TS_ERROR);
     886           0 :       return;
     887             :     }
     888           0 :     if (!CheckAlpn()) {
     889             :       // Despite connecting, the connection doesn't have a valid ALPN label.
     890             :       // Forcibly close the connection so that the peer isn't left hanging
     891             :       // (assuming the close_notify isn't dropped).
     892           0 :       ssl_fd_ = nullptr;
     893           0 :       TL_SET_STATE(TS_ERROR);
     894           0 :       return;
     895             :     }
     896             : 
     897           0 :     TL_SET_STATE(TS_OPEN);
     898             :   } else {
     899           0 :     int32_t err = PR_GetError();
     900           0 :     switch(err) {
     901             :       case SSL_ERROR_RX_MALFORMED_HANDSHAKE:
     902           0 :         MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Malformed DTLS message; ignoring");
     903             :         // If this were TLS (and not DTLS), this would be fatal, but
     904             :         // here we're required to ignore bad messages, so fall through
     905             :         MOZ_FALLTHROUGH;
     906             :       case PR_WOULD_BLOCK_ERROR:
     907           0 :         MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Handshake would have blocked");
     908             :         PRIntervalTime timeout;
     909           0 :         rv = DTLS_GetHandshakeTimeout(ssl_fd_.get(), &timeout);
     910           0 :         if (rv == SECSuccess) {
     911           0 :           uint32_t timeout_ms = PR_IntervalToMilliseconds(timeout);
     912             : 
     913           0 :           MOZ_MTLOG(ML_DEBUG,
     914             :                     LAYER_INFO << "Setting DTLS timeout to " << timeout_ms);
     915           0 :           timer_->SetTarget(target_);
     916           0 :           timer_->InitWithNamedFuncCallback(TimerCallback,
     917             :                                             this, timeout_ms,
     918             :                                             nsITimer::TYPE_ONE_SHOT,
     919           0 :                                             "TransportLayerDtls::TimerCallback");
     920             :         }
     921           0 :         break;
     922             :       default:
     923           0 :         const char *err_msg = PR_ErrorToName(err);
     924           0 :         MOZ_MTLOG(ML_ERROR, LAYER_INFO << "DTLS handshake error " << err << " ("
     925             :                   << err_msg << ")");
     926           0 :         TL_SET_STATE(TS_ERROR);
     927           0 :         break;
     928             :     }
     929             :   }
     930             : }
     931             : 
     932             : // Checks if ALPN was negotiated correctly and returns false if it wasn't.
     933             : // After this returns successfully, alpn_ will be set to the negotiated
     934             : // protocol.
     935           0 : bool TransportLayerDtls::CheckAlpn() {
     936           0 :   if (alpn_allowed_.empty()) {
     937           0 :     return true;
     938             :   }
     939             : 
     940             :   SSLNextProtoState alpnState;
     941             :   char chosenAlpn[MAX_ALPN_LENGTH];
     942             :   unsigned int chosenAlpnLen;
     943           0 :   SECStatus rv = SSL_GetNextProto(ssl_fd_.get(), &alpnState,
     944             :                                   reinterpret_cast<unsigned char*>(chosenAlpn),
     945           0 :                                   &chosenAlpnLen, sizeof(chosenAlpn));
     946           0 :   if (rv != SECSuccess) {
     947           0 :     MOZ_MTLOG(ML_ERROR, LAYER_INFO << "ALPN error");
     948           0 :     return false;
     949             :   }
     950           0 :   switch (alpnState) {
     951             :     case SSL_NEXT_PROTO_SELECTED:
     952             :     case SSL_NEXT_PROTO_NEGOTIATED:
     953           0 :       break; // OK
     954             : 
     955             :     case SSL_NEXT_PROTO_NO_SUPPORT:
     956           0 :       MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "ALPN not negotiated, "
     957             :                 << (alpn_default_.empty() ? "failing" : "selecting default"));
     958           0 :       alpn_ = alpn_default_;
     959           0 :       return !alpn_.empty();
     960             : 
     961             :     case SSL_NEXT_PROTO_NO_OVERLAP:
     962             :       // This only happens if there is a custom NPN/ALPN callback installed and
     963             :       // that callback doesn't properly handle ALPN.
     964           0 :       MOZ_MTLOG(ML_ERROR, LAYER_INFO << "error in ALPN selection callback");
     965           0 :       return false;
     966             : 
     967             :     case SSL_NEXT_PROTO_EARLY_VALUE:
     968           0 :       MOZ_CRASH("Unexpected 0-RTT ALPN value");
     969             :       return false;
     970             :   }
     971             : 
     972             :   // Warning: NSS won't null terminate the ALPN string for us.
     973           0 :   std::string chosen(chosenAlpn, chosenAlpnLen);
     974           0 :   MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Selected ALPN string: " << chosen);
     975           0 :   if (alpn_allowed_.find(chosen) == alpn_allowed_.end()) {
     976             :     // Maybe our peer chose a protocol we didn't offer (when we are client), or
     977             :     // something is seriously wrong.
     978           0 :     std::ostringstream ss;
     979           0 :     for (auto i = alpn_allowed_.begin(); i != alpn_allowed_.end(); ++i) {
     980           0 :       ss << (i == alpn_allowed_.begin() ? " '" : ", '") << *i << "'";
     981             :     }
     982           0 :     MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Bad ALPN string: '" << chosen
     983             :               << "'; permitted:" << ss.str());
     984           0 :     return false;
     985             :   }
     986           0 :   alpn_ = chosen;
     987           0 :   return true;
     988             : }
     989             : 
     990             : 
     991           0 : void TransportLayerDtls::PacketReceived(TransportLayer* layer,
     992             :                                         const unsigned char *data,
     993             :                                         size_t len) {
     994           0 :   CheckThread();
     995           0 :   MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "PacketReceived(" << len << ")");
     996             : 
     997           0 :   if (state_ != TS_CONNECTING && state_ != TS_OPEN) {
     998           0 :     MOZ_MTLOG(ML_DEBUG,
     999             :               LAYER_INFO << "Discarding packet in inappropriate state");
    1000           0 :     return;
    1001             :   }
    1002             : 
    1003             :   // not DTLS per RFC 7983
    1004           0 :   if (data[0] < 20 || data[0] > 63) {
    1005           0 :     return;
    1006             :   }
    1007             : 
    1008           0 :   nspr_io_adapter_->PacketReceived(data, len);
    1009             : 
    1010             :   // If we're still connecting, try to handshake
    1011           0 :   if (state_ == TS_CONNECTING) {
    1012           0 :     Handshake();
    1013             :   }
    1014             : 
    1015             :   // Now try a recv if we're open, since there might be data left
    1016           0 :   if (state_ == TS_OPEN) {
    1017             :     // nICEr uses a 9216 bytes buffer to allow support for jumbo frames
    1018             :     unsigned char buf[9216];
    1019             :     int32_t rv;
    1020             :     // One packet might contain several DTLS packets
    1021           0 :     do {
    1022           0 :       rv = PR_Recv(ssl_fd_.get(), buf, sizeof(buf), 0, PR_INTERVAL_NO_WAIT);
    1023           0 :       if (rv > 0) {
    1024             :         // We have data
    1025           0 :         MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Read " << rv << " bytes from NSS");
    1026           0 :         SignalPacketReceived(this, buf, rv);
    1027           0 :       } else if (rv == 0) {
    1028           0 :         TL_SET_STATE(TS_CLOSED);
    1029             :       } else {
    1030           0 :         int32_t err = PR_GetError();
    1031             : 
    1032           0 :         if (err == PR_WOULD_BLOCK_ERROR) {
    1033             :           // This gets ignored
    1034           0 :           MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Receive would have blocked");
    1035             :         } else {
    1036           0 :           MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err);
    1037           0 :           TL_SET_STATE(TS_ERROR);
    1038             :         }
    1039             :       }
    1040           0 :     } while (rv > 0);
    1041             :   }
    1042             : }
    1043             : 
    1044           0 : void TransportLayerDtls::SetState(State state,
    1045             :                                   const char *file,
    1046             :                                   unsigned line) {
    1047           0 :   if (state > state_) {
    1048           0 :     switch (state) {
    1049             :       case TS_NONE:
    1050             :       case TS_INIT:
    1051           0 :         MOZ_ASSERT(false);
    1052             :         break;
    1053             :       case TS_CONNECTING:
    1054           0 :         handshake_started_ = TimeStamp::Now();
    1055           0 :         break;
    1056             :       case TS_OPEN:
    1057             :       case TS_CLOSED:
    1058             :       case TS_ERROR:
    1059           0 :         timer_->Cancel();
    1060           0 :         if (state_ == TS_CONNECTING) {
    1061           0 :           RecordHandshakeCompletionTelemetry(state);
    1062             :         }
    1063           0 :         break;
    1064             :     }
    1065             :   } else {
    1066           0 :     MOZ_ASSERT(false, "Invalid state transition");
    1067             :   }
    1068             : 
    1069           0 :   TransportLayer::SetState(state, file, line);
    1070           0 : }
    1071             : 
    1072           0 : TransportResult TransportLayerDtls::SendPacket(const unsigned char *data,
    1073             :                                                size_t len) {
    1074           0 :   CheckThread();
    1075           0 :   if (state_ != TS_OPEN) {
    1076           0 :     MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Can't call SendPacket() in state "
    1077             :               << state_);
    1078           0 :     return TE_ERROR;
    1079             :   }
    1080             : 
    1081           0 :   int32_t rv = PR_Send(ssl_fd_.get(), data, len, 0, PR_INTERVAL_NO_WAIT);
    1082             : 
    1083           0 :   if (rv > 0) {
    1084             :     // We have data
    1085           0 :     MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Wrote " << rv << " bytes to SSL Layer");
    1086           0 :     return rv;
    1087             :   }
    1088             : 
    1089           0 :   if (rv == 0) {
    1090           0 :     TL_SET_STATE(TS_CLOSED);
    1091           0 :     return 0;
    1092             :   }
    1093             : 
    1094           0 :   int32_t err = PR_GetError();
    1095             : 
    1096           0 :   if (err == PR_WOULD_BLOCK_ERROR) {
    1097             :     // This gets ignored
    1098           0 :     MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Send would have blocked");
    1099           0 :     return TE_WOULDBLOCK;
    1100             :   }
    1101             : 
    1102           0 :   MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "NSS Error " << err);
    1103           0 :   TL_SET_STATE(TS_ERROR);
    1104           0 :   return TE_ERROR;
    1105             : }
    1106             : 
    1107           0 : SECStatus TransportLayerDtls::GetClientAuthDataHook(void *arg, PRFileDesc *fd,
    1108             :                                                     CERTDistNames *caNames,
    1109             :                                                     CERTCertificate **pRetCert,
    1110             :                                                     SECKEYPrivateKey **pRetKey) {
    1111           0 :   MOZ_MTLOG(ML_DEBUG, "Server requested client auth");
    1112             : 
    1113           0 :   TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg);
    1114           0 :   stream->CheckThread();
    1115             : 
    1116           0 :   if (!stream->identity_) {
    1117           0 :     MOZ_MTLOG(ML_ERROR, "No identity available");
    1118           0 :     PR_SetError(SSL_ERROR_NO_CERTIFICATE, 0);
    1119           0 :     return SECFailure;
    1120             :   }
    1121             : 
    1122           0 :   *pRetCert = CERT_DupCertificate(stream->identity_->cert().get());
    1123           0 :   if (!*pRetCert) {
    1124           0 :     PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    1125           0 :     return SECFailure;
    1126             :   }
    1127             : 
    1128           0 :   *pRetKey = SECKEY_CopyPrivateKey(stream->identity_->privkey().get());
    1129           0 :   if (!*pRetKey) {
    1130           0 :     CERT_DestroyCertificate(*pRetCert);
    1131           0 :     *pRetCert = nullptr;
    1132           0 :     PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
    1133           0 :     return SECFailure;
    1134             :   }
    1135             : 
    1136           0 :   return SECSuccess;
    1137             : }
    1138             : 
    1139           0 : nsresult TransportLayerDtls::SetSrtpCiphers(std::vector<uint16_t> ciphers) {
    1140             :   // TODO: We should check these
    1141           0 :   srtp_ciphers_ = ciphers;
    1142             : 
    1143           0 :   return NS_OK;
    1144             : }
    1145             : 
    1146           0 : nsresult TransportLayerDtls::GetSrtpCipher(uint16_t *cipher) const {
    1147           0 :   CheckThread();
    1148           0 :   if (state_ != TS_OPEN) {
    1149           0 :     return NS_ERROR_NOT_AVAILABLE;
    1150             :   }
    1151           0 :   SECStatus rv = SSL_GetSRTPCipher(ssl_fd_.get(), cipher);
    1152           0 :   if (rv != SECSuccess) {
    1153           0 :     MOZ_MTLOG(ML_DEBUG, "No SRTP cipher negotiated");
    1154           0 :     return NS_ERROR_FAILURE;
    1155             :   }
    1156             : 
    1157           0 :   return NS_OK;
    1158             : }
    1159             : 
    1160           0 : nsresult TransportLayerDtls::ExportKeyingMaterial(const std::string& label,
    1161             :                                                   bool use_context,
    1162             :                                                   const std::string& context,
    1163             :                                                   unsigned char *out,
    1164             :                                                   unsigned int outlen) {
    1165           0 :   CheckThread();
    1166           0 :   if (state_ != TS_OPEN) {
    1167           0 :     MOZ_ASSERT(false, "Transport must be open for ExportKeyingMaterial");
    1168             :     return NS_ERROR_NOT_AVAILABLE;
    1169             :   }
    1170           0 :   SECStatus rv = SSL_ExportKeyingMaterial(ssl_fd_.get(),
    1171             :                                           label.c_str(),
    1172           0 :                                           label.size(),
    1173             :                                           use_context,
    1174             :                                           reinterpret_cast<const unsigned char *>(
    1175           0 :                                               context.c_str()),
    1176           0 :                                           context.size(),
    1177             :                                           out,
    1178           0 :                                           outlen);
    1179           0 :   if (rv != SECSuccess) {
    1180           0 :     MOZ_MTLOG(ML_ERROR, "Couldn't export SSL keying material");
    1181           0 :     return NS_ERROR_FAILURE;
    1182             :   }
    1183             : 
    1184           0 :   return NS_OK;
    1185             : }
    1186             : 
    1187           0 : SECStatus TransportLayerDtls::AuthCertificateHook(void *arg,
    1188             :                                                   PRFileDesc *fd,
    1189             :                                                   PRBool checksig,
    1190             :                                                   PRBool isServer) {
    1191           0 :   TransportLayerDtls *stream = reinterpret_cast<TransportLayerDtls *>(arg);
    1192           0 :   stream->CheckThread();
    1193           0 :   return stream->AuthCertificateHook(fd, checksig, isServer);
    1194             : }
    1195             : 
    1196             : SECStatus
    1197           0 : TransportLayerDtls::CheckDigest(const RefPtr<VerificationDigest>& digest,
    1198             :                                 UniqueCERTCertificate& peer_cert) const {
    1199             :   unsigned char computed_digest[kMaxDigestLength];
    1200             :   size_t computed_digest_len;
    1201             : 
    1202           0 :   MOZ_MTLOG(ML_DEBUG, LAYER_INFO << "Checking digest, algorithm="
    1203             :             << digest->algorithm_);
    1204             :   nsresult res =
    1205           0 :       DtlsIdentity::ComputeFingerprint(peer_cert,
    1206           0 :                                        digest->algorithm_,
    1207             :                                        computed_digest,
    1208             :                                        sizeof(computed_digest),
    1209           0 :                                        &computed_digest_len);
    1210           0 :   if (NS_FAILED(res)) {
    1211           0 :     MOZ_MTLOG(ML_ERROR, "Could not compute peer fingerprint for digest " <<
    1212             :               digest->algorithm_);
    1213             :     // Go to end
    1214           0 :     PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
    1215           0 :     return SECFailure;
    1216             :   }
    1217             : 
    1218           0 :   if (computed_digest_len != digest->len_) {
    1219           0 :     MOZ_MTLOG(ML_ERROR, "Digest is wrong length " << digest->len_ <<
    1220             :               " should be " << computed_digest_len << " for algorithm " <<
    1221             :               digest->algorithm_);
    1222           0 :     PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
    1223           0 :     return SECFailure;
    1224             :   }
    1225             : 
    1226           0 :   if (memcmp(digest->value_, computed_digest, computed_digest_len) != 0) {
    1227           0 :     MOZ_MTLOG(ML_ERROR, "Digest does not match");
    1228           0 :     PR_SetError(SSL_ERROR_BAD_CERTIFICATE, 0);
    1229           0 :     return SECFailure;
    1230             :   }
    1231             : 
    1232           0 :   return SECSuccess;
    1233             : }
    1234             : 
    1235             : 
    1236           0 : SECStatus TransportLayerDtls::AuthCertificateHook(PRFileDesc *fd,
    1237             :                                                   PRBool checksig,
    1238             :                                                   PRBool isServer) {
    1239           0 :   CheckThread();
    1240           0 :   UniqueCERTCertificate peer_cert(SSL_PeerCertificate(fd));
    1241             : 
    1242             :   // We are not set up to take this being called multiple
    1243             :   // times. Change this if we ever add renegotiation.
    1244           0 :   MOZ_ASSERT(!auth_hook_called_);
    1245           0 :   if (auth_hook_called_) {
    1246           0 :     PR_SetError(PR_UNKNOWN_ERROR, 0);
    1247           0 :     return SECFailure;
    1248             :   }
    1249           0 :   auth_hook_called_ = true;
    1250             : 
    1251           0 :   MOZ_ASSERT(verification_mode_ != VERIFY_UNSET);
    1252             : 
    1253           0 :   switch (verification_mode_) {
    1254             :     case VERIFY_UNSET:
    1255             :       // Break out to error exit
    1256           0 :       PR_SetError(PR_UNKNOWN_ERROR, 0);
    1257           0 :       break;
    1258             : 
    1259             :     case VERIFY_ALLOW_ALL:
    1260           0 :       cert_ok_ = true;
    1261           0 :       return SECSuccess;
    1262             : 
    1263             :     case VERIFY_DIGEST:
    1264             :       {
    1265           0 :         MOZ_ASSERT(digests_.size() != 0);
    1266             :         // Check all the provided digests
    1267             : 
    1268             :         // Checking functions call PR_SetError()
    1269           0 :         SECStatus rv = SECFailure;
    1270           0 :         for (auto digest : digests_) {
    1271           0 :           rv = CheckDigest(digest, peer_cert);
    1272             : 
    1273             :           // Matches a digest, we are good to go
    1274           0 :           if (rv == SECSuccess) {
    1275           0 :             cert_ok_ = true;
    1276           0 :             return SECSuccess;
    1277             :           }
    1278             :         }
    1279             :       }
    1280           0 :       break;
    1281             :     default:
    1282           0 :       MOZ_CRASH();  // Can't happen
    1283             :   }
    1284             : 
    1285           0 :   return SECFailure;
    1286             : }
    1287             : 
    1288           0 : void TransportLayerDtls::TimerCallback(nsITimer *timer, void *arg) {
    1289           0 :   TransportLayerDtls *dtls = reinterpret_cast<TransportLayerDtls *>(arg);
    1290             : 
    1291           0 :   MOZ_MTLOG(ML_DEBUG, "DTLS timer expired");
    1292             : 
    1293           0 :   dtls->Handshake();
    1294           0 : }
    1295             : 
    1296             : void
    1297           0 : TransportLayerDtls::RecordHandshakeCompletionTelemetry(
    1298             :     TransportLayer::State endState) {
    1299           0 :   int32_t delta = (TimeStamp::Now() - handshake_started_).ToMilliseconds();
    1300             : 
    1301           0 :   switch (endState) {
    1302             :     case TransportLayer::State::TS_OPEN:
    1303           0 :       if (role_ == TransportLayerDtls::CLIENT) {
    1304           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_CLIENT_SUCCESS_TIME,
    1305           0 :                               delta);
    1306             :       } else {
    1307           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_SERVER_SUCCESS_TIME,
    1308           0 :                               delta);
    1309             :       }
    1310           0 :       return;
    1311             :     case TransportLayer::State::TS_ERROR:
    1312           0 :       if (role_ == TransportLayerDtls::CLIENT) {
    1313           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_CLIENT_FAILURE_TIME,
    1314           0 :                               delta);
    1315             :       } else {
    1316           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_SERVER_FAILURE_TIME,
    1317           0 :                               delta);
    1318             :       }
    1319           0 :       return;
    1320             :     case TransportLayer::State::TS_CLOSED:
    1321           0 :       if (role_ == TransportLayerDtls::CLIENT) {
    1322           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_CLIENT_ABORT_TIME, delta);
    1323             :       } else {
    1324           0 :         Telemetry::Accumulate(Telemetry::WEBRTC_DTLS_SERVER_ABORT_TIME, delta);
    1325             :       }
    1326           0 :       return;
    1327             :     default:
    1328           0 :       MOZ_ASSERT(false);
    1329             :   }
    1330             : }
    1331             : 
    1332             : }  // close namespace

Generated by: LCOV version 1.13