Improve RFC 8446 PSK key exchange mode compliance
It's a MUST-level requirement that if the client sends a pre_shared_key
extension not accompanied by a psk_key_exchange_modes extension, the
server must abort the handshake.  Prior to this commit the server
would continue on.
@@ -57,6 +57,7 @@ static int final_sig_algs(SSL *s, unsigned int context, int sent);
static int final_early_data(SSL *s, unsigned int context, int sent);
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
static int init_post_handshake_auth(SSL *s, unsigned int context);
+static int final_psk(SSL *s, unsigned int context, int sent);
/* Structure to define a built-in extension */
typedef struct extensions_definition_st {
@@ -381,7 +382,7 @@ static const EXTENSION_DEFINITION ext_defs[] = {
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
- tls_construct_ctos_psk, NULL
+ tls_construct_ctos_psk, final_psk
}
};
@@ -1676,3 +1677,19 @@ static int init_post_handshake_auth(SSL *s, ossl_unused unsigned int context)
return 1;
}
+
+/*
+ * If clients offer "pre_shared_key" without a "psk_key_exchange_modes"
+ * extension, servers MUST abort the handshake.
+ */
+static int final_psk(SSL *s, unsigned int context, int sent)
+{
+ if (s->server && sent && s->clienthello != NULL
+ && !s->clienthello->pre_proc_exts[TLSEXT_IDX_psk_kex_modes].present) {
+ SSLfatal(s, TLS13_AD_MISSING_EXTENSION,
+ SSL_R_MISSING_PSK_KEX_MODES_EXTENSION);
+ return 0;
+ }
+
+ return 1;
+}
