void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, TC_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) #endif // !TC_WINDOWS_BOOT { int ea = ci->ea; unsigned __int8 *ks = ci->ks; unsigned __int8 *ks2 = ci->ks2; int cipher; switch (ci->mode) { case XTS: ks += EAGetKeyScheduleSize (ea); ks2 += EAGetKeyScheduleSize (ea); for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); ks2 -= CipherGetKeyScheduleSize (cipher); DecryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ks, ks2, cipher); } break; default: // Unknown/wrong ID TC_THROW_FATAL_EXCEPTION; } }
// DecryptBuffer // // buf: data to be decrypted; the start of the buffer is assumed to be aligned with the start of a data unit. // len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible // by the largest block size used within the cascade) void DecryptBuffer (unsigned __int8 *buf, TC_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) { switch (cryptoInfo->mode) { case XTS: { unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); unsigned __int8 *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); UINT64_STRUCT dataUnitNo; int cipher; // When encrypting/decrypting a buffer (typically a volume header) the sequential number // of the first XTS data unit in the buffer is always 0 and the start of the buffer is // always assumed to be aligned with the start of the data unit 0. dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; for (cipher = EAGetLastCipher (cryptoInfo->ea); cipher != 0; cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); ks2 -= CipherGetKeyScheduleSize (cipher); DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); } } break; default: // Unknown/wrong ID TC_THROW_FATAL_EXCEPTION; } }
static void EAGetDisplayName(char *buf, int ea, int i) { strcpy (buf, CipherGetName (i)); if (i = EAGetPreviousCipher(ea, i)) { strcat (buf, "("); EAGetDisplayName (&buf[strlen(buf)], ea, i); strcat (buf, ")"); } }
void DecryptBufferLRW128 (byte *buffer, uint64 length, uint64 blockIndex, PCRYPTO_INFO cryptoInfo) { /* Deprecated/legacy */ int cipher = EAGetFirstCipher (cryptoInfo->ea); int cipherCount = EAGetCipherCount (cryptoInfo->ea); unsigned __int8 *p = buffer; unsigned __int8 *ks = cryptoInfo->ks; unsigned __int8 i[8]; unsigned __int8 t[16]; unsigned __int64 b; *(unsigned __int64 *)i = BE64(blockIndex); if (length % 16) GST_THROW_FATAL_EXCEPTION; // Note that the maximum supported volume size is 8589934592 GB (i.e., 2^63 bytes). for (b = 0; b < length >> 4; b++) { Gf128MulBy64Tab (i, t, &cryptoInfo->gf_ctx); Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); if (cipherCount > 1) { // Cipher cascade ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); for (cipher = EAGetLastCipher (cryptoInfo->ea); cipher != 0; cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); DecipherBlock (cipher, p, ks); } } else { DecipherBlock (cipher, p, ks); } Xor128 ((unsigned __int64 *)p, (unsigned __int64 *)t); p += 16; if (i[7] != 0xff) i[7]++; else *(unsigned __int64 *)i = BE64 ( BE64(*(unsigned __int64 *)i) + 1 ); } FAST_ERASE64 (t, sizeof(t)); }
// Returns name of EA, cascaded cipher names are separated by hyphens char *EAGetName (char *buf, int ea) { int i = EAGetLastCipher(ea); strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); while (i = EAGetPreviousCipher(ea, i)) { strcat (buf, "-"); strcat (buf, CipherGetName (i)); } return buf; }
// Returns name of EA, cascaded cipher names are separated by hyphens char *EAGetName (char *buf, int ea, int guiDisplay) { if (guiDisplay) { EAGetDisplayName (buf, ea, EAGetLastCipher(ea)); } else { int i = EAGetLastCipher(ea); strcpy (buf, (i != 0) ? CipherGetName (i) : "?"); while (i = EAGetPreviousCipher(ea, i)) { strcat (buf, "-"); strcat (buf, CipherGetName (i)); } } return buf; }
void DecryptDataUnitsCurrentThread (unsigned __int8 *buf, const UINT64_STRUCT *structUnitNo, GST_LARGEST_COMPILER_UINT nbrUnits, PCRYPTO_INFO ci) #endif // !GST_WINDOWS_BOOT { int ea = ci->ea; unsigned __int8 *ks = ci->ks; unsigned __int8 *ks2 = ci->ks2; int cipher; #ifndef GST_NO_COMPILER_INT64 void *iv = ci->k2; // Deprecated/legacy unsigned __int64 unitNo = structUnitNo->Value; unsigned __int64 *iv64 = (unsigned __int64 *) iv; // Deprecated/legacy unsigned __int32 sectorIV[4]; // Deprecated/legacy unsigned __int32 secWhitening[2]; // Deprecated/legacy #endif // #ifndef GST_NO_COMPILER_INT64 switch (ci->mode) { case XTS: ks += EAGetKeyScheduleSize (ea); ks2 += EAGetKeyScheduleSize (ea); for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); ks2 -= CipherGetKeyScheduleSize (cipher); DecryptBufferXTS (buf, nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, structUnitNo, 0, ks, ks2, cipher); } break; #ifndef GST_NO_COMPILER_INT64 case LRW: /* Deprecated/legacy */ switch (CipherGetBlockSize (EAGetFirstCipher (ea))) { case 8: DecryptBufferLRW64 (buf, (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, DataUnit2LRWIndex (unitNo, 8, ci), ci); break; case 16: DecryptBufferLRW128 (buf, (unsigned __int64) nbrUnits * ENCRYPTION_DATA_UNIT_SIZE, DataUnit2LRWIndex (unitNo, 16, ci), ci); break; default: GST_THROW_FATAL_EXCEPTION; } break; case CBC: case INNER_CBC: /* Deprecated/legacy */ while (nbrUnits--) { ks += EAGetKeyScheduleSize (ea); for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (cipher), sectorIV, iv64, secWhitening); ks -= CipherGetKeyScheduleSize (cipher); DecryptBufferCBC ((unsigned __int32 *) buf, ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, 0, cipher); } buf += ENCRYPTION_DATA_UNIT_SIZE; unitNo++; } break; case OUTER_CBC: /* Deprecated/legacy */ while (nbrUnits--) { InitSectorIVAndWhitening (unitNo, CipherGetBlockSize (EAGetFirstCipher (ea)), sectorIV, iv64, secWhitening); DecryptBufferCBC ((unsigned __int32 *) buf, ENCRYPTION_DATA_UNIT_SIZE, ks, sectorIV, secWhitening, ea, 0); buf += ENCRYPTION_DATA_UNIT_SIZE; unitNo++; } break; #endif // #ifndef GST_NO_COMPILER_INT64 default: // Unknown/wrong ID GST_THROW_FATAL_EXCEPTION; } }
// DecryptBuffer // // buf: data to be decrypted; the start of the buffer is assumed to be aligned with the start of a data unit. // len: number of bytes to decrypt; must be divisible by the block size (for cascaded ciphers, divisible // by the largest block size used within the cascade) void DecryptBuffer (unsigned __int8 *buf, GST_LARGEST_COMPILER_UINT len, PCRYPTO_INFO cryptoInfo) { switch (cryptoInfo->mode) { case XTS: { unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); unsigned __int8 *ks2 = cryptoInfo->ks2 + EAGetKeyScheduleSize (cryptoInfo->ea); UINT64_STRUCT dataUnitNo; int cipher; // When encrypting/decrypting a buffer (typically a volume header) the sequential number // of the first XTS data unit in the buffer is always 0 and the start of the buffer is // always assumed to be aligned with the start of the data unit 0. dataUnitNo.LowPart = 0; dataUnitNo.HighPart = 0; for (cipher = EAGetLastCipher (cryptoInfo->ea); cipher != 0; cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); ks2 -= CipherGetKeyScheduleSize (cipher); DecryptBufferXTS (buf, len, &dataUnitNo, 0, ks, ks2, cipher); } } break; #ifndef GST_NO_COMPILER_INT64 case LRW: /* Deprecated/legacy */ switch (CipherGetBlockSize (EAGetFirstCipher (cryptoInfo->ea))) { case 8: DecryptBufferLRW64 (buf, (unsigned __int64) len, 1, cryptoInfo); break; case 16: DecryptBufferLRW128 (buf, (unsigned __int64) len, 1, cryptoInfo); break; default: GST_THROW_FATAL_EXCEPTION; } break; case CBC: case INNER_CBC: { /* Deprecated/legacy */ unsigned __int8 *ks = cryptoInfo->ks + EAGetKeyScheduleSize (cryptoInfo->ea); int cipher; for (cipher = EAGetLastCipher (cryptoInfo->ea); cipher != 0; cipher = EAGetPreviousCipher (cryptoInfo->ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); DecryptBufferCBC ((unsigned __int32 *) buf, (unsigned int) len, ks, (unsigned __int32 *) cryptoInfo->k2, (unsigned __int32 *) &cryptoInfo->k2[8], 0, cipher); } } break; case OUTER_CBC: /* Deprecated/legacy */ DecryptBufferCBC ((unsigned __int32 *) buf, (unsigned int) len, cryptoInfo->ks, (unsigned __int32 *) cryptoInfo->k2, (unsigned __int32 *) &cryptoInfo->k2[8], cryptoInfo->ea, 0); break; #endif // #ifndef GST_NO_COMPILER_INT64 default: // Unknown/wrong ID GST_THROW_FATAL_EXCEPTION; } }
static void DecryptBufferCBC (unsigned __int32 *data, unsigned int len, unsigned __int8 *ks, unsigned __int32 *iv, unsigned __int32 *whitening, int ea, int cipher) { /* IMPORTANT: This function has been deprecated (legacy) */ unsigned __int32 bufIV[4]; unsigned __int64 i; unsigned __int32 ct[4]; int blockSize = CipherGetBlockSize (ea != 0 ? EAGetFirstCipher (ea) : cipher); if (len % blockSize) GST_THROW_FATAL_EXCEPTION; // IV bufIV[0] = iv[0]; bufIV[1] = iv[1]; if (blockSize == 16) { bufIV[2] = iv[2]; bufIV[3] = iv[3]; } // Decrypt each block for (i = 0; i < len/blockSize; i++) { // Dewhitening data[0] ^= whitening[0]; data[1] ^= whitening[1]; if (blockSize == 16) { data[2] ^= whitening[0]; data[3] ^= whitening[1]; } // CBC ct[0] = data[0]; ct[1] = data[1]; if (blockSize == 16) { ct[2] = data[2]; ct[3] = data[3]; } if (ea != 0) { // Outer-CBC ks += EAGetKeyScheduleSize (ea); for (cipher = EAGetLastCipher (ea); cipher != 0; cipher = EAGetPreviousCipher (ea, cipher)) { ks -= CipherGetKeyScheduleSize (cipher); DecipherBlock (cipher, data, ks); } } else { // CBC/inner-CBC DecipherBlock (cipher, data, ks); } // CBC data[0] ^= bufIV[0]; data[1] ^= bufIV[1]; bufIV[0] = ct[0]; bufIV[1] = ct[1]; if (blockSize == 16) { data[2] ^= bufIV[2]; data[3] ^= bufIV[3]; bufIV[2] = ct[2]; bufIV[3] = ct[3]; } data += blockSize / sizeof(*data); } }