summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Jacobs <kjacobs@mozilla.com>2020-06-04 00:22:43 +0000
committerKevin Jacobs <kjacobs@mozilla.com>2020-06-04 00:22:43 +0000
commite219e0fd50d570d89a5e32ebef9043d61be55e66 (patch)
tree174fb8f5d67ff53f66d04de557eb273dda50bc69
parentc0a4eb1da8fac2dc8cdb3baef7e0b0490d013932 (diff)
downloadnss-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.cc37
-rw-r--r--lib/ssl/sslinfo.c14
-rw-r--r--lib/ssl/tls13con.c10
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;