summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaiki Ueno <dueno@redhat.com>2019-04-08 10:05:56 +0200
committerDaiki Ueno <dueno@redhat.com>2019-04-08 10:05:56 +0200
commit0151b2ce26b409ab041e1a08ba4bd905cd565dc5 (patch)
treec59ce243b8dda474fb933382c79695afaab1751f
parent57344729bcdc0be111130c848a412526262ad817 (diff)
downloadnss-hg-0151b2ce26b409ab041e1a08ba4bd905cd565dc5.tar.gz
Bug 1532312, fix transcript-hash calculation after handshake, r=mt
Summary: In post-handshake, Handshake Context should be: ``` ClientHello ... client Finished + CertificateRequest ``` while NSS continues feeding any handshake message after handshake. Reviewers: mt Reviewed By: mt Bug #: 1532312 Differential Revision: https://phabricator.services.mozilla.com/D21935
-rw-r--r--gtests/ssl_gtest/ssl_auth_unittest.cc40
-rw-r--r--lib/ssl/ssl3con.c53
-rw-r--r--lib/ssl/sslencode.c9
-rw-r--r--lib/ssl/sslimpl.h22
-rw-r--r--lib/ssl/sslsecur.c13
-rw-r--r--lib/ssl/tls13con.c147
-rw-r--r--lib/ssl/tls13con.h7
-rw-r--r--lib/ssl/tls13hashstate.c6
8 files changed, 257 insertions, 40 deletions
diff --git a/gtests/ssl_gtest/ssl_auth_unittest.cc b/gtests/ssl_gtest/ssl_auth_unittest.cc
index 8db23e74e..7d4416edd 100644
--- a/gtests/ssl_gtest/ssl_auth_unittest.cc
+++ b/gtests/ssl_gtest/ssl_auth_unittest.cc
@@ -320,6 +320,46 @@ TEST_F(TlsConnectStreamTls13, PostHandshakeAuthConcurrent) {
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
+TEST_F(TlsConnectStreamTls13, PostHandshakeAuthBeforeKeyUpdate) {
+ client_->SetupClientAuth();
+ EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
+ SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
+ Connect();
+ // Send CertificateRequest.
+ EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
+ << "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
+ // Send KeyUpdate.
+ EXPECT_EQ(SECFailure, SSL_KeyUpdate(server_->ssl_fd(), PR_TRUE));
+ EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
+}
+
+TEST_F(TlsConnectStreamTls13, PostHandshakeAuthDuringClientKeyUpdate) {
+ client_->SetupClientAuth();
+ EXPECT_EQ(SECSuccess, SSL_OptionSet(client_->ssl_fd(),
+ SSL_ENABLE_POST_HANDSHAKE_AUTH, PR_TRUE));
+ Connect();
+ CheckEpochs(3, 3);
+ // Send CertificateRequest from server.
+ EXPECT_EQ(SECSuccess, SSL_SendCertificateRequest(server_->ssl_fd()))
+ << "Unexpected error: " << PORT_ErrorToName(PORT_GetError());
+ // Send KeyUpdate from client.
+ EXPECT_EQ(SECSuccess, SSL_KeyUpdate(client_->ssl_fd(), PR_TRUE));
+ server_->SendData(50); // server sends CertificateRequest
+ client_->SendData(50); // client sends KeyUpdate
+ server_->ReadBytes(50); // server receives KeyUpdate and defers response
+ CheckEpochs(4, 3);
+ client_->ReadBytes(50); // client receives CertificateRequest
+ client_->SendData(
+ 50); // client sends Certificate, CertificateVerify, Finished
+ server_->ReadBytes(
+ 50); // server receives Certificate, CertificateVerify, Finished
+ client_->CheckEpochs(3, 4);
+ server_->CheckEpochs(4, 4);
+ server_->SendData(50); // server sends KeyUpdate
+ client_->ReadBytes(50); // client receives KeyUpdate
+ client_->CheckEpochs(4, 4);
+}
+
TEST_F(TlsConnectStreamTls13, PostHandshakeAuthMissingExtension) {
client_->SetupClientAuth();
Connect();
diff --git a/lib/ssl/ssl3con.c b/lib/ssl/ssl3con.c
index 9385e5263..c88be6432 100644
--- a/lib/ssl/ssl3con.c
+++ b/lib/ssl/ssl3con.c
@@ -3719,6 +3719,10 @@ ssl3_RestartHandshakeHashes(sslSocket *ss)
PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
ss->ssl3.hs.sha = NULL;
}
+ if (ss->ssl3.hs.shaPostHandshake) {
+ PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE);
+ ss->ssl3.hs.shaPostHandshake = NULL;
+ }
}
/*
@@ -3779,6 +3783,24 @@ ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l
}
SECStatus
+ssl3_UpdatePostHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l)
+{
+ SECStatus rv = SECSuccess;
+
+ PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+
+ PRINT_BUF(90, (ss, "post handshake hash input:", b, l));
+
+ PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single);
+ PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
+ rv = PK11_DigestOp(ss->ssl3.hs.shaPostHandshake, b, l);
+ if (rv != SECSuccess) {
+ PORT_SetError(SSL_ERROR_DIGEST_FAILURE);
+ }
+ return rv;
+}
+
+SECStatus
ssl3_AppendHandshakeHeader(sslSocket *ss, SSLHandshakeType t, PRUint32 length)
{
SECStatus rv;
@@ -11623,7 +11645,8 @@ ssl3_FinishHandshake(sslSocket *ss)
SECStatus
ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct,
PRUint32 dtlsSeq,
- const PRUint8 *b, PRUint32 length)
+ const PRUint8 *b, PRUint32 length,
+ sslUpdateHandshakeHashes updateHashes)
{
PRUint8 hdr[4];
PRUint8 dtlsData[8];
@@ -11636,7 +11659,7 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct,
hdr[2] = (PRUint8)(length >> 8);
hdr[3] = (PRUint8)(length);
- rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)hdr, 4);
+ rv = updateHashes(ss, (unsigned char *)hdr, 4);
if (rv != SECSuccess)
return rv; /* err code already set. */
@@ -11656,14 +11679,13 @@ ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType ct,
dtlsData[6] = (PRUint8)(length >> 8);
dtlsData[7] = (PRUint8)(length);
- rv = ssl3_UpdateHandshakeHashes(ss, (unsigned char *)dtlsData,
- sizeof(dtlsData));
+ rv = updateHashes(ss, (unsigned char *)dtlsData, sizeof(dtlsData));
if (rv != SECSuccess)
return rv; /* err code already set. */
}
/* The message body */
- rv = ssl3_UpdateHandshakeHashes(ss, b, length);
+ rv = updateHashes(ss, b, length);
if (rv != SECSuccess)
return rv; /* err code already set. */
@@ -11675,7 +11697,15 @@ ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType ct,
const PRUint8 *b, PRUint32 length)
{
return ssl_HashHandshakeMessageInt(ss, ct, ss->ssl3.hs.recvMessageSeq,
- b, length);
+ b, length, ssl3_UpdateHandshakeHashes);
+}
+
+SECStatus
+ssl_HashPostHandshakeMessage(sslSocket *ss, SSLHandshakeType ct,
+ const PRUint8 *b, PRUint32 length)
+{
+ return ssl_HashHandshakeMessageInt(ss, ct, ss->ssl3.hs.recvMessageSeq,
+ b, length, ssl3_UpdatePostHandshakeHashes);
}
/* Called from ssl3_HandleHandshake() when it has gathered a complete ssl3
@@ -11714,9 +11744,11 @@ ssl3_HandleHandshakeMessage(sslSocket *ss, PRUint8 *b, PRUint32 length,
break;
default:
- rv = ssl_HashHandshakeMessage(ss, ss->ssl3.hs.msg_type, b, length);
- if (rv != SECSuccess) {
- return SECFailure;
+ if (!tls13_IsPostHandshake(ss)) {
+ rv = ssl_HashHandshakeMessage(ss, ss->ssl3.hs.msg_type, b, length);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
}
}
@@ -13129,6 +13161,9 @@ ssl3_DestroySSL3Info(sslSocket *ss)
if (ss->ssl3.hs.sha) {
PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
}
+ if (ss->ssl3.hs.shaPostHandshake) {
+ PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE);
+ }
if (ss->ssl3.hs.messages.buf) {
sslBuffer_Clear(&ss->ssl3.hs.messages);
}
diff --git a/lib/ssl/sslencode.c b/lib/ssl/sslencode.c
index e50880451..e59e758ff 100644
--- a/lib/ssl/sslencode.c
+++ b/lib/ssl/sslencode.c
@@ -10,6 +10,7 @@
#include "prnetdb.h"
#include "ssl.h"
#include "sslimpl.h"
+#include "sslproto.h"
/* Helper function to encode an unsigned integer into a buffer. */
static void
@@ -263,9 +264,11 @@ ssl3_AppendHandshake(sslSocket *ss, const void *void_src, unsigned int bytes)
}
PRINT_BUF(60, (ss, "Append to Handshake", (unsigned char *)void_src, bytes));
- rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
- if (rv != SECSuccess)
- return SECFailure; /* error code set by ssl3_UpdateHandshakeHashes */
+ if (!ss->firstHsDone || ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ rv = ssl3_UpdateHandshakeHashes(ss, src, bytes);
+ if (rv != SECSuccess)
+ return SECFailure; /* error code set by ssl3_UpdateHandshakeHashes */
+ }
while (bytes > room) {
if (room > 0)
diff --git a/lib/ssl/sslimpl.h b/lib/ssl/sslimpl.h
index 575f4964a..b70ddc955 100644
--- a/lib/ssl/sslimpl.h
+++ b/lib/ssl/sslimpl.h
@@ -144,6 +144,11 @@ typedef enum {
ticket_allow_psk_sign_auth = 16
} TLS13SessionTicketFlags;
+typedef enum {
+ update_not_requested = 0,
+ update_requested = 1
+} tls13KeyUpdateRequest;
+
struct sslNamedGroupDefStr {
/* The name is the value that is encoded on the wire in TLS. */
SSLNamedGroup name;
@@ -610,6 +615,7 @@ typedef struct SSL3HandshakeStateStr {
* TLS 1.2 and later use only |sha|, for SHA-256. */
PK11Context *md5;
PK11Context *sha;
+ PK11Context *shaPostHandshake;
SSLSignatureScheme signatureScheme;
const ssl3KEADef *kea_def;
ssl3CipherSuite cipher_suite;
@@ -743,6 +749,11 @@ struct ssl3StateStr {
* update is initiated locally. */
PRBool peerRequestedKeyUpdate;
+ /* This is true if we deferred sending a key update as
+ * post-handshake auth is in progress. */
+ PRBool keyUpdateDeferred;
+ tls13KeyUpdateRequest deferredKeyUpdateRequest;
+
/* This is true after the server requests client certificate;
* false after the client certificate is received. Used by the
* server. */
@@ -1213,15 +1224,24 @@ extern SECStatus Null_Cipher(void *ctx, unsigned char *output, unsigned int *out
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen);
extern void ssl3_RestartHandshakeHashes(sslSocket *ss);
+typedef SECStatus (*sslUpdateHandshakeHashes)(sslSocket *ss,
+ const unsigned char *b,
+ unsigned int l);
extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
const unsigned char *b,
unsigned int l);
+extern SECStatus ssl3_UpdatePostHandshakeHashes(sslSocket *ss,
+ const unsigned char *b,
+ unsigned int l);
SECStatus
ssl_HashHandshakeMessageInt(sslSocket *ss, SSLHandshakeType type,
PRUint32 dtlsSeq,
- const PRUint8 *b, PRUint32 length);
+ const PRUint8 *b, PRUint32 length,
+ sslUpdateHandshakeHashes cb);
SECStatus ssl_HashHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
const PRUint8 *b, PRUint32 length);
+SECStatus ssl_HashPostHandshakeMessage(sslSocket *ss, SSLHandshakeType type,
+ const PRUint8 *b, PRUint32 length);
/* Returns PR_TRUE if we are still waiting for the server to complete its
* response to our client second round. Once we've received the Finished from
diff --git a/lib/ssl/sslsecur.c b/lib/ssl/sslsecur.c
index 79634e403..14320fa19 100644
--- a/lib/ssl/sslsecur.c
+++ b/lib/ssl/sslsecur.c
@@ -720,7 +720,8 @@ tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir)
ssl3CipherSpec *spec;
sslSequenceNumber seqNum;
sslSequenceNumber margin;
- SECStatus rv;
+ tls13KeyUpdateRequest keyUpdateRequest;
+ SECStatus rv = SECSuccess;
/* Bug 1413368: enable for DTLS */
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 || IS_DTLS(ss)) {
@@ -755,9 +756,15 @@ tls13_CheckKeyUpdate(sslSocket *ss, SSLSecretDirection dir)
SSL_TRC(5, ("%d: SSL[%d]: automatic key update at %llx for %s cipher spec",
SSL_GETPID(), ss->fd, seqNum,
(dir == ssl_secret_read) ? "read" : "write"));
+ keyUpdateRequest = (dir == ssl_secret_read) ? update_requested : update_not_requested;
ssl_GetSSL3HandshakeLock(ss);
- rv = tls13_SendKeyUpdate(ss, (dir == ssl_secret_read) ? update_requested : update_not_requested,
- dir == ssl_secret_write /* buffer */);
+ if (ss->ssl3.clientCertRequested) {
+ ss->ssl3.keyUpdateDeferred = PR_TRUE;
+ ss->ssl3.deferredKeyUpdateRequest = keyUpdateRequest;
+ } else {
+ rv = tls13_SendKeyUpdate(ss, keyUpdateRequest,
+ dir == ssl_secret_write /* buffer */);
+ }
ssl_ReleaseSSL3HandshakeLock(ss);
return rv;
}
diff --git a/lib/ssl/tls13con.c b/lib/ssl/tls13con.c
index 704618070..88bc618b3 100644
--- a/lib/ssl/tls13con.c
+++ b/lib/ssl/tls13con.c
@@ -259,6 +259,12 @@ tls13_CheckHsState(sslSocket *ss, int err, const char *error_name,
return SECFailure;
}
+PRBool
+tls13_IsPostHandshake(const sslSocket *ss)
+{
+ return ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 && ss->firstHsDone;
+}
+
SSLHashType
tls13_GetHashForCipherSuite(ssl3CipherSuite suite)
{
@@ -682,8 +688,9 @@ tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request, PRBool buffer)
: "not requested"));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
+ PORT_Assert(!ss->sec.isServer || !ss->ssl3.clientCertRequested);
- if (!ss->firstHsDone) {
+ if (!tls13_IsPostHandshake(ss)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
@@ -741,11 +748,16 @@ SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate)
return SECFailure;
}
- if (!ss->firstHsDone) {
+ if (!tls13_IsPostHandshake(ss)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ if (ss->ssl3.clientCertRequested) {
+ PORT_SetError(PR_WOULD_BLOCK_ERROR);
+ return SECFailure;
+ }
+
rv = TLS13_CHECK_HS_STATE(ss, SEC_ERROR_INVALID_ARGS,
idle_handshake);
if (rv != SECSuccess) {
@@ -786,7 +798,7 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length)
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->firstHsDone);
- if (!ss->firstHsDone) {
+ if (!tls13_IsPostHandshake(ss)) {
FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_KEY_UPDATE, unexpected_message);
return SECFailure;
}
@@ -820,7 +832,12 @@ tls13_HandleKeyUpdate(sslSocket *ss, PRUint8 *b, unsigned int length)
if (update == update_requested) {
PRBool sendUpdate;
- if (ss->ssl3.peerRequestedKeyUpdate) {
+ if (ss->ssl3.clientCertRequested) {
+ /* Post-handshake auth is in progress; defer sending a key update. */
+ ss->ssl3.keyUpdateDeferred = PR_TRUE;
+ ss->ssl3.deferredKeyUpdateRequest = update_not_requested;
+ sendUpdate = PR_FALSE;
+ } else if (ss->ssl3.peerRequestedKeyUpdate) {
/* Only send an update if we have sent with the current spec. This
* prevents us from being forced to crank forward pointlessly. */
ssl_GetSpecReadLock(ss);
@@ -857,7 +874,7 @@ SSLExp_SendCertificateRequest(PRFileDesc *fd)
return SECFailure;
}
- if (!ss->firstHsDone || ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
+ if (!tls13_IsPostHandshake(ss)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
@@ -2195,10 +2212,20 @@ tls13_SendCertificateRequest(sslSocket *ss)
{
SECStatus rv;
sslBuffer extensionBuf = SSL_BUFFER_EMPTY;
+ unsigned int offset = 0;
SSL_TRC(3, ("%d: TLS13[%d]: begin send certificate_request",
SSL_GETPID(), ss->fd));
+ if (ss->firstHsDone) {
+ PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL);
+ ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha);
+ if (ss->ssl3.hs.shaPostHandshake == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ }
+
rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_certificate_request);
if (rv != SECSuccess) {
return SECFailure; /* Code already set. */
@@ -2222,6 +2249,8 @@ tls13_SendCertificateRequest(sslSocket *ss)
FATAL_ERROR(ss, SEC_ERROR_NO_MEMORY, internal_error);
goto loser;
}
+
+ offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf);
}
rv = ssl3_AppendHandshakeHeader(ss, ssl_hs_certificate_request,
@@ -2245,6 +2274,15 @@ tls13_SendCertificateRequest(sslSocket *ss)
goto loser; /* err set by AppendHandshake. */
}
+ if (ss->firstHsDone) {
+ rv = ssl3_UpdatePostHandshakeHashes(ss,
+ SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset,
+ SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ }
+
sslBuffer_Clear(&extensionBuf);
return SECSuccess;
@@ -2410,7 +2448,19 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECFailure;
}
- if (ss->firstHsDone) {
+ if (tls13_IsPostHandshake(ss)) {
+ PORT_Assert(ss->ssl3.hs.shaPostHandshake == NULL);
+ ss->ssl3.hs.shaPostHandshake = PK11_CloneContext(ss->ssl3.hs.sha);
+ if (ss->ssl3.hs.shaPostHandshake == NULL) {
+ ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
+ return SECFailure;
+ }
+ rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_request, b, length);
+ if (rv != SECSuccess) {
+ FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
+ return SECFailure;
+ }
+
/* clean up anything left from previous handshake. */
if (ss->ssl3.clientCertChain != NULL) {
CERT_DestroyCertificateList(ss->ssl3.clientCertChain);
@@ -2441,7 +2491,7 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
/* Unless it is a post-handshake client auth, the certificate
* request context must be empty. */
- if (!ss->firstHsDone && context.len > 0) {
+ if (!tls13_IsPostHandshake(ss) && context.len > 0) {
FATAL_ERROR(ss, SSL_ERROR_RX_MALFORMED_CERT_REQUEST, illegal_parameter);
return SECFailure;
}
@@ -2501,6 +2551,9 @@ tls13_HandleCertificateRequest(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECFailure;
}
PORT_Assert(ss->ssl3.hs.ws == idle_handshake);
+ PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL);
+ PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE);
+ ss->ssl3.hs.shaPostHandshake = NULL;
} else {
TLS13_SET_HS_STATE(ss, wait_server_cert);
}
@@ -3058,6 +3111,15 @@ tls13_HandleCertificate(sslSocket *ss, PRUint8 *b, PRUint32 length)
ssl_CipherSpecReleaseByEpoch(ss, ssl_secret_read, TrafficKeyClearText);
dtls_ReceivedFirstMessageInFlight(ss);
}
+
+ if (ss->firstHsDone) {
+ rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate, b, length);
+ if (rv != SECSuccess) {
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ }
+
/* Process the context string */
rv = ssl3_ConsumeHandshakeVariable(ss, &context, 1, &b, &length);
if (rv != SECSuccess)
@@ -3615,7 +3677,11 @@ tls13_ComputeHandshakeHashes(sslSocket *ss, SSL3Hashes *hashes)
goto loser;
}
} else {
- ctx = PK11_CloneContext(ss->ssl3.hs.sha);
+ if (ss->firstHsDone) {
+ ctx = PK11_CloneContext(ss->ssl3.hs.shaPostHandshake);
+ } else {
+ ctx = PK11_CloneContext(ss->ssl3.hs.sha);
+ }
if (!ctx) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
@@ -4069,7 +4135,11 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
return SECFailure;
}
- rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length);
+ if (ss->firstHsDone) {
+ rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_certificate_verify, b, length);
+ } else {
+ rv = ssl_HashHandshakeMessage(ss, ssl_hs_certificate_verify, b, length);
+ }
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
@@ -4129,10 +4199,6 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
}
}
- if (ss->ssl3.clientCertRequested) {
- PORT_Assert(ss->sec.isServer);
- ss->ssl3.clientCertRequested = PR_FALSE;
- }
TLS13_SET_HS_STATE(ss, wait_finished);
return SECSuccess;
@@ -4393,7 +4459,11 @@ tls13_CommonHandleFinished(sslSocket *ss, PK11SymKey *key,
return SECFailure;
}
- rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length);
+ if (ss->firstHsDone) {
+ rv = ssl_HashPostHandshakeMessage(ss, ssl_hs_finished, b, length);
+ } else {
+ rv = ssl_HashHandshakeMessage(ss, ssl_hs_finished, b, length);
+ }
if (rv != SECSuccess) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
@@ -4443,6 +4513,22 @@ tls13_ServerHandleFinished(sslSocket *ss, PRUint8 *b, PRUint32 length)
if (ss->firstHsDone) {
TLS13_SET_HS_STATE(ss, idle_handshake);
+
+ PORT_Assert(ss->ssl3.hs.shaPostHandshake != NULL);
+ PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE);
+ ss->ssl3.hs.shaPostHandshake = NULL;
+
+ ss->ssl3.clientCertRequested = PR_FALSE;
+
+ if (ss->ssl3.keyUpdateDeferred) {
+ rv = tls13_SendKeyUpdate(ss, ss->ssl3.deferredKeyUpdateRequest,
+ PR_FALSE);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error is set. */
+ }
+ ss->ssl3.keyUpdateDeferred = PR_FALSE;
+ }
+
return SECSuccess;
}
@@ -4525,11 +4611,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert,
SSL3AlertDescription *sendAlert)
{
SECStatus rv;
+ unsigned int offset = 0;
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
*sendAlert = internal_error;
+ if (ss->firstHsDone) {
+ offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf);
+ }
+
if (ss->ssl3.sendEmptyCert) {
ss->ssl3.sendEmptyCert = PR_FALSE;
rv = ssl3_SendEmptyCertificate(ss);
@@ -4543,6 +4634,16 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert,
return SECFailure; /* error code is set. */
}
}
+
+ if (ss->firstHsDone) {
+ rv = ssl3_UpdatePostHandshakeHashes(ss,
+ SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset,
+ SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error code is set. */
+ }
+ }
+
if (ss->ssl3.hs.clientCertRequested) {
SECITEM_FreeItem(&ss->xtnData.certReqContext, PR_FALSE);
if (ss->xtnData.certReqAuthorities.arena) {
@@ -4555,12 +4656,25 @@ tls13_SendClientSecondFlight(sslSocket *ss, PRBool sendClientCert,
}
if (sendClientCert) {
+ if (ss->firstHsDone) {
+ offset = SSL_BUFFER_LEN(&ss->sec.ci.sendBuf);
+ }
+
rv = tls13_SendCertificateVerify(ss, ss->ssl3.clientPrivateKey);
SECKEY_DestroyPrivateKey(ss->ssl3.clientPrivateKey);
ss->ssl3.clientPrivateKey = NULL;
if (rv != SECSuccess) {
return SECFailure; /* err is set. */
}
+
+ if (ss->firstHsDone) {
+ rv = ssl3_UpdatePostHandshakeHashes(ss,
+ SSL_BUFFER_BASE(&ss->sec.ci.sendBuf) + offset,
+ SSL_BUFFER_LEN(&ss->sec.ci.sendBuf) - offset);
+ if (rv != SECSuccess) {
+ return SECFailure; /* error is set. */
+ }
+ }
}
rv = tls13_SendFinished(ss, ss->firstHsDone ? ss->ssl3.hs.clientTrafficSecret : ss->ssl3.hs.clientHsTrafficSecret);
@@ -4825,8 +4939,7 @@ SSLExp_SendSessionTicket(PRFileDesc *fd, const PRUint8 *token,
return SECFailure;
}
- if (!ss->sec.isServer || !ss->firstHsDone ||
- ss->version < SSL_LIBRARY_VERSION_TLS_1_3 ||
+ if (!ss->sec.isServer || !tls13_IsPostHandshake(ss) ||
tokenLen > 0xffff) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
@@ -4862,7 +4975,7 @@ tls13_HandleNewSessionTicket(sslSocket *ss, PRUint8 *b, PRUint32 length)
if (rv != SECSuccess) {
return SECFailure;
}
- if (!ss->firstHsDone || ss->sec.isServer) {
+ if (!tls13_IsPostHandshake(ss) || ss->sec.isServer) {
FATAL_ERROR(ss, SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET,
unexpected_message);
return SECFailure;
diff --git a/lib/ssl/tls13con.h b/lib/ssl/tls13con.h
index ed4c4ec78..4968ac361 100644
--- a/lib/ssl/tls13con.h
+++ b/lib/ssl/tls13con.h
@@ -18,11 +18,6 @@ typedef enum {
tls13_extension_unknown
} tls13ExtensionStatus;
-typedef enum {
- update_not_requested = 0,
- update_requested = 1
-} tls13KeyUpdateRequest;
-
#define TLS13_MAX_FINISHED_SIZE 64
SECStatus tls13_UnprotectRecord(
@@ -47,6 +42,8 @@ PRBool tls13_InHsState(sslSocket *ss, ...);
#define TLS13_IN_HS_STATE(ss, ...) \
tls13_InHsState(ss, __VA_ARGS__, wait_invalid)
+PRBool tls13_IsPostHandshake(const sslSocket *ss);
+
SSLHashType tls13_GetHashForCipherSuite(ssl3CipherSuite suite);
SSLHashType tls13_GetHash(const sslSocket *ss);
unsigned int tls13_GetHashSizeForHash(SSLHashType hash);
diff --git a/lib/ssl/tls13hashstate.c b/lib/ssl/tls13hashstate.c
index cc0ed286b..53d3738f0 100644
--- a/lib/ssl/tls13hashstate.c
+++ b/lib/ssl/tls13hashstate.c
@@ -157,7 +157,8 @@ tls13_RecoverHashState(sslSocket *ss,
/* Now reinject the message. */
SSL_ASSERT_HASHES_EMPTY(ss);
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_message_hash, 0,
- SSL_READER_CURRENT(&reader), hashLen);
+ SSL_READER_CURRENT(&reader), hashLen,
+ ssl3_UpdateHandshakeHashes);
if (rv != SECSuccess) {
return SECFailure;
}
@@ -173,7 +174,8 @@ tls13_RecoverHashState(sslSocket *ss,
rv = ssl_HashHandshakeMessageInt(ss, ssl_hs_server_hello, 0,
SSL_BUFFER_BASE(&messageBuf),
- SSL_BUFFER_LEN(&messageBuf));
+ SSL_BUFFER_LEN(&messageBuf),
+ ssl3_UpdateHandshakeHashes);
sslBuffer_Clear(&messageBuf);
if (rv != SECSuccess) {
return SECFailure;