ssl_cert_ext_unittest.cc (9277B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ssl.h" 8 #include "sslerr.h" 9 #include "sslproto.h" 10 11 #include <memory> 12 13 #include "tls_connect.h" 14 #include "tls_filter.h" 15 #include "tls_parser.h" 16 17 namespace nss_test { 18 19 // Tests for Certificate Transparency (RFC 6962) 20 // These don't work with TLS 1.3: see bug 1252745. 21 22 // Helper class - stores signed certificate timestamps as provided 23 // by the relevant callbacks on the client. 24 class SignedCertificateTimestampsExtractor { 25 public: 26 SignedCertificateTimestampsExtractor(std::shared_ptr<TlsAgent>& client) 27 : client_(client) { 28 client->SetAuthCertificateCallback( 29 [this](TlsAgent* agent, bool checksig, bool isServer) -> SECStatus { 30 const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd()); 31 EXPECT_TRUE(scts); 32 if (!scts) { 33 return SECFailure; 34 } 35 auth_timestamps_.reset(new DataBuffer(scts->data, scts->len)); 36 return SECSuccess; 37 }); 38 client->SetHandshakeCallback([this](TlsAgent* agent) { 39 const SECItem* scts = SSL_PeerSignedCertTimestamps(agent->ssl_fd()); 40 ASSERT_TRUE(scts); 41 handshake_timestamps_.reset(new DataBuffer(scts->data, scts->len)); 42 }); 43 } 44 45 void assertTimestamps(const DataBuffer& timestamps) { 46 ASSERT_NE(nullptr, auth_timestamps_); 47 EXPECT_EQ(timestamps, *auth_timestamps_); 48 49 ASSERT_NE(nullptr, handshake_timestamps_); 50 EXPECT_EQ(timestamps, *handshake_timestamps_); 51 52 const SECItem* current = 53 SSL_PeerSignedCertTimestamps(client_.lock()->ssl_fd()); 54 EXPECT_EQ(timestamps, DataBuffer(current->data, current->len)); 55 } 56 57 private: 58 std::weak_ptr<TlsAgent> client_; 59 std::unique_ptr<DataBuffer> auth_timestamps_; 60 std::unique_ptr<DataBuffer> handshake_timestamps_; 61 }; 62 63 static const uint8_t kSctValue[] = {0x01, 0x23, 0x45, 0x67, 0x89}; 64 static const SECItem kSctItem = {siBuffer, const_cast<uint8_t*>(kSctValue), 65 sizeof(kSctValue)}; 66 static const DataBuffer kSctBuffer(kSctValue, sizeof(kSctValue)); 67 static const SSLExtraServerCertData kExtraSctData = { 68 ssl_auth_null, nullptr, nullptr, &kSctItem, nullptr, nullptr}; 69 70 // Test timestamps extraction during a successful handshake. 71 TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsLegacy) { 72 EnsureTlsSetup(); 73 74 // We have to use the legacy API consistently here for configuring certs. 75 // Also, this doesn't work in TLS 1.3 because this only configures the SCT for 76 // RSA decrypt and PKCS#1 signing, not PSS. 77 ScopedCERTCertificate cert; 78 ScopedSECKEYPrivateKey priv; 79 ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsa, &cert, &priv)); 80 EXPECT_EQ(SECSuccess, SSL_ConfigSecureServerWithCertChain( 81 server_->ssl_fd(), cert.get(), nullptr, priv.get(), 82 ssl_kea_rsa)); 83 EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(), 84 &kSctItem, ssl_kea_rsa)); 85 86 client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE); 87 SignedCertificateTimestampsExtractor timestamps_extractor(client_); 88 89 Connect(); 90 91 timestamps_extractor.assertTimestamps(kSctBuffer); 92 } 93 94 TEST_P(TlsConnectGeneric, SignedCertificateTimestampsSuccess) { 95 EnsureTlsSetup(); 96 EXPECT_TRUE( 97 server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData)); 98 client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE); 99 SignedCertificateTimestampsExtractor timestamps_extractor(client_); 100 101 Connect(); 102 103 timestamps_extractor.assertTimestamps(kSctBuffer); 104 } 105 106 // Test SSL_PeerSignedCertTimestamps returning zero-length SECItem 107 // when the client / the server / both have not enabled the feature. 108 TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveClient) { 109 EnsureTlsSetup(); 110 EXPECT_TRUE( 111 server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData)); 112 SignedCertificateTimestampsExtractor timestamps_extractor(client_); 113 114 Connect(); 115 timestamps_extractor.assertTimestamps(DataBuffer()); 116 } 117 118 TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveServer) { 119 EnsureTlsSetup(); 120 client_->SetOption(SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE); 121 SignedCertificateTimestampsExtractor timestamps_extractor(client_); 122 123 Connect(); 124 timestamps_extractor.assertTimestamps(DataBuffer()); 125 } 126 127 TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveBoth) { 128 EnsureTlsSetup(); 129 SignedCertificateTimestampsExtractor timestamps_extractor(client_); 130 131 Connect(); 132 timestamps_extractor.assertTimestamps(DataBuffer()); 133 } 134 135 // Check that the given agent doesn't have an OCSP response for its peer. 136 static SECStatus CheckNoOCSP(TlsAgent* agent, bool checksig, bool isServer) { 137 const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd()); 138 EXPECT_TRUE(ocsp); 139 EXPECT_EQ(0U, ocsp->len); 140 return SECSuccess; 141 } 142 143 static const uint8_t kOcspValue1[] = {1, 2, 3, 4, 5, 6}; 144 static const uint8_t kOcspValue2[] = {7, 8, 9}; 145 static const SECItem kOcspItems[] = { 146 {siBuffer, const_cast<uint8_t*>(kOcspValue1), sizeof(kOcspValue1)}, 147 {siBuffer, const_cast<uint8_t*>(kOcspValue2), sizeof(kOcspValue2)}}; 148 static const SECItemArray kOcspResponses = {const_cast<SECItem*>(kOcspItems), 149 PR_ARRAY_SIZE(kOcspItems)}; 150 const static SSLExtraServerCertData kOcspExtraData = { 151 ssl_auth_null, nullptr, &kOcspResponses, nullptr, nullptr, nullptr}; 152 153 TEST_P(TlsConnectGeneric, NoOcsp) { 154 EnsureTlsSetup(); 155 client_->SetAuthCertificateCallback(CheckNoOCSP); 156 Connect(); 157 } 158 159 // The client doesn't get OCSP stapling unless it asks. 160 TEST_P(TlsConnectGeneric, OcspNotRequested) { 161 EnsureTlsSetup(); 162 client_->SetAuthCertificateCallback(CheckNoOCSP); 163 EXPECT_TRUE( 164 server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData)); 165 Connect(); 166 } 167 168 // Even if the client asks, the server has nothing unless it is configured. 169 TEST_P(TlsConnectGeneric, OcspNotProvided) { 170 EnsureTlsSetup(); 171 client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE); 172 client_->SetAuthCertificateCallback(CheckNoOCSP); 173 Connect(); 174 } 175 176 TEST_P(TlsConnectGenericPre13, OcspMangled) { 177 EnsureTlsSetup(); 178 client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE); 179 EXPECT_TRUE( 180 server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData)); 181 182 static const uint8_t val[] = {1}; 183 auto replacer = MakeTlsFilter<TlsExtensionReplacer>( 184 server_, ssl_cert_status_xtn, DataBuffer(val, sizeof(val))); 185 ConnectExpectAlert(client_, kTlsAlertIllegalParameter); 186 client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO); 187 server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT); 188 } 189 190 TEST_P(TlsConnectGeneric, OcspSuccess) { 191 EnsureTlsSetup(); 192 client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE); 193 auto capture_ocsp = 194 MakeTlsFilter<TlsExtensionCapture>(server_, ssl_cert_status_xtn); 195 196 // The value should be available during the AuthCertificateCallback 197 client_->SetAuthCertificateCallback([](TlsAgent* agent, bool checksig, 198 bool isServer) -> SECStatus { 199 const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd()); 200 if (!ocsp) { 201 return SECFailure; 202 } 203 EXPECT_EQ(1U, ocsp->len) << "We only provide the first item"; 204 EXPECT_EQ(0, SECITEM_CompareItem(&kOcspItems[0], &ocsp->items[0])); 205 return SECSuccess; 206 }); 207 EXPECT_TRUE( 208 server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kOcspExtraData)); 209 210 Connect(); 211 // In TLS 1.3, the server doesn't provide a visible ServerHello extension. 212 // For earlier versions, the extension is just empty. 213 EXPECT_EQ(0U, capture_ocsp->extension().len()); 214 } 215 216 TEST_P(TlsConnectGeneric, OcspHugeSuccess) { 217 EnsureTlsSetup(); 218 client_->SetOption(SSL_ENABLE_OCSP_STAPLING, PR_TRUE); 219 220 uint8_t hugeOcspValue[16385]; 221 memset(hugeOcspValue, 0xa1, sizeof(hugeOcspValue)); 222 const SECItem hugeOcspItems[] = { 223 {siBuffer, const_cast<uint8_t*>(hugeOcspValue), sizeof(hugeOcspValue)}}; 224 const SECItemArray hugeOcspResponses = {const_cast<SECItem*>(hugeOcspItems), 225 PR_ARRAY_SIZE(hugeOcspItems)}; 226 const SSLExtraServerCertData hugeOcspExtraData = { 227 ssl_auth_null, nullptr, &hugeOcspResponses, nullptr, nullptr, nullptr}; 228 229 // The value should be available during the AuthCertificateCallback 230 client_->SetAuthCertificateCallback([&](TlsAgent* agent, bool checksig, 231 bool isServer) -> SECStatus { 232 const SECItemArray* ocsp = SSL_PeerStapledOCSPResponses(agent->ssl_fd()); 233 if (!ocsp) { 234 return SECFailure; 235 } 236 EXPECT_EQ(1U, ocsp->len) << "We only provide the first item"; 237 EXPECT_EQ(0, SECITEM_CompareItem(&hugeOcspItems[0], &ocsp->items[0])); 238 return SECSuccess; 239 }); 240 EXPECT_TRUE(server_->ConfigServerCert(TlsAgent::kServerRsa, true, 241 &hugeOcspExtraData)); 242 243 Connect(); 244 } 245 246 } // namespace nss_test