Merge pull request #4306 from dgarske/pk_tls13

Fixes for PK callbacks with TLS v1.3
This commit is contained in:
John Safranek
2021-08-18 15:42:19 -07:00
committed by GitHub
5 changed files with 81 additions and 119 deletions

View File

@ -3110,6 +3110,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
wolfSSL_KeepArrays(ssl);
#endif
#ifdef HAVE_PK_CALLBACKS
/* This must be before SetKeyShare */
if (pkCallbacks) {
SetupPkCallbackContexts(ssl, &pkCbInfo);
}
#endif
#if defined(WOLFSSL_STATIC_MEMORY) && defined(DEBUG_WOLFSSL)
fprintf(stderr, "After creating SSL\n");
if (wolfSSL_CTX_is_static_memory(ctx, &mem_stats) != 1)
@ -3288,10 +3295,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (atomicUser)
SetupAtomicUser(ctx, ssl);
#endif
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks)
SetupPkCallbackContexts(ssl, &pkCbInfo);
#endif
if (matchName && doPeerCheck)
wolfSSL_check_domain_name(ssl, domain);
#ifndef WOLFSSL_CALLBACKS
@ -3744,6 +3748,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
if (!doDhKeyCheck)
wolfSSL_SetEnableDhKeyTest(sslResume, 0);
#endif
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks) {
SetupPkCallbackContexts(sslResume, &pkCbInfo);
}
#endif
if (dtlsUDP) {
TEST_DELAY();

View File

@ -2401,16 +2401,17 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
}
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks)
SetupPkCallbacks(ctx);
if (pkCallbacks)
SetupPkCallbacks(ctx);
#endif
ssl = SSL_new(ctx);
if (ssl == NULL)
err_sys_ex(catastrophic, "unable to create an SSL object");
#ifdef OPENSSL_EXTRA
wolfSSL_KeepArrays(ssl);
#endif
ssl = SSL_new(ctx);
if (ssl == NULL)
err_sys_ex(catastrophic, "unable to create an SSL object");
#ifdef OPENSSL_EXTRA
wolfSSL_KeepArrays(ssl);
#endif
/* Support for loading private key and cert using WOLFSSL object */
#if !defined(NO_CERTS)
@ -2594,10 +2595,12 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
#endif /* NO_RSA */
#endif /* HAVE_OCSP */
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks)
#ifdef HAVE_PK_CALLBACKS
/* This must be before SetKeyShare */
if (pkCallbacks) {
SetupPkCallbackContexts(ssl, &pkCbInfo);
#endif
}
#endif
#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)
if (version >= 4) {

View File

@ -4550,70 +4550,13 @@ int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out,
return ret;
}
#ifdef HAVE_PK_CALLBACKS
/* Gets ECC key for shared secret callback testing
* Client side: returns peer key
* Server side: returns private key
*/
static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey)
{
int ret = NO_PEER_KEY;
ecc_key* tmpKey = NULL;
if (ssl == NULL || otherKey == NULL) {
return BAD_FUNC_ARG;
}
if (ssl->options.side == WOLFSSL_CLIENT_END) {
if (ssl->specs.static_ecdh) {
if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent ||
!ssl->peerEccDsaKey->dp) {
return NO_PEER_KEY;
}
tmpKey = (struct ecc_key*)ssl->peerEccDsaKey;
}
else {
if (!ssl->peerEccKey || !ssl->peerEccKeyPresent ||
!ssl->peerEccKey->dp) {
return NO_PEER_KEY;
}
tmpKey = (struct ecc_key*)ssl->peerEccKey;
}
}
else if (ssl->options.side == WOLFSSL_SERVER_END) {
if (ssl->specs.static_ecdh) {
if (ssl->hsKey == NULL) {
return NO_PRIVATE_KEY;
}
tmpKey = (struct ecc_key*)ssl->hsKey;
}
else {
if (!ssl->eccTempKeyPresent) {
return NO_PRIVATE_KEY;
}
tmpKey = (struct ecc_key*)ssl->eccTempKey;
}
}
if (tmpKey) {
*otherKey = tmpKey;
ret = 0;
}
return ret;
}
#endif /* HAVE_PK_CALLBACKS */
int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen,
int side)
{
int ret;
#ifdef HAVE_PK_CALLBACKS
ecc_key* otherKey = NULL;
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev;
WC_ASYNC_DEV* asyncDev = NULL;
#endif
(void)ssl;
@ -4623,19 +4566,11 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
WOLFSSL_ENTER("EccSharedSecret");
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->EccSharedSecretCb) {
ret = EccGetKey(ssl, &otherKey);
if (ret != 0)
return ret;
#ifdef WOLFSSL_ASYNC_CRYPT
asyncDev = &otherKey->asyncDev;
#endif
}
#endif
#ifdef WOLFSSL_ASYNC_CRYPT
/* initialize event */
if (priv_key != NULL) {
asyncDev = &priv_key->asyncDev;
}
ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
if (ret != 0)
return ret;
@ -4644,6 +4579,7 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
#ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->EccSharedSecretCb) {
void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl);
ecc_key* otherKey = (side == WOLFSSL_CLIENT_END) ? pub_key : priv_key;
ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer,
pubKeySz, out, outlen, side, ctx);
}
@ -22685,6 +22621,12 @@ exit_dpk:
ssl->options.cipherSuite0 = cs0;
ssl->options.cipherSuite = cs1;
#ifdef WOLFSSL_DEBUG_TLS
WOLFSSL_MSG("Chosen cipher suite:");
WOLFSSL_MSG(GetCipherNameInternal(ssl->options.cipherSuite0,
ssl->options.cipherSuite));
#endif
compression = input[i++];
#ifndef WOLFSSL_NO_STRICT_CIPHER_SUITE

View File

@ -7415,6 +7415,7 @@ static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl,
if (ssl->peerEccKey != NULL) {
wc_ecc_free(ssl->peerEccKey);
ssl->peerEccKey = NULL;
ssl->peerEccKeyPresent = 0;
}
#endif
@ -7491,6 +7492,7 @@ static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
if (ssl->peerEccKey != NULL) {
wc_ecc_free(ssl->peerEccKey);
ssl->peerEccKey = NULL;
ssl->peerEccKeyPresent = 0;
}
#endif
@ -7607,6 +7609,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
if (ssl->peerEccKey != NULL) {
wc_ecc_free(ssl->peerEccKey);
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->peerEccKeyPresent = 0;
}
ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
@ -7631,6 +7634,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
if (ret == 0) {
ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
ssl->peerEccKeyPresent = 1;
}
}
@ -7649,10 +7653,15 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
}
/* done with key share, release resources */
if (ssl->peerEccKey != NULL) {
if (ssl->peerEccKey != NULL
#ifdef HAVE_PK_CALLBACKS
&& ssl->ctx->EccSharedSecretCb == NULL
#endif
) {
wc_ecc_free(ssl->peerEccKey);
XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->peerEccKey = NULL;
ssl->peerEccKeyPresent = 0;
}
if (keyShareEntry->key) {
wc_ecc_free((ecc_key*)keyShareEntry->key);

View File

@ -3475,6 +3475,7 @@ typedef struct PkCbInfo {
curve448_key curve;
#endif
} keyGen;
int hasKeyGen;
#endif
} PkCbInfo;
@ -3490,14 +3491,11 @@ static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz,
int ecc_curve, void* ctx)
{
int ret;
WC_RNG rng;
PkCbInfo* cbInfo = (PkCbInfo*)ctx;
ecc_key* new_key;
#ifdef TEST_PK_PRIVKEY
byte qx[MAX_ECC_BYTES], qy[MAX_ECC_BYTES];
word32 qxLen = sizeof(qx), qyLen = sizeof(qy);
new_key = &cbInfo->keyGen.ecc;
#ifdef TEST_PK_PRIVKEY
new_key = cbInfo ? &cbInfo->keyGen.ecc : key;
#else
new_key = key;
#endif
@ -3507,17 +3505,18 @@ static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz,
WOLFSSL_PKMSG("PK ECC KeyGen: keySz %d, Curve ID %d\n", keySz, ecc_curve);
ret = wc_InitRng(&rng);
if (ret != 0)
return ret;
ret = wc_ecc_init(new_key);
if (ret == 0) {
WC_RNG *rng = wolfSSL_GetRNG(ssl);
/* create new key */
ret = wc_ecc_make_key_ex(&rng, keySz, new_key, ecc_curve);
ret = wc_ecc_make_key_ex(rng, keySz, new_key, ecc_curve);
#ifdef TEST_PK_PRIVKEY
if (ret == 0) {
if (ret == 0 && new_key != key) {
byte qx[MAX_ECC_BYTES], qy[MAX_ECC_BYTES];
word32 qxLen = sizeof(qx), qyLen = sizeof(qy);
/* extract public portion from new key into `key` arg */
ret = wc_ecc_export_public_raw(new_key, qx, &qxLen, qy, &qyLen);
if (ret == 0) {
@ -3527,13 +3526,14 @@ static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz,
(void)qxLen;
(void)qyLen;
}
if (ret == 0 && cbInfo != NULL) {
cbInfo->hasKeyGen = 1;
}
#endif
}
WOLFSSL_PKMSG("PK ECC KeyGen: ret %d\n", ret);
wc_FreeRng(&rng);
return ret;
}
@ -3541,7 +3541,6 @@ static WC_INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
{
int ret;
WC_RNG rng;
word32 idx = 0;
ecc_key myKey;
byte* keyBuf = (byte*)key;
@ -3558,20 +3557,17 @@ static WC_INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz,
return ret;
#endif
ret = wc_InitRng(&rng);
if (ret != 0)
return ret;
ret = wc_ecc_init(&myKey);
if (ret == 0) {
ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &myKey, keySz);
if (ret == 0) {
WC_RNG *rng = wolfSSL_GetRNG(ssl);
WOLFSSL_PKMSG("PK ECC Sign: Curve ID %d\n", myKey.dp->id);
ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey);
ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, &myKey);
}
wc_ecc_free(&myKey);
}
wc_FreeRng(&rng);
#ifdef TEST_PK_PRIVKEY
free(keyBuf);
@ -3634,29 +3630,27 @@ static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
/* for client: create and export public key */
if (side == WOLFSSL_CLIENT_END) {
WC_RNG rng;
#ifdef TEST_PK_PRIVKEY
privKey = cbInfo ? &cbInfo->keyGen.ecc : &tmpKey;
#else
privKey = &tmpKey;
#endif
pubKey = otherKey;
ret = wc_InitRng(&rng);
if (ret == 0) {
ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id);
#ifdef WOLFSSL_ASYNC_CRYPT
if (ret == WC_PENDING_E) {
ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE);
}
#endif
if (ret == 0)
/* TLS v1.2 and older we must generate a key here for the client ony.
* TLS v1.3 calls key gen early with key share */
if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) {
ret = myEccKeyGen(ssl, privKey, 0, otherKey->dp->id, ctx);
if (ret == 0) {
ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz);
wc_FreeRng(&rng);
}
}
}
/* for server: import public key */
else if (side == WOLFSSL_SERVER_END) {
#ifdef TEST_PK_PRIVKEY
privKey = &cbInfo->keyGen.ecc;
privKey = cbInfo ? &cbInfo->keyGen.ecc : otherKey;
#else
privKey = otherKey;
#endif
@ -3669,6 +3663,10 @@ static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
ret = BAD_FUNC_ARG;
}
if (privKey == NULL || pubKey == NULL) {
ret = BAD_FUNC_ARG;
}
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
@ -3688,8 +3686,9 @@ static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
}
#ifdef TEST_PK_PRIVKEY
if (side == WOLFSSL_SERVER_END) {
if (cbInfo && cbInfo->hasKeyGen) {
wc_ecc_free(&cbInfo->keyGen.ecc);
cbInfo->hasKeyGen = 0;
}
#endif