forked from wolfSSL/wolfssl
Added TLS v1.3 session resumption support. TLS v1.3 uses session tickets and a resumption secret is derived after the "finished" message. This uses the internal static wolf session cache to retain the resumption secret between sniffer sessions.
This commit is contained in:
120
src/sniffer.c
120
src/sniffer.c
@ -2520,8 +2520,14 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
|
||||
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
input += OPAQUE8_LEN + len;
|
||||
*sslBytes -= OPAQUE8_LEN + len;
|
||||
input += OPAQUE8_LEN;
|
||||
*sslBytes -= OPAQUE8_LEN;
|
||||
/* store nonce in server for DeriveResumptionPSK */
|
||||
session->sslServer->session.ticketNonce.len = len;
|
||||
if (len > 0)
|
||||
XMEMCPY(&session->sslServer->session.ticketNonce.data, input, len);
|
||||
input += len;
|
||||
*sslBytes -= len;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2549,10 +2555,24 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
|
||||
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* set haveSessionId to use the wolfSession cache */
|
||||
ssl->options.haveSessionId = 1;
|
||||
|
||||
/* Use the wolf Session cache to retain resumption secret */
|
||||
if (session->flags.cached == 0) {
|
||||
WOLFSSL_SESSION* sess = GetSession(ssl, NULL, 0);
|
||||
if (sess == NULL) {
|
||||
AddSession(ssl); /* don't re add */
|
||||
#ifdef WOLFSSL_SNIFFER_STATS
|
||||
INC_STAT(SnifferStats.sslResumptionInserts);
|
||||
#endif
|
||||
}
|
||||
session->flags.cached = 1;
|
||||
}
|
||||
#endif /* HAVE_SESSION_TICKET */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#endif /* WOLFSSL_TLS13 */
|
||||
{
|
||||
/* make sure ticket id isn't too long */
|
||||
if (len > ID_LEN) {
|
||||
@ -2716,6 +2736,11 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
/* indicates we want to use resumption */
|
||||
session->sslServer->options.resuming = 1;
|
||||
session->sslClient->options.resuming = 1;
|
||||
/* default nonce to len = 1, data = 0 */
|
||||
session->sslServer->session.ticketNonce.len = 1;
|
||||
session->sslServer->session.ticketNonce.data[0] = 0;
|
||||
session->sslClient->session.ticketNonce.len = 1;
|
||||
session->sslClient->session.ticketNonce.data[0] = 0;
|
||||
break;
|
||||
#endif
|
||||
case EXT_SUPPORTED_VERSIONS:
|
||||
@ -2764,18 +2789,32 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
}
|
||||
|
||||
if (doResume) {
|
||||
SSL_SESSION* resume = GetSession(session->sslServer,
|
||||
session->sslServer->arrays->masterSecret, 0);
|
||||
if (resume == NULL && !IsAtLeastTLSv1_3(session->sslServer->version)) {
|
||||
WOLFSSL_SESSION* resume;
|
||||
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
|
||||
resume = GetSession(session->sslServer,
|
||||
session->sslServer->session.masterSecret, 0);
|
||||
}
|
||||
else {
|
||||
resume = GetSession(session->sslServer,
|
||||
session->sslServer->arrays->masterSecret, 0);
|
||||
}
|
||||
if (resume == NULL) {
|
||||
#ifdef WOLFSSL_SNIFFER_STATS
|
||||
INC_STAT(SnifferStats.sslResumeMisses);
|
||||
#endif
|
||||
SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* make sure client has master secret too */
|
||||
XMEMCPY(session->sslClient->arrays->masterSecret,
|
||||
session->sslServer->arrays->masterSecret, SECRET_LEN);
|
||||
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
|
||||
XMEMCPY(session->sslClient->session.masterSecret,
|
||||
session->sslServer->session.masterSecret, SECRET_LEN);
|
||||
}
|
||||
else {
|
||||
XMEMCPY(session->sslClient->arrays->masterSecret,
|
||||
session->sslServer->arrays->masterSecret, SECRET_LEN);
|
||||
}
|
||||
session->flags.resuming = 1;
|
||||
|
||||
Trace(SERVER_DID_RESUMPTION_STR);
|
||||
@ -2806,6 +2845,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||
session->sslServer->arrays->psk_key,
|
||||
session->sslServer->arrays->psk_keySz);
|
||||
#endif
|
||||
/* handshake key setup below and traffic keys done in SetupKeys */
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -3120,10 +3160,9 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
||||
inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
|
||||
|
||||
/* call to decrypt session ticket */
|
||||
ret = DoClientTicket(ssl, identity, idLen);
|
||||
if (ret != 0) {
|
||||
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
if (DoClientTicket(ssl, identity, idLen) != 0) {
|
||||
/* we aren't decrypting the resumption, since we know the master secret */
|
||||
/* ignore errors */
|
||||
}
|
||||
ssl->options.resuming = 1;
|
||||
|
||||
@ -3310,33 +3349,54 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
|
||||
|
||||
#ifdef WOLFSSL_TLS13
|
||||
/* Derive TLS v1.3 traffic keys */
|
||||
if (IsAtLeastTLSv1_3(ssl->version) && !session->flags.gotFinished) {
|
||||
/* When either side gets "finished" derive master secret and keys, but only set the key for the side encrypting data */
|
||||
ret = DeriveMasterSecret(session->sslServer);
|
||||
ret += DeriveMasterSecret(session->sslClient);
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||
#else
|
||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
||||
#endif
|
||||
if (IsAtLeastTLSv1_3(ssl->version)) {
|
||||
if (!session->flags.gotFinished) {
|
||||
/* When either side gets "finished" derive master secret and keys */
|
||||
ret = DeriveMasterSecret(session->sslServer);
|
||||
ret += DeriveMasterSecret(session->sslClient);
|
||||
#ifdef WOLFSSL_EARLY_DATA
|
||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||
#else
|
||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
||||
#endif
|
||||
|
||||
if (ret != 0) {
|
||||
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
session->flags.gotFinished = 1;
|
||||
#ifdef SHOW_SECRETS
|
||||
ShowTlsSecrets(session);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (session->flags.side == WOLFSSL_SERVER_END) {
|
||||
ret += SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
|
||||
/* finished from client to server */
|
||||
ret = SetKeysSide(session->sslServer, DECRYPT_SIDE_ONLY);
|
||||
ret += SetKeysSide(session->sslClient, ENCRYPT_SIDE_ONLY);
|
||||
|
||||
#ifdef HAVE_SESSION_TICKET
|
||||
/* derive resumption secret for next session - on finished (from client) */
|
||||
ret += DeriveResumptionSecret(session->sslClient, session->sslClient->session.masterSecret);
|
||||
|
||||
/* copy resumption secret to server */
|
||||
XMEMCPY(session->sslServer->session.masterSecret,
|
||||
session->sslClient->session.masterSecret, SECRET_LEN);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
ret += SetKeysSide(session->sslServer, ENCRYPT_SIDE_ONLY);
|
||||
/* finished from server to client */
|
||||
ret = SetKeysSide(session->sslServer, ENCRYPT_SIDE_ONLY);
|
||||
ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
|
||||
return -1;
|
||||
}
|
||||
session->flags.gotFinished = 1;
|
||||
#ifdef SHOW_SECRETS
|
||||
ShowTlsSecrets(session);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -737,7 +737,7 @@ static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
|
||||
* key The derived key.
|
||||
* returns 0 on success, otherwise failure.
|
||||
*/
|
||||
static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
|
||||
int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
|
||||
{
|
||||
WOLFSSL_MSG("Derive Resumption Secret");
|
||||
if (ssl == NULL || ssl->arrays == NULL) {
|
||||
|
@ -2590,6 +2590,7 @@ WOLFSSL_LOCAL int DeriveHandshakeSecret(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store);
|
||||
WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl);
|
||||
WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret);
|
||||
WOLFSSL_LOCAL int DeriveResumptionSecret(WOLFSSL* ssl, byte* key);
|
||||
|
||||
/* The key update request values for KeyUpdate message. */
|
||||
enum KeyUpdateRequest {
|
||||
|
Reference in New Issue
Block a user