November 2014
S M T W T F S
« Oct    
 1
2345678
9101112131415
16171819202122
23242526272829
30  

Recent Posts

DiceLockXTSIndexedSectorBasedCheck, C++ program for Linux to verify DiceLock encryption cipher architecture with DiceLockXTSIndexed class encrypting storage sector based

DiceLockXTSIndexedSectorBasedCheck is a C++ program for Linux to verify that DiceLockXTSIndexed class implementing one of DiceLock different architectures is working as expected.

DiceLockXTSIndexed class is the cryptographic architecture aimed to storage devices based on XTS operation mode (XEX-based tweaked-codebook mode with ciphertext stealing encryption algorithm) and providing same intrinsic characteristics of DiceLock cipher architecture.

DiceLockXTSIndexed class is the class that implements DiceLock architecture with the following characteristics:
– storage devide sector length is any value multiple of 128 bits bigger than 512 bits,
– base encryption cipher/decipher is a block cipher working with symmetric key,
ciphered index pointing symmetric key modification plus ciphertext is checked for random number test properties,
– any function that is able to change original symmetric key with new values generating index pointing out such modification,
bit random number tests that can verify that encrypted ciphertext is at random.

Current algorithm classes that can be used with DiceLockXTSIndexed architecture are:

– as base encryption cipher/decipher:

  • any of following block ciphers:
      AES (Advanced Encryption Standard) with 128, 192 or 256 key bits,
      Camellia with 128, 192 or 256 key bits,
      Serpent with 128, 192 or 256 key bits,
      Twofish with 128, 192 or 256 key bits, or
  • – symmetric key changers: IncreaseBase0IndexModifier_6_0_0_1 and DecreaseBase0IndexModifier_6_0_0_1,
    – random number tests: Frequency, Block Frequency, Cumulative Sum Forward, Cumulative Sum Reverse, Runs, Longest Run Of Ones, Rank, Universal, Approximate Entropy, Serial, Discrete Fourier Transform tests and random number test Suite with any or all previous enumerated random number tests.

    Because DiceLockXTSIndexed class can work on full length plaintext length or sector based length, there are different alternatives for encryption/decryption, we have split DiceLockXTSIndexed class tests in two main C++ program tests:
    DiceLockXTSIndexedSectorBasedCheck C++ Source Code program applying DiceLockXTSIndexed encryption/decryption on sector base,, and
    DiceLockXTSIndexedFullBasedCheck C++ Source Code program applying DiceLockXTSIndexed encryption/decryption on full plaintext length basis,.

    In this test we verify DiceLockXTSIndexedSectorBasedCheck C++ Source Code program encryption/decryption on device storage sector base with the configuration shown below.

    DiceLockXTSDigested is able to work on device storage sector basis lengths. For these tests sector length can be in bytes = 512, 1024, 1536, 2048, 2560, 3072, 3584, 4096, 16384, 32768, (selected in a random basis),

    In order to verify that DiceLockXTSIndexed class is performing the following program has been used. Execution call must be:
    DiceLockXTSIndexedSectorBasedCheck [block cipher][key modifier][stream type] log_output_file, where the different values can be easily infered from source code.

    Test program in C++ language:

    // DiceLockXTSIndexedSectorBasedCheck.cpp : Defines the entry point for the console application.
    //
    
    #include 
    #include 
    #include "DiceLockCipher.h"
    
    using namespace DiceLockSecurity::Cipher::SymmetricCipher::DiceLock;
    using namespace DiceLockSecurity::Cipher::SymmetricCipher::BlockCipher;
    
    #define MIN_LENGTH_TESTS	8
    #define MAX_LENGTH_TESTS	500000
    #define RANDOM_ALPHA		0.001
    #define FILE_NAME_LENGTH	300
    #define BYTE_BITS			8
    
    
    BlockCiphers SetBlockCipherType(unsigned char cipher) {
    
    	switch (cipher) {
    		case '0' :	return AES_128;
    		case '1' :	return AES_192;
    		case '2' :	return AES_256;
    		case '3' :	return Camellia_128;
    		case '4' :	return Camellia_192;
    		case '5' :	return Camellia_256;
    		case '6' :	return Serpent_128;
    		case '7' :	return Serpent_192;
    		case '8' :	return Serpent_256;
    		case '9' :	return Twofish_128;
    		case 'A' :	return Twofish_192;
    		case 'B' :	return Twofish_256;
    	}
    	return DiceLockSecurity::Cipher::SymmetricCipher::BlockCipher::NotDefined;
    }
    
    BaseIndexModifier* SetIndexModifier(unsigned long int indexer, unsigned long int indexLength) {
    	BaseIndexModifier* modifier;
    
    	modifier = NULL;
    	if ( indexer == '0' ) {
    		modifier = new IncreaseBase0IndexModifier_6_0_0_1();
    		((IncreaseBase0IndexModifier_6_0_0_1*)modifier)->SetBitIndexLength(indexLength);
    	}
    	if ( indexer == '1' ) {
    		modifier = new DecreaseBase0IndexModifier_6_0_0_1();
    		((DecreaseBase0IndexModifier_6_0_0_1*)modifier)->SetBitIndexLength(indexLength);
    	}
    	return modifier;
    }
    
    void RemoveIndexModifier(BaseIndexModifier* modifier, unsigned long int indexer) {
    
    	if ( indexer == '0' ) {
    		delete (IncreaseBase0IndexModifier_6_0_0_1*)modifier;
    	}
    	if ( indexer == '1' ) {
    		delete (DecreaseBase0IndexModifier_6_0_0_1*)modifier;
    	}
    }
    
    BaseCryptoRandomStream*	SetStreamType(unsigned char stream, unsigned long int bitLength) {
    	BaseCryptoRandomStream* streamObject;
    
    	streamObject = NULL;
    	switch (stream) {
    		case '0' :	streamObject = new DefaultCryptoRandomStream(bitLength);
    			break;
    		case '1' :	streamObject = new PhysicalCryptoRandomStream(bitLength);
    			break;
    	}
    	return streamObject;
    }
    
    void RemoveStreamType(BaseCryptoRandomStream* streamObject, unsigned char stream) {
    
    	switch (stream) {
    		case '0' :	delete (DefaultCryptoRandomStream*)streamObject;
    			break;
    		case '1' :	delete (PhysicalCryptoRandomStream*)streamObject;
    			break;
    	}
    }
    
    unsigned long int SetSectorSizeBytes(unsigned long int size) {
    	unsigned long int bitSize;
    
    	bitSize = 0;
    	switch ( size ) {
    		case 0: bitSize = 512;
    			break;
    		case 1: bitSize = 1024;
    			break;
    		case 2: bitSize = 1536;
    			break;
    		case 3: bitSize = 2048;
    			break;
    		case 4: bitSize = 2560;
    			break;
    		case 5: bitSize = 3072;
    			break;
    		case 6: bitSize = 3584;
    			break;
    		case 7: bitSize = 4096;
    			break;
    	}
    	return bitSize;
    }
    
    void SetRandomTestsAndAlpha(RandomTestSuite* suite) {
    
    	suite->AddFrequencyTest();
    	suite->AddBlockFrequencyTest();
    	suite->AddCumulativeSumForwardTest();
    	suite->AddLongestRunOfOnesTest();
    	suite->AddRunsTest();
    	suite->SetAlpha(RANDOM_ALPHA);
    }
    
    void VerifyDecryption(BaseCryptoRandomStream* plaintext, BaseCryptoRandomStream* decipheredtext, unsigned long int* correctDecipher, unsigned long int* incorrectDecipher) {
    
    	if ( plaintext->Equals(decipheredtext) ) {
    		(*correctDecipher)++;
    	}
    	else {
    		(*incorrectDecipher)++;
    	}
    }
    
    int main(int argc, char* argv[])
    {
    
    	unsigned long int performedTests;
    	unsigned long int length;
    	unsigned long int sectorSizeBytes;
    	unsigned long long dataUnit;
    	unsigned long int startBlock;
    	unsigned long int reciphers;
    	unsigned long int maxReciphers;
    	unsigned long int correctDecipher;
    	unsigned long int incorrectDecipher;
    	unsigned char cipher;
    	unsigned char keyModifier;
    	unsigned char dataStream;
    	char reciphersFile[FILE_NAME_LENGTH];
    	FILE* fp;
    	FILE* fr;
    
    	DiceLockXTSIndexed*		diceLock;
    	XTS_Mode*				xtsMode;
    	RandomTestSuite*		randomSuite;
    	BaseIndexModifier*		modifier;
    	BaseCryptoRandomStream* key;
    	BaseCryptoRandomStream* plaintext;
    	BaseCryptoRandomStream* ciphertext;
    	BaseCryptoRandomStream* decipheredtext;
    
    	// Gets execution parameters from command line
    	cipher = argv[1][0];
    	keyModifier = argv[1][1];
    	dataStream = argv[1][2];
    
    	// Pseudo-random generation, fixed intitialitation seed allows 
    	// re-run same test with identical data
    	srand(1);
    
    	performedTests = 0;
    	reciphers = 0;
    	maxReciphers = 0;
    	memset(reciphersFile, 0, FILE_NAME_LENGTH);
    	strcat(reciphersFile, argv[2]);
    	strcat(reciphersFile, ".reciphered");
    	if ( (fr = fopen(reciphersFile, "w")) == NULL ) {
    		printf(" ERROR OPENING FILE\n");
    		return 1;
    	}
    	fprintf(fr, "keyUC,plainUC,length,Sector length,dataUnit,startBlock,reciphers\n");
    	correctDecipher = 0;
    	incorrectDecipher = 0;
    
    	for ( length = MIN_LENGTH_TESTS; length <= MAX_LENGTH_TESTS; length = length + 8 ) {
    
    		printf("length: %lu\n", length);
    		performedTests++;
    
    		// Sector size in bytes
    		sectorSizeBytes = SetSectorSizeBytes(rand() % 8);
    
    		// Specific XTS mode operation mode parameters
    		dataUnit = (unsigned long long)(rand());
    		startBlock = (unsigned long int)(rand() & 0x000000FF);
    
    		// Encryption
    		diceLock =  new DiceLockXTSIndexed();
    		xtsMode = new XTS_Mode();
    		xtsMode->SetBlockCiphers(SetBlockCipherType(cipher));
    		diceLock->SetXTS_Mode(xtsMode);
    		randomSuite = new RandomTestSuite();
    		SetRandomTestsAndAlpha(randomSuite);
    		diceLock->SetRandomTestSuite(randomSuite);
    		modifier = SetIndexModifier(keyModifier, xtsMode->GetBitBaseBlockLength());
    		diceLock->SetIndexModifier(modifier);
    
    		// Sets sector size 
    		diceLock->SetSectorSizeLengthUCs(sectorSizeBytes);
    
    		key = SetStreamType(dataStream, diceLock->GetBitKeyLength());
    		plaintext = SetStreamType(dataStream, length);
    		ciphertext = SetStreamType(dataStream, diceLock->GetSectorBasedBitCiphertextLength(plaintext->GetBitLength()));
    		
    		key->FillUC((unsigned char)(rand() & 0x000000FF));
    		plaintext->FillUC((unsigned char)(rand() & 0x000000FF));
    
    		diceLock->Initialize();
    		diceLock->SetSymmetricKey(key);
    		diceLock->CipherSectorBased(plaintext, ciphertext, dataUnit, startBlock);
    
    		if ( diceLock->GetReciphers() > 0 ) {
    			reciphers++;
    			if ( maxReciphers < diceLock->GetReciphers() ) {
    				maxReciphers = diceLock->GetReciphers();
    			}
    			fprintf(fr, "%02x,%02x,%lu,%lu,%lli,%lu,%lu\n", key->GetUCPosition(0), plaintext->GetUCPosition(0), length, sectorSizeBytes, dataUnit, startBlock, diceLock->GetReciphers());
    		}
    
    		RemoveIndexModifier(modifier, keyModifier);
    		delete randomSuite;
    		delete xtsMode;
    		delete diceLock;
    
    		// Decryption
    		diceLock =  new DiceLockXTSIndexed();
    		xtsMode = new XTS_Mode();
    		xtsMode->SetBlockCiphers(SetBlockCipherType(cipher));
    		diceLock->SetXTS_Mode(xtsMode);
    		modifier = SetIndexModifier(keyModifier, xtsMode->GetBitBaseBlockLength());
    		diceLock->SetIndexModifier(modifier);
    
    		// Sets sector size 
    		diceLock->SetSectorSizeLengthUCs(sectorSizeBytes);
    
    		decipheredtext = SetStreamType(dataStream, diceLock->GetSectorBasedBitDecipheredtextLength(ciphertext->GetBitLength()));
    
    		diceLock->Initialize();
    		diceLock->SetSymmetricKey(key);
    		diceLock->DecipherSectorBased(ciphertext, decipheredtext, dataUnit, startBlock);
    
    		RemoveIndexModifier(modifier, keyModifier);
    		delete xtsMode;
    		delete diceLock;
    
    		// Verifying plaintext and decipheredtext
    		VerifyDecryption(plaintext, decipheredtext, &correctDecipher, &incorrectDecipher);
    
    		RemoveStreamType(key, dataStream);
    		RemoveStreamType(plaintext, dataStream);
    		RemoveStreamType(ciphertext, dataStream);
    		RemoveStreamType(decipheredtext, dataStream);
    	}
    	fclose(fr);
    
    	// Total Output 
    	if ( (fp = fopen(argv[2], "w")) == NULL ) {
    		printf(" ERROR OPENING FILE\n");
    		return 1;
    	}
    	fprintf(fp, "Verified:\n");
    	fprintf(fp, "---------\n");
    	fprintf(fp, "%s\n", argv[2]);
    	fprintf(fp, "\n");
    	fprintf(fp, "Number of streams tested: %lu\n", performedTests);
    	fprintf(fp, "\n");
    	fprintf(fp, "From length of shorter stream tested in bits: %d\n", MIN_LENGTH_TESTS);
    	fprintf(fp, "Up to length of larger stream tested in bits: %d\n", MAX_LENGTH_TESTS);
    	fprintf(fp, "\n");
    	fprintf(fp, "\n");
    	fprintf(fp, "Number of correct streams deciphered: %lu\n", correctDecipher);
    	fprintf(fp, "Number of incorrect streams deciphered: %lu\n", incorrectDecipher);
    	if ( incorrectDecipher == 0 ) {
    		fprintf(fp, "Incorrect deciphered streams = %lu ==> ---OK---\n", incorrectDecipher);
    	}
    	else {
    		fprintf(fp, "Incorrect deciphered streams = %lu ==> ---ERROR---\n", incorrectDecipher);
    	}
    	fprintf(fp, "\n");
    	fprintf(fp, "Total encrypted streams with at least one sector being reciphered: %lu\n", reciphers);
    	fprintf(fp, "Maximum number of reciphers performed over one stream being reciphered: %lu\n", maxReciphers);
    	fprintf(fp, "\n");
    	fprintf(fp, "File with reciphered stream data:\n");
    	fprintf(fp, "%s\n", reciphersFile);
    	fprintf(fp, "\n");
    	fclose(fp);
    
    	return 0;
    }
    
    

    All different tests are performed over 62.500 streams and we will post each one result promptly.

    Leave a Reply