summaryrefslogtreecommitdiff
path: root/gtests
diff options
context:
space:
mode:
authorLeander Schwarz <lschwarz@mozilla.com>2023-01-16 17:56:43 +0000
committerLeander Schwarz <lschwarz@mozilla.com>2023-01-16 17:56:43 +0000
commit69332f168fa98b92983f6ef3fcfbf3bde765e9e2 (patch)
treefc6ec91bb02b2d6f90b5e1cf9b160ec3050b91a1 /gtests
parent11bdd24bb405af450ad1007064eb70db02b3317d (diff)
downloadnss-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.json2
-rw-r--r--gtests/nss_bogo_shim/nss_bogo_shim.cc74
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) {