provided parameters found in legacy CH
diff --git a/lib/picotls.c b/lib/picotls.c
index 78fa0f1..1355ed7 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -286,6 +286,7 @@
#define MAX_CLIENT_CIPHERS 32
struct st_ptls_client_hello_t {
+ uint16_t legacy_version;
const uint8_t *random_bytes;
ptls_iovec_t legacy_session_id;
struct {
@@ -331,7 +332,8 @@
size_t count;
} identities;
unsigned ke_modes;
- int early_data_indication;
+ unsigned early_data_indication : 1;
+ unsigned is_last_extension : 1;
} psk;
ptls_raw_extension_t unknown_extensions[MAX_UNKNOWN_EXTENSIONS + 1];
unsigned status_request : 1;
@@ -3144,14 +3146,12 @@
uint16_t exttype = 0;
int ret;
- { /* check protocol version */
- uint16_t protver;
- if ((ret = ptls_decode16(&protver, &src, end)) != 0)
- goto Exit;
- if (protver != 0x0303) {
- ret = PTLS_ALERT_HANDSHAKE_FAILURE;
- goto Exit;
- }
+ /* decode protocol version (do not bare to decode something older than TLS 1.0) */
+ if ((ret = ptls_decode16(&ch->legacy_version, &src, end)) != 0)
+ goto Exit;
+ if (ch->legacy_version < 0x0301) {
+ ret = PTLS_ALERT_PROTOCOL_VERSION;
+ goto Exit;
}
/* skip random */
@@ -3201,6 +3201,7 @@
/* decode extensions */
decode_extensions(src, end, PTLS_HANDSHAKE_TYPE_CLIENT_HELLO, &exttype, {
+ ch->psk.is_last_extension = 0;
if (tls->ctx->on_extension != NULL &&
(ret = tls->ctx->on_extension->cb(tls->ctx->on_extension, tls, PTLS_HANDSHAKE_TYPE_CLIENT_HELLO, exttype,
ptls_iovec_init(src, end - src)) != 0))
@@ -3379,6 +3380,7 @@
goto Exit;
}
});
+ ch->psk.is_last_extension = 1;
} break;
case PTLS_EXTENSION_TYPE_PSK_KEY_EXCHANGE_MODES:
ptls_decode_block(src, end, 1, {
@@ -3405,37 +3407,6 @@
src = end;
});
- /* check if client hello make sense */
- if (is_supported_version(ch->selected_version)) {
- if (!(ch->compression_methods.count == 1 && ch->compression_methods.ids[0] == 0)) {
- ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- goto Exit;
- }
- /* esni */
- if (ch->esni.cipher != NULL) {
- if (ch->key_shares.base == NULL) {
- ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- goto Exit;
- }
- }
- /* pre-shared key */
- if (ch->psk.hash_end != NULL) {
- /* PSK must be the last extension */
- if (exttype != PTLS_EXTENSION_TYPE_PRE_SHARED_KEY) {
- ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- goto Exit;
- }
- } else {
- if (ch->psk.early_data_indication) {
- ret = PTLS_ALERT_ILLEGAL_PARAMETER;
- goto Exit;
- }
- }
- } else {
- ret = PTLS_ALERT_PROTOCOL_VERSION;
- goto Exit;
- }
-
ret = 0;
Exit:
return ret;
@@ -3633,7 +3604,7 @@
additional_extensions \
} while (0); \
})
- struct st_ptls_client_hello_t ch = {NULL, {NULL}, {NULL}, 0, {NULL}, {NULL}, {NULL}, {{0}},
+ struct st_ptls_client_hello_t ch = {0, NULL, {NULL}, {NULL}, 0, {NULL}, {NULL}, {NULL}, {{0}},
{NULL}, {NULL}, {{{NULL}}}, {{0}}, {{0}}, {{NULL}}, {NULL}, {{UINT16_MAX}}};
struct {
ptls_key_exchange_algorithm_t *algorithm;
@@ -3648,6 +3619,47 @@
if ((ret = decode_client_hello(tls, &ch, message.base + PTLS_HANDSHAKE_HEADER_SIZE, message.base + message.len, properties)) !=
0)
goto Exit;
+
+ /* check if ClientHello makes sense */
+ if (!(ch.legacy_version == 0x0303 && is_supported_version(ch.selected_version))) {
+ if (!is_second_flight && tls->ctx->on_client_hello != NULL) {
+ ptls_on_client_hello_parameters_t params = {
+ .server_name = ch.server_name,
+ .raw_message = message,
+ .negotiated_protocols = {ch.alpn.list, ch.alpn.count},
+ .incompatible_version = 1,
+ };
+ if ((ret = tls->ctx->on_client_hello->cb(tls->ctx->on_client_hello, tls, ¶ms)) != 0)
+ goto Exit;
+ }
+ ret = PTLS_ALERT_PROTOCOL_VERSION;
+ goto Exit;
+ }
+ if (!(ch.compression_methods.count == 1 && ch.compression_methods.ids[0] == 0)) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ /* esni */
+ if (ch.esni.cipher != NULL) {
+ if (ch.key_shares.base == NULL) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+ /* pre-shared key */
+ if (ch.psk.hash_end != NULL) {
+ /* PSK must be the last extension */
+ if (!ch.psk.is_last_extension) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ } else {
+ if (ch.psk.early_data_indication) {
+ ret = PTLS_ALERT_ILLEGAL_PARAMETER;
+ goto Exit;
+ }
+ }
+
if (tls->ctx->require_dhe_on_psk)
ch.psk.ke_modes &= ~(1u << PTLS_PSK_KE_MODE_PSK);