tor-browser

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

ssl_custext_unittest.cc (18654B)


      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 "ssl3prot.h"
      9 #include "sslerr.h"
     10 #include "sslproto.h"
     11 #include "sslexp.h"
     12 
     13 #include <memory>
     14 
     15 #include "tls_connect.h"
     16 
     17 namespace nss_test {
     18 
     19 static void IncrementCounterArg(void *arg) {
     20  if (arg) {
     21    auto *called = reinterpret_cast<size_t *>(arg);
     22    ++*called;
     23  }
     24 }
     25 
     26 static PRBool NoopExtensionWriter(PRFileDesc *fd, SSLHandshakeType message,
     27                                  PRUint8 *data, unsigned int *len,
     28                                  unsigned int maxLen, void *arg) {
     29  IncrementCounterArg(arg);
     30  return PR_FALSE;
     31 }
     32 
     33 static PRBool EmptyExtensionWriter(PRFileDesc *fd, SSLHandshakeType message,
     34                                   PRUint8 *data, unsigned int *len,
     35                                   unsigned int maxLen, void *arg) {
     36  IncrementCounterArg(arg);
     37  return PR_TRUE;
     38 }
     39 
     40 static SECStatus NoopExtensionHandler(PRFileDesc *fd, SSLHandshakeType message,
     41                                      const PRUint8 *data, unsigned int len,
     42                                      SSLAlertDescription *alert, void *arg) {
     43  return SECSuccess;
     44 }
     45 
     46 // All of the (current) set of supported extensions, plus a few extra.
     47 static const uint16_t kManyExtensions[] = {
     48    ssl_server_name_xtn,
     49    ssl_cert_status_xtn,
     50    ssl_supported_groups_xtn,
     51    ssl_ec_point_formats_xtn,
     52    ssl_signature_algorithms_xtn,
     53    ssl_signature_algorithms_cert_xtn,
     54    ssl_use_srtp_xtn,
     55    ssl_app_layer_protocol_xtn,
     56    ssl_signed_cert_timestamp_xtn,
     57    ssl_padding_xtn,
     58    ssl_extended_master_secret_xtn,
     59    ssl_certificate_compression_xtn,
     60    ssl_session_ticket_xtn,
     61    ssl_tls13_key_share_xtn,
     62    ssl_tls13_pre_shared_key_xtn,
     63    ssl_tls13_early_data_xtn,
     64    ssl_tls13_supported_versions_xtn,
     65    ssl_tls13_cookie_xtn,
     66    ssl_tls13_psk_key_exchange_modes_xtn,
     67    ssl_tls13_ticket_early_data_info_xtn,
     68    ssl_tls13_certificate_authorities_xtn,
     69    ssl_next_proto_nego_xtn,
     70    ssl_renegotiation_info_xtn,
     71    ssl_record_size_limit_xtn,
     72    ssl_tls13_encrypted_client_hello_xtn,
     73    1,
     74    0xffff};
     75 // The list here includes all extensions we expect to use (SSL_MAX_EXTENSIONS),
     76 // plus the deprecated values (see sslt.h), and two extra dummy values.
     77 PR_STATIC_ASSERT((SSL_MAX_EXTENSIONS + 5) == PR_ARRAY_SIZE(kManyExtensions));
     78 
     79 void InstallManyWriters(std::shared_ptr<TlsAgent> agent,
     80                        SSLExtensionWriter writer, size_t *installed = nullptr,
     81                        size_t *called = nullptr) {
     82  for (size_t i = 0; i < PR_ARRAY_SIZE(kManyExtensions); ++i) {
     83    SSLExtensionSupport support = ssl_ext_none;
     84    SECStatus rv = SSL_GetExtensionSupport(kManyExtensions[i], &support);
     85    ASSERT_EQ(SECSuccess, rv) << "SSL_GetExtensionSupport cannot fail";
     86 
     87    rv = SSL_InstallExtensionHooks(agent->ssl_fd(), kManyExtensions[i], writer,
     88                                   called, NoopExtensionHandler, nullptr);
     89    if (support == ssl_ext_native_only) {
     90      EXPECT_EQ(SECFailure, rv);
     91      EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
     92    } else {
     93      if (installed) {
     94        ++*installed;
     95      }
     96      EXPECT_EQ(SECSuccess, rv);
     97    }
     98  }
     99 }
    100 
    101 TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopClient) {
    102  EnsureTlsSetup();
    103  size_t installed = 0;
    104  size_t called = 0;
    105  InstallManyWriters(client_, NoopExtensionWriter, &installed, &called);
    106  EXPECT_LT(0U, installed);
    107  Connect();
    108  EXPECT_EQ(installed, called);
    109 }
    110 
    111 TEST_F(TlsConnectStreamTls13, CustomExtensionAllNoopServer) {
    112  EnsureTlsSetup();
    113  size_t installed = 0;
    114  size_t called = 0;
    115  InstallManyWriters(server_, NoopExtensionWriter, &installed, &called);
    116  EXPECT_LT(0U, installed);
    117  Connect();
    118  // Extension writers are all called for each of ServerHello,
    119  // EncryptedExtensions, and Certificate.
    120  EXPECT_EQ(installed * 3, called);
    121 }
    122 
    123 TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterClient) {
    124  EnsureTlsSetup();
    125  InstallManyWriters(client_, EmptyExtensionWriter);
    126  InstallManyWriters(server_, EmptyExtensionWriter);
    127  Connect();
    128 }
    129 
    130 TEST_F(TlsConnectStreamTls13, CustomExtensionEmptyWriterServer) {
    131  EnsureTlsSetup();
    132  InstallManyWriters(server_, EmptyExtensionWriter);
    133  // Sending extensions that the client doesn't expect leads to extensions
    134  // appearing even if the client didn't send one, or in the wrong messages.
    135  client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
    136  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    137  ConnectExpectFail();
    138 }
    139 
    140 // Install an writer to disable sending of a natively-supported extension.
    141 TEST_F(TlsConnectStreamTls13, CustomExtensionWriterDisable) {
    142  EnsureTlsSetup();
    143 
    144  // This option enables sending the extension via the native support.
    145  SECStatus rv = SSL_OptionSet(client_->ssl_fd(),
    146                               SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE);
    147  EXPECT_EQ(SECSuccess, rv);
    148 
    149  // This installs an override that doesn't do anything.  You have to specify
    150  // something; passing all nullptr values removes an existing handler.
    151  rv = SSL_InstallExtensionHooks(
    152      client_->ssl_fd(), ssl_signed_cert_timestamp_xtn, NoopExtensionWriter,
    153      nullptr, NoopExtensionHandler, nullptr);
    154  EXPECT_EQ(SECSuccess, rv);
    155  auto capture = MakeTlsFilter<TlsExtensionCapture>(
    156      client_, ssl_signed_cert_timestamp_xtn);
    157 
    158  Connect();
    159  // So nothing will be sent.
    160  EXPECT_FALSE(capture->captured());
    161 }
    162 
    163 // An extension that is unlikely to be parsed as valid.
    164 static uint8_t kNonsenseExtension[] = {91, 82, 73, 64, 55, 46, 37, 28, 19};
    165 
    166 static PRBool NonsenseExtensionWriter(PRFileDesc *fd, SSLHandshakeType message,
    167                                      PRUint8 *data, unsigned int *len,
    168                                      unsigned int maxLen, void *arg) {
    169  TlsAgent *agent = reinterpret_cast<TlsAgent *>(arg);
    170  EXPECT_NE(nullptr, agent);
    171  EXPECT_NE(nullptr, data);
    172  EXPECT_NE(nullptr, len);
    173  EXPECT_EQ(0U, *len);
    174  EXPECT_LT(0U, maxLen);
    175  EXPECT_EQ(agent->ssl_fd(), fd);
    176 
    177  if (message != ssl_hs_client_hello && message != ssl_hs_server_hello &&
    178      message != ssl_hs_encrypted_extensions) {
    179    return PR_FALSE;
    180  }
    181 
    182  *len = static_cast<unsigned int>(sizeof(kNonsenseExtension));
    183  EXPECT_GE(maxLen, *len);
    184  if (maxLen < *len) {
    185    return PR_FALSE;
    186  }
    187  PORT_Memcpy(data, kNonsenseExtension, *len);
    188  return PR_TRUE;
    189 }
    190 
    191 // Override the extension handler for an natively-supported and produce
    192 // nonsense, which results in a handshake failure.
    193 TEST_F(TlsConnectStreamTls13, CustomExtensionOverride) {
    194  EnsureTlsSetup();
    195 
    196  // This option enables sending the extension via the native support.
    197  SECStatus rv = SSL_OptionSet(client_->ssl_fd(),
    198                               SSL_ENABLE_SIGNED_CERT_TIMESTAMPS, PR_TRUE);
    199  EXPECT_EQ(SECSuccess, rv);
    200 
    201  // This installs an override that sends nonsense.
    202  rv = SSL_InstallExtensionHooks(
    203      client_->ssl_fd(), ssl_signed_cert_timestamp_xtn, NonsenseExtensionWriter,
    204      client_.get(), NoopExtensionHandler, nullptr);
    205  EXPECT_EQ(SECSuccess, rv);
    206 
    207  // Capture it to see what we got.
    208  auto capture = MakeTlsFilter<TlsExtensionCapture>(
    209      client_, ssl_signed_cert_timestamp_xtn);
    210 
    211  ConnectExpectAlert(server_, kTlsAlertDecodeError);
    212 
    213  EXPECT_TRUE(capture->captured());
    214  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    215            capture->extension());
    216 }
    217 
    218 static SECStatus NonsenseExtensionHandler(PRFileDesc *fd,
    219                                          SSLHandshakeType message,
    220                                          const PRUint8 *data, unsigned int len,
    221                                          SSLAlertDescription *alert,
    222                                          void *arg) {
    223  TlsAgent *agent = reinterpret_cast<TlsAgent *>(arg);
    224  EXPECT_EQ(agent->ssl_fd(), fd);
    225  if (agent->role() == TlsAgent::SERVER) {
    226    EXPECT_EQ(ssl_hs_client_hello, message);
    227  } else {
    228    EXPECT_TRUE(message == ssl_hs_server_hello ||
    229                message == ssl_hs_encrypted_extensions);
    230  }
    231  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    232            DataBuffer(data, len));
    233  EXPECT_NE(nullptr, alert);
    234  return SECSuccess;
    235 }
    236 
    237 // Send nonsense in an extension from client to server.
    238 TEST_F(TlsConnectStreamTls13, CustomExtensionClientToServer) {
    239  EnsureTlsSetup();
    240 
    241  // This installs an override that sends nonsense.
    242  const uint16_t extension_code = 0xffe5;
    243  SECStatus rv = SSL_InstallExtensionHooks(
    244      client_->ssl_fd(), extension_code, NonsenseExtensionWriter, client_.get(),
    245      NoopExtensionHandler, nullptr);
    246  EXPECT_EQ(SECSuccess, rv);
    247 
    248  // Capture it to see what we got.
    249  auto capture = MakeTlsFilter<TlsExtensionCapture>(client_, extension_code);
    250 
    251  // Handle it so that the handshake completes.
    252  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    253                                 NoopExtensionWriter, nullptr,
    254                                 NonsenseExtensionHandler, server_.get());
    255  EXPECT_EQ(SECSuccess, rv);
    256 
    257  Connect();
    258 
    259  EXPECT_TRUE(capture->captured());
    260  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    261            capture->extension());
    262 }
    263 
    264 static PRBool NonsenseExtensionWriterSH(PRFileDesc *fd,
    265                                        SSLHandshakeType message, PRUint8 *data,
    266                                        unsigned int *len, unsigned int maxLen,
    267                                        void *arg) {
    268  if (message == ssl_hs_server_hello) {
    269    return NonsenseExtensionWriter(fd, message, data, len, maxLen, arg);
    270  }
    271  return PR_FALSE;
    272 }
    273 
    274 // Send nonsense in an extension from server to client, in ServerHello.
    275 TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientSH) {
    276  EnsureTlsSetup();
    277 
    278  // This installs an override that sends nothing but expects nonsense.
    279  const uint16_t extension_code = 0xff5e;
    280  SECStatus rv = SSL_InstallExtensionHooks(
    281      client_->ssl_fd(), extension_code, EmptyExtensionWriter, nullptr,
    282      NonsenseExtensionHandler, client_.get());
    283  EXPECT_EQ(SECSuccess, rv);
    284 
    285  // Have the server send nonsense.
    286  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    287                                 NonsenseExtensionWriterSH, server_.get(),
    288                                 NoopExtensionHandler, nullptr);
    289  EXPECT_EQ(SECSuccess, rv);
    290 
    291  // Capture the extension from the ServerHello only and check it.
    292  auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code);
    293  capture->SetHandshakeTypes({kTlsHandshakeServerHello});
    294 
    295  Connect();
    296 
    297  EXPECT_TRUE(capture->captured());
    298  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    299            capture->extension());
    300 }
    301 
    302 static PRBool NonsenseExtensionWriterEE(PRFileDesc *fd,
    303                                        SSLHandshakeType message, PRUint8 *data,
    304                                        unsigned int *len, unsigned int maxLen,
    305                                        void *arg) {
    306  if (message == ssl_hs_encrypted_extensions) {
    307    return NonsenseExtensionWriter(fd, message, data, len, maxLen, arg);
    308  }
    309  return PR_FALSE;
    310 }
    311 
    312 // Send nonsense in an extension from server to client, in EncryptedExtensions.
    313 TEST_F(TlsConnectStreamTls13, CustomExtensionServerToClientEE) {
    314  EnsureTlsSetup();
    315 
    316  // This installs an override that sends nothing but expects nonsense.
    317  const uint16_t extension_code = 0xff5e;
    318  SECStatus rv = SSL_InstallExtensionHooks(
    319      client_->ssl_fd(), extension_code, EmptyExtensionWriter, nullptr,
    320      NonsenseExtensionHandler, client_.get());
    321  EXPECT_EQ(SECSuccess, rv);
    322 
    323  // Have the server send nonsense.
    324  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    325                                 NonsenseExtensionWriterEE, server_.get(),
    326                                 NoopExtensionHandler, nullptr);
    327  EXPECT_EQ(SECSuccess, rv);
    328 
    329  // Capture the extension from the EncryptedExtensions only and check it.
    330  auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code);
    331  capture->SetHandshakeTypes({kTlsHandshakeEncryptedExtensions});
    332  capture->EnableDecryption();
    333 
    334  Connect();
    335 
    336  EXPECT_TRUE(capture->captured());
    337  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    338            capture->extension());
    339 }
    340 
    341 TEST_F(TlsConnectStreamTls13, CustomExtensionUnsolicitedServer) {
    342  EnsureTlsSetup();
    343 
    344  const uint16_t extension_code = 0xff5e;
    345  SECStatus rv = SSL_InstallExtensionHooks(
    346      server_->ssl_fd(), extension_code, NonsenseExtensionWriter, server_.get(),
    347      NoopExtensionHandler, nullptr);
    348  EXPECT_EQ(SECSuccess, rv);
    349 
    350  // Capture it to see what we got.
    351  auto capture = MakeTlsFilter<TlsExtensionCapture>(server_, extension_code);
    352 
    353  client_->ExpectSendAlert(kTlsAlertUnsupportedExtension);
    354  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    355  ConnectExpectFail();
    356 
    357  EXPECT_TRUE(capture->captured());
    358  EXPECT_EQ(DataBuffer(kNonsenseExtension, sizeof(kNonsenseExtension)),
    359            capture->extension());
    360 }
    361 
    362 SECStatus RejectExtensionHandler(PRFileDesc *fd, SSLHandshakeType message,
    363                                 const PRUint8 *data, unsigned int len,
    364                                 SSLAlertDescription *alert, void *arg) {
    365  return SECFailure;
    366 }
    367 
    368 TEST_F(TlsConnectStreamTls13, CustomExtensionServerReject) {
    369  EnsureTlsSetup();
    370 
    371  // This installs an override that sends nonsense.
    372  const uint16_t extension_code = 0xffe7;
    373  SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code,
    374                                           EmptyExtensionWriter, nullptr,
    375                                           NoopExtensionHandler, nullptr);
    376  EXPECT_EQ(SECSuccess, rv);
    377 
    378  // Reject the extension for no good reason.
    379  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    380                                 NoopExtensionWriter, nullptr,
    381                                 RejectExtensionHandler, nullptr);
    382  EXPECT_EQ(SECSuccess, rv);
    383 
    384  ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
    385 }
    386 
    387 // Send nonsense in an extension from client to server.
    388 TEST_F(TlsConnectStreamTls13, CustomExtensionClientReject) {
    389  EnsureTlsSetup();
    390 
    391  // This installs an override that sends nothing but expects nonsense.
    392  const uint16_t extension_code = 0xff58;
    393  SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code,
    394                                           EmptyExtensionWriter, nullptr,
    395                                           RejectExtensionHandler, nullptr);
    396  EXPECT_EQ(SECSuccess, rv);
    397 
    398  // Have the server send nonsense.
    399  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    400                                 EmptyExtensionWriter, nullptr,
    401                                 NoopExtensionHandler, nullptr);
    402  EXPECT_EQ(SECSuccess, rv);
    403 
    404  client_->ExpectSendAlert(kTlsAlertHandshakeFailure);
    405  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    406  ConnectExpectFail();
    407 }
    408 
    409 static const uint8_t kCustomAlert = 0xf6;
    410 
    411 SECStatus AlertExtensionHandler(PRFileDesc *fd, SSLHandshakeType message,
    412                                const PRUint8 *data, unsigned int len,
    413                                SSLAlertDescription *alert, void *arg) {
    414  *alert = kCustomAlert;
    415  return SECFailure;
    416 }
    417 
    418 TEST_F(TlsConnectStreamTls13, CustomExtensionServerRejectAlert) {
    419  EnsureTlsSetup();
    420 
    421  // This installs an override that sends nonsense.
    422  const uint16_t extension_code = 0xffea;
    423  SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code,
    424                                           EmptyExtensionWriter, nullptr,
    425                                           NoopExtensionHandler, nullptr);
    426  EXPECT_EQ(SECSuccess, rv);
    427 
    428  // Reject the extension for no good reason.
    429  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    430                                 NoopExtensionWriter, nullptr,
    431                                 AlertExtensionHandler, nullptr);
    432  EXPECT_EQ(SECSuccess, rv);
    433 
    434  ConnectExpectAlert(server_, kCustomAlert);
    435 }
    436 
    437 // Send nonsense in an extension from client to server.
    438 TEST_F(TlsConnectStreamTls13, CustomExtensionClientRejectAlert) {
    439  EnsureTlsSetup();
    440 
    441  // This installs an override that sends nothing but expects nonsense.
    442  const uint16_t extension_code = 0xff5a;
    443  SECStatus rv = SSL_InstallExtensionHooks(client_->ssl_fd(), extension_code,
    444                                           EmptyExtensionWriter, nullptr,
    445                                           AlertExtensionHandler, nullptr);
    446  EXPECT_EQ(SECSuccess, rv);
    447 
    448  // Have the server send nonsense.
    449  rv = SSL_InstallExtensionHooks(server_->ssl_fd(), extension_code,
    450                                 EmptyExtensionWriter, nullptr,
    451                                 NoopExtensionHandler, nullptr);
    452  EXPECT_EQ(SECSuccess, rv);
    453 
    454  client_->ExpectSendAlert(kCustomAlert);
    455  server_->ExpectSendAlert(kTlsAlertUnexpectedMessage);
    456  ConnectExpectFail();
    457 }
    458 
    459 // Configure a custom extension hook badly.
    460 TEST_F(TlsConnectStreamTls13, CustomExtensionOnlyWriter) {
    461  EnsureTlsSetup();
    462 
    463  // This installs an override that sends nothing but expects nonsense.
    464  SECStatus rv =
    465      SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff6c, EmptyExtensionWriter,
    466                                nullptr, nullptr, nullptr);
    467  EXPECT_EQ(SECFailure, rv);
    468  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    469 }
    470 
    471 TEST_F(TlsConnectStreamTls13, CustomExtensionOnlyHandler) {
    472  EnsureTlsSetup();
    473 
    474  // This installs an override that sends nothing but expects nonsense.
    475  SECStatus rv =
    476      SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff6d, nullptr, nullptr,
    477                                NoopExtensionHandler, nullptr);
    478  EXPECT_EQ(SECFailure, rv);
    479  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
    480 }
    481 
    482 TEST_F(TlsConnectStreamTls13, CustomExtensionOverrunBuffer) {
    483  EnsureTlsSetup();
    484  // This doesn't actually overrun the buffer, but it says that it does.
    485  auto overrun_writer = [](PRFileDesc *fd, SSLHandshakeType message,
    486                           PRUint8 *data, unsigned int *len,
    487                           unsigned int maxLen, void *arg) -> PRBool {
    488    *len = maxLen + 1;
    489    return PR_TRUE;
    490  };
    491  SECStatus rv =
    492      SSL_InstallExtensionHooks(client_->ssl_fd(), 0xff71, overrun_writer,
    493                                nullptr, NoopExtensionHandler, nullptr);
    494  EXPECT_EQ(SECSuccess, rv);
    495  client_->StartConnect();
    496  client_->Handshake();
    497  client_->CheckErrorCode(SEC_ERROR_APPLICATION_CALLBACK_ERROR);
    498 }
    499 
    500 }  // namespace nss_test