upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
authorNsable-sh <nsable-sh@noreply.git.bitflash.network>2026-08-07 10:55:50 -0300
committerBitflash <admin@bitflash.network>2026-08-07 11:05:09 -0300
commitd925be57e22213554b0ab2a64d7618611fedf81d (patch)
tree4d43fe71e94849255e259aaca0d197453cb24a20 /src/main.cpp
parent09ff5751264de6101f1bf0981accac0123351a7a (diff)
wallet: cleanse unlocked secrets before clearing them (#2)
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp56
1 files changed, 47 insertions, 9 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 0342650..e149062 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -165,6 +165,9 @@ int MinerThreadCount()
165 return (int)(nCores - 1); 165 return (int)(nCores - 1);
166} 166}
167 167
168static void SecureClearBytes(vector<unsigned char>& vch);
169static void SecureClearKeyingMaterial(CKeyingMaterial& vch);
170
168bool AddKey(const CKey& key) 171bool AddKey(const CKey& key)
169{ 172{
170 if (IsWalletEncrypted()) 173 if (IsWalletEncrypted())
@@ -174,9 +177,13 @@ bool AddKey(const CKey& key)
174 vector<unsigned char> vchCryptedSecret; 177 vector<unsigned char> vchCryptedSecret;
175 if (IsWalletLocked()) 178 if (IsWalletLocked())
176 return error("AddKey() : wallet is locked\n"); 179 return error("AddKey() : wallet is locked\n");
177 if (!EncryptSecret(vWalletMasterKey, vector<unsigned char>(vchPrivKey.begin(), vchPrivKey.end()), 180 vector<unsigned char> vchPlainSecret(vchPrivKey.begin(), vchPrivKey.end());
178 WalletKeyIV(key.GetPubKey()), vchCryptedSecret)) 181 if (!EncryptSecret(vWalletMasterKey, vchPlainSecret, WalletKeyIV(key.GetPubKey()), vchCryptedSecret))
182 {
183 SecureClearBytes(vchPlainSecret);
179 return error("AddKey() : encrypting key failed\n"); 184 return error("AddKey() : encrypting key failed\n");
185 }
186 SecureClearBytes(vchPlainSecret);
180 if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret)) 187 if (!AddCryptedKey(key.GetPubKey(), vchCryptedSecret))
181 return false; 188 return false;
182 return CWalletDB().WriteCryptedKey(key.GetPubKey(), vchCryptedSecret); 189 return CWalletDB().WriteCryptedKey(key.GetPubKey(), vchCryptedSecret);
@@ -200,17 +207,31 @@ bool IsWalletLocked()
200 return fWalletEncrypted && fWalletLocked; 207 return fWalletEncrypted && fWalletLocked;
201} 208}
202 209
210static void SecureClearBytes(vector<unsigned char>& vch)
211{
212 if (!vch.empty())
213 OPENSSL_cleanse(&vch[0], vch.size());
214 vch.clear();
215}
216
217static void SecureClearKeyingMaterial(CKeyingMaterial& vch)
218{
219 if (!vch.empty())
220 OPENSSL_cleanse(&vch[0], vch.size());
221 vch.clear();
222}
223
203void LockWallet() 224void LockWallet()
204{ 225{
205 if (!fWalletEncrypted) 226 if (!fWalletEncrypted)
206 return; 227 return;
207 CRITICAL_BLOCK(cs_mapKeys) 228 CRITICAL_BLOCK(cs_mapKeys)
208 { 229 {
209 vWalletMasterKey.clear(); 230 SecureClearKeyingMaterial(vWalletMasterKey);
210 if (!vchCryptedHDMaster.empty()) 231 if (!vchCryptedHDMaster.empty())
211 vchHDMaster.clear(); 232 SecureClearBytes(vchHDMaster);
212 if (!vchCryptedHDChainCode.empty()) 233 if (!vchCryptedHDChainCode.empty())
213 vchHDChainCode.clear(); 234 SecureClearBytes(vchHDChainCode);
214 fWalletLocked = true; 235 fWalletLocked = true;
215 } 236 }
216} 237}
@@ -235,14 +256,14 @@ bool DeriveWalletPassphraseKey(const string& strPassphrase,
235 chKey, chIV); 256 chKey, chIV);
236 if (n != 32) 257 if (n != 32)
237 { 258 {
238 memset(chKey, 0, sizeof(chKey)); 259 OPENSSL_cleanse(chKey, sizeof(chKey));
239 memset(chIV, 0, sizeof(chIV)); 260 OPENSSL_cleanse(chIV, sizeof(chIV));
240 return false; 261 return false;
241 } 262 }
242 vchKeyRet.assign(chKey, chKey + sizeof(chKey)); 263 vchKeyRet.assign(chKey, chKey + sizeof(chKey));
243 vchIVRet.assign(chIV, chIV + sizeof(chIV)); 264 vchIVRet.assign(chIV, chIV + sizeof(chIV));
244 memset(chKey, 0, sizeof(chKey)); 265 OPENSSL_cleanse(chKey, sizeof(chKey));
245 memset(chIV, 0, sizeof(chIV)); 266 OPENSSL_cleanse(chIV, sizeof(chIV));
246 return true; 267 return true;
247} 268}
248 269
@@ -303,6 +324,8 @@ bool DecryptSecret(const CKeyingMaterial& vchKey,
303 vchPlaintextRet.swap(vchOut); 324 vchPlaintextRet.swap(vchOut);
304 fOk = true; 325 fOk = true;
305 } 326 }
327 if (!fOk)
328 SecureClearBytes(vchOut);
306 EVP_CIPHER_CTX_free(ctx); 329 EVP_CIPHER_CTX_free(ctx);
307 return fOk; 330 return fOk;
308} 331}
@@ -378,6 +401,7 @@ bool GetWalletPrivKey(const vector<unsigned char>& vchPubKey,
378 } 401 }
379 402
380 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end()); 403 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end());
404 SecureClearBytes(vchPlaintext);
381 CKey key; 405 CKey key;
382 if (!key.SetPrivKey(vchPrivKey) || key.GetPubKey() != vchPubKey) 406 if (!key.SetPrivKey(vchPrivKey) || key.GetPubKey() != vchPubKey)
383 { 407 {
@@ -412,11 +436,20 @@ bool UnlockWallet(const string& strPassphrase, string& strErrorRet)
412 vector<unsigned char> vchMasterPlain; 436 vector<unsigned char> vchMasterPlain;
413 if (!DecryptSecret(vchPassKey, kMasterKey.vchCryptedKey, 437 if (!DecryptSecret(vchPassKey, kMasterKey.vchCryptedKey,
414 vchPassIV, vchMasterPlain)) 438 vchPassIV, vchMasterPlain))
439 {
440 SecureClearBytes(vchPassIV);
415 continue; 441 continue;
442 }
416 if (vchMasterPlain.size() != 32) 443 if (vchMasterPlain.size() != 32)
444 {
445 SecureClearBytes(vchMasterPlain);
446 SecureClearBytes(vchPassIV);
417 continue; 447 continue;
448 }
418 449
419 CKeyingMaterial vchCandidate(vchMasterPlain.begin(), vchMasterPlain.end()); 450 CKeyingMaterial vchCandidate(vchMasterPlain.begin(), vchMasterPlain.end());
451 SecureClearBytes(vchMasterPlain);
452 SecureClearBytes(vchPassIV);
420 bool fValid = mapCryptedKeys.empty(); 453 bool fValid = mapCryptedKeys.empty();
421 for (map<vector<unsigned char>, vector<unsigned char> >::iterator mci = mapCryptedKeys.begin(); 454 for (map<vector<unsigned char>, vector<unsigned char> >::iterator mci = mapCryptedKeys.begin();
422 mci != mapCryptedKeys.end(); ++mci) 455 mci != mapCryptedKeys.end(); ++mci)
@@ -425,6 +458,7 @@ bool UnlockWallet(const string& strPassphrase, string& strErrorRet)
425 if (!DecryptSecret(vchCandidate, (*mci).second, WalletKeyIV((*mci).first), vchPlaintext)) 458 if (!DecryptSecret(vchCandidate, (*mci).second, WalletKeyIV((*mci).first), vchPlaintext))
426 break; 459 break;
427 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end()); 460 CPrivKey vchPrivKey(vchPlaintext.begin(), vchPlaintext.end());
461 SecureClearBytes(vchPlaintext);
428 CKey key; 462 CKey key;
429 if (key.SetPrivKey(vchPrivKey) && key.GetPubKey() == (*mci).first) 463 if (key.SetPrivKey(vchPrivKey) && key.GetPubKey() == (*mci).first)
430 fValid = true; 464 fValid = true;
@@ -440,10 +474,12 @@ bool UnlockWallet(const string& strPassphrase, string& strErrorRet)
440 WalletSecretIV("hdmaster"), vchPlainHDMaster) || 474 WalletSecretIV("hdmaster"), vchPlainHDMaster) ||
441 vchPlainHDMaster.size() != 32) 475 vchPlainHDMaster.size() != 32)
442 { 476 {
477 SecureClearBytes(vchPlainHDMaster);
443 strErrorRet = "could not decrypt HD master key"; 478 strErrorRet = "could not decrypt HD master key";
444 return false; 479 return false;
445 } 480 }
446 vchHDMaster = vchPlainHDMaster; 481 vchHDMaster = vchPlainHDMaster;
482 SecureClearBytes(vchPlainHDMaster);
447 } 483 }
448 if (!vchCryptedHDChainCode.empty()) 484 if (!vchCryptedHDChainCode.empty())
449 { 485 {
@@ -452,10 +488,12 @@ bool UnlockWallet(const string& strPassphrase, string& strErrorRet)
452 WalletSecretIV("hdchaincode"), vchPlainHDChainCode) || 488 WalletSecretIV("hdchaincode"), vchPlainHDChainCode) ||
453 vchPlainHDChainCode.size() != 32) 489 vchPlainHDChainCode.size() != 32)
454 { 490 {
491 SecureClearBytes(vchPlainHDChainCode);
455 strErrorRet = "could not decrypt HD chain code"; 492 strErrorRet = "could not decrypt HD chain code";
456 return false; 493 return false;
457 } 494 }
458 vchHDChainCode = vchPlainHDChainCode; 495 vchHDChainCode = vchPlainHDChainCode;
496 SecureClearBytes(vchPlainHDChainCode);
459 } 497 }
460 fWalletLocked = false; 498 fWalletLocked = false;
461 return true; 499 return true;