blob: 5c61f6a2f7d54e4a691221e84df203b134ef0354 [file] [log] [blame]
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +00001/*
2 * Copyright 2014 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
jbauch555604a2016-04-26 03:13:22 -070011#include <memory>
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000012#include <string>
13
kjellandere96c45b2017-06-30 10:45:21 -070014#include "webrtc/rtc_base/gunit.h"
15#include "webrtc/rtc_base/ipaddress.h"
16#include "webrtc/rtc_base/socketstream.h"
17#include "webrtc/rtc_base/ssladapter.h"
18#include "webrtc/rtc_base/sslidentity.h"
19#include "webrtc/rtc_base/sslstreamadapter.h"
20#include "webrtc/rtc_base/stream.h"
21#include "webrtc/rtc_base/stringencode.h"
22#include "webrtc/rtc_base/virtualsocketserver.h"
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000023
24static const int kTimeout = 5000;
25
26static rtc::AsyncSocket* CreateSocket(const rtc::SSLMode& ssl_mode) {
27 rtc::SocketAddress address(rtc::IPAddress(INADDR_ANY), 0);
28
29 rtc::AsyncSocket* socket = rtc::Thread::Current()->
30 socketserver()->CreateAsyncSocket(
31 address.family(), (ssl_mode == rtc::SSL_MODE_DTLS) ?
32 SOCK_DGRAM : SOCK_STREAM);
33 socket->Bind(address);
34
35 return socket;
36}
37
38static std::string GetSSLProtocolName(const rtc::SSLMode& ssl_mode) {
39 return (ssl_mode == rtc::SSL_MODE_DTLS) ? "DTLS" : "TLS";
40}
41
42class SSLAdapterTestDummyClient : public sigslot::has_slots<> {
43 public:
44 explicit SSLAdapterTestDummyClient(const rtc::SSLMode& ssl_mode)
45 : ssl_mode_(ssl_mode) {
46 rtc::AsyncSocket* socket = CreateSocket(ssl_mode_);
47
48 ssl_adapter_.reset(rtc::SSLAdapter::Create(socket));
49
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +000050 ssl_adapter_->SetMode(ssl_mode_);
51
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000052 // Ignore any certificate errors for the purpose of testing.
53 // Note: We do this only because we don't have a real certificate.
54 // NEVER USE THIS IN PRODUCTION CODE!
Diogo Real1dca9d52017-08-29 12:18:32 -070055 ssl_adapter_->SetIgnoreBadCert(true);
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000056
57 ssl_adapter_->SignalReadEvent.connect(this,
58 &SSLAdapterTestDummyClient::OnSSLAdapterReadEvent);
59 ssl_adapter_->SignalCloseEvent.connect(this,
60 &SSLAdapterTestDummyClient::OnSSLAdapterCloseEvent);
61 }
62
Diogo Real1dca9d52017-08-29 12:18:32 -070063 void SetAlpnProtocols(const std::vector<std::string>& protos) {
64 ssl_adapter_->SetAlpnProtocols(protos);
65 }
66
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +000067 rtc::SocketAddress GetAddress() const {
68 return ssl_adapter_->GetLocalAddress();
69 }
70
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000071 rtc::AsyncSocket::ConnState GetState() const {
72 return ssl_adapter_->GetState();
73 }
74
75 const std::string& GetReceivedData() const {
76 return data_;
77 }
78
79 int Connect(const std::string& hostname, const rtc::SocketAddress& address) {
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000080 LOG(LS_INFO) << "Initiating connection with " << address;
81
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +000082 int rv = ssl_adapter_->Connect(address);
83
84 if (rv == 0) {
85 LOG(LS_INFO) << "Starting " << GetSSLProtocolName(ssl_mode_)
86 << " handshake with " << hostname;
87
88 if (ssl_adapter_->StartSSL(hostname.c_str(), false) != 0) {
89 return -1;
90 }
91 }
92
93 return rv;
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +000094 }
95
96 int Close() {
97 return ssl_adapter_->Close();
98 }
99
100 int Send(const std::string& message) {
101 LOG(LS_INFO) << "Client sending '" << message << "'";
102
103 return ssl_adapter_->Send(message.data(), message.length());
104 }
105
106 void OnSSLAdapterReadEvent(rtc::AsyncSocket* socket) {
107 char buffer[4096] = "";
108
109 // Read data received from the server and store it in our internal buffer.
Stefan Holmer9131efd2016-05-23 18:19:26 +0200110 int read = socket->Recv(buffer, sizeof(buffer) - 1, nullptr);
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000111 if (read != -1) {
112 buffer[read] = '\0';
113
114 LOG(LS_INFO) << "Client received '" << buffer << "'";
115
116 data_ += buffer;
117 }
118 }
119
120 void OnSSLAdapterCloseEvent(rtc::AsyncSocket* socket, int error) {
121 // OpenSSLAdapter signals handshake failure with a close event, but without
122 // closing the socket! Let's close the socket here. This way GetState() can
123 // return CS_CLOSED after failure.
124 if (socket->GetState() != rtc::AsyncSocket::CS_CLOSED) {
125 socket->Close();
126 }
127 }
128
129 private:
130 const rtc::SSLMode ssl_mode_;
131
jbauch555604a2016-04-26 03:13:22 -0700132 std::unique_ptr<rtc::SSLAdapter> ssl_adapter_;
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000133
134 std::string data_;
135};
136
137class SSLAdapterTestDummyServer : public sigslot::has_slots<> {
138 public:
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200139 explicit SSLAdapterTestDummyServer(const rtc::SSLMode& ssl_mode,
torbjorng4e572472015-10-08 09:42:49 -0700140 const rtc::KeyParams& key_params)
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000141 : ssl_mode_(ssl_mode) {
142 // Generate a key pair and a certificate for this host.
torbjorng4e572472015-10-08 09:42:49 -0700143 ssl_identity_.reset(rtc::SSLIdentity::Generate(GetHostname(), key_params));
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000144
145 server_socket_.reset(CreateSocket(ssl_mode_));
146
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000147 if (ssl_mode_ == rtc::SSL_MODE_TLS) {
148 server_socket_->SignalReadEvent.connect(this,
149 &SSLAdapterTestDummyServer::OnServerSocketReadEvent);
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000150
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000151 server_socket_->Listen(1);
152 }
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000153
154 LOG(LS_INFO) << ((ssl_mode_ == rtc::SSL_MODE_DTLS) ? "UDP" : "TCP")
155 << " server listening on " << server_socket_->GetLocalAddress();
156 }
157
158 rtc::SocketAddress GetAddress() const {
159 return server_socket_->GetLocalAddress();
160 }
161
162 std::string GetHostname() const {
163 // Since we don't have a real certificate anyway, the value here doesn't
164 // really matter.
165 return "example.com";
166 }
167
168 const std::string& GetReceivedData() const {
169 return data_;
170 }
171
172 int Send(const std::string& message) {
deadbeef37f5ecf2017-02-27 14:06:41 -0800173 if (ssl_stream_adapter_ == nullptr ||
174 ssl_stream_adapter_->GetState() != rtc::SS_OPEN) {
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000175 // No connection yet.
176 return -1;
177 }
178
179 LOG(LS_INFO) << "Server sending '" << message << "'";
180
181 size_t written;
182 int error;
183
184 rtc::StreamResult r = ssl_stream_adapter_->Write(message.data(),
185 message.length(), &written, &error);
186 if (r == rtc::SR_SUCCESS) {
187 return written;
188 } else {
189 return -1;
190 }
191 }
192
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000193 void AcceptConnection(const rtc::SocketAddress& address) {
194 // Only a single connection is supported.
deadbeef37f5ecf2017-02-27 14:06:41 -0800195 ASSERT_TRUE(ssl_stream_adapter_ == nullptr);
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000196
197 // This is only for DTLS.
198 ASSERT_EQ(rtc::SSL_MODE_DTLS, ssl_mode_);
199
200 // Transfer ownership of the socket to the SSLStreamAdapter object.
201 rtc::AsyncSocket* socket = server_socket_.release();
202
203 socket->Connect(address);
204
205 DoHandshake(socket);
206 }
207
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000208 void OnServerSocketReadEvent(rtc::AsyncSocket* socket) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000209 // Only a single connection is supported.
deadbeef37f5ecf2017-02-27 14:06:41 -0800210 ASSERT_TRUE(ssl_stream_adapter_ == nullptr);
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000211
deadbeef37f5ecf2017-02-27 14:06:41 -0800212 DoHandshake(server_socket_->Accept(nullptr));
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000213 }
214
215 void OnSSLStreamAdapterEvent(rtc::StreamInterface* stream, int sig, int err) {
216 if (sig & rtc::SE_READ) {
217 char buffer[4096] = "";
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000218 size_t read;
219 int error;
220
221 // Read data received from the client and store it in our internal
222 // buffer.
deadbeefed3b9862017-06-02 10:33:16 -0700223 rtc::StreamResult r =
224 stream->Read(buffer, sizeof(buffer) - 1, &read, &error);
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000225 if (r == rtc::SR_SUCCESS) {
226 buffer[read] = '\0';
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000227 LOG(LS_INFO) << "Server received '" << buffer << "'";
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000228 data_ += buffer;
229 }
230 }
231 }
232
233 private:
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000234 void DoHandshake(rtc::AsyncSocket* socket) {
235 rtc::SocketStream* stream = new rtc::SocketStream(socket);
236
237 ssl_stream_adapter_.reset(rtc::SSLStreamAdapter::Create(stream));
238
239 ssl_stream_adapter_->SetMode(ssl_mode_);
240 ssl_stream_adapter_->SetServerRole();
241
242 // SSLStreamAdapter is normally used for peer-to-peer communication, but
243 // here we're testing communication between a client and a server
244 // (e.g. a WebRTC-based application and an RFC 5766 TURN server), where
245 // clients are not required to provide a certificate during handshake.
246 // Accordingly, we must disable client authentication here.
247 ssl_stream_adapter_->set_client_auth_enabled(false);
248
249 ssl_stream_adapter_->SetIdentity(ssl_identity_->GetReference());
250
251 // Set a bogus peer certificate digest.
252 unsigned char digest[20];
253 size_t digest_len = sizeof(digest);
254 ssl_stream_adapter_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest,
255 digest_len);
256
Taylor Brandstetterc8762a82016-08-11 12:01:49 -0700257 ssl_stream_adapter_->StartSSL();
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000258
259 ssl_stream_adapter_->SignalEvent.connect(this,
260 &SSLAdapterTestDummyServer::OnSSLStreamAdapterEvent);
261 }
262
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000263 const rtc::SSLMode ssl_mode_;
264
jbauch555604a2016-04-26 03:13:22 -0700265 std::unique_ptr<rtc::AsyncSocket> server_socket_;
266 std::unique_ptr<rtc::SSLStreamAdapter> ssl_stream_adapter_;
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000267
jbauch555604a2016-04-26 03:13:22 -0700268 std::unique_ptr<rtc::SSLIdentity> ssl_identity_;
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000269
270 std::string data_;
271};
272
273class SSLAdapterTestBase : public testing::Test,
274 public sigslot::has_slots<> {
275 public:
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200276 explicit SSLAdapterTestBase(const rtc::SSLMode& ssl_mode,
torbjorng4e572472015-10-08 09:42:49 -0700277 const rtc::KeyParams& key_params)
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000278 : ssl_mode_(ssl_mode),
deadbeef98e186c2017-05-16 18:00:06 -0700279 vss_(new rtc::VirtualSocketServer()),
nisse7eaa4ea2017-05-08 05:25:41 -0700280 thread_(vss_.get()),
torbjorng4e572472015-10-08 09:42:49 -0700281 server_(new SSLAdapterTestDummyServer(ssl_mode_, key_params)),
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000282 client_(new SSLAdapterTestDummyClient(ssl_mode_)),
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200283 handshake_wait_(kTimeout) {}
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000284
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000285 void SetHandshakeWait(int wait) {
286 handshake_wait_ = wait;
287 }
288
Diogo Real1dca9d52017-08-29 12:18:32 -0700289 void SetAlpnProtocols(const std::vector<std::string>& protos) {
290 client_->SetAlpnProtocols(protos);
291 }
292
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000293 void TestHandshake(bool expect_success) {
294 int rv;
295
296 // The initial state is CS_CLOSED
297 ASSERT_EQ(rtc::AsyncSocket::CS_CLOSED, client_->GetState());
298
299 rv = client_->Connect(server_->GetHostname(), server_->GetAddress());
300 ASSERT_EQ(0, rv);
301
302 // Now the state should be CS_CONNECTING
303 ASSERT_EQ(rtc::AsyncSocket::CS_CONNECTING, client_->GetState());
304
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000305 if (ssl_mode_ == rtc::SSL_MODE_DTLS) {
306 // For DTLS, call AcceptConnection() with the client's address.
307 server_->AcceptConnection(client_->GetAddress());
308 }
309
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000310 if (expect_success) {
311 // If expecting success, the client should end up in the CS_CONNECTED
312 // state after handshake.
313 EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CONNECTED, client_->GetState(),
314 handshake_wait_);
315
316 LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake complete.";
317
318 } else {
319 // On handshake failure the client should end up in the CS_CLOSED state.
320 EXPECT_EQ_WAIT(rtc::AsyncSocket::CS_CLOSED, client_->GetState(),
321 handshake_wait_);
322
323 LOG(LS_INFO) << GetSSLProtocolName(ssl_mode_) << " handshake failed.";
324 }
325 }
326
327 void TestTransfer(const std::string& message) {
328 int rv;
329
330 rv = client_->Send(message);
331 ASSERT_EQ(static_cast<int>(message.length()), rv);
332
333 // The server should have received the client's message.
334 EXPECT_EQ_WAIT(message, server_->GetReceivedData(), kTimeout);
335
336 rv = server_->Send(message);
337 ASSERT_EQ(static_cast<int>(message.length()), rv);
338
339 // The client should have received the server's message.
340 EXPECT_EQ_WAIT(message, client_->GetReceivedData(), kTimeout);
341
342 LOG(LS_INFO) << "Transfer complete.";
343 }
344
deadbeefed3b9862017-06-02 10:33:16 -0700345 protected:
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000346 const rtc::SSLMode ssl_mode_;
347
nisse7eaa4ea2017-05-08 05:25:41 -0700348 std::unique_ptr<rtc::VirtualSocketServer> vss_;
349 rtc::AutoSocketServerThread thread_;
jbauch555604a2016-04-26 03:13:22 -0700350 std::unique_ptr<SSLAdapterTestDummyServer> server_;
351 std::unique_ptr<SSLAdapterTestDummyClient> client_;
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000352
353 int handshake_wait_;
354};
355
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200356class SSLAdapterTestTLS_RSA : public SSLAdapterTestBase {
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000357 public:
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200358 SSLAdapterTestTLS_RSA()
torbjorng4e572472015-10-08 09:42:49 -0700359 : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::RSA()) {}
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000360};
361
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200362class SSLAdapterTestTLS_ECDSA : public SSLAdapterTestBase {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000363 public:
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200364 SSLAdapterTestTLS_ECDSA()
torbjorng4e572472015-10-08 09:42:49 -0700365 : SSLAdapterTestBase(rtc::SSL_MODE_TLS, rtc::KeyParams::ECDSA()) {}
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200366};
367
368class SSLAdapterTestDTLS_RSA : public SSLAdapterTestBase {
369 public:
370 SSLAdapterTestDTLS_RSA()
torbjorng4e572472015-10-08 09:42:49 -0700371 : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::RSA()) {}
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200372};
373
374class SSLAdapterTestDTLS_ECDSA : public SSLAdapterTestBase {
375 public:
376 SSLAdapterTestDTLS_ECDSA()
torbjorng4e572472015-10-08 09:42:49 -0700377 : SSLAdapterTestBase(rtc::SSL_MODE_DTLS, rtc::KeyParams::ECDSA()) {}
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000378};
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000379
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000380// Basic tests: TLS
381
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200382// Test that handshake works, using RSA
383TEST_F(SSLAdapterTestTLS_RSA, TestTLSConnect) {
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000384 TestHandshake(true);
385}
386
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200387// Test that handshake works, using ECDSA
388TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSConnect) {
389 TestHandshake(true);
390}
391
392// Test transfer between client and server, using RSA
393TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransfer) {
394 TestHandshake(true);
395 TestTransfer("Hello, world!");
396}
397
deadbeefed3b9862017-06-02 10:33:16 -0700398TEST_F(SSLAdapterTestTLS_RSA, TestTLSTransferWithBlockedSocket) {
399 TestHandshake(true);
400
401 // Tell the underlying socket to simulate being blocked.
402 vss_->SetSendingBlocked(true);
403
404 std::string expected;
405 int rv;
406 // Send messages until the SSL socket adapter starts applying backpressure.
407 // Note that this may not occur immediately since there may be some amount of
408 // intermediate buffering (either in our code or in BoringSSL).
409 for (int i = 0; i < 1024; ++i) {
410 std::string message = "Hello, world: " + rtc::ToString(i);
411 rv = client_->Send(message);
412 if (rv != static_cast<int>(message.size())) {
413 // This test assumes either the whole message or none of it is sent.
414 ASSERT_EQ(-1, rv);
415 break;
416 }
417 expected += message;
418 }
419 // Assert that the loop above exited due to Send returning -1.
420 ASSERT_EQ(-1, rv);
421
422 // Try sending another message while blocked. -1 should be returned again and
423 // it shouldn't end up received by the server later.
424 EXPECT_EQ(-1, client_->Send("Never sent"));
425
426 // Unblock the underlying socket. All of the buffered messages should be sent
427 // without any further action.
428 vss_->SetSendingBlocked(false);
429 EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout);
430
431 // Send another message. This previously wasn't working
432 std::string final_message = "Fin.";
433 expected += final_message;
434 EXPECT_EQ(static_cast<int>(final_message.size()),
435 client_->Send(final_message));
436 EXPECT_EQ_WAIT(expected, server_->GetReceivedData(), kTimeout);
437}
438
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200439// Test transfer between client and server, using ECDSA
440TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSTransfer) {
tkchin@webrtc.orgc569a492014-09-23 05:56:44 +0000441 TestHandshake(true);
442 TestTransfer("Hello, world!");
443}
444
Diogo Real1dca9d52017-08-29 12:18:32 -0700445// Test transfer using ALPN with protos as h2 and http/1.1
446TEST_F(SSLAdapterTestTLS_ECDSA, TestTLSALPN) {
447 std::vector<std::string> alpn_protos{"h2", "http/1.1"};
448 SetAlpnProtocols(alpn_protos);
449 TestHandshake(true);
450 TestTransfer("Hello, world!");
451}
452
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000453// Basic tests: DTLS
454
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200455// Test that handshake works, using RSA
456TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSConnect) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000457 TestHandshake(true);
458}
459
Torbjorn Granlundb6d4ec42015-08-17 14:08:59 +0200460// Test that handshake works, using ECDSA
461TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSConnect) {
462 TestHandshake(true);
463}
464
465// Test transfer between client and server, using RSA
466TEST_F(SSLAdapterTestDTLS_RSA, TestDTLSTransfer) {
467 TestHandshake(true);
468 TestTransfer("Hello, world!");
469}
470
471// Test transfer between client and server, using ECDSA
472TEST_F(SSLAdapterTestDTLS_ECDSA, TestDTLSTransfer) {
pthatcher@webrtc.orga9b1ec02014-12-29 23:00:14 +0000473 TestHandshake(true);
474 TestTransfer("Hello, world!");
475}