|
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 |
|
14 #include "sigslot.h" |
|
15 |
|
16 #include "mozilla/RefPtr.h" |
|
17 #include "mozilla/Scoped.h" |
|
18 #include "nsCOMPtr.h" |
|
19 #include "nsIEventTarget.h" |
|
20 #include "nsITimer.h" |
|
21 #include "ScopedNSSTypes.h" |
|
22 #include "m_cpp_utils.h" |
|
23 #include "dtlsidentity.h" |
|
24 #include "transportflow.h" |
|
25 #include "transportlayer.h" |
|
26 |
|
27 namespace mozilla { |
|
28 |
|
29 struct Packet; |
|
30 |
|
31 class TransportLayerNSPRAdapter { |
|
32 public: |
|
33 TransportLayerNSPRAdapter(TransportLayer *output) : |
|
34 output_(output), |
|
35 input_() {} |
|
36 |
|
37 void PacketReceived(const void *data, int32_t len); |
|
38 int32_t Read(void *data, int32_t len); |
|
39 int32_t Write(const void *buf, int32_t length); |
|
40 |
|
41 private: |
|
42 DISALLOW_COPY_ASSIGN(TransportLayerNSPRAdapter); |
|
43 |
|
44 TransportLayer *output_; |
|
45 std::queue<Packet *> input_; |
|
46 }; |
|
47 |
|
48 class TransportLayerDtls : public TransportLayer { |
|
49 public: |
|
50 TransportLayerDtls() : |
|
51 TransportLayer(DGRAM), |
|
52 role_(CLIENT), |
|
53 verification_mode_(VERIFY_UNSET), |
|
54 ssl_fd_(nullptr), |
|
55 auth_hook_called_(false), |
|
56 cert_ok_(false) {} |
|
57 |
|
58 virtual ~TransportLayerDtls(); |
|
59 |
|
60 enum Role { CLIENT, SERVER}; |
|
61 enum Verification { VERIFY_UNSET, VERIFY_ALLOW_ALL, VERIFY_DIGEST}; |
|
62 const static size_t kMaxDigestLength = HASH_LENGTH_MAX; |
|
63 |
|
64 // DTLS-specific operations |
|
65 void SetRole(Role role) { role_ = role;} |
|
66 Role role() { return role_; } |
|
67 |
|
68 void SetIdentity(const RefPtr<DtlsIdentity>& identity) { |
|
69 identity_ = identity; |
|
70 } |
|
71 nsresult SetVerificationAllowAll(); |
|
72 nsresult SetVerificationDigest(const std::string digest_algorithm, |
|
73 const unsigned char *digest_value, |
|
74 size_t digest_len); |
|
75 |
|
76 nsresult SetSrtpCiphers(std::vector<uint16_t> ciphers); |
|
77 nsresult GetSrtpCipher(uint16_t *cipher); |
|
78 |
|
79 nsresult ExportKeyingMaterial(const std::string& label, |
|
80 bool use_context, |
|
81 const std::string& context, |
|
82 unsigned char *out, |
|
83 unsigned int outlen); |
|
84 |
|
85 const CERTCertificate *GetPeerCert() const { |
|
86 return peer_cert_; |
|
87 } |
|
88 |
|
89 // Transport layer overrides. |
|
90 virtual nsresult InitInternal(); |
|
91 virtual void WasInserted(); |
|
92 virtual TransportResult SendPacket(const unsigned char *data, size_t len); |
|
93 |
|
94 // Signals |
|
95 void StateChange(TransportLayer *layer, State state); |
|
96 void PacketReceived(TransportLayer* layer, const unsigned char *data, |
|
97 size_t len); |
|
98 |
|
99 TRANSPORT_LAYER_ID("dtls") |
|
100 |
|
101 private: |
|
102 DISALLOW_COPY_ASSIGN(TransportLayerDtls); |
|
103 |
|
104 // A single digest to check |
|
105 class VerificationDigest { |
|
106 public: |
|
107 VerificationDigest(std::string algorithm, |
|
108 const unsigned char *value, size_t len) { |
|
109 MOZ_ASSERT(len <= sizeof(value_)); |
|
110 |
|
111 algorithm_ = algorithm; |
|
112 memcpy(value_, value, len); |
|
113 len_ = len; |
|
114 } |
|
115 |
|
116 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VerificationDigest) |
|
117 |
|
118 std::string algorithm_; |
|
119 size_t len_; |
|
120 unsigned char value_[kMaxDigestLength]; |
|
121 |
|
122 private: |
|
123 DISALLOW_COPY_ASSIGN(VerificationDigest); |
|
124 }; |
|
125 |
|
126 |
|
127 bool Setup(); |
|
128 void Handshake(); |
|
129 |
|
130 static SECStatus GetClientAuthDataHook(void *arg, PRFileDesc *fd, |
|
131 CERTDistNames *caNames, |
|
132 CERTCertificate **pRetCert, |
|
133 SECKEYPrivateKey **pRetKey); |
|
134 static SECStatus AuthCertificateHook(void *arg, |
|
135 PRFileDesc *fd, |
|
136 PRBool checksig, |
|
137 PRBool isServer); |
|
138 SECStatus AuthCertificateHook(PRFileDesc *fd, |
|
139 PRBool checksig, |
|
140 PRBool isServer); |
|
141 |
|
142 static void TimerCallback(nsITimer *timer, void *arg); |
|
143 |
|
144 SECStatus CheckDigest(const RefPtr<VerificationDigest>& digest, |
|
145 CERTCertificate *cert); |
|
146 |
|
147 RefPtr<DtlsIdentity> identity_; |
|
148 std::vector<uint16_t> srtp_ciphers_; |
|
149 |
|
150 Role role_; |
|
151 Verification verification_mode_; |
|
152 std::vector<RefPtr<VerificationDigest> > digests_; |
|
153 |
|
154 // Must delete nspr_io_adapter after ssl_fd_ b/c ssl_fd_ causes an alert |
|
155 // (ssl_fd_ contains an un-owning pointer to nspr_io_adapter_) |
|
156 ScopedDeletePtr<TransportLayerNSPRAdapter> nspr_io_adapter_; |
|
157 ScopedPRFileDesc ssl_fd_; |
|
158 |
|
159 ScopedCERTCertificate peer_cert_; |
|
160 nsCOMPtr<nsITimer> timer_; |
|
161 bool auth_hook_called_; |
|
162 bool cert_ok_; |
|
163 }; |
|
164 |
|
165 |
|
166 } // close namespace |
|
167 #endif |