summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 17:24:45 -0500
committerDoan Luu Duc Tai <doan@luuduct.ai>2026-10-30 17:24:45 -0500
commitcf2f0e8c6752c401f152a8e534ba166839d4307e (patch)
treea495aee0cbdc111cd9773f7d2d02753cd1d778d5 /docs
parentf196c27faf265cd14d8d7accf58e87b4df3c8a91 (diff)
Prove OpenSSL PQ crypto in browser WASI and document the migration
Diffstat (limited to 'docs')
-rw-r--r--docs/CHAT-DESIGN.txt4
-rw-r--r--docs/CHAT-OPENSSL-MIGRATION.txt253
-rw-r--r--docs/CHAT-SECURITY-REVIEW.txt5
-rw-r--r--docs/POLICY.txt6
4 files changed, 264 insertions, 4 deletions
diff --git a/docs/CHAT-DESIGN.txt b/docs/CHAT-DESIGN.txt
index 7b2a14f..7b8849c 100644
--- a/docs/CHAT-DESIGN.txt
+++ b/docs/CHAT-DESIGN.txt
@@ -111,7 +111,9 @@ LIBREJS AND LICENSING
REMAINING RELIABILITY WORK
- Resolve the blocking review in CHAT-SECURITY-REVIEW.txt. Then implement and
+ The OpenSSL compatibility experiment is in CHAT-OPENSSL-MIGRATION.txt.
+ It supersedes the original backend gate, not the remaining application review.
+ Implement and
test file creation/import, recovery confirmation, signed one-use challenges,
authorization, encrypted sends/replies, replay rejection, N=0 and pagination,
authenticated counters, quotas, rate limits, hostile file and packet limits,
diff --git a/docs/CHAT-OPENSSL-MIGRATION.txt b/docs/CHAT-OPENSSL-MIGRATION.txt
new file mode 100644
index 0000000..17149ac
--- /dev/null
+++ b/docs/CHAT-OPENSSL-MIGRATION.txt
@@ -0,0 +1,253 @@
+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. Branch: feature/private-chat.
+ Scope: a compatibility and dependency-security experiment, not a messenger.
+ Main and production are unchanged. No real identity files are created.
+
+DECISION AND FIXED ALGORITHMS
+
+ Retain Sequoia OpenPGP 2.4.2 and RFC 9980 ML-KEM-1024 + X448 encryption.
+ Retain ML-DSA-87 + Ed448 signatures, OpenPGP v6 keys, and AES-256 content
+ encryption. Change the cryptographic backend, not the algorithms or wire
+ protocol. Probe assertions reject an unexpected backend or key algorithms.
+
+ The previous Rust backend reached cx448 0.1.1 -> crypto-bigint 0.5.5 during
+ curve arithmetic. It also included rsa 0.9.10. See CHAT-SECURITY-REVIEW.txt
+ for the original reachability investigation. Neither RustSec issue was
+ ignored. No mathematical implementation was patched locally.
+
+ The current manifest enables only Sequoia's crypto-openssl feature. The
+ allow-experimental-crypto and allow-variable-time-crypto opt-ins are gone.
+ The resolved graph has no cx448, crypto-bigint, or rsa crate. This removes
+ those Rust backend dependencies; it does not prove that all side channels
+ are absent from a browser or that external C dependencies have no 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 were checked against upstream GitHub release asset metadata. The
+ build script verifies each archive before extraction. Hash checking pins
+ these inputs; it is not a claim that upstream release signatures were
+ independently verified or that output is bit-for-bit reproducible across
+ hosts. Archives, SDK, libraries, and build products stay under ignored
+ .tools/ and target/. The native development library is supplied by the OS.
+
+WHY WASI
+
+ The original Rust-backend proof used wasm32-unknown-unknown and generated
+ wasm-bindgen JavaScript. The OpenSSL proof uses a wasm32-wasip1 command
+ module and a small explicit browser WASI bridge. The Rust command calls
+ the same compatibility_probe function used by native tests.
+
+ The browser harness loads the new WASI binary directly, not old generated
+ glue. It requires the output to identify OpenSSL 3.6.5, preventing a stale
+ Rust-backend artifact from being accepted as evidence of OpenSSL support.
+ Old browser-build commands are historical and must not be reused here.
+
+BUILD CONFIGURATION AND BOUNDARIES
+
+ infra/chat/openssl-wasi.conf adds a build target inheriting BASE_unix with
+ little-endian and 32-bit bignum configuration. It changes configuration,
+ not OpenSSL's cryptographic source routines. C code is compiled at -O2.
+ No third-party rand.patch, unconditional entropy-success patch, or custom
+ random-number generator is applied. A SHA-256 comparison of all 5889 original
+ regular files against the downloaded OpenSSL archive found no changed or
+ missing originals after the build; only the separate target configuration
+ was added. OpenSSL 3.6.5 already 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.
+
+ Build options 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. They avoid
+ unsupported host capabilities and use static libraries. Disabling the
+ secure-memory arena means ordinary WASM linear memory is used; it does not
+ establish secure erasure, locked pages, or protection from delivered JS.
+ Disabling C stdio does not disable the Rust command's captured output.
+
+ _WASI_EMULATED_GETPID and libwasi-emulated-getpid supply the SDK's process-ID
+ emulation. getuid/geteuid/getgid/getegid map to getpagesize, following the
+ common WASI port configuration: the browser module has no real OS user IDs
+ or privilege boundary. These values are not used as randomness or identity
+ credentials. This is an explicit portability assumption, not a general
+ POSIX security emulation layer.
+
+ Rust bindings use the SDK's libclang and WASI sysroot with target
+ wasm32-wasip1 and -fvisibility=default. Without explicit visibility, the
+ initial bindgen attempt omitted function declarations. Rust's bundled WASI
+ libc search path precedes the SDK libraries: reversing that order initially
+ failed to link __wasi_init_tp. The SDK library path remains available for
+ the emulated-getpid archive. These failures were toolchain integration
+ issues; no generated cryptographic bindings were manually 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.
+
+ Those capability denials protect against accidentally connecting the WASI
+ module to host storage or networking. They do not isolate it from malicious
+ JavaScript delivered by the same server. Memory, clocks, randomness, and
+ imported bridge functions remain part of the trusted browser environment.
+ A test deadline 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 also observes no external requests, cookies, localStorage,
+ sessionStorage, IndexedDB databases, or service-worker registrations.
+ Its HTTP responses carry Cache-Control: no-store. This establishes only
+ this probe's behavior, not that browsers/OSes cannot retain memory, caches,
+ crash dumps, swap, or restored state. A complete chat session does not exist.
+
+ The native tests, WASI build, and browser test are separate checks. A native
+ pass cannot stand in for browser execution. A functional pass and a clean
+ vulnerability scan cannot stand in for a cryptographic or side-channel audit.
+
+DEPENDENCY POLICY REVIEW
+
+ The RustSec database reports no advisories for the current resolved graph.
+ No advisory ignore was added. Bans on wildcards, unknown Git/registry sources,
+ and unreviewed duplicate versions remain enabled. The following existing
+ upstream API generations cannot be unified merely by cargo update. Duplicate
+ exceptions match only the exact older version; other versions remain subject
+ to the duplicate ban. All these packages still undergo advisory and license
+ checks. Cargo.lock pins both sides of each pair.
+
+ 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, scoped to libloading, a bindgen/clang
+ dependency. GNU-compatible third-party licenses remain correctly attributed.
+ cargo-about generates notices for the complete workspace. The static OpenSSL
+ C library and SDK are not Rust crates; their original licenses and sources
+ must accompany any distributed browser artifact as appropriate. Source
+ OpenSSL LICENSE.txt is Apache-2.0. Do not treat the Rust notice page alone
+ as complete documentation of external C/toolchain distribution obligations.
+
+EXTERNAL LIBRARY MAINTENANCE
+
+ cargo-deny does not audit the externally built OpenSSL C archive or SDK.
+ Review OpenSSL's release/advisory pages separately and rebuild when needed:
+ https://openssl-library.org/news/timeline/
+ https://openssl-library.org/news/vulnerabilities-3.6/
+ OpenSSL 3.6.5 is the tested security-patch release dated 2026-09-29. A green
+ Rust audit is not a lifetime security guarantee for this pinned C version.
+ Choose and 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 install --prefix .tools/browser --save-exact playwright@1.64.1
+ PLAYWRIGHT_BROWSERS_PATH="$PWD/.tools/browsers" .tools/browser/node_modules/.bin/playwright install chromium
+ PLAYWRIGHT_BROWSERS_PATH="$PWD/.tools/browsers" node crates/chat-crypto/tests/browser.mjs
+ cargo stack check
+
+ The build script pins archive versions and hashes, configures static OpenSSL,
+ installs it under .tools/openssl-wasi, builds the Rust WASI command, and prints
+ its SHA-256. It does not download/use an unverified precompiled OpenSSL binary.
+ It may reuse already extracted sources; use a fresh ignored tools/build tree
+ when independently verifying the source archive rather than trusting a
+ previously modified extraction. Downloads and 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 removes the specific Rust-backend dependency blocker and demonstrates
+ the fixed algorithms in a browser. It is not a complete messaging service,
+ audit of OpenSSL/WASI/JIT timing behavior, LibreJS certification, or proof
+ against malicious delivery. The file format, authentication, server/database,
+ quotas, hostile-input handling, pagination/counts, backup recovery, complete
+ session lifecycle, and browser-state tests still need implementation.
diff --git a/docs/CHAT-SECURITY-REVIEW.txt b/docs/CHAT-SECURITY-REVIEW.txt
index 7de1d36..4567322 100644
--- a/docs/CHAT-SECURITY-REVIEW.txt
+++ b/docs/CHAT-SECURITY-REVIEW.txt
@@ -16,7 +16,9 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
CHAT CRYPTOGRAPHY SECURITY REVIEW
- Date: 2026-10-30. Status: blocked for deployment and private-message use.
+ Date: 2026-10-30. Historical review of the initial Rust backend.
+ The current OpenSSL migration is recorded in CHAT-OPENSSL-MIGRATION.txt.
+ Private-message use and production deployment are still not ready.
Branch: feature/private-chat. Production and main remain unchanged.
FIXED REQUIREMENT
@@ -24,6 +26,7 @@ FIXED REQUIREMENT
Encryption must remain RFC 9980 ML-KEM-1024 + X448 using v6 keys.
The compatibility probe pairs it with ML-DSA-87 + Ed448 signatures.
No fallback encryption profile is implemented or approved.
+ The findings below apply to checkpoint 436e217, before the backend change.
TEST RESULTS
diff --git a/docs/POLICY.txt b/docs/POLICY.txt
index e2cc4a9..4c8d0bd 100644
--- a/docs/POLICY.txt
+++ b/docs/POLICY.txt
@@ -48,8 +48,10 @@ STRICTNESS
or broad warning suppression is introduced.
cargo-deny rejects duplicate crate versions, wildcard requirements, unknown
- registries, unknown Git sources, and yanked versions. There are no duplicate
- version skip exceptions. Its AGPL allowance is scoped to this package.
+ registries, unknown Git sources, and yanked versions. The chat prototype has
+ exact-version duplicate exceptions reviewed in CHAT-OPENSSL-MIGRATION.txt.
+ No RustSec advisories are ignored. First-party AGPL and required dependency
+ license allowances are scoped to their individual packages.
The dependency allowlist retains the requested permissive licenses and
Zlib; an unused allowance may produce an informational audit warning.