LCOV - code coverage report
Current view: top level - src/wallet - crypter.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 47 53 88.7 %
Date: 2015-10-12 22:39:14 Functions: 14 20 70.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.11