/*++ Copyright (c) 1996 Microsoft Corporation Module Name: encrypt.c Abstract: This module will support data encryption and decryption Author: Robert Gu (robertg) 08-Dec-1996 Environment: Kernel Mode Only Revision History: --*/ #include "efsrtl.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, EFSDesEnc) #pragma alloc_text(PAGE, EFSDesDec) #pragma alloc_text(PAGE, EFSDesXEnc) #pragma alloc_text(PAGE, EFSDesXDec) #pragma alloc_text(PAGE, EFSDes3Enc) #pragma alloc_text(PAGE, EFSDes3Dec) #pragma alloc_text(PAGE, EFSAesEnc) #pragma alloc_text(PAGE, EFSAesDec) #endif VOID EFSDesEnc( IN PUCHAR InBuffer, OUT PUCHAR OutBuffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DES CBC encryption. The DES is implemented by LIB function des(). Arguments: InBuffer - Pointer to the data buffer (encryption in place) IV - Initial chaining vector (DES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DES_BLOCKLEN = 0) Note: Input buffer can only be touched once. This the requirement by the Ntfs & CC. --*/ { ULONGLONG chainBlock; ULONGLONG tmpData; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % DES_BLOCKLEN == 0); chainBlock = *(ULONGLONG *)IV; KeyTable = &(KeyBlob->Key[0]); while (Length > 0){ // // Block chaining // tmpData = *(ULONGLONG *)InBuffer; tmpData ^= chainBlock; // // Call DES LIB to encrypt the DES_BLOCKLEN bytes // We are using DECRYPT/ENCRYPT for real ENCRYPT/DECRYPT. This is for the backward // compatiblity. The old definitions were reversed. // des( OutBuffer, (PUCHAR) &tmpData, KeyTable, DECRYPT ); chainBlock = *(ULONGLONG *)OutBuffer; Length -= DES_BLOCKLEN; InBuffer += DES_BLOCKLEN; OutBuffer += DES_BLOCKLEN; } } VOID EFSDesDec( IN OUT PUCHAR Buffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DES CBC decryption. The DES is implemented by LIB function des(). Arguments: Buffer - Pointer to the data buffer (decryption in place) IV - Initial chaining vector (DES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DES_BLOCKLEN = 0) --*/ { ULONGLONG chainBlock; PUCHAR pBuffer; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % DES_BLOCKLEN == 0); pBuffer = Buffer + Length - DES_BLOCKLEN; KeyTable = &(KeyBlob->Key[0]); while (pBuffer > Buffer){ // // Call DES LIB to decrypt the DES_BLOCKLEN bytes // We are using DECRYPT/ENCRYPT for real ENCRYPT/DECRYPT. This is for the backward // compatiblity. The old definitions were reversed. // des( pBuffer, pBuffer, KeyTable, ENCRYPT ); // // Undo the block chaining // chainBlock = *(ULONGLONG *)( pBuffer - DES_BLOCKLEN ); *(ULONGLONG *)pBuffer ^= chainBlock; pBuffer -= DES_BLOCKLEN; } // // Now decrypt the first block // des( pBuffer, pBuffer, KeyTable, ENCRYPT ); chainBlock = *(ULONGLONG *)IV; *(ULONGLONG *)pBuffer ^= chainBlock; } VOID EFSDesXEnc( IN PUCHAR InBuffer, OUT PUCHAR OutBuffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DESX CBC encryption. The DESX is implemented by LIBRARY function desx(). Arguments: InBuffer - Pointer to the data buffer (encryption in place) IV - Initial chaining vector (DESX_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DESX_BLOCKLEN = 0) Note: Input buffer can only be touched once. This the requirement by the Ntfs & CC. --*/ { ULONGLONG chainBlock; ULONGLONG tmpData; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % DESX_BLOCKLEN == 0); chainBlock = *(ULONGLONG *)IV; KeyTable = &(KeyBlob->Key[0]); while (Length > 0){ // // Block chaining // tmpData = *(ULONGLONG *)InBuffer; tmpData ^= chainBlock; // // Call LIB to encrypt the DESX_BLOCKLEN bytes // We are using DECRYPT/ENCRYPT for real ENCRYPT/DECRYPT. This is for the backward // compatiblity. The old definitions were reversed. // desx( OutBuffer, (PUCHAR) &tmpData, KeyTable, DECRYPT ); chainBlock = *(ULONGLONG *)OutBuffer; Length -= DESX_BLOCKLEN; InBuffer += DESX_BLOCKLEN; OutBuffer += DESX_BLOCKLEN; } } VOID EFSDesXDec( IN OUT PUCHAR Buffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DESX CBC decryption. The DESX is implemented by LIBRARY function desx(). Arguments: Buffer - Pointer to the data buffer (decryption in place) IV - Initial chaining vector (DESX_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DESX_BLOCKLEN = 0) --*/ { ULONGLONG chainBlock; PUCHAR pBuffer; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % DESX_BLOCKLEN == 0); pBuffer = Buffer + Length - DESX_BLOCKLEN; KeyTable = &(KeyBlob->Key[0]); while (pBuffer > Buffer){ // // Call LIB to decrypt the DESX_BLOCKLEN bytes // We are using DECRYPT/ENCRYPT for real ENCRYPT/DECRYPT. This is for the backward // compatiblity. The old definitions were reversed. // desx( pBuffer, pBuffer, KeyTable, ENCRYPT ); // // Undo the block chaining // chainBlock = *(ULONGLONG *)( pBuffer - DESX_BLOCKLEN ); *(ULONGLONG *)pBuffer ^= chainBlock; pBuffer -= DESX_BLOCKLEN; } // // Now decrypt the first block // desx( pBuffer, pBuffer, KeyTable, ENCRYPT ); chainBlock = *(ULONGLONG *)IV; *(ULONGLONG *)pBuffer ^= chainBlock; } VOID EFSDes3Enc( IN PUCHAR InBuffer, OUT PUCHAR OutBuffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DES3 CBC encryption. The DES3 is implemented by LIBRARY function tripledes(). Arguments: InBuffer - Pointer to the data buffer (encryption in place) IV - Initial chaining vector (DES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DES_BLOCKLEN = 0) Note: Input buffer can only be touched once. This the requirement by the Ntfs & CC. --*/ { ULONGLONG chainBlock = *(ULONGLONG *)IV; ULONGLONG tmpData; PUCHAR KeyTable; ASSERT (Length % DES_BLOCKLEN == 0); EfsData.FipsFunctionTable.FipsBlockCBC( FIPS_CBC_3DES, OutBuffer, InBuffer, Length, &(KeyBlob->Key[0]), ENCRYPT, (PUCHAR) &chainBlock ); } VOID EFSDes3Dec( IN OUT PUCHAR Buffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DES3 CBC decryption. The DES3 is implemented by LIBRARY function tripledes(). Arguments: Buffer - Pointer to the data buffer (decryption in place) IV - Initial chaining vector (DES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % DES_BLOCKLEN = 0) --*/ { ULONGLONG ChainIV = *(ULONGLONG *)IV; ASSERT (Length % DESX_BLOCKLEN == 0); EfsData.FipsFunctionTable.FipsBlockCBC( FIPS_CBC_3DES, Buffer, Buffer, Length, &(KeyBlob->Key[0]), DECRYPT, (PUCHAR) &ChainIV ); } VOID EFSAesEnc( IN PUCHAR InBuffer, OUT PUCHAR OutBuffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements AES CBC encryption. The AES is implemented by LIBRARY function aes(). Arguments: InBuffer - Pointer to the data buffer (encryption in place) IV - Initial chaining vector (AES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % AES_BLOCKLEN = 0) Note: Input buffer can only be touched once. This the requirement by the Ntfs & CC. --*/ { ULONGLONG chainBlock[2]; ULONGLONG tmpData[2]; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % AES_BLOCKLEN == 0); chainBlock[0] = *(ULONGLONG *)IV; chainBlock[1] = *(ULONGLONG *)(IV+sizeof(ULONGLONG)); KeyTable = &(KeyBlob->Key[0]); while (Length > 0){ // // Block chaining // tmpData[0] = *(ULONGLONG *)InBuffer; tmpData[1] = *(ULONGLONG *)(InBuffer+sizeof(ULONGLONG)); tmpData[0] ^= chainBlock[0]; tmpData[1] ^= chainBlock[1]; aes256( OutBuffer, (PUCHAR) &tmpData[0], KeyTable, ENCRYPT ); chainBlock[0] = *(ULONGLONG *)OutBuffer; chainBlock[1] = *(ULONGLONG *)(OutBuffer+sizeof(ULONGLONG)); Length -= AES_BLOCKLEN; InBuffer += AES_BLOCKLEN; OutBuffer += AES_BLOCKLEN; } } VOID EFSAesDec( IN OUT PUCHAR Buffer, IN PUCHAR IV, IN PKEY_BLOB KeyBlob, IN LONG Length ) /*++ Routine Description: This routine implements DESX CBC decryption. The DESX is implemented by LIBRARY function desx(). Arguments: Buffer - Pointer to the data buffer (decryption in place) IV - Initial chaining vector (AES_BLOCKLEN bytes) KeyBlob - Set during the create or FSCTL Length - Length of the data in the buffer ( Length % AES_BLOCKLEN = 0) --*/ { ULONGLONG chainBlock[2]; PUCHAR pBuffer; PUCHAR KeyTable; PAGED_CODE(); ASSERT (Length % AES_BLOCKLEN == 0); pBuffer = Buffer + Length - AES_BLOCKLEN; KeyTable = &(KeyBlob->Key[0]); while (pBuffer > Buffer){ aes256( pBuffer, pBuffer, KeyTable, DECRYPT ); // // Undo the block chaining // chainBlock[0] = *(ULONGLONG *)( pBuffer - AES_BLOCKLEN ); chainBlock[1] = *(ULONGLONG *)(pBuffer - sizeof(ULONGLONG)); *(ULONGLONG *)pBuffer ^= chainBlock[0]; *(ULONGLONG *)(pBuffer+sizeof(ULONGLONG)) ^= chainBlock[1]; pBuffer -= AES_BLOCKLEN; } // // Now decrypt the first block // aes256( pBuffer, pBuffer, KeyTable, DECRYPT ); *(ULONGLONG *)pBuffer ^= *(ULONGLONG *)IV; *(ULONGLONG *)(pBuffer+sizeof(ULONGLONG)) ^= *(ULONGLONG *)(IV+sizeof(ULONGLONG)); }