Skip to content

Commit d0073d9

Browse files
authored
Merge pull request #10326 from sebastian-carpenter/tls-ech-maxnamelen
Add maximum_name_length to TLS ECH padding
2 parents 00fe73b + d029aed commit d0073d9

5 files changed

Lines changed: 77 additions & 45 deletions

File tree

src/ssl_ech.c

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@
3232
/* create the hpke key and ech config to send to clients */
3333
int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
3434
word16 kemId, word16 kdfId, word16 aeadId)
35+
{
36+
return wolfSSL_CTX_GenerateEchConfigEx(ctx, publicName, kemId, kdfId,
37+
aeadId, 0);
38+
}
39+
40+
/* create the hpke key and ech config to send to clients
41+
* maximum_name_length may also be set for a more stable padding length */
42+
int wolfSSL_CTX_GenerateEchConfigEx(WOLFSSL_CTX* ctx, const char* publicName,
43+
word16 kemId, word16 kdfId, word16 aeadId, byte maxNameLen)
3544
{
3645
int ret = 0;
3746
WOLFSSL_EchConfig* newConfig;
@@ -129,8 +138,8 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
129138
ret = MEMORY_E;
130139
}
131140
else {
132-
XMEMCPY(newConfig->publicName, publicName,
133-
XSTRLEN(publicName) + 1);
141+
XMEMCPY(newConfig->publicName, publicName, XSTRLEN(publicName) + 1);
142+
newConfig->maxNameLen = maxNameLen;
134143
}
135144
}
136145

@@ -166,33 +175,52 @@ int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx, const char* publicName,
166175
return ret;
167176
}
168177

169-
int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64,
170-
word32 echConfigs64Len)
178+
/* base64-decode echConfigs into a freshly allocated buffer */
179+
static int DecodeEchConfigsBase64(void* heap, const char* echConfigs64,
180+
word32 echConfigs64Len, byte** decodedConfigs, word32* decodedLen)
171181
{
172182
int ret = 0;
173-
word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
174-
byte* decodedConfigs;
183+
byte* buf;
184+
word32 len = echConfigs64Len * 3 / 4 + 1;
175185

176-
if (ctx == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
186+
if (echConfigs64 == NULL || echConfigs64Len == 0)
177187
return BAD_FUNC_ARG;
178188

179-
decodedConfigs = (byte*)XMALLOC(decodedLen, ctx->heap,
180-
DYNAMIC_TYPE_TMP_BUFFER);
189+
buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER);
181190

182-
if (decodedConfigs == NULL)
191+
if (buf == NULL)
183192
return MEMORY_E;
184193

185-
decodedConfigs[decodedLen - 1] = 0;
194+
buf[len - 1] = 0;
186195

187196
/* decode the echConfigs */
188-
ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len,
189-
decodedConfigs, &decodedLen);
197+
ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len, buf, &len);
190198

191199
if (ret != 0) {
192-
XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
200+
XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER);
193201
return ret;
194202
}
195203

204+
*decodedConfigs = buf;
205+
*decodedLen = len;
206+
return 0;
207+
}
208+
209+
int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx, const char* echConfigs64,
210+
word32 echConfigs64Len)
211+
{
212+
int ret;
213+
word32 decodedLen;
214+
byte* decodedConfigs;
215+
216+
if (ctx == NULL)
217+
return BAD_FUNC_ARG;
218+
219+
ret = DecodeEchConfigsBase64(ctx->heap, echConfigs64, echConfigs64Len,
220+
&decodedConfigs, &decodedLen);
221+
if (ret != 0)
222+
return ret;
223+
196224
ret = wolfSSL_CTX_SetEchConfigs(ctx, decodedConfigs, decodedLen);
197225

198226
XFREE(decodedConfigs, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER);
@@ -249,34 +277,17 @@ void wolfSSL_CTX_SetEchEnable(WOLFSSL_CTX* ctx, byte enable)
249277
int wolfSSL_SetEchConfigsBase64(WOLFSSL* ssl, const char* echConfigs64,
250278
word32 echConfigs64Len)
251279
{
252-
int ret = 0;
253-
word32 decodedLen = echConfigs64Len * 3 / 4 + 1;
280+
int ret;
281+
word32 decodedLen;
254282
byte* decodedConfigs;
255283

256-
if (ssl == NULL || echConfigs64 == NULL || echConfigs64Len == 0)
284+
if (ssl == NULL)
257285
return BAD_FUNC_ARG;
258286

259-
/* already have ech configs */
260-
if (ssl->echConfigs != NULL) {
261-
return WOLFSSL_FATAL_ERROR;
262-
}
263-
264-
decodedConfigs = (byte*)XMALLOC(decodedLen, ssl->heap,
265-
DYNAMIC_TYPE_TMP_BUFFER);
266-
267-
if (decodedConfigs == NULL)
268-
return MEMORY_E;
269-
270-
decodedConfigs[decodedLen - 1] = 0;
271-
272-
/* decode the echConfigs */
273-
ret = Base64_Decode((const byte*)echConfigs64, echConfigs64Len,
274-
decodedConfigs, &decodedLen);
275-
276-
if (ret != 0) {
277-
XFREE(decodedConfigs, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
287+
ret = DecodeEchConfigsBase64(ssl->heap, echConfigs64, echConfigs64Len,
288+
&decodedConfigs, &decodedLen);
289+
if (ret != 0)
278290
return ret;
279-
}
280291

281292
ret = wolfSSL_SetEchConfigs(ssl, decodedConfigs, decodedLen);
282293

@@ -418,8 +429,8 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
418429
output += 2;
419430
}
420431

421-
/* set maximum name length to 0 */
422-
*output = 0;
432+
/* maximum name len */
433+
*output = config->maxNameLen;
423434
output++;
424435

425436
/* publicName len */
@@ -430,7 +441,7 @@ int GetEchConfig(WOLFSSL_EchConfig* config, byte* output, word32* outputLen)
430441
XMEMCPY(output, config->publicName, publicNameLen);
431442
output += publicNameLen;
432443

433-
/* terminating zeros */
444+
/* no extensions, print zeros */
434445
c16toa(0, output);
435446
/* output += 2; */
436447

@@ -656,11 +667,12 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
656667
idx += 4;
657668
}
658669

659-
/* ignore maximum name length */
670+
/* maxNameLen */
660671
if (idx + 1 > length) {
661672
ret = BUFFER_E;
662673
break;
663674
}
675+
workingConfig->maxNameLen = echConfig[idx];
664676
idx += 1;
665677

666678
/* publicName */
@@ -701,7 +713,7 @@ int SetEchConfigsEx(WOLFSSL_EchConfig** outputConfigs, void* heap,
701713
}
702714

703715
ret = EchConfigCheckExtensions(echConfig + idx, extensionsLen);
704-
if (ret < 0)
716+
if (ret < 0 && ret != WC_NO_ERR_TRACE(UNSUPPORTED_EXTENSION))
705717
break;
706718

707719
/* KEM, ciphersuite, or mandatory extension not supported, free this

src/tls13.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4825,9 +4825,23 @@ int SendTls13ClientHello(WOLFSSL* ssl)
48254825
if (ret != 0)
48264826
return ret;
48274827

4828+
/* calculate padding (RFC 9849, section 6.1.3) */
4829+
if (args->ech->privateName != NULL) {
4830+
word16 nameLen = (word16)XSTRLEN(args->ech->privateName);
4831+
if (nameLen > args->ech->echConfig->maxNameLen)
4832+
args->ech->paddingLen = 0;
4833+
else
4834+
args->ech->paddingLen =
4835+
(word16)args->ech->echConfig->maxNameLen - nameLen;
4836+
}
4837+
else {
4838+
args->ech->paddingLen = args->ech->echConfig->maxNameLen + 9;
4839+
}
4840+
48284841
/* innerClientHelloLen and padding are based on the
48294842
* encoded (sealed) inner */
4830-
args->ech->paddingLen = 31 - ((encodedLen - 1) % 32);
4843+
args->ech->paddingLen += 31 -
4844+
((encodedLen + args->ech->paddingLen - 1) % 32);
48314845
args->ech->innerClientHelloLen = encodedLen +
48324846
args->ech->paddingLen + args->ech->hpke->Nt;
48334847

tests/api.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15066,8 +15066,10 @@ static int test_ech_server_ctx_ready(WOLFSSL_CTX* ctx)
1506615066
{
1506715067
int ret;
1506815068

15069-
ret = wolfSSL_CTX_GenerateEchConfig(ctx, echCbTestPublicName,
15070-
echCbTestKemID, echCbTestKdfID, echCbTestAeadID);
15069+
/* +20 for this isn't significant, it just exercises the padding code */
15070+
ret = wolfSSL_CTX_GenerateEchConfigEx(ctx, echCbTestPublicName,
15071+
echCbTestKemID, echCbTestKdfID, echCbTestAeadID,
15072+
XSTRLEN(echCbTestPublicName) + 20);
1507115073
if (ret != WOLFSSL_SUCCESS)
1507215074
return TEST_FAIL;
1507315075

wolfssl/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3147,6 +3147,7 @@ typedef struct WOLFSSL_EchConfig {
31473147
byte configId;
31483148
byte numCipherSuites;
31493149
byte receiverPubkey[HPKE_Npk_MAX];
3150+
byte maxNameLen;
31503151
} WOLFSSL_EchConfig;
31513152

31523153
typedef struct WOLFSSL_ECH {

wolfssl/ssl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1231,6 +1231,9 @@ WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void);
12311231
#if defined(WOLFSSL_TLS13) && defined(HAVE_ECH)
12321232
WOLFSSL_API int wolfSSL_CTX_GenerateEchConfig(WOLFSSL_CTX* ctx,
12331233
const char* publicName, word16 kemId, word16 kdfId, word16 aeadId);
1234+
WOLFSSL_API int wolfSSL_CTX_GenerateEchConfigEx(WOLFSSL_CTX* ctx,
1235+
const char* publicName, word16 kemId, word16 kdfId, word16 aeadId,
1236+
byte maxNameLen);
12341237

12351238
WOLFSSL_API int wolfSSL_CTX_SetEchConfigsBase64(WOLFSSL_CTX* ctx,
12361239
const char* echConfigs64, word32 echConfigs64Len);

0 commit comments

Comments
 (0)