tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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