java-topology/defects/openssl/patch/openssl-0001.patch
russell@unturf.com 9934133dcf whitepaper: 312 sites / 151 ecosystems — wave2+3 defect tables and PDF rebuild
Add 88 new defect entries to HIGH and MEDIUM tables:
  HIGH: mysql-0001/0002, mariadb-0001, redis-0001/0002, valkey-0001/0002, openvpn-0001,
        vlc-0001, prometheus-0001, otel-collector-0001, cockroachdb-0001..0004,
        tidb-0001..0008, kubernetes-0001/0002, go-0001, kotlin-0002, scala-0001,
        allegro5-0001, sdl2-0001, grafana-0001, clickhouse-0001, duckdb-0001,
        mongodb-0001, envoy-0001, istio-0001, cilium-0001, linkerd2-0001,
        linux-0001/0002/0003, tor-0002/0003, curl-0001, julia-0001, lua-0001,
        perl5-0001, nats-0001, spring-0003/0004, tomcat-0001, onos-0002, odl-0002

  MEDIUM: helm-0001, mariadb-0002, openssl-0001/0002, memcached-0001,
          cassandra-0001..0004, flink-0001, storm-0001/0002, zookeeper-0001..0003,
          pip-0001, gradle-0001, nginx-0001, haproxy-0001, caddy-0001, varnish-0001,
          ffmpeg-0001, gstreamer-0001, raylib-0001, love2d-0001, php-0001/0002,
          r-source-0001, cpython-0002, ruby-0001, rabbitmq-0003/0004, activemq-0001,
          ovs-0001, onos-0003, odl-0002, jetty-0001

PDF: 976K
2026-03-27 15:23:43 -04:00

59 lines
2.3 KiB
Diff

From b8df87a Mon Sep 17 00:00:00 2001
Subject: [CWE-407] ssl_lib: fix O(n²) SSL_get_shared_ciphers via hash-set membership
SSL_get_shared_ciphers() iterated all client ciphers and called
sk_SSL_CIPHER_find() on the unsorted server stack for each one.
sk_SSL_CIPHER_find() on an unsorted stack falls through to a linear
scan (see crypto/stack/stack.c:internal_find), making the total
complexity O(n*m).
Fix: build a 64-bit bitmask of server cipher IDs before the loop.
All TLS cipher IDs fit in 32 bits; we use a simple open-addressing
hash table of size 256 (power-of-two, load ≤ 50% for typical lists
of ≤128 ciphers) so lookup is O(1) expected.
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -3594,6 +3594,8 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size)
{
char *p;
STACK_OF(SSL_CIPHER) *clntsk, *srvrsk;
+ uint32_t srvr_ids[256]; /* open-addressing hash set, 0 = empty slot */
+ int srvr_count, j;
const SSL_CIPHER *c;
int i;
const SSL_CONNECTION *sc = SSL_CONNECTION_FROM_CONST_SSL(s);
@@ -3610,12 +3612,30 @@ char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size)
if (clntsk == NULL || sk_SSL_CIPHER_num(clntsk) == 0
|| srvrsk == NULL || sk_SSL_CIPHER_num(srvrsk) == 0)
return buf;
+
+ /* Build O(1) membership set from server ciphers.
+ * Table size 256, probe = linear, load kept ≤ 50%. */
+ memset(srvr_ids, 0, sizeof(srvr_ids));
+ srvr_count = sk_SSL_CIPHER_num(srvrsk);
+ for (j = 0; j < srvr_count; j++) {
+ uint32_t id = sk_SSL_CIPHER_value(srvrsk, j)->id;
+ unsigned slot = (id * 2654435761u) >> 24; /* Knuth multiplicative hash */
+ while (srvr_ids[slot] != 0 && srvr_ids[slot] != id)
+ slot = (slot + 1) & 0xff;
+ srvr_ids[slot] = id;
+ }
for (i = 0; i < sk_SSL_CIPHER_num(clntsk); i++) {
int n;
+ uint32_t id;
+ unsigned slot;
c = sk_SSL_CIPHER_value(clntsk, i);
- if (sk_SSL_CIPHER_find(srvrsk, c) < 0)
- continue;
+ id = c->id;
+ slot = (id * 2654435761u) >> 24;
+ while (srvr_ids[slot] != 0 && srvr_ids[slot] != id)
+ slot = (slot + 1) & 0xff;
+ if (srvr_ids[slot] != id)
+ continue; /* not in server set */
n = (int)OPENSSL_strnlen(c->name, size);
if (n >= size)