ssl_resumption_unittest.cc 26.9 KB
Newer Older
1 2 3 4 5 6
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

7 8 9
#include <functional>
#include <memory>
#include "secerr.h"
10
#include "ssl.h"
11
#include "sslerr.h"
12
#include "sslexp.h"
13 14 15 16 17 18 19
#include "sslproto.h"

extern "C" {
// This is not something that should make you happy.
#include "libssl_internals.h"
}

20
#include "gtest_utils.h"
21 22
#include "scoped_ptrs.h"
#include "tls_connect.h"
23 24
#include "tls_filter.h"
#include "tls_parser.h"
25
#include "tls_protect.h"
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175

namespace nss_test {

class TlsServerKeyExchangeEcdhe {
 public:
  bool Parse(const DataBuffer& buffer) {
    TlsParser parser(buffer);

    uint8_t curve_type;
    if (!parser.Read(&curve_type)) {
      return false;
    }

    if (curve_type != 3) {  // named_curve
      return false;
    }

    uint32_t named_curve;
    if (!parser.Read(&named_curve, 2)) {
      return false;
    }

    return parser.ReadVariable(&public_key_, 1);
  }

  DataBuffer public_key_;
};

TEST_P(TlsConnectGenericPre13, ConnectResumed) {
  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
  Connect();

  Reset();
  ExpectResumption(RESUME_SESSIONID);
  Connect();
}

TEST_P(TlsConnectGeneric, ConnectClientCacheDisabled) {
  ConfigureSessionCache(RESUME_NONE, RESUME_SESSIONID);
  Connect();
  SendReceive();

  Reset();
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectServerCacheDisabled) {
  ConfigureSessionCache(RESUME_SESSIONID, RESUME_NONE);
  Connect();
  SendReceive();

  Reset();
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectSessionCacheDisabled) {
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
  Connect();
  SendReceive();

  Reset();
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeSupportBoth) {
  // This prefers tickets.
  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_BOTH);
  ExpectResumption(RESUME_TICKET);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientTicketServerBoth) {
  // This causes no resumption because the client needs the
  // session cache to resume even with tickets.
  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_TICKET, RESUME_BOTH);
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicket) {
  // This causes a ticket resumption.
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_TICKET);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientServerTicketOnly) {
  // This causes no resumption because the client needs the
  // session cache to resume even with tickets.
  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_TICKET, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientBothServerNone) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_NONE);
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientNoneServerBoth) {
  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_NONE, RESUME_BOTH);
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

TEST_P(TlsConnectGenericPre13, ConnectResumeWithHigherVersion) {
  ConfigureSessionCache(RESUME_SESSIONID, RESUME_SESSIONID);
176 177
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_1);
  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_1);
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
  Connect();

  Reset();
  EnsureTlsSetup();
  SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                           SSL_LIBRARY_VERSION_TLS_1_2);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_1,
                           SSL_LIBRARY_VERSION_TLS_1_2);
  ExpectResumption(RESUME_NONE);
  Connect();
}

TEST_P(TlsConnectGeneric, ConnectResumeClientBothTicketServerTicketForget) {
  // This causes a ticket resumption.
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();

  Reset();
  ClearServerCache();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);
  Connect();
  SendReceive();
}

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtClient) {
  SSLInt_SetTicketLifetime(1);  // one second
  // This causes a ticket resumption.
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();

  WAIT_(false, 1000);

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);

  // TLS 1.3 uses the pre-shared key extension instead.
  SSLExtensionType xtn = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3)
                             ? ssl_tls13_pre_shared_key_xtn
                             : ssl_session_ticket_xtn;
  auto capture = std::make_shared<TlsExtensionCapture>(xtn);
  client_->SetPacketFilter(capture);
  Connect();

  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    EXPECT_FALSE(capture->captured());
  } else {
    EXPECT_TRUE(capture->captured());
    EXPECT_EQ(0U, capture->extension().len());
  }
}

TEST_P(TlsConnectGeneric, ConnectWithExpiredTicketAtServer) {
  SSLInt_SetTicketLifetime(1);  // one second
  // This causes a ticket resumption.
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);

  SSLExtensionType xtn = (version_ >= SSL_LIBRARY_VERSION_TLS_1_3)
                             ? ssl_tls13_pre_shared_key_xtn
                             : ssl_session_ticket_xtn;
  auto capture = std::make_shared<TlsExtensionCapture>(xtn);
  client_->SetPacketFilter(capture);
  client_->StartConnect();
  server_->StartConnect();
  client_->Handshake();
  EXPECT_TRUE(capture->captured());
  EXPECT_LT(0U, capture->extension().len());

  WAIT_(false, 1000);  // Let the ticket expire on the server.

  Handshake();
  CheckConnected();
}

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
TEST_P(TlsConnectGeneric, ConnectResumeCorruptTicket) {
  // This causes a ticket resumption.
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();

  Reset();
  static const uint8_t kHmacKey1Buf[32] = {0};
  static const DataBuffer kHmacKey1(kHmacKey1Buf, sizeof(kHmacKey1Buf));

  SECItem key_item = {siBuffer, const_cast<uint8_t*>(kHmacKey1Buf),
                      sizeof(kHmacKey1Buf)};

  ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
  PK11SymKey* hmac_key =
      PK11_ImportSymKey(slot.get(), CKM_SHA256_HMAC, PK11_OriginUnwrap,
                        CKA_SIGN, &key_item, nullptr);
  ASSERT_NE(nullptr, hmac_key);
  SSLInt_SetSelfEncryptMacKey(hmac_key);
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConnectExpectAlert(server_, illegal_parameter);
  server_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO);
}

286 287
// This callback switches out the "server" cert used on the server with
// the "client" certificate, which should be the same type.
288
static int32_t SwitchCertificates(TlsAgent* agent, const SECItem* srvNameArr,
289
                                  uint32_t srvNameArrSize) {
290
  bool ok = agent->ConfigServerCert("client");
291 292
  if (!ok) return SSL_SNI_SEND_ALERT;

293
  return 0;  // first config
294 295 296 297 298 299 300 301 302 303 304 305 306
};

TEST_P(TlsConnectGeneric, ServerSNICertSwitch) {
  Connect();
  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));

  Reset();
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);

  server_->SetSniCallback(SwitchCertificates);

  Connect();
  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
307
  CheckKeys();
308 309 310 311
  EXPECT_FALSE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
}

TEST_P(TlsConnectGeneric, ServerSNICertTypeSwitch) {
312
  Reset(TlsAgent::kServerEcdsa256);
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
  Connect();
  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));

  Reset();
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);

  // Because we configure an RSA certificate here, it only adds a second, unused
  // certificate, which has no effect on what the server uses.
  server_->SetSniCallback(SwitchCertificates);

  Connect();
  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
  CheckKeys(ssl_kea_ecdh, ssl_auth_ecdsa);
  EXPECT_TRUE(SECITEM_ItemsAreEqual(&cert1->derCert, &cert2->derCert));
}

// Prior to TLS 1.3, we were not fully ephemeral; though 1.3 fixes that
TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceReuseKey) {
331 332
  auto i1 = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      kTlsHandshakeServerKeyExchange);
333 334
  server_->SetPacketFilter(i1);
  Connect();
335
  CheckKeys();
336 337 338 339 340
  TlsServerKeyExchangeEcdhe dhe1;
  EXPECT_TRUE(dhe1.Parse(i1->buffer()));

  // Restart
  Reset();
341 342
  auto i2 = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      kTlsHandshakeServerKeyExchange);
343 344 345
  server_->SetPacketFilter(i2);
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
  Connect();
346
  CheckKeys();
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

  TlsServerKeyExchangeEcdhe dhe2;
  EXPECT_TRUE(dhe2.Parse(i2->buffer()));

  // Make sure they are the same.
  EXPECT_EQ(dhe1.public_key_.len(), dhe2.public_key_.len());
  EXPECT_TRUE(!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
                      dhe1.public_key_.len()));
}

// This test parses the ServerKeyExchange, which isn't in 1.3
TEST_P(TlsConnectGenericPre13, ConnectEcdheTwiceNewKey) {
  server_->EnsureTlsSetup();
  SECStatus rv =
      SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
  EXPECT_EQ(SECSuccess, rv);
363 364
  auto i1 = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      kTlsHandshakeServerKeyExchange);
365 366
  server_->SetPacketFilter(i1);
  Connect();
367
  CheckKeys();
