Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable non-extractable keys for Web Crypto #11481

Closed
lucacasonato opened this issue Jul 21, 2021 · 7 comments · Fixed by #11705
Closed

Enable non-extractable keys for Web Crypto #11481

lucacasonato opened this issue Jul 21, 2021 · 7 comments · Fixed by #11705
Labels
ext/crypto related to the ext/crypto crate feat new feature (which has been agreed to/accepted) web related to Web APIs

Comments

@lucacasonato
Copy link
Member

Before some we can do this we need confirmation from spec authors for the following statements:

  1. Non extractable keys are not meant to be a security primitive. They are purely meant for obfuscation.
  2. It is expected that a compromise of the render process, or in process timing side channel attacks (Spectre) can extract "non extractable" keys.

If either of these statements are not correct we do not have any technical way to implement non extractable keys securely.

Knowing more about how web crypto is implemented in browsers (Chrome, Safari, and Firefox) would help here:

  • Is underlying key material stored in the render process, or in a separate process that communicates with the render process via IPC for any cryptographic operations?
@lucacasonato lucacasonato added feat new feature (which has been agreed to/accepted) web related to Web APIs labels Jul 21, 2021
@littledivy
Copy link
Member

The spec recommends use of IndexedDB for storing key material. https://www.w3.org/TR/WebCryptoAPI/#concepts-key-storage


Also:

Authors should be aware that this specification places no normative requirements on implementations as to how the underlying cryptographic key material is stored. The only requirement is that key material is not exposed to script, except through the use of the exportKey and wrapKey operations

I'll assume storing key material in memory is fine with extractable=false

@panva
Copy link
Contributor

panva commented Jul 21, 2021

The key language from that section I believe is in bold

This allows the storage and retrieval of key material, without ever exposing that key material to the application or the JavaScript environment

That being said that whole section is marked as non-normative.

@panva
Copy link
Contributor

panva commented Jul 21, 2021

https://www.w3.org/TR/WebCryptoAPI/#scope-out-of-scope

This API, while allowing applications to generate, retrieve, and manipulate keying material, does not specifically address the provisioning of keys in particular types of key storage, such as secure elements or smart cards. This is due to such provisioning operations often being burdened with vendor-specific details that make defining a vendor-agnostic interface an unsuitably unbounded task. Additionally, this API does not deal with or address the discovery of cryptographic modules, as such concepts are dependent upon the underlying user agent and are not concepts that are portable between common operating systems, cryptographic libraries, and implementations.

@lucacasonato
Copy link
Member Author

These sections are all non normative. We can't make a decision on this until we have more clarity about other vendor implementations. Also see w3c/webcrypto#269

@panva
Copy link
Contributor

panva commented Aug 11, 2021

@lucacasonato can you update the title to state non-extractable rather than extractable?

@kitsonk kitsonk changed the title Enable extractable keys for Web Crypto Enable non-extractable keys for Web Crypto Aug 11, 2021
@kitsonk kitsonk added the ext/crypto related to the ext/crypto crate label Aug 12, 2021
@lucacasonato
Copy link
Member Author

Ok, this has been unblocked. Discussion here has resulted in the observation that all shipping implementations store key material in an unprivileged process, thus not being "spectre safe". We can thus do the same.

@lucacasonato
Copy link
Member Author

I also reached out to Daniel Huigens (primary editor of the Web Cryptography Specification at the moment). Here is what he had to say:

While I think it would be nice to add protection against Spectre-type attacks eventually, this depends on the feasibility and willingness of implementers to do so, which needs to be investigated, and it would of course be unreasonable to demand that Deno does so while the other implementers haven't yet.

That being said, I do think this is an important issue that deserves more attention, and while the spec in its current form doesn't make any explicit demands from implementers to protect against these attacks, it does leave a lot of freedom to do so, and is intentionally vague about how (and where) cryptographic operations should be implemented and key material should be stored. (And, arguably, Spectre attacks violate the requirement that the private key material is not extractable by a script.) If you are of the opinion that, with Deno's focus on security, it's important to protect against these attacks, then I wouldn't let the lack of an explicit requirement in the spec stop you from doing so. On the other hand, I can also imagine that in a server environment (where I imagine Deno is most commonly used?) where the JS code is "trusted" (modulo supply chain attacks), it may not be worth the effort.

The sort of threat model / scenario that non-extractable keys may be useful for, are things such as:

  1. On first run, an application generates a non-extractable key and stores it in IndexedDB (let's assume the application doesn't have access to disk / to the file where the IndexedDB is stored)
  2. The application sends out the public key and uses the private key to decrypt messages from clients (and stores the messages encrypted in IndexedDB as well)
  3. Then, after some time has passed, one library that the application depends on gets compromised with some code that dumps the entirety of IndexedDB and sends it to some malicious server

If messages are stored encrypted and the private key is non-extractable, then the above attack is prevented. Of course, the attacker could instead decrypt the messages from IndexedDB and then send them over, but that would be a targeted attack and require knowledge of the IndexedDB "schema", etc, whereas the above is a generic attack that would work against any application. With Spectre, the attacker could instead write some code to attack and extract the private key, and it would still be completely application-independent.

In addition, in the case of a signing key rather than a decryption key, extracting the key material allows an attacker to sign new messages for as long as they want, rather than only for the duration of the compromise of the server.

For now we will take the "easy path" where we store key material in process, like existing implementations do. Once (and if) the security model is changed upstream in the spec to be made more strict, we can reconsider.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ext/crypto related to the ext/crypto crate feat new feature (which has been agreed to/accepted) web related to Web APIs
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants