iqlusioninc/crates

Support zeroize on wasm targets

Closed this issue · 8 comments

I would like to support zeroize on wasm targets. However, zeroize was created with an explicit goal in mind:

No insecure fallbacks

To that end, any solution implemented MUST guarantee execution. Based on my preliminary research, I think there are options available for both stable and nightly Rust:

  • nightly: The existing wrapper for volatile_set_memory(), to my understanding, will provide the desired behavior of a volatile zeroing operation using LLVM's volatile semantics
  • stable: The aforementioned function is an unstable LLVM intrinsic guarded by a feature flag and is not available on stable. However via Twitter comes a clever idea: at least on WASM targets where the JS bridge is available, call out to JS to clear the buffer. While I'm a bit worried that eventually the WASM <-> JS bridge might potentially be optimized to the point it can see through this an optimize it away, so far based on some preliminary investigation that does not seem to be the case with any existing browser / WASM implementation

I'm a bit worried that the "stable" solution is the sort of "clever hack" this crate was created to avoid, although I think it falls into the "good enough for now" category.

Another approach which might work on stable is to directly emit the WASM necessary to perform a volatile zeroing operation. However, I have never tried that before and wouldn't really know where to start.

Using wasm_bindgen you could easily call a js function the problems are:

  • dependencies are not supposed to call into js themselves
  • you would have to supply the JS side too

But the pro on wasm is that everything is sandboxed and belongs to the browser, so your memory is protected, but I don't know how the browser clears that memory.

It looks like bulk memory operations (currently design phase) might be useful for this purpose: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md

Another approach which might work on stable is to directly emit the WASM necessary to perform a volatile zeroing operation. However, I have never tried that before and wouldn't really know where to start.

Does rust have any way to include things for llvm or assembly?

so your memory is protected, but I don't know how the browser clears that memory.

My understanding of the WASM memory model in a browser context is it's TypedArray that lives in the DOM, in which case it would be very nice to ensure secrets are cleared, as otherwise they could get potentially exposed unintentionally (ala Cloudbleed / Jetleak).

Does rust have any way to include things for llvm or assembly?

LLVM intrinsics and inline ASM are only available on nightly. But I'm already using volatile_set_memory there.

In an ELF executable, on stable Rust you can include assembly by first creating an object from it, then link that together with Rust code (by e.g. creating a static library and linking with it using FFI + attributes).

I know very little about Rust WASM so I have no idea what the analogous linking operation for that would be.

Wasm is just like asm there just may be a different Syntax, but I know little about rust and asm so I can't really help there.

FYI, I think #142 is the path forward here. I'll look into adding a wasm target to CI.

This was fixed in #142, with CI added in #143