Browse Source

NVbit source added

master
vkumar 2 years ago
commit
bca68bc0f5

+ 21
- 0
bit/Makefile View File

@@ -0,0 +1,21 @@

CC=gcc
CFLAGS=`pkg-config --cflags fuse` -O2 -Wall -D_REENTRANT -DDRIVER -DDEBUG_ON -o nvbit

# -DHAVE_CONFIG_H -D_REENTRANT -DFUSE_USE_VERSION=26 -DLIBDIR=/usr/local/lib -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -g -O2 -Wall -W

LDFLAGS=`pkg-config --libs fuse`

nvbit:
${CC} ${CFLAGS} ${LDFLAGS} *.c nvbitlocker/*.c nvbitlocker/aes/*.c nvbitlocker/sha256/*.c nvbitlocker/decrypt_key/*.c nvbitlocker/VMK_PASSWORD/*.c
#$^ -o $@

clean:
rm -f *.o *.obj
rm -f nvbit
${RM} *~
${RM} nvbit




+ 409
- 0
bit/main.c View File

@@ -0,0 +1,409 @@
/*
nvbit Bitlocker for linux
------------------------------

Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in

web: http://www.nvlabs.in


Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/

#define FUSE_USE_VERSION 26
#define _FILE_OFFSET_BITS 64


#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>



// include bitlocker relaed files
#include "nvbitlocker/common.h"
#include "nvbitlocker/main.h"
#include "nvbitlocker/header.h"
#include "nvbitlocker/interface.h"

#define VERSION "0.04"
static const char *NTFS_FILENAME = "/NV_bitlocker_on_linux";



static struct Globals{
char *Filename;
FILE *FileStruct;
int FD;
struct stat Stat;


Interface* input_interface; // used to communicae wit bitocker encrypted volume
options_structure options; /* used for internal processing such as
keys, volume metadata etc
*/

} Global_Data;




/* This function fills the directory structure */

static int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
off_t offset, struct fuse_file_info *fi);

/*this function opens up the file */

static int fs_open(const char *path, struct fuse_file_info *fi);

/* used to read decrypted buffer */
static int fs_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi);

// used to obtain attributes of files
static int fs_getattr(const char *path, struct stat *stbuf);


// print usage
void usage( char **argv );



static struct fuse_operations fs_oper = {
/* .getattr = hello_getattr,
.readdir = hello_readdir,
.open = hello_open,
.read = hello_read,
*/
.getattr = fs_getattr,
.readdir = fs_readdir,
.open = fs_open,
.read = fs_read,
};



static int fs_getattr(const char *path, struct stat *stbuf)
{
int res = 0;

memset(stbuf, 0, sizeof(struct stat));
if(strcmp(path, "/") == 0) {
stbuf->st_mode = S_IFDIR | 0755;
stbuf->st_nlink = 2;
}
else if(strcmp(path, NTFS_FILENAME) == 0) {
stbuf->st_mode = S_IFREG | 0444;
stbuf->st_nlink = 1;
stbuf->st_size = 1023 * 1024 * 1024; // change limit here , it's currently 1023 GB

// stbuf->st_uid=fuse_get_context()->uid;
// stbuf->st_gid=fuse_get_context()->gid;
}
else
res = -ENOENT;
return res;
}


static int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
(void) offset;
(void) fi;

if(strcmp(path, "/") != 0)
return -ENOENT;

filler(buf, ".", NULL, 0);
filler(buf, "..", NULL, 0);
filler(buf, NTFS_FILENAME + 1, NULL, 0);

return 0;
}


// since only 1 file will be opened, messy code is not at all required
static int fs_open(const char *path, struct fuse_file_info *fi)
{
if(strcmp(path, NTFS_FILENAME) != 0)
return -ENOENT;

if((fi->flags & 3) != O_RDONLY)
return -EACCES;

return 0;
}


static int fs_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{


unsigned char *buffer;

long long sector_count;
long long sector_start;
unsigned long loop_var;
unsigned long len;

if(strcmp(path, NTFS_FILENAME) != 0)
return -ENOENT;


if ( size == 0)
return 0;





/* logic to do this is below

count the number of full sectors add 2 to it 1 for lower and one for upper limit
now decode all sectors

now select and copy the data to user and deallocate all buffers

*/

// this code cannot service large requests huh but who cares

buffer = NULL;
sector_count = (( size / Global_Data.input_interface->SectorSize ) + 2) ;
sector_start = offset / Global_Data.input_interface->SectorSize;

buffer = malloc ( sector_count * Global_Data.input_interface->SectorSize);

if(!buffer) // if buffer could not be allocated, return with empty size
return 0;



// read all sectors one by one and decrypt them if necessary

for(loop_var = 0 ; loop_var < sector_count; loop_var++){

Read_Sector(Global_Data.input_interface,(long long)((long long)loop_var+(long long)sector_start) ,1, buffer + loop_var * Global_Data.input_interface->SectorSize);

// don't decrypt the first 4 sectors whatever might be the case



if ( (long long)((long long)loop_var+(long long)sector_start) < 4) {
// if it is first sector fix it up
if ( (long long)((long long)loop_var+(long long)sector_start) == 0){
fix_sector(&Global_Data.options , buffer + loop_var * Global_Data.input_interface->SectorSize);

}

}
else { // decrypt the sector
decrypt_sector(&Global_Data.options,buffer + loop_var * Global_Data.input_interface->SectorSize,(long long)((long long)loop_var+(long long)sector_start));


}


}


// now copy the required amount of data to the user buffer
memcpy(buf,
buffer + ( offset % Global_Data.input_interface->SectorSize),
size);

free(buffer);



return size;
}








// init necessary stuff here
void init(){
Global_Data.Filename=NULL;
Global_Data.FileStruct=NULL;
Global_Data.FD=-1;


// init fuse function callbacks

//options structure is set to zero

memset(&Global_Data.options,0,sizeof(options_structure));


}




int main(int argc, char *argv[])
{


if (argc <=4 ){
usage(argv);
exit(-1);
}

#ifdef DEBUG_ON

printf("Starting nvbit Bitlocker Volume FUSE Driver\n");
#endif
init();


// process parameters supplied

process_options(argc,argv, &Global_Data.options);


Global_Data.input_interface = InitializeInputInterface ( Global_Data.options.filename );

// we will be here if and only if necessary options have been found and processed
// now we will verify whether the volume is a bitlocker volume

verify_input_volume_and_parse(Global_Data.input_interface, &Global_Data.options);


// everything is fine till now, so we got a key and we got data, so lets decode other set of keys
decrypt_vmk(&Global_Data.options);

if ( Global_Data.options.VMK_key_present < 1 ) {
fprintf(stderr,"VMK could not be decrypted , VERIFY your keys !!! \n");
exit(1);
}


// we have now obainted VMK, now lets hunt down FVEK
decrypt_fvek(&Global_Data.options);


if ( Global_Data.options.FVEK_key_present < 1 ) {
// this situation means something is not correct with the bitlocker volume
// this situation should never occur, until the partition is manually damaged or th disk gets damaged
fprintf(stderr,"FVEK could not be decrypted. Your partition is most probably corrupt !!! \n");
exit(1);
}




// inform user about encryption used

switch (Global_Data.options.Encryption_Type) {
case AES128:
printf("This Volume was encrypted using AES 128\n");
break;
case AES256:
printf("This Volume was encrypted using AES 256\n");
break;
case AES128_diffuser:
printf("This Volume was encrypted using AES 128 + diffuser\n");
break;
case AES256_diffuser:
printf("This Volume was encrypted using AES 256 + diffuser\n");
break;
default:
printf("Unknown Algorithm\n"
"Cannot Continue, Quitting \n");
exit(1);
}



// init keys once and for all


init_keys(&Global_Data.options);


#ifdef DEBUG_ON
printf("Volume successfully mounted\n");
#endif


// assumming our program always takes 2 paramters
{ /* basic fuse stuff */
int i;
int diff;
char **nargv = (char **) malloc(argc * sizeof(char *));
diff = 4; // number of paramters for our program excluding the program name
int nargc = argc - diff;


nargv[0] = argv[0];

for(i = 0; i < nargc; i++) {
nargv[i + 1] = argv[i + diff +1];
};
return fuse_main(nargc, nargv, &fs_oper,NULL);
}




}













void usage( char **argv ){

printf("nvbit %s: Bitlocker for Linux \n" , VERSION );
printf ("\n"
"This is free software. You may redistribute copies of it under the terms\n"
"of the GNU General Public License Version 3<http://www.gnu.org/licenses/gpl-3.0.txt>.\n"
"There is NO WARRANTY, to the extent permitted by law.\n");
printf("\n"
"usage:\n"
"nvbit options mount_point [<FUSE library options>]\n"
"The following options are supported.\n"
"-i /i the name of input bitlocker voume which is to be decrypted\n"
"-sk /sk Startup Key file or Recovery key file (normally stored on USB key)\n"
"-rp /rp Recovery password which can be entered by hand and is of the form xxxxx-xxxxx--xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx\n"
"\n\n Visit www.nvlabs.in for updates/information\n\n");


}

BIN
bit/nvbit View File


+ 143
- 0
bit/nvbitlocker/VMK_PASSWORD/RecoveryPassword.c View File

@@ -0,0 +1,143 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
/* this file implement recovery password related functions such as verify, testing etc
sample recovery password 428593-377069-419914-450824-036729-210243-469029-482394
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "../common.h"
#include "recoverypassword.h"
#include "../sha256/sha.h"
long Calculate_Recovery_Key_From_Password(unsigned char *recovery_password,
unsigned char *header, unsigned long *output);
long Calculate_Key(unsigned char *recovery_password, unsigned long
recovery_password_length, unsigned char *salt, unsigned long *output);
long Calculate_Recovery_Key_From_Password(unsigned char *recovery_password,
unsigned char *header, unsigned long *output){
//since recovery key consists of 8 blocks of data,
// preprocess them, at this stage recovery password is of the form
// 1111-1111-11111-11111 and so on
unsigned long temporary_password_block[8];
int16 recovery_pass[8];
unsigned long loop_var_i;
unsigned char buffer[2000];
unsigned char buffer2[2000];
memset(temporary_password_block, 0, sizeof(temporary_password_block));
sscanf(recovery_password, "%d-%d-%d-%d-%d-%d-%d-%d",
&temporary_password_block[0], &temporary_password_block[1],
&temporary_password_block[2], &temporary_password_block[3],
&temporary_password_block[4], &temporary_password_block[5],
&temporary_password_block[6], &temporary_password_block[7]);
for (loop_var_i = 0; loop_var_i <= 7; loop_var_i++){
// each block should be independantly perfectly divisible by 11
if ((temporary_password_block[loop_var_i] % 11) == 0)
recovery_pass[loop_var_i] = (int16)(temporary_password_block[loop_var_i]
/ 11);
else
return 0;
}
// we are here means password looks valid
// now try to obtain actual key
return Calculate_Key((unsigned char*)recovery_pass, 16,
// since this is 128 bit key
header + 12, output);
}
long Calculate_Key(unsigned char *recovery_password, unsigned long
recovery_password_length, unsigned char *salt, unsigned long *output){
blob my_blob;
unsigned char *output_buffer;
unsigned long max_loop_count = 0x100000;
memset(&my_blob, 0, sizeof(blob));
memcpy(my_blob.salt, salt, 0x10); // we only take 16 bytes of salt
if (recovery_password_length < 0x65535){
sha256(recovery_password, recovery_password_length, my_blob.sha_password);
}
else
return 0;
/// return due to error caused
while (max_loop_count){
sha256((unsigned char*) &my_blob, sizeof(blob), my_blob.sha_current);
my_blob.hash_count++;
max_loop_count--;
}
output_buffer = malloc(0xc + 0x20);
memset(output_buffer, 0, 0x2c);
// copy the resultant key out to the buffer
memcpy((output_buffer + 0xC), &my_blob.sha_current, 0x20);
*output = (int32)output_buffer;
// TODO zero out the buffers
// also clear up the the internal state of SHA function
return 0;
}

+ 42
- 0
bit/nvbitlocker/VMK_PASSWORD/RecoveryPassword.h View File

@@ -0,0 +1,42 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
#ifndef RECOVERY_PASSWORD_H
#define RECOVERY_PASSWORD_H
#include "../common.h"
// this blob is used for calculating recovery key from recovery password
# pragma pack (1) // 1 byte packing
typedef struct {
unsigned char sha_current[32];
unsigned char sha_password[32];
unsigned char salt[16];
int64 hash_count;
}blob;
# pragma pack () // restore original packing
long Calculate_Recovery_Key_From_Password(
unsigned char *recovery_password,
unsigned char *header,
unsigned long *output);
#endif

+ 1023
- 0
bit/nvbitlocker/aes/aes.c
File diff suppressed because it is too large
View File


+ 103
- 0
bit/nvbitlocker/aes/aes.h View File

@@ -0,0 +1,103 @@
/**
* \file aes.h
*/
#ifndef XYSSL_AES_H
#define XYSSL_AES_H

#define AES_ENCRYPT 0
#define AES_DECRYPT 1

/**
* \brief AES context structure
*/
typedef struct
{
int nr; /*!< number of rounds */
unsigned long *rk; /*!< AES round keys */
unsigned long buf[68]; /*!< unaligned data */
}
aes_context;

#ifdef __cplusplus
extern "C" {
#endif

/**
* \brief AES key schedule (encryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keysize must be 128, 192 or 256
*/
void aes_setkey_enc( aes_context *ctx, unsigned char *key, int keysize );

/**
* \brief AES key schedule (decryption)
*
* \param ctx AES context to be initialized
* \param key decryption key
* \param keysize must be 128, 192 or 256
*/
void aes_setkey_dec( aes_context *ctx, unsigned char *key, int keysize );

/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*/
void aes_crypt_ecb( aes_context *ctx,
int mode,
unsigned char input[16],
unsigned char output[16] );

/**
* \brief AES-CBC buffer encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void aes_crypt_cbc( aes_context *ctx,
int mode,
int length,
unsigned char iv[16],
unsigned char *input,
unsigned char *output );

/**
* \brief AES-CFB buffer encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void aes_crypt_cfb( aes_context *ctx,
int mode,
int length,
int *iv_off,
unsigned char iv[16],
unsigned char *input,
unsigned char *output );

/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
*/
int aes_self_test( int verbose );

#ifdef __cplusplus
}
#endif

#endif /* aes.h */

+ 70
- 0
bit/nvbitlocker/aes/aes_config.h View File

@@ -0,0 +1,70 @@
/**
* \file config.h
*
* This set of compile-time options may be used to enable
* or disable features selectively, and reduce the global
* memory footprint.
*/
#ifndef XYSSL_CONFIG_H
#define XYSSL_CONFIG_H
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
/*
* Uncomment if native integers are 8-bit wide.
*
#define XYSSL_HAVE_INT8
*/
/*
* Uncomment if native integers are 16-bit wide.
*
#define XYSSL_HAVE_INT16
*/
/*
* Uncomment if the compiler supports long long.
*
#define XYSSL_HAVE_LONGLONG
*/
/*
* Uncomment if the CPU supports SSE2 (IA-32 specific).
*
#define XYSSL_HAVE_SSE2
*/
/*
* Enable all SSL/TLS debugging messages.
*/
#define XYSSL_DEBUG_MSG
/*
* Enable the checkup functions (*_self_test).
*/
#define XYSSL_SELF_TEST
/*
* Enable the prime-number generation code.
*/
#define XYSSL_GENPRIME
/*
* Uncomment this macro to store the AES tables in ROM.
*
#define XYSSL_AES_ROM_TABLES
*/
/*
* Module: library/aes.c
* Caller: library/ssl_tls.c
*
* This module enables the following ciphersuites:
* SSL_RSA_AES_256_SHA
* SSL_EDH_RSA_AES_256_SHA
*/
#define XYSSL_AES_C
#endif

+ 69
- 0
bit/nvbitlocker/aes/padlock.h View File

@@ -0,0 +1,69 @@
/**
* \file padlock.h
*/
#ifndef XYSSL_PADLOCK_H
#define XYSSL_PADLOCK_H

#include "aes.h"

#if (defined(__GNUC__) && defined(__i386__))

#ifndef XYSSL_HAVE_X86
#define XYSSL_HAVE_X86
#endif

#define PADLOCK_RNG 0x000C
#define PADLOCK_ACE 0x00C0
#define PADLOCK_PHE 0x0C00
#define PADLOCK_PMM 0x3000

#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15))

#ifdef __cplusplus
extern "C" {
#endif

/**
* \brief PadLock detection routine
*
* \return 1 if CPU has support for the feature, 0 otherwise
*/
int padlock_supports( int feature );

/**
* \brief PadLock AES-ECB block en(de)cryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*/
void padlock_xcryptecb( aes_context *ctx,
int mode,
unsigned char input[16],
unsigned char output[16] );

/**
* \brief PadLock AES-CBC buffer en(de)cryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*/
void padlock_xcryptcbc( aes_context *ctx,
int mode,
int length,
unsigned char iv[16],
unsigned char *input,
unsigned char *output );

#ifdef __cplusplus
}
#endif

#endif /* HAVE_X86 */

#endif /* padlock.h */

+ 77
- 0
bit/nvbitlocker/common.c View File

@@ -0,0 +1,77 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
// This file contains some common definitions
#include <stdio.h>
#include <malloc.h>
#include "common.h"
#include "header.h"
// all keys are 32 bytes or 256 bit
// though this sgould be a function which should calculate key size from header and after header data
// however, at this time it's hard code, however it's working till now !!!!!
#define GetKeySize(x) 0x20
// this will return a pointer to the next header
HEADER *Next_Header(HEADER * header_ptr)
{
HEADER *header;
header = header_ptr;
header = (HEADER *)((int8 *)header + header->Size);
if(header)
return header;
return NULL;
}
// this will return a pointer to data contained in the header
int8 *Header_Data_Pointer(HEADER * header)
{
if ( header->Size > sizeof(HEADER))
return ((int8 *)header + sizeof(HEADER));
else
return 0; // if no data then return 0
}
// this will allocate a buffer and zero it out
void *malloc_zero(int32 Size)
{
void *ptr;
ptr = malloc(Size);
if(!ptr)
return 0; // return if memory could not be allocated
// now do a memset
memset(ptr,0,Size);
return ptr;
}

+ 97
- 0
bit/nvbitlocker/common.h View File

@@ -0,0 +1,97 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
// this header file contains all common definitions including data types
// disable warnings
#pragma warning( disable : 4047 4244 4996 4267 4013 4311)
#ifndef COMMON_H
#define COMMON_H
#include <stdio.h>
#define LINUX
// data type defines for VC++ 6.0
#ifdef WIN32
typedef unsigned __int8 int8;
typedef unsigned __int16 int16;
typedef unsigned __int32 int32;
typedef unsigned __int64 int64;
#endif
#ifdef LINUX // data type define for linux
typedef unsigned char int8;
typedef unsigned short int16;
typedef unsigned long int32;
typedef unsigned long long int64;
#endif
typedef int64 FILETIME;
/* guids are of the following type
02DD640E-E6E7-439E-B526-3F419CA3CE95
1 2 3 4 5
*/
/*#ifdef GUID
#undefine GUID
#endif
*/
# pragma pack (1) // 1 byte packing
typedef struct _GUID {
int32 first; // it should be value defined in FVE_SIGNATURE in fve.h
int16 second;
int16 third;
int8 fourth[2];
int8 fifth[6] ;
} GUID;
# pragma pack () // restore original packing
#endif // COMMON_H

+ 451
- 0
bit/nvbitlocker/decrypt_data.c View File

@@ -0,0 +1,451 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
/* This file contains sector decrytion releated functions.This file also contains diffuser implementation (one sided)
*/
#include <stdio.h>
#include <stdlib.h> // for _lrotr function
#include <malloc.h>
#include <time.h>
#include "common.h"
#include "header.h"
#include "interface.h"
#include "aes/aes.h"
#define ROTATE(a,n) (((a)<<(n))|(((a)&0xffffffff)>>(32-(n))))
/* Only first and last sectors need to be patched */
void fix_sector( options_structure *options,
int8 *buffer) // the buffer which needs to be fixed
{
/* only changes that are made to a ntfs boot sector after enabling bitlocker are
the MFT mirror paramter is chaged to point to FVE meta data
the volume identifier is changed from "NTFS " to "-FVE-FS-"
then changed MFT mirror value is stored in the FVE-metadata
*/
FVE_META_DATA *meta_data;
meta_data = (FVE_META_DATA *)buffer;
meta_data->MetaDataLCN = options->more_fve_data.MFT_Mirror ;
// now update the the partion id
memcpy( meta_data->Signature,NTFS_SIGNATURE,8);
// successful patching done so return
}
void init_keys(options_structure *options)
{
// volume keys are always 256 bit whatevr the condition
aes_setkey_enc( &options->context.VMK_E_ctx, options->VMK_key+12,256);
aes_setkey_dec( &options->context.VMK_D_ctx, options->VMK_key+12,256);
//FVEK keys depend on algorithm
if ( options->Encryption_Type == AES128 || options->Encryption_Type == AES128_diffuser ) {
aes_setkey_enc( &options->context.FVEK_E_ctx, options->FVEK_key+12,128);
aes_setkey_dec( &options->context.FVEK_D_ctx, options->FVEK_key+12,128);
}
if ( options->Encryption_Type == AES256 || options->Encryption_Type == AES256_diffuser ) {
aes_setkey_enc( &options->context.FVEK_E_ctx, options->FVEK_key+12,256);
aes_setkey_dec( &options->context.FVEK_D_ctx, options->FVEK_key+12,256);
}
// TWEAK keys also depend on algorithm
if ( options->Encryption_Type == AES128_diffuser ) {
aes_setkey_enc( &options->context.TWEAK_E_ctx, options->Tweak_Key+12,128);
aes_setkey_dec( &options->context.TWEAK_D_ctx, options->Tweak_Key+12,128);
}
if ( options->Encryption_Type == AES256_diffuser ) {
aes_setkey_enc( &options->context.TWEAK_E_ctx, options->Tweak_Key+12,256);
aes_setkey_dec( &options->context.TWEAK_D_ctx, options->Tweak_Key+12,256);
}
// all key contexts have been set
}
void decrypt_diffused_sector( options_structure *options, // the usual keys
int8 *sector_data, // actual encrypted data after decrypted data is also available here
int32 sector_size, // size of sector which is being decoded
int64 sector );
// this means a sector encrypted with pure AES 128 or AES 256
unsigned long decrypt_normal_sector( options_structure *options, // the usual keys
int8 *sector_data, // actual encrypted data after decrypted data is also available here
int32 sector_size, // size of sector which is being decoded
int64 sector ) // this means if a 4 th sector sector is being decoded
{
aes_context fvek_d_ctxt;
int8 IV[20] ; // initilization vector
/*
// if algorithm is not AES 128 or AES 256 return -1
if ( options->Encryption_Type == AES128_diffuser ||
options->Encryption_Type == AES256_diffuser )
return -1;
// setup key schedule according to the algorithm
if ( options->Encryption_Type == AES128 )
aes_setkey_dec( &fvek_d_ctxt, options->FVEK_key + 12, 128); // 128 bit encryption
else if (options->Encryption_Type == AES256)
aes_setkey_dec( &fvek_d_ctxt, options->FVEK_key + 12, 256); // select 256 bit encryption
else
return -1;
*/
memset(IV,0,sizeof(IV)); // init initialization vector
aes_crypt_cbc(&options->context.FVEK_D_ctx,AES_DECRYPT,sector_size,IV,sector_data,sector_data);
return 0;
}
// this will select a decryptor based on the algorithm selected in the FVEK
// and return result
void decrypt_sector(options_structure *options,
int8 *sector_data,
int64 sector )
{
// select a function based on algorithm
if ( options->Encryption_Type == AES128 || options->Encryption_Type == AES256 )
return decrypt_normal_sector(options,sector_data,options->fve_meta_data.BytesPerSector,sector);
if ( options->Encryption_Type == AES128_diffuser || options->Encryption_Type == AES256_diffuser )
return decrypt_diffused_sector(options,sector_data,options->fve_meta_data.BytesPerSector,sector);
// we are here means unknown algorithm
return -1;
}
// this function does the actual decryption of data
void decrypt_data(Interface* input_interface, options_structure *options) {
unsigned char encrypted_buffer[ 8192];
unsigned char decrypted_buffer[8192];
FILE *stream;
unsigned long loop_var;
if( (stream = fopen( "decrypted", "w+b" )) == NULL ) {
printf("Output file could not be opned");
return ;
}
// process first sector and write it
Read_Sector( input_interface,0 ,1, encrypted_buffer);
fix_sector(options,encrypted_buffer);
fwrite(encrypted_buffer,1,512,stream);
loop_var =0; // start decrypting from the 9 sector
#define DECRYPTED_SECTORS 10
for ( loop_var =1 ;loop_var < DECRYPTED_SECTORS;loop_var++)
{
Read_Sector( input_interface,loop_var ,1, encrypted_buffer);
fwrite(encrypted_buffer,1,512,stream);
}
loop_var = DECRYPTED_SECTORS ;
//for(loop_var = 0; loop_var < 100000 ;loop_var++)
while( 1)//!feof(input_interface->stream ))
{
loop_var++;
// read one sector at a time and decrypt it
//if (! feof( input_interface->stream)) {
Read_Sector( input_interface,loop_var ,1, encrypted_buffer);
//}
// if eof break;
if ( feof(input_interface->stream ))
break;
// sector has been read now decrypt it
decrypt_sector(options,encrypted_buffer,loop_var);
fwrite(encrypted_buffer,1,512,stream);
}
// we are here means whole file has been decrypte including the last sector
// so fix it up
// it is done by seeking back 512 bytes
// reading 0 sector , fixing it up
// and then writing it again
custom_fseek(stream, (int64)0 - (int64)input_interface->SectorSize ,SEEK_CUR);
Read_Sector( input_interface,0 ,1, encrypted_buffer);
fix_sector(options,encrypted_buffer);
fwrite(encrypted_buffer,1,512,stream);
fclose(stream);
}
unsigned long Diffuser_B_Decrypt(unsigned char *input, int32 input_size);
unsigned long Diffuser_A_Decrypt(unsigned char *input, int32 input_size);
void decrypt_diffused_sector( options_structure *options, // the usual keys
unsigned char *sector_data, // actual encrypted data after decrypted data is also available here
int32 sector_size, // size of sector which is being decoded
int64 sector ) // this means if a 4 th sector sector is being decoded
{
unsigned char IV[20]; // used to stor IV which is sector specific
unsigned char e[20] ; // used to store sector byte offset
unsigned char sector_key_buffer[40]; // it's actuall a 512 bit value which is xored into the plain text
int64 temp_var_e;
unsigned long loop_var;
/*aes_context fvek_e_ctxt,fvek_d_ctxt;
aes_context tweak_e_ctxt,tweak_d_ctxt;
// initialise contexts
aes_setkey_dec( &fvek_d_ctxt, options->FVEK_key + 12, 128);
aes_setkey_enc( &fvek_e_ctxt, options->FVEK_key + 12, 128);
aes_setkey_dec (&tweak_d_ctxt, options->Tweak_Key + 12 , 128);
aes_setkey_enc (&tweak_e_ctxt, options->Tweak_Key + 12 , 128); // this key is used to get sector key
*/
// let us compute e and other data which is necessary for decryption
/*first e is computed
e is nothing byt byte offset of that sector from start of volume
*/
temp_var_e = sector * options->fve_meta_data.BytesPerSector ;
memset(e,0,sizeof(e));
memcpy(e, &temp_var_e , sizeof(temp_var_e)); // copy this number into a buffer in least byte first encoding
// now let us fill in IV for this sector
aes_crypt_ecb(&options->context.FVEK_E_ctx,AES_ENCRYPT,e , IV);
// this block will fill the sector key
{
// now let us compuet sector_key_buffer
aes_crypt_ecb(&options->context.TWEAK_E_ctx,AES_ENCRYPT,e,sector_key_buffer) ;
//now put 128 in the 16th byte of e
e[15] = 128; // now e represent's e'
aes_crypt_ecb(&options->context.TWEAK_E_ctx,AES_ENCRYPT,e,sector_key_buffer+ 16) ;
}
// now decrypt the buffer usinf AESCBC using the fvek key decryption context
// we use the same buffer as both input and output
aes_crypt_cbc(&options->context.FVEK_D_ctx,AES_DECRYPT,options->fve_meta_data.BytesPerSector,IV,sector_data,sector_data);
// now let us call the diffuser B decryptor
Diffuser_B_Decrypt(sector_data,options->fve_meta_data.BytesPerSector);
// now let us call the diffuser B decryptor
Diffuser_A_Decrypt(sector_data,options->fve_meta_data.BytesPerSector);
// apply sector XOR wit sector key
for( loop_var = 0 ; loop_var < options->fve_meta_data.BytesPerSector ;loop_var++)
sector_data[loop_var] = sector_data[loop_var] ^ sector_key_buffer[ loop_var % 32] ;
// at this stage the buffer is already decrypted succesfully, if everything went right
return ;
}
// TODO write an ecryption function just convertting first plus into minus will make an encryption function
//this applies to both Diffuser A and Diffuser B , thus we can have write support
// this will apply an in place diffuser B decryption function
int32 Diffuser_B_Decrypt(unsigned char *input, unsigned long input_size)
{
int32 temp_array[512];
int32 loop_var;
int32 max_loop;
int32 total_loop; // no . of times diffuser is applied to whole block
//init array with supplied data
memcpy(temp_array,input, input_size);
max_loop = input_size / 4;
total_loop = 3; // the diffuser function is applied a total of 3 times
while ( total_loop) {
// the below loop should be executed
for ( loop_var = 0 ; loop_var < (max_loop-1) ;) {
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var +2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var + 5) % max_loop]),0));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var +2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var + 5) % max_loop]),10));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var +2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var + 5) % max_loop]),0));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var +2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var + 5) % max_loop]),25));
loop_var++;
}
total_loop-- ;
} // end total_loop
// now copy the output onto to the input
memcpy(input, temp_array, input_size);
return 0;
}
// this will apply an in place diffuser A decryption function
int32 Diffuser_A_Decrypt(unsigned char *input, int32 input_size)
{
unsigned long temp_array[512];
unsigned long loop_var;
unsigned long max_loop;
unsigned long total_loop; // no . of times diffuser is applied to whole block
//init array with supplied data
memcpy(temp_array,input, input_size);
max_loop = input_size / 4;
total_loop = 5; // the diffuser function is applied a total of 3 times
while ( total_loop) {
// the below loop should be executed
for ( loop_var = 0 ; loop_var < (max_loop-1) ;) {
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var -2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var - 5) % max_loop]),9));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var -2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var - 5) % max_loop]),0));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var -2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var - 5) % max_loop]),13));
loop_var++;
temp_array[loop_var] = temp_array[loop_var] + ( temp_array [ (loop_var -2 ) % max_loop] ^ ROTATE( (temp_array [ ( loop_var - 5) % max_loop]),0));
loop_var++;
}
total_loop-- ;
} // end total_loop
// now copy the output onto to the input
memcpy(input, temp_array, input_size);
return 0;
}

+ 184
- 0
bit/nvbitlocker/decrypt_key/DecryptKey.c View File

@@ -0,0 +1,184 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
/* this file implements functions to decrypt in AESS, CCM mode as done by bitlocker
*/
#include <string.h>
#include "decryptkey.h"
#include "../aes/aes.h"
#include "../header.h"
/*
when encrypting a microsoft compatible style a 16 byte hash is prepended to data
which contains AES form authentication code, but really we don't care about
or should we start caring ????
*/
// user is responsible for aligning the input to align on 6 byte boundary
void aes_ccm_encrypt_decrypt(aes_context *ctxt,
unsigned char *iv, unsigned long iv_length,
unsigned char *input, unsigned long input_length,
unsigned char *output)
{
unsigned char internal_iv[20];
unsigned char loop_var;
unsigned char temp_buf[16];
int32 local_input_length;
/*
here is how the counter works in microsoft compatible ccm implementation
user supplies less than 16 byte iv
after copying it forms into this format
1 byte field
15-iv_length-1 | iv (max 14 bytes) | a single byte counter counting from zero
now applying counter mode of aes
*/
memset(internal_iv,0,sizeof(internal_iv));
memcpy(internal_iv+1 , iv, (iv_length % 16)); // avoiding buffer overflow
*internal_iv = 15 -iv_length -1;
/* aes_crypt_ecb( ctxt, mode, internal_iv, temp_buf );
// xor it encoded internal_iv (present in temp_buf
for(loop_var =0 ; loop_var <=15;loop_var++)
output[loop_var] = input[loop_var] ^ temp_buf[loop_var];
// increment internal_iv
internal_iv[15] = 1;
// now process the whole data
input = input+16;
output = output+16;
*/
local_input_length = input_length;
while ( local_input_length > 0) {
aes_crypt_ecb( ctxt, AES_ENCRYPT, internal_iv, temp_buf );
for(loop_var =0 ; loop_var <=15;loop_var++)
output[loop_var] = input[loop_var] ^ temp_buf[loop_var];
internal_iv[15]++;
local_input_length -= 16;
input = input+16;
output = output+16;
// handle last block since data could be misaligned
if ( local_input_length > 0 &&
local_input_length < 16)
{
aes_crypt_ecb( ctxt, AES_ENCRYPT, internal_iv, temp_buf );
for(loop_var =0 ; loop_var <=15;loop_var++)
output[loop_var] = input[loop_var] ^ temp_buf[loop_var];
break; // jump out of loop
}
}
}
long decrypt(unsigned char *input,
unsigned char *key,
unsigned long *output,
unsigned long *output_size)
{
aes_context ctx;
unsigned char local_input_buffer[1024];
unsigned char local_output_buffer[1024];
unsigned long input_size;
unsigned long local_output_size;
unsigned char *output_buffer;
HEADER *header = (HEADER *)input;
//allocate output_buffer
output_buffer = malloc(header->Size - 36); /* 8 byte header
12 byte nounce
16 byte authenticator */
local_output_size= header->Size - 36;
input_size = header->Size - 20 ; /* 8 byte header
12 byte nounce
auhtenticator is used while decrypting
*/
memcpy ( local_input_buffer , input + 20 , input_size) ;
// set key which is used to decrypt
aes_setkey_enc( &ctx, key + 12, 256);
aes_ccm_encrypt_decrypt (&ctx,
input+8,
0xc , // nounce is hardcode to be 0xc or 12 bytes
local_input_buffer,
input_size,
output);
//local_output_buffer);
*output_size = local_output_size;
memmove(output, ((long)output + 16),local_output_size);
memset ( ((long)output+local_output_size), 0 , 32);
//memset(local_output_buffer,0,output_size+16);
free(output_buffer);
return 0;
}

+ 33
- 0
bit/nvbitlocker/decrypt_key/DecryptKey.h View File

@@ -0,0 +1,33 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
#ifndef DECRYPT_KEY_H
#define DECRYPT_KEY_H
long decrypt(unsigned char *input,
unsigned char *key,
unsigned long *output,
unsigned long *output_size);
#endif

+ 45
- 0
bit/nvbitlocker/error_codes.h View File

@@ -0,0 +1,45 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
// this header file contains all common definitions including data types
// disable warnings
#pragma warning( disable : 4047 4244 4996 4267 4013 4311)
#ifndef ERROR_CODES_H
#define ERROR_CODES_H
#define NO_RECOVERY_PASSWORD_CONTAINER_FOUND 0xC0000101
#define NO_STARTUP_PASSWORD_CONTAINER_FOUND 0xC0000102
#define INVALID_STARTUP_KEY 0xC0000200
#define INVALID_FVEK_KEY 0xC0000201
#endif // ERROR_CODES_H

+ 88
- 0
bit/nvbitlocker/fve.h View File

@@ -0,0 +1,88 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
// this header file contains all definition to to FVE ( Full volume Encryption of Bitlocker)
#include "common.h"
#ifndef FVE_H
#define FVE_H
// this is the signature for FVE partition
#define FVE_SIGNATURE "-FVE-FS-"
#define NTFS_SIGNATURE "NTFS "
// this is the structure of the first sector of FVE encrypted Volume
# pragma pack (1) // 1 byte packing
typedef struct _FVE_META_DATA {
int8 jmp[3]; //offset 0x0 // this is the jmp // never used
int8 Signature[8]; //offset 0x3 // 8 bytes signature
int16 BytesPerSector; //offset 0xB // it can be 512,1024 and so on
int8 SectorPerCluster;//offset 0xD
/* it can be
0x1 ,0x2, 0x4 ,0x8
0x10,0x20,0x40,0x80 */
int16 ReservedClusters; //offset 0xe // 0x0000
int8 FATCount; //offset 0x10 // 0x00
int16 RootEntries; //offset 0x11 // 0x0000
int16 Sectors; //offset 0x13 // 0x0000
int16 SectorsPerFAT; //offset 0x16 // 0x0000
int16 unknown1; // just a placeholder
int32 LargeSectors; //offset 0x20 // 0x00000000
int32 unknown; // offset 0x24
int32 unknown2; // place holder
int16 unknown3;
int8 unknown4;
int64 Total_Sectors; // total number of sectors in volu me
int64 MFT;
int64 MetaDataLCN; //offset 0x38
// This points to cluster containing VMK metadata
// to calculate sectornumber = MetaDataLCN * SectorPerCluster
} FVE_META_DATA;
typedef struct _MORE_FVE_DATA {
int8 Signature[8];
int8 header[8];
int8 reserved[16] ;
int64 FVE_MetaData[3];
int64 MFT_Mirror; // this value is filled from NTFS boot sector before conversion
} MORE_FVE_DATA;
# pragma pack () // restore original packing
#endif // FVE_H

+ 320
- 0
bit/nvbitlocker/header.h View File

@@ -0,0 +1,320 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3
-------------------
Copyright (c) 2008
Released under the GPL Version 3
http://www.gnu.org/licenses/gpl-3.0.txt
*/
// this header file contains all definition to header structure
#include "common.h"
#include "fve.h"
#include "time.h"
#include "aes/aes.h"
#ifndef HEADER_H
#define HEADER_H
// this is the header of every data contained in FVE_METADATA
/* here goes a brief tree for the structure
MAIN_HEADER
HEADER // this contains drive label
KEY_CONTAINER // there can be a number of key conatiner
HEADER after some random no of bytes another HEADER is present
the above 2 headers are no in the key container, is there something special about them
the KEY_CONTAINER itself itself consists of a number of HEADER
KEY_CONTAINER HEADER
HEADER // contains info such as External Key, DiskPassword etc
HEADER // the VMK key most probably
HEADER // another key MOST probably FVEK
*/
// this header is starts at 0x40 always
// VMK header is prepended by this header
//Main header, it acts like a sub container for other information
///structure is a minimum of 0x30 or 48 bytes total
# pragma pack (1) // 1 byte packing
typedef struct _MAIN_HEADER {
int32 Size; // it should be value defined in FVE_SIGNATURE in fve.h
int32 Version; // it's 1 for now
int32 Isize; // it is size of initial structure and is always 0x30 // does it reallly serve any purpose
int32 Size1; //a copy of Size
int8 Reserved1[16]; // it's probably used to store something hash or salt but unknown,
int32 Reserved2; // it's the same as Version
int32 Encryption_Type; /* it's should be one of these
0x8000 AES 128 + diffuser
0x8001 AES 256 + diffuser
0x8002 AES 128
0x8003 AES 256
*/
FILETIME Time; // it is the time when this structure was started to fill up;
// so we can analyse this to found time or when it was last updated and tell when was Bitlocker enabled
// this is just an assumption
} MAIN_HEADER;
# pragma pack () // restore original packing
// codes assigned by M$FT, to various algorithms
#define AES128_diffuser 0x8000
#define AES256_diffuser 0x8001
#define AES128 0x8002
#define AES256 0x8003
/* KEY_CONTAINER stores the data after the header,
after header there are 3 header, one contains name, the other 2 contain keys
*/
# pragma pack (1) // 1 byte packing
typedef struct _KEY_CONTAINER {
int16 Size; // it should be value defined in FVE_SIGNATURE in fve.h
// if size is zero means no more headers
int16 unknown1;
int16 Type; /* the following types have been identified for now
0x2 for label , label data starts after this header and is in unicode
0x3 for VMK structure , it is immediately followed by guid
then follow 12 byte unknown
then comes the name such as "DiskPassword"
0x5 for key
0x8 This means it has the VMK means this header contains sub header
after headr follows the GUID then a number of bytes with unknown type
// however first sub header header starts at offset 36
*/
int16 Version;
GUID Guid; // it's used to store GUID,
FILETIME Time; // it is the time when this structure was started to fill up;
// so we can analyse this to found time or when it was last updated and tell when was Bitlocker enabled
// this is just an assumption
int32 Reserved2; // it's the same as Version
} KEY_CONTAINER;
# pragma pack () // restore original packing
// this header is always followed by data , data size = Size - ( sizeof(_HEADER))
# pragma pack (1) // 1 byte packing
typedef struct _HEADER {
int16 Size; // it should be value defined in FVE_SIGNATURE in fve.h
// if size is zero means no more headers
int16 unknown1;
int16 Type; /* the following types have been identified for now
0x2 for label , label data starts after this header and is in unicode
0x3 for VMK structure , it is immediately followed by guid
then follow 12 byte unknown
then comes the name such as "DiskPassword"
0x5 for key
0x8 This means it has the VMK means this header contains sub header
after headr follows the GUID then a number of bytes with unknown type
// however first sub header header starts at offset 36
*/
int16 Version;
} HEADER;
# pragma pack () // restore original packing
/* BEK_CONTAINER stores the data after the header,
after header there are 2 header, one contains name, the other one contains key
BEK conatiner is only found in BEK extension files which are stored mostly on External USB drives
NOTE: - Sometimes BEK conatins only 1 header the KEY header
*/
# pragma pack (1) // 1 byte packing
typedef struct _BEK_CONTAINER {
int16 Size; // it should be value defined in FVE_SIGNATURE in fve.h
// if size is zero means no more headers
int16 unknown1;
int16 Type; /* the following types have been identified for now
0x2 for label , label data starts after this header and is in unicode
0x3 for VMK structure , it is immediately followed by guid
then follow 12 byte unknown
then comes the name such as "DiskPassword"
0x5 for key
0x8 This means it has the VMK means this header contains sub header
after headr follows the GUID then a number of bytes with unknown type
// however first sub header header starts at offset 36
*/
int16 Version;
GUID Guid; // it's used to store GUID,
FILETIME Time; // it is the time when this structure was started to fill up;
// so we can analyse this to found time or when it was last updated and tell when was Bitlocker enabled
// this is just an assumption
} BEK_CONTAINER;
# pragma pack () // restore original packing
/*
The type field in header denotes one of these, any extra header that is required
is present just after header
HEADER + (optional extra header) + data
*/
enum int16 {
HEADER_KEY = 1, /* extra header KEY_TYPE
KEY is present in uncrypted form after optional header */
HEADER_LABEL = 2, /* a unicode string is present as data or label */
HEADER_KEY_DISK = 3, /* header + time + int32 unknown +
44 byte encrypted HEADER_KEY/60 byte encrypted blob*/
HEADER_KEY_EXTERNAL = 4,
HEADER_KEY_FVEK = 5,
HEADER_KEY_CONTAINER =8, /* header + GUID + time +int32 + 1 or more headers*/
HEADER_BEK_CONTAINER =9 /* header + GUID + time +int32 + 1 or more headers*/
};
enum KEY_TYPE{
KEY_SALT = 0x00001000,
KEY_VMK_COMPOSITE = 0x00002000,
KEY_VMK = 0x00002003,
KEY_VMK_USB = 0x00002002, // this key can be used to decode appropriate VMK key
/*
also encryption method is also stored here probably
*/
KEY_FVEK_0 = 0x00008000, /* size including header is 0x40 bytes*/
KEY_FVEK_1 = 0x00008001, /* size including header is 0x40 bytes*/
KEY_FVEK_2 = 0x00008002, /* size is 0x10 bytes */
KEY_FVEK_3 = 0x00008003 /* size is 0x20 bytes */
};
# pragma pack (1) // 1 byte packing
typedef struct _PROCESSED_FVE_META_DATA {
MAIN_HEADER Main_Header;
HEADER Header; // a maximum of 3 have been seen till tonight
unsigned char Header_Copy[1024]; // this also includes header
struct {
KEY_CONTAINER Container;
struct {
HEADER Header; // a maximum of 3 have been seen till tonight
unsigned char Header_Copy[1024]; // this also includes header
}Header[5];
long Header_Count;
}Key[8]; // unknown maximum number but only a few can exist
// below we have 2 unlinked keys inaccessible from normal go through, fill them in here
unsigned char UNLINKED_Header_Copy[2][1024]; // this also includes header
long Key_Count;
} PROCESSED_FVE_META_DATA;
# pragma pack () // restore original packing
#define KEY_RECOVERY_PASSWORD 1
#define KEY_STARTUP_PASSWORD 2
typedef struct _options_structure {
unsigned char filename[512]; // this will store either the name of file or drive letter in windows
int8 file;
unsigned char recovery_password[512]; // this will store recovery password
int8 rp;
unsigned char startup_key_filename[512]; // file name for key
unsigned char startup_key[512];
int8 sk;
long using_container; // this contain index of container which was used to obtain VMK
long using_key;
unsigned char key[512]; // this is used to store key which decrypts VMK;
int8 key_present;
unsigned char VMK_key[512]; // this is used to store key which decryptes FVEK
int8 VMK_key_present;
unsigned char FVEK_key[512]; // this is used to store key which actually decrypts the volume
int8 FVEK_key_present;
unsigned char Tweak_Key[512]; // this is the sector key which can be obtained from FVEK if diffuser is enabled
int8 Tweak_key_present;
PROCESSED_FVE_META_DATA processed_fve_meta_data;
FVE_META_DATA fve_meta_data;
MORE_FVE_DATA more_fve_data;
unsigned long Encryption_Type;
// keys are expanded and kept ready for use
struct {
aes_context VMK_E_ctx; // vmk encryption ctx
aes_context VMK_D_ctx; // decryption ctx
aes_context FVEK_E_ctx; //FVEK enc ctx
aes_context FVEK_D_ctx; //FVEK dec ctx
aes_context TWEAK_E_ctx; // tweak key enc ctx
aes_context TWEAK_D_ctx; // tweak key dec ctx
}context;
}options_structure;
// this function does the command line argument processing and fill the structure above
int process_options (int argc, char *argv[], options_structure *options);
void init_keys(options_structure *options);
typedef struct _decrypt_structure {
aes_context FVEK_ctx;
aes_context Sector_ctx;
}decrypt_context;
#endif

+ 99
- 0
bit/nvbitlocker/interface.c View File

@@ -0,0 +1,99 @@
/*
nvbit Bitlocker for linux
------------------------------
Nitin Kumar nitin at nvlabs.in
Vipin Kumar vipin at nvlabs.in
web: http://www.nvlabs.in
Licensed under GPL Version 3