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 */
"Bad Decrypt Size",
"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,
SnifferSession* session, char* error)
{
word32 idx = 0;
RsaKey key;
int ret;
int tryEcc = 0;
int ret;
if (session->sslServer->buffers.key == 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);
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) {
SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
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) {
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
ret = wc_RsaSetRNG(&key, session->sslServer->rng);
if (ret != 0) {
SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
#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;
/* 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);
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) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
return -1;
}
if (SetCipherSpecs(session->sslClient) != 0) {
SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
wc_FreeRsaKey(&key);
return -1;
}
@ -1591,7 +1681,6 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
}
#endif
wc_FreeRsaKey(&key);
return ret;
}

View File

@ -119,6 +119,8 @@
#define BAD_DECRYPT_SIZE 81
#define EXTENDED_MASTER_HASH_STR 82
#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 !!!! */

View File

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