mirror of https://github.com/bol-van/zapret/
4 changed files with 1255 additions and 1255 deletions
@ -1,483 +1,483 @@ |
|||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL |
* 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 |
* This is a simple and straightforward implementation of the AES Rijndael |
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus |
* 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 |
* of this work was correctness & accuracy. It is written in 'C' without any |
||||
* particular focus upon optimization or speed. It should be endian (memory |
* particular focus upon optimization or speed. It should be endian (memory |
||||
* byte order) neutral since the few places that care are handled explicitly. |
* 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. |
* 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 |
* 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. |
* reference implementation of the SQRL (Secure Quick Reliable Login) client. |
||||
* |
* |
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
* |
* |
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE |
* 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. |
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK. |
||||
* |
* |
||||
*******************************************************************************/ |
*******************************************************************************/ |
||||
|
|
||||
#include "aes.h" |
#include "aes.h" |
||||
|
|
||||
static int aes_tables_inited = 0; // run-once flag for performing key
|
static int aes_tables_inited = 0; // run-once flag for performing key
|
||||
// expasion table generation (see below)
|
// expasion table generation (see below)
|
||||
/*
|
/*
|
||||
* The following static local tables must be filled-in before the first use of |
* 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 |
* 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 |
* and once built are read-only and thread safe. The "gcm_initialize" function |
||||
* must be called once during system initialization to populate these arrays |
* 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 |
* 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. |
* before attempted use, an error will be returned to the caller. |
||||
* |
* |
||||
* NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since |
* NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since |
||||
* GCM uses AES in counter-mode, where the AES cipher output is XORed with |
* 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 |
* 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. |
* decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h. |
||||
*/ |
*/ |
||||
// We always need our forward tables
|
// We always need our forward tables
|
||||
static uchar FSb[256]; // Forward substitution box (FSb)
|
static uchar FSb[256]; // Forward substitution box (FSb)
|
||||
static uint32_t FT0[256]; // Forward key schedule assembly tables
|
static uint32_t FT0[256]; // Forward key schedule assembly tables
|
||||
static uint32_t FT1[256]; |
static uint32_t FT1[256]; |
||||
static uint32_t FT2[256]; |
static uint32_t FT2[256]; |
||||
static uint32_t FT3[256]; |
static uint32_t FT3[256]; |
||||
|
|
||||
#if AES_DECRYPTION // We ONLY need reverse for decryption
|
#if AES_DECRYPTION // We ONLY need reverse for decryption
|
||||
static uchar RSb[256]; // Reverse substitution box (RSb)
|
static uchar RSb[256]; // Reverse substitution box (RSb)
|
||||
static uint32_t RT0[256]; // Reverse key schedule assembly tables
|
static uint32_t RT0[256]; // Reverse key schedule assembly tables
|
||||
static uint32_t RT1[256]; |
static uint32_t RT1[256]; |
||||
static uint32_t RT2[256]; |
static uint32_t RT2[256]; |
||||
static uint32_t RT3[256]; |
static uint32_t RT3[256]; |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
static uint32_t RCON[10]; // AES round constants
|
static uint32_t RCON[10]; // AES round constants
|
||||
|
|
||||
/*
|
/*
|
||||
* Platform Endianness Neutralizing Load and Store Macro definitions |
* Platform Endianness Neutralizing Load and Store Macro definitions |
||||
* AES wants platform-neutral Little Endian (LE) byte ordering |
* AES wants platform-neutral Little Endian (LE) byte ordering |
||||
*/ |
*/ |
||||
#define GET_UINT32_LE(n,b,i) { \ |
#define GET_UINT32_LE(n,b,i) { \ |
||||
(n) = ( (uint32_t) (b)[(i) ] ) \ |
(n) = ( (uint32_t) (b)[(i) ] ) \ |
||||
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
| ( (uint32_t) (b)[(i) + 1] << 8 ) \ |
||||
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
| ( (uint32_t) (b)[(i) + 2] << 16 ) \ |
||||
| ( (uint32_t) (b)[(i) + 3] << 24 ); } |
| ( (uint32_t) (b)[(i) + 3] << 24 ); } |
||||
|
|
||||
#define PUT_UINT32_LE(n,b,i) { \ |
#define PUT_UINT32_LE(n,b,i) { \ |
||||
(b)[(i) ] = (uchar) ( (n) ); \ |
(b)[(i) ] = (uchar) ( (n) ); \ |
||||
(b)[(i) + 1] = (uchar) ( (n) >> 8 ); \ |
(b)[(i) + 1] = (uchar) ( (n) >> 8 ); \ |
||||
(b)[(i) + 2] = (uchar) ( (n) >> 16 ); \ |
(b)[(i) + 2] = (uchar) ( (n) >> 16 ); \ |
||||
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); } |
(b)[(i) + 3] = (uchar) ( (n) >> 24 ); } |
||||
|
|
||||
/*
|
/*
|
||||
* AES forward and reverse encryption round processing macros |
* AES forward and reverse encryption round processing macros |
||||
*/ |
*/ |
||||
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
||||
{ \ |
{ \ |
||||
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ |
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ |
||||
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
||||
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
||||
FT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
FT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ |
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ |
||||
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
||||
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
||||
FT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
FT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ |
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ |
||||
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
||||
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
||||
FT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
FT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ |
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ |
||||
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
||||
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
||||
FT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
FT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
||||
} |
} |
||||
|
|
||||
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
||||
{ \ |
{ \ |
||||
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ |
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ |
||||
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
||||
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
||||
RT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
RT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ |
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ |
||||
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
||||
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
||||
RT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
RT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ |
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ |
||||
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
||||
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
||||
RT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
RT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
||||
\ |
\ |
||||
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ |
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ |
||||
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
||||
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
||||
RT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
RT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
||||
} |
} |
||||
|
|
||||
/*
|
/*
|
||||
* These macros improve the readability of the key |
* These macros improve the readability of the key |
||||
* generation initialization code by collapsing |
* generation initialization code by collapsing |
||||
* repetitive common operations into logical pieces. |
* repetitive common operations into logical pieces. |
||||
*/ |
*/ |
||||
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) |
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) |
||||
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) |
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) |
||||
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) |
#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 MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; } |
||||
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \ |
#define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \ |
||||
*RK++ = *SK++; *RK++ = *SK++; } |
*RK++ = *SK++; *RK++ = *SK++; } |
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* AES_INIT_KEYGEN_TABLES |
* AES_INIT_KEYGEN_TABLES |
||||
* |
* |
||||
* Fills the AES key expansion tables allocated above with their static |
* Fills the AES key expansion tables allocated above with their static |
||||
* data. This is not "per key" data, but static system-wide read-only |
* 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 |
* table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once |
||||
* at system initialization to setup the tables for all subsequent use. |
* at system initialization to setup the tables for all subsequent use. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
void aes_init_keygen_tables(void) |
void aes_init_keygen_tables(void) |
||||
{ |
{ |
||||
int i, x, y, z; // general purpose iteration and computation locals
|
int i, x, y, z; // general purpose iteration and computation locals
|
||||
int pow[256]; |
int pow[256]; |
||||
int log[256]; |
int log[256]; |
||||
|
|
||||
if (aes_tables_inited) return; |
if (aes_tables_inited) return; |
||||
|
|
||||
// fill the 'pow' and 'log' tables over GF(2^8)
|
// fill the 'pow' and 'log' tables over GF(2^8)
|
||||
for (i = 0, x = 1; i < 256; i++) { |
for (i = 0, x = 1; i < 256; i++) { |
||||
pow[i] = x; |
pow[i] = x; |
||||
log[x] = i; |
log[x] = i; |
||||
x = (x ^ XTIME(x)) & 0xFF; |
x = (x ^ XTIME(x)) & 0xFF; |
||||
} |
} |
||||
// compute the round constants
|
// compute the round constants
|
||||
for (i = 0, x = 1; i < 10; i++) { |
for (i = 0, x = 1; i < 10; i++) { |
||||
RCON[i] = (uint32_t)x; |
RCON[i] = (uint32_t)x; |
||||
x = XTIME(x) & 0xFF; |
x = XTIME(x) & 0xFF; |
||||
} |
} |
||||
// fill the forward and reverse substitution boxes
|
// fill the forward and reverse substitution boxes
|
||||
FSb[0x00] = 0x63; |
FSb[0x00] = 0x63; |
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
RSb[0x63] = 0x00; |
RSb[0x63] = 0x00; |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
for (i = 1; i < 256; i++) { |
for (i = 1; i < 256; i++) { |
||||
x = y = pow[255 - log[i]]; |
x = y = pow[255 - log[i]]; |
||||
MIX(x, y); |
MIX(x, y); |
||||
MIX(x, y); |
MIX(x, y); |
||||
MIX(x, y); |
MIX(x, y); |
||||
MIX(x, y); |
MIX(x, y); |
||||
FSb[i] = (uchar)(x ^= 0x63); |
FSb[i] = (uchar)(x ^= 0x63); |
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
RSb[x] = (uchar)i; |
RSb[x] = (uchar)i; |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
} |
} |
||||
// generate the forward and reverse key expansion tables
|
// generate the forward and reverse key expansion tables
|
||||
for (i = 0; i < 256; i++) { |
for (i = 0; i < 256; i++) { |
||||
x = FSb[i]; |
x = FSb[i]; |
||||
y = XTIME(x) & 0xFF; |
y = XTIME(x) & 0xFF; |
||||
z = (y ^ x) & 0xFF; |
z = (y ^ x) & 0xFF; |
||||
|
|
||||
FT0[i] = ((uint32_t)y) ^ ((uint32_t)x << 8) ^ |
FT0[i] = ((uint32_t)y) ^ ((uint32_t)x << 8) ^ |
||||
((uint32_t)x << 16) ^ ((uint32_t)z << 24); |
((uint32_t)x << 16) ^ ((uint32_t)z << 24); |
||||
|
|
||||
FT1[i] = ROTL8(FT0[i]); |
FT1[i] = ROTL8(FT0[i]); |
||||
FT2[i] = ROTL8(FT1[i]); |
FT2[i] = ROTL8(FT1[i]); |
||||
FT3[i] = ROTL8(FT2[i]); |
FT3[i] = ROTL8(FT2[i]); |
||||
|
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
x = RSb[i]; |
x = RSb[i]; |
||||
|
|
||||
RT0[i] = ((uint32_t)MUL(0x0E, x)) ^ |
RT0[i] = ((uint32_t)MUL(0x0E, x)) ^ |
||||
((uint32_t)MUL(0x09, x) << 8) ^ |
((uint32_t)MUL(0x09, x) << 8) ^ |
||||
((uint32_t)MUL(0x0D, x) << 16) ^ |
((uint32_t)MUL(0x0D, x) << 16) ^ |
||||
((uint32_t)MUL(0x0B, x) << 24); |
((uint32_t)MUL(0x0B, x) << 24); |
||||
|
|
||||
RT1[i] = ROTL8(RT0[i]); |
RT1[i] = ROTL8(RT0[i]); |
||||
RT2[i] = ROTL8(RT1[i]); |
RT2[i] = ROTL8(RT1[i]); |
||||
RT3[i] = ROTL8(RT2[i]); |
RT3[i] = ROTL8(RT2[i]); |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
} |
} |
||||
aes_tables_inited = 1; // flag that the tables have been generated
|
aes_tables_inited = 1; // flag that the tables have been generated
|
||||
} // to permit subsequent use of the AES cipher
|
} // to permit subsequent use of the AES cipher
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* AES_SET_ENCRYPTION_KEY |
* AES_SET_ENCRYPTION_KEY |
||||
* |
* |
||||
* This is called by 'aes_setkey' when we're establishing a key for |
* This is called by 'aes_setkey' when we're establishing a key for |
||||
* subsequent encryption. We give it a pointer to the encryption |
* subsequent encryption. We give it a pointer to the encryption |
||||
* context, a pointer to the key, and the key's length in bytes. |
* 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). |
* Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits). |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_set_encryption_key(aes_context *ctx, |
int aes_set_encryption_key(aes_context *ctx, |
||||
const uchar *key, |
const uchar *key, |
||||
uint keysize) |
uint keysize) |
||||
{ |
{ |
||||
uint i; // general purpose iteration local
|
uint i; // general purpose iteration local
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
|
|
||||
for (i = 0; i < (keysize >> 2); i++) { |
for (i = 0; i < (keysize >> 2); i++) { |
||||
GET_UINT32_LE(RK[i], key, i << 2); |
GET_UINT32_LE(RK[i], key, i << 2); |
||||
} |
} |
||||
|
|
||||
switch (ctx->rounds) |
switch (ctx->rounds) |
||||
{ |
{ |
||||
case 10: |
case 10: |
||||
for (i = 0; i < 10; i++, RK += 4) { |
for (i = 0; i < 10; i++, RK += 4) { |
||||
RK[4] = RK[0] ^ RCON[i] ^ |
RK[4] = RK[0] ^ RCON[i] ^ |
||||
((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^ |
((uint32_t)FSb[(RK[3] >> 8) & 0xFF]) ^ |
||||
((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^ |
((uint32_t)FSb[(RK[3] >> 16) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^ |
((uint32_t)FSb[(RK[3] >> 24) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(RK[3]) & 0xFF] << 24); |
((uint32_t)FSb[(RK[3]) & 0xFF] << 24); |
||||
|
|
||||
RK[5] = RK[1] ^ RK[4]; |
RK[5] = RK[1] ^ RK[4]; |
||||
RK[6] = RK[2] ^ RK[5]; |
RK[6] = RK[2] ^ RK[5]; |
||||
RK[7] = RK[3] ^ RK[6]; |
RK[7] = RK[3] ^ RK[6]; |
||||
} |
} |
||||
break; |
break; |
||||
|
|
||||
case 12: |
case 12: |
||||
for (i = 0; i < 8; i++, RK += 6) { |
for (i = 0; i < 8; i++, RK += 6) { |
||||
RK[6] = RK[0] ^ RCON[i] ^ |
RK[6] = RK[0] ^ RCON[i] ^ |
||||
((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^ |
((uint32_t)FSb[(RK[5] >> 8) & 0xFF]) ^ |
||||
((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^ |
((uint32_t)FSb[(RK[5] >> 16) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(RK[5] >> 24) & 0xFF] << 16) ^ |
((uint32_t)FSb[(RK[5] >> 24) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(RK[5]) & 0xFF] << 24); |
((uint32_t)FSb[(RK[5]) & 0xFF] << 24); |
||||
|
|
||||
RK[7] = RK[1] ^ RK[6]; |
RK[7] = RK[1] ^ RK[6]; |
||||
RK[8] = RK[2] ^ RK[7]; |
RK[8] = RK[2] ^ RK[7]; |
||||
RK[9] = RK[3] ^ RK[8]; |
RK[9] = RK[3] ^ RK[8]; |
||||
RK[10] = RK[4] ^ RK[9]; |
RK[10] = RK[4] ^ RK[9]; |
||||
RK[11] = RK[5] ^ RK[10]; |
RK[11] = RK[5] ^ RK[10]; |
||||
} |
} |
||||
break; |
break; |
||||
|
|
||||
case 14: |
case 14: |
||||
for (i = 0; i < 7; i++, RK += 8) { |
for (i = 0; i < 7; i++, RK += 8) { |
||||
RK[8] = RK[0] ^ RCON[i] ^ |
RK[8] = RK[0] ^ RCON[i] ^ |
||||
((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^ |
((uint32_t)FSb[(RK[7] >> 8) & 0xFF]) ^ |
||||
((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^ |
((uint32_t)FSb[(RK[7] >> 16) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(RK[7] >> 24) & 0xFF] << 16) ^ |
((uint32_t)FSb[(RK[7] >> 24) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(RK[7]) & 0xFF] << 24); |
((uint32_t)FSb[(RK[7]) & 0xFF] << 24); |
||||
|
|
||||
RK[9] = RK[1] ^ RK[8]; |
RK[9] = RK[1] ^ RK[8]; |
||||
RK[10] = RK[2] ^ RK[9]; |
RK[10] = RK[2] ^ RK[9]; |
||||
RK[11] = RK[3] ^ RK[10]; |
RK[11] = RK[3] ^ RK[10]; |
||||
|
|
||||
RK[12] = RK[4] ^ |
RK[12] = RK[4] ^ |
||||
((uint32_t)FSb[(RK[11]) & 0xFF]) ^ |
((uint32_t)FSb[(RK[11]) & 0xFF]) ^ |
||||
((uint32_t)FSb[(RK[11] >> 8) & 0xFF] << 8) ^ |
((uint32_t)FSb[(RK[11] >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(RK[11] >> 16) & 0xFF] << 16) ^ |
((uint32_t)FSb[(RK[11] >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(RK[11] >> 24) & 0xFF] << 24); |
((uint32_t)FSb[(RK[11] >> 24) & 0xFF] << 24); |
||||
|
|
||||
RK[13] = RK[5] ^ RK[12]; |
RK[13] = RK[5] ^ RK[12]; |
||||
RK[14] = RK[6] ^ RK[13]; |
RK[14] = RK[6] ^ RK[13]; |
||||
RK[15] = RK[7] ^ RK[14]; |
RK[15] = RK[7] ^ RK[14]; |
||||
} |
} |
||||
break; |
break; |
||||
|
|
||||
default: |
default: |
||||
return -1; |
return -1; |
||||
} |
} |
||||
return(0); |
return(0); |
||||
} |
} |
||||
|
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* AES_SET_DECRYPTION_KEY |
* AES_SET_DECRYPTION_KEY |
||||
* |
* |
||||
* This is called by 'aes_setkey' when we're establishing a |
* This is called by 'aes_setkey' when we're establishing a |
||||
* key for subsequent decryption. We give it a pointer to |
* key for subsequent decryption. We give it a pointer to |
||||
* the encryption context, a pointer to the key, and the key's |
* the encryption context, a pointer to the key, and the key's |
||||
* length in bits. Valid lengths are: 128, 192, or 256 bits. |
* length in bits. Valid lengths are: 128, 192, or 256 bits. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_set_decryption_key(aes_context *ctx, |
int aes_set_decryption_key(aes_context *ctx, |
||||
const uchar *key, |
const uchar *key, |
||||
uint keysize) |
uint keysize) |
||||
{ |
{ |
||||
int i, j; |
int i, j; |
||||
aes_context cty; // a calling aes context for set_encryption_key
|
aes_context cty; // a calling aes context for set_encryption_key
|
||||
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
|
||||
uint32_t *SK; |
uint32_t *SK; |
||||
int ret; |
int ret; |
||||
|
|
||||
cty.rounds = ctx->rounds; // initialize our local aes context
|
cty.rounds = ctx->rounds; // initialize our local aes context
|
||||
cty.rk = cty.buf; // round count and key buf pointer
|
cty.rk = cty.buf; // round count and key buf pointer
|
||||
|
|
||||
if ((ret = aes_set_encryption_key(&cty, key, keysize)) != 0) |
if ((ret = aes_set_encryption_key(&cty, key, keysize)) != 0) |
||||
return(ret); |
return(ret); |
||||
|
|
||||
SK = cty.rk + cty.rounds * 4; |
SK = cty.rk + cty.rounds * 4; |
||||
|
|
||||
CPY128 // copy a 128-bit block from *SK to *RK
|
CPY128 // copy a 128-bit block from *SK to *RK
|
||||
|
|
||||
for (i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8) { |
for (i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8) { |
||||
for (j = 0; j < 4; j++, SK++) { |
for (j = 0; j < 4; j++, SK++) { |
||||
*RK++ = RT0[FSb[(*SK) & 0xFF]] ^ |
*RK++ = RT0[FSb[(*SK) & 0xFF]] ^ |
||||
RT1[FSb[(*SK >> 8) & 0xFF]] ^ |
RT1[FSb[(*SK >> 8) & 0xFF]] ^ |
||||
RT2[FSb[(*SK >> 16) & 0xFF]] ^ |
RT2[FSb[(*SK >> 16) & 0xFF]] ^ |
||||
RT3[FSb[(*SK >> 24) & 0xFF]]; |
RT3[FSb[(*SK >> 24) & 0xFF]]; |
||||
} |
} |
||||
} |
} |
||||
CPY128 // copy a 128-bit block from *SK to *RK
|
CPY128 // copy a 128-bit block from *SK to *RK
|
||||
memset(&cty, 0, sizeof(aes_context)); // clear local aes context
|
memset(&cty, 0, sizeof(aes_context)); // clear local aes context
|
||||
return(0); |
return(0); |
||||
} |
} |
||||
|
|
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* AES_SETKEY |
* AES_SETKEY |
||||
* |
* |
||||
* Invoked to establish the key schedule for subsequent encryption/decryption |
* Invoked to establish the key schedule for subsequent encryption/decryption |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
int aes_setkey(aes_context *ctx, // AES context provided by our caller
|
||||
int mode, // ENCRYPT or DECRYPT flag
|
int mode, // ENCRYPT or DECRYPT flag
|
||||
const uchar *key, // pointer to the key
|
const uchar *key, // pointer to the key
|
||||
uint keysize) // key length in bytes
|
uint keysize) // key length in bytes
|
||||
{ |
{ |
||||
// since table initialization is not thread safe, we could either add
|
// since table initialization is not thread safe, we could either add
|
||||
// system-specific mutexes and init the AES key generation tables on
|
// system-specific mutexes and init the AES key generation tables on
|
||||
// demand, or ask the developer to simply call "gcm_initialize" once during
|
// demand, or ask the developer to simply call "gcm_initialize" once during
|
||||
// application startup before threading begins. That's what we choose.
|
// application startup before threading begins. That's what we choose.
|
||||
if (!aes_tables_inited) return (-1); // fail the call when not inited.
|
if (!aes_tables_inited) return (-1); // fail the call when not inited.
|
||||
|
|
||||
ctx->mode = mode; // capture the key type we're creating
|
ctx->mode = mode; // capture the key type we're creating
|
||||
ctx->rk = ctx->buf; // initialize our round key pointer
|
ctx->rk = ctx->buf; // initialize our round key pointer
|
||||
|
|
||||
switch (keysize) // set the rounds count based upon the keysize
|
switch (keysize) // set the rounds count based upon the keysize
|
||||
{ |
{ |
||||
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
|
case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
|
||||
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
|
case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
|
||||
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
|
case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
|
||||
default: return(-1); |
default: return(-1); |
||||
} |
} |
||||
|
|
||||
#if AES_DECRYPTION |
#if AES_DECRYPTION |
||||
if (mode == DECRYPT) // expand our key for encryption or decryption
|
if (mode == DECRYPT) // expand our key for encryption or decryption
|
||||
return(aes_set_decryption_key(ctx, key, keysize)); |
return(aes_set_decryption_key(ctx, key, keysize)); |
||||
else /* ENCRYPT */ |
else /* ENCRYPT */ |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
return(aes_set_encryption_key(ctx, key, keysize)); |
return(aes_set_encryption_key(ctx, key, keysize)); |
||||
} |
} |
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* AES_CIPHER |
* AES_CIPHER |
||||
* |
* |
||||
* Perform AES encryption and decryption. |
* Perform AES encryption and decryption. |
||||
* The AES context will have been setup with the encryption mode |
* The AES context will have been setup with the encryption mode |
||||
* and all keying information appropriate for the task. |
* and all keying information appropriate for the task. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_cipher(aes_context *ctx, |
int aes_cipher(aes_context *ctx, |
||||
const uchar input[16], |
const uchar input[16], |
||||
uchar output[16]) |
uchar output[16]) |
||||
{ |
{ |
||||
int i; |
int i; |
||||
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
|
||||
|
|
||||
RK = ctx->rk; |
RK = ctx->rk; |
||||
|
|
||||
GET_UINT32_LE(X0, input, 0); X0 ^= *RK++; // load our 128-bit
|
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(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(X2, input, 8); X2 ^= *RK++; // memory endian-neutral way
|
||||
GET_UINT32_LE(X3, input, 12); X3 ^= *RK++; |
GET_UINT32_LE(X3, input, 12); X3 ^= *RK++; |
||||
|
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
|
|
||||
if (ctx->mode == DECRYPT) |
if (ctx->mode == DECRYPT) |
||||
{ |
{ |
||||
for (i = (ctx->rounds >> 1) - 1; i > 0; i--) |
for (i = (ctx->rounds >> 1) - 1; i > 0; i--) |
||||
{ |
{ |
||||
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
||||
AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); |
AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); |
||||
} |
} |
||||
|
|
||||
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
||||
|
|
||||
X0 = *RK++ ^ \ |
X0 = *RK++ ^ \ |
||||
((uint32_t)RSb[(Y0) & 0xFF]) ^ |
((uint32_t)RSb[(Y0) & 0xFF]) ^ |
||||
((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^ |
((uint32_t)RSb[(Y3 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^ |
((uint32_t)RSb[(Y2 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24); |
((uint32_t)RSb[(Y1 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X1 = *RK++ ^ \ |
X1 = *RK++ ^ \ |
||||
((uint32_t)RSb[(Y1) & 0xFF]) ^ |
((uint32_t)RSb[(Y1) & 0xFF]) ^ |
||||
((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^ |
((uint32_t)RSb[(Y0 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^ |
((uint32_t)RSb[(Y3 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24); |
((uint32_t)RSb[(Y2 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X2 = *RK++ ^ \ |
X2 = *RK++ ^ \ |
||||
((uint32_t)RSb[(Y2) & 0xFF]) ^ |
((uint32_t)RSb[(Y2) & 0xFF]) ^ |
||||
((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^ |
((uint32_t)RSb[(Y1 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^ |
((uint32_t)RSb[(Y0 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24); |
((uint32_t)RSb[(Y3 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X3 = *RK++ ^ \ |
X3 = *RK++ ^ \ |
||||
((uint32_t)RSb[(Y3) & 0xFF]) ^ |
((uint32_t)RSb[(Y3) & 0xFF]) ^ |
||||
((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^ |
((uint32_t)RSb[(Y2 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^ |
((uint32_t)RSb[(Y1 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)RSb[(Y0 >> 24) & 0xFF] << 24); |
((uint32_t)RSb[(Y0 >> 24) & 0xFF] << 24); |
||||
} |
} |
||||
else /* ENCRYPT */ |
else /* ENCRYPT */ |
||||
{ |
{ |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
for (i = (ctx->rounds >> 1) - 1; i > 0; i--) |
for (i = (ctx->rounds >> 1) - 1; i > 0; i--) |
||||
{ |
{ |
||||
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
||||
AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); |
AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); |
||||
} |
} |
||||
|
|
||||
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); |
||||
|
|
||||
X0 = *RK++ ^ \ |
X0 = *RK++ ^ \ |
||||
((uint32_t)FSb[(Y0) & 0xFF]) ^ |
((uint32_t)FSb[(Y0) & 0xFF]) ^ |
||||
((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^ |
((uint32_t)FSb[(Y1 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^ |
((uint32_t)FSb[(Y2 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24); |
((uint32_t)FSb[(Y3 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X1 = *RK++ ^ \ |
X1 = *RK++ ^ \ |
||||
((uint32_t)FSb[(Y1) & 0xFF]) ^ |
((uint32_t)FSb[(Y1) & 0xFF]) ^ |
||||
((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^ |
((uint32_t)FSb[(Y2 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^ |
((uint32_t)FSb[(Y3 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24); |
((uint32_t)FSb[(Y0 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X2 = *RK++ ^ \ |
X2 = *RK++ ^ \ |
||||
((uint32_t)FSb[(Y2) & 0xFF]) ^ |
((uint32_t)FSb[(Y2) & 0xFF]) ^ |
||||
((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^ |
((uint32_t)FSb[(Y3 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^ |
((uint32_t)FSb[(Y0 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24); |
((uint32_t)FSb[(Y1 >> 24) & 0xFF] << 24); |
||||
|
|
||||
X3 = *RK++ ^ \ |
X3 = *RK++ ^ \ |
||||
((uint32_t)FSb[(Y3) & 0xFF]) ^ |
((uint32_t)FSb[(Y3) & 0xFF]) ^ |
||||
((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^ |
((uint32_t)FSb[(Y0 >> 8) & 0xFF] << 8) ^ |
||||
((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^ |
((uint32_t)FSb[(Y1 >> 16) & 0xFF] << 16) ^ |
||||
((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24); |
((uint32_t)FSb[(Y2 >> 24) & 0xFF] << 24); |
||||
|
|
||||
#if AES_DECRYPTION // whether AES decryption is supported
|
#if AES_DECRYPTION // whether AES decryption is supported
|
||||
} |
} |
||||
#endif /* AES_DECRYPTION */ |
#endif /* AES_DECRYPTION */ |
||||
|
|
||||
PUT_UINT32_LE(X0, output, 0); |
PUT_UINT32_LE(X0, output, 0); |
||||
PUT_UINT32_LE(X1, output, 4); |
PUT_UINT32_LE(X1, output, 4); |
||||
PUT_UINT32_LE(X2, output, 8); |
PUT_UINT32_LE(X2, output, 8); |
||||
PUT_UINT32_LE(X3, output, 12); |
PUT_UINT32_LE(X3, output, 12); |
||||
|
|
||||
return(0); |
return(0); |
||||
} |
} |
||||
/* end of aes.c */ |
/* end of aes.c */ |
||||
|
@ -1,78 +1,78 @@ |
|||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL |
* 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 |
* This is a simple and straightforward implementation of the AES Rijndael |
||||
* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus |
* 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 |
* of this work was correctness & accuracy. It is written in 'C' without any |
||||
* particular focus upon optimization or speed. It should be endian (memory |
* particular focus upon optimization or speed. It should be endian (memory |
||||
* byte order) neutral since the few places that care are handled explicitly. |
* 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. |
* 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 |
* 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. |
* reference implementation of the SQRL (Secure Quick Reliable Login) client. |
||||
* |
* |
||||
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
* See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
|
||||
* |
* |
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE |
* 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. |
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK. |
||||
* |
* |
||||
*******************************************************************************/ |
*******************************************************************************/ |
||||
|
|
||||
#pragma once |
#pragma once |
||||
|
|
||||
/******************************************************************************/ |
/******************************************************************************/ |
||||
#define AES_DECRYPTION 0 // whether AES decryption is supported
|
#define AES_DECRYPTION 0 // whether AES decryption is supported
|
||||
/******************************************************************************/ |
/******************************************************************************/ |
||||
|
|
||||
#include <string.h> |
#include <string.h> |
||||
|
|
||||
#define ENCRYPT 1 // specify whether we're encrypting
|
#define ENCRYPT 1 // specify whether we're encrypting
|
||||
#define DECRYPT 0 // or decrypting
|
#define DECRYPT 0 // or decrypting
|
||||
|
|
||||
#if defined(_MSC_VER) |
#if defined(_MSC_VER) |
||||
#include <basetsd.h> |
#include <basetsd.h> |
||||
typedef UINT32 uint32_t; |
typedef UINT32 uint32_t; |
||||
#else |
#else |
||||
#include <inttypes.h> |
#include <inttypes.h> |
||||
#endif |
#endif |
||||
|
|
||||
typedef unsigned char uchar; // add some convienent shorter types
|
typedef unsigned char uchar; // add some convienent shorter types
|
||||
typedef unsigned int uint; |
typedef unsigned int uint; |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use |
* AES_INIT_KEYGEN_TABLES : MUST be called once before any AES use |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
void aes_init_keygen_tables(void); |
void aes_init_keygen_tables(void); |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* AES_CONTEXT : cipher context / holds inter-call data |
* AES_CONTEXT : cipher context / holds inter-call data |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
typedef struct { |
typedef struct { |
||||
int mode; // 1 for Encryption, 0 for Decryption
|
int mode; // 1 for Encryption, 0 for Decryption
|
||||
int rounds; // keysize-based rounds count
|
int rounds; // keysize-based rounds count
|
||||
uint32_t *rk; // pointer to current round key
|
uint32_t *rk; // pointer to current round key
|
||||
uint32_t buf[68]; // key expansion buffer
|
uint32_t buf[68]; // key expansion buffer
|
||||
} aes_context; |
} aes_context; |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* AES_SETKEY : called to expand the key for encryption or decryption |
* AES_SETKEY : called to expand the key for encryption or decryption |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_setkey(aes_context *ctx, // pointer to context
|
int aes_setkey(aes_context *ctx, // pointer to context
|
||||
int mode, // 1 or 0 for Encrypt/Decrypt
|
int mode, // 1 or 0 for Encrypt/Decrypt
|
||||
const uchar *key, // AES input key
|
const uchar *key, // AES input key
|
||||
uint keysize); // size in bytes (must be 16, 24, 32 for
|
uint keysize); // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
// 128, 192 or 256-bit keys respectively)
|
||||
// returns 0 for success
|
// returns 0 for success
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data |
* AES_CIPHER : called to encrypt or decrypt ONE 128-bit block of data |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int aes_cipher(aes_context *ctx, // pointer to context
|
int aes_cipher(aes_context *ctx, // pointer to context
|
||||
const uchar input[16], // 128-bit block to en/decipher
|
const uchar input[16], // 128-bit block to en/decipher
|
||||
uchar output[16]); // 128-bit output result block
|
uchar output[16]); // 128-bit output result block
|
||||
// returns 0 for success
|
// returns 0 for success
|
||||
|
File diff suppressed because it is too large
@ -1,183 +1,183 @@ |
|||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL |
* 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 |
* This is a simple and straightforward implementation of AES-GCM authenticated |
||||
* encryption. The focus of this work was correctness & accuracy. It is written |
* encryption. The focus of this work was correctness & accuracy. It is written |
||||
* in straight 'C' without any particular focus upon optimization or speed. It |
* 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 |
* should be endian (memory byte order) neutral since the few places that care |
||||
* are handled explicitly. |
* are handled explicitly. |
||||
* |
* |
||||
* This implementation of AES-GCM was created by Steven M. Gibson of GRC.com. |
* 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 |
* 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. |
* reference implementation of the SQRL (Secure Quick Reliable Login) client. |
||||
* |
* |
||||
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
* See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
|
||||
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \ |
* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \ |
||||
* gcm/gcm-revised-spec.pdf |
* gcm/gcm-revised-spec.pdf |
||||
* |
* |
||||
* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE |
* 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. |
* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK. |
||||
* |
* |
||||
*******************************************************************************/ |
*******************************************************************************/ |
||||
#pragma once |
#pragma once |
||||
|
|
||||
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
#define GCM_AUTH_FAILURE 0x55555555 // authentication failure
|
||||
|
|
||||
#include "aes.h" // gcm_context includes aes_context |
#include "aes.h" // gcm_context includes aes_context |
||||
|
|
||||
#if defined(_MSC_VER) |
#if defined(_MSC_VER) |
||||
#include <basetsd.h> |
#include <basetsd.h> |
||||
typedef unsigned int size_t;// use the right type for length declarations
|
typedef unsigned int size_t;// use the right type for length declarations
|
||||
typedef UINT32 uint32_t; |
typedef UINT32 uint32_t; |
||||
typedef UINT64 uint64_t; |
typedef UINT64 uint64_t; |
||||
#else |
#else |
||||
#include <stdint.h> |
#include <stdint.h> |
||||
#endif |
#endif |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx |
* GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
typedef struct { |
typedef struct { |
||||
int mode; // cipher direction: encrypt/decrypt
|
int mode; // cipher direction: encrypt/decrypt
|
||||
uint64_t len; // cipher data length processed so far
|
uint64_t len; // cipher data length processed so far
|
||||
uint64_t add_len; // total add data length
|
uint64_t add_len; // total add data length
|
||||
uint64_t HL[16]; // precalculated lo-half HTable
|
uint64_t HL[16]; // precalculated lo-half HTable
|
||||
uint64_t HH[16]; // precalculated hi-half HTable
|
uint64_t HH[16]; // precalculated hi-half HTable
|
||||
uchar base_ectr[16]; // first counter-mode cipher output for tag
|
uchar base_ectr[16]; // first counter-mode cipher output for tag
|
||||
uchar y[16]; // the current cipher-input IV|Counter value
|
uchar y[16]; // the current cipher-input IV|Counter value
|
||||
uchar buf[16]; // buf working value
|
uchar buf[16]; // buf working value
|
||||
aes_context aes_ctx; // cipher context used
|
aes_context aes_ctx; // cipher context used
|
||||
} gcm_context; |
} gcm_context; |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* GCM_CONTEXT : MUST be called once before ANY use of this library |
* GCM_CONTEXT : MUST be called once before ANY use of this library |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_initialize(void); |
int gcm_initialize(void); |
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* GCM_SETKEY : sets the GCM (and AES) keying material for use |
* GCM_SETKEY : sets the GCM (and AES) keying material for use |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_setkey(gcm_context *ctx, // caller-provided context ptr
|
int gcm_setkey(gcm_context *ctx, // caller-provided context ptr
|
||||
const uchar *key, // pointer to cipher key
|
const uchar *key, // pointer to cipher key
|
||||
const uint keysize // size in bytes (must be 16, 24, 32 for
|
const uint keysize // size in bytes (must be 16, 24, 32 for
|
||||
// 128, 192 or 256-bit keys respectively)
|
// 128, 192 or 256-bit keys respectively)
|
||||
); // returns 0 for success
|
); // returns 0 for success
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_CRYPT_AND_TAG |
* GCM_CRYPT_AND_TAG |
||||
* |
* |
||||
* This either encrypts or decrypts the user-provided data and, either |
* This either encrypts or decrypts the user-provided data and, either |
||||
* way, generates an authentication tag of the requested length. It must be |
* 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. |
* 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 |
* The user would typically call this explicitly to ENCRYPT a buffer of data |
||||
* and optional associated data, and produce its an authentication tag. |
* and optional associated data, and produce its an authentication tag. |
||||
* |
* |
||||
* To reverse the process the user would typically call the companion |
* To reverse the process the user would typically call the companion |
||||
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided |
* GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided |
||||
* authentication tag. The GCM_AUTH_DECRYPT function calls this function |
* authentication tag. The GCM_AUTH_DECRYPT function calls this function |
||||
* to perform its decryption and tag generation, which it then compares. |
* to perform its decryption and tag generation, which it then compares. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_crypt_and_tag( |
int gcm_crypt_and_tag( |
||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context *ctx, // gcm context with key already setup
|
||||
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
|
int mode, // cipher direction: ENCRYPT (1) or DECRYPT (0)
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||
uchar *tag, // pointer to the tag to be generated
|
uchar *tag, // pointer to the tag to be generated
|
||||
size_t tag_len); // byte length of the tag to be generated
|
size_t tag_len); // byte length of the tag to be generated
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_AUTH_DECRYPT |
* GCM_AUTH_DECRYPT |
||||
* |
* |
||||
* This DECRYPTS a user-provided data buffer with optional associated data. |
* This DECRYPTS a user-provided data buffer with optional associated data. |
||||
* It then verifies a user-supplied authentication tag against the tag just |
* 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. |
* 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 |
* This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption |
||||
* and authentication tag generation. |
* and authentication tag generation. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_auth_decrypt( |
int gcm_auth_decrypt( |
||||
gcm_context *ctx, // gcm context with key already setup
|
gcm_context *ctx, // gcm context with key already setup
|
||||
const uchar *iv, // pointer to the 12-byte initialization vector
|
const uchar *iv, // pointer to the 12-byte initialization vector
|
||||
size_t iv_len, // byte length if the IV. should always be 12
|
size_t iv_len, // byte length if the IV. should always be 12
|
||||
const uchar *add, // pointer to the non-ciphered additional data
|
const uchar *add, // pointer to the non-ciphered additional data
|
||||
size_t add_len, // byte length of the additional AEAD data
|
size_t add_len, // byte length of the additional AEAD data
|
||||
const uchar *input, // pointer to the cipher data source
|
const uchar *input, // pointer to the cipher data source
|
||||
uchar *output, // pointer to the cipher data destination
|
uchar *output, // pointer to the cipher data destination
|
||||
size_t length, // byte length of the cipher data
|
size_t length, // byte length of the cipher data
|
||||
const uchar *tag, // pointer to the tag to be authenticated
|
const uchar *tag, // pointer to the tag to be authenticated
|
||||
size_t tag_len); // byte length of the tag <= 16
|
size_t tag_len); // byte length of the tag <= 16
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_START |
* GCM_START |
||||
* |
* |
||||
* Given a user-provided GCM context, this initializes it, sets the encryption |
* Given a user-provided GCM context, this initializes it, sets the encryption |
||||
* mode, and preprocesses the initialization vector and additional AEAD data. |
* mode, and preprocesses the initialization vector and additional AEAD data. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_start(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
int mode, // ENCRYPT (1) or DECRYPT (0)
|
int mode, // ENCRYPT (1) or DECRYPT (0)
|
||||
const uchar *iv, // pointer to initialization vector
|
const uchar *iv, // pointer to initialization vector
|
||||
size_t iv_len, // IV length in bytes (should == 12)
|
size_t iv_len, // IV length in bytes (should == 12)
|
||||
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
const uchar *add, // pointer to additional AEAD data (NULL if none)
|
||||
size_t add_len); // length of additional AEAD data (bytes)
|
size_t add_len); // length of additional AEAD data (bytes)
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_UPDATE |
* GCM_UPDATE |
||||
* |
* |
||||
* This is called once or more to process bulk plaintext or ciphertext data. |
* 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 |
* 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 |
* 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 |
* invocation MUST be called with length mod 16 == 0. (Only the final call can |
||||
* have a partial block length of < 128 bits.) |
* have a partial block length of < 128 bits.) |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_update(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
size_t length, // length, in bytes, of data to process
|
size_t length, // length, in bytes, of data to process
|
||||
const uchar *input, // pointer to source data
|
const uchar *input, // pointer to source data
|
||||
uchar *output); // pointer to destination data
|
uchar *output); // pointer to destination data
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_FINISH |
* GCM_FINISH |
||||
* |
* |
||||
* This is called once after all calls to GCM_UPDATE to finalize the GCM. |
* 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. |
* It performs the final GHASH to produce the resulting authentication TAG. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
int gcm_finish(gcm_context *ctx, // pointer to user-provided GCM context
|
||||
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
uchar *tag, // ptr to tag buffer - NULL if tag_len = 0
|
||||
size_t tag_len); // length, in bytes, of the tag-receiving buf
|
size_t tag_len); // length, in bytes, of the tag-receiving buf
|
||||
|
|
||||
|
|
||||
/******************************************************************************
|
/******************************************************************************
|
||||
* |
* |
||||
* GCM_ZERO_CTX |
* GCM_ZERO_CTX |
||||
* |
* |
||||
* The GCM context contains both the GCM context and the AES context. |
* The GCM context contains both the GCM context and the AES context. |
||||
* This includes keying and key-related material which is security- |
* This includes keying and key-related material which is security- |
||||
* sensitive, so it MUST be zeroed after use. This function does that. |
* sensitive, so it MUST be zeroed after use. This function does that. |
||||
* |
* |
||||
******************************************************************************/ |
******************************************************************************/ |
||||
void gcm_zero_ctx(gcm_context *ctx); |
void gcm_zero_ctx(gcm_context *ctx); |
||||
|
Loading…
Reference in new issue