Skip to content
This repository has been archived by the owner on Mar 6, 2020. It is now read-only.

Securely zero key material before freeing memory #10

Merged
merged 1 commit into from
Jan 14, 2019
Merged

Conversation

ilammy
Copy link
Owner

@ilammy ilammy commented Jan 12, 2019

It is a good security practice to wipe sensitive data from memory as soon as it no longer needed. Obviously, the data has to be in memory for some time but we should not keep it around for more than absolutely necessary. The data in a memory region is not erased when the memory is freed so we have to make sure it's gone ourselves.

Initially I was overconfident and tried writing my own zeroing. Don't do this, kids. There's a whole load of issues that need to be resolved in order to securely zero out a memory region. You can read the implementation details in the source code of "zeroize" or elsewhere.

Therefore we use a dedicated library for the task. It makes sure that the compiler does not optimize away the code that tries its best to write zeros into the main memory (not the caches). Currently zeroize does not use these fancy functions like memset_s(), explicit_bzero(), RtlSecureZeroMemory(), etc. but it might it the future.

There's also a test to verify that the memory is indeed zeroed out. By definition, the test contains some technically unsafe code, but it's unlikely to crash or misbehave.

@Lagovas was concerned about this feature in cossacklabs/themis#340. These changes will be included in the next bulk PR into the main Themis repository (along with other stuff).

It is a good security practice to wipe sensitive data from memory as
soon as it no longer needed. Obviously, the data has to be in memory
for some time but we should not keep it around for more than absolutely
necessary. The data in a memory region is not erased when the memory
is freed so we have to make sure it's gone ourselves.

Initially I was overconfident and tried writing my own zeroing. Don't
do this, kids. There's a whole load of issues that need to be resolved
in order to *securely* zero out a memory region. You can read the
implementation details in the source code of "zeroize" or elsewhere.

Therefore we use a dedicated library for the task. It makes sure that
the compiler does not optimize away the code that tries its best to
write zeros into the main memory (not the caches). Currently zeroize
does not use these fancy functions like memset_s(), explicit_bzero(),
RtlSecureZeroMemory(), etc. but it might it the future.

There's also a test to verify the the memory is indeed zeroed out.
By definition, the test contains some technically unsafe code, but
it's unlikely to crash or misbehave.
@ilammy ilammy mentioned this pull request Jan 12, 2019
15 tasks
@vixentael
Copy link

Wow, didn't expect it to be so complicated to zero value in memory.

@ilammy
Copy link
Owner Author

ilammy commented Jan 14, 2019

Well, I also thought that a simple destructor like this

impl Drop for KeyBytes {
    fn drop(&mut self) {
        for byte in self.0.iter_mut() {
            *byte = 0;
        }
    }
}

will do just fine (and it kinda does: at least, the test passes with this, even in release mode).

But then I got curious about all the fuss around secure zeroing, looked around a bit, and the reasoning behind those complications makes sense now. The test may pass, but that's probably because it's running in a single threaded environment and the compiler may actually see the pointer aliasing (I did not study LLVM's output to say for sure).

@ilammy ilammy merged commit 74f0d8d into master Jan 14, 2019
@ilammy ilammy deleted the secure-zero branch January 14, 2019 13:00
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants