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