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