Fixes for static ephemeral key support with threading and possible use after free.

This commit is contained in:
David Garske
2021-11-05 09:57:59 -07:00
parent 4a04e56ac8
commit e91439f2eb
5 changed files with 427 additions and 313 deletions

View File

@ -2400,16 +2400,19 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef NO_DH
if (ctx->staticKE.dhKey && ctx->staticKE.weOwnDH)
FreeDer(&ctx->staticKE.dhKey);
FreeDer(&ctx->staticKE.dhKey);
#endif
#ifdef HAVE_ECC
if (ctx->staticKE.ecKey && ctx->staticKE.weOwnEC)
FreeDer(&ctx->staticKE.ecKey);
FreeDer(&ctx->staticKE.ecKey);
#endif
#ifdef HAVE_CURVE25519
if (ctx->staticKE.x25519Key && ctx->staticKE.weOwnX25519)
FreeDer(&ctx->staticKE.x25519Key);
FreeDer(&ctx->staticKE.x25519Key);
#endif
#ifndef SINGLE_THREADED
if (ctx->staticKELockInit) {
wc_FreeMutex(&ctx->staticKELock);
ctx->staticKELockInit = 0;
}
#endif
#endif
(void)heapAtCTXInit;
@ -6381,19 +6384,6 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
ssl->options.useClientOrder = ctx->useClientOrder;
ssl->options.mutualAuth = ctx->mutualAuth;
#ifdef WOLFSSL_STATIC_EPHEMERAL
XMEMCPY(&ssl->staticKE, &ctx->staticKE, sizeof(StaticKeyExchangeInfo_t));
#ifdef HAVE_ECC
ssl->staticKE.weOwnEC = 0;
#endif
#ifndef NO_DH
ssl->staticKE.weOwnDH = 0;
#endif
#ifdef HAVE_CURVE25519
ssl->staticKE.weOwnX25519 = 0;
#endif
#endif
#ifdef WOLFSSL_TLS13
#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER)
ssl->options.maxTicketTls13 = ctx->maxTicketTls13;
@ -7207,16 +7197,13 @@ void SSL_ResourceFree(WOLFSSL* ssl)
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef NO_DH
if (ssl->staticKE.dhKey && ssl->staticKE.weOwnDH)
FreeDer(&ssl->staticKE.dhKey);
FreeDer(&ssl->staticKE.dhKey);
#endif
#ifdef HAVE_ECC
if (ssl->staticKE.ecKey && ssl->staticKE.weOwnEC)
FreeDer(&ssl->staticKE.ecKey);
FreeDer(&ssl->staticKE.ecKey);
#endif
#ifdef HAVE_CURVE25519
if (ssl->staticKE.x25519Key && ssl->staticKE.weOwnX25519)
FreeDer(&ssl->staticKE.x25519Key);
FreeDer(&ssl->staticKE.x25519Key);
#endif
#endif

View File

