We'd like to enable FIPS 140-3 mode for GOARCH=wasm. From a validation point of view, this is not very different from validating a JVM bytecode module, but it is a much less-trodden path: I am aware of only one FIPS 140-2 Wasm module and no FIPS 140-3 Wasm modules.
The two main challenges are:
- getting access to the module's "text" to run the integrity check;
- making the internal Entropy Source work.
We can leave (2) for the future by focusing on getting the FIPS 140-3 Go Cryptographic Module v1.0.0 working, which still uses passive entropy.
For (1), we can have the linker set aside a section in memory for the module, and then populate it from the instantiating Javascript. This, for now, will only work on wasm/js. See CL 758441 for details. Concretely, it looks like extending globalThis.Go.run to take two optional arguments: the WebAssembly.Module, and the bufferSource that was passed to WebAssembly.instantiate.
Since the linker section has a cost, we'd only enable it if the build uses GOFIPS140. This is a slight regression compared to other architectures where GODEBUG=fips140=on can be used with any build, but it's preferable to imposing a memory cost on every non-FIPS 140 Wasm instance.
Running a Wasm module in FIPS 140-3 mode would look like building the module with GOFIPS140=v1.0.1 (a future version we'll validate that doesn't reject GOARCH=wasm) and then instantiating it as
const go = new Go();
const source = await (await fetch("test.wasm")).arrayBuffer();
const result = await WebAssembly.instantiate(source, go.importObject);
await go.run(result.instance, result.module, source);
That would work both in Node.js and in the browser.
There's a bit of chicken-and-egg problem where we can't validate v1.0.1 until there's toolchain support, but the toolchain support will be pretty useless until v1.0.1 exists. To break it, we'll add a GODEBUG=fips140wasmentropy=bypass undocumented setting to make GOFIPS140=latest work, so we can properly test the toolchain support while we wait for v1.0.1.
/cc @DanielMorsing @golang/security
We'd like to enable FIPS 140-3 mode for
GOARCH=wasm. From a validation point of view, this is not very different from validating a JVM bytecode module, but it is a much less-trodden path: I am aware of only one FIPS 140-2 Wasm module and no FIPS 140-3 Wasm modules.The two main challenges are:
We can leave (2) for the future by focusing on getting the FIPS 140-3 Go Cryptographic Module v1.0.0 working, which still uses passive entropy.
For (1), we can have the linker set aside a section in memory for the module, and then populate it from the instantiating Javascript. This, for now, will only work on wasm/js. See CL 758441 for details. Concretely, it looks like extending
globalThis.Go.runto take two optional arguments: the WebAssembly.Module, and the bufferSource that was passed toWebAssembly.instantiate.Since the linker section has a cost, we'd only enable it if the build uses
GOFIPS140. This is a slight regression compared to other architectures whereGODEBUG=fips140=oncan be used with any build, but it's preferable to imposing a memory cost on every non-FIPS 140 Wasm instance.Running a Wasm module in FIPS 140-3 mode would look like building the module with
GOFIPS140=v1.0.1(a future version we'll validate that doesn't rejectGOARCH=wasm) and then instantiating it asThat would work both in Node.js and in the browser.
There's a bit of chicken-and-egg problem where we can't validate v1.0.1 until there's toolchain support, but the toolchain support will be pretty useless until v1.0.1 exists. To break it, we'll add a
GODEBUG=fips140wasmentropy=bypassundocumented setting to makeGOFIPS140=latestwork, so we can properly test the toolchain support while we wait for v1.0.1./cc @DanielMorsing @golang/security