368 369 370 371 372 373 374 375
  TlsServerKeyExchangeEcdhe dhe1;
  EXPECT_TRUE(dhe1.Parse(i1->buffer()));

  // Restart
  Reset();
  server_->EnsureTlsSetup();
  rv = SSL_OptionSet(server_->ssl_fd(), SSL_REUSE_SERVER_ECDHE_KEY, PR_FALSE);
  EXPECT_EQ(SECSuccess, rv);
376 377
  auto i2 = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      kTlsHandshakeServerKeyExchange);
378 379 380
  server_->SetPacketFilter(i2);
  ConfigureSessionCache(RESUME_NONE, RESUME_NONE);
  Connect();
381
  CheckKeys();
382 383 384 385 386 387 388 389 390 391

  TlsServerKeyExchangeEcdhe dhe2;
  EXPECT_TRUE(dhe2.Parse(i2->buffer()));

  // Make sure they are different.
  EXPECT_FALSE((dhe1.public_key_.len() == dhe2.public_key_.len()) &&
               (!memcmp(dhe1.public_key_.data(), dhe2.public_key_.data(),
                        dhe1.public_key_.len())));
}

392 393 394 395 396
// Verify that TLS 1.3 reports an accurate group on resumption.
TEST_P(TlsConnectTls13, TestTls13ResumeDifferentGroup) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  Connect();
  SendReceive();  // Need to read so that we absorb the session ticket.
397
  CheckKeys();
398 399 400 401 402 403 404

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_TICKET);
  client_->ConfigNamedGroups(kFFDHEGroups);
  server_->ConfigNamedGroups(kFFDHEGroups);
  Connect();
405
  CheckKeys(ssl_kea_dh, ssl_grp_ffdhe_2048, ssl_auth_rsa_sign, ssl_sig_none);
406 407
}

408 409 410 411 412 413 414 415 416 417 418
// We need to enable different cipher suites at different times in the following
// tests.  Those cipher suites need to be suited to the version.
static uint16_t ChooseOneCipher(uint16_t version) {
  if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
    return TLS_AES_128_GCM_SHA256;
  }
  return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA;
}

static uint16_t ChooseAnotherCipher(uint16_t version) {
  if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
419
    return TLS_AES_256_GCM_SHA384;
420 421 422 423
  }
  return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA;
}

424
// Test that we don't resume when we can't negotiate the same cipher.
425
TEST_P(TlsConnectGeneric, TestResumeClientDifferentCipher) {
426
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
427
  client_->EnableSingleCipher(ChooseOneCipher(version_));
428
  Connect();
429 430
  SendReceive();
  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
431 432 433 434

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);
435
  client_->EnableSingleCipher(ChooseAnotherCipher(version_));
436 437 438 439 440 441
  uint16_t ticket_extension;
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    ticket_extension = ssl_tls13_pre_shared_key_xtn;
  } else {
    ticket_extension = ssl_session_ticket_xtn;
  }
442
  auto ticket_capture = std::make_shared<TlsExtensionCapture>(ticket_extension);
443
  client_->SetPacketFilter(ticket_capture);
444
  Connect();
445
  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);
446
  EXPECT_EQ(0U, ticket_capture->extension().len());
447 448 449
}

// Test that we don't resume when we can't negotiate the same cipher.
450
TEST_P(TlsConnectGeneric, TestResumeServerDifferentCipher) {
451
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
452
  server_->EnableSingleCipher(ChooseOneCipher(version_));
453 454
  Connect();
  SendReceive();  // Need to read so that we absorb the session ticket.
455
  CheckKeys();
456 457 458 459

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ExpectResumption(RESUME_NONE);
460
  server_->EnableSingleCipher(ChooseAnotherCipher(version_));
461
  Connect();
462
  CheckKeys();
463 464
}

465 466 467
// Test that the client doesn't tolerate the server picking a different cipher
// suite for resumption.
TEST_P(TlsConnectStream, TestResumptionOverrideCipher) {
468
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
469
  server_->EnableSingleCipher(ChooseOneCipher(version_));
470 471 472 473 474 475
  Connect();
  SendReceive();
  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
476 477
  server_->SetPacketFilter(std::make_shared<SelectedCipherSuiteReplacer>(
      ChooseAnotherCipher(version_)));
478

479 480 481 482 483 484
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    client_->ExpectSendAlert(kTlsAlertIllegalParameter);
    server_->ExpectSendAlert(kTlsAlertBadRecordMac);
  } else {
    ExpectAlert(client_, kTlsAlertHandshakeFailure);
  }
