diff options
Diffstat (limited to 'security/nss/gtests/nss_bogo_shim')
-rw-r--r-- | security/nss/gtests/nss_bogo_shim/config.json | 31 | ||||
-rw-r--r-- | security/nss/gtests/nss_bogo_shim/manifest.mn | 6 | ||||
-rw-r--r-- | security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc | 179 | ||||
-rw-r--r-- | security/nss/gtests/nss_bogo_shim/nss_bogo_shim.gyp | 1 |
4 files changed, 125 insertions, 92 deletions
diff --git a/security/nss/gtests/nss_bogo_shim/config.json b/security/nss/gtests/nss_bogo_shim/config.json index 6dc155bef..5c7a2e348 100644 --- a/security/nss/gtests/nss_bogo_shim/config.json +++ b/security/nss/gtests/nss_bogo_shim/config.json @@ -1,6 +1,9 @@ { "DisabledTests": { "### These tests break whenever we rev versions, so just leave them here for easy uncommenting":"", + "*TLS13Draft*":"NSS supports RFC 8446 only.", + "IgnoreClientVersionOrder":"Uses draft23", + "DuplicateCertCompressionExt*":"BoGo expects that an alert is sent if more than one compression algorithm is sent.", "ServerBogusVersion":"Check that SH.legacy_version=TLS12 when the server picks TLS 1.3 (Bug 1443761)", "DummyPQPadding-Server*":"Boring is testing a dummy PQ padding extension", "VerifyPreferences-Enforced":"NSS sends alerts in response to errors in protected handshake messages in the clear", @@ -12,17 +15,10 @@ "ServerCipherFilter*":"Add Ed25519 support (Bug 1325335)", "GarbageCertificate*":"Send bad_certificate alert when certificate parsing fails (Bug 1441565)", "SupportedVersionSelection-TLS12":"Should maybe reject TLS 1.2 in SH.supported_versions (Bug 1438266)", - "*TLS13*":"(NSS=19, BoGo=18)", - "*HelloRetryRequest*":"(NSS=19, BoGo=18)", - "*KeyShare*":"(NSS=19, BoGo=18)", - "*EncryptedExtensions*":"(NSS=19, BoGo=18)", - "*SecondClientHello*":"(NSS=19, BoGo=18)", - "*IgnoreClientVersionOrder*":"(NSS=19, BoGo=18)", - "SkipEarlyData*":"(NSS=19, BoGo=18)", - "*Binder*":"(NSS=19, BoGo=18)", "Resume-Server-BinderWrongLength":"Alert disagreement (Bug 1317633)", "Resume-Server-NoPSKBinder":"Alert disagreement (Bug 1317633)", "CheckRecordVersion-TLS*":"Bug 1317634", + "GarbageInitialRecordVersion-TLS*":"NSS doesn't strictly check the ClientHello record version", "GREASE-Server-TLS13":"BoringSSL GREASEs without a flag, but we ignore it", "TLS13-ExpectNoSessionTicketOnBadKEMode-Server":"Bug in NSS. Don't send ticket when not permitted by KE modes (Bug 1317635)", "*KeyUpdate*":"KeyUpdate Unimplemented", @@ -48,14 +44,14 @@ "StrayHelloRequest*":"NSS doesn't disable renegotiation by default", "NoSupportedCurves-TLS13":"wanted SSL_ERROR_NO_CYPHER_OVERLAP, got missing extension error", "FragmentedClientVersion":"received a malformed Client Hello handshake message", - "UnofferedExtension-Client-TLS13":"nss updated/broken", - "UnknownExtension-Client-TLS13":"nss updated/broken", - "WrongMessageType-TLS13-EncryptedExtensions":"nss updated/broken", - "WrongMessageType-TLS13-CertificateRequest":"nss updated/broken", - "WrongMessageType-TLS13-ServerCertificateVerify":"nss updated/broken", - "WrongMessageType-TLS13-ServerCertificate":"nss updated/broken", - "WrongMessageType-TLS13-ServerFinished":"nss updated/broken", - "EmptyEncryptedExtensions":"nss updated/broken", + "WrongMessageType-TLS13-EncryptedExtensions":"Boring expects CCS (Bugs 1481209, 1304603)", + "TrailingMessageData-TLS13-EncryptedExtensions":"Boring expects CCS (Bugs 1481209, 1304603)", + "UnofferedExtension-Client-TLS13":"Boring expects CCS (Bugs 1481209, 1304603)", + "UnknownExtension-Client-TLS13":"Boring expects CCS (Bugs 1481209, 1304603)", + "WrongMessageType-TLS13-CertificateRequest":"Boring expects CCS (Bugs 1481209, 1304603)", + "WrongMessageType-TLS13-ServerCertificateVerify":"Boring expects CCS (Bugs 1481209, 1304603)", + "WrongMessageType-TLS13-ServerCertificate":"Boring expects CCS (Bugs 1481209, 1304603)", + "WrongMessageType-TLS13-ServerFinished":"Boring expects CCS (Bugs 1481209, 1304603)", "TrailingMessageData-*": "Bug 1304575", "DuplicateKeyShares":"Bug 1304578", "Resume-Server-TLS13-TLS13":"Bug 1314351", @@ -68,7 +64,8 @@ "RequireAnyClientCertificate-TLS1*":"Bug 1339387", "SendExtensionOnClientCertificate-TLS13":"Bug 1339392", "ALPNClient-Mismatch-TLS13":"NSS sends alerts in response to errors in protected handshake messages in the clear", - "P224-Server":"NSS doesn't support P-224" + "P224-Server":"NSS doesn't support P-224", + "ClientAuth-SHA1-Fallback*":"Boring wants us to fall back to SHA-1 if supported_signature_algorithms in CR is empty." }, "ErrorMap" : { ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:":"SSL_ERROR_NO_CYPHER_OVERLAP", diff --git a/security/nss/gtests/nss_bogo_shim/manifest.mn b/security/nss/gtests/nss_bogo_shim/manifest.mn index 2d60ddea3..f8a6b07af 100644 --- a/security/nss/gtests/nss_bogo_shim/manifest.mn +++ b/security/nss/gtests/nss_bogo_shim/manifest.mn @@ -12,9 +12,11 @@ CPPSRCS = \ nss_bogo_shim.cc \ $(NULL) -REQUIRES = nspr nss libdbm +INCLUDES += -I$(CORE_DEPTH)/cpputil + +REQUIRES = nspr nss libdbm cpputil PROGRAM = nss_bogo_shim -#EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)softokn.$(LIB_SUFFIX) +EXTRA_LIBS = $(DIST)/lib/$(LIB_PREFIX)cpputil.$(LIB_SUFFIX) USE_STATIC_LIBS = 1 diff --git a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc index 72dbd5771..b2ce6898d 100644 --- a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc +++ b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.cc @@ -18,6 +18,7 @@ #include "ssl3prot.h" #include "sslerr.h" #include "sslproto.h" +#include "nss_scoped_ptrs.h" #include "nsskeys.h" @@ -33,30 +34,9 @@ std::string FormatError(PRErrorCode code) { class TestAgent { public: - TestAgent(const Config& cfg) - : cfg_(cfg), - pr_fd_(nullptr), - ssl_fd_(nullptr), - cert_(nullptr), - key_(nullptr) {} + TestAgent(const Config& cfg) : cfg_(cfg) {} - ~TestAgent() { - if (pr_fd_) { - PR_Close(pr_fd_); - } - - if (ssl_fd_) { - PR_Close(ssl_fd_); - } - - if (key_) { - SECKEY_DestroyPrivateKey(key_); - } - - if (cert_) { - CERT_DestroyCertificate(cert_); - } - } + ~TestAgent() {} static std::unique_ptr<TestAgent> Create(const Config& cfg) { std::unique_ptr<TestAgent> agent(new TestAgent(cfg)); @@ -81,39 +61,46 @@ class TestAgent { return false; } - SECStatus rv = SSL_ResetHandshake(ssl_fd_, cfg_.get<bool>("server")); + SECStatus rv = SSL_ResetHandshake(ssl_fd_.get(), cfg_.get<bool>("server")); if (rv != SECSuccess) return false; return true; } bool ConnectTcp() { + // Try IPv6 first, then IPv4 in case of failure. + if (!OpenConnection("::1") && !OpenConnection("127.0.0.1")) { + return false; + } + + ssl_fd_ = ScopedPRFileDesc(SSL_ImportFD(NULL, pr_fd_.get())); + if (!ssl_fd_) { + return false; + } + pr_fd_.release(); + + return true; + } + + bool OpenConnection(const char* ip) { PRStatus prv; PRNetAddr addr; - // Try IPv6 first. - prv = PR_StringToNetAddr("::1", &addr); + prv = PR_StringToNetAddr(ip, &addr); + if (prv != PR_SUCCESS) { - // If that fails, try IPv4. - prv = PR_StringToNetAddr("127.0.0.1", &addr); - if (prv != PR_SUCCESS) { - return false; - } + return false; } + addr.inet.port = PR_htons(cfg_.get<int>("port")); - pr_fd_ = PR_OpenTCPSocket(addr.raw.family); + pr_fd_ = ScopedPRFileDesc(PR_OpenTCPSocket(addr.raw.family)); if (!pr_fd_) return false; - prv = PR_Connect(pr_fd_, &addr, PR_INTERVAL_NO_TIMEOUT); + prv = PR_Connect(pr_fd_.get(), &addr, PR_INTERVAL_NO_TIMEOUT); if (prv != PR_SUCCESS) { return false; } - - ssl_fd_ = SSL_ImportFD(NULL, pr_fd_); - if (!ssl_fd_) return false; - pr_fd_ = nullptr; - return true; } @@ -121,21 +108,24 @@ class TestAgent { SECStatus rv; if (cfg_.get<std::string>("key-file") != "") { - key_ = ReadPrivateKey(cfg_.get<std::string>("key-file")); + key_ = ScopedSECKEYPrivateKey( + ReadPrivateKey(cfg_.get<std::string>("key-file"))); if (!key_) return false; } if (cfg_.get<std::string>("cert-file") != "") { - cert_ = ReadCertificate(cfg_.get<std::string>("cert-file")); + cert_ = ScopedCERTCertificate( + ReadCertificate(cfg_.get<std::string>("cert-file"))); if (!cert_) return false; } // Needed because certs are not entirely valid. - rv = SSL_AuthCertificateHook(ssl_fd_, AuthCertificateHook, this); + rv = SSL_AuthCertificateHook(ssl_fd_.get(), AuthCertificateHook, this); if (rv != SECSuccess) return false; if (cfg_.get<bool>("server")) { // Server - rv = SSL_ConfigServerCert(ssl_fd_, cert_, key_, nullptr, 0); + rv = SSL_ConfigServerCert(ssl_fd_.get(), cert_.get(), key_.get(), nullptr, + 0); if (rv != SECSuccess) { std::cerr << "Couldn't configure server cert\n"; return false; @@ -143,7 +133,8 @@ class TestAgent { } else if (key_ && cert_) { // Client. - rv = SSL_GetClientAuthDataHook(ssl_fd_, GetClientAuthDataHook, this); + rv = + SSL_GetClientAuthDataHook(ssl_fd_.get(), GetClientAuthDataHook, this); if (rv != SECSuccess) return false; } @@ -263,36 +254,36 @@ class TestAgent { bool SetupOptions() { SECStatus rv = - SSL_OptionSet(ssl_fd_, SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); + SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_TLS13_COMPAT_MODE, PR_TRUE); if (rv != SECSuccess) return false; - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_SESSION_TICKETS, PR_TRUE); if (rv != SECSuccess) return false; SSLVersionRange vrange; if (!GetVersionRange(&vrange, ssl_variant_stream)) return false; - rv = SSL_VersionRangeSet(ssl_fd_, &vrange); + rv = SSL_VersionRangeSet(ssl_fd_.get(), &vrange); if (rv != SECSuccess) return false; SSLVersionRange verify_vrange; - rv = SSL_VersionRangeGet(ssl_fd_, &verify_vrange); + rv = SSL_VersionRangeGet(ssl_fd_.get(), &verify_vrange); if (rv != SECSuccess) return false; if (vrange.min != verify_vrange.min || vrange.max != verify_vrange.max) return false; - rv = SSL_OptionSet(ssl_fd_, SSL_NO_CACHE, false); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_NO_CACHE, false); if (rv != SECSuccess) return false; auto alpn = cfg_.get<std::string>("advertise-alpn"); if (!alpn.empty()) { assert(!cfg_.get<bool>("server")); - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_ALPN, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_ALPN, PR_TRUE); if (rv != SECSuccess) return false; rv = SSL_SetNextProtoNego( - ssl_fd_, reinterpret_cast<const unsigned char*>(alpn.c_str()), + ssl_fd_.get(), reinterpret_cast<const unsigned char*>(alpn.c_str()), alpn.size()); if (rv != SECSuccess) return false; } @@ -312,23 +303,23 @@ class TestAgent { [](int scheme) { return static_cast<SSLSignatureScheme>(scheme); }); rv = SSL_SignatureSchemePrefSet( - ssl_fd_, sig_schemes.data(), + ssl_fd_.get(), sig_schemes.data(), static_cast<unsigned int>(sig_schemes.size())); if (rv != SECSuccess) return false; } if (cfg_.get<bool>("fallback-scsv")) { - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_FALLBACK_SCSV, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_FALLBACK_SCSV, PR_TRUE); if (rv != SECSuccess) return false; } if (cfg_.get<bool>("false-start")) { - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_FALSE_START, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_FALSE_START, PR_TRUE); if (rv != SECSuccess) return false; } if (cfg_.get<bool>("enable-ocsp-stapling")) { - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_OCSP_STAPLING, PR_TRUE); if (rv != SECSuccess) return false; } @@ -336,29 +327,63 @@ class TestAgent { if (requireClientCert || cfg_.get<bool>("verify-peer")) { assert(cfg_.get<bool>("server")); - rv = SSL_OptionSet(ssl_fd_, SSL_REQUEST_CERTIFICATE, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_REQUEST_CERTIFICATE, PR_TRUE); if (rv != SECSuccess) return false; rv = SSL_OptionSet( - ssl_fd_, SSL_REQUIRE_CERTIFICATE, + ssl_fd_.get(), SSL_REQUIRE_CERTIFICATE, requireClientCert ? SSL_REQUIRE_ALWAYS : SSL_REQUIRE_NO_ERROR); if (rv != SECSuccess) return false; } if (!cfg_.get<bool>("server")) { // Needed to make resumption work. - rv = SSL_SetURL(ssl_fd_, "server"); + rv = SSL_SetURL(ssl_fd_.get(), "server"); if (rv != SECSuccess) return false; } - rv = SSL_OptionSet(ssl_fd_, SSL_ENABLE_EXTENDED_MASTER_SECRET, PR_TRUE); + rv = SSL_OptionSet(ssl_fd_.get(), SSL_ENABLE_EXTENDED_MASTER_SECRET, + PR_TRUE); if (rv != SECSuccess) return false; - if (!EnableNonExportCiphers()) return false; + if (!ConfigureCiphers()) return false; return true; } + bool ConfigureCiphers() { + auto cipherList = cfg_.get<std::string>("nss-cipher"); + + if (cipherList.empty()) { + return EnableNonExportCiphers(); + } + + for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) { + SSLCipherSuiteInfo csinfo; + std::string::size_type n; + SECStatus rv = SSL_GetCipherSuiteInfo(SSL_ImplementedCiphers[i], &csinfo, + sizeof(csinfo)); + if (rv != SECSuccess) { + return false; + } + + // Check if cipherList contains the name of the Cipher Suite and + // enable/disable accordingly. + n = cipherList.find(csinfo.cipherSuiteName, 0); + if (std::string::npos == n) { + rv = SSL_CipherPrefSet(ssl_fd_.get(), SSL_ImplementedCiphers[i], + PR_FALSE); + } else { + rv = SSL_CipherPrefSet(ssl_fd_.get(), SSL_ImplementedCiphers[i], + PR_TRUE); + } + if (rv != SECSuccess) { + return false; + } + } + return true; + } + bool EnableNonExportCiphers() { for (size_t i = 0; i < SSL_NumImplementedCiphers; ++i) { SSLCipherSuiteInfo csinfo; @@ -369,7 +394,7 @@ class TestAgent { return false; } - rv = SSL_CipherPrefSet(ssl_fd_, SSL_ImplementedCiphers[i], PR_TRUE); + rv = SSL_CipherPrefSet(ssl_fd_.get(), SSL_ImplementedCiphers[i], PR_TRUE); if (rv != SECSuccess) { return false; } @@ -388,19 +413,19 @@ class TestAgent { CERTCertificate** cert, SECKEYPrivateKey** privKey) { TestAgent* a = static_cast<TestAgent*>(self); - *cert = CERT_DupCertificate(a->cert_); - *privKey = SECKEY_CopyPrivateKey(a->key_); + *cert = CERT_DupCertificate(a->cert_.get()); + *privKey = SECKEY_CopyPrivateKey(a->key_.get()); return SECSuccess; } - SECStatus Handshake() { return SSL_ForceHandshake(ssl_fd_); } + SECStatus Handshake() { return SSL_ForceHandshake(ssl_fd_.get()); } // Implement a trivial echo client/server. Read bytes from the other side, // flip all the bits, and send them back. SECStatus ReadWrite() { for (;;) { uint8_t block[512]; - int32_t rv = PR_Read(ssl_fd_, block, sizeof(block)); + int32_t rv = PR_Read(ssl_fd_.get(), block, sizeof(block)); if (rv < 0) { std::cerr << "Failure reading\n"; return SECFailure; @@ -412,7 +437,7 @@ class TestAgent { block[i] ^= 0xff; } - rv = PR_Write(ssl_fd_, block, len); + rv = PR_Write(ssl_fd_.get(), block, len); if (rv != len) { std::cerr << "Write failure\n"; PORT_SetError(SEC_ERROR_OUTPUT_LEN); @@ -431,7 +456,7 @@ class TestAgent { // reader and writer. uint8_t block[600]; memset(block, ch, sizeof(block)); - int32_t rv = PR_Write(ssl_fd_, block, sizeof(block)); + int32_t rv = PR_Write(ssl_fd_.get(), block, sizeof(block)); if (rv != sizeof(block)) { std::cerr << "Write failure\n"; PORT_SetError(SEC_ERROR_OUTPUT_LEN); @@ -440,7 +465,7 @@ class TestAgent { size_t left = sizeof(block); while (left) { - rv = PR_Read(ssl_fd_, block, left); + rv = PR_Read(ssl_fd_.get(), block, left); if (rv < 0) { std::cerr << "Failure reading\n"; return SECFailure; @@ -494,7 +519,7 @@ class TestAgent { SSLNextProtoState state; char chosen[256]; unsigned int chosen_len; - rv = SSL_GetNextProto(ssl_fd_, &state, + rv = SSL_GetNextProto(ssl_fd_.get(), &state, reinterpret_cast<unsigned char*>(chosen), &chosen_len, sizeof(chosen)); if (rv != SECSuccess) { @@ -514,7 +539,7 @@ class TestAgent { auto sig_alg = cfg_.get<int>("expect-peer-signature-algorithm"); if (sig_alg) { SSLChannelInfo info; - rv = SSL_GetChannelInfo(ssl_fd_, &info, sizeof(info)); + rv = SSL_GetChannelInfo(ssl_fd_.get(), &info, sizeof(info)); if (rv != SECSuccess) { PRErrorCode err = PR_GetError(); std::cerr << "SSL_GetChannelInfo failed with error=" << FormatError(err) @@ -534,10 +559,10 @@ class TestAgent { private: const Config& cfg_; - PRFileDesc* pr_fd_; - PRFileDesc* ssl_fd_; - CERTCertificate* cert_; - SECKEYPrivateKey* key_; + ScopedPRFileDesc pr_fd_; + ScopedPRFileDesc ssl_fd_; + ScopedCERTCertificate cert_; + ScopedSECKEYPrivateKey key_; }; std::unique_ptr<const Config> ReadConfig(int argc, char** argv) { @@ -559,11 +584,14 @@ std::unique_ptr<const Config> ReadConfig(int argc, char** argv) { cfg->AddEntry<bool>("write-then-read", false); cfg->AddEntry<bool>("require-any-client-certificate", false); cfg->AddEntry<bool>("verify-peer", false); + cfg->AddEntry<bool>("is-handshaker-supported", false); + cfg->AddEntry<std::string>("handshaker-path", ""); // Ignore this cfg->AddEntry<std::string>("advertise-alpn", ""); cfg->AddEntry<std::string>("expect-alpn", ""); cfg->AddEntry<std::vector<int>>("signing-prefs", std::vector<int>()); cfg->AddEntry<std::vector<int>>("verify-prefs", std::vector<int>()); cfg->AddEntry<int>("expect-peer-signature-algorithm", 0); + cfg->AddEntry<std::string>("nss-cipher", ""); auto rv = cfg->ParseArgs(argc, argv); switch (rv) { @@ -602,6 +630,11 @@ int main(int argc, char** argv) { return GetExitCode(false); } + if (cfg->get<bool>("is-handshaker-supported")) { + std::cout << "No\n"; + return 0; + } + if (cfg->get<bool>("server")) { if (SSL_ConfigServerSessionIDCache(1024, 0, 0, ".") != SECSuccess) { std::cerr << "Couldn't configure session cache\n"; diff --git a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.gyp b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.gyp index b8f71f95f..d08a6bde3 100644 --- a/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.gyp +++ b/security/nss/gtests/nss_bogo_shim/nss_bogo_shim.gyp @@ -37,6 +37,7 @@ '<(DEPTH)/lib/freebl/freebl.gyp:freebl', '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib', '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix', + '<(DEPTH)/cpputil/cpputil.gyp:cpputil', ], 'conditions': [ [ 'disable_dbm==0', { |