aboutsummaryrefslogtreecommitdiff
path: root/client/wolfssl/src/tls.c
diff options
context:
space:
mode:
authorauth12 <[email protected]>2020-07-22 08:40:38 -0700
committerauth12 <[email protected]>2020-07-22 08:40:38 -0700
commit4ff89e85e74884e8f04edb5c31a94b4323e895e9 (patch)
tree65f98ebf9af0d0947e44bf397b1fac0f107d7a2f /client/wolfssl/src/tls.c
parentClient injection. (diff)
downloadloader-4ff89e85e74884e8f04edb5c31a94b4323e895e9.tar.xz
loader-4ff89e85e74884e8f04edb5c31a94b4323e895e9.zip
Removed wolfssl
Diffstat (limited to 'client/wolfssl/src/tls.c')
-rw-r--r--client/wolfssl/src/tls.c11755
1 files changed, 0 insertions, 11755 deletions
diff --git a/client/wolfssl/src/tls.c b/client/wolfssl/src/tls.c
deleted file mode 100644
index 1b9858a..0000000
--- a/client/wolfssl/src/tls.c
+++ /dev/null
@@ -1,11755 +0,0 @@
-/* tls.c
- *
- * Copyright (C) 2006-2020 wolfSSL Inc.
- *
- * This file is part of wolfSSL.
- *
- * wolfSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * wolfSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
- */
-
-
-
-#ifdef HAVE_CONFIG_H
- #include <config.h>
-#endif
-
-#include <wolfssl/wolfcrypt/settings.h>
-
-#ifndef WOLFCRYPT_ONLY
-
-#include <wolfssl/ssl.h>
-#include <wolfssl/internal.h>
-#include <wolfssl/error-ssl.h>
-#include <wolfssl/wolfcrypt/hmac.h>
-#ifdef NO_INLINE
- #include <wolfssl/wolfcrypt/misc.h>
-#else
- #define WOLFSSL_MISC_INCLUDED
- #include <wolfcrypt/src/misc.c>
-#endif
-
-#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>
-#endif
-
-#ifdef HAVE_QSH
- static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key);
- static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name);
-#if defined(HAVE_NTRU)
- static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type);
-#endif
-#endif /* HAVE_QSH */
-
-#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \
- !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \
- (defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES))
-static int TLSX_KeyShare_IsSupported(int namedGroup);
-#endif
-
-#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_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
-
-
-#ifndef NO_TLS
-
-/* Digest enable checks */
-#ifdef NO_OLD_TLS /* TLS 1.2 only */
- #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \
- !defined(WOLFSSL_SHA512)
- #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2
- #endif
-#else /* TLS 1.1 or older */
- #if defined(NO_MD5) && defined(NO_SHA)
- #error Must have SHA1 and MD5 enabled for old TLS
- #endif
-#endif
-
-#ifdef WOLFSSL_TLS13
- #if !defined(NO_DH) && \
- !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \
- !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \
- !defined(HAVE_FFDHE_8192)
- #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192
- #endif
- #if !defined(NO_RSA) && !defined(WC_RSA_PSS)
- #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA
- #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 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
- 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) {
- ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash);
- hashSz = WC_SHA256_DIGEST_SIZE;
- }
-#endif
-#ifdef WOLFSSL_SHA384
- if (ssl->specs.mac_algorithm == sha384_mac) {
- ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash);
- hashSz = WC_SHA384_DIGEST_SIZE;
- }
-#endif
- }
-
- *hashLen = hashSz;
-
- if (ret != 0)
- ret = BUILD_MSG_ERROR;
-
- return ret;
-}
-
-
-int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender)
-{
- int ret;
- const byte* side;
- 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)
- side = tls_client;
- else
- side = tls_server;
-
-#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);
-#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;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifndef NO_OLD_TLS
-
-#ifdef WOLFSSL_ALLOW_TLSV10
-ProtocolVersion MakeTLSv1(void)
-{
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_MINOR;
-
- return pv;
-}
-#endif /* WOLFSSL_ALLOW_TLSV10 */
-
-
-ProtocolVersion MakeTLSv1_1(void)
-{
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_1_MINOR;
-
- return pv;
-}
-
-#endif /* !NO_OLD_TLS */
-
-
-#ifndef WOLFSSL_NO_TLS12
-
-ProtocolVersion MakeTLSv1_2(void)
-{
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_2_MINOR;
-
- return pv;
-}
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef WOLFSSL_TLS13
-/* The TLS v1.3 protocol version.
- *
- * returns the protocol version data for TLS v1.3.
- */
-ProtocolVersion MakeTLSv1_3(void)
-{
- ProtocolVersion pv;
- pv.major = SSLv3_MAJOR;
- pv.minor = TLSv1_3_MINOR;
-
- return pv;
-}
-#endif
-
-#ifndef WOLFSSL_NO_TLS12
-
-#ifdef HAVE_EXTENDED_MASTER
-static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] =
- "extended master secret";
-#endif
-static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret";
-static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion";
-
-static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
- const byte* ms, word32 msLen,
- const byte* sr, const byte* cr,
- int tls1_2, int hash_type,
- 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);
-
-#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;
-}
-
-/* External facing wrapper so user can call as well, 0 on success */
-int wolfSSL_DeriveTlsKeys(byte* key_dig, word32 key_dig_len,
- const byte* ms, word32 msLen,
- const byte* sr, const byte* cr,
- int tls1_2, int hash_type)
-{
- return _DeriveTlsKeys(key_dig, key_dig_len, ms, msLen, sr, cr, tls1_2,
- hash_type, NULL, INVALID_DEVID);
-}
-
-
-int DeriveTlsKeys(WOLFSSL* ssl)
-{
- int ret;
- int key_dig_len = 2 * ssl->specs.hash_size +
- 2 * ssl->specs.key_size +
- 2 * ssl->specs.iv_size;
-#ifdef WOLFSSL_SMALL_STACK
- byte* key_dig;
-#else
- byte key_dig[MAX_PRF_DIG];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST);
- if (key_dig == NULL) {
- 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,
- IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm,
- 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);
-#endif
-
- return ret;
-}
-
-static int _MakeTlsMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* cr, const byte* sr,
- int tls1_2, int hash_type,
- 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, cr, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, sr, RAN_LEN);
-
-#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 */
-int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* cr, const byte* sr,
- int tls1_2, int hash_type)
-{
- return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2,
- hash_type, NULL, INVALID_DEVID);
-}
-
-
-#ifdef HAVE_EXTENDED_MASTER
-
-static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* sHash, word32 sHashLen,
- int tls1_2, int hash_type,
- void* heap, int devId)
-{
- 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 */
-int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen,
- const byte* pms, word32 pmsLen,
- const byte* sHash, word32 sHashLen,
- int tls1_2, int hash_type)
-{
- return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen,
- tls1_2, hash_type, NULL, INVALID_DEVID);
-}
-
-#endif /* HAVE_EXTENDED_MASTER */
-
-
-int MakeTlsMasterSecret(WOLFSSL* ssl)
-{
- int ret;
-
-#ifdef HAVE_EXTENDED_MASTER
- if (ssl->options.haveEMS) {
- word32 hashSz = HSHASH_SZ;
- #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) {
- 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);
- #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
- /* 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);
- }
-
- return ret;
-}
-
-
-/* Used by EAP-TLS and EAP-TTLS to derive keying material from
- * the master_secret. */
-int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len,
- const char* label)
-{
- int ret;
-#ifdef WOLFSSL_SMALL_STACK
- byte* seed;
-#else
- byte seed[SEED_LEN];
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- seed = (byte*)XMALLOC(SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED);
- if (seed == NULL)
- return MEMORY_E;
-#endif
-
- /*
- * As per RFC-5281, the order of the client and server randoms is reversed
- * from that used by the TLS protocol to derive keys.
- */
- XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN);
- XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_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);
-#endif
-
- return ret;
-}
-
-
-static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2])
-{
- if (verify) {
- seq[0] = ssl->keys.peer_sequence_number_hi;
- seq[1] = ssl->keys.peer_sequence_number_lo++;
- if (seq[1] > ssl->keys.peer_sequence_number_lo) {
- /* handle rollover */
- ssl->keys.peer_sequence_number_hi++;
- }
- }
- else {
- seq[0] = ssl->keys.sequence_number_hi;
- seq[1] = ssl->keys.sequence_number_lo++;
- if (seq[1] > ssl->keys.sequence_number_lo) {
- /* handle rollover */
- ssl->keys.sequence_number_hi++;
- }
- }
-}
-
-
-#ifdef WOLFSSL_DTLS
-static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2])
-{
- if (order == PREV_ORDER) {
- /* Previous epoch case */
- 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] = ((word32)ssl->keys.curEpoch << 16) |
- (ssl->keys.curSeq_hi & 0xFFFF);
- seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */
- }
- else {
- seq[0] = ((word32)ssl->keys.dtls_epoch << 16) |
- (ssl->keys.dtls_sequence_number_hi & 0xFFFF);
- seq[1] = ssl->keys.dtls_sequence_number_lo;
- }
-}
-#endif /* WOLFSSL_DTLS */
-
-
-static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out)
-{
- word32 seq[2] = {0, 0};
-
- if (!ssl->options.dtls) {
- GetSEQIncrement(ssl, verifyOrder, seq);
- }
- else {
-#ifdef WOLFSSL_DTLS
- DtlsGetSEQ(ssl, verifyOrder, seq);
-#endif
- }
-
- c32toa(seq[0], out);
- c32toa(seq[1], out + OPAQUE32_LEN);
-}
-
-
-/*** end copy ***/
-
-
-/* return HMAC digest type in wolfSSL format */
-int wolfSSL_GetHmacType(WOLFSSL* ssl)
-{
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- switch (ssl->specs.mac_algorithm) {
- #ifndef NO_MD5
- case md5_mac:
- {
- return WC_MD5;
- }
- #endif
- #ifndef NO_SHA256
- case sha256_mac:
- {
- return WC_SHA256;
- }
- #endif
- #ifdef WOLFSSL_SHA384
- case sha384_mac:
- {
- return WC_SHA384;
- }
-
- #endif
- #ifndef NO_SHA
- case sha_mac:
- {
- return WC_SHA;
- }
- #endif
- #ifdef HAVE_BLAKE2
- case blake2b_mac:
- {
- return BLAKE2B_ID;
- }
- #endif
- default:
- {
- return WOLFSSL_FATAL_ERROR;
- }
- }
-}
-
-
-int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content,
- int verify)
-{
- if (ssl == NULL || inner == NULL)
- return BAD_FUNC_ARG;
-
- XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ);
-
- WriteSEQ(ssl, verify, inner);
- inner[SEQ_SZ] = (byte)content;
- inner[SEQ_SZ + ENUM_LEN] = ssl->version.major;
- inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor;
- c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ);
-
- return 0;
-}
-
-
-#ifndef WOLFSSL_AEAD_ONLY
-#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
-
-/* Update the hash in the HMAC.
- *
- * hmac HMAC object.
- * data Data to be hashed.
- * sz Size of data to hash.
- * returns 0 on success, otherwise failure.
- */
-static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz)
-{
- int ret = BAD_FUNC_ARG;
-
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_ShaUpdate(&hmac->hash.sha, data, sz);
- break;
- #endif /* !NO_SHA */
-
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_Sha256Update(&hmac->hash.sha256, data, sz);
- break;
- #endif /* !NO_SHA256 */
-
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_Sha384Update(&hmac->hash.sha384, data, sz);
- break;
- #endif /* WOLFSSL_SHA384 */
-
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_Sha512Update(&hmac->hash.sha512, data, sz);
- break;
- #endif /* WOLFSSL_SHA512 */
- }
-
- return ret;
-}
-
-/* Finalize the hash but don't put the EOC, padding or length in.
- *
- * hmac HMAC object.
- * hash Hash result.
- * returns 0 on success, otherwise failure.
- */
-static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash)
-{
- int ret = BAD_FUNC_ARG;
-
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- ret = wc_ShaFinalRaw(&hmac->hash.sha, hash);
- break;
- #endif /* !NO_SHA */
-
- #ifndef NO_SHA256
- case WC_SHA256:
- ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash);
- break;
- #endif /* !NO_SHA256 */
-
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash);
- break;
- #endif /* WOLFSSL_SHA384 */
-
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash);
- break;
- #endif /* WOLFSSL_SHA512 */
- }
-
- return ret;
-}
-
-/* Finalize the HMAC by performing outer hash.
- *
- * hmac HMAC object.
- * mac MAC result.
- * returns 0 on success, otherwise failure.
- */
-static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac)
-{
- int ret = BAD_FUNC_ARG;
- 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;
-}
-
-/* Calculate the HMAC of the header + message data.
- * Constant time implementation using wc_Sha*FinalRaw().
- *
- * hmac HMAC object.
- * digest MAC result.
- * in Message data.
- * sz Size of the message data.
- * header Constructed record header with length of handshake data.
- * returns 0 on success, otherwise failure.
- */
-static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in,
- word32 sz, byte* header)
-{
- byte lenBytes[8];
- int i, j, k;
- int blockBits, blockMask;
- int lastBlockLen, macLen, extraLen, eocIndex;
- int blocks, safeBlocks, lenBlock, eocBlock;
- int maxLen;
- int blockSz, padSz;
- int ret;
- word32 realLen;
- byte extraBlock;
-
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- blockSz = WC_SHA_BLOCK_SIZE;
- blockBits = 6;
- macLen = WC_SHA_DIGEST_SIZE;
- padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA */
-
- #ifndef NO_SHA256
- case WC_SHA256:
- blockSz = WC_SHA256_BLOCK_SIZE;
- blockBits = 6;
- macLen = WC_SHA256_DIGEST_SIZE;
- padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA256 */
-
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- blockSz = WC_SHA384_BLOCK_SIZE;
- blockBits = 7;
- macLen = WC_SHA384_DIGEST_SIZE;
- padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA384 */
-
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- blockSz = WC_SHA512_BLOCK_SIZE;
- blockBits = 7;
- macLen = WC_SHA512_DIGEST_SIZE;
- padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA512 */
-
- default:
- return BAD_FUNC_ARG;
- }
- blockMask = blockSz - 1;
-
- /* Size of data to HMAC if padding length byte is zero. */
- maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen;
- /* Complete data (including padding) has block for EOC and/or length. */
- extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz);
- /* Total number of blocks for data including padding. */
- blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock;
- /* Up to last 6 blocks can be hashed safely. */
- safeBlocks = blocks - 6;
-
- /* Length of message data. */
- realLen = maxLen - in[sz - 1];
- /* Number of message bytes in last block. */
- lastBlockLen = realLen & blockMask;
- /* Number of padding bytes in last block. */
- extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1;
- /* Number of blocks to create for hash. */
- lenBlock = (realLen + extraLen) >> blockBits;
- /* Block containing EOC byte. */
- eocBlock = realLen >> blockBits;
- /* Index of EOC byte in block. */
- eocIndex = realLen & blockMask;
-
- /* Add length of hmac's ipad to total length. */
- realLen += blockSz;
- /* Length as bits - 8 bytes bigendian. */
- c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes);
- c32toa(realLen << 3, lenBytes + sizeof(word32));
-
- ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz);
- if (ret != 0)
- return ret;
-
- XMEMSET(hmac->innerHash, 0, macLen);
-
- if (safeBlocks > 0) {
- ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret != 0)
- return ret;
- ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz -
- WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret != 0)
- return ret;
- }
- else
- safeBlocks = 0;
-
- XMEMSET(digest, 0, macLen);
- k = safeBlocks * blockSz;
- for (i = safeBlocks; i < blocks; i++) {
- unsigned char hashBlock[WC_MAX_BLOCK_SIZE];
- unsigned char isEocBlock = ctMaskEq(i, eocBlock);
- unsigned char isOutBlock = ctMaskEq(i, lenBlock);
-
- for (j = 0; j < blockSz; j++, k++) {
- unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock;
- unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock;
- unsigned char b = 0;
-
- if (k < WOLFSSL_TLS_HMAC_INNER_SZ)
- b = header[k];
- else if (k < maxLen)
- b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ];
-
- b = ctMaskSel(atEoc, 0x80, b);
- b &= (unsigned char)~(word32)pastEoc;
- b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock;
-
- if (j >= blockSz - 8) {
- b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b);
- }
-
- hashBlock[j] = b;
- }
-
- ret = Hmac_HashUpdate(hmac, hashBlock, blockSz);
- if (ret != 0)
- return ret;
- ret = Hmac_HashFinalRaw(hmac, hashBlock);
- if (ret != 0)
- return ret;
- for (j = 0; j < macLen; j++)
- ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock;
- }
-
- ret = Hmac_OuterHash(hmac, digest);
-
- return ret;
-}
-
-#endif
-
-#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \
- defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2)
-
-/* Calculate the HMAC of the header + message data.
- * Constant time implementation using normal hashing operations.
- * Update-Final need to be constant time.
- *
- * hmac HMAC object.
- * digest MAC result.
- * in Message data.
- * sz Size of the message data.
- * header Constructed record header with length of handshake data.
- * returns 0 on success, otherwise failure.
- */
-static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in,
- word32 sz, byte* header)
-{
- byte dummy[WC_MAX_BLOCK_SIZE] = {0};
- int ret;
- word32 msgSz, blockSz, macSz, padSz, maxSz, realSz;
- word32 currSz, offset = 0;
- int msgBlocks, blocks, blockBits;
- int i;
-
- switch (hmac->macType) {
- #ifndef NO_SHA
- case WC_SHA:
- blockSz = WC_SHA_BLOCK_SIZE;
- blockBits = 6;
- macSz = WC_SHA_DIGEST_SIZE;
- padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA */
-
- #ifndef NO_SHA256
- case WC_SHA256:
- blockSz = WC_SHA256_BLOCK_SIZE;
- blockBits = 6;
- macSz = WC_SHA256_DIGEST_SIZE;
- padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1;
- break;
- #endif /* !NO_SHA256 */
-
- #ifdef WOLFSSL_SHA384
- case WC_SHA384:
- blockSz = WC_SHA384_BLOCK_SIZE;
- blockBits = 7;
- macSz = WC_SHA384_DIGEST_SIZE;
- padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA384 */
-
- #ifdef WOLFSSL_SHA512
- case WC_SHA512:
- blockSz = WC_SHA512_BLOCK_SIZE;
- blockBits = 7;
- macSz = WC_SHA512_DIGEST_SIZE;
- padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1;
- break;
- #endif /* WOLFSSL_SHA512 */
-
- #ifdef HAVE_BLAKE2
- case WC_HASH_TYPE_BLAKE2B:
- blockSz = BLAKE2B_BLOCKBYTES;
- blockBits = 7;
- macSz = BLAKE2B_256;
- padSz = 0;
- break;
- #endif /* HAVE_BLAK2 */
-
- default:
- return BAD_FUNC_ARG;
- }
-
- msgSz = sz - (1 + in[sz - 1] + macSz);
- /* Make negative result 0 */
- msgSz &= ~(0 - (msgSz >> 31));
- realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz;
- maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz;
-
- /* Calculate #blocks processed in HMAC for max and real data. */
- blocks = maxSz >> blockBits;
- blocks += ((maxSz + padSz) % blockSz) < padSz;
- msgBlocks = realSz >> blockBits;
- /* #Extra blocks to process. */
- blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz);
- /* Calculate whole blocks. */
- msgBlocks--;
-
- ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ);
- if (ret == 0) {
- /* Fill the rest of the block with any available data. */
- currSz = ctMaskLT(msgSz, blockSz) & msgSz;
- currSz |= ctMaskGTE(msgSz, blockSz) & blockSz;
- currSz -= WOLFSSL_TLS_HMAC_INNER_SZ;
- currSz &= ~(0 - (currSz >> 31));
- ret = wc_HmacUpdate(hmac, in, currSz);
- offset = currSz;
- }
- if (ret == 0) {
- /* Do the hash operations on a block basis. */
- for (i = 0; i < msgBlocks; i++, offset += blockSz) {
- ret = wc_HmacUpdate(hmac, in + offset, blockSz);
- if (ret != 0)
- break;
- }
- }
- if (ret == 0)
- ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset);
- if (ret == 0)
- ret = wc_HmacFinal(hmac, digest);
- if (ret == 0) {
- /* Do the dummy hash operations. Do at least one. */
- for (i = 0; i < blocks + 1; i++) {
- ret = wc_HmacUpdate(hmac, dummy, blockSz);
- if (ret != 0)
- break;
- }
- }
-
- return ret;
-}
-
-#endif
-
-int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
- int content, int verify)
-{
- 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;
-
-#ifdef HAVE_FUZZER
- /* Fuzz "in" buffer with sz to be used in HMAC algorithm */
- if (ssl->fuzzerCb) {
- if (verify && padSz >= 0) {
- ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC,
- ssl->fuzzerCtx);
- }
- else {
- ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx);
- }
- }
-#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;
-
- ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl),
- wolfSSL_GetMacSecret(ssl, verify),
- ssl->specs.hash_size);
- if (ret == 0) {
- /* Constant time verification required. */
- if (verify && padSz >= 0) {
-#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \
- !defined(HAVE_SELFTEST)
- #ifdef HAVE_BLAKE2
- if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
- ret = Hmac_UpdateFinal(&hmac, digest, in,
- sz + hashSz + padSz + 1, myInner);
- }
- else
- #endif
- {
- ret = Hmac_UpdateFinal_CT(&hmac, digest, in,
- sz + hashSz + padSz + 1, myInner);
- }
-#else
- ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz + padSz + 1,
- myInner);
-#endif
- }
- else {
- ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner));
- if (ret == 0)
- ret = wc_HmacUpdate(&hmac, in, sz); /* content */
- if (ret == 0)
- ret = wc_HmacFinal(&hmac, digest);
- }
- }
-
- wc_HmacFree(&hmac);
-
- return ret;
-}
-#endif /* WOLFSSL_AEAD_ONLY */
-
-#endif /* !WOLFSSL_NO_TLS12 */
-
-#ifdef HAVE_TLS_EXTENSIONS
-
-/**
- * The TLSX semaphore is used to calculate the size of the extensions to be sent
- * from one peer to another.
- */
-
-/** Supports up to 64 flags. Increase as needed. */
-#define SEMAPHORE_SIZE 8
-
-/**
- * Converts the extension type (id) to an index in the semaphore.
- *
- * Official reference for TLS extension types:
- * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml
- *
- * Motivation:
- * Previously, we used the extension type itself as the index of that
- * extension in the semaphore as the extension types were declared
- * sequentially, but maintain a semaphore as big as the number of available
- * extensions is no longer an option since the release of renegotiation_info.
- *
- * How to update:
- * Assign extension types that extrapolate the number of available semaphores
- * to the first available index going backwards in the semaphore array.
- * When adding a new extension type that don't extrapolate the number of
- * available semaphores, check for a possible collision with with a
- * 'remapped' extension type.
- */
-static WC_INLINE word16 TLSX_ToSemaphore(word16 type)
-{
- switch (type) {
-
- case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */
- return 63;
-
- default:
- if (type > 62) {
- /* This message SHOULD only happens during the adding of
- new TLS extensions in which its IANA number overflows
- the current semaphore's range, or if its number already
- 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 collision or overflow detected!");
- }
- }
-
- return type;
-}
-
-/** Checks if a specific light (tls extension) is not set in the semaphore. */
-#define IS_OFF(semaphore, light) \
- (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8)))))
-
-/** Turn on a specific light (tls extension) in the semaphore. */
-/* the semaphore marks the extensions already written to the message */
-#define TURN_ON(semaphore, light) \
- ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8)))
-
-/** Turn off a specific light (tls extension) in the semaphore. */
-#define TURN_OFF(semaphore, light) \
- ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8)))
-
-/** Creates a new extension. */
-static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap)
-{
- TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX);
-
- (void)heap;
-
- if (extension) {
- extension->type = type;
- extension->data = data;
- extension->resp = 0;
- extension->next = NULL;
- }
-
- return extension;
-}
-
-/**
- * Creates a new extension and pushes it to the provided list.
- * Checks for duplicate extensions, keeps the newest.
- */
-static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap)
-{
- TLSX* extension = TLSX_New(type, data, heap);
-
- if (extension == NULL)
- return MEMORY_E;
-
- /* pushes the new extension on the list. */
- extension->next = *list;
- *list = extension;
-
- /* remove duplicate extensions, there should be only one of each type. */
- do {
- if (extension->next && extension->next->type == type) {
- TLSX *next = extension->next;
-
- extension->next = next->next;
- next->next = NULL;
-
- TLSX_FreeAll(next, heap);
-
- /* there is no way to occur more than
- * two extensions of the same type.
- */
- break;
- }
- } while ((extension = extension->next));
-
- return 0;
-}
-
-#ifndef NO_WOLFSSL_CLIENT
-
-int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type);
-
-int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type)
-{
- TLSX *extension = TLSX_Find(ssl->extensions, type);
-
- if (!extension)
- extension = TLSX_Find(ssl->ctx->extensions, type);
-
- return extension == NULL;
-}
-
-int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl);
-
-int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl)
-{
- SendAlert(ssl, alert_fatal, unsupported_extension);
- return UNSUPPORTED_EXTENSION;
-}
-
-#else
-
-#define TLSX_CheckUnsupportedExtension(ssl, type) 0
-#define TLSX_HandleUnsupportedExtension(ssl) 0
-
-#endif
-
-/** Mark an extension to be sent back to the client. */
-void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type);
-
-void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type)
-{
- TLSX *extension = TLSX_Find(ssl->extensions, type);
-
- if (extension)
- extension->resp = 1;
-}
-
-/******************************************************************************/
-/* Application-Layer Protocol Negotiation */
-/******************************************************************************/
-
-#ifdef HAVE_ALPN
-/** Creates a new ALPN object, providing protocol name to use. */
-static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz,
- void* heap)
-{
- ALPN *alpn;
-
- WOLFSSL_ENTER("TLSX_ALPN_New");
-
- if (protocol_name == NULL ||
- protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) {
- WOLFSSL_MSG("Invalid arguments");
- return NULL;
- }
-
- alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return NULL;
- }
-
- alpn->next = NULL;
- alpn->negotiated = 0;
- alpn->options = 0;
-
- alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1,
- heap, DYNAMIC_TYPE_TLSX);
- if (alpn->protocol_name == NULL) {
- WOLFSSL_MSG("Memory failure");
- XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
- return NULL;
- }
-
- XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz);
- alpn->protocol_name[protocol_nameSz] = 0;
-
- (void)heap;
-
- return alpn;
-}
-
-/** Releases an ALPN object. */
-static void TLSX_ALPN_Free(ALPN *alpn, void* heap)
-{
- (void)heap;
-
- if (alpn == NULL)
- return;
-
- XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX);
- XFREE(alpn, heap, DYNAMIC_TYPE_TLSX);
-}
-
-/** Releases all ALPN objects in the provided list. */
-static void TLSX_ALPN_FreeAll(ALPN *list, void* heap)
-{
- ALPN* alpn;
-
- while ((alpn = list)) {
- list = alpn->next;
- TLSX_ALPN_Free(alpn, heap);
- }
-}
-
-/** Tells the buffered size of the ALPN objects in a list. */
-static word16 TLSX_ALPN_GetSize(ALPN *list)
-{
- ALPN* alpn;
- word16 length = OPAQUE16_LEN; /* list length */
-
- while ((alpn = list)) {
- list = alpn->next;
-
- length++; /* protocol name length is on one byte */
- length += (word16)XSTRLEN(alpn->protocol_name);
- }
-
- return length;
-}
-
-/** Writes the ALPN objects of a list in a buffer. */
-static word16 TLSX_ALPN_Write(ALPN *list, byte *output)
-{
- ALPN* alpn;
- word16 length = 0;
- word16 offset = OPAQUE16_LEN; /* list length offset */
-
- while ((alpn = list)) {
- list = alpn->next;
-
- length = (word16)XSTRLEN(alpn->protocol_name);
-
- /* protocol name length */
- output[offset++] = (byte)length;
-
- /* protocol name value */
- XMEMCPY(output + offset, alpn->protocol_name, length);
-
- offset += length;
- }
-
- /* writing list length */
- c16toa(offset - OPAQUE16_LEN, output);
-
- return offset;
-}
-
-/** Finds a protocol name in the provided ALPN list */
-static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size)
-{
- ALPN *alpn;
-
- if (list == NULL || protocol_name == NULL)
- return NULL;
-
- alpn = list;
- while (alpn != NULL && (
- (word16)XSTRLEN(alpn->protocol_name) != size ||
- XSTRNCMP(alpn->protocol_name, protocol_name, size)))
- alpn = alpn->next;
-
- return alpn;
-}
-
-/** Set the ALPN matching client and server requirements */
-static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size,
- void* heap)
-{
- ALPN *alpn;
- int ret;
-
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
-
- alpn = TLSX_ALPN_New((char *)data, size, heap);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return MEMORY_E;
- }
-
- alpn->negotiated = 1;
-
- ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn,
- heap);
- if (ret != 0) {
- TLSX_ALPN_Free(alpn, heap);
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-/** Parses a buffer of ALPN extensions and set the first one matching
- * client and server requirements */
-static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length,
- byte isRequest)
-{
- word16 size = 0, offset = 0, idx = 0;
- int r = BUFFER_ERROR;
- byte match = 0;
- TLSX *extension;
- ALPN *alpn = NULL, *list;
-
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
-
- 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,
- TLSX_APPLICATION_LAYER_PROTOCOL);
-
-#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
- if (ssl->alpnSelect != NULL) {
- const byte* out;
- unsigned char outLen;
-
- if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size,
- ssl->alpnSelectArg) == 0) {
- WOLFSSL_MSG("ALPN protocol match");
- if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap)
- == WOLFSSL_SUCCESS) {
- if (extension == NULL) {
- extension = TLSX_Find(ssl->extensions,
- TLSX_APPLICATION_LAYER_PROTOCOL);
- }
- }
- }
- }
-#endif
-
- if (extension == NULL || extension->data == NULL) {
- return isRequest ? 0
- : TLSX_HandleUnsupportedExtension(ssl);
- }
-
- /* validating alpn list length */
- if (length != OPAQUE16_LEN + size)
- return BUFFER_ERROR;
-
- list = (ALPN*)extension->data;
-
- /* keep the list sent by client */
- if (isRequest) {
- if (ssl->alpn_client_list != NULL)
- XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN);
-
- ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap,
- DYNAMIC_TYPE_ALPN);
- if (ssl->alpn_client_list == NULL)
- return MEMORY_ERROR;
- }
-
- for (size = 0; offset < length; offset += size) {
-
- size = input[offset++];
- if (offset + size > length || size == 0)
- return BUFFER_ERROR;
-
- if (isRequest) {
- XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size);
- idx += size;
- ssl->alpn_client_list[idx++] = ',';
- }
-
- if (!match) {
- alpn = TLSX_ALPN_Find(list, (char*)input + offset, size);
- if (alpn != NULL) {
- WOLFSSL_MSG("ALPN protocol match");
- match = 1;
-
- /* skip reading other values if not required */
- if (!isRequest)
- break;
- }
- }
- }
-
- if (isRequest)
- ssl->alpn_client_list[idx-1] = 0;
-
- if (!match) {
- WOLFSSL_MSG("No ALPN protocol match");
-
- /* do nothing if no protocol match between client and server and option
- is set to continue (like OpenSSL) */
- if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) {
- WOLFSSL_MSG("Continue on mismatch");
- return 0;
- }
-
- SendAlert(ssl, alert_fatal, no_application_protocol);
- return UNKNOWN_ALPN_PROTOCOL_NAME_E;
- }
-
- /* set the matching negotiated protocol */
- r = TLSX_SetALPN(&ssl->extensions,
- alpn->protocol_name,
- (word16)XSTRLEN(alpn->protocol_name),
- ssl->heap);
- if (r != WOLFSSL_SUCCESS) {
- WOLFSSL_MSG("TLSX_UseALPN failed");
- return BUFFER_ERROR;
- }
-
- /* reply to ALPN extension sent from client */
- if (isRequest) {
-#ifndef NO_WOLFSSL_SERVER
- TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL);
-#endif
- }
-
- return 0;
-}
-
-/** Add a protocol name to the list of accepted usable ones */
-int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options,
- void* heap)
-{
- ALPN *alpn;
- TLSX *extension;
- int ret;
-
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
-
- alpn = TLSX_ALPN_New((char *)data, size, heap);
- if (alpn == NULL) {
- WOLFSSL_MSG("Memory failure");
- return MEMORY_E;
- }
-
- /* Set Options of ALPN */
- alpn->options = options;
-
- extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL) {
- ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL,
- (void*)alpn, heap);
- if (ret != 0) {
- TLSX_ALPN_Free(alpn, heap);
- return ret;
- }
- }
- else {
- /* push new ALPN object to extension data. */
- alpn->next = (ALPN*)extension->data;
- extension->data = (void*)alpn;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-/** Get the protocol name set by the server */
-int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
-{
- TLSX *extension;
- ALPN *alpn;
-
- if (extensions == NULL || data == NULL || dataSz == NULL)
- return BAD_FUNC_ARG;
-
- extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL);
- if (extension == NULL) {
- WOLFSSL_MSG("TLS extension not found");
- return WOLFSSL_ALPN_NOT_FOUND;
- }
-
- alpn = (ALPN *)extension->data;
- if (alpn == NULL) {
- WOLFSSL_MSG("ALPN extension not found");
- *data = NULL;
- *dataSz = 0;
- return WOLFSSL_FATAL_ERROR;
- }
-
- if (alpn->negotiated != 1) {
-
- /* consider as an error */
- if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) {
- WOLFSSL_MSG("No protocol match with peer -> Failed");
- return WOLFSSL_FATAL_ERROR;
- }
-
- /* continue without negotiated protocol */
- WOLFSSL_MSG("No protocol match with peer -> Continue");
- return WOLFSSL_ALPN_NOT_FOUND;
- }
-
- if (alpn->next != NULL) {
- WOLFSSL_MSG("Only one protocol name must be accepted");
- return WOLFSSL_FATAL_ERROR;
- }
-
- *data = alpn->protocol_name;
- *dataSz = (word16)XSTRLEN((char*)*data);
-
- return WOLFSSL_SUCCESS;
-}
-
-#define ALPN_FREE_ALL TLSX_ALPN_FreeAll
-#define ALPN_GET_SIZE TLSX_ALPN_GetSize
-#define ALPN_WRITE TLSX_ALPN_Write
-#define ALPN_PARSE TLSX_ALPN_ParseAndSet
-
-#else /* HAVE_ALPN */
-
-#define ALPN_FREE_ALL(list, heap)
-#define ALPN_GET_SIZE(list) 0
-#define ALPN_WRITE(a, b) 0
-#define ALPN_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_ALPN */
-
-/******************************************************************************/
-/* Server Name Indication */
-/******************************************************************************/
-
-#ifdef HAVE_SNI
-
-/** Creates a new SNI object. */
-static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
-{
- SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX);
-
- (void)heap;
-
- if (sni) {
- sni->type = type;
- sni->next = NULL;
-
- #ifndef NO_WOLFSSL_SERVER
- sni->options = 0;
- sni->status = WOLFSSL_SNI_NO_MATCH;
- #endif
-
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- sni->data.host_name = (char*)XMALLOC(size + 1, heap,
- DYNAMIC_TYPE_TLSX);
- if (sni->data.host_name) {
- XSTRNCPY(sni->data.host_name, (const char*)data, size);
- sni->data.host_name[size] = '\0';
- } else {
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- sni = NULL;
- }
- break;
-
- default: /* invalid type */
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- sni = NULL;
- }
- }
-
- return sni;
-}
-
-/** Releases a SNI object. */
-static void TLSX_SNI_Free(SNI* sni, void* heap)
-{
- if (sni) {
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
- break;
- }
-
- XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
-}
-
-/** Releases all SNI objects in the provided list. */
-static void TLSX_SNI_FreeAll(SNI* list, void* heap)
-{
- SNI* sni;
-
- while ((sni = list)) {
- list = sni->next;
- TLSX_SNI_Free(sni, heap);
- }
-}
-
-/** Tells the buffered size of the SNI objects in a list. */
-static word16 TLSX_SNI_GetSize(SNI* list)
-{
- SNI* sni;
- word16 length = OPAQUE16_LEN; /* list length */
-
- while ((sni = list)) {
- list = sni->next;
-
- length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */
-
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- length += (word16)XSTRLEN((char*)sni->data.host_name);
- break;
- }
- }
-
- return length;
-}
-
-/** Writes the SNI objects of a list in a buffer. */
-static word16 TLSX_SNI_Write(SNI* list, byte* output)
-{
- SNI* sni;
- word16 length = 0;
- word16 offset = OPAQUE16_LEN; /* list length offset */
-
- while ((sni = list)) {
- list = sni->next;
-
- output[offset++] = sni->type; /* sni type */
-
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- length = (word16)XSTRLEN((char*)sni->data.host_name);
-
- c16toa(length, output + offset); /* sni length */
- offset += OPAQUE16_LEN;
-
- XMEMCPY(output + offset, sni->data.host_name, length);
-
- offset += length;
- break;
- }
- }
-
- c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
-
- return offset;
-}
-
-/** Finds a SNI object in the provided list. */
-static SNI* TLSX_SNI_Find(SNI *list, byte type)
-{
- SNI* sni = list;
-
- while (sni && sni->type != type)
- sni = sni->next;
-
- return sni;
-}
-
-/** Sets the status of a SNI object. */
-static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
-
- if (sni)
- sni->status = status;
-}
-
-/** Gets the status of a SNI object. */
-byte TLSX_SNI_Status(TLSX* extensions, byte type)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
-
- if (sni)
- return sni->status;
-
- return 0;
-}
-
-/** Parses a buffer of SNI extensions. */
-static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
-#ifndef NO_WOLFSSL_SERVER
- 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);
-
- if (!extension)
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
-
- if (!isRequest) {
- #ifndef NO_WOLFSSL_CLIENT
- if (!extension || !extension->data)
- return TLSX_HandleUnsupportedExtension(ssl);
-
- if (length > 0)
- return BUFFER_ERROR; /* SNI response MUST be empty. */
-
- /* This call enables wolfSSL_SNI_GetRequest() to be called in the
- * client side to fetch the used SNI. It will only work if the SNI
- * was set at the SSL object level. Right now we only support one
- * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the
- * inclusion of other name types will turn this method inaccurate,
- * as the extension response doesn't contains information of which
- * name was accepted.
- */
- TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME,
- WOLFSSL_SNI_REAL_MATCH);
-
- return 0;
- #endif
- }
-
-#ifndef NO_WOLFSSL_SERVER
- if (!extension || !extension->data) {
- #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER)
- /* This will keep SNI even though TLSX_UseSNI has not been called.
- * Enable it so that the received sni is available to functions
- * that use a custom callback when SNI is received.
- */
-
- cacheOnly = 1;
- WOLFSSL_MSG("Forcing SSL object to store SNI parameter");
- #else
- /* Skipping, SNI not enabled at server side. */
- return 0;
- #endif
- }
-
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
-
- ato16(input, &size);
- offset += OPAQUE16_LEN;
-
- /* validating sni list length */
- 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;
-
- 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)
- 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;
-#endif
-
- return 0;
-}
-
-static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest)
-{
- (void)ssl;
-
- if (isRequest) {
- #ifndef NO_WOLFSSL_SERVER
- TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME);
- TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME);
- SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL;
- SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL;
- SNI* sni = NULL;
-
- for (; ctx_sni; ctx_sni = ctx_sni->next) {
- if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
- sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type);
-
- if (sni) {
- if (sni->status != WOLFSSL_SNI_NO_MATCH)
- continue;
-
- /* if ssl level overrides ctx level, it is ok. */
- if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0)
- continue;
- }
-
- SendAlert(ssl, alert_fatal, handshake_failure);
- return SNI_ABSENT_ERROR;
- }
- }
-
- for (; ssl_sni; ssl_sni = ssl_sni->next) {
- if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) {
- if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH)
- continue;
-
- SendAlert(ssl, alert_fatal, handshake_failure);
- return SNI_ABSENT_ERROR;
- }
- }
- #endif /* NO_WOLFSSL_SERVER */
- }
-
- return 0;
-}
-
-int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size,
- void* heap)
-{
- TLSX* extension;
- SNI* sni = NULL;
-
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
-
- if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL)
- return MEMORY_E;
-
- extension = TLSX_Find(*extensions, TLSX_SERVER_NAME);
- if (!extension) {
- int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap);
-
- if (ret != 0) {
- TLSX_SNI_Free(sni, heap);
- return ret;
- }
- }
- else {
- /* push new SNI object to extension data. */
- sni->next = (SNI*)extension->data;
- extension->data = (void*)sni;
-
- /* remove duplicate SNI, there should be only one of each type. */
- do {
- if (sni->next && sni->next->type == type) {
- SNI* next = sni->next;
-
- sni->next = next->next;
- TLSX_SNI_Free(next, heap);
-
- /* there is no way to occur more than
- * two SNIs of the same type.
- */
- break;
- }
- } while ((sni = sni->next));
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-#ifndef NO_WOLFSSL_SERVER
-
-/** Tells the SNI requested by the client. */
-word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
-
- if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) {
- switch (sni->type) {
- case WOLFSSL_SNI_HOST_NAME:
- if (data) {
- *data = sni->data.host_name;
- return (word16)XSTRLEN((char*)*data);
- }
- }
- }
-
- return 0;
-}
-
-/** Sets the options for a SNI object. */
-void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME);
- SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type);
-
- if (sni)
- sni->options = options;
-}
-
-/** Retrieves a SNI request from a client hello buffer. */
-int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
- byte type, byte* sni, word32* inOutSz)
-{
- word32 offset = 0;
- word32 len32 = 0;
- word16 len16 = 0;
-
- if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST)
- return INCOMPLETE_DATA;
-
- /* TLS record header */
- if ((enum ContentType) clientHello[offset++] != handshake) {
-
- /* checking for SSLv2.0 client hello according to: */
- /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */
- if ((enum HandShakeType) clientHello[++offset] == client_hello) {
- offset += ENUM_LEN + VERSION_SZ; /* skip version */
-
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
-
- if (len16 % 3) /* cipher_spec_length must be multiple of 3 */
- return BUFFER_ERROR;
-
- ato16(clientHello + offset, &len16);
- /* Returning SNI_UNSUPPORTED do not increment offset here */
-
- if (len16 != 0) /* session_id_length must be 0 */
- return BUFFER_ERROR;
-
- return SNI_UNSUPPORTED;
- }
-
- return BUFFER_ERROR;
- }
-
- if (clientHello[offset++] != SSLv3_MAJOR)
- return BUFFER_ERROR;
-
- if (clientHello[offset++] < TLSv1_MINOR)
- return SNI_UNSUPPORTED;
-
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
-
- if (offset + len16 > helloSz)
- return INCOMPLETE_DATA;
-
- /* Handshake header */
- if ((enum HandShakeType) clientHello[offset] != client_hello)
- return BUFFER_ERROR;
-
- c24to32(clientHello + offset + 1, &len32);
- offset += HANDSHAKE_HEADER_SZ;
-
- if (offset + len32 > helloSz)
- return BUFFER_ERROR;
-
- /* client hello */
- offset += VERSION_SZ + RAN_LEN; /* version, random */
-
- if (helloSz < offset + clientHello[offset])
- return BUFFER_ERROR;
-
- offset += ENUM_LEN + clientHello[offset]; /* skip session id */
-
- /* cypher suites */
- if (helloSz < offset + OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
-
- if (helloSz < offset + len16)
- return BUFFER_ERROR;
-
- offset += len16; /* skip cypher suites */
-
- /* compression methods */
- if (helloSz < offset + 1)
- return BUFFER_ERROR;
-
- if (helloSz < offset + clientHello[offset])
- return BUFFER_ERROR;
-
- offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */
-
- /* extensions */
- if (helloSz < offset + OPAQUE16_LEN)
- return 0; /* no extensions in client hello. */
-
- ato16(clientHello + offset, &len16);
- offset += OPAQUE16_LEN;
-
- if (helloSz < offset + len16)
- return BUFFER_ERROR;
-
- while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) {
- word16 extType;
- word16 extLen;
-
- ato16(clientHello + offset, &extType);
- offset += OPAQUE16_LEN;
-
- ato16(clientHello + offset, &extLen);
- offset += OPAQUE16_LEN;
-
- if (helloSz < offset + extLen)
- return BUFFER_ERROR;
-
- if (extType != TLSX_SERVER_NAME) {
- offset += extLen; /* skip extension */
- } else {
- word16 listLen;
-
- ato16(clientHello + offset, &listLen);
- offset += OPAQUE16_LEN;
-
- if (helloSz < offset + listLen)
- return BUFFER_ERROR;
-
- while (listLen > ENUM_LEN + OPAQUE16_LEN) {
- byte sniType = clientHello[offset++];
- word16 sniLen;
-
- ato16(clientHello + offset, &sniLen);
- offset += OPAQUE16_LEN;
-
- if (helloSz < offset + sniLen)
- return BUFFER_ERROR;
-
- if (sniType != type) {
- offset += sniLen;
- listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
- continue;
- }
-
- *inOutSz = min(sniLen, *inOutSz);
- XMEMCPY(sni, clientHello + offset, *inOutSz);
-
- return WOLFSSL_SUCCESS;
- }
- }
-
- len16 -= min(2 * OPAQUE16_LEN + extLen, len16);
- }
-
- return len16 ? BUFFER_ERROR : 0;
-}
-
-#endif
-
-#define SNI_FREE_ALL TLSX_SNI_FreeAll
-#define SNI_GET_SIZE TLSX_SNI_GetSize
-#define SNI_WRITE TLSX_SNI_Write
-#define SNI_PARSE TLSX_SNI_Parse
-#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse
-
-#else
-
-#define SNI_FREE_ALL(list, heap)
-#define SNI_GET_SIZE(list) 0
-#define SNI_WRITE(a, b) 0
-#define SNI_PARSE(a, b, c, d) 0
-#define SNI_VERIFY_PARSE(a, b) 0
-
-#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 */
-/******************************************************************************/
-
-#ifdef HAVE_MAX_FRAGMENT
-
-static word16 TLSX_MFL_Write(byte* data, byte* output)
-{
- output[0] = data[0];
-
- return ENUM_LEN;
-}
-
-static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- if (length != ENUM_LEN)
- return BUFFER_ERROR;
-
-#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
- (void) isRequest;
-#else
- if (!isRequest)
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH))
- return TLSX_HandleUnsupportedExtension(ssl);
-#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;
- case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break;
- case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break;
-
- default:
- SendAlert(ssl, alert_fatal, illegal_parameter);
-
- return UNKNOWN_MAX_FRAG_LEN_E;
- }
-
-#ifndef NO_WOLFSSL_SERVER
- if (isRequest) {
- int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap);
-
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
-
- TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH);
- }
-#endif
-
- return 0;
-}
-
-int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap)
-{
- byte* data = NULL;
- int ret = 0;
-
- if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX)
- return BAD_FUNC_ARG;
-
- data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX);
- if (data == NULL)
- return MEMORY_E;
-
- data[0] = mfl;
-
- ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap);
- if (ret != 0) {
- XFREE(data, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-
-#define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
-#define MFL_GET_SIZE(data) ENUM_LEN
-#define MFL_WRITE TLSX_MFL_Write
-#define MFL_PARSE TLSX_MFL_Parse
-
-#else
-
-#define MFL_FREE_ALL(a, b)
-#define MFL_GET_SIZE(a) 0
-#define MFL_WRITE(a, b) 0
-#define MFL_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_MAX_FRAGMENT */
-
-/******************************************************************************/
-/* Truncated HMAC */
-/******************************************************************************/
-
-#ifdef HAVE_TRUNCATED_HMAC
-
-static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- if (length != 0 || input == NULL)
- return BUFFER_ERROR;
-
- if (!isRequest) {
- #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC))
- return TLSX_HandleUnsupportedExtension(ssl);
- #endif
- }
- else {
- #ifndef NO_WOLFSSL_SERVER
- int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap);
-
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
-
- TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC);
- #endif
- }
-
- ssl->truncated_hmac = 1;
-
- return 0;
-}
-
-int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap)
-{
- int ret = 0;
-
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap);
- if (ret != 0)
- return ret;
-
- return WOLFSSL_SUCCESS;
-}
-
-#define THM_PARSE TLSX_THM_Parse
-
-#else
-
-#define THM_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_TRUNCATED_HMAC */
-
-/******************************************************************************/
-/* Certificate Status Request */
-/******************************************************************************/
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST
-
-static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap)
-{
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- FreeOcspRequest(&csr->request.ocsp);
- break;
- }
-
- XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
- (void)heap;
-}
-
-static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest)
-{
- word16 size = 0;
-
- /* shut up compiler warnings */
- (void) csr; (void) isRequest;
-
-#ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- size += ENUM_LEN + 2 * OPAQUE16_LEN;
-
- if (csr->request.ocsp.nonceSz)
- size += OCSP_NONCE_EXT_SZ;
- break;
- }
- }
-#endif
-#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
- if (!isRequest && csr->ssl->options.tls1_3)
- return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length;
-#endif
-
- return size;
-}
-
-static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output,
- byte isRequest)
-{
- /* shut up compiler warnings */
- (void) csr; (void) output; (void) isRequest;
-
-#ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- word16 offset = 0;
- word16 length = 0;
-
- /* type */
- output[offset++] = csr->status_type;
-
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- /* responder id list */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
-
- /* request extensions */
- if (csr->request.ocsp.nonceSz)
- length = (word16)EncodeOcspRequestExtensions(
- &csr->request.ocsp,
- output + offset + OPAQUE16_LEN,
- OCSP_NONCE_EXT_SZ);
-
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN + length;
-
- break;
- }
-
- return offset;
- }
-#endif
-#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER)
- if (!isRequest && csr->ssl->options.tls1_3) {
- word16 offset = 0;
- output[offset++] = csr->status_type;
- c32to24(csr->response.length, output + offset);
- offset += OPAQUE24_LEN;
- XMEMCPY(output + offset, csr->response.buffer, csr->response.length);
- offset += csr->response.length;
- return offset;
- }
-#endif
-
- return 0;
-}
-
-static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- int ret;
-
- /* shut up compiler warnings */
- (void) ssl; (void) input;
-
- if (!isRequest) {
-#ifndef NO_WOLFSSL_CLIENT
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
-
- if (!csr) {
- /* look at context level */
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST);
- csr = extension ? (CertificateStatusRequest*)extension->data : NULL;
-
- if (!csr) /* unexpected extension */
- return TLSX_HandleUnsupportedExtension(ssl);
-
- /* enable extension at ssl level */
- ret = TLSX_UseCertificateStatusRequest(&ssl->extensions,
- csr->status_type, csr->options, ssl,
- ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
-
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- /* propagate nonce */
- if (csr->request.ocsp.nonceSz) {
- OcspRequest* request =
- (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions);
-
- if (request) {
- XMEMCPY(request->nonce, csr->request.ocsp.nonce,
- csr->request.ocsp.nonceSz);
- request->nonceSz = csr->request.ocsp.nonceSz;
- }
- }
- break;
- }
- }
-
- ssl->status_request = 1;
-
- #ifdef WOLFSSL_TLS13
- 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;
- if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP)
- ret = BAD_CERTIFICATE_STATUS_ERROR;
- if (ret == 0) {
- c24to32(input + offset, &resp_length);
- offset += OPAQUE24_LEN;
- 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;
- }
- else
- #endif
- {
- /* extension_data MUST be empty. */
- return length ? BUFFER_ERROR : 0;
- }
-#endif
- }
- else {
-#ifndef NO_WOLFSSL_SERVER
- byte status_type;
- word16 offset = 0;
- word16 size = 0;
-
- if (length == 0)
- return 0;
- if (length < ENUM_LEN)
- return BUFFER_ERROR;
-
- status_type = input[offset++];
-
- switch (status_type) {
- case WOLFSSL_CSR_OCSP: {
-
- /* skip responder_id_list */
- if (length - offset < OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN + size;
-
- /* skip request_extensions */
- if (length - offset < OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN + size;
-
- if (offset > length)
- return BUFFER_ERROR;
-
- /* is able to send OCSP response? */
- if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled)
- return 0;
- }
- break;
-
- /* unknown status type */
- default:
- return 0;
- }
-
- /* if using status_request and already sending it, skip this one */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
- if (ssl->status_request_v2)
- return 0;
- #endif
-
- /* accept the first good status_type and return */
- ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type,
- 0, ssl, ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
-
- #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
- }
-
- return 0;
-}
-
-int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
- int ret = 0;
-
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP: {
- byte nonce[MAX_OCSP_NONCE_SZ];
- int nonceSz = csr->request.ocsp.nonceSz;
-
- /* preserve nonce */
- XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz);
-
- if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap))
- != 0)
- return ret;
-
- /* restore nonce */
- XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz);
- csr->request.ocsp.nonceSz = nonceSz;
- }
- break;
- }
- }
-
- return ret;
-}
-
-void* TLSX_CSR_GetRequest(TLSX* extensions)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
-
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- return &csr->request.ocsp;
- break;
- }
- }
-
- return NULL;
-}
-
-int TLSX_CSR_ForceRequest(WOLFSSL* ssl)
-{
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST);
- CertificateStatusRequest* csr = extension ?
- (CertificateStatusRequest*)extension->data : NULL;
-
- if (csr) {
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- if (ssl->ctx->cm->ocspEnabled) {
- csr->request.ocsp.ssl = ssl;
- return CheckOcspRequest(ssl->ctx->cm->ocsp,
- &csr->request.ocsp, NULL);
- }
- else
- return OCSP_LOOKUP_FAIL;
- }
- }
-
- return 0;
-}
-
-int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type,
- byte options, WOLFSSL* ssl, void* heap,
- int devId)
-{
- CertificateStatusRequest* csr = NULL;
- int ret = 0;
-
- if (!extensions || status_type != WOLFSSL_CSR_OCSP)
- return BAD_FUNC_ARG;
-
- csr = (CertificateStatusRequest*)
- XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX);
- if (!csr)
- return MEMORY_E;
-
- ForceZero(csr, sizeof(CertificateStatusRequest));
-
- csr->status_type = status_type;
- csr->options = options;
- csr->ssl = ssl;
-
- switch (csr->status_type) {
- case WOLFSSL_CSR_OCSP:
- if (options & WOLFSSL_CSR_OCSP_USE_NONCE) {
- WC_RNG rng;
-
- #ifndef HAVE_FIPS
- ret = wc_InitRng_ex(&rng, heap, devId);
- #else
- ret = wc_InitRng(&rng);
- (void)devId;
- #endif
- if (ret == 0) {
- if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce,
- MAX_OCSP_NONCE_SZ) == 0)
- csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ;
-
- wc_FreeRng(&rng);
- }
- }
- break;
- }
-
- if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) {
- XFREE(csr, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-#define CSR_FREE_ALL TLSX_CSR_Free
-#define CSR_GET_SIZE TLSX_CSR_GetSize
-#define CSR_WRITE TLSX_CSR_Write
-#define CSR_PARSE TLSX_CSR_Parse
-
-#else
-
-#define CSR_FREE_ALL(data, heap)
-#define CSR_GET_SIZE(a, b) 0
-#define CSR_WRITE(a, b, c) 0
-#define CSR_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */
-
-/******************************************************************************/
-/* Certificate Status Request v2 */
-/******************************************************************************/
-
-#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2
-
-static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap)
-{
- CertificateStatusRequestItemV2* next;
-
- for (; csr2; csr2 = next) {
- next = csr2->next;
-
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- while(csr2->requests--)
- FreeOcspRequest(&csr2->request.ocsp[csr2->requests]);
- break;
- }
-
- XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
-}
-
-static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2,
- byte isRequest)
-{
- word16 size = 0;
-
- /* shut up compiler warnings */
- (void) csr2; (void) isRequest;
-
-#ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- CertificateStatusRequestItemV2* next;
-
- for (size = OPAQUE16_LEN; csr2; csr2 = next) {
- next = csr2->next;
-
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- size += ENUM_LEN + 3 * OPAQUE16_LEN;
-
- if (csr2->request.ocsp[0].nonceSz)
- size += OCSP_NONCE_EXT_SZ;
- break;
- }
- }
- }
-#endif
-
- return size;
-}
-
-static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2,
- byte* output, byte isRequest)
-{
- /* shut up compiler warnings */
- (void) csr2; (void) output; (void) isRequest;
-
-#ifndef NO_WOLFSSL_CLIENT
- if (isRequest) {
- word16 offset;
- word16 length;
-
- for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) {
- /* status_type */
- output[offset++] = csr2->status_type;
-
- /* request */
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* request_length */
- length = 2 * OPAQUE16_LEN;
-
- if (csr2->request.ocsp[0].nonceSz)
- length += OCSP_NONCE_EXT_SZ;
-
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN;
-
- /* responder id list */
- c16toa(0, output + offset);
- offset += OPAQUE16_LEN;
-
- /* request extensions */
- length = 0;
-
- if (csr2->request.ocsp[0].nonceSz)
- length = (word16)EncodeOcspRequestExtensions(
- &csr2->request.ocsp[0],
- output + offset + OPAQUE16_LEN,
- OCSP_NONCE_EXT_SZ);
-
- c16toa(length, output + offset);
- offset += OPAQUE16_LEN + length;
- break;
- }
- }
-
- /* list size */
- c16toa(offset - OPAQUE16_LEN, output);
-
- return offset;
- }
-#endif
-
- return 0;
-}
-
-static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- int ret;
-
- /* shut up compiler warnings */
- (void) ssl; (void) input;
-
- if (!isRequest) {
-#ifndef NO_WOLFSSL_CLIENT
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
-
- if (!csr2) {
- /* look at context level */
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2);
- csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
-
- if (!csr2) /* unexpected extension */
- return TLSX_HandleUnsupportedExtension(ssl);
-
- /* enable extension at ssl level */
- for (; csr2; csr2 = csr2->next) {
- ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
- csr2->status_type, csr2->options, ssl->heap,
- ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
-
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* propagate nonce */
- if (csr2->request.ocsp[0].nonceSz) {
- OcspRequest* request =
- (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions,
- csr2->status_type, 0);
-
- if (request) {
- XMEMCPY(request->nonce,
- csr2->request.ocsp[0].nonce,
- csr2->request.ocsp[0].nonceSz);
-
- request->nonceSz =
- csr2->request.ocsp[0].nonceSz;
- }
- }
- break;
- }
- }
- }
-
- ssl->status_request_v2 = 1;
-
- return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */
-#endif
- }
- else {
-#ifndef NO_WOLFSSL_SERVER
- byte status_type;
- word16 request_length;
- word16 offset = 0;
- word16 size = 0;
-
- /* list size */
- if (offset + OPAQUE16_LEN >= length) {
- return BUFFER_E;
- }
-
- ato16(input + offset, &request_length);
- offset += OPAQUE16_LEN;
-
- if (length - OPAQUE16_LEN != request_length)
- return BUFFER_ERROR;
-
- while (length > offset) {
- if (length - offset < ENUM_LEN + OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- status_type = input[offset++];
-
- ato16(input + offset, &request_length);
- offset += OPAQUE16_LEN;
-
- if (length - offset < request_length)
- return BUFFER_ERROR;
-
- switch (status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* skip responder_id_list */
- if (length - offset < OPAQUE16_LEN)
- 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;
-
- /* is able to send OCSP response? */
- if (ssl->ctx->cm == NULL
- || !ssl->ctx->cm->ocspStaplingEnabled)
- continue;
- break;
-
- default:
- /* unknown status type, skipping! */
- offset += request_length;
- continue;
- }
-
- /* if using status_request and already sending it, skip this one */
- #ifdef HAVE_CERTIFICATE_STATUS_REQUEST
- if (ssl->status_request)
- return 0;
- #endif
-
- /* accept the first good status_type and return */
- ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions,
- status_type, 0, ssl->heap, ssl->devId);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
-
- TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2);
- ssl->status_request_v2 = status_type;
-
- return 0;
- }
-#endif
- }
-
- return 0;
-}
-
-int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer,
- void* heap)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
- int ret = 0;
-
- for (; csr2; csr2 = csr2->next) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- if (!isPeer || csr2->requests != 0)
- break;
-
- FALL_THROUGH; /* followed by */
-
- case WOLFSSL_CSR2_OCSP_MULTI: {
- if (csr2->requests < 1 + MAX_CHAIN_DEPTH) {
- byte nonce[MAX_OCSP_NONCE_SZ];
- int nonceSz = csr2->request.ocsp[0].nonceSz;
-
- /* preserve nonce, replicating nonce of ocsp[0] */
- XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz);
-
- if ((ret = InitOcspRequest(
- &csr2->request.ocsp[csr2->requests], cert,
- 0, heap)) != 0)
- return ret;
-
- /* restore nonce */
- XMEMCPY(csr2->request.ocsp[csr2->requests].nonce,
- nonce, nonceSz);
- csr2->request.ocsp[csr2->requests].nonceSz = nonceSz;
- csr2->requests++;
- }
- }
- break;
- }
- }
-
- (void)cert;
- return ret;
-}
-
-void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx)
-{
- TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
-
- for (; csr2; csr2 = csr2->next) {
- if (csr2->status_type == status_type) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
-
- case WOLFSSL_CSR2_OCSP_MULTI:
- /* requests are initialized in the reverse order */
- return idx < csr2->requests
- ? &csr2->request.ocsp[csr2->requests - idx - 1]
- : NULL;
- break;
- }
- }
- }
-
- return NULL;
-}
-
-int TLSX_CSR2_ForceRequest(WOLFSSL* ssl)
-{
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2);
- CertificateStatusRequestItemV2* csr2 = extension ?
- (CertificateStatusRequestItemV2*)extension->data : NULL;
-
- /* forces only the first one */
- if (csr2) {
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- /* followed by */
-
- case WOLFSSL_CSR2_OCSP_MULTI:
- if (ssl->ctx->cm->ocspEnabled) {
- csr2->request.ocsp[0].ssl = ssl;
- return CheckOcspRequest(ssl->ctx->cm->ocsp,
- &csr2->request.ocsp[0], NULL);
- }
- else
- return OCSP_LOOKUP_FAIL;
- }
- }
-
- return 0;
-}
-
-int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type,
- byte options, void* heap, int devId)
-{
- TLSX* extension = NULL;
- CertificateStatusRequestItemV2* csr2 = NULL;
- int ret = 0;
-
- if (!extensions)
- return BAD_FUNC_ARG;
-
- if (status_type != WOLFSSL_CSR2_OCSP
- && status_type != WOLFSSL_CSR2_OCSP_MULTI)
- return BAD_FUNC_ARG;
-
- csr2 = (CertificateStatusRequestItemV2*)
- XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX);
- if (!csr2)
- return MEMORY_E;
-
- ForceZero(csr2, sizeof(CertificateStatusRequestItemV2));
-
- csr2->status_type = status_type;
- csr2->options = options;
- csr2->next = NULL;
-
- switch (csr2->status_type) {
- case WOLFSSL_CSR2_OCSP:
- case WOLFSSL_CSR2_OCSP_MULTI:
- if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) {
- WC_RNG rng;
-
- #ifndef HAVE_FIPS
- ret = wc_InitRng_ex(&rng, heap, devId);
- #else
- ret = wc_InitRng(&rng);
- (void)devId;
- #endif
- if (ret == 0) {
- if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce,
- MAX_OCSP_NONCE_SZ) == 0)
- csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ;
-
- wc_FreeRng(&rng);
- }
- }
- break;
- }
-
- /* append new item */
- if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) {
- CertificateStatusRequestItemV2* last =
- (CertificateStatusRequestItemV2*)extension->data;
-
- for (; last->next; last = last->next);
-
- last->next = csr2;
- }
- else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) {
- XFREE(csr2, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-#define CSR2_FREE_ALL TLSX_CSR2_FreeAll
-#define CSR2_GET_SIZE TLSX_CSR2_GetSize
-#define CSR2_WRITE TLSX_CSR2_Write
-#define CSR2_PARSE TLSX_CSR2_Parse
-
-#else
-
-#define CSR2_FREE_ALL(data, heap)
-#define CSR2_GET_SIZE(a, b) 0
-#define CSR2_WRITE(a, b, c) 0
-#define CSR2_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */
-
-/******************************************************************************/
-/* Supported Elliptic Curves */
-/******************************************************************************/
-
-#ifdef HAVE_SUPPORTED_CURVES
-
-#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. \
- Alternatively use FFDHE for DH ciperhsuites.
-#endif
-
-static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name,
- void* heap)
-{
- if (curve == NULL)
- return BAD_FUNC_ARG;
-
- (void)heap;
-
- *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap,
- DYNAMIC_TYPE_TLSX);
- if (*curve == NULL)
- return MEMORY_E;
-
- (*curve)->name = name;
- (*curve)->next = NULL;
-
- return 0;
-}
-
-static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap)
-{
- if (point == NULL)
- return BAD_FUNC_ARG;
-
- (void)heap;
-
- *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap,
- DYNAMIC_TYPE_TLSX);
- if (*point == NULL)
- return MEMORY_E;
-
- (*point)->format = format;
- (*point)->next = NULL;
-
- return 0;
-}
-
-static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap)
-{
- SupportedCurve* curve;
-
- while ((curve = list)) {
- list = curve->next;
- XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
-}
-
-static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap)
-{
- PointFormat* point;
-
- while ((point = list)) {
- list = point->next;
- XFREE(point, heap, DYNAMIC_TYPE_TLSX);
- }
- (void)heap;
-}
-
-static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name,
- void* heap)
-{
- int ret = BAD_FUNC_ARG;
-
- while (list) {
- if (list->name == name) {
- ret = 0; /* curve already in use */
- break;
- }
-
- if (list->next == NULL) {
- ret = TLSX_SupportedCurve_New(&list->next, name, heap);
- break;
- }
-
- list = list->next;
- }
-
- return ret;
-}
-
-static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap)
-{
- int ret = BAD_FUNC_ARG;
-
- while (list) {
- if (list->format == format) {
- ret = 0; /* format already in use */
- break;
- }
-
- if (list->next == NULL) {
- ret = TLSX_PointFormat_New(&list->next, format, heap);
- break;
- }
-
- list = list->next;
- }
-
- return ret;
-}
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
-
-static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
-{
- 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) {
- #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));
-}
-
-static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
-{
- 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) {
- #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));
-}
-
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-
-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) {
-#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
-#ifndef NO_WOLFSSL_CLIENT
-
-static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list)
-{
- SupportedCurve* curve;
- word16 length = OPAQUE16_LEN; /* list length */
-
- while ((curve = list)) {
- list = curve->next;
- length += OPAQUE16_LEN; /* curve length */
- }
-
- return length;
-}
-
-#endif
-
-static word16 TLSX_PointFormat_GetSize(PointFormat* list)
-{
- PointFormat* point;
- word16 length = ENUM_LEN; /* list length */
-
- while ((point = list)) {
- list = point->next;
- length += ENUM_LEN; /* format length */
- }
-
- return length;
-}
-
-#ifndef NO_WOLFSSL_CLIENT
-
-static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output)
-{
- word16 offset = OPAQUE16_LEN;
-
- while (list) {
- c16toa(list->name, output + offset);
- offset += OPAQUE16_LEN;
- list = list->next;
- }
-
- c16toa(offset - OPAQUE16_LEN, output); /* writing list length */
-
- return offset;
-}
-
-#endif
-
-static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output)
-{
- word16 offset = ENUM_LEN;
-
- while (list) {
- output[offset++] = list->format;
- list = list->next;
- }
-
- output[0] = (byte)(offset - ENUM_LEN);
-
- return offset;
-}
-
-#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
- !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
-
-static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- word16 offset;
- word16 name;
- int ret;
-
- 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;
-
- ato16(input, &offset);
-
- /* validating curve list length */
- if (length != OPAQUE16_LEN + offset)
- return BUFFER_ERROR;
-
- offset = OPAQUE16_LEN;
- if (offset == length)
- return 0;
-
-#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)
- if (!isRequest) {
- TLSX* extension;
- SupportedCurve* curve;
-
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension != NULL) {
- /* Replace client list with server list of supported groups. */
- curve = (SupportedCurve*)extension->data;
- extension->data = NULL;
- TLSX_SupportedCurve_FreeAll(curve, ssl->heap);
-
- ato16(input + offset, &name);
- offset += OPAQUE16_LEN;
-
- ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap);
- if (ret != 0)
- return ret; /* throw error */
- extension->data = (void*)curve;
- }
- }
-#endif
-
- for (; offset < length; offset += OPAQUE16_LEN) {
- ato16(input + offset, &name);
-
- ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
- }
-
- return 0;
-}
-
-#endif
-
-#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.
- *
- * ssl SSL/TLS object.
- * returns 0 on success, otherwise an error.
- */
-int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl)
-{
- int ret;
- TLSX* extension;
- TLSX* priority = NULL;
- TLSX* ext = NULL;
- word16 name;
- SupportedCurve* curve;
-
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- /* May be doing PSK with no key exchange. */
- if (extension == NULL)
- return 0;
-
- if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS)
- return ret;
-
- ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS);
- curve = (SupportedCurve*)ext->data;
- name = curve->name;
-
- curve = (SupportedCurve*)extension->data;
- while (curve != NULL) {
- if (curve->name == name)
- break;
- curve = curve->next;
- }
-
- if (curve == NULL) {
- /* Couldn't find the preferred group in client list. */
- extension->resp = 1;
-
- /* Send server list back and free client list. */
- curve = (SupportedCurve*)extension->data;
- extension->data = ext->data;
- ext->data = curve;
- }
-
- TLSX_FreeAll(priority, ssl->heap);
-
- return 0;
-}
-
-#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.
- *
- * ssl SSL/TLS object.
- * checkSupported Whether to check for the first supported group.
- * returns BAD_FUNC_ARG if no group found, otherwise the group.
- */
-int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported)
-{
- TLSX* extension;
- SupportedCurve* curve;
-
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension == NULL)
- return BAD_FUNC_ARG;
-
- curve = (SupportedCurve*)extension->data;
- while (curve != NULL) {
- if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name))
- return curve->name;
- curve = curve->next;
- }
-
- return BAD_FUNC_ARG;
-}
-
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-
-static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- int ret;
-
- /* validating formats list length */
- if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0])
- return BUFFER_ERROR;
-
- if (isRequest) {
- /* adding uncompressed point format to response */
- ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED,
- ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret; /* throw error */
-
- TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS);
- }
-
- return 0;
-}
-
-#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
-int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) {
- 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 */
-
- (void)oid;
-
- if (first == ECC_BYTE || first == CHACHA_BYTE)
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (!extension)
- return 1; /* no suite restriction */
-
- for (curve = (SupportedCurve*)extension->data;
- curve && !(sig && key);
- 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
-
- /* find supported curve */
- switch (curve->name) {
-#ifdef HAVE_ECC
- #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP160R1:
- pkOid = oid = ECC_SECP160R1_OID;
- octets = 20;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_SECPR2
- case WOLFSSL_ECC_SECP160R2:
- pkOid = oid = ECC_SECP160R2_OID;
- octets = 20;
- break;
- #endif /* HAVE_ECC_SECPR2 */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP160K1:
- pkOid = oid = ECC_SECP160K1_OID;
- octets = 20;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP192R1:
- pkOid = oid = ECC_SECP192R1_OID;
- octets = 24;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP192K1:
- pkOid = oid = ECC_SECP192K1_OID;
- octets = 24;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP224R1:
- pkOid = oid = ECC_SECP224R1_OID;
- octets = 28;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP224K1:
- pkOid = oid = ECC_SECP224K1_OID;
- octets = 28;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #endif
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- pkOid = oid = ECC_SECP256R1_OID;
- octets = 32;
- break;
- #endif /* !NO_ECC_SECP */
- #endif /* !NO_ECC256 || HAVE_ALL_CURVES */
-#endif
- #ifdef HAVE_CURVE25519
- case WOLFSSL_ECC_X25519:
- oid = ECC_X25519_OID;
- #ifdef HAVE_ED25519
- pkOid = ECC_ED25519_OID;
- #else
- pkOid = ECC_X25519_OID;
- #endif
- octets = 32;
- break;
- #endif /* HAVE_CURVE25519 */
-#ifdef HAVE_ECC
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifdef HAVE_ECC_KOBLITZ
- case WOLFSSL_ECC_SECP256K1:
- pkOid = oid = ECC_SECP256K1_OID;
- octets = 32;
- break;
- #endif /* HAVE_ECC_KOBLITZ */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP256R1:
- pkOid = oid = ECC_BRAINPOOLP256R1_OID;
- octets = 32;
- 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:
- pkOid = oid = ECC_SECP384R1_OID;
- octets = 48;
- break;
- #endif /* !NO_ECC_SECP */
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP384R1:
- pkOid = oid = ECC_BRAINPOOLP384R1_OID;
- octets = 48;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #endif
- #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES)
- #ifdef HAVE_ECC_BRAINPOOL
- case WOLFSSL_ECC_BRAINPOOLP512R1:
- pkOid = oid = ECC_BRAINPOOLP512R1_OID;
- octets = 64;
- break;
- #endif /* HAVE_ECC_BRAINPOOL */
- #endif
- #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- pkOid = oid = ECC_SECP521R1_OID;
- octets = 66;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
-#endif
- default: continue; /* unsupported curve */
- }
-
- #ifdef HAVE_ECC
- /* Set default Oid */
- if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) {
- defOid = oid;
- 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) {
- nextOid = oid;
- nextSz = octets;
- }
- #else
- if (defOid == 0 && defSz > octets) {
- defOid = oid;
- defSz = octets;
- }
-
- if (currOid == 0)
- currOid = oid;
- if (nextOid == 0 || nextSz > octets) {
- nextOid = oid;
- nextSz = octets;
- }
- #endif
-
- if (first == ECC_BYTE) {
- switch (second) {
- /* ECDHE_ECDSA */
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
- case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8:
- case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8:
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
-
-#ifdef WOLFSSL_STATIC_DH
- /* ECDH_ECDSA */
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
- case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid == ECC_X448_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->pkCurveOID == oid;
- break;
-#endif /* WOLFSSL_STATIC_DH */
-#ifndef NO_RSA
- /* ECDHE_RSA */
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
- sig = 1;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
-
-#ifdef WOLFSSL_STATIC_DH
- /* ECDH_RSA */
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
- case TLS_ECDH_RSA_WITH_RC4_128_SHA:
- case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
- case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
- case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
- case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
- case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- if (oid == ECC_X448_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- sig = 1;
- key |= ssl->pkCurveOID == pkOid;
- break;
-#endif /* WOLFSSL_STATIC_DH */
-#endif
- default:
- if (oid == ECC_X25519_OID && defOid == oid) {
- defOid = 0;
- defSz = 80;
- }
- 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;
- }
- }
-
- /* ChaCha20-Poly1305 ECC cipher suites */
- if (first == CHACHA_BYTE) {
- switch (second) {
- /* ECDHE_ECDSA */
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 :
- case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
- sig |= ssl->pkCurveOID == pkOid;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
-#ifndef NO_RSA
- /* ECDHE_RSA */
- case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 :
- case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 :
- sig = 1;
- key |= ssl->ecdhCurveOID == oid;
- ephmSuite = 1;
- break;
-#endif
- default:
- sig = 1;
- key = 1;
- break;
- }
- }
- }
-
- /* Choose the default if it is at the required strength. */
-#ifdef HAVE_ECC
- if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz)
-#else
- if (ssl->ecdhCurveOID == 0)
-#endif
- {
- key = 1;
- ssl->ecdhCurveOID = defOid;
- }
- /* Choose any curve at the required strength. */
- if (ssl->ecdhCurveOID == 0) {
- key = 1;
- ssl->ecdhCurveOID = currOid;
- }
- /* Choose the default if it is at the next highest strength. */
- if (ssl->ecdhCurveOID == 0 && defSz == nextSz)
- ssl->ecdhCurveOID = defOid;
- /* Choose any curve at the next highest strength. */
- if (ssl->ecdhCurveOID == 0)
- ssl->ecdhCurveOID = nextOid;
- /* No curve and ephemeral ECC suite requires a matching curve. */
- if (ssl->ecdhCurveOID == 0 && ephmSuite)
- key = 0;
-
- return sig && key;
-}
-#endif
-
-#endif /* NO_WOLFSSL_SERVER */
-
-int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap)
-{
- TLSX* extension = NULL;
- SupportedCurve* curve = NULL;
- int ret;
-
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS);
-
- if (!extension) {
- ret = TLSX_SupportedCurve_New(&curve, name, heap);
- if (ret != 0)
- return ret;
-
- ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap);
- if (ret != 0) {
- XFREE(curve, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name,
- heap);
- if (ret != 0)
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap)
-{
- TLSX* extension = NULL;
- PointFormat* point = NULL;
- int ret = 0;
-
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS);
-
- if (!extension) {
- ret = TLSX_PointFormat_New(&point, format, heap);
- if (ret != 0)
- return ret;
-
- ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap);
- if (ret != 0) {
- XFREE(point, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format,
- heap);
- if (ret != 0)
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-#define EC_FREE_ALL TLSX_SupportedCurve_FreeAll
-#define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest
-
-#ifndef NO_WOLFSSL_CLIENT
-#define EC_GET_SIZE TLSX_SupportedCurve_GetSize
-#define EC_WRITE TLSX_SupportedCurve_Write
-#else
-#define EC_GET_SIZE(list) 0
-#define EC_WRITE(a, b) 0
-#endif
-
-#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \
- !defined(WOLFSSL_NO_SERVER_GROUPS_EXT))
-#define EC_PARSE TLSX_SupportedCurve_Parse
-#else
-#define EC_PARSE(a, b, c, d) 0
-#endif
-
-#define PF_FREE_ALL TLSX_PointFormat_FreeAll
-#define PF_VALIDATE_REQUEST TLSX_PointFormat_ValidateRequest
-#define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse
-
-#define PF_GET_SIZE TLSX_PointFormat_GetSize
-#define PF_WRITE TLSX_PointFormat_Write
-
-#ifndef NO_WOLFSSL_SERVER
-#define PF_PARSE TLSX_PointFormat_Parse
-#else
-#define PF_PARSE(a, b, c, d) 0
-#endif
-
-#else
-
-#define EC_FREE_ALL(list, heap)
-#define EC_GET_SIZE(list) 0
-#define EC_WRITE(a, b) 0
-#define EC_PARSE(a, b, c, d) 0
-#define EC_VALIDATE_REQUEST(a, b)
-
-#define PF_FREE_ALL(list, heap)
-#define PF_GET_SIZE(list) 0
-#define PF_WRITE(a, b) 0
-#define PF_PARSE(a, b, c, d) 0
-#define PF_VALIDATE_REQUEST(a, b)
-#define PF_VALIDATE_RESPONSE(a, b)
-
-#endif /* HAVE_SUPPORTED_CURVES */
-
-/******************************************************************************/
-/* Renegotiation Indication */
-/******************************************************************************/
-
-#if defined(HAVE_SECURE_RENEGOTIATION) \
- || defined(HAVE_SERVER_RENEGOTIATION_INFO)
-
-static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data,
- int isRequest)
-{
- byte length = OPAQUE8_LEN; /* empty info length */
-
- /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */
- if (data && data->enabled && data->verifySet) {
- /* client sends client_verify_data only */
- length += TLS_FINISHED_SZ;
-
- /* server also sends server_verify_data */
- if (!isRequest)
- length += TLS_FINISHED_SZ;
- }
-
- return length;
-}
-
-static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data,
- byte* output, int isRequest)
-{
- word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */
- 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;
-
- /* server also sends server_verify_data */
- if (!isRequest) {
- XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ);
- offset += TLS_FINISHED_SZ;
- }
- }
-
- output[0] = (byte)(offset - 1); /* info length - self */
-
- return offset;
-}
-
-static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input,
- word16 length, byte isRequest)
-{
- int ret = SECURE_RENEGOTIATION_E;
-
- if (length >= OPAQUE8_LEN) {
- if (isRequest) {
- #ifndef NO_WOLFSSL_SERVER
- 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 {
- /* already in error state */
- WOLFSSL_MSG("SCR client verify data Failure");
- }
- }
- }
- #endif
- }
- else {
- #ifndef NO_WOLFSSL_CLIENT
- if (!ssl->secure_renegotiation->enabled) {
- if (*input == 0) {
- ssl->secure_renegotiation->enabled = 1;
- ret = 0;
- }
- }
- else if (*input == 2 * TLS_FINISHED_SZ &&
- length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) {
- input++; /* get past size */
-
- /* validate client and server verify data */
- if (XMEMCMP(input,
- ssl->secure_renegotiation->client_verify_data,
- TLS_FINISHED_SZ) == 0 &&
- XMEMCMP(input + TLS_FINISHED_SZ,
- ssl->secure_renegotiation->server_verify_data,
- TLS_FINISHED_SZ) == 0) {
- WOLFSSL_MSG("SCR client and server verify data match");
- ret = 0; /* verified */
- } else {
- /* already in error state */
- WOLFSSL_MSG("SCR client and server verify data Failure");
- }
- }
- #endif
- }
- }
-
- if (ret != 0) {
- SendAlert(ssl, alert_fatal, handshake_failure);
- }
-
- return ret;
-}
-
-int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap)
-{
- int ret = 0;
- SecureRenegotiation* data;
-
- data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap,
- DYNAMIC_TYPE_TLSX);
- if (data == NULL)
- return MEMORY_E;
-
- XMEMSET(data, 0, sizeof(SecureRenegotiation));
-
- ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap);
- if (ret != 0) {
- XFREE(data, heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
-
- return WOLFSSL_SUCCESS;
-}
-
-#ifdef HAVE_SERVER_RENEGOTIATION_INFO
-
-int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap)
-{
- int 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;
-
- return WOLFSSL_SUCCESS;
-}
-
-#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
-
-
-#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX)
-#define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize
-#define SCR_WRITE TLSX_SecureRenegotiation_Write
-#define SCR_PARSE TLSX_SecureRenegotiation_Parse
-
-#else
-
-#define SCR_FREE_ALL(a, heap)
-#define SCR_GET_SIZE(a, b) 0
-#define SCR_WRITE(a, b, c) 0
-#define SCR_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_SECURE_RENEGOTIATION */
-
-/******************************************************************************/
-/* Session Tickets */
-/******************************************************************************/
-
-#ifdef HAVE_SESSION_TICKET
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
-static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl)
-{
- TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET);
- SessionTicket* ticket = extension ?
- (SessionTicket*)extension->data : NULL;
-
- if (ticket) {
- /* TODO validate ticket timeout here! */
- if (ticket->lifetime == 0xfffffff) {
- /* send empty ticket on timeout */
- TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- }
- }
-}
-#endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
-
-
-static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest)
-{
- (void)isRequest;
- return ticket ? ticket->size : 0;
-}
-
-static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output,
- int isRequest)
-{
- word16 offset = 0; /* empty ticket */
-
- if (isRequest && ticket) {
- XMEMCPY(output + offset, ticket->data, ticket->size);
- offset += ticket->size;
- }
-
- return offset;
-}
-
-
-static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- int ret = 0;
-
- (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */
-
- if (!isRequest) {
- if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET))
- return TLSX_HandleUnsupportedExtension(ssl);
-
- if (length != 0)
- return BUFFER_ERROR;
-
-#ifndef NO_WOLFSSL_CLIENT
- ssl->expect_session_ticket = 1;
-#endif
- }
-#ifndef NO_WOLFSSL_SERVER
- else {
- /* server side */
- if (ssl->ctx->ticketEncCb == NULL) {
- WOLFSSL_MSG("Client sent session ticket, server has no callback");
- return 0;
- }
-
- if (length == 0) {
- /* blank ticket */
- ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- ret = 0;
- TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */
- ssl->options.createTicket = 1; /* will send ticket msg */
- ssl->options.useTicket = 1;
- ssl->options.resuming = 0; /* no standard resumption */
- ssl->arrays->sessionIDSz = 0; /* no echo on blank ticket */
- }
- } else {
- /* got actual ticket from client */
- ret = DoClientTicket(ssl, input, length);
- if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */
- WOLFSSL_MSG("Using existing client ticket");
- ssl->options.useTicket = 1;
- ssl->options.resuming = 1;
- } else if (ret == WOLFSSL_TICKET_RET_CREATE) {
- WOLFSSL_MSG("Using existing client ticket, creating new one");
- ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap);
- if (ret == WOLFSSL_SUCCESS) {
- ret = 0;
- TLSX_SetResponse(ssl, TLSX_SESSION_TICKET);
- /* send blank ticket */
- ssl->options.createTicket = 1; /* will send ticket msg */
- ssl->options.useTicket = 1;
- ssl->options.resuming = 1;
- }
- } else if (ret == WOLFSSL_TICKET_RET_REJECT) {
- WOLFSSL_MSG("Process client ticket rejected, not using");
- ssl->options.rejectTicket = 1;
- ret = 0; /* not fatal */
- } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) {
- WOLFSSL_MSG("Process client ticket fatal error, not using");
- }
- }
- }
-#endif /* NO_WOLFSSL_SERVER */
-
- return ret;
-}
-
-WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime,
- byte* data, word16 size, void* heap)
-{
- SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket),
- heap, DYNAMIC_TYPE_TLSX);
- if (ticket) {
- ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX);
- if (ticket->data == NULL) {
- XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
- return NULL;
- }
-
- XMEMCPY(ticket->data, data, size);
- ticket->size = size;
- ticket->lifetime = lifetime;
- }
-
- (void)heap;
-
- return ticket;
-}
-WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap)
-{
- if (ticket) {
- XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX);
- XFREE(ticket, heap, DYNAMIC_TYPE_TLSX);
- }
-
- (void)heap;
-}
-
-int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap)
-{
- int ret = 0;
-
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- /* If the ticket is NULL, the client will request a new ticket from the
- server. Otherwise, the client will use it in the next client hello. */
- if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, heap))
- != 0)
- return ret;
-
- return WOLFSSL_SUCCESS;
-}
-
-#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest
-#define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize
-#define WOLF_STK_WRITE TLSX_SessionTicket_Write
-#define WOLF_STK_PARSE TLSX_SessionTicket_Parse
-#define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap))
-
-#else
-
-#define WOLF_STK_FREE(a, b)
-#define WOLF_STK_VALIDATE_REQUEST(a)
-#define WOLF_STK_GET_SIZE(a, b) 0
-#define WOLF_STK_WRITE(a, b, c) 0
-#define WOLF_STK_PARSE(a, b, c, d) 0
-
-#endif /* HAVE_SESSION_TICKET */
-
-/******************************************************************************/
-/* Quantum-Safe-Hybrid */
-/******************************************************************************/
-
-#ifdef HAVE_QSH
-#if defined(HAVE_NTRU)
-static WC_RNG* gRng;
-static wolfSSL_Mutex* gRngMutex;
-#endif
-
-static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap)
-{
- QSHScheme* current;
-
- while ((current = list)) {
- list = current->next;
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
-
- (void)heap;
-}
-
-static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub,
- word16 pubLen)
-{
- QSHScheme* temp;
-
- if (list == NULL)
- return BAD_FUNC_ARG;
-
- if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
-
- temp->name = name;
- temp->PK = pub;
- temp->PKLen = pubLen;
- temp->next = *list;
-
- *list = temp;
-
- return 0;
-}
-
-
-/* request for server's public key : 02 indicates 0-2 requested */
-static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest)
-{
- if (isRequest) {
- /* only request one public key from the server */
- output[0] = 0x01;
-
- return OPAQUE8_LEN;
- }
- else {
- return 0;
- }
-}
-
-#ifndef NO_WOLFSSL_CLIENT
-
-/* check for TLS_QSH suite */
-static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore)
-{
- int i;
-
- for (i = 0; i < ssl->suites->suiteSz; i+= 2)
- if (ssl->suites->suites[i] == QSH_BYTE)
- return;
-
- /* No QSH suite found */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID));
-}
-
-
-/* return the size of the QSH hello extension
- list the list of QSHScheme structs containing id and key
- isRequest if 1 then is being sent to the server
- */
-word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest)
-{
- QSHScheme* temp = list;
- word16 length = 0;
-
- /* account for size of scheme list and public key list */
- if (isRequest)
- length = OPAQUE16_LEN;
- length += OPAQUE24_LEN;
-
- /* for each non null element in list add size */
- while ((temp)) {
- /* add public key info Scheme | Key Length | Key */
- length += OPAQUE16_LEN;
- length += OPAQUE16_LEN;
- length += temp->PKLen;
-
- /* if client add name size for scheme list
- advance to next QSHScheme struct in list */
- if (isRequest)
- length += OPAQUE16_LEN;
- temp = temp->next;
- }
-
- /* add length for request server public keys */
- if (isRequest)
- length += OPAQUE8_LEN;
-
- return length;
-}
-
-
-/* write out a list of QSHScheme IDs */
-static word16 TLSX_QSH_Write(QSHScheme* list, byte* output)
-{
- QSHScheme* current = list;
- word16 length = 0;
-
- length += OPAQUE16_LEN;
-
- while (current) {
- c16toa(current->name, output + length);
- length += OPAQUE16_LEN;
- current = (QSHScheme*)current->next;
- }
-
- c16toa(length - OPAQUE16_LEN, output); /* writing list length */
-
- return length;
-}
-
-
-/* write public key list in extension */
-static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output)
-{
- word32 offset = 0;
- word16 public_len = 0;
-
- if (!format)
- return offset;
-
- /* write scheme ID */
- c16toa(format->name, output + offset);
- offset += OPAQUE16_LEN;
-
- /* write public key matching scheme */
- public_len = format->PKLen;
- c16toa(public_len, output + offset);
- offset += OPAQUE16_LEN;
- if (format->PK) {
- XMEMCPY(output+offset, format->PK, public_len);
- }
-
- return public_len + offset;
-}
-
-word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output)
-{
- QSHScheme* current = list;
- word32 length = 0;
- word24 toWire;
-
- length += OPAQUE24_LEN;
-
- while (current) {
- length += TLSX_QSHPK_WriteR(current, output + length);
- current = (QSHScheme*)current->next;
- }
- /* length of public keys sent */
- c32to24(length - OPAQUE24_LEN, toWire);
- output[0] = toWire[0];
- output[1] = toWire[1];
- output[2] = toWire[2];
-
- return length;
-}
-
-#endif /* NO_WOLFSSL_CLIENT */
-#ifndef NO_WOLFSSL_SERVER
-
-static void TLSX_QSHAgreement(TLSX** extensions, void* heap)
-{
- TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- QSHScheme* format = NULL;
- QSHScheme* del = NULL;
- QSHScheme* prev = NULL;
-
- if (extension == NULL)
- return;
-
- format = (QSHScheme*)extension->data;
- while (format) {
- if (format->PKLen == 0) {
- /* case of head */
- if (format == extension->data) {
- extension->data = format->next;
- }
- if (prev)
- prev->next = format->next;
- del = format;
- format = format->next;
- XFREE(del, heap, DYNAMIC_TYPE_TMP_BUFFER);
- del = NULL;
- } else {
- prev = format;
- format = format->next;
- }
- }
-
- (void)heap;
-}
-
-
-/* Parse in hello extension
- input the byte stream to process
- length length of total extension found
- isRequest set to 1 if being sent to the server
- */
-static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte isRequest)
-{
- byte numKeys = 0;
- word16 offset = 0;
- word16 schemSz = 0;
- word16 offset_len = 0;
- word32 offset_pk = 0;
- word16 name = 0;
- word16 PKLen = 0;
- byte* PK = NULL;
- int r;
-
-
- if (OPAQUE16_LEN > length)
- return BUFFER_ERROR;
-
- if (isRequest) {
- ato16(input, &schemSz);
-
- /* list of public keys available for QSH schemes */
- offset_len = schemSz + OPAQUE16_LEN;
- }
-
- offset_pk = ((input[offset_len] << 16) & 0xFF00000) |
- (((input[offset_len + 1]) << 8) & 0xFF00) |
- (input[offset_len + 2] & 0xFF);
- offset_len += OPAQUE24_LEN;
-
- /* check buffer size */
- if (offset_pk > length)
- return BUFFER_ERROR;
-
- /* set maximum number of keys the client will accept */
- if (!isRequest)
- numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest;
-
- /* hello extension read list of scheme ids */
- if (isRequest) {
-
- /* read in request for public keys */
- ssl->minRequest = (input[length -1] >> 4) & 0xFF;
- ssl->maxRequest = input[length -1] & 0x0F;
-
- /* choose the min between min requested by client and 1 */
- numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
-
- if (ssl->minRequest > ssl->maxRequest)
- return BAD_FUNC_ARG;
-
- offset += OPAQUE16_LEN;
- schemSz += offset;
-
- /* check buffer size */
- if (schemSz > length)
- return BUFFER_ERROR;
-
- while ((offset < schemSz) && numKeys) {
- /* Scheme ID list */
- ato16(input + offset, &name);
- offset += OPAQUE16_LEN;
-
- /* validate we have scheme id */
- if (ssl->user_set_QSHSchemes &&
- !TLSX_ValidateQSHScheme(&ssl->extensions, name)) {
- continue;
- }
-
- /* server create keys on demand */
- if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return r;
- }
-
- /* peer sent an agreed upon scheme */
- r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap);
-
- if (r != WOLFSSL_SUCCESS) return r; /* throw error */
-
- numKeys--;
- }
-
- /* choose the min between min requested by client and 1 */
- numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1;
- }
-
- /* QSHPK struct */
- offset_pk += offset_len;
- while ((offset_len < offset_pk) && numKeys) {
- QSHKey * temp;
-
- if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
-
- /* initialize */
- temp->next = NULL;
- temp->pub.buffer = NULL;
- temp->pub.length = 0;
- temp->pri.buffer = NULL;
- temp->pri.length = 0;
-
- /* scheme id */
- ato16(input + offset_len, &(temp->name));
- offset_len += OPAQUE16_LEN;
-
- /* public key length */
- ato16(input + offset_len, &PKLen);
- temp->pub.length = PKLen;
- offset_len += OPAQUE16_LEN;
-
-
- if (isRequest) {
- /* validate we have scheme id */
- if (ssl->user_set_QSHSchemes &&
- (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) {
- offset_len += PKLen;
- XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
- continue;
- }
- }
-
- /* read in public key */
- if (PKLen > 0) {
- temp->pub.buffer = (byte*)XMALLOC(temp->pub.length,
- ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length);
- offset_len += PKLen;
- }
- else {
- PK = NULL;
- }
-
- /* use own key when adding to extensions list for sending reply */
- PKLen = 0;
- PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name);
- r = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen,
- ssl->heap);
-
- /* store peers key */
- ssl->peerQSHKeyPresent = 1;
- if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0)
- return MEMORY_E;
-
- if (temp->pub.length == 0) {
- XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX);
- }
-
- if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */
-
- numKeys--;
- }
-
- /* reply to a QSH extension sent from client */
- if (isRequest) {
- TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID);
- /* only use schemes we have key generated for -- free the rest */
- TLSX_QSHAgreement(&ssl->extensions, ssl->heap);
- }
-
- return 0;
-}
-
-
-/* Used for parsing in QSHCipher structs on Key Exchange */
-int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length,
- byte isServer)
-{
- QSHKey* key;
- word16 Max_Secret_Len = 48;
- word16 offset = 0;
- word16 offset_len = 0;
- word32 offset_pk = 0;
- word16 name = 0;
- word16 secretLen = 0;
- byte* secret = NULL;
- word16 buffLen = 0;
- byte buff[145]; /* size enough for 3 secrets */
- buffer* buf;
-
- /* pointer to location where secret should be stored */
- if (isServer) {
- buf = ssl->QSH_secret->CliSi;
- }
- else {
- buf = ssl->QSH_secret->SerSi;
- }
-
- offset_pk = ((input[offset_len] << 16) & 0xFF0000) |
- (((input[offset_len + 1]) << 8) & 0xFF00) |
- (input[offset_len + 2] & 0xFF);
- offset_len += OPAQUE24_LEN;
-
- /* validating extension list length -- check if trying to read over edge
- of buffer */
- if (length < (offset_pk + OPAQUE24_LEN)) {
- return BUFFER_ERROR;
- }
-
- /* QSHCipherList struct */
- offset_pk += offset_len;
- while (offset_len < offset_pk) {
-
- /* scheme id */
- ato16(input + offset_len, &name);
- offset_len += OPAQUE16_LEN;
-
- /* public key length */
- ato16(input + offset_len, &secretLen);
- offset_len += OPAQUE16_LEN;
-
- /* read in public key */
- if (secretLen > 0) {
- secret = (byte*)(input + offset_len);
- offset_len += secretLen;
- }
- else {
- secret = NULL;
- }
-
- /* no secret sent */
- if (secret == NULL)
- continue;
-
- /* find corresponding key */
- key = ssl->QSH_Key;
- while (key) {
- if (key->name == name)
- break;
- else
- key = (QSHKey*)key->next;
- }
-
- /* if we do not have the key than there was a big issue negotiation */
- if (key == NULL) {
- WOLFSSL_MSG("key was null for decryption!!!\n");
- return MEMORY_E;
- }
-
- /* Decrypt sent secret */
- buffLen = Max_Secret_Len;
- QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen);
- offset += buffLen;
- }
-
- /* allocate memory for buffer */
- buf->length = offset;
- buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
- if (buf->buffer == NULL)
- return MEMORY_E;
-
- /* store secrets */
- XMEMCPY(buf->buffer, buff, offset);
- ForceZero(buff, offset);
-
- return offset_len;
-}
-
-
-/* return 1 on success */
-int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) {
- TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID);
- QSHScheme* format = NULL;
-
- /* if no extension is sent then do not use QSH */
- if (!extension) {
- WOLFSSL_MSG("No QSH Extension");
- return 0;
- }
-
- for (format = (QSHScheme*)extension->data; format; format = format->next) {
- if (format->name == theirs) {
- WOLFSSL_MSG("Found Matching QSH Scheme");
- return 1; /* have QSH */
- }
- }
-
- return 0;
-}
-#endif /* NO_WOLFSSL_SERVER */
-
-/* test if the QSH Scheme is implemented
- return 1 if yes 0 if no */
-static int TLSX_HaveQSHScheme(word16 name)
-{
- switch(name) {
- #ifdef HAVE_NTRU
- case WOLFSSL_NTRU_EESS439:
- case WOLFSSL_NTRU_EESS593:
- case WOLFSSL_NTRU_EESS743:
- return 1;
- #endif
- case WOLFSSL_LWE_XXX:
- case WOLFSSL_HFE_XXX:
- return 0; /* not supported yet */
-
- default:
- return 0;
- }
-}
-
-
-/* Add a QSHScheme struct to list of usable ones */
-int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz,
- void* heap)
-{
- TLSX* extension = NULL;
- QSHScheme* format = NULL;
- int ret = 0;
-
- /* sanity check */
- 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) {
- XFREE(format, 0, DYNAMIC_TYPE_TLSX);
- return ret;
- }
- }
- else {
- /* push new QSH object to extension data. */
- format->next = (QSHScheme*)extension->data;
- extension->data = (void*)format;
-
- /* look for another format of the same name to remove (replacement) */
- do {
- if (format->next && (format->next->name == name)) {
- QSHScheme* next = format->next;
-
- format->next = next->next;
- XFREE(next, 0, DYNAMIC_TYPE_TLSX);
-
- break;
- }
- } while ((format = format->next));
- }
- }
- return WOLFSSL_SUCCESS;
-}
-
-#define QSH_FREE_ALL TLSX_QSH_FreeAll
-#define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest
-
-#ifndef NO_WOLFSSL_CLIENT
-#define QSH_GET_SIZE TLSX_QSH_GetSize
-#define QSH_WRITE TLSX_QSH_Write
-#else
-#define QSH_GET_SIZE(list, a) 0
-#define QSH_WRITE(a, b) 0
-#endif
-
-#ifndef NO_WOLFSSL_SERVER
-#define QSH_PARSE TLSX_QSH_Parse
-#else
-#define QSH_PARSE(a, b, c, d) 0
-#endif
-
-#define QSHPK_WRITE TLSX_QSHPK_Write
-#define QSH_SERREQ TLSX_QSH_SerPKReq
-#else
-
-#define QSH_FREE_ALL(list, heap)
-#define QSH_GET_SIZE(list, a) 0
-#define QSH_WRITE(a, b) 0
-#define QSH_PARSE(a, b, c, d) 0
-#define QSHPK_WRITE(a, b) 0
-#define QSH_SERREQ(a, b) 0
-#define QSH_VALIDATE_REQUEST(a, b)
-
-#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 */
-/******************************************************************************/
-
-#ifdef WOLFSSL_TLS13
-/* Return the size of the SupportedVersions extension's data.
- *
- * data The SSL/TLS object.
- * msgType The type of the message this extension is being written into.
- * returns the length of data that will be in the extension.
- */
-static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
-
- if (msgType == client_hello) {
- /* TLS v1.2 and TLS v1.3 */
- 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
- #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
- if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0)
- #endif
- cnt++;
- #ifdef WOLFSSL_ALLOW_TLSV10
- #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);
- }
-#ifndef WOLFSSL_TLS13_DRAFT_18
- else if (msgType == server_hello || msgType == hello_retry_request)
- *pSz += OPAQUE16_LEN;
-#endif
- else
- return SANITY_MSG_E;
-
- return 0;
-}
-
-/* Writes the SupportedVersions extension into the buffer.
- *
- * data The SSL/TLS object.
- * output The buffer to write the extension into.
- * msgType The type of the message this extension is being written into.
- * returns the length of data that was written.
- */
-static int TLSX_SupportedVersions_Write(void* data, byte* output,
- byte msgType, word16* pSz)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
- byte major;
- byte* cnt;
-
- if (msgType == client_hello) {
- 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;
-#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
-
-#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) {
- #ifdef WOLFSSL_TLS13_DRAFT
- if (ssl->version.major == SSLv3_MAJOR &&
- ssl->version.minor == TLSv1_3_MINOR) {
- output[0] = TLS_DRAFT_MAJOR;
- output[1] = TLS_DRAFT_MINOR;
- }
- else
- #endif
- {
- output[0] = ssl->version.major;
- output[1] = ssl->version.minor;
- }
-
- *pSz += OPAQUE16_LEN;
- }
-#endif
- else
- return SANITY_MSG_E;
-
- return 0;
-}
-
-/* Parse the SupportedVersions extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input,
- word16 length, byte msgType)
-{
- ProtocolVersion pv = ssl->ctx->method->version;
- int i;
- int len;
- byte major, minor;
- int newMinor = 0;
- int set = 0;
-
- if (msgType == client_hello) {
- /* Must contain a length and at least one version. */
- if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1)
- return BUFFER_ERROR;
-
- len = *input;
-
- /* Protocol version array must fill rest of data. */
- if (length != (word16)OPAQUE8_LEN + len)
- return BUFFER_ERROR;
-
- input++;
-
- /* Find first match. */
- for (i = 0; i < len; i += OPAQUE16_LEN) {
- major = input[i];
- minor = input[i + OPAQUE8_LEN];
-
-#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)
- continue;
-
- /* No upgrade allowed. */
- if (minor > ssl->version.minor)
- continue;
- /* Check downgrade. */
- if (minor < ssl->version.minor) {
- if (!ssl->options.downgrade)
- continue;
-
- if (minor < ssl->options.minDowngrade)
- continue;
-
- if (newMinor == 0 && minor > ssl->options.oldMinor) {
- /* Downgrade the version. */
- ssl->version.minor = minor;
- }
- }
-
- if (minor >= TLSv1_3_MINOR) {
- if (!ssl->options.tls1_3) {
- ssl->options.tls1_3 = 1;
- TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, ssl,
- ssl->heap);
-#ifndef WOLFSSL_TLS13_DRAFT_18
- TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS);
-#endif
- }
- if (minor > newMinor) {
- ssl->version.minor = minor;
- newMinor = minor;
- }
- }
- 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
- else if (msgType == server_hello || msgType == hello_retry_request) {
- /* Must contain one version. */
- if (length != OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- major = input[0];
- minor = input[OPAQUE8_LEN];
-
- #ifdef WOLFSSL_TLS13_DRAFT
- if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) {
- major = SSLv3_MAJOR;
- minor = TLSv1_3_MINOR;
- }
- #endif
-
- if (major != pv.major)
- return VERSION_ERROR;
-
- /* Can't downgrade with this extension below TLS v1.3. */
- if (minor < TLSv1_3_MINOR)
- return VERSION_ERROR;
-
- /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */
- if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) {
- /* Set minor version back to TLS v1.3+ */
- ssl->version.minor = ssl->ctx->method->version.minor;
- }
-
- /* No upgrade allowed. */
- if (ssl->version.minor < minor)
- return VERSION_ERROR;
-
- /* Check downgrade. */
- if (ssl->version.minor > minor) {
- if (!ssl->options.downgrade)
- return VERSION_ERROR;
-
- if (minor < ssl->options.minDowngrade)
- return VERSION_ERROR;
-
- /* Downgrade the version. */
- ssl->version.minor = minor;
- }
- }
-#endif
- else
- return SANITY_MSG_E;
-
- return 0;
-}
-
-/* Sets a new SupportedVersions extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data,
- void* heap)
-{
- if (extensions == NULL || data == NULL)
- return BAD_FUNC_ARG;
-
- return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap);
-}
-
-#define SV_GET_SIZE TLSX_SupportedVersions_GetSize
-#define SV_WRITE TLSX_SupportedVersions_Write
-#define SV_PARSE TLSX_SupportedVersions_Parse
-
-#else
-
-#define SV_GET_SIZE(a, b, c) 0
-#define SV_WRITE(a, b, c, d) 0
-#define SV_PARSE(a, b, c, d) 0
-
-#endif /* WOLFSSL_TLS13 */
-
-#if defined(WOLFSSL_TLS13)
-
-/******************************************************************************/
-/* Cookie */
-/******************************************************************************/
-
-/* Free the cookie data.
- *
- * cookie Cookie data.
- * heap The heap used for allocation.
- */
-static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap)
-{
- (void)heap;
-
- if (cookie != NULL)
- XFREE(cookie, heap, DYNAMIC_TYPE_TLSX);
-}
-
-/* Get the size of the encoded Cookie extension.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * cookie The cookie to write.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded Cookie extension.
- */
-static int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz)
-{
- if (msgType == client_hello || msgType == hello_retry_request)
- *pSz += OPAQUE16_LEN + cookie->len;
- else
- return SANITY_MSG_E;
- return 0;
-}
-
-/* Writes the Cookie extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * cookie The cookie to write.
- * output The buffer to write into.
- * 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)
-{
- if (msgType == client_hello || msgType == hello_retry_request) {
- c16toa(cookie->len, output);
- output += OPAQUE16_LEN;
- XMEMCPY(output, &cookie->data, cookie->len);
- *pSz += OPAQUE16_LEN + cookie->len;
- }
- else
- return SANITY_MSG_E;
- return 0;
-}
-
-/* Parse the Cookie extension.
- * In messages: ClientHello and HelloRetryRequest.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- word16 len;
- word16 idx = 0;
- TLSX* extension;
- Cookie* cookie;
-
- if (msgType != client_hello && msgType != hello_retry_request)
- return SANITY_MSG_E;
-
- /* Message contains length and Cookie which must be at least one byte
- * in length.
- */
- if (length < OPAQUE16_LEN + 1)
- return BUFFER_E;
- ato16(input + idx, &len);
- idx += OPAQUE16_LEN;
- if (length - idx != len)
- return BUFFER_E;
-
- if (msgType == hello_retry_request)
- return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0);
-
- /* client_hello */
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL)
- return HRR_COOKIE_ERROR;
-
- cookie = (Cookie*)extension->data;
- if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0)
- return HRR_COOKIE_ERROR;
-
- /* Request seen. */
- extension->resp = 0;
-
- return 0;
-}
-
-/* Use the data to create a new Cookie object in the extensions.
- *
- * ssl SSL/TLS object.
- * data Cookie data.
- * len Length of cookie data in bytes.
- * mac MAC data.
- * macSz Length of MAC data in bytes.
- * resp Indicates the extension will go into a response (HelloRetryRequest).
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac,
- byte macSz, int resp)
-{
- int ret = 0;
- TLSX* extension;
- Cookie* cookie;
-
- /* Find the cookie extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL) {
- /* Push new cookie extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
-
- extension = TLSX_Find(ssl->extensions, TLSX_COOKIE);
- if (extension == NULL)
- return MEMORY_E;
- }
-
- /* The Cookie structure has one byte for cookie data already. */
- cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (cookie == NULL)
- return MEMORY_E;
-
- cookie->len = len + macSz;
- XMEMCPY(&cookie->data, data, len);
- if (mac != NULL)
- XMEMCPY(&cookie->data + len, mac, macSz);
-
- extension->data = (void*)cookie;
- extension->resp = (byte)resp;
-
- return 0;
-}
-
-#define CKE_FREE_ALL TLSX_Cookie_FreeAll
-#define CKE_GET_SIZE TLSX_Cookie_GetSize
-#define CKE_WRITE TLSX_Cookie_Write
-#define CKE_PARSE TLSX_Cookie_Parse
-
-#else
-
-#define CKE_FREE_ALL(a, b) 0
-#define CKE_GET_SIZE(a, b, c) 0
-#define CKE_WRITE(a, b, c, d) 0
-#define CKE_PARSE(a, b, c, d) 0
-
-#endif
-#if !defined(WOLFSSL_NO_SIGALG)
-/******************************************************************************/
-/* Signature Algorithms */
-/******************************************************************************/
-
-/* Return the size of the SignatureAlgorithms extension's data.
- *
- * data Unused
- * returns the length of data that will be in the extension.
- */
-
-static word16 TLSX_SignatureAlgorithms_GetSize(void* data)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
-
- return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
-}
-
-/* Creates a bit string of supported hash algorithms with RSA PSS.
- * The bit string is used when determining which signature algorithm to use
- * when creating the CertificateVerify message.
- * Note: Valid data has an even length as each signature algorithm is two bytes.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the list of supported signature algorithms.
- * length The length of the list in bytes.
- * returns 0 on success, BUFFER_ERROR when the length is not even.
- */
-static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input,
- word16 length)
-{
- word16 i;
-
- if ((length & 1) == 1)
- return BUFFER_ERROR;
-
- ssl->pssAlgo = 0;
- 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;
-}
-
-/* Writes the SignatureAlgorithms extension into the buffer.
- *
- * data Unused
- * output The buffer to write the extension into.
- * returns the length of data that was written.
- */
-static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
-
- c16toa(ssl->suites->hashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo,
- ssl->suites->hashSigAlgoSz);
-
- TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN,
- ssl->suites->hashSigAlgoSz);
-
- return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz;
-}
-
-/* Parse the SignatureAlgorithms extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input,
- word16 length, byte isRequest, Suites* suites)
-{
- word16 len;
-
- if (!isRequest)
- return BUFFER_ERROR;
-
- /* Must contain a length and at least algorithm. */
- if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
- return BUFFER_ERROR;
-
- ato16(input, &len);
- input += OPAQUE16_LEN;
-
- /* Algorithm array must fill rest of data. */
- if (length != OPAQUE16_LEN + len)
- return BUFFER_ERROR;
-
- /* truncate hashSigAlgo list if too long */
- suites->hashSigAlgoSz = len;
- if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
- WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
- suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
- }
- XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz);
-
- return TLSX_SignatureAlgorithms_MapPss(ssl, input, len);
-}
-
-/* Sets a new SignatureAlgorithms extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data,
- void* heap)
-{
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap);
-}
-
-#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize
-#define SA_WRITE TLSX_SignatureAlgorithms_Write
-#define SA_PARSE TLSX_SignatureAlgorithms_Parse
-#endif
-/******************************************************************************/
-/* Signature Algorithms Certificate */
-/******************************************************************************/
-
-#ifdef WOLFSSL_TLS13
-#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
-/* Return the size of the SignatureAlgorithms extension's data.
- *
- * data Unused
- * returns the length of data that will be in the extension.
- */
-static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
-
- return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
-}
-
-/* Writes the SignatureAlgorithmsCert extension into the buffer.
- *
- * data Unused
- * output The buffer to write the extension into.
- * returns the length of data that was written.
- */
-static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output)
-{
- WOLFSSL* ssl = (WOLFSSL*)data;
-
- c16toa(ssl->certHashSigAlgoSz, output);
- XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo,
- ssl->certHashSigAlgoSz);
-
- return OPAQUE16_LEN + ssl->certHashSigAlgoSz;
-}
-
-/* Parse the SignatureAlgorithmsCert extension.
- *
- * ssl The SSL/TLS object.
- * input The buffer with the extension data.
- * length The length of the extension data.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input,
- word16 length, byte isRequest)
-{
- word16 len;
-
- if (!isRequest)
- return BUFFER_ERROR;
-
- /* Must contain a length and at least algorithm. */
- if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0)
- return BUFFER_ERROR;
-
- ato16(input, &len);
- input += OPAQUE16_LEN;
-
- /* Algorithm array must fill rest of data. */
- if (length != OPAQUE16_LEN + len)
- return BUFFER_ERROR;
-
- /* truncate hashSigAlgo list if too long */
- ssl->certHashSigAlgoSz = len;
- if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) {
- WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating");
- ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
- }
- XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz);
-
- return 0;
-}
-
-/* Sets a new SignatureAlgorithmsCert extension into the extension list.
- *
- * extensions The list of extensions.
- * data The extensions specific data.
- * heap The heap used for allocation.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data,
- void* heap)
-{
- if (extensions == NULL)
- return BAD_FUNC_ARG;
-
- return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data,
- heap);
-}
-
-#define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize
-#define SAC_WRITE TLSX_SignatureAlgorithmsCert_Write
-#define SAC_PARSE TLSX_SignatureAlgorithmsCert_Parse
-#endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
-#endif /* WOLFSSL_TLS13 */
-
-
-/******************************************************************************/
-/* Key Share */
-/******************************************************************************/
-
-#ifdef WOLFSSL_TLS13
-/* Create a key share entry using named Diffie-Hellman 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_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse)
-{
- int ret;
-#ifndef NO_DH
- byte* keyData;
- void* key = NULL;
- word32 keySz;
- word32 dataSz;
- const DhParams* params;
-#ifdef WOLFSSL_SMALL_STACK
- DhKey* dhKey = NULL;
-#else
- DhKey dhKey[1];
-#endif
-
- /* TODO: [TLS13] The key size should come from wolfcrypt. */
- /* Pick the parameters from the named group. */
- switch (kse->group) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- params = wc_Dh_ffdhe2048_Get();
- keySz = 29;
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- params = wc_Dh_ffdhe3072_Get();
- keySz = 34;
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- params = wc_Dh_ffdhe4096_Get();
- keySz = 39;
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- params = wc_Dh_ffdhe6144_Get();
- keySz = 46;
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- params = wc_Dh_ffdhe8192_Get();
- keySz = 52;
- break;
- #endif
- default:
- return BAD_FUNC_ARG;
- }
-
-#ifdef WOLFSSL_SMALL_STACK
- dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
- if (dhKey == NULL)
- return MEMORY_E;
-#endif
-
- ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
-
- /* Allocate space for the public key. */
- dataSz = params->p_len;
- keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- ret = MEMORY_E;
- goto end;
- }
- /* Allocate space for the private key. */
- key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- if (key == NULL) {
- ret = MEMORY_E;
- goto end;
- }
-
- /* Set key */
- ret = wc_DhSetKey(dhKey,
- (byte*)params->p, params->p_len,
- (byte*)params->g, params->g_len);
- if (ret != 0)
- goto end;
-
- /* Generate a new key pair. */
- ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData,
- &dataSz);
-#ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
-#endif
- if (ret != 0)
- goto end;
-
- if (params->p_len != dataSz) {
- /* Pad the front of the key data with zeros. */
- XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz);
- XMEMSET(keyData, 0, params->p_len - dataSz);
- }
-
- kse->pubKey = keyData;
- kse->pubKeyLen = params->p_len;
- kse->key = key;
- kse->keyLen = keySz;
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public DH Key");
- WOLFSSL_BUFFER(keyData, params->p_len);
-#endif
-
-end:
-
- wc_FreeDhKey(dhKey);
-#ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
-#endif
-
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (key != NULL)
- XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- }
-#else
- (void)ssl;
- (void)kse;
-
- ret = NOT_COMPILED_IN;
-#endif
-
- return ret;
-}
-
-/* Create a key share entry using X25519 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_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse)
-{
- int ret;
-#ifdef HAVE_CURVE25519
- byte* keyData = NULL;
- word32 dataSize = CURVE25519_KEYSIZE;
- curve25519_key* key;
-
- /* Allocate an ECC key to hold 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;
- }
-
- /* Make an ECC key. */
- ret = wc_curve25519_init(key);
- if (ret != 0)
- goto end;
- ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key);
- if (ret != 0)
- goto end;
-
- /* Allocate space for the public key. */
- keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- goto end;
- }
-
- /* Export public key. */
- if (wc_curve25519_export_public_ex(key, keyData, &dataSize,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_EXPORT_ERROR;
- goto end;
- }
-
- kse->pubKey = keyData;
- kse->pubKeyLen = CURVE25519_KEYSIZE;
- kse->key = key;
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public Curve25519 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_curve25519_free(key);
- XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- }
-#else
- (void)ssl;
- (void)kse;
-
- ret = NOT_COMPILED_IN;
-#endif /* HAVE_CURVE25519 */
-
- 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.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry object.
- * returns 0 on success, otherwise failure.
- */
-static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse)
-{
- int ret;
-#ifdef HAVE_ECC
- byte* keyData = NULL;
- word32 dataSize;
- byte* keyPtr = NULL;
- word32 keySize;
- ecc_key* eccKey;
- word16 curveId;
-
- /* TODO: [TLS13] The key sizes should come from wolfcrypt. */
- /* Translate named group to a curve id. */
- switch (kse->group) {
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- curveId = ECC_SECP256R1;
- keySize = 32;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- curveId = ECC_SECP384R1;
- keySize = 48;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- curveId = ECC_SECP521R1;
- keySize = 66;
- dataSize = keySize * 2 + 1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #ifdef HAVE_X448
- case WOLFSSL_ECC_X448:
- curveId = ECC_X448;
- dataSize = keySize = 56;
- break;
- #endif
- default:
- return BAD_FUNC_ARG;
- }
-
- /* Allocate an ECC key to hold private key. */
- keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_PRIVATE_KEY);
- if (keyPtr == NULL) {
- WOLFSSL_MSG("EccTempKey Memory error");
- return MEMORY_E;
- }
- eccKey = (ecc_key*)keyPtr;
-
- /* Make an ECC key. */
- ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId);
- if (ret != 0)
- goto end;
- ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId);
-#ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
-#endif
- if (ret != 0)
- goto end;
-
- /* Allocate space for the public key. */
- keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (keyData == NULL) {
- WOLFSSL_MSG("Key data Memory error");
- ret = MEMORY_E;
- goto end;
- }
-
- /* Export public key. */
- if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) {
- ret = ECC_EXPORT_ERROR;
- goto end;
- }
-
- kse->pubKey = keyData;
- kse->pubKeyLen = dataSize;
- kse->key = keyPtr;
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Public ECC Key");
- WOLFSSL_BUFFER(keyData, dataSize);
-#endif
-
-end:
- if (ret != 0) {
- /* Data owned by key share entry otherwise. */
- if (keyPtr != NULL)
- XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
- if (keyData != NULL)
- XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
-#else
- (void)ssl;
- (void)kse;
-
- ret = NOT_COMPILED_IN;
-#endif /* HAVE_ECC */
-
- return ret;
-}
-
-/* Generate a secret/key using the key share entry.
- *
- * ssl The SSL/TLS object.
- * kse The key share entry holding peer data.
- */
-static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
-{
- /* Named FFHE groups have a bit set to identify them. */
- if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK)
- return TLSX_KeyShare_GenDhKey(ssl, kse);
- if (kse->group == WOLFSSL_ECC_X25519)
- return TLSX_KeyShare_GenX25519Key(ssl, kse);
- if (kse->group == WOLFSSL_ECC_X448)
- return TLSX_KeyShare_GenX448Key(ssl, kse);
- return TLSX_KeyShare_GenEccKey(ssl, kse);
-}
-
-/* Free the key share dynamic data.
- *
- * list The linked list of key share entry objects.
- * heap The heap used for allocation.
- */
-static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
-{
- KeyShareEntry* current;
-
- while ((current = list) != NULL) {
- list = current->next;
- if ((current->group & NAMED_DH_MASK) == 0) {
- if (current->group == WOLFSSL_ECC_X25519) {
-#ifdef HAVE_CURVE25519
- wc_curve25519_free((curve25519_key*)current->key);
-#endif
- }
- else if (current->group == WOLFSSL_ECC_X448) {
-#ifdef HAVE_CURVE448
- wc_curve448_free((curve448_key*)current->key);
-#endif
- }
- else {
-#ifdef HAVE_ECC
- wc_ecc_free((ecc_key*)(current->key));
-#endif
- }
- }
- if (current->key != NULL)
- XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY);
- XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY);
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
-
- (void)heap;
-}
-
-/* Get the size of the encoded key share extension.
- *
- * list The linked list of key share extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded key share extension.
- */
-static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType)
-{
- word16 len = 0;
- byte isRequest = (msgType == client_hello);
- KeyShareEntry* current;
-
- /* The named group the server wants to use. */
- if (msgType == hello_retry_request)
- return OPAQUE16_LEN;
-
- /* List of key exchange groups. */
- if (isRequest)
- len += OPAQUE16_LEN;
- while ((current = list) != NULL) {
- list = current->next;
-
- if (!isRequest && current->key == NULL)
- continue;
-
- len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen;
- }
-
- return len;
-}
-
-/* Writes the key share extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output,
- byte msgType)
-{
- word16 i = 0;
- byte isRequest = (msgType == client_hello);
- KeyShareEntry* current;
-
- if (msgType == hello_retry_request) {
- c16toa(list->group, output);
- return OPAQUE16_LEN;
- }
-
- /* ClientHello has a list but ServerHello is only the chosen. */
- if (isRequest)
- i += OPAQUE16_LEN;
-
- /* Write out all in the list. */
- while ((current = list) != NULL) {
- list = current->next;
-
- if (!isRequest && current->key == NULL)
- continue;
-
- c16toa(current->group, &output[i]);
- i += KE_GROUP_LEN;
- c16toa((word16)(current->pubKeyLen), &output[i]);
- i += OPAQUE16_LEN;
- XMEMCPY(&output[i], current->pubKey, current->pubKeyLen);
- i += (word16)current->pubKeyLen;
- }
- /* Write the length of the list if required. */
- if (isRequest)
- c16toa(i - OPAQUE16_LEN, output);
-
- return i;
-}
-
-/* Process the DH 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_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
-{
-#ifndef NO_DH
- int ret;
- const DhParams* params;
-#ifdef WOLFSSL_SMALL_STACK
- DhKey* dhKey = NULL;
-#else
- DhKey dhKey[1];
-#endif
-
- switch (keyShareEntry->group) {
- #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
- default:
- return PEER_KEY_ERROR;
- }
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer DH Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
-#endif
-
-#ifdef WOLFSSL_SMALL_STACK
- dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH);
- if (dhKey == NULL)
- return MEMORY_E;
-#endif
-
- ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId);
- if (ret != 0) {
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
-
- /* Set key */
- ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g,
- params->g_len);
- if (ret != 0) {
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return ret;
- }
-
- ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen);
- if (ret != 0) {
- wc_FreeDhKey(dhKey);
- #ifdef WOLFSSL_SMALL_STACK
- XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH);
- #endif
- return PEER_KEY_ERROR;
- }
-
- /* Derive secret from private key and peer's public key. */
- ret = wc_DhAgree(dhKey,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
- (const byte*)keyShareEntry->key, keyShareEntry->keyLen,
- keyShareEntry->ke, keyShareEntry->keLen);
-#ifdef WOLFSSL_ASYNC_CRYPT
- /* TODO: Make this function non-blocking */
- if (ret == WC_PENDING_E) {
- ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE);
- }
-#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
- (void)ssl;
- (void)keyShareEntry;
- return PEER_KEY_ERROR;
-#endif
-}
-
-/* Process the X25519 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_ProcessX25519(WOLFSSL* ssl,
- KeyShareEntry* keyShareEntry)
-{
- int ret;
-
-#ifdef HAVE_CURVE25519
- curve25519_key* key = (curve25519_key*)keyShareEntry->key;
- curve25519_key* peerX25519Key;
-
-#ifdef HAVE_ECC
- if (ssl->peerEccKey != NULL) {
- wc_ecc_free(ssl->peerEccKey);
- ssl->peerEccKey = NULL;
- }
-#endif
-
- peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap,
- DYNAMIC_TYPE_TLSX);
- if (peerX25519Key == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_ERROR;
- }
- ret = wc_curve25519_init(peerX25519Key);
- if (ret != 0) {
- XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX);
- return ret;
- }
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer Curve25519 Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
-#endif
-
- if (wc_curve25519_check_public(keyShareEntry->ke, keyShareEntry->keLen,
- EC25519_LITTLE_ENDIAN) != 0) {
- ret = ECC_PEERKEY_ERROR;
- }
-
- if (ret == 0) {
- 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,
- ssl->arrays->preMasterSecret,
- &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;
-
- ret = PEER_KEY_ERROR;
-#endif /* HAVE_CURVE25519 */
-
- 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.
- * 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_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
-{
- int ret;
-
-#ifdef HAVE_ECC
- int curveId;
- ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key;
-
- if (ssl->peerEccKey != NULL)
- wc_ecc_free(ssl->peerEccKey);
-
- ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap,
- DYNAMIC_TYPE_ECC);
- if (ssl->peerEccKey == NULL) {
- WOLFSSL_MSG("PeerEccKey Memory error");
- return MEMORY_ERROR;
- }
- ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId);
- if (ret != 0)
- return ret;
-
- /* find supported curve */
- switch (keyShareEntry->group) {
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- curveId = ECC_SECP256R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP384R1:
- curveId = ECC_SECP384R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- curveId = ECC_SECP521R1;
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #ifdef HAVE_X448
- case WOLFSSL_ECC_X448:
- curveId = ECC_X448;
- break;
- #endif
- default:
- /* unsupported curve */
- return ECC_PEERKEY_ERROR;
- }
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("Peer ECC Key");
- WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen);
-#endif
-
- /* Point is validated by import function. */
- if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen,
- ssl->peerEccKey, curveId) != 0) {
- return ECC_PEERKEY_ERROR;
- }
- ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
-
- do {
- #if defined(WOLFSSL_ASYNC_CRYPT)
- ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
- #endif
- if (ret >= 0)
- ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz);
- } while (ret == WC_PENDING_E);
-
-#if 0
- /* TODO: Switch to support async here and use: */
- ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey,
- keyShareEntry->ke, &keyShareEntry->keLen,
- ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz,
- ssl->options.side
- );
-#endif
-
- 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;
- (void)keyShareEntry;
-
- ret = PEER_KEY_ERROR;
-#endif /* HAVE_ECC */
-
- return ret;
-}
-
-/* Process the 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_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
-{
- int ret;
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- ssl->session.namedGroup = (byte)keyShareEntry->group;
-#endif
- /* Use Key Share Data from server. */
- if (keyShareEntry->group & NAMED_DH_MASK)
- 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);
-
-#ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_MSG("KE Secret");
- WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz);
-#endif
-
- return ret;
-}
-
-/* Parse an entry of the KeyShare extension.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * kse The new key share entry object.
- * returns a positive number to indicate amount of data parsed and a negative
- * number on error.
- */
-static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length,
- KeyShareEntry **kse)
-{
- int ret;
- word16 group;
- word16 keLen;
- int offset = 0;
- byte* ke;
-
- if (length < OPAQUE16_LEN + OPAQUE16_LEN)
- return BUFFER_ERROR;
- /* Named group */
- ato16(&input[offset], &group);
- offset += OPAQUE16_LEN;
- /* Key exchange data - public key. */
- ato16(&input[offset], &keLen);
- offset += OPAQUE16_LEN;
- if (keLen == 0)
- return INVALID_PARAMETER;
- if (keLen > length - offset)
- return BUFFER_ERROR;
-
- /* Store a copy in the key share object. */
- ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- if (ke == NULL)
- return MEMORY_E;
- XMEMCPY(ke, &input[offset], keLen);
-
- /* Populate a key share object in the extension. */
- ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse);
- if (ret != 0) {
- XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- return ret;
- }
-
- /* Total length of the parsed data. */
- return offset + keLen;
-}
-
-/* Searches the groups sent for the specified named group.
- *
- * ssl SSL/TLS object.
- * name Group name to match.
- * returns 1 when the extension has the group name and 0 otherwise.
- */
-static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group)
-{
- TLSX* extension;
- KeyShareEntry* list;
-
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE);
- if (extension == NULL)
- return 0;
- }
-
- list = (KeyShareEntry*)extension->data;
- while (list != NULL) {
- if (list->group == group)
- return 1;
- list = list->next;
- }
-
- return 0;
-}
-
-
-/* Searches the supported groups extension for the specified named group.
- *
- * ssl The SSL/TLS object.
- * name The group name to match.
- * returns 1 when the extension has the group name and 0 otherwise.
- */
-static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name)
-{
-#ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
-
- if ((extension = TLSX_Find(ssl->extensions,
- TLSX_SUPPORTED_GROUPS)) == NULL) {
- if ((extension = TLSX_Find(ssl->ctx->extensions,
- TLSX_SUPPORTED_GROUPS)) == NULL) {
- return 0;
- }
- }
-
- for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) {
- if (curve->name == name)
- return 1;
- }
-#endif
-
- (void)ssl;
- (void)name;
-
- return 0;
-}
-
-
-/* Parse the KeyShare extension.
- * Different formats in different messages.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- int ret;
- KeyShareEntry *keyShareEntry = NULL;
- word16 group;
-
- if (msgType == client_hello) {
- int offset = 0;
- word16 len;
- TLSX* extension;
-
- /* Add a KeyShare extension if it doesn't exist. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
- }
-
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- /* ClientHello contains zero or more key share entries. */
- ato16(input, &len);
- if (len != length - OPAQUE16_LEN)
- return BUFFER_ERROR;
- offset += OPAQUE16_LEN;
-
- while (offset < (int)length) {
- ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset,
- &keyShareEntry);
- if (ret < 0)
- return ret;
-
- offset += ret;
- }
-
- ret = 0;
- }
- else if (msgType == server_hello) {
- int len;
-
- if (length < OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- /* The data is the named group the server wants to use. */
- ato16(input, &group);
-
- /* Check the selected group was supported by ClientHello extensions. */
- if (!TLSX_SupportedGroups_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
-
- /* Check if the group was sent. */
- if (!TLSX_KeyShare_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
-
- /* ServerHello contains one key share entry. */
- len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry);
- if (len != (int)length)
- return BUFFER_ERROR;
-
- /* Not in list sent if there isn't a private key. */
- if (keyShareEntry == NULL || keyShareEntry->key == NULL)
- return BAD_KEY_SHARE_DATA;
-
- /* Process the entry to calculate the secret. */
- ret = TLSX_KeyShare_Process(ssl, keyShareEntry);
- if (ret == 0)
- ssl->session.namedGroup = ssl->namedGroup = group;
- }
- else if (msgType == hello_retry_request) {
- if (length != OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- /* The data is the named group the server wants to use. */
- ato16(input, &group);
-
- /* Check the selected group was supported by ClientHello extensions. */
- if (!TLSX_SupportedGroups_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
-
- /* Check if the group was sent. */
- if (TLSX_KeyShare_Find(ssl, group))
- return BAD_KEY_SHARE_DATA;
-
- /* Clear out unusable key shares. */
- ret = TLSX_KeyShare_Empty(ssl);
- if (ret != 0)
- return ret;
-
- /* Try to use the server's group. */
- ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL);
- }
- else {
- /* Not a message type that is allowed to have this extension. */
- return SANITY_MSG_E;
- }
-
- return ret;
-}
-
-/* Create a new key share entry and put it into the list.
- *
- * list The linked list of key share entries.
- * group The named group.
- * heap The memory to allocate with.
- * keyShareEntry The new key share entry object.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
- KeyShareEntry** keyShareEntry)
-{
- KeyShareEntry* kse;
- KeyShareEntry** next;
-
- kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap,
- DYNAMIC_TYPE_TLSX);
- if (kse == NULL)
- return MEMORY_E;
-
- XMEMSET(kse, 0, sizeof(*kse));
- kse->group = (word16)group;
-
- /* Add it to the back and maintain the links. */
- while (*list != NULL) {
- /* Assign to temporary to work around compiler bug found by customer. */
- next = &((*list)->next);
- list = next;
- }
- *list = kse;
- *keyShareEntry = kse;
-
- (void)heap;
-
- return 0;
-}
-
-/* Use the data to create a new key share object in the extensions.
- *
- * ssl The SSL/TLS object.
- * group The named group.
- * len The length of the public key data.
- * data The public key data.
- * kse The new key share entry object.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data,
- KeyShareEntry **kse)
-{
- int ret = 0;
- TLSX* extension;
- KeyShareEntry* keyShareEntry = NULL;
-
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- if (ret != 0)
- return ret;
-
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL)
- return MEMORY_E;
- }
- extension->resp = 0;
-
- /* Try to find the key share entry with this group. */
- keyShareEntry = (KeyShareEntry*)extension->data;
- while (keyShareEntry != NULL) {
- if (keyShareEntry->group == group)
- break;
- keyShareEntry = keyShareEntry->next;
- }
-
- /* Create a new key share entry if not found. */
- if (keyShareEntry == NULL) {
- ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group,
- ssl->heap, &keyShareEntry);
- if (ret != 0)
- return ret;
- }
-
- if (data != NULL) {
- if (keyShareEntry->ke != NULL) {
- XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
- }
- keyShareEntry->ke = data;
- keyShareEntry->keLen = len;
- }
- else {
- /* Generate a key pair. */
- ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry);
- if (ret != 0)
- return ret;
- }
-
- if (kse != NULL)
- *kse = keyShareEntry;
-
- return 0;
-}
-
-/* Set an empty Key Share extension.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_KeyShare_Empty(WOLFSSL* ssl)
-{
- int ret = 0;
- TLSX* extension;
-
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension == NULL) {
- /* Push new KeyShare extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap);
- }
- else if (extension->data != NULL) {
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = NULL;
- }
-
- return ret;
-}
-
-/* Returns whether this group is supported.
- *
- * namedGroup The named group to check.
- * returns 1 when supported or 0 otherwise.
- */
-static int TLSX_KeyShare_IsSupported(int namedGroup)
-{
- switch (namedGroup) {
- #ifdef HAVE_FFDHE_2048
- case WOLFSSL_FFDHE_2048:
- break;
- #endif
- #ifdef HAVE_FFDHE_3072
- case WOLFSSL_FFDHE_3072:
- break;
- #endif
- #ifdef HAVE_FFDHE_4096
- case WOLFSSL_FFDHE_4096:
- break;
- #endif
- #ifdef HAVE_FFDHE_6144
- case WOLFSSL_FFDHE_6144:
- break;
- #endif
- #ifdef HAVE_FFDHE_8192
- case WOLFSSL_FFDHE_8192:
- break;
- #endif
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP256R1:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #ifdef HAVE_CURVE25519
- 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:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- case WOLFSSL_ECC_SECP521R1:
- break;
- #endif /* !NO_ECC_SECP */
- #endif
- default:
- return 0;
- }
-
- return 1;
-}
-
-/* Examines the application specified group ranking and returns the rank of the
- * group.
- * If no group ranking set then all groups are rank 0 (highest).
- *
- * ssl The SSL/TLS object.
- * group The group to check ranking for.
- * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list.
- */
-static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group)
-{
- byte i;
-
- if (ssl->numGroups == 0) {
-#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES)
- #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1;
- #endif
- #endif
-#endif
- #ifndef HAVE_FIPS
- #if defined(HAVE_CURVE25519)
- 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
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1;
- #endif
- #endif
- #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
- #ifndef NO_ECC_SECP
- ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1;
- #endif
- #endif
-#endif
- /* Add FFDHE supported groups. */
- #ifdef HAVE_FFDHE_2048
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048;
- #endif
- #ifdef HAVE_FFDHE_3072
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072;
- #endif
- #ifdef HAVE_FFDHE_4096
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096;
- #endif
- #ifdef HAVE_FFDHE_6144
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144;
- #endif
- #ifdef HAVE_FFDHE_8192
- ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192;
- #endif
- }
-
- for (i = 0; i < ssl->numGroups; i++)
- if (ssl->group[i] == (word16)group)
- return i;
-
- return -1;
-}
-
-/* Set a key share that is supported by the client into extensions.
- *
- * ssl The SSL/TLS object.
- * returns BAD_KEY_SHARE_DATA if no supported group has a key share,
- * 0 if a supported group has a key share and other values indicate an error.
- */
-static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl)
-{
- int ret;
-#ifdef HAVE_SUPPORTED_CURVES
- TLSX* extension;
- SupportedCurve* curve = NULL;
- SupportedCurve* preferredCurve = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
-
- extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS);
- if (extension != NULL)
- curve = (SupportedCurve*)extension->data;
- /* Use server's preference order. */
- for (; curve != NULL; curve = curve->next) {
- if (!TLSX_KeyShare_IsSupported(curve->name))
- continue;
-
- rank = TLSX_KeyShare_GroupRank(ssl, curve->name);
- if (rank == -1)
- continue;
- if (rank < preferredRank) {
- preferredCurve = curve;
- preferredRank = rank;
- }
- }
- curve = preferredCurve;
-
- if (curve == NULL)
- return BAD_KEY_SHARE_DATA;
-
- /* Delete the old key share data list. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL) {
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = NULL;
- }
-
- /* Add in the chosen group. */
- ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL);
- if (ret != 0)
- return ret;
-
- /* Set extension to be in response. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- extension->resp = 1;
-#else
-
- (void)ssl;
- ret = NOT_COMPILED_IN;
-#endif
-
- return ret;
-}
-
-/* Ensure there is a key pair that can be used for key exchange.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_KeyShare_Establish(WOLFSSL *ssl)
-{
- int ret;
- TLSX* extension;
- KeyShareEntry* clientKSE = NULL;
- KeyShareEntry* serverKSE;
- KeyShareEntry* list = NULL;
- KeyShareEntry* preferredKSE = NULL;
- int preferredRank = WOLFSSL_MAX_GROUP_COUNT;
- int rank;
-
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL)
- list = (KeyShareEntry*)extension->data;
-
- if (extension && extension->resp == 1)
- return 0;
-
- /* Use server's preference order. */
- for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) {
- if (clientKSE->ke == NULL)
- continue;
-
- /* Check consistency now - extensions in any order. */
- if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group))
- return BAD_KEY_SHARE_DATA;
-
- #ifdef OPENSSL_EXTRA
- if ((clientKSE->group & NAMED_DH_MASK) == 0) {
- /* Check if server supports group. */
- if (ssl->ctx->disabledCurves & (1 << clientKSE->group))
- continue;
- }
- #endif
- if (!TLSX_KeyShare_IsSupported(clientKSE->group))
- continue;
-
- rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group);
- if (rank == -1)
- continue;
- if (rank < preferredRank) {
- preferredKSE = clientKSE;
- preferredRank = rank;
- }
- }
- clientKSE = preferredKSE;
-
- /* No supported group found - send HelloRetryRequest. */
- if (clientKSE == NULL) {
- ret = TLSX_KeyShare_SetSupported(ssl);
- /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */
- if (ret == 0)
- return KEY_SHARE_ERROR;
- return ret;
- }
-
- list = NULL;
- /* Generate a new key pair. */
- ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE);
- if (ret != 0)
- return ret;
-
- if (clientKSE->key == NULL) {
- ret = TLSX_KeyShare_GenKey(ssl, serverKSE);
- if (ret != 0)
- return ret;
- }
- else {
- serverKSE->key = clientKSE->key;
- serverKSE->keyLen = clientKSE->keyLen;
- serverKSE->pubKey = clientKSE->pubKey;
- serverKSE->pubKeyLen = clientKSE->pubKeyLen;
- clientKSE->key = NULL;
- clientKSE->pubKey = NULL;
- }
- serverKSE->ke = clientKSE->ke;
- serverKSE->keLen = clientKSE->keLen;
- clientKSE->ke = NULL;
- clientKSE->keLen = 0;
-
- TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap);
- extension->data = (void *)serverKSE;
-
- extension->resp = 1;
-
- return 0;
-}
-
-/* Derive the shared secret of the key exchange.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl)
-{
- int ret;
- TLSX* extension;
- KeyShareEntry* list = NULL;
-
- /* Find the KeyShare extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE);
- if (extension != NULL)
- list = (KeyShareEntry*)extension->data;
-
- if (list == NULL)
- return KEY_SHARE_ERROR;
-
- /* Calculate secret. */
- ret = TLSX_KeyShare_Process(ssl, list);
- if (ret != 0)
- return ret;
-
- return ret;
-}
-
-#define KS_FREE_ALL TLSX_KeyShare_FreeAll
-#define KS_GET_SIZE TLSX_KeyShare_GetSize
-#define KS_WRITE TLSX_KeyShare_Write
-#define KS_PARSE TLSX_KeyShare_Parse
-
-#else
-
-#define KS_FREE_ALL(a, b)
-#define KS_GET_SIZE(a, b) 0
-#define KS_WRITE(a, b, c) 0
-#define KS_PARSE(a, b, c, d) 0
-
-#endif /* WOLFSSL_TLS13 */
-
-/******************************************************************************/
-/* Pre-Shared Key */
-/******************************************************************************/
-
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
-/* Free the pre-shared key dynamic data.
- *
- * list The linked list of key share entry objects.
- * heap The heap used for allocation.
- */
-static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap)
-{
- PreSharedKey* current;
-
- while ((current = list) != NULL) {
- list = current->next;
- XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX);
- XFREE(current, heap, DYNAMIC_TYPE_TLSX);
- }
-
- (void)heap;
-}
-
-/* Get the size of the encoded pre shared key extension.
- *
- * list The linked list of pre-shared key extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded pre-shared key extension or
- * SANITY_MSG_E to indicate invalid message type.
- */
-static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType,
- word16* pSz)
-{
- if (msgType == client_hello) {
- /* Length of identities + Length of binders. */
- word16 len = OPAQUE16_LEN + OPAQUE16_LEN;
- while (list != NULL) {
- /* Each entry has: identity, ticket age and binder. */
- len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN +
- OPAQUE8_LEN + list->binderLen;
- list = list->next;
- }
- *pSz += len;
- return 0;
- }
-
- if (msgType == server_hello) {
- *pSz += OPAQUE16_LEN;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* The number of bytes to be written for the binders.
- *
- * list The linked list of pre-shared key extensions.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes of the encoded pre-shared key extension or
- * SANITY_MSG_E to indicate invalid message type.
- */
-int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType,
- word16* pSz)
-{
- word16 len;
-
- if (msgType != client_hello)
- return SANITY_MSG_E;
-
- /* Length of all binders. */
- len = OPAQUE16_LEN;
- while (list != NULL) {
- len += OPAQUE8_LEN + list->binderLen;
- list = list->next;
- }
-
- *pSz = len;
- return 0;
-}
-
-/* Writes the pre-shared key extension into the output buffer - binders only.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output,
- byte msgType, word16* pSz)
-{
- PreSharedKey* current = list;
- word16 idx = 0;
- word16 lenIdx;
- word16 len;
-
- if (msgType != client_hello)
- return SANITY_MSG_E;
-
- /* Skip length of all binders. */
- lenIdx = idx;
- idx += OPAQUE16_LEN;
- while (current != NULL) {
- /* Binder data length. */
- output[idx++] = current->binderLen;
- /* Binder data. */
- XMEMCPY(output + idx, current->binder, current->binderLen);
- idx += current->binderLen;
-
- current = current->next;
- }
- /* Length of the binders. */
- len = idx - lenIdx - OPAQUE16_LEN;
- c16toa(len, output + lenIdx);
-
- *pSz = idx;
- return 0;
-}
-
-
-/* Writes the pre-shared key extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- *
- * list The linked list of key share entries.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-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;
- idx += OPAQUE16_LEN;
- while (current != NULL) {
- /* Identity length */
- c16toa(current->identityLen, output + idx);
- idx += OPAQUE16_LEN;
- /* Identity data */
- XMEMCPY(output + idx, current->identity, current->identityLen);
- idx += current->identityLen;
-
- /* Obfuscated ticket age. */
- c32toa(current->ticketAge, output + idx);
- idx += OPAQUE32_LEN;
-
- current = current->next;
- }
- /* Length of the identites. */
- len = idx - lenIdx - OPAQUE16_LEN;
- c16toa(len, output + lenIdx);
-
- /* Don't include binders here.
- * The binders are based on the hash of all the ClientHello data up to
- * and include the identities written above.
- */
- 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. */
- for (i=0; list != NULL && !list->chosen; i++)
- list = list->next;
- if (list == NULL)
- return BUILD_MSG_ERROR;
-
- /* The index of the identity chosen by the server from the list supplied
- * by the client.
- */
- c16toa(i, output);
- *pSz += OPAQUE16_LEN;
- }
- else
- return SANITY_MSG_E;
-
- return 0;
-}
-
-/* Parse the pre-shared key extension.
- * Different formats in different messages.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- TLSX* extension;
- PreSharedKey* list;
-
- if (msgType == client_hello) {
- int ret;
- word16 len;
- word16 idx = 0;
-
- TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
-
- /* Length of identities and of binders. */
- if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN)
- return BUFFER_E;
-
- /* Length of identities. */
- ato16(input + idx, &len);
- idx += OPAQUE16_LEN;
- if (len < MIN_PSK_ID_LEN || length - idx < len)
- return BUFFER_E;
-
- /* Create a pre-shared key object for each identity. */
- while (len > 0) {
- byte* identity;
- word16 identityLen;
- word32 age;
-
- if (len < OPAQUE16_LEN)
- return BUFFER_E;
-
- /* Length of identity. */
- ato16(input + idx, &identityLen);
- idx += OPAQUE16_LEN;
- if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN ||
- identityLen > MAX_PSK_ID_LEN)
- return BUFFER_E;
- /* Cache identity pointer. */
- identity = input + idx;
- idx += identityLen;
- /* Ticket age. */
- ato32(input + idx, &age);
- idx += OPAQUE32_LEN;
-
- ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac,
- 0, 0, 1, NULL);
- if (ret != 0)
- return ret;
-
- /* Done with this identity. */
- len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN;
- }
-
- /* Find the list of identities sent to server. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return PSK_KEY_ERROR;
- 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)
- return BUFFER_E;
-
- /* Set binder for each identity. */
- while (list != NULL && len > 0) {
- /* Length of binder */
- list->binderLen = input[idx++];
- if (list->binderLen < WC_SHA256_DIGEST_SIZE ||
- list->binderLen > WC_MAX_DIGEST_SIZE)
- return BUFFER_E;
- if (len < OPAQUE8_LEN + list->binderLen)
- return BUFFER_E;
-
- /* Copy binder into static buffer. */
- XMEMCPY(list->binder, input + idx, list->binderLen);
- idx += list->binderLen;
-
- /* Done with binder entry. */
- len -= OPAQUE8_LEN + list->binderLen;
-
- /* Next identity. */
- list = list->next;
- }
- if (list != NULL || len != 0)
- return BUFFER_E;
-
- return 0;
- }
-
- if (msgType == server_hello) {
- word16 idx;
-
- /* Index of identity chosen by server. */
- if (length != OPAQUE16_LEN)
- return BUFFER_E;
- ato16(input, &idx);
-
- #ifdef WOLFSSL_EARLY_DATA
- ssl->options.pskIdIndex = idx + 1;
- #endif
-
- /* Find the list of identities sent to server. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return PSK_KEY_ERROR;
- list = (PreSharedKey*)extension->data;
-
- /* Mark the identity as chosen. */
- for (; list != NULL && idx > 0; idx--)
- list = list->next;
- if (list == NULL)
- return PSK_KEY_ERROR;
- list->chosen = 1;
-
- #ifdef HAVE_SESSION_TICKET
- if (list->resumption) {
- /* Check that the session's details are the same as the server's. */
- if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 ||
- ssl->options.cipherSuite != ssl->session.cipherSuite ||
- ssl->session.version.major != ssl->ctx->method->version.major ||
- ssl->session.version.minor != ssl->ctx->method->version.minor) {
- return PSK_KEY_ERROR;
- }
- }
- #endif
-
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Create a new pre-shared key and put it into the list.
- *
- * list The linked list of pre-shared key.
- * identity The identity.
- * len The length of the identity data.
- * heap The memory to allocate with.
- * preSharedKey The new pre-shared key object.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity,
- word16 len, void *heap,
- PreSharedKey** preSharedKey)
-{
- PreSharedKey* psk;
- PreSharedKey** next;
-
- psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX);
- if (psk == NULL)
- return MEMORY_E;
- XMEMSET(psk, 0, sizeof(*psk));
-
- /* Make a copy of the identity data. */
- psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX);
- if (psk->identity == NULL) {
- XFREE(psk, heap, DYNAMIC_TYPE_TLSX);
- return MEMORY_E;
- }
- XMEMCPY(psk->identity, identity, len);
- psk->identityLen = len;
-
- /* Add it to the end and maintain the links. */
- 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;
-}
-
-static WC_INLINE byte GetHmacLength(int hmac)
-{
- switch (hmac) {
- #ifndef NO_SHA256
- case sha256_mac:
- return WC_SHA256_DIGEST_SIZE;
- #endif
- #ifdef WOLFSSL_SHA384
- case sha384_mac:
- return WC_SHA384_DIGEST_SIZE;
- #endif
- #ifdef WOLFSSL_SHA512
- case sha512_mac:
- return WC_SHA512_DIGEST_SIZE;
- #endif
- }
- return 0;
-}
-
-/* Use the data to create a new pre-shared key object in the extensions.
- *
- * ssl The SSL/TLS object.
- * identity The identity.
- * len The length of the identity data.
- * age The age of the identity.
- * hmac The HMAC algorithm.
- * ciphersuite0 The first byte of the ciphersuite to use.
- * ciphersuite The second byte of the ciphersuite to use.
- * resumption The PSK is for resumption of a session.
- * preSharedKey The new pre-shared key object.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age,
- byte hmac, byte cipherSuite0,
- byte cipherSuite, byte resumption,
- PreSharedKey **preSharedKey)
-{
- int ret = 0;
- TLSX* extension;
- PreSharedKey* psk = NULL;
-
- /* Find the pre-shared key extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL) {
- /* Push new pre-shared key extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap);
- if (ret != 0)
- return ret;
-
- extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY);
- if (extension == NULL)
- return MEMORY_E;
- }
-
- /* Try to find the pre-shared key with this identity. */
- psk = (PreSharedKey*)extension->data;
- while (psk != NULL) {
- if ((psk->identityLen == len) &&
- (XMEMCMP(psk->identity, identity, len) == 0)) {
- break;
- }
- psk = psk->next;
- }
-
- /* Create a new pre-shared key object if not found. */
- if (psk == NULL) {
- ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity,
- len, ssl->heap, &psk);
- if (ret != 0)
- return ret;
- }
-
- /* Update/set age and HMAC algorithm. */
- psk->ticketAge = age;
- psk->hmac = hmac;
- psk->cipherSuite0 = cipherSuite0;
- psk->cipherSuite = cipherSuite;
- psk->resumption = resumption;
- psk->binderLen = GetHmacLength(psk->hmac);
-
- if (preSharedKey != NULL)
- *preSharedKey = psk;
-
- return 0;
-}
-
-#define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll
-#define PSK_GET_SIZE TLSX_PreSharedKey_GetSize
-#define PSK_WRITE TLSX_PreSharedKey_Write
-#define PSK_PARSE TLSX_PreSharedKey_Parse
-
-#else
-
-#define PSK_FREE_ALL(a, b)
-#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
-
-/******************************************************************************/
-/* PSK Key Exchange Modes */
-/******************************************************************************/
-
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
-/* Get the size of the encoded PSK KE modes extension.
- * Only in ClientHello.
- *
- * modes The PSK KE mode bit string.
- * 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 int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz)
-{
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- word16 len = OPAQUE8_LEN;
- /* Check whether each possible mode is to be written. */
- if (modes & (1 << PSK_KE))
- len += OPAQUE8_LEN;
- if (modes & (1 << PSK_DHE_KE))
- len += OPAQUE8_LEN;
- *pSz += len;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Writes the PSK KE modes extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * Only in ClientHello.
- *
- * modes The PSK KE mode bit string.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType,
- word16* pSz)
-{
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- int idx = OPAQUE8_LEN;
-
- /* Write out each possible mode. */
- if (modes & (1 << PSK_KE))
- output[idx++] = PSK_KE;
- if (modes & (1 << PSK_DHE_KE))
- output[idx++] = PSK_DHE_KE;
- /* Write out length of mode list. */
- output[0] = idx - OPAQUE8_LEN;
-
- *pSz += idx;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Parse the PSK KE modes extension.
- * Only in ClientHello.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- int ret;
-
- if (msgType == client_hello) {
- /* Format: Len | Modes* */
- int idx = 0;
- word16 len;
- byte modes = 0;
-
- /* Ensure length byte exists. */
- if (length < OPAQUE8_LEN)
- return BUFFER_E;
-
- /* Get length of mode list and ensure that is the only data. */
- len = input[0];
- if (length - OPAQUE8_LEN != len)
- return BUFFER_E;
-
- idx = OPAQUE8_LEN;
- /* Set a bit for each recognized modes. */
- while (len > 0) {
- /* Ignore unrecognized modes. */
- if (input[idx] <= PSK_DHE_KE)
- modes |= 1 << input[idx];
- idx++;
- len--;
- }
-
- ret = TLSX_PskKeModes_Use(ssl, modes);
- if (ret != 0)
- return ret;
-
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Use the data to create a new PSK Key Exchange Modes object in the extensions.
- *
- * ssl The SSL/TLS object.
- * modes The PSK key exchange modes.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes)
-{
- int ret = 0;
- TLSX* extension;
-
- /* Find the PSK key exchange modes extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
- if (extension == NULL) {
- /* Push new PSK key exchange modes extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL,
- ssl->heap);
- if (ret != 0)
- return ret;
-
- extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES);
- if (extension == NULL)
- return MEMORY_E;
- }
-
- extension->val = modes;
-
- return 0;
-}
-
-#define PKM_GET_SIZE TLSX_PskKeModes_GetSize
-#define PKM_WRITE TLSX_PskKeModes_Write
-#define PKM_PARSE TLSX_PskKeModes_Parse
-
-#else
-
-#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
-
-/******************************************************************************/
-/* Post-Handshake Authentication */
-/******************************************************************************/
-
-#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH)
-/* 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-Handshake Authentication
- * extension.
- */
-static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz)
-{
- if (msgType == client_hello) {
- *pSz += 0;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Writes the Post-Handshake Authentication extension into the output buffer.
- * Assumes that the the output buffer is big enough to hold data.
- * Only in ClientHello.
- *
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz)
-{
- (void)output;
-
- if (msgType == client_hello) {
- *pSz += 0;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Parse the Post-Handshake Authentication extension.
- * Only in ClientHello.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- (void)input;
-
- if (msgType == client_hello) {
- /* Ensure extension is empty. */
- if (length != 0)
- return BUFFER_E;
-
- ssl->options.postHandshakeAuth = 1;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Create a new Post-handshake authentication object in the extensions.
- *
- * ssl The SSL/TLS object.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_PostHandAuth_Use(WOLFSSL* ssl)
-{
- int ret = 0;
- TLSX* extension;
-
- /* Find the PSK key exchange modes extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH);
- if (extension == NULL) {
- /* Push new Post-handshake Authentication extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL,
- ssl->heap);
- if (ret != 0)
- return ret;
- }
-
- return 0;
-}
-
-#define PHA_GET_SIZE TLSX_PostHandAuth_GetSize
-#define PHA_WRITE TLSX_PostHandAuth_Write
-#define PHA_PARSE TLSX_PostHandAuth_Parse
-
-#else
-
-#define PHA_GET_SIZE(a, b) 0
-#define PHA_WRITE(a, b, c) 0
-#define PHA_PARSE(a, b, c, d) 0
-
-#endif
-
-/******************************************************************************/
-/* Early Data Indication */
-/******************************************************************************/
-
-#ifdef WOLFSSL_EARLY_DATA
-/* Get the size of the encoded Early Data Indication extension.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * 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 int TLSX_EarlyData_GetSize(byte msgType, word16* pSz)
-{
- int ret = 0;
-
- if (msgType == client_hello || msgType == encrypted_extensions)
- *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.
- * Assumes that the the output buffer is big enough to hold data.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * max The maximum early data size.
- * output The buffer to write into.
- * msgType The type of the message this extension is being written into.
- * returns the number of bytes written into the buffer.
- */
-static int TLSX_EarlyData_Write(word32 max, byte* output, byte msgType,
- word16* pSz)
-{
- if (msgType == client_hello || msgType == encrypted_extensions)
- return 0;
- else if (msgType == session_ticket) {
- c32toa(max, output);
- *pSz += OPAQUE32_LEN;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Parse the Early Data Indicator extension.
- * In messages: ClientHello, EncryptedExtensions and NewSessionTicket.
- *
- * ssl The SSL/TLS object.
- * input The extension data.
- * length The length of the extension data.
- * msgType The type of the message this extension is being parsed from.
- * returns 0 on success and other values indicate failure.
- */
-static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length,
- byte msgType)
-{
- if (msgType == client_hello) {
- if (length != 0)
- return BUFFER_E;
-
- 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)
- return BUFFER_E;
-
- /* Ensure the index of PSK identity chosen by server is 0.
- * Index is plus one to handle 'not set' value of 0.
- */
- if (ssl->options.pskIdIndex != 1)
- return PSK_KEY_ERROR;
-
- return TLSX_EarlyData_Use(ssl, 1);
- }
- if (msgType == session_ticket) {
- word32 maxSz;
-
- if (length != OPAQUE32_LEN)
- return BUFFER_E;
- ato32(input, &maxSz);
-
- ssl->session.maxEarlyDataSz = maxSz;
- return 0;
- }
-
- return SANITY_MSG_E;
-}
-
-/* Use the data to create a new Early Data object in the extensions.
- *
- * ssl The SSL/TLS object.
- * max The maximum early data size.
- * returns 0 on success and other values indicate failure.
- */
-int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max)
-{
- int ret = 0;
- TLSX* extension;
-
- /* Find the early data extension if it exists. */
- extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
- if (extension == NULL) {
- /* Push new early data extension. */
- ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap);
- if (ret != 0)
- return ret;
-
- extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA);
- if (extension == NULL)
- return MEMORY_E;
- }
-
- extension->resp = 1;
- extension->val = max;
-
- return 0;
-}
-
-#define EDI_GET_SIZE TLSX_EarlyData_GetSize
-#define EDI_WRITE TLSX_EarlyData_Write
-#define EDI_PARSE TLSX_EarlyData_Parse
-
-#else
-
-#define EDI_GET_SIZE(a, b) 0
-#define EDI_WRITE(a, b, c, d) 0
-#define EDI_PARSE(a, b, c, d) 0
-
-#endif
-
-/******************************************************************************/
-/* TLS Extensions Framework */
-/******************************************************************************/
-
-/** Finds an extension in the provided list. */
-TLSX* TLSX_Find(TLSX* list, TLSX_Type type)
-{
- TLSX* extension = list;
-
- while (extension && extension->type != type)
- extension = extension->next;
-
- return extension;
-}
-
-/** Remove an extension. */
-void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap)
-{
- TLSX* extension = *list;
- TLSX** next = list;
-
- while (extension && extension->type != type) {
- next = &extension->next;
- extension = extension->next;
- }
-
- if (extension) {
- *next = extension->next;
- extension->next = NULL;
- TLSX_FreeAll(extension, heap);
- }
-}
-
-/** Releases all extensions in the provided list. */
-void TLSX_FreeAll(TLSX* list, void* heap)
-{
- TLSX* extension;
-
- while ((extension = list)) {
- list = extension->next;
-
- switch (extension->type) {
-
- case TLSX_SERVER_NAME:
- 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;
-
- case TLSX_TRUNCATED_HMAC:
- /* Nothing to do. */
- break;
-
- case TLSX_SUPPORTED_GROUPS:
- EC_FREE_ALL((SupportedCurve*)extension->data, heap);
- break;
-
- case TLSX_EC_POINT_FORMATS:
- PF_FREE_ALL((PointFormat*)extension->data, heap);
- break;
-
- case TLSX_STATUS_REQUEST:
- CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap);
- break;
-
- case TLSX_STATUS_REQUEST_V2:
- CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data,
- heap);
- break;
-
- case TLSX_RENEGOTIATION_INFO:
- SCR_FREE_ALL(extension->data, heap);
- break;
-
- case TLSX_SESSION_TICKET:
- WOLF_STK_FREE(extension->data, heap);
- break;
-
- case TLSX_QUANTUM_SAFE_HYBRID:
- QSH_FREE_ALL((QSHScheme*)extension->data, heap);
- break;
-
- 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;
-
- case TLSX_COOKIE:
- CKE_FREE_ALL((Cookie*)extension->data, heap);
- break;
-
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- PSK_FREE_ALL((PreSharedKey*)extension->data, heap);
- break;
-
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- break;
- #endif
-
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- break;
- #endif
-
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- break;
- #endif
-
- #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- break;
- #endif
-
- case TLSX_KEY_SHARE:
- KS_FREE_ALL((KeyShareEntry*)extension->data, heap);
- break;
-#endif
- }
-
- XFREE(extension, heap, DYNAMIC_TYPE_TLSX);
- }
-
- (void)heap;
-}
-
-/** Checks if the tls extensions are supported based on the protocol version. */
-int TLSX_SupportExtensions(WOLFSSL* ssl) {
- return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR);
-}
-
-/** Tells the buffered size of the extensions in a list. */
-static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType,
- word16* pLength)
-{
- int ret = 0;
- TLSX* extension;
- word16 length = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
-
- while ((extension = list)) {
- list = extension->next;
-
- /* only extensions marked as response are sent back to the client. */
- if (!isRequest && !extension->resp)
- continue; /* skip! */
-
- /* ssl level extensions are expected to override ctx level ones. */
- if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
- continue; /* skip! */
-
- /* extension type + extension data length. */
- length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
-
-
- switch (extension->type) {
-
- case TLSX_SERVER_NAME:
- /* SNI only sends the name on the request. */
- if (isRequest)
- 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;
-
- case TLSX_TRUNCATED_HMAC:
- /* always empty. */
- break;
-
- case TLSX_SUPPORTED_GROUPS:
- length += EC_GET_SIZE((SupportedCurve*)extension->data);
- break;
-
- case TLSX_EC_POINT_FORMATS:
- length += PF_GET_SIZE((PointFormat*)extension->data);
- break;
-
- case TLSX_STATUS_REQUEST:
- length += CSR_GET_SIZE(
- (CertificateStatusRequest*)extension->data, isRequest);
- break;
-
- case TLSX_STATUS_REQUEST_V2:
- length += CSR2_GET_SIZE(
- (CertificateStatusRequestItemV2*)extension->data,
- isRequest);
- break;
-
- case TLSX_RENEGOTIATION_INFO:
- length += SCR_GET_SIZE((SecureRenegotiation*)extension->data,
- isRequest);
- break;
-
- case TLSX_SESSION_TICKET:
- length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data,
- isRequest);
- break;
-
- case TLSX_QUANTUM_SAFE_HYBRID:
- length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest);
- break;
-
- 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);
- break;
-
- case TLSX_COOKIE:
- ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length);
- break;
-
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType,
- &length);
- break;
-
- case TLSX_PSK_KEY_EXCHANGE_MODES:
- ret = PKM_GET_SIZE(extension->val, msgType, &length);
- break;
- #endif
-
- #ifdef WOLFSSL_EARLY_DATA
- case TLSX_EARLY_DATA:
- ret = EDI_GET_SIZE(msgType, &length);
- break;
- #endif
-
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- case TLSX_POST_HANDSHAKE_AUTH:
- ret = PHA_GET_SIZE(msgType, &length);
- break;
- #endif
-
- #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- length += SAC_GET_SIZE(extension->data);
- break;
- #endif
-
- case TLSX_KEY_SHARE:
- length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType);
- break;
-#endif
- }
-
- /* marks the extension as processed so ctx level */
- /* extensions don't overlap with ssl level ones. */
- TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
- }
-
- *pLength += length;
-
- return ret;
-}
-
-/** Writes the extensions of a list in a buffer. */
-static int TLSX_Write(TLSX* list, byte* output, byte* semaphore,
- byte msgType, word16* pOffset)
-{
- int ret = 0;
- TLSX* extension;
- word16 offset = 0;
- word16 length_offset = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
-
- while ((extension = list)) {
- list = extension->next;
-
- /* only extensions marked as response are written in a response. */
- if (!isRequest && !extension->resp)
- continue; /* skip! */
-
- /* ssl level extensions are expected to override ctx level ones. */
- if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type)))
- continue; /* skip! */
-
- /* writes extension type. */
- c16toa(extension->type, output + offset);
- offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN;
- length_offset = offset;
-
- /* extension data should be written internally. */
- switch (extension->type) {
- case TLSX_SERVER_NAME:
- if (isRequest) {
- WOLFSSL_MSG("SNI extension to write");
- offset += SNI_WRITE((SNI*)extension->data, output + offset);
- }
- 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);
- break;
-
- case TLSX_TRUNCATED_HMAC:
- WOLFSSL_MSG("Truncated HMAC extension to write");
- /* always empty. */
- break;
-
- case TLSX_SUPPORTED_GROUPS:
- WOLFSSL_MSG("Supported Groups extension to write");
- offset += EC_WRITE((SupportedCurve*)extension->data,
- output + offset);
- break;
-
- case TLSX_EC_POINT_FORMATS:
- WOLFSSL_MSG("Point Formats extension to write");
- offset += PF_WRITE((PointFormat*)extension->data,
- output + offset);
- break;
-
- case TLSX_STATUS_REQUEST:
- WOLFSSL_MSG("Certificate Status Request extension to write");
- offset += CSR_WRITE((CertificateStatusRequest*)extension->data,
- output + offset, isRequest);
- break;
-
- case TLSX_STATUS_REQUEST_V2:
- WOLFSSL_MSG("Certificate Status Request v2 extension to write");
- offset += CSR2_WRITE(
- (CertificateStatusRequestItemV2*)extension->data,
- output + offset, isRequest);
- break;
-
- case TLSX_RENEGOTIATION_INFO:
- WOLFSSL_MSG("Secure Renegotiation extension to write");
- offset += SCR_WRITE((SecureRenegotiation*)extension->data,
- output + offset, isRequest);
- break;
-
- case TLSX_SESSION_TICKET:
- WOLFSSL_MSG("Session Ticket extension to write");
- offset += WOLF_STK_WRITE((SessionTicket*)extension->data,
- output + offset, isRequest);
- break;
-
- case TLSX_QUANTUM_SAFE_HYBRID:
- WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write");
- if (isRequest) {
- offset += QSH_WRITE((QSHScheme*)extension->data, output + offset);
- }
- offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset);
- offset += QSH_SERREQ(output + offset, isRequest);
- break;
-
- case TLSX_APPLICATION_LAYER_PROTOCOL:
- 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");
- ret = SV_WRITE(extension->data, output + offset, msgType, &offset);
- break;
-
- case TLSX_COOKIE:
- WOLFSSL_MSG("Cookie extension to write");
- ret = CKE_WRITE((Cookie*)extension->data, output + offset,
- msgType, &offset);
- break;
-
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- case TLSX_PRE_SHARED_KEY:
- WOLFSSL_MSG("Pre-Shared Key extension to write");
- 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");
- 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");
- 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");
- ret = PHA_WRITE(output + offset, msgType, &offset);
- break;
- #endif
-
- #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
- case TLSX_SIGNATURE_ALGORITHMS_CERT:
- WOLFSSL_MSG("Signature Algorithms extension to write");
- offset += SAC_WRITE(extension->data, output + offset);
- break;
- #endif
-
- case TLSX_KEY_SHARE:
- WOLFSSL_MSG("Key Share extension to write");
- offset += KS_WRITE((KeyShareEntry*)extension->data,
- output + offset, msgType);
- break;
-#endif
- }
-
- /* writes extension data length. */
- c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN);
-
- /* marks the extension as processed so ctx level */
- /* extensions don't overlap with ssl level ones. */
- TURN_ON(semaphore, TLSX_ToSemaphore(extension->type));
- }
-
- *pOffset += offset;
-
- return ret;
-}
-
-
-#if defined(HAVE_NTRU) && defined(HAVE_QSH)
-
-static word32 GetEntropy(unsigned char* out, word32 num_bytes)
-{
- int ret = 0;
-
- if (gRng == NULL) {
- if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return DRBG_OUT_OF_MEMORY;
- wc_InitRng(gRng);
- }
-
- if (gRngMutex == NULL) {
- if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return DRBG_OUT_OF_MEMORY;
- wc_InitMutex(gRngMutex);
- }
-
- ret |= wc_LockMutex(gRngMutex);
- ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes);
- ret |= wc_UnLockMutex(gRngMutex);
-
- if (ret != 0)
- return DRBG_ENTROPY_FAIL;
-
- return DRBG_OK;
-}
-#endif
-
-
-#ifdef HAVE_QSH
-static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type)
-{
- int ret = -1;
-
- (void)ssl;
-
- switch (type) {
-#ifdef HAVE_NTRU
- case WOLFSSL_NTRU_EESS439:
- case WOLFSSL_NTRU_EESS593:
- case WOLFSSL_NTRU_EESS743:
- ret = TLSX_CreateNtruKey(ssl, type);
- break;
-#endif
- default:
- WOLFSSL_MSG("Unknown type for creating NTRU key");
- break;
- }
-
- return ret;
-}
-
-
-static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key)
-{
- QSHKey* current;
-
- if (key == NULL)
- return BAD_FUNC_ARG;
-
- /* if no public key stored in key then do not add */
- if (key->pub.length == 0 || key->pub.buffer == NULL)
- return 0;
-
- /* first element to be added to the list */
- current = *list;
- if (current == NULL) {
- *list = key;
- return 0;
- }
-
- while (current->next) {
- /* can only have one of the key in the list */
- if (current->name == key->name)
- return -1;
- current = (QSHKey*)current->next;
- }
-
- current->next = (struct QSHKey*)key;
-
- return 0;
-}
-
-
-#if defined(HAVE_NTRU)
-int TLSX_CreateNtruKey(WOLFSSL* ssl, int type)
-{
- int ret = -1;
- int ntruType;
-
- /* variable declarations for NTRU*/
- QSHKey* temp = NULL;
- byte public_key[1027];
- word16 public_key_len = sizeof(public_key);
- byte private_key[1120];
- word16 private_key_len = sizeof(private_key);
- DRBG_HANDLE drbg;
-
- if (ssl == NULL)
- return BAD_FUNC_ARG;
-
- switch (type) {
- case WOLFSSL_NTRU_EESS439:
- ntruType = NTRU_EES439EP1;
- break;
- case WOLFSSL_NTRU_EESS593:
- ntruType = NTRU_EES593EP1;
- break;
- case WOLFSSL_NTRU_EESS743:
- ntruType = NTRU_EES743EP1;
- break;
- default:
- WOLFSSL_MSG("Unknown type for creating NTRU key");
- return -1;
- }
- ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg);
- if (ret != DRBG_OK) {
- WOLFSSL_MSG("NTRU drbg instantiate failed\n");
- return ret;
- }
-
- if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
- &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK)
- return ret;
-
- if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType,
- &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK)
- return ret;
-
- ret = ntru_crypto_drbg_uninstantiate(drbg);
- if (ret != NTRU_OK) {
- WOLFSSL_MSG("NTRU drbg uninstantiate failed\n");
- return ret;
- }
-
- if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap,
- DYNAMIC_TYPE_TLSX)) == NULL)
- return MEMORY_E;
- temp->name = type;
- temp->pub.length = public_key_len;
- temp->pub.buffer = (byte*)XMALLOC(public_key_len, ssl->heap,
- DYNAMIC_TYPE_PUBLIC_KEY);
- XMEMCPY(temp->pub.buffer, public_key, public_key_len);
- temp->pri.length = private_key_len;
- temp->pri.buffer = (byte*)XMALLOC(private_key_len, ssl->heap,
- DYNAMIC_TYPE_ARRAYS);
- XMEMCPY(temp->pri.buffer, private_key, private_key_len);
- temp->next = NULL;
-
- TLSX_AddQSHKey(&ssl->QSH_Key, temp);
-
- (void)ssl;
- (void)type;
-
- return ret;
-}
-#endif
-
-
-/*
- Used to find a public key from the list of keys
- pubLen length of array
- name input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX
-
- returns a pointer to public key byte* or NULL if not found
- */
-static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name)
-{
- QSHKey* current = qsh;
-
- if (qsh == NULL || pubLen == NULL)
- return NULL;
-
- *pubLen = 0;
-
- while(current) {
- if (current->name == name) {
- *pubLen = current->pub.length;
- return current->pub.buffer;
- }
- current = (QSHKey*)current->next;
- }
-
- return NULL;
-}
-#endif /* HAVE_QSH */
-
-#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_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;
-#ifdef WOLFSSL_TLS13
- int i;
-
-#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.resuming && ssl->session.namedGroup != 0) {
- return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup,
- ssl->heap);
- }
-#endif
-
- if (ssl->numGroups != 0) {
- for (i = 0; i < ssl->numGroups; i++) {
- ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- return WOLFSSL_SUCCESS;
- }
-#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,
- WOLFSSL_ECC_SECP160R1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_SECPR2
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP160R2, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #ifdef HAVE_ECC_KOBLITZ
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_ECC_SECP160K1, ssl->heap);
- if (ret != WOLFSSL_SUCCESS) return ret;
- #endif
- #endif
- #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_FFDHE_8192, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_6144
- if (6144/8 >= ssl->options.minDhKeySz &&
- 6144/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_6144, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_4096
- if (4096/8 >= ssl->options.minDhKeySz &&
- 4096/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_4096, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #ifdef HAVE_FFDHE_3072
- if (3072/8 >= ssl->options.minDhKeySz &&
- 3072/8 <= ssl->options.maxDhKeySz) {
- ret = TLSX_UseSupportedCurve(extensions,
- WOLFSSL_FFDHE_3072, ssl->heap);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- }
- #endif
- #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
-
- (void)ssl;
- (void)extensions;
-
- return ret;
-}
-
-#endif
-
-int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer)
-{
- int ret = 0;
- byte* public_key = NULL;
- word16 public_key_len = 0;
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- int usingPSK = 0;
-#endif
-#ifdef HAVE_QSH
- TLSX* extension;
- QSHScheme* qsh;
- QSHScheme* next;
-
- /* add supported QSHSchemes */
- WOLFSSL_MSG("Adding supported QSH Schemes");
-#endif
-
- /* 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 */
- if (!ssl->user_set_QSHSchemes) {
- if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
- if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) {
- WOLFSSL_MSG("Error creating ntru keys");
- return ret;
- }
-
- /* add NTRU 256 */
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS743);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
-
- /* add NTRU 196 */
- if (ssl->sendQSHKeys) {
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS593);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
-
- /* add NTRU 128 */
- if (ssl->sendQSHKeys) {
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, WOLFSSL_NTRU_EESS439);
- }
- if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439,
- public_key, public_key_len, ssl->heap)
- != WOLFSSL_SUCCESS)
- ret = -1;
- }
- else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) {
- /* for each scheme make a client key */
- extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
- if (extension) {
- qsh = (QSHScheme*)extension->data;
-
- while (qsh) {
- if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0)
- return ret;
-
- /* get next now because qsh could be freed */
- next = qsh->next;
-
- /* find the public key created and add to extension*/
- public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key,
- &public_key_len, qsh->name);
- if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name,
- public_key, public_key_len,
- ssl->heap) != WOLFSSL_SUCCESS)
- ret = -1;
- qsh = next;
- }
- }
- }
-#endif
-
-#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) || 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 */
- WOLFSSL_MSG("Adding supported versions extension");
- if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl,
- ssl->heap)) != 0) {
- return ret;
- }
-
- #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \
- !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);
- if (ret != WOLFSSL_SUCCESS)
- return ret;
- ret = 0;
- }
- #endif /* (HAVE_ECC || CURVE25519 || CURVE448) && HAVE_SUPPORTED_CURVES */
-
- #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22)
- if (ssl->certHashSigAlgoSz > 0) {
- WOLFSSL_MSG("Adding signature algorithms cert extension");
- if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions,
- ssl, ssl->heap)) != 0) {
- return ret;
- }
- }
- #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */
-
- if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) {
- word16 namedGroup;
-
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (ssl->options.resuming && ssl->session.namedGroup != 0)
- namedGroup = ssl->session.namedGroup;
- else
- #endif
- {
- #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \
- defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP)
- 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;
- #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \
- defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP)
- namedGroup = WOLFSSL_ECC_SECP521R1;
- #elif defined(HAVE_FFDHE_2048)
- namedGroup = WOLFSSL_FFDHE_2048;
- #elif defined(HAVE_FFDHE_3072)
- namedGroup = WOLFSSL_FFDHE_3072;
- #elif defined(HAVE_FFDHE_4096)
- namedGroup = WOLFSSL_FFDHE_4096;
- #elif defined(HAVE_FFDHE_6144)
- namedGroup = WOLFSSL_FFDHE_6144;
- #elif defined(HAVE_FFDHE_8192)
- namedGroup = WOLFSSL_FFDHE_8192;
- #else
- return KEY_SHARE_ERROR;
- #endif
- }
- ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL);
- if (ret != 0)
- return ret;
- }
-
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap);
- #endif
- #if defined(HAVE_SESSION_TICKET)
- if (ssl->options.resuming && ssl->session.ticketLen > 0) {
- 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;
- ret = SetCipherSpecs(ssl);
- if (ret != 0)
- return ret;
- milli = TimeNowInMilliseconds() - sess->ticketSeen +
- sess->ticketAdd;
- /* Pre-shared key is mandatory extension for resumption. */
- ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen,
- milli, ssl->specs.mac_algorithm,
- ssl->options.cipherSuite0,
- ssl->options.cipherSuite, 1,
- NULL);
- if (ret != 0)
- return ret;
-
- usingPSK = 1;
- }
- #endif
- #ifndef NO_PSK
- 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;
- 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;
- }
- ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0';
- /* TODO: Callback should be able to change ciphersuite. */
- ssl->options.cipherSuite0 = cipherSuite0;
- ssl->options.cipherSuite = cipherSuite;
- ret = SetCipherSpecs(ssl);
- if (ret != 0)
- return ret;
-
- ret = TLSX_PreSharedKey_Use(ssl,
- (byte*)ssl->arrays->client_identity,
- (word16)XSTRLEN(ssl->arrays->client_identity),
- 0, ssl->specs.mac_algorithm,
- cipherSuite0, cipherSuite, 0,
- NULL);
- if (ret != 0)
- return ret;
-
- usingPSK = 1;
- }
- #endif
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (usingPSK) {
- byte modes;
-
- /* Pre-shared key modes: mandatory extension for resumption. */
- modes = 1 << PSK_KE;
- #if !defined(NO_DH) || defined(HAVE_ECC) || \
- defined(HAVE_CURVE25519) || defined(HAVE_CURVE448)
- if (!ssl->options.noPskDheKe)
- modes |= 1 << PSK_DHE_KE;
- #endif
- ret = TLSX_PskKeModes_Use(ssl, modes);
- if (ret != 0)
- return ret;
- }
- #endif
- #if defined(WOLFSSL_POST_HANDSHAKE_AUTH)
- if (!isServer && ssl->options.postHandshakeAuth) {
- ret = TLSX_PostHandAuth_Use(ssl);
- if (ret != 0)
- return ret;
- }
- #endif
- }
-
- #endif
-
- (void)isServer;
- (void)public_key;
- (void)public_key_len;
- (void)ssl;
-
- return ret;
-}
-
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT)
-
-/** Tells the buffered size of extensions to be sent into the client hello. */
-int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength)
-{
- int ret = 0;
- word16 length = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
-
- if (!TLSX_SupportExtensions(ssl))
- return 0;
- if (msgType == client_hello) {
- EC_VALIDATE_REQUEST(ssl, semaphore);
- 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));
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- #endif
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
- #endif
- }
-#endif
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- if (!ssl->ctx->cm->ocspStaplingEnabled) {
- /* mark already sent, so it won't send it */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- }
- #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
- */
- }
- #endif
-#endif
- if (ssl->extensions) {
- ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length);
- 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) || ssl->options.downgrade)) {
- length += HELLO_EXT_SZ;
- }
-#endif
-
- if (length)
- length += OPAQUE16_LEN; /* for total length storage. */
-
- *pLength += length;
-
- return ret;
-}
-
-/** Writes the extensions to be sent into the client hello. */
-int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset)
-{
- int ret = 0;
- word16 offset = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
-
- if (!TLSX_SupportExtensions(ssl) || output == NULL)
- return 0;
-
- offset += OPAQUE16_LEN; /* extensions length */
-
- if (msgType == client_hello) {
- EC_VALIDATE_REQUEST(ssl, semaphore);
- 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));
- if (!IsAtLeastTLSv1_3(ssl->version)) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES));
- #endif
- #ifdef WOLFSSL_EARLY_DATA
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- #endif
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- #ifdef WOLFSSL_POST_HANDSHAKE_AUTH
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH));
- #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.
- */
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
-#endif
- #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \
- || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)
- /* mark already sent, so it won't send it */
- if (!ssl->ctx->cm->ocspStaplingEnabled) {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2));
- }
- #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, TLSX_OID_FILTERS
- * TLSX_STATUS_REQUEST
- */
- }
- #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) || ssl->options.downgrade)) {
- WOLFSSL_MSG("EMS extension to write");
- c16toa(HELLO_EXT_EXTMS, output + offset);
- offset += HELLO_EXT_TYPE_SZ;
- c16toa(0, output + offset);
- offset += HELLO_EXT_SZ_SZ;
- }
-#endif
-
-#ifdef WOLFSSL_TLS13
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) {
- /* Write out what we can of Pre-shared key extension. */
- 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
-
- if (offset > OPAQUE16_LEN || msgType != client_hello)
- c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
-
- *pOffset += offset;
-
- return ret;
-}
-
-#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */
-
-#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER)
-
-/** Tells the buffered size of extensions to be sent into the server hello. */
-int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength)
-{
- int ret = 0;
- word16 length = 0;
- byte semaphore[SEMAPHORE_SIZE] = {0};
-
- switch (msgType) {
-#ifndef NO_WOLFSSL_SERVER
- case server_hello:
- PF_VALIDATE_RESPONSE(ssl, semaphore);
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #ifndef WOLFSSL_TLS13_DRAFT_18
- TURN_OFF(semaphore,
- TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #endif
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- else {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #endif
- break;
-
- #ifdef WOLFSSL_TLS13
- case hello_retry_request:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #ifndef WOLFSSL_TLS13_DRAFT_18
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #endif
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE));
- break;
- #endif
-
- #ifdef WOLFSSL_TLS13
- case encrypted_extensions:
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- #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
- case session_ticket:
- if (ssl->options.tls1_3) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- }
- break;
- #endif
- #endif
-#endif
-
-#ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- case certificate:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_SERVER_CERTIFICATE_TYPE
- */
- break;
- #endif
-#endif
- }
-
- #ifdef HAVE_QSH
- /* change response if not using TLS_QSH */
- if (!ssl->options.haveQSH) {
- TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID);
- if (ext)
- ext->resp = 0;
- }
- #endif
-
-#ifdef HAVE_EXTENDED_MASTER
- if (ssl->options.haveEMS && msgType == server_hello &&
- !IsAtLeastTLSv1_3(ssl->version)) {
- length += HELLO_EXT_SZ;
- }
-#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. */
-
- if (length || msgType != server_hello)
- length += OPAQUE16_LEN; /* for total length storage. */
-
- *pLength += length;
-
- return ret;
-}
-
-/** Writes the server hello extensions into a buffer. */
-int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset)
-{
- int ret = 0;
- word16 offset = 0;
-
- if (TLSX_SupportExtensions(ssl) && output) {
- byte semaphore[SEMAPHORE_SIZE] = {0};
-
- switch (msgType) {
-#ifndef NO_WOLFSSL_SERVER
- case server_hello:
- PF_VALIDATE_RESPONSE(ssl, semaphore);
- #ifdef WOLFSSL_TLS13
- if (IsAtLeastTLSv1_3(ssl->version)) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #ifndef WOLFSSL_TLS13_DRAFT_18
- TURN_OFF(semaphore,
- TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #endif
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- else {
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- }
- #endif
- break;
-
- #ifdef WOLFSSL_TLS13
- case hello_retry_request:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- #ifndef WOLFSSL_TLS13_DRAFT_18
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- #endif
- if (!ssl->options.noPskDheKe)
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- /* Cookie is written below as last extension. */
- break;
- #endif
-
- #ifdef WOLFSSL_TLS13
- case encrypted_extensions:
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET));
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE));
- #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
- TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY));
- #endif
- #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
- case session_ticket:
- if (ssl->options.tls1_3) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA));
- }
- break;
- #endif
- #endif
-#endif
-
- #ifdef WOLFSSL_TLS13
- #ifndef NO_CERTS
- case certificate:
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST));
- /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP,
- * TLSX_SERVER_CERTIFICATE_TYPE
- */
- break;
- #endif
- #endif
- }
-
- offset += OPAQUE16_LEN; /* extensions length */
-
- ret = TLSX_Write(ssl->extensions, output + offset, semaphore,
- msgType, &offset);
- if (ret != 0)
- return ret;
-
-#ifdef WOLFSSL_TLS13
- if (msgType == hello_retry_request) {
- XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE);
- 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 &&
- !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);
- offset += HELLO_EXT_SZ_SZ;
- }
-#endif
-
- if (offset > OPAQUE16_LEN || msgType != server_hello)
- c16toa(offset - OPAQUE16_LEN, output); /* extensions length */
- }
-
- if (pOffset)
- *pOffset += offset;
-
- return ret;
-}
-
-#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)
-{
- int ret = 0;
- word16 offset = 0;
- byte isRequest = (msgType == client_hello ||
- msgType == certificate_request);
-
-#ifdef HAVE_EXTENDED_MASTER
- byte pendingEMS = 0;
-#endif
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- int pskDone = 0;
-#endif
-
- if (!ssl || !input || (isRequest && !suites))
- return BAD_FUNC_ARG;
-
- while (ret == 0 && offset < length) {
- word16 type;
- word16 size;
-
-#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK))
- if (msgType == client_hello && pskDone)
- return PSK_KEY_ERROR;
-#endif
-
- if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN)
- return BUFFER_ERROR;
-
- ato16(input + offset, &type);
- offset += HELLO_EXT_TYPE_SZ;
-
- ato16(input + offset, &size);
- offset += OPAQUE16_LEN;
-
- if (offset + size > length)
- return BUFFER_ERROR;
-
- 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) &&
- msgType != client_hello &&
- msgType != encrypted_extensions) {
- return EXT_NOT_ALLOWED;
- }
-#endif
- 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) &&
- msgType != client_hello &&
- 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))
- break;
-#endif
- ret = THM_PARSE(ssl, input + offset, size, isRequest);
- break;
-
- 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))
- break;
-#endif
- ret = PF_PARSE(ssl, input + offset, size, isRequest);
- break;
-
- case TLSX_STATUS_REQUEST:
- WOLFSSL_MSG("Certificate Status Request extension received");
- #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) &&
- msgType != client_hello &&
- msgType != certificate_request &&
- msgType != certificate) {
- return EXT_NOT_ALLOWED;
- }
-#endif
- ret = CSR2_PARSE(ssl, input + offset, size, isRequest);
- break;
-
-#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))
- break;
-#endif
- if (size != 0)
- return BUFFER_ERROR;
-
-#ifndef NO_WOLFSSL_SERVER
- if (isRequest)
- ssl->options.haveEMS = 1;
-#endif
- pendingEMS = 1;
- break;
-#endif
-
- 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))
- break;
-#endif
- ret = SCR_PARSE(ssl, input + offset, size, isRequest);
- break;
-
- 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) &&
- msgType != client_hello) {
- return EXT_NOT_ALLOWED;
- }
-#endif
- ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest);
- break;
-
- 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))
- break;
-#endif
- ret = QSH_PARSE(ssl, input + offset, size, isRequest);
- break;
-
- 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 &&
- msgType != certificate_request) {
- return EXT_NOT_ALLOWED;
- }
-#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("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 (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");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
-
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
-
- 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 (msgType != client_hello)
- return EXT_NOT_ALLOWED;
-
- ret = PKM_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
-
- #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 (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);
- break;
- #endif
-
- #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 (msgType != client_hello)
- return EXT_NOT_ALLOWED;
-
- ret = PHA_PARSE(ssl, input + offset, size, msgType);
- break;
- #endif
-
- #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 (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;
- #endif
-
- case TLSX_KEY_SHARE:
- WOLFSSL_MSG("Key Share extension received");
- #ifdef WOLFSSL_DEBUG_TLS
- WOLFSSL_BUFFER(input + offset, size);
- #endif
-
- if (!IsAtLeastTLSv1_3(ssl->version))
- break;
-
- 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! */
- offset += size;
- }
-
-#ifdef HAVE_EXTENDED_MASTER
- if (!isRequest && ssl->options.haveEMS && !pendingEMS)
- ssl->options.haveEMS = 0;
-#endif
-
- if (ret == 0)
- ret = SNI_VERIFY_PARSE(ssl, isRequest);
- if (ret == 0)
- ret = TCA_VERIFY_PARSE(ssl, isRequest);
-
- return ret;
-}
-
-/* undefining semaphore macros */
-#undef IS_OFF
-#undef TURN_ON
-#undef SEMAPHORE_SIZE
-
-#endif /* HAVE_TLS_EXTENSIONS */
-
-#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
- 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;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
-
- WOLFSSL_METHOD* wolfTLSv1_1_client_method(void)
- {
- 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
- /* The TLS v1.3 client method data.
- *
- * 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);
- }
-
- /* The TLS v1.3 client method data.
- *
- * heap The heap used for allocation.
- * returns the method data for a TLS v1.3 client.
- */
- WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method = (WOLFSSL_METHOD*)
- 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 */
-
-#ifdef WOLFSSL_DTLS
-
- WOLFSSL_METHOD* wolfDTLS_client_method(void)
- {
- 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(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;
- 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;
- }
- return method;
- }
- #endif /* WOLFSSL_ALLOW_TLSV10 */
-
- 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;
- }
- return method;
- }
-#endif /* !NO_OLD_TLS */
-
-
-#ifndef WOLFSSL_NO_TLS12
- 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
- /* The TLS v1.3 server method data.
- *
- * returns the method data for a TLS v1.3 server.
- */
- WOLFSSL_METHOD* wolfTLSv1_3_server_method(void)
- {
- return wolfTLSv1_3_server_method_ex(NULL);
- }
-
- /* The TLS v1.3 server method data.
- *
- * heap The heap used for allocation.
- * returns the method data for a TLS v1.3 server.
- */
- WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap)
- {
- WOLFSSL_METHOD* method =
- (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;
- }
- return method;
- }
-#endif /* WOLFSSL_TLS13 */
-
-#ifdef WOLFSSL_DTLS
- WOLFSSL_METHOD* wolfDTLS_server_method(void)
- {
- 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(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;
- 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 */