490 lines
11 KiB
C
490 lines
11 KiB
C
|
/*++
|
||
|
|
||
|
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));
|
||
|
}
|
||
|
|