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