Fixes for sniffer with hello_retry_request. Fix for TLS v1.3 certificate processing.

This commit is contained in:
David Garske
2020-11-04 12:54:14 -08:00
parent c7bb602a30
commit b74f0fb6b8
5 changed files with 76 additions and 19 deletions

View File

@ -299,6 +299,7 @@ static const char* const msgTable[] =
"Store data callback failed", "Store data callback failed",
"Loading chain input", "Loading chain input",
"Got encrypted extension", "Got encrypted extension",
"Got Hello Retry Request",
}; };
@ -2415,13 +2416,18 @@ static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
/* Named group and public key */ /* Named group and public key */
info->named_group = (word16)((input[index] << 8) | input[index+1]); info->named_group = (word16)((input[index] << 8) | input[index+1]);
index += OPAQUE16_LEN; index += OPAQUE16_LEN;
info->key_len = (word16)((input[index] << 8) | input[index+1]); info->key_len = 0;
index += OPAQUE16_LEN; info->key = NULL;
if (info->key_len == 0 || info->key_len > len - index) { /* If key was provided... (a hello_retry_request will not send a key) */
return -1; if (index + 2 <= len) {
info->key_len = (word16)((input[index] << 8) | input[index+1]);
index += OPAQUE16_LEN;
if (info->key_len == 0 || info->key_len > len - index) {
return -1;
}
info->key = &input[index];
index += info->key_len;
} }
info->key = &input[index];
index += info->key_len;
switch (info->named_group) { switch (info->named_group) {
#ifndef NO_DH #ifndef NO_DH
@ -2502,13 +2508,14 @@ static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int
int ret; int ret;
if (session->cliKeyShare == NULL || session->cliKeyShareSz == 0) { if (session->cliKeyShare == NULL || session->cliKeyShareSz == 0) {
SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); /* session->cliKeyShareSz could not be provided yet if the client_hello
return -1; did not send a key share to force a hello_retry_request */
return 0;
} }
/* Get server_hello key share */ /* Get server_hello key share (and key) */
ret = ProcessKeyShare(&session->srvKs, input, len, 0); ret = ProcessKeyShare(&session->srvKs, input, len, 0);
if (ret == 0) { if (ret == 0 && session->srvKs.key_len > 0) {
/* Get client_hello key share */ /* Get client_hello key share */
ret = ProcessKeyShare(&session->cliKs, session->cliKeyShare, ret = ProcessKeyShare(&session->cliKs, session->cliKeyShare,
session->cliKeyShareSz, session->srvKs.named_group); session->cliKeyShareSz, session->srvKs.named_group);
@ -2642,10 +2649,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
byte b, b0; byte b, b0;
int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
int doResume = 0; int doResume = 0;
const byte* inputHello = input;
int initialBytes = *sslBytes; int initialBytes = *sslBytes;
(void)msgSz; (void)msgSz;
(void)initialBytes;
/* make sure we didn't miss ClientHello */ /* make sure we didn't miss ClientHello */
if (session->flags.clientHello == 0) { if (session->flags.clientHello == 0) {
@ -2665,6 +2672,10 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
session->sslServer->version = pv; session->sslServer->version = pv;
session->sslClient->version = pv; session->sslClient->version = pv;
if (pv.minor >= TLSv1_MINOR) {
session->sslServer->options.tls = 1;
session->sslClient->options.tls = 1;
}
XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN); XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN); XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
@ -2856,6 +2867,32 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
actual sessionID */ actual sessionID */
} }
#ifdef WOLFSSL_TLS13
/* Is TLS v1.3 hello_retry_request? */
if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
Trace(GOT_HELLO_RETRY_REQ_STR);
/* do not compute keys yet */
session->flags.serverCipherOn = 0;
/* make sure the mac and digest size are set */
SetCipherSpecs(session->sslServer);
SetCipherSpecs(session->sslClient);
/* reset hashes */
RestartHandshakeHash(session->sslServer);
RestartHandshakeHash(session->sslClient);
doResume = 0;
}
#endif
/* hash server_hello */
HashRaw(session->sslServer, inputHello - HANDSHAKE_HEADER_SZ,
initialBytes + HANDSHAKE_HEADER_SZ);
HashRaw(session->sslClient, inputHello - HANDSHAKE_HEADER_SZ,
initialBytes + HANDSHAKE_HEADER_SZ);
if (doResume) { if (doResume) {
WOLFSSL_SESSION* resume; WOLFSSL_SESSION* resume;
if (IsAtLeastTLSv1_3(session->sslServer->version)) { if (IsAtLeastTLSv1_3(session->sslServer->version)) {
@ -2950,7 +2987,7 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
/* Setup handshake keys */ /* Setup handshake keys */
if (IsAtLeastTLSv1_3(session->sslServer->version)) { if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len > 0) {
DerBuffer* key = session->sslServer->buffers.key; DerBuffer* key = session->sslServer->buffers.key;
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
if (session->sslServer->staticKE.key) if (session->sslServer->staticKE.key)
@ -3321,7 +3358,6 @@ static int KeyWatchCall(SnifferSession* session, const byte* data, int dataSz,
static int ProcessCertificate(const byte* input, int* sslBytes, static int ProcessCertificate(const byte* input, int* sslBytes,
SnifferSession* session, char* error) SnifferSession* session, char* error)
{ {
const byte* certChain;
word32 certChainSz; word32 certChainSz;
word32 certSz; word32 certSz;
@ -3334,6 +3370,15 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
/* skip 1 byte (Request context len) */
input += OPAQUE8_LEN;
*sslBytes -= OPAQUE8_LEN;
}
#endif
ato24(input, &certChainSz); ato24(input, &certChainSz);
*sslBytes -= CERT_HEADER_SZ; *sslBytes -= CERT_HEADER_SZ;
input += CERT_HEADER_SZ; input += CERT_HEADER_SZ;
@ -3342,7 +3387,6 @@ static int ProcessCertificate(const byte* input, int* sslBytes,
SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
certChain = input;
ato24(input, &certSz); ato24(input, &certSz);
input += OPAQUE24_LEN; input += OPAQUE24_LEN;
@ -3561,12 +3605,13 @@ static int DoHandShake(const byte* input, int* sslBytes,
#endif #endif
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
if (type != client_hello) { if (type != client_hello && type != server_hello) {
/* For resumption the hash is before / after client_hello PSK binder */ /* For resumption the hash is before / after client_hello PSK binder */
/* hash the packet including header */ /* hash the packet including header */
/* TLS v1.3 requires the hash for the handshake and transfer key derivation */ /* TLS v1.3 requires the hash for the handshake and transfer key derivation */
/* we hash even for non TLS v1.3, since we don't know if its actually /* we hash even for non TLS v1.3, since we don't know if its actually
TLS v1.3 till later at EXT_SUPPORTED_VERSIONS in server_hello */ TLS v1.3 till later at EXT_SUPPORTED_VERSIONS in server_hello */
/* hello retry request restarts hash prior to server_hello hash calc */
HashRaw(session->sslServer, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ); HashRaw(session->sslServer, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
HashRaw(session->sslClient, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ); HashRaw(session->sslClient, input - HANDSHAKE_HEADER_SZ, size + HANDSHAKE_HEADER_SZ);
} }
@ -4983,8 +5028,17 @@ doPart:
} }
break; break;
case change_cipher_spec: case change_cipher_spec:
if (session->flags.side == WOLFSSL_SERVER_END) if (session->flags.side == WOLFSSL_SERVER_END) {
session->flags.serverCipherOn = 1; #ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version) && session->srvKs.key_len == 0) {
session->flags.serverCipherOn = 0;
}
else
#endif
{
session->flags.serverCipherOn = 1;
}
}
else else
session->flags.clientCipherOn = 1; session->flags.clientCipherOn = 1;
Trace(GOT_CHANGE_CIPHER_STR); Trace(GOT_CHANGE_CIPHER_STR);

View File

@ -2365,7 +2365,7 @@ static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz)
* ssl The SSL/TLS object. * ssl The SSL/TLS object.
* returns 0 on success, otherwise failure. * returns 0 on success, otherwise failure.
*/ */
static int RestartHandshakeHash(WOLFSSL* ssl) int RestartHandshakeHash(WOLFSSL* ssl)
{ {
int ret; int ret;
Hashes hashes; Hashes hashes;

View File

@ -1727,6 +1727,7 @@ WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input,
WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input,
word32* inOutIdx, word32 helloSz, word32* inOutIdx, word32 helloSz,
byte* extMsgType); byte* extMsgType);
WOLFSSL_LOCAL int RestartHandshakeHash(WOLFSSL* ssl);
#endif #endif
int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t,
int pLen, int content); int pLen, int content);

View File

@ -109,7 +109,6 @@
#define GOT_CERT_STATUS_STR 73 #define GOT_CERT_STATUS_STR 73
#define RSA_KEY_MISSING_STR 74 #define RSA_KEY_MISSING_STR 74
#define NO_SECURE_RENEGOTIATION 75 #define NO_SECURE_RENEGOTIATION 75
#define BAD_SESSION_STATS 76 #define BAD_SESSION_STATS 76
#define REASSEMBLY_MAX_STR 77 #define REASSEMBLY_MAX_STR 77
#define DROPPING_LOST_FRAG_STR 78 #define DROPPING_LOST_FRAG_STR 78
@ -131,6 +130,7 @@
#define STORE_DATA_FAIL_STR 92 #define STORE_DATA_FAIL_STR 92
#define CHAIN_INPUT_STR 93 #define CHAIN_INPUT_STR 93
#define GOT_ENC_EXT_STR 94 #define GOT_ENC_EXT_STR 94
#define GOT_HELLO_RETRY_REQ_STR 95
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */

View File

@ -112,5 +112,7 @@ STRINGTABLE
91, "No data destination Error" 91, "No data destination Error"
92, "Store Data callback failed" 92, "Store Data callback failed"
93, "Loading chain input" 93, "Loading chain input"
94, "Got encrypted extension"
95, "Hello retry request"
} }