media/mtransport/transportlayerdtls.cpp

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

mercurial