diff --git a/src/ssl_ech.c b/src/ssl_ech.c index 1f864bc15b..a71350c6c1 100644 --- a/src/ssl_ech.c +++ b/src/ssl_ech.c @@ -32,6 +32,15 @@ /* 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) +{ + return wolfSSL_CTX_GenerateEchConfigEx(ctx, publicName, kemId, kdfId, + aeadId, 0); +} + +/* create the hpke key and ech config to send to clients + * maximum_name_length may also be set for a more stable padding length */ +int wolfSSL_CTX_GenerateEchConfigEx(WOLFSSL_CTX* ctx, const char* publicName, + word16 kemId, word16 kdfId, word16 aeadId, byte maxNameLen) { int ret = 0; WOLFSSL_EchConfig* newConfig; @@ -129,8 +138,8 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName, ret = MEMORY_E; } else { - XMEMCPY(newConfig->publicName, publicName, - XSTRLEN(publicName) + 1); + XMEMCPY(newConfig->publicName, publicName, XSTRLEN(publicName) + 1); + newConfig->maxNameLen = maxNameLen; } } @@ -399,8 +408,8 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen) output += 2; } - /* set maximum name length to 0 */ - *output = 0; + /* maximum name len */ + *output = config->maxNameLen; output++; /* publicName len */ @@ -411,7 +420,7 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen) XMEMCPY(output, config->publicName, publicNameLen); output += publicNameLen; - /* terminating zeros */ + /* no extensions, print zeros */ c16toa(0, output); /* output += 2; */ @@ -599,12 +608,13 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap, echConfig += 4; } - /* ignore the maximum name length */ + /* maxNameLen */ idx++; if (idx >= length) { ret = BUFFER_E; break; } + workingConfig->maxNameLen = *echConfig; echConfig++; /* publicNameLen */ diff --git a/src/tls13.c b/src/tls13.c index fba9a05cad..ebea8e2e08 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -4786,8 +4786,22 @@ int SendTls13ClientHello(WOLFSSL* ssl) if (ret != 0) return ret; + /* calculate padding (RFC 9849, section 6.1.3) */ + if (args->ech->privateName != NULL) { + word16 nameLen = (word16)XSTRLEN(args->ech->privateName); + if (nameLen > args->ech->echConfig->maxNameLen) + args->ech->paddingLen = 0; + else + args->ech->paddingLen = + (word16)args->ech->echConfig->maxNameLen - nameLen; + } + else { + args->ech->paddingLen = args->ech->echConfig->maxNameLen + 9; + } + args->ech->paddingLen += 31 - + ((args->length + args->ech->paddingLen - 1) % 32); + /* 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; if (args->ech->innerClientHelloLen > 0xFFFF) diff --git a/tests/api.c b/tests/api.c index 05a7688d7f..fcfc1bb8ca 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14822,8 +14822,10 @@ static int test_ech_server_ctx_ready(WOLFSSL_CTX* ctx) { int ret; - ret = wolfSSL_CTX_GenerateEchConfig(ctx, echCbTestPublicName, - echCbTestKemID, echCbTestKdfID, echCbTestAeadID); + /* +20 for this isn't significant, it just exercises the padding code */ + ret = wolfSSL_CTX_GenerateEchConfigEx(ctx, echCbTestPublicName, + echCbTestKemID, echCbTestKdfID, echCbTestAeadID, + XSTRLEN(echCbTestPublicName) + 20); if (ret != WOLFSSL_SUCCESS) return TEST_FAIL; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 96606ba4f9..ab5a4d3f7b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -3137,6 +3137,7 @@ typedef struct WOLFSSL_EchConfig { byte configId; byte numCipherSuites; byte receiverPubkey[HPKE_Npk_MAX]; + byte maxNameLen; } WOLFSSL_EchConfig; typedef struct WOLFSSL_ECH { diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 236515157b..1bd1992b9c 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1218,6 +1218,9 @@ WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void); #if defined(WOLFSSL_TLS13) && 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_GenerateEchConfigEx(WOLFSSL_CTX* ctx, + const char* publicName, word16 kemId, word16 kdfId, word16 aeadId, + byte maxNameLen); WOLFSSL_API int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64, word32 echConfigs64Len);