1. Refactor `ProcessClientKeyExchange()` so it can be expanded to handle ECC keys for ECDH support.
2. Add support to the sniffer for ECDH based cipher suites.
This commit is contained in:
John Safranek
2019-05-14 13:33:52 -07:00
parent 9d4d877919
commit a8b469eb7f
3 changed files with 145 additions and 52 deletions

View File

@ -246,7 +246,9 @@ static const char* const msgTable[] =
/* 81 */ /* 81 */
"Bad Decrypt Size", "Bad Decrypt Size",
"Extended Master Secret Hash Error", "Extended Master Secret Hash Error",
"Handshake Message Split Across TLS Records" "Handshake Message Split Across TLS Records",
"ECC Private Decode Error",
"ECC Public Decode Error"
}; };
@ -1476,13 +1478,13 @@ static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
} }
/* Process Client Key Exchange, RSA only */ /* Process Client Key Exchange, RSA or static ECDH */
static int ProcessClientKeyExchange(const byte* input, int* sslBytes, static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SnifferSession* session, char* error) SnifferSession* session, char* error)
{ {
word32 idx = 0; word32 idx = 0;
RsaKey key; int tryEcc = 0;
int ret; int ret;
if (session->sslServer->buffers.key == NULL || if (session->sslServer->buffers.key == NULL ||
session->sslServer->buffers.key->buffer == NULL || session->sslServer->buffers.key->buffer == NULL ||
@ -1491,75 +1493,163 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE); SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
return -1; return -1;
} }
ret = wc_InitRsaKey(&key, 0);
if (ret == 0)
ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key->buffer,
&idx, &key, session->sslServer->buffers.key->length);
if (ret == 0) {
int length = wc_RsaEncryptSize(&key);
if (IsTLS(session->sslServer)) {
input += 2; /* tls pre length */ RsaKey key;
int length;
if (length > *sslBytes) { ret = wc_InitRsaKey(&key, 0);
SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE); if (ret == 0) {
wc_FreeRsaKey(&key); ret = wc_RsaPrivateKeyDecode(
return -1; session->sslServer->buffers.key->buffer,
&idx, &key, session->sslServer->buffers.key->length);
if (ret != 0) {
tryEcc = 1;
#ifndef HAVE_ECC
SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
#else
/* If we can do ECC, this isn't fatal. Not loading an ECC
* key will be fatal, though. */
SetError(RSA_DECODE_STR, error, session, 0);
#endif
}
} }
if (ret == 0) {
length = wc_RsaEncryptSize(&key);
if (IsTLS(session->sslServer)) {
input += 2; /* tls pre length */
}
if (length > *sslBytes) {
SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
ret = -1;
}
}
if (ret == 0) {
#ifdef WC_RSA_BLINDING #ifdef WC_RSA_BLINDING
ret = wc_RsaSetRNG(&key, session->sslServer->rng); ret = wc_RsaSetRNG(&key, session->sslServer->rng);
if (ret != 0) { if (ret != 0) {
SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
return -1;
} }
#endif #endif
do {
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaPrivateDecrypt(input, length,
session->sslServer->arrays->preMasterSecret, SECRET_LEN,
&key);
}
} while (ret == WC_PENDING_E);
if (ret != SECRET_LEN) {
SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
return -1;
} }
if (ret == 0) {
do {
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wc_AsyncWait(ret, &key.asyncDev,
WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_RsaPrivateDecrypt(input, length,
session->sslServer->arrays->preMasterSecret,
SECRET_LEN, &key);
}
} while (ret == WC_PENDING_E);
if (ret != SECRET_LEN) {
SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
}
}
session->sslServer->arrays->preMasterSz = SECRET_LEN; session->sslServer->arrays->preMasterSz = SECRET_LEN;
/* store for client side as well */
XMEMCPY(session->sslClient->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSecret, SECRET_LEN);
session->sslClient->arrays->preMasterSz = SECRET_LEN;
#ifdef SHOW_SECRETS
{
int i;
printf("pre master secret: ");
for (i = 0; i < SECRET_LEN; i++)
printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
printf("\n");
}
#endif
}
else {
SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key); wc_FreeRsaKey(&key);
return -1;
} }
if (tryEcc) {
#ifdef HAVE_ECC
ecc_key key;
ecc_key pubKey;
int length, keyInit = 0, pubKeyInit = 0;
idx = 0;
ret = wc_ecc_init(&key);
if (ret == 0) {
keyInit = 1;
ret = wc_ecc_init(&pubKey);
}
if (ret == 0) {
pubKeyInit = 1;
ret = wc_EccPrivateKeyDecode(
session->sslServer->buffers.key->buffer,
&idx, &key, session->sslServer->buffers.key->length);
if (ret != 0) {
SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
}
}
if (ret == 0) {
length = wc_ecc_size(&key) * 2 + 1;
/* The length should be 2 times the key size (x and y), plus 1
* for the type byte. */
if (IsTLS(session->sslServer)) {
input += 1; /* Don't include the TLS length for the key. */
}
if (length + 1 > *sslBytes) {
SetError(PARTIAL_INPUT_STR,
error, session, FATAL_ERROR_STATE);
ret = -1;
}
}
if (ret == 0) {
ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF);
if (ret != 0) {
SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
}
}
if (ret == 0) {
session->sslServer->arrays->preMasterSz = ENCRYPT_LEN;
do {
#ifdef WOLFSSL_ASYNC_CRYPT
ret = wc_AsyncWait(ret, &key.asyncDev,
WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret >= 0) {
ret = wc_ecc_shared_secret(&key, &pubKey,
session->sslServer->arrays->preMasterSecret,
&session->sslServer->arrays->preMasterSz);
}
} while (ret == WC_PENDING_E);
}
if (keyInit)
wc_ecc_free(&key);
if (pubKeyInit)
wc_ecc_free(&pubKey);
#endif
}
/* store for client side as well */
XMEMCPY(session->sslClient->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz);
session->sslClient->arrays->preMasterSz =
session->sslServer->arrays->preMasterSz;
#ifdef SHOW_SECRETS
{
int i;
printf("pre master secret: ");
for (i = 0; i < session->sslServer->arrays->preMasterSz; i++)
printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
printf("\n");
}
#endif
if (SetCipherSpecs(session->sslServer) != 0) { if (SetCipherSpecs(session->sslServer) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
return -1; return -1;
} }
if (SetCipherSpecs(session->sslClient) != 0) { if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
return -1; return -1;
} }
@ -1591,7 +1681,6 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
} }
#endif #endif
wc_FreeRsaKey(&key);
return ret; return ret;
} }

View File

@ -119,6 +119,8 @@
#define BAD_DECRYPT_SIZE 81 #define BAD_DECRYPT_SIZE 81
#define EXTENDED_MASTER_HASH_STR 82 #define EXTENDED_MASTER_HASH_STR 82
#define SPLIT_HANDSHAKE_MSG_STR 83 #define SPLIT_HANDSHAKE_MSG_STR 83
#define ECC_DECODE_STR 84
#define ECC_PUB_DECODE_STR 85
/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ /* !!!! also add to msgTable in sniffer.c and .rc file !!!! */

View File

@ -100,5 +100,7 @@ STRINGTABLE
81, "Bad Decrypt Size" 81, "Bad Decrypt Size"
82, "Extended Master Secret Hash Error" 82, "Extended Master Secret Hash Error"
83, "Handshake Message Split Across TLS Records" 83, "Handshake Message Split Across TLS Records"
84, "ECC Private Decode Error"
85, "ECC Public Decode Error"
} }