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