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

Secure in memory data with libgcrypt #540

Closed
dol opened this issue Aug 17, 2015 · 10 comments
Closed

Secure in memory data with libgcrypt #540

dol opened this issue Aug 17, 2015 · 10 comments

Comments

@dol
Copy link
Contributor

dol commented Aug 17, 2015

libgcrypt has a cross platform support for protecting memory pages => gcry_malloc_secure
If I remember correctly a libraries could be linked statically with go. A libgcrypt go C-binding is missing at the moment.

@sethvargo
Copy link
Contributor

Hi @dol

Thank you for reaching out. Protecting against memory analysis is something explicitly called out in our Thread Model: https://vaultproject.io/docs/internals/security.html as something that is not part of our model.

@dol
Copy link
Contributor Author

dol commented Aug 17, 2015

@sethvargo Thx for the quick response. I was not looking at the thread model. Sorry.

@dol dol closed this as completed Aug 17, 2015
@sethvargo
Copy link
Contributor

Hey @dol

No problem 😄. If it's easy to implement, I don't see a reason why we can't use libgcrypt, so let's keep this open until we can do some research.

@sethvargo sethvargo reopened this Aug 17, 2015
@dol
Copy link
Contributor Author

dol commented Aug 17, 2015

👍

@dol
Copy link
Contributor Author

dol commented May 6, 2017

The library is brand new, but promising: https://github.com/libeclipse/memguard

@jefferai
Copy link
Member

jefferai commented May 8, 2017

I took a look at it. Unless I'm missing something about the internals of the Go allocator, it doesn't really fix the problem.

When you "move" data into one of these memguarded objects, you still are coming from a Go-allocated byte slice. Once that byte slice has been allocated, even if the memguard library attempts to zero/free it, you don't know when the garbage collector will actually free it or what it will do with the memory. This leaves you in the same boat as what we have right now in Vault where we attempt to zero out memory that contained very critical data but is not in use, but cannot guarantee that it is zeroed.

Much of the rest of what it does (stack protection and so on) seem to be a requirement of allocating the memory outside of Go, so it's basically attempting to add back things Go already gives you.

I'd love to be wrong about this, but as long as the memory originated in Go, I don't see how this really makes a difference over our current best-effort attempts to zero out memory.

@agnivade
Copy link

When you "move" data into one of these memguarded objects, you still are coming from a Go-allocated byte slice.

This is not true anymore. Memguard now uses system calls to manage memory, thereby bypassing the Go runtime completely. Have a look at awnumar/memguard#3 for more information.

@jefferai
Copy link
Member

As far as I can tell it is still true, and I'm not the only one -- see golang/go#21865 for instance -- any Go code that touches the memory that memguard is managing is an easy way to have said memory be exposed outside of memguard.

Maybe I'm missing something, but this seems to be the case even in the example program at https://godoc.org/github.com/awnumar/memguard -- you're getting a key allocated by memguard, but now anything I do with said key that results in a copy -- say, base64 it to return across the wire, or send it to Vault's barrier to be encrypted before saving to disk -- means that the key is now in Go's memory space as well as memguard's. You're shifting the problem, but not eliminating it.

As a defense-in-depth approach it has merit, and could maybe have higher impact in specific, key parts of Vault, but simply peppering memguard around is not sufficient for "secure memory" in Go; plus, it makes it difficult to find the memory, but not impossible (the value is still in plaintext in memory). A much higher impact is likely to come from something like SGX where the value is actually encrypted in memory. It'll still have the same problems as memguard w.r.t. interfacing with Go code, but it's less reliant on obfuscation as opposed to actual cryptography.

@agnivade
Copy link

Well you have shifted your original point to something else. Originally, you mentioned that memguard allocates memory which is managed by the Go runtime. I pointed out that it is not true. As far as I understand, this is correct.

But it is also true that whenever you make a copy, now again you are back to square one. However, I do see a line mentioning how to get a pointer to the underlying buffer.
keyArrayPtr := (*[16]byte)(unsafe.Pointer(&key.Buffer()[0])).

@jefferai
Copy link
Member

@agnivade I've expanded on my original point, not shifted it. I still maintain that this call: https://godoc.org/github.com/awnumar/memguard#LockedBuffer.Move requires memory allocated by the Go runtime -- the parameter to the function (the data to move into the container) is a Go-allocated byte slice. As a result, the sensitive data still lives in memory over which you have no control (as well as memory over which you do have control). And in either case the memory is still plaintext, even if memguard tries to obfuscate where it lives.

Copies of slices made by underlying Go stdlib calls or other such code simply exacerbate the problem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants