nfqws: crypto dos2unix

This commit is contained in:
bol-van 2022-03-25 19:55:54 +03:00
parent 6c31029999
commit 4dc6639b5a
4 changed files with 1255 additions and 1255 deletions

View File

@ -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 */

View File

@ -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 Load Diff

View File

@ -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);