Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/media/mtransport/transportlayerdtls.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef transportlayerdtls_h__
10
#define transportlayerdtls_h__
11
12
#include <queue>
13
#include <set>
14
15
#include "sigslot.h"
16
17
#include "mozilla/RefPtr.h"
18
#include "mozilla/UniquePtr.h"
19
#include "mozilla/TimeStamp.h"
20
#include "nsCOMPtr.h"
21
#include "nsIEventTarget.h"
22
#include "nsITimer.h"
23
#include "ScopedNSSTypes.h"
24
#include "m_cpp_utils.h"
25
#include "dtlsidentity.h"
26
#include "transportlayer.h"
27
#include "ssl.h"
28
29
namespace mozilla {
30
31
// RFC 5764 (we don't support the NULL cipher)
32
static const uint16_t kDtlsSrtpAes128CmHmacSha1_80 = 0x0001;
33
static const uint16_t kDtlsSrtpAes128CmHmacSha1_32 = 0x0002;
34
// RFC 7714
35
static const uint16_t kDtlsSrtpAeadAes128Gcm =       0x0007;
36
static const uint16_t kDtlsSrtpAeadAes256Gcm =       0x0008;
37
38
struct Packet;
39
40
class TransportLayerNSPRAdapter {
41
 public:
42
  explicit TransportLayerNSPRAdapter(TransportLayer *output) :
43
  output_(output),
44
  input_(),
45
0
  enabled_(true) {}
46
47
  void PacketReceived(MediaPacket& packet);
48
  int32_t Recv(void *buf, int32_t buflen);
49
  int32_t Write(const void *buf, int32_t length);
50
0
  void SetEnabled(bool enabled) { enabled_ = enabled; }
51
52
 private:
53
  DISALLOW_COPY_ASSIGN(TransportLayerNSPRAdapter);
54
55
  TransportLayer *output_;
56
  std::queue<MediaPacket *> input_;
57
  bool enabled_;
58
};
59
60
class TransportLayerDtls final : public TransportLayer {
61
 public:
62
0
  TransportLayerDtls() = default;
63
64
  virtual ~TransportLayerDtls();
65
66
  enum Role { CLIENT, SERVER};
67
  enum Verification { VERIFY_UNSET, VERIFY_ALLOW_ALL, VERIFY_DIGEST};
68
  const static size_t kMaxDigestLength = HASH_LENGTH_MAX;
69
70
  // DTLS-specific operations
71
0
  void SetRole(Role role) { role_ = role;}
72
  Role role() { return role_; }
73
74
0
  void SetIdentity(const RefPtr<DtlsIdentity>& identity) {
75
0
    identity_ = identity;
76
0
  }
77
  nsresult SetAlpn(const std::set<std::string>& allowedAlpn,
78
                   const std::string& alpnDefault);
79
0
  const std::string& GetNegotiatedAlpn() const { return alpn_; }
80
81
  nsresult SetVerificationAllowAll();
82
  nsresult SetVerificationDigest(const std::string digest_algorithm,
83
                                 const unsigned char *digest_value,
84
                                 size_t digest_len);
85
86
  nsresult GetCipherSuite(uint16_t* cipherSuite) const;
87
88
  nsresult SetSrtpCiphers(const std::vector<uint16_t>& ciphers);
89
  nsresult GetSrtpCipher(uint16_t *cipher) const;
90
91
  nsresult ExportKeyingMaterial(const std::string& label,
92
                                bool use_context,
93
                                const std::string& context,
94
                                unsigned char *out,
95
                                unsigned int outlen);
96
97
  // Transport layer overrides.
98
  nsresult InitInternal() override;
99
  void WasInserted() override;
100
  TransportResult SendPacket(MediaPacket& packet) override;
101
102
  // Signals
103
  void StateChange(TransportLayer *layer, State state);
104
  void PacketReceived(TransportLayer* layer, MediaPacket& packet);
105
106
  // For testing use only.  Returns the fd.
107
0
  PRFileDesc* internal_fd() { CheckThread(); return ssl_fd_.get(); }
108
109
  TRANSPORT_LAYER_ID("dtls")
110
111
  protected:
112
  void SetState(State state, const char *file, unsigned line) override;
113
114
  private:
115
  DISALLOW_COPY_ASSIGN(TransportLayerDtls);
116
117
  // A single digest to check
118
  class VerificationDigest {
119
   public:
120
    VerificationDigest(std::string algorithm,
121
0
                       const unsigned char *value, size_t len) {
122
0
      MOZ_ASSERT(len <= sizeof(value_));
123
0
124
0
      algorithm_ = algorithm;
125
0
      memcpy(value_, value, len);
126
0
      len_ = len;
127
0
    }
128
129
    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VerificationDigest)
130
131
    std::string algorithm_;
132
    size_t len_;
133
    unsigned char value_[kMaxDigestLength];
134
135
   private:
136
0
    ~VerificationDigest() {}
137
    DISALLOW_COPY_ASSIGN(VerificationDigest);
138
  };
139
140
141
  bool Setup();
142
  bool SetupCipherSuites(UniquePRFileDesc& ssl_fd);
143
  bool SetupAlpn(UniquePRFileDesc& ssl_fd) const;
144
  void GetDecryptedPackets();
145
  void Handshake();
146
147
  bool CheckAlpn();
148
149
  static SECStatus GetClientAuthDataHook(void *arg, PRFileDesc *fd,
150
                                         CERTDistNames *caNames,
151
                                         CERTCertificate **pRetCert,
152
                                         SECKEYPrivateKey **pRetKey);
153
  static SECStatus AuthCertificateHook(void *arg,
154
                                       PRFileDesc *fd,
155
                                       PRBool checksig,
156
                                       PRBool isServer);
157
  SECStatus AuthCertificateHook(PRFileDesc *fd,
158
                                PRBool checksig,
159
                                PRBool isServer);
160
161
  static void TimerCallback(nsITimer *timer, void *arg);
162
163
  SECStatus CheckDigest(const RefPtr<VerificationDigest>& digest,
164
                        UniqueCERTCertificate& cert) const;
165
166
  void RecordHandshakeCompletionTelemetry(TransportLayer::State endState);
167
  void RecordCipherTelemetry();
168
169
  static PRBool WriteSrtpXtn(PRFileDesc* fd, SSLHandshakeType message,
170
                             uint8_t* data, unsigned int* len,
171
                             unsigned int max_len, void* arg);
172
173
  static SECStatus HandleSrtpXtn(PRFileDesc* fd, SSLHandshakeType message,
174
                                 const uint8_t* data, unsigned int len,
175
                                 SSLAlertDescription* alert, void* arg);
176
177
  RefPtr<DtlsIdentity> identity_;
178
  // What ALPN identifiers are permitted.
179
  std::set<std::string> alpn_allowed_;
180
  // What ALPN identifier is used if ALPN is not supported.
181
  // The empty string indicates that ALPN is required.
182
  std::string alpn_default_;
183
  // What ALPN string was negotiated.
184
  std::string alpn_;
185
  std::vector<uint16_t> enabled_srtp_ciphers_;
186
  uint16_t srtp_cipher_ = 0;
187
188
  Role role_ = CLIENT;
189
  Verification verification_mode_ = VERIFY_UNSET;
190
  std::vector<RefPtr<VerificationDigest> > digests_;
191
192
  // Must delete nspr_io_adapter after ssl_fd_ b/c ssl_fd_ causes an alert
193
  // (ssl_fd_ contains an un-owning pointer to nspr_io_adapter_)
194
  UniquePtr<TransportLayerNSPRAdapter> nspr_io_adapter_ = nullptr;
195
  UniquePRFileDesc ssl_fd_ = nullptr;
196
197
  nsCOMPtr<nsITimer> timer_ = nullptr;
198
  bool auth_hook_called_ = false;
199
  bool cert_ok_ = false;
200
  TimeStamp handshake_started_;
201
};
202
203
204
}  // close namespace
205
#endif