diff --git a/examples/client/client.c b/examples/client/client.c index db2c29661..f9376c278 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -273,8 +273,9 @@ static void ShowVersions(void) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) #define MAX_GROUP_NUMBER 4 static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, - int useX448) + int useX448, int setGroups) { + int ret; int groups[MAX_GROUP_NUMBER] = {0}; int count = 0; @@ -283,49 +284,78 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); if (onlyKeyShare == 0 || onlyKeyShare == 2) { - #ifdef HAVE_CURVE25519 if (useX25519) { - groups[count++] = WOLFSSL_ECC_X25519; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) != WOLFSSL_SUCCESS) - err_sys("unable to use curve x25519"); - } - else + #ifdef HAVE_CURVE25519 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X25519; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x25519"); + } while (ret == WC_PENDING_E); #endif + } + else if (useX448) { #ifdef HAVE_CURVE448 - if (useX448) { - groups[count++] = WOLFSSL_ECC_X448; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) != WOLFSSL_SUCCESS) - err_sys("unable to use curve x448"); - } - else + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X448; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x448"); + } while (ret == WC_PENDING_E); #endif - { + } + else { #ifdef HAVE_ECC #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - groups[count++] = WOLFSSL_ECC_SECP256R1; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_SECP256R1; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve secp256r1"); + } while (ret == WC_PENDING_E); #endif #endif } } if (onlyKeyShare == 0 || onlyKeyShare == 1) { #ifdef HAVE_FFDHE_2048 - groups[count++] = WOLFSSL_FFDHE_2048; - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) != WOLFSSL_SUCCESS) - err_sys("unable to use DH 2048-bit parameters"); + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_FFDHE_2048; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use DH 2048-bit parameters"); + } while (ret == WC_PENDING_E); #endif } - if (count >= MAX_GROUP_NUMBER) err_sys("example group array size error"); - if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) - err_sys("unable to set groups"); + if (setGroups && count > 0) { + if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) + err_sys("unable to set groups"); + } WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); } -#endif +#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */ #ifdef WOLFSSL_EARLY_DATA static void EarlyData(WOLFSSL_CTX* ctx, WOLFSSL* ssl, const char* msg, @@ -443,7 +473,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) else if (version >= 4) { if (!helloRetry) - SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); else wolfSSL_NoKeyShares(ssl); } @@ -527,7 +557,7 @@ static int ClientBenchmarkConnections(WOLFSSL_CTX* ctx, char* host, word16 port, /* Measures throughput in mbps. Throughput = number of bytes */ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, int dtlsUDP, int dtlsSCTP, int block, size_t throughput, int useX25519, - int useX448, int exitWithRet) + int useX448, int exitWithRet, int version, int onlyKeyShare) { double start, conn_time = 0, tx_time = 0, rx_time = 0; SOCKET_T sockfd; @@ -546,24 +576,13 @@ static int ClientBenchmarkThroughput(WOLFSSL_CTX* ctx, char* host, word16 port, (void)useX25519; (void)useX448; - #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - #endif - #ifdef HAVE_CURVE448 - if (useX448) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - } - #endif - #endif + (void)version; + (void)onlyKeyShare; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) + if (version >= 4) { + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 1); + } +#endif do { err = 0; /* reset error */ @@ -2778,7 +2797,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef HAVE_SNI @@ -2885,7 +2904,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) ((func_args*)args)->return_code = ClientBenchmarkThroughput(ctx, host, port, dtlsUDP, dtlsSCTP, block, throughput, useX25519, useX448, - exitWithRet); + exitWithRet, version, onlyKeyShare); wolfSSL_CTX_free(ctx); ctx = NULL; if (!exitWithRet) XEXIT_T(EXIT_SUCCESS); @@ -3002,43 +3021,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) if (!helloRetry && version >= 4) { - #if defined(WOLFSSL_TLS13) && (!defined(NO_DH) || defined(HAVE_ECC) || \ - defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)) - if (onlyKeyShare == 0 || onlyKeyShare == 2) { - #ifdef HAVE_CURVE25519 - if (useX25519) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - } - #endif - #ifdef HAVE_CURVE448 - if (useX448) { - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - } - #endif - #ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - #endif - #endif - } - if (onlyKeyShare == 0 || onlyKeyShare == 1) { - #ifdef HAVE_FFDHE_2048 - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) - != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - #endif - } - #endif + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448, 0); } else { wolfSSL_NoKeyShares(ssl); @@ -3379,7 +3362,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (bio != NULL) { if (wolfSSL_SESSION_print(bio, wolfSSL_get_session(ssl)) != WOLFSSL_SUCCESS) { - wolfSSL_BIO_printf(bio, "ERROR: Unable to print out session\n"); + wolfSSL_BIO_printf(bio, "BIO error printing session\n"); } } wolfSSL_BIO_free(bio); diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 27e034a65..105b024e0 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -219,7 +219,7 @@ void echoclient_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ ssl = SSL_new(ctx); diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index d50f84847..fc36a26be 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -293,7 +293,7 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ SignalReady(args, port); diff --git a/examples/server/server.c b/examples/server/server.c index e99b76277..c6fa74f61 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -708,6 +708,95 @@ static void ServerWrite(WOLFSSL* ssl, const char* output, int outputLen) err_sys_ex(runWithErrors, "SSL_write failed"); } } + +#if defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES) +#define MAX_GROUP_NUMBER 4 +static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519, + int useX448) +{ + int ret; + int groups[MAX_GROUP_NUMBER] = {0}; + int count = 0; + + (void)useX25519; + (void)useX448; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + if (onlyKeyShare == 2) { + if (useX25519) { + #ifdef HAVE_CURVE25519 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X25519; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x25519"); + } while (ret == WC_PENDING_E); + #endif + } + else if (useX448) { + #ifdef HAVE_CURVE448 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_X448; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve x448"); + } while (ret == WC_PENDING_E); + #endif + } + else { + #ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_ECC_SECP256R1; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use curve secp256r1"); + } while (ret == WC_PENDING_E); + #endif + #endif + } + } + if (onlyKeyShare == 1) { + #ifdef HAVE_FFDHE_2048 + do { + ret = wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048); + if (ret == WOLFSSL_SUCCESS) + groups[count++] = WOLFSSL_FFDHE_2048; + #ifdef WOLFSSL_ASYNC_CRYPT + else if (ret == WC_PENDING_E) + wolfSSL_AsyncPoll(ssl, WOLF_POLL_FLAG_CHECK_HW); + #endif + else + err_sys("unable to use DH 2048-bit parameters"); + } while (ret == WC_PENDING_E); + #endif + } + if (count >= MAX_GROUP_NUMBER) + err_sys("example group array size error"); + if (count > 0) { + if (wolfSSL_set_groups(ssl, groups, count) != WOLFSSL_SUCCESS) + err_sys("unable to set groups"); + } + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); +} +#endif /* WOLFSSL_TLS13 && HAVE_SUPPORTED_CURVES */ + + /* when adding new option, please follow the steps below: */ /* 1. add new option message in English section */ /* 2. increase the number of the second column */ @@ -2367,7 +2456,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) if (ret < 0) { printf("Async device open failed\nRunning without async\n"); } - wolfSSL_CTX_UseAsync(ctx, devId); + wolfSSL_CTX_SetDevId(ctx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ #ifdef WOLFSSL_TLS13 @@ -2627,64 +2716,7 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #ifdef WOLFSSL_TLS13 if (version >= 4) { - WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); - if (onlyKeyShare == 2) { - if (useX25519 == 1) { - #ifdef HAVE_CURVE25519 - int groups[1] = { WOLFSSL_ECC_X25519 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X25519) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x25519"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: x25519"); - } - #endif - } - else if (useX448 == 1) { - #ifdef HAVE_CURVE448 - int groups[1] = { WOLFSSL_ECC_X448 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_X448) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve x448"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: x448"); - } - #endif - } - else { - #ifdef HAVE_ECC - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - int groups[1] = { WOLFSSL_ECC_SECP256R1 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_ECC_SECP256R1) - != WOLFSSL_SUCCESS) { - err_sys("unable to use curve secp256r1"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: secp256r1"); - } - #endif - #endif - } - } - else if (onlyKeyShare == 1) { - #ifdef HAVE_FFDHE_2048 - int groups[1] = { WOLFSSL_FFDHE_2048 }; - - if (wolfSSL_UseKeyShare(ssl, WOLFSSL_FFDHE_2048) - != WOLFSSL_SUCCESS) { - err_sys("unable to use DH 2048-bit parameters"); - } - if (wolfSSL_set_groups(ssl, groups, 1) != WOLFSSL_SUCCESS) { - err_sys("unable to set groups: DH 2048-bit"); - } - #endif - } - WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + SetKeyShare(ssl, onlyKeyShare, useX25519, useX448); } #endif diff --git a/src/internal.c b/src/internal.c index 9a5e27c67..18732349d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4417,17 +4417,16 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) /* get key size */ if (peer == NULL || peer->dp == NULL) { keySz = ssl->eccTempKeySz; + /* get curve type */ + if (ssl->ecdhCurveOID > 0) { + ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); + } } else { keySz = peer->dp->size; ecc_curve = peer->dp->id; } - /* get curve type */ - if (ssl->ecdhCurveOID > 0) { - ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); - } - #ifdef HAVE_PK_CALLBACKS if (ssl->ctx->EccKeyGenCb) { void* ctx = wolfSSL_GetEccKeyGenCtx(ssl); @@ -4765,6 +4764,8 @@ static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key, } #endif /* HAVE_CURVE25519 */ +#endif /* !WOLFSSL_NO_TLS12 */ + #ifdef HAVE_ED448 /* Check whether the key contains a public key. * If not then pull it out of the leaf certificate. @@ -4933,6 +4934,8 @@ int Ed448Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, } #endif /* HAVE_ED448 */ +#ifndef WOLFSSL_NO_TLS12 + #ifdef HAVE_CURVE448 #ifdef HAVE_PK_CALLBACKS /* Gets X448 key for shared secret callback testing @@ -5067,6 +5070,8 @@ static int X448MakeKey(WOLFSSL* ssl, curve448_key* key, curve448_key* peer) } #endif /* HAVE_CURVE448 */ +#endif /* !WOLFSSL_NO_TLS12 */ + #if !defined(NO_CERTS) || !defined(NO_PSK) #if !defined(NO_DH) @@ -5102,7 +5107,8 @@ int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, int DhAgree(WOLFSSL* ssl, DhKey* dhKey, const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, - byte* agree, word32* agreeSz) + byte* agree, word32* agreeSz, + const byte* prime, word32 primeSz) { int ret; @@ -5129,9 +5135,18 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey, #endif { #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) - ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer, - ssl->buffers.serverDH_P.length, otherPub, otherPubSz); + /* check the public key has valid number */ + if (dhKey != NULL && (prime == NULL || primeSz == 0)) { + /* wc_DhCheckPubKey does not do exponentiation */ + ret = wc_DhCheckPubKey(dhKey, otherPub, otherPubSz); + } + else { + ret = wc_DhCheckPubValue(prime, primeSz, otherPub, otherPubSz); + } if (ret != 0) { + /* translate to valid error (wc_DhCheckPubValue returns MP_VAL -1) */ + ret = PEER_KEY_ERROR; + #ifdef OPENSSL_EXTRA SendAlert(ssl, alert_fatal, illegal_parameter); #endif @@ -5153,13 +5168,14 @@ int DhAgree(WOLFSSL* ssl, DhKey* dhKey, WOLFSSL_LEAVE("DhAgree", ret); + (void)prime; + (void)primeSz; + return ret; } #endif /* !NO_DH */ #endif /* !NO_CERTS || !NO_PSK */ -#endif /* !WOLFSSL_NO_TLS12 */ - #ifdef HAVE_PK_CALLBACKS int wolfSSL_IsPrivatePkSet(WOLFSSL* ssl) @@ -8179,7 +8195,7 @@ static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, #endif /* NO_CERTS */ /** - * Send the handshake message. This funcion handles fragmenting the message + * Send the handshake message. This function handles fragmenting the message * so that it will fit into the desired MTU or the max fragment size. * @param ssl Connection object * @param input Input starting at the record layer header. This function @@ -24643,7 +24659,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH */ @@ -24661,7 +24679,9 @@ int SendClientKeyExchange(WOLFSSL* ssl) ssl->buffers.serverDH_Pub.buffer, ssl->buffers.serverDH_Pub.length, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH && !NO_PSK */ @@ -27649,7 +27669,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* !WOLFSSL_NO_TLS12 */ - /* Make sure server cert/key are valid for this suite, true on success */ + /* Make sure server cert/key are valid for this suite, true on success + * Returns 1 for valid server suite or 0 if not found + * For asynchronous this can return WC_PENDING_E + */ static int VerifyServerSuite(WOLFSSL* ssl, word16 idx) { int haveRSA = !ssl->options.haveStaticECC; @@ -27772,13 +27795,20 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.side == WOLFSSL_SERVER_END) { #ifdef HAVE_SUPPORTED_CURVES + int doHelloRetry = 0; /* Try to establish a key share. */ - int ret = TLSX_KeyShare_Establish(ssl); - if (ret == KEY_SHARE_ERROR) + int ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry); + if (doHelloRetry) { ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - else if (ret != 0) - return 0; - #endif + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (!doHelloRetry && ret != 0) { + return 0; /* not found */ + } + #endif /* HAVE_SUPPORTED_CURVES */ } else if (first == TLS13_BYTE || (first == ECC_BYTE && (second == TLS_SHA256_SHA256 || second == TLS_SHA384_SHA384))) { @@ -27786,7 +27816,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, * version. */ return 0; } -#endif +#endif /* WOLFSSL_TLS13 */ return 1; } @@ -27798,17 +27828,21 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->suites->suites[i] == peerSuites->suites[j] && ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { - if (VerifyServerSuite(ssl, i)) { - int result; + int ret = VerifyServerSuite(ssl, i); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret) { WOLFSSL_MSG("Verified suite validity"); ssl->options.cipherSuite0 = ssl->suites->suites[i]; ssl->options.cipherSuite = ssl->suites->suites[i+1]; - result = SetCipherSpecs(ssl); - if (result == 0) { - result = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + ret = SetCipherSpecs(ssl); + if (ret == 0) { + ret = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, peerSuites->hashSigAlgoSz); } - return result; + return ret; } else { WOLFSSL_MSG("Could not verify suite validity, continue"); @@ -31209,7 +31243,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, (word16)args->sigSz, ssl->arrays->preMasterSecret, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH */ @@ -31222,7 +31258,9 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], input + args->idx, (word16)args->sigSz, ssl->arrays->preMasterSecret + OPAQUE16_LEN, - &ssl->arrays->preMasterSz); + &ssl->arrays->preMasterSz, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); break; } #endif /* !NO_DH && !NO_PSK */ diff --git a/src/sniffer.c b/src/sniffer.c index c5bfb7640..1b77ae962 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -2280,7 +2280,7 @@ static int SetupKeys(const byte* input, int* sslBytes, SnifferSession* session, /* Derive secret from private key and peer's public key */ do { #ifdef WOLFSSL_ASYNC_CRYPT - ret = wc_AsyncWait(ret, &dhPriv.asyncDev, + ret = wc_AsyncWait(ret, &dhKey.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); #endif if (ret >= 0) { diff --git a/src/ssl.c b/src/ssl.c index 855514dd2..ad8c9797c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -548,7 +548,6 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) WOLFSSL* ssl = NULL; int ret = 0; - (void)ret; WOLFSSL_ENTER("SSL_new"); if (ctx == NULL) @@ -562,6 +561,8 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) } WOLFSSL_LEAVE("SSL_new", ret); + (void)ret; + return ssl; } @@ -52972,10 +52973,10 @@ int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, } str_len++; if (flags & ASN1_STRFLGS_DUMP_DER){ - hex_tmp[0] = hex_char[str->type >> 4]; - hex_tmp[1] = hex_char[str->type & 0xf]; - hex_tmp[2] = hex_char[str->length >> 4]; - hex_tmp[3] = hex_char[str->length & 0xf]; + hex_tmp[0] = hex_char[(str->type & 0xf0) >> 4]; + hex_tmp[1] = hex_char[(str->type & 0x0f)]; + hex_tmp[2] = hex_char[(str->length & 0xf0) >> 4]; + hex_tmp[3] = hex_char[(str->length & 0x0f)]; if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){ goto err_exit; } @@ -54625,8 +54626,10 @@ error: XFREE(section, NULL, DYNAMIC_TYPE_PKCS7); if (canonSection != NULL) XFREE(canonSection, NULL, DYNAMIC_TYPE_PKCS7); - wolfSSL_BIO_free(*bcont); - *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */ + if (bcont) { + wolfSSL_BIO_free(*bcont); + *bcont = NULL; /* reset 'bcount' pointer to NULL on failure */ + } return NULL; } diff --git a/src/tls.c b/src/tls.c index dc39e5b46..15c762b9e 100644 --- a/src/tls.c +++ b/src/tls.c @@ -6667,18 +6667,11 @@ static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, */ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; -#ifndef NO_DH - byte* keyData; - void* key = NULL; - word32 keySz; - word32 dataSz; - const DhParams* params; -#ifdef WOLFSSL_SMALL_STACK - DhKey* dhKey = NULL; -#else - DhKey dhKey[1]; -#endif + int ret = 0; +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + word32 keySz; + const DhParams* params = NULL; + DhKey* dhKey = (DhKey*)kse->key; /* TODO: [TLS13] The key size should come from wolfcrypt. */ /* Pick the parameters from the named group. */ @@ -6714,98 +6707,116 @@ static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) break; #endif default: - return BAD_FUNC_ARG; + break; } -#ifdef WOLFSSL_SMALL_STACK - dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); - if (dhKey == NULL) - return MEMORY_E; -#endif + if (params == NULL) + return BAD_FUNC_ARG; - ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - /* Allocate space for the public key */ - dataSz = params->p_len; - keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - ret = MEMORY_E; - goto end; - } - /* Allocate space for the private key */ - key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - ret = MEMORY_E; - goto end; - } - - /* Set key */ - ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, - params->g_len); - if (ret != 0) - goto end; - -#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*)key, &keySz, keyData, &dataSz); - } - } - else -#endif - { - /* Generate a new key pair */ - ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData, - &dataSz); - #ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); - } - #endif - } - if (ret != 0) - goto end; - - if (params->p_len != dataSz) { - /* Zero pad the front of the public key to match prime "p" size */ - XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); - XMEMSET(keyData, 0, params->p_len - dataSz); - } - - kse->pubKey = keyData; kse->pubKeyLen = params->p_len; - kse->key = key; kse->keyLen = keySz; -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public DH Key"); - WOLFSSL_BUFFER(keyData, params->p_len); -#endif + /* Trigger Key Generation */ + if (kse->pubKey == NULL || kse->privKey == NULL) { + if (kse->key == NULL) { + kse->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, + DYNAMIC_TYPE_DH); + if (kse->key == NULL) + return MEMORY_E; -end: + /* Setup Key */ + ret = wc_InitDhKey_ex((DhKey*)kse->key, ssl->heap, ssl->devId); + if (ret == 0) { + dhKey = (DhKey*)kse->key; + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, + params->g_len); + } + } - wc_FreeDhKey(dhKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); -#endif + /* Allocate space for the private and public key */ + if (ret == 0 && kse->pubKey == NULL) { + kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (kse->pubKey == NULL) + ret = MEMORY_E; + } + + if (ret == 0 && kse->privKey == NULL) { + kse->privKey = (byte*)XMALLOC(kse->keyLen, ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->privKey == NULL) + ret = MEMORY_E; + } + + 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 */ + ); + } + } + else + #endif + { + /* Generate a new key pair */ + /* For async this is called once and when event is done, the + * provided buffers will be populated. + * Final processing is zero pad below. */ + ret = DhGenKeyPair(ssl, dhKey, + (byte*)kse->privKey, &kse->keyLen, /* private */ + kse->pubKey, &kse->pubKeyLen /* public */ + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + } + } + + if (ret == 0) { + if (params->p_len != kse->pubKeyLen) { + /* Zero pad the front of the public key to match prime "p" size */ + XMEMMOVE(kse->pubKey + params->p_len - kse->pubKeyLen, kse->pubKey, + kse->pubKeyLen); + XMEMSET(kse->pubKey, 0, params->p_len - kse->pubKeyLen); + } + + kse->pubKeyLen = params->p_len; + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + #endif + } + + /* Always release the DH key to free up memory. + * The DhKey will be setup again in TLSX_KeyShare_ProcessDh */ + if (dhKey != NULL) + wc_FreeDhKey(dhKey); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_DH); + kse->key = NULL; + } if (ret != 0) { - /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (key != NULL) - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + /* Cleanup on error, otherwise data owned by key share entry */ + if (kse->privKey != NULL) { + XFREE(kse->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->privKey = NULL; + } + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } } #else (void)ssl; @@ -6826,60 +6837,66 @@ end: */ static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_CURVE25519 - byte* keyData = NULL; - word32 dataSize = CURVE25519_KEYSIZE; - curve25519_key* key; + curve25519_key* key = (curve25519_key*)kse->key; - /* Allocate an ECC key to hold private key. */ - key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, + if (kse->key == NULL) { + /* Allocate a Curve25519 key to hold private key. */ + kse->key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; + if (kse->key == NULL) { + WOLFSSL_MSG("GenX25519Key memory error"); + return MEMORY_E; + } + + /* Make an Curve25519 key. */ + ret = wc_curve25519_init((curve25519_key*)kse->key); + if (ret == 0) { + key = (curve25519_key*)kse->key; + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + } } - /* Make an ECC key. */ - ret = wc_curve25519_init(key); - if (ret != 0) - goto end; - ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); - if (ret != 0) - goto end; - - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap, + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key. */ + kse->pubKey = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + if (kse->pubKey == NULL) { + WOLFSSL_MSG("GenX25519Key pub memory error"); + ret = MEMORY_E; + } } - /* Export public key. */ - if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + if (ret == 0) { + /* Export Curve25519 public key. */ + kse->pubKeyLen = CURVE25519_KEYSIZE; + if (wc_curve25519_export_public_ex(key, kse->pubKey, &kse->pubKeyLen, EC25519_LITTLE_ENDIAN) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + ret = ECC_EXPORT_ERROR; + } + kse->pubKeyLen = CURVE25519_KEYSIZE; /* always CURVE25519_KEYSIZE */ } - kse->pubKey = keyData; - kse->pubKeyLen = CURVE25519_KEYSIZE; - kse->key = key; - #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public Curve25519 Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public Curve25519 Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - wc_curve25519_free(key); - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (key != NULL) + wc_curve25519_free(key); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -6900,60 +6917,66 @@ end: */ static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_CURVE448 - byte* keyData = NULL; - word32 dataSize = CURVE448_KEY_SIZE; - curve448_key* key; + curve448_key* key = (curve448_key*)kse->key; - /* Allocate an ECC key to hold private key. */ - key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + if (kse->key == NULL) { + /* Allocate a Curve448 key to hold private key. */ + kse->key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (key == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; + if (kse->key == NULL) { + WOLFSSL_MSG("GenX448Key memory error"); + return MEMORY_E; + } + + /* Make an Curve448 key. */ + ret = wc_curve448_init((curve448_key*)kse->key); + if (ret == 0) { + key = (curve448_key*)kse->key; + ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); + } } - /* Make an ECC key. */ - ret = wc_curve448_init(key); - if (ret != 0) - goto end; - ret = wc_curve448_make_key(ssl->rng, CURVE448_KEY_SIZE, key); - if (ret != 0) - goto end; - - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap, + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key. */ + kse->pubKey = (byte*)XMALLOC(CURVE448_KEY_SIZE, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + if (kse->pubKey == NULL) { + WOLFSSL_MSG("GenX448Key pub memory error"); + ret = MEMORY_E; + } } - /* Export public key. */ - if (wc_curve448_export_public_ex(key, keyData, &dataSize, + if (ret == 0) { + /* Export Curve448 public key. */ + kse->pubKeyLen = CURVE448_KEY_SIZE; + if (wc_curve448_export_public_ex(key, kse->pubKey, &kse->pubKeyLen, EC448_LITTLE_ENDIAN) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + ret = ECC_EXPORT_ERROR; + } + kse->pubKeyLen = CURVE448_KEY_SIZE; /* always CURVE448_KEY_SIZE */ } - - kse->pubKey = keyData; - kse->pubKeyLen = CURVE448_KEY_SIZE; - kse->key = key; - + #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public Curve448 Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public Curve448 Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { /* Data owned by key share entry otherwise. */ - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - wc_curve448_free(key); - XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (key != NULL) + wc_curve448_free(key); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -6974,14 +6997,11 @@ end: */ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) { - int ret; + int ret = 0; #ifdef HAVE_ECC - byte* keyData = NULL; - word32 dataSize; - byte* keyPtr = NULL; - word32 keySize; - ecc_key* eccKey; - word16 curveId; + word32 keySize = 0; + word16 curveId = ECC_CURVE_INVALID; + ecc_key* eccKey = (ecc_key*)kse->key; /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ /* Translate named group to a curve id. */ @@ -6991,7 +7011,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP256R1: curveId = ECC_SECP256R1; keySize = 32; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ #endif @@ -7000,7 +7019,6 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP384R1: curveId = ECC_SECP384R1; keySize = 48; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ #endif @@ -7009,86 +7027,95 @@ static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) case WOLFSSL_ECC_SECP521R1: curveId = ECC_SECP521R1; keySize = 66; - dataSize = keySize * 2 + 1; break; #endif /* !NO_ECC_SECP */ - #endif - #if defined(HAVE_X448) && ECC_MIN_KEY_SZ <= 448 - case WOLFSSL_ECC_X448: - curveId = ECC_X448; - dataSize = keySize = 56; - break; #endif default: return BAD_FUNC_ARG; } - /* Allocate an ECC key to hold private key. */ - keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, + if (kse->key == NULL) { + kse->keyLen = keySize; + kse->pubKeyLen = keySize * 2 + 1; + + /* Allocate an ECC key to hold private key. */ + kse->key = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (keyPtr == NULL) { - WOLFSSL_MSG("EccTempKey Memory error"); - return MEMORY_E; - } - eccKey = (ecc_key*)keyPtr; - - /* Make an ECC key. */ - ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); - if (ret != 0) - goto end; - -#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 -#endif - { - /* Generate ephemeral ECC key */ - ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); - #ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (kse->key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; } - #endif - } - if (ret != 0) - goto end; - /* Allocate space for the public key. */ - keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - if (keyData == NULL) { - WOLFSSL_MSG("Key data Memory error"); - ret = MEMORY_E; - goto end; + /* Make an ECC key */ + ret = wc_ecc_init_ex((ecc_key*)kse->key, ssl->heap, ssl->devId); + if (ret == 0) { + 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 + #endif + { + /* set curve info for EccMakeKey "peer" info */ + ret = wc_ecc_set_curve(eccKey, kse->keyLen, curveId); + if (ret == 0) { + /* Generate ephemeral ECC key */ + /* For async this is called once and when event is done, the + * provided buffers in key be populated. + * Final processing is x963 key export below. */ + ret = EccMakeKey(ssl, eccKey, eccKey); + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + } + } } - /* Export public key. */ - if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { - ret = ECC_EXPORT_ERROR; - goto end; + if (ret == 0 && kse->pubKey == NULL) { + /* Allocate space for the public key */ + kse->pubKey = (byte*)XMALLOC(kse->pubKeyLen, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (kse->pubKey == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + } } - kse->pubKey = keyData; - kse->pubKeyLen = dataSize; - kse->key = keyPtr; + if (ret == 0) { + XMEMSET(kse->pubKey, 0, kse->pubKeyLen); + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, kse->pubKey, &kse->pubKeyLen) != 0) { + ret = ECC_EXPORT_ERROR; + } + } #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Public ECC Key"); - WOLFSSL_BUFFER(keyData, dataSize); + if (ret == 0) { + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(kse->pubKey, kse->pubKeyLen); + } #endif -end: if (ret != 0) { - /* Data owned by key share entry otherwise. */ - if (keyPtr != NULL) - XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); - if (keyData != NULL) - XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + /* Cleanup on error, otherwise data owned by key share entry */ + if (kse->pubKey != NULL) { + XFREE(kse->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + kse->pubKey = NULL; + } + if (eccKey != NULL) + wc_ecc_free(eccKey); + if (kse->key != NULL) { + XFREE(kse->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + kse->key = NULL; + } } #else (void)ssl; @@ -7107,14 +7134,20 @@ end: */ static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) { + int ret; /* Named FFHE groups have a bit set to identify them. */ if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) - return TLSX_KeyShare_GenDhKey(ssl, kse); - if (kse->group == WOLFSSL_ECC_X25519) - return TLSX_KeyShare_GenX25519Key(ssl, kse); - if (kse->group == WOLFSSL_ECC_X448) - return TLSX_KeyShare_GenX448Key(ssl, kse); - return TLSX_KeyShare_GenEccKey(ssl, kse); + ret = TLSX_KeyShare_GenDhKey(ssl, kse); + else if (kse->group == WOLFSSL_ECC_X25519) + ret = TLSX_KeyShare_GenX25519Key(ssl, kse); + else if (kse->group == WOLFSSL_ECC_X448) + ret = TLSX_KeyShare_GenX448Key(ssl, kse); + else + ret = TLSX_KeyShare_GenEccKey(ssl, kse); +#ifdef WOLFSSL_ASYNC_CRYPT + kse->lastRet = ret; +#endif + return ret; } /* Free the key share dynamic data. @@ -7128,25 +7161,30 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) while ((current = list) != NULL) { list = current->next; - if ((current->group & NAMED_DH_MASK) == 0) { - if (current->group == WOLFSSL_ECC_X25519) { -#ifdef HAVE_CURVE25519 - wc_curve25519_free((curve25519_key*)current->key); + if ((current->group & NAMED_DH_MASK) == NAMED_DH_MASK) { +#ifndef NO_DH + wc_FreeDhKey((DhKey*)current->key); #endif - } - else if (current->group == WOLFSSL_ECC_X448) { -#ifdef HAVE_CURVE448 - wc_curve448_free((curve448_key*)current->key); -#endif - } - else { -#ifdef HAVE_ECC - wc_ecc_free((ecc_key*)(current->key)); -#endif - } } - if (current->key != NULL) - XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + else if (current->group == WOLFSSL_ECC_X25519) { +#ifdef HAVE_CURVE25519 + wc_curve25519_free((curve25519_key*)current->key); +#endif + } + else if (current->group == WOLFSSL_ECC_X448) { +#ifdef HAVE_CURVE448 + wc_curve448_free((curve448_key*)current->key); +#endif + } + else { +#ifdef HAVE_ECC + wc_ecc_free((ecc_key*)current->key); +#endif + } + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + #if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + XFREE(current->privKey, heap, DYNAMIC_TYPE_PRIVATE_KEY); + #endif XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current, heap, DYNAMIC_TYPE_TLSX); @@ -7177,7 +7215,7 @@ static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) while ((current = list) != NULL) { list = current->next; - if (!isRequest && current->key == NULL) + if (!isRequest && current->pubKey == NULL) continue; len += (word16)(KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen); @@ -7214,7 +7252,7 @@ static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, while ((current = list) != NULL) { list = current->next; - if (!isRequest && current->key == NULL) + if (!isRequest && current->pubKey == NULL) continue; c16toa(current->group, &output[i]); @@ -7239,14 +7277,10 @@ static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, */ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) { -#ifndef NO_DH - int ret; - const DhParams* params; -#ifdef WOLFSSL_SMALL_STACK - DhKey* dhKey = NULL; -#else - DhKey dhKey[1]; -#endif + int ret = 0; +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) + const DhParams* params = NULL; + DhKey* dhKey = (DhKey*)keyShareEntry->key; switch (keyShareEntry->group) { #ifdef HAVE_FFDHE_2048 @@ -7275,91 +7309,88 @@ static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) break; #endif default: - return PEER_KEY_ERROR; + break; } -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Peer DH Key"); - WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); -#endif - -#ifdef WOLFSSL_SMALL_STACK - dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); - if (dhKey == NULL) - return MEMORY_E; -#endif - - ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); - if (ret != 0) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - /* Set key */ - ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, - params->g_len); - if (ret != 0) { - wc_FreeDhKey(dhKey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif - return ret; - } - - ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen); - if (ret != 0) { - wc_FreeDhKey(dhKey); - #ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); - #endif + if (params == NULL) return PEER_KEY_ERROR; + + /* if DhKey is not setup, do it now */ + if (keyShareEntry->key == NULL) { + keyShareEntry->key = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, + DYNAMIC_TYPE_DH); + if (keyShareEntry->key == NULL) + return MEMORY_E; + + /* Setup Key */ + ret = wc_InitDhKey_ex((DhKey*)keyShareEntry->key, ssl->heap, ssl->devId); + if (ret == 0) { + dhKey = (DhKey*)keyShareEntry->key; + ret = wc_DhSetKey(dhKey, params->p, params->p_len, params->g, + params->g_len); + } } - /* Derive secret from private key and peer's public key. */ - ret = wc_DhAgree(dhKey, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, - (const byte*)keyShareEntry->key, keyShareEntry->keyLen, - keyShareEntry->ke, keyShareEntry->keLen); -#ifdef WOLFSSL_ASYNC_CRYPT - /* TODO: Make this function non-blocking */ - if (ret == WC_PENDING_E) { - ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret == 0 + #ifdef WOLFSSL_ASYNC_CRYPT + && keyShareEntry->lastRet == 0 /* don't enter here if WC_PENDING_E */ + #endif + ) { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); + #endif + + ssl->options.dhKeySz = (word16)params->p_len; + + /* Derive secret from private key and peer's public key. */ + ret = DhAgree(ssl, dhKey, + (const byte*)keyShareEntry->privKey, keyShareEntry->keyLen, /* our private */ + keyShareEntry->ke, keyShareEntry->keLen, /* peer's public key */ + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, /* secret */ + NULL, 0 + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } + #endif } -#endif + /* RFC 8446 Section 7.4.1: * ... left-padded with zeros up to the size of the prime. ... */ - if (params->p_len > ssl->arrays->preMasterSz) { - word32 diff = params->p_len - ssl->arrays->preMasterSz; + if (ret == 0 && (word32)ssl->options.dhKeySz > ssl->arrays->preMasterSz) { + word32 diff = (word32)ssl->options.dhKeySz - ssl->arrays->preMasterSz; XMEMMOVE(ssl->arrays->preMasterSecret + diff, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); XMEMSET(ssl->arrays->preMasterSecret, 0, diff); - ssl->arrays->preMasterSz = params->p_len; + ssl->arrays->preMasterSz = ssl->options.dhKeySz; } - ssl->options.dhKeySz = (word16)params->p_len; - - wc_FreeDhKey(dhKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); -#endif - if (keyShareEntry->key != NULL) { - XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + /* done with key share, release resources */ + if (dhKey) + wc_FreeDhKey(dhKey); + if (keyShareEntry->key) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_DH); keyShareEntry->key = NULL; } - XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); - keyShareEntry->pubKey = NULL; + if (keyShareEntry->privKey != NULL) { + XFREE(keyShareEntry->privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->privKey = NULL; + } + if (keyShareEntry->pubKey != NULL) { + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->pubKey = NULL; + } XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); keyShareEntry->ke = NULL; - - return ret; #else (void)ssl; (void)keyShareEntry; - return PEER_KEY_ERROR; + ret = PEER_KEY_ERROR; #endif + return ret; } /* Process the X25519 key share extension on the client side. @@ -7523,24 +7554,10 @@ static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) */ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) { - int ret; - + int ret = 0; #ifdef HAVE_ECC - int curveId; - ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; - - if (ssl->peerEccKey != NULL) - wc_ecc_free(ssl->peerEccKey); - - ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, - DYNAMIC_TYPE_ECC); - if (ssl->peerEccKey == NULL) { - WOLFSSL_MSG("PeerEccKey Memory error"); - return MEMORY_ERROR; - } - ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); - if (ret != 0) - return ret; + int curveId = ECC_CURVE_INVALID; + ecc_key* eccKey = (ecc_key*)keyShareEntry->key; /* find supported curve */ switch (keyShareEntry->group) { @@ -7574,55 +7591,73 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) /* unsupported curve */ return ECC_PEERKEY_ERROR; } - -#ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Peer ECC Key"); - WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (keyShareEntry->lastRet == 0) /* don't enter here if WC_PENDING_E */ #endif - - /* Point is validated by import function. */ - if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, - ssl->peerEccKey, curveId) != 0) { - return ECC_PEERKEY_ERROR; - } - ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; - -#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \ - (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION != 2))) && \ - !defined(HAVE_SELFTEST) - ret = wc_ecc_set_rng(keyShareKey, ssl->rng); - if (ret != 0) { - return ret; - } -#endif - - do { - #if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); #endif - if (ret >= 0) - ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); - } while (ret == WC_PENDING_E); -#if 0 - /* TODO: Switch to support async here and use: */ - ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, - keyShareEntry->ke, &keyShareEntry->keLen, - ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, - ssl->options.side - ); -#endif + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + } - wc_ecc_free(ssl->peerEccKey); - XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); - ssl->peerEccKey = NULL; - wc_ecc_free((ecc_key*)(keyShareEntry->key)); - if (keyShareEntry->key != NULL) { - XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + ret = MEMORY_ERROR; + } + + if (ret == 0) { + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + } + + /* Point is validated by import function. */ + if (ret == 0) { + ret = wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId); + if (ret != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { + ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; + } + } + + if (ret == 0 && eccKey == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0) { + ret = EccSharedSecret(ssl, eccKey, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + } + + /* done with key share, release resources */ + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + } + if (keyShareEntry->key) { + wc_ecc_free((ecc_key*)keyShareEntry->key); + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_ECC); keyShareEntry->key = NULL; } - + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; #else (void)ssl; (void)keyShareEntry; @@ -7657,8 +7692,13 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("KE Secret"); - WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + if (ret == 0) { + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + keyShareEntry->lastRet = ret; #endif return ret; @@ -7848,8 +7888,13 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, return BUFFER_ERROR; /* Not in list sent if there isn't a private key. */ - if (keyShareEntry == NULL || keyShareEntry->key == NULL) + if (keyShareEntry == NULL || (keyShareEntry->key == NULL + #ifndef NO_DH + && keyShareEntry->privKey == NULL + #endif + )) { return BAD_KEY_SHARE_DATA; + } /* Process the entry to calculate the secret. */ ret = TLSX_KeyShare_Process(ssl, keyShareEntry); @@ -7863,18 +7908,24 @@ static int TLSX_KeyShare_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* The data is the named group the server wants to use. */ ato16(input, &group); - /* Check the selected group was supported by ClientHello extensions. */ - if (!TLSX_SupportedGroups_Find(ssl, group)) - return BAD_KEY_SHARE_DATA; + #ifdef WOLFSSL_ASYNC_CRYPT + /* only perform find and clear TLSX if not returning from async */ + if (ssl->error != WC_PENDING_E) + #endif + { + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; - /* Check if the group was sent. */ - if (TLSX_KeyShare_Find(ssl, group)) - return BAD_KEY_SHARE_DATA; + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; - /* Clear out unusable key shares. */ - ret = TLSX_KeyShare_Empty(ssl); - if (ret != 0) - return ret; + /* Clear out unusable key shares. */ + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + } /* Try to use the server's group. */ ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); @@ -8181,13 +8232,20 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) /* Delete the old key share data list. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension != NULL) { - TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); - extension->data = NULL; + KeyShareEntry* kse = (KeyShareEntry*)extension->data; + #ifdef WOLFSSL_ASYNC_CRYPT + /* for async don't free, call `TLSX_KeyShare_Use` again */ + if (kse && kse->lastRet != WC_PENDING_E) + #endif + { + TLSX_KeyShare_FreeAll(kse, ssl->heap); + extension->data = NULL; + } } /* Add in the chosen group. */ ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); - if (ret != 0) + if (ret != 0 && ret != WC_PENDING_E) return ret; /* Set extension to be in response. */ @@ -8205,9 +8263,10 @@ static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) /* Ensure there is a key pair that can be used for key exchange. * * ssl The SSL/TLS object. + * doHelloRetry If set to non-zero will do hello_retry * returns 0 on success and other values indicate failure. */ -int TLSX_KeyShare_Establish(WOLFSSL *ssl) +int TLSX_KeyShare_Establish(WOLFSSL *ssl, int* doHelloRetry) { int ret; TLSX* extension; @@ -8223,8 +8282,19 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (extension != NULL) list = (KeyShareEntry*)extension->data; - if (extension && extension->resp == 1) - return 0; + if (extension && extension->resp == 1) { + ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + /* in async case make sure key generation is finalized */ + serverKSE = (KeyShareEntry*)extension->data; + if (serverKSE->lastRet == WC_PENDING_E) { + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) + *doHelloRetry = 1; + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + } + #endif + return ret; + } /* Use server's preference order. */ for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { @@ -8261,11 +8331,9 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) /* No supported group found - send HelloRetryRequest. */ if (clientKSE == NULL) { - ret = TLSX_KeyShare_SetSupported(ssl); - /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ - if (ret == 0) - return KEY_SHARE_ERROR; - return ret; + /* Set KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + *doHelloRetry = 1; + return TLSX_KeyShare_SetSupported(ssl); } list = NULL; @@ -8276,16 +8344,27 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) if (clientKSE->key == NULL) { ret = TLSX_KeyShare_GenKey(ssl, serverKSE); - if (ret != 0) + /* for async do setup of serverKSE below, but return WC_PENDING_E */ + if (ret != 0 + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { return ret; + } } else { + /* transfer buffers to serverKSE */ serverKSE->key = clientKSE->key; + clientKSE->key = NULL; serverKSE->keyLen = clientKSE->keyLen; serverKSE->pubKey = clientKSE->pubKey; - serverKSE->pubKeyLen = clientKSE->pubKeyLen; - clientKSE->key = NULL; clientKSE->pubKey = NULL; + serverKSE->pubKeyLen = clientKSE->pubKeyLen; + #ifndef NO_DH + serverKSE->privKey = clientKSE->privKey; + clientKSE->privKey = NULL; + #endif } serverKSE->ke = clientKSE->ke; serverKSE->keLen = clientKSE->keLen; @@ -8297,7 +8376,7 @@ int TLSX_KeyShare_Establish(WOLFSSL *ssl) extension->resp = 1; - return 0; + return ret; } /* Derive the shared secret of the key exchange. @@ -8311,6 +8390,14 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) TLSX* extension; KeyShareEntry* list = NULL; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, NULL); + /* Check for error */ + if (ret != WC_NOT_PENDING_E && ret < 0) { + return ret; + } +#endif + /* Find the KeyShare extension if it exists. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); if (extension != NULL) @@ -8321,8 +8408,6 @@ int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) /* Calculate secret. */ ret = TLSX_KeyShare_Process(ssl, list); - if (ret != 0) - return ret; return ret; } @@ -10163,8 +10248,13 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) int usingPSK = 0; #endif +#if defined(HAVE_SUPPORTED_CURVES) || defined(HAVE_QSH) + TLSX* extension = NULL; +#endif +#if defined(HAVE_SUPPORTED_CURVES) + word16 namedGroup = 0; +#endif #ifdef HAVE_QSH - TLSX* extension; QSHScheme* qsh; QSHScheme* next; @@ -10318,9 +10408,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #endif #if defined(HAVE_SUPPORTED_CURVES) - if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { - word16 namedGroup; - + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) if (ssl->options.resuming && ssl->session.namedGroup != 0) namedGroup = ssl->session.namedGroup; @@ -10348,16 +10437,22 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } } } - else { /* Choose the most preferred group. */ namedGroup = preferredGroup[0]; } + } + else { + KeyShareEntry* kse = (KeyShareEntry*)extension->data; + if (kse) + namedGroup = kse->group; + } + if (namedGroup > 0) { ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); if (ret != 0) return ret; } - #endif + #endif /* HAVE_SUPPORTED_CURVES */ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); @@ -10532,6 +10627,8 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) (void)public_key; (void)public_key_len; (void)ssl; + (void)extension; + (void)namedGroup; return ret; } diff --git a/src/tls13.c b/src/tls13.c index 62d113361..357f2ed0e 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -2192,7 +2192,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, - WC_ASYNC_FLAG_CALL_AGAIN); + WC_ASYNC_FLAG_NONE); if (ret != 0) break; #endif @@ -2215,7 +2215,7 @@ int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, - WC_ASYNC_FLAG_CALL_AGAIN); + WC_ASYNC_FLAG_NONE); if (ret != 0) break; #endif @@ -2655,8 +2655,10 @@ int RestartHandshakeHash(WOLFSSL* ssl) AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); +#ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Restart Hash"); WOLFSSL_BUFFER(hash, hashSz); +#endif #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) if (ssl->options.sendCookie) { @@ -3030,13 +3032,24 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) * ssl The SSL/TLS object. * returns 0 on success and otherwise failure. */ + +typedef struct Sch13Args { + byte* output; + word32 idx; + int sendSz; + word16 length; +} Sch13Args; + int SendTls13ClientHello(WOLFSSL* ssl) { - byte* output; - word16 length; - word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; - int sendSz; - int ret; + int ret; +#ifdef WOLFSSL_ASYNC_CRYPT + Sch13Args* args = (Sch13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Sch13Args args[1]; +#endif WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); WOLFSSL_ENTER("SendTls13ClientHello"); @@ -3065,19 +3078,55 @@ int SendTls13ClientHello(WOLFSSL* ssl) return SUITES_ERROR; } - /* Version | Random | Session Id | Cipher Suites | Compression */ - length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + - SUITE_LEN + COMP_LEN + ENUM_LEN; - #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) - length += ID_LEN; - #else - if (ssl->session.sessionIDSz > 0) - length += ssl->session.sessionIDSz; - #endif +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Sch13Args)); + } + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + /* Version | Random | Session Id | Cipher Suites | Compression */ + args->length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; +#if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + args->length += ID_LEN; +#else + if (ssl->session.sessionIDSz > 0) + args->length += ssl->session.sessionIDSz; +#endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { /* Auto populate extensions supported unless user defined. */ if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) return ret; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { #ifdef WOLFSSL_EARLY_DATA #ifndef NO_PSK if (!ssl->options.resuming && @@ -3097,65 +3146,67 @@ int SendTls13ClientHello(WOLFSSL* ssl) } #endif /* Include length of TLS extensions. */ - ret = TLSX_GetRequestSize(ssl, client_hello, &length); + ret = TLSX_GetRequestSize(ssl, client_hello, &args->length); if (ret != 0) return ret; /* Total message size. */ - sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; /* Check buffers are big enough and grow if needed. */ - if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) return ret; /* Get position in output buffer to write new message to. */ - output = ssl->buffers.outputBuffer.buffer + - ssl->buffers.outputBuffer.length; + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; /* Put the record and handshake headers on. */ - AddTls13Headers(output, length, client_hello, ssl); + AddTls13Headers(args->output, args->length, client_hello, ssl); /* Protocol version - negotiation now in extension: supported_versions. */ - output[idx++] = SSLv3_MAJOR; - output[idx++] = TLSv1_2_MINOR; + args->output[args->idx++] = SSLv3_MAJOR; + args->output[args->idx++] = TLSv1_2_MINOR; /* Keep for downgrade. */ ssl->chVersion = ssl->version; /* Client Random */ if (ssl->options.connectState == CONNECT_BEGIN) { - ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + ret = wc_RNG_GenerateBlock(ssl->rng, args->output + args->idx, RAN_LEN); if (ret != 0) return ret; /* Store random for possible second ClientHello. */ - XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + XMEMCPY(ssl->arrays->clientRandom, args->output + args->idx, RAN_LEN); } else - XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); - idx += RAN_LEN; + XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN); + args->idx += RAN_LEN; if (ssl->session.sessionIDSz > 0) { /* Session resumption for old versions of protocol. */ - output[idx++] = ID_LEN; - XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); - idx += ID_LEN; + args->output[args->idx++] = ID_LEN; + XMEMCPY(args->output + args->idx, ssl->session.sessionID, + ssl->session.sessionIDSz); + args->idx += ID_LEN; } else { #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT - output[idx++] = ID_LEN; - XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN); - idx += ID_LEN; + args->output[args->idx++] = ID_LEN; + XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, ID_LEN); + args->idx += ID_LEN; #else /* TLS v1.3 does not use session id - 0 length. */ - output[idx++] = 0; + args->output[args->idx++] = 0; #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ } /* Cipher suites */ - c16toa(ssl->suites->suiteSz, output + idx); - idx += OPAQUE16_LEN; - XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); - idx += ssl->suites->suiteSz; + c16toa(ssl->suites->suiteSz, args->output + args->idx); + args->idx += OPAQUE16_LEN; + XMEMCPY(args->output + args->idx, &ssl->suites->suites, + ssl->suites->suiteSz); + args->idx += ssl->suites->suiteSz; #ifdef WOLFSSL_DEBUG_TLS { int ii; @@ -3168,25 +3219,26 @@ int SendTls13ClientHello(WOLFSSL* ssl) #endif /* Compression not supported in TLS v1.3. */ - output[idx++] = COMP_LEN; - output[idx++] = NO_COMPRESSION; + args->output[args->idx++] = COMP_LEN; + args->output[args->idx++] = NO_COMPRESSION; /* Write out extensions for a request. */ - length = 0; - ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length); + args->length = 0; + ret = TLSX_WriteRequest(ssl, args->output + args->idx, client_hello, + &args->length); if (ret != 0) return ret; - idx += length; + args->idx += args->length; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Resumption has a specific set of extensions and binder is calculated * for each identity. */ if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY)) - ret = WritePSKBinders(ssl, output, idx); + ret = WritePSKBinders(ssl, args->output, args->idx); else #endif - ret = HashOutput(ssl, output, idx, 0); + ret = HashOutput(ssl, args->output, args->idx, 0); if (ret != 0) return ret; @@ -3195,18 +3247,23 @@ int SendTls13ClientHello(WOLFSSL* ssl) #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) { - AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + AddPacketInfo(ssl, "ClientHello", handshake, args->output, args->sendSz, WRITE_PROTO, ssl->heap); } #endif - ssl->buffers.outputBuffer.length += sendSz; + ssl->buffers.outputBuffer.length += args->sendSz; #ifdef WOLFSSL_EARLY_DATA_GROUP if (ssl->earlyData == no_early_data) #endif ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ WOLFSSL_LEAVE("SendTls13ClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); @@ -3225,64 +3282,95 @@ int SendTls13ClientHello(WOLFSSL* ssl) * helloSz The length of the current handshake message. * returns 0 on success and otherwise failure. */ + +typedef struct Dsh13Args { + ProtocolVersion pv; + word32 idx; + word32 begin; + const byte* sessId; + word16 totalExtSz; + byte sessIdSz; + byte extMsgType; +} Dsh13Args; + int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz, byte* extMsgType) { - ProtocolVersion pv; - word32 i = *inOutIdx; - word32 begin = i; - int ret; - byte sessIdSz; - const byte* sessId; - byte b; - int foundVersion; - word16 totalExtSz; - byte suite[2]; -#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - TLSX* ext; - PreSharedKey* psk = NULL; + int ret; + byte suite[2]; +#ifdef WOLFSSL_ASYNC_CRYPT + Dsh13Args* args = (Dsh13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dsh13Args args[1]; #endif WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); WOLFSSL_ENTER("DoTls13ServerHello"); - if (ssl->arrays == NULL) + if (ssl == NULL || ssl->arrays == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dsh13Args)); + } + + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + byte b; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); #endif - if (ssl == NULL || ssl->arrays == NULL) - return BAD_FUNC_ARG; - /* Protocol version length check. */ - if (OPAQUE16_LEN > helloSz) + if (helloSz < OPAQUE16_LEN) return BUFFER_ERROR; + args->idx = *inOutIdx; + args->begin = args->idx; + /* Protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - i += OPAQUE16_LEN; + XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN); + args->idx += OPAQUE16_LEN; #ifndef WOLFSSL_NO_TLS12 - if (pv.major == ssl->version.major && pv.minor < TLSv1_2_MINOR && - ssl->options.downgrade) { + if (args->pv.major == ssl->version.major && + args->pv.minor < TLSv1_2_MINOR && + ssl->options.downgrade) + { /* Force client hello version 1.2 to work for static RSA. */ ssl->chVersion.minor = TLSv1_2_MINOR; ssl->version.minor = TLSv1_2_MINOR; return DoServerHello(ssl, input, inOutIdx, helloSz); } #endif - if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR) + if (args->pv.major != ssl->version.major || + args->pv.minor != TLSv1_2_MINOR) { return VERSION_ERROR; + } /* Random and session id length check */ - if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz) + if ((args->idx - args->begin) + RAN_LEN + ENUM_LEN > helloSz) return BUFFER_ERROR; - if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) { + /* Check if hello retry request */ + if (XMEMCMP(input + args->idx, helloRetryRequestRandom, RAN_LEN) == 0) { *extMsgType = hello_retry_request; + /* A HelloRetryRequest comes in as an ServerHello for MiddleBox compat. * Found message to be a HelloRetryRequest. * Don't allow more than one HelloRetryRequest or ServerHello. @@ -3290,31 +3378,29 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (ssl->msgsReceived.got_hello_retry_request == 1) { return DUPLICATE_MSG_E; } - /* Update counts to reflect change of message type. */ - ssl->msgsReceived.got_hello_retry_request++; - ssl->msgsReceived.got_server_hello--; } + args->extMsgType = *extMsgType; /* Server random - keep for debugging. */ - XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); - i += RAN_LEN; + XMEMCPY(ssl->arrays->serverRandom, input + args->idx, RAN_LEN); + args->idx += RAN_LEN; /* Session id */ - sessIdSz = input[i++]; - if ((i - begin) + sessIdSz > helloSz) + args->sessIdSz = input[args->idx++]; + if ((args->idx - args->begin) + args->sessIdSz > helloSz) return BUFFER_ERROR; - sessId = input + i; - i += sessIdSz; + args->sessId = input + args->idx; + args->idx += args->sessIdSz; ssl->options.haveSessionId = 1; /* Ciphersuite and compression check */ - if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + if ((args->idx - args->begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) return BUFFER_ERROR; /* Set the cipher suite from the message. */ - ssl->options.cipherSuite0 = input[i++]; - ssl->options.cipherSuite = input[i++]; + ssl->options.cipherSuite0 = input[args->idx++]; + ssl->options.cipherSuite = input[args->idx++]; #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("Chosen cipher suite:"); WOLFSSL_MSG(GetCipherNameInternal(ssl->options.cipherSuite0, @@ -3322,13 +3408,13 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* Compression */ - b = input[i++]; + b = input[args->idx++]; if (b != 0) { WOLFSSL_MSG("Must be no compression types in list"); return INVALID_PARAMETER; } - if ((i - begin) + OPAQUE16_LEN > helloSz) { + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) { if (!ssl->options.downgrade) return BUFFER_ERROR; #ifndef WOLFSSL_NO_TLS12 @@ -3336,18 +3422,21 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif ssl->options.haveEMS = 0; } - if ((i - begin) < helloSz) { + + if ((args->idx - args->begin) < helloSz) { + int foundVersion; + /* Get extension length and length check. */ - if ((i - begin) + OPAQUE16_LEN > helloSz) + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) return BUFFER_ERROR; - ato16(&input[i], &totalExtSz); - i += OPAQUE16_LEN; - if ((i - begin) + totalExtSz > helloSz) + ato16(&input[args->idx], &args->totalExtSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + args->totalExtSz > helloSz) return BUFFER_ERROR; /* Need to negotiate version first. */ - if ((ret = TLSX_ParseVersion(ssl, input + i, totalExtSz, *extMsgType, - &foundVersion))) { + if ((ret = TLSX_ParseVersion(ssl, input + args->idx, + args->totalExtSz, *extMsgType, &foundVersion))) { return ret; } if (!foundVersion) { @@ -3357,23 +3446,50 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return VERSION_ERROR; } - if (pv.minor < ssl->options.minDowngrade) + if (args->pv.minor < ssl->options.minDowngrade) return VERSION_ERROR; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; } - - if (foundVersion && ssl->options.downgrade && (pv.minor < ssl->options.minDowngrade)) { + if (foundVersion && ssl->options.downgrade && + (args->pv.minor < ssl->options.minDowngrade)) { return VERSION_ERROR; } - - /* Parse and handle extensions. */ - ret = TLSX_Parse(ssl, input + i, totalExtSz, *extMsgType, NULL); - if (ret != 0) - return ret; - - i += totalExtSz; } - *inOutIdx = i; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { + /* restore message type */ + *extMsgType = args->extMsgType; + + if (args->totalExtSz > 0) { + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, input + args->idx, args->totalExtSz, + *extMsgType, NULL); + if (ret != 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_server_hello--; + } + #endif + return ret; + } + args->idx += args->totalExtSz; + } + + if (*extMsgType == hello_retry_request) { + /* Update counts to reflect change of message type. */ + ssl->msgsReceived.got_hello_retry_request = 1; + ssl->msgsReceived.got_server_hello--; + } + *inOutIdx = args->idx; ssl->options.serverState = SERVER_HELLO_COMPLETE; @@ -3393,7 +3509,7 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, */ if (!IsAtLeastTLSv1_3(ssl->version)) { #ifndef WOLFSSL_NO_TLS12 - ssl->arrays->sessionIDSz = sessIdSz; + ssl->arrays->sessionIDSz = args->sessIdSz; if (ssl->arrays->sessionIDSz > ID_LEN) { WOLFSSL_MSG("Invalid session ID size"); @@ -3401,7 +3517,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return BUFFER_ERROR; } else if (ssl->arrays->sessionIDSz) { - XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz); + XMEMCPY(ssl->arrays->sessionID, args->sessId, + ssl->arrays->sessionIDSz); ssl->options.haveSessionId = 1; } @@ -3419,20 +3536,31 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, return ret; } + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT - if (sessIdSz == 0) + if (args->sessIdSz == 0) return INVALID_PARAMETER; if (ssl->session.sessionIDSz != 0) { - if (ssl->session.sessionIDSz != sessIdSz || - XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) { + if (ssl->session.sessionIDSz != args->sessIdSz || + XMEMCMP(ssl->session.sessionID, args->sessId, + args->sessIdSz) != 0) { return INVALID_PARAMETER; } } - else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0) + else if (XMEMCMP(ssl->arrays->clientRandom, args->sessId, + args->sessIdSz) != 0) { return INVALID_PARAMETER; + } #else - if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 && - XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) { + if (args->sessIdSz != ssl->session.sessionIDSz || (args->sessIdSz > 0 && + XMEMCMP(ssl->session.sessionID, args->sessId, args->sessIdSz) != 0)) + { WOLFSSL_MSG("Server sent different session id"); return INVALID_PARAMETER; } @@ -3464,7 +3592,8 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (*extMsgType == server_hello) { #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + PreSharedKey* psk = NULL; + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); if (ext != NULL) psk = (PreSharedKey*)ext->data; while (psk != NULL && !psk->chosen) @@ -3488,6 +3617,12 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = RestartHandshakeHash(ssl); } + break; + } /* case TLS_ASYNC_FINALIZE */ + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ + WOLFSSL_LEAVE("DoTls13ServerHello", ret); WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); @@ -3804,7 +3939,8 @@ static int FindPsk(WOLFSSL* ssl, PreSharedKey* psk, byte* suite, int* err) * * ssl SSL/TLS object. * suite Cipher suite to find PSK for. - * usingPSK Indicates handshake is using Pre-Shared Keys. + * usingPSK 1=Indicates handshake is using Pre-Shared Keys (2=Ephemeral) + * first Set to 1 if first in extension * returns 0 on success and otherwise failure. */ static int DoPreSharedKeys(WOLFSSL* ssl, byte* suite, int* usingPSK, int* first) @@ -4099,17 +4235,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, ext != NULL) { /* Only use named group used in last session. */ ssl->namedGroup = ssl->session.namedGroup; - - /* Pick key share and Generate a new key if not present. */ - ret = TLSX_KeyShare_Establish(ssl); - if (ret == KEY_SHARE_ERROR) { - ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; - } - else if (ret < 0) - return ret; - - /* Send new public key to client. */ - ext->resp = 1; + + *usingPSK = 2; /* generate new ephemeral key */ } else #endif @@ -4118,6 +4245,8 @@ static int CheckPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, return PSK_KEY_ERROR; ssl->options.noPskDheKe = 1; ssl->arrays->preMasterSz = 0; + + *usingPSK = 1; } } #ifdef WOLFSSL_PSK_ID_PROTECTION @@ -4303,7 +4432,7 @@ static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) hrrIdx += 2; #ifdef WOLFSSL_DEBUG_TLS - WOLFSSL_MSG("Reconstucted HelloRetryRequest"); + WOLFSSL_MSG("Reconstructed HelloRetryRequest"); WOLFSSL_BUFFER(hrr, hrrIdx); WOLFSSL_MSG("Cookie"); WOLFSSL_BUFFER(cookieData, cookie->len); @@ -4387,163 +4516,216 @@ static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i, * helloSz The length of the current handshake message. * returns 0 on success and otherwise failure. */ + +typedef struct Dch13Args { + ProtocolVersion pv; + Suites* clSuites; + word32 idx; + word32 begin; + int usingPSK; +} Dch13Args; + +static void FreeDch13Args(WOLFSSL* ssl, void* pArgs) +{ + Dch13Args* args = (Dch13Args*)pArgs; + + (void)ssl; + + if (args->clSuites) { + XFREE(args->clSuites, ssl->heap, DYNAMIC_TYPE_SUITES); + args->clSuites = NULL; + } +} + int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 helloSz) { - int ret = VERSION_ERROR; - byte b = 0; - ProtocolVersion pv; - Suites clSuites; - word32 i = *inOutIdx; - word32 begin = i; - word16 totalExtSz = 0; - byte sessIdSz = 0; - int wantDowngrade = 0; -#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ - defined(HAVE_TLS_EXTENSIONS) - int usingPSK = 0; + int ret; +#ifdef WOLFSSL_ASYNC_CRYPT + Dch13Args* args = (Dch13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dch13Args args[1]; #endif WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); WOLFSSL_ENTER("DoTls13ClientHello"); - XMEMSET(&pv, 0, sizeof(ProtocolVersion)); - XMEMSET(&clSuites, 0, sizeof(Suites)); +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } + else +#endif + { + /* Reset state */ + ret = VERSION_ERROR; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dch13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDch13Args; + #endif + } + + switch (ssl->options.asyncState) { + case TLS_ASYNC_BEGIN: + { + byte b; + byte sessIdSz; + int wantDowngrade = 0; + word16 totalExtSz = 0; #ifdef WOLFSSL_CALLBACKS if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); #endif + args->idx = *inOutIdx; + args->begin = args->idx; + /* protocol version, random and session id length check */ - if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) { + ERROR_OUT(BUFFER_ERROR, exit_dch); + } /* Protocol version */ - XMEMCPY(&pv, input + i, OPAQUE16_LEN); - ssl->chVersion = pv; /* store */ - i += OPAQUE16_LEN; - if (pv.major < SSLv3_MAJOR) { + XMEMCPY(&args->pv, input + args->idx, OPAQUE16_LEN); + ssl->chVersion = args->pv; /* store */ + args->idx += OPAQUE16_LEN; + if (args->pv.major < SSLv3_MAJOR) { WOLFSSL_MSG("Legacy version field contains unsupported value"); #ifdef WOLFSSL_MYSQL_COMPATIBLE SendAlert(ssl, alert_fatal, wc_protocol_version); #else SendAlert(ssl, alert_fatal, protocol_version); #endif - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ - if (pv.major > SSLv3_MAJOR || (pv.major == SSLv3_MAJOR && - pv.minor >= TLSv1_3_MINOR)) { - pv.major = SSLv3_MAJOR; - pv.minor = TLSv1_2_MINOR; + if (args->pv.major > SSLv3_MAJOR || (args->pv.major == SSLv3_MAJOR && + args->pv.minor >= TLSv1_3_MINOR)) { + args->pv.major = SSLv3_MAJOR; + args->pv.minor = TLSv1_2_MINOR; wantDowngrade = 1; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; } /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ - else if (pv.major == SSLv3_MAJOR && pv.minor < TLSv1_2_MINOR) { + else if (args->pv.major == SSLv3_MAJOR && args->pv.minor < TLSv1_2_MINOR) { wantDowngrade = 1; - ssl->version.minor = pv.minor; + ssl->version.minor = args->pv.minor; } else { - ret = DoTls13SupportedVersions(ssl, input + begin, i - begin, helloSz, - &wantDowngrade); + ret = DoTls13SupportedVersions(ssl, input + args->begin, + args->idx - args->begin, helloSz, &wantDowngrade); if (ret < 0) - return ret; + goto exit_dch; } if (wantDowngrade) { #ifndef WOLFSSL_NO_TLS12 if (!ssl->options.downgrade) { WOLFSSL_MSG("Client trying to connect with lesser version than " "TLS v1.3"); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); } - if (pv.minor < ssl->options.minDowngrade) - return VERSION_ERROR; + if (args->pv.minor < ssl->options.minDowngrade) + ERROR_OUT(VERSION_ERROR, exit_dch); - if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) - return ret; - return DoClientHello(ssl, input, inOutIdx, helloSz); + ret = HashInput(ssl, input + args->begin, helloSz); + if (ret == 0) { + ret = DoClientHello(ssl, input, inOutIdx, helloSz); + } + goto exit_dch; #else WOLFSSL_MSG("Client trying to connect with lesser version than " "TLS v1.3"); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); #endif } /* From here on we are a TLS 1.3 ClientHello. */ /* Client random */ - XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); - i += RAN_LEN; + XMEMCPY(ssl->arrays->clientRandom, input + args->idx, RAN_LEN); + args->idx += RAN_LEN; #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG("client random"); WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); #endif - sessIdSz = input[i++]; + sessIdSz = input[args->idx++]; if (sessIdSz != ID_LEN && sessIdSz != 0) - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); - if (sessIdSz + i > helloSz) { - return BUFFER_ERROR; + if (sessIdSz + args->idx > helloSz) { + ERROR_OUT(BUFFER_ERROR, exit_dch); } ssl->session.sessionIDSz = sessIdSz; if (sessIdSz == ID_LEN) { - XMEMCPY(ssl->session.sessionID, input + i, sessIdSz); - i += ID_LEN; + XMEMCPY(ssl->session.sessionID, input + args->idx, sessIdSz); + args->idx += ID_LEN; + } + + args->clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (args->clSuites == NULL) { + ERROR_OUT(MEMORY_E, exit_dch); } /* Cipher suites */ - if ((i - begin) + OPAQUE16_LEN > helloSz) - return BUFFER_ERROR; - ato16(&input[i], &clSuites.suiteSz); - i += OPAQUE16_LEN; + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + ato16(&input[args->idx], &args->clSuites->suiteSz); + args->idx += OPAQUE16_LEN; /* suites and compression length check */ - if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) - return BUFFER_ERROR; - if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) - return BUFFER_ERROR; - XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); - i += clSuites.suiteSz; - clSuites.hashSigAlgoSz = 0; + if ((args->idx - args->begin) + args->clSuites->suiteSz + OPAQUE8_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + if (args->clSuites->suiteSz > WOLFSSL_MAX_SUITE_SZ) + ERROR_OUT(BUFFER_ERROR, exit_dch); + XMEMCPY(args->clSuites->suites, input + args->idx, args->clSuites->suiteSz); + args->idx += args->clSuites->suiteSz; + args->clSuites->hashSigAlgoSz = 0; /* Compression */ - b = input[i++]; - if ((i - begin) + b > helloSz) - return BUFFER_ERROR; + b = input[args->idx++]; + if ((args->idx - args->begin) + b > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); if (b != COMP_LEN) { WOLFSSL_MSG("Must be one compression type in list"); - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } - b = input[i++]; + b = input[args->idx++]; if (b != NO_COMPRESSION) { WOLFSSL_MSG("Must be no compression type in list"); - return INVALID_PARAMETER; + ERROR_OUT(INVALID_PARAMETER, exit_dch); } /* Extensions */ - if ((i - begin) == helloSz) - return BUFFER_ERROR; - if ((i - begin) + OPAQUE16_LEN > helloSz) - return BUFFER_ERROR; + if ((args->idx - args->begin) == helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); + if ((args->idx - args->begin) + OPAQUE16_LEN > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); - ato16(&input[i], &totalExtSz); - i += OPAQUE16_LEN; - if ((i - begin) + totalExtSz > helloSz) - return BUFFER_ERROR; + ato16(&input[args->idx], &totalExtSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + totalExtSz > helloSz) + ERROR_OUT(BUFFER_ERROR, exit_dch); /* Auto populate extensions supported unless user defined. */ if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) - return ret; + goto exit_dch; /* Parse extensions */ - if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, client_hello, - &clSuites))) { - return ret; + if ((ret = TLSX_Parse(ssl, input + args->idx, totalExtSz, client_hello, + args->clSuites))) { + goto exit_dch; } #ifdef HAVE_SNI @@ -4552,13 +4734,9 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ssl->options.side = WOLFSSL_SERVER_END; #endif - i += totalExtSz; - *inOutIdx = i; - - ssl->options.sendVerify = SEND_CERT; - - ssl->options.clientState = CLIENT_HELLO_COMPLETE; + args->idx += totalExtSz; ssl->options.haveSessionId = 1; + ssl->options.sendVerify = SEND_CERT; #if defined(WOLFSSL_SEND_HRR_COOKIE) if (ssl->options.sendCookie && @@ -4566,31 +4744,33 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, TLSX* ext; if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) - return HRR_COOKIE_ERROR; + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); + /* Ensure the cookie came from client and isn't the one in the - * response - HelloRetryRequest. - */ + * response - HelloRetryRequest. + */ if (ext->resp == 1) - return HRR_COOKIE_ERROR; + ERROR_OUT(HRR_COOKIE_ERROR, exit_dch); ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); if (ret != 0) - return ret; + goto exit_dch; } #endif #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ defined(HAVE_TLS_EXTENSIONS) - ret = CheckPreSharedKeys(ssl, input + begin, helloSz, &clSuites, &usingPSK); + ret = CheckPreSharedKeys(ssl, input + args->begin, helloSz, args->clSuites, + &args->usingPSK); if (ret != 0) - return ret; + goto exit_dch; #else - if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) - return ret; + if ((ret = HashInput(ssl, input + args->begin, helloSz)) != 0) + goto exit_dch; #endif #if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ defined(HAVE_TLS_EXTENSIONS) - if (!usingPSK) + if (!args->usingPSK) #endif { /* Not using PSK so don't require no KE. */ @@ -4600,20 +4780,67 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { WOLFSSL_MSG("Client did not send a KeyShare extension"); SendAlert(ssl, alert_fatal, missing_extension); - return INCOMPLETE_DATA; + ERROR_OUT(INCOMPLETE_DATA, exit_dch); } if (TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS) == NULL) { WOLFSSL_MSG("Client did not send a SignatureAlgorithms extension"); SendAlert(ssl, alert_fatal, missing_extension); - return INCOMPLETE_DATA; + ERROR_OUT(INCOMPLETE_DATA, exit_dch); } +#else + ERROR_OUT(INVALID_PARAMETER, exit_dch); +#endif + } - if ((ret = MatchSuite(ssl, &clSuites)) < 0) { + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + case TLS_ASYNC_DO: + { +#ifndef NO_CERTS + if (!args->usingPSK) { + if ((ret = MatchSuite(ssl, args->clSuites)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dch; + #endif WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); SendAlert(ssl, alert_fatal, handshake_failure); - return ret; + goto exit_dch; } + } + else +#endif +#ifdef HAVE_SUPPORTED_CURVES + if (args->usingPSK == 2) { + /* Pick key share and Generate a new key if not present. */ + int doHelloRetry = 0; + ret = TLSX_KeyShare_Establish(ssl, &doHelloRetry); + if (doHelloRetry) { + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + if (ret != WC_PENDING_E) + ret = 0; /* for hello_retry return 0 */ + } + if (ret != 0) + goto exit_dch; + } +#endif + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_BUILD || TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + *inOutIdx = args->idx; + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + + if (!args->usingPSK) { +#ifndef NO_CERTS #ifdef HAVE_NULL_CIPHER if (ssl->options.cipherSuite0 == ECC_BYTE && (ssl->options.cipherSuite == TLS_SHA256_SHA256 || @@ -4627,7 +4854,7 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Negotiated ciphersuite from lesser version than " "TLS v1.3"); SendAlert(ssl, alert_fatal, handshake_failure); - return VERSION_ERROR; + ERROR_OUT(VERSION_ERROR, exit_dch); } #ifdef HAVE_SESSION_TICKET @@ -4639,13 +4866,27 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* Derive early secret for handshake secret. */ if ((ret = DeriveEarlySecret(ssl)) != 0) - return ret; -#else - ret = INVALID_PARAMETER; -#endif + goto exit_dch; +#endif /* !NO_CERTS */ } + break; + } /* case TLS_ASYNC_FINALIZE */ + default: + ret = INPUT_CASE_ERROR; + } /* switch (ssl->options.asyncState) */ + +exit_dch: WOLFSSL_LEAVE("DoTls13ClientHello", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ssl->msgsReceived.got_client_hello = 0; + return ret; + } +#endif + + FreeDch13Args(ssl, args); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); return ret; @@ -8295,6 +8536,7 @@ int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret, * ssl The SSL/TLS object. * group The named group. * returns 0 on success, otherwise failure. + * for async can return WC_PENDING_E and should be called again */ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) { @@ -8303,6 +8545,15 @@ int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) if (ssl == NULL) return BAD_FUNC_ARG; +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, NULL); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + return ret; + } +#endif + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); if (ret != 0) return ret; diff --git a/tests/suites.c b/tests/suites.c index 531978855..cd554f96e 100644 --- a/tests/suites.c +++ b/tests/suites.c @@ -809,7 +809,7 @@ int SuiteTest(int argc, char** argv) args.return_code = EXIT_FAILURE; goto exit; } - wolfSSL_CTX_UseAsync(cipherSuiteCtx, devId); + wolfSSL_CTX_SetDevId(cipherSuiteCtx, devId); #endif /* WOLFSSL_ASYNC_CRYPT */ /* support for custom command line tests */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 29c9c1e79..64e8147c5 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -18934,7 +18934,7 @@ int wc_MIME_parse_headers(char* in, int inLen, MimeHdr** headers) else { mimeType = MIME_HDR; } - start = end = 0; + start = 0; lineLen = XSTRLEN(curLine); if (lineLen == 0) { ret = BAD_FUNC_ARG; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 4492bb16e..7f34a6d95 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1552,7 +1552,7 @@ const char* wc_ecc_get_name(int curve_id) int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) { - if (keysize <= 0 && curve_id < 0) { + if (key == NULL || (keysize <= 0 && curve_id < 0)) { return BAD_FUNC_ARG; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 9dc4d341c..a994293a2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -2627,17 +2627,23 @@ typedef struct KeyShareEntry { word16 group; /* NamedGroup */ byte* ke; /* Key exchange data */ word32 keLen; /* Key exchange data length */ - void* key; /* Private key */ - word32 keyLen; /* Private key length */ + void* key; /* Key struct */ + word32 keyLen; /* Key size (bytes) */ byte* pubKey; /* Public key */ word32 pubKeyLen; /* Public key length */ +#ifndef NO_DH + byte* privKey; /* Private key - DH only */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + int lastRet; +#endif struct KeyShareEntry* next; /* List pointer */ } KeyShareEntry; WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, KeyShareEntry **kse); WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); -WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl, int* doHelloRetry); WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl); @@ -4826,14 +4832,15 @@ WOLFSSL_LOCAL int SetRsaInternal(WOLFSSL_RSA* rsa); WOLFSSL_LOCAL int SetDhInternal(WOLFSSL_DH* dh); WOLFSSL_LOCAL int SetDhExternal(WOLFSSL_DH *dh); -#ifndef NO_DH +#if !defined(NO_DH) && (!defined(NO_CERTS) || !defined(NO_PSK)) WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, byte* priv, word32* privSz, byte* pub, word32* pubSz); WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey, const byte* priv, word32 privSz, const byte* otherPub, word32 otherPubSz, - byte* agree, word32* agreeSz); + byte* agree, word32* agreeSz, + const byte* prime, word32 primeSz); #endif /* !NO_DH */ #ifdef HAVE_ECC