use constant, state check in `decode_server_hello`
diff --git a/lib/picotls.c b/lib/picotls.c
index 323b23c..dcd332c 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -77,6 +77,8 @@
#define PTLS_ECH_CLIENT_HELLO_TYPE_OUTER 0
#define PTLS_ECH_CLIENT_HELLO_TYPE_INNER 1
+#define PTLS_ECH_CONFIRM_LENGTH 8
+
static const char ech_info_prefix[8] = "tls ech";
#define PTLS_SERVER_CERTIFICATE_VERIFY_CONTEXT_STRING "TLS 1.3, server CertificateVerify"
@@ -389,13 +391,13 @@
struct st_ptls_server_hello_t {
uint8_t random_[PTLS_HELLO_RANDOM_SIZE];
ptls_iovec_t legacy_session_id;
- ptls_iovec_t ech;
int is_retry_request;
union {
ptls_iovec_t peerkey;
struct {
uint16_t selected_group;
ptls_iovec_t cookie;
+ const uint8_t *ech;
} retry_request;
};
};
@@ -2566,13 +2568,15 @@
}
break;
case PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO:
- if (sh->is_retry_request && tls->ech.aead != NULL) {
- if (end - src != 8) {
- ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- goto Exit;
- }
+ if (!(tls->ech.offered && sh->is_retry_request)) {
+ ret = PTLS_ALERT_UNSUPPORTED_EXTENSION;
+ goto Exit;
}
- sh->ech = ptls_iovec_init(src, end - src);
+ if (end - src != PTLS_ECH_CONFIRM_LENGTH) {
+ ret = PTLS_ALERT_DECODE_ERROR;
+ goto Exit;
+ }
+ sh->retry_request.ech = src;
src = end;
break;
default:
@@ -2654,7 +2658,7 @@
static int client_ech_select_hello(ptls_t *tls, ptls_iovec_t message, size_t confirm_hash_off, const char *label)
{
- uint8_t confirm_hash_delivered[8], confirm_hash_expected[8];
+ uint8_t confirm_hash_delivered[PTLS_ECH_CONFIRM_LENGTH], confirm_hash_expected[PTLS_ECH_CONFIRM_LENGTH];
int ret = 0;
/* Determine if ECH has been accepted by checking the confirmation hash. `confirm_hash_off` set to zero indicates that HRR was
@@ -2701,7 +2705,7 @@
goto Exit;
key_schedule_transform_post_ch1hash(tls->key_schedule);
if (tls->ech.aead != NULL &&
- (ret = client_ech_select_hello(tls, message, sh.ech.base != NULL ? sh.ech.base - message.base : 0,
+ (ret = client_ech_select_hello(tls, message, sh.retry_request.ech != NULL ? sh.retry_request.ech - message.base : 0,
ECH_CONFIRMATION_HRR)) != 0)
goto Exit;
ptls__key_schedule_update_hash(tls->key_schedule, message.base, message.len, 0);
@@ -2713,15 +2717,11 @@
goto Exit;
/* check if ECH is accepted (at the same time rolling the hash) */
- static const size_t confirm_hash_off = PTLS_HANDSHAKE_HEADER_SIZE + 2 /* legacy_version */ + PTLS_HELLO_RANDOM_SIZE - 8;
+ static const size_t confirm_hash_off =
+ PTLS_HANDSHAKE_HEADER_SIZE + 2 /* legacy_version */ + PTLS_HELLO_RANDOM_SIZE - PTLS_ECH_CONFIRM_LENGTH;
if (tls->ech.aead != NULL &&
(ret = client_ech_select_hello(tls, message, confirm_hash_off, ECH_CONFIRMATION_SERVER_HELLO)) != 0)
goto Exit;
- /* When ECH is accepted, ServerHello MUST NOT contain an ECH extension (draft-15 section 5). */
- if (tls->ech.aead != NULL && sh.ech.base != NULL) {
- ret = PTLS_ALERT_UNSUPPORTED_EXTENSION;
- goto Exit;
- }
ptls__key_schedule_update_hash(tls->key_schedule, message.base, message.len, 0);
@@ -4341,11 +4341,11 @@
ptls_buffer_t *sendbuf = emitter->buf;
if (ptls_is_ech_handshake(tls, NULL, NULL)) {
buffer_push_extension(sendbuf, PTLS_EXTENSION_TYPE_ENCRYPTED_CLIENT_HELLO, {
- if ((ret = ptls_buffer_reserve(sendbuf, 8)) != 0)
+ if ((ret = ptls_buffer_reserve(sendbuf, PTLS_ECH_CONFIRM_LENGTH)) != 0)
goto Exit;
- memset(sendbuf->base + sendbuf->off, 0, 8);
+ memset(sendbuf->base + sendbuf->off, 0, PTLS_ECH_CONFIRM_LENGTH);
ech_confirm_off = sendbuf->off;
- sendbuf->off += 8;
+ sendbuf->off += PTLS_ECH_CONFIRM_LENGTH;
});
}
if (retry_uses_cookie) {
@@ -4479,8 +4479,8 @@
tls->ctx->random_bytes(emitter->buf->base + emitter->buf->off, PTLS_HELLO_RANDOM_SIZE);
/* when accepting CHInner, last 8 byte of SH.random is zero for the handshake transcript */
if (ptls_is_ech_handshake(tls, NULL, NULL)) {
- ech_confirm_off = emitter->buf->off + PTLS_HELLO_RANDOM_SIZE - 8;
- memset(emitter->buf->base + ech_confirm_off, 0, 8);
+ ech_confirm_off = emitter->buf->off + PTLS_HELLO_RANDOM_SIZE - PTLS_ECH_CONFIRM_LENGTH;
+ memset(emitter->buf->base + ech_confirm_off, 0, PTLS_ECH_CONFIRM_LENGTH);
}
},
{