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