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
|