summaryrefslogtreecommitdiff
path: root/docs/CHAT-OPENSSL-MIGRATION.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/CHAT-OPENSSL-MIGRATION.txt')
-rw-r--r--docs/CHAT-OPENSSL-MIGRATION.txt234
1 files changed, 234 insertions, 0 deletions
diff --git a/docs/CHAT-OPENSSL-MIGRATION.txt b/docs/CHAT-OPENSSL-MIGRATION.txt
new file mode 100644
index 0000000..4bb87fb
--- /dev/null
+++ b/docs/CHAT-OPENSSL-MIGRATION.txt
@@ -0,0 +1,234 @@
+Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+
+OPENSSL BACKEND MIGRATION RECORD
+
+ Date: 2026-10-30. Historical compatibility/dependency-security experiment
+ using disposable identities. For the later messenger and packaged deployment,
+ see CHAT-APPLICATION.txt and CHAT-PRODUCTION.txt.
+
+DECISION AND FIXED ALGORITHMS
+
+ Retain Sequoia OpenPGP 2.4.2, RFC 9980 ML-KEM-1024 + X448 encryption,
+ ML-DSA-87 + Ed448 signatures, OpenPGP v6 keys, and AES-256 content encryption.
+ Only the backend changes; algorithms and wire protocol stay fixed.
+ Probe assertions reject unexpected backends or key algorithms.
+
+ Previous Rust curve arithmetic reached cx448 0.1.1 -> crypto-bigint 0.5.5;
+ the backend also included rsa 0.9.10. Neither RustSec issue was ignored;
+ no mathematical implementation was patched locally.
+ RUSTSEC-2026-0387 affected required X448/Ed448 curve arithmetic, not unused RSA.
+ Its fix requires crypto-bigint >=0.7.6; cx448 0.1.1 requires incompatible 0.5.
+ A lockfile update alone could not fix it. No practical browser key-extraction
+ exploit was demonstrated; functional tests do not prove constant-time behavior.
+ The closed probe used no RSA private operations, but that did not establish
+ unreachability through hostile imports or future application interfaces.
+ https://rustsec.org/advisories/RUSTSEC-2026-0387.html
+ https://rustsec.org/advisories/RUSTSEC-2023-0071.html
+
+ Only crypto-openssl is enabled. allow-experimental-crypto and
+ allow-variable-time-crypto are removed. The resolved graph has no cx448,
+ crypto-bigint, or rsa crate. Removing those dependencies does not prove
+ absence of browser side channels or external C defects.
+
+VERSIONS AND SOURCE PROVENANCE
+
+ Rust toolchain: 1.99.1, pinned in rust-toolchain.toml.
+ Sequoia OpenPGP: 2.4.2, exact requirement and Cargo.lock.
+ OpenSSL: 3.6.5, native host library and source-built static WASI libraries.
+ WASI SDK: 34.0 x86_64 Linux, bundled Clang/libclang 23.1.0-wasi-sdk.
+ Browser test runner: Playwright 1.64.1, Chromium 156.0.8078.4.
+
+ SDK archive:
+ https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-34/wasi-sdk-34.0-x86_64-linux.tar.gz
+ SHA-256 b761e3a0721dbae9c09a0059e5fdb2bf917d1b4a8a7b430fb3b5aafb0984b2c4
+
+ OpenSSL archive:
+ https://github.com/openssl/openssl/releases/download/openssl-3.6.5/openssl-3.6.5.tar.gz
+ SHA-256 a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98
+
+ Digests match upstream GitHub release asset metadata; scripts verify them
+ before extraction. This pins inputs, without independently verifying release
+ signatures or proving cross-host bit-for-bit builds. Archives, SDK, libraries,
+ and build products stay under ignored .tools/ and target/. The OS supplies
+ the native development library.
+
+WHY WASI
+
+ The Rust proof used wasm32-unknown-unknown and wasm-bindgen glue. OpenSSL uses
+ a wasm32-wasip1 command and explicit browser WASI bridge, calling the native
+ tests' compatibility_probe. The browser loads this binary directly and
+ requires output identifying OpenSSL 3.6.5; stale Rust-backend artifacts cannot
+ count as OpenSSL evidence. Do not reuse historical browser-build commands.
+
+BUILD CONFIGURATION AND BOUNDARIES
+
+ infra/chat/openssl-wasi.conf adds a BASE_unix target with little-endian,
+ 32-bit bignums; cryptographic routines are unchanged. C uses -O2. No rand.patch,
+ unconditional entropy-success patch, or custom RNG is applied. SHA-256 checks
+ of all 5889 original regular files against the downloaded archive found none
+ changed or missing after build; only the target configuration was added.
+ OpenSSL 3.6.5 supports WASI getentropy in
+ providers/implementations/rands/seeding/rand_unix.c.
+
+ Configure selects --with-rand-seed=getrandom. WASI libc's entropy request
+ reaches wasi_snapshot_preview1.random_get. The browser bridge services it
+ exclusively through crypto.getRandomValues, splitting requests at 65536
+ bytes. There is no Math.random, fixed seed, or success-on-failure fallback.
+ The negative test replaces that API with a failure and requires rejection.
+
+ Static builds disable assembly, async operations, automatic config loading,
+ DSO/modules, POSIX I/O, secure-memory arenas, shared libraries, sockets,
+ C stdio, thread pools, threads, and interactive console UI to avoid unsupported
+ capabilities. Ordinary WASM linear memory provides no secure-erasure,
+ locked-page, or delivered-JS protection. Rust output remains captured.
+
+ _WASI_EMULATED_GETPID and libwasi-emulated-getpid supply SDK process-ID emulation.
+ getuid/geteuid/getgid/getegid map to getpagesize, following common WASI port
+ configuration. The browser module has no real OS user IDs or privilege boundary.
+ These values supply neither randomness nor identity credentials. This portability
+ assumption does not emulate general POSIX security.
+
+ Bindings use SDK libclang/WASI sysroot, target wasm32-wasip1, and
+ -fvisibility=default; without explicit visibility, bindgen omitted declarations.
+ Rust's bundled WASI libc precedes SDK libraries; reversed order failed to link
+ __wasi_init_tp. SDK libraries remain available for emulated-getpid. These were
+ toolchain integration failures; generated cryptographic bindings were not edited.
+
+BROWSER CAPABILITIES
+
+ The WASI bridge supplies clocks, browser CSPRNG, empty arguments/environment,
+ EOF on stdin, and bounded in-memory stdout/stderr for this closed test.
+ It supplies no real files, preopened directories, sockets, or process launch.
+ Listed filesystem/network operations return NOTCAPABLE or BADF. Unknown
+ imports fail before instantiation. Standard output is capped at 65536 chars.
+
+ Denials prevent accidental host storage/network access, not malicious JS from
+ the same server. Memory, clocks, randomness, and bridge imports remain trusted.
+ The test closes Chromium after 120 seconds if execution stalls.
+
+VERIFICATION
+
+ Native: the same probe passes using OpenSSL 3.6.5. It checks v6 generation,
+ exact algorithm selection, protected-secret-key serialization/import,
+ signed UTF-8 encryption to both participants, decryption by each, wrong
+ password rejection, unexpected signer rejection, and ciphertext tampering.
+
+ Browser: actual Chromium executes the OpenSSL WASI binary and passes the
+ same checks, then repeats with a fresh module instance. One observed normal
+ execution requested 1792 bytes across 72 browser CSPRNG calls. These counts
+ are observations, not cryptographic requirements or entropy estimates.
+ Removing secure randomness causes failure rather than a successful result.
+ A modified module requesting an unknown host import is also rejected before
+ instantiation. These negative tests require the expected failure reason.
+
+ The harness observed no external requests, cookies, localStorage,
+ sessionStorage, IndexedDB databases, or service-worker registrations; responses
+ carry Cache-Control: no-store. This concerns only the probe. Browsers/OSes can
+ retain memory, caches, crash dumps, swap, and restored state. No complete chat
+ session existed at this checkpoint. Native tests, WASI build, and browser
+ execution are separate gates; functional tests and scans are not cryptographic
+ or side-channel audits.
+
+DEPENDENCY POLICY REVIEW
+
+ RustSec reports no advisories for this resolved graph; no ignore was added.
+ Bans on wildcards, unknown Git/registry sources, and unreviewed duplicates remain.
+ cargo update cannot unify these upstream API generations. Exceptions match only
+ exact older versions; advisory/license checks still apply. Cargo.lock pins both sides:
+
+ block-buffer 0.10.4 vs 0.12.1
+ crypto-common 0.1.7 vs 0.2.2
+ digest 0.10.7 vs 0.11.3
+ Sequoia's Argon2 0.5.3 -> BLAKE2 0.10 uses the older digest API.
+ Root SHA-256 and the parser generator's SHA3 use the newer API.
+
+ cpufeatures 0.2.17 vs 0.3.1
+ Argon2 uses 0.2; root SHA-256 and parser-generator SHA3 use 0.3.
+
+ generic-array 0.14.7 vs 1.4.5
+ Argon2/BLAKE2 digest uses 0.14; SHA1 collision detection uses 1.x.
+
+ getrandom 0.2.17 vs 0.4.3
+ Sequoia's unknown-unknown WASM target dependencies declare 0.2;
+ the root CLI's tempfile uses 0.4. The current browser target is WASI,
+ whose OpenSSL entropy source is the bridge described above. The
+ all-target graph is still audited rather than excluding that edge.
+
+ hashbrown 0.15.5 vs 0.17.1
+ petgraph uses 0.15 directly and indexmap 2.14 uses 0.17. Both are
+ brought in by the parser generator at build time.
+
+ itertools 0.13.0 vs 0.15.0
+ shlex 1.3.0 vs 2.0.1
+ bindgen uses older APIs; lalrpop and cc require the newer ones.
+ These are build dependencies, not a justification to skip auditing.
+
+ syn 2.0.119 vs 3.0.9
+ bindgen/prettyplease and Windows support use syn 2. Root derive
+ macros and other dependencies use syn 3. Changing that would require
+ upstream migration or unrelated dependency downgrades.
+
+ The only new license allowance is ISC for bindgen/clang's libloading.
+ GNU-compatible licenses retain attribution; cargo-about covers the workspace.
+ OpenSSL C and SDK are outside Cargo. Distributed browser artifacts must carry
+ their original licenses/sources as required. OpenSSL LICENSE.txt is Apache-2.0.
+ Rust notices alone do not cover external C/toolchain distribution obligations.
+
+EXTERNAL LIBRARY MAINTENANCE
+
+ cargo-deny excludes external OpenSSL C and SDK. Review separately; rebuild as needed:
+ https://openssl-library.org/news/timeline/
+ https://openssl-library.org/news/vulnerabilities-3.6/
+ Tested OpenSSL 3.6.5 is the 2026-09-29 security-patch release. A Rust audit
+ does not guarantee this pinned C version's future security. Document a supported
+ update policy before production deployment.
+
+REPRODUCE FROM THE STACK ROOT
+
+ Native prerequisites: OpenSSL >=3.5 development headers/library, libclang,
+ pkg-config, and the pinned Rust toolchain. For the cross build also provide
+ a Linux x86_64 build host, Perl, make, curl, tar, and sha256sum. No root-owned
+ packages or system settings are changed by the cross-build script.
+
+ cargo test --locked -p stack-chat-crypto
+ cargo run --locked -p stack-chat-crypto
+ sh infra/chat/build-openssl-wasi.sh
+ npm run build
+ PLAYWRIGHT_BROWSERS_PATH="$PWD/.tools/browsers" node_modules/.bin/playwright install chromium
+ PLAYWRIGHT_BROWSERS_PATH="$PWD/.tools/browsers" npm run test:crypto
+ cargo stack check
+
+ The script pins versions/hashes, builds static OpenSSL under .tools/openssl-wasi,
+ builds the Rust WASI command, and prints its SHA-256. It uses no unverified
+ precompiled OpenSSL. Extracted sources may be reused; independent verification
+ needs a fresh ignored tools/build tree. Downloads/test artifacts are not secrets.
+
+ Build logs and complete dependency trees are local ignored diagnostics in
+ .tools/chat-openssl-*.log and .tools/chat-openssl-duplicates.txt. The native
+ result and the browser result must explicitly identify the OpenSSL backend.
+
+REMAINING WORK
+
+ Observed WASI artifact SHA-256 on this development machine:
+ 7fba6b96377619ef41f056d4027c4409107372e9300b2dd69be865e72892df79
+ This is a diagnostic identifier, not a cross-host reproducibility promise.
+
+ This checkpoint removed the Rust-backend blocker and demonstrated fixed
+ algorithms in-browser. It was not a complete messenger, OpenSSL/WASI/JIT timing
+ audit, LibreJS certification, or proof against malicious delivery. File format,
+ authentication, server/database, quotas, hostile-input handling, pagination/counts,
+ recovery, session lifecycle, and browser-state tests remained to implement.