Merge pull request #3476 from dgarske/sniffer_hrr

Fixes for TLS sniffer with v1.3 (HRR and Certs)
This commit is contained in:
toddouska
2020-11-18 16:07:11 -08:00
committed by GitHub
14 changed files with 406 additions and 189 deletions

View File

@ -1756,7 +1756,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
if (ret != 0) { if (ret != 0) {
err_sys_ex(runWithErrors, "error loading static ECDH key"); err_sys_ex(runWithErrors, "error loading static ECDH key");
} }
#elif !defined(NO_DH) #endif
#ifndef NO_DH
ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_DH, ret = wolfSSL_CTX_set_ephemeral_key(ctx, WC_PK_TYPE_DH,
"./certs/statickeys/dh-ffdhe2048.pem", 0, WOLFSSL_FILETYPE_PEM); "./certs/statickeys/dh-ffdhe2048.pem", 0, WOLFSSL_FILETYPE_PEM);
if (ret != 0) { if (ret != 0) {

View File

@ -91,6 +91,7 @@ EXTRA_DIST += scripts/testsuite.pcap \
scripts/sniffer-tls13-dh.pcap \ scripts/sniffer-tls13-dh.pcap \
scripts/sniffer-tls13-ecc.pcap \ scripts/sniffer-tls13-ecc.pcap \
scripts/sniffer-tls13-gen.sh \ scripts/sniffer-tls13-gen.sh \
scripts/sniffer-tls13-hrr.pcap \
scripts/ping.test \ scripts/ping.test \
scripts/benchmark.test \ scripts/benchmark.test \
scripts/memtest.sh scripts/memtest.sh

View File

@ -39,6 +39,16 @@ then
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH\n" && exit 1 [ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 DH\n" && exit 1
fi fi
# TLS v1.3 sniffer test hello_retry_request (HRR) with ECDHE
if test $# -ne 0
then
./sslSniffer/sslSnifferTest/snifftest ./scripts/sniffer-tls13-hrr.pcap ./certs/statickeys/ecc-secp256r1.pem 127.0.0.1 11111
RESULT=$?
[ $RESULT -ne 0 ] && echo -e "\nsnifftest TLS v1.3 HRR\n" && exit 1
fi
# IPv6 # IPv6
if test $# -ne 0 && test "x$1" = "x-6"; if test $# -ne 0 && test "x$1" = "x-6";
then then

View File

@ -22,3 +22,8 @@
./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r ./examples/client/client -v 4 -l TLS13-AES256-GCM-SHA384 -r
./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r & ./examples/server/server -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r &
./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r ./examples/client/client -v 4 -l TLS13-CHACHA20-POLY1305-SHA256 -r
# TLS v1.3 Hello Retry Request (save this as sniffer-tls13-hrr.pcap)
# ./configure --enable-sniffer CFLAGS="-DWOLFSSL_SNIFFER_WATCH" --disable-dh && make
./examples/server/server -v 4 -i -x -g &
./examples/client/client -v 4 -J

Binary file not shown.

View File

@ -1897,9 +1897,14 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
} }
#endif #endif
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
if (ctx->staticKE.key) { #ifndef NO_DH
FreeDer(&ctx->staticKE.key); if (ctx->staticKE.dhKey)
} FreeDer(&ctx->staticKE.dhKey);
#endif
#ifdef HAVE_ECC
if (ctx->staticKE.ecKey)
FreeDer(&ctx->staticKE.ecKey);
#endif
#endif #endif
#ifdef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_STATIC_MEMORY
if (ctx->heap != NULL) { if (ctx->heap != NULL) {
@ -6426,9 +6431,14 @@ void SSL_ResourceFree(WOLFSSL* ssl)
} }
#endif #endif
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
if (ssl->staticKE.key != NULL && ssl->staticKE.key != ssl->ctx->staticKE.key) { #ifndef NO_DH
FreeDer(&ssl->staticKE.key); if (ssl->staticKE.dhKey && ssl->staticKE.dhKey != ssl->ctx->staticKE.dhKey)
} FreeDer(&ssl->staticKE.dhKey);
#endif
#ifdef HAVE_ECC
if (ssl->staticKE.ecKey && ssl->staticKE.ecKey != ssl->ctx->staticKE.ecKey)
FreeDer(&ssl->staticKE.ecKey);
#endif
#endif #endif
#ifdef WOLFSSL_STATIC_MEMORY #ifdef WOLFSSL_STATIC_MEMORY

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",
}; };
@ -2066,11 +2067,26 @@ static void ShowTlsSecrets(SnifferSession* session)
/* Process Keys */ /* Process Keys */
/* contains static ephemeral keys */
typedef struct {
#ifndef NO_DH
DerBuffer* dhKey;
#endif
#ifdef HAVE_ECC
DerBuffer* ecKey;
#endif
#if !defined(NO_RSA) && defined(WOLFSSL_STATIC_RSA)
DerBuffer* rsaKey;
#endif
} KeyBuffers_t;
static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
char* error, KeyShareInfo* ksInfo, DerBuffer* keyBuf) char* error, KeyShareInfo* ksInfo, KeyBuffers_t* keys)
{ {
word32 idx = 0; word32 idx = 0;
int ret; int ret;
DerBuffer* keyBuf;
#ifdef HAVE_ECC #ifdef HAVE_ECC
int useEccCurveId = ECC_CURVE_DEF; int useEccCurveId = ECC_CURVE_DEF;
if (ksInfo && ksInfo->curve_id != 0) if (ksInfo && ksInfo->curve_id != 0)
@ -2079,10 +2095,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifndef NO_RSA #ifndef NO_RSA
/* Static RSA */ /* Static RSA */
if (ksInfo == NULL) { if (ksInfo == NULL && keys->rsaKey) {
RsaKey key; RsaKey key;
int length; int length;
keyBuf = keys->rsaKey;
ret = wc_InitRsaKey(&key, 0); ret = wc_InitRsaKey(&key, 0);
if (ret == 0) { if (ret == 0) {
ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length); ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length);
@ -2151,11 +2169,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) #if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
/* Static DH Key */ /* Static DH Key */
if (ksInfo && ksInfo->dh_key_bits != 0) { if (ksInfo && ksInfo->dh_key_bits != 0 && keys->dhKey) {
DhKey dhKey; DhKey dhKey;
const DhParams* params; const DhParams* params;
word32 privKeySz; word32 privKeySz;
byte privKey[52]; /* max for TLS */ byte privKey[52]; /* max for TLS */
keyBuf = keys->dhKey;
/* get DH params */ /* get DH params */
switch (ksInfo->named_group) { switch (ksInfo->named_group) {
@ -2239,11 +2259,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifdef HAVE_ECC #ifdef HAVE_ECC
/* Static ECC Key */ /* Static ECC Key */
if (useEccCurveId >= ECC_CURVE_DEF) { if (useEccCurveId >= ECC_CURVE_DEF && keys->ecKey) {
ecc_key key; ecc_key key;
ecc_key pubKey; ecc_key pubKey;
int length, keyInit = 0, pubKeyInit = 0; int length, keyInit = 0, pubKeyInit = 0;
keyBuf = keys->ecKey;
idx = 0; idx = 0;
ret = wc_ecc_init(&key); ret = wc_ecc_init(&key);
if (ret == 0) { if (ret == 0) {
@ -2394,6 +2415,8 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
static int ProcessClientKeyExchange(const byte* input, int* sslBytes, static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SnifferSession* session, char* error) SnifferSession* session, char* error)
{ {
KeyBuffers_t keys;
if (session->sslServer->buffers.key == NULL || if (session->sslServer->buffers.key == NULL ||
session->sslServer->buffers.key->buffer == NULL || session->sslServer->buffers.key->buffer == NULL ||
session->sslServer->buffers.key->length == 0) { session->sslServer->buffers.key->length == 0) {
@ -2402,8 +2425,17 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
return -1; return -1;
} }
return SetupKeys(input, sslBytes, session, error, NULL, XMEMSET(&keys, 0, sizeof(keys));
session->sslServer->buffers.key); #ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef NO_DH
keys.dhKey = session->sslServer->staticKE.dhKey;
#endif
#ifdef HAVE_ECC
keys.ecKey = session->sslServer->staticKE.ecKey;
#endif
#endif
keys.rsaKey = session->sslServer->buffers.key;
return SetupKeys(input, sslBytes, session, error, NULL, &keys);
} }
#ifdef WOLFSSL_TLS13 #ifdef WOLFSSL_TLS13
@ -2412,16 +2444,24 @@ static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
{ {
int index = 0; int index = 0;
while (index < len) { while (index < len) {
/* clear info (reset dh_key_bits and curve_id) */
XMEMSET(info, 0, sizeof(KeyShareInfo));
/* 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
@ -2485,15 +2525,15 @@ static int ProcessKeyShare(KeyShareInfo* info, const byte* input, int len,
break; break;
#endif #endif
default: default:
/* unsupported curve */ /* do not throw error here, keep iterating the client key share */
return ECC_PEERKEY_ERROR; break;
} }
if (filter_group == 0 || filter_group == info->named_group) { if (filter_group == 0 || filter_group == info->named_group) {
return 0; return 0;
} }
} }
return -1; return NO_PEER_KEY; /* unsupported key type */
} }
static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int len, static int ProcessServerKeyShare(SnifferSession* session, const byte* input, int len,
@ -2502,13 +2542,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);
@ -2632,6 +2673,98 @@ static int ProcessSessionTicket(const byte* input, int* sslBytes,
return 0; return 0;
} }
static int DoResume(SnifferSession* session, char* error)
{
int ret = 0;
WOLFSSL_SESSION* resume;
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
resume = GetSession(session->sslServer,
session->sslServer->session.masterSecret, 0);
}
else
#endif
{
resume = GetSession(session->sslServer,
session->sslServer->arrays->masterSecret, 0);
}
if (resume == NULL) {
/* a session id without resume is okay with hello_retry_request */
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslStandardConns);
#endif
return 0;
}
/* make sure client has master secret too */
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
XMEMCPY(session->sslClient->session.masterSecret,
session->sslServer->session.masterSecret, SECRET_LEN);
}
else
#endif
{
XMEMCPY(session->sslClient->arrays->masterSecret,
session->sslServer->arrays->masterSecret, SECRET_LEN);
}
session->flags.resuming = 1;
Trace(SERVER_DID_RESUMPTION_STR);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslResumedConns);
INC_STAT(SnifferStats.sslResumptionValid);
#endif
if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
#ifdef HAVE_SESSION_TICKET
/* Resumption PSK is resumption master secret. */
session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size;
session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size;
ret = DeriveResumptionPSK(session->sslServer, session->sslServer->session.ticketNonce.data,
session->sslServer->session.ticketNonce.len, session->sslServer->arrays->psk_key);
/* Copy resumption PSK to client */
XMEMCPY(session->sslClient->arrays->psk_key,
session->sslServer->arrays->psk_key,
session->sslServer->arrays->psk_keySz);
#endif
/* handshake key setup below and traffic keys done in SetupKeys */
}
else
#endif
{
if (IsTLS(session->sslServer)) {
ret = DeriveTlsKeys(session->sslServer);
ret += DeriveTlsKeys(session->sslClient);
}
else {
#ifndef NO_OLD_TLS
ret = DeriveKeys(session->sslServer);
ret += DeriveKeys(session->sslClient);
#endif
}
ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
}
if (ret != 0) {
SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
return ret;
}
/* Process Server Hello */ /* Process Server Hello */
static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
@ -2642,10 +2775,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 +2798,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,85 +2993,36 @@ 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; ret = DoResume(session, error);
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 */
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);
#ifdef WOLFSSL_SNIFFER_STATS
INC_STAT(SnifferStats.sslResumedConns);
INC_STAT(SnifferStats.sslResumptionValid);
#endif
if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
#ifdef WOLFSSL_TLS13
if (IsAtLeastTLSv1_3(session->sslServer->version)) {
#ifdef HAVE_SESSION_TICKET
/* Resumption PSK is resumption master secret. */
session->sslServer->arrays->psk_keySz = session->sslServer->specs.hash_size;
session->sslClient->arrays->psk_keySz = session->sslClient->specs.hash_size;
ret = DeriveResumptionPSK(session->sslServer, session->sslServer->session.ticketNonce.data,
session->sslServer->session.ticketNonce.len, session->sslServer->arrays->psk_key);
/* Copy resumption PSK to client */
XMEMCPY(session->sslClient->arrays->psk_key,
session->sslServer->arrays->psk_key,
session->sslServer->arrays->psk_keySz);
#endif
/* handshake key setup below and traffic keys done in SetupKeys */
}
else
#endif
{
if (IsTLS(session->sslServer)) {
ret = DeriveTlsKeys(session->sslServer);
ret += DeriveTlsKeys(session->sslClient);
}
else {
#ifndef NO_OLD_TLS
ret = DeriveKeys(session->sslServer);
ret += DeriveKeys(session->sslClient);
#endif
}
ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
}
if (ret != 0) { if (ret != 0) {
SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE); return ret;
return -1;
} }
} }
else { else {
@ -2950,14 +3038,20 @@ 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; KeyBuffers_t keys;
XMEMSET(&keys, 0, sizeof(keys));
keys.rsaKey = session->sslServer->buffers.key;
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
if (session->sslServer->staticKE.key) #ifndef NO_DH
key = session->sslServer->staticKE.key; keys.dhKey = session->sslServer->staticKE.dhKey;
#endif
#ifdef HAVE_ECC
keys.ecKey = session->sslServer->staticKE.ecKey;
#endif
#endif #endif
ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len, ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
session, error, &session->cliKs, key); session, error, &session->cliKs, &keys);
if (ret != 0) { if (ret != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
return ret; return ret;
@ -3321,7 +3415,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 +3427,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 +3444,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 +3662,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);
} }
@ -4926,6 +5028,11 @@ doMessage:
|| (session->flags.side == WOLFSSL_CLIENT_END && || (session->flags.side == WOLFSSL_CLIENT_END &&
session->flags.clientCipherOn)) { session->flags.clientCipherOn)) {
int ivAdvance = 0; /* TLSv1.1 advance amount */ int ivAdvance = 0; /* TLSv1.1 advance amount */
/* change_cipher_spec is not encrypted */
if (rh.type == change_cipher_spec) {
goto doPart;
}
if (ssl->decrypt.setup != 1) { if (ssl->decrypt.setup != 1) {
SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE); SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
return -1; return -1;
@ -4934,6 +5041,7 @@ doMessage:
SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
sslFrame = DecryptMessage(ssl, sslFrame, rhSize, sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
ssl->buffers.outputBuffer.buffer, &errCode, ssl->buffers.outputBuffer.buffer, &errCode,
&ivAdvance, &rh); &ivAdvance, &rh);
@ -4983,8 +5091,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

@ -48914,9 +48914,10 @@ int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo, static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
const char* key, unsigned int keySz, int format, void* heap) const char* key, unsigned int keySz, int format, void* heap, WOLFSSL_CTX* ctx)
{ {
int ret = 0; int ret = 0;
DerBuffer* der = NULL;
byte* keyBuf = NULL; byte* keyBuf = NULL;
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
const char* keyFile = NULL; const char* keyFile = NULL;
@ -48927,6 +48928,20 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
WOLFSSL_ENTER("SetStaticEphemeralKey");
/* if key is already set free it */
#ifndef NO_DH
if (keyAlgo == WC_PK_TYPE_DH && staticKE->dhKey &&
(ctx == NULL || staticKE->dhKey != ctx->staticKE.dhKey))
FreeDer(&staticKE->dhKey);
#endif
#ifdef HAVE_ECC
if (keyAlgo == WC_PK_TYPE_ECDH && staticKE->ecKey &&
(ctx == NULL || staticKE->ecKey != ctx->staticKE.ecKey))
FreeDer(&staticKE->ecKey);
#endif
/* check if just free'ing key */ /* check if just free'ing key */
if (key == NULL && keySz == 0) { if (key == NULL && keySz == 0) {
return 0; return 0;
@ -48953,7 +48968,7 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
if (format == WOLFSSL_FILETYPE_PEM) { if (format == WOLFSSL_FILETYPE_PEM) {
#ifdef WOLFSSL_PEM_TO_DER #ifdef WOLFSSL_PEM_TO_DER
int keyFormat = 0; int keyFormat = 0;
ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &staticKE->key, ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &der,
heap, NULL, &keyFormat); heap, NULL, &keyFormat);
/* auto detect key type */ /* auto detect key type */
if (ret == 0 && keyAlgo == 0) { if (ret == 0 && keyAlgo == 0) {
@ -48967,18 +48982,38 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
#endif #endif
} }
else { else {
ret = AllocDer(&staticKE->key, keySz, PRIVATEKEY_TYPE, heap); ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap);
if (ret == 0) { if (ret == 0) {
XMEMCPY(staticKE->key->buffer, keyBuf, keySz); XMEMCPY(der->buffer, keyBuf, keySz);
} }
} }
staticKE->keyAlgo = keyAlgo;
switch (keyAlgo) {
#ifndef NO_DH
case WC_PK_TYPE_DH:
staticKE->dhKey = der;
break;
#endif
#ifdef HAVE_ECC
case WC_PK_TYPE_ECDH:
staticKE->ecKey = der;
break;
#endif
default:
/* not supported */
ret = NOT_COMPILED_IN;
FreeDer(&der);
break;
}
#ifndef NO_FILESYSTEM #ifndef NO_FILESYSTEM
if (keyFile && keyBuf) { if (keyFile && keyBuf) {
XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER);
} }
#endif #endif
WOLFSSL_LEAVE("SetStaticEphemeralKey", ret);
return ret; return ret;
} }
@ -48989,13 +49024,8 @@ int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
/* if key is already set free it */
if (ctx->staticKE.key != NULL) {
FreeDer(&ctx->staticKE.key);
}
return SetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz, format, return SetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz, format,
ctx->heap); ctx->heap, NULL);
} }
int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo, int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
@ -49005,13 +49035,8 @@ int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
/* if key is already set and not created by ctx... set free it */
if (ssl->staticKE.key != NULL && ssl->staticKE.key != ssl->ctx->staticKE.key) {
FreeDer(&ssl->staticKE.key);
}
return SetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz, format, return SetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz, format,
ssl->heap); ssl->heap, ssl->ctx);
} }
#endif /* WOLFSSL_STATIC_EPHEMERAL */ #endif /* WOLFSSL_STATIC_EPHEMERAL */

View File

@ -6685,8 +6685,8 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
goto end; goto end;
#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA) #if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA)
if (ssl->staticKE.key && ssl->staticKE.keyAlgo == WC_PK_TYPE_DH) { if (ssl->staticKE.dhKey) {
DerBuffer* keyDer = ssl->staticKE.key; DerBuffer* keyDer = ssl->staticKE.dhKey;
word32 idx = 0; word32 idx = 0;
WOLFSSL_MSG("Using static DH key"); WOLFSSL_MSG("Using static DH key");
ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length); ret = wc_DhKeyDecode(keyDer->buffer, &idx, dhKey, keyDer->length);
@ -6971,8 +6971,8 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
goto end; goto end;
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
if (ssl->staticKE.key && ssl->staticKE.keyAlgo == WC_PK_TYPE_ECDH) { if (ssl->staticKE.ecKey) {
DerBuffer* keyDer = ssl->staticKE.key; DerBuffer* keyDer = ssl->staticKE.ecKey;
word32 idx = 0; word32 idx = 0;
WOLFSSL_MSG("Using static ECDH key"); WOLFSSL_MSG("Using static ECDH key");
ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, keyDer->length); ret = wc_EccPrivateKeyDecode(keyDer->buffer, &idx, eccKey, keyDer->length);

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

@ -103,7 +103,11 @@ enum {
#ifndef DEFAULT_SERVER_EPH_KEY #ifndef DEFAULT_SERVER_EPH_KEY
#if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \ #if defined(HAVE_ECC) && !defined(NO_ECC_SECP) && \
(!defined(NO_ECC256) || defined(HAVE_ALL_CURVES)) (!defined(NO_ECC256) || defined(HAVE_ALL_CURVES))
#define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC #if !defined(NO_DH)
#define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC "," DEFAULT_SERVER_EPH_KEY_DH
#else
#define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_ECC
#endif
#elif !defined(NO_DH) #elif !defined(NO_DH)
#define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_DH #define DEFAULT_SERVER_EPH_KEY DEFAULT_SERVER_EPH_KEY_DH
#endif #endif
@ -311,6 +315,54 @@ static int myStoreDataCb(const unsigned char* decryptBuf,
} }
#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */ #endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
/* try and load as both static ephemeral and private key */
/* only fail if no key is loaded */
/* Allow comma seperated list of files */
static int load_key(const char* name, const char* server, int port,
const char* keyFiles, const char* passwd, char* err)
{
int ret = -1;
int loadCount = 0;
char *keyFile, *ptr = NULL;
keyFile = XSTRTOK((char*)keyFiles, ",", &ptr);
while (keyFile != NULL) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifdef HAVE_SNI
ret = ssl_SetNamedEphemeralKey(name, server, port, keyFile,
FILETYPE_PEM, passwd, err);
#else
ret = ssl_SetEphemeralKey(server, port, keyFile,
FILETYPE_PEM, passwd, err);
#endif
if (ret == 0)
loadCount++;
#endif
#ifdef HAVE_SNI
ret = ssl_SetNamedPrivateKey(name, server, port, keyFile,
FILETYPE_PEM, passwd, err);
#else
ret = ssl_SetPrivateKey(server, port, keyFile,
FILETYPE_PEM, passwd, err);
#endif
if (ret == 0)
loadCount++;
if (loadCount == 0) {
printf("Failed loading private key %s: ret %d\n", keyFile, ret);
printf("Please run directly from sslSniffer/sslSnifferTest dir\n");
ret = -1;
}
else {
ret = 0;
}
keyFile = XSTRTOK(NULL, ",", &ptr);
}
(void)name;
return ret;
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -323,7 +375,10 @@ int main(int argc, char** argv)
int frame = ETHER_IF_FRAME_LEN; int frame = ETHER_IF_FRAME_LEN;
char err[PCAP_ERRBUF_SIZE]; char err[PCAP_ERRBUF_SIZE];
char filter[32]; char filter[32];
const char *keyFiles = NULL;
char keyFilesBuf[MAX_FILENAME_SZ];
const char *server = NULL; const char *server = NULL;
const char *sniName = NULL;
struct bpf_program fp; struct bpf_program fp;
pcap_if_t *d; pcap_if_t *d;
pcap_addr_t *a; pcap_addr_t *a;
@ -436,6 +491,35 @@ int main(int argc, char** argv)
ret = pcap_setfilter(pcap, &fp); ret = pcap_setfilter(pcap, &fp);
if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap)); if (ret != 0) printf("pcap_setfilter failed %s\n", pcap_geterr(pcap));
/* optionally enter the private key to use */
#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(DEFAULT_SERVER_EPH_KEY)
keyFiles = DEFAULT_SERVER_EPH_KEY;
#else
keyFiles = DEFAULT_SERVER_KEY;
#endif
printf("Enter the server key [default: %s]: ", keyFiles);
XMEMSET(keyFilesBuf, 0, sizeof(keyFilesBuf));
if (XFGETS(keyFilesBuf, sizeof(keyFilesBuf), stdin)) {
if (keyFilesBuf[0] != '\r' && keyFilesBuf[0] != '\n') {
keyFiles = keyFilesBuf;
}
}
if (keyFiles != keyFilesBuf) {
XSTRNCPY(keyFilesBuf, keyFiles, sizeof(keyFilesBuf));
keyFiles = keyFilesBuf;
}
/* optionally enter a named key (SNI) */
#if !defined(WOLFSSL_SNIFFER_WATCH) && defined(HAVE_SNI)
printf("Enter alternate SNI [default: none]: ");
XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg));
if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) {
if (XSTRLEN(cmdLineArg) > 0) {
sniName = cmdLineArg;
}
}
#endif /* !WOLFSSL_SNIFFER_WATCH && HAVE_SNI */
/* get IPv4 or IPv6 addresses for selected interface */ /* get IPv4 or IPv6 addresses for selected interface */
for (a = d->addresses; a; a = a->next) { for (a = d->addresses; a; a = a->next) {
server = NULL; server = NULL;
@ -449,39 +533,10 @@ int main(int argc, char** argv)
} }
if (server) { if (server) {
#ifdef DEFAULT_SERVER_KEY ret = load_key(sniName, server, port, keyFiles, NULL, err);
ret = ssl_SetPrivateKey(server, port, DEFAULT_SERVER_KEY,
FILETYPE_PEM, NULL, err);
if (ret != 0) { if (ret != 0) {
printf("Please run directly from sslSniffer/sslSnifferTest" exit(EXIT_FAILURE);
"dir\n");
} }
#endif
#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(DEFAULT_SERVER_EPH_KEY)
ret = ssl_SetEphemeralKey(server, port, DEFAULT_SERVER_EPH_KEY,
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from sslSniffer/sslSnifferTest"
"dir\n");
}
#endif /* WOLFSSL_STATIC_EPHEMERAL */
#ifndef WOLFSSL_SNIFFER_WATCH
#ifdef HAVE_SNI
printf("Enter alternate SNI: ");
XMEMSET(cmdLineArg, 0, sizeof(cmdLineArg));
if (XFGETS(cmdLineArg, sizeof(cmdLineArg), stdin)) {
if (XSTRLEN(cmdLineArg) > 0) {
ret = ssl_SetNamedPrivateKey(cmdLineArg,
server, port, DEFAULT_SERVER_KEY,
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from "
"sslSniffer/sslSnifferTest dir\n");
}
}
}
#endif /* HAVE_SNI */
#endif /* WOLFSSL_SNIFFER_WATCH */
} }
} }
} }
@ -494,11 +549,11 @@ int main(int argc, char** argv)
} }
else { else {
const char* passwd = NULL; const char* passwd = NULL;
int loadCount = 0;
/* defaults for server and port */ /* defaults for server and port */
port = 443; port = 443;
server = "127.0.0.1"; server = "127.0.0.1";
keyFiles = argv[2];
if (argc >= 4) if (argc >= 4)
server = argv[3]; server = argv[3];
@ -509,22 +564,8 @@ int main(int argc, char** argv)
if (argc >= 6) if (argc >= 6)
passwd = argv[5]; passwd = argv[5];
/* try and load as both static ephemeral and private key */ ret = load_key(NULL, server, port, keyFiles, passwd, err);
/* only fail if no key is loaded */ if (ret != 0) {
#ifdef WOLFSSL_STATIC_EPHEMERAL
ret = ssl_SetEphemeralKey(server, port, argv[2],
FILETYPE_PEM, passwd, err);
if (ret == 0)
loadCount++;
#endif
ret = ssl_SetPrivateKey(server, port, argv[2],
FILETYPE_PEM, passwd, err);
if (ret == 0)
loadCount++;
if (loadCount == 0) {
printf("Failed loading private key %d\n", ret);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

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);
@ -2624,9 +2625,14 @@ enum SetCBIO {
#endif #endif
#ifdef WOLFSSL_STATIC_EPHEMERAL #ifdef WOLFSSL_STATIC_EPHEMERAL
/* contains static ephemeral keys */
typedef struct { typedef struct {
int keyAlgo; #ifndef NO_DH
DerBuffer* key; DerBuffer* dhKey;
#endif
#ifdef HAVE_ECC
DerBuffer* ecKey;
#endif
} StaticKeyExchangeInfo_t; } StaticKeyExchangeInfo_t;
#endif #endif

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,6 @@ 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, "Got Hello Retry Request"
} }