A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Revision:
6:819c17738dc2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/aes-gcm/aes.c	Sun Sep 01 18:15:12 2019 +0000
@@ -0,0 +1,477 @@
+/******************************************************************************
+*
+* THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
+*
+* This is a simple and straightforward implementation of the AES Rijndael
+* 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
+* of this work was correctness & accuracy.  It is written in 'C' without any
+* particular focus upon optimization or speed. It should be endian (memory
+* byte order) neutral since the few places that care are handled explicitly.
+*
+* This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
+*
+* It is intended for general purpose use, but was written in support of GRC's
+* reference implementation of the SQRL (Secure Quick Reliable Login) client.
+*
+* See:    http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
+*
+* NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
+* REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
+*
+*******************************************************************************/
+
+#include "aes.h"
+
+static int aes_tables_inited = 0;   // run-once flag for performing key
+                                    // expasion table generation (see below)
+/*
+ *  The following static local tables must be filled-in before the first use of
+ *  the GCM or AES ciphers. They are used for the AES key expansion/scheduling
+ *  and once built are read-only and thread safe. The "gcm_initialize" function
+ *  must be called once during system initialization to populate these arrays
+ *  for subsequent use by the AES key scheduler. If they have not been built
+ *  before attempted use, an error will be returned to the caller.
+ *
+ *  NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since
+ *  GCM uses AES in counter-mode, where the AES cipher output is XORed with
+ *  the GCM input, we ONLY NEED AES encryption.  Thus, to save space AES
+ *  decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
+ */
+                            // We always need our forward tables
+static uchar FSb[256];      // Forward substitution box (FSb)
+static uint32_t FT0[256];   // Forward key schedule assembly tables
+static uint32_t FT1[256];
+static uint32_t FT2[256];
+static uint32_t FT3[256];
+
+#if AES_DECRYPTION          // We ONLY need reverse for decryption
+static uchar RSb[256];      // Reverse substitution box (RSb)
+static uint32_t RT0[256];   // Reverse key schedule assembly tables
+static uint32_t RT1[256];
+static uint32_t RT2[256];
+static uint32_t RT3[256];
+#endif                      /* AES_DECRYPTION */
+
+static uint32_t RCON[10];   // AES round constants
+
+/* 
+ * Platform Endianness Neutralizing Load and Store Macro definitions
+ * AES wants platform-neutral Little Endian (LE) byte ordering
+ */
+#define GET_UINT32_LE(n,b,i) {                  \
+    (n) = ( (uint32_t) (b)[(i)    ]       )     \
+        | ( (uint32_t) (b)[(i) + 1] <<  8 )     \
+        | ( (uint32_t) (b)[(i) + 2] << 16 )     \
+        | ( (uint32_t) (b)[(i) + 3] << 24 ); }
+
+#define PUT_UINT32_LE(n,b,i) {                  \
+    (b)[(i)    ] = (uchar) ( (n)       );       \
+    (b)[(i) + 1] = (uchar) ( (n) >>  8 );       \
+    (b)[(i) + 2] = (uchar) ( (n) >> 16 );       \
+    (b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
+
+/*
+ *  AES forward and reverse encryption round processing macros
+ */
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ FT0[ ( Y0       ) & 0xFF ] ^   \
+                 FT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ FT0[ ( Y1       ) & 0xFF ] ^   \
+                 FT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y0 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ FT0[ ( Y2       ) & 0xFF ] ^   \
+                 FT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ FT0[ ( Y3       ) & 0xFF ] ^   \
+                 FT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 FT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 FT3[ ( Y2 >> 24 ) & 0xFF ];    \
+}
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3)     \
+{                                               \
+    X0 = *RK++ ^ RT0[ ( Y0       ) & 0xFF ] ^   \
+                 RT1[ ( Y3 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y2 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y1 >> 24 ) & 0xFF ];    \
+                                                \
+    X1 = *RK++ ^ RT0[ ( Y1       ) & 0xFF ] ^   \
+                 RT1[ ( Y0 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y3 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y2 >> 24 ) & 0xFF ];    \
+                                                \
+    X2 = *RK++ ^ RT0[ ( Y2       ) & 0xFF ] ^   \
+                 RT1[ ( Y1 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y0 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y3 >> 24 ) & 0xFF ];    \
+                                                \
+    X3 = *RK++ ^ RT0[ ( Y3       ) & 0xFF ] ^   \
+                 RT1[ ( Y2 >>  8 ) & 0xFF ] ^   \
+                 RT2[ ( Y1 >> 16 ) & 0xFF ] ^   \
+                 RT3[ ( Y0 >> 24 ) & 0xFF ];    \
+}
+
+/*
+ *  These macros improve the readability of the key
+ *  generation initialization code by collapsing
+ *  repetitive common operations into logical pieces.
+ */
+#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
+#define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
+#define CPY128   { *RK++ = *SK++; *RK++ = *SK++; \
+                   *RK++ = *SK++; *RK++ = *SK++; }
+
+/******************************************************************************
+ *
+ *  AES_INIT_KEYGEN_TABLES
+ *
+ *  Fills the AES key expansion tables allocated above with their static
+ *  data. This is not "per key" data, but static system-wide read-only
+ *  table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once
+ *  at system initialization to setup the tables for all subsequent use.
+ *
+ ******************************************************************************/
+void aes_init_keygen_tables( void )
+{
+    int i, x, y, z;     // general purpose iteration and computation locals
+    int pow[256];
+    int log[256];
+
+    // fill the 'pow' and 'log' tables over GF(2^8)
+    for( i = 0, x = 1; i < 256; i++ )   {
+        pow[i] = x;
+        log[x] = i;
+        x = ( x ^ XTIME( x ) ) & 0xFF;
+    }
+    // compute the round constants
+    for( i = 0, x = 1; i < 10; i++ )    {
+        RCON[i] = (uint32_t) x;
+        x = XTIME( x ) & 0xFF;
+    }
+    // fill the forward and reverse substitution boxes
+    FSb[0x00] = 0x63;
+#if AES_DECRYPTION  // whether AES decryption is supported
+    RSb[0x63] = 0x00;
+#endif /* AES_DECRYPTION */
+
+    for( i = 1; i < 256; i++ )          {
+        x = y = pow[255 - log[i]];
+        MIX(x,y);
+        MIX(x,y);
+        MIX(x,y);
+        MIX(x,y); 
+        FSb[i] = (uchar) ( x ^= 0x63 );
+#if AES_DECRYPTION  // whether AES decryption is supported
+        RSb[x] = (uchar) i;
+#endif /* AES_DECRYPTION */
+
+    }
+    // generate the forward and reverse key expansion tables
+    for( i = 0; i < 256; i++ )          {
+        x = FSb[i];
+        y = XTIME( x ) & 0xFF;
+        z =  ( y ^ x ) & 0xFF;
+
+        FT0[i] = ( (uint32_t) y       ) ^ ( (uint32_t) x <<  8 ) ^
+                 ( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 );
+
+        FT1[i] = ROTL8( FT0[i] );
+        FT2[i] = ROTL8( FT1[i] );
+        FT3[i] = ROTL8( FT2[i] );
+
+#if AES_DECRYPTION  // whether AES decryption is supported
+        x = RSb[i];
+
+        RT0[i] = ( (uint32_t) MUL( 0x0E, x )       ) ^
+                 ( (uint32_t) MUL( 0x09, x ) <<  8 ) ^
+                 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
+                 ( (uint32_t) MUL( 0x0B, x ) << 24 );
+
+        RT1[i] = ROTL8( RT0[i] );
+        RT2[i] = ROTL8( RT1[i] );
+        RT3[i] = ROTL8( RT2[i] );
+#endif /* AES_DECRYPTION */
+    }
+    aes_tables_inited = 1;  // flag that the tables have been generated
+}                           // to permit subsequent use of the AES cipher
+
+/******************************************************************************
+ *
+ *  AES_SET_ENCRYPTION_KEY
+ *
+ *  This is called by 'aes_setkey' when we're establishing a key for
+ *  subsequent encryption.  We give it a pointer to the encryption
+ *  context, a pointer to the key, and the key's length in bytes.
+ *  Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
+ *
+ ******************************************************************************/
+int aes_set_encryption_key( aes_context *ctx,
+                            const uchar *key,
+                            uint keysize )
+{
+    uint i;                 // general purpose iteration local
+    uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
+
+    for( i = 0; i < (keysize >> 2); i++ ) {
+        GET_UINT32_LE( RK[i], key, i << 2 );
+    }
+
+    switch( ctx->rounds )
+    {
+        case 10:
+            for( i = 0; i < 10; i++, RK += 4 ) {
+                RK[4]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[3] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[3]       ) & 0xFF ] << 24 );
+
+                RK[5]  = RK[1] ^ RK[4];
+                RK[6]  = RK[2] ^ RK[5];
+                RK[7]  = RK[3] ^ RK[6];
+            }
+            break;
+
+        case 12:
+            for( i = 0; i < 8; i++, RK += 6 ) {
+                RK[6]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[5] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[5]       ) & 0xFF ] << 24 );
+
+                RK[7]  = RK[1] ^ RK[6];
+                RK[8]  = RK[2] ^ RK[7];
+                RK[9]  = RK[3] ^ RK[8];
+                RK[10] = RK[4] ^ RK[9];
+                RK[11] = RK[5] ^ RK[10];
+            }
+            break;
+
+        case 14:
+            for( i = 0; i < 7; i++, RK += 8 ) {
+                RK[8]  = RK[0] ^ RCON[i] ^
+                ( (uint32_t) FSb[ ( RK[7] >>  8 ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[7]       ) & 0xFF ] << 24 );
+
+                RK[9]  = RK[1] ^ RK[8];
+                RK[10] = RK[2] ^ RK[9];
+                RK[11] = RK[3] ^ RK[10];
+
+                RK[12] = RK[4] ^
+                ( (uint32_t) FSb[ ( RK[11]       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( RK[11] >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
+
+                RK[13] = RK[5] ^ RK[12];
+                RK[14] = RK[6] ^ RK[13];
+                RK[15] = RK[7] ^ RK[14];
+            }
+            break;
+    }
+    return( 0 );
+}
+
+#if AES_DECRYPTION  // whether AES decryption is supported
+
+/******************************************************************************
+ *
+ *  AES_SET_DECRYPTION_KEY
+ *
+ *  This is called by 'aes_setkey' when we're establishing a
+ *  key for subsequent decryption.  We give it a pointer to
+ *  the encryption context, a pointer to the key, and the key's
+ *  length in bits. Valid lengths are: 128, 192, or 256 bits.
+ *
+ ******************************************************************************/
+int aes_set_decryption_key( aes_context *ctx,
+                            const uchar *key,
+                            uint keysize )
+{
+    int i, j;
+    aes_context cty;            // a calling aes context for set_encryption_key
+    uint32_t *RK = ctx->rk;     // initialize our RoundKey buffer pointer
+    uint32_t *SK;
+    int ret;
+
+    cty.rounds = ctx->rounds;   // initialize our local aes context
+    cty.rk = cty.buf;           // round count and key buf pointer
+
+    if (( ret = aes_set_encryption_key( &cty, key, keysize )) != 0 )
+        return( ret );
+
+    SK = cty.rk + cty.rounds * 4;
+
+    CPY128  // copy a 128-bit block from *SK to *RK
+
+    for( i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8 ) {
+        for( j = 0; j < 4; j++, SK++ ) {
+            *RK++ = RT0[ FSb[ ( *SK       ) & 0xFF ] ] ^
+                    RT1[ FSb[ ( *SK >>  8 ) & 0xFF ] ] ^
+                    RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
+                    RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
+        }
+    }
+    CPY128  // copy a 128-bit block from *SK to *RK
+    memset( &cty, 0, sizeof( aes_context ) );   // clear local aes context
+    return( 0 );
+}
+
+#endif /* AES_DECRYPTION */
+
+/******************************************************************************
+ *
+ *  AES_SETKEY
+ *
+ *  Invoked to establish the key schedule for subsequent encryption/decryption
+ *
+ ******************************************************************************/
+int aes_setkey( aes_context *ctx,   // AES context provided by our caller
+                int mode,           // ENCRYPT or DECRYPT flag
+                const uchar *key,   // pointer to the key
+                uint keysize )      // key length in bytes
+{
+    // since table initialization is not thread safe, we could either add
+    // system-specific mutexes and init the AES key generation tables on
+    // demand, or ask the developer to simply call "gcm_initialize" once during
+    // application startup before threading begins. That's what we choose.
+    if( !aes_tables_inited ) return ( 0 );  // fail the call when not inited.
+    
+    ctx->mode = mode;       // capture the key type we're creating
+    ctx->rk = ctx->buf;     // initialize our round key pointer
+
+    switch( keysize )       // set the rounds count based upon the keysize
+    {
+        case 16: ctx->rounds = 10; break;   // 16-byte, 128-bit key
+        case 24: ctx->rounds = 12; break;   // 24-byte, 192-bit key
+        case 32: ctx->rounds = 14; break;   // 32-byte, 256-bit key
+    }
+
+#if AES_DECRYPTION
+    if( mode == DECRYPT )   // expand our key for encryption or decryption
+        return( aes_set_decryption_key( ctx, key, keysize ) );
+    else     /* ENCRYPT */
+#endif /* AES_DECRYPTION */
+        return( aes_set_encryption_key( ctx, key, keysize ) );
+}
+
+/******************************************************************************
+ *
+ *  AES_CIPHER
+ *
+ *  Perform AES encryption and decryption.
+ *  The AES context will have been setup with the encryption mode
+ *  and all keying information appropriate for the task.
+ *
+ ******************************************************************************/
+int aes_cipher( aes_context *ctx,
+                    const uchar input[16],
+                    uchar output[16] )
+{
+    int i;
+    uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;   // general purpose locals
+
+    RK = ctx->rk;
+
+    GET_UINT32_LE( X0, input,  0 ); X0 ^= *RK++;    // load our 128-bit
+    GET_UINT32_LE( X1, input,  4 ); X1 ^= *RK++;    // input buffer in a storage
+    GET_UINT32_LE( X2, input,  8 ); X2 ^= *RK++;    // memory endian-neutral way
+    GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
+
+#if AES_DECRYPTION  // whether AES decryption is supported
+
+    if( ctx->mode == DECRYPT )
+    {
+        for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
+        {
+            AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (uint32_t) RSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (uint32_t) RSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+    }
+    else /* ENCRYPT */
+    {
+#endif /* AES_DECRYPTION */
+
+        for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
+        {
+            AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+            AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+        }
+
+        AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+
+        X0 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y0       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y1 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
+
+        X1 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y1       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y2 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
+
+        X2 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y2       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y3 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
+
+        X3 = *RK++ ^ \
+                ( (uint32_t) FSb[ ( Y3       ) & 0xFF ]       ) ^
+                ( (uint32_t) FSb[ ( Y0 >>  8 ) & 0xFF ] <<  8 ) ^
+                ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
+                ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
+
+#if AES_DECRYPTION  // whether AES decryption is supported
+    }
+#endif /* AES_DECRYPTION */
+
+    PUT_UINT32_LE( X0, output,  0 );
+    PUT_UINT32_LE( X1, output,  4 );
+    PUT_UINT32_LE( X2, output,  8 );
+    PUT_UINT32_LE( X3, output, 12 );
+
+    return( 0 );
+}
+/* end of aes.c */