diff options
author | Kevin Jacobs <kjacobs@mozilla.com> | 2020-06-04 00:22:43 +0000 |
---|---|---|
committer | Kevin Jacobs <kjacobs@mozilla.com> | 2020-06-04 00:22:43 +0000 |
commit | e219e0fd50d570d89a5e32ebef9043d61be55e66 (patch) | |
tree | 174fb8f5d67ff53f66d04de557eb273dda50bc69 | |
parent | c0a4eb1da8fac2dc8cdb3baef7e0b0490d013932 (diff) | |
download | nss-hg-e219e0fd50d570d89a5e32ebef9043d61be55e66.tar.gz |
Bug 1643123 - Allow External PSKs to be used with Early Export r=mt
This patch adjusts `tls13_exporter` to pull the hash algorithm from the first PSK when a suite is not configured yet, which allows early export with external PSKs.
Differential Revision: https://phabricator.services.mozilla.com/D78150
-rw-r--r-- | gtests/ssl_gtest/ssl_exporter_unittest.cc | 37 | ||||
-rw-r--r-- | lib/ssl/sslinfo.c | 14 | ||||
-rw-r--r-- | lib/ssl/tls13con.c | 10 |
3 files changed, 58 insertions, 3 deletions
diff --git a/gtests/ssl_gtest/ssl_exporter_unittest.cc b/gtests/ssl_gtest/ssl_exporter_unittest.cc index c42883eb7..26ed6bc0e 100644 --- a/gtests/ssl_gtest/ssl_exporter_unittest.cc +++ b/gtests/ssl_gtest/ssl_exporter_unittest.cc @@ -148,4 +148,41 @@ TEST_P(TlsConnectTls13, EarlyExporter) { SendReceive(); } +TEST_P(TlsConnectTls13, EarlyExporterExternalPsk) { + RolloverAntiReplay(); + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_TRUE(!!slot); + ScopedPK11SymKey scoped_psk( + PK11_KeyGen(slot.get(), CKM_HKDF_KEY_GEN, nullptr, 16, nullptr)); + AddPsk(scoped_psk, std::string("foo"), ssl_hash_sha256, + TLS_CHACHA20_POLY1305_SHA256); + StartConnect(); + client_->Set0RttEnabled(true); + server_->Set0RttEnabled(true); + client_->Handshake(); // Send ClientHello. + uint8_t client_value[10] = {0}; + RegularExporterShouldFail(client_.get(), nullptr, 0); + + EXPECT_EQ(SECSuccess, + SSL_ExportEarlyKeyingMaterial( + client_->ssl_fd(), kExporterLabel, strlen(kExporterLabel), + kExporterContext, sizeof(kExporterContext), client_value, + sizeof(client_value))); + + server_->SetSniCallback(RegularExporterShouldFail); + server_->Handshake(); // Handle ClientHello. + uint8_t server_value[10] = {0}; + EXPECT_EQ(SECSuccess, + SSL_ExportEarlyKeyingMaterial( + server_->ssl_fd(), kExporterLabel, strlen(kExporterLabel), + kExporterContext, sizeof(kExporterContext), server_value, + sizeof(server_value))); + EXPECT_EQ(0, memcmp(client_value, server_value, sizeof(client_value))); + + Handshake(); + ExpectEarlyDataAccepted(true); + CheckConnected(); + SendReceive(); +} + } // namespace nss_test diff --git a/lib/ssl/sslinfo.c b/lib/ssl/sslinfo.c index 18a03949b..a92ed1604 100644 --- a/lib/ssl/sslinfo.c +++ b/lib/ssl/sslinfo.c @@ -429,8 +429,20 @@ tls13_Exporter(sslSocket *ss, PK11SymKey *secret, return SECFailure; } + SSLHashType hashAlg; + /* Early export requires a PSK. As in 0-RTT, default + * to the first PSK if no suite is negotiated yet. */ + if (secret == ss->ssl3.hs.earlyExporterSecret && !ss->ssl3.hs.suite_def) { + if (PR_CLIST_IS_EMPTY(&ss->ssl3.hs.psks)) { + PORT_SetError(SEC_ERROR_INVALID_ARGS); + return SECFailure; + } + hashAlg = ((sslPsk *)PR_LIST_HEAD(&ss->ssl3.hs.psks))->hash; + } else { + hashAlg = tls13_GetHash(ss); + } + /* Pre-hash the context. */ - SSLHashType hashAlg = tls13_GetHash(ss); rv = tls13_ComputeHash(ss, &contextHash, context, contextLen, hashAlg); if (rv != SECSuccess) { return rv; diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c index 50102d493..b79045bb4 100644 --- a/lib/ssl/tls13con.c +++ b/lib/ssl/tls13con.c @@ -269,9 +269,15 @@ SSLHashType tls13_GetHash(const sslSocket *ss) { /* suite_def may not be set yet when doing EPSK 0-Rtt. */ - if (!ss->ssl3.hs.suite_def && ss->xtnData.selectedPsk) { - return ss->xtnData.selectedPsk->hash; + if (!ss->ssl3.hs.suite_def) { + if (ss->xtnData.selectedPsk) { + return ss->xtnData.selectedPsk->hash; + } + /* This should never happen. */ + PORT_Assert(0); + return ssl_hash_none; } + /* All TLS 1.3 cipher suites must have an explict PRF hash. */ PORT_Assert(ss->ssl3.hs.suite_def->prf_hash != ssl_hash_none); return ss->ssl3.hs.suite_def->prf_hash; |