diff options
author | Leander Schwarz <lschwarz@mozilla.com> | 2023-01-16 17:56:43 +0000 |
---|---|---|
committer | Leander Schwarz <lschwarz@mozilla.com> | 2023-01-16 17:56:43 +0000 |
commit | 69332f168fa98b92983f6ef3fcfbf3bde765e9e2 (patch) | |
tree | fc6ec91bb02b2d6f90b5e1cf9b160ec3050b91a1 /gtests | |
parent | 11bdd24bb405af450ad1007064eb70db02b3317d (diff) | |
download | nss-hg-69332f168fa98b92983f6ef3fcfbf3bde765e9e2.tar.gz |
Bug 1771100 - Added Bogo ECH rejection test support. r=djackson
Differential Revision: https://phabricator.services.mozilla.com/D154631
Diffstat (limited to 'gtests')
-rw-r--r-- | gtests/nss_bogo_shim/config.json | 2 | ||||
-rw-r--r-- | gtests/nss_bogo_shim/nss_bogo_shim.cc | 74 |
2 files changed, 67 insertions, 9 deletions
diff --git a/gtests/nss_bogo_shim/config.json b/gtests/nss_bogo_shim/config.json index 52d477ad1..f237595ae 100644 --- a/gtests/nss_bogo_shim/config.json +++ b/gtests/nss_bogo_shim/config.json @@ -48,6 +48,8 @@ "*ECH*UnsolicitedInnerServerNameAck":"NSS always sends SNI in CHInner, Bogo tests if the client detects an unsolicited SNI in SH if CHInner did not include it. Bug 1781224", "CorruptTicket-TLS-TLS12":"NSS sends an alert on reception of a corrupted session ticket instead of falling back to full handshake. Bug 1783812", "HelloRetryRequest-NonResumableCipher-TLS13":"TODO", + "TLS-ECH-Client-Reject-TLS12":"TODO", + "FalseStart-ALPN*":"TODO", "####################":"####################", "### TLS1/11 failures due to unsupported signature algorithms":"", diff --git a/gtests/nss_bogo_shim/nss_bogo_shim.cc b/gtests/nss_bogo_shim/nss_bogo_shim.cc index e8de3e3f9..bbab34baf 100644 --- a/gtests/nss_bogo_shim/nss_bogo_shim.cc +++ b/gtests/nss_bogo_shim/nss_bogo_shim.cc @@ -28,6 +28,9 @@ static const char* kVersionDisableFlags[] = {"no-ssl3", "no-tls1", "no-tls11", "no-tls12", "no-tls13"}; +/* Default EarlyData dummy data determined by Bogo implementation. */ +const unsigned char kBogoDummyData[] = {'h', 'e', 'l', 'l', 'o'}; + bool exitCodeUnimplemented = false; std::string FormatError(PRErrorCode code) { @@ -35,6 +38,11 @@ std::string FormatError(PRErrorCode code) { PORT_ErrorToString(code); } +static void StringRemoveNewlines(std::string& str) { + str.erase(std::remove(str.begin(), str.end(), '\n'), str.cend()); + str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend()); +} + class TestAgent { public: TestAgent(const Config& cfg) : cfg_(cfg) {} @@ -523,16 +531,13 @@ class TestAgent { SECStatus DoExchange() { SECStatus rv; + int earlyDataSent = 0; sslSocket* ss = ssl_FindSocket(ssl_fd_.get()); if (!ss) { return SECFailure; } - /* Default EarlyData determined by Bogo implementation. */ - const unsigned char earlyDataDefault[] = {'h', 'e', 'l', 'l', 'o'}; - int earlyDataSent = 0; - - /* As client send ClientHello. */ + /* If client send ClientHello. */ if (!cfg_.get<bool>("server")) { ssl_Get1stHandshakeLock(ss); rv = ssl_BeginClientHandshake(ss); @@ -549,7 +554,7 @@ class TestAgent { /* If the client should send EarlyData. */ if (cfg_.get<bool>("on-resume-shim-writes-first")) { earlyDataSent = - ssl_SecureWrite(ss, earlyDataDefault, sizeof(earlyDataDefault)); + ssl_SecureWrite(ss, kBogoDummyData, sizeof(kBogoDummyData)); if (earlyDataSent < 0) { std::cerr << "Sending of EarlyData failed" << std::endl; return SECFailure; @@ -577,6 +582,44 @@ class TestAgent { /* As server start, as client continue handshake. */ rv = Handshake(); + + /* Retry config evaluation must be done before error handling since + * handshake failure is intended on ech_required tests. */ + if (cfg_.get<bool>("expect-no-ech-retry-configs")) { + if (ss->xtnData.ech && ss->xtnData.ech->retryConfigsValid) { + std::cerr << "Unexpectedly received ECH retry configs" << std::endl; + return SECFailure; + } + } + + /* If given, verify received retry configs before error handling. */ + std::string expectedRCs64 = + cfg_.get<std::string>("expect-ech-retry-configs"); + if (!expectedRCs64.empty()) { + SECItem receivedRCs; + + /* Get received RetryConfigs. */ + if (SSLExp_GetEchRetryConfigs(ssl_fd_.get(), &receivedRCs) != + SECSuccess) { + std::cerr << "Failed to get ECH retry configs." << std::endl; + return SECFailure; + } + + /* (Re-)Encode received configs to compare with expected ASCII string. */ + std::string receivedRCs64( + BTOA_DataToAscii(receivedRCs.data, receivedRCs.len)); + /* Remove newlines (for unknown reasons) added during b64 encoding. */ + StringRemoveNewlines(receivedRCs64); + + if (receivedRCs64 != expectedRCs64) { + std::cerr << "Received ECH retry configs did not match expected retry " + "configs." + << std::endl; + return SECFailure; + } + } + + /* Check if handshake succeeded. */ if (rv != SECSuccess) { PRErrorCode err = PR_GetError(); std::cerr << "Handshake failed with error=" << err << FormatError(err) @@ -586,10 +629,10 @@ class TestAgent { /* If parts of data was sent as EarlyData make sure to send possibly * unsent rest. This is required to pass bogo resumption tests. */ - if (earlyDataSent && earlyDataSent < int(sizeof(earlyDataDefault))) { - int toSend = sizeof(earlyDataDefault) - earlyDataSent; + if (earlyDataSent && earlyDataSent < int(sizeof(kBogoDummyData))) { + int toSend = sizeof(kBogoDummyData) - earlyDataSent; earlyDataSent = - ssl_SecureWrite(ss, &earlyDataDefault[earlyDataSent], toSend); + ssl_SecureWrite(ss, &kBogoDummyData[earlyDataSent], toSend); if (earlyDataSent != toSend) { std::cerr << "Could not send rest of EarlyData after handshake completion" @@ -663,6 +706,7 @@ class TestAgent { } } + /* if resumed */ if (info.resumed) { if (cfg_.get<bool>("expect-session-miss")) { std::cerr << "Expected reject Resume" << std::endl; @@ -681,6 +725,13 @@ class TestAgent { return SECFailure; } } + } else { /* Explicitly not on resume */ + if (cfg_.get<bool>("on-initial-expect-ech-accept")) { + if (!info.echAccepted) { + std::cerr << "Expected ECH accept on initial connection" << std::endl; + return SECFailure; + } + } } if (cfg_.get<bool>("expect-hrr")) { @@ -739,7 +790,12 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) { cfg->AddEntry<bool>("expect-ticket-supports-early-data", false); cfg->AddEntry<bool>("on-resume-shim-writes-first", false); // Always means 0Rtt write + cfg->AddEntry<bool>("shim-writes-first", + false); // Unimplemented since not required so far cfg->AddEntry<bool>("expect-session-miss", false); + cfg->AddEntry<std::string>("expect-ech-retry-configs", ""); + cfg->AddEntry<bool>("expect-no-ech-retry-configs", false); + cfg->AddEntry<bool>("on-initial-expect-ech-accept", false); auto rv = cfg->ParseArgs(argc, argv); switch (rv) { |