|
|
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
Module Name:
efsstruc.h
Abstract:
EFS (Encrypting File System) defines, data and function prototypes.
Author:
Robert Reichel (RobertRe) Robert Gu (RobertG)
Environment:
Revision History:
--*/
#ifndef _EFSSTRUC_ #define _EFSSTRUC_
#ifdef __cplusplus extern "C" { #endif
#ifndef ALGIDDEF #define ALGIDDEF typedef unsigned int ALG_ID; #endif
// // Our OID. Remove from here once it's in the real headers. //
#ifndef szOID_EFS_CRYPTO #define szOID_EFS_CRYPTO "1.3.6.1.4.1.311.10.3.4" #endif
#ifndef szOID_EFS_RECOVERY #define szOID_EFS_RECOVERY "1.3.6.1.4.1.311.10.3.4.1" #endif
// // Context flag //
#define CONTEXT_FOR_EXPORT 0x00000000 #define CONTEXT_FOR_IMPORT 0x00000001 #define CONTEXT_INVALID 0x00000002 #define CONTEXT_OPEN_FOR_DIR 0x00008000
// // Context ID // #define EFS_CONTEXT_ID 0x00000001
// // Signature type // #define SIG_LENGTH 0x00000008 #define SIG_NO_MATCH 0x00000000 #define SIG_EFS_FILE 0x00000001 #define SIG_EFS_STREAM 0x00000002 #define SIG_EFS_DATA 0x00000003
// // Export file format stream flag information //
#define STREAM_NOT_ENCRYPTED 0x0001
#define EFS_EXP_FORMAT_CURRENT_VERSION 0x0100 #define EFS_SIGNATURE_LENGTH 4 #define EFS_STREAM_ID 0x1910
#define FSCTL_IMPORT_INPUT_LENGTH (4 * 1024) #define FSCTL_EXPORT_INPUT_LENGTH ( 128 ) #define FSCTL_OUTPUT_INITIAL_LENGTH (68 * 1024) #define FSCTL_OUTPUT_LESS_LENGTH (8 * 1024) #define FSCTL_OUTPUT_MIN_LENGTH (20 * 1024) #define FSCTL_OUTPUT_MISC_LENGTH (4 * 1024)
// // FSCTL data shared between server and driver //
#define EFS_SET_ENCRYPT 0 #define EFS_SET_ATTRIBUTE 1 #define EFS_DEL_ATTRIBUTE 2 #define EFS_GET_ATTRIBUTE 3 #define EFS_OVERWRITE_ATTRIBUTE 4 #define EFS_ENCRYPT_DONE 5 #define EFS_DECRYPT_BEGIN 6
// // Mask for Set EFS Attribute //
#define WRITE_EFS_ATTRIBUTE 0x00000001 #define SET_EFS_KEYBLOB 0x00000002
// // Sub code of SET_ENCRYPT FSCTL //
#define EFS_FSCTL_ON_DIR 0x80000000 #define EFS_ENCRYPT_FILE 0x00000001 #define EFS_DECRYPT_FILE 0x00000002 #define EFS_ENCRYPT_STREAM 0x00000003 #define EFS_DECRYPT_STREAM 0x00000004 #define EFS_DECRYPT_DIRFILE 0x80000002 #define EFS_ENCRYPT_DIRSTR 0x80000003 #define EFS_DECRYPT_DIRSTR 0x80000004
// // EFS Version Information // // EFS_CURRENT_VERSION must always be the highest known revision // level. This value is placed in the EfsVersion field of the // $EFS header. //
#define EFS_VERSION_1 (0x00000001) #define EFS_VERSION_2 (0x00000002) #define EFS_CURRENT_VERSION EFS_VERSION_2
/////////////////////////////////////////////////////////////////////////////// // / // EFS Data structures / // / ///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////// // / // EFS_KEY Structure / // / /////////////////////////////////////////////////////////////////////
typedef struct _EFS_KEY {
// // The length in bytes of the appended key. //
ULONG KeyLength;
// // The number of bits of entropy in the key. // For example, an 8 byte key has 56 bits of // entropy. //
ULONG Entropy;
// // The algorithm used in conjunction with this key. // // Note: this is not the algorithm used to encrypt the // actual key data itself. //
ALG_ID Algorithm;
// // This structure must be a multiple of 8 in size, // including the KeyData at the end. //
ULONG Pad;
// // KeyData is appended to the end of the structure. //
// UCHAR KeyData[1];
} EFS_KEY, *PEFS_KEY;
// // Private macros to manipulate data structures //
#define EFS_KEY_SIZE( pKey ) (sizeof( EFS_KEY ) + (pKey)->KeyLength)
#define EFS_KEY_DATA( Key ) (PUCHAR)(((PUCHAR)(Key)) + sizeof( EFS_KEY ))
#define OFFSET_TO_POINTER( FieldName, Base ) ((PCHAR)(Base) + (Base)->FieldName)
#define POINTER_TO_OFFSET( Pointer, Base ) (((PUCHAR)(Pointer)) - ((PUCHAR)(Base)))
// // We're going to use MD5 to hash the EFS stream. MD5 yields a 16 byte long hash. //
#define MD5_HASH_SIZE 16
typedef struct _EFS_DATA_STREAM_HEADER { ULONG Length; ULONG State; ULONG EfsVersion; ULONG CryptoApiVersion; GUID EfsId; UCHAR EfsHash[MD5_HASH_SIZE]; UCHAR DrfIntegrity[MD5_HASH_SIZE]; ULONG DataDecryptionField; //Offset to DDF ULONG DataRecoveryField; //Offset to DRF ULONG Reserved; ULONG Reserved2; ULONG Reserved3; } EFS_DATA_STREAM_HEADER, *PEFS_DATA_STREAM_HEADER;
/////////////////////////////////////////////////////////////////////////////// // / // EFS_PUBLIC_KEY_INFO / // / // This structure is used to contain all the information necessary to decrypt / // the FEK. / // / ///////////////////////////////////////////////////////////////////////////////
typedef struct _EFS_CERT_HASH_DATA { ULONG pbHash; // offset from start of structure ULONG cbHash; // count of bytes in hash ULONG ContainerName; // hint data, offset to LPWSTR ULONG ProviderName; // hint data, offset to LPWSTR ULONG lpDisplayInformation; // offset to an LPWSTR } EFS_CERT_HASH_DATA, *PEFS_CERT_HASH_DATA;
typedef struct _EFS_PUBLIC_KEY_INFO {
// // The length of this entire structure, including string data // appended to the end. //
ULONG Length;
// // Sid of owner of the public key (regardless of format). // This field is to be treated as a hint only. //
ULONG PossibleKeyOwner;
// // Contains information describing how to interpret // the public key information //
ULONG KeySourceTag;
union { struct {
// // The following fields contain offsets based at the // beginning of the structure. Each offset is to // a NULL terminated WCHAR string. //
ULONG ContainerName; ULONG ProviderName;
// // The exported public key used to encrypt the FEK. // This field contains an offset from the beginning of the // structure. //
ULONG PublicKeyBlob;
// // Length of the PublicKeyBlob in bytes //
ULONG PublicKeyBlobLength;
} ContainerInfo;
struct {
ULONG CertificateLength; // in bytes ULONG Certificate; // offset from start of structure
} CertificateInfo;
struct {
ULONG ThumbprintLength; // in bytes ULONG CertHashData; // offset from start of structure
} CertificateThumbprint; };
} EFS_PUBLIC_KEY_INFO, *PEFS_PUBLIC_KEY_INFO;
// // Possible KeyTag values //
typedef enum _PUBLIC_KEY_SOURCE_TAG { EfsCryptoAPIContainer = 1, EfsCertificate, EfsCertificateThumbprint } PUBLIC_KEY_SOURCE_TAG, *PPUBLIC_KEY_SOURCE_TAG;
/////////////////////////////////////////////////////////////////////////////// // / // RECOVERY_KEY Data Structure / // / ///////////////////////////////////////////////////////////////////////////////
// // Current format of recovery data. //
typedef struct _RECOVERY_KEY_1_1 { ULONG TotalLength; EFS_PUBLIC_KEY_INFO PublicKeyInfo; } RECOVERY_KEY_1_1, *PRECOVERY_KEY_1_1;
/////////////////////////////////////////////////////////////////////////////// // / // KEY_INTEGRITY_INFO / // / // The KEY_INTEGRITY_INFO structure is used to verify that / // the user's key has correctly decrypted the file's FEK. / // / ///////////////////////////////////////////////////////////////////////////////
typedef struct _KEY_INTEGRITY_INFO {
// // The length of the entire structure, including the // variable length integrity information appended to // the end //
ULONG Length;
// // The algorithm used to hash the combined FEK and // public key //
ALG_ID HashAlgorithm;
// // The length of just the hash data. //
ULONG HashDataLength;
// // Integrity information goes here //
// UCHAR Integrity Info[] } KEY_INTEGRITY_INFO, *PKEY_INTEGRITY_INFO;
typedef struct _EFS_KEY_SALT { ULONG Length; // total length of header plus data ULONG SaltType; // figure out what you want for this // // Put data here, so total length of the structure is // sizeof( EFS_KEY_SALT ) + length of your data // } EFS_KEY_SALT, *PEFS_KEY_SALT;
// // EFS Private DataStructures //
typedef struct _ENCRYPTED_KEY {
// // Total length of this structure and its data //
ULONG Length;
// // contains an offset from beginning of structure, // used to decrypt the EncryptedKey //
ULONG PublicKeyInfo;
// // Length in bytes of EncryptedFEK field //
ULONG EncryptedFEKLength;
// // offset from beginning of structure to encrypted // EFS_KEY containing the FEK // // Type is PUCHAR because data is encrypted. //
ULONG EncryptedFEK;
// // offset from beginning of structure to KEY_INTEGRITY_INFO //
ULONG EfsKeySalt;
// // FEK Data // // KEY_INTEGRITY_INFO Data // // PEFS_PUBLIC_KEY_INFO Data //
} ENCRYPTED_KEY, *PENCRYPTED_KEY;
// // The Key Ring Structure. //
typedef struct _ENCRYPTED_KEYS { ULONG KeyCount; ENCRYPTED_KEY EncryptedKey[1]; } ENCRYPTED_KEYS, *PENCRYPTED_KEYS;
typedef ENCRYPTED_KEYS DDF, *PDDF; typedef ENCRYPTED_KEYS DRF, *PDRF;
typedef struct _EFS_STREAM_SIZE { ULONG StreamFlag; LARGE_INTEGER EOFSize; LARGE_INTEGER AllocSize; } EFS_STREAM_SIZE, *PEFS_STREAM_SIZE;
#define NEXT_ENCRYPTED_KEY( pEncryptedKey ) (PENCRYPTED_KEY)(((PBYTE)(pEncryptedKey)) + *((ULONG UNALIGNED *)&((PENCRYPTED_KEY)(pEncryptedKey))->Length))
// // Import context //
typedef struct IMPORT_CONTEXT{
ULONG ContextID; //To distinguish from other LSA context. Offset is fixed across LSA. ULONG Flag; // Indicate the type of context HANDLE Handle; // File handle, used to create rest streams ULONG Attribute; ULONG CreateDisposition; ULONG CreateOptions; ULONG DesiredAccess;
} IMPORT_CONTEXT, *PIMPORT_CONTEXT;
// // Export context //
typedef struct EXPORT_CONTEXT{
ULONG ContextID; //To distinguish from other LSA context. Offset is fixed across LSA. ULONG Flag; // Indicate the type of context HANDLE Handle; // File handle, used to open rest streams ULONG NumberOfStreams; PHANDLE StreamHandles; PUNICODE_STRING StreamNames; PFILE_STREAM_INFORMATION StreamInfoBase;
} EXPORT_CONTEXT, *PEXPORT_CONTEXT;
// // EFS Export/Import RPC pipe status //
typedef struct EFS_EXIM_STATE{ PVOID ExImCallback; PVOID CallbackContext; char *WorkBuf; ULONG BufLength; ULONG Status; } EFS_EXIM_STATE, *PEFS_EXIM_STATE;
// // Export file format //
typedef struct EFSEXP_FILE_HEADER{
ULONG VersionID; // Export file version WCHAR FileSignature[EFS_SIGNATURE_LENGTH]; // Signature of the file ULONG Reserved[2]; //STREAM_DADA Streams[0]; // An array of STREAM_BLOCK
} EFSEXP_FILE_HEADER, *PEFSEXP_FILE_HEADER;
typedef struct EFSEXP_STREAM_HEADER{
ULONG Length; // Redundant information. The length of this block not including DataBlocks but // including itself; This field is to simplify the import routine. WCHAR StreamSignature[EFS_SIGNATURE_LENGTH]; // Signature of the stream ULONG Flag; // Indicating if the stream is encrypted or not and etc. ULONG Reserved[2]; // For future use ULONG NameLength; // Length of the stream name //WCHAR StreamName[0]; // ID of the stream, Binary value can be used. //DATA_BLOCK DataBlocks[0]; // Variable number of data block
} EFSEXP_STREAM_HEADER, *PEFSEXP_STREAM_HEADER;
typedef struct EFSEXP_DATA_HEADER{
ULONG Length; // Length of the block including this ULONG WCHAR DataSignature[EFS_SIGNATURE_LENGTH]; // Signature of the data ULONG Flag; // For future use. // BYTE DataBlock[N]; // N = Length - 2 * sizeof (ULONG) - 4 * sizeof (WCHAR)
} EFSEXP_DATA_HEADER, *PEFSEXP_DATA_HEADER;
// // TotalLength - total length of the RECOVERY_KEY Datastructure. // // KeyName - the storage stream will actually have the characters terminated by // a NULL character. // AlgorithmId - CryptAPI Algorithm ID - in V1 it is always RSA. // // CSPName - the storage stream will actually have the characters terminated by // a NULL character. // CSPType - CryptAPI type of CSP. // // PublicBlobLength - Length of the public blob that is importable in CryptoAPI in bytes. //
// // Recovery Policy Data Structures //
typedef struct _RECOVERY_POLICY_HEADER { USHORT MajorRevision; USHORT MinorRevision; ULONG RecoveryKeyCount; } RECOVERY_POLICY_HEADER, *PRECOVERY_POLICY_HEADER;
typedef struct _RECOVERY_POLICY_1_1 { RECOVERY_POLICY_HEADER RecoveryPolicyHeader; RECOVERY_KEY_1_1 RecoveryKeyList[1]; } RECOVERY_POLICY_1_1, *PRECOVERY_POLICY_1_1;
#define EFS_RECOVERY_POLICY_MAJOR_REVISION_1 (1) #define EFS_RECOVERY_POLICY_MINOR_REVISION_0 (0)
#define EFS_RECOVERY_POLICY_MINOR_REVISION_1 (1)
// // Major/Minor Revision - revision number of policy information. // // RecoveryKeyCount - number of recovery keys configured in this policy. // // RecoveryKeyList - array of recovery keys. //
// // Session Key Structure //
#define SESSION_KEY_SIZE 8 #define COMMON_FSCTL_HEADER_SIZE (7 * sizeof( ULONG ) + 2 * SESSION_KEY_SIZE)
typedef struct _EFS_INIT_DATAEXG { UCHAR Key[SESSION_KEY_SIZE]; HANDLE LsaProcessID; // The reason we use HANDLE is for the sake of 64 bits } EFS_INIT_DATAEXG, *PEFS_INIT_DATAEXG;
// // Server API, callable from kernel mode //
NTSTATUS EfsGenerateKey( PEFS_KEY * Fek, PEFS_DATA_STREAM_HEADER * EfsStream, PEFS_DATA_STREAM_HEADER DirectoryEfsStream, ULONG DirectoryEfsStreamLength, PVOID * BufferBase, PULONG BufferLength );
NTSTATUS GenerateDirEfs( PEFS_DATA_STREAM_HEADER DirectoryEfsStream, ULONG DirectoryEfsStreamLength, PEFS_DATA_STREAM_HEADER * NewEfs, PVOID * BufferBase, PULONG BufferLength );
#define EFS_OPEN_NORMAL 1 #define EFS_OPEN_RESTORE 2 #define EFS_OPEN_BACKUP 3
NTSTATUS EfsDecryptFek( IN OUT PEFS_KEY * Fek, IN PEFS_DATA_STREAM_HEADER CurrentEfs, IN ULONG EfsStreamLength, IN ULONG OpenType, //Normal, Recovery or Backup OUT PEFS_DATA_STREAM_HEADER *NewEfs, //In case the DDF, DRF are changed PVOID * BufferBase, PULONG BufferLength );
NTSTATUS GenerateSessionKey( OUT EFS_INIT_DATAEXG * SessionKey );
// // Private usermode server API //
ULONG EfsEncryptFileRPCClient( IN PUNICODE_STRING FileName );
ULONG EfsDecryptFileRPCClient( PUNICODE_STRING FileName, ULONG OpenFlag );
ULONG EfsOpenFileRawRPCClient( IN LPCWSTR FileName, IN ULONG Flags, OUT PVOID * Context );
VOID EfsCloseFileRawRPCClient( IN PVOID Context );
#ifdef __cplusplus } #endif
#endif // _EFSSTRUC_
|