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

Already on GitHub? Sign in to your account

[wallet] Securely erase potentially sensitive keys/values #10308

Merged
merged 1 commit into from May 11, 2017

Conversation

Projects
None yet
6 participants
Contributor

tjps commented May 1, 2017

Doing an audit of "memset(.*0" usage I found a few locations that intended to clear potentially sensitive memory right before freeing it, but were not using the nice memory_cleanse() function in the codebase. I have not verified that the compiler was actually eliding those calls, but better to be safe than sorry. Also changed one path that potentially left a value unscrubbed if it threw while deserializing.

@fanquake fanquake added the Wallet label May 1, 2017

src/support/cleanse.h
@@ -8,6 +8,8 @@
#include <stdlib.h>
+// Securely erase a span of memory in a way guaranteed not to be
@sipa

sipa May 1, 2017

Owner

I don't believe anything in C++ can actually guarantee this.

@tjps

tjps May 2, 2017

Contributor

While it's true that there is nothing in the standard that guarantees this, there are numerous compiler-specific attributes for this, as well as libraries that guarantee this (like right now, memory_cleanse is just a wrapper around OPENSSL_cleanse)

My goal with adding the comment is to explain its purpose to other maintainers of the codebase, as it hopefully sees more use.

@tjps

tjps May 2, 2017

Contributor

On further research, I'm not sure OPENSSL_cleanse actually guarantees anything at all.

@gmaxwell

gmaxwell May 3, 2017

Member

On further research, I'm not sure OPENSSL_cleanse actually guarantees anything at all.

Yep.

@tjps

tjps May 3, 2017

Contributor

To be fair in this case since OPENSSL_cleanse() exists in an external shared object, we know it won't be optimized out. Should I back out this comment though?

@sipa

sipa May 3, 2017

Owner

@tjps Nothing in C++ can guarantee that memory will be overwritten. The memset_s function from the C11 standard does require a guarantee, but gcc/g++ don't implement it I believe. So, writing in the source code that something has a guarantee may be misleading. Furthermore, the memory being overwritten is not the only thing we're after. The compiler is free to for example copy some of the memory to the stack first, where it could live longer.

However, if we restrict ourselves to supported systems and platforms, we know more at this point in time. We know what optimizations are implemented, and what compilers are capable of. It is reasonable that a call won't be optimized out if it's in another module, but that may not be the case if we'd switch to LTO builds, for example.

I would just write "Attempt to overwrite a span of memory" or something.

@tjps

tjps May 3, 2017

Contributor

Agreed, I reduced the verbiage to make it clear that it is a best-effort attempt.

Also, it is my understanding that LTO only affects the object files you are linking, so dynamically loaded .so's are still safe from compiler analysis. But I could be wrong, I've never actually come across a project of any significant size using LTO.

Comment updated.

src/wallet/db.h
+ memory_cleanse(datKey.get_data(), datKey.get_size());
+ bool success = false;
+ if (datValue.get_data() != NULL)
+ {
@sipa

sipa May 1, 2017

Owner

Style nit: brace on the same line as the if.

@tjps

tjps May 2, 2017

Contributor

That's actually my preference as well, but I thought that was against the style guide for this repo. Can I assume brace on same line for code going forward?

+ CDataStream ssValue((char*)datValue.get_data(), (char*)datValue.get_data() + datValue.get_size(), SER_DISK, CLIENT_VERSION);
+ ssValue >> value;
+ success = true;
+ } catch (const std::exception&) {
@laanwj

laanwj May 2, 2017

Owner

Silently ignored exceptions are one of the larger frustrations when troubleshooting C++ code. Checking more closely it seems this is ok: please add a comment e.g. /* success = false */ here to show what is happening.

@tjps

tjps May 2, 2017

Contributor

Good idea, added.

Owner

laanwj commented May 2, 2017

LGTM, utACK, as we have the memory_cleanse function anyway let's use it where it makes sense.

Member

jonasschnelli commented May 2, 2017

utACK 2ac5445

@laanwj laanwj merged commit 6c914ac into bitcoin:master May 11, 2017

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

laanwj added a commit that referenced this pull request May 11, 2017

Merge #10308: [wallet] Securely erase potentially sensitive keys/values
6c914ac [wallet] Securely erase potentially sensitive keys/values (Thomas Snider)

Tree-SHA512: 071d88c4093108d4e4eced35a6ffcebe3f499798194f5b1be661ffa5b78b5f55311667f6d2a72758d85290f61f958381ee95d380b9045ca18e9e1875f0e686c8

@tjps tjps deleted the tjps:tjps_secure_erase branch May 13, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 3, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 3, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 3, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 5, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 5, 2017

luke-jr added a commit to luke-jr/bitcoin that referenced this pull request Jun 5, 2017

nomnombtc added a commit to nomnombtc/bitcoin that referenced this pull request Jul 17, 2017

runn1ng added a commit to runn1ng/bitcoin that referenced this pull request Oct 30, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment