Index: webrtc/base/sslstreamadapter_unittest.cc |
diff --git a/webrtc/base/sslstreamadapter_unittest.cc b/webrtc/base/sslstreamadapter_unittest.cc |
index 341e09ff1e7e1ef46aafff695b8352807dd00bf3..9e156c0b3c1df82c0c3791edd6888080c31e4516 100644 |
--- a/webrtc/base/sslstreamadapter_unittest.cc |
+++ b/webrtc/base/sslstreamadapter_unittest.cc |
@@ -325,36 +325,44 @@ class SSLStreamAdapterTestBase : public testing::Test, |
} |
} |
- void SetPeerIdentitiesByDigest(bool correct) { |
- unsigned char digest[20]; |
- size_t digest_len; |
+ void SetPeerIdentitiesByDigest(bool correct, bool expect_success) { |
+ unsigned char server_digest[20]; |
+ size_t server_digest_len; |
+ unsigned char client_digest[20]; |
+ size_t client_digest_len; |
bool rv; |
+ rtc::SSLPeerCertificateDigestError err; |
+ rtc::SSLPeerCertificateDigestError expected_err = |
+ expect_success |
+ ? rtc::SSLPeerCertificateDigestError::NONE |
+ : rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED; |
LOG(LS_INFO) << "Setting peer identities by digest"; |
- rv = server_identity_->certificate().ComputeDigest(rtc::DIGEST_SHA_1, |
- digest, 20, |
- &digest_len); |
+ rv = server_identity_->certificate().ComputeDigest( |
+ rtc::DIGEST_SHA_1, server_digest, 20, &server_digest_len); |
ASSERT_TRUE(rv); |
+ rv = client_identity_->certificate().ComputeDigest( |
+ rtc::DIGEST_SHA_1, client_digest, 20, &client_digest_len); |
+ ASSERT_TRUE(rv); |
+ |
if (!correct) { |
LOG(LS_INFO) << "Setting bogus digest for server cert"; |
- digest[0]++; |
+ server_digest[0]++; |
} |
- rv = client_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest, |
- digest_len); |
- ASSERT_TRUE(rv); |
+ rv = client_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, server_digest, |
+ server_digest_len, &err); |
+ EXPECT_EQ(expected_err, err); |
+ EXPECT_EQ(expect_success, rv); |
- |
- rv = client_identity_->certificate().ComputeDigest(rtc::DIGEST_SHA_1, |
- digest, 20, &digest_len); |
- ASSERT_TRUE(rv); |
if (!correct) { |
LOG(LS_INFO) << "Setting bogus digest for client cert"; |
- digest[0]++; |
+ client_digest[0]++; |
} |
- rv = server_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, digest, |
- digest_len); |
- ASSERT_TRUE(rv); |
+ rv = server_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, client_digest, |
+ client_digest_len, &err); |
+ EXPECT_EQ(expected_err, err); |
+ EXPECT_EQ(expect_success, rv); |
identities_set_ = true; |
} |
@@ -379,7 +387,7 @@ class SSLStreamAdapterTestBase : public testing::Test, |
} |
if (!identities_set_) |
- SetPeerIdentitiesByDigest(true); |
+ SetPeerIdentitiesByDigest(true, true); |
// Start the handshake |
int rv; |
@@ -402,6 +410,57 @@ class SSLStreamAdapterTestBase : public testing::Test, |
} |
} |
+ // This tests that the handshake can complete before the identity is |
+ // verified, and the identity will be verified after the fact. |
+ void TestHandshakeWithDelayedIdentity(bool valid_identity) { |
+ server_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); |
+ client_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); |
+ |
+ if (!dtls_) { |
+ // Make sure we simulate a reliable network for TLS. |
+ // This is just a check to make sure that people don't write wrong |
+ // tests. |
+ ASSERT((mtu_ == 1460) && (loss_ == 0) && (lose_first_packet_ == 0)); |
+ } |
+ |
+ // Start the handshake |
+ int rv; |
+ |
+ server_ssl_->SetServerRole(); |
+ rv = server_ssl_->StartSSL(); |
+ ASSERT_EQ(0, rv); |
+ |
+ rv = client_ssl_->StartSSL(); |
+ ASSERT_EQ(0, rv); |
+ |
+ // Now run the handshake. |
+ EXPECT_TRUE_WAIT( |
+ client_ssl_->IsTlsConnected() && server_ssl_->IsTlsConnected(), |
+ handshake_wait_); |
+ |
+ // Until the identity has been verified, the state should still be |
+ // SS_OPENING and writes should return SR_BLOCK. |
+ EXPECT_EQ(rtc::SS_OPENING, client_ssl_->GetState()); |
+ EXPECT_EQ(rtc::SS_OPENING, server_ssl_->GetState()); |
+ unsigned char packet[1]; |
+ size_t sent; |
+ EXPECT_EQ(rtc::SR_BLOCK, client_ssl_->Write(&packet, 1, &sent, 0)); |
+ EXPECT_EQ(rtc::SR_BLOCK, server_ssl_->Write(&packet, 1, &sent, 0)); |
+ |
+ // If we set an invalid identity at this point, SetPeerCertificateDigest |
+ // should return false. |
+ SetPeerIdentitiesByDigest(valid_identity, valid_identity); |
+ // State should then transition to SS_OPEN or SS_CLOSED based on validation |
+ // of the identity. |
+ if (valid_identity) { |
+ EXPECT_EQ(rtc::SS_OPEN, client_ssl_->GetState()); |
+ EXPECT_EQ(rtc::SS_OPEN, server_ssl_->GetState()); |
+ } else { |
+ EXPECT_EQ(rtc::SS_CLOSED, client_ssl_->GetState()); |
+ EXPECT_EQ(rtc::SS_CLOSED, server_ssl_->GetState()); |
+ } |
+ } |
+ |
rtc::StreamResult DataWritten(SSLDummyStreamBase *from, const void *data, |
size_t data_len, size_t *written, |
int *error) { |
@@ -849,10 +908,55 @@ TEST_P(SSLStreamAdapterTestTLS, ReadWriteAfterClose) { |
// Test a handshake with a bogus peer digest |
TEST_P(SSLStreamAdapterTestTLS, TestTLSBogusDigest) { |
- SetPeerIdentitiesByDigest(false); |
+ SetPeerIdentitiesByDigest(false, true); |
TestHandshake(false); |
}; |
+TEST_P(SSLStreamAdapterTestTLS, TestTLSDelayedIdentity) { |
+ TestHandshakeWithDelayedIdentity(true); |
+}; |
+ |
+TEST_P(SSLStreamAdapterTestTLS, TestTLSDelayedIdentityWithBogusDigest) { |
+ TestHandshakeWithDelayedIdentity(false); |
+}; |
+ |
+// Test that the correct error is returned when SetPeerCertificateDigest is |
+// called with an unknown algorithm. |
+TEST_P(SSLStreamAdapterTestTLS, |
+ TestSetPeerCertificateDigestWithUnknownAlgorithm) { |
+ unsigned char server_digest[20]; |
+ size_t server_digest_len; |
+ bool rv; |
+ rtc::SSLPeerCertificateDigestError err; |
+ |
+ rv = server_identity_->certificate().ComputeDigest( |
+ rtc::DIGEST_SHA_1, server_digest, 20, &server_digest_len); |
+ ASSERT_TRUE(rv); |
+ |
+ rv = client_ssl_->SetPeerCertificateDigest("unknown algorithm", server_digest, |
+ server_digest_len, &err); |
+ EXPECT_EQ(rtc::SSLPeerCertificateDigestError::UNKNOWN_ALGORITHM, err); |
+ EXPECT_FALSE(rv); |
+} |
+ |
+// Test that the correct error is returned when SetPeerCertificateDigest is |
+// called with an invalid digest length. |
+TEST_P(SSLStreamAdapterTestTLS, TestSetPeerCertificateDigestWithInvalidLength) { |
+ unsigned char server_digest[20]; |
+ size_t server_digest_len; |
+ bool rv; |
+ rtc::SSLPeerCertificateDigestError err; |
+ |
+ rv = server_identity_->certificate().ComputeDigest( |
+ rtc::DIGEST_SHA_1, server_digest, 20, &server_digest_len); |
+ ASSERT_TRUE(rv); |
+ |
+ rv = client_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, server_digest, |
+ server_digest_len - 1, &err); |
+ EXPECT_EQ(rtc::SSLPeerCertificateDigestError::INVALID_LENGTH, err); |
+ EXPECT_FALSE(rv); |
+} |
+ |
// Test moving a bunch of data |
// Basic tests: DTLS |
@@ -911,6 +1015,14 @@ TEST_P(SSLStreamAdapterTestDTLS, TestDTLSTransferWithDamage) { |
TestTransfer(100); |
}; |
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSDelayedIdentity) { |
+ TestHandshakeWithDelayedIdentity(true); |
+}; |
+ |
+TEST_P(SSLStreamAdapterTestDTLS, TestDTLSDelayedIdentityWithBogusDigest) { |
+ TestHandshakeWithDelayedIdentity(false); |
+}; |
+ |
// Test DTLS-SRTP with all high ciphers |
TEST_P(SSLStreamAdapterTestDTLS, TestDTLSSrtpHigh) { |
MAYBE_SKIP_TEST(HaveDtlsSrtp); |