|
|
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.