awnumar / memguard

Secure software enclave for storage of sensitive information in memory.
Apache License 2.0
2.49k stars 124 forks source link

How to invalidate Enclaves? #121

Closed capnspacehook closed 4 years ago

capnspacehook commented 4 years ago

I'm implementing a transparently encrypted in-memory filesystem, and I'm storing the data of in-memory files as pointers to Enclaves *memguard.Enclave. I'm not sure what to do when I need to delete a file, or truncate a file to 0. I know that LockedBuffers can be destroyed with the Destroy method, but Enclaves don't have such a method.

I'm also aware that when memguard.Purge is called, Enclaves are rendered useless by rolling the decryption key for them, which makes sense. How then can I safely invalidate a single enclave at will? Is that possible?

awnumar commented 4 years ago

Interesting problem.

Invalidating enclaves on an individual scale would require holding seperate keys for each one. This is expensive. Letting them fall out of scope and become unreachable is the intended way to discard them. This does mean potentially that copies of the ciphertext are littered around the heap but this is a non-issue as it's assumed the key is secure.

In any case, I don't think that storing files as enclaves is a good idea as decrypting them would require allocating a huge LockedBuffer to hold the entire file in memory. This would be easier once streaming is implemented but if you really want to do this then I guess you can store a file as an array of enclaves of a specified chunk size.

Another solution is to store an encryption key in an enclave and use it to encrypt files which can be stored and manipulated any way you like. Invalidating a single file then would require wiping the key that was used to encrypt it.

capnspacehook commented 4 years ago

You have some really good points, I knew that storing each file as an Enclave wasn't the most efficient, and that converting back and forth between LockedBuffers is slow, but I couldn't think of any alternatives.... I think your latter suggestion will work perfectly for me, I'll try it out and let you know if I have any problems

capnspacehook commented 4 years ago

Yeah that sped up performance a bit more than 360% lol, thanks for the suggestion!!

I just had a thought though, couldn't Enclaves export a Wipe function that would just call core.Wipe on the stored ciphertext, and maybe set an internal field to note the the Enclave is wiped? That seems doable. Because Enclave.ciphertext is not exported

awnumar commented 4 years ago

Heyy that's great.

couldn't Enclaves export a Wipe function that would just call core.Wipe on the stored ciphertext

It's possible but useless as ciphertext is stored within ordinary byte slices on the go heap and so we have to assume there are copies.

capnspacehook commented 4 years ago

That's a good point. So I would assume in this scenario, to overwrite the key stored in an Enclave, I'd just re-encrypt the file data with a random key, and wipe the random key after? As there's no way to safely wipe an Enclave?

awnumar commented 4 years ago

I see what you mean.

I'd just re-encrypt the file data with a random key, and wipe the random key after

This would very likely still leave a copy of the old ciphertext in memory somewhere.

Enclaves weren't really designed to be wiped individually like you want. They store ciphertext which is assumed to be safe to shout from the rooftops, as long as the Coffer object is assumed to be working as intended. Purge is designed to invalidate everything that has been created before the moment Purge is called, initializing a fresh environment in the process.

It is safe to simply discard the Enclave by letting it fall out of scope and becoming unreachable. If not wiping it violates your security model then you don't trust the Coffer object to secure the key at which point you might as well not use the library at all.

awnumar commented 4 years ago

What is the security model by the way?

capnspacehook commented 4 years ago

Ok yeah, it seems I'm overthinking this. I trust the implementation of the Coffer, I've read over the code a few times and it looks reasonably secure to me.

My threat model is adversaries dumping the process's memory that is hosting my VFS, and reading files in the VFS.

capnspacehook commented 4 years ago

Closing as all my questions are answered, thanks for the help!