485 486 487 488 489 490 491 492 493 494 495 496 497 498
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
  if (version_ >= SSL_LIBRARY_VERSION_TLS_1_3) {
    // The reason this test is stream only: the server is unable to decrypt
    // the alert that the client sends, see bug 1304603.
    server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
  } else {
    server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
  }
}

class SelectedVersionReplacer : public TlsHandshakeFilter {
 public:
  SelectedVersionReplacer(uint16_t version) : version_(version) {}
499

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
 protected:
  PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
                                       const DataBuffer& input,
                                       DataBuffer* output) override {
    if (header.handshake_type() != kTlsHandshakeServerHello) {
      return KEEP;
    }

    *output = input;
    output->Write(0, static_cast<uint32_t>(version_), 2);
    return CHANGE;
  }

 private:
  uint16_t version_;
};

// Test how the client handles the case where the server picks a
// lower version number on resumption.
TEST_P(TlsConnectGenericPre13, TestResumptionOverrideVersion) {
  uint16_t override_version = 0;
521
  if (variant_ == ssl_variant_stream) {
522 523
    switch (version_) {
      case SSL_LIBRARY_VERSION_TLS_1_0:
524
        return;  // Skip the test.
525 526 527 528 529 530 531 532 533 534 535 536 537 538
      case SSL_LIBRARY_VERSION_TLS_1_1:
        override_version = SSL_LIBRARY_VERSION_TLS_1_0;
        break;
      case SSL_LIBRARY_VERSION_TLS_1_2:
        override_version = SSL_LIBRARY_VERSION_TLS_1_1;
        break;
      default:
        ASSERT_TRUE(false) << "unknown version";
    }
  } else {
    if (version_ == SSL_LIBRARY_VERSION_TLS_1_2) {
      override_version = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
    } else {
      ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, version_);
539
      return;  // Skip the test.
540 541 542 543 544 545 546 547 548 549 550 551 552 553
    }
  }

  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  // Need to use a cipher that is plausible for the lower version.
  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
  Connect();
  CheckKeys(ssl_kea_ecdh, ssl_auth_rsa_sign);

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  // Enable the lower version on the client.
  client_->SetVersionRange(version_ - 1, version_);
  server_->EnableSingleCipher(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA);
554 555
  server_->SetPacketFilter(
      std::make_shared<SelectedVersionReplacer>(override_version));
556

557
  ConnectExpectAlert(client_, kTlsAlertHandshakeFailure);
558
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
559
  server_->CheckErrorCode(SSL_ERROR_HANDSHAKE_FAILURE_ALERT);
560 561
}

562 563 564 565
// Test that two TLS resumptions work and produce the same ticket.
// This will change after bug 1257047 is fixed.
TEST_F(TlsConnectTest, TestTls13ResumptionTwice) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
566 567
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);

568
  Connect();
569
  SendReceive();  // Need to read so that we absorb the session ticket.
570
  CheckKeys();
571 572 573 574 575
  uint16_t original_suite;
  EXPECT_TRUE(client_->cipher_suite(&original_suite));

  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
576 577
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ExpectResumption(RESUME_TICKET);
578
  auto c1 = std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
579 580 581
  client_->SetPacketFilter(c1);
  Connect();
  SendReceive();
582
  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
583
            ssl_sig_none);
584 585 586 587 588 589 590 591 592 593
  // The filter will go away when we reset, so save the captured extension.
  DataBuffer initialTicket(c1->extension());
  ASSERT_LT(0U, initialTicket.len());

  ScopedCERTCertificate cert1(SSL_PeerCertificate(client_->ssl_fd()));
  ASSERT_TRUE(!!cert1.get());

  Reset();
  ClearStats();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
594
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
595
  auto c2 = std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
596 597 598 599
  client_->SetPacketFilter(c2);
  ExpectResumption(RESUME_TICKET);
  Connect();
  SendReceive();
600
  CheckKeys(ssl_kea_ecdh, ssl_grp_ec_curve25519, ssl_auth_rsa_sign,
601
            ssl_sig_none);
