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)
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
17
ReadMe.md
17
ReadMe.md
@@ -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
|
||||
-------------------------
|
||||
|
||||
|
||||
1335
lib/CryptLib_Aes.c
1335
lib/CryptLib_Aes.c
File diff suppressed because it is too large
Load Diff
@@ -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]
|
||||
);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
);
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 )
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user