<div dir="ltr">The OpenSSL engine concept can be used to store cryptographical keys in a safe manner.<div>The engine is a plugin for the OpenSSL libcrypto and the API for loading and using engines is supported in the crypto application in OTP.</div><div><br></div><div>SeeĀ <a href="http://erlang.org/doc/apps/crypto/engine_keys.html">http://erlang.org/doc/apps/crypto/engine_keys.html</a></div><div><br></div><div>/Kenneth, Erlang/OTP Ericsson</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Oct 28, 2019 at 1:24 PM Amit K <<a href="mailto:klg.amit@gmail.com">klg.amit@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Daniel,<br>
<br>
Thanks very much for your thoughts and insights.<br>
Regarding your following comment about refc binaries:<br>
<br>
> What you should worry about are things like shared, reference-counted binaries. They may be shared between sensitive and non-sensitive processes, so do they have to be zeroed or not? What about the memory allocated by NIF-s in sensitive processes? Like the openssl data structures where crypto will copy the keys? I have a feeling that blindly zeroing every freed up memory is inefficient, but doable, while extending the sensitive concept to cover every aspect of the BEAM VM may not be feasible at all.<br>
<br>
I read up on this a little bit here:<br>
<a href="http://erlang.org/doc/efficiency_guide/binaryhandling.html" rel="noreferrer" target="_blank">http://erlang.org/doc/efficiency_guide/binaryhandling.html</a><br>
and it seems that even when the binary is not shared it can reside on<br>
the global binary heap - either because it is larger than 64 bytes, or<br>
because it was referenced from another term, even if it's in the same<br>
process. The latter seems to be easily avoidable if you carefully<br>
write your sensitive data handling code, and the same goes for shared<br>
binaries - if you're really writing code that handles sensitive data<br>
you need to be careful about which other processes you share it with<br>
anyway :)<br>
The size limitation of 64 bytes however is a bit more painful,<br>
although actually, for symmetric crypto keys and passwords 64 bytes is<br>
very reasonable because AES-256 keys for example are only 32 bytes<br>
long. Most passwords are also much shorter than 64 bytes. However of<br>
course for asymmetric crypto the key sizes are much larger than 64<br>
bytes and this becomes a real issue.<br>
<br>
I have two ideas on how to address this:<br>
<br>
1. Add a "sensitive" flag for the entire Erlang node as well, which at<br>
least to begin with, will only tell the GC to also zero the binary<br>
heap when it frees it. More relevant actions can be piled on top of<br>
that semantic in the future.<br>
<br>
2. The second would be to allow larger binaries to reside on the<br>
process heap of sensitive processes, possibly even make this<br>
configurable. This sounds to me a bit more complex than 1.<br>
<br>
One final point about NIFs - I think that's outside the scope of what<br>
is possible to address. The use case I really want to address is the<br>
handling of sensitive data in Erlang code and the passing of it to and<br>
from the "crypto" module. Granted, OpenSSL is a C program and hence a<br>
NIF (hope I got that right) but if OpenSSL fails to zero its internal<br>
sensitive buffers, that's a bug that should be handled in the OpenSSL<br>
context :)<br>
<br>
(BTW: after a bit of searching I found that OpenSSL uses<br>
"openssl_cleanse" whenever it<br>
needs to zero a sensitive buffer -<br>
<a href="https://github.com/openssl/openssl/search?q=openssl_cleanse&unscoped_q=openssl_cleanse" rel="noreferrer" target="_blank">https://github.com/openssl/openssl/search?q=openssl_cleanse&unscoped_q=openssl_cleanse</a>)<br>
<br>
Thanks,<br>
Amit<br>
</blockquote></div>