blob: 1fe1a6634841c1185f06a7ec563f62fe63a1ef3d [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);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000210 talk_base::CleanupSSL();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000211 }
212
213 static void SetUpTestCase() {
214 talk_base::InitializeSSL();
215 }
216
217 virtual void OnEvent(talk_base::StreamInterface *stream, int sig, int err) {
218 LOG(LS_INFO) << "SSLStreamAdapterTestBase::OnEvent sig=" << sig;
219
220 if (sig & talk_base::SE_READ) {
221 ReadData(stream);
222 }
223
224 if ((stream == client_ssl_.get()) && (sig & talk_base::SE_WRITE)) {
225 WriteData();
226 }
227 }
228
229 void SetPeerIdentitiesByCertificate(bool correct) {
230 LOG(LS_INFO) << "Setting peer identities by certificate";
231
232 if (correct) {
233 client_ssl_->SetPeerCertificate(server_identity_->certificate().
234 GetReference());
235 server_ssl_->SetPeerCertificate(client_identity_->certificate().
236 GetReference());
237 } else {
238 // If incorrect, set up to expect our own certificate at the peer
239 client_ssl_->SetPeerCertificate(client_identity_->certificate().
240 GetReference());
241 server_ssl_->SetPeerCertificate(server_identity_->certificate().
242 GetReference());
243 }
244 identities_set_ = true;
245 }
246
247 void SetPeerIdentitiesByDigest(bool correct) {
248 unsigned char digest[20];
249 size_t digest_len;
250 bool rv;
251
252 LOG(LS_INFO) << "Setting peer identities by digest";
253
254 rv = server_identity_->certificate().ComputeDigest(talk_base::DIGEST_SHA_1,
255 digest, 20,
256 &digest_len);
257 ASSERT_TRUE(rv);
258 if (!correct) {
259 LOG(LS_INFO) << "Setting bogus digest for server cert";
260 digest[0]++;
261 }
262 rv = client_ssl_->SetPeerCertificateDigest(talk_base::DIGEST_SHA_1, digest,
263 digest_len);
264 ASSERT_TRUE(rv);
265
266
267 rv = client_identity_->certificate().ComputeDigest(talk_base::DIGEST_SHA_1,
268 digest, 20, &digest_len);
269 ASSERT_TRUE(rv);
270 if (!correct) {
271 LOG(LS_INFO) << "Setting bogus digest for client cert";
272 digest[0]++;
273 }
274 rv = server_ssl_->SetPeerCertificateDigest(talk_base::DIGEST_SHA_1, digest,
275 digest_len);
276 ASSERT_TRUE(rv);
277
278 identities_set_ = true;
279 }
280
281 void TestHandshake(bool expect_success = true) {
282 server_ssl_->SetMode(dtls_ ? talk_base::SSL_MODE_DTLS :
283 talk_base::SSL_MODE_TLS);
284 client_ssl_->SetMode(dtls_ ? talk_base::SSL_MODE_DTLS :
285 talk_base::SSL_MODE_TLS);
286
287 if (!dtls_) {
288 // Make sure we simulate a reliable network for TLS.
289 // This is just a check to make sure that people don't write wrong
290 // tests.
291 ASSERT((mtu_ == 1460) && (loss_ == 0) && (lose_first_packet_ == 0));
292 }
293
294 if (!identities_set_)
295 SetPeerIdentitiesByDigest(true);
296
297 // Start the handshake
298 int rv;
299
300 server_ssl_->SetServerRole();
301 rv = server_ssl_->StartSSLWithPeer();
302 ASSERT_EQ(0, rv);
303
304 rv = client_ssl_->StartSSLWithPeer();
305 ASSERT_EQ(0, rv);
306
307 // Now run the handshake
308 if (expect_success) {
309 EXPECT_TRUE_WAIT((client_ssl_->GetState() == talk_base::SS_OPEN)
310 && (server_ssl_->GetState() == talk_base::SS_OPEN),
311 handshake_wait_);
312 } else {
313 EXPECT_TRUE_WAIT(client_ssl_->GetState() == talk_base::SS_CLOSED,
314 handshake_wait_);
315 }
316 }
317
318 talk_base::StreamResult DataWritten(SSLDummyStream *from, const void *data,
319 size_t data_len, size_t *written,
320 int *error) {
321 // Randomly drop loss_ percent of packets
322 if (talk_base::CreateRandomId() % 100 < static_cast<uint32>(loss_)) {
323 LOG(LS_INFO) << "Randomly dropping packet, size=" << data_len;
324 *written = data_len;
325 return talk_base::SR_SUCCESS;
326 }
327 if (dtls_ && (data_len > mtu_)) {
328 LOG(LS_INFO) << "Dropping packet > mtu, size=" << data_len;
329 *written = data_len;
330 return talk_base::SR_SUCCESS;
331 }
332
333 // Optionally damage application data (type 23). Note that we don't damage
334 // handshake packets and we damage the last byte to keep the header
335 // intact but break the MAC.
336 if (damage_ && (*static_cast<const unsigned char *>(data) == 23)) {
337 std::vector<char> buf(data_len);
338
339 LOG(LS_INFO) << "Damaging packet";
340
341 memcpy(&buf[0], data, data_len);
342 buf[data_len - 1]++;
343
344 return from->WriteData(&buf[0], data_len, written, error);
345 }
346
347 return from->WriteData(data, data_len, written, error);
348 }
349
350 void SetDelay(int delay) {
351 delay_ = delay;
352 }
353 int GetDelay() { return delay_; }
354
355 void SetLoseFirstPacket(bool lose) {
356 lose_first_packet_ = lose;
357 }
358 bool GetLoseFirstPacket() { return lose_first_packet_; }
359
360 void SetLoss(int percent) {
361 loss_ = percent;
362 }
363
364 void SetDamage() {
365 damage_ = true;
366 }
367
368 void SetMtu(size_t mtu) {
369 mtu_ = mtu;
370 }
371
372 void SetHandshakeWait(int wait) {
373 handshake_wait_ = wait;
374 }
375
376 void SetDtlsSrtpCiphers(const std::vector<std::string> &ciphers,
377 bool client) {
378 if (client)
379 client_ssl_->SetDtlsSrtpCiphers(ciphers);
380 else
381 server_ssl_->SetDtlsSrtpCiphers(ciphers);
382 }
383
384 bool GetDtlsSrtpCipher(bool client, std::string *retval) {
385 if (client)
386 return client_ssl_->GetDtlsSrtpCipher(retval);
387 else
388 return server_ssl_->GetDtlsSrtpCipher(retval);
389 }
390
391 bool ExportKeyingMaterial(const char *label,
392 const unsigned char *context,
393 size_t context_len,
394 bool use_context,
395 bool client,
396 unsigned char *result,
397 size_t result_len) {
398 if (client)
399 return client_ssl_->ExportKeyingMaterial(label,
400 context, context_len,
401 use_context,
402 result, result_len);
403 else
404 return server_ssl_->ExportKeyingMaterial(label,
405 context, context_len,
406 use_context,
407 result, result_len);
408 }
409
410 // To be implemented by subclasses.
411 virtual void WriteData() = 0;
412 virtual void ReadData(talk_base::StreamInterface *stream) = 0;
413 virtual void TestTransfer(int size) = 0;
414
415 protected:
416 talk_base::FifoBuffer client_buffer_;
417 talk_base::FifoBuffer server_buffer_;
418 SSLDummyStream *client_stream_; // freed by client_ssl_ destructor
419 SSLDummyStream *server_stream_; // freed by server_ssl_ destructor
420 talk_base::scoped_ptr<talk_base::SSLStreamAdapter> client_ssl_;
421 talk_base::scoped_ptr<talk_base::SSLStreamAdapter> server_ssl_;
422 talk_base::SSLIdentity *client_identity_; // freed by client_ssl_ destructor
423 talk_base::SSLIdentity *server_identity_; // freed by server_ssl_ destructor
424 int delay_;
425 size_t mtu_;
426 int loss_;
427 bool lose_first_packet_;
428 bool damage_;
429 bool dtls_;
430 int handshake_wait_;
431 bool identities_set_;
432};
433
434class SSLStreamAdapterTestTLS : public SSLStreamAdapterTestBase {
435 public:
436 SSLStreamAdapterTestTLS() :
437 SSLStreamAdapterTestBase("", "", false) {
438 };
439
440 // Test data transfer for TLS
441 virtual void TestTransfer(int size) {
442 LOG(LS_INFO) << "Starting transfer test with " << size << " bytes";
443 // Create some dummy data to send.
444 size_t received;
445
446 send_stream_.ReserveSize(size);
447 for (int i = 0; i < size; ++i) {
448 char ch = static_cast<char>(i);
449 send_stream_.Write(&ch, 1, NULL, NULL);
450 }
451 send_stream_.Rewind();
452
453 // Prepare the receive stream.
454 recv_stream_.ReserveSize(size);
455
456 // Start sending
457 WriteData();
458
459 // Wait for the client to close
460 EXPECT_TRUE_WAIT(server_ssl_->GetState() == talk_base::SS_CLOSED, 10000);
461
462 // Now check the data
463 recv_stream_.GetSize(&received);
464
465 EXPECT_EQ(static_cast<size_t>(size), received);
466 EXPECT_EQ(0, memcmp(send_stream_.GetBuffer(),
467 recv_stream_.GetBuffer(), size));
468 }
469
470 void WriteData() {
471 size_t position, tosend, size;
472 talk_base::StreamResult rv;
473 size_t sent;
474 char block[kBlockSize];
475
476 send_stream_.GetSize(&size);
477 if (!size)
478 return;
479
480 for (;;) {
481 send_stream_.GetPosition(&position);
482 if (send_stream_.Read(block, sizeof(block), &tosend, NULL) !=
483 talk_base::SR_EOS) {
484 rv = client_ssl_->Write(block, tosend, &sent, 0);
485
486 if (rv == talk_base::SR_SUCCESS) {
487 send_stream_.SetPosition(position + sent);
488 LOG(LS_VERBOSE) << "Sent: " << position + sent;
489 } else if (rv == talk_base::SR_BLOCK) {
490 LOG(LS_VERBOSE) << "Blocked...";
491 send_stream_.SetPosition(position);
492 break;
493 } else {
494 ADD_FAILURE();
495 break;
496 }
497 } else {
498 // Now close
499 LOG(LS_INFO) << "Wrote " << position << " bytes. Closing";
500 client_ssl_->Close();
501 break;
502 }
503 }
504 };
505
506 virtual void ReadData(talk_base::StreamInterface *stream) {
507 char buffer[1600];
508 size_t bread;
509 int err2;
510 talk_base::StreamResult r;
511
512 for (;;) {
513 r = stream->Read(buffer, sizeof(buffer), &bread, &err2);
514
515 if (r == talk_base::SR_ERROR || r == talk_base::SR_EOS) {
516 // Unfortunately, errors are the way that the stream adapter
517 // signals close in OpenSSL
518 stream->Close();
519 return;
520 }
521
522 if (r == talk_base::SR_BLOCK)
523 break;
524
525 ASSERT_EQ(talk_base::SR_SUCCESS, r);
526 LOG(LS_INFO) << "Read " << bread;
527
528 recv_stream_.Write(buffer, bread, NULL, NULL);
529 }
530 }
531
532 private:
533 talk_base::MemoryStream send_stream_;
534 talk_base::MemoryStream recv_stream_;
535};
536
537class SSLStreamAdapterTestDTLS : public SSLStreamAdapterTestBase {
538 public:
539 SSLStreamAdapterTestDTLS() :
540 SSLStreamAdapterTestBase("", "", true),
541 packet_size_(1000), count_(0), sent_(0) {
542 }
543
544 SSLStreamAdapterTestDTLS(const std::string& cert_pem,
545 const std::string& private_key_pem) :
546 SSLStreamAdapterTestBase(cert_pem, private_key_pem, true),
547 packet_size_(1000), count_(0), sent_(0) {
548 }
549
550 virtual void WriteData() {
551 unsigned char *packet = new unsigned char[1600];
552
553 do {
554 memset(packet, sent_ & 0xff, packet_size_);
555 *(reinterpret_cast<uint32_t *>(packet)) = sent_;
556
557 size_t sent;
558 int rv = client_ssl_->Write(packet, packet_size_, &sent, 0);
559 if (rv == talk_base::SR_SUCCESS) {
560 LOG(LS_VERBOSE) << "Sent: " << sent_;
561 sent_++;
562 } else if (rv == talk_base::SR_BLOCK) {
563 LOG(LS_VERBOSE) << "Blocked...";
564 break;
565 } else {
566 ADD_FAILURE();
567 break;
568 }
569 } while (sent_ < count_);
570
571 delete [] packet;
572 }
573
574 virtual void ReadData(talk_base::StreamInterface *stream) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000575 unsigned char buffer[2000];
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000576 size_t bread;
577 int err2;
578 talk_base::StreamResult r;
579
580 for (;;) {
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000581 r = stream->Read(buffer, 2000, &bread, &err2);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000582
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);
henrike@webrtc.org28654cb2013-07-22 21:07:49 +0000598 unsigned char* ptr_to_buffer = buffer;
599 uint32_t packet_num = *(reinterpret_cast<uint32_t *>(ptr_to_buffer));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000600
601 for (size_t i = 4; i < packet_size_; i++) {
602 ASSERT_EQ((packet_num & 0xff), buffer[i]);
603 }
604 received_.insert(packet_num);
605 }
606 }
607
608 virtual void TestTransfer(int count) {
609 count_ = count;
610
611 WriteData();
612
613 EXPECT_TRUE_WAIT(sent_ == count_, 10000);
614 LOG(LS_INFO) << "sent_ == " << sent_;
615
616 if (damage_) {
617 WAIT(false, 2000);
618 EXPECT_EQ(0U, received_.size());
619 } else if (loss_ == 0) {
620 EXPECT_EQ_WAIT(static_cast<size_t>(sent_), received_.size(), 1000);
621 } else {
622 LOG(LS_INFO) << "Sent " << sent_ << " packets; received " <<
623 received_.size();
624 }
625 };
626
627 private:
628 size_t packet_size_;
629 int count_;
630 int sent_;
631 std::set<int> received_;
632};
633
634
635talk_base::StreamResult SSLDummyStream::Write(const void* data, size_t data_len,
636 size_t* written, int* error) {
637 *written = data_len;
638
639 LOG(LS_INFO) << "Writing to loopback " << data_len;
640
641 if (first_packet_) {
642 first_packet_ = false;
643 if (test_->GetLoseFirstPacket()) {
644 LOG(LS_INFO) << "Losing initial packet of length " << data_len;
645 return talk_base::SR_SUCCESS;
646 }
647 }
648
649 return test_->DataWritten(this, data, data_len, written, error);
650
651 return talk_base::SR_SUCCESS;
652};
653
654class SSLStreamAdapterTestDTLSFromPEMStrings : public SSLStreamAdapterTestDTLS {
655 public:
656 SSLStreamAdapterTestDTLSFromPEMStrings() :
657 SSLStreamAdapterTestDTLS(kCERT_PEM, kRSA_PRIVATE_KEY_PEM) {
658 }
659};
660
661// Basic tests: TLS
662
663// Test that we cannot read/write if we have not yet handshaked.
664// This test only applies to NSS because OpenSSL has passthrough
665// semantics for I/O before the handshake is started.
666#if SSL_USE_NSS
667TEST_F(SSLStreamAdapterTestTLS, TestNoReadWriteBeforeConnect) {
668 talk_base::StreamResult rv;
669 char block[kBlockSize];
670 size_t dummy;
671
672 rv = client_ssl_->Write(block, sizeof(block), &dummy, NULL);
673 ASSERT_EQ(talk_base::SR_BLOCK, rv);
674
675 rv = client_ssl_->Read(block, sizeof(block), &dummy, NULL);
676 ASSERT_EQ(talk_base::SR_BLOCK, rv);
677}
678#endif
679
680
681// Test that we can make a handshake work
682TEST_F(SSLStreamAdapterTestTLS, TestTLSConnect) {
683 TestHandshake();
684};
685
686// Test transfer -- trivial
687TEST_F(SSLStreamAdapterTestTLS, TestTLSTransfer) {
688 TestHandshake();
689 TestTransfer(100000);
690};
691
692// Test read-write after close.
693TEST_F(SSLStreamAdapterTestTLS, ReadWriteAfterClose) {
694 TestHandshake();
695 TestTransfer(100000);
696 client_ssl_->Close();
697
698 talk_base::StreamResult rv;
699 char block[kBlockSize];
700 size_t dummy;
701
702 // It's an error to write after closed.
703 rv = client_ssl_->Write(block, sizeof(block), &dummy, NULL);
704 ASSERT_EQ(talk_base::SR_ERROR, rv);
705
706 // But after closed read gives you EOS.
707 rv = client_ssl_->Read(block, sizeof(block), &dummy, NULL);
708 ASSERT_EQ(talk_base::SR_EOS, rv);
709};
710
711// Test a handshake with a bogus peer digest
712TEST_F(SSLStreamAdapterTestTLS, TestTLSBogusDigest) {
713 SetPeerIdentitiesByDigest(false);
714 TestHandshake(false);
715};
716
717// Test a handshake with a peer certificate
718TEST_F(SSLStreamAdapterTestTLS, TestTLSPeerCertificate) {
719 SetPeerIdentitiesByCertificate(true);
720 TestHandshake();
721};
722
723// Test a handshake with a bogus peer certificate
724TEST_F(SSLStreamAdapterTestTLS, TestTLSBogusPeerCertificate) {
725 SetPeerIdentitiesByCertificate(false);
726 TestHandshake(false);
727};
728// Test moving a bunch of data
729
730// Basic tests: DTLS
731// Test that we can make a handshake work
732TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnect) {
733 MAYBE_SKIP_TEST(HaveDtls);
734 TestHandshake();
735};
736
737// Test that we can make a handshake work if the first packet in
738// each direction is lost. This gives us predictable loss
739// rather than having to tune random
740TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithLostFirstPacket) {
741 MAYBE_SKIP_TEST(HaveDtls);
742 SetLoseFirstPacket(true);
743 TestHandshake();
744};
745
746// Test a handshake with loss and delay
747TEST_F(SSLStreamAdapterTestDTLS,
748 TestDTLSConnectWithLostFirstPacketDelay2s) {
749 MAYBE_SKIP_TEST(HaveDtls);
750 SetLoseFirstPacket(true);
751 SetDelay(2000);
752 SetHandshakeWait(20000);
753 TestHandshake();
754};
755
756// Test a handshake with small MTU
757TEST_F(SSLStreamAdapterTestDTLS, TestDTLSConnectWithSmallMtu) {
758 MAYBE_SKIP_TEST(HaveDtls);
759 SetMtu(700);
760 SetHandshakeWait(20000);
761 TestHandshake();
762};
763
764// Test transfer -- trivial
765TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransfer) {
766 MAYBE_SKIP_TEST(HaveDtls);
767 TestHandshake();
768 TestTransfer(100);
769};
770
771TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithLoss) {
772 MAYBE_SKIP_TEST(HaveDtls);
773 TestHandshake();
774 SetLoss(10);
775 TestTransfer(100);
776};
777
778TEST_F(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) {
779 MAYBE_SKIP_TEST(HaveDtls);
780 SetDamage(); // Must be called first because first packet
781 // write happens at end of handshake.
782 TestHandshake();
783 TestTransfer(100);
784};
785
786// Test DTLS-SRTP with all high ciphers
787TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) {
788 MAYBE_SKIP_TEST(HaveDtlsSrtp);
789 std::vector<std::string> high;
790 high.push_back(kAES_CM_HMAC_SHA1_80);
791 SetDtlsSrtpCiphers(high, true);
792 SetDtlsSrtpCiphers(high, false);
793 TestHandshake();
794
795 std::string client_cipher;
796 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
797 std::string server_cipher;
798 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
799
800 ASSERT_EQ(client_cipher, server_cipher);
801 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_80);
802};
803
804// Test DTLS-SRTP with all low ciphers
805TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpLow) {
806 MAYBE_SKIP_TEST(HaveDtlsSrtp);
807 std::vector<std::string> low;
808 low.push_back(kAES_CM_HMAC_SHA1_32);
809 SetDtlsSrtpCiphers(low, true);
810 SetDtlsSrtpCiphers(low, false);
811 TestHandshake();
812
813 std::string client_cipher;
814 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
815 std::string server_cipher;
816 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
817
818 ASSERT_EQ(client_cipher, server_cipher);
819 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_32);
820};
821
822
823// Test DTLS-SRTP with a mismatch -- should not converge
824TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpHighLow) {
825 MAYBE_SKIP_TEST(HaveDtlsSrtp);
826 std::vector<std::string> high;
827 high.push_back(kAES_CM_HMAC_SHA1_80);
828 std::vector<std::string> low;
829 low.push_back(kAES_CM_HMAC_SHA1_32);
830 SetDtlsSrtpCiphers(high, true);
831 SetDtlsSrtpCiphers(low, false);
832 TestHandshake();
833
834 std::string client_cipher;
835 ASSERT_FALSE(GetDtlsSrtpCipher(true, &client_cipher));
836 std::string server_cipher;
837 ASSERT_FALSE(GetDtlsSrtpCipher(false, &server_cipher));
838};
839
840// Test DTLS-SRTP with each side being mixed -- should select high
841TEST_F(SSLStreamAdapterTestDTLS, TestDTLSSrtpMixed) {
842 MAYBE_SKIP_TEST(HaveDtlsSrtp);
843 std::vector<std::string> mixed;
844 mixed.push_back(kAES_CM_HMAC_SHA1_80);
845 mixed.push_back(kAES_CM_HMAC_SHA1_32);
846 SetDtlsSrtpCiphers(mixed, true);
847 SetDtlsSrtpCiphers(mixed, false);
848 TestHandshake();
849
850 std::string client_cipher;
851 ASSERT_TRUE(GetDtlsSrtpCipher(true, &client_cipher));
852 std::string server_cipher;
853 ASSERT_TRUE(GetDtlsSrtpCipher(false, &server_cipher));
854
855 ASSERT_EQ(client_cipher, server_cipher);
856 ASSERT_EQ(client_cipher, kAES_CM_HMAC_SHA1_80);
857};
858
859// Test an exporter
860TEST_F(SSLStreamAdapterTestDTLS, TestDTLSExporter) {
861 MAYBE_SKIP_TEST(HaveExporter);
862 TestHandshake();
863 unsigned char client_out[20];
864 unsigned char server_out[20];
865
866 bool result;
867 result = ExportKeyingMaterial(kExporterLabel,
868 kExporterContext, kExporterContextLen,
869 true, true,
870 client_out, sizeof(client_out));
871 ASSERT_TRUE(result);
872
873 result = ExportKeyingMaterial(kExporterLabel,
874 kExporterContext, kExporterContextLen,
875 true, false,
876 server_out, sizeof(server_out));
877 ASSERT_TRUE(result);
878
879 ASSERT_TRUE(!memcmp(client_out, server_out, sizeof(client_out)));
880}
881
882// Test data transfer using certs created from strings.
883TEST_F(SSLStreamAdapterTestDTLSFromPEMStrings, TestTransfer) {
884 MAYBE_SKIP_TEST(HaveDtls);
885 TestHandshake();
886 TestTransfer(100);
887}