mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 22:28:36 -07:00
Add e-subghz chat app (by @twisted-pear)
This commit is contained in:
483
applications/external/esubghz_chat/crypto/aes.c
vendored
Normal file
483
applications/external/esubghz_chat/crypto/aes.c
vendored
Normal file
@@ -0,0 +1,483 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of the AES Rijndael
|
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
|
||||
* of this work was correctness & accuracy. It is written in 'C' without any
|
||||
* particular focus upon optimization or speed. It should be endian (memory
|
||||
* byte order) neutral since the few places that care are handled explicitly.
|
||||
*
|
||||
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
static int aes_tables_inited = 0; // run-once flag for performing key
|
||||
// expasion table generation (see below)
|
||||
/*
|
||||
* The following static local tables must be filled-in before the first use of
|
||||
* the GCM or AES ciphers. They are used for the AES key expansion/scheduling
|
||||
* and once built are read-only and thread safe. The "gcm_initialize" function
|
||||
* must be called once during system initialization to populate these arrays
|
||||
* for subsequent use by the AES key scheduler. If they have not been built
|
||||
* before attempted use, an error will be returned to the caller.
|
||||
*
|
||||
* NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since
|
||||
* GCM uses AES in counter-mode, where the AES cipher output is XORed with
|
||||
* the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
|
||||
* decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
|
||||
*/
|
||||
// We always need our forward tables
|
||||
static uchar FSb[256]; // Forward substitution box (FSb)
|
||||
static uint32_t FT0[256]; // Forward key schedule assembly tables
|
||||
static uint32_t FT1[256];
|
||||
static uint32_t FT2[256];
|
||||
static uint32_t FT3[256];
|
||||
|
||||
#if AES_DECRYPTION // We ONLY need reverse for decryption
|
||||
static uchar RSb[256]; // Reverse substitution box (RSb)
|
||||
static uint32_t RT0[256]; // Reverse key schedule assembly tables
|
||||
static uint32_t RT1[256];
|
||||
static uint32_t RT2[256];
|
||||
static uint32_t RT3[256];
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
static uint32_t RCON[10]; // AES round constants
|
||||
|
||||
/*
|
||||
* Platform Endianness Neutralizing Load and Store Macro definitions
|
||||
* AES wants platform-neutral Little Endian (LE) byte ordering
|
||||
*/
|
||||
#define GET_UINT32_LE(n,b,i) { \
|
||||
(n) = ( (uint32_t) (b)[(i) ] ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] << 24 ); }
|
||||
|
||||
#define PUT_UINT32_LE(n,b,i) { \
|
||||
(b)[(i) ] = (uchar) ( (n) ); \
|
||||
(b)[(i) + 1] = (uchar) ( (n) >> 8 ); \
|
||||
(b)[(i) + 2] = (uchar) ( (n) >> 16 ); \
|
||||
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
|
||||
|
||||
/*
|
||||
* AES forward and reverse encryption round processing macros
|
||||
*/
|
||||
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
|
||||
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
|
||||
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
|
||||
FT3[ ( Y3 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
|
||||
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
|
||||
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
|
||||
FT3[ ( Y0 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
|
||||
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
|
||||
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
|
||||
FT3[ ( Y1 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
|
||||
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
|
||||
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
|
||||
FT3[ ( Y2 >> 24 ) & 0xFF ]; \
|
||||
}
|
||||
|
||||
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
|
||||
{ \
|
||||
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
|
||||
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
|
||||
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
|
||||
RT3[ ( Y1 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
|
||||
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
|
||||
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
|
||||
RT3[ ( Y2 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
|
||||
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
|
||||
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
|
||||
RT3[ ( Y3 >> 24 ) & 0xFF ]; \
|
||||
\
|
||||
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
|
||||
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
|
||||
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
|
||||
RT3[ ( Y0 >> 24 ) & 0xFF ]; \
|
||||
}
|
||||
|
||||
/*
|
||||
* These macros improve the readability of the key
|
||||
* generation initialization code by collapsing
|
||||
* repetitive common operations into logical pieces.
|
||||
*/
|
||||
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
|
||||
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
|
||||
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
|
||||
#define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
|
||||
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \
|
||||
*RK++ = *SK++; *RK++ = *SK++; }
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* AES_INIT_KEYGEN_TABLES
|
||||
*
|
||||
* Fills the AES key expansion tables allocated above with their static
|
||||
* data. This is not "per key" data, but static system-wide read-only
|
||||
* table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once
|
||||
* at system initialization to setup the tables for all subsequent use.
|
||||
*
|
||||
******************************************************************************/
|
||||
void aes_init_keygen_tables( void )
|
||||
{
|
||||
int i, x, y, z; // general purpose iteration and computation locals
|
||||
int pow[256];
|
||||
int log[256];
|
||||
|
||||
if (aes_tables_inited) return;
|
||||
|
||||
// fill the 'pow' and 'log' tables over GF(2^8)
|
||||
for( i = 0, x = 1; i < 256; i++ ) {
|
||||
pow[i] = x;
|
||||
log[x] = i;
|
||||
x = ( x ^ XTIME( x ) ) & 0xFF;
|
||||
}
|
||||
// compute the round constants
|
||||
for( i = 0, x = 1; i < 10; i++ ) {
|
||||
RCON[i] = (uint32_t) x;
|
||||
x = XTIME( x ) & 0xFF;
|
||||
}
|
||||
// fill the forward and reverse substitution boxes
|
||||
FSb[0x00] = 0x63;
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
RSb[0x63] = 0x00;
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
for( i = 1; i < 256; i++ ) {
|
||||
x = y = pow[255 - log[i]];
|
||||
MIX(x,y);
|
||||
MIX(x,y);
|
||||
MIX(x,y);
|
||||
MIX(x,y);
|
||||
FSb[i] = (uchar) ( x ^= 0x63 );
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
RSb[x] = (uchar) i;
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
}
|
||||
// generate the forward and reverse key expansion tables
|
||||
for( i = 0; i < 256; i++ ) {
|
||||
x = FSb[i];
|
||||
y = XTIME( x ) & 0xFF;
|
||||
z = ( y ^ x ) & 0xFF;
|
||||
|
||||
FT0[i] = ( (uint32_t) y ) ^ ( (uint32_t) x << 8 ) ^
|
||||
( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 );
|
||||
|
||||
FT1[i] = ROTL8( FT0[i] );
|
||||
FT2[i] = ROTL8( FT1[i] );
|
||||
FT3[i] = ROTL8( FT2[i] );
|
||||
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
x = RSb[i];
|
||||
|
||||
RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
|
||||
( (uint32_t) MUL( 0x09, x ) << 8 ) ^
|
||||
( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
|
||||
( (uint32_t) MUL( 0x0B, x ) << 24 );
|
||||
|
||||
RT1[i] = ROTL8( RT0[i] );
|
||||
RT2[i] = ROTL8( RT1[i] );
|
||||
RT3[i] = ROTL8( RT2[i] );
|
||||
#endif /* AES_DECRYPTION */
|
||||
}
|
||||
aes_tables_inited = 1; // flag that the tables have been generated
|
||||
} // to permit subsequent use of the AES cipher
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* AES_SET_ENCRYPTION_KEY
|
||||
*
|
||||
* This is called by 'aes_setkey' when we're establishing a key for
|
||||
* subsequent encryption. We give it a pointer to the encryption
|
||||
* context, a pointer to the key, and the key's length in bytes.
|
||||
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_set_encryption_key( aes_context *ctx,
|
||||
const uchar *key,
|
||||
uint keysize )
|
||||
{
|
||||
uint i; // general purpose iteration local
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
|
||||
for( i = 0; i < (keysize >> 2); i++ ) {
|
||||
GET_UINT32_LE( RK[i], key, i << 2 );
|
||||
}
|
||||
|
||||
switch( ctx->rounds )
|
||||
{
|
||||
case 10:
|
||||
for( i = 0; i < 10; i++, RK += 4 ) {
|
||||
RK[4] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[5] = RK[1] ^ RK[4];
|
||||
RK[6] = RK[2] ^ RK[5];
|
||||
RK[7] = RK[3] ^ RK[6];
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
for( i = 0; i < 8; i++, RK += 6 ) {
|
||||
RK[6] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[7] = RK[1] ^ RK[6];
|
||||
RK[8] = RK[2] ^ RK[7];
|
||||
RK[9] = RK[3] ^ RK[8];
|
||||
RK[10] = RK[4] ^ RK[9];
|
||||
RK[11] = RK[5] ^ RK[10];
|
||||
}
|
||||
break;
|
||||
|
||||
case 14:
|
||||
for( i = 0; i < 7; i++, RK += 8 ) {
|
||||
RK[8] = RK[0] ^ RCON[i] ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
|
||||
|
||||
RK[9] = RK[1] ^ RK[8];
|
||||
RK[10] = RK[2] ^ RK[9];
|
||||
RK[11] = RK[3] ^ RK[10];
|
||||
|
||||
RK[12] = RK[4] ^
|
||||
( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
RK[13] = RK[5] ^ RK[12];
|
||||
RK[14] = RK[6] ^ RK[13];
|
||||
RK[15] = RK[7] ^ RK[14];
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* AES_SET_DECRYPTION_KEY
|
||||
*
|
||||
* This is called by 'aes_setkey' when we're establishing a
|
||||
* key for subsequent decryption. We give it a pointer to
|
||||
* the encryption context, a pointer to the key, and the key's
|
||||
* length in bits. Valid lengths are: 128, 192, or 256 bits.
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_set_decryption_key( aes_context *ctx,
|
||||
const uchar *key,
|
||||
uint keysize )
|
||||
{
|
||||
int i, j;
|
||||
aes_context cty; // a calling aes context for set_encryption_key
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
uint32_t *SK;
|
||||
int ret;
|
||||
|
||||
cty.rounds = ctx->rounds; // initialize our local aes context
|
||||
cty.rk = cty.buf; // round count and key buf pointer
|
||||
|
||||
if (( ret = aes_set_encryption_key( &cty, key, keysize )) != 0 )
|
||||
return( ret );
|
||||
|
||||
SK = cty.rk + cty.rounds * 4;
|
||||
|
||||
CPY128 // copy a 128-bit block from *SK to *RK
|
||||
|
||||
for( i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8 ) {
|
||||
for( j = 0; j < 4; j++, SK++ ) {
|
||||
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
|
||||
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
|
||||
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
|
||||
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
|
||||
}
|
||||
}
|
||||
CPY128 // copy a 128-bit block from *SK to *RK
|
||||
memset( &cty, 0, sizeof( aes_context ) ); // clear local aes context
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* AES_SETKEY
|
||||
*
|
||||
* Invoked to establish the key schedule for subsequent encryption/decryption
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_setkey( aes_context *ctx, // AES context provided by our caller
|
||||
int mode, // ENCRYPT or DECRYPT flag
|
||||
const uchar *key, // pointer to the key
|
||||
uint keysize ) // key length in bytes
|
||||
{
|
||||
// since table initialization is not thread safe, we could either add
|
||||
// system-specific mutexes and init the AES key generation tables on
|
||||
// demand, or ask the developer to simply call "gcm_initialize" once during
|
||||
// application startup before threading begins. That's what we choose.
|
||||
if( !aes_tables_inited ) return ( -1 ); // fail the call when not inited.
|
||||
|
||||
ctx->mode = mode; // capture the key type we're creating
|
||||
ctx->rk = ctx->buf; // initialize our round key pointer
|
||||
|
||||
switch( keysize ) // set the rounds count based upon the keysize
|
||||
{
|
||||
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
|
||||
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
|
||||
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
|
||||
default: return(-1);
|
||||
}
|
||||
|
||||
#if AES_DECRYPTION
|
||||
if( mode == DECRYPT ) // expand our key for encryption or decryption
|
||||
return( aes_set_decryption_key( ctx, key, keysize ) );
|
||||
else /* ENCRYPT */
|
||||
#endif /* AES_DECRYPTION */
|
||||
return( aes_set_encryption_key( ctx, key, keysize ) );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* AES_CIPHER
|
||||
*
|
||||
* Perform AES encryption and decryption.
|
||||
* The AES context will have been setup with the encryption mode
|
||||
* and all keying information appropriate for the task.
|
||||
*
|
||||
******************************************************************************/
|
||||
int aes_cipher( aes_context *ctx,
|
||||
const uchar input[16],
|
||||
uchar output[16] )
|
||||
{
|
||||
int i;
|
||||
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
||||
|
||||
RK = ctx->rk;
|
||||
|
||||
GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; // load our 128-bit
|
||||
GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; // input buffer in a storage
|
||||
GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; // memory endian-neutral way
|
||||
GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
|
||||
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
|
||||
if( ctx->mode == DECRYPT )
|
||||
{
|
||||
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
|
||||
{
|
||||
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
||||
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
|
||||
}
|
||||
|
||||
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
||||
|
||||
X0 = *RK++ ^ \
|
||||
( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
|
||||
( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X1 = *RK++ ^ \
|
||||
( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
|
||||
( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X2 = *RK++ ^ \
|
||||
( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
|
||||
( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X3 = *RK++ ^ \
|
||||
( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
|
||||
( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
|
||||
}
|
||||
else /* ENCRYPT */
|
||||
{
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
|
||||
{
|
||||
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
||||
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
|
||||
}
|
||||
|
||||
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
|
||||
|
||||
X0 = *RK++ ^ \
|
||||
( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X1 = *RK++ ^ \
|
||||
( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X2 = *RK++ ^ \
|
||||
( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
X3 = *RK++ ^ \
|
||||
( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
|
||||
( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
|
||||
( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
|
||||
( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
|
||||
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
}
|
||||
#endif /* AES_DECRYPTION */
|
||||
|
||||
PUT_UINT32_LE( X0, output, 0 );
|
||||
PUT_UINT32_LE( X1, output, 4 );
|
||||
PUT_UINT32_LE( X2, output, 8 );
|
||||
PUT_UINT32_LE( X3, output, 12 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
/* end of aes.c */
|
||||
81
applications/external/esubghz_chat/crypto/aes.h
vendored
Normal file
81
applications/external/esubghz_chat/crypto/aes.h
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of the AES Rijndael
|
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
|
||||
* of this work was correctness & accuracy. It is written in 'C' without any
|
||||
* particular focus upon optimization or speed. It should be endian (memory
|
||||
* byte order) neutral since the few places that care are handled explicitly.
|
||||
*
|
||||
* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef AES_HEADER
|
||||
#define AES_HEADER
|
||||
|
||||
/******************************************************************************/
|
||||
#define AES_DECRYPTION 0 // whether AES decryption is supported
|
||||
/******************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define ENCRYPT 1 // specify whether we're encrypting
|
||||
#define DECRYPT 0 // or decrypting
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
typedef UINT32 uint32_t;
|
||||
#else
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
typedef unsigned char uchar; // add some convienent shorter types
|
||||
typedef unsigned int uint;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use
|
||||
******************************************************************************/
|
||||
void aes_init_keygen_tables( void );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CONTEXT : cipher context / holds inter-call data
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // 1 for Encryption, 0 for Decryption
|
||||
int rounds; // keysize-based rounds count
|
||||
uint32_t *rk; // pointer to current round key
|
||||
uint32_t buf[68]; // key expansion buffer
|
||||
} aes_context;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* AES_SETKEY : called to expand the key for encryption or decryption
|
||||
******************************************************************************/
|
||||
int aes_setkey( aes_context *ctx, // pointer to context
|
||||
int mode, // 1 or 0 for Encrypt/Decrypt
|
||||
const uchar *key, // AES input key
|
||||
uint keysize ); // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
// returns 0 for success
|
||||
|
||||
/******************************************************************************
|
||||
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data
|
||||
******************************************************************************/
|
||||
int aes_cipher( aes_context *ctx, // pointer to context
|
||||
const uchar input[16], // 128-bit block to en/decipher
|
||||
uchar output[16] ); // 128-bit output result block
|
||||
// returns 0 for success
|
||||
|
||||
#endif /* AES_HEADER */
|
||||
511
applications/external/esubghz_chat/crypto/gcm.c
vendored
Normal file
511
applications/external/esubghz_chat/crypto/gcm.c
vendored
Normal file
@@ -0,0 +1,511 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of AES-GCM authenticated
|
||||
* encryption. The focus of this work was correctness & accuracy. It is written
|
||||
* in straight 'C' without any particular focus upon optimization or speed. It
|
||||
* should be endian (memory byte order) neutral since the few places that care
|
||||
* are handled explicitly.
|
||||
*
|
||||
* This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/
|
||||
* gcm/gcm-revised-spec.pdf
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "gcm.h"
|
||||
#include "aes.h"
|
||||
|
||||
/******************************************************************************
|
||||
* ==== IMPLEMENTATION WARNING ====
|
||||
*
|
||||
* This code was developed for use within SQRL's fixed environmnent. Thus, it
|
||||
* is somewhat less "general purpose" than it would be if it were designed as
|
||||
* a general purpose AES-GCM library. Specifically, it bothers with almost NO
|
||||
* error checking on parameter limits, buffer bounds, etc. It assumes that it
|
||||
* is being invoked by its author or by someone who understands the values it
|
||||
* expects to receive. Its behavior will be undefined otherwise.
|
||||
*
|
||||
* All functions that might fail are defined to return 'ints' to indicate a
|
||||
* problem. Most do not do so now. But this allows for error propagation out
|
||||
* of internal functions if robust error checking should ever be desired.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
/* Calculating the "GHASH"
|
||||
*
|
||||
* There are many ways of calculating the so-called GHASH in software, each with
|
||||
* a traditional size vs performance tradeoff. The GHASH (Galois field hash) is
|
||||
* an intriguing construction which takes two 128-bit strings (also the cipher's
|
||||
* block size and the fundamental operation size for the system) and hashes them
|
||||
* into a third 128-bit result.
|
||||
*
|
||||
* Many implementation solutions have been worked out that use large precomputed
|
||||
* table lookups in place of more time consuming bit fiddling, and this approach
|
||||
* can be scaled easily upward or downward as needed to change the time/space
|
||||
* tradeoff. It's been studied extensively and there's a solid body of theory and
|
||||
* practice. For example, without using any lookup tables an implementation
|
||||
* might obtain 119 cycles per byte throughput, whereas using a simple, though
|
||||
* large, key-specific 64 kbyte 8-bit lookup table the performance jumps to 13
|
||||
* cycles per byte.
|
||||
*
|
||||
* And Intel's processors have, since 2010, included an instruction which does
|
||||
* the entire 128x128->128 bit job in just several 64x64->128 bit pieces.
|
||||
*
|
||||
* Since SQRL is interactive, and only processing a few 128-bit blocks, I've
|
||||
* settled upon a relatively slower but appealing small-table compromise which
|
||||
* folds a bunch of not only time consuming but also bit twiddling into a simple
|
||||
* 16-entry table which is attributed to Victor Shoup's 1996 work while at
|
||||
* Bellcore: "On Fast and Provably Secure MessageAuthentication Based on
|
||||
* Universal Hashing." See: http://www.shoup.net/papers/macs.pdf
|
||||
* See, also section 4.1 of the "gcm-revised-spec" cited above.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This 16-entry table of pre-computed constants is used by the
|
||||
* GHASH multiplier to improve over a strictly table-free but
|
||||
* significantly slower 128x128 bit multiple within GF(2^128).
|
||||
*/
|
||||
static const uint64_t last4[16] = {
|
||||
0x0000, 0x1c20, 0x3840, 0x2460, 0x7080, 0x6ca0, 0x48c0, 0x54e0,
|
||||
0xe100, 0xfd20, 0xd940, 0xc560, 0x9180, 0x8da0, 0xa9c0, 0xb5e0 };
|
||||
|
||||
/*
|
||||
* Platform Endianness Neutralizing Load and Store Macro definitions
|
||||
* GCM wants platform-neutral Big Endian (BE) byte ordering
|
||||
*/
|
||||
#define GET_UINT32_BE(n,b,i) { \
|
||||
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
|
||||
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
|
||||
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
|
||||
| ( (uint32_t) (b)[(i) + 3] ); }
|
||||
|
||||
#define PUT_UINT32_BE(n,b,i) { \
|
||||
(b)[(i) ] = (uchar) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (uchar) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (uchar) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (uchar) ( (n) ); }
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_INITIALIZE
|
||||
*
|
||||
* Must be called once to initialize the GCM library.
|
||||
*
|
||||
* At present, this only calls the AES keygen table generator, which expands
|
||||
* the AES keying tables for use. This is NOT A THREAD-SAFE function, so it
|
||||
* MUST be called during system initialization before a multi-threading
|
||||
* environment is running.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_initialize( void )
|
||||
{
|
||||
aes_init_keygen_tables();
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_MULT
|
||||
*
|
||||
* Performs a GHASH operation on the 128-bit input vector 'x', setting
|
||||
* the 128-bit output vector to 'x' times H using our precomputed tables.
|
||||
* 'x' and 'output' are seen as elements of GCM's GF(2^128) Galois field.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void gcm_mult( gcm_context *ctx, // pointer to established context
|
||||
const uchar x[16], // pointer to 128-bit input vector
|
||||
uchar output[16] ) // pointer to 128-bit output vector
|
||||
{
|
||||
int i;
|
||||
uchar lo, hi, rem;
|
||||
uint64_t zh, zl;
|
||||
|
||||
lo = (uchar)( x[15] & 0x0f );
|
||||
hi = (uchar)( x[15] >> 4 );
|
||||
zh = ctx->HH[lo];
|
||||
zl = ctx->HL[lo];
|
||||
|
||||
for( i = 15; i >= 0; i-- ) {
|
||||
lo = (uchar) ( x[i] & 0x0f );
|
||||
hi = (uchar) ( x[i] >> 4 );
|
||||
|
||||
if( i != 15 ) {
|
||||
rem = (uchar) ( zl & 0x0f );
|
||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
||||
zh = ( zh >> 4 );
|
||||
zh ^= (uint64_t) last4[rem] << 48;
|
||||
zh ^= ctx->HH[lo];
|
||||
zl ^= ctx->HL[lo];
|
||||
}
|
||||
rem = (uchar) ( zl & 0x0f );
|
||||
zl = ( zh << 60 ) | ( zl >> 4 );
|
||||
zh = ( zh >> 4 );
|
||||
zh ^= (uint64_t) last4[rem] << 48;
|
||||
zh ^= ctx->HH[hi];
|
||||
zl ^= ctx->HL[hi];
|
||||
}
|
||||
PUT_UINT32_BE( zh >> 32, output, 0 );
|
||||
PUT_UINT32_BE( zh, output, 4 );
|
||||
PUT_UINT32_BE( zl >> 32, output, 8 );
|
||||
PUT_UINT32_BE( zl, output, 12 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_SETKEY
|
||||
*
|
||||
* This is called to set the AES-GCM key. It initializes the AES key
|
||||
* and populates the gcm context's pre-calculated HTables.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_setkey( gcm_context *ctx, // pointer to caller-provided gcm context
|
||||
const uchar *key, // pointer to the AES encryption key
|
||||
const uint keysize) // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
{
|
||||
int ret, i, j;
|
||||
uint64_t hi, lo;
|
||||
uint64_t vl, vh;
|
||||
unsigned char h[16];
|
||||
|
||||
memset( ctx, 0, sizeof(gcm_context) ); // zero caller-provided GCM context
|
||||
memset( h, 0, 16 ); // initialize the block to encrypt
|
||||
|
||||
// encrypt the null 128-bit block to generate a key-based value
|
||||
// which is then used to initialize our GHASH lookup tables
|
||||
if(( ret = aes_setkey( &ctx->aes_ctx, ENCRYPT, key, keysize )) != 0 )
|
||||
return( ret );
|
||||
if(( ret = aes_cipher( &ctx->aes_ctx, h, h )) != 0 )
|
||||
return( ret );
|
||||
|
||||
GET_UINT32_BE( hi, h, 0 ); // pack h as two 64-bit ints, big-endian
|
||||
GET_UINT32_BE( lo, h, 4 );
|
||||
vh = (uint64_t) hi << 32 | lo;
|
||||
|
||||
GET_UINT32_BE( hi, h, 8 );
|
||||
GET_UINT32_BE( lo, h, 12 );
|
||||
vl = (uint64_t) hi << 32 | lo;
|
||||
|
||||
ctx->HL[8] = vl; // 8 = 1000 corresponds to 1 in GF(2^128)
|
||||
ctx->HH[8] = vh;
|
||||
ctx->HH[0] = 0; // 0 corresponds to 0 in GF(2^128)
|
||||
ctx->HL[0] = 0;
|
||||
|
||||
for( i = 4; i > 0; i >>= 1 ) {
|
||||
uint32_t T = (uint32_t) ( vl & 1 ) * 0xe1000000U;
|
||||
vl = ( vh << 63 ) | ( vl >> 1 );
|
||||
vh = ( vh >> 1 ) ^ ( (uint64_t) T << 32);
|
||||
ctx->HL[i] = vl;
|
||||
ctx->HH[i] = vh;
|
||||
}
|
||||
for (i = 2; i < 16; i <<= 1 ) {
|
||||
uint64_t *HiL = ctx->HL + i, *HiH = ctx->HH + i;
|
||||
vh = *HiH;
|
||||
vl = *HiL;
|
||||
for( j = 1; j < i; j++ ) {
|
||||
HiH[j] = vh ^ ctx->HH[j];
|
||||
HiL[j] = vl ^ ctx->HL[j];
|
||||
}
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM processing occurs four phases: SETKEY, START, UPDATE and FINISH.
|
||||
*
|
||||
* SETKEY:
|
||||
*
|
||||
* START: Sets the Encryption/Decryption mode.
|
||||
* Accepts the initialization vector and additional data.
|
||||
*
|
||||
* UPDATE: Encrypts or decrypts the plaintext or ciphertext.
|
||||
*
|
||||
* FINISH: Performs a final GHASH to generate the authentication tag.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* GCM_START
|
||||
*
|
||||
* Given a user-provided GCM context, this initializes it, sets the encryption
|
||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
int mode, // GCM_ENCRYPT or GCM_DECRYPT
|
||||
const uchar *iv, // pointer to initialization vector
|
||||
size_t iv_len, // IV length in bytes (should == 12)
|
||||
const uchar *add, // ptr to additional AEAD data (NULL if none)
|
||||
size_t add_len ) // length of additional AEAD data (bytes)
|
||||
{
|
||||
int ret; // our error return if the AES encrypt fails
|
||||
uchar work_buf[16]; // XOR source built from provided IV if len != 16
|
||||
const uchar *p; // general purpose array pointer
|
||||
size_t use_len; // byte count to process, up to 16 bytes
|
||||
size_t i; // local loop iterator
|
||||
|
||||
// since the context might be reused under the same key
|
||||
// we zero the working buffers for this next new process
|
||||
memset( ctx->y, 0x00, sizeof(ctx->y ) );
|
||||
memset( ctx->buf, 0x00, sizeof(ctx->buf) );
|
||||
ctx->len = 0;
|
||||
ctx->add_len = 0;
|
||||
|
||||
ctx->mode = mode; // set the GCM encryption/decryption mode
|
||||
ctx->aes_ctx.mode = ENCRYPT; // GCM *always* runs AES in ENCRYPTION mode
|
||||
|
||||
if( iv_len == 12 ) { // GCM natively uses a 12-byte, 96-bit IV
|
||||
memcpy( ctx->y, iv, iv_len ); // copy the IV to the top of the 'y' buff
|
||||
ctx->y[15] = 1; // start "counting" from 1 (not 0)
|
||||
}
|
||||
else // if we don't have a 12-byte IV, we GHASH whatever we've been given
|
||||
{
|
||||
memset( work_buf, 0x00, 16 ); // clear the working buffer
|
||||
PUT_UINT32_BE( iv_len * 8, work_buf, 12 ); // place the IV into buffer
|
||||
|
||||
p = iv;
|
||||
while( iv_len > 0 ) {
|
||||
use_len = ( iv_len < 16 ) ? iv_len : 16;
|
||||
for( i = 0; i < use_len; i++ ) ctx->y[i] ^= p[i];
|
||||
gcm_mult( ctx, ctx->y, ctx->y );
|
||||
iv_len -= use_len;
|
||||
p += use_len;
|
||||
}
|
||||
for( i = 0; i < 16; i++ ) ctx->y[i] ^= work_buf[i];
|
||||
gcm_mult( ctx, ctx->y, ctx->y );
|
||||
}
|
||||
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ctx->base_ectr ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ctx->add_len = add_len;
|
||||
p = add;
|
||||
while( add_len > 0 ) {
|
||||
use_len = ( add_len < 16 ) ? add_len : 16;
|
||||
for( i = 0; i < use_len; i++ ) ctx->buf[i] ^= p[i];
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
add_len -= use_len;
|
||||
p += use_len;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_UPDATE
|
||||
*
|
||||
* This is called once or more to process bulk plaintext or ciphertext data.
|
||||
* We give this some number of bytes of input and it returns the same number
|
||||
* of output bytes. If called multiple times (which is fine) all but the final
|
||||
* invocation MUST be called with length mod 16 == 0. (Only the final call can
|
||||
* have a partial block length of < 128 bits.)
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t length, // length, in bytes, of data to process
|
||||
const uchar *input, // pointer to source data
|
||||
uchar *output ) // pointer to destination data
|
||||
{
|
||||
int ret; // our error return if the AES encrypt fails
|
||||
uchar ectr[16]; // counter-mode cipher output for XORing
|
||||
size_t use_len; // byte count to process, up to 16 bytes
|
||||
size_t i; // local loop iterator
|
||||
|
||||
ctx->len += length; // bump the GCM context's running length count
|
||||
|
||||
while( length > 0 ) {
|
||||
// clamp the length to process at 16 bytes
|
||||
use_len = ( length < 16 ) ? length : 16;
|
||||
|
||||
// increment the context's 128-bit IV||Counter 'y' vector
|
||||
for( i = 16; i > 12; i-- ) if( ++ctx->y[i - 1] != 0 ) break;
|
||||
|
||||
// encrypt the context's 'y' vector under the established key
|
||||
if( ( ret = aes_cipher( &ctx->aes_ctx, ctx->y, ectr ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
// encrypt or decrypt the input to the output
|
||||
if( ctx->mode == ENCRYPT )
|
||||
{
|
||||
for( i = 0; i < use_len; i++ ) {
|
||||
// XOR the cipher's ouptut vector (ectr) with our input
|
||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
||||
// now we mix in our data into the authentication hash.
|
||||
// if we're ENcrypting we XOR in the post-XOR (output)
|
||||
// results, but if we're DEcrypting we XOR in the input
|
||||
// data
|
||||
ctx->buf[i] ^= output[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < use_len; i++ ) {
|
||||
// but if we're DEcrypting we XOR in the input data first,
|
||||
// i.e. before saving to ouput data, otherwise if the input
|
||||
// and output buffer are the same (inplace decryption) we
|
||||
// would not get the correct auth tag
|
||||
|
||||
ctx->buf[i] ^= input[i];
|
||||
|
||||
// XOR the cipher's ouptut vector (ectr) with our input
|
||||
output[i] = (uchar) ( ectr[i] ^ input[i] );
|
||||
}
|
||||
}
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf ); // perform a GHASH operation
|
||||
|
||||
length -= use_len; // drop the remaining byte count to process
|
||||
input += use_len; // bump our input pointer forward
|
||||
output += use_len; // bump our output pointer forward
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_FINISH
|
||||
*
|
||||
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
|
||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uchar *tag, // pointer to buffer which receives the tag
|
||||
size_t tag_len ) // length, in bytes, of the tag-receiving buf
|
||||
{
|
||||
uchar work_buf[16];
|
||||
uint64_t orig_len = ctx->len * 8;
|
||||
uint64_t orig_add_len = ctx->add_len * 8;
|
||||
size_t i;
|
||||
|
||||
if( tag_len != 0 ) memcpy( tag, ctx->base_ectr, tag_len );
|
||||
|
||||
if( orig_len || orig_add_len ) {
|
||||
memset( work_buf, 0x00, 16 );
|
||||
|
||||
PUT_UINT32_BE( ( orig_add_len >> 32 ), work_buf, 0 );
|
||||
PUT_UINT32_BE( ( orig_add_len ), work_buf, 4 );
|
||||
PUT_UINT32_BE( ( orig_len >> 32 ), work_buf, 8 );
|
||||
PUT_UINT32_BE( ( orig_len ), work_buf, 12 );
|
||||
|
||||
for( i = 0; i < 16; i++ ) ctx->buf[i] ^= work_buf[i];
|
||||
gcm_mult( ctx, ctx->buf, ctx->buf );
|
||||
for( i = 0; i < tag_len; i++ ) tag[i] ^= ctx->buf[i];
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
*
|
||||
* This either encrypts or decrypts the user-provided data and, either
|
||||
* way, generates an authentication tag of the requested length. It must be
|
||||
* called with a GCM context whose key has already been set with GCM_SETKEY.
|
||||
*
|
||||
* The user would typically call this explicitly to ENCRYPT a buffer of data
|
||||
* and optional associated data, and produce its an authentication tag.
|
||||
*
|
||||
* To reverse the process the user would typically call the companion
|
||||
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
|
||||
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
|
||||
* to perform its decryption and tag generation, which it then compares.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_crypt_and_tag(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
uchar *tag, // pointer to the tag to be generated
|
||||
size_t tag_len ) // byte length of the tag to be generated
|
||||
{ /*
|
||||
assuming that the caller has already invoked gcm_setkey to
|
||||
prepare the gcm context with the keying material, we simply
|
||||
invoke each of the three GCM sub-functions in turn...
|
||||
*/
|
||||
gcm_start ( ctx, mode, iv, iv_len, add, add_len );
|
||||
gcm_update ( ctx, length, input, output );
|
||||
gcm_finish ( ctx, tag, tag_len );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
*
|
||||
* This DECRYPTS a user-provided data buffer with optional associated data.
|
||||
* It then verifies a user-supplied authentication tag against the tag just
|
||||
* re-created during decryption to verify that the data has not been altered.
|
||||
*
|
||||
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
|
||||
* and authentication tag generation.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_auth_decrypt(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
const uchar *tag, // pointer to the tag to be authenticated
|
||||
size_t tag_len ) // byte length of the tag <= 16
|
||||
{
|
||||
uchar check_tag[16]; // the tag generated and returned by decryption
|
||||
int diff; // an ORed flag to detect authentication errors
|
||||
size_t i; // our local iterator
|
||||
/*
|
||||
we use GCM_DECRYPT_AND_TAG (above) to perform our decryption
|
||||
(which is an identical XORing to reverse the previous one)
|
||||
and also to re-generate the matching authentication tag
|
||||
*/
|
||||
gcm_crypt_and_tag( ctx, DECRYPT, iv, iv_len, add, add_len,
|
||||
input, output, length, check_tag, tag_len );
|
||||
|
||||
// now we verify the authentication tag in 'constant time'
|
||||
for( diff = 0, i = 0; i < tag_len; i++ )
|
||||
diff |= tag[i] ^ check_tag[i];
|
||||
|
||||
if( diff != 0 ) { // see whether any bits differed?
|
||||
memset( output, 0, length ); // if so... wipe the output data
|
||||
return( GCM_AUTH_FAILURE ); // return GCM_AUTH_FAILURE
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_ZERO_CTX
|
||||
*
|
||||
* The GCM context contains both the GCM context and the AES context.
|
||||
* This includes keying and key-related material which is security-
|
||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||
*
|
||||
******************************************************************************/
|
||||
void gcm_zero_ctx( gcm_context *ctx )
|
||||
{
|
||||
// zero the context originally provided to us
|
||||
memset( ctx, 0, sizeof( gcm_context ) );
|
||||
}
|
||||
187
applications/external/esubghz_chat/crypto/gcm.h
vendored
Normal file
187
applications/external/esubghz_chat/crypto/gcm.h
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
|
||||
*
|
||||
* This is a simple and straightforward implementation of AES-GCM authenticated
|
||||
* encryption. The focus of this work was correctness & accuracy. It is written
|
||||
* in straight 'C' without any particular focus upon optimization or speed. It
|
||||
* should be endian (memory byte order) neutral since the few places that care
|
||||
* are handled explicitly.
|
||||
*
|
||||
* This implementation of AES-GCM was created by Steven M. Gibson of GRC.com.
|
||||
*
|
||||
* It is intended for general purpose use, but was written in support of GRC's
|
||||
* reference implementation of the SQRL (Secure Quick Reliable Login) client.
|
||||
*
|
||||
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \
|
||||
* gcm/gcm-revised-spec.pdf
|
||||
*
|
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
|
||||
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#ifndef GCM_HEADER
|
||||
#define GCM_HEADER
|
||||
|
||||
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
||||
|
||||
#include "aes.h" // gcm_context includes aes_context
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <basetsd.h>
|
||||
typedef unsigned int size_t;// use the right type for length declarations
|
||||
typedef UINT32 uint32_t;
|
||||
typedef UINT64 uint64_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
int mode; // cipher direction: encrypt/decrypt
|
||||
uint64_t len; // cipher data length processed so far
|
||||
uint64_t add_len; // total add data length
|
||||
uint64_t HL[16]; // precalculated lo-half HTable
|
||||
uint64_t HH[16]; // precalculated hi-half HTable
|
||||
uchar base_ectr[16]; // first counter-mode cipher output for tag
|
||||
uchar y[16]; // the current cipher-input IV|Counter value
|
||||
uchar buf[16]; // buf working value
|
||||
aes_context aes_ctx; // cipher context used
|
||||
} gcm_context;
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_CONTEXT : MUST be called once before ANY use of this library
|
||||
******************************************************************************/
|
||||
int gcm_initialize( void );
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* GCM_SETKEY : sets the GCM (and AES) keying material for use
|
||||
******************************************************************************/
|
||||
int gcm_setkey( gcm_context *ctx, // caller-provided context ptr
|
||||
const uchar *key, // pointer to cipher key
|
||||
const uint keysize // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
||||
); // returns 0 for success
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_CRYPT_AND_TAG
|
||||
*
|
||||
* This either encrypts or decrypts the user-provided data and, either
|
||||
* way, generates an authentication tag of the requested length. It must be
|
||||
* called with a GCM context whose key has already been set with GCM_SETKEY.
|
||||
*
|
||||
* The user would typically call this explicitly to ENCRYPT a buffer of data
|
||||
* and optional associated data, and produce its an authentication tag.
|
||||
*
|
||||
* To reverse the process the user would typically call the companion
|
||||
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided
|
||||
* authentication tag. The GCM_AUTH_DECRYPT function calls this function
|
||||
* to perform its decryption and tag generation, which it then compares.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_crypt_and_tag(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
uchar *tag, // pointer to the tag to be generated
|
||||
size_t tag_len ); // byte length of the tag to be generated
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_AUTH_DECRYPT
|
||||
*
|
||||
* This DECRYPTS a user-provided data buffer with optional associated data.
|
||||
* It then verifies a user-supplied authentication tag against the tag just
|
||||
* re-created during decryption to verify that the data has not been altered.
|
||||
*
|
||||
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption
|
||||
* and authentication tag generation.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_auth_decrypt(
|
||||
gcm_context *ctx, // gcm context with key already setup
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
||||
const uchar *tag, // pointer to the tag to be authenticated
|
||||
size_t tag_len ); // byte length of the tag <= 16
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_START
|
||||
*
|
||||
* Given a user-provided GCM context, this initializes it, sets the encryption
|
||||
* mode, and preprocesses the initialization vector and additional AEAD data.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
int mode, // ENCRYPT (1) or DECRYPT (0)
|
||||
const uchar *iv, // pointer to initialization vector
|
||||
size_t iv_len, // IV length in bytes (should == 12)
|
||||
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
||||
size_t add_len ); // length of additional AEAD data (bytes)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_UPDATE
|
||||
*
|
||||
* This is called once or more to process bulk plaintext or ciphertext data.
|
||||
* We give this some number of bytes of input and it returns the same number
|
||||
* of output bytes. If called multiple times (which is fine) all but the final
|
||||
* invocation MUST be called with length mod 16 == 0. (Only the final call can
|
||||
* have a partial block length of < 128 bits.)
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t length, // length, in bytes, of data to process
|
||||
const uchar *input, // pointer to source data
|
||||
uchar *output ); // pointer to destination data
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_FINISH
|
||||
*
|
||||
* This is called once after all calls to GCM_UPDATE to finalize the GCM.
|
||||
* It performs the final GHASH to produce the resulting authentication TAG.
|
||||
*
|
||||
******************************************************************************/
|
||||
int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
||||
size_t tag_len ); // length, in bytes, of the tag-receiving buf
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* GCM_ZERO_CTX
|
||||
*
|
||||
* The GCM context contains both the GCM context and the AES context.
|
||||
* This includes keying and key-related material which is security-
|
||||
* sensitive, so it MUST be zeroed after use. This function does that.
|
||||
*
|
||||
******************************************************************************/
|
||||
void gcm_zero_ctx( gcm_context *ctx );
|
||||
|
||||
|
||||
#endif /* GCM_HEADER */
|
||||
Reference in New Issue
Block a user