wave11: 488/227 — ROS2/OpenCV/Open3D/metaflow/kubeflow/optuna/openssl/mbedtls/wolfssl + Kafka Streams/Pulsar

This commit is contained in:
russell@unturf.com 2026-03-27 17:31:52 -04:00
parent 6276aea2e5
commit 19333b378e
36 changed files with 4634 additions and 5 deletions

View file

@ -0,0 +1,182 @@
package unit;
import java.util.HashMap;
/**
* mbedtls-0002 unit test
*
* Models the O(S×C×D) cipher suite selection in ssl_tls12_server.c
* and the O(S+C) fixed version using a hash set of client-offered IDs.
*
* Compile: javac -d . MbedTlsCipherSelectTest.java
* Run: java unit.MbedTlsCipherSelectTest
*/
public class MbedTlsCipherSelectTest {
// Simulated ciphersuite_definitions table (D entries)
static final int[] CIPHER_DEFINITIONS;
static {
// Representative TLS 1.2 cipher suite IDs (a subset of the ~70 in mbedTLS)
CIPHER_DEFINITIONS = new int[]{
0xC02B, // TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
0xC02C, // TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
0xC02F, // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
0xC030, // TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
0xCCA9, // TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
0xCCA8, // TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
0xC009, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
0xC013, // TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
0x002F, // TLS_RSA_WITH_AES_128_CBC_SHA
0x0035, // TLS_RSA_WITH_AES_256_CBC_SHA
0x003C, // TLS_RSA_WITH_AES_128_CBC_SHA256
0x003D, // TLS_RSA_WITH_AES_256_CBC_SHA256
0x009C, // TLS_RSA_WITH_AES_128_GCM_SHA256
0x009D, // TLS_RSA_WITH_AES_256_GCM_SHA384
0xC023, // TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
0xC024, // TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
};
}
// O(D) linear lookup — mirrors mbedtls_ssl_ciphersuite_from_id
static boolean cipherDefinitionExists(int id) {
for (int def : CIPHER_DEFINITIONS) {
if (def == id) return true;
}
return false;
}
// ------------------------------------------------------------------ //
// DEFECTIVE: O(S × C × D) //
// server-preference mode (most common): for each server suite, //
// scan all client suites; on match, call ciphersuite_match (O(D)) //
// ------------------------------------------------------------------ //
static int defectiveSelect(int[] serverSuites, int[] clientSuites) {
for (int sid : serverSuites) {
for (int cid : clientSuites) {
if (cid == sid) {
// ssl_ciphersuite_match calls mbedtls_ssl_ciphersuite_from_id (O(D))
if (cipherDefinitionExists(sid))
return sid;
}
}
}
return -1;
}
// ------------------------------------------------------------------ //
// FIXED: O(S + C) — hash set of client IDs, O(1) membership test //
// ------------------------------------------------------------------ //
static int fixedSelect(int[] serverSuites, int[] clientSuites) {
// Build hash set of client IDs — O(C)
HashMap<Integer, Boolean> clientSet = new HashMap<>();
for (int cid : clientSuites) clientSet.put(cid, Boolean.TRUE);
// Iterate server list — O(S), each lookup O(1)
for (int sid : serverSuites) {
if (clientSet.containsKey(sid)) {
// ciphersuite_match still needed, but only on actual matches
if (cipherDefinitionExists(sid))
return sid;
}
}
return -1;
}
// ------------------------------------------------------------------ //
// Counting versions //
// ------------------------------------------------------------------ //
static long[] ops = new long[2]; // [defective, fixed]
static int defectiveCounting(int[] server, int[] client) {
for (int sid : server) {
for (int cid : client) {
ops[0]++; // inner comparison
if (cid == sid) {
for (int def : CIPHER_DEFINITIONS) {
ops[0]++; // O(D) lookup
if (def == sid) return sid;
}
}
}
}
return -1;
}
static int fixedCounting(int[] server, int[] client) {
HashMap<Integer, Boolean> cs = new HashMap<>();
for (int cid : client) { ops[1]++; cs.put(cid, Boolean.TRUE); }
for (int sid : server) {
ops[1]++;
if (cs.containsKey(sid)) {
for (int def : CIPHER_DEFINITIONS) {
ops[1]++;
if (def == sid) return sid;
}
}
}
return -1;
}
static int pass = 0, fail = 0;
static void check(String label, boolean cond) {
if (cond) { System.out.println(" PASS " + label); pass++; }
else { System.out.println(" FAIL " + label); fail++; }
}
public static void main(String[] args) {
System.out.println("=== mbedtls-0002: TLS 1.2 cipher selection O(S×C×D) defect ===\n");
// Server prefers ECDHE-ECDSA-AES128-GCM, then ECDHE-RSA-AES128-GCM
int[] serverList = {0xC02B, 0xC02F, 0x002F};
// Test 1: first server suite matches
int[] client1 = {0xC02F, 0xC02B, 0x0000};
check("defective: picks server-preferred 0xC02B",
defectiveSelect(serverList, client1) == 0xC02B);
check("fixed: picks server-preferred 0xC02B",
fixedSelect(serverList, client1) == 0xC02B);
// Test 2: only second server suite matches
int[] client2 = {0xC02F, 0x0035};
check("defective: picks 0xC02F (second server entry)",
defectiveSelect(serverList, client2) == 0xC02F);
check("fixed: picks 0xC02F (second server entry)",
fixedSelect(serverList, client2) == 0xC02F);
// Test 3: no common suite
int[] client3 = {0x0004, 0x0005, 0x000A};
check("defective: no match → -1", defectiveSelect(serverList, client3) == -1);
check("fixed: no match → -1", fixedSelect(serverList, client3) == -1);
// Test 4: complexity — adversarial large client list with no match
// (no-match is worst case: defective must scan all S*C combinations)
int S = 20;
int C = 300;
int D = CIPHER_DEFINITIONS.length;
int[] bigServer = new int[S];
for (int i = 0; i < S; i++)
bigServer[i] = 0x1000 + i; // server suites NOT in CIPHER_DEFINITIONS
// client sends C unknown IDs → no match, full O(S*C) scan
int[] bigClient = new int[C];
for (int i = 0; i < C; i++) bigClient[i] = 0x9000 + i;
ops[0] = 0; ops[1] = 0;
int rd = defectiveCounting(bigServer, bigClient);
int rf = fixedCounting(bigServer, bigClient);
System.out.println("\n Complexity comparison (S=" + S + ", C=" + C + ", D=" + D + ", no-match):");
System.out.println(" Defective ops: " + ops[0] + " (expected ~" + ((long)S * C) + ")");
System.out.println(" Fixed ops: " + ops[1] + " (expected ~" + (S + C) + ")");
System.out.printf(" Speedup: %.1fx%n", (double) ops[0] / ops[1]);
check("defective and fixed agree on result (both -1)", rd == rf && rd == -1);
check("defective ops > 5x fixed ops (quadratic vs linear)",
ops[0] > 5 * ops[1]);
System.out.println("\n--- " + (pass + fail) + " tests: " + pass + " passed, " + fail + " failed ---");
if (fail > 0) System.exit(1);
}
}