|
|
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/Time.h"
10: #include "Crc32.h"
11: #include "EncryptionModeXTS.h"
12: #include "Pkcs5Kdf.h"
13: #include "Pkcs5Kdf.h"
14: #include "VolumeHeader.h"
15: #include "VolumeException.h"
16:
17: namespace TrueCrypt
18: {
19: VolumeHeader::VolumeHeader (uint32 size)
20: : HeaderSize (size), EncryptedHeaderDataSize (size - EncryptedHeaderDataOffset)
21: {
22: }
23:
24: VolumeHeader::~VolumeHeader ()
25: {
26: VolumeKeyAreaCrc32 = 0;
27: VolumeCreationTime = 0;
28: HeaderCreationTime = 0;
29: mVolumeType = VolumeType::Unknown;
30: HiddenVolumeDataSize = 0;
31: VolumeDataSize = 0;
32: EncryptedAreaStart = 0;
33: EncryptedAreaLength = 0;
34: }
35:
36: void VolumeHeader::Create (const BufferPtr &headerBuffer, VolumeHeaderCreationOptions &options)
37: {
38: if (options.DataKey.Size() != options.EA->GetKeySize() * 2 || options.Salt.Size() != GetSaltSize())
39: throw ParameterIncorrect (SRC_POS);
40:
41: headerBuffer.Zero();
42:
43: HeaderVersion = CurrentHeaderVersion;
44: RequiredMinProgramVersion = CurrentRequiredMinProgramVersion;
45:
46: DataAreaKey.Zero();
47: DataAreaKey.CopyFrom (options.DataKey);
48:
49: VolumeCreationTime = Time::GetCurrent();
50: HiddenVolumeDataSize = (options.Type == VolumeType::Hidden ? options.VolumeSize : 0);
51: VolumeDataSize = options.VolumeSize;
52:
53: EncryptedAreaStart = 0;
54: EncryptedAreaLength = options.VolumeSize;
55:
56: EA = options.EA;
57: shared_ptr <EncryptionMode> mode (new EncryptionModeXTS ());
58: EA->SetMode (mode);
59:
60: EncryptNew (headerBuffer, options.Salt, options.HeaderKey, options.Kdf);
61: }
62:
63: bool VolumeHeader::Decrypt (const ConstBufferPtr &encryptedData, const VolumePassword &password, const EncryptionAlgorithmList &encryptionAlgorithms, const EncryptionModeList &encryptionModes)
64: {
65: if (password.Size() < 1)
66: throw PasswordEmpty (SRC_POS);
67:
68: ConstBufferPtr salt (encryptedData.GetRange (SaltOffset, SaltSize));
69: SecureBuffer header (EncryptedHeaderDataSize);
70: SecureBuffer headerKey (GetLargestSerializedKeySize());
71:
72: foreach (shared_ptr <Pkcs5Kdf> pkcs5, Pkcs5Kdf::GetAvailableAlgorithms())
73: {
74: pkcs5->DeriveKey (headerKey, password, salt);
75:
76: foreach (shared_ptr <EncryptionMode> mode, encryptionModes)
77: {
78: if (typeid (*mode) != typeid (EncryptionModeXTS))
79: mode->SetKey (headerKey.GetRange (0, mode->GetKeySize()));
80:
81: foreach (shared_ptr <EncryptionAlgorithm> ea, encryptionAlgorithms)
82: {
83: if (!ea->IsModeSupported (mode))
84: continue;
85:
86: if (typeid (*mode) == typeid (EncryptionModeXTS))
87: {
88: ea->SetKey (headerKey.GetRange (0, ea->GetKeySize()));
89:
90: mode = mode->GetNew();
91: mode->SetKey (headerKey.GetRange (ea->GetKeySize(), ea->GetKeySize()));
92: }
93: else
94: {
95: ea->SetKey (headerKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
96: }
97:
98: ea->SetMode (mode);
99:
100: header.CopyFrom (encryptedData.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize));
101: ea->Decrypt (header);
102:
103: if (Deserialize (header, ea, mode))
104: {
105: EA = ea;
106: Pkcs5 = pkcs5;
107: return true;
108: }
109: }
110: }
111: }
112:
113: return false;
114: }
115:
116: bool VolumeHeader::Deserialize (const ConstBufferPtr &header, shared_ptr <EncryptionAlgorithm> &ea, shared_ptr <EncryptionMode> &mode)
117: {
118: if (header.Size() != EncryptedHeaderDataSize)
119: throw ParameterIncorrect (SRC_POS);
120:
121: if (header[0] != 'T' ||
122: header[1] != 'R' ||
123: header[2] != 'U' ||
124: header[3] != 'E')
125: return false;
126:
127: size_t offset = 4;
128: HeaderVersion = DeserializeEntry <uint16> (header, offset);
129:
130: if (HeaderVersion < MinAllowedHeaderVersion)
131: return false;
132:
133: RequiredMinProgramVersion = DeserializeEntry <uint16> (header, offset);
134:
135: if (RequiredMinProgramVersion > Version::Number())
136: throw HigherVersionRequired (SRC_POS);
137:
138: VolumeKeyAreaCrc32 = DeserializeEntry <uint32> (header, offset);
139: VolumeCreationTime = DeserializeEntry <uint64> (header, offset);
140: HeaderCreationTime = DeserializeEntry <uint64> (header, offset);
141: HiddenVolumeDataSize = DeserializeEntry <uint64> (header, offset);
142: mVolumeType = (HiddenVolumeDataSize != 0 ? VolumeType::Hidden : VolumeType::Normal);
143: VolumeDataSize = DeserializeEntry <uint64> (header, offset);
144: EncryptedAreaStart = DeserializeEntry <uint64> (header, offset);
145: EncryptedAreaLength = DeserializeEntry <uint64> (header, offset);
146:
147: offset = DataAreaKeyOffset;
148:
149: if (VolumeKeyAreaCrc32 != Crc32::ProcessBuffer (header.GetRange (offset, DataKeyAreaMaxSize)))
150: return false;
151:
152: DataAreaKey.CopyFrom (header.GetRange (offset, DataKeyAreaMaxSize));
153:
154: ea = ea->GetNew();
155: mode = mode->GetNew();
156:
157: if (typeid (*mode) == typeid (EncryptionModeXTS))
158: {
159: ea->SetKey (header.GetRange (offset, ea->GetKeySize()));
160: mode->SetKey (header.GetRange (offset + ea->GetKeySize(), ea->GetKeySize()));
161: }
162: else
163: {
164: mode->SetKey (header.GetRange (offset, mode->GetKeySize()));
165: ea->SetKey (header.GetRange (offset + LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
166: }
167:
168: ea->SetMode (mode);
169:
170: return true;
171: }
172:
173: template <typename T>
174: T VolumeHeader::DeserializeEntry (const ConstBufferPtr &header, size_t &offset) const
175: {
176: offset += sizeof (T);
177:
178: if (offset > header.Size())
179: throw ParameterIncorrect (SRC_POS);
180:
181: return Endian::Big (*reinterpret_cast<const T *> (header.Get() + offset - sizeof (T)));
182: }
183:
184: void VolumeHeader::EncryptNew (const BufferPtr &newHeaderBuffer, const ConstBufferPtr &newSalt, const ConstBufferPtr &newHeaderKey, shared_ptr <Pkcs5Kdf> newPkcs5Kdf)
185: {
186: if (newHeaderBuffer.Size() != HeaderSize || newSalt.Size() != SaltSize)
187: throw ParameterIncorrect (SRC_POS);
188:
189: shared_ptr <EncryptionMode> mode = EA->GetMode()->GetNew();
190: shared_ptr <EncryptionAlgorithm> ea = EA->GetNew();
191:
192: if (typeid (*mode) == typeid (EncryptionModeXTS))
193: {
194: mode->SetKey (newHeaderKey.GetRange (EA->GetKeySize(), EA->GetKeySize()));
195: ea->SetKey (newHeaderKey.GetRange (0, ea->GetKeySize()));
196: }
197: else
198: {
199: mode->SetKey (newHeaderKey.GetRange (0, mode->GetKeySize()));
200: ea->SetKey (newHeaderKey.GetRange (LegacyEncryptionModeKeyAreaSize, ea->GetKeySize()));
201: }
202:
203: ea->SetMode (mode);
204:
205: BufferPtr headerData = newHeaderBuffer.GetRange (EncryptedHeaderDataOffset, EncryptedHeaderDataSize);
206:
207: Serialize (headerData);
208: ea->Encrypt (headerData);
209:
210: Memory::Copy (newHeaderBuffer, newSalt, newSalt.Size());
211:
212: if (newPkcs5Kdf)
213: Pkcs5 = newPkcs5Kdf;
214: }
215:
216: size_t VolumeHeader::GetLargestSerializedKeySize ()
217: {
218: size_t largestKey = EncryptionAlgorithm::GetLargestKeySize (EncryptionAlgorithm::GetAvailableAlgorithms());
219:
220: // XTS mode requires the same key size as the encryption algorithm.
221: // Legacy modes may require larger key than XTS.
222: if (LegacyEncryptionModeKeyAreaSize + largestKey > largestKey * 2)
223: return LegacyEncryptionModeKeyAreaSize + largestKey;
224:
225: return largestKey * 2;
226: }
227:
228: void VolumeHeader::Serialize (const BufferPtr &header) const
229: {
230: if (header.Size() != EncryptedHeaderDataSize)
231: throw ParameterIncorrect (SRC_POS);
232:
233: header.Zero();
234:
235: header[0] = 'T';
236: header[1] = 'R';
237: header[2] = 'U';
238: header[3] = 'E';
239: size_t offset = 4;
240:
241: header.GetRange (DataAreaKeyOffset, DataAreaKey.Size()).CopyFrom (DataAreaKey);
242:
243: SerializeEntry (HeaderVersion, header, offset);
244: SerializeEntry (RequiredMinProgramVersion, header, offset);
245: SerializeEntry (Crc32::ProcessBuffer (header.GetRange (DataAreaKeyOffset, DataKeyAreaMaxSize)), header, offset);
246: SerializeEntry (VolumeCreationTime, header, offset);
247: SerializeEntry (Time::GetCurrent(), header, offset);
248: SerializeEntry (HiddenVolumeDataSize, header, offset);
249: SerializeEntry (VolumeDataSize, header, offset);
250: SerializeEntry (EncryptedAreaStart, header, offset);
251: SerializeEntry (EncryptedAreaLength, header, offset);
252:
253: }
254:
255: template <typename T>
256: void VolumeHeader::SerializeEntry (const T &entry, const BufferPtr &header, size_t &offset) const
257: {
258: offset += sizeof (T);
259:
260: if (offset > header.Size())
261: throw ParameterIncorrect (SRC_POS);
262:
263: *reinterpret_cast<T *> (header.Get() + offset - sizeof (T)) = Endian::Big (entry);
264: }
265: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.