Commit fe9c29d0a1 for openssl.org
commit fe9c29d0a1f1e5b075660c32568ef4b5da85a70a
Author: Jakub Zelenka <jakub.zelenka@openssl.foundation>
Date: Sun Oct 4 15:40:23 2026 +0200
Omit key_share from a cookie-only HelloRetryRequest
When the server requires a HelloRetryRequest cookie and the client is
resuming with a PSK-only key exchange, no (EC)DHE group is selected, so
there is no key_share to process and the group id stays at zero. The
HelloRetryRequest construction still treated a missing peer key share
as "ask for a different group" and emitted a key_share extension naming
group 0, which the client rightly rejects with illegal_parameter.
Only include key_share in the HelloRetryRequest when a different group
was actually selected, and record the same decision in the cookie so the
transcript is reconstructed correctly on the second ClientHello.
A DTLS test for this follows with the SSL_OP_COOKIE_EXCHANGE change that
exposed it. SSL_stateless() cannot be used for it since it fails the PSK
binder check on the second ClientHello for an unrelated reason.
Assisted-by: Claude:claude-fable-5-1
Reviewed-by: Matt Caswell <matt@openssl.foundation>
Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
Merge-date: Tue Oct 6 14:46:54 2026
Merged-from: https://github.com/openssl/openssl/pull/33093
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 02ff6e8106..e3a25e2bd3 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -2020,6 +2020,12 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL_CONNECTION *s, WPACKET *pkt
return EXT_RETURN_SENT;
}
+/* Does the HelloRetryRequest ask the client for a different key_share? */
+static int hrr_sends_key_share(const SSL_CONNECTION *s)
+{
+ return s->s3.peer_tmp == NULL && s->s3.group_id != 0;
+}
+
EXT_RETURN tls_construct_stoc_key_share(SSL_CONNECTION *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
@@ -2031,10 +2037,8 @@ EXT_RETURN tls_construct_stoc_key_share(SSL_CONNECTION *s, WPACKET *pkt,
const TLS_GROUP_INFO *ginf = NULL;
if (s->hello_retry_request == SSL_HRR_PENDING) {
- if (ckey != NULL) {
- /* Original key_share was acceptable so don't ask for another one */
+ if (!hrr_sends_key_share(s))
return EXT_RETURN_NOT_SENT;
- }
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->s3.group_id)
@@ -2205,7 +2209,7 @@ EXT_RETURN tls_construct_stoc_cookie(SSL_CONNECTION *s, WPACKET *pkt,
|| !ssl->method->put_cipher_by_char(s->s3.tmp.new_cipher, pkt,
&ciphlen)
/* Is there a key_share extension present in this HRR? */
- || !WPACKET_put_bytes_u8(pkt, s->s3.peer_tmp == NULL)
+ || !WPACKET_put_bytes_u8(pkt, hrr_sends_key_share(s))
|| !WPACKET_put_bytes_u64(pkt, time(NULL))
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {