|
|
1.1 root 1: /*
2: Copyright (c) 2008 TrueCrypt Foundation. All rights reserved.
3:
4: Governed by the TrueCrypt License 2.4 the full text of which is contained
5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
7: */
8:
9: #include "Platform/Memory.h"
10: #include "Common/Crc.h"
11: #include "Common/Endian.h"
12: #include "EncryptionModeCBC.h"
13:
14: namespace TrueCrypt
15: {
16: void EncryptionModeCBC::Decrypt (byte *data, uint64 length) const
17: {
18: if_debug (ValidateState ());
19: if_debug (ValidateParameters (data, length));
20:
21: if (IsOuterCBC (Ciphers))
22: {
23: DecryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
24: }
25: else
26: {
27: for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
28: iCipherList != Ciphers.rend();
29: ++iCipherList)
30: {
31: CipherList cl;
32: cl.push_back (*iCipherList);
33:
34: DecryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
35: }
36: }
37: }
38:
39: void EncryptionModeCBC::DecryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
40: {
41: size_t blockSize = ciphers.front()->GetBlockSize();
42: if (blockSize != 8 && blockSize != 16)
43: throw ParameterIncorrect (SRC_POS);
44:
45: uint32 *data32 = (uint32 *) data;
46: uint32 bufIV[4];
47: uint32 ct[4];
48: uint64 i;
49:
50: bufIV[0] = iv[0];
51: bufIV[1] = iv[1];
52: if (blockSize == 16)
53: {
54: bufIV[2] = iv[2];
55: bufIV[3] = iv[3];
56: }
57:
58: for (i = 0; i < length / blockSize; i++)
59: {
60: // Dewhitening
61: data32[0] ^= whitening[0];
62: data32[1] ^= whitening[1];
63: if (blockSize == 16)
64: {
65: data32[2] ^= whitening[0];
66: data32[3] ^= whitening[1];
67: }
68:
69: // CBC
70: ct[0] = data32[0];
71: ct[1] = data32[1];
72: if (blockSize == 16)
73: {
74: ct[2] = data32[2];
75: ct[3] = data32[3];
76: }
77:
78: for (CipherList::const_reverse_iterator iCipherList = ciphers.rbegin();
79: iCipherList != ciphers.rend();
80: ++iCipherList)
81: {
82: const Cipher &c = **iCipherList;
83:
84: if (c.GetBlockSize () != blockSize)
85: throw ParameterIncorrect (SRC_POS);
86:
87: c.DecryptBlock ((byte *) data32);
88: }
89:
90: // CBC
91: data32[0] ^= bufIV[0];
92: data32[1] ^= bufIV[1];
93: bufIV[0] = ct[0];
94: bufIV[1] = ct[1];
95: if (blockSize == 16)
96: {
97: data32[2] ^= bufIV[2];
98: data32[3] ^= bufIV[3];
99: bufIV[2] = ct[2];
100: bufIV[3] = ct[3];
101: }
102:
103: data32 += blockSize / sizeof(*data32);
104: }
105:
106: Memory::Erase (bufIV, sizeof (bufIV));
107: Memory::Erase (ct, sizeof (ct));
108: }
109:
110: void EncryptionModeCBC::DecryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
111: {
112: if_debug (ValidateState ());
113: if_debug (ValidateParameters (data, sectorCount, sectorSize));
114:
115: uint32 sectorIV[4];
116: uint32 sectorWhitening[2];
117:
118: while (sectorCount--)
119: {
120: if (IsOuterCBC (Ciphers))
121: {
122: InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
123: DecryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
124: }
125: else
126: {
127: for (CipherList::const_reverse_iterator iCipherList = Ciphers.rbegin();
128: iCipherList != Ciphers.rend();
129: ++iCipherList)
130: {
131: const Cipher &c = **iCipherList;
132: CipherList cl;
133: cl.push_back (*iCipherList);
134:
135: InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
136: DecryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
137: }
138: }
139:
140: data += sectorSize;
141: sectorIndex++;
142: }
143:
144: Memory::Erase (sectorIV, sizeof (sectorIV));
145: Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
146: }
147:
148: void EncryptionModeCBC::Encrypt (byte *data, uint64 length) const
149: {
150: if_debug (ValidateState ());
151: if_debug (ValidateParameters (data, length));
152:
153: if (IsOuterCBC (Ciphers))
154: {
155: EncryptBuffer (data, length, Ciphers, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
156: }
157: else
158: {
159: for (CipherList::const_iterator iCipherList = Ciphers.begin();
160: iCipherList != Ciphers.end();
161: ++iCipherList)
162: {
163: CipherList cl;
164: cl.push_back (*iCipherList);
165:
166: EncryptBuffer (data, length, cl, (uint32 *) IV.Ptr(), (uint32 *) (IV.Ptr() + WhiteningIVOffset));
167: }
168: }
169: }
170:
171: void EncryptionModeCBC::EncryptBuffer (byte *data, uint64 length, const CipherList &ciphers, const uint32 *iv, const uint32 *whitening) const
172: {
173: size_t blockSize = ciphers.front()->GetBlockSize();
174: if (blockSize != 8 && blockSize != 16)
175: throw ParameterIncorrect (SRC_POS);
176:
177: uint32 *data32 = (uint32 *) data;
178: uint32 bufIV[4];
179: uint64 i;
180:
181: bufIV[0] = iv[0];
182: bufIV[1] = iv[1];
183: if (blockSize == 16)
184: {
185: bufIV[2] = iv[2];
186: bufIV[3] = iv[3];
187: }
188:
189: for (i = 0; i < length / blockSize; i++)
190: {
191: data32[0] ^= bufIV[0];
192: data32[1] ^= bufIV[1];
193: if (blockSize == 16)
194: {
195: data32[2] ^= bufIV[2];
196: data32[3] ^= bufIV[3];
197: }
198:
199: for (CipherList::const_iterator iCipherList = ciphers.begin();
200: iCipherList != ciphers.end();
201: ++iCipherList)
202: {
203: const Cipher &c = **iCipherList;
204:
205: if (c.GetBlockSize () != blockSize)
206: throw ParameterIncorrect (SRC_POS);
207:
208: c.EncryptBlock ((byte *) data32);
209: }
210:
211: bufIV[0] = data32[0];
212: bufIV[1] = data32[1];
213: if (blockSize == 16)
214: {
215: bufIV[2] = data32[2];
216: bufIV[3] = data32[3];
217: }
218:
219: data32[0] ^= whitening[0];
220: data32[1] ^= whitening[1];
221: if (blockSize == 16)
222: {
223: data32[2] ^= whitening[0];
224: data32[3] ^= whitening[1];
225: }
226:
227: data32 += blockSize / sizeof(*data32);
228: }
229:
230: Memory::Erase (bufIV, sizeof (bufIV));
231: }
232:
233: void EncryptionModeCBC::EncryptSectors (byte *data, uint64 sectorIndex, uint64 sectorCount, size_t sectorSize) const
234: {
235: if_debug (ValidateState ());
236: if_debug (ValidateParameters (data, sectorCount, sectorSize));
237:
238: uint32 sectorIV[4];
239: uint32 sectorWhitening[2];
240:
241: while (sectorCount--)
242: {
243: if (IsOuterCBC (Ciphers))
244: {
245: InitSectorIVAndWhitening (sectorIndex, Ciphers.front()->GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
246: EncryptBuffer (data, sectorSize, Ciphers, sectorIV, sectorWhitening);
247: }
248: else
249: {
250: for (CipherList::const_iterator iCipherList = Ciphers.begin();
251: iCipherList != Ciphers.end();
252: ++iCipherList)
253: {
254: const Cipher &c = **iCipherList;
255: CipherList cl;
256: cl.push_back (*iCipherList);
257:
258: InitSectorIVAndWhitening (sectorIndex, c.GetBlockSize(), (uint64 *) IV.Ptr(), sectorIV, sectorWhitening);
259: EncryptBuffer (data, sectorSize, cl, sectorIV, sectorWhitening);
260: }
261: }
262:
263: data += sectorSize;
264: sectorIndex++;
265: }
266:
267: Memory::Erase (sectorIV, sizeof (sectorIV));
268: Memory::Erase (sectorWhitening, sizeof (sectorWhitening));
269: }
270:
271: void EncryptionModeCBC::InitSectorIVAndWhitening (uint64 sectorIndex, size_t blockSize, const uint64 *ivSeed, uint32 *iv, uint32 *whitening) const
272: {
273: if (blockSize != 8 && blockSize != 16)
274: throw ParameterIncorrect (SRC_POS);
275:
276: uint64 iv64[4];
277: uint32 *iv32 = (uint32 *) iv64;
278:
279: iv64[0] = ivSeed[0] ^ Endian::Little (sectorIndex);
280: iv64[1] = ivSeed[1] ^ Endian::Little (sectorIndex);
281: iv64[2] = ivSeed[2] ^ Endian::Little (sectorIndex);
282: if (blockSize == 16)
283: {
284: iv64[3] = ivSeed[3] ^ Endian::Little (sectorIndex);
285: }
286:
287: iv[0] = iv32[0];
288: iv[1] = iv32[1];
289:
290: if (blockSize == 8)
291: {
292: whitening[0] = Endian::Little ( crc32int ( &iv32[2] ) ^ crc32int ( &iv32[5] ) );
293: whitening[1] = Endian::Little ( crc32int ( &iv32[3] ) ^ crc32int ( &iv32[4] ) );
294: }
295: else
296: {
297: iv[2] = iv32[2];
298: iv[3] = iv32[3];
299:
300: whitening[0] = Endian::Little ( crc32int ( &iv32[4] ) ^ crc32int ( &iv32[7] ) );
301: whitening[1] = Endian::Little ( crc32int ( &iv32[5] ) ^ crc32int ( &iv32[6] ) );
302: }
303: }
304:
305: bool EncryptionModeCBC::IsOuterCBC (const CipherList &ciphers) const
306: {
307: if (ciphers.size() < 2)
308: return false;
309:
310: size_t blockSize = ciphers.front()->GetBlockSize();
311:
312: for (CipherList::const_iterator iCipherList = ciphers.begin();
313: iCipherList != ciphers.end();
314: ++iCipherList)
315: {
316: const Cipher &c = **iCipherList;
317: if (c.GetBlockSize() != blockSize)
318: return false;
319: }
320:
321: return true;
322: }
323:
324: void EncryptionModeCBC::SetKey (const ConstBufferPtr &key)
325: {
326: if (key.Size() != GetKeySize ())
327: throw ParameterIncorrect (SRC_POS);
328:
329: if (!KeySet)
330: IV.Allocate (GetKeySize ());
331:
332: IV.CopyFrom (key);
333: KeySet = true;
334: }
335: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.