// Based on function Ox10001973
void cryptFiles(hProv, aesKey) {
for every file candidate F:
cryptFile(hProv, aesKey);
}
// Based on function 0x1000189A
void cryptFile(hProv, aesKey, Path) {
// Get handle to Path
HANDLE hFile = CreateFile(...);
uint64_t size;
// This is not the exact Windows API, but this makes the explanation easier...
GetFileSizeEx(hFile, &size);
bool final;
// Compute encryption size
if (size <= 0x100000) {
// Here, the next multiple of 16 of Size is computed. Indeed, when the
// file is less than 1MB, CryptEncrypt this will use PKCS5 padding for
// the last block. Our file will be thus at most one 16 byte block larger.
size = ((size/16) + 1)*16;
final = TRUE;
}
else {
// If we have 1MB of data to encrypt, then the Final is set to FALSE.
// Indeed, CryptEncrypt will *always* add a final padding block, even if
// the size of the data to encrypt is a multiple of 16. In this case, if
// it has set the Final flag to TRUE, 16 bytes would have been overwritten
// in the original file (as encryption is done in-place, see above),
// with no chance of retrieving them.
final = FALSE;
}
// MemoryMap isn't a Windows API. This is basically just to say that
// only "size" bytes are memory mapped.
void* buffer = MemoryMap(hFile, size);
DWORD sizeEncrypted;
CryptEncrypt(hProv, 0, final, buffer, &sizeEncrypted, size);
// This makes sure that encrypted data are effectively written on the
// hard disk.
FlushViewOfFile(..);
// Then close the memory map and the file.
}