@ -2158,32 +2158,19 @@ static void ShowTlsSecrets(SnifferSession* session)
/* Process Keys */
/* contains static ephemeral keys */
typedef struct {
#ifndef NO_DH
DerBuffer* dhKey;
#endif
#ifdef HAVE_ECC
DerBuffer* ecKey;
#endif
#ifdef HAVE_CURVE25519
DerBuffer* x25519Key;
#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, KeyBuffers_t* keys)
char* error, KeyShareInfo* ksInfo)
{
word32 idx = 0;
int ret;
DerBuffer* keyBuf;
DerBuffer* keyBuf = NULL;
int keyBufFree = 0;
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
int useCurveId = 0;
#endif
int devId = INVALID_DEVID;
WOLFSSL_CTX* ctx = session->context->ctx;
WOLFSSL* ssl = session->sslServer;
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
if (ksInfo && ksInfo->curve_id != 0)
@ -2201,15 +2188,18 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifndef NO_RSA
/* Static RSA */
if (ksInfo == NULL && keys->rsaKey) {
if (ksInfo == NULL && ssl->buffers.key) {
RsaKey key;
int length;
keyBuf = keys->rsaKey;
int keyInit = 0;
ret = wc_InitRsaKey_ex(&key, NULL, devId);
if (ret == 0) {
ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length);
keyInit = 1;
keyBuf = ssl->buffers.key;
ret = wc_RsaPrivateKeyDecode(keyBuf->buffer, &idx, &key,
keyBuf->length);
if (ret != 0) {
#ifndef HAVE_ECC
#ifdef WOLFSSL_SNIFFER_STATS
@ -2217,18 +2207,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#endif
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. */
/* If we can do ECC, this isn't fatal. Not loading a key later
* will be fatal, though. */
SetError(RSA_DECODE_STR, error, session, 0);
if (keys->ecKey == NULL)
keys->ecKey = session->sslServer->buffers.key; /* try ECC */
keyBuf = NULL;
#endif
}
#if defined(HAVE_ECC) || defined(HAVE_CURVE25519)
else {
useCurveId = -1; /* don't try loading further */
}
#endif
}
if (ret == 0) {
@ -2243,14 +2227,14 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
}
#ifdef WC_RSA_BLINDING
#ifdef WC_RSA_BLINDING
if (ret == 0) {
ret = wc_RsaSetRNG(&key, session->sslServer->rng);
if (ret != 0) {
SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
}
}
#endif
#endif
if (ret == 0) {
session->keySz = length * WOLFSSL_BIT_SIZE;
@ -2264,8 +2248,8 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#endif
if (ret >= 0) {
ret = wc_RsaPrivateDecrypt(input, length,
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz, &key);
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz, &key);
}
} while (ret == WC_PENDING_E);
@ -2274,100 +2258,137 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
}
wc_FreeRsaKey(&key);
if (keyInit) {
wc_FreeRsaKey(&key);
}
}
#endif /* !NO_RSA */
#if !defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)
/* Static DH Key */
if (ksInfo && ksInfo->dh_key_bits != 0 && keys->dhKey) {
if (ksInfo && ksInfo->dh_key_bits != 0 && keyBuf == NULL) {
DhKey dhKey;
#ifdef HAVE_PUBLIC_FFDHE
#ifdef HAVE_PUBLIC_FFDHE
const DhParams* params;
word32 privKeySz;
#else
#endif
word32 privKeySz = 0, p_len = 0;
#endif
byte privKey[52]; /* max for TLS */
int keyInit = 0;
keyBuf = keys->dhKey;
/* try and load static ephemeral */
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef SINGLE_THREADED
int keyLocked = 0;
if (ctx->staticKELockInit &&
wc_LockMutex(&ctx->staticKELock) == 0)
#endif
{
#ifndef SINGLE_THREADED
keyLocked = 1;
#endif
keyBuf = ssl->staticKE.dhKey;
if (keyBuf == NULL)
keyBuf = ctx->staticKE.dhKey;
}
#endif
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
ret = 0;
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
if (KeyCb != NULL) {
if (keyBuf == NULL) {
ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
if (ret == 0)
keyBufFree = 1;
}
ret = KeyCb(session, ksInfo->named_group,
session->srvKs.key, session->srvKs.key_len,
session->cliKs.key, session->cliKs.key_len,
keyBuf, KeyCbCtx, error);
if (ret != 0) {
SetError(-1, error, session, FATAL_ERROR_STATE);
return ret;
}
}
#endif
#ifdef HAVE_PUBLIC_FFDHE
/* get DH params */
switch (ksInfo->named_group) {
#ifdef HAVE_FFDHE_2048
case WOLFSSL_FFDHE_2048:
params = wc_Dh_ffdhe2048_Get();
privKeySz = 29;
break;
#endif
#ifdef HAVE_FFDHE_3072
case WOLFSSL_FFDHE_3072:
params = wc_Dh_ffdhe3072_Get();
privKeySz = 34;
break;
#endif
#ifdef HAVE_FFDHE_4096
case WOLFSSL_FFDHE_4096:
params = wc_Dh_ffdhe4096_Get();
privKeySz = 39;
break;
#endif
#ifdef HAVE_FFDHE_6144
case WOLFSSL_FFDHE_6144:
params = wc_Dh_ffdhe6144_Get();
privKeySz = 46;
break;
#endif
#ifdef HAVE_FFDHE_8192
case WOLFSSL_FFDHE_8192:
params = wc_Dh_ffdhe8192_Get();
privKeySz = 52;
break;
#endif
default:
return BAD_FUNC_ARG;
#endif
if (ret == 0 && keyBuf == NULL) {
ret = BUFFER_E;
}
#endif
ret = wc_InitDhKey_ex(&dhKey, NULL, devId);
#ifdef HAVE_PUBLIC_FFDHE
if (ret == 0) {
#ifdef HAVE_PUBLIC_FFDHE
/* get DH params */
switch (ksInfo->named_group) {
#ifdef HAVE_FFDHE_2048
case WOLFSSL_FFDHE_2048:
params = wc_Dh_ffdhe2048_Get();
privKeySz = 29;
break;
#endif
#ifdef HAVE_FFDHE_3072
case WOLFSSL_FFDHE_3072:
params = wc_Dh_ffdhe3072_Get();
privKeySz = 34;
break;
#endif
#ifdef HAVE_FFDHE_4096
case WOLFSSL_FFDHE_4096:
params = wc_Dh_ffdhe4096_Get();
privKeySz = 39;
break;
#endif
#ifdef HAVE_FFDHE_6144
case WOLFSSL_FFDHE_6144:
params = wc_Dh_ffdhe6144_Get();
privKeySz = 46;
break;
#endif
#ifdef HAVE_FFDHE_8192
case WOLFSSL_FFDHE_8192:
params = wc_Dh_ffdhe8192_Get();
privKeySz = 52;
break;
#endif
default:
ret = BAD_FUNC_ARG;
}
}
#endif
if (ret == 0) {
ret = wc_InitDhKey_ex(&dhKey, NULL, devId);
if (ret == 0)
keyInit = 1;
}
if (ret == 0) {
#ifdef HAVE_PUBLIC_FFDHE
ret = wc_DhSetKey(&dhKey,
(byte*)params->p, params->p_len,
(byte*)params->g, params->g_len);
#else
p_len = params->p_len;
#else
ret = wc_DhSetNamedKey(&dhKey, ksInfo->named_group);
#endif
if (ret == 0) {
ret = wc_DhKeyDecode(keyBuf->buffer, &idx, &dhKey,
keyBuf->length);
}
#ifndef HAVE_PUBLIC_FFDHE
if (ret == 0) {
privKeySz = wc_DhGetNamedKeyMinSize(ksInfo->named_group);
ret = wc_DhGetNamedKeyParamSize(ksInfo->named_group,
&p_len, NULL, NULL);
}
#endif
if (ret == 0) {
ret = wc_DhExportKeyPair(&dhKey, privKey, &privKeySz, NULL,
NULL);
}
#endif
}
if (ret == 0) {
ret = wc_DhKeyDecode(keyBuf->buffer, &idx, &dhKey,
keyBuf->length);
}
if (ret == 0) {
ret = wc_DhExportKeyPair(&dhKey, privKey, &privKeySz, NULL,
NULL);
}
#if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
if (keyLocked) {
wc_UnLockMutex(&ctx->staticKELock);
}
#endif
if (ret == 0) {
/* Derive secret from private key and peer's public key */
do {
#ifdef WOLFSSL_ASYNC_CRYPT
@ -2384,71 +2405,86 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
PRIVATE_KEY_LOCK();
}
} while (ret == WC_PENDING_E);
}
if (keyInit)
wc_FreeDhKey(&dhKey);
#ifdef WOLFSSL_SNIFFER_STATS
if (ret != 0)
INC_STAT(SnifferStats.sslKeyFails);
#endif
#ifdef WOLFSSL_SNIFFER_STATS
if (ret != 0)
INC_STAT(SnifferStats.sslKeyFails);
#endif
/* left-padded with zeros up to the size of the prime */
#ifdef HAVE_PUBLIC_FFDHE
if (ret == 0 && params->p_len > session->sslServer->arrays->preMasterSz) {
word32 diff = params->p_len - session->sslServer->arrays->preMasterSz;
XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff,
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz);
XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff);
session->sslServer->arrays->preMasterSz = params->p_len;
}
#else /* HAVE_PUBLIC_FFDHE */
if (ret == 0 && p_len > session->sslServer->arrays->preMasterSz) {
word32 diff = p_len - session->sslServer->arrays->preMasterSz;
XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff,
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz);
XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff);
session->sslServer->arrays->preMasterSz = p_len;
}
#endif /* HAVE_PUBLIC_FFDHE */
/* left-padded with zeros up to the size of the prime */
if (ret == 0 && p_len > session->sslServer->arrays->preMasterSz) {
word32 diff = p_len - session->sslServer->arrays->preMasterSz;
XMEMMOVE(session->sslServer->arrays->preMasterSecret + diff,
session->sslServer->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSz);
XMEMSET(session->sslServer->arrays->preMasterSecret, 0, diff);
session->sslServer->arrays->preMasterSz = p_len;
}
}
#endif /* !NO_DH && WOLFSSL_DH_EXTRA */
#ifdef HAVE_ECC
/* Static ECC Key */
if (useCurveId >= 0 && keys->ecKey
if (useCurveId >= 0 && keyBuf == NULL
#ifdef HAVE_CURVE25519
&& useCurveId != ECC_X25519
#endif
) {
ecc_key key;
ecc_key pubKey;
ecc_key key, pubKey;
int length, keyInit = 0, pubKeyInit = 0;
keyBuf = keys->ecKey;
/* try and load static ephemeral */
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef SINGLE_THREADED
int keyLocked = 0;
if (ctx->staticKELockInit &&
wc_LockMutex(&ctx->staticKELock) == 0)
#endif
{
#ifndef SINGLE_THREADED
keyLocked = 1;
#endif
keyBuf = ssl->staticKE.ecKey;
if (keyBuf == NULL)
keyBuf = ctx->staticKE.ecKey;
}
#endif
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
/* try static ECC */
if (keyBuf == NULL) {
keyBuf = session->sslServer->buffers.key;
}
ret = 0;
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
if (KeyCb != NULL && ksInfo) {
if (keyBuf == NULL) {
ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
if (ret == 0)
keyBufFree = 1;
}
ret = KeyCb(session, ksInfo->named_group,
session->srvKs.key, session->srvKs.key_len,
session->cliKs.key, session->cliKs.key_len,
keyBuf, KeyCbCtx, error);
if (ret != 0) {
SetError(-1, error, session, FATAL_ERROR_STATE);
return ret;
}
}
#endif
#endif
idx = 0;
ret = wc_ecc_init_ex(&key, NULL, devId);
if (ret == 0) {
keyInit = 1;
ret = wc_ecc_init(&pubKey);
if (ret == 0 && keyBuf == NULL) {
ret = BUFFER_E;
}
if (ret == 0) {
ret = wc_ecc_init_ex(&key, NULL, devId);
if (ret == 0)
keyInit = 1;
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \
!defined(HAVE_SELFTEST)
@ -2456,15 +2492,20 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
ret = wc_ecc_set_rng(&key, session->sslServer->rng);
}
#endif
if (ret == 0) {
pubKeyInit = 1;
idx = 0;
ret = wc_EccPrivateKeyDecode(keyBuf->buffer, &idx, &key, keyBuf->length);
if (ret != 0) {
SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE);
}
}
#if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
if (keyLocked) {
wc_UnLockMutex(&ctx->staticKELock);
}
#endif
if (ret == 0) {
length = wc_ecc_size(&key) * 2 + 1;
/* The length should be 2 times the key size (x and y), plus 1
@ -2483,14 +2524,17 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
useCurveId = key.dp->id;
}
}
if (ret == 0) {
ret = wc_ecc_init(&pubKey);
if (ret == 0)
pubKeyInit = 1;
}
if (ret == 0) {
ret = wc_ecc_import_x963_ex(input, length, &pubKey, useCurveId);
if (ret != 0) {
SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE);
}
}
if (ret == 0) {
session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE;
/* Length is in bytes. Subtract 1 for the ECC key type. Divide
@ -2513,10 +2557,10 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
} while (ret == WC_PENDING_E);
}
#ifdef WOLFSSL_SNIFFER_STATS
#ifdef WOLFSSL_SNIFFER_STATS
if (ret != 0)
INC_STAT(SnifferStats.sslKeyFails);
#endif
#endif
if (keyInit)
wc_ecc_free(&key);
@ -2527,15 +2571,34 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
#ifdef HAVE_CURVE25519
/* Static Curve25519 Key */
if (useCurveId == ECC_X25519 && keys->x25519Key) {
curve25519_key key;
curve25519_key pubKey;
if (useCurveId == ECC_X25519) {
curve25519_key key, pubKey;
int length, keyInit = 0, pubKeyInit = 0;
keyBuf = keys->x25519Key;
/* try and load static ephemeral */
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef SINGLE_THREADED
int keyLocked = 0;
if (ctx->staticKELockInit &&
wc_LockMutex(&ctx->staticKELock) == 0)
#endif
{
#ifndef SINGLE_THREADED
keyLocked = 1;
#endif
keyBuf = ssl->staticKE.x25519Key;
if (keyBuf == NULL)
keyBuf = ctx->staticKE.x25519Key;
}
#endif
#ifdef WOLFSSL_SNIFFER_KEY_CALLBACK
if (KeyCb != NULL && ksInfo) {
if (keyBuf == NULL) {
ret = AllocDer(&keyBuf, FILE_BUFFER_SIZE, PRIVATEKEY_TYPE, NULL);
if (ret == 0)
keyBufFree = 1;
}
ret = KeyCb(session, ksInfo->named_group,
session->srvKs.key, session->srvKs.key_len,
session->cliKs.key, session->cliKs.key_len,
@ -2547,15 +2610,16 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
#endif
idx = 0;
ret = wc_curve25519_init_ex(&key, NULL, devId);
if (ret == 0) {
keyInit = 1;
ret = wc_curve25519_init(&pubKey);
if (ret == 0 && keyBuf == NULL) {
ret = BUFFER_E;
}
if (ret == 0) {
pubKeyInit = 1;
ret = wc_curve25519_init_ex(&key, NULL, devId);
if (ret == 0)
keyInit = 1;
}
if (ret == 0) {
idx = 0;
ret = wc_Curve25519PrivateKeyDecode(keyBuf->buffer, &idx, &key,
keyBuf->length);
if (ret != 0) {
@ -2563,6 +2627,12 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
}
#if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
if (keyLocked) {
wc_UnLockMutex(&ctx->staticKELock);
}
#endif
if (ret == 0) {
length = CURVE25519_KEYSIZE;
if (length > *sslBytes) {
@ -2570,7 +2640,11 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
ret = -1;
}
}
if (ret == 0) {
ret = wc_curve25519_init(&pubKey);
if (ret == 0)
pubKeyInit = 1;
}
if (ret == 0) {
ret = wc_curve25519_import_public_ex(input, length, &pubKey,
EC25519_LITTLE_ENDIAN);
@ -2601,6 +2675,10 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
}
#endif /* HAVE_CURVE25519 */
if (keyBufFree && keyBuf != NULL) {
FreeDer(&keyBuf);
}
/* store for client side as well */
XMEMCPY(session->sslClient->arrays->preMasterSecret,
session->sslServer->arrays->preMasterSecret,
@ -2666,12 +2744,13 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session,
return ret;
}
/* Process Client Key Exchange, static RSA */
/* Process Client Key Exchange */
static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SnifferSession* session, char* error)
{
KeyBuffers_t keys;
int ret;
#ifndef WOLFSSL_STATIC_EPHEMERAL
if (session->sslServer->buffers.key == NULL ||
session->sslServer->buffers.key->buffer == NULL ||
session->sslServer->buffers.key->length == 0) {
@ -2679,23 +2758,11 @@ static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
return -1;
}
#endif
XMEMSET(&keys, 0, sizeof(keys));
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef NO_DH
keys.dhKey = session->sslServer->staticKE.dhKey;
#endif
#ifdef HAVE_ECC
keys.ecKey = session->sslServer->staticKE.ecKey;
#endif
#ifdef HAVE_CURVE25519
keys.x25519Key = session->sslServer->staticKE.x25519Key;
#endif
#endif
#ifndef NO_RSA
keys.rsaKey = session->sslServer->buffers.key;
#endif
return SetupKeys(input, sslBytes, session, error, NULL, &keys);
ret = SetupKeys(input, sslBytes, session, error, NULL);
return ret;
}
#ifdef WOLFSSL_TLS13
@ -3315,25 +3382,8 @@ 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) {
KeyBuffers_t keys;
XMEMSET(&keys, 0, sizeof(keys));
#ifndef NO_RSA
keys.rsaKey = session->sslServer->buffers.key;
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
#ifndef NO_DH
keys.dhKey = session->sslServer->staticKE.dhKey;
#endif
#ifdef HAVE_ECC
keys.ecKey = session->sslServer->staticKE.ecKey;
#endif
#ifdef HAVE_CURVE25519
keys.x25519Key = session->sslServer->staticKE.x25519Key;
#endif
#endif
ret = SetupKeys(session->cliKs.key, &session->cliKs.key_len,
session, error, &session->cliKs, &keys);
session, error, &session->cliKs);
if (ret != 0) {
SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
return ret;

214
src/ssl.c
View File

@ -55597,8 +55597,82 @@ int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey)
#endif /* OPENSSL_ALL && !NO_CERTS && WOLFSSL_CERT_GEN && WOLFSSL_CERT_REQ */
#ifdef WOLFSSL_STATIC_EPHEMERAL
static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
const char* key, unsigned int keySz, int format, void* heap)
int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr)
{
int ret = BUFFER_E;
word32 idx = 0;
DerBuffer* der = NULL;
if (ssl == NULL || ssl->ctx == NULL || keyPtr == NULL) {
return BAD_FUNC_ARG;
}
#ifndef SINGLE_THREADED
if (!ssl->ctx->staticKELockInit) {
return BUFFER_E; /* no keys set */
}
ret = wc_LockMutex(&ssl->ctx->staticKELock);
if (ret != 0) {
return ret;
}
#endif
switch (keyAlgo) {
#ifndef NO_DH
case WC_PK_TYPE_DH:
if (ssl != NULL)
der = ssl->staticKE.dhKey;
if (der == NULL)
der = ssl->ctx->staticKE.dhKey;
if (der != NULL) {
DhKey* key = (DhKey*)keyPtr;
WOLFSSL_MSG("Using static DH key");
ret = wc_DhKeyDecode(der->buffer, &idx, key, der->length);
}
break;
#endif
#ifdef HAVE_ECC
case WC_PK_TYPE_ECDH:
if (ssl != NULL)
der = ssl->staticKE.ecKey;
if (der == NULL)
der = ssl->ctx->staticKE.ecKey;
if (der != NULL) {
ecc_key* key = (ecc_key*)keyPtr;
WOLFSSL_MSG("Using static ECDH key");
ret = wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length);
}
break;
#endif
#ifdef HAVE_CURVE25519
case WC_PK_TYPE_CURVE25519:
if (ssl != NULL)
der = ssl->staticKE.x25519Key;
if (der == NULL)
der = ssl->ctx->staticKE.x25519Key;
if (der != NULL) {
curve25519_key* key = (curve25519_key*)keyPtr;
WOLFSSL_MSG("Using static X25519 key");
ret = wc_Curve25519PrivateKeyDecode(der->buffer, &idx, key,
der->length);
}
break;
#endif
default:
/* not supported */
ret = NOT_COMPILED_IN;
break;
}
#ifndef SINGLE_THREADED
wc_UnLockMutex(&ssl->ctx->staticKELock);
#endif
return ret;
}
static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx,
StaticKeyExchangeInfo_t* staticKE, int keyAlgo, const char* key,
unsigned int keySz, int format, void* heap)
{
int ret = 0;
DerBuffer* der = NULL;
@ -55711,53 +55785,55 @@ static int SetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
}
#endif
/* if key is already allocated then set free it */
#ifndef NO_DH
if (keyAlgo == WC_PK_TYPE_DH && staticKE->dhKey && staticKE->weOwnDH) {
FreeDer(&staticKE->dhKey);
}
#endif
#ifdef HAVE_ECC
if (keyAlgo == WC_PK_TYPE_ECDH && staticKE->ecKey && staticKE->weOwnEC) {
FreeDer(&staticKE->ecKey);
}
#endif
#ifdef HAVE_CURVE25519
if (keyAlgo == WC_PK_TYPE_CURVE25519 && staticKE->x25519Key &&
staticKE->weOwnX25519) {
FreeDer(&staticKE->x25519Key);
#ifndef SINGLE_THREADED
if (ret == 0 && !ctx->staticKELockInit) {
ret = wc_InitMutex(&ctx->staticKELock);
if (ret == 0) {
ctx->staticKELockInit = 1;
}
}
#endif
if (ret == 0
#ifndef SINGLE_THREADED
&& (ret = wc_LockMutex(&ctx->staticKELock)) == 0
#endif
) {
switch (keyAlgo) {
#ifndef NO_DH
case WC_PK_TYPE_DH:
FreeDer(&staticKE->dhKey);
staticKE->dhKey = der; der = NULL;
break;
#endif
#ifdef HAVE_ECC
case WC_PK_TYPE_ECDH:
FreeDer(&staticKE->ecKey);
staticKE->ecKey = der; der = NULL;
break;
#endif
#ifdef HAVE_CURVE25519
case WC_PK_TYPE_CURVE25519:
FreeDer(&staticKE->x25519Key);
staticKE->x25519Key = der; der = NULL;
break;
#endif
default:
/* not supported */
ret = NOT_COMPILED_IN;
break;
}
switch (keyAlgo) {
#ifndef NO_DH
case WC_PK_TYPE_DH:
staticKE->dhKey = der; der = NULL;
staticKE->weOwnDH = 1;
break;
#ifndef SINGLE_THREADED
wc_UnLockMutex(&ctx->staticKELock);
#endif
#ifdef HAVE_ECC
case WC_PK_TYPE_ECDH:
staticKE->ecKey = der; der = NULL;
staticKE->weOwnEC = 1;
break;
#endif
#ifdef HAVE_CURVE25519
case WC_PK_TYPE_CURVE25519:
staticKE->x25519Key = der; der = NULL;
staticKE->weOwnX25519 = 1;
break;
#endif
default:
/* not supported */
ret = NOT_COMPILED_IN;
break;
}
if (ret != 0) {
FreeDer(&der);
}
(void)ctx; /* not used for single threaded */
WOLFSSL_LEAVE("SetStaticEphemeralKey", ret);
return ret;
@ -55769,48 +55845,58 @@ int wolfSSL_CTX_set_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
if (ctx == NULL) {
return BAD_FUNC_ARG;
}
return SetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz, format,
ctx->heap);
return SetStaticEphemeralKey(ctx, &ctx->staticKE, keyAlgo,
key, keySz, format, ctx->heap);
}
int wolfSSL_set_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
const char* key, unsigned int keySz, int format)
{
if (ssl == NULL) {
if (ssl == NULL || ssl->ctx == NULL) {
return BAD_FUNC_ARG;
}
return SetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz, format,
ssl->heap);
return SetStaticEphemeralKey(ssl->ctx, &ssl->staticKE, keyAlgo,
key, keySz, format, ssl->heap);
}
static int GetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
const unsigned char** key, unsigned int* keySz)
static int GetStaticEphemeralKey(WOLFSSL_CTX* ctx, WOLFSSL* ssl,
int keyAlgo, const unsigned char** key, unsigned int* keySz)
{
int ret = 0;
DerBuffer* der = NULL;
if (staticKE == NULL || key == NULL || keySz == NULL) {
return BAD_FUNC_ARG;
}
if (key) *key = NULL;
if (keySz) *keySz = 0;
*key = NULL;
*keySz = 0;
#ifndef SINGLE_THREADED
if (ctx->staticKELockInit &&
(ret = wc_LockMutex(&ctx->staticKELock)) != 0) {
return ret;
}
#endif
switch (keyAlgo) {
#ifndef NO_DH
case WC_PK_TYPE_DH:
der = staticKE->dhKey;
if (ssl != NULL)
der = ssl->staticKE.dhKey;
if (der == NULL)
der = ctx->staticKE.dhKey;
break;
#endif
#ifdef HAVE_ECC
case WC_PK_TYPE_ECDH:
der = staticKE->ecKey;
if (ssl != NULL)
der = ssl->staticKE.ecKey;
if (der == NULL)
der = ctx->staticKE.ecKey;
break;
#endif
#ifdef HAVE_CURVE25519
case WC_PK_TYPE_CURVE25519:
der = staticKE->x25519Key;
if (ssl != NULL)
der = ssl->staticKE.x25519Key;
if (der == NULL)
der = ctx->staticKE.x25519Key;
break;
#endif
default:
@ -55820,10 +55906,16 @@ static int GetStaticEphemeralKey(StaticKeyExchangeInfo_t* staticKE, int keyAlgo,
}
if (der) {
*key = der->buffer;
*keySz = der->length;
if (key)
*key = der->buffer;
if (keySz)
*keySz = der->length;
}
#ifndef SINGLE_THREADED
wc_UnLockMutex(&ctx->staticKELock);
#endif
return ret;
}
@ -55836,16 +55928,16 @@ int wolfSSL_CTX_get_ephemeral_key(WOLFSSL_CTX* ctx, int keyAlgo,
return BAD_FUNC_ARG;
}
return GetStaticEphemeralKey(&ctx->staticKE, keyAlgo, key, keySz);
return GetStaticEphemeralKey(ctx, NULL, keyAlgo, key, keySz);
}
int wolfSSL_get_ephemeral_key(WOLFSSL* ssl, int keyAlgo,
const unsigned char** key, unsigned int* keySz)
{
if (ssl == NULL) {
if (ssl == NULL || ssl->ctx == NULL) {
return BAD_FUNC_ARG;
}
return GetStaticEphemeralKey(&ssl->staticKE, keyAlgo, key, keySz);
return GetStaticEphemeralKey(ssl->ctx, ssl, keyAlgo, key, keySz);
}
#endif /* WOLFSSL_STATIC_EPHEMERAL */

View File

@ -6217,18 +6217,12 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
if (ret == 0) {
#if defined(WOLFSSL_STATIC_EPHEMERAL) && defined(WOLFSSL_DH_EXTRA)
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);
if (ret == 0) {
ret = wc_DhExportKeyPair(dhKey,
(byte*)kse->privKey, &kse->keyLen, /* private */
kse->pubKey, &kse->pubKeyLen /* public */
);
}
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_DH, kse->key);
if (ret == 0) {
ret = wc_DhExportKeyPair(dhKey,
(byte*)kse->privKey, &kse->keyLen, /* private */
kse->pubKey, &kse->pubKeyLen /* public */
);
}
else
#endif
@ -6329,16 +6323,12 @@ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
ret = wc_curve25519_init_ex((curve25519_key*)kse->key, ssl->heap,
INVALID_DEVID);
if (ret == 0) {
/* setting "key" means okay to call wc_curve25519_free */
key = (curve25519_key*)kse->key;
#ifdef WOLFSSL_STATIC_EPHEMERAL
if (ssl->staticKE.x25519Key) {
DerBuffer* keyDer = ssl->staticKE.x25519Key;
word32 idx = 0;
WOLFSSL_MSG("Using static X25519 key");
ret = wc_Curve25519PrivateKeyDecode(keyDer->buffer, &idx, key,
keyDer->length);
}
else
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_CURVE25519, kse->key);
if (ret != 0)
#endif
{
ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
@ -6536,17 +6526,12 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
/* Make an ECC key */
ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId);
if (ret == 0) {
/* setting eccKey means okay to call wc_ecc_free */
eccKey = (ecc_key*)kse->key;
#ifdef WOLFSSL_STATIC_EPHEMERAL
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);
}
else
ret = wolfSSL_StaticEphemeralKeyLoad(ssl, WC_PK_TYPE_ECDH, kse->key);
if (ret != 0)
#endif
{
/* set curve info for EccMakeKey "peer" info */

View File

@ -2731,19 +2731,8 @@ typedef struct {
#ifdef HAVE_CURVE25519
DerBuffer* x25519Key;
#endif
/* bits */
#ifndef NO_DH
byte weOwnDH:1;
#endif
#ifdef HAVE_ECC
byte weOwnEC:1;
#endif
#ifdef HAVE_CURVE25519
byte weOwnX25519:1;
#endif
} StaticKeyExchangeInfo_t;
#endif
#endif /* WOLFSSL_STATIC_EPHEMERAL */
/* wolfSSL context type */
@ -2846,6 +2835,10 @@ struct WOLFSSL_CTX {
#ifdef WOLFSSL_STATIC_MEMORY
byte onHeapHint:1; /* whether the ctx/method is put on heap hint */
#endif
#if defined(WOLFSSL_STATIC_EPHEMERAL) && !defined(SINGLE_THREADED)
byte staticKELockInit:1;
#endif
#ifdef WOLFSSL_MULTICAST
byte haveMcast; /* multicast requested */
byte mcastID; /* multicast group ID */
@ -3074,6 +3067,9 @@ struct WOLFSSL_CTX {
#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK */
#ifdef WOLFSSL_STATIC_EPHEMERAL
StaticKeyExchangeInfo_t staticKE;
#ifndef SINGLE_THREADED
wolfSSL_Mutex staticKELock;
#endif
#endif
};
@ -5029,6 +5025,10 @@ WOLFSSL_LOCAL int oid2nid(word32 oid, int grp);
WOLFSSL_LOCAL word32 nid2oid(int nid, int grp);
#endif
#ifdef WOLFSSL_STATIC_EPHEMERAL
WOLFSSL_LOCAL int wolfSSL_StaticEphemeralKeyLoad(WOLFSSL* ssl, int keyAlgo, void* keyPtr);
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif