wolfSSL SSL/TLS library, support up to TLS1.3
Dependents: CyaSSL-Twitter-OAuth4Tw Example-client-tls-cert TwitterReader TweetTest ... more
Diff: src/tls.c
- Revision:
- 16:8e0d178b1d1e
- Parent:
- 15:117db924cf7c
--- a/src/tls.c Sat Aug 18 22:20:43 2018 +0000 +++ b/src/tls.c Thu Jun 04 23:57:22 2020 +0000 @@ -1,6 +1,6 @@ /* tls.c * - * Copyright (C) 2006-2017 wolfSSL Inc. + * Copyright (C) 2006-2020 wolfSSL Inc. * * This file is part of wolfSSL. * @@ -43,7 +43,9 @@ #ifdef HAVE_CURVE25519 #include <wolfssl/wolfcrypt/curve25519.h> #endif - +#ifdef HAVE_CURVE448 + #include <wolfssl/wolfcrypt/curve448.h> +#endif #ifdef HAVE_NTRU #include "libntruencrypt/ntru_crypto.h" #include <wolfssl/wolfcrypt/random.h> @@ -63,12 +65,13 @@ static int TLSX_KeyShare_IsSupported(int namedGroup); #endif -#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ +#if ((!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ - (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && \ - !defined(HAVE_CURVE25519) && defined(HAVE_SUPPORTED_CURVES)) || \ - ((defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ - defined(HAVE_SUPPORTED_CURVES)) + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES))) && \ + defined(HAVE_TLS_EXTENSIONS) static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions); #endif @@ -97,313 +100,75 @@ #if !defined(NO_RSA) && !defined(WC_RSA_PSS) #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA #endif -#endif - + #ifndef HAVE_TLS_EXTENSIONS + #ifndef _MSC_VER + #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3" + #else + #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3") + #endif + #endif +#endif + +/* Warn if secrets logging is enabled */ +#if defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE) + #ifndef _MSC_VER + #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment + #else + #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment") + #endif +#endif + +/* Optional Pre-Master-Secret logging for Wireshark */ +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) +#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT + #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log" +#endif +#endif #ifndef WOLFSSL_NO_TLS12 #ifdef WOLFSSL_SHA384 - #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE -#else - #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE -#endif - -/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ -static int p_hash(byte* result, word32 resLen, const byte* secret, - word32 secLen, const byte* seed, word32 seedLen, int hash, - void* heap, int devId) -{ - word32 len = P_HASH_MAX_SIZE; - word32 times; - word32 lastLen; - word32 lastTime; - word32 i; - word32 idx = 0; - int ret = 0; -#ifdef WOLFSSL_SMALL_STACK - byte* previous; - byte* current; - Hmac* hmac; -#else - byte previous[P_HASH_MAX_SIZE]; /* max size */ - byte current[P_HASH_MAX_SIZE]; /* max size */ - Hmac hmac[1]; -#endif - -#ifdef WOLFSSL_SMALL_STACK - previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); - current = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); - hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); - - if (previous == NULL || current == NULL || hmac == NULL) { - if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); - if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST); - if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); - - return MEMORY_E; - } -#endif - - switch (hash) { - #ifndef NO_MD5 - case md5_mac: - hash = WC_MD5; - len = WC_MD5_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA256 - case sha256_mac: - hash = WC_SHA256; - len = WC_SHA256_DIGEST_SIZE; - break; - #endif - - #ifdef WOLFSSL_SHA384 - case sha384_mac: - hash = WC_SHA384; - len = WC_SHA384_DIGEST_SIZE; - break; - #endif - - #ifndef NO_SHA - case sha_mac: - default: - hash = WC_SHA; - len = WC_SHA_DIGEST_SIZE; - break; - #endif - } - - times = resLen / len; - lastLen = resLen % len; - - if (lastLen) - times += 1; - - lastTime = times - 1; - - ret = wc_HmacInit(hmac, heap, devId); - if (ret == 0) { - ret = wc_HmacSetKey(hmac, hash, secret, secLen); - if (ret == 0) - ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */ - if (ret == 0) - ret = wc_HmacFinal(hmac, previous); /* A1 */ - if (ret == 0) { - for (i = 0; i < times; i++) { - ret = wc_HmacUpdate(hmac, previous, len); - if (ret != 0) - break; - ret = wc_HmacUpdate(hmac, seed, seedLen); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, current); - if (ret != 0) - break; - - if ((i == lastTime) && lastLen) - XMEMCPY(&result[idx], current, - min(lastLen, P_HASH_MAX_SIZE)); - else { - XMEMCPY(&result[idx], current, len); - idx += len; - ret = wc_HmacUpdate(hmac, previous, len); - if (ret != 0) - break; - ret = wc_HmacFinal(hmac, previous); - if (ret != 0) - break; - } - } - } - wc_HmacFree(hmac); - } - - ForceZero(previous, P_HASH_MAX_SIZE); - ForceZero(current, P_HASH_MAX_SIZE); - ForceZero(hmac, sizeof(Hmac)); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); - XFREE(current, heap, DYNAMIC_TYPE_DIGEST); - XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); -#endif - - return ret; -} - -#undef P_HASH_MAX_SIZE - -#endif /* !WOLFSSL_NO_TLS12 */ - - -#ifndef NO_OLD_TLS - -/* calculate XOR for TLSv1 PRF */ -static WC_INLINE void get_xor(byte *digest, word32 digLen, byte* md5, byte* sha) -{ - word32 i; - - for (i = 0; i < digLen; i++) - digest[i] = md5[i] ^ sha[i]; -} - - -/* compute TLSv1 PRF (pseudo random function using HMAC) */ -static int doPRF(byte* digest, word32 digLen, const byte* secret,word32 secLen, - const byte* label, word32 labLen, const byte* seed, - word32 seedLen, void* heap, int devId) -{ - int ret = 0; - word32 half = (secLen + 1) / 2; - -#ifdef WOLFSSL_SMALL_STACK - byte* md5_half; - byte* sha_half; - byte* md5_result; - byte* sha_result; -#else - byte md5_half[MAX_PRF_HALF]; /* half is real size */ - byte sha_half[MAX_PRF_HALF]; /* half is real size */ - byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ - byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ -#endif - DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); - - if (half > MAX_PRF_HALF) - return BUFFER_E; - if (labLen + seedLen > MAX_PRF_LABSEED) - return BUFFER_E; - if (digLen > MAX_PRF_DIG) - return BUFFER_E; - -#ifdef WOLFSSL_SMALL_STACK - md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); - sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); - md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); - sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); - - if (md5_half == NULL || sha_half == NULL || md5_result == NULL || - sha_result == NULL) { - if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); - if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); - if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); - if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); - FREE_VAR(labelSeed, heap); - - return MEMORY_E; - } -#endif - - XMEMSET(md5_result, 0, digLen); - XMEMSET(sha_result, 0, digLen); - - XMEMCPY(md5_half, secret, half); - XMEMCPY(sha_half, secret + half - secLen % 2, half); - - XMEMCPY(labelSeed, label, labLen); - XMEMCPY(labelSeed + labLen, seed, seedLen); - - if ((ret = p_hash(md5_result, digLen, md5_half, half, labelSeed, - labLen + seedLen, md5_mac, heap, devId)) == 0) { - if ((ret = p_hash(sha_result, digLen, sha_half, half, labelSeed, - labLen + seedLen, sha_mac, heap, devId)) == 0) { - get_xor(digest, digLen, md5_result, sha_result); - } - } - -#ifdef WOLFSSL_SMALL_STACK - XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); - XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); - XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); - XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); -#endif - - FREE_VAR(labelSeed, heap); - - return ret; -} - -#endif - - -#ifndef WOLFSSL_NO_TLS12 - -/* Wrapper to call straight thru to p_hash in TSL 1.2 cases to remove stack - use */ -static int PRF(byte* digest, word32 digLen, const byte* secret, word32 secLen, - const byte* label, word32 labLen, const byte* seed, word32 seedLen, - int useAtLeastSha256, int hash_type, void* heap, int devId) -{ - int ret = 0; - - if (useAtLeastSha256) { - DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); - - if (labLen + seedLen > MAX_PRF_LABSEED) - return BUFFER_E; - - XMEMCPY(labelSeed, label, labLen); - XMEMCPY(labelSeed + labLen, seed, seedLen); - - /* If a cipher suite wants an algorithm better than sha256, it - * should use better. */ - if (hash_type < sha256_mac || hash_type == blake2b_mac) - hash_type = sha256_mac; - ret = p_hash(digest, digLen, secret, secLen, labelSeed, - labLen + seedLen, hash_type, heap, devId); - - FREE_VAR(labelSeed, heap); - } -#ifndef NO_OLD_TLS - else { - ret = doPRF(digest, digLen, secret, secLen, label, labLen, seed, - seedLen, heap, devId); - } -#endif - - return ret; -} - -#ifdef WOLFSSL_SHA384 #define HSHASH_SZ WC_SHA384_DIGEST_SIZE #else #define HSHASH_SZ FINISHED_SZ #endif +#ifdef WOLFSSL_RENESAS_TSIP_TLS + int tsip_useable(const WOLFSSL *ssl); + int tsip_generateMasterSecret(const byte *pre, + const byte *cr,const byte *sr, + byte *ms/* out */); + int tsip_generateSeesionKey(WOLFSSL *ssl); + int tsip_generateVerifyData(const byte *ms, const byte *side, + const byte *handshake_hash, + byte *hashes /* out */); +#endif int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) { + int ret = 0; word32 hashSz = FINISHED_SZ; if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ) return BAD_FUNC_ARG; + /* for constant timing perform these even if error */ #ifndef NO_OLD_TLS - wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); - wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); + ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); + ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); #endif if (IsAtLeastTLSv1_2(ssl)) { #ifndef NO_SHA256 if (ssl->specs.mac_algorithm <= sha256_mac || ssl->specs.mac_algorithm == blake2b_mac) { - int ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); - - if (ret != 0) - return ret; - + ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); hashSz = WC_SHA256_DIGEST_SIZE; } #endif #ifdef WOLFSSL_SHA384 if (ssl->specs.mac_algorithm == sha384_mac) { - int ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); - - if (ret != 0) - return ret; - + ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); hashSz = WC_SHA384_DIGEST_SIZE; } #endif @@ -411,36 +176,58 @@ *hashLen = hashSz; - return 0; + if (ret != 0) + ret = BUILD_MSG_ERROR; + + return ret; } int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) { - int ret; + int ret; const byte* side; - byte* handshake_hash; - word32 hashSz = HSHASH_SZ; - - /* using allocate here to allow async hardware to use buffer directly */ - handshake_hash = (byte*)XMALLOC(hashSz, ssl->heap, DYNAMIC_TYPE_DIGEST); + word32 hashSz = HSHASH_SZ; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); if (handshake_hash == NULL) return MEMORY_E; +#else + byte handshake_hash[HSHASH_SZ]; +#endif ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); if (ret == 0) { - if ( XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) side = tls_client; else side = tls_server; - ret = PRF((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, +#ifdef WOLFSSL_HAVE_PRF +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = tsip_generateVerifyData(ssl->arrays->tsip_masterSecret, + side, handshake_hash, (byte*)hashes /* out */); + } else +#endif + ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, ssl->devId); - } - - XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)side; + (void)hashes; +#endif + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(handshake_hash, ssl->heap); +#endif return ret; } @@ -517,15 +304,43 @@ void* heap, int devId) { int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif XMEMCPY(seed, sr, RAN_LEN); XMEMCPY(seed + RAN_LEN, cr, RAN_LEN); - ret = PRF(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, seed, SEED_LEN, tls1_2, hash_type, heap, devId); - +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)key_dig; + (void)key_dig_len; + (void)ms; + (void)msLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; + (void)key_label; + (void)master_label; +#ifdef HAVE_EXTENDED_MASTER + (void)ext_master_label; +#endif +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) FREE_VAR(seed, heap); +#endif return ret; } @@ -559,7 +374,12 @@ return MEMORY_E; } #endif - +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) + ret = tsip_generateSeesionKey(ssl); + else { +#endif ret = _DeriveTlsKeys(key_dig, key_dig_len, ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->serverRandom, ssl->arrays->clientRandom, @@ -567,6 +387,10 @@ ssl->heap, ssl->devId); if (ret == 0) ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER); +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + } +#endif #ifdef WOLFSSL_SMALL_STACK XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); @@ -581,13 +405,41 @@ int tls1_2, int hash_type, void* heap, int devId) { - byte seed[SEED_LEN]; + int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif XMEMCPY(seed, cr, RAN_LEN); XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); - return PRF(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, seed, SEED_LEN, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(seed, heap); +#endif + + return ret; } /* External facing wrapper so user can call as well, 0 on success */ @@ -609,8 +461,28 @@ int tls1_2, int hash_type, void* heap, int devId) { - return PRF(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, + int ret; + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, sHash, sHashLen, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)sHash; + (void)sHashLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + return ret; } /* External facing wrapper so user can call as well, 0 on success */ @@ -628,48 +500,93 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) { - int ret; + int ret; + #ifdef HAVE_EXTENDED_MASTER if (ssl->options.haveEMS) { - byte* handshake_hash; word32 hashSz = HSHASH_SZ; - - handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, - DYNAMIC_TYPE_DIGEST); + #ifdef WOLFSSL_SMALL_STACK + byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, + DYNAMIC_TYPE_DIGEST); if (handshake_hash == NULL) return MEMORY_E; + #else + byte handshake_hash[HSHASH_SZ]; + #endif ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); - if (ret < 0) { - XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); - return ret; - } - - ret = _MakeTlsExtendedMasterSecret( + if (ret == 0) { + ret = _MakeTlsExtendedMasterSecret( ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, ssl->devId); - + } + + #ifdef WOLFSSL_SMALL_STACK XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); - } else -#endif - ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, + #endif + } + else +#endif /* HAVE_EXTENDED_MASTER */ + { +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + ret = tsip_generateMasterSecret( + &ssl->arrays->preMasterSecret[VERSION_SZ], + ssl->arrays->clientRandom, + ssl->arrays->serverRandom, + ssl->arrays->tsip_masterSecret); + } else +#endif + ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, ssl->arrays->clientRandom, ssl->arrays->serverRandom, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, ssl->devId); - + } if (ret == 0) { #ifdef SHOW_SECRETS - int i; - - printf("master secret: "); - for (i = 0; i < SECRET_LEN; i++) - printf("%02x", ssl->arrays->masterSecret[i]); - printf("\n"); - #endif + /* Wireshark Pre-Master-Secret Format: + * CLIENT_RANDOM <clientrandom> <mastersecret> + */ + const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM"; + int i, pmsPos = 0; + char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1]; + + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ", + CLIENT_RANDOM_LABEL); + pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1; + for (i = 0; i < RAN_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->clientRandom[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " "); + pmsPos += 1; + for (i = 0; i < SECRET_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->masterSecret[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n"); + pmsPos += 1; + + /* print master secret */ + puts(pmsBuf); + + #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) + { + FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a"); + if (f != XBADFILE) { + XFWRITE(pmsBuf, 1, pmsPos, f); + XFCLOSE(f); + } + } + #endif + #endif /* SHOW_SECRETS */ ret = DeriveTlsKeys(ssl); } @@ -703,10 +620,20 @@ XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); - ret = PRF((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, ssl->devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)msk; + (void)len; + (void)label; +#endif #ifdef WOLFSSL_SMALL_STACK XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED); @@ -742,17 +669,17 @@ { if (order == PREV_ORDER) { /* Previous epoch case */ - seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + seq[0] = (((word32)ssl->keys.dtls_epoch - 1) << 16) | (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_prev_sequence_number_lo; } else if (order == PEER_ORDER) { - seq[0] = (ssl->keys.curEpoch << 16) | + seq[0] = ((word32)ssl->keys.curEpoch << 16) | (ssl->keys.curSeq_hi & 0xFFFF); seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ } else { - seq[0] = (ssl->keys.dtls_epoch << 16) | + seq[0] = ((word32)ssl->keys.dtls_epoch << 16) | (ssl->keys.dtls_sequence_number_hi & 0xFFFF); seq[1] = ssl->keys.dtls_sequence_number_lo; } @@ -845,6 +772,7 @@ } +#ifndef WOLFSSL_AEAD_ONLY #if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ !defined(HAVE_SELFTEST) @@ -936,66 +864,23 @@ static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) { int ret = BAD_FUNC_ARG; - - switch (hmac->macType) { - #ifndef NO_SHA - case WC_SHA: - ret = wc_InitSha(&hmac->hash.sha); - if (ret == 0) - ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad, - WC_SHA_BLOCK_SIZE); - if (ret == 0) - ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash, - WC_SHA_DIGEST_SIZE); - if (ret == 0) - ret = wc_ShaFinal(&hmac->hash.sha, mac); - break; - #endif /* !NO_SHA */ - - #ifndef NO_SHA256 - case WC_SHA256: - ret = wc_InitSha256(&hmac->hash.sha256); - if (ret == 0) - ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, - WC_SHA256_BLOCK_SIZE); - if (ret == 0) - ret = wc_Sha256Update(&hmac->hash.sha256, - (byte*)hmac->innerHash, - WC_SHA256_DIGEST_SIZE); - if (ret == 0) - ret = wc_Sha256Final(&hmac->hash.sha256, mac); - break; - #endif /* !NO_SHA256 */ - - #ifdef WOLFSSL_SHA384 - case WC_SHA384: - ret = wc_InitSha384(&hmac->hash.sha384); - if (ret == 0) - ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad, - WC_SHA384_BLOCK_SIZE); - if (ret == 0) - ret = wc_Sha384Update(&hmac->hash.sha384, - (byte*)hmac->innerHash, - WC_SHA384_DIGEST_SIZE); - if (ret == 0) - ret = wc_Sha384Final(&hmac->hash.sha384, mac); - break; - #endif /* WOLFSSL_SHA384 */ - - #ifdef WOLFSSL_SHA512 - case WC_SHA512: - ret = wc_InitSha512(&hmac->hash.sha512); - if (ret == 0) - ret = wc_Sha512Update(&hmac->hash.sha512,(byte*)hmac->opad, - WC_SHA512_BLOCK_SIZE); - if (ret == 0) - ret = wc_Sha512Update(&hmac->hash.sha512, - (byte*)hmac->innerHash, - WC_SHA512_DIGEST_SIZE); - if (ret == 0) - ret = wc_Sha512Final(&hmac->hash.sha512, mac); - break; - #endif /* WOLFSSL_SHA512 */ + wc_HashAlg hash; + enum wc_HashType hashType = (enum wc_HashType)hmac->macType; + int digestSz = wc_HashGetDigestSize(hashType); + int blockSz = wc_HashGetBlockSize(hashType); + + if ((digestSz >= 0) && (blockSz >= 0)) { + ret = wc_HashInit(&hash, hashType); + } + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad, + blockSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash, + digestSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, mac); + wc_HashFree(&hash, hashType); } return ret; @@ -1017,11 +902,12 @@ byte lenBytes[8]; int i, j, k; int blockBits, blockMask; - int realLen, lastBlockLen, macLen, extraLen, eocIndex; + int lastBlockLen, macLen, extraLen, eocIndex; int blocks, safeBlocks, lenBlock, eocBlock; int maxLen; int blockSz, padSz; int ret; + word32 realLen; byte extraBlock; switch (hmac->macType) { @@ -1129,12 +1015,12 @@ else if (k < maxLen) b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ]; - b = ctMaskSel(atEoc, b, 0x80); + b = ctMaskSel(atEoc, 0x80, b); b &= (unsigned char)~(word32)pastEoc; b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock; if (j >= blockSz - 8) { - b = ctMaskSel(isOutBlock, b, lenBytes[j - (blockSz - 8)]); + b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b); } hashBlock[j] = b; @@ -1177,7 +1063,7 @@ byte dummy[WC_MAX_BLOCK_SIZE] = {0}; int ret; word32 msgSz, blockSz, macSz, padSz, maxSz, realSz; - word32 currSz, offset; + word32 currSz, offset = 0; int msgBlocks, blocks, blockBits; int i; @@ -1288,6 +1174,12 @@ Hmac hmac; byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; int ret = 0; +#ifdef HAVE_TRUNCATED_HMAC + word32 hashSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 hashSz = ssl->specs.hash_size; +#endif if (ssl == NULL) return BAD_FUNC_ARG; @@ -1296,8 +1188,8 @@ /* Fuzz "in" buffer with sz to be used in HMAC algorithm */ if (ssl->fuzzerCb) { if (verify && padSz >= 0) { - ssl->fuzzerCb(ssl, in, sz + ssl->specs.hash_size + padSz + 1, - FUZZ_HMAC, ssl->fuzzerCtx); + ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC, + ssl->fuzzerCtx); } else { ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); @@ -1306,7 +1198,21 @@ #endif wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); - +#if defined(WOLFSSL_RENESAS_TSIP_TLS) && \ + !defined(NO_WOLFSSL_RENESAS_TSIP_TLS_SESSION) + if (tsip_useable(ssl)) { + if (ssl->specs.hash_size == WC_SHA_DIGEST_SIZE) + ret = tsip_Sha1Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ, + in, sz, digest, verify); + else if (ssl->specs.hash_size == WC_SHA256_DIGEST_SIZE) + ret = tsip_Sha256Hmac(ssl, myInner, WOLFSSL_TLS_HMAC_INNER_SZ, + in, sz, digest, verify); + else + ret = TSIP_MAC_DIGSZ_E; + + return ret; + } +#endif ret = wc_HmacInit(&hmac, ssl->heap, ssl->devId); if (ret != 0) return ret; @@ -1321,21 +1227,18 @@ !defined(HAVE_SELFTEST) #ifdef HAVE_BLAKE2 if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) { - ret = Hmac_UpdateFinal(&hmac, digest, in, sz + - ssl->specs.hash_size + padSz + 1, - myInner); + ret = Hmac_UpdateFinal(&hmac, digest, in, + sz + hashSz + padSz + 1, myInner); } else #endif { - ret = Hmac_UpdateFinal_CT(&hmac, digest, in, sz + - ssl->specs.hash_size + padSz + 1, - myInner); + ret = Hmac_UpdateFinal_CT(&hmac, digest, in, + sz + hashSz + padSz + 1, myInner); } #else - ret = Hmac_UpdateFinal(&hmac, digest, in, sz + - ssl->specs.hash_size + padSz + 1, - myInner); + ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz + padSz + 1, + myInner); #endif } else { @@ -1351,6 +1254,7 @@ return ret; } +#endif /* WOLFSSL_AEAD_ONLY */ #endif /* !WOLFSSL_NO_TLS12 */ @@ -1367,7 +1271,7 @@ /** * Converts the extension type (id) to an index in the semaphore. * - * Oficial reference for TLS extension types: + * Official reference for TLS extension types: * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml * * Motivation: @@ -1398,7 +1302,7 @@ is assigned to be used by another extension. Use this check value for the new extension and decrement the check value by one. */ - WOLFSSL_MSG("### TLSX semaphore colision or overflow detected!"); + WOLFSSL_MSG("### TLSX semaphore collision or overflow detected!"); } } @@ -1550,6 +1454,8 @@ XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz); alpn->protocol_name[protocol_nameSz] = 0; + (void)heap; + return alpn; } @@ -1681,6 +1587,9 @@ ato16(input, &size); offset += OPAQUE16_LEN; + if (size == 0) + return BUFFER_ERROR; + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) extension = TLSX_Find(ssl->ctx->extensions, @@ -1730,7 +1639,7 @@ for (size = 0; offset < length; offset += size) { size = input[offset++]; - if (offset + size > length) + if (offset + size > length || size == 0) return BUFFER_ERROR; if (isRequest) { @@ -1899,6 +1808,8 @@ { SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX); + (void)heap; + if (sni) { sni->type = type; sni->next = NULL; @@ -2049,6 +1960,10 @@ word16 size = 0; word16 offset = 0; int cacheOnly = 0; + SNI *sni = NULL; + byte type; + int matchStat; + byte matched; #endif TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); @@ -2102,73 +2017,64 @@ offset += OPAQUE16_LEN; /* validating sni list length */ - if (length != OPAQUE16_LEN + size) + if (length != OPAQUE16_LEN + size || size == 0) + return BUFFER_ERROR; + + /* SNI was badly specified and only one type is now recognized and allowed. + * Only one SNI value per type (RFC6066), so, no loop. */ + type = input[offset++]; + if (type != WOLFSSL_SNI_HOST_NAME) return BUFFER_ERROR; - for (size = 0; offset < length; offset += size) { - SNI *sni = NULL; - byte type = input[offset++]; - - if (offset + OPAQUE16_LEN > length) - return BUFFER_ERROR; - - ato16(input + offset, &size); - offset += OPAQUE16_LEN; - - if (offset + size > length) - return BUFFER_ERROR; - - if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type))) - continue; /* not using this type of SNI. */ - - switch(type) { - case WOLFSSL_SNI_HOST_NAME: { - int matchStat; - byte matched; + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size != length || size == 0) + return BUFFER_ERROR; + + if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type))) + return 0; /* not using this type of SNI. */ #ifdef WOLFSSL_TLS13 - /* Don't process the second ClientHello SNI extension if there - * was problems with the first. - */ - if (!cacheOnly && sni->status != 0) - break; -#endif - matched = cacheOnly || - ((XSTRLEN(sni->data.host_name) == size) && - (XSTRNCMP(sni->data.host_name, - (const char*)input + offset, size) == 0)); - - if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { - int r = TLSX_UseSNI(&ssl->extensions, - type, input + offset, size, ssl->heap); - - if (r != WOLFSSL_SUCCESS) - return r; /* throws error. */ - - if(cacheOnly) { - WOLFSSL_MSG("Forcing storage of SNI, Fake match"); - matchStat = WOLFSSL_SNI_FORCE_KEEP; - } else if(matched) { - WOLFSSL_MSG("SNI did match!"); - matchStat = WOLFSSL_SNI_REAL_MATCH; - } else { - WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH"); - matchStat = WOLFSSL_SNI_FAKE_MATCH; - } - - TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); - - if(!cacheOnly) - TLSX_SetResponse(ssl, TLSX_SERVER_NAME); - - } else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { - SendAlert(ssl, alert_fatal, unrecognized_name); - - return UNKNOWN_SNI_HOST_NAME_E; - } - break; - } - } + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (!cacheOnly && sni->status != 0) + return 0; +#endif + matched = cacheOnly || (XSTRLEN(sni->data.host_name) == size && + XSTRNCMP(sni->data.host_name, (const char*)input + offset, size) == 0); + + if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { + int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size, + ssl->heap); + if (r != WOLFSSL_SUCCESS) + return r; /* throws error. */ + + if (cacheOnly) { + WOLFSSL_MSG("Forcing storage of SNI, Fake match"); + matchStat = WOLFSSL_SNI_FORCE_KEEP; + } + else if (matched) { + WOLFSSL_MSG("SNI did match!"); + matchStat = WOLFSSL_SNI_REAL_MATCH; + } + else { + WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH"); + matchStat = WOLFSSL_SNI_FAKE_MATCH; + } + + TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); + + if(!cacheOnly) + TLSX_SetResponse(ssl, TLSX_SERVER_NAME); + } + else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { + SendAlert(ssl, alert_fatal, unrecognized_name); + + return UNKNOWN_SNI_HOST_NAME_E; } #else (void)input; @@ -2468,6 +2374,344 @@ #endif /* HAVE_SNI */ /******************************************************************************/ +/* Trusted CA Key Indication */ +/******************************************************************************/ + +#ifdef HAVE_TRUSTED_CA + +/** Creates a new TCA object. */ +static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap) +{ + TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX); + + if (tca) { + XMEMSET(tca, 0, sizeof(TCA)); + tca->type = type; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (idSz == WC_SHA_DIGEST_SIZE && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + #endif + + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (idSz > 0 && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + + default: /* invalid type */ + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + } + + (void)heap; + + return tca; +} + +/** Releases a TCA object. */ +static void TLSX_TCA_Free(TCA* tca, void* heap) +{ + (void)heap; + + if (tca) { + if (tca->id) + XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX); + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + } +} + +/** Releases all TCA objects in the provided list. */ +static void TLSX_TCA_FreeAll(TCA* list, void* heap) +{ + TCA* tca; + + while ((tca = list)) { + list = tca->next; + TLSX_TCA_Free(tca, heap); + } +} + +/** Tells the buffered size of the TCA objects in a list. */ +static word16 TLSX_TCA_GetSize(TCA* list) +{ + TCA* tca; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((tca = list)) { + list = tca->next; + + length += ENUM_LEN; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + length += tca->idSz; + break; + case WOLFSSL_TRUSTED_CA_X509_NAME: + length += OPAQUE16_LEN + tca->idSz; + break; + } + } + + return length; +} + +/** Writes the TCA objects of a list in a buffer. */ +static word16 TLSX_TCA_Write(TCA* list, byte* output) +{ + TCA* tca; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((tca = list)) { + list = tca->next; + + output[offset++] = tca->type; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (tca->id != NULL) { + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (tca->id != NULL) { + c16toa(tca->idSz, output + offset); /* tca length */ + offset += OPAQUE16_LEN; + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + default: + /* ID unknown. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +#ifndef NO_WOLFSSL_SERVER +static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz) +{ + TCA* tca = list; + + while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED && + idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz)) + tca = tca->next; + + return tca; +} +#endif /* NO_WOLFSSL_SERVER */ + +/** Parses a buffer of TCA extensions. */ +static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) +{ +#ifndef NO_WOLFSSL_SERVER + word16 size = 0; + word16 offset = 0; +#endif + + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); + + if (length > 0) + return BUFFER_ERROR; /* TCA response MUST be empty. */ + + /* Set the flag that we're good for keys */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + + return 0; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + if (!extension || !extension->data) { + /* Skipping, TCA not enabled at server side. */ + return 0; + } + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating tca list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + for (size = 0; offset < length; offset += size) { + TCA *tca = NULL; + byte type; + const byte* id = NULL; + word16 idSz = 0; + + if (offset + ENUM_LEN > length) + return BUFFER_ERROR; + + type = input[offset++]; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (offset + WC_SHA_DIGEST_SIZE > length) + return BUFFER_ERROR; + idSz = WC_SHA_DIGEST_SIZE; + id = input + offset; + offset += idSz; + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &idSz); + offset += OPAQUE16_LEN; + if ((offset > length) || (idSz > length - offset)) + return BUFFER_ERROR; + id = input + offset; + offset += idSz; + break; + default: + return TCA_INVALID_ID_TYPE; + } + + /* Find the type/ID in the TCA list. */ + tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz); + if (tca != NULL) { + /* Found it. Set the response flag and break out of the loop. */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + break; + } + } +#else + (void)input; +#endif + + return 0; +} + +/* Checks to see if the server sent a response for the TCA. */ +static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest) +{ + (void)ssl; + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (extension && !extension->resp) { + SendAlert(ssl, alert_fatal, handshake_failure); + return TCA_ABSENT_ERROR; + } + #endif /* NO_WOLFSSL_CLIENT */ + } + + return 0; +} + +int TLSX_UseTrustedCA(TLSX** extensions, byte type, + const byte* id, word16 idSz, void* heap) +{ + TLSX* extension; + TCA* tca = NULL; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL) + return MEMORY_E; + + extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS); + if (!extension) { + int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap); + + if (ret != 0) { + TLSX_TCA_Free(tca, heap); + return ret; + } + } + else { + /* push new TCA object to extension data. */ + tca->next = (TCA*)extension->data; + extension->data = (void*)tca; + } + + return WOLFSSL_SUCCESS; +} + +#define TCA_FREE_ALL TLSX_TCA_FreeAll +#define TCA_GET_SIZE TLSX_TCA_GetSize +#define TCA_WRITE TLSX_TCA_Write +#define TCA_PARSE TLSX_TCA_Parse +#define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse + +#else /* HAVE_TRUSTED_CA */ + +#define TCA_FREE_ALL(list, heap) +#define TCA_GET_SIZE(list) 0 +#define TCA_WRITE(a, b) 0 +#define TCA_PARSE(a, b, c, d) 0 +#define TCA_VERIFY_PARSE(a, b) 0 + +#endif /* HAVE_TRUSTED_CA */ + +/******************************************************************************/ /* Max Fragment Length Negotiation */ /******************************************************************************/ @@ -2495,6 +2739,7 @@ #endif switch (*input) { + case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; @@ -2526,7 +2771,7 @@ byte* data = NULL; int ret = 0; - if (extensions == NULL || mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) + if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX) return BAD_FUNC_ARG; data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX); @@ -2653,15 +2898,8 @@ } #endif #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) - if (!isRequest && csr->ssl->options.tls1_3) { - if (csr->response.buffer == NULL) { - OcspRequest* request = &csr->request.ocsp; - int ret = CreateOcspResponse(csr->ssl, &request, &csr->response); - if (ret < 0) - return ret; - } + if (!isRequest && csr->ssl->options.tls1_3) return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length; - } #endif return size; @@ -2770,6 +3008,13 @@ if (ssl->options.tls1_3) { word32 resp_length; word32 offset = 0; + + /* Get the new extension potentially created above. */ + extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + ret = 0; if (OPAQUE8_LEN + OPAQUE24_LEN > length) ret = BUFFER_ERROR; @@ -2781,10 +3026,12 @@ if (offset + resp_length != length) ret = BUFFER_ERROR; } + #if !defined(NO_WOLFSSL_SERVER) if (ret == 0) { csr->response.buffer = input + offset; csr->response.length = resp_length; } + #endif return ret; } @@ -2802,6 +3049,8 @@ word16 offset = 0; word16 size = 0; + if (length == 0) + return 0; if (length < ENUM_LEN) return BUFFER_ERROR; @@ -2850,7 +3099,25 @@ if (ret != WOLFSSL_SUCCESS) return ret; /* throw error */ - TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.tls1_3) { + OcspRequest* request; + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + + request = &csr->request.ocsp; + ret = CreateOcspResponse(ssl, &request, &csr->response); + if (ret != 0) + return ret; + if (csr->response.buffer) + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + } + else + #endif + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); ssl->status_request = status_type; #endif } @@ -3205,15 +3472,19 @@ return BUFFER_ERROR; ato16(input + offset, &size); + if (length - offset < size) + return BUFFER_ERROR; + offset += OPAQUE16_LEN + size; - /* skip request_extensions */ if (length - offset < OPAQUE16_LEN) return BUFFER_ERROR; ato16(input + offset, &size); + if (length - offset < size) + return BUFFER_ERROR; + offset += OPAQUE16_LEN + size; - if (offset > length) return BUFFER_ERROR; @@ -3432,9 +3703,11 @@ #ifdef HAVE_SUPPORTED_CURVES -#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(WOLFSSL_TLS13) +#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_CURVE448) \ + && !defined(HAVE_FFDHE) #error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ - Use --enable-ecc in the configure script or define HAVE_ECC. + Use --enable-ecc in the configure script or define HAVE_ECC. \ + Alternatively use FFDHE for DH ciperhsuites. #endif static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, @@ -3503,7 +3776,7 @@ while (list) { if (list->name == name) { - ret = 0; /* curve alreay in use */ + ret = 0; /* curve already in use */ break; } @@ -3543,13 +3816,24 @@ static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { - int i; - - for (i = 0; i < ssl->suites->suiteSz; i+= 2) + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE || - ssl->suites->suites[i] == TLS13_BYTE) + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); @@ -3557,13 +3841,24 @@ static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore) { - int i; - - for (i = 0; i < ssl->suites->suiteSz; i+= 2) + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; if (ssl->suites->suites[i] == ECC_BYTE || - ssl->suites->suites[i] == CHACHA_BYTE || - ssl->suites->suites[i] == TLS13_BYTE) + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); @@ -3575,13 +3870,30 @@ static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore) { +#if defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448) + (void)semaphore; +#endif + + if (ssl->options.cipherSuite0 == TLS13_BYTE) + return; if (ssl->options.cipherSuite0 == ECC_BYTE || - ssl->options.cipherSuite0 == CHACHA_BYTE || - ssl->options.cipherSuite0 == TLS13_BYTE) + ssl->options.cipherSuite0 == CHACHA_BYTE) { +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) return; - +#endif + } + else { +#ifdef HAVE_FFDHE + return; +#endif + } + +#if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448)) /* turns semaphore on to avoid sending this extension. */ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +#endif } #endif @@ -3658,8 +3970,13 @@ word16 name; int ret; - if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) + if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) { +#ifdef WOLFSSL_ALLOW_SERVER_SC_EXT + return 0; +#else return BUFFER_ERROR; /* servers doesn't send this extension. */ +#endif + } if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) return BUFFER_ERROR; @@ -3710,8 +4027,9 @@ #endif -#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ - !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +#if !defined(NO_WOLFSSL_SERVER) + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) /* Checks the priority of the groups on the server and set the supported groups * response if there is a group not advertised by the client that is preferred. @@ -3764,6 +4082,128 @@ #endif +#if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12) +/* Set the highest priority common FFDHE group on the server as compared to + * client extensions. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + SupportedCurve* serverGroup; + SupportedCurve* clientGroup; + SupportedCurve* group; + const DhParams* params = NULL; + int found = 0; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + clientGroup = (SupportedCurve*)extension->data; + for (group = clientGroup; group != NULL; group = group->next) { + if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) { + found = 1; + break; + } + } + if (!found) + return 0; + + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ssl->buffers.weOwnDH = 0; + ssl->options.haveDH = 0; + + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + ret = 0; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + serverGroup = (SupportedCurve*)ext->data; + + for (; serverGroup != NULL; serverGroup = serverGroup->next) { + if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK) + continue; + + for (group = clientGroup; group != NULL; group = group->next) { + if (serverGroup->name != group->name) + continue; + + switch (serverGroup->name) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + } + if (params == NULL) + return BAD_FUNC_ARG; + if (params->p_len >= ssl->options.minDhKeySz && + params->p_len <= ssl->options.maxDhKeySz) { + break; + } + } + + if (group != NULL && serverGroup->name == group->name) + break; + } + + if (serverGroup) { + ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p; + ssl->buffers.serverDH_P.length = params->p_len; + ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g; + ssl->buffers.serverDH_G.length = params->g_len; + ssl->namedGroup = serverGroup->name; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 0; + #endif + ssl->options.haveDH = 1; + } + + TLSX_FreeAll(priority, ssl->heap); + + return ret; +} +#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */ + +#endif /* !NO_WOLFSSL_SERVER */ + #if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) /* Return the preferred group. * @@ -3800,7 +4240,7 @@ int ret; /* validating formats list length */ - if (ENUM_LEN > length || length != ENUM_LEN + input[0]) + if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0]) return BUFFER_ERROR; if (isRequest) { @@ -3816,26 +4256,26 @@ return 0; } -#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { - TLSX* extension = (first == ECC_BYTE || first == CHACHA_BYTE) - ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) - : NULL; + TLSX* extension = NULL; SupportedCurve* curve = NULL; - word32 oid = 0; - word32 pkOid = 0; - word32 defOid = 0; - word32 defSz = 80; /* Maximum known curve size is 66. */ - word32 nextOid = 0; - word32 nextSz = 80; /* Maximum known curve size is 66. */ - word32 currOid = ssl->ecdhCurveOID; - int ephmSuite = 0; - word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ - int sig = 0; /* validate signature */ - int key = 0; /* validate key */ + word32 oid = 0; + word32 pkOid = 0; + word32 defOid = 0; + word32 defSz = 80; /* Maximum known curve size is 66. */ + word32 nextOid = 0; + word32 nextSz = 80; /* Maximum known curve size is 66. */ + word32 currOid = ssl->ecdhCurveOID; + int ephmSuite = 0; + word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ + int sig = 0; /* validate signature */ + int key = 0; /* validate key */ (void)oid; + if (first == ECC_BYTE || first == CHACHA_BYTE) + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); if (!extension) return 1; /* no suite restriction */ @@ -3844,6 +4284,10 @@ curve = curve->next) { #ifdef OPENSSL_EXTRA + /* skip if name is not in supported ECC range */ + if (curve->name > WOLFSSL_ECC_X448) + continue; + /* skip if curve is disabled by user */ if (ssl->ctx->disabledCurves & (1 << curve->name)) continue; #endif @@ -3934,6 +4378,19 @@ break; #endif /* HAVE_ECC_BRAINPOOL */ #endif +#endif + #ifdef HAVE_CURVE448 + case WOLFSSL_ECC_X448: + oid = ECC_X448_OID; + #ifdef HAVE_ED448 + pkOid = ECC_ED448_OID; + #else + pkOid = ECC_X448_OID; + #endif + octets = 57; + break; + #endif /* HAVE_CURVE448 */ +#ifdef HAVE_ECC #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP384R1: @@ -3975,6 +4432,7 @@ defSz = octets; } + /* The eccTempKeySz is the preferred ephemeral key size */ if (currOid == 0 && ssl->eccTempKeySz == octets) currOid = oid; if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { @@ -4027,6 +4485,10 @@ defOid = 0; defSz = 80; } + if (oid == ECC_X448_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } sig |= ssl->pkCurveOID == pkOid; key |= ssl->pkCurveOID == oid; break; @@ -4060,6 +4522,10 @@ defOid = 0; defSz = 80; } + if (oid == ECC_X448_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } sig = 1; key |= ssl->pkCurveOID == pkOid; break; @@ -4070,8 +4536,13 @@ defOid = 0; defSz = 80; } - if (oid != ECC_X25519_OID) + if (oid == ECC_X448_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid != ECC_X25519_OID && oid != ECC_X448_OID) { sig = 1; + } key = 1; break; } @@ -4260,7 +4731,7 @@ byte length = OPAQUE8_LEN; /* empty info length */ /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */ - if (data && data->enabled) { + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ length += TLS_FINISHED_SZ; @@ -4276,8 +4747,7 @@ byte* output, int isRequest) { word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */ - - if (data && data->enabled) { + if (data && data->enabled && data->verifySet) { /* client sends client_verify_data only */ XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); offset += TLS_FINISHED_SZ; @@ -4300,39 +4770,48 @@ int ret = SECURE_RENEGOTIATION_E; if (length >= OPAQUE8_LEN) { - if (ssl->secure_renegotiation == NULL) { + if (isRequest) { #ifndef NO_WOLFSSL_SERVER - if (isRequest && *input == 0) { - #ifdef HAVE_SERVER_RENEGOTIATION_INFO - if (length == OPAQUE8_LEN) { - if (TLSX_Find(ssl->extensions, - TLSX_RENEGOTIATION_INFO) == NULL) { - ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, - ssl->heap); - if (ret == WOLFSSL_SUCCESS) - ret = 0; - + if (ssl->secure_renegotiation == NULL) { + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret == WOLFSSL_SUCCESS) + ret = 0; + } + if (ret != 0 && ret != SECURE_RENEGOTIATION_E) { + } + else if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + input++; /* get past size */ + + ssl->secure_renegotiation->enabled = 1; + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; + } + else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data present"); + } + } + else if (*input == TLS_FINISHED_SZ) { + if (length < TLS_FINISHED_SZ + 1) { + WOLFSSL_MSG("SCR malformed buffer"); + ret = BUFFER_E; + } + else { + input++; /* get past size */ + + /* validate client verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client verify data match"); + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; /* verified */ } else { - ret = 0; + /* already in error state */ + WOLFSSL_MSG("SCR client verify data Failure"); } } - #else - ret = 0; /* don't reply, user didn't enable */ - #endif /* HAVE_SERVER_RENEGOTIATION_INFO */ - } - #ifdef HAVE_SERVER_RENEGOTIATION_INFO - else if (!isRequest) { - /* don't do anything on client side */ - ret = 0; - } - #endif - #endif - } - else if (isRequest) { - #ifndef NO_WOLFSSL_SERVER - if (*input == TLS_FINISHED_SZ) { - /* TODO compare client_verify_data */ - ret = 0; } #endif } @@ -4376,7 +4855,7 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap) { int ret = 0; - SecureRenegotiation* data = NULL; + SecureRenegotiation* data; data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap, DYNAMIC_TYPE_TLSX); @@ -4400,12 +4879,15 @@ { int ret; - ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, NULL, heap); - if (ret != 0) - return ret; - /* send empty renegotiation_info extension */ TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + if (ext == NULL) { + ret = TLSX_UseSecureRenegotiation(extensions, heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + } if (ext) ext->resp = 1; @@ -4514,7 +4996,7 @@ /* got actual ticket from client */ ret = DoClientTicket(ssl, input, length); if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */ - WOLFSSL_MSG("Using exisitng client ticket"); + WOLFSSL_MSG("Using existing client ticket"); ssl->options.useTicket = 1; ssl->options.resuming = 1; } else if (ret == WOLFSSL_TICKET_RET_CREATE) { @@ -4559,6 +5041,8 @@ ticket->lifetime = lifetime; } + (void)heap; + return ticket; } WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap) @@ -4735,7 +5219,6 @@ /* write public key list in extension */ -static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output); static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output) { word32 offset = 0; @@ -5127,7 +5610,7 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, void* heap) { - TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + TLSX* extension = NULL; QSHScheme* format = NULL; int ret = 0; @@ -5135,11 +5618,14 @@ if (extensions == NULL || (pKey == NULL && pkeySz != 0)) return BAD_FUNC_ARG; + extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + /* if scheme is implemented than add */ if (TLSX_HaveQSHScheme(name)) { if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0) return ret; + extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); if (!extension) { if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format, heap)) != 0) { @@ -5175,7 +5661,7 @@ #define QSH_GET_SIZE TLSX_QSH_GetSize #define QSH_WRITE TLSX_QSH_Write #else -#define QSH_GET_SIZE(list) 0 +#define QSH_GET_SIZE(list, a) 0 #define QSH_WRITE(a, b) 0 #endif @@ -5199,6 +5685,148 @@ #endif /* HAVE_QSH */ +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) +/******************************************************************************/ +/* Encrypt-then-MAC */ +/******************************************************************************/ + +#ifndef WOLFSSL_NO_TLS12 +static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl); + +/** + * Get the size of the Encrypt-Then-MAC extension. + * + * msgType Type of message to put extension into. + * pSz Size of extension data. + * return SANITY_MSG_E when the message is not allowed to have extension and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_GetSize(byte msgType, word16* pSz) +{ + (void)pSz; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + + return 0; +} + +/** + * Write the Encrypt-Then-MAC extension. + * + * data Unused + * output Extension data buffer. Unused. + * msgType Type of message to put extension into. + * pSz Size of extension data. + * return SANITY_MSG_E when the message is not allowed to have extension and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_Write(void* data, byte* output, byte msgType, + word16* pSz) +{ + (void)data; + (void)output; + (void)pSz; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + + return 0; +} + +/** + * Parse the Encrypt-Then-MAC extension. + * + * ssl SSL object + * input Extension data buffer. + * length Length of this extension's data. + * msgType Type of message to extension appeared in. + * return SANITY_MSG_E when the message is not allowed to have extension, + * BUFFER_ERROR when the extension's data is invalid, + * MEMORY_E when unable to allocate memory and + * 0 otherwise. + */ +static int TLSX_EncryptThenMac_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + (void)input; + + if (msgType != client_hello && msgType != server_hello) { + return SANITY_MSG_E; + } + + /* Empty extension */ + if (length != 0) + return BUFFER_ERROR; + + if (msgType == client_hello) { + /* Check the user hasn't disallowed use of Encrypt-Then-Mac. */ + if (!ssl->options.disallowEncThenMac) { + ssl->options.encThenMac = 1; + /* Set the extension reply. */ + ret = TLSX_EncryptThenMac_Use(ssl); + if (ret != 0) + return ret; + TLSX_SetResponse(ssl, TLSX_ENCRYPT_THEN_MAC); + } + return 0; + } + + /* Server Hello */ + if (ssl->options.disallowEncThenMac) + return SANITY_MSG_E; + + ssl->options.encThenMac = 1; + return 0; + +} + +/** + * Add the Encrypt-Then-MAC extension to list. + * + * ssl SSL object + * return MEMORY_E when unable to allocate memory and 0 otherwise. + */ +static int TLSX_EncryptThenMac_Use(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the Encrypt-Then-Mac extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_ENCRYPT_THEN_MAC); + if (extension == NULL) { + /* Push new Encrypt-Then-Mac extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_ENCRYPT_THEN_MAC, NULL, + ssl->heap); + if (ret != 0) + return ret; + } + + return 0; +} + +#define ETM_GET_SIZE TLSX_EncryptThenMac_GetSize +#define ETM_WRITE TLSX_EncryptThenMac_Write +#define ETM_PARSE TLSX_EncryptThenMac_Parse + +#else + +#define ETM_GET_SIZE(a, b) 0 +#define ETM_WRITE(a, b, c, d) 0 +#define ETM_PARSE(a, b, c, d) 0 + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* HAVE_ENCRYPT_THEN_MAC && !WOLFSSL_AEAD_ONLY */ + /******************************************************************************/ /* Supported Versions */ /******************************************************************************/ @@ -5216,19 +5844,34 @@ if (msgType == client_hello) { /* TLS v1.2 and TLS v1.3 */ - int cnt = 2; + int cnt = 0; + + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + cnt++; + + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + cnt++; +#endif #ifndef NO_OLD_TLS - /* TLS v1.1 */ - cnt++; + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + cnt++; #ifdef WOLFSSL_ALLOW_TLSV10 - /* TLS v1.0 */ - cnt++; - #endif -#endif - - if (!ssl->options.downgrade) - cnt = 1; + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + cnt++; + #endif +#endif + } *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); } @@ -5250,52 +5893,72 @@ * returns the length of data that was written. */ static int TLSX_SupportedVersions_Write(void* data, byte* output, - byte msgType, word16* pSz) + byte msgType, word16* pSz) { WOLFSSL* ssl = (WOLFSSL*)data; - ProtocolVersion pv; - int i; - int cnt; + byte major; + byte* cnt; if (msgType == client_hello) { - pv = ssl->ctx->method->version; - /* TLS v1.2 and TLS v1.3 */ - cnt = 2; - -#ifndef NO_OLD_TLS - /* TLS v1.1 */ - cnt++; - #ifdef WOLFSSL_ALLOW_TLSV10 - /* TLS v1.0 */ - cnt++; - #endif -#endif - - if (!ssl->options.downgrade) - cnt = 1; - - *(output++) = (byte)(cnt * OPAQUE16_LEN); - for (i = 0; i < cnt; i++) { -#ifndef WOLFSSL_TLS13_FINAL - /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ - if (pv.minor - i == TLSv1_3_MINOR) { + major = ssl->ctx->method->version.major; + + + cnt = output++; + *cnt = 0; + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + { + *cnt += OPAQUE16_LEN; +#ifdef WOLFSSL_TLS13_DRAFT /* The TLS draft major number. */ *(output++) = TLS_DRAFT_MAJOR; /* Version of draft supported. */ *(output++) = TLS_DRAFT_MINOR; - continue; +#else + *(output++) = major; + *(output++) = (byte)TLSv1_3_MINOR; +#endif + } + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_2_MINOR; } #endif - *(output++) = pv.major; - *(output++) = (byte)(pv.minor - i); - } - - *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); +#ifndef NO_OLD_TLS + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_1_MINOR; + } + #ifdef WOLFSSL_ALLOW_TLSV10 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_MINOR; + } + #endif +#endif + } + + *pSz += (word16)(OPAQUE8_LEN + *cnt); } #ifndef WOLFSSL_TLS13_DRAFT_18 else if (msgType == server_hello || msgType == hello_retry_request) { - #ifndef WOLFSSL_TLS13_FINAL + #ifdef WOLFSSL_TLS13_DRAFT if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor == TLSv1_3_MINOR) { output[0] = TLS_DRAFT_MAJOR; @@ -5333,6 +5996,7 @@ int len; byte major, minor; int newMinor = 0; + int set = 0; if (msgType == client_hello) { /* Must contain a length and at least one version. */ @@ -5342,7 +6006,7 @@ len = *input; /* Protocol version array must fill rest of data. */ - if (length != OPAQUE8_LEN + len) + if (length != (word16)OPAQUE8_LEN + len) return BUFFER_ERROR; input++; @@ -5352,12 +6016,14 @@ major = input[i]; minor = input[i + OPAQUE8_LEN]; -#ifndef WOLFSSL_TLS13_FINAL - /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ +#ifdef WOLFSSL_TLS13_DRAFT if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { major = SSLv3_MAJOR; minor = TLSv1_3_MINOR; } +#else + if (major == TLS_DRAFT_MAJOR) + continue; #endif if (major != pv.major) @@ -5396,6 +6062,16 @@ } else if (minor > ssl->options.oldMinor) ssl->options.oldMinor = minor; + + set = 1; + } + if (!set) { + #ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); + #else + SendAlert(ssl, alert_fatal, protocol_version); + #endif + return VERSION_ERROR; } } #ifndef WOLFSSL_TLS13_DRAFT_18 @@ -5407,8 +6083,7 @@ major = input[0]; minor = input[OPAQUE8_LEN]; - #ifndef WOLFSSL_TLS13_FINAL - /* TODO: [TLS13] Remove code when TLS v1.3 becomes an RFC. */ + #ifdef WOLFSSL_TLS13_DRAFT if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { major = SSLv3_MAJOR; minor = TLSv1_3_MINOR; @@ -5523,7 +6198,8 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, word16* pSz) +static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, + word16* pSz) { if (msgType == client_hello || msgType == hello_retry_request) { c16toa(cookie->len, output); @@ -5644,7 +6320,7 @@ #define CKE_PARSE(a, b, c, d) 0 #endif - +#if !defined(WOLFSSL_NO_SIGALG) /******************************************************************************/ /* Signature Algorithms */ /******************************************************************************/ @@ -5654,6 +6330,7 @@ * data Unused * returns the length of data that will be in the extension. */ + static word16 TLSX_SignatureAlgorithms_GetSize(void* data) { WOLFSSL* ssl = (WOLFSSL*)data; @@ -5683,6 +6360,12 @@ for (i = 0; i < length; i += 2) { if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac) ssl->pssAlgo |= 1 << input[i + 1]; + #ifdef WOLFSSL_TLS13 + if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 && + input[i + 1] <= pss_sha512) { + ssl->pssAlgo |= 1 << input[i + 1]; + } + #endif } return 0; @@ -5764,7 +6447,7 @@ #define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize #define SA_WRITE TLSX_SignatureAlgorithms_Write #define SA_PARSE TLSX_SignatureAlgorithms_Parse - +#endif /******************************************************************************/ /* Signature Algorithms Certificate */ /******************************************************************************/ @@ -6028,8 +6711,8 @@ curve25519_key* key; /* Allocate an ECC key to hold private key. */ - key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), - ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); if (key == NULL) { WOLFSSL_MSG("EccTempKey Memory error"); return MEMORY_E; @@ -6086,6 +6769,80 @@ return ret; } +/* Create a key share entry using X448 parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenX448Key(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifdef HAVE_CURVE448 + byte* keyData = NULL; + word32 dataSize = CURVE448_KEY_SIZE; + curve448_key* key; + + /* Allocate an ECC key to hold private key. */ + key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* 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, + DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_curve448_export_public_ex(key, keyData, &dataSize, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->pubKey = keyData; + kse->pubKeyLen = CURVE448_KEY_SIZE; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public Curve448 Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#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); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_CURVE448 */ + + return ret; +} + /* Create a key share entry using named elliptic curve parameters group. * Generates a key pair. * @@ -6220,6 +6977,8 @@ 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); } @@ -6240,13 +6999,19 @@ 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 (current->key != NULL) + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY); XFREE(current, heap, DYNAMIC_TYPE_TLSX); @@ -6263,7 +7028,7 @@ */ static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) { - int len = 0; + word16 len = 0; byte isRequest = (msgType == client_hello); KeyShareEntry* current; @@ -6280,10 +7045,10 @@ if (!isRequest && current->key == NULL) continue; - len += (int)(KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen); - } - - return (word16)len; + len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen; + } + + return len; } /* Writes the key share extension into the output buffer. @@ -6425,14 +7190,34 @@ #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 + ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#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; + XMEMMOVE(ssl->arrays->preMasterSecret + diff, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + XMEMSET(ssl->arrays->preMasterSecret, 0, diff); + ssl->arrays->preMasterSz = params->p_len; + } + + ssl->options.dhKeySz = 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); + keyShareEntry->key = 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 @@ -6480,15 +7265,20 @@ WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); #endif - /* Point is validated by import function. */ - if (wc_curve25519_import_public_ex(keyShareEntry->ke, keyShareEntry->keLen, - peerX25519Key, + if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen, EC25519_LITTLE_ENDIAN) != 0) { ret = ECC_PEERKEY_ERROR; } if (ret == 0) { - ssl->arrays->preMasterSz = ENCRYPT_LEN; + if (wc_curve25519_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { ssl->ecdhCurveOID = ECC_X25519_OID; ret = wc_curve25519_shared_secret_ex(key, peerX25519Key, @@ -6496,8 +7286,14 @@ &ssl->arrays->preMasterSz, EC25519_LITTLE_ENDIAN); } + wc_curve25519_free(peerX25519Key); XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX); + wc_curve25519_free((curve25519_key*)keyShareEntry->key); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } #else (void)ssl; (void)keyShareEntry; @@ -6508,6 +7304,82 @@ return ret; } +/* Process the X448 key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessX448(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_CURVE448 + curve448_key* key = (curve448_key*)keyShareEntry->key; + curve448_key* peerX448Key; + +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKey = NULL; + } +#endif + + peerX448Key = (curve448_key*)XMALLOC(sizeof(curve448_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (peerX448Key == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve448_init(peerX448Key); + if (ret != 0) { + XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer Curve448 Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + if (wc_curve448_check_public(keyShareEntry->ke, keyShareEntry->keLen, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + + if (ret == 0) { + if (wc_curve448_import_public_ex(keyShareEntry->ke, + keyShareEntry->keLen, peerX448Key, + EC448_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X448_OID; + + ret = wc_curve448_shared_secret_ex(key, peerX448Key, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + EC448_LITTLE_ENDIAN); + } + + wc_curve448_free(peerX448Key); + XFREE(peerX448Key, ssl->heap, DYNAMIC_TYPE_TLSX); + wc_curve448_free((curve448_key*)keyShareEntry->key); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_CURVE448 */ + + return ret; +} + /* Process the ECC key share extension on the client side. * * ssl The SSL/TLS object. @@ -6580,7 +7452,6 @@ } ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; - ssl->arrays->preMasterSz = ENCRYPT_LEN; do { #if defined(WOLFSSL_ASYNC_CRYPT) ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); @@ -6599,6 +7470,14 @@ ); #endif + 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); + keyShareEntry->key = NULL; + } #else (void)ssl; @@ -6628,6 +7507,8 @@ ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry); else if (keyShareEntry->group == WOLFSSL_ECC_X25519) ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); + else if (keyShareEntry->group == WOLFSSL_ECC_X448) + ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry); else ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); @@ -6665,7 +7546,9 @@ /* Key exchange data - public key. */ ato16(&input[offset], &keLen); offset += OPAQUE16_LEN; - if (keLen < 1 || keLen > length - offset) + if (keLen == 0) + return INVALID_PARAMETER; + if (keLen > length - offset) return BUFFER_ERROR; /* Store a copy in the key share object. */ @@ -6760,7 +7643,7 @@ byte msgType) { int ret; - KeyShareEntry *keyShareEntry; + KeyShareEntry *keyShareEntry = NULL; word16 group; if (msgType == client_hello) { @@ -6786,8 +7669,8 @@ return BUFFER_ERROR; offset += OPAQUE16_LEN; - while (offset < length) { - ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length, + while (offset < (int)length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset, &keyShareEntry); if (ret < 0) return ret; @@ -6816,11 +7699,11 @@ /* ServerHello contains one key share entry. */ len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); - if (len != length) + if (len != (int)length) return BUFFER_ERROR; /* Not in list sent if there isn't a private key. */ - if (keyShareEntry->key == NULL) + if (keyShareEntry == NULL || keyShareEntry->key == NULL) return BAD_KEY_SHARE_DATA; /* Process the entry to calculate the secret. */ @@ -6871,6 +7754,7 @@ KeyShareEntry** keyShareEntry) { KeyShareEntry* kse; + KeyShareEntry** next; kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, DYNAMIC_TYPE_TLSX); @@ -6881,8 +7765,11 @@ kse->group = (word16)group; /* Add it to the back and maintain the links. */ - while (*list != NULL) - list = &((*list)->next); + while (*list != NULL) { + /* Assign to temporary to work around compiler bug found by customer. */ + next = &((*list)->next); + list = next; + } *list = kse; *keyShareEntry = kse; @@ -6938,6 +7825,9 @@ } if (data != NULL) { + if (keyShareEntry->ke != NULL) { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } keyShareEntry->ke = data; keyShareEntry->keLen = len; } @@ -7016,6 +7906,10 @@ case WOLFSSL_ECC_X25519: break; #endif + #ifdef HAVE_CURVE448 + case WOLFSSL_ECC_X448: + break; + #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP case WOLFSSL_ECC_SECP384R1: @@ -7028,10 +7922,6 @@ break; #endif /* !NO_ECC_SECP */ #endif - #ifdef HAVE_X448 - case WOLFSSL_ECC_X448: - break; - #endif default: return 0; } @@ -7064,6 +7954,11 @@ ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519; #endif #endif + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE448) + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X448; + #endif + #endif #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP @@ -7095,7 +7990,7 @@ } for (i = 0; i < ssl->numGroups; i++) - if (ssl->group[i] == group) + if (ssl->group[i] == (word16)group) return i; return -1; @@ -7150,7 +8045,7 @@ if (ret != 0) return ret; - /* Set extension to be in reponse. */ + /* Set extension to be in response. */ extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); extension->resp = 1; #else @@ -7327,7 +8222,8 @@ * returns the number of bytes of the encoded pre-shared key extension or * SANITY_MSG_E to indicate invalid message type. */ -static word16 TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType) +static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType, + word16* pSz) { if (msgType == client_hello) { /* Length of identities + Length of binders. */ @@ -7338,14 +8234,16 @@ OPAQUE8_LEN + list->binderLen; list = list->next; } - return len; + *pSz += len; + return 0; } if (msgType == server_hello) { - return OPAQUE16_LEN; - } - - return 0; + *pSz += OPAQUE16_LEN; + return 0; + } + + return SANITY_MSG_E; } /* The number of bytes to be written for the binders. @@ -7355,7 +8253,8 @@ * returns the number of bytes of the encoded pre-shared key extension or * SANITY_MSG_E to indicate invalid message type. */ -word16 TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType) +int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, + word16* pSz) { word16 len; @@ -7369,7 +8268,8 @@ list = list->next; } - return len; + *pSz = len; + return 0; } /* Writes the pre-shared key extension into the output buffer - binders only. @@ -7380,8 +8280,8 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -word16 TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, - byte msgType) +int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) { PreSharedKey* current = list; word16 idx = 0; @@ -7407,7 +8307,8 @@ len = idx - lenIdx - OPAQUE16_LEN; c16toa(len, output + lenIdx); - return idx; + *pSz = idx; + return 0; } @@ -7419,14 +8320,15 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -static word16 TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, - byte msgType) +static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) { if (msgType == client_hello) { PreSharedKey* current = list; word16 idx = 0; word16 lenIdx; word16 len; + int ret; /* Write identites only. Binders after HMACing over this. */ lenIdx = idx; @@ -7453,12 +8355,12 @@ * The binders are based on the hash of all the ClientHello data up to * and include the identities written above. */ - idx += TLSX_PreSharedKey_GetSizeBinders(list, msgType); - - return idx; - } - - if (msgType == server_hello) { + ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len); + if (ret < 0) + return ret; + *pSz += idx + len; + } + else if (msgType == server_hello) { word16 i; /* Find the index of the chosen identity. */ @@ -7471,8 +8373,10 @@ * by the client. */ c16toa(i, output); - return OPAQUE16_LEN; - } + *pSz += OPAQUE16_LEN; + } + else + return SANITY_MSG_E; return 0; } @@ -7521,7 +8425,8 @@ /* Length of identity. */ ato16(input + idx, &identityLen); idx += OPAQUE16_LEN; - if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN) + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN || + identityLen > MAX_PSK_ID_LEN) return BUFFER_E; /* Cache identity pointer. */ identity = input + idx; @@ -7546,6 +8451,8 @@ list = (PreSharedKey*)extension->data; /* Length of binders. */ + if (idx + OPAQUE16_LEN > length) + return BUFFER_E; ato16(input + idx, &len); idx += OPAQUE16_LEN; if (len < MIN_PSK_BINDERS_LEN || length - idx < len) @@ -7634,6 +8541,7 @@ PreSharedKey** preSharedKey) { PreSharedKey* psk; + PreSharedKey** next; psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX); if (psk == NULL) @@ -7650,11 +8558,16 @@ psk->identityLen = len; /* Add it to the end and maintain the links. */ - while (*list != NULL) - list = &((*list)->next); + while (*list != NULL) { + /* Assign to temporary to work around compiler bug found by customer. */ + next = &((*list)->next); + list = next; + } *list = psk; *preSharedKey = psk; + (void)heap; + return 0; } @@ -7752,8 +8665,8 @@ #else #define PSK_FREE_ALL(a, b) -#define PSK_GET_SIZE(a, b) 0 -#define PSK_WRITE(a, b, c) 0 +#define PSK_GET_SIZE(a, b, c) 0 +#define PSK_WRITE(a, b, c, d) 0 #define PSK_PARSE(a, b, c, d) 0 #endif @@ -7770,7 +8683,7 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes of the encoded PSK KE mode extension. */ -static word16 TLSX_PskKeModes_GetSize(byte modes, byte msgType) +static int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz) { if (msgType == client_hello) { /* Format: Len | Modes* */ @@ -7780,7 +8693,8 @@ len += OPAQUE8_LEN; if (modes & (1 << PSK_DHE_KE)) len += OPAQUE8_LEN; - return len; + *pSz += len; + return 0; } return SANITY_MSG_E; @@ -7795,7 +8709,8 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -static word16 TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType) +static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, + word16* pSz) { if (msgType == client_hello) { /* Format: Len | Modes* */ @@ -7809,7 +8724,8 @@ /* Write out length of mode list. */ output[0] = idx - OPAQUE8_LEN; - return idx; + *pSz += idx; + return 0; } return SANITY_MSG_E; @@ -7832,7 +8748,7 @@ if (msgType == client_hello) { /* Format: Len | Modes* */ int idx = 0; - int len; + word16 len; byte modes = 0; /* Ensure length byte exists. */ @@ -7900,8 +8816,8 @@ #else -#define PKM_GET_SIZE(a, b) 0 -#define PKM_WRITE(a, b, c) 0 +#define PKM_GET_SIZE(a, b, c) 0 +#define PKM_WRITE(a, b, c, d) 0 #define PKM_PARSE(a, b, c, d) 0 #endif @@ -7911,17 +8827,19 @@ /******************************************************************************/ #if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) -/* Get the size of the encoded Post-Hanshake Authentication extension. +/* Get the size of the encoded Post-Handshake Authentication extension. * Only in ClientHello. * * msgType The type of the message this extension is being written into. - * returns the number of bytes of the encoded Post-Hanshake Authentication + * returns the number of bytes of the encoded Post-Handshake Authentication * extension. */ -static word16 TLSX_PostHandAuth_GetSize(byte msgType) -{ - if (msgType == client_hello) +static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + *pSz += 0; return 0; + } return SANITY_MSG_E; } @@ -7934,12 +8852,14 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -static word16 TLSX_PostHandAuth_Write(byte* output, byte msgType) +static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz) { (void)output; - if (msgType == client_hello) + if (msgType == client_hello) { + *pSz += 0; return 0; + } return SANITY_MSG_E; } @@ -7999,8 +8919,8 @@ #else -#define PHA_GET_SIZE(a) 0 -#define PHA_WRITE(a, b) 0 +#define PHA_GET_SIZE(a, b) 0 +#define PHA_WRITE(a, b, c) 0 #define PHA_PARSE(a, b, c, d) 0 #endif @@ -8016,14 +8936,18 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes of the encoded Early Data Indication extension. */ -static word16 TLSX_EarlyData_GetSize(byte msgType) -{ +static int TLSX_EarlyData_GetSize(byte msgType, word16* pSz) +{ + int ret = 0; + if (msgType == client_hello || msgType == encrypted_extensions) - return 0; - if (msgType == session_ticket) - return OPAQUE32_LEN; - - return SANITY_MSG_E; + *pSz += 0; + else if (msgType == session_ticket) + *pSz += OPAQUE32_LEN; + else + ret = SANITY_MSG_E; + + return ret; } /* Writes the Early Data Indicator extension into the output buffer. @@ -8035,14 +8959,15 @@ * msgType The type of the message this extension is being written into. * returns the number of bytes written into the buffer. */ -static word16 TLSX_EarlyData_Write(word32 max, byte* output, byte msgType) -{ - if (msgType == client_hello || msgType == encrypted_extensions) { +static int TLSX_EarlyData_Write(word32 max, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello || msgType == encrypted_extensions) return 0; - } - if (msgType == session_ticket) { + else if (msgType == session_ticket) { c32toa(max, output); - return OPAQUE32_LEN; + *pSz += OPAQUE32_LEN; + return 0; } return SANITY_MSG_E; @@ -8064,7 +8989,10 @@ if (length != 0) return BUFFER_E; - return TLSX_EarlyData_Use(ssl, 0); + if (ssl->earlyData == expecting_early_data) + return TLSX_EarlyData_Use(ssl, 0); + ssl->earlyData = early_data_ext; + return 0; } if (msgType == encrypted_extensions) { if (length != 0) @@ -8079,13 +9007,13 @@ return TLSX_EarlyData_Use(ssl, 1); } if (msgType == session_ticket) { - word32 max; + word32 maxSz; if (length != OPAQUE32_LEN) return BUFFER_E; - ato32(input, &max); - - ssl->session.maxEarlyDataSz = max; + ato32(input, &maxSz); + + ssl->session.maxEarlyDataSz = maxSz; return 0; } @@ -8128,8 +9056,8 @@ #else -#define EDI_GET_SIZE(a) 0 -#define EDI_WRITE(a, b, c) 0 +#define EDI_GET_SIZE(a, b) 0 +#define EDI_WRITE(a, b, c, d) 0 #define EDI_PARSE(a, b, c, d) 0 #endif @@ -8181,6 +9109,10 @@ SNI_FREE_ALL((SNI*)extension->data, heap); break; + case TLSX_TRUSTED_CA_KEYS: + TCA_FREE_ALL((TCA*)extension->data, heap); + break; + case TLSX_MAX_FRAGMENT_LENGTH: MFL_FREE_ALL(extension->data, heap); break; @@ -8221,10 +9153,14 @@ case TLSX_APPLICATION_LAYER_PROTOCOL: ALPN_FREE_ALL((ALPN*)extension->data, heap); break; - +#if !defined(WOLFSSL_NO_SIGALG) case TLSX_SIGNATURE_ALGORITHMS: break; - +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + break; +#endif #ifdef WOLFSSL_TLS13 case TLSX_SUPPORTED_VERSIONS: break; @@ -8275,7 +9211,8 @@ } /** Tells the buffered size of the extensions in a list. */ -static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, word16* pLength) +static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, + word16* pLength) { int ret = 0; TLSX* extension; @@ -8306,6 +9243,12 @@ length += SNI_GET_SIZE((SNI*)extension->data); break; + case TLSX_TRUSTED_CA_KEYS: + /* TCA only sends the list on the request. */ + if (isRequest) + length += TCA_GET_SIZE((TCA*)extension->data); + break; + case TLSX_MAX_FRAGMENT_LENGTH: length += MFL_GET_SIZE(extension->data); break; @@ -8350,11 +9293,16 @@ case TLSX_APPLICATION_LAYER_PROTOCOL: length += ALPN_GET_SIZE((ALPN*)extension->data); break; - +#if !defined(WOLFSSL_NO_SIGALG) case TLSX_SIGNATURE_ALGORITHMS: length += SA_GET_SIZE(extension->data); break; - +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + ret = ETM_GET_SIZE(msgType, &length); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ #ifdef WOLFSSL_TLS13 case TLSX_SUPPORTED_VERSIONS: ret = SV_GET_SIZE(extension->data, msgType, &length); @@ -8366,23 +9314,24 @@ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: - length += PSK_GET_SIZE((PreSharedKey*)extension->data, msgType); + ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType, + &length); break; case TLSX_PSK_KEY_EXCHANGE_MODES: - length += PKM_GET_SIZE(extension->val, msgType); + ret = PKM_GET_SIZE(extension->val, msgType, &length); break; #endif #ifdef WOLFSSL_EARLY_DATA case TLSX_EARLY_DATA: - length += EDI_GET_SIZE(msgType); + ret = EDI_GET_SIZE(msgType, &length); break; #endif #ifdef WOLFSSL_POST_HANDSHAKE_AUTH case TLSX_POST_HANDSHAKE_AUTH: - length += PHA_GET_SIZE(msgType); + ret = PHA_GET_SIZE(msgType, &length); break; #endif @@ -8444,6 +9393,13 @@ } break; + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA Indication extension to write"); + if (isRequest) { + offset += TCA_WRITE((TCA*)extension->data, output + offset); + } + break; + case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension to write"); offset += MFL_WRITE((byte*)extension->data, output + offset); @@ -8504,12 +9460,18 @@ WOLFSSL_MSG("ALPN extension to write"); offset += ALPN_WRITE((ALPN*)extension->data, output + offset); break; - +#if !defined(WOLFSSL_NO_SIGALG) case TLSX_SIGNATURE_ALGORITHMS: WOLFSSL_MSG("Signature Algorithms extension to write"); offset += SA_WRITE(extension->data, output + offset); break; - +#endif +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + WOLFSSL_MSG("Encrypt-Then-Mac extension to write"); + ret = ETM_WRITE(extension->data, output, msgType, &offset); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ #ifdef WOLFSSL_TLS13 case TLSX_SUPPORTED_VERSIONS: WOLFSSL_MSG("Supported Versions extension to write"); @@ -8525,27 +9487,29 @@ #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension to write"); - offset += PSK_WRITE((PreSharedKey*)extension->data, - output + offset, msgType); + ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset, + msgType, &offset); break; case TLSX_PSK_KEY_EXCHANGE_MODES: WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); - offset += PKM_WRITE(extension->val, output + offset, msgType); + ret = PKM_WRITE(extension->val, output + offset, msgType, + &offset); break; #endif #ifdef WOLFSSL_EARLY_DATA case TLSX_EARLY_DATA: WOLFSSL_MSG("Early Data extension to write"); - offset += EDI_WRITE(extension->val, output + offset, msgType); + ret = EDI_WRITE(extension->val, output + offset, msgType, + &offset); break; #endif #ifdef WOLFSSL_POST_HANDSHAKE_AUTH case TLSX_POST_HANDSHAKE_AUTH: WOLFSSL_MSG("Post-Handshake Authentication extension to write"); - offset += PHA_WRITE(output + offset, msgType); + ret = PHA_WRITE(output + offset, msgType, &offset); break; #endif @@ -8559,7 +9523,7 @@ case TLSX_KEY_SHARE: WOLFSSL_MSG("Key Share extension to write"); offset += KS_WRITE((KeyShareEntry*)extension->data, - output + offset, msgType); + output + offset, msgType); break; #endif } @@ -8613,7 +9577,7 @@ #ifdef HAVE_QSH static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) { - int ret; + int ret = -1; (void)ssl; @@ -8627,7 +9591,7 @@ #endif default: WOLFSSL_MSG("Unknown type for creating NTRU key"); - return -1; + break; } return ret; @@ -8770,11 +9734,12 @@ #if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ - (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && \ - !defined(HAVE_CURVE25519) && defined(HAVE_SUPPORTED_CURVES)) || \ - ((defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ - defined(HAVE_SUPPORTED_CURVES)) - + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) \ + && !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES)) + +/* Populates the default supported groups / curves */ static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) { int ret = WOLFSSL_SUCCESS; @@ -8799,7 +9764,98 @@ #endif /* WOLFSSL_TLS13 */ #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + /* list in order by strength, since not all servers choose by strength */ + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE448) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X448, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #ifndef HAVE_FIPS + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP ret = TLSX_UseSupportedCurve(extensions, @@ -8817,124 +9873,55 @@ if (ret != WOLFSSL_SUCCESS) return ret; #endif #endif - #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP192R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP192K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif - #endif - #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP + #endif /* HAVE_FIPS */ +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_8192 + if (8192/8 >= ssl->options.minDhKeySz && + 8192/8 <= ssl->options.maxDhKeySz) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP224R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP224K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif -#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ - - #ifndef HAVE_FIPS - #if defined(HAVE_CURVE25519) + #ifdef HAVE_FFDHE_6144 + if (6144/8 >= ssl->options.minDhKeySz && + 6144/8 <= ssl->options.maxDhKeySz) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_X25519, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif /* HAVE_FIPS */ - -#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) - #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) - #ifdef HAVE_ECC_KOBLITZ - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP256K1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif - #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP + #ifdef HAVE_FFDHE_4096 + if (4096/8 >= ssl->options.minDhKeySz && + 4096/8 <= ssl->options.maxDhKeySz) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_ECC_BRAINPOOL - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif - #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) - #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_FFDHE_3072 + if (3072/8 >= ssl->options.minDhKeySz && + 3072/8 <= ssl->options.maxDhKeySz) { ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } #endif - #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) - #ifndef NO_ECC_SECP - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_ECC_SECP521R1, ssl->heap); - if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #endif -#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ - - #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version)) { - /* Add FFDHE supported groups. */ #ifdef HAVE_FFDHE_2048 + if (2048/8 >= ssl->options.minDhKeySz && + 2048/8 <= ssl->options.maxDhKeySz) { ret = TLSX_UseSupportedCurve(extensions, WOLFSSL_FFDHE_2048, ssl->heap); if (ret != WOLFSSL_SUCCESS) return ret; - #endif - #ifdef HAVE_FFDHE_3072 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_3072, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_4096 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_4096, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; + } #endif - #ifdef HAVE_FFDHE_6144 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_6144, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - #ifdef HAVE_FFDHE_8192 - ret = TLSX_UseSupportedCurve(extensions, - WOLFSSL_FFDHE_8192, ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - #endif - } - #endif /* WOLFSSL_TLS13 */ (void)ssl; (void)extensions; @@ -8961,7 +9948,7 @@ WOLFSSL_MSG("Adding supported QSH Schemes"); #endif - /* server will add extension depending on whats parsed from client */ + /* server will add extension depending on what is parsed from client */ if (!isServer) { #ifdef HAVE_QSH /* test if user has set a specific scheme already */ @@ -9035,45 +10022,44 @@ } #endif -#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ - defined(HAVE_SUPPORTED_CURVES) +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + if (!ssl->options.disallowEncThenMac) { + ret = TLSX_EncryptThenMac_Use(ssl); + if (ret != 0) + return ret; + } +#endif + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + defined(HAVE_CURVE448)) && defined(HAVE_SUPPORTED_CURVES) if (!ssl->options.userCurves && !ssl->ctx->userCurves) { if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); if (ret != WOLFSSL_SUCCESS) return ret; - if (!IsAtLeastTLSv1_3(ssl->version) && - TLSX_Find(ssl->ctx->extensions, - TLSX_EC_POINT_FORMATS) == NULL && - TLSX_Find(ssl->extensions, - TLSX_EC_POINT_FORMATS) == NULL) { - ret = TLSX_UsePointFormat(&ssl->extensions, - WOLFSSL_EC_PF_UNCOMPRESSED, - ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } } - else if (!IsAtLeastTLSv1_3(ssl->version) && - TLSX_Find(ssl->ctx->extensions, - TLSX_EC_POINT_FORMATS) == NULL) { - ret = TLSX_UsePointFormat(&ssl->ctx->extensions, - WOLFSSL_EC_PF_UNCOMPRESSED, - ssl->heap); - if (ret != WOLFSSL_SUCCESS) - return ret; - } - } -#endif /* (HAVE_ECC || HAVE_CURVE25519) && HAVE_SUPPORTED_CURVES */ + } + if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) && + TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL && + TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) { + ret = TLSX_UsePointFormat(&ssl->extensions, + WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } +#endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ } /* is not server */ +#if !defined(WOLFSSL_NO_SIGALG) WOLFSSL_MSG("Adding signature algorithms extension"); if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) != 0) { return ret; } - +#else + ret = 0; +#endif #ifdef WOLFSSL_TLS13 if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { /* Add mandatory TLS v1.3 extension: supported version */ @@ -9084,7 +10070,7 @@ } #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \ - defined(HAVE_SUPPORTED_CURVES) + !defined(HAVE_CURVE448) && defined(HAVE_SUPPORTED_CURVES) if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { /* Put in DH groups for TLS 1.3 only. */ ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); @@ -9092,7 +10078,7 @@ return ret; ret = 0; } - #endif /* !HAVE_ECC && !HAVE_CURVE25519 && HAVE_SUPPORTED_CURVES */ + #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */ #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) if (ssl->certHashSigAlgoSz > 0) { @@ -9118,6 +10104,8 @@ namedGroup = WOLFSSL_ECC_SECP256R1; #elif defined(HAVE_CURVE25519) namedGroup = WOLFSSL_ECC_X25519; + #elif defined(HAVE_CURVE448) + namedGroup = WOLFSSL_ECC_X448; #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \ defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) namedGroup = WOLFSSL_ECC_SECP384R1; @@ -9151,6 +10139,11 @@ WOLFSSL_SESSION* sess = &ssl->session; word32 milli; + if (sess->ticketLen > MAX_PSK_ID_LEN) { + WOLFSSL_MSG("Session ticket length for PSK ext is too large"); + return BUFFER_ERROR; + } + /* Determine the MAC algorithm for the cipher suite used. */ ssl->options.cipherSuite0 = sess->cipherSuite0; ssl->options.cipherSuite = sess->cipherSuite; @@ -9172,14 +10165,28 @@ } #endif #ifndef NO_PSK - if (ssl->options.client_psk_cb != NULL) { + if (ssl->options.client_psk_cb != NULL || + ssl->options.client_psk_tls13_cb != NULL) { /* Default ciphersuite. */ byte cipherSuite0 = TLS13_BYTE; byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; - - ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + const char* cipherName = NULL; + + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, ssl->arrays->server_hint, ssl->arrays->client_identity, MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + } if (ssl->arrays->psk_keySz == 0 || ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { return PSK_KEY_ERROR; @@ -9210,7 +10217,8 @@ /* Pre-shared key modes: mandatory extension for resumption. */ modes = 1 << PSK_KE; - #if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) + #if !defined(NO_DH) || defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519) || defined(HAVE_CURVE448) if (!ssl->options.noPskDheKe) modes |= 1 << PSK_DHE_KE; #endif @@ -9255,8 +10263,10 @@ PF_VALIDATE_REQUEST(ssl, semaphore); QSH_VALIDATE_REQUEST(ssl, semaphore); WOLF_STK_VALIDATE_REQUEST(ssl); +#if !defined(WOLFSSL_NO_SIGALG) if (ssl->suites->hashSigAlgoSz == 0) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif #if defined(WOLFSSL_TLS13) if (!IsAtLeastTLSv1_2(ssl)) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); @@ -9274,18 +10284,6 @@ TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); #endif } - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.noPskDheKe) { - #if !defined(NO_PSK) - if (ssl->options.havePSK) - TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #endif - #if defined(HAVE_SESSION_TICKET) - if (ssl->options.resuming) - TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #endif - } - #endif #endif #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) @@ -9296,11 +10294,14 @@ } #endif } + #ifdef WOLFSSL_TLS13 #ifndef NO_CERTS else if (msgType == certificate_request) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); +#if !defined(WOLFSSL_NO_SIGALG) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS * TLSX_STATUS_REQUEST @@ -9308,15 +10309,20 @@ } #endif #endif - - if (ssl->extensions) + if (ssl->extensions) { ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); - if (ssl->ctx && ssl->ctx->extensions) + if (ret != 0) + return ret; + } + if (ssl->ctx && ssl->ctx->extensions) { ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } #ifdef HAVE_EXTENDED_MASTER if (msgType == client_hello && ssl->options.haveEMS && - !IsAtLeastTLSv1_3(ssl->version)) { + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { length += HELLO_EXT_SZ; } #endif @@ -9346,8 +10352,10 @@ PF_VALIDATE_REQUEST(ssl, semaphore); WOLF_STK_VALIDATE_REQUEST(ssl); QSH_VALIDATE_REQUEST(ssl, semaphore); +#if !defined(WOLFSSL_NO_SIGALG) if (ssl->suites->hashSigAlgoSz == 0) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif #ifdef WOLFSSL_TLS13 if (!IsAtLeastTLSv1_2(ssl)) TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); @@ -9365,18 +10373,6 @@ #endif } #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) - if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.noPskDheKe) { - #if !defined(NO_PSK) - if (ssl->options.havePSK) - TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #endif - #if defined(HAVE_SESSION_TICKET) - if (ssl->options.resuming) - TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); - #endif - } - #endif - #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) /* Must write Pre-shared Key extension at the end in TLS v1.3. * Must not write out Pre-shared Key extension in earlier versions of * protocol. @@ -9394,10 +10390,12 @@ #endif } #ifdef WOLFSSL_TLS13 - #ifndef NO_CERT + #ifndef NO_CERTS else if (msgType == certificate_request) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); +#if !defined(WOLFSSL_NO_SIGALG) TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS * TLSX_STATUS_REQUEST @@ -9405,19 +10403,23 @@ } #endif #endif - if (ssl->extensions) { ret = TLSX_Write(ssl->extensions, output + offset, semaphore, msgType, &offset); + if (ret != 0) + return ret; } if (ssl->ctx && ssl->ctx->extensions) { ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore, msgType, &offset); + if (ret != 0) + return ret; } #ifdef HAVE_EXTENDED_MASTER if (msgType == client_hello && ssl->options.haveEMS && - !IsAtLeastTLSv1_3(ssl->version)) { + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { + WOLFSSL_MSG("EMS extension to write"); c16toa(HELLO_EXT_EXTMS, output + offset); offset += HELLO_EXT_TYPE_SZ; c16toa(0, output + offset); @@ -9432,6 +10434,8 @@ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); ret = TLSX_Write(ssl->extensions, output + offset, semaphore, client_hello, &offset); + if (ret != 0) + return ret; } #endif #endif @@ -9460,7 +10464,7 @@ case server_hello: PF_VALIDATE_RESPONSE(ssl, semaphore); #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { + if (IsAtLeastTLSv1_3(ssl->version)) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, @@ -9505,6 +10509,9 @@ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #endif break; #ifdef WOLFSSL_EARLY_DATA @@ -9519,7 +10526,7 @@ #endif #ifdef WOLFSSL_TLS13 - #ifndef NO_CERT + #ifndef NO_CERTS case certificate: XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); @@ -9541,12 +10548,17 @@ #endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS && msgType == server_hello) + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { length += HELLO_EXT_SZ; -#endif - - if (TLSX_SupportExtensions(ssl)) + } +#endif + + if (TLSX_SupportExtensions(ssl)) { ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } /* All the response data is set at the ssl object only, so no ctx here. */ @@ -9572,7 +10584,7 @@ case server_hello: PF_VALIDATE_RESPONSE(ssl, semaphore); #ifdef WOLFSSL_TLS13 - if (ssl->options.tls1_3) { + if (IsAtLeastTLSv1_3(ssl->version)) { XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); #ifndef WOLFSSL_TLS13_DRAFT_18 TURN_OFF(semaphore, @@ -9617,6 +10629,9 @@ #ifdef HAVE_CERTIFICATE_STATUS_REQUEST TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #endif break; #ifdef WOLFSSL_EARLY_DATA @@ -9647,6 +10662,8 @@ ret = TLSX_Write(ssl->extensions, output + offset, semaphore, msgType, &offset); + if (ret != 0) + return ret; #ifdef WOLFSSL_TLS13 if (msgType == hello_retry_request) { @@ -9654,11 +10671,15 @@ TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); ret = TLSX_Write(ssl->extensions, output + offset, semaphore, msgType, &offset); + if (ret != 0) + return ret; } #endif #ifdef HAVE_EXTENDED_MASTER - if (ssl->options.haveEMS && msgType == server_hello) { + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { + WOLFSSL_MSG("EMS extension to write"); c16toa(HELLO_EXT_EXTMS, output + offset); offset += HELLO_EXT_TYPE_SZ; c16toa(0, output + offset); @@ -9678,6 +10699,50 @@ #endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */ +#ifdef WOLFSSL_TLS13 +int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType, + int* found) +{ + int ret = 0; + int offset = 0; + + *found = 0; + while (offset < (int)length) { + word16 type; + word16 size; + + if (offset + (2 * OPAQUE16_LEN) > length) { + ret = BUFFER_ERROR; + break; + } + + ato16(input + offset, &type); + offset += HELLO_EXT_TYPE_SZ; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) { + ret = BUFFER_ERROR; + break; + } + + if (type == TLSX_SUPPORTED_VERSIONS) { + *found = 1; + + WOLFSSL_MSG("Supported Versions extension received"); + + ret = SV_PARSE(ssl, input + offset, size, msgType); + break; + } + + offset += size; + } + + return ret; +} +#endif + /** Parses a buffer of TLS extensions. */ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, Suites *suites) @@ -9721,6 +10786,30 @@ switch (type) { case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = SNI_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && @@ -9729,11 +10818,14 @@ return EXT_NOT_ALLOWED; } #endif - ret = SNI_PARSE(ssl, input + offset, size, isRequest); + ret = TCA_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && @@ -9741,15 +10833,22 @@ msgType != encrypted_extensions) { return EXT_NOT_ALLOWED; } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } #endif ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + if (IsAtLeastTLSv1_3(ssl->version)) break; #endif ret = THM_PARSE(ssl, input + offset, size, isRequest); @@ -9757,22 +10856,33 @@ case TLSX_SUPPORTED_GROUPS: WOLFSSL_MSG("Supported Groups extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && msgType != client_hello && + msgType != server_hello && msgType != encrypted_extensions) { return EXT_NOT_ALLOWED; } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } #endif ret = EC_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_EC_POINT_FORMATS: WOLFSSL_MSG("Point Formats extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + if (IsAtLeastTLSv1_3(ssl->version)) break; #endif ret = PF_PARSE(ssl, input + offset, size, isRequest); @@ -9780,16 +10890,26 @@ case TLSX_STATUS_REQUEST: WOLFSSL_MSG("Certificate Status Request extension received"); - -#ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) - break; -#endif + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request && + msgType != certificate) { + break; + } + #endif ret = CSR_PARSE(ssl, input + offset, size, isRequest); break; case TLSX_STATUS_REQUEST_V2: WOLFSSL_MSG("Certificate Status Request v2 extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && @@ -9805,11 +10925,17 @@ #ifdef HAVE_EXTENDED_MASTER case HELLO_EXT_EXTMS: WOLFSSL_MSG("Extended Master Secret extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + if (IsAtLeastTLSv1_3(ssl->version)) break; #endif + if (size != 0) + return BUFFER_ERROR; + #ifndef NO_WOLFSSL_SERVER if (isRequest) ssl->options.haveEMS = 1; @@ -9820,9 +10946,12 @@ case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + if (IsAtLeastTLSv1_3(ssl->version)) break; #endif ret = SCR_PARSE(ssl, input + offset, size, isRequest); @@ -9830,6 +10959,9 @@ case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && @@ -9842,9 +10974,12 @@ case TLSX_QUANTUM_SAFE_HYBRID: WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif #ifdef WOLFSSL_TLS13 - if (IsAtLeastTLSv1_3(ssl->version) && !ssl->options.downgrade) + if (IsAtLeastTLSv1_3(ssl->version)) break; #endif ret = QSH_PARSE(ssl, input + offset, size, isRequest); @@ -9853,22 +10988,33 @@ case TLSX_APPLICATION_LAYER_PROTOCOL: WOLFSSL_MSG("ALPN extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && msgType != client_hello && + msgType != server_hello && msgType != encrypted_extensions) { return EXT_NOT_ALLOWED; } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } #endif ret = ALPN_PARSE(ssl, input + offset, size, isRequest); break; - +#if !defined(WOLFSSL_NO_SIGALG) case TLSX_SIGNATURE_ALGORITHMS: WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_2(ssl)) break; - #ifdef WOLFSSL_TLS13 if (IsAtLeastTLSv1_3(ssl->version) && msgType != client_hello && @@ -9878,68 +11024,75 @@ #endif ret = SA_PARSE(ssl, input + offset, size, isRequest, suites); break; +#endif + +#if defined(HAVE_ENCRYPT_THEN_MAC) && !defined(WOLFSSL_AEAD_ONLY) + case TLSX_ENCRYPT_THEN_MAC: + WOLFSSL_MSG("Encrypt-Then-Mac extension received"); + + /* Ignore for TLS 1.3+ */ + if (IsAtLeastTLSv1_3(ssl->version)) + break; + + ret = ETM_PARSE(ssl, input + offset, size, msgType); + break; +#endif /* HAVE_ENCRYPT_THEN_MAC */ #ifdef WOLFSSL_TLS13 case TLSX_SUPPORTED_VERSIONS: - WOLFSSL_MSG("Supported Versions extension received"); - - if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) - break; - - if (IsAtLeastTLSv1_3(ssl->version) && - #ifdef WOLFSSL_TLS13_DRAFT_18 - msgType != client_hello - #else - msgType != client_hello && - msgType != server_hello && - msgType != hello_retry_request - #endif - ) { - return EXT_NOT_ALLOWED; - } - ret = SV_PARSE(ssl, input + offset, size, msgType); + WOLFSSL_MSG("Skipping Supported Versions - already processed"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + break; case TLSX_COOKIE: WOLFSSL_MSG("Cookie extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && + if (msgType != client_hello && msgType != hello_retry_request) { return EXT_NOT_ALLOWED; } + ret = CKE_PARSE(ssl, input + offset, size, msgType); break; #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) case TLSX_PRE_SHARED_KEY: WOLFSSL_MSG("Pre-Shared Key extension received"); - - if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && - msgType != server_hello) { + if (msgType != client_hello && msgType != server_hello) return EXT_NOT_ALLOWED; - } + ret = PSK_PARSE(ssl, input + offset, size, msgType); pskDone = 1; break; case TLSX_PSK_KEY_EXCHANGE_MODES: WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello) { + if (msgType != client_hello) return EXT_NOT_ALLOWED; - } + ret = PKM_PARSE(ssl, input + offset, size, msgType); break; #endif @@ -9947,14 +11100,20 @@ #ifdef WOLFSSL_EARLY_DATA case TLSX_EARLY_DATA: WOLFSSL_MSG("Early Data extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && - msgType != session_ticket && - msgType != encrypted_extensions) { + if (msgType != client_hello && msgType != session_ticket && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + if (!IsAtLeastTLSv1_3(ssl->version) && + (msgType == session_ticket || + msgType == encrypted_extensions)) { return EXT_NOT_ALLOWED; } ret = EDI_PARSE(ssl, input + offset, size, msgType); @@ -9964,14 +11123,16 @@ #ifdef WOLFSSL_POST_HANDSHAKE_AUTH case TLSX_POST_HANDSHAKE_AUTH: WOLFSSL_MSG("Post Handshake Authentication extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello) { + if (msgType != client_hello) return EXT_NOT_ALLOWED; - } + ret = PHA_PARSE(ssl, input + offset, size, msgType); break; #endif @@ -9979,15 +11140,21 @@ #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) case TLSX_SIGNATURE_ALGORITHMS_CERT: WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->version) && - msgType != client_hello && + if (msgType != client_hello && msgType != certificate_request) { return EXT_NOT_ALLOWED; } + if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == certificate_request) { + return EXT_NOT_ALLOWED; + } ret = SAC_PARSE(ssl, input + offset, size, isRequest); break; @@ -9995,19 +11162,22 @@ case TLSX_KEY_SHARE: WOLFSSL_MSG("Key Share extension received"); - - if (!IsAtLeastTLSv1_3(ssl->ctx->method->version)) + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) break; - if (IsAtLeastTLSv1_3(ssl->ctx->method->version) && - msgType != client_hello && - msgType != server_hello && + if (msgType != client_hello && msgType != server_hello && msgType != hello_retry_request) { return EXT_NOT_ALLOWED; } ret = KS_PARSE(ssl, input + offset, size, msgType); break; #endif + default: + WOLFSSL_MSG("Unknown TLS extension type"); } /* offset should be updated here! */ @@ -10021,6 +11191,8 @@ if (ret == 0) ret = SNI_VERIFY_PARSE(ssl, isRequest); + if (ret == 0) + ret = TCA_VERIFY_PARSE(ssl, isRequest); return ret; } @@ -10034,41 +11206,49 @@ #ifndef NO_WOLFSSL_CLIENT + WOLFSSL_METHOD* wolfTLS_client_method(void) + { + return wolfTLS_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLS_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLS_client_method_ex"); + if (method) { + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #elif defined(WOLFSSL_ALLOW_TLSV10) + InitSSL_Method(method, MakeTLSv1()); + #else + #error No TLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_CLIENT_END; + } + return method; + } + #ifndef NO_OLD_TLS - #ifdef WOLFSSL_ALLOW_TLSV10 - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - /* Gets a WOLFSL_METHOD type that is not set as client or server - * - * Returns a pointer to a WOLFSSL_METHOD struct - */ - WOLFSSL_METHOD* wolfTLSv1_method(void) { - WOLFSSL_METHOD* m; - WOLFSSL_ENTER("wolfTLSv1_method"); - #ifndef NO_WOLFSSL_CLIENT - m = wolfTLSv1_client_method(); - #else - m = wolfTLSv1_server_method(); - #endif - if (m != NULL) { - m->side = WOLFSSL_NEITHER_END; - } - - return m; - } - #endif /* OPENSSL_EXTRA || OPENSSL_ALL*/ - WOLFSSL_METHOD* wolfTLSv1_client_method(void) { return wolfTLSv1_client_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_client_method_ex"); if (method) InitSSL_Method(method, MakeTLSv1()); return method; @@ -10079,38 +11259,36 @@ { return wolfTLSv1_1_client_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_1_client_method_ex"); if (method) InitSSL_Method(method, MakeTLSv1_1()); return method; } - #endif /* !NO_OLD_TLS */ #ifndef WOLFSSL_NO_TLS12 - + WOLFSSL_ABI WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) { return wolfTLSv1_2_client_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_2_client_method_ex"); if (method) InitSSL_Method(method, MakeTLSv1_2()); return method; } - #endif /* WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_TLS13 @@ -10118,6 +11296,7 @@ * * returns the method data for a TLS v1.3 client. */ + WOLFSSL_ABI WOLFSSL_METHOD* wolfTLSv1_3_client_method(void) { return wolfTLSv1_3_client_method_ex(NULL); @@ -10134,63 +11313,295 @@ XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_3_client_method_ex"); if (method) InitSSL_Method(method, MakeTLSv1_3()); return method; } #endif /* WOLFSSL_TLS13 */ - - WOLFSSL_METHOD* wolfSSLv23_client_method(void) +#ifdef WOLFSSL_DTLS + + WOLFSSL_METHOD* wolfDTLS_client_method(void) { - return wolfSSLv23_client_method_ex(NULL); - } - - - WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) + return wolfDTLS_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("DTLS_client_method_ex"); if (method) { -#if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) -#if defined(WOLFSSL_TLS13) - InitSSL_Method(method, MakeTLSv1_3()); -#else - InitSSL_Method(method, MakeTLSv1_2()); -#endif -#else - #ifndef NO_OLD_TLS - InitSSL_Method(method, MakeTLSv1_1()); - #endif -#endif -#if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + method->downgrade = 1; -#endif + method->side = WOLFSSL_CLIENT_END; } return method; } + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_client_method(void) + { + return wolfDTLSv1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1()); + return method; + } + #endif /* NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void) + { + return wolfDTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1_2()); + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ + #endif /* NO_WOLFSSL_CLIENT */ +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_method(void) + { + return wolfTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_client_method_ex(heap); + #else + m = wolfTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_1_method(void) + { + return wolfTLSv1_1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_1_client_method_ex(heap); + #else + m = wolfTLSv1_1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_2_method(void) + { + return wolfTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_2_client_method_ex(heap); + #else + m = wolfTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ + + #ifdef WOLFSSL_TLS13 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_3_method(void) + { + return wolfTLSv1_3_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_3_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_3_client_method_ex(heap); + #else + m = wolfTLSv1_3_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_method(void) + { + return wolfDTLS_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLS_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLS_client_method_ex(heap); + #else + m = wolfDTLS_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_method(void) + { + return wolfDTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_client_method_ex(heap); + #else + m = wolfDTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_method(void) + { + return wolfDTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_2_client_method_ex(heap); + #else + m = wolfDTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + #ifndef NO_WOLFSSL_SERVER + WOLFSSL_METHOD* wolfTLS_server_method(void) + { + return wolfTLS_server_method_ex(NULL); + } + + WOLFSSL_METHOD* wolfTLS_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLS_server_method_ex"); + if (method) { + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #elif defined(WOLFSSL_ALLOW_TLSV10) + InitSSL_Method(method, MakeTLSv1()); + #else + #error No TLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_TLSV10 WOLFSSL_METHOD* wolfTLSv1_server_method(void) { return wolfTLSv1_server_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1()); method->side = WOLFSSL_SERVER_END; @@ -10198,38 +11609,18 @@ return method; } #endif /* WOLFSSL_ALLOW_TLSV10 */ - - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - /* Gets a WOLFSL_METHOD type that is not set as client or server - * - * Returns a pointer to a WOLFSSL_METHOD struct - */ - WOLFSSL_METHOD* wolfTLSv1_1_method(void) { - WOLFSSL_METHOD* m; - WOLFSSL_ENTER("wolfTLSv1_1_method"); - #ifndef NO_WOLFSSL_CLIENT - m = wolfTLSv1_1_client_method(); - #else - m = wolfTLSv1_1_server_method(); - #endif - if (m != NULL) { - m->side = WOLFSSL_NEITHER_END; - } - return m; - } - #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ WOLFSSL_METHOD* wolfTLSv1_1_server_method(void) { return wolfTLSv1_1_server_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_1_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1_1()); method->side = WOLFSSL_SERVER_END; @@ -10238,46 +11629,25 @@ } #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 - - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) - /* Gets a WOLFSL_METHOD type that is not set as client or server - * - * Returns a pointer to a WOLFSSL_METHOD struct - */ - WOLFSSL_METHOD* wolfTLSv1_2_method(void) { - WOLFSSL_METHOD* m; - WOLFSSL_ENTER("wolfTLSv1_2_method"); - #ifndef NO_WOLFSSL_CLIENT - m = wolfTLSv1_2_client_method(); - #else - m = wolfTLSv1_2_server_method(); - #endif - if (m != NULL) { - m->side = WOLFSSL_NEITHER_END; - } - return m; - } - #endif /* OPENSSL_EXTRA || OPENSSL_ALL */ - WOLFSSL_METHOD* wolfTLSv1_2_server_method(void) { return wolfTLSv1_2_server_method_ex(NULL); } - WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_2_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1_2()); method->side = WOLFSSL_SERVER_END; } return method; } - #endif /* !WOLFSSL_NO_TLS12 */ #ifdef WOLFSSL_TLS13 @@ -10301,6 +11671,7 @@ (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("TLSv1_3_server_method_ex"); if (method) { InitSSL_Method(method, MakeTLSv1_3()); method->side = WOLFSSL_SERVER_END; @@ -10309,41 +11680,77 @@ } #endif /* WOLFSSL_TLS13 */ - WOLFSSL_METHOD* wolfSSLv23_server_method(void) +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_server_method(void) { - return wolfSSLv23_server_method_ex(NULL); - } - - WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap) + return wolfDTLS_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap) { WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), heap, DYNAMIC_TYPE_METHOD); (void)heap; + WOLFSSL_ENTER("DTLS_server_method_ex"); if (method) { -#if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) -#ifdef WOLFSSL_TLS13 - InitSSL_Method(method, MakeTLSv1_3()); -#else - InitSSL_Method(method, MakeTLSv1_2()); -#endif -#else - #ifndef NO_OLD_TLS - InitSSL_Method(method, MakeTLSv1_1()); - #else - #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 - #endif -#endif -#if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + method->downgrade = 1; -#endif method->side = WOLFSSL_SERVER_END; } return method; } + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_server_method(void) + { + return wolfDTLSv1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeDTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* !NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void) + { + return wolfDTLSv1_2_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_2_server_method_ex"); + (void)heap; + if (method) { + InitSSL_Method(method, MakeDTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ #endif /* NO_WOLFSSL_SERVER */ + #endif /* NO_TLS */ #endif /* WOLFCRYPT_ONLY */