602 603 604 605 606 607 608 609 610 611 612 613 614
  ASSERT_LT(0U, c2->extension().len());

  ScopedCERTCertificate cert2(SSL_PeerCertificate(client_->ssl_fd()));
  ASSERT_TRUE(!!cert2.get());

  // Check that the cipher suite is reported the same on both sides, though in
  // TLS 1.3 resumption actually negotiates a different cipher suite.
  uint16_t resumed_suite;
  EXPECT_TRUE(server_->cipher_suite(&resumed_suite));
  EXPECT_EQ(original_suite, resumed_suite);
  EXPECT_TRUE(client_->cipher_suite(&resumed_suite));
  EXPECT_EQ(original_suite, resumed_suite);

615
  ASSERT_NE(initialTicket, c2->extension());
616
}
617

618 619 620 621 622 623 624
// Check that resumption works after receiving two NST messages.
TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNST) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();

  // Clear the session ticket keys to invalidate the old ticket.
625
  SSLInt_ClearSelfEncryptKey();
626
  SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0);
627 628 629 630 631 632 633 634 635 636 637 638 639

  SendReceive();  // Need to read so that we absorb the session tickets.
  CheckKeys();

  // Resume the connection.
  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ExpectResumption(RESUME_TICKET);
  Connect();
  SendReceive();
}

640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
// Check that the value captured in a NewSessionTicket message matches the value
// captured from a pre_shared_key extension.
void NstTicketMatchesPskIdentity(const DataBuffer& nst, const DataBuffer& psk) {
  uint32_t len;

  size_t offset = 4 + 4;  // Skip ticket_lifetime and ticket_age_add.
  ASSERT_TRUE(nst.Read(offset, 1, &len));
  offset += 1 + len;  // Skip ticket_nonce.

  ASSERT_TRUE(nst.Read(offset, 2, &len));
  offset += 2;  // Skip the ticket length.
  ASSERT_LE(offset + len, nst.len());
  DataBuffer nst_ticket(nst.data() + offset, static_cast<size_t>(len));

  offset = 2;  // Skip the identities length.
  ASSERT_TRUE(psk.Read(offset, 2, &len));
  offset += 2;  // Skip the identity length.
  ASSERT_LE(offset + len, psk.len());
  DataBuffer psk_ticket(psk.data() + offset, static_cast<size_t>(len));

  EXPECT_EQ(nst_ticket, psk_ticket);
}

TEST_F(TlsConnectTest, TestTls13ResumptionDuplicateNSTWithToken) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);

  auto nst_capture = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      ssl_hs_new_session_ticket);
  server_->SetTlsRecordFilter(nst_capture);
  Connect();

  // Clear the session ticket keys to invalidate the old ticket.
  SSLInt_ClearSelfEncryptKey();
  nst_capture->Reset();
  uint8_t token[] = {0x20, 0x20, 0xff, 0x00};
  EXPECT_EQ(SECSuccess,
            SSL_SendSessionTicket(server_->ssl_fd(), token, sizeof(token)));

  SendReceive();  // Need to read so that we absorb the session tickets.
  CheckKeys();
  EXPECT_LT(0U, nst_capture->buffer().len());

  // Resume the connection.
  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ExpectResumption(RESUME_TICKET);

  auto psk_capture =
      std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
  client_->SetPacketFilter(psk_capture);
  Connect();
  SendReceive();

  NstTicketMatchesPskIdentity(nst_capture->buffer(), psk_capture->extension());
}

// Disable SSL_ENABLE_SESSION_TICKETS but ensure that tickets can still be sent
// by invoking SSL_SendSessionTicket directly (and that the ticket is usable).
TEST_F(TlsConnectTest, SendSessionTicketWithTicketsDisabled) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);

  EXPECT_EQ(SECSuccess, SSL_OptionSet(server_->ssl_fd(),
                                      SSL_ENABLE_SESSION_TICKETS, PR_FALSE));

  auto nst_capture = std::make_shared<TlsInspectorRecordHandshakeMessage>(
      ssl_hs_new_session_ticket);
  server_->SetTlsRecordFilter(nst_capture);
  Connect();

  EXPECT_EQ(0U, nst_capture->buffer().len()) << "expect nothing captured yet";

  EXPECT_EQ(SECSuccess, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0));
  EXPECT_LT(0U, nst_capture->buffer().len()) << "should capture now";

  SendReceive();  // Ensure that the client reads the ticket.

  // Resume the connection.
  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ExpectResumption(RESUME_TICKET);

  auto psk_capture =
      std::make_shared<TlsExtensionCapture>(ssl_tls13_pre_shared_key_xtn);
  client_->SetPacketFilter(psk_capture);
  Connect();
  SendReceive();

  NstTicketMatchesPskIdentity(nst_capture->buffer(), psk_capture->extension());
}

// Test calling SSL_SendSessionTicket in inappropriate conditions.
TEST_F(TlsConnectTest, SendSessionTicketInappropriate) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_2);

  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(client_->ssl_fd(), NULL, 0))
      << "clients can't send tickets";
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());

  server_->StartConnect();
  client_->StartConnect();

  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0))
      << "no ticket before the handshake has started";
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
  Handshake();
  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0))
      << "no special tickets in TLS 1.2";
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}

TEST_F(TlsConnectTest, SendSessionTicketMassiveToken) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
  // It should be safe to set length with a NULL token because the length should
  // be checked before reading token.
761 762
  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0x1ffff))
      << "this is clearly too big";
763 764
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());

765 766 767 768
  static const uint8_t big_token[0xffff] = {1};
  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), big_token,
                                              sizeof(big_token)))
      << "this is too big, but that's not immediately obvious";
769 770 771 772 773 774 775 776 777 778 779 780
  EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
}

TEST_F(TlsConnectDatagram13, SendSessionTicketDtls) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();
  EXPECT_EQ(SECFailure, SSL_SendSessionTicket(server_->ssl_fd(), NULL, 0))
      << "no extra tickets in DTLS until we have Ack support";
  EXPECT_EQ(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_VERSION, PORT_GetError());
}

781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
TEST_F(TlsConnectTest, TestTls13ResumptionDowngrade) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();

  SendReceive();  // Need to read so that we absorb the session tickets.
  CheckKeys();

  // Try resuming the connection. This will fail resuming the 1.3 session
  // from before, but will successfully establish a 1.2 connection.
  Reset();
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);
  server_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_2);
  Connect();

  // Renegotiate to ensure we don't carryover any state
  // from the 1.3 resumption attempt.
  client_->SetExpectedVersion(SSL_LIBRARY_VERSION_TLS_1_2);
  client_->PrepareForRenegotiate();
  server_->StartRenegotiate();
  Handshake();

  SendReceive();
  CheckKeys();
}

TEST_F(TlsConnectTest, TestTls13ResumptionForcedDowngrade) {
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  Connect();

  SendReceive();  // Need to read so that we absorb the session tickets.
  CheckKeys();

  // Try resuming the connection.
  Reset();
  ConfigureVersion(SSL_LIBRARY_VERSION_TLS_1_3);
  ConfigureSessionCache(RESUME_BOTH, RESUME_TICKET);
  // Enable the lower version on the client.
  client_->SetVersionRange(SSL_LIBRARY_VERSION_TLS_1_2,
                           SSL_LIBRARY_VERSION_TLS_1_3);

  // Add filters that set downgrade SH.version to 1.2 and the cipher suite
  // to one that works with 1.2, so that we don't run into early sanity checks.
  // We will eventually fail the (sid.version == SH.version) check.
829 830
  std::vector<std::shared_ptr<PacketFilter>> filters;
  filters.push_back(std::make_shared<SelectedCipherSuiteReplacer>(
831
      TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256));
832 833 834
  filters.push_back(
      std::make_shared<SelectedVersionReplacer>(SSL_LIBRARY_VERSION_TLS_1_2));
  server_->SetPacketFilter(std::make_shared<ChainedPacketFilter>(filters));
835

836 837
  client_->ExpectSendAlert(kTlsAlertDecodeError);
  server_->ExpectSendAlert(kTlsAlertBadRecordMac);  // Server can't read
838 839 840 841 842
  ConnectExpectFail();
  client_->CheckErrorCode(SSL_ERROR_RX_MALFORMED_SERVER_HELLO);
  server_->CheckErrorCode(SSL_ERROR_BAD_MAC_READ);
}

843
}  // namespace nss_test