wallet: Don't allow an HDSeed to be overwritten

We can maybe relax this restriction later once we have worked out the UX
implications.
This commit is contained in:
Jack Grigg 2018-09-03 10:45:17 +01:00
parent 4c1a26fb60
commit b33a7ec46e
No known key found for this signature in database
GPG Key ID: 1B8D649257DB0829
3 changed files with 32 additions and 19 deletions

View File

@ -35,10 +35,10 @@ TEST(keystore_tests, StoreAndRetrieveHDSeed) {
auto seed2 = HDSeed::Random(); auto seed2 = HDSeed::Random();
EXPECT_NE(seed, seed2); EXPECT_NE(seed, seed2);
// We should be able to set and retrieve a different seed // We should not be able to set and retrieve a different seed
ASSERT_TRUE(keyStore.SetHDSeed(seed2)); EXPECT_FALSE(keyStore.SetHDSeed(seed2));
ASSERT_TRUE(keyStore.GetHDSeed(seedOut)); ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed2, seedOut); EXPECT_EQ(seed, seedOut);
} }
TEST(keystore_tests, sapling_keys) { TEST(keystore_tests, sapling_keys) {
@ -276,12 +276,12 @@ TEST(keystore_tests, StoreAndRetrieveHDSeedInEncryptedStore) {
ASSERT_TRUE(keyStore.GetHDSeed(seedOut)); ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed, seedOut); EXPECT_EQ(seed, seedOut);
// 2) Test replacing the seed in an already-encrypted key store // 2) Test replacing the seed in an already-encrypted key store fails
auto seed2 = HDSeed::Random(); auto seed2 = HDSeed::Random();
ASSERT_TRUE(keyStore.SetHDSeed(seed2)); EXPECT_FALSE(keyStore.SetHDSeed(seed2));
EXPECT_TRUE(keyStore.HaveHDSeed()); EXPECT_TRUE(keyStore.HaveHDSeed());
ASSERT_TRUE(keyStore.GetHDSeed(seedOut)); ASSERT_TRUE(keyStore.GetHDSeed(seedOut));
EXPECT_EQ(seed2, seedOut); EXPECT_EQ(seed, seedOut);
// 3) Test adding a new seed to an already-encrypted key store // 3) Test adding a new seed to an already-encrypted key store
TestCCryptoKeyStore keyStore2; TestCCryptoKeyStore keyStore2;

View File

@ -26,6 +26,11 @@ bool CKeyStore::AddKey(const CKey &key) {
bool CBasicKeyStore::SetHDSeed(const HDSeed& seed) bool CBasicKeyStore::SetHDSeed(const HDSeed& seed)
{ {
LOCK(cs_SpendingKeyStore); LOCK(cs_SpendingKeyStore);
if (!hdSeed.IsNull()) {
// Don't allow an existing seed to be changed. We can maybe relax this
// restriction later once we have worked out the UX implications.
return false;
}
hdSeed = seed; hdSeed = seed;
return true; return true;
} }

View File

@ -219,7 +219,7 @@ bool CCryptoKeyStore::Unlock(const CKeyingMaterial& vMasterKeyIn)
bool keyPass = false; bool keyPass = false;
bool keyFail = false; bool keyFail = false;
{ if (!cryptedHDSeed.first.IsNull()) {
HDSeed seed; HDSeed seed;
if (!DecryptHDSeed(vMasterKeyIn, cryptedHDSeed.second, cryptedHDSeed.first, seed)) if (!DecryptHDSeed(vMasterKeyIn, cryptedHDSeed.second, cryptedHDSeed.first, seed))
{ {
@ -322,6 +322,12 @@ bool CCryptoKeyStore::SetCryptedHDSeed(
return false; return false;
} }
if (!cryptedHDSeed.first.IsNull()) {
// Don't allow an existing seed to be changed. We can maybe relax this
// restriction later once we have worked out the UX implications.
return false;
}
cryptedHDSeed = std::make_pair(seedFp, vchCryptedSecret); cryptedHDSeed = std::make_pair(seedFp, vchCryptedSecret);
} }
return true; return true;
@ -550,20 +556,22 @@ bool CCryptoKeyStore::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
return false; return false;
fUseCrypto = true; fUseCrypto = true;
{ if (!hdSeed.IsNull()) {
std::vector<unsigned char> vchCryptedSecret; {
// Use seed's fingerprint as IV std::vector<unsigned char> vchCryptedSecret;
// TODO: Handle this properly when we make encryption a supported feature // Use seed's fingerprint as IV
auto seedFp = hdSeed.Fingerprint(); // TODO: Handle this properly when we make encryption a supported feature
if (!EncryptSecret(vMasterKeyIn, hdSeed.RawSeed(), seedFp, vchCryptedSecret)) { auto seedFp = hdSeed.Fingerprint();
return false; if (!EncryptSecret(vMasterKeyIn, hdSeed.RawSeed(), seedFp, vchCryptedSecret)) {
} return false;
// This will call into CWallet to store the crypted seed to disk }
if (!SetCryptedHDSeed(seedFp, vchCryptedSecret)) { // This will call into CWallet to store the crypted seed to disk
return false; if (!SetCryptedHDSeed(seedFp, vchCryptedSecret)) {
return false;
}
} }
hdSeed = HDSeed();
} }
hdSeed = HDSeed();
BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys) BOOST_FOREACH(KeyMap::value_type& mKey, mapKeys)
{ {
const CKey &key = mKey.second; const CKey &key = mKey.second;