Version 2.3.0
* Added AES-CBC module. * Added functions Md5Calculate, Sha1Calculate, Sha256Calculate, and Sha512Calculate to calculate a hash in one call. * Added function Rc4XorWithKey to encrypt/decrypt a buffer with RC4 in one call. * Bugfix: AesInitialise now returns -1 if invalid key size is provided. Previously it would return 0 despite what was documented.
This commit is contained in:
@@ -6,6 +6,8 @@ project( WjCryptLib )
|
|||||||
add_library( WjCryptLib STATIC
|
add_library( WjCryptLib STATIC
|
||||||
lib/WjCryptLib_Aes.h
|
lib/WjCryptLib_Aes.h
|
||||||
lib/WjCryptLib_Aes.c
|
lib/WjCryptLib_Aes.c
|
||||||
|
lib/WjCryptLib_AesCbc.h
|
||||||
|
lib/WjCryptLib_AesCbc.c
|
||||||
lib/WjCryptLib_AesCtr.h
|
lib/WjCryptLib_AesCtr.h
|
||||||
lib/WjCryptLib_AesCtr.c
|
lib/WjCryptLib_AesCtr.c
|
||||||
lib/WjCryptLib_AesOfb.h
|
lib/WjCryptLib_AesOfb.h
|
||||||
|
|||||||
15
ReadMe.md
15
ReadMe.md
@@ -32,10 +32,23 @@ depending on what cryptographic functions are wanted.
|
|||||||
and WjCryptLib_Aes.c)
|
and WjCryptLib_Aes.c)
|
||||||
* AES-OFB - (WjCryptLib_AesOfb.h, and WjCryptLib_AesOfb.c, WjCryptLib_Aes.h,
|
* AES-OFB - (WjCryptLib_AesOfb.h, and WjCryptLib_AesOfb.c, WjCryptLib_Aes.h,
|
||||||
and WjCryptLib_Aes.c)
|
and WjCryptLib_Aes.c)
|
||||||
|
* AES-CBC - (WjCryptLib_AesCbc.h, and WjCryptLib_AesCbc.c, WjCryptLib_Aes.h,
|
||||||
|
and WjCryptLib_Aes.c)
|
||||||
|
|
||||||
|
|
||||||
|
Version 2.3.0 - March 2018
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* Added AES-CBC module.
|
||||||
|
* Added functions Md5Calculate, Sha1Calculate, Sha256Calculate, and
|
||||||
|
Sha512Calculate to calculate a hash in one call.
|
||||||
|
* Added function Rc4XorWithKey to encrypt/decrypt a buffer with RC4 in
|
||||||
|
one call.
|
||||||
|
* Bugfix: AesInitialise now returns -1 if invalid key size is provided.
|
||||||
|
Previously it would return 0 despite what was documented.
|
||||||
|
|
||||||
Version 2.2.0 - January 2018
|
Version 2.2.0 - January 2018
|
||||||
------------
|
----------------------------
|
||||||
|
|
||||||
* Added AES-OFB module.
|
* Added AES-OFB module.
|
||||||
* File names have been changed to have the prefix `WjCryptLib_` rather
|
* File names have been changed to have the prefix `WjCryptLib_` rather
|
||||||
|
|||||||
@@ -789,6 +789,10 @@ int
|
|||||||
rk += 8;
|
rk += 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Setup the inverse key now
|
// Setup the inverse key now
|
||||||
rk = Context->dK;
|
rk = Context->dK;
|
||||||
|
|||||||
265
lib/WjCryptLib_AesCbc.c
Normal file
265
lib/WjCryptLib_AesCbc.c
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// WjCryptLib_AesCbc
|
||||||
|
//
|
||||||
|
// Implementation of AES CBC cipher.
|
||||||
|
//
|
||||||
|
// Depends on: CryptoLib_Aes
|
||||||
|
//
|
||||||
|
// AES CBC is a cipher using AES in Cipher Block Chaining mode. Encryption and decryption must be performed in
|
||||||
|
// multiples of the AES block size (128 bits).
|
||||||
|
// This implementation works on both little and big endian architectures.
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain - March 2018 waterjuice.org
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IMPORTS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "WjCryptLib_AesCbc.h"
|
||||||
|
#include "WjCryptLib_Aes.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <memory.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// MACROS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define MIN( x, y ) ( ((x)<(y))?(x):(y) )
|
||||||
|
|
||||||
|
#define STORE64H( x, y ) \
|
||||||
|
{ (y)[0] = (uint8_t)(((x)>>56)&255); (y)[1] = (uint8_t)(((x)>>48)&255); \
|
||||||
|
(y)[2] = (uint8_t)(((x)>>40)&255); (y)[3] = (uint8_t)(((x)>>32)&255); \
|
||||||
|
(y)[4] = (uint8_t)(((x)>>24)&255); (y)[5] = (uint8_t)(((x)>>16)&255); \
|
||||||
|
(y)[6] = (uint8_t)(((x)>>8)&255); (y)[7] = (uint8_t)((x)&255); }
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// INTERNAL FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// XorAesBlock
|
||||||
|
//
|
||||||
|
// Takes two source blocks (size AES_BLOCK_SIZE) and XORs them together and puts the result in first block
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static
|
||||||
|
void
|
||||||
|
XorAesBlock
|
||||||
|
(
|
||||||
|
uint8_t* Block1, // [in out]
|
||||||
|
uint8_t const* Block2 // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
for( i=0; i<AES_BLOCK_SIZE; i++ )
|
||||||
|
{
|
||||||
|
Block1[i] ^= Block2[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcInitialise
|
||||||
|
//
|
||||||
|
// Initialises an AesCbcContext with an already initialised AesContext and a IV. This function can quickly be used
|
||||||
|
// to change the IV without requiring the more lengthy processes of reinitialising an AES key.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
AesCbcInitialise
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [out]
|
||||||
|
AesContext const* InitialisedAesContext, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE] // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Setup context values
|
||||||
|
Context->Aes = *InitialisedAesContext;
|
||||||
|
memcpy( Context->PreviousCipherBlock, IV, sizeof(Context->PreviousCipherBlock) );
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcInitialiseWithKey
|
||||||
|
//
|
||||||
|
// Initialises an AesCbcContext with an AES Key and an IV. This combines the initialising an AES Context and then
|
||||||
|
// running AesCbcInitialise. 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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcInitialiseWithKey
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [out]
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE] // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
AesContext aes;
|
||||||
|
|
||||||
|
// Initialise AES Context
|
||||||
|
if( 0 != AesInitialise( &aes, Key, KeySize ) )
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now set-up AesCbcContext
|
||||||
|
AesCbcInitialise( Context, &aes, IV );
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcEncrypt
|
||||||
|
//
|
||||||
|
// Encrypts a buffer of data using an AES CBC context. The data buffer must be a multiple of 16 bytes (128 bits)
|
||||||
|
// in size. The "position" of the context will be advanced by the buffer amount. A buffer can be encrypted in one
|
||||||
|
// go or in smaller chunks at a time. The result will be the same as long as data is fed into the function in the
|
||||||
|
// same order.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for in-place encrypting.
|
||||||
|
// Returns 0 if successful, or -1 if Size is not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcEncrypt
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [in out]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t Size // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t numBlocks = Size / AES_BLOCK_SIZE;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if( 0 != Size % AES_BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
// Size not a multiple of AES block size (16 bytes).
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=0; i<numBlocks; i++ )
|
||||||
|
{
|
||||||
|
// XOR on the next block of data onto the previous cipher block
|
||||||
|
XorAesBlock( Context->PreviousCipherBlock, (uint8_t*)InBuffer + offset );
|
||||||
|
|
||||||
|
// Encrypt to make new cipher block
|
||||||
|
AesEncryptInPlace( &Context->Aes, Context->PreviousCipherBlock );
|
||||||
|
|
||||||
|
// Output cipher block
|
||||||
|
memcpy( (uint8_t*)OutBuffer + offset, Context->PreviousCipherBlock, AES_BLOCK_SIZE );
|
||||||
|
|
||||||
|
offset += AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcDecrypt
|
||||||
|
//
|
||||||
|
// Decrypts a buffer of data using an AES CBC context. The data buffer must be a multiple of 16 bytes (128 bits)
|
||||||
|
// in size. The "position" of the context will be advanced by the buffer amount.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for in-place decrypting.
|
||||||
|
// Returns 0 if successful, or -1 if Size is not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcDecrypt
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [in out]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t Size // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t numBlocks = Size / AES_BLOCK_SIZE;
|
||||||
|
uint32_t offset = 0;
|
||||||
|
uint32_t i;
|
||||||
|
uint8_t previousCipherBlock [AES_BLOCK_SIZE];
|
||||||
|
|
||||||
|
if( 0 != Size % AES_BLOCK_SIZE )
|
||||||
|
{
|
||||||
|
// Size not a multiple of AES block size (16 bytes).
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i=0; i<numBlocks; i++ )
|
||||||
|
{
|
||||||
|
// Copy previous cipher block and place current one in context
|
||||||
|
memcpy( previousCipherBlock, Context->PreviousCipherBlock, AES_BLOCK_SIZE );
|
||||||
|
memcpy( Context->PreviousCipherBlock, (uint8_t*)InBuffer + offset, AES_BLOCK_SIZE );
|
||||||
|
|
||||||
|
// Decrypt cipher block
|
||||||
|
AesDecrypt( &Context->Aes, Context->PreviousCipherBlock, (uint8_t*)OutBuffer + offset );
|
||||||
|
|
||||||
|
// XOR on previous cipher block
|
||||||
|
XorAesBlock( (uint8_t*)OutBuffer + offset, previousCipherBlock );
|
||||||
|
|
||||||
|
offset += AES_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcEncryptWithKey
|
||||||
|
//
|
||||||
|
// This function combines AesCbcInitialiseWithKey and AesCbcEncrypt. This is suitable when encrypting data in one go
|
||||||
|
// with a key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace encrypting.
|
||||||
|
// Returns 0 if successful, or -1 if invalid KeySize provided or BufferSize not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcEncryptWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE], // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
AesCbcContext context;
|
||||||
|
|
||||||
|
error = AesCbcInitialiseWithKey( &context, Key, KeySize, IV );
|
||||||
|
if( 0 == error )
|
||||||
|
{
|
||||||
|
error = AesCbcEncrypt( &context, InBuffer, OutBuffer, BufferSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcDecryptWithKey
|
||||||
|
//
|
||||||
|
// This function combines AesCbcInitialiseWithKey and AesCbcDecrypt. This is suitable when decrypting data in one go
|
||||||
|
// with a key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace decrypting.
|
||||||
|
// Returns 0 if successful, or -1 if invalid KeySize provided or BufferSize not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcDecryptWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE], // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
AesCbcContext context;
|
||||||
|
|
||||||
|
error = AesCbcInitialiseWithKey( &context, Key, KeySize, IV );
|
||||||
|
if( 0 == error )
|
||||||
|
{
|
||||||
|
error = AesCbcDecrypt( &context, InBuffer, OutBuffer, BufferSize );
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
148
lib/WjCryptLib_AesCbc.h
Normal file
148
lib/WjCryptLib_AesCbc.h
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// WjCryptLib_AesCbc
|
||||||
|
//
|
||||||
|
// Implementation of AES CBC cipher.
|
||||||
|
//
|
||||||
|
// Depends on: CryptoLib_Aes
|
||||||
|
//
|
||||||
|
// AES CBC is a cipher using AES in Cipher Block Chaining mode. Encryption and decryption must be performed in
|
||||||
|
// multiples of the AES block size (128 bits).
|
||||||
|
// This implementation works on both little and big endian architectures.
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain - March 2018 waterjuice.org
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IMPORTS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "WjCryptLib_Aes.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TYPES
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define AES_CBC_IV_SIZE AES_BLOCK_SIZE
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TYPES
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// AesCbcContext
|
||||||
|
// Do not modify the contents of this structure directly.
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
AesContext Aes;
|
||||||
|
uint8_t PreviousCipherBlock [AES_BLOCK_SIZE];
|
||||||
|
} AesCbcContext;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcInitialise
|
||||||
|
//
|
||||||
|
// Initialises an AesCbcContext with an already initialised AesContext and a IV. This function can quickly be used
|
||||||
|
// to change the IV without requiring the more lengthy processes of reinitialising an AES key.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
AesCbcInitialise
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [out]
|
||||||
|
AesContext const* InitialisedAesContext, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE] // [in]
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcInitialiseWithKey
|
||||||
|
//
|
||||||
|
// Initialises an AesCbcContext with an AES Key and an IV. This combines the initialising an AES Context and then
|
||||||
|
// running AesCbcInitialise. 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
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcInitialiseWithKey
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [out]
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE] // [in]
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcEncrypt
|
||||||
|
//
|
||||||
|
// Encrypts a buffer of data using an AES CBC context. The data buffer must be a multiple of 16 bytes (128 bits)
|
||||||
|
// in size. The "position" of the context will be advanced by the buffer amount. A buffer can be encrypted in one
|
||||||
|
// go or in smaller chunks at a time. The result will be the same as long as data is fed into the function in the
|
||||||
|
// same order.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for in-place encrypting.
|
||||||
|
// Returns 0 if successful, or -1 if Size is not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcEncrypt
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [in out]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t Size // [in]
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcDecrypt
|
||||||
|
//
|
||||||
|
// Decrypts a buffer of data using an AES CBC context. The data buffer must be a multiple of 16 bytes (128 bits)
|
||||||
|
// in size. The "position" of the context will be advanced by the buffer amount.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for in-place decrypting.
|
||||||
|
// Returns 0 if successful, or -1 if Size is not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcDecrypt
|
||||||
|
(
|
||||||
|
AesCbcContext* Context, // [in out]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t Size // [in]
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcEncryptWithKey
|
||||||
|
//
|
||||||
|
// This function combines AesCbcInitialiseWithKey and AesCbcEncrypt. This is suitable when encrypting data in one go
|
||||||
|
// with a key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace encrypting.
|
||||||
|
// Returns 0 if successful, or -1 if invalid KeySize provided or BufferSize not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcEncryptWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE], // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// AesCbcDecryptWithKey
|
||||||
|
//
|
||||||
|
// This function combines AesCbcInitialiseWithKey and AesCbcDecrypt. This is suitable when decrypting data in one go
|
||||||
|
// with a key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace decrypting.
|
||||||
|
// Returns 0 if successful, or -1 if invalid KeySize provided or BufferSize not a multiple of 16 bytes.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
AesCbcDecryptWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint8_t const IV [AES_CBC_IV_SIZE], // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
);
|
||||||
@@ -313,3 +313,23 @@ void
|
|||||||
Digest->bytes[14] = (uint8_t)( Context->d >> 16 );
|
Digest->bytes[14] = (uint8_t)( Context->d >> 16 );
|
||||||
Digest->bytes[15] = (uint8_t)( Context->d >> 24 );
|
Digest->bytes[15] = (uint8_t)( Context->d >> 24 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Md5Calculate
|
||||||
|
//
|
||||||
|
// Combines Md5Initialise, Md5Update, and Md5Finalise into one function. Calculates the MD5 hash of the buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Md5Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
MD5_HASH* Digest // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Md5Context context;
|
||||||
|
|
||||||
|
Md5Initialise( &context );
|
||||||
|
Md5Update( &context, Buffer, BufferSize );
|
||||||
|
Md5Finalise( &context, Digest );
|
||||||
|
}
|
||||||
|
|||||||
@@ -81,3 +81,16 @@ void
|
|||||||
Md5Context* Context, // [in out]
|
Md5Context* Context, // [in out]
|
||||||
MD5_HASH* Digest // [in]
|
MD5_HASH* Digest // [in]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Md5Calculate
|
||||||
|
//
|
||||||
|
// Combines Md5Initialise, Md5Update, and Md5Finalise into one function. Calculates the MD5 hash of the buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Md5Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
MD5_HASH* Digest // [in]
|
||||||
|
);
|
||||||
|
|||||||
@@ -126,3 +126,27 @@ void
|
|||||||
^ ( Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ] );
|
^ ( Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Rc4XorWithKey
|
||||||
|
//
|
||||||
|
// This function combines Rc4Initialise and Rc4Xor. This is suitable when encrypting/decrypting data in one go with a
|
||||||
|
// key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Rc4XorWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint32_t DropN, // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Rc4Context context;
|
||||||
|
|
||||||
|
Rc4Initialise( &context, Key, KeySize, DropN );
|
||||||
|
Rc4Xor( &context, InBuffer, OutBuffer, BufferSize );
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,3 +71,21 @@ void
|
|||||||
void* OutBuffer, // [out]
|
void* OutBuffer, // [out]
|
||||||
uint32_t Size // [in]
|
uint32_t Size // [in]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Rc4XorWithKey
|
||||||
|
//
|
||||||
|
// This function combines Rc4Initialise and Rc4Xor. This is suitable when encrypting/decrypting data in one go with a
|
||||||
|
// key that is not going to be reused.
|
||||||
|
// InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Rc4XorWithKey
|
||||||
|
(
|
||||||
|
uint8_t const* Key, // [in]
|
||||||
|
uint32_t KeySize, // [in]
|
||||||
|
uint32_t DropN, // [in]
|
||||||
|
void const* InBuffer, // [in]
|
||||||
|
void* OutBuffer, // [out]
|
||||||
|
uint32_t BufferSize // [in]
|
||||||
|
);
|
||||||
|
|||||||
@@ -247,3 +247,23 @@ void
|
|||||||
Digest->bytes[i] = (uint8_t)((Context->State[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
Digest->bytes[i] = (uint8_t)((Context->State[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sha1Calculate
|
||||||
|
//
|
||||||
|
// Combines Sha1Initialise, Sha1Update, and Sha1Finalise into one function. Calculates the SHA1 hash of the buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Sha1Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
SHA1_HASH* Digest // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Sha1Context context;
|
||||||
|
|
||||||
|
Sha1Initialise( &context );
|
||||||
|
Sha1Update( &context, Buffer, BufferSize );
|
||||||
|
Sha1Finalise( &context, Digest );
|
||||||
|
}
|
||||||
|
|||||||
@@ -79,3 +79,16 @@ void
|
|||||||
Sha1Context* Context, // [in out]
|
Sha1Context* Context, // [in out]
|
||||||
SHA1_HASH* Digest // [in]
|
SHA1_HASH* Digest // [in]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sha1Calculate
|
||||||
|
//
|
||||||
|
// Combines Sha1Initialise, Sha1Update, and Sha1Finalise into one function. Calculates the SHA1 hash of the buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Sha1Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
SHA1_HASH* Digest // [in]
|
||||||
|
);
|
||||||
|
|||||||
@@ -271,3 +271,24 @@ void
|
|||||||
STORE32H( Context->state[i], Digest->bytes+(4*i) );
|
STORE32H( Context->state[i], Digest->bytes+(4*i) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sha256Calculate
|
||||||
|
//
|
||||||
|
// Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
|
||||||
|
// buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Sha256Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
SHA256_HASH* Digest // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Sha256Context context;
|
||||||
|
|
||||||
|
Sha256Initialise( &context );
|
||||||
|
Sha256Update( &context, Buffer, BufferSize );
|
||||||
|
Sha256Finalise( &context, Digest );
|
||||||
|
}
|
||||||
|
|||||||
@@ -73,3 +73,17 @@ void
|
|||||||
Sha256Context* Context, // [in out]
|
Sha256Context* Context, // [in out]
|
||||||
SHA256_HASH* Digest // [out]
|
SHA256_HASH* Digest // [out]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sha256Calculate
|
||||||
|
//
|
||||||
|
// Combines Sha256Initialise, Sha256Update, and Sha256Finalise into one function. Calculates the SHA256 hash of the
|
||||||
|
// buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Sha256Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
SHA256_HASH* Digest // [in]
|
||||||
|
);
|
||||||
|
|||||||
@@ -273,3 +273,24 @@ void
|
|||||||
STORE64H( Context->state[i], Digest->bytes+(8*i) );
|
STORE64H( Context->state[i], Digest->bytes+(8*i) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Sha512Calculate
|
||||||
|
//
|
||||||
|
// Combines Sha512Initialise, Sha512Update, and Sha512Finalise into one function. Calculates the SHA512 hash of the
|
||||||
|
// buffer.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
Sha512Calculate
|
||||||
|
(
|
||||||
|
void const* Buffer, // [in]
|
||||||
|
uint32_t BufferSize, // [in]
|
||||||
|
SHA512_HASH* Digest // [in]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Sha512Context context;
|
||||||
|
|
||||||
|
Sha512Initialise( &context );
|
||||||
|
Sha512Update( &context, Buffer, BufferSize );
|
||||||
|
Sha512Finalise( &context, Digest );
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// AesBlock
|
// AesBlock
|
||||||
//
|
//
|
||||||
// Encrypts or Decrypts a single 128 bit block specified on the command line as a hex string. Key is also on
|
// Encrypts or Decrypts a single 128 bit block specified on the command line as a hex string. Key is also on
|
||||||
// command line and may be 128, 192, or 256 bits in size.
|
// command line and may be 128, 192, or 256 bits in size.
|
||||||
//
|
//
|
||||||
// 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 - November 2017 waterjuice.org
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define StringCaseInsensitiveCmp stricmp
|
#define StringCaseInsensitiveCmp stricmp
|
||||||
#else
|
#else
|
||||||
#define StringCaseInsensitiveCmp strcasecmp
|
#define StringCaseInsensitiveCmp strcasecmp
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
// This function ignores any character that isn't a hex character.
|
// This function ignores any character that isn't a hex character.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
ReadHexData
|
ReadHexData
|
||||||
(
|
(
|
||||||
char const* HexString,
|
char const* HexString,
|
||||||
@@ -116,7 +116,7 @@ int
|
|||||||
" AesBlock [-D] <KeyHex> <BlockHex>\n" );
|
" AesBlock [-D] <KeyHex> <BlockHex>\n" );
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for( i=1; i<(uint32_t)ArgC; i++ )
|
for( i=1; i<(uint32_t)ArgC; i++ )
|
||||||
{
|
{
|
||||||
if( 0 == StringCaseInsensitiveCmp( ArgV[i], "-d" ) )
|
if( 0 == StringCaseInsensitiveCmp( ArgV[i], "-d" ) )
|
||||||
@@ -132,7 +132,7 @@ int
|
|||||||
printf( "Invalid syntax\n" );
|
printf( "Invalid syntax\n" );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadHexData( ArgV[i], bufferPtr, bufferSizePtr );
|
ReadHexData( ArgV[i], bufferPtr, bufferSizePtr );
|
||||||
paramIndex += 1;
|
paramIndex += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
// This function ignores any character that isn't a hex character.
|
// This function ignores any character that isn't a hex character.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
ReadHexData
|
ReadHexData
|
||||||
(
|
(
|
||||||
char const* HexString, // [in]
|
char const* HexString, // [in]
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
// This function ignores any character that isn't a hex character.
|
// This function ignores any character that isn't a hex character.
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
ReadHexData
|
ReadHexData
|
||||||
(
|
(
|
||||||
char const* HexString, // [in]
|
char const* HexString, // [in]
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ add_executable( ${MODULE_NAME}
|
|||||||
WjCryptLibTest_Rc4.h
|
WjCryptLibTest_Rc4.h
|
||||||
WjCryptLibTest_Aes.c
|
WjCryptLibTest_Aes.c
|
||||||
WjCryptLibTest_Aes.h
|
WjCryptLibTest_Aes.h
|
||||||
|
WjCryptLibTest_AesCbc.c
|
||||||
|
WjCryptLibTest_AesCbc.h
|
||||||
WjCryptLibTest_AesCtr.c
|
WjCryptLibTest_AesCtr.c
|
||||||
WjCryptLibTest_AesCtr.h
|
WjCryptLibTest_AesCtr.h
|
||||||
WjCryptLibTest_AesOfb.c
|
WjCryptLibTest_AesOfb.c
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "WjCryptLibTest_Aes.h"
|
#include "WjCryptLibTest_Aes.h"
|
||||||
|
#include "WjCryptLibTest_AesCbc.h"
|
||||||
#include "WjCryptLibTest_AesCtr.h"
|
#include "WjCryptLibTest_AesCtr.h"
|
||||||
#include "WjCryptLibTest_AesOfb.h"
|
#include "WjCryptLibTest_AesOfb.h"
|
||||||
#include "WjCryptLibTest_Hashes.h"
|
#include "WjCryptLibTest_Hashes.h"
|
||||||
@@ -55,6 +56,10 @@ int
|
|||||||
if( !success ) { allSuccess = false; }
|
if( !success ) { allSuccess = false; }
|
||||||
printf( "Test AES - %s\n", success?"Pass":"Fail" );
|
printf( "Test AES - %s\n", success?"Pass":"Fail" );
|
||||||
|
|
||||||
|
success = TestAesCbc( );
|
||||||
|
if( !success ) { allSuccess = false; }
|
||||||
|
printf( "Test AES CBC - %s\n", success?"Pass":"Fail" );
|
||||||
|
|
||||||
success = TestAesCtr( );
|
success = TestAesCtr( );
|
||||||
if( !success ) { allSuccess = false; }
|
if( !success ) { allSuccess = false; }
|
||||||
printf( "Test AES CTR - %s\n", success?"Pass":"Fail" );
|
printf( "Test AES CTR - %s\n", success?"Pass":"Fail" );
|
||||||
|
|||||||
299
projects/WjCryptLibTest/WjCryptLibTest_AesCbc.c
Normal file
299
projects/WjCryptLibTest/WjCryptLibTest_AesCbc.c
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// WjCryptLibTest_AesCbc
|
||||||
|
//
|
||||||
|
// Tests the cryptography functions against known test vectors to verify algorithms are correct.
|
||||||
|
// Tests the following:
|
||||||
|
// AES CBC
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain - March 2018 waterjuice.org
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IMPORTS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "WjCryptLib_AesCbc.h"
|
||||||
|
#include "WjCryptLib_Sha1.h"
|
||||||
|
#include "WjCryptLib_Rc4.h"
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// MACROS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define MIN( x, y ) ( ((x)<(y))?(x):(y) )
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TYPES
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define MAX_PLAINTEXT_SIZE 100
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char* KeyHex;
|
||||||
|
char* IvHex;
|
||||||
|
char* CipherTextHex;
|
||||||
|
} TestVector;
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// GLOBALS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// These test vectors were created using openssl. Using the following commands:
|
||||||
|
// (Note: As CBC is not a stream cipher, the input is created using an RC4 stream generated from a key of 0)
|
||||||
|
// (Also note: openssl outputs an additional block of data due to some padding. We ignore this)
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-128-cbc -K 00000000000000000000000000000000 -iv 00000000000000000000000000000000 | head -c 64 | xxd -p -c 64
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-128-cbc -K 0102030405060708a1a2a3a4a5a6a7a8 -iv 00000000000000000000000000000000 | head -c 64 | xxd -p -c 64
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-128-cbc -K 00000000000000000000000000000000 -iv b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8 | head -c 64 | xxd -p -c 64
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-128-cbc -K 0102030405060708a1a2a3a4a5a6a7a8 -iv b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8 | head -c 64 | xxd -p -c 64
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-192-cbc -K 0102030405060708a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8 -iv c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8 | head -c 64 | xxd -p -c 64
|
||||||
|
// > dd if=/dev/zero iflag=count_bytes count=64 status=none | openssl enc -rc4 -K 0 | openssl enc -aes-256-cbc -K 0102030405060708a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8 -iv d1d2d3d4d5d6d7d8e1e2e3e4e5e6e7e8 | head -c 64 | xxd -p -c 64
|
||||||
|
static TestVector gTestVectors [] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"c2af41ffe8b9f1b295d68038e3e8ed3f70b72b168cd3d402ccbf0bb4fa12561fc703951c91d8ce81c5643155b5db1d34eb7b36c2cc4715c03ea24944bb5c5625"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0102030405060708a1a2a3a4a5a6a7a8",
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"638198794af111670d5d7a7e13851484f71831108a5a134a9329787ad73379eb449e5068150233c4f0ae8c08d86708bc09724efaad3e6936e03c58f83f2abf3f"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"00000000000000000000000000000000",
|
||||||
|
"b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8",
|
||||||
|
"c696d1b757d5b4ee2069d1c50b1e5569aa931d0ecc058a5adce099e2f844153db0cf0884102720e42ab58efe449faba054edd92c4006fffbd9b0aec297b852ae"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0102030405060708a1a2a3a4a5a6a7a8",
|
||||||
|
"b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8",
|
||||||
|
"a3c80c1c5ee817ad5faf31c6610e7895f480bdc9055362f0a7148b47b1dc5f11d041d94026266625cd6b512451a539ee9f3820667a84ace6cfbbe7edf746a14d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0102030405060708a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8",
|
||||||
|
"c1c2c3c4c5c6c7c8d1d2d3d4d5d6d7d8",
|
||||||
|
"93928e29c82e5536bc5942c35bbbd4d7a69f0a7daa35c77ecb13b3ac2c46c473cb608f403982d8401385fd7fe66a1e329aa0f90a50180fb73b36e98cb7214736"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0102030405060708a1a2a3a4a5a6a7a8b1b2b3b4b5b6b7b8c1c2c3c4c5c6c7c8",
|
||||||
|
"d1d2d3d4d5d6d7d8e1e2e3e4e5e6e7e8",
|
||||||
|
"2b559a644b62f1540c4ff9c50140fadedeefd49de9827dfbc8be8e4f7e2ac4ea746c8432d184059f62facaf765d90eadb7bdecac5e23bdc23f4026cd32d18ae2"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_TEST_VECTORS ( sizeof(gTestVectors) / sizeof(gTestVectors[0]) )
|
||||||
|
#define TEST_VECTOR_OUTPUT_SIZE 48
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// INTERNAL FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// HexToBytes
|
||||||
|
//
|
||||||
|
// Reads a string as hex and places it in Data. This function will output as many bytes as represented in the input
|
||||||
|
// string, it will not check the output buffer length. On return *pDataSize will be number of bytes read.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static
|
||||||
|
void
|
||||||
|
HexToBytes
|
||||||
|
(
|
||||||
|
char const* HexString, // [in]
|
||||||
|
uint8_t* Data, // [out]
|
||||||
|
uint32_t* pDataSize // [out optional]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
char holdingBuffer [3] = {0};
|
||||||
|
unsigned hexToNumber;
|
||||||
|
uint32_t outputIndex = 0;
|
||||||
|
|
||||||
|
for( i=0; i<strlen(HexString)/2; i++ )
|
||||||
|
{
|
||||||
|
holdingBuffer[0] = HexString[i*2 + 0];
|
||||||
|
holdingBuffer[1] = HexString[i*2 + 1];
|
||||||
|
sscanf( holdingBuffer, "%x", &hexToNumber );
|
||||||
|
Data[i] = (uint8_t) hexToNumber;
|
||||||
|
outputIndex += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( NULL != pDataSize )
|
||||||
|
{
|
||||||
|
*pDataSize = outputIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TestVectors
|
||||||
|
//
|
||||||
|
// Tests AES CBC against fixed test vectors
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
TestVectors
|
||||||
|
(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
uint32_t vectorIndex;
|
||||||
|
uint8_t key [AES_KEY_SIZE_256];
|
||||||
|
uint32_t keySize = 0;
|
||||||
|
uint8_t iv [AES_CBC_IV_SIZE];
|
||||||
|
uint8_t vector [TEST_VECTOR_OUTPUT_SIZE];
|
||||||
|
uint8_t aesCbcOutput [TEST_VECTOR_OUTPUT_SIZE];
|
||||||
|
uint8_t decryptBuffer [TEST_VECTOR_OUTPUT_SIZE];
|
||||||
|
uint8_t inputBuffer [TEST_VECTOR_OUTPUT_SIZE] = {0};
|
||||||
|
uint8_t rc4Key = 0;
|
||||||
|
|
||||||
|
// We can't encrypt just a zero buffer or we will end up with same result as OFB. As this is not a stream
|
||||||
|
// cipher we need to change the input. These test vectors were generated by using an RC4 stream as input.
|
||||||
|
// The RC4 stream is created by using a key of 0.
|
||||||
|
Rc4XorWithKey( &rc4Key, sizeof(rc4Key), 0, inputBuffer, inputBuffer, sizeof(inputBuffer) );
|
||||||
|
|
||||||
|
for( vectorIndex=0; vectorIndex<NUM_TEST_VECTORS; vectorIndex++ )
|
||||||
|
{
|
||||||
|
HexToBytes( gTestVectors[vectorIndex].KeyHex, key, &keySize );
|
||||||
|
HexToBytes( gTestVectors[vectorIndex].IvHex, iv, NULL );
|
||||||
|
HexToBytes( gTestVectors[vectorIndex].CipherTextHex, vector, NULL );
|
||||||
|
|
||||||
|
AesCbcEncryptWithKey( key, keySize, iv, inputBuffer, aesCbcOutput, TEST_VECTOR_OUTPUT_SIZE );
|
||||||
|
if( 0 != memcmp( aesCbcOutput, vector, TEST_VECTOR_OUTPUT_SIZE ) )
|
||||||
|
{
|
||||||
|
printf( "Test vector (index:%u) failed\n", vectorIndex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
AesCbcDecryptWithKey( key, keySize, iv, aesCbcOutput, decryptBuffer, TEST_VECTOR_OUTPUT_SIZE );
|
||||||
|
if( 0 != memcmp( decryptBuffer, inputBuffer, TEST_VECTOR_OUTPUT_SIZE ) )
|
||||||
|
{
|
||||||
|
printf( "Test vector (index:%u) failed decrypt\n", vectorIndex );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TestLargeVector
|
||||||
|
//
|
||||||
|
// Tests AES OFB 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 -rc4 -K 0 | openssl enc -aes-128-cbc -K 00001111222233334444555566667777 -iv 88889999aaaabbbbccccddddeeeeffff | head -c 1000000 | openssl sha1
|
||||||
|
//(stdin)= 859463d3f0f27e67d37f05603f19b9d5c71c2059
|
||||||
|
|
||||||
|
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\xcc\xcc\xdd\xdd\xee\xee\xff\xff";
|
||||||
|
uint8_t const* sha1Hash = (uint8_t const*)"\x85\x94\x63\xd3\xf0\xf2\x7e\x67\xd3\x7f\x05\x60\x3f\x19\xb9\xd5\xc7\x1c\x20\x59";
|
||||||
|
uint32_t const numBytesToGenerate = 1000000;
|
||||||
|
uint8_t const rc4Key = 0;
|
||||||
|
|
||||||
|
uint8_t* buffer = malloc( numBytesToGenerate );
|
||||||
|
uint8_t* buffer2 = malloc( numBytesToGenerate );
|
||||||
|
uint32_t amountLeft = numBytesToGenerate;
|
||||||
|
uint32_t chunkSize;
|
||||||
|
Sha1Context sha1Context;
|
||||||
|
AesCbcContext aesCbcContext;
|
||||||
|
SHA1_HASH calcSha1;
|
||||||
|
uint32_t offset;
|
||||||
|
SHA1_HASH initialInputSha1;
|
||||||
|
|
||||||
|
// Encrypt in one go first.
|
||||||
|
// Generate the Rc4 stream to encrypt
|
||||||
|
memset( buffer, 0, numBytesToGenerate );
|
||||||
|
Rc4XorWithKey( &rc4Key, 1, 0, buffer, buffer, numBytesToGenerate );
|
||||||
|
Sha1Calculate( buffer, numBytesToGenerate, &initialInputSha1 );
|
||||||
|
|
||||||
|
AesCbcEncryptWithKey( key, AES_KEY_SIZE_128, iv, buffer, buffer2, numBytesToGenerate );
|
||||||
|
|
||||||
|
Sha1Initialise( &sha1Context );
|
||||||
|
Sha1Update( &sha1Context, buffer2, numBytesToGenerate );
|
||||||
|
Sha1Finalise( &sha1Context, &calcSha1 );
|
||||||
|
|
||||||
|
if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) )
|
||||||
|
{
|
||||||
|
printf( "Large test vector failed (1)\n" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now decrypt the buffer to verify it goes back to the original.
|
||||||
|
AesCbcDecryptWithKey( key, AES_KEY_SIZE_128, iv, buffer, buffer2, numBytesToGenerate );
|
||||||
|
Sha1Calculate( buffer, numBytesToGenerate, &calcSha1 );
|
||||||
|
|
||||||
|
if( 0 != memcmp( &calcSha1, &initialInputSha1, SHA1_HASH_SIZE ) )
|
||||||
|
{
|
||||||
|
printf( "Large test vector failed decrypting\n" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( buffer, 0, numBytesToGenerate );
|
||||||
|
|
||||||
|
// Now encrypt in smaller pieces (10000 bytes at a time)
|
||||||
|
Sha1Initialise( &sha1Context );
|
||||||
|
AesCbcInitialiseWithKey( &aesCbcContext, key, AES_KEY_SIZE_128, iv );
|
||||||
|
|
||||||
|
memset( buffer, 0, numBytesToGenerate );
|
||||||
|
Rc4XorWithKey( &rc4Key, 1, 0, buffer, buffer, numBytesToGenerate );
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
while( amountLeft > 0 )
|
||||||
|
{
|
||||||
|
chunkSize = MIN( amountLeft, 10000 );
|
||||||
|
AesCbcEncrypt( &aesCbcContext, buffer+offset, buffer+offset, chunkSize );
|
||||||
|
Sha1Update( &sha1Context, buffer+offset, chunkSize );
|
||||||
|
amountLeft -= chunkSize;
|
||||||
|
offset += chunkSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sha1Finalise( &sha1Context, &calcSha1 );
|
||||||
|
|
||||||
|
if( 0 != memcmp( &calcSha1, sha1Hash, SHA1_HASH_SIZE ) )
|
||||||
|
{
|
||||||
|
printf( "Large test vector failed (2)\n" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PUBLIC FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TestAesOfb
|
||||||
|
//
|
||||||
|
// Test AES CBC algorithm
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool
|
||||||
|
TestAesCbc
|
||||||
|
(
|
||||||
|
void
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool totalSuccess = true;
|
||||||
|
bool success;
|
||||||
|
|
||||||
|
success = TestVectors( );
|
||||||
|
if( !success ) { totalSuccess = false; }
|
||||||
|
|
||||||
|
success = TestLargeVector( );
|
||||||
|
if( !success ) { totalSuccess = false; }
|
||||||
|
|
||||||
|
return totalSuccess;
|
||||||
|
}
|
||||||
30
projects/WjCryptLibTest/WjCryptLibTest_AesCbc.h
Normal file
30
projects/WjCryptLibTest/WjCryptLibTest_AesCbc.h
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// WjCryptLibTest_AesCbc
|
||||||
|
//
|
||||||
|
// Tests the cryptography functions against known test vectors to verify algorithms are correct.
|
||||||
|
// Tests the following:
|
||||||
|
// AES CBC
|
||||||
|
//
|
||||||
|
// This is free and unencumbered software released into the public domain - March 2018 waterjuice.org
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// IMPORTS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// EXPORTED FUNCTIONS
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// TestAesCbc
|
||||||
|
//
|
||||||
|
// Test AES CBC algorithm
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
bool
|
||||||
|
TestAesCbc
|
||||||
|
(
|
||||||
|
void
|
||||||
|
);
|
||||||
@@ -233,7 +233,6 @@ bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// TestStreamConsistency
|
// TestStreamConsistency
|
||||||
//
|
//
|
||||||
@@ -327,7 +326,7 @@ bool
|
|||||||
uint8_t const iv [AES_CTR_IV_SIZE] = { 5,5,5,5,6,6,6,6 };
|
uint8_t const iv [AES_CTR_IV_SIZE] = { 5,5,5,5,6,6,6,6 };
|
||||||
uint64_t const positionIndex = 0x1020304050607080ULL;
|
uint64_t const positionIndex = 0x1020304050607080ULL;
|
||||||
uint8_t output [256 / 8] = {0};
|
uint8_t output [256 / 8] = {0};
|
||||||
uint8_t const vector [256 / 8] =
|
uint8_t const vector [256 / 8] =
|
||||||
{ 0x17, 0x07, 0x27, 0x7b, 0x9e, 0x51, 0xdf, 0x5b,
|
{ 0x17, 0x07, 0x27, 0x7b, 0x9e, 0x51, 0xdf, 0x5b,
|
||||||
0x23, 0xbe, 0xa1, 0xce, 0xc9, 0x40, 0x49, 0xfc,
|
0x23, 0xbe, 0xa1, 0xce, 0xc9, 0x40, 0x49, 0xfc,
|
||||||
0xf8, 0x8f, 0x45, 0xd1, 0xf6, 0x68, 0x28, 0x54,
|
0xf8, 0x8f, 0x45, 0xd1, 0xf6, 0x68, 0x28, 0x54,
|
||||||
|
|||||||
@@ -232,7 +232,6 @@ bool
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// TestStreamConsistency
|
// TestStreamConsistency
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user