Projects : bitcoin : bitcoin_dumpblock_no_losers
1 | // Copyright (c) 2011 The Bitcoin Developers |
2 | // Distributed under the MIT/X11 software license, see the accompanying |
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
4 | |
5 | #include <openssl/aes.h> |
6 | #include <openssl/evp.h> |
7 | #include <vector> |
8 | #include <string> |
9 | #include "headers.h" |
10 | |
11 | #include "crypter.h" |
12 | #include "main.h" |
13 | #include "util.h" |
14 | |
15 | bool CCrypter::SetKeyFromPassphrase(const SecureString& strKeyData, const std::vector<unsigned char>& chSalt, const unsigned int nRounds, const unsigned int nDerivationMethod) |
16 | { |
17 | if (nRounds < 1 || chSalt.size() != WALLET_CRYPTO_SALT_SIZE) |
18 | return false; |
19 | |
20 | // Try to keep the keydata out of swap (and be a bit over-careful to keep the IV that we don't even use out of swap) |
21 | // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) |
22 | // 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. |
23 | mlock(&chKey[0], sizeof chKey); |
24 | mlock(&chIV[0], sizeof chIV); |
25 | |
26 | int i = 0; |
27 | if (nDerivationMethod == 0) |
28 | i = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), &chSalt[0], |
29 | (unsigned char *)&strKeyData[0], strKeyData.size(), nRounds, chKey, chIV); |
30 | |
31 | if (i != WALLET_CRYPTO_KEY_SIZE) |
32 | { |
33 | memset(&chKey, 0, sizeof chKey); |
34 | memset(&chIV, 0, sizeof chIV); |
35 | return false; |
36 | } |
37 | |
38 | fKeySet = true; |
39 | return true; |
40 | } |
41 | |
42 | bool CCrypter::SetKey(const CKeyingMaterial& chNewKey, const std::vector<unsigned char>& chNewIV) |
43 | { |
44 | if (chNewKey.size() != WALLET_CRYPTO_KEY_SIZE || chNewIV.size() != WALLET_CRYPTO_KEY_SIZE) |
45 | return false; |
46 | |
47 | // Try to keep the keydata out of swap |
48 | // Note that this does nothing about suspend-to-disk (which will put all our key data on disk) |
49 | // 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. |
50 | mlock(&chKey[0], sizeof chKey); |
51 | mlock(&chIV[0], sizeof chIV); |
52 | |
53 | memcpy(&chKey[0], &chNewKey[0], sizeof chKey); |
54 | memcpy(&chIV[0], &chNewIV[0], sizeof chIV); |
55 | |
56 | fKeySet = true; |
57 | return true; |
58 | } |
59 | |
60 | bool CCrypter::Encrypt(const CKeyingMaterial& vchPlaintext, std::vector<unsigned char> &vchCiphertext) |
61 | { |
62 | if (!fKeySet) |
63 | return false; |
64 | |
65 | // max ciphertext len for a n bytes of plaintext is |
66 | // n + AES_BLOCK_SIZE - 1 bytes |
67 | int nLen = vchPlaintext.size(); |
68 | int nCLen = nLen + AES_BLOCK_SIZE, nFLen = 0; |
69 | vchCiphertext = std::vector<unsigned char> (nCLen); |
70 | |
71 | EVP_CIPHER_CTX ctx; |
72 | |
73 | EVP_CIPHER_CTX_init(&ctx); |
74 | EVP_EncryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); |
75 | |
76 | EVP_EncryptUpdate(&ctx, &vchCiphertext[0], &nCLen, &vchPlaintext[0], nLen); |
77 | EVP_EncryptFinal_ex(&ctx, (&vchCiphertext[0])+nCLen, &nFLen); |
78 | |
79 | EVP_CIPHER_CTX_cleanup(&ctx); |
80 | |
81 | vchCiphertext.resize(nCLen + nFLen); |
82 | return true; |
83 | } |
84 | |
85 | bool CCrypter::Decrypt(const std::vector<unsigned char>& vchCiphertext, CKeyingMaterial& vchPlaintext) |
86 | { |
87 | if (!fKeySet) |
88 | return false; |
89 | |
90 | // plaintext will always be equal to or lesser than length of ciphertext |
91 | int nLen = vchCiphertext.size(); |
92 | int nPLen = nLen, nFLen = 0; |
93 | |
94 | vchPlaintext = CKeyingMaterial(nPLen); |
95 | |
96 | EVP_CIPHER_CTX ctx; |
97 | |
98 | EVP_CIPHER_CTX_init(&ctx); |
99 | EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, chKey, chIV); |
100 | |
101 | EVP_DecryptUpdate(&ctx, &vchPlaintext[0], &nPLen, &vchCiphertext[0], nLen); |
102 | EVP_DecryptFinal_ex(&ctx, (&vchPlaintext[0])+nPLen, &nFLen); |
103 | |
104 | EVP_CIPHER_CTX_cleanup(&ctx); |
105 | |
106 | vchPlaintext.resize(nPLen + nFLen); |
107 | return true; |
108 | } |
109 | |
110 | |
111 | bool EncryptSecret(CKeyingMaterial& vMasterKey, const CSecret &vchPlaintext, const uint256& nIV, std::vector<unsigned char> &vchCiphertext) |
112 | { |
113 | CCrypter cKeyCrypter; |
114 | std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); |
115 | memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); |
116 | if(!cKeyCrypter.SetKey(vMasterKey, chIV)) |
117 | return false; |
118 | return cKeyCrypter.Encrypt((CKeyingMaterial)vchPlaintext, vchCiphertext); |
119 | } |
120 | |
121 | bool DecryptSecret(const CKeyingMaterial& vMasterKey, const std::vector<unsigned char>& vchCiphertext, const uint256& nIV, CSecret& vchPlaintext) |
122 | { |
123 | CCrypter cKeyCrypter; |
124 | std::vector<unsigned char> chIV(WALLET_CRYPTO_KEY_SIZE); |
125 | memcpy(&chIV[0], &nIV, WALLET_CRYPTO_KEY_SIZE); |
126 | if(!cKeyCrypter.SetKey(vMasterKey, chIV)) |
127 | return false; |
128 | return cKeyCrypter.Decrypt(vchCiphertext, *((CKeyingMaterial*)&vchPlaintext)); |
129 | } |