Fix for secure renegotiation, which was not keeping handshake resources. Added NULL checks for case where handshake resources might be free'd to prevent possible use of NULL. Refactor the SNI client hello processing to not assume TLS header is in prior buffer (not there for decrypted handshake packets).

This commit is contained in:
David Garske
2021-07-13 13:56:00 -07:00
parent db32570ab3
commit 3ff21171cb

View File

@ -1603,7 +1603,7 @@ static int CreateWatchSnifferServer(char* error)
#endif
/* Caller locks ServerListMutex */
static int SetNamedPrivateKey(const char* name, const char* address, int port,
const char* keyFile, int keySz, int typeKey, const char* password,
char* error, int isEphemeralKey)
@ -1658,6 +1658,7 @@ static int SetNamedPrivateKey(const char* name, const char* address, int port,
serverIp.version = IPV6;
}
}
sniffer = ServerList;
while (sniffer != NULL &&
(!MatchAddr(sniffer->server, serverIp) || sniffer->port != port)) {
@ -2171,6 +2172,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
devId = CryptoDeviceId;
#endif
if (session->sslServer->arrays == NULL || session->sslClient->arrays == NULL) {
/* secret's have already been established and released */
/* this can happen with secure renegotiation */
return 0;
}
#ifndef NO_RSA
/* Static RSA */
if (ksInfo == NULL && keys->rsaKey) {
@ -2773,8 +2780,10 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
}
/* store session with macID as sessionID */
session->sslServer->options.haveSessionId = 1;
XMEMCPY(session->sslServer->arrays->sessionID,
input + len - ID_LEN, ID_LEN);
if (session->sslServer->arrays) {
XMEMCPY(session->sslServer->arrays->sessionID,
input + len - ID_LEN, ID_LEN);
}
}
return 0;
@ -3011,6 +3020,9 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
FATAL_ERROR_STATE);
return -1;
}
#ifdef DEBUG_SNIFFER
printf("\tserver_hello ext: 0x%02x (len %d)\n", extType, extLen);
#endif
switch (extType) {
#ifdef WOLFSSL_TLS13
@ -3070,7 +3082,14 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
session->flags.expectEms = 1;
#endif
break;
}
case EXT_RENEGOTIATION_INFO:
#if defined(HAVE_SECURE_RENEGOTIATION) || \
defined(HAVE_SERVER_RENEGOTIATION_INFO)
session->sslServer->secure_renegotiation->enabled = 1;
session->sslClient->secure_renegotiation->enabled = 1;
#endif
break;
} /* switch (extType) */
input += extLen;
*sslBytes -= extLen;
@ -3179,6 +3198,48 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
return 0;
}
#ifdef HAVE_SNI
static int LoadNamedKey(SnifferSession* session, const byte* name, word16 nameSz)
{
int ret = 0;
WOLFSSL* ssl = session->sslServer;
NamedKey* namedKey;
wc_LockMutex(&session->context->namedKeysMutex);
namedKey = session->context->namedKeys;
while (namedKey != NULL) {
if (nameSz == namedKey->nameSz &&
XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
if (namedKey->isEphemeralKey) {
/* auto detect key type with WC_PK_TYPE_NONE */
ret = wolfSSL_set_ephemeral_key(ssl,
WC_PK_TYPE_NONE, (const char*)namedKey->key,
namedKey->keySz, WOLFSSL_FILETYPE_ASN1);
if (ret == 0)
ret = WOLFSSL_SUCCESS;
}
else
#endif
{
ret = wolfSSL_use_PrivateKey_buffer(ssl,
namedKey->key, namedKey->keySz,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS) {
ret = -1;
break;
}
session->sni = namedKey->name;
break;
}
else
namedKey = namedKey->next;
}
wc_UnLockMutex(&session->context->namedKeysMutex);
return ret;
}
#endif
/* Process normal Client Hello */
static int ProcessClientHello(const byte* input, int* sslBytes,
@ -3193,65 +3254,6 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
WOLFSSL* ssl = session->sslServer;
int didHash = 0;
#ifdef HAVE_SNI
{
byte name[MAX_SERVER_NAME];
word32 nameSz = sizeof(name);
ret = wolfSSL_SNI_GetFromBuffer(
input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
*sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
WOLFSSL_SNI_HOST_NAME, name, &nameSz);
if (ret == WOLFSSL_SUCCESS) {
NamedKey* namedKey;
if (nameSz > sizeof(name) - 1)
nameSz = sizeof(name) - 1;
name[nameSz] = 0;
wc_LockMutex(&session->context->namedKeysMutex);
namedKey = session->context->namedKeys;
while (namedKey != NULL) {
if (nameSz == namedKey->nameSz &&
XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
if (namedKey->isEphemeralKey) {
/* auto detect key type with WC_PK_TYPE_NONE */
ret = wolfSSL_set_ephemeral_key(ssl,
WC_PK_TYPE_NONE, (const char*)namedKey->key,
namedKey->keySz, WOLFSSL_FILETYPE_ASN1);
if (ret == 0)
ret = WOLFSSL_SUCCESS;
}
else
#endif
{
ret = wolfSSL_use_PrivateKey_buffer(ssl,
namedKey->key, namedKey->keySz,
WOLFSSL_FILETYPE_ASN1);
}
if (ret != WOLFSSL_SUCCESS) {
wc_UnLockMutex(&session->context->namedKeysMutex);
SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
FATAL_ERROR_STATE);
return -1;
}
session->sni = namedKey->name;
break;
}
else
namedKey = namedKey->next;
}
wc_UnLockMutex(&session->context->namedKeysMutex);
}
/* SSLv3 does not support the SNI TLS Extension and may return SNI_UNSUPPORTED */
if (ret > 0 || ret == SNI_UNSUPPORTED) {
/* make sure WOLFSSL_SUCCESS is converted to zero error code */
ret = 0;
}
}
#endif
session->flags.clientHello = 1; /* don't process again */
/* make sure can read up to session len */
@ -3264,8 +3266,11 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
input += VERSION_SZ;
*sslBytes -= VERSION_SZ;
XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
/* for secure renegotiation server arrays can be NULL */
if (session->sslServer->arrays)
XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
if (session->sslClient->arrays)
XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
input += RAN_LEN;
*sslBytes -= RAN_LEN;
@ -3287,7 +3292,8 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
}
#ifdef SHOW_SECRETS
PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN);
if (ssl->arrays)
PrintSecret("client random", ssl->arrays->clientRandom, RAN_LEN);
#endif
input += bLen;
@ -3359,7 +3365,46 @@ static int ProcessClientHello(const byte* input, int* sslBytes,
return -1;
}
#ifdef DEBUG_SNIFFER
printf("\tclient_hello ext: 0x%02x (len %d)\n", extType, extLen);
#endif
switch (extType) {
#ifdef HAVE_SNI
case EXT_SERVER_NAME:
{
word16 listLen = 0, offset = 0;
ato16(input + offset, &listLen);
offset += OPAQUE16_LEN;
if (extLen < offset + listLen)
return BUFFER_ERROR;
while (listLen > ENUM_LEN + OPAQUE16_LEN) {
byte sniType = input[offset++];
word16 sniLen;
ato16(input + offset, &sniLen);
offset += OPAQUE16_LEN;
if (extLen < offset + sniLen)
return BUFFER_ERROR;
if (sniType == WOLFSSL_SNI_HOST_NAME) {
ret = LoadNamedKey(session, input + offset, sniLen);
if (ret < 0) {
/* don't treat this as fatal error */
SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, 0);
break;
}
}
offset += sniLen;
listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
}
break;
}
#endif
#ifdef WOLFSSL_TLS13
case EXT_KEY_SHARE:
{
@ -3675,6 +3720,9 @@ static int ProcessFinished(const byte* input, int size, int* sslBytes,
}
#endif
/* TODO: Do not free yet if Extension: renegotiation_info (len=1) provided - secure reneg */
/* If receiving a finished message from one side, free the resources
* from the other side's tracker. */
if (session->flags.side == WOLFSSL_SERVER_END)