Static ephemeral refactor to support loading both DHE and ECDHE keys. Added ability to specify key using snifftest input at run-time. Improved snifftest key loading for named keys and static ephemeral.

This commit is contained in:
David Garske 2020-11-09 16:07:14 -08:00
parent 1c87f3bdc1
commit 71d9f1e9bd
7 changed files with 172 additions and 90 deletions

View File

@ -1747,7 +1747,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
if (ret != 0) {
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,
"./certs/statickeys/dh-ffdhe2048.pem", 0, WOLFSSL_FILETYPE_PEM);
if (ret != 0) {

View File

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

View File

@ -2067,11 +2067,26 @@ static void ShowTlsSecrets(SnifferSession* session)
/* Process Keys */
/* contains static ephemeral keys */
typedef struct {
#ifndef NO_DH
DerBuffer* ecKey;
#endif
#ifdef HAVE_ECC
DerBuffer* dhKey;
#endif
#if !defined(NO_RSA) && defined(WOLFSSL_STATIC_RSA)
DerBuffer* rsaKey;
#endif
} KeyBuffers_t;
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;
int ret;
DerBuffer* keyBuf;
#ifdef HAVE_ECC
int useEccCurveId = ECC_CURVE_DEF;
if (ksInfo && ksInfo->curve_id != 0)
@ -2080,9 +2095,11 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifndef NO_RSA
/* Static RSA */
if (ksInfo == NULL) {
if (ksInfo == NULL && keys->rsaKey) {
RsaKey key;
int length;
keyBuf = keys->rsaKey;
ret = wc_InitRsaKey(&key, 0);
if (ret == 0) {
@ -2152,11 +2169,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
/* Static DH Key */
if (ksInfo && ksInfo->dh_key_bits != 0) {
if (ksInfo && ksInfo->dh_key_bits != 0 && keys->dhKey) {
DhKey dhKey;
const DhParams* params;
word32 privKeySz;
byte privKey[52]; /* max for TLS */
keyBuf = keys->dhKey;
/* get DH params */
switch (ksInfo->named_group) {
@ -2240,11 +2259,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifdef HAVE_ECC
/* Static ECC Key */
if (useEccCurveId >= ECC_CURVE_DEF) {
if (useEccCurveId >= ECC_CURVE_DEF && keys->ecKey) {
ecc_key key;
ecc_key pubKey;
int length, keyInit = 0, pubKeyInit = 0;
keyBuf = keys->ecKey;
idx = 0;
ret = wc_ecc_init(&key);
if (ret == 0) {
@ -2395,6 +2415,8 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SnifferSession* session, char* error)
{
KeyBuffers_t keys;
if (session->sslServer->buffers.key == NULL ||
session->sslServer->buffers.key->buffer == NULL ||
session->sslServer->buffers.key->length == 0) {
@ -2403,8 +2425,9 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
return -1;
}
return SetupKeys(input, sslBytes, session, error, NULL,
session->sslServer->buffers.key);
XMEMSET(&keys, 0, sizeof(keys));
keys.rsaKey = session->sslServer->buffers.key;
return SetupKeys(input, sslBytes, session, error, NULL, &keys);
}
#ifdef WOLFSSL_TLS13
@ -3012,13 +3035,19 @@ static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
#ifdef WOLFSSL_TLS13
/* Setup handshake keys */
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
if (session->sslServer->staticKE.key)
key = session->sslServer->staticKE.key;
#ifndef NO_DH
keys.dhKey = session->sslServer->staticKE.dhKey;
#endif
#ifdef HAVE_ECC
keys.ecKey = session->sslServer->staticKE.ecKey;
#endif
#endif
ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
session, error, &session->cliKs, key);
session, error, &session->cliKs, &keys);
if (ret != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
return ret;

View File

@ -48874,9 +48874,10 @@ int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
#ifdef WOLFSSL_STATIC_EPHEMERAL
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;
DerBuffer* der = NULL;
byte* keyBuf = NULL;
#ifndef NO_FILESYSTEM
const char* keyFile = NULL;
@ -48887,6 +48888,16 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
return BAD_FUNC_ARG;
}
/* if key is already set free it */
#ifndef NO_DH
if (staticKE->dhKey && (ctx == NULL || staticKE->dhKey != ctx->staticKE.dhKey))
FreeDer(&staticKE->dhKey);
#endif
#ifdef HAVE_ECC
if (staticKE->ecKey && (ctx == NULL || staticKE->ecKey != ctx->staticKE.ecKey))
FreeDer(&staticKE->ecKey);
#endif
/* check if just free'ing key */
if (key == NULL && keySz == 0) {
return 0;
@ -48913,7 +48924,7 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
if (format == WOLFSSL_FILETYPE_PEM) {
#ifdef WOLFSSL_PEM_TO_DER
int keyFormat = 0;
ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &staticKE->key,
ret = PemToDer(keyBuf, keySz, PRIVATEKEY_TYPE, &der,
heap, NULL, &keyFormat);
/* auto detect key type */
if (ret == 0 && keyAlgo == 0) {
@ -48927,12 +48938,29 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
#endif
}
else {
ret = AllocDer(&staticKE->key, keySz, PRIVATEKEY_TYPE, heap);
ret = AllocDer(&der, keySz, PRIVATEKEY_TYPE, heap);
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
if (keyFile && keyBuf) {
@ -48949,13 +48977,8 @@ int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
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,
ctx->heap);
ctx->heap, NULL);
}
int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
@ -48965,13 +48988,8 @@ int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
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,
ssl->heap);
ssl->heap, ssl->ctx);
}
#endif /* WOLFSSL_STATIC_EPHEMERAL */

View File

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

View File

@ -311,6 +311,43 @@ static int myStoreDataCb(const unsigned char* decryptBuf,
}
#endif /* WOLFSSL_SNIFFER_STORE_DATA_CB */
/* try and load as both static ephemeral and private key */
/* only fail if no key is loaded */
static int load_key(const char* name, const char* server, int port,
const char* keyFile, const char* passwd, char* err)
{
int ret;
int loadCount = 0;
#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);
ret = -1;
}
(void)name;
return ret;
}
int main(int argc, char** argv)
{
@ -323,7 +360,10 @@ int main(int argc, char** argv)
int frame = ETHER_IF_FRAME_LEN;
char err[PCAP_ERRBUF_SIZE];
char filter[32];
const char *keyFile = NULL;
char keyFileBuf[128];
const char *server = NULL;
const char *sniName = NULL;
struct bpf_program fp;
pcap_if_t *d;
pcap_addr_t *a;
@ -436,6 +476,31 @@ int main(int argc, char** argv)
ret = pcap_setfilter(pcap, &fp);
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)
keyFile = DEFAULT_SERVER_EPH_KEY;
#else
keyFile = DEFAULT_SERVER_KEY;
#endif
printf("Enter the server key [default: %s]: ", keyFile);
XMEMSET(keyFileBuf, 0, sizeof(keyFileBuf));
if (XFGETS(keyFileBuf, sizeof(keyFileBuf), stdin)) {
if (keyFileBuf[0] != '\r' && keyFileBuf[0] != '\n') {
keyFile = keyFileBuf;
}
}
/* 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 */
for (a = d->addresses; a; a = a->next) {
server = NULL;
@ -449,39 +514,7 @@ int main(int argc, char** argv)
}
if (server) {
#ifdef DEFAULT_SERVER_KEY
ret = ssl_SetPrivateKey(server, port, DEFAULT_SERVER_KEY,
FILETYPE_PEM, NULL, err);
if (ret != 0) {
printf("Please run directly from sslSniffer/sslSnifferTest"
"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 */
load_key(sniName, server, port, keyFile, NULL, err);
}
}
}
@ -494,11 +527,11 @@ int main(int argc, char** argv)
}
else {
const char* passwd = NULL;
int loadCount = 0;
/* defaults for server and port */
port = 443;
server = "127.0.0.1";
keyFile = argv[2];
if (argc >= 4)
server = argv[3];
@ -509,22 +542,8 @@ int main(int argc, char** argv)
if (argc >= 6)
passwd = argv[5];
/* try and load as both static ephemeral and private key */
/* only fail if no key is loaded */
#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);
ret = load_key(NULL, server, port, keyFile, passwd, err);
if (ret != 0) {
exit(EXIT_FAILURE);
}

View File

@ -2625,9 +2625,14 @@ enum SetCBIO {
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
/* contains static ephemeral keys */
typedef struct {
int keyAlgo;
DerBuffer* key;
#ifndef NO_DH
DerBuffer* dhKey;
#endif
#ifdef HAVE_ECC
DerBuffer* ecKey;
#endif
} StaticKeyExchangeInfo_t;
#endif