Skip to content

Commit

Permalink
Adds support for TLS v1.3 Encrypted Client Hello (ECH) draft-ietf-tls…
Browse files Browse the repository at this point in the history
…-esni) and HPKE (Hybrid Public Key Encryption) RFC9180.
  • Loading branch information
dgarske committed Jan 18, 2023
1 parent 7120ae1 commit 6b6ad38
Show file tree
Hide file tree
Showing 15 changed files with 4,109 additions and 47 deletions.
36 changes: 36 additions & 0 deletions configure.ac
Expand Up @@ -742,6 +742,7 @@ then
test "$enable_trusted_ca" = "" && enable_trusted_ca=yes
test "$enable_session_ticket" = "" && enable_session_ticket=yes
test "$enable_earlydata" = "" && enable_earlydata=yes
test "$enable_ech" = "" && enable_ech=yes

if test "$ENABLED_32BIT" != "yes"
then
Expand Down Expand Up @@ -1120,6 +1121,25 @@ AC_ARG_ENABLE([cryptonly],

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 is a prereq for the options mcast, sctp, and jni. Enabling any of those
# without DTLS will also enable DTLS.
Expand Down Expand Up @@ -2980,6 +3000,20 @@ then
AM_CFLAGS="$AM_CFLAGS -DHAVE_HKDF"
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
AC_ARG_ENABLE([x963kdf],
[AS_HELP_STRING([--enable-x963kdf],[Enable X9.63 KDF support (default: disabled)])],
Expand Down Expand Up @@ -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_QUIC],[test "x$ENABLED_QUIC" = "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_MAXQ10XX],[test "x$ENABLED_MAXQ10XX" = "xyes"])

Expand Down Expand Up @@ -8740,6 +8775,7 @@ echo " * PWDBASED: $ENABLED_PWDBASED"
echo " * scrypt: $ENABLED_SCRYPT"
echo " * wolfCrypt Only: $ENABLED_CRYPTONLY"
echo " * HKDF: $ENABLED_HKDF"
echo " * HPKE: $ENABLED_HPKE"
echo " * X9.63 KDF: $ENABLED_X963KDF"
echo " * MD4: $ENABLED_MD4"
echo " * PSK: $ENABLED_PSK"
Expand Down
3 changes: 3 additions & 0 deletions examples/configs/user_settings_all.h
Expand Up @@ -234,6 +234,9 @@ extern "C" {
#define HAVE_KEYING_MATERIAL
#define WOLFSSL_HAVE_PRF

/* Encrypted Client Hello */
#define HAVE_HPKE
#define HAVE_ECH

/* Non-Standard Algorithms (DG disabled) */
//#define HAVE_CAMELLIA
Expand Down
4 changes: 4 additions & 0 deletions src/include.am
Expand Up @@ -509,6 +509,10 @@ if BUILD_ASN
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/asn.c
endif

if BUILD_HPKE
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/hpke.c
endif

endif !BUILD_FIPS_RAND

if BUILD_CODING
Expand Down
110 changes: 110 additions & 0 deletions src/internal.c
Expand Up @@ -2398,6 +2398,36 @@ void wolfSSL_CRYPTO_cleanup_ex_data(WOLFSSL_CRYPTO_EX_DATA* ex_data)
}
#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. */

/* The allocations done in InitSSL_Ctx must be free'd with ctx->onHeapHint
Expand Down Expand Up @@ -2554,6 +2584,10 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx)
ctx->staticKELockInit = 0;
}
#endif
#endif
#if defined(HAVE_ECH)
FreeEchConfigs(ctx->echConfigs, ctx->heap);
ctx->echConfigs = NULL;
#endif
(void)heapAtCTXInit;
}
Expand Down Expand Up @@ -6479,6 +6513,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.
* For example wolfSSL_clear() is called then wolfSSL_connect or accept */
int ReinitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
Expand Down Expand Up @@ -7463,6 +7562,17 @@ void SSL_ResourceFree(WOLFSSL* ssl)
ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret));
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
#ifdef WOLFSSL_HAVE_TLS_UNIQUE
ForceZero(&ssl->clientFinished, TLS_FINISHED_SZ_MAX);
Expand Down

0 comments on commit 6b6ad38

Please sign in to comment.