Repository navigation
Commit 4135f55
Fix out-of-bounds valid_flags access after SSL_set_SSL_CTX()
SSL_new() sizes the connection-local signature algorithm state from the
SSL_CTX the connection was created from: sc->ssl_pkey_num counts the
built-in certificate slots plus one for each of that context's provider
TLS-SIGALG entries, and s3.tmp.valid_flags is later allocated to match.
SSL_set_SSL_CTX() installs a duplicate of the replacement context's CERT
but leaves both of those describing the original context. Peer signature
algorithm codepoints are subsequently resolved against the replacement
context, where a provider sigalg's sig_idx is simply its position in
that context's list. If the replacement context advertises more provider
sigalgs than the original, a codepoint occupying one of the excess slots
yields an index past the end of valid_flags.
The usual route is a switch from the servername callback, which runs
before tls1_set_server_sigalgs() allocates the buffer: the stale
ssl_pkey_num undersizes the allocation, and tls1_process_sigalgs() then
reads one 4-byte word past the end for each such codepoint the peer
offered, and writes CERT_PKEY_EXPLICIT_SIGN|CERT_PKEY_SIGN where that
word already reads zero. The peer chooses how many of these accesses
occur, and at which offsets, by selecting which codepoints to send.
Refresh ssl_pkey_num from the newly installed CERT and, where a
valid_flags buffer already exists, replace it with one sized for that
context. A count which is too large is wrong in the same way as one that
is too small: loops bounded by ssl_pkey_num index cert->pkeys, which the
replacement context sizes. The replacement buffer is allocated before
the point at which the switch is committed, so that a failure can still
be reported rather than leaving the connection half switched.
The built-in slots are copied across rather than zeroed. They may
already hold peer signature algorithm state which is not derived from
the SSL_CTX, and nothing recomputes it after a context switch: at TLS
1.2 and above tls1_check_chain() only ORs CERT_PKEY_SIGN and
CERT_PKEY_EXPLICIT_SIGN in from the existing value, and ssl_set_masks()
needs them to enable ECDSA, Ed25519 and Ed448. Zeroing them makes a
TLSv1.2 handshake with an ECDSA certificate fail with "no shared
cipher". The provider slots are positional and context specific, so they
are reset.
Fixes CVE-2026-72897
Assisted-by: Claude Code:claude-opus-5[1m]
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Merge-date: Tue Sep 29 11:22:11 20261 parent 906cf0e commit 4135f55
1 file changed
Lines changed: 35 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5485 | 5485 | | |
5486 | 5486 | | |
5487 | 5487 | | |
| 5488 | + | |
5488 | 5489 | | |
5489 | 5490 | | |
5490 | 5491 | | |
| |||
5509 | 5510 | | |
5510 | 5511 | | |
5511 | 5512 | | |
| 5513 | + | |
| 5514 | + | |
| 5515 | + | |
| 5516 | + | |
| 5517 | + | |
| 5518 | + | |
| 5519 | + | |
| 5520 | + | |
| 5521 | + | |
| 5522 | + | |
| 5523 | + | |
| 5524 | + | |
| 5525 | + | |
| 5526 | + | |
| 5527 | + | |
| 5528 | + | |
| 5529 | + | |
| 5530 | + | |
| 5531 | + | |
| 5532 | + | |
| 5533 | + | |
| 5534 | + | |
| 5535 | + | |
| 5536 | + | |
| 5537 | + | |
| 5538 | + | |
| 5539 | + | |
| 5540 | + | |
5512 | 5541 | | |
5513 | 5542 | | |
5514 | 5543 | | |
| |||
5525 | 5554 | | |
5526 | 5555 | | |
5527 | 5556 | | |
| 5557 | + | |
| 5558 | + | |
| 5559 | + | |
| 5560 | + | |
| 5561 | + | |
5528 | 5562 | | |
5529 | 5563 | | |
5530 | 5564 | | |
5531 | 5565 | | |
5532 | 5566 | | |
5533 | 5567 | | |
| 5568 | + | |
5534 | 5569 | | |
5535 | 5570 | | |
5536 | 5571 | | |
| |||
0 commit comments