1 Commits

Author SHA1 Message Date
waterjuice
3201fb4d83 Version 2.1.0
* Changed implementation of AES to one which is almost 5 times as fast. The new implementation comes from LibTomCrypt. The newer implementation produces a larger binary size as a trade-off.
* AES-CTR module now supports OpenMP and when compiled with OpenMP will run in parallel giving a much greater speed.
* Changed interface for Initialisation functions for both AES and AES-CTR to be match RC4 (The context is first parameter not last)
2017-12-11 11:22:47 +11:00
25 changed files with 1144 additions and 624 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -7,7 +7,8 @@ and a a single .h file. AES-CTR does depend on the AES module, so in this
case all four files are needed.
The functions are designed to be portable and have been tested on both
a Little-Endian and a Big-Endian architecture
a Little-Endian and a Big-Endian architecture. OpenMP is supported where
parallelisation can occur.
The library and the demo programs can be built using CMake to generate
a build setup for any system, including Visual Studio on Windows and
@@ -15,6 +16,19 @@ Make or Ninja for Linux. Refer to cmake.org to get CMake.
*Placed into Public Domain by WaterJuice 2013 - 2017*
Version 2.1.0 - December 2017
-----------------------------
Changes:
* Changed implementation of AES to one which is almost 5 times as fast.
The new implementation comes from LibTomCrypt. The newer implementation
produces a larger binary size as a trade-off.
* AES-CTR module now supports OpenMP and when compiled with OpenMP will
run in parallel giving a much greater speed.
* Changed interface for Initialisation functions for both AES and AES-CTR
to be match RC4 (The context is first parameter not last)
Version 2.0.0 - December 2017
-----------------------------
@@ -42,7 +56,6 @@ depending on what cryptographic functions are wanted.
* AES-CTR - (CryptLib_AesCtr.h, and CryptLib_AesCtr.c, CryptLib_Aes.h,
and CryptLib_Aes.c)
Version 1.0.0 - June 2013
-------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,22 @@
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CryptLib_Aes
//
// Implementation of AES block cipher. Originally written by Kokke (https://github.com/kokke). Modified by WaterJuice
// retaining Public Domain license.
// Implementation of AES block cipher. This implementation was modified from LibTomCrypt written by Tom St Denis
// (https://github.com/libtom). Modified by WaterJuice retaining Public Domain license.
// Derived from Public Domain source by original authors:
// Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
// Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
// Paulo Barreto <paulo.barreto@terra.com.br>
//
// AES is a block cipher that operates on 128 bit blocks. Encryption an Decryption routines use an AesContext which
// must be initialised with the key. An AesContext can be initialised with a 128, 192, or 256 bit key. Use the
// AesInitialise[n] functions to initialise the context with the key. Once an AES context is initialised its contents
// are not changed by the encrypting and decrypting functions. A context only needs to be initialised once for any
// given key and the context may be used by the encrypt/decrypt functions in simultaneous threads.
// All operations are performed byte wise and this implementation works in both little and endian processors.
// All operations are performed BYTE wise and this implementation works in both little and endian processors.
// There are no alignment requirements with the keys and data blocks.
//
// This is free and unencumbered software released into the public domain - November 2017 waterjuice.org
// This is free and unencumbered software released into the public domain - December 2017 waterjuice.org
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma once
@@ -36,9 +40,9 @@
// Do not modify the contents of this structure directly.
typedef struct
{
uint32_t KeySizeInWords;
uint32_t NumberOfRounds;
uint8_t RoundKey[240];
uint32_t eK[60];
uint32_t dK[60];
uint_fast32_t Nr;
} AesContext;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -46,39 +50,17 @@ typedef struct
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AesInitialise128
// AesInitialise
//
// Initialises an AesContext with a 128 bit key.
// Initialises an AesContext with an AES Key. KeySize must be 16, 24, or 32 (for 128, 192, or 256 bit key size)
// Returns 0 if successful, or -1 if invalid KeySize provided
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
AesInitialise128
int
AesInitialise
(
uint8_t const Key [AES_KEY_SIZE_128], // [in]
AesContext* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AesInitialise192
//
// Initialises an AesContext with a 192 bit key.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
AesInitialise192
(
uint8_t const Key [AES_KEY_SIZE_192], // [in]
AesContext* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// AesInitialise256
//
// Initialises an AesContext with a 256 bit key.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
AesInitialise256
(
uint8_t const Key [AES_KEY_SIZE_256], // [in]
AesContext* Context // [out]
AesContext* Context, // [out]
void const* Key, // [in]
uint32_t KeySize // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -96,9 +96,9 @@ void
void
AesCtrInitialise
(
AesCtrContext* Context, // [out]
AesContext const* InitialisedAesContext, // [in]
uint8_t const IV [AES_CTR_IV_SIZE], // [in]
AesCtrContext* Context // [out]
uint8_t const IV [AES_CTR_IV_SIZE] // [in]
)
{
// Setup context values
@@ -121,27 +121,22 @@ void
int
AesCtrInitialiseWithKey
(
AesCtrContext* Context, // [out]
uint8_t const* Key, // [in]
uint32_t KeySize, // [in]
uint8_t const IV [AES_CTR_IV_SIZE], // [in]
AesCtrContext* Context // [out]
uint8_t const IV [AES_CTR_IV_SIZE] // [in]
)
{
AesContext aes;
// Initialise AES Context
switch( KeySize )
if( 0 != AesInitialise( &aes, Key, KeySize ) )
{
case AES_KEY_SIZE_128: AesInitialise128( Key, &aes ); break;
case AES_KEY_SIZE_192: AesInitialise192( Key, &aes ); break;
case AES_KEY_SIZE_256: AesInitialise256( Key, &aes ); break;
default:
// Invalid key size
return -1;
}
// Now set-up AesCtrContext
AesCtrInitialise( &aes, IV, Context );
AesCtrInitialise( Context, &aes, IV );
return 0;
}
@@ -177,7 +172,7 @@ void
// advance the stream index by that number of bytes.
// Use once over data to encrypt it. Use it a second time over the same data from the same stream position and the
// data will be decrypted.
// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
// InBuffer and OutBuffer can point to the same location for in-place encrypting/decrypting
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
AesCtrXor
@@ -188,47 +183,68 @@ void
uint32_t Size // [in]
)
{
uint32_t amountLeft = Size;
uint32_t outputOffset = 0;
uint32_t chunkSize;
uint32_t amountAvailableInBlock;
uint32_t firstChunkSize;
uint32_t amountAvailableInBlock;
int numIterations;
int i;
uint64_t loopStartingCipherBlockIndex;
uint32_t loopStartingOutputOffset;
uint8_t preCipherBlock [AES_KEY_SIZE_128];
uint8_t encCipherBlock [AES_KEY_SIZE_128];
uint64_t cipherBlockIndex = 0;
// First determine how much is available in the current block.
amountAvailableInBlock = AES_BLOCK_SIZE - (Context->StreamIndex % AES_BLOCK_SIZE);
// Determine how much of the current block we will take, either all that is available, or less
// if the amount requested is smaller.
chunkSize = MIN( amountAvailableInBlock, amountLeft );
firstChunkSize = MIN( amountAvailableInBlock, Size );
// XOR the bytes from the cipher block
XorBuffers( InBuffer, Context->CurrentCipherBlock + (AES_BLOCK_SIZE - amountAvailableInBlock), OutBuffer, chunkSize );
XorBuffers( InBuffer, Context->CurrentCipherBlock + (AES_BLOCK_SIZE - amountAvailableInBlock), OutBuffer, firstChunkSize );
amountLeft -= chunkSize;
outputOffset += chunkSize;
// Determine how many iterations will be needed for generating cipher blocks.
// We always have to finish with a non-depleted cipher block.
// Also calculate the cipher block index and the output offset for when we start the loop.
// This function may be built with OpenMP and the loop will run in parallel. So we set-up variables that will
// be common at the start of the loop.
numIterations = ( (Size - firstChunkSize) + AES_BLOCK_SIZE ) / AES_BLOCK_SIZE;
loopStartingCipherBlockIndex = Context->CurrentCipherBlockIndex + 1;
loopStartingOutputOffset = firstChunkSize;
// Copy the IV into the first half of the preCipherBlock. When built for OpenMP preCipherBlock will be copied into
// a local version within the loop.
memcpy( preCipherBlock, Context->IV, AES_CTR_IV_SIZE );
// Now start generating new cipher blocks as required.
while( amountLeft > 0 )
#ifdef _OPENMP
#pragma omp parallel for firstprivate( preCipherBlock, cipherBlockIndex ) lastprivate( encCipherBlock, cipherBlockIndex )
#endif
for( i=0; i<numIterations; i++ )
{
uint32_t outputOffset = loopStartingOutputOffset + (AES_BLOCK_SIZE * i);
uint32_t amountLeft = Size - outputOffset;
uint32_t chunkSize = MIN( amountLeft, AES_BLOCK_SIZE );
// Increment block index and regenerate cipher block
Context->CurrentCipherBlockIndex += 1;
CreateCurrentCipherBlock( Context );
cipherBlockIndex = loopStartingCipherBlockIndex + i;
// Determine how much of the current block we need and XOR it out onto the buffer
chunkSize = MIN( amountLeft, AES_BLOCK_SIZE );
XorBuffers( (uint8_t*)InBuffer + outputOffset, Context->CurrentCipherBlock, (uint8_t*)OutBuffer + outputOffset, chunkSize );
// Now place in the counter in Big Endian form in second half of preCipherBlock
STORE64H( cipherBlockIndex, preCipherBlock + AES_CTR_IV_SIZE );
amountLeft -= chunkSize;
outputOffset += chunkSize;
// Perform AES encryption on the preCipherBlock and put result in encCipherBlock
AesEncrypt( &Context->Aes, preCipherBlock, encCipherBlock );
// XOR block out onto the buffer.
XorBuffers( (uint8_t*)InBuffer + outputOffset, encCipherBlock, (uint8_t*)OutBuffer + outputOffset, chunkSize );
}
// All data read out now, so update index in the context.
// Update context
Context->StreamIndex += Size;
// If we ended up completely reading the last cipher block we need to generate a new one for next time.
if( AES_BLOCK_SIZE == chunkSize )
if( numIterations > 0 )
{
Context->CurrentCipherBlockIndex += 1;
CreateCurrentCipherBlock( Context );
Context->CurrentCipherBlockIndex = cipherBlockIndex;
memcpy( Context->CurrentCipherBlock, encCipherBlock, AES_BLOCK_SIZE );
}
}
@@ -273,7 +289,7 @@ int
int error;
AesCtrContext context;
error = AesCtrInitialiseWithKey( Key, KeySize, IV, &context );
error = AesCtrInitialiseWithKey( &context, Key, KeySize, IV );
if( 0 == error )
{
AesCtrXor( &context, InBuffer, OutBuffer, BufferSize );

View File

@@ -54,9 +54,9 @@ typedef struct
void
AesCtrInitialise
(
AesCtrContext* Context, // [out]
AesContext const* InitialisedAesContext, // [in]
uint8_t const IV [AES_CTR_IV_SIZE], // [in]
AesCtrContext* Context // [out]
uint8_t const IV [AES_CTR_IV_SIZE] // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -69,10 +69,10 @@ void
int
AesCtrInitialiseWithKey
(
AesCtrContext* Context, // [out]
uint8_t const* Key, // [in]
uint32_t KeySize, // [in]
uint8_t const IV [AES_CTR_IV_SIZE], // [in]
AesCtrContext* Context // [out]
uint8_t const IV [AES_CTR_IV_SIZE] // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -95,7 +95,7 @@ void
// advance the stream index by that number of bytes.
// Use once over data to encrypt it. Use it a second time over the same data from the same stream position and the
// data will be decrypted.
// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
// InBuffer and OutBuffer can point to the same location for in-place encrypting/decrypting
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
AesCtrXor

View File

@@ -66,10 +66,10 @@ void*
#define GET(n) (ctx->block[(n)])
#define SET(n) (ctx->block[(n)] = \
((uint32_t)ptr[(n)*4 + 0] << 0 ) \
| ((uint32_t)ptr[(n)*4 + 1] << 8 ) \
| ((uint32_t)ptr[(n)*4 + 2] << 16) \
| ((uint32_t)ptr[(n)*4 + 3] << 24) )
((uint32_t)ptr[(n)*4 + 0] << 0 ) \
| ((uint32_t)ptr[(n)*4 + 1] << 8 ) \
| ((uint32_t)ptr[(n)*4 + 2] << 16) \
| ((uint32_t)ptr[(n)*4 + 3] << 24) )
ptr = (uint8_t*)data;
@@ -188,7 +188,7 @@ void*
void
Md5Initialise
(
Md5Context* Context
Md5Context* Context // [out]
)
{
Context->a = 0x67452301;
@@ -209,9 +209,9 @@ void
void
Md5Update
(
Md5Context* Context,
void const* Buffer,
uint32_t BufferSize
Md5Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
)
{
uint32_t saved_lo;
@@ -261,8 +261,8 @@ void
void
Md5Finalise
(
Md5Context* Context,
MD5_HASH* Digest
Md5Context* Context, // [in out]
MD5_HASH* Digest // [in]
)
{
uint32_t used;

View File

@@ -52,7 +52,7 @@ typedef struct
void
Md5Initialise
(
Md5Context* Context
Md5Context* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -64,9 +64,9 @@ void
void
Md5Update
(
Md5Context* Context,
void const* Buffer,
uint32_t BufferSize
Md5Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -78,6 +78,6 @@ void
void
Md5Finalise
(
Md5Context* Context,
MD5_HASH* Digest
Md5Context* Context, // [in out]
MD5_HASH* Digest // [in]
);

View File

@@ -36,10 +36,10 @@
void
Rc4Initialise
(
Rc4Context* Context,
void const* Key,
uint32_t KeySize,
uint32_t DropN
Rc4Context* Context, // [out]
void const* Key, // [in]
uint32_t KeySize, // [in]
uint32_t DropN // [in]
)
{
uint32_t i;
@@ -82,9 +82,9 @@ void
void
Rc4Output
(
Rc4Context* Context,
void* Buffer,
uint32_t Size
Rc4Context* Context, // [in out]
void* Buffer, // [out]
uint32_t Size // [in]
)
{
uint32_t n;
@@ -108,10 +108,10 @@ void
void
Rc4Xor
(
Rc4Context* Context,
void const* InBuffer,
void* OutBuffer,
uint32_t Size
Rc4Context* Context, // [in out]
void const* InBuffer, // [in]
void* OutBuffer, // [out]
uint32_t Size // [in]
)
{
uint32_t n;

View File

@@ -38,10 +38,10 @@ typedef struct
void
Rc4Initialise
(
Rc4Context* Context,
void const* Key,
uint32_t KeySize,
uint32_t DropN
Rc4Context* Context, // [out]
void const* Key, // [in]
uint32_t KeySize, // [in]
uint32_t DropN // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -52,9 +52,9 @@ void
void
Rc4Output
(
Rc4Context* Context,
void* Buffer,
uint32_t Size
Rc4Context* Context, // [in out]
void* Buffer, // [out]
uint32_t Size // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -66,8 +66,8 @@ void
void
Rc4Xor
(
Rc4Context* Context,
void const* InBuffer,
void* OutBuffer,
uint32_t Size
Rc4Context* Context, // [in out]
void const* InBuffer, // [in]
void* OutBuffer, // [out]
uint32_t Size // [in]
);

View File

@@ -158,7 +158,7 @@ void
void
Sha1Initialise
(
Sha1Context* Context
Sha1Context* Context // [out]
)
{
// SHA1 initialisation constants
@@ -180,9 +180,9 @@ void
void
Sha1Update
(
Sha1Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha1Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
)
{
uint32_t i;
@@ -223,8 +223,8 @@ void
void
Sha1Finalise
(
Sha1Context* Context,
SHA1_HASH* Digest
Sha1Context* Context, // [in out]
SHA1_HASH* Digest // [in]
)
{
uint32_t i;

View File

@@ -50,7 +50,7 @@ typedef struct
void
Sha1Initialise
(
Sha1Context* Context
Sha1Context* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -62,9 +62,9 @@ void
void
Sha1Update
(
Sha1Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha1Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -76,6 +76,6 @@ void
void
Sha1Finalise
(
Sha1Context* Context,
SHA1_HASH* Digest
Sha1Context* Context, // [in out]
SHA1_HASH* Digest // [in]
);

View File

@@ -151,9 +151,10 @@ void
//
// Initialises a SHA256 Context. Use this to initialise/reset a context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Initialise
void
Sha256Initialise
(
Sha256Context* Context
Sha256Context* Context // [out]
)
{
Context->curlen = 0;
@@ -174,15 +175,16 @@ void Sha256Initialise
// Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Update
void
Sha256Update
(
Sha256Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha256Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
)
{
uint32_t n
;
uint32_t n;
if( Context->curlen > sizeof(Context->buf) )
{
return;
@@ -223,8 +225,8 @@ void Sha256Update
void
Sha256Finalise
(
Sha256Context* Context,
SHA256_HASH* Digest
Sha256Context* Context, // [in out]
SHA256_HASH* Digest // [out]
)
{
int i;

View File

@@ -41,9 +41,10 @@ typedef struct
//
// Initialises a SHA256 Context. Use this to initialise/reset a context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Initialise
void
Sha256Initialise
(
Sha256Context* Context
Sha256Context* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -52,11 +53,12 @@ void Sha256Initialise
// Adds data to the SHA256 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha256Finalise to calculate the hash.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha256Update
void
Sha256Update
(
Sha256Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha256Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,6 +70,6 @@ void Sha256Update
void
Sha256Finalise
(
Sha256Context* Context,
SHA256_HASH* Digest
Sha256Context* Context, // [in out]
SHA256_HASH* Digest // [out]
);

View File

@@ -154,7 +154,7 @@ void
void
Sha512Initialise
(
Sha512Context* Context
Sha512Context* Context // [out]
)
{
Context->curlen = 0;
@@ -178,9 +178,9 @@ void
void
Sha512Update
(
Sha512Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha512Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
)
{
uint32_t n;
@@ -225,8 +225,8 @@ void
void
Sha512Finalise
(
Sha512Context* Context,
SHA512_HASH* Digest
Sha512Context* Context, // [in out]
SHA512_HASH* Digest // [out]
)
{
int i;

View File

@@ -41,9 +41,10 @@ typedef struct
//
// Initialises a SHA512 Context. Use this to initialise/reset a context.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha512Initialise
void
Sha512Initialise
(
Sha512Context* Context
Sha512Context* Context // [out]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -52,11 +53,12 @@ void Sha512Initialise
// Adds data to the SHA512 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha512Finalise to calculate the hash.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Sha512Update
void
Sha512Update
(
Sha512Context* Context,
void const* Buffer,
uint32_t BufferSize
Sha512Context* Context, // [in out]
void const* Buffer, // [in]
uint32_t BufferSize // [in]
);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -68,6 +70,6 @@ void Sha512Update
void
Sha512Finalise
(
Sha512Context* Context,
SHA512_HASH* Digest
Sha512Context* Context, // [in out]
SHA512_HASH* Digest // [out]
);

View File

@@ -146,9 +146,9 @@ int
switch( keySize )
{
case 128/8: AesInitialise128( key, &aesContext ); break;
case 192/8: AesInitialise192( key, &aesContext ); break;
case 256/8: AesInitialise256( key, &aesContext ); break;
case 128/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_128 ); break;
case 192/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_192 ); break;
case 256/8: AesInitialise( &aesContext, key, AES_KEY_SIZE_256 ); break;
default:
printf( "Invalid key size, must be 128, 192, or 256 bits (was %u bits)\n", keySize*8 );
exit( 1 );

View File

@@ -101,7 +101,7 @@ int
uint8_t buffer [BUFFER_SIZE];
uint32_t amountLeft;
uint32_t chunk;
AesCtrContext aesCtr = {{0}};
AesCtrContext aesCtr;
uint8_t key [AES_KEY_SIZE_256];
uint32_t keySize = sizeof(key);
uint8_t IV [AES_CTR_IV_SIZE];
@@ -134,7 +134,7 @@ int
numBytes = atoi( ArgV[3] );
AesCtrInitialiseWithKey( key, keySize, IV, &aesCtr );
AesCtrInitialiseWithKey( &aesCtr, key, keySize, IV );
amountLeft = numBytes;
while( amountLeft > 0 )

View File

@@ -117,15 +117,15 @@ bool
for( i=0; i<NUM_TEST_VECTORS; i++ )
{
AesInitialise128( gTestVectors[i].Key128, &context );
AesInitialise( &context, gTestVectors[i].Key128, AES_KEY_SIZE_128 );
AesEncrypt( &context, gTestVectors[i].PlainText, encBlock128 );
AesDecrypt( &context, gTestVectors[i].CipherText128, decBlock128 );
AesInitialise192( gTestVectors[i].Key192, &context );
AesInitialise( &context, gTestVectors[i].Key192, AES_KEY_SIZE_192 );
AesEncrypt( &context, gTestVectors[i].PlainText, encBlock192 );
AesDecrypt( &context, gTestVectors[i].CipherText192, decBlock192 );
AesInitialise256( gTestVectors[i].Key256, &context );
AesInitialise( &context, gTestVectors[i].Key256, AES_KEY_SIZE_256 );
AesEncrypt( &context, gTestVectors[i].PlainText, encBlock256 );
AesDecrypt( &context, gTestVectors[i].CipherText256, decBlock256 );

View File

@@ -18,6 +18,7 @@
#include <string.h>
#include <stdbool.h>
#include "CryptLib_AesCtr.h"
#include "CryptLib_Sha1.h"
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// MACROS
@@ -163,6 +164,76 @@ bool
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TestLargeVector
//
// Tests AES CTR against a known large vector (of 1 million bytes). We check it against a known SHA-1 hash of
// the output.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static
bool
TestLargeVector
(
void
)
{
//dd if=/dev/zero iflag=count_bytes count=1000000 status=none | openssl enc -aes-128-ctr -K 00001111222233334444555566667777 -iv 88889999aaaabbbb | openssl sha1
//(stdin)= 6227c0192b110133fadd6d229790bbdf13c068ab
uint8_t const* key = (uint8_t const*)"\x00\x00\x11\x11\x22\x22\x33\x33\x44\x44\x55\x55\x66\x66\x77\x77";
uint8_t const* iv = (uint8_t const*)"\x88\x88\x99\x99\xaa\xaa\xbb\xbb";
uint8_t const* sha1Hash = (uint8_t const*)"\xe1\x63\x5f\xa4\xf5\x7c\x98\x54\xf6\x18\xec\x0c\x8f\x18\x7f\x04\x34\xa2\xe1\x72";
uint32_t const numBytesToGenerate = 1000000;
uint8_t* buffer = malloc( numBytesToGenerate );
uint32_t amountLeft = numBytesToGenerate;
uint32_t chunkSize;
Sha1Context sha1Context;
AesCtrContext aesCtrContext;
SHA1_HASH calcSha1;
// Encrypt in one go first.
memset( buffer, 0, numBytesToGenerate );
AesCtrXorWithKey( key, AES_KEY_SIZE_128, iv, buffer, buffer, numBytesToGenerate );
Sha1Initialise( &sha1Context );
Sha1Update( &sha1Context, buffer, numBytesToGenerate );
Sha1Finalise( &sha1Context, &calcSha1 );
if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) )
{
printf( "Large test vector failed\n" );
return false;
}
memset( buffer, 0, numBytesToGenerate );
// Now encrypt in smaller pieces (10000 bytes at a time)
Sha1Initialise( &sha1Context );
AesCtrInitialiseWithKey( &aesCtrContext, key, AES_KEY_SIZE_128, iv );
while( amountLeft > 0 )
{
memset( buffer, 0, numBytesToGenerate );
chunkSize = MIN( amountLeft, 10000 );
AesCtrOutput( &aesCtrContext, buffer, chunkSize );
Sha1Update( &sha1Context, buffer, chunkSize );
amountLeft -= chunkSize;
}
Sha1Finalise( &sha1Context, &calcSha1 );
if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) )
{
printf( "Large test vector failed\n" );
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TestStreamConsistency
//
@@ -199,7 +270,7 @@ bool
}
// Now recreate the stream in small bits. Starting at 1 byte at a time and increasing chunk size
AesCtrInitialiseWithKey( key, sizeof(key), iv, &context );
AesCtrInitialiseWithKey( &context, key, sizeof(key), iv );
for( chunkSize=1; chunkSize<64; chunkSize++ )
{
uint32_t amountLeft = STREAMSIZE;
@@ -262,7 +333,7 @@ bool
0xf8, 0x8f, 0x45, 0xd1, 0xf6, 0x68, 0x28, 0x54,
0x6f, 0xef, 0xce, 0xf9, 0x23, 0x1b, 0xb0, 0x08 };
AesCtrInitialiseWithKey( key, sizeof(key), iv, &context );
AesCtrInitialiseWithKey( &context, key, sizeof(key), iv );
AesCtrSetStreamIndex( &context, positionIndex );
AesCtrOutput( &context, output, sizeof(output) );
@@ -296,6 +367,9 @@ bool
success = TestVectors( );
if( !success ) { totalSuccess = false; }
success = TestLargeVector( );
if( !success ) { totalSuccess = false; }
success = TestStreamConsistency( );
if( !success ) { totalSuccess = false; }