Skip to content

Fix WASM entropy source when HEAPU8 is not exported - #265

Merged
utelle merged 1 commit into
utelle:mainfrom
SchwarzDigits:fix/wasm-crypto-heapu8
Sep 12, 2026
Merged

utelle merged 1 commit into
utelle:mainfrom
SchwarzDigits:fix/wasm-crypto-heapu8

Conversation

@mtrossbach

Copy link
Copy Markdown
Contributor

Hi Ulrich,

while testing the WebAssembly build, I noticed that encryption aborts on main as soon as random numbers are needed.

wasm_crypto_getrandom() in src/chacha20poly1305.c (added in 91b45ec) accesses the memory as Module.HEAPU8. Current Emscripten versions no longer export HEAPU8 on the Module object by default. The official v2.5.1 WASM package doesn't expose it there either. So the call fails, entropy() returns no data, and chacha20_rng() aborts. The release build only reports Aborted(); with -sASSERTIONS the message is:

Aborted('HEAPU8' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the Emscripten FAQ))

This affects every cipher scheme that needs random numbers: chacha20 (the default), sqlcipher, ascon128 and aegis. Only aes128cbc, aes256cbc and rc4, which don't use random numbers, keep working. The released v2.5.1 isn't affected, because it still used getentropy(). The same line is also on the hwaccel branch.

The change: use HEAPU8 directly instead of Module.HEAPU8. Inside EM_JS code the view is always in scope, whether or not it's exported, and it is kept up to date when the memory grows.

How I tested it

Emscripten 6.0.9 with Node. I rebuilt the WASM package the way the release workflow does (SQLite 3.53.4 sources, the patches from packaging/wasm, make dist dist.build=oz), once from main and once with this change. Then I wrote and read a database with each cipher scheme, each in its own process:

Cipher scheme Before After
aes128cbc, aes256cbc, rc4 OK OK
chacha20, sqlcipher, ascon128, aegis aborts OK

A small test program built directly with emcc gives the same results, for the default build (with and without -sASSERTIONS) and for -sMODULARIZE -sEXPORT_ES6. With -sEXPORTED_RUNTIME_METHODS=HEAPU8, both versions work. These builds use -sALLOW_MEMORY_GROWTH with a small initial memory (16 MiB).

Best regards,
Markus

The Emscripten variant of entropy() accessed the WebAssembly memory
through Module.HEAPU8. Current Emscripten versions no longer export
HEAPU8 on the Module object by default, so the access failed, entropy()
returned no data and chacha20_rng() aborted on its first use, for example
when writing a database encrypted with the default cipher scheme.

Use the HEAPU8 view directly. It is always in scope for EM_JS code and is
kept up to date when the memory grows.
@utelle

utelle commented Sep 12, 2026

Copy link
Copy Markdown
Owner

The change was an attempt to replace the call to getentropy() with something more reliably returning true random data. Obviously a failure. - Thanks for detecting, reporting and fixing it.

@utelle
utelle merged commit a393e13 into utelle:main Sep 12, 2026
13 checks passed
utelle added a commit that referenced this pull request Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants