mirror of https://github.com/wolfSSL/wolfssl.git
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.
parent
1b051d9c5b
commit
3be390d50d
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);
|
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
input += OPAQUE8_LEN + len;
|
input += OPAQUE8_LEN;
|
||||||
*sslBytes -= OPAQUE8_LEN + 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
|
#endif
|
||||||
|
|
||||||
|
@ -2549,10 +2555,24 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
|
||||||
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
||||||
return -1;
|
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
|
else
|
||||||
#endif
|
#endif /* WOLFSSL_TLS13 */
|
||||||
{
|
{
|
||||||
/* make sure ticket id isn't too long */
|
/* make sure ticket id isn't too long */
|
||||||
if (len > ID_LEN) {
|
if (len > ID_LEN) {
|
||||||
|
@ -2716,6 +2736,11 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||||
/* indicates we want to use resumption */
|
/* indicates we want to use resumption */
|
||||||
session->sslServer->options.resuming = 1;
|
session->sslServer->options.resuming = 1;
|
||||||
session->sslClient->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;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case EXT_SUPPORTED_VERSIONS:
|
case EXT_SUPPORTED_VERSIONS:
|
||||||
|
@ -2764,18 +2789,32 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doResume) {
|
if (doResume) {
|
||||||
SSL_SESSION* resume = GetSession(session->sslServer,
|
WOLFSSL_SESSION* resume;
|
||||||
session->sslServer->arrays->masterSecret, 0);
|
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
|
||||||
if (resume == NULL && !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
|
#ifdef WOLFSSL_SNIFFER_STATS
|
||||||
INC_STAT(SnifferStats.sslResumeMisses);
|
INC_STAT(SnifferStats.sslResumeMisses);
|
||||||
#endif
|
#endif
|
||||||
SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
|
SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make sure client has master secret too */
|
/* make sure client has master secret too */
|
||||||
XMEMCPY(session->sslClient->arrays->masterSecret,
|
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
|
||||||
session->sslServer->arrays->masterSecret, SECRET_LEN);
|
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;
|
session->flags.resuming = 1;
|
||||||
|
|
||||||
Trace(SERVER_DID_RESUMPTION_STR);
|
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_key,
|
||||||
session->sslServer->arrays->psk_keySz);
|
session->sslServer->arrays->psk_keySz);
|
||||||
#endif
|
#endif
|
||||||
|
/* handshake key setup below and traffic keys done in SetupKeys */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
@ -3120,10 +3160,9 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
|
||||||
inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
|
inputHelloSz - bindersLen + HANDSHAKE_HEADER_SZ);
|
||||||
|
|
||||||
/* call to decrypt session ticket */
|
/* call to decrypt session ticket */
|
||||||
ret = DoClientTicket(ssl, identity, idLen);
|
if (DoClientTicket(ssl, identity, idLen) != 0) {
|
||||||
if (ret != 0) {
|
/* we aren't decrypting the resumption, since we know the master secret */
|
||||||
SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
|
/* ignore errors */
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
ssl->options.resuming = 1;
|
ssl->options.resuming = 1;
|
||||||
|
|
||||||
|
@ -3310,33 +3349,54 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
|
||||||
|
|
||||||
#ifdef WOLFSSL_TLS13
|
#ifdef WOLFSSL_TLS13
|
||||||
/* Derive TLS v1.3 traffic keys */
|
/* Derive TLS v1.3 traffic keys */
|
||||||
if (IsAtLeastTLSv1_3(ssl->version) && !session->flags.gotFinished) {
|
if (IsAtLeastTLSv1_3(ssl->version)) {
|
||||||
/* When either side gets "finished" derive master secret and keys, but only set the key for the side encrypting data */
|
if (!session->flags.gotFinished) {
|
||||||
ret = DeriveMasterSecret(session->sslServer);
|
/* When either side gets "finished" derive master secret and keys */
|
||||||
ret += DeriveMasterSecret(session->sslClient);
|
ret = DeriveMasterSecret(session->sslServer);
|
||||||
#ifdef WOLFSSL_EARLY_DATA
|
ret += DeriveMasterSecret(session->sslClient);
|
||||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
#ifdef WOLFSSL_EARLY_DATA
|
||||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||||
#else
|
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, ssl->earlyData == no_early_data);
|
||||||
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
#else
|
||||||
ret += DeriveTls13Keys(session->sslClient, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
ret += DeriveTls13Keys(session->sslServer, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, 1);
|
||||||
#endif
|
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) {
|
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);
|
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 {
|
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);
|
ret += SetKeysSide(session->sslClient, DECRYPT_SIDE_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
|
SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
session->flags.gotFinished = 1;
|
|
||||||
#ifdef SHOW_SECRETS
|
|
||||||
ShowTlsSecrets(session);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -737,7 +737,7 @@ static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] =
|
||||||
* key The derived key.
|
* key The derived key.
|
||||||
* returns 0 on success, otherwise failure.
|
* returns 0 on success, otherwise failure.
|
||||||
*/
|
*/
|
||||||
static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
|
int DeriveResumptionSecret(WOLFSSL* ssl, byte* key)
|
||||||
{
|
{
|
||||||
WOLFSSL_MSG("Derive Resumption Secret");
|
WOLFSSL_MSG("Derive Resumption Secret");
|
||||||
if (ssl == NULL || ssl->arrays == NULL) {
|
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 DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store);
|
||||||
WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl);
|
WOLFSSL_LOCAL int DeriveMasterSecret(WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret);
|
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. */
|
/* The key update request values for KeyUpdate message. */
|
||||||
enum KeyUpdateRequest {
|
enum KeyUpdateRequest {
|
||||||
|
|
Loading…
Reference in New Issue