blob: 5cc4bfda73c73cf967f9e0dadafaa6bae95d3abc [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2011, Google Inc.
4 * Portions Copyright 2011, RTFM, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29
30#include <algorithm>
31#include <set>
32#include <string>
33
34#include "talk/base/gunit.h"
35#include "talk/base/helpers.h"
wu@webrtc.org4551b792013-10-09 15:37:36 +000036#include "talk/base/scoped_ptr.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037#include "talk/base/ssladapter.h"
38#include "talk/base/sslconfig.h"
39#include "talk/base/sslidentity.h"
40#include "talk/base/sslstreamadapter.h"
41#include "talk/base/stream.h"
42
43static const int kBlockSize = 4096;
44static const char kAES_CM_HMAC_SHA1_80[] = "AES_CM_128_HMAC_SHA1_80";
45static const char kAES_CM_HMAC_SHA1_32[] = "AES_CM_128_HMAC_SHA1_32";
46static const char kExporterLabel[] = "label";
47static const unsigned char kExporterContext[] = "context";
48static int kExporterContextLen = sizeof(kExporterContext);
49
50static const char kRSA_PRIVATE_KEY_PEM[] =
51 "-----BEGIN RSA PRIVATE KEY-----\n"
52 "MIICXQIBAAKBgQDCueE4a9hDMZ3sbVZdlXOz9ZA+cvzie3zJ9gXnT/BCt9P4b9HE\n"
53 "vD/tr73YBqD3Wr5ZWScmyGYF9EMn0r3rzBxv6oooLU5TdUvOm4rzUjkCLQaQML8o\n"
54 "NxXq+qW/j3zUKGikLhaaAl/amaX2zSWUsRQ1CpngQ3+tmDNH4/25TncNmQIDAQAB\n"
55 "AoGAUcuU0Id0k10fMjYHZk4mCPzot2LD2Tr4Aznl5vFMQipHzv7hhZtx2xzMSRcX\n"
56 "vG+Qr6VkbcUWHgApyWubvZXCh3+N7Vo2aYdMAQ8XqmFpBdIrL5CVdVfqFfEMlgEy\n"
57 "LSZNG5klnrIfl3c7zQVovLr4eMqyl2oGfAqPQz75+fecv1UCQQD6wNHch9NbAG1q\n"
58 "yuFEhMARB6gDXb+5SdzFjjtTWW5uJfm4DcZLoYyaIZm0uxOwsUKd0Rsma+oGitS1\n"
59 "CXmuqfpPAkEAxszyN3vIdpD44SREEtyKZBMNOk5pEIIGdbeMJC5/XHvpxww9xkoC\n"
60 "+39NbvUZYd54uT+rafbx4QZKc0h9xA/HlwJBAL37lYVWy4XpPv1olWCKi9LbUCqs\n"
61 "vvQtyD1N1BkEayy9TQRsO09WKOcmigRqsTJwOx7DLaTgokEuspYvhagWVPUCQE/y\n"
62 "0+YkTbYBD1Xbs9SyBKXCU6uDJRWSdO6aZi2W1XloC9gUwDMiSJjD1Wwt/YsyYPJ+\n"
63 "/Hyc5yFL2l0KZimW/vkCQQCjuZ/lPcH46EuzhdbRfumDOG5N3ld7UhGI1TIRy17W\n"
64 "dGF90cG33/L6BfS8Ll+fkkW/2AMRk8FDvF4CZi2nfW4L\n"
65 "-----END RSA PRIVATE KEY-----\n";
66
67static const char kCERT_PEM[] =
68 "-----BEGIN CERTIFICATE-----\n"
69 "MIIBmTCCAQICCQCPNJORW/M13DANBgkqhkiG9w0BAQUFADARMQ8wDQYDVQQDDAZ3\n"
70 "ZWJydGMwHhcNMTMwNjE0MjIzMDAxWhcNMTQwNjE0MjIzMDAxWjARMQ8wDQYDVQQD\n"
71 "DAZ3ZWJydGMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMK54Thr2EMxnext\n"
72 "Vl2Vc7P1kD5y/OJ7fMn2BedP8EK30/hv0cS8P+2vvdgGoPdavllZJybIZgX0QyfS\n"
73 "vevMHG/qiigtTlN1S86bivNSOQItBpAwvyg3Fer6pb+PfNQoaKQuFpoCX9qZpfbN\n"
74 "JZSxFDUKmeBDf62YM0fj/blOdw2ZAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAECMt\n"
75 "UZb35H8TnjGx4XPzco/kbnurMLFFWcuve/DwTsuf10Ia9N4md8LY0UtgIgtyNqWc\n"
76 "ZwyRMwxONF6ty3wcaIiPbGqiAa55T3YRuPibkRmck9CjrmM9JAtyvqHnpHd2TsBD\n"
77 "qCV42aXS3onOXDQ1ibuWq0fr0//aj0wo4KV474c=\n"
78 "-----END CERTIFICATE-----\n";
79
80#define MAYBE_SKIP_TEST(feature) \
81 if (!(talk_base::SSLStreamAdapter::feature())) { \
82 LOG(LS_INFO) << "Feature disabled... skipping"; \
83 return; \
84 }
85
86class SSLStreamAdapterTestBase;
87
88class SSLDummyStream : public talk_base::StreamInterface,
89 public sigslot::has_slots<> {
90 public:
91 explicit SSLDummyStream(SSLStreamAdapterTestBase *test,
92 const std::string &side,
93 talk_base::FifoBuffer *in,
94 talk_base::FifoBuffer *out) :
95 test_(test),
96 side_(side),
97 in_(in),
98 out_(out),
99 first_packet_(true) {
100 in_->SignalEvent.connect(this, &SSLDummyStream::OnEventIn);
101 out_->SignalEvent.connect(this, &SSLDummyStream::OnEventOut);
102 }
103
104 virtual talk_base::StreamState GetState() const { return talk_base::SS_OPEN; }
105
106 virtual talk_base::StreamResult Read(void* buffer, size_t buffer_len,
107 size_t* read, int* error) {
108 talk_base::StreamResult r;
109
110 r = in_->Read(buffer, buffer_len, read, error);
111 if (r == talk_base::SR_BLOCK)
112 return talk_base::SR_BLOCK;
113 if (r == talk_base::SR_EOS)
114 return talk_base::SR_EOS;
115
116 if (r != talk_base::SR_SUCCESS) {
117 ADD_FAILURE();
118 return talk_base::SR_ERROR;
119 }
120
121 return talk_base::SR_SUCCESS;
122 }
123
124 // Catch readability events on in and pass them up.
125 virtual void OnEventIn(talk_base::StreamInterface *stream, int sig,
126 int err) {
127 int mask = (talk_base::SE_READ | talk_base::SE_CLOSE);
128
129 if (sig & mask) {
130 LOG(LS_INFO) << "SSLDummyStream::OnEvent side=" << side_ << " sig="
131 << sig << " forwarding upward";
132 PostEvent(sig & mask, 0);
133 }
134 }
135
136 // Catch writeability events on out and pass them up.
137 virtual void OnEventOut(talk_base::StreamInterface *stream, int sig,
138 int err) {
139 if (sig & talk_base::SE_WRITE) {
140 LOG(LS_INFO) << "SSLDummyStream::OnEvent side=" << side_ << " sig="
141 << sig << " forwarding upward";
142
143 PostEvent(sig & talk_base::SE_WRITE, 0);
144 }
145 }
146
147 // Write to the outgoing FifoBuffer
148 talk_base::StreamResult WriteData(const void* data, size_t data_len,
149 size_t* written, int* error) {
150 return out_->Write(data, data_len, written, error);
151 }
152
153 // Defined later
154 virtual talk_base::StreamResult Write(const void* data, size_t data_len,
155 size_t* written, int* error);
156
157 virtual void Close() {
158 LOG(LS_INFO) << "Closing outbound stream";
159 out_->Close();
160 }
161
162 private:
163 SSLStreamAdapterTestBase *test_;
164 const std::string side_;
165 talk_base::FifoBuffer *in_;
166 talk_base::FifoBuffer *out_;
167 bool first_packet_;
168};
169
170static const int kFifoBufferSize = 4096;
171
172class SSLStreamAdapterTestBase : public testing::Test,
173 public sigslot::has_slots<> {
174 public:
175 SSLStreamAdapterTestBase(const std::string& client_cert_pem,
176 const std::string& client_private_key_pem,
177 bool dtls) :
178 client_buffer_(kFifoBufferSize), server_buffer_(kFifoBufferSize),
179 client_stream_(
180 new SSLDummyStream(this, "c2s", &client_buffer_, &server_buffer_)),
181 server_stream_(
182 new SSLDummyStream(this, "s2c", &server_buffer_, &client_buffer_)),
183 client_ssl_(talk_base::SSLStreamAdapter::Create(client_stream_)),
184 server_ssl_(talk_base::SSLStreamAdapter::Create(server_stream_)),
185 client_identity_(NULL), server_identity_(NULL),
186 delay_(0), mtu_(1460), loss_(0), lose_first_packet_(false),
187 damage_(false), dtls_(dtls),
188 handshake_wait_(5000), identities_set_(false) {
189 // Set use of the test RNG to get predictable loss patterns.
190 talk_base::SetRandomTestMode(true);
191
192 // Set up the slots
193 client_ssl_->SignalEvent.connect(this, &SSLStreamAdapterTestBase::OnEvent);
194 server_ssl_->SignalEvent.connect(this, &SSLStreamAdapterTestBase::OnEvent);
195
196 if (!client_cert_pem.empty() && !client_private_key_pem.empty()) {
197 client_identity_ = talk_base::SSLIdentity::FromPEMStrings(
198 client_private_key_pem, client_cert_pem);
199 } else {
200 client_identity_ = talk_base::SSLIdentity::Generate("client");
201 }
202 server_identity_ = talk_base::SSLIdentity::Generate("server");
203
204 client_ssl_->SetIdentity(client_identity_);
205 server_ssl_->SetIdentity(server_identity_);
206 }
207
208 ~SSLStreamAdapterTestBase() {
209 // Put it back for the next test.
210 talk_base::SetRandomTestMode(false);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000211 talk_base::CleanupSSL();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212 }
213
214 static void SetUpTestCase() {
215 talk_base::InitializeSSL();
216 }
217
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000218 // Recreate the client/server identities with the specified validity period.
219 // |not_before| and |not_after| are offsets from the current time in number
220 // of seconds.
221 void ResetIdentitiesWithValidity(int not_before, int not_after) {
222 client_stream_ =
223 new SSLDummyStream(this, "c2s", &client_buffer_, &server_buffer_);
224 server_stream_ =
225 new SSLDummyStream(this, "s2c", &server_buffer_, &client_buffer_);
226
227 client_ssl_.reset(talk_base::SSLStreamAdapter::Create(client_stream_));
228 server_ssl_.reset(talk_base::SSLStreamAdapter::Create(server_stream_));
229
230 client_ssl_->SignalEvent.connect(this, &SSLStreamAdapterTestBase::OnEvent);
231 server_ssl_->SignalEvent.connect(this, &SSLStreamAdapterTestBase::OnEvent);
232
233 talk_base::SSLIdentityParams client_params;
234 client_params.common_name = "client";
235 client_params.not_before = not_before;
236 client_params.not_after = not_after;
237 client_identity_ = talk_base::SSLIdentity::GenerateForTest(client_params);
238
239 talk_base::SSLIdentityParams server_params;
240 server_params.common_name = "server";
241 server_params.not_before = not_before;
242 server_params.not_after = not_after;
243 server_identity_ = talk_base::SSLIdentity::GenerateForTest(server_params);
244
245 client_ssl_->SetIdentity(client_identity_);
246 server_ssl_->SetIdentity(server_identity_);
247 }
248
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000249 virtual void OnEvent(talk_base::StreamInterface *stream, int sig, int err) {
250 LOG(LS_INFO) << "SSLStreamAdapterTestBase::OnEvent sig=" << sig;
251
252 if (sig & talk_base::SE_READ) {
253 ReadData(stream);
254 }
255
256 if ((stream == client_ssl_.get()) && (sig & talk_base::SE_WRITE)) {
257 WriteData();
258 }
259 }
260
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261 void SetPeerIdentitiesByDigest(bool correct) {
262 unsigned char digest[20];
263 size_t digest_len;
264 bool rv;
265
266 LOG(LS_INFO) << "Setting peer identities by digest";
267
268 rv = server_identity_->certificate().ComputeDigest(talk_base::DIGEST_SHA_1,
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000269 digest, 20,
270 &digest_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271 ASSERT_TRUE(rv);
272 if (!correct) {
273 LOG(LS_INFO) << "Setting bogus digest for server cert";
274 digest[0]++;
275 }
276 rv = client_ssl_->SetPeerCertificateDigest(talk_base::DIGEST_SHA_1, digest,
277 digest_len);
278 ASSERT_TRUE(rv);
279
280
281 rv = client_identity_->certificate().ComputeDigest(talk_base::DIGEST_SHA_1,
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000282 digest, 20, &digest_len);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000283 ASSERT_TRUE(rv);
284 if (!correct) {
285 LOG(LS_INFO) << "Setting bogus digest for client cert";
286 digest[0]++;
287 }
288 rv = server_ssl_->SetPeerCertificateDigest(talk_base::DIGEST_SHA_1, digest,
289 digest_len);
290 ASSERT_TRUE(rv);
291
292 identities_set_ = true;
293 }
294
295 void TestHandshake(bool expect_success = true) {
296 server_ssl_->SetMode(dtls_ ? talk_base::SSL_MODE_DTLS :
297 talk_base::SSL_MODE_TLS);
298 client_ssl_->SetMode(dtls_ ? talk_base::SSL_MODE_DTLS :
299 talk_base::SSL_MODE_TLS);
300
301 if (!dtls_) {
302 // Make sure we simulate a reliable network for TLS.
303 // This is just a check to make sure that people don't write wrong
304 // tests.
305 ASSERT((mtu_ == 1460) && (loss_ == 0) && (lose_first_packet_ == 0));
306 }
307
308 if (!identities_set_)
309 SetPeerIdentitiesByDigest(true);
310
311 // Start the handshake
312 int rv;
313
314 server_ssl_->SetServerRole();
315 rv = server_ssl_->StartSSLWithPeer();
316 ASSERT_EQ(0, rv);
317
318 rv = client_ssl_->StartSSLWithPeer();
319 ASSERT_EQ(0, rv);
320
321 // Now run the handshake
322 if (expect_success) {
323 EXPECT_TRUE_WAIT((client_ssl_->GetState() == talk_base::SS_OPEN)
324 && (server_ssl_->GetState() == talk_base::SS_OPEN),
325 handshake_wait_);
326 } else {
327 EXPECT_TRUE_WAIT(client_ssl_->GetState() == talk_base::SS_CLOSED,
328 handshake_wait_);
329 }
330 }
331
332 talk_base::StreamResult DataWritten(SSLDummyStream *from, const void *data,
333 size_t data_len, size_t *written,
334 int *error) {
335 // Randomly drop loss_ percent of packets
336 if (talk_base::CreateRandomId() % 100 < static_cast<uint32>(loss_)) {
337 LOG(LS_INFO) << "Randomly dropping packet, size=" << data_len;
338 *written = data_len;
339 return talk_base::SR_SUCCESS;
340 }
341 if (dtls_ && (data_len > mtu_)) {
342 LOG(LS_INFO) << "Dropping packet > mtu, size=" << data_len;
343 *written = data_len;
344 return talk_base::SR_SUCCESS;
345 }
346
347 // Optionally damage application data (type 23). Note that we don't damage
348 // handshake packets and we damage the last byte to keep the header
349 // intact but break the MAC.
350 if (damage_ && (*static_cast<const unsigned char *>(data) == 23)) {
351 std::vector<char> buf(data_len);
352
353 LOG(LS_INFO) << "Damaging packet";
354
355 memcpy(&buf[0], data, data_len);
356 buf[data_len - 1]++;
357
358 return from->WriteData(&buf[0], data_len, written, error);
359 }
360
361 return from->WriteData(data, data_len, written, error);
362 }
363
364 void SetDelay(int delay) {
365 delay_ = delay;
366 }
367 int GetDelay() { return delay_; }
368
369 void SetLoseFirstPacket(bool lose) {
370 lose_first_packet_ = lose;
371 }
372 bool GetLoseFirstPacket() { return lose_first_packet_; }
373
374 void SetLoss(int percent) {
375 loss_ = percent;
376 }
377
378 void SetDamage() {
379 damage_ = true;
380 }
381
382 void SetMtu(size_t mtu) {
383 mtu_ = mtu;
384 }
385
386 void SetHandshakeWait(int wait) {
387 handshake_wait_ = wait;
388 }
389
390 void SetDtlsSrtpCiphers(const std::vector<std::string> &ciphers,
391 bool client) {
392 if (client)
393 client_ssl_->SetDtlsSrtpCiphers(ciphers);
394 else
395 server_ssl_->SetDtlsSrtpCiphers(ciphers);
396 }
397
398 bool GetDtlsSrtpCipher(bool client, std::string *retval) {
399 if (client)
400 return client_ssl_->GetDtlsSrtpCipher(retval);
401 else
402 return server_ssl_->GetDtlsSrtpCipher(retval);
403 }
404
wu@webrtc.org4551b792013-10-09 15:37:36 +0000405 bool GetPeerCertificate(bool client, talk_base::SSLCertificate** cert) {
406 if (client)
407 return client_ssl_->GetPeerCertificate(cert);
408 else
409 return server_ssl_->GetPeerCertificate(cert);
410 }
411
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000412 bool ExportKeyingMaterial(const char *label,
413 const unsigned char *context,
414 size_t context_len,
415 bool use_context,
416 bool client,
417 unsigned char *result,
418 size_t result_len) {
419 if (client)
420 return client_ssl_->ExportKeyingMaterial(label,
421 context, context_len,
422 use_context,
423 result, result_len);
424 else
425 return server_ssl_->ExportKeyingMaterial(label,
426 context, context_len,
427 use_context,
428 result, result_len);
429 }
430
431 // To be implemented by subclasses.
432 virtual void WriteData() = 0;
433 virtual void ReadData(talk_base::StreamInterface *stream) = 0;
434 virtual void TestTransfer(int size) = 0;
435
436 protected:
437 talk_base::FifoBuffer client_buffer_;
438 talk_base::FifoBuffer server_buffer_;
439 SSLDummyStream *client_stream_; // freed by client_ssl_ destructor
440 SSLDummyStream *server_stream_; // freed by server_ssl_ destructor
441 talk_base::scoped_ptr<talk_base::SSLStreamAdapter> client_ssl_;
442 talk_base::scoped_ptr<talk_base::SSLStreamAdapter> server_ssl_;
443 talk_base::SSLIdentity *client_identity_; // freed by client_ssl_ destructor
444 talk_base::SSLIdentity *server_identity_; // freed by server_ssl_ destructor
445 int delay_;
446 size_t mtu_;
447 int loss_;
448 bool lose_first_packet_;
449 bool damage_;
450 bool dtls_;
451 int handshake_wait_;
452 bool identities_set_;
453};
454
455class SSLStreamAdapterTestTLS : public SSLStreamAdapterTestBase {
456 public:
457 SSLStreamAdapterTestTLS() :
458 SSLStreamAdapterTestBase("", "", false) {
459 };
460
461 // Test data transfer for TLS
462 virtual void TestTransfer(int size) {
463 LOG(LS_INFO) << "Starting transfer test with " << size << " bytes";
464 // Create some dummy data to send.
465 size_t received;
466
467 send_stream_.ReserveSize(size);
468 for (int i = 0; i < size; ++i) {
469 char ch = static_cast<char>(i);
470 send_stream_.Write(&ch, 1, NULL, NULL);
471 }
472 send_stream_.Rewind();
473
474 // Prepare the receive stream.
475 recv_stream_.ReserveSize(size);
476
477 // Start sending
478 WriteData();
479
480 // Wait for the client to close
481 EXPECT_TRUE_WAIT(server_ssl_->GetState() == talk_base::SS_CLOSED, 10000);
482
483 // Now check the data
484 recv_stream_.GetSize(&received);
485
486 EXPECT_EQ(static_cast<size_t>(size), received);
487 EXPECT_EQ(0, memcmp(send_stream_.GetBuffer(),
488 recv_stream_.GetBuffer(), size));
489 }
490
491 void WriteData() {
492 size_t position, tosend, size;
493 talk_base::StreamResult rv;
494 size_t sent;
495 char block[kBlockSize];
496
497 send_stream_.GetSize(&size);
498 if (!size)
499 return;
500
501 for (;;) {
502 send_stream_.GetPosition(&position);
503 if (send_stream_.Read(block, sizeof(block), &tosend, NULL) !=
504 talk_base::SR_EOS) {
505 rv = client_ssl_->Write(block, tosend, &sent, 0);
506
507 if (rv == talk_base::SR_SUCCESS) {
508 send_stream_.SetPosition(position + sent);
509 LOG(LS_VERBOSE) << "Sent: " << position + sent;
510 } else if (rv == talk_base::SR_BLOCK) {
511 LOG(LS_VERBOSE) << "Blocked...";
512 send_stream_.SetPosition(position);
513 break;
514 } else {
515 ADD_FAILURE();
516 break;
517 }
518 } else {
519 // Now close
520 LOG(LS_INFO) << "Wrote " << position << " bytes. Closing";
521 client_ssl_->Close();
522 break;
523 }
524 }
525 };
526
527 virtual void ReadData(talk_base::StreamInterface *stream) {
528 char buffer[1600];
529 size_t bread;
530 int err2;
531 talk_base::StreamResult r;
532
533 for (;;) {
534 r = stream->Read(buffer, sizeof(buffer), &bread, &err2);
535
536 if (r == talk_base::SR_ERROR || r == talk_base::SR_EOS) {
537 // Unfortunately, errors are the way that the stream adapter
538 // signals close in OpenSSL
539 stream->Close();
540 return;
541 }
542
543 if (r == talk_base::SR_BLOCK)
544 break;
545
546 ASSERT_EQ(talk_base::SR_SUCCESS, r);
547 LOG(LS_INFO) << "Read " << bread;
548
549 recv_stream_.Write(buffer, bread, NULL, NULL);
550 }
551 }
552
553 private:
554 talk_base::MemoryStream send_stream_;
555 talk_base::MemoryStream recv_stream_;
556};
557
558class SSLStreamAdapterTestDTLS : public SSLStreamAdapterTestBase {
559 public:
560 SSLStreamAdapterTestDTLS() :
561 SSLStreamAdapterTestBase("", "", true),
562 packet_size_(1000), count_(0), sent_(0) {
563 }
564
565 SSLStreamAdapterTestDTLS(const std::string& cert_pem,
566 const std::string& private_key_pem) :
567 SSLStreamAdapterTestBase(cert_pem, private_key_pem, true),
568 packet_size_(1000), count_(0), sent_(0) {
569 }
570
571 virtual void WriteData() {
572 unsigned char *packet = new unsigned char[1600];
573
574 do {
575 memset(packet, sent_ & 0xff, packet_size_);
576 *(reinterpret_cast<uint32_t *>(packet)) = sent_;
577
578 size_t sent;
579 int rv = client_ssl_->Write(packet, packet_size_, &sent, 0);
580 if (rv == talk_base::SR_SUCCESS) {
581 LOG(LS_VERBOSE) << "Sent: " << sent_;
582 sent_++;
583 } else if (rv == talk_base::SR_BLOCK) {
584 LOG(LS_VERBOSE) << "Blocked...";
585 break;
586 } else {
587 ADD_FAILURE();
588 break;
589 }
590 } while (sent_ < count_);
591
592 delete [] packet;
593 }
594
595 virtual void ReadData(talk_base::StreamInterface *stream) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000596 unsigned char buffer[2000];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000597 size_t bread;
598 int err2;
599 talk_base::StreamResult r;
600
601 for (;;) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000602 r = stream->Read(buffer, 2000, &bread, &err2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000603
604 if (r == talk_base::SR_ERROR) {
605 // Unfortunately, errors are the way that the stream adapter
606 // signals close right now
607 stream->Close();
608 return;
609 }
610
611 if (r == talk_base::SR_BLOCK)
612 break;
613
614 ASSERT_EQ(talk_base::SR_SUCCESS, r);
615 LOG(LS_INFO) << "Read " << bread;
616
617 // Now parse the datagram
618 ASSERT_EQ(packet_size_, bread);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000619 unsigned char* ptr_to_buffer = buffer;
620 uint32_t packet_num = *(reinterpret_cast<uint32_t *>(ptr_to_buffer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000621
622 for (size_t i = 4; i < packet_size_; i++) {
623 ASSERT_EQ((packet_num & 0xff), buffer[i]);
624 }
625 received_.insert(packet_num);
626 }
627 }
628
629 virtual void TestTransfer(int count) {
630 count_ = count;
631
632 WriteData();
633
634 EXPECT_TRUE_WAIT(sent_ == count_, 10000);
635 LOG(LS_INFO) << "sent_ == " << sent_;
636
637 if (damage_) {
638 WAIT(false, 2000);
639 EXPECT_EQ(0U, received_.size());
640 } else if (loss_ == 0) {
641 EXPECT_EQ_WAIT(static_cast<size_t>(sent_), received_.size(), 1000);
642 } else {
643 LOG(LS_INFO) << "Sent " << sent_ << " packets; received " <<
644 received_.size();
645 }
646 };
647
648 private:
649 size_t packet_size_;
650 int count_;
651 int sent_;
652 std::set<int> received_;
653};
654
655
656talk_base::StreamResult SSLDummyStream::Write(const void* data, size_t data_len,
657 size_t* written, int* error) {
658 *written = data_len;
659
660 LOG(LS_INFO) << "Writing to loopback " << data_len;
661
662 if (first_packet_) {
663 first_packet_ = false;
664 if (test_->GetLoseFirstPacket()) {
665 LOG(LS_INFO) << "Losing initial packet of length " << data_len;
666 return talk_base::SR_SUCCESS;
667 }
668 }
669
670 return test_->DataWritten(this, data, data_len, written, error);
671
672 return talk_base::SR_SUCCESS;
673};
674
675class SSLStreamAdapterTestDTLSFromPEMStrings : public SSLStreamAdapterTestDTLS {
676 public:
677 SSLStreamAdapterTestDTLSFromPEMStrings() :
678 SSLStreamAdapterTestDTLS(kCERT_PEM, kRSA_PRIVATE_KEY_PEM) {
679 }
680};
681
682// Basic tests: TLS
683
684// Test that we cannot read/write if we have not yet handshaked.
685// This test only applies to NSS because OpenSSL has passthrough
686// semantics for I/O before the handshake is started.
687#if SSL_USE_NSS
688TEST_F(SSLStreamAdapterTestTLS, TestNoReadWriteBeforeConnect) {
689 talk_base::StreamResult rv;
690 char block[kBlockSize];
691 size_t dummy;
692
693 rv = client_ssl_->Write(block, sizeof(block), &dummy, NULL);
694 ASSERT_EQ(talk_base::SR_BLOCK, rv);
695
696 rv = client_ssl_->Read(block, sizeof(block), &dummy, NULL);
697 ASSERT_EQ(talk_base::SR_BLOCK, rv);
698}
699#endif
700
701
702// Test that we can make a handshake work
703TEST_F(SSLStreamAdapterTestTLS, TestTLSConnect) {
704 TestHandshake();
705};
706
707// Test transfer -- trivial
708TEST_F(SSLStreamAdapterTestTLS, TestTLSTransfer) {
709 TestHandshake();
710 TestTransfer(100000);
711};
712
713// Test read-write after close.
714TEST_F(SSLStreamAdapterTestTLS, ReadWriteAfterClose) {
715 TestHandshake();
716 TestTransfer(100000);
717 client_ssl_->Close();
718
719 talk_base::StreamResult rv;
720 char block[kBlockSize];
721 size_t dummy;
722
723 // It's an error to write after closed.
724 rv = client_ssl_->Write(block, sizeof(block), &dummy, NULL);
725 ASSERT_EQ(talk_base::SR_ERROR, rv);
726
727 // But after closed read gives you EOS.
728 rv = client_ssl_->Read(block, sizeof(block), &dummy, NULL);
729 ASSERT_EQ(talk_base::SR_EOS, rv);
730};
731
732// Test a handshake with a bogus peer digest
733TEST_F(SSLStreamAdapterTestTLS, TestTLSBogusDigest) {
734 SetPeerIdentitiesByDigest(false);
735 TestHandshake(false);
736};
737
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000738// Test moving a bunch of data
739
740// Basic tests: DTLS
741// Test that we can make a handshake work
742TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnect) {
743 MAYBE_SKIP_TEST(HaveDtls);
744 TestHandshake();
745};
746
747// Test that we can make a handshake work if the first packet in
748// each direction is lost. This gives us predictable loss
749// rather than having to tune random
750TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacket) {
751 MAYBE_SKIP_TEST(HaveDtls);
752 SetLoseFirstPacket(true);
753 TestHandshake();
754};
755
756// Test a handshake with loss and delay
757TEST_F(SSLStreamAdapterTestDTLS,
758 TestDTLSConnectWithLostFirstPacketDelay2s) {
759 MAYBE_SKIP_TEST(HaveDtls);
760 SetLoseFirstPacket(true);
761 SetDelay(2000);
762 SetHandshakeWait(20000);
763 TestHandshake();
764};
765
766// Test a handshake with small MTU
wu@webrtc.org20182692013-12-12 22:54:25 +0000767TEST_F(SSLStreamAdapterTestDTLS, DISABLED_TestDTLSConnectWithSmallMtu) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000768 MAYBE_SKIP_TEST(HaveDtls);
769 SetMtu(700);
770 SetHandshakeWait(20000);
771 TestHandshake();
772};
773
774// Test transfer -- trivial
775TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransfer) {
776 MAYBE_SKIP_TEST(HaveDtls);
777 TestHandshake();
778 TestTransfer(100);
779};
780
781TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
782 MAYBE_SKIP_TEST(HaveDtls);
783 TestHandshake();
784 SetLoss(10);
785 TestTransfer(100);
786};
787
788TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) {
789 MAYBE_SKIP_TEST(HaveDtls);
790 SetDamage(); // Must be called first because first packet
791 // write happens at end of handshake.
792 TestHandshake();
793 TestTransfer(100);
794};
795
796// Test DTLS-SRTP with all high ciphers
797TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) {
798 MAYBE_SKIP_TEST(HaveDtlsSrtp);
799 std::vector<std::string> high;
800 high.push_back(kAES_CM_HMAC_SHA1_80);
801 SetDtlsSrtpCiphers(high, true);
802 SetDtlsSrtpCiphers(high, false);
803 TestHandshake();
804
805 std::string client_cipher;
806 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
807 std::string server_cipher;
808 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
809
810 ASSERT_EQ(client_cipher, server_cipher);
811 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_80);
812};
813
814// Test DTLS-SRTP with all low ciphers
815TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpLow) {
816 MAYBE_SKIP_TEST(HaveDtlsSrtp);
817 std::vector<std::string> low;
818 low.push_back(kAES_CM_HMAC_SHA1_32);
819 SetDtlsSrtpCiphers(low, true);
820 SetDtlsSrtpCiphers(low, false);
821 TestHandshake();
822
823 std::string client_cipher;
824 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
825 std::string server_cipher;
826 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
827
828 ASSERT_EQ(client_cipher, server_cipher);
829 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_32);
830};
831
832
833// Test DTLS-SRTP with a mismatch -- should not converge
834TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHighLow) {
835 MAYBE_SKIP_TEST(HaveDtlsSrtp);
836 std::vector<std::string> high;
837 high.push_back(kAES_CM_HMAC_SHA1_80);
838 std::vector<std::string> low;
839 low.push_back(kAES_CM_HMAC_SHA1_32);
840 SetDtlsSrtpCiphers(high, true);
841 SetDtlsSrtpCiphers(low, false);
842 TestHandshake();
843
844 std::string client_cipher;
845 ASSERT_FALSE(GetDtlsSrtpCipher(true, &client_cipher));
846 std::string server_cipher;
847 ASSERT_FALSE(GetDtlsSrtpCipher(false, &server_cipher));
848};
849
850// Test DTLS-SRTP with each side being mixed -- should select high
851TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpMixed) {
852 MAYBE_SKIP_TEST(HaveDtlsSrtp);
853 std::vector<std::string> mixed;
854 mixed.push_back(kAES_CM_HMAC_SHA1_80);
855 mixed.push_back(kAES_CM_HMAC_SHA1_32);
856 SetDtlsSrtpCiphers(mixed, true);
857 SetDtlsSrtpCiphers(mixed, false);
858 TestHandshake();
859
860 std::string client_cipher;
861 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
862 std::string server_cipher;
863 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
864
865 ASSERT_EQ(client_cipher, server_cipher);
866 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_80);
867};
868
869// Test an exporter
870TEST_F(SSLStreamAdapterTestDTLS, TestDTLSExporter) {
871 MAYBE_SKIP_TEST(HaveExporter);
872 TestHandshake();
873 unsigned char client_out[20];
874 unsigned char server_out[20];
875
876 bool result;
877 result = ExportKeyingMaterial(kExporterLabel,
878 kExporterContext, kExporterContextLen,
879 true, true,
880 client_out, sizeof(client_out));
881 ASSERT_TRUE(result);
882
883 result = ExportKeyingMaterial(kExporterLabel,
884 kExporterContext, kExporterContextLen,
885 true, false,
886 server_out, sizeof(server_out));
887 ASSERT_TRUE(result);
888
889 ASSERT_TRUE(!memcmp(client_out, server_out, sizeof(client_out)));
890}
891
wu@webrtc.orgf6d6ed02014-01-03 22:08:47 +0000892// Test not yet valid certificates are not rejected.
893TEST_F(SSLStreamAdapterTestDTLS, TestCertNotYetValid) {
894 MAYBE_SKIP_TEST(HaveDtls);
895 long one_day = 60 * 60 * 24;
896 // Make the certificates not valid until one day later.
897 ResetIdentitiesWithValidity(one_day, one_day);
898 TestHandshake();
899}
900
901// Test expired certificates are not rejected.
902TEST_F(SSLStreamAdapterTestDTLS, TestCertExpired) {
903 MAYBE_SKIP_TEST(HaveDtls);
904 long one_day = 60 * 60 * 24;
905 // Make the certificates already expired.
906 ResetIdentitiesWithValidity(-one_day, -one_day);
907 TestHandshake();
908}
909
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000910// Test data transfer using certs created from strings.
911TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestTransfer) {
912 MAYBE_SKIP_TEST(HaveDtls);
913 TestHandshake();
914 TestTransfer(100);
915}
wu@webrtc.org4551b792013-10-09 15:37:36 +0000916
917// Test getting the remote certificate.
918TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestDTLSGetPeerCertificate) {
919 MAYBE_SKIP_TEST(HaveDtls);
920
921 // Peer certificates haven't been received yet.
922 talk_base::scoped_ptr<talk_base::SSLCertificate> client_peer_cert;
923 ASSERT_FALSE(GetPeerCertificate(true, client_peer_cert.accept()));
924 ASSERT_FALSE(client_peer_cert != NULL);
925
926 talk_base::scoped_ptr<talk_base::SSLCertificate> server_peer_cert;
927 ASSERT_FALSE(GetPeerCertificate(false, server_peer_cert.accept()));
928 ASSERT_FALSE(server_peer_cert != NULL);
929
930 TestHandshake();
931
932 // The client should have a peer certificate after the handshake.
933 ASSERT_TRUE(GetPeerCertificate(true, client_peer_cert.accept()));
934 ASSERT_TRUE(client_peer_cert != NULL);
935
936 // It's not kCERT_PEM.
937 std::string client_peer_string = client_peer_cert->ToPEMString();
938 ASSERT_NE(kCERT_PEM, client_peer_string);
939
940 // It must not have a chain, because the test certs are self-signed.
941 talk_base::SSLCertChain* client_peer_chain;
942 ASSERT_FALSE(client_peer_cert->GetChain(&client_peer_chain));
943
944 // The server should have a peer certificate after the handshake.
945 ASSERT_TRUE(GetPeerCertificate(false, server_peer_cert.accept()));
946 ASSERT_TRUE(server_peer_cert != NULL);
947
948 // It's kCERT_PEM
949 ASSERT_EQ(kCERT_PEM, server_peer_cert->ToPEMString());
950
951 // It must not have a chain, because the test certs are self-signed.
952 talk_base::SSLCertChain* server_peer_chain;
953 ASSERT_FALSE(server_peer_cert->GetChain(&server_peer_chain));
954}