mirror of https://github.com/wolfSSL/wolfssl.git
Merge pull request #5623 from dgarske/hpke
Adds support for TLS v1.3 Encrypted Client Hello (ECH) and HPKE (Hybrid Public Key Encryption)pull/5912/head
commit
fc19aed8c8
36
configure.ac
36
configure.ac
|
@ -742,6 +742,7 @@ then
|
||||||
test "$enable_trusted_ca" = "" && enable_trusted_ca=yes
|
test "$enable_trusted_ca" = "" && enable_trusted_ca=yes
|
||||||
test "$enable_session_ticket" = "" && enable_session_ticket=yes
|
test "$enable_session_ticket" = "" && enable_session_ticket=yes
|
||||||
test "$enable_earlydata" = "" && enable_earlydata=yes
|
test "$enable_earlydata" = "" && enable_earlydata=yes
|
||||||
|
test "$enable_ech" = "" && enable_ech=yes
|
||||||
|
|
||||||
if test "$ENABLED_32BIT" != "yes"
|
if test "$ENABLED_32BIT" != "yes"
|
||||||
then
|
then
|
||||||
|
@ -1120,6 +1121,25 @@ AC_ARG_ENABLE([cryptonly],
|
||||||
|
|
||||||
AS_IF([test "x$FIPS_VERSION" = "xrand"],[ENABLED_CRYPTONLY="yes"])
|
AS_IF([test "x$FIPS_VERSION" = "xrand"],[ENABLED_CRYPTONLY="yes"])
|
||||||
|
|
||||||
|
# ECH
|
||||||
|
AC_ARG_ENABLE([ech],
|
||||||
|
[AS_HELP_STRING([--enable-ech],[Enable ECH (default: disabled)])],
|
||||||
|
[ ENABLED_ECH=$enableval ],
|
||||||
|
[ ENABLED_ECH=no ]
|
||||||
|
)
|
||||||
|
if test "$ENABLED_ECH" = "yes"
|
||||||
|
then
|
||||||
|
AM_CFLAGS="$AM_CFLAGS -DHAVE_ECH"
|
||||||
|
|
||||||
|
test "$enable_hpke" = "" && enable_hpke=yes
|
||||||
|
test "$enable_ecc" = "" && enable_ecc=yes
|
||||||
|
test "$enable_curve25519" = "" && enable_curve25519=yes
|
||||||
|
test "$enable_sha256" = "" && enable_sha256=yes
|
||||||
|
test "$enable_tlsx" = "" && enable_tlsx=yes
|
||||||
|
test "$enable_sni" = "" && enable_sni=yes
|
||||||
|
test "$enable_tls13" = "" && enable_tls13=yes
|
||||||
|
fi
|
||||||
|
|
||||||
# DTLS
|
# DTLS
|
||||||
# DTLS is a prereq for the options mcast, sctp, and jni. Enabling any of those
|
# DTLS is a prereq for the options mcast, sctp, and jni. Enabling any of those
|
||||||
# without DTLS will also enable DTLS.
|
# without DTLS will also enable DTLS.
|
||||||
|
@ -2980,6 +3000,20 @@ then
|
||||||
AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"
|
AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# HPKE
|
||||||
|
AC_ARG_ENABLE([hpke],
|
||||||
|
[AS_HELP_STRING([--enable-hpke],[Enable HKPE support (default: disabled)])],
|
||||||
|
[ ENABLED_HPKE=$enableval ],
|
||||||
|
[ ENABLED_HPKE=no ]
|
||||||
|
)
|
||||||
|
if test "$ENABLED_HPKE" = "yes"
|
||||||
|
then
|
||||||
|
AM_CFLAGS="$AM_CFLAGS -DHAVE_HPKE"
|
||||||
|
|
||||||
|
test "$enable_hkdf" = "" && enable_hkdf=yes
|
||||||
|
fi
|
||||||
|
|
||||||
# X9.63 KDF
|
# X9.63 KDF
|
||||||
AC_ARG_ENABLE([x963kdf],
|
AC_ARG_ENABLE([x963kdf],
|
||||||
[AS_HELP_STRING([--enable-x963kdf],[Enable X9.63 KDF support (default: disabled)])],
|
[AS_HELP_STRING([--enable-x963kdf],[Enable X9.63 KDF support (default: disabled)])],
|
||||||
|
@ -8450,6 +8484,7 @@ AM_CONDITIONAL([BUILD_PSA],[test "x$ENABLED_PSA" = "xyes"])
|
||||||
AM_CONDITIONAL([BUILD_DTLS13],[test "x$ENABLED_DTLS13" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
AM_CONDITIONAL([BUILD_DTLS13],[test "x$ENABLED_DTLS13" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||||
AM_CONDITIONAL([BUILD_QUIC],[test "x$ENABLED_QUIC" = "xyes"])
|
AM_CONDITIONAL([BUILD_QUIC],[test "x$ENABLED_QUIC" = "xyes"])
|
||||||
AM_CONDITIONAL([BUILD_DTLS_CID],[test "x$ENABLED_DTLS_CID" = "xyes"])
|
AM_CONDITIONAL([BUILD_DTLS_CID],[test "x$ENABLED_DTLS_CID" = "xyes"])
|
||||||
|
AM_CONDITIONAL([BUILD_HPKE],[test "x$ENABLED_HPKE" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||||
AM_CONDITIONAL([BUILD_DTLS],[test "x$ENABLED_DTLS" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
AM_CONDITIONAL([BUILD_DTLS],[test "x$ENABLED_DTLS" = "xyes" || test "x$ENABLED_USERSETTINGS" = "xyes"])
|
||||||
AM_CONDITIONAL([BUILD_MAXQ10XX],[test "x$ENABLED_MAXQ10XX" = "xyes"])
|
AM_CONDITIONAL([BUILD_MAXQ10XX],[test "x$ENABLED_MAXQ10XX" = "xyes"])
|
||||||
|
|
||||||
|
@ -8740,6 +8775,7 @@ echo " * PWDBASED: $ENABLED_PWDBASED"
|
||||||
echo " * scrypt: $ENABLED_SCRYPT"
|
echo " * scrypt: $ENABLED_SCRYPT"
|
||||||
echo " * wolfCrypt Only: $ENABLED_CRYPTONLY"
|
echo " * wolfCrypt Only: $ENABLED_CRYPTONLY"
|
||||||
echo " * HKDF: $ENABLED_HKDF"
|
echo " * HKDF: $ENABLED_HKDF"
|
||||||
|
echo " * HPKE: $ENABLED_HPKE"
|
||||||
echo " * X9.63 KDF: $ENABLED_X963KDF"
|
echo " * X9.63 KDF: $ENABLED_X963KDF"
|
||||||
echo " * MD4: $ENABLED_MD4"
|
echo " * MD4: $ENABLED_MD4"
|
||||||
echo " * PSK: $ENABLED_PSK"
|
echo " * PSK: $ENABLED_PSK"
|
||||||
|
|
|
@ -234,6 +234,9 @@ extern "C" {
|
||||||
#define HAVE_KEYING_MATERIAL
|
#define HAVE_KEYING_MATERIAL
|
||||||
#define WOLFSSL_HAVE_PRF
|
#define WOLFSSL_HAVE_PRF
|
||||||
|
|
||||||
|
/* Encrypted Client Hello */
|
||||||
|
#define HAVE_HPKE
|
||||||
|
#define HAVE_ECH
|
||||||
|
|
||||||
/* Non-Standard Algorithms (DG disabled) */
|
/* Non-Standard Algorithms (DG disabled) */
|
||||||
//#define HAVE_CAMELLIA
|
//#define HAVE_CAMELLIA
|
||||||
|
|
|
@ -509,6 +509,10 @@ if BUILD_ASN
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/asn.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/asn.c
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if BUILD_HPKE
|
||||||
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/hpke.c
|
||||||
|
endif
|
||||||
|
|
||||||
endif !BUILD_FIPS_RAND
|
endif !BUILD_FIPS_RAND
|
||||||
|
|
||||||
if BUILD_CODING
|
if BUILD_CODING
|
||||||
|
|
110
src/internal.c
110
src/internal.c
|
@ -2398,6 +2398,36 @@ void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data)
|
||||||
}
|
}
|
||||||
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
|
#endif /* HAVE_EX_DATA_CLEANUP_HOOKS */
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* free all ech configs in the list */
|
||||||
|
static void FreeEchConfigs(WOLFSSL_EchConfig* configs, void* heap)
|
||||||
|
{
|
||||||
|
WOLFSSL_EchConfig* working_config = configs;
|
||||||
|
WOLFSSL_EchConfig* next_config;
|
||||||
|
|
||||||
|
while (working_config != NULL) {
|
||||||
|
next_config = working_config->next;
|
||||||
|
|
||||||
|
XFREE(working_config->cipherSuites, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(working_config->publicName, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
if (working_config->raw != NULL)
|
||||||
|
XFREE(working_config->raw, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
if (working_config->receiverPrivkey != NULL) {
|
||||||
|
wc_HpkeFreeKey(NULL, working_config->kemId,
|
||||||
|
working_config->receiverPrivkey, heap);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFREE(working_config, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
working_config = next_config;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)heap;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* In case contexts are held in array and don't want to free actual ctx. */
|
/* In case contexts are held in array and don't want to free actual ctx. */
|
||||||
|
|
||||||
/* The allocations done in InitSSL_Ctx must be free'd with ctx->onHeapHint
|
/* The allocations done in InitSSL_Ctx must be free'd with ctx->onHeapHint
|
||||||
|
@ -2554,6 +2584,10 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
|
||||||
ctx->staticKELockInit = 0;
|
ctx->staticKELockInit = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
FreeEchConfigs(ctx->echConfigs, ctx->heap);
|
||||||
|
ctx->echConfigs = NULL;
|
||||||
#endif
|
#endif
|
||||||
(void)heapAtCTXInit;
|
(void)heapAtCTXInit;
|
||||||
}
|
}
|
||||||
|
@ -6538,6 +6572,71 @@ void FreeHandshakeHashes(WOLFSSL* ssl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy the hashes from source to a newly made destination return status */
|
||||||
|
int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source,
|
||||||
|
HS_Hashes** destination)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
HS_Hashes* tmpHashes;
|
||||||
|
|
||||||
|
if (source == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* save the original so we can put it back afterward */
|
||||||
|
tmpHashes = ssl->hsHashes;
|
||||||
|
ssl->hsHashes = NULL;
|
||||||
|
|
||||||
|
InitHandshakeHashes(ssl);
|
||||||
|
|
||||||
|
*destination = ssl->hsHashes;
|
||||||
|
ssl->hsHashes = tmpHashes;
|
||||||
|
|
||||||
|
/* now copy the source contents to the destination */
|
||||||
|
#ifndef NO_OLD_TLS
|
||||||
|
#ifndef NO_SHA
|
||||||
|
ret = wc_ShaCopy(&source->hashSha, &(*destination)->hashSha);
|
||||||
|
#endif
|
||||||
|
#ifndef NO_MD5
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Md5Copy(&source->hashMd5, &(*destination)->hashMd5);
|
||||||
|
#endif
|
||||||
|
#endif /* !NO_OLD_TLS */
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha256Copy(&source->hashSha256,
|
||||||
|
&(*destination)->hashSha256);
|
||||||
|
#endif
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha384Copy(&source->hashSha384,
|
||||||
|
&(*destination)->hashSha384);
|
||||||
|
#endif
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Sha512Copy(&source->hashSha512,
|
||||||
|
&(*destination)->hashSha512);
|
||||||
|
#endif
|
||||||
|
#if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \
|
||||||
|
!defined(WOLFSSL_NO_CLIENT_AUTH)
|
||||||
|
if (ret == 0 && source->messages != NULL) {
|
||||||
|
(*destination)->messages = (byte*)XMALLOC(source->length, ssl->heap,
|
||||||
|
DYNAMIC_TYPE_HASHES);
|
||||||
|
(*destination)->length = source->length;
|
||||||
|
(*destination)->prevLen = source->prevLen;
|
||||||
|
|
||||||
|
if ((*destination)->messages == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XMEMCPY((*destination)->messages, source->messages,
|
||||||
|
source->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* called if user attempts to re-use WOLFSSL object for a new session.
|
/* called if user attempts to re-use WOLFSSL object for a new session.
|
||||||
* For example wolfSSL_clear() is called then wolfSSL_connect or accept */
|
* For example wolfSSL_clear() is called then wolfSSL_connect or accept */
|
||||||
int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
|
||||||
|
@ -7505,6 +7604,17 @@ void SSL_ResourceFree(WOLFSSL* ssl)
|
||||||
ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret));
|
ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret));
|
||||||
ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
|
ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
FreeEchConfigs(ssl->echConfigs, ssl->heap);
|
||||||
|
ssl->echConfigs = NULL;
|
||||||
|
/* free the ech specific hashes */
|
||||||
|
ssl->hsHashes = ssl->hsHashesEch;
|
||||||
|
FreeHandshakeHashes(ssl);
|
||||||
|
ssl->options.useEch = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_HAVE_TLS_UNIQUE
|
#ifdef WOLFSSL_HAVE_TLS_UNIQUE
|
||||||
ForceZero(&ssl->clientFinished, TLS_FINISHED_SZ_MAX);
|
ForceZero(&ssl->clientFinished, TLS_FINISHED_SZ_MAX);
|
||||||
|
|
594
src/ssl.c
594
src/ssl.c
|
@ -222,6 +222,8 @@
|
||||||
#endif /* !WOLFSSL_NO_OPENSSL_RAND_CB */
|
#endif /* !WOLFSSL_NO_OPENSSL_RAND_CB */
|
||||||
#endif /* OPENSSL_EXTRA */
|
#endif /* OPENSSL_EXTRA */
|
||||||
|
|
||||||
|
#include <wolfssl/wolfcrypt/hpke.h>
|
||||||
|
|
||||||
#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC)
|
||||||
const WOLF_EC_NIST_NAME kNistCurves[] = {
|
const WOLF_EC_NIST_NAME kNistCurves[] = {
|
||||||
{XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1},
|
{XSTR_SIZEOF("P-192"), "P-192", NID_X9_62_prime192v1},
|
||||||
|
@ -260,6 +262,598 @@ const WOLF_EC_NIST_NAME kNistCurves[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* create the hpke key and ech config to send to clients */
|
||||||
|
int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
|
||||||
|
word16 kemId, word16 kdfId, word16 aeadId)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
word16 encLen = DHKEM_X25519_ENC_LEN;
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
Hpke* hpke = NULL;
|
||||||
|
WC_RNG* rng;
|
||||||
|
#else
|
||||||
|
Hpke hpke[1];
|
||||||
|
WC_RNG rng[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctx == NULL || publicName == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG);
|
||||||
|
if (rng == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
#endif
|
||||||
|
ret = wc_InitRng(rng);
|
||||||
|
if (ret != 0) {
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->echConfigs = (WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
|
||||||
|
ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (ctx->echConfigs == NULL)
|
||||||
|
ret = MEMORY_E;
|
||||||
|
else
|
||||||
|
XMEMSET(ctx->echConfigs, 0, sizeof(WOLFSSL_EchConfig));
|
||||||
|
|
||||||
|
/* set random config id */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_RNG_GenerateByte(rng, &ctx->echConfigs->configId);
|
||||||
|
|
||||||
|
/* if 0 is selected for algorithms use default, may change with draft */
|
||||||
|
if (kemId == 0)
|
||||||
|
kemId = DHKEM_X25519_HKDF_SHA256;
|
||||||
|
|
||||||
|
if (kdfId == 0)
|
||||||
|
kdfId = HKDF_SHA256;
|
||||||
|
|
||||||
|
if (aeadId == 0)
|
||||||
|
aeadId = HPKE_AES_128_GCM;
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* set the kem id */
|
||||||
|
ctx->echConfigs->kemId = kemId;
|
||||||
|
|
||||||
|
/* set the cipher suite, only 1 for now */
|
||||||
|
ctx->echConfigs->numCipherSuites = 1;
|
||||||
|
ctx->echConfigs->cipherSuites = (EchCipherSuite*)XMALLOC(
|
||||||
|
sizeof(EchCipherSuite), ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
if (ctx->echConfigs->cipherSuites == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ctx->echConfigs->cipherSuites[0].kdfId = kdfId;
|
||||||
|
ctx->echConfigs->cipherSuites[0].aeadId = aeadId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
if (ret == 0) {
|
||||||
|
hpke = (Hpke*)XMALLOC(sizeof(Hpke), ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (hpke == NULL)
|
||||||
|
ret = MEMORY_E;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeInit(hpke, kemId, kdfId, aeadId, ctx->heap);
|
||||||
|
|
||||||
|
/* generate the receiver private key */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeGenerateKeyPair(hpke, &ctx->echConfigs->receiverPrivkey,
|
||||||
|
rng);
|
||||||
|
|
||||||
|
/* done with RNG */
|
||||||
|
wc_FreeRng(rng);
|
||||||
|
|
||||||
|
/* serialize the receiver key */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeSerializePublicKey(hpke, ctx->echConfigs->receiverPrivkey,
|
||||||
|
ctx->echConfigs->receiverPubkey, &encLen);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
ctx->echConfigs->publicName = (char*)XMALLOC(XSTRLEN(publicName) + 1,
|
||||||
|
ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (ctx->echConfigs->publicName == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
XMEMCPY(ctx->echConfigs->publicName, publicName,
|
||||||
|
XSTRLEN(publicName) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
if (ctx->echConfigs) {
|
||||||
|
XFREE(ctx->echConfigs->cipherSuites, ctx->heap,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(ctx->echConfigs->publicName, ctx->heap,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(ctx->echConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
/* set to null to avoid double free in cleanup */
|
||||||
|
ctx->echConfigs = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = WOLFSSL_SUCCESS;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
XFREE(hpke, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the ech configs that the server context is using */
|
||||||
|
int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
|
||||||
|
word32* outputLen) {
|
||||||
|
if (ctx == NULL || outputLen == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* if we don't have ech configs */
|
||||||
|
if (ctx->echConfigs == NULL) {
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetEchConfigsEx(ctx->echConfigs, output, outputLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the ech config from base64 for our client ssl object, base64 is the
|
||||||
|
* format ech configs are sent using dns records */
|
||||||
|
int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
|
||||||
|
word32 echConfigs64Len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
|
||||||
|
byte* decodedConfigs;
|
||||||
|
|
||||||
|
if (ssl == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* already have ech configs */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
decodedConfigs = (byte*)XMALLOC(decodedLen, ssl->heap,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
if (decodedConfigs == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
|
||||||
|
decodedConfigs[decodedLen - 1] = 0;
|
||||||
|
|
||||||
|
/* decode the echConfigs */
|
||||||
|
ret = Base64_Decode((byte*)echConfigs64, echConfigs64Len,
|
||||||
|
decodedConfigs, &decodedLen);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = wolfSSL_SetEchConfigs(ssl, decodedConfigs, decodedLen);
|
||||||
|
|
||||||
|
XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set the ech config from a raw buffer, this is the format ech configs are
|
||||||
|
* sent using retry_configs from the ech server */
|
||||||
|
int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
|
||||||
|
word32 echConfigsLen)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int i;
|
||||||
|
int j;
|
||||||
|
word16 totalLength;
|
||||||
|
word16 version;
|
||||||
|
word16 length;
|
||||||
|
word16 hpkePubkeyLen;
|
||||||
|
word16 cipherSuitesLen;
|
||||||
|
word16 publicNameLen;
|
||||||
|
WOLFSSL_EchConfig* configList = NULL;
|
||||||
|
WOLFSSL_EchConfig* workingConfig = NULL;
|
||||||
|
WOLFSSL_EchConfig* lastConfig = NULL;
|
||||||
|
byte* echConfig = NULL;
|
||||||
|
|
||||||
|
if (ssl == NULL || echConfigs == NULL || echConfigsLen == 0)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* already have ech configs */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check that the total length is well formed */
|
||||||
|
ato16(echConfigs, &totalLength);
|
||||||
|
|
||||||
|
if (totalLength != echConfigsLen - 2) {
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip the total length uint16_t */
|
||||||
|
i = 2;
|
||||||
|
|
||||||
|
do {
|
||||||
|
echConfig = (byte*)echConfigs + i;
|
||||||
|
ato16(echConfig, &version);
|
||||||
|
ato16(echConfig + 2, &length);
|
||||||
|
|
||||||
|
/* if the version does not match */
|
||||||
|
if (version != TLSX_ECH) {
|
||||||
|
/* we hit the end of the configs */
|
||||||
|
if ( (word32)i + 2 >= echConfigsLen ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip this config, +4 for version and length */
|
||||||
|
i += length + 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if the length will overrun the buffer */
|
||||||
|
if ((word32)i + length + 4 > echConfigsLen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workingConfig == NULL) {
|
||||||
|
workingConfig =
|
||||||
|
(WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
configList = workingConfig;
|
||||||
|
workingConfig->next = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lastConfig = workingConfig;
|
||||||
|
workingConfig->next =
|
||||||
|
(WOLFSSL_EchConfig*)XMALLOC(sizeof(WOLFSSL_EchConfig),
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
workingConfig = workingConfig->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workingConfig == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMSET(workingConfig, 0, sizeof(WOLFSSL_EchConfig));
|
||||||
|
|
||||||
|
/* rawLen */
|
||||||
|
workingConfig->rawLen = length + 4;
|
||||||
|
|
||||||
|
/* raw body */
|
||||||
|
workingConfig->raw = (byte*)XMALLOC(workingConfig->rawLen,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (workingConfig->raw == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(workingConfig->raw, echConfig, workingConfig->rawLen);
|
||||||
|
|
||||||
|
/* skip over version and length */
|
||||||
|
echConfig += 4;
|
||||||
|
|
||||||
|
/* configId, 1 byte */
|
||||||
|
workingConfig->configId = *(echConfig);
|
||||||
|
echConfig++;
|
||||||
|
/* kemId, 2 bytes */
|
||||||
|
ato16(echConfig, &workingConfig->kemId);
|
||||||
|
echConfig += 2;
|
||||||
|
/* hpke public_key length, 2 bytes */
|
||||||
|
ato16(echConfig, &hpkePubkeyLen);
|
||||||
|
echConfig += 2;
|
||||||
|
/* hpke public_key */
|
||||||
|
XMEMCPY(workingConfig->receiverPubkey, echConfig, hpkePubkeyLen);
|
||||||
|
echConfig += hpkePubkeyLen;
|
||||||
|
/* cipherSuitesLen */
|
||||||
|
ato16(echConfig, &cipherSuitesLen);
|
||||||
|
|
||||||
|
workingConfig->cipherSuites = (EchCipherSuite*)XMALLOC(cipherSuitesLen,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (workingConfig->cipherSuites == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
echConfig += 2;
|
||||||
|
workingConfig->numCipherSuites = cipherSuitesLen / 4;
|
||||||
|
/* cipherSuites */
|
||||||
|
for (j = 0; j < workingConfig->numCipherSuites; j++) {
|
||||||
|
ato16(echConfig + j * 4, &workingConfig->cipherSuites[j].kdfId);
|
||||||
|
ato16(echConfig + j * 4 + 2,
|
||||||
|
&workingConfig->cipherSuites[j].aeadId);
|
||||||
|
}
|
||||||
|
echConfig += cipherSuitesLen;
|
||||||
|
/* publicNameLen */
|
||||||
|
ato16(echConfig, &publicNameLen);
|
||||||
|
workingConfig->publicName = (char*)XMALLOC(publicNameLen + 1,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (workingConfig->publicName == NULL) {
|
||||||
|
ret = MEMORY_E;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
echConfig += 2;
|
||||||
|
/* publicName */
|
||||||
|
XMEMCPY(workingConfig->publicName, echConfig, publicNameLen);
|
||||||
|
/* null terminated */
|
||||||
|
workingConfig->publicName[publicNameLen] = 0;
|
||||||
|
|
||||||
|
/* add length to go to next config, +4 for version and length */
|
||||||
|
i += length + 4;
|
||||||
|
|
||||||
|
/* check that we support this config */
|
||||||
|
for (j = 0; j < HPKE_SUPPORTED_KEM_LEN; j++) {
|
||||||
|
if (hpkeSupportedKem[j] == workingConfig->kemId)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we don't support the kem or at least one cipher suite */
|
||||||
|
if (j >= HPKE_SUPPORTED_KEM_LEN ||
|
||||||
|
EchConfigGetSupportedCipherSuite(workingConfig) < 0)
|
||||||
|
{
|
||||||
|
XFREE(workingConfig->cipherSuites, ssl->heap,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(workingConfig->publicName, ssl->heap,
|
||||||
|
DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(workingConfig->raw, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
workingConfig = lastConfig;
|
||||||
|
}
|
||||||
|
} while ((word32)i < echConfigsLen);
|
||||||
|
|
||||||
|
/* if we found valid configs */
|
||||||
|
if (ret == 0 && configList != NULL) {
|
||||||
|
ssl->options.useEch = 1;
|
||||||
|
ssl->echConfigs = configList;
|
||||||
|
|
||||||
|
return WOLFSSL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
workingConfig = configList;
|
||||||
|
|
||||||
|
while (workingConfig != NULL) {
|
||||||
|
lastConfig = workingConfig;
|
||||||
|
workingConfig = workingConfig->next;
|
||||||
|
|
||||||
|
XFREE(lastConfig->cipherSuites, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(lastConfig->publicName, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(lastConfig->raw, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
XFREE(lastConfig, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the raw ech config from our struct */
|
||||||
|
int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
word16 totalLen = 0;
|
||||||
|
|
||||||
|
if (config == NULL || (output == NULL && outputLen == NULL))
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* 2 for version */
|
||||||
|
totalLen += 2;
|
||||||
|
/* 2 for length */
|
||||||
|
totalLen += 2;
|
||||||
|
/* 1 for configId */
|
||||||
|
totalLen += 1;
|
||||||
|
/* 2 for kemId */
|
||||||
|
totalLen += 2;
|
||||||
|
/* 2 for hpke_len */
|
||||||
|
totalLen += 2;
|
||||||
|
|
||||||
|
/* hpke_pub_key */
|
||||||
|
switch (config->kemId) {
|
||||||
|
case DHKEM_P256_HKDF_SHA256:
|
||||||
|
totalLen += DHKEM_P256_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_P384_HKDF_SHA384:
|
||||||
|
totalLen += DHKEM_P384_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_P521_HKDF_SHA512:
|
||||||
|
totalLen += DHKEM_P521_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_X25519_HKDF_SHA256:
|
||||||
|
totalLen += DHKEM_X25519_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_X448_HKDF_SHA512:
|
||||||
|
totalLen += DHKEM_X448_ENC_LEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cipherSuitesLen */
|
||||||
|
totalLen += 2;
|
||||||
|
/* cipherSuites */
|
||||||
|
totalLen += config->numCipherSuites * 4;
|
||||||
|
/* public name len */
|
||||||
|
totalLen += 2;
|
||||||
|
|
||||||
|
/* public name */
|
||||||
|
totalLen += XSTRLEN(config->publicName);
|
||||||
|
/* trailing zeros */
|
||||||
|
totalLen += 2;
|
||||||
|
|
||||||
|
if (output == NULL) {
|
||||||
|
*outputLen = totalLen;
|
||||||
|
return LENGTH_ONLY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalLen > *outputLen) {
|
||||||
|
*outputLen = totalLen;
|
||||||
|
return INPUT_SIZE_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
c16toa(TLSX_ECH, output);
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
/* length - 4 for version and length itself */
|
||||||
|
c16toa(totalLen - 4, output);
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
/* configId */
|
||||||
|
*output = config->configId;
|
||||||
|
output++;
|
||||||
|
/* kemId */
|
||||||
|
c16toa(config->kemId, output);
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
/* length and key itself */
|
||||||
|
switch (config->kemId) {
|
||||||
|
case DHKEM_P256_HKDF_SHA256:
|
||||||
|
c16toa(DHKEM_P256_ENC_LEN, output);
|
||||||
|
output += 2;
|
||||||
|
XMEMCPY(output, config->receiverPubkey, DHKEM_P256_ENC_LEN);
|
||||||
|
output += DHKEM_P256_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_P384_HKDF_SHA384:
|
||||||
|
c16toa(DHKEM_P384_ENC_LEN, output);
|
||||||
|
output += 2;
|
||||||
|
XMEMCPY(output, config->receiverPubkey, DHKEM_P384_ENC_LEN);
|
||||||
|
output += DHKEM_P384_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_P521_HKDF_SHA512:
|
||||||
|
c16toa(DHKEM_P521_ENC_LEN, output);
|
||||||
|
output += 2;
|
||||||
|
XMEMCPY(output, config->receiverPubkey, DHKEM_P521_ENC_LEN);
|
||||||
|
output += DHKEM_P521_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_X25519_HKDF_SHA256:
|
||||||
|
c16toa(DHKEM_X25519_ENC_LEN, output);
|
||||||
|
output += 2;
|
||||||
|
XMEMCPY(output, config->receiverPubkey, DHKEM_X25519_ENC_LEN);
|
||||||
|
output += DHKEM_X25519_ENC_LEN;
|
||||||
|
break;
|
||||||
|
case DHKEM_X448_HKDF_SHA512:
|
||||||
|
c16toa(DHKEM_X448_ENC_LEN, output);
|
||||||
|
output += 2;
|
||||||
|
XMEMCPY(output, config->receiverPubkey, DHKEM_X448_ENC_LEN);
|
||||||
|
output += DHKEM_X448_ENC_LEN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cipherSuites len */
|
||||||
|
c16toa(config->numCipherSuites * 4, output);
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
/* cipherSuites */
|
||||||
|
for (i = 0; i < config->numCipherSuites; i++) {
|
||||||
|
c16toa(config->cipherSuites[i].kdfId, output);
|
||||||
|
output += 2;
|
||||||
|
c16toa(config->cipherSuites[i].aeadId, output);
|
||||||
|
output += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* publicName len */
|
||||||
|
c16toa(XSTRLEN(config->publicName), output);
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
/* publicName */
|
||||||
|
XMEMCPY(output, config->publicName,
|
||||||
|
XSTRLEN(config->publicName));
|
||||||
|
output += XSTRLEN(config->publicName);
|
||||||
|
|
||||||
|
/* terminating zeros */
|
||||||
|
c16toa(0, output);
|
||||||
|
/* output += 2; */
|
||||||
|
|
||||||
|
*outputLen = totalLen;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wrapper function to get ech configs from application code */
|
||||||
|
int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* output, word32* outputLen)
|
||||||
|
{
|
||||||
|
if (ssl == NULL || outputLen == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* if we don't have ech configs */
|
||||||
|
if (ssl->options.useEch != 1) {
|
||||||
|
return WOLFSSL_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetEchConfigsEx(ssl->echConfigs, output, outputLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the raw ech configs from our linked list of ech config structs */
|
||||||
|
int GetEchConfigsEx(WOLFSSL_EchConfig* configs, byte* output, word32* outputLen)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
WOLFSSL_EchConfig* workingConfig = NULL;
|
||||||
|
byte* outputStart = output;
|
||||||
|
word32 totalLen = 2;
|
||||||
|
word32 workingOutputLen;
|
||||||
|
|
||||||
|
if (configs == NULL || outputLen == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
workingOutputLen = *outputLen - totalLen;
|
||||||
|
|
||||||
|
/* skip over total length which we fill in later */
|
||||||
|
if (output != NULL)
|
||||||
|
output += 2;
|
||||||
|
|
||||||
|
workingConfig = configs;
|
||||||
|
|
||||||
|
while (workingConfig != NULL) {
|
||||||
|
/* get this config */
|
||||||
|
ret = GetEchConfig(workingConfig, output, &workingOutputLen);
|
||||||
|
|
||||||
|
if (output != NULL)
|
||||||
|
output += workingOutputLen;
|
||||||
|
|
||||||
|
/* add this config's length to the total length */
|
||||||
|
totalLen += workingOutputLen;
|
||||||
|
|
||||||
|
if (totalLen > *outputLen)
|
||||||
|
workingOutputLen = 0;
|
||||||
|
else
|
||||||
|
workingOutputLen = *outputLen - totalLen;
|
||||||
|
|
||||||
|
/* only error we break on, other 2 we need to keep finding length */
|
||||||
|
if (ret == BAD_FUNC_ARG)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
workingConfig = workingConfig->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output == NULL) {
|
||||||
|
*outputLen = totalLen;
|
||||||
|
return LENGTH_ONLY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalLen > *outputLen) {
|
||||||
|
*outputLen = totalLen;
|
||||||
|
return INPUT_SIZE_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* total size -2 for size itself */
|
||||||
|
c16toa(totalLen - 2, outputStart);
|
||||||
|
|
||||||
|
*outputLen = totalLen;
|
||||||
|
|
||||||
|
return WOLFSSL_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_ECH */
|
||||||
|
|
||||||
|
|
||||||
#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_SCEPROTECT)
|
#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_SCEPROTECT)
|
||||||
#include <wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h>
|
#include <wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
519
src/tls13.c
519
src/tls13.c
|
@ -165,6 +165,23 @@ static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 ";
|
||||||
static const byte dtls13ProtocolLabel[DTLS13_PROTOCOL_LABEL_SZ + 1] = "dtls13";
|
static const byte dtls13ProtocolLabel[DTLS13_PROTOCOL_LABEL_SZ + 1] = "dtls13";
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
#define ECH_ACCEPT_CONFIRMATION_SZ 8
|
||||||
|
#define ECH_ACCEPT_CONFIRMATION_LABEL_SZ 23
|
||||||
|
static const byte
|
||||||
|
echAcceptConfirmationLabel[ECH_ACCEPT_CONFIRMATION_LABEL_SZ + 1] =
|
||||||
|
"ech accept confirmation";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef NO_CERTS
|
||||||
|
#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \
|
||||||
|
defined(HAVE_ED448) || defined(HAVE_PQC)
|
||||||
|
|
||||||
|
static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Expand data using HMAC, salt and label and info.
|
/* Expand data using HMAC, salt and label and info.
|
||||||
* TLS v1.3 defines this function. Use callback if available.
|
* TLS v1.3 defines this function. Use callback if available.
|
||||||
*
|
*
|
||||||
|
@ -253,7 +270,6 @@ PRAGMA_GCC_DIAG_POP;
|
||||||
}
|
}
|
||||||
#endif /* !HAVE_FIPS || !wc_Tls13_HKDF_Expand_Label */
|
#endif /* !HAVE_FIPS || !wc_Tls13_HKDF_Expand_Label */
|
||||||
|
|
||||||
|
|
||||||
/* Derive a key from a message.
|
/* Derive a key from a message.
|
||||||
*
|
*
|
||||||
* ssl The SSL/TLS object.
|
* ssl The SSL/TLS object.
|
||||||
|
@ -3830,6 +3846,71 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* returns the index of the first supported cipher suite, -1 if none */
|
||||||
|
int EchConfigGetSupportedCipherSuite(WOLFSSL_EchConfig* config)
|
||||||
|
{
|
||||||
|
int i, j, supported = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < config->numCipherSuites; i++) {
|
||||||
|
supported = 0;
|
||||||
|
|
||||||
|
for (j = 0; j < HPKE_SUPPORTED_KDF_LEN; j++) {
|
||||||
|
if (config->cipherSuites[i].kdfId == hpkeSupportedKdf[j])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j < HPKE_SUPPORTED_KDF_LEN)
|
||||||
|
for (j = 0; j < HPKE_SUPPORTED_AEAD_LEN; j++) {
|
||||||
|
if (config->cipherSuites[i].aeadId == hpkeSupportedAead[j]) {
|
||||||
|
supported = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supported)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* returns status after we hash the ech inner */
|
||||||
|
static int EchHashHelloInner(WOLFSSL* ssl, WOLFSSL_ECH* ech)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
HS_Hashes* tmpHashes;
|
||||||
|
byte falseHeader[HANDSHAKE_HEADER_SZ];
|
||||||
|
|
||||||
|
if (ssl == NULL || ech == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
/* switch hsHashes to the ech version */
|
||||||
|
InitHandshakeHashesAndCopy(ssl, ssl->hsHashes, &ssl->hsHashesEch);
|
||||||
|
|
||||||
|
/* swap hsHashes so the regular hash functions work */
|
||||||
|
tmpHashes = ssl->hsHashes;
|
||||||
|
ssl->hsHashes = ssl->hsHashesEch;
|
||||||
|
|
||||||
|
/* do the handshake header then the body */
|
||||||
|
AddTls13HandShakeHeader(falseHeader,
|
||||||
|
ech->innerClientHelloLen - ech->paddingLen - ech->hpke->Nt, 0, 0,
|
||||||
|
client_hello, ssl);
|
||||||
|
ret = HashRaw(ssl, falseHeader, HANDSHAKE_HEADER_SZ);
|
||||||
|
|
||||||
|
/* hash the body */
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = HashRaw(ssl, ech->innerClientHello,
|
||||||
|
ech->innerClientHelloLen - ech->paddingLen - ech->hpke->Nt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* swap hsHashes back */
|
||||||
|
ssl->hsHashes = tmpHashes;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* handle generation of TLS 1.3 client_hello (1) */
|
/* handle generation of TLS 1.3 client_hello (1) */
|
||||||
/* Send a ClientHello message to the server.
|
/* Send a ClientHello message to the server.
|
||||||
* Include the information required to start a handshake with servers using
|
* Include the information required to start a handshake with servers using
|
||||||
|
@ -3845,6 +3926,11 @@ typedef struct Sch13Args {
|
||||||
word32 idx;
|
word32 idx;
|
||||||
int sendSz;
|
int sendSz;
|
||||||
word16 length;
|
word16 length;
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
int clientRandomOffset;
|
||||||
|
int preXLength;
|
||||||
|
WOLFSSL_ECH* ech;
|
||||||
|
#endif
|
||||||
} Sch13Args;
|
} Sch13Args;
|
||||||
|
|
||||||
int SendTls13ClientHello(WOLFSSL* ssl)
|
int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
|
@ -3859,7 +3945,6 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
byte major, tls12minor;
|
byte major, tls12minor;
|
||||||
const Suites* suites;
|
const Suites* suites;
|
||||||
|
|
||||||
|
|
||||||
WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
|
WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND);
|
||||||
WOLFSSL_ENTER("SendTls13ClientHello");
|
WOLFSSL_ENTER("SendTls13ClientHello");
|
||||||
|
|
||||||
|
@ -4018,6 +4103,38 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* find length of outer and inner */
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
TLSX* echX = TLSX_Find(ssl->extensions, TLSX_ECH);
|
||||||
|
if (echX == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
args->ech = (WOLFSSL_ECH*)echX->data;
|
||||||
|
if (args->ech == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* set the type to inner */
|
||||||
|
args->ech->type = ECH_TYPE_INNER;
|
||||||
|
args->preXLength = args->length;
|
||||||
|
|
||||||
|
/* get size for inner */
|
||||||
|
ret = TLSX_GetRequestSize(ssl, client_hello, &args->length);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* set the type to outer */
|
||||||
|
args->ech->type = 0;
|
||||||
|
/* set innerClientHelloLen to ClientHelloInner + padding + tag */
|
||||||
|
args->ech->paddingLen = 31 - ((args->length - 1) % 32);
|
||||||
|
args->ech->innerClientHelloLen = args->length +
|
||||||
|
args->ech->paddingLen + args->ech->hpke->Nt;
|
||||||
|
/* set the length back to before we computed ClientHelloInner size */
|
||||||
|
args->length = args->preXLength;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Include length of TLS extensions. */
|
/* Include length of TLS extensions. */
|
||||||
ret = TLSX_GetRequestSize(ssl, client_hello, &args->length);
|
ret = TLSX_GetRequestSize(ssl, client_hello, &args->length);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
|
@ -4063,6 +4180,11 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN);
|
XMEMCPY(args->output + args->idx, ssl->arrays->clientRandom, RAN_LEN);
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
args->clientRandomOffset = args->idx;
|
||||||
|
#endif
|
||||||
|
|
||||||
args->idx += RAN_LEN;
|
args->idx += RAN_LEN;
|
||||||
|
|
||||||
if (ssl->session->sessionIDSz > 0) {
|
if (ssl->session->sessionIDSz > 0) {
|
||||||
|
@ -4124,14 +4246,78 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
args->output[args->idx++] = COMP_LEN;
|
args->output[args->idx++] = COMP_LEN;
|
||||||
args->output[args->idx++] = NO_COMPRESSION;
|
args->output[args->idx++] = NO_COMPRESSION;
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* write inner then outer */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
/* set the type to inner */
|
||||||
|
args->ech->type = ECH_TYPE_INNER;
|
||||||
|
|
||||||
|
/* allocate the inner */
|
||||||
|
args->ech->innerClientHello =
|
||||||
|
(byte*)XMALLOC(args->ech->innerClientHelloLen - args->ech->hpke->Nt,
|
||||||
|
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (args->ech->innerClientHello == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
|
||||||
|
/* set the padding bytes to 0 */
|
||||||
|
XMEMSET(args->ech->innerClientHello + args->ech->innerClientHelloLen -
|
||||||
|
args->ech->hpke->Nt - args->ech->paddingLen, 0,
|
||||||
|
args->ech->paddingLen);
|
||||||
|
|
||||||
|
/* copy the client hello to the ech innerClientHello, exclude record */
|
||||||
|
/* and handshake headers */
|
||||||
|
XMEMCPY(args->ech->innerClientHello,
|
||||||
|
args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ,
|
||||||
|
args->idx - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ));
|
||||||
|
|
||||||
|
/* copy the client random to inner */
|
||||||
|
XMEMCPY(ssl->arrays->clientRandomInner, ssl->arrays->clientRandom,
|
||||||
|
RAN_LEN);
|
||||||
|
|
||||||
|
/* change the outer client random */
|
||||||
|
ret = wc_RNG_GenerateBlock(ssl->rng, args->output +
|
||||||
|
args->clientRandomOffset, RAN_LEN);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* copy the new client random */
|
||||||
|
XMEMCPY(ssl->arrays->clientRandom, args->output +
|
||||||
|
args->clientRandomOffset, RAN_LEN);
|
||||||
|
|
||||||
|
/* write the extensions for inner */
|
||||||
|
args->length = 0;
|
||||||
|
ret = TLSX_WriteRequest(ssl, args->ech->innerClientHello + args->idx -
|
||||||
|
(RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ), client_hello,
|
||||||
|
&args->length);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* set the type to outer */
|
||||||
|
args->ech->type = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Write out extensions for a request. */
|
/* Write out extensions for a request. */
|
||||||
args->length = 0;
|
args->length = 0;
|
||||||
ret = TLSX_WriteRequest(ssl, args->output + args->idx, client_hello,
|
ret = TLSX_WriteRequest(ssl, args->output + args->idx, client_hello,
|
||||||
&args->length);
|
&args->length);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
args->idx += args->length;
|
args->idx += args->length;
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* encrypt and pack the ech innerClientHello */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
ret = TLSX_FinalizeEch(args->ech,
|
||||||
|
args->output + RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ,
|
||||||
|
args->sendSz - (RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ));
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)
|
||||||
/* Resumption has a specific set of extensions and binder is calculated
|
/* Resumption has a specific set of extensions and binder is calculated
|
||||||
* for each identity.
|
* for each identity.
|
||||||
|
@ -4141,7 +4327,7 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef WOLFSSL_DTLS13
|
#ifdef WOLFSSL_DTLS13
|
||||||
if (ssl->options.dtls)
|
if (ssl->options.dtls)
|
||||||
ret = Dtls13HashHandshake(ssl,
|
ret = Dtls13HashHandshake(ssl,
|
||||||
|
@ -4149,8 +4335,19 @@ int SendTls13ClientHello(WOLFSSL* ssl)
|
||||||
(word16)args->idx - Dtls13GetRlHeaderLength(ssl, 0));
|
(word16)args->idx - Dtls13GetRlHeaderLength(ssl, 0));
|
||||||
else
|
else
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
|
{
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* compute the inner hash */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
ret = EchHashHelloInner(ssl, args->ech);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* compute the outer hash */
|
||||||
|
if (ret == 0)
|
||||||
ret = HashOutput(ssl, args->output, args->idx, 0);
|
ret = HashOutput(ssl, args->output, args->idx, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -4236,6 +4433,233 @@ static int Dtls13DoDowngrade(WOLFSSL* ssl)
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSL_DTLS13 && !WOLFSSL_NO_CLIENT*/
|
#endif /* WOLFSSL_DTLS13 && !WOLFSSL_NO_CLIENT*/
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* check if the server accepted ech or not */
|
||||||
|
static int EchCheckAcceptance(WOLFSSL* ssl, const byte* input,
|
||||||
|
int serverRandomOffset, int helloSz)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int digestType;
|
||||||
|
int digestSize;
|
||||||
|
HS_Hashes* tmpHashes;
|
||||||
|
HS_Hashes* acceptHashes;
|
||||||
|
byte zeros[WC_MAX_DIGEST_SIZE] = {0};
|
||||||
|
byte transcriptEchConf[WC_MAX_DIGEST_SIZE];
|
||||||
|
byte expandLabelPrk[WC_MAX_DIGEST_SIZE];
|
||||||
|
byte acceptConfirmation[ECH_ACCEPT_CONFIRMATION_SZ];
|
||||||
|
|
||||||
|
/* copy ech hashes to accept */
|
||||||
|
ret = InitHandshakeHashesAndCopy(ssl, ssl->hsHashesEch, &acceptHashes);
|
||||||
|
|
||||||
|
/* swap hsHashes to acceptHashes */
|
||||||
|
tmpHashes = ssl->hsHashes;
|
||||||
|
ssl->hsHashes = acceptHashes;
|
||||||
|
|
||||||
|
/* hash up to the last 8 bytes */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, input, serverRandomOffset + RAN_LEN -
|
||||||
|
ECH_ACCEPT_CONFIRMATION_SZ);
|
||||||
|
|
||||||
|
/* hash 8 zeros */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, zeros, ECH_ACCEPT_CONFIRMATION_SZ);
|
||||||
|
|
||||||
|
/* hash the rest of the hello */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, input + serverRandomOffset + RAN_LEN,
|
||||||
|
helloSz + HANDSHAKE_HEADER_SZ - (serverRandomOffset + RAN_LEN));
|
||||||
|
|
||||||
|
/* get the modified transcript hash */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = GetMsgHash(ssl, transcriptEchConf);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
/* pick the right type and size based on mac_algorithm */
|
||||||
|
if (ret == 0)
|
||||||
|
switch (ssl->specs.mac_algorithm) {
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case sha256_mac:
|
||||||
|
digestType = WC_SHA256;
|
||||||
|
digestSize = WC_SHA256_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case sha384_mac:
|
||||||
|
digestType = WC_SHA384;
|
||||||
|
digestSize = WC_SHA384_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
#ifdef WOLFSSL_TLS13_SHA512
|
||||||
|
case sha512_mac:
|
||||||
|
digestType = WC_SHA512;
|
||||||
|
digestSize = WC_SHA512_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_TLS13_SHA512 */
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract clientRandomInner with a key of all zeros */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HKDF_Extract(digestType, zeros, digestSize,
|
||||||
|
ssl->arrays->clientRandomInner, RAN_LEN, expandLabelPrk);
|
||||||
|
|
||||||
|
/* tls expand with the confirmation label */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Tls13_HKDF_Expand_Label(acceptConfirmation,
|
||||||
|
ECH_ACCEPT_CONFIRMATION_SZ,
|
||||||
|
expandLabelPrk, digestSize, tls13ProtocolLabel,
|
||||||
|
TLS13_PROTOCOL_LABEL_SZ, echAcceptConfirmationLabel,
|
||||||
|
ECH_ACCEPT_CONFIRMATION_LABEL_SZ, transcriptEchConf, digestSize,
|
||||||
|
digestType);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
/* last 8 bytes should match our expand output */
|
||||||
|
ret = XMEMCMP(acceptConfirmation,
|
||||||
|
ssl->arrays->serverRandom + RAN_LEN - ECH_ACCEPT_CONFIRMATION_SZ,
|
||||||
|
ECH_ACCEPT_CONFIRMATION_SZ);
|
||||||
|
|
||||||
|
/* ech accepted */
|
||||||
|
if (ret == 0) {
|
||||||
|
/* use the inner random for client random */
|
||||||
|
XMEMCPY(ssl->arrays->clientRandom, ssl->arrays->clientRandomInner,
|
||||||
|
RAN_LEN);
|
||||||
|
|
||||||
|
/* switch back to original hsHashes */
|
||||||
|
ssl->hsHashes = tmpHashes;
|
||||||
|
|
||||||
|
/* free hsHashes */
|
||||||
|
FreeHandshakeHashes(ssl);
|
||||||
|
|
||||||
|
/* set the final hsHashes to the ech hashes */
|
||||||
|
tmpHashes = ssl->hsHashesEch;
|
||||||
|
|
||||||
|
/* set hsHashesEch to NULL to avoid double free */
|
||||||
|
ssl->hsHashesEch = NULL;
|
||||||
|
}
|
||||||
|
/* ech rejected */
|
||||||
|
else {
|
||||||
|
/* switch to hsHashesEch */
|
||||||
|
ssl->hsHashes = ssl->hsHashesEch;
|
||||||
|
|
||||||
|
/* free ech hashes */
|
||||||
|
FreeHandshakeHashes(ssl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* continue with outer if we failed to verify ech was accepted */
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* switch to acceptHashes */
|
||||||
|
ssl->hsHashes = acceptHashes;
|
||||||
|
|
||||||
|
/* free acceptHashes */
|
||||||
|
FreeHandshakeHashes(ssl);
|
||||||
|
|
||||||
|
ssl->hsHashes = tmpHashes;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* replace the last 8 bytes of the server random with the ech acceptance
|
||||||
|
* parameter, return status */
|
||||||
|
static int EchWriteAcceptance(WOLFSSL* ssl, byte* output,
|
||||||
|
int serverRandomOffset, int helloSz)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int digestType;
|
||||||
|
int digestSize;
|
||||||
|
HS_Hashes* tmpHashes;
|
||||||
|
HS_Hashes* acceptHashes;
|
||||||
|
byte zeros[WC_MAX_DIGEST_SIZE] = {0};
|
||||||
|
byte transcriptEchConf[WC_MAX_DIGEST_SIZE];
|
||||||
|
byte expandLabelPrk[WC_MAX_DIGEST_SIZE];
|
||||||
|
|
||||||
|
/* copy ech hashes to accept */
|
||||||
|
ret = InitHandshakeHashesAndCopy(ssl, ssl->hsHashes, &acceptHashes);
|
||||||
|
|
||||||
|
/* swap hsHashes to acceptHashes */
|
||||||
|
tmpHashes = ssl->hsHashes;
|
||||||
|
ssl->hsHashes = acceptHashes;
|
||||||
|
|
||||||
|
/* hash up to the last 8 bytes */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, output, serverRandomOffset + RAN_LEN -
|
||||||
|
ECH_ACCEPT_CONFIRMATION_SZ);
|
||||||
|
|
||||||
|
/* hash 8 zeros */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, zeros, ECH_ACCEPT_CONFIRMATION_SZ);
|
||||||
|
|
||||||
|
/* hash the rest of the hello */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashRaw(ssl, output + serverRandomOffset + RAN_LEN,
|
||||||
|
helloSz - (serverRandomOffset + RAN_LEN));
|
||||||
|
|
||||||
|
/* get the modified transcript hash */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = GetMsgHash(ssl, transcriptEchConf);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
/* pick the right type and size based on mac_algorithm */
|
||||||
|
if (ret == 0)
|
||||||
|
switch (ssl->specs.mac_algorithm) {
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
case sha256_mac:
|
||||||
|
digestType = WC_SHA256;
|
||||||
|
digestSize = WC_SHA256_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* !NO_SHA256 */
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
case sha384_mac:
|
||||||
|
digestType = WC_SHA384;
|
||||||
|
digestSize = WC_SHA384_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_SHA384 */
|
||||||
|
#ifdef WOLFSSL_TLS13_SHA512
|
||||||
|
case sha512_mac:
|
||||||
|
digestType = WC_SHA512;
|
||||||
|
digestSize = WC_SHA512_DIGEST_SIZE;
|
||||||
|
break;
|
||||||
|
#endif /* WOLFSSL_TLS13_SHA512 */
|
||||||
|
default:
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* extract clientRandom with a key of all zeros */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HKDF_Extract(digestType, zeros, digestSize,
|
||||||
|
ssl->arrays->clientRandom, RAN_LEN, expandLabelPrk);
|
||||||
|
|
||||||
|
/* tls expand with the confirmation label */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_Tls13_HKDF_Expand_Label(
|
||||||
|
output + serverRandomOffset + RAN_LEN - ECH_ACCEPT_CONFIRMATION_SZ,
|
||||||
|
ECH_ACCEPT_CONFIRMATION_SZ,
|
||||||
|
expandLabelPrk, digestSize, tls13ProtocolLabel,
|
||||||
|
TLS13_PROTOCOL_LABEL_SZ, echAcceptConfirmationLabel,
|
||||||
|
ECH_ACCEPT_CONFIRMATION_LABEL_SZ, transcriptEchConf, digestSize,
|
||||||
|
digestType);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
XMEMCPY(ssl->arrays->serverRandom, output + serverRandomOffset,
|
||||||
|
RAN_LEN);
|
||||||
|
|
||||||
|
/* free acceptHashes */
|
||||||
|
FreeHandshakeHashes(ssl);
|
||||||
|
|
||||||
|
ssl->hsHashes = tmpHashes;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
|
/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */
|
||||||
/* Handle the ServerHello message from the server.
|
/* Handle the ServerHello message from the server.
|
||||||
* Only a client will receive this message.
|
* Only a client will receive this message.
|
||||||
|
@ -4256,6 +4680,9 @@ typedef struct Dsh13Args {
|
||||||
word16 totalExtSz;
|
word16 totalExtSz;
|
||||||
byte sessIdSz;
|
byte sessIdSz;
|
||||||
byte extMsgType;
|
byte extMsgType;
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
int serverRandomOffset;
|
||||||
|
#endif
|
||||||
} Dsh13Args;
|
} Dsh13Args;
|
||||||
|
|
||||||
int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||||
|
@ -4403,6 +4830,9 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||||
|
|
||||||
/* Server random - keep for debugging. */
|
/* Server random - keep for debugging. */
|
||||||
XMEMCPY(ssl->arrays->serverRandom, input + args->idx, RAN_LEN);
|
XMEMCPY(ssl->arrays->serverRandom, input + args->idx, RAN_LEN);
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
args->serverRandomOffset = args->idx;
|
||||||
|
#endif
|
||||||
args->idx += RAN_LEN;
|
args->idx += RAN_LEN;
|
||||||
|
|
||||||
/* Session id */
|
/* Session id */
|
||||||
|
@ -4685,6 +5115,16 @@ int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||||
ret = SetCipherSpecs(ssl);
|
ret = SetCipherSpecs(ssl);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* check for acceptConfirmation and HashInput with 8 0 bytes */
|
||||||
|
if (ssl->options.useEch == 1) {
|
||||||
|
ret = EchCheckAcceptance(ssl, input, args->serverRandomOffset, helloSz);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_NULL_CIPHER
|
#ifdef HAVE_NULL_CIPHER
|
||||||
if (ssl->options.cipherSuite0 == ECC_BYTE &&
|
if (ssl->options.cipherSuite0 == ECC_BYTE &&
|
||||||
(ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
|
(ssl->options.cipherSuite == TLS_SHA256_SHA256 ||
|
||||||
|
@ -5829,6 +6269,10 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||||
#else
|
#else
|
||||||
Dch13Args args[1];
|
Dch13Args args[1];
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
word32 echInOutIdx;
|
||||||
|
TLSX* echX = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
|
WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO);
|
||||||
WOLFSSL_ENTER("DoTls13ClientHello");
|
WOLFSSL_ENTER("DoTls13ClientHello");
|
||||||
|
@ -6042,12 +6486,31 @@ int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx,
|
||||||
if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
|
if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0)
|
||||||
goto exit_dch;
|
goto exit_dch;
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
if (ssl->ctx->echConfigs != NULL) {
|
||||||
|
/* save the start of the buffer so we can use it when parsing ech */
|
||||||
|
echX = TLSX_Find(ssl->extensions, TLSX_ECH);
|
||||||
|
|
||||||
|
if (echX == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
((WOLFSSL_ECH*)echX->data)->aad = input + HANDSHAKE_HEADER_SZ;
|
||||||
|
((WOLFSSL_ECH*)echX->data)->aadLen = helloSz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Parse extensions */
|
/* Parse extensions */
|
||||||
if ((ret = TLSX_Parse(ssl, input + args->idx, totalExtSz, client_hello,
|
if ((ret = TLSX_Parse(ssl, input + args->idx, totalExtSz, client_hello,
|
||||||
args->clSuites))) {
|
args->clSuites))) {
|
||||||
goto exit_dch;
|
goto exit_dch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* jump to the end to clean things up */
|
||||||
|
if (echX != NULL && ((WOLFSSL_ECH*)echX->data)->state == ECH_WRITE_NONE)
|
||||||
|
goto exit_dch;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_SNI
|
#ifdef HAVE_SNI
|
||||||
if ((ret = SNI_Callback(ssl)) != 0)
|
if ((ret = SNI_Callback(ssl)) != 0)
|
||||||
goto exit_dch;
|
goto exit_dch;
|
||||||
|
@ -6282,6 +6745,27 @@ exit_dch:
|
||||||
WOLFSSL_ERROR_VERBOSE(ret);
|
WOLFSSL_ERROR_VERBOSE(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
/* do the hello again with the inner */
|
||||||
|
if (echX != NULL && ((WOLFSSL_ECH*)echX->data)->state == ECH_WRITE_NONE) {
|
||||||
|
/* reset the idx */
|
||||||
|
echInOutIdx = args->begin;
|
||||||
|
|
||||||
|
/* add the header to the inner hello */
|
||||||
|
AddTls13HandShakeHeader(((WOLFSSL_ECH*)echX->data)->innerClientHello,
|
||||||
|
((WOLFSSL_ECH*)echX->data)->innerClientHelloLen, 0, 0,
|
||||||
|
client_hello, ssl);
|
||||||
|
|
||||||
|
ret = DoTls13ClientHello(ssl,
|
||||||
|
((WOLFSSL_ECH*)echX->data)->innerClientHello,
|
||||||
|
&echInOutIdx, ((WOLFSSL_ECH*)echX->data)->innerClientHelloLen);
|
||||||
|
|
||||||
|
/* inner hello succeeded, consider this handshake message processed */
|
||||||
|
if (ret == 0)
|
||||||
|
*inOutIdx = args->begin + helloSz;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6299,6 +6783,10 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
||||||
word16 length;
|
word16 length;
|
||||||
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ;
|
||||||
int sendSz;
|
int sendSz;
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
TLSX* echX = NULL;
|
||||||
|
word32 serverRandomOffset;
|
||||||
|
#endif
|
||||||
|
|
||||||
WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
|
WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND);
|
||||||
WOLFSSL_ENTER("SendTls13ServerHello");
|
WOLFSSL_ENTER("SendTls13ServerHello");
|
||||||
|
@ -6350,6 +6838,10 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
||||||
XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
|
XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
serverRandomOffset = idx;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Store in SSL for debugging. */
|
/* Store in SSL for debugging. */
|
||||||
XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
|
XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN);
|
||||||
idx += RAN_LEN;
|
idx += RAN_LEN;
|
||||||
|
@ -6401,7 +6893,26 @@ int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType)
|
||||||
else
|
else
|
||||||
#endif /* WOLFSSL_DTLS13 */
|
#endif /* WOLFSSL_DTLS13 */
|
||||||
{
|
{
|
||||||
ret = HashOutput(ssl, output, sendSz, 0);
|
#if defined(HAVE_ECH)
|
||||||
|
if (ssl->ctx->echConfigs != NULL) {
|
||||||
|
echX = TLSX_Find(ssl->extensions, TLSX_ECH);
|
||||||
|
|
||||||
|
if (echX == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* replace the last 8 bytes of server random with the accept */
|
||||||
|
if (((WOLFSSL_ECH*)echX->data)->state == ECH_PARSED_INTERNAL) {
|
||||||
|
ret = EchWriteAcceptance(ssl, output + RECORD_HEADER_SZ,
|
||||||
|
serverRandomOffset - RECORD_HEADER_SZ,
|
||||||
|
sendSz - RECORD_HEADER_SZ);
|
||||||
|
|
||||||
|
/* remove ech so we don't keep sending it in write */
|
||||||
|
TLSX_Remove(&ssl->extensions, TLSX_ECH, ssl->heap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (ret == 0)
|
||||||
|
ret = HashOutput(ssl, output, sendSz, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
248
tests/api.c
248
tests/api.c
|
@ -340,7 +340,8 @@
|
||||||
#if (defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN)) || \
|
#if (defined(SESSION_CERTS) && defined(TEST_PEER_CERT_CHAIN)) || \
|
||||||
defined(HAVE_SESSION_TICKET) || (defined(OPENSSL_EXTRA) && \
|
defined(HAVE_SESSION_TICKET) || (defined(OPENSSL_EXTRA) && \
|
||||||
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \
|
defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN)) || \
|
||||||
defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS)
|
defined(WOLFSSL_TEST_STATIC_BUILD) || defined(WOLFSSL_DTLS) || \
|
||||||
|
defined(HAVE_ECH)
|
||||||
/* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT,
|
/* for testing SSL_get_peer_cert_chain, or SESSION_TICKET_HINT_DEFAULT,
|
||||||
* for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence
|
* for setting authKeyIdSrc in WOLFSSL_X509, or testing DTLS sequence
|
||||||
* number tracking */
|
* number tracking */
|
||||||
|
@ -8542,51 +8543,61 @@ static int test_wolfSSL_UseSNI_connection(void)
|
||||||
server_cb.devId = testDevId;
|
server_cb.devId = testDevId;
|
||||||
|
|
||||||
/* success case at ctx */
|
/* success case at ctx */
|
||||||
|
printf("success case at ctx\n");
|
||||||
client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = use_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching;
|
server_cb.ctx_ready = use_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* success case at ssl */
|
/* success case at ssl */
|
||||||
|
printf("success case at ssl\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_SNI_at_ssl; client_cb.on_result = verify_SNI_real_matching;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = use_SNI_at_ssl; client_cb.on_result = verify_SNI_real_matching;
|
||||||
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_real_matching;
|
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_real_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* default mismatch behavior */
|
/* default mismatch behavior */
|
||||||
|
printf("default mismatch behavior\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
||||||
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_UNKNOWN_SNI_on_server;
|
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_UNKNOWN_SNI_on_server;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* continue on mismatch */
|
/* continue on mismatch */
|
||||||
|
printf("continue on mismatch\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl; server_cb.on_result = verify_SNI_no_matching;
|
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_CONTINUE_at_ssl; server_cb.on_result = verify_SNI_no_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* fake answer on mismatch */
|
/* fake answer on mismatch */
|
||||||
|
printf("fake answer on mismatch\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl; server_cb.on_result = verify_SNI_fake_matching;
|
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_SNI_WITH_FAKE_ANSWER_at_ssl; server_cb.on_result = verify_SNI_fake_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* sni abort - success */
|
/* sni abort - success */
|
||||||
|
printf("sni abort - success\n");
|
||||||
client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
client_cb.ctx_ready = use_SNI_at_ctx; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching;
|
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_real_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* sni abort - abort when absent (ctx) */
|
/* sni abort - abort when absent (ctx) */
|
||||||
|
printf("sni abort - abort when absent (ctx)\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
||||||
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_ABSENT_on_server;
|
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_ABSENT_on_server;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* sni abort - abort when absent (ssl) */
|
/* sni abort - abort when absent (ssl) */
|
||||||
|
printf("sni abort - abort when absent (ssl)\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = verify_FATAL_ERROR_on_client;
|
||||||
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_MANDATORY_SNI_at_ssl; server_cb.on_result = verify_SNI_ABSENT_on_server;
|
server_cb.ctx_ready = NULL; server_cb.ssl_ready = use_MANDATORY_SNI_at_ssl; server_cb.on_result = verify_SNI_ABSENT_on_server;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* sni abort - success when overwritten */
|
/* sni abort - success when overwritten */
|
||||||
|
printf("sni abort - success when overwritten\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = NULL; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_no_matching;
|
server_cb.ctx_ready = use_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = use_SNI_at_ssl; server_cb.on_result = verify_SNI_no_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
|
||||||
/* sni abort - success when allowing mismatches */
|
/* sni abort - success when allowing mismatches */
|
||||||
|
printf("sni abort - success when allowing mismatches\n");
|
||||||
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
client_cb.ctx_ready = NULL; client_cb.ssl_ready = different_SNI_at_ssl; client_cb.on_result = NULL;
|
||||||
server_cb.ctx_ready = use_PSEUDO_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_fake_matching;
|
server_cb.ctx_ready = use_PSEUDO_MANDATORY_SNI_at_ctx; server_cb.ssl_ready = NULL; server_cb.on_result = verify_SNI_fake_matching;
|
||||||
test_wolfSSL_client_server(&client_cb, &server_cb);
|
test_wolfSSL_client_server(&client_cb, &server_cb);
|
||||||
|
@ -35308,6 +35319,89 @@ static int test_wolfSSL_CTX_add_client_CA(void)
|
||||||
#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_WOLFSSL_CLIENT */
|
#endif /* OPENSSL_EXTRA && !NO_RSA && !NO_CERTS && !NO_WOLFSSL_CLIENT */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
|
||||||
|
static THREAD_RETURN WOLFSSL_THREAD server_task_ech(void* args)
|
||||||
|
{
|
||||||
|
callback_functions* callbacks = ((func_args*)args)->callbacks;
|
||||||
|
WOLFSSL_CTX* ctx = callbacks->ctx;
|
||||||
|
WOLFSSL* ssl = NULL;
|
||||||
|
SOCKET_T sfd = 0;
|
||||||
|
SOCKET_T cfd = 0;
|
||||||
|
word16 port;
|
||||||
|
char input[1024];
|
||||||
|
int idx;
|
||||||
|
int ret, err = 0;
|
||||||
|
const char* privateName = "ech-private-name.com";
|
||||||
|
int privateNameLen = (int)XSTRLEN(privateName);
|
||||||
|
|
||||||
|
((func_args*)args)->return_code = TEST_FAIL;
|
||||||
|
port = ((func_args*)args)->signal->port;
|
||||||
|
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_load_verify_locations(ctx, cliCertFile, 0));
|
||||||
|
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_use_certificate_file(ctx, svrCertFile,
|
||||||
|
WOLFSSL_FILETYPE_PEM));
|
||||||
|
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_use_PrivateKey_file(ctx, svrKeyFile,
|
||||||
|
WOLFSSL_FILETYPE_PEM));
|
||||||
|
|
||||||
|
if (callbacks->ctx_ready)
|
||||||
|
callbacks->ctx_ready(ctx);
|
||||||
|
|
||||||
|
ssl = wolfSSL_new(ctx);
|
||||||
|
|
||||||
|
/* set the sni for the server */
|
||||||
|
wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, privateName, privateNameLen);
|
||||||
|
|
||||||
|
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 0, 1, NULL, NULL);
|
||||||
|
CloseSocket(sfd);
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_set_fd(ssl, cfd));
|
||||||
|
|
||||||
|
if (callbacks->ssl_ready)
|
||||||
|
callbacks->ssl_ready(ssl);
|
||||||
|
|
||||||
|
do {
|
||||||
|
err = 0; /* Reset error */
|
||||||
|
ret = wolfSSL_accept(ssl);
|
||||||
|
if (ret != WOLFSSL_SUCCESS) {
|
||||||
|
err = wolfSSL_get_error(ssl, 0);
|
||||||
|
}
|
||||||
|
} while (ret != WOLFSSL_SUCCESS && err == WC_PENDING_E);
|
||||||
|
|
||||||
|
if (ret != WOLFSSL_SUCCESS) {
|
||||||
|
char buff[WOLFSSL_MAX_ERROR_SZ];
|
||||||
|
printf("error = %d, %s\n", err, wolfSSL_ERR_error_string(err, buff));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (0 < (idx = wolfSSL_read(ssl, input, sizeof(input)-1))) {
|
||||||
|
input[idx] = 0;
|
||||||
|
printf("Client message: %s\n", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertIntEQ(privateNameLen, wolfSSL_write(ssl, privateName,
|
||||||
|
privateNameLen));
|
||||||
|
((func_args*)args)->return_code = TEST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callbacks->on_result)
|
||||||
|
callbacks->on_result(ssl);
|
||||||
|
|
||||||
|
wolfSSL_shutdown(ssl);
|
||||||
|
wolfSSL_free(ssl);
|
||||||
|
wolfSSL_CTX_free(ctx);
|
||||||
|
CloseSocket(cfd);
|
||||||
|
|
||||||
|
#ifdef FP_ECC
|
||||||
|
wc_ecc_fp_free();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_ECH && WOLFSSL_TLS13 */
|
||||||
|
|
||||||
#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK)
|
#if defined(OPENSSL_EXTRA) && defined(HAVE_SECRET_CALLBACK)
|
||||||
static THREAD_RETURN WOLFSSL_THREAD server_task(void* args)
|
static THREAD_RETURN WOLFSSL_THREAD server_task(void* args)
|
||||||
{
|
{
|
||||||
|
@ -35673,6 +35767,154 @@ static int test_wolfSSL_Tls13_Key_Logging_test(void)
|
||||||
#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && WOLFSSL_TLS13 */
|
#endif /* OPENSSL_EXTRA && HAVE_SECRET_CALLBACK && WOLFSSL_TLS13 */
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
|
||||||
|
static int test_wolfSSL_Tls13_ECH_params(void)
|
||||||
|
{
|
||||||
|
#if !defined(NO_WOLFSSL_CLIENT)
|
||||||
|
word32 outputLen = 0;
|
||||||
|
byte testBuf[72];
|
||||||
|
WOLFSSL_CTX *ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method());
|
||||||
|
WOLFSSL *ssl = wolfSSL_new(ctx);
|
||||||
|
|
||||||
|
AssertNotNull(ctx);
|
||||||
|
AssertNotNull(ssl);
|
||||||
|
|
||||||
|
/* invalid ctx */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(NULL,
|
||||||
|
"ech-public-name.com", 0, 0, 0));
|
||||||
|
/* invalid public name */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx, NULL, 0,
|
||||||
|
0, 0));
|
||||||
|
/* invalid algorithms */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(ctx,
|
||||||
|
"ech-public-name.com", 1000, 1000, 1000));
|
||||||
|
|
||||||
|
/* invalid ctx */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(NULL, NULL,
|
||||||
|
&outputLen));
|
||||||
|
/* invalid output len */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_CTX_GetEchConfigs(ctx, NULL, NULL));
|
||||||
|
|
||||||
|
/* invalid ssl */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(NULL,
|
||||||
|
(char*)testBuf, sizeof(testBuf)));
|
||||||
|
/* invalid configs64 */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl, NULL,
|
||||||
|
sizeof(testBuf)));
|
||||||
|
/* invalid size */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigsBase64(ssl,
|
||||||
|
(char*)testBuf, 0));
|
||||||
|
|
||||||
|
/* invalid ssl */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(NULL, testBuf,
|
||||||
|
sizeof(testBuf)));
|
||||||
|
/* invalid configs */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, NULL,
|
||||||
|
sizeof(testBuf)));
|
||||||
|
/* invalid size */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, testBuf, 0));
|
||||||
|
|
||||||
|
/* invalid ssl */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(NULL, NULL, &outputLen));
|
||||||
|
/* invalid size */
|
||||||
|
AssertIntNE(WOLFSSL_SUCCESS, wolfSSL_GetEchConfigs(ssl, NULL, NULL));
|
||||||
|
|
||||||
|
wolfSSL_free(ssl);
|
||||||
|
wolfSSL_CTX_free(ctx);
|
||||||
|
#endif /* !NO_WOLFSSL_CLIENT */
|
||||||
|
|
||||||
|
return TEST_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int test_wolfSSL_Tls13_ECH(void)
|
||||||
|
{
|
||||||
|
tcp_ready ready;
|
||||||
|
func_args client_args;
|
||||||
|
func_args server_args;
|
||||||
|
THREAD_TYPE serverThread;
|
||||||
|
callback_functions server_cbf;
|
||||||
|
callback_functions client_cbf;
|
||||||
|
SOCKET_T sockfd = 0;
|
||||||
|
WOLFSSL_CTX* ctx;
|
||||||
|
WOLFSSL* ssl;
|
||||||
|
const char* publicName = "ech-public-name.com";
|
||||||
|
const char* privateName = "ech-private-name.com";
|
||||||
|
int privateNameLen = 20;
|
||||||
|
char reply[1024];
|
||||||
|
int replyLen = 0;
|
||||||
|
byte rawEchConfig[128];
|
||||||
|
word32 rawEchConfigLen = sizeof(rawEchConfig);
|
||||||
|
|
||||||
|
InitTcpReady(&ready);
|
||||||
|
ready.port = 22222;
|
||||||
|
|
||||||
|
XMEMSET(&client_args, 0, sizeof(func_args));
|
||||||
|
XMEMSET(&server_args, 0, sizeof(func_args));
|
||||||
|
XMEMSET(&server_cbf, 0, sizeof(callback_functions));
|
||||||
|
XMEMSET(&client_cbf, 0, sizeof(callback_functions));
|
||||||
|
server_cbf.method = wolfTLSv1_3_server_method; /* TLS1.3 */
|
||||||
|
|
||||||
|
/* create the server context here so we can get the ech config */
|
||||||
|
AssertNotNull(server_cbf.ctx =
|
||||||
|
wolfSSL_CTX_new(wolfTLSv1_3_server_method()));
|
||||||
|
|
||||||
|
/* generate ech config */
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_GenerateEchConfig(server_cbf.ctx,
|
||||||
|
publicName, 0, 0, 0));
|
||||||
|
|
||||||
|
/* get the config for the client to use */
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_GetEchConfigs(server_cbf.ctx, rawEchConfig,
|
||||||
|
&rawEchConfigLen));
|
||||||
|
|
||||||
|
server_args.callbacks = &server_cbf;
|
||||||
|
server_args.signal = &ready;
|
||||||
|
|
||||||
|
/* start server task */
|
||||||
|
start_thread(server_task_ech, &server_args, &serverThread);
|
||||||
|
wait_tcp_ready(&server_args);
|
||||||
|
|
||||||
|
/* run as a TLS1.3 client */
|
||||||
|
AssertNotNull(ctx = wolfSSL_CTX_new(wolfTLSv1_3_client_method()));
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_load_verify_locations(ctx, caCertFile, 0));
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_use_certificate_file(ctx, cliCertFile, SSL_FILETYPE_PEM));
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS,
|
||||||
|
wolfSSL_CTX_use_PrivateKey_file(ctx, cliKeyFile, SSL_FILETYPE_PEM));
|
||||||
|
|
||||||
|
tcp_connect(&sockfd, wolfSSLIP, server_args.signal->port, 0, 0, NULL);
|
||||||
|
|
||||||
|
/* get connected the server task */
|
||||||
|
AssertNotNull(ssl = wolfSSL_new(ctx));
|
||||||
|
|
||||||
|
/* set the ech configs for the client */
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetEchConfigs(ssl, rawEchConfig,
|
||||||
|
rawEchConfigLen));
|
||||||
|
|
||||||
|
/* set the sni for the client */
|
||||||
|
AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME,
|
||||||
|
privateName, privateNameLen));
|
||||||
|
|
||||||
|
AssertIntEQ(wolfSSL_set_fd(ssl, sockfd), WOLFSSL_SUCCESS);
|
||||||
|
AssertIntEQ(wolfSSL_connect(ssl), WOLFSSL_SUCCESS);
|
||||||
|
AssertIntEQ(wolfSSL_write(ssl, privateName, privateNameLen),
|
||||||
|
privateNameLen);
|
||||||
|
AssertIntGT((replyLen = wolfSSL_read(ssl, reply, sizeof(reply))), 0);
|
||||||
|
/* add th null terminator for string compare */
|
||||||
|
reply[replyLen] = 0;
|
||||||
|
/* check that the server replied with the private name */
|
||||||
|
AssertStrEQ(privateName, reply);
|
||||||
|
wolfSSL_free(ssl);
|
||||||
|
wolfSSL_CTX_free(ctx);
|
||||||
|
|
||||||
|
join_thread(serverThread);
|
||||||
|
|
||||||
|
FreeTcpReady(&ready);
|
||||||
|
|
||||||
|
return TEST_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_ECH && WOLFSSL_TLS13 */
|
||||||
|
|
||||||
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && \
|
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && \
|
||||||
defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
|
defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \
|
||||||
|
@ -60187,6 +60429,10 @@ TEST_CASE testCases[] = {
|
||||||
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
|
TEST_DECL(test_wolfSSL_wolfSSL_UseSecureRenegotiation),
|
||||||
TEST_DECL(test_wolfSSL_SCR_Reconnect),
|
TEST_DECL(test_wolfSSL_SCR_Reconnect),
|
||||||
TEST_DECL(test_tls_ext_duplicate),
|
TEST_DECL(test_tls_ext_duplicate),
|
||||||
|
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
|
||||||
|
TEST_DECL(test_wolfSSL_Tls13_ECH_params),
|
||||||
|
TEST_DECL(test_wolfSSL_Tls13_ECH),
|
||||||
|
#endif
|
||||||
|
|
||||||
/* X509 tests */
|
/* X509 tests */
|
||||||
TEST_DECL(test_wolfSSL_X509_NAME_get_entry),
|
TEST_DECL(test_wolfSSL_X509_NAME_get_entry),
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -253,6 +253,9 @@
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
#include <wolfssl/wolfcrypt/ecc.h>
|
#include <wolfssl/wolfcrypt/ecc.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_HPKE
|
||||||
|
#include <wolfssl/wolfcrypt/hpke.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_CURVE25519
|
#ifdef HAVE_CURVE25519
|
||||||
#include <wolfssl/wolfcrypt/curve25519.h>
|
#include <wolfssl/wolfcrypt/curve25519.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -434,6 +437,7 @@ WOLFSSL_TEST_SUBROUTINE int sshkdf_test(void);
|
||||||
WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void);
|
WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void);
|
||||||
#endif
|
#endif
|
||||||
WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void);
|
WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void);
|
||||||
|
WOLFSSL_TEST_SUBROUTINE int hpke_test(void);
|
||||||
WOLFSSL_TEST_SUBROUTINE int arc4_test(void);
|
WOLFSSL_TEST_SUBROUTINE int arc4_test(void);
|
||||||
#ifdef WC_RC2
|
#ifdef WC_RC2
|
||||||
WOLFSSL_TEST_SUBROUTINE int rc2_test(void);
|
WOLFSSL_TEST_SUBROUTINE int rc2_test(void);
|
||||||
|
@ -1064,6 +1068,13 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
|
||||||
TEST_PASS("X963-KDF test passed!\n");
|
TEST_PASS("X963-KDF test passed!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_HPKE) && defined(HAVE_ECC) && defined(HAVE_AESGCM)
|
||||||
|
if ( (ret = hpke_test()) != 0)
|
||||||
|
return err_sys("HPKE test failed!\n", ret);
|
||||||
|
else
|
||||||
|
TEST_PASS("HPKE test passed!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) && \
|
#if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) && \
|
||||||
!defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT)
|
!defined(WOLFSSL_AFALG_XILINX_AES) && !defined(WOLFSSL_XILINX_CRYPT)
|
||||||
if ( (ret = gmac_test()) != 0)
|
if ( (ret = gmac_test()) != 0)
|
||||||
|
@ -22244,8 +22255,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)ceTrafficLabel, (word32)strlen(ceTrafficLabel),
|
(byte*)ceTrafficLabel, (word32)XSTRLEN(ceTrafficLabel),
|
||||||
tv->hashHello1, hashAlgSz, tv->hashAlg);
|
tv->hashHello1, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22254,8 +22265,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)eExpMasterLabel, (word32)strlen(eExpMasterLabel),
|
(byte*)eExpMasterLabel, (word32)XSTRLEN(eExpMasterLabel),
|
||||||
tv->hashHello1, hashAlgSz, tv->hashAlg);
|
tv->hashHello1, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22264,8 +22275,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(salt, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(salt, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)derivedLabel, (word32)strlen(derivedLabel),
|
(byte*)derivedLabel, (word32)XSTRLEN(derivedLabel),
|
||||||
hashZero, hashAlgSz, tv->hashAlg);
|
hashZero, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22276,8 +22287,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)cHsTrafficLabel, (word32)strlen(cHsTrafficLabel),
|
(byte*)cHsTrafficLabel, (word32)XSTRLEN(cHsTrafficLabel),
|
||||||
tv->hashHello2, hashAlgSz, tv->hashAlg);
|
tv->hashHello2, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22287,8 +22298,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)sHsTrafficLabel, (word32)strlen(sHsTrafficLabel),
|
(byte*)sHsTrafficLabel, (word32)XSTRLEN(sHsTrafficLabel),
|
||||||
tv->hashHello2, hashAlgSz, tv->hashAlg);
|
tv->hashHello2, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22297,8 +22308,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(salt, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(salt, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)derivedLabel, (word32)strlen(derivedLabel),
|
(byte*)derivedLabel, (word32)XSTRLEN(derivedLabel),
|
||||||
hashZero, hashAlgSz, tv->hashAlg);
|
hashZero, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22308,8 +22319,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)cAppTrafficLabel, (word32)strlen(cAppTrafficLabel),
|
(byte*)cAppTrafficLabel, (word32)XSTRLEN(cAppTrafficLabel),
|
||||||
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22318,8 +22329,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)sAppTrafficLabel, (word32)strlen(sAppTrafficLabel),
|
(byte*)sAppTrafficLabel, (word32)XSTRLEN(sAppTrafficLabel),
|
||||||
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22328,8 +22339,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)expMasterLabel, (word32)strlen(expMasterLabel),
|
(byte*)expMasterLabel, (word32)XSTRLEN(expMasterLabel),
|
||||||
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
tv->hashFinished1, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22338,8 +22349,8 @@ WOLFSSL_TEST_SUBROUTINE int tls13_kdf_test(void)
|
||||||
|
|
||||||
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
ret = wc_Tls13_HKDF_Expand_Label(output, hashAlgSz,
|
||||||
secret, hashAlgSz,
|
secret, hashAlgSz,
|
||||||
(byte*)protocolLabel, (word32)strlen(protocolLabel),
|
(byte*)protocolLabel, (word32)XSTRLEN(protocolLabel),
|
||||||
(byte*)resMasterLabel, (word32)strlen(resMasterLabel),
|
(byte*)resMasterLabel, (word32)XSTRLEN(resMasterLabel),
|
||||||
tv->hashFinished2, hashAlgSz, tv->hashAlg);
|
tv->hashFinished2, hashAlgSz, tv->hashAlg);
|
||||||
if (ret != 0) break;
|
if (ret != 0) break;
|
||||||
|
|
||||||
|
@ -22498,6 +22509,138 @@ WOLFSSL_TEST_SUBROUTINE int x963kdf_test(void)
|
||||||
|
|
||||||
#endif /* HAVE_X963_KDF */
|
#endif /* HAVE_X963_KDF */
|
||||||
|
|
||||||
|
#if defined(HAVE_HPKE) && (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \
|
||||||
|
defined(HAVE_AESGCM)
|
||||||
|
|
||||||
|
static int hpke_test_single(Hpke* hpke)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
int rngRet = 0;
|
||||||
|
WC_RNG rng[1];
|
||||||
|
const char* start_text = "this is a test";
|
||||||
|
const char* info_text = "info";
|
||||||
|
const char* aad_text = "aad";
|
||||||
|
byte ciphertext[MAX_HPKE_LABEL_SZ];
|
||||||
|
byte plaintext[MAX_HPKE_LABEL_SZ];
|
||||||
|
void* receiverKey = NULL;
|
||||||
|
void* ephemeralKey = NULL;
|
||||||
|
uint8_t pubKey[HPKE_Npk_MAX]; /* public key */
|
||||||
|
word16 pubKeySz = (word16)sizeof(pubKey);
|
||||||
|
|
||||||
|
rngRet = ret = wc_InitRng(rng);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* generate the keys */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeGenerateKeyPair(hpke, &ephemeralKey, rng);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeGenerateKeyPair(hpke, &receiverKey, rng);
|
||||||
|
|
||||||
|
/* seal */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeSealBase(hpke, ephemeralKey, receiverKey,
|
||||||
|
(byte*)info_text, (word32)XSTRLEN(info_text),
|
||||||
|
(byte*)aad_text, (word32)XSTRLEN(aad_text),
|
||||||
|
(byte*)start_text, (word32)XSTRLEN(start_text),
|
||||||
|
ciphertext);
|
||||||
|
|
||||||
|
/* export ephemeral key */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeSerializePublicKey(hpke, ephemeralKey, pubKey, &pubKeySz);
|
||||||
|
|
||||||
|
/* open with exported ephemeral key */
|
||||||
|
if (ret == 0)
|
||||||
|
ret = wc_HpkeOpenBase(hpke, receiverKey, pubKey, pubKeySz,
|
||||||
|
(byte*)info_text, (word32)XSTRLEN(info_text),
|
||||||
|
(byte*)aad_text, (word32)XSTRLEN(aad_text),
|
||||||
|
ciphertext, (word32)XSTRLEN(start_text),
|
||||||
|
plaintext);
|
||||||
|
|
||||||
|
if (ret == 0)
|
||||||
|
ret = XMEMCMP(plaintext, start_text, XSTRLEN(start_text));
|
||||||
|
|
||||||
|
if (ephemeralKey != NULL)
|
||||||
|
wc_HpkeFreeKey(hpke, hpke->kem, ephemeralKey, hpke->heap);
|
||||||
|
|
||||||
|
if (receiverKey != NULL)
|
||||||
|
wc_HpkeFreeKey(hpke, hpke->kem, receiverKey, hpke->heap);
|
||||||
|
|
||||||
|
if (rngRet == 0)
|
||||||
|
wc_FreeRng(rng);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
WOLFSSL_TEST_SUBROUTINE int hpke_test(void)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
Hpke hpke[1];
|
||||||
|
|
||||||
|
#if defined(HAVE_ECC)
|
||||||
|
#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256)
|
||||||
|
/* p256 */
|
||||||
|
ret = wc_HpkeInit(hpke, DHKEM_P256_HKDF_SHA256, HKDF_SHA256,
|
||||||
|
HPKE_AES_128_GCM, NULL);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hpke_test_single(hpke);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
/* p384 */
|
||||||
|
ret = wc_HpkeInit(hpke, DHKEM_P384_HKDF_SHA384, HKDF_SHA384,
|
||||||
|
HPKE_AES_128_GCM, NULL);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hpke_test_single(hpke);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512)
|
||||||
|
/* p521 */
|
||||||
|
ret = wc_HpkeInit(hpke, DHKEM_P521_HKDF_SHA512, HKDF_SHA512,
|
||||||
|
HPKE_AES_128_GCM, NULL);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hpke_test_single(hpke);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_CURVE25519)
|
||||||
|
/* test with curve25519 and aes256 */
|
||||||
|
ret = wc_HpkeInit(hpke, DHKEM_X25519_HKDF_SHA256, HKDF_SHA256,
|
||||||
|
HPKE_AES_256_GCM, NULL);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = hpke_test_single(hpke);
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
/* x448 and chacha20 are unimplemented */
|
||||||
|
}
|
||||||
|
#endif /* HAVE_HPKE && HAVE_ECC && HAVE_AESGCM */
|
||||||
|
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
|
|
||||||
|
|
|
@ -265,6 +265,8 @@
|
||||||
#include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
|
#include <wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <wolfssl/wolfcrypt/hpke.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -2594,8 +2596,74 @@ typedef enum {
|
||||||
#ifdef WOLFSSL_QUIC
|
#ifdef WOLFSSL_QUIC
|
||||||
TLSX_KEY_QUIC_TP_PARAMS_DRAFT = 0xffa5, /* from draft-ietf-quic-tls-27 */
|
TLSX_KEY_QUIC_TP_PARAMS_DRAFT = 0xffa5, /* from draft-ietf-quic-tls-27 */
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
TLSX_ECH = 0xfe0d, /* from draft-ietf-tls-esni-13 */
|
||||||
|
#endif
|
||||||
} TLSX_Type;
|
} TLSX_Type;
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ECH_TYPE_OUTER = 0,
|
||||||
|
ECH_TYPE_INNER = 1
|
||||||
|
} EchType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ECH_WRITE_GREASE,
|
||||||
|
ECH_WRITE_REAL,
|
||||||
|
ECH_WRITE_RETRY_CONFIGS,
|
||||||
|
ECH_WRITE_NONE,
|
||||||
|
ECH_PARSED_INTERNAL,
|
||||||
|
} EchState;
|
||||||
|
|
||||||
|
typedef struct EchCipherSuite {
|
||||||
|
word16 kdfId;
|
||||||
|
word16 aeadId;
|
||||||
|
} EchCipherSuite;
|
||||||
|
|
||||||
|
typedef struct WOLFSSL_EchConfig {
|
||||||
|
byte* raw;
|
||||||
|
char* publicName;
|
||||||
|
void* receiverPrivkey;
|
||||||
|
struct WOLFSSL_EchConfig* next;
|
||||||
|
EchCipherSuite* cipherSuites;
|
||||||
|
word32 rawLen;
|
||||||
|
word16 kemId;
|
||||||
|
byte configId;
|
||||||
|
byte numCipherSuites;
|
||||||
|
byte receiverPubkey[HPKE_Npk_MAX];
|
||||||
|
} WOLFSSL_EchConfig;
|
||||||
|
|
||||||
|
typedef struct WOLFSSL_ECH {
|
||||||
|
Hpke* hpke;
|
||||||
|
const byte* aad;
|
||||||
|
void* ephemeralKey;
|
||||||
|
WOLFSSL_EchConfig* echConfig;
|
||||||
|
byte* innerClientHello;
|
||||||
|
byte* outerClientPayload;
|
||||||
|
EchCipherSuite cipherSuite;
|
||||||
|
word16 aadLen;
|
||||||
|
word16 paddingLen;
|
||||||
|
word16 innerClientHelloLen;
|
||||||
|
word16 kemId;
|
||||||
|
word16 encLen;
|
||||||
|
EchState state;
|
||||||
|
byte type;
|
||||||
|
byte configId;
|
||||||
|
byte enc[HPKE_Npk_MAX];
|
||||||
|
} WOLFSSL_ECH;
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int EchConfigGetSupportedCipherSuite(WOLFSSL_EchConfig* config);
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int TLSX_FinalizeEch(WOLFSSL_ECH* ech, byte* aad, word32 aadLen);
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int GetEchConfig(WOLFSSL_EchConfig* config, byte* output,
|
||||||
|
word32* outputLen);
|
||||||
|
|
||||||
|
WOLFSSL_LOCAL int GetEchConfigsEx(WOLFSSL_EchConfig* configs,
|
||||||
|
byte* output, word32* outputLen);
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct TLSX {
|
typedef struct TLSX {
|
||||||
TLSX_Type type; /* Extension Type */
|
TLSX_Type type; /* Extension Type */
|
||||||
void* data; /* Extension Data */
|
void* data; /* Extension Data */
|
||||||
|
@ -3498,6 +3566,9 @@ struct WOLFSSL_CTX {
|
||||||
const WOLFSSL_QUIC_METHOD *method;
|
const WOLFSSL_QUIC_METHOD *method;
|
||||||
} quic;
|
} quic;
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
WOLFSSL_EchConfig* echConfigs;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
WOLFSSL_LOCAL
|
WOLFSSL_LOCAL
|
||||||
|
@ -4258,6 +4329,12 @@ typedef struct Options {
|
||||||
#ifdef WOLFSSL_TLS13
|
#ifdef WOLFSSL_TLS13
|
||||||
word16 tls13MiddleBoxCompat:1; /* TLSv1.3 middlebox compatibility */
|
word16 tls13MiddleBoxCompat:1; /* TLSv1.3 middlebox compatibility */
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WOLFSSL_DTLS_CID
|
||||||
|
byte useDtlsCID:1;
|
||||||
|
#endif /* WOLFSSL_DTLS_CID */
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
byte useEch:1;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* need full byte values for this section */
|
/* need full byte values for this section */
|
||||||
byte processReply; /* nonblocking resume */
|
byte processReply; /* nonblocking resume */
|
||||||
|
@ -4303,9 +4380,6 @@ typedef struct Options {
|
||||||
#ifdef WOLFSSL_TLS13
|
#ifdef WOLFSSL_TLS13
|
||||||
byte oldMinor; /* client preferred version < TLS 1.3 */
|
byte oldMinor; /* client preferred version < TLS 1.3 */
|
||||||
#endif
|
#endif
|
||||||
#ifdef WOLFSSL_DTLS_CID
|
|
||||||
byte useDtlsCID:1;
|
|
||||||
#endif /* WOLFSSL_DTLS_CID */
|
|
||||||
} Options;
|
} Options;
|
||||||
|
|
||||||
typedef struct Arrays {
|
typedef struct Arrays {
|
||||||
|
@ -4321,6 +4395,9 @@ typedef struct Arrays {
|
||||||
byte psk_key[MAX_PSK_KEY_LEN];
|
byte psk_key[MAX_PSK_KEY_LEN];
|
||||||
#endif
|
#endif
|
||||||
byte clientRandom[RAN_LEN];
|
byte clientRandom[RAN_LEN];
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
byte clientRandomInner[RAN_LEN];
|
||||||
|
#endif
|
||||||
byte serverRandom[RAN_LEN];
|
byte serverRandom[RAN_LEN];
|
||||||
byte sessionID[ID_LEN];
|
byte sessionID[ID_LEN];
|
||||||
byte sessionIDSz;
|
byte sessionIDSz;
|
||||||
|
@ -4889,6 +4966,9 @@ struct WOLFSSL {
|
||||||
byte serverSecret[SECRET_LEN];
|
byte serverSecret[SECRET_LEN];
|
||||||
#endif
|
#endif
|
||||||
HS_Hashes* hsHashes;
|
HS_Hashes* hsHashes;
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
HS_Hashes* hsHashesEch;
|
||||||
|
#endif
|
||||||
void* IOCB_ReadCtx;
|
void* IOCB_ReadCtx;
|
||||||
void* IOCB_WriteCtx;
|
void* IOCB_WriteCtx;
|
||||||
WC_RNG* rng;
|
WC_RNG* rng;
|
||||||
|
@ -5348,6 +5428,9 @@ struct WOLFSSL {
|
||||||
* content have not been handled yet by quic */
|
* content have not been handled yet by quic */
|
||||||
} quic;
|
} quic;
|
||||||
#endif /* WOLFSSL_QUIC */
|
#endif /* WOLFSSL_QUIC */
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
WOLFSSL_EchConfig* echConfigs;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -5853,6 +5936,8 @@ WOLFSSL_LOCAL int SetDhExternal(WOLFSSL_DH *dh);
|
||||||
|
|
||||||
WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl);
|
WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl);
|
||||||
WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl);
|
WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl);
|
||||||
|
WOLFSSL_LOCAL int InitHandshakeHashesAndCopy(WOLFSSL* ssl, HS_Hashes* source,
|
||||||
|
HS_Hashes** destination);
|
||||||
|
|
||||||
|
|
||||||
#ifndef WOLFSSL_NO_TLS12
|
#ifndef WOLFSSL_NO_TLS12
|
||||||
|
|
|
@ -992,6 +992,23 @@ WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void);
|
||||||
|
|
||||||
#endif /* WOLFSSL_DTLS */
|
#endif /* WOLFSSL_DTLS */
|
||||||
|
|
||||||
|
#if defined(HAVE_ECH)
|
||||||
|
WOLFSSL_API int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx,
|
||||||
|
const char* publicName, word16 kemId, word16 kdfId, word16 aeadId);
|
||||||
|
|
||||||
|
WOLFSSL_API int wolfSSL_CTX_GetEchConfigs(WOLFSSL_CTX* ctx, byte* output,
|
||||||
|
word32* outputLen);
|
||||||
|
|
||||||
|
WOLFSSL_API int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, char* echConfigs64,
|
||||||
|
word32 echConfigs64Len);
|
||||||
|
|
||||||
|
WOLFSSL_API int wolfSSL_SetEchConfigs(WOLFSSL* ssl, const byte* echConfigs,
|
||||||
|
word32 echConfigsLen);
|
||||||
|
|
||||||
|
WOLFSSL_API int wolfSSL_GetEchConfigs(WOLFSSL* ssl, byte* echConfigs,
|
||||||
|
word32* echConfigsLen);
|
||||||
|
#endif /* HAVE_ECH */
|
||||||
|
|
||||||
#ifdef HAVE_POLY1305
|
#ifdef HAVE_POLY1305
|
||||||
WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL* ssl, int value);
|
WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL* ssl, int value);
|
||||||
#endif
|
#endif
|
||||||
|
@ -3702,7 +3719,8 @@ WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl);
|
||||||
|
|
||||||
/* SNI types */
|
/* SNI types */
|
||||||
enum {
|
enum {
|
||||||
WOLFSSL_SNI_HOST_NAME = 0
|
WOLFSSL_SNI_HOST_NAME = 0,
|
||||||
|
WOLFSSL_SNI_HOST_NAME_OUTER = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
|
WOLFSSL_ABI WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type,
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/* hpke.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2022 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file wolfssl/wolfcrypt/hpke.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wolfssl/wolfcrypt/settings.h>
|
||||||
|
#include <wolfssl/wolfcrypt/types.h>
|
||||||
|
#include <wolfssl/wolfcrypt/ecc.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_HPKE) && defined(HAVE_ECC)
|
||||||
|
|
||||||
|
#ifndef WOLFCRYPT_HPKE
|
||||||
|
#define WOLFCRYPT_HPKE
|
||||||
|
|
||||||
|
/* KEM enum */
|
||||||
|
enum {
|
||||||
|
DHKEM_P256_HKDF_SHA256 = 0x0010,
|
||||||
|
DHKEM_P384_HKDF_SHA384 = 0x0011,
|
||||||
|
DHKEM_P521_HKDF_SHA512 = 0x0012,
|
||||||
|
DHKEM_X25519_HKDF_SHA256 = 0x0020,
|
||||||
|
DHKEM_X448_HKDF_SHA512 = 0x0021,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DHKEM_P256_ENC_LEN 65
|
||||||
|
#define DHKEM_P384_ENC_LEN 97
|
||||||
|
#define DHKEM_P521_ENC_LEN 133
|
||||||
|
#define DHKEM_X25519_ENC_LEN 32
|
||||||
|
#define DHKEM_X448_ENC_LEN 56
|
||||||
|
|
||||||
|
/* KDF enum */
|
||||||
|
enum {
|
||||||
|
HKDF_SHA256 = 0x0001,
|
||||||
|
HKDF_SHA384 = 0x0002,
|
||||||
|
HKDF_SHA512 = 0x0003,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* AEAD enum */
|
||||||
|
enum {
|
||||||
|
HPKE_AES_128_GCM = 0x0001,
|
||||||
|
HPKE_AES_256_GCM = 0x0002,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* TODO better way of doing this */
|
||||||
|
#define HPKE_SUPPORTED_KEM_LEN 4
|
||||||
|
#define HPKE_SUPPORTED_KDF_LEN 3
|
||||||
|
#define HPKE_SUPPORTED_AEAD_LEN 2
|
||||||
|
extern const int hpkeSupportedKem[HPKE_SUPPORTED_KEM_LEN];
|
||||||
|
extern const int hpkeSupportedKdf[HPKE_SUPPORTED_KDF_LEN];
|
||||||
|
extern const int hpkeSupportedAead[HPKE_SUPPORTED_AEAD_LEN];
|
||||||
|
|
||||||
|
#define HPKE_Nh_MAX 64
|
||||||
|
#define HPKE_Nk_MAX 32
|
||||||
|
#define HPKE_Nn_MAX 12
|
||||||
|
#define HPKE_Nt_MAX 16
|
||||||
|
#define HPKE_Ndh_MAX 66
|
||||||
|
#define HPKE_Npk_MAX 133
|
||||||
|
#define HPKE_Nsecret_MAX 64
|
||||||
|
#define KEM_SUITE_ID_LEN 5
|
||||||
|
#define HPKE_SUITE_ID_LEN 10
|
||||||
|
|
||||||
|
#ifndef MAX_HPKE_LABEL_SZ
|
||||||
|
#define MAX_HPKE_LABEL_SZ 512
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* heap;
|
||||||
|
word32 kem;
|
||||||
|
word32 kdf;
|
||||||
|
word32 aead;
|
||||||
|
word32 Nh;
|
||||||
|
word32 Nk;
|
||||||
|
word32 Nn;
|
||||||
|
word32 Nt;
|
||||||
|
word32 Ndh;
|
||||||
|
word32 Npk;
|
||||||
|
word32 Nsecret;
|
||||||
|
int kdf_digest;
|
||||||
|
int curve_id;
|
||||||
|
byte kem_suite_id[KEM_SUITE_ID_LEN];
|
||||||
|
byte hpke_suite_id[HPKE_SUITE_ID_LEN];
|
||||||
|
} Hpke;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int seq;
|
||||||
|
byte key[HPKE_Nk_MAX];
|
||||||
|
byte base_nonce[HPKE_Nn_MAX];
|
||||||
|
byte exporter_secret[HPKE_Nsecret_MAX];
|
||||||
|
} HpkeBaseContext;
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSL_API int wc_HpkeInit(Hpke* hpke, int kem, int kdf, int aead, void* heap);
|
||||||
|
WOLFSSL_API int wc_HpkeGenerateKeyPair(Hpke* hpke, void** keypair, WC_RNG* rng);
|
||||||
|
WOLFSSL_API int wc_HpkeSerializePublicKey(Hpke* hpke, void* key, byte* out,
|
||||||
|
word16* outSz);
|
||||||
|
WOLFSSL_API int wc_HpkeDeserializePublicKey(Hpke* hpke, void** key,
|
||||||
|
const byte* in, word16 inSz);
|
||||||
|
WOLFSSL_API void wc_HpkeFreeKey(Hpke* hpke, word16 kem, void* keypair,
|
||||||
|
void* heap);
|
||||||
|
WOLFSSL_API int wc_HpkeSealBase(Hpke* hpke, void* ephemeralKey,
|
||||||
|
void* receiverKey, byte* info, word32 infoSz, byte* aad, word32 aadSz,
|
||||||
|
byte* plaintext, word32 ptSz, byte* ciphertext);
|
||||||
|
WOLFSSL_API int wc_HpkeOpenBase(Hpke* hpke, void* receiverKey,
|
||||||
|
const byte* pubKey, word16 pubKeySz, byte* info, word32 infoSz, byte* aad,
|
||||||
|
word32 aadSz, byte* ciphertext, word32 ctSz, byte* plaintext);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HAVE_HPKE && HAVE_ECC */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
|
@ -32,6 +32,7 @@ nobase_include_HEADERS+= \
|
||||||
wolfssl/wolfcrypt/fips_test.h \
|
wolfssl/wolfcrypt/fips_test.h \
|
||||||
wolfssl/wolfcrypt/hash.h \
|
wolfssl/wolfcrypt/hash.h \
|
||||||
wolfssl/wolfcrypt/hmac.h \
|
wolfssl/wolfcrypt/hmac.h \
|
||||||
|
wolfssl/wolfcrypt/hpke.h \
|
||||||
wolfssl/wolfcrypt/kdf.h \
|
wolfssl/wolfcrypt/kdf.h \
|
||||||
wolfssl/wolfcrypt/integer.h \
|
wolfssl/wolfcrypt/integer.h \
|
||||||
wolfssl/wolfcrypt/md2.h \
|
wolfssl/wolfcrypt/md2.h \
|
||||||
|
|
|
@ -2879,6 +2879,10 @@ extern void uITRON4_free(void *p) ;
|
||||||
#define WOLFSSL_NO_SHAKE256
|
#define WOLFSSL_NO_SHAKE256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Encrypted Client Hello - requires HPKE */
|
||||||
|
#if defined(HAVE_ECH) && !defined(HAVE_HPKE)
|
||||||
|
#define HAVE_HPKE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue