Line data Source code
1 : // Copyright (c) 2009-2014 The Bitcoin Core developers
2 : // Distributed under the MIT software license, see the accompanying
3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 :
5 : #ifndef BITCOIN_WALLET_CRYPTER_H
6 : #define BITCOIN_WALLET_CRYPTER_H
7 :
8 : #include "keystore.h"
9 : #include "serialize.h"
10 : #include "support/allocators/secure.h"
11 :
12 : class uint256;
13 :
14 : const unsigned int WALLET_CRYPTO_KEY_SIZE = 32;
15 : const unsigned int WALLET_CRYPTO_SALT_SIZE = 8;
16 :
17 : /**
18 : * Private key encryption is done based on a CMasterKey,
19 : * which holds a salt and random encryption key.
20 : *
21 : * CMasterKeys are encrypted using AES-256-CBC using a key
22 : * derived using derivation method nDerivationMethod
23 : * (0 == EVP_sha512()) and derivation iterations nDeriveIterations.
24 : * vchOtherDerivationParameters is provided for alternative algorithms
25 : * which may require more parameters (such as scrypt).
26 : *
27 : * Wallet Private Keys are then encrypted using AES-256-CBC
28 : * with the double-sha256 of the public key as the IV, and the
29 : * master key's key as the encryption key (see keystore.[ch]).
30 : */
31 :
32 : /** Master key for wallet encryption */
33 38 : class CMasterKey
34 : {
35 : public:
36 : std::vector<unsigned char> vchCryptedKey;
37 : std::vector<unsigned char> vchSalt;
38 : //! 0 = EVP_sha512()
39 : //! 1 = scrypt()
40 : unsigned int nDerivationMethod;
41 : unsigned int nDeriveIterations;
42 : //! Use this for more parameters to key derivation,
43 : //! such as the various parameters to scrypt
44 : std::vector<unsigned char> vchOtherDerivationParameters;
45 :
46 2 : ADD_SERIALIZE_METHODS;
47 :
48 : template <typename Stream, typename Operation>
49 2 : inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
50 2 : READWRITE(vchCryptedKey);
51 2 : READWRITE(vchSalt);
52 2 : READWRITE(nDerivationMethod);
53 2 : READWRITE(nDeriveIterations);
54 2 : READWRITE(vchOtherDerivationParameters);
55 2 : }
56 :
57 4 : CMasterKey()
58 12 : {
59 : // 25000 rounds is just under 0.1 seconds on a 1.86 GHz Pentium M
60 : // ie slightly lower than the lowest hardware we need bother supporting
61 4 : nDeriveIterations = 25000;
62 4 : nDerivationMethod = 0;
63 12 : vchOtherDerivationParameters = std::vector<unsigned char>(0);
64 4 : }
65 : };
66 :
67 : typedef std::vector<unsigned char, secure_allocator<unsigned char> > CKeyingMaterial;
68 :
69 : /** Encryption/decryption context with key information */
70 : class CCrypter
71 : {
72 : private:
73 : unsigned char chKey[WALLET_CRYPTO_KEY_SIZE];
74 : unsigned char chIV[WALLET_CRYPTO_KEY_SIZE];
75 : bool fKeySet;
76 :
77 : public:
78 : bool SetKeyFromPassphrase(const SecureString &strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod);
79 : bool Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext);
80 : bool Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext);
81 : bool SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV);
82 :
83 261 : void CleanKey()
84 : {
85 261 : memory_cleanse(chKey, sizeof(chKey));
86 261 : memory_cleanse(chIV, sizeof(chIV));
87 261 : fKeySet = false;
88 261 : }
89 :
90 261 : CCrypter()
91 : {
92 261 : fKeySet = false;
93 :
94 : // Try to keep the key data out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap)
95 : // Note that this does nothing about suspend-to-disk (which will put all our key data on disk)
96 : // Note as well that at no point in this program is any attempt made to prevent stealing of keys by reading the memory of the running process.
97 522 : LockedPageManager::Instance().LockRange(&chKey[0], sizeof chKey);
98 522 : LockedPageManager::Instance().LockRange(&chIV[0], sizeof chIV);
99 261 : }
100 :
101 261 : ~CCrypter()
102 : {
103 261 : CleanKey();
104 :
105 522 : LockedPageManager::Instance().UnlockRange(&chKey[0], sizeof chKey);
106 522 : LockedPageManager::Instance().UnlockRange(&chIV[0], sizeof chIV);
107 261 : }
108 : };
109 :
110 : /** Keystore which keeps the private keys encrypted.
111 : * It derives from the basic key store, which is used if no encryption is active.
112 : */
113 484 : class CCryptoKeyStore : public CBasicKeyStore
114 : {
115 : private:
116 : CryptedKeyMap mapCryptedKeys;
117 :
118 : CKeyingMaterial vMasterKey;
119 :
120 : //! if fUseCrypto is true, mapKeys must be empty
121 : //! if fUseCrypto is false, vMasterKey must be empty
122 : bool fUseCrypto;
123 :
124 : //! keeps track of whether Unlock has run a thorough check before
125 : bool fDecryptionThoroughlyChecked;
126 :
127 : protected:
128 : bool SetCrypted();
129 :
130 : //! will encrypt previously unencrypted keys
131 : bool EncryptKeys(CKeyingMaterial& vMasterKeyIn);
132 :
133 : bool Unlock(const CKeyingMaterial& vMasterKeyIn);
134 :
135 : public:
136 484 : CCryptoKeyStore() : fUseCrypto(false), fDecryptionThoroughlyChecked(false)
137 : {
138 121 : }
139 :
140 0 : bool IsCrypted() const
141 : {
142 0 : return fUseCrypto;
143 : }
144 :
145 1842 : bool IsLocked() const
146 : {
147 1842 : if (!IsCrypted())
148 : return false;
149 : bool result;
150 : {
151 221 : LOCK(cs_KeyStore);
152 442 : result = vMasterKey.empty();
153 : }
154 221 : return result;
155 : }
156 :
157 : bool Lock();
158 :
159 : virtual bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
160 : bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
161 35267 : bool HaveKey(const CKeyID &address) const
162 : {
163 : {
164 35267 : LOCK(cs_KeyStore);
165 35267 : if (!IsCrypted())
166 33618 : return CBasicKeyStore::HaveKey(address);
167 3298 : return mapCryptedKeys.count(address) > 0;
168 : }
169 : return false;
170 : }
171 : bool GetKey(const CKeyID &address, CKey& keyOut) const;
172 : bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const;
173 3 : void GetKeys(std::set<CKeyID> &setAddress) const
174 : {
175 3 : if (!IsCrypted())
176 : {
177 3 : CBasicKeyStore::GetKeys(setAddress);
178 3 : return;
179 : }
180 : setAddress.clear();
181 0 : CryptedKeyMap::const_iterator mi = mapCryptedKeys.begin();
182 0 : while (mi != mapCryptedKeys.end())
183 : {
184 0 : setAddress.insert((*mi).first);
185 0 : mi++;
186 : }
187 : }
188 :
189 : /**
190 : * Wallet status (encrypted, locked) changed.
191 : * Note: Called without locks held.
192 : */
193 : boost::signals2::signal<void (CCryptoKeyStore* wallet)> NotifyStatusChanged;
194 : };
195 :
196 : #endif // BITCOIN_WALLET_CRYPTER_H
|