A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sun Sep 01 18:15:12 2019 +0000
Revision:
6:819c17738dc2
Making progress - now have decryption working.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 6:819c17738dc2 1 /******************************************************************************
andrewboyson 6:819c17738dc2 2 *
andrewboyson 6:819c17738dc2 3 * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL
andrewboyson 6:819c17738dc2 4 *
andrewboyson 6:819c17738dc2 5 * This is a simple and straightforward implementation of the AES Rijndael
andrewboyson 6:819c17738dc2 6 * 128-bit block cipher designed by Vincent Rijmen and Joan Daemen. The focus
andrewboyson 6:819c17738dc2 7 * of this work was correctness & accuracy. It is written in 'C' without any
andrewboyson 6:819c17738dc2 8 * particular focus upon optimization or speed. It should be endian (memory
andrewboyson 6:819c17738dc2 9 * byte order) neutral since the few places that care are handled explicitly.
andrewboyson 6:819c17738dc2 10 *
andrewboyson 6:819c17738dc2 11 * This implementation of Rijndael was created by Steven M. Gibson of GRC.com.
andrewboyson 6:819c17738dc2 12 *
andrewboyson 6:819c17738dc2 13 * It is intended for general purpose use, but was written in support of GRC's
andrewboyson 6:819c17738dc2 14 * reference implementation of the SQRL (Secure Quick Reliable Login) client.
andrewboyson 6:819c17738dc2 15 *
andrewboyson 6:819c17738dc2 16 * See: http://csrc.nist.gov/archive/aes/rijndael/wsdindex.html
andrewboyson 6:819c17738dc2 17 *
andrewboyson 6:819c17738dc2 18 * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE
andrewboyson 6:819c17738dc2 19 * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK.
andrewboyson 6:819c17738dc2 20 *
andrewboyson 6:819c17738dc2 21 *******************************************************************************/
andrewboyson 6:819c17738dc2 22
andrewboyson 6:819c17738dc2 23 #include "aes.h"
andrewboyson 6:819c17738dc2 24
andrewboyson 6:819c17738dc2 25 static int aes_tables_inited = 0; // run-once flag for performing key
andrewboyson 6:819c17738dc2 26 // expasion table generation (see below)
andrewboyson 6:819c17738dc2 27 /*
andrewboyson 6:819c17738dc2 28 * The following static local tables must be filled-in before the first use of
andrewboyson 6:819c17738dc2 29 * the GCM or AES ciphers. They are used for the AES key expansion/scheduling
andrewboyson 6:819c17738dc2 30 * and once built are read-only and thread safe. The "gcm_initialize" function
andrewboyson 6:819c17738dc2 31 * must be called once during system initialization to populate these arrays
andrewboyson 6:819c17738dc2 32 * for subsequent use by the AES key scheduler. If they have not been built
andrewboyson 6:819c17738dc2 33 * before attempted use, an error will be returned to the caller.
andrewboyson 6:819c17738dc2 34 *
andrewboyson 6:819c17738dc2 35 * NOTE: GCM Encryption/Decryption does NOT REQUIRE AES decryption. Since
andrewboyson 6:819c17738dc2 36 * GCM uses AES in counter-mode, where the AES cipher output is XORed with
andrewboyson 6:819c17738dc2 37 * the GCM input, we ONLY NEED AES encryption. Thus, to save space AES
andrewboyson 6:819c17738dc2 38 * decryption is typically disabled by setting AES_DECRYPTION to 0 in aes.h.
andrewboyson 6:819c17738dc2 39 */
andrewboyson 6:819c17738dc2 40 // We always need our forward tables
andrewboyson 6:819c17738dc2 41 static uchar FSb[256]; // Forward substitution box (FSb)
andrewboyson 6:819c17738dc2 42 static uint32_t FT0[256]; // Forward key schedule assembly tables
andrewboyson 6:819c17738dc2 43 static uint32_t FT1[256];
andrewboyson 6:819c17738dc2 44 static uint32_t FT2[256];
andrewboyson 6:819c17738dc2 45 static uint32_t FT3[256];
andrewboyson 6:819c17738dc2 46
andrewboyson 6:819c17738dc2 47 #if AES_DECRYPTION // We ONLY need reverse for decryption
andrewboyson 6:819c17738dc2 48 static uchar RSb[256]; // Reverse substitution box (RSb)
andrewboyson 6:819c17738dc2 49 static uint32_t RT0[256]; // Reverse key schedule assembly tables
andrewboyson 6:819c17738dc2 50 static uint32_t RT1[256];
andrewboyson 6:819c17738dc2 51 static uint32_t RT2[256];
andrewboyson 6:819c17738dc2 52 static uint32_t RT3[256];
andrewboyson 6:819c17738dc2 53 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 54
andrewboyson 6:819c17738dc2 55 static uint32_t RCON[10]; // AES round constants
andrewboyson 6:819c17738dc2 56
andrewboyson 6:819c17738dc2 57 /*
andrewboyson 6:819c17738dc2 58 * Platform Endianness Neutralizing Load and Store Macro definitions
andrewboyson 6:819c17738dc2 59 * AES wants platform-neutral Little Endian (LE) byte ordering
andrewboyson 6:819c17738dc2 60 */
andrewboyson 6:819c17738dc2 61 #define GET_UINT32_LE(n,b,i) { \
andrewboyson 6:819c17738dc2 62 (n) = ( (uint32_t) (b)[(i) ] ) \
andrewboyson 6:819c17738dc2 63 | ( (uint32_t) (b)[(i) + 1] << 8 ) \
andrewboyson 6:819c17738dc2 64 | ( (uint32_t) (b)[(i) + 2] << 16 ) \
andrewboyson 6:819c17738dc2 65 | ( (uint32_t) (b)[(i) + 3] << 24 ); }
andrewboyson 6:819c17738dc2 66
andrewboyson 6:819c17738dc2 67 #define PUT_UINT32_LE(n,b,i) { \
andrewboyson 6:819c17738dc2 68 (b)[(i) ] = (uchar) ( (n) ); \
andrewboyson 6:819c17738dc2 69 (b)[(i) + 1] = (uchar) ( (n) >> 8 ); \
andrewboyson 6:819c17738dc2 70 (b)[(i) + 2] = (uchar) ( (n) >> 16 ); \
andrewboyson 6:819c17738dc2 71 (b)[(i) + 3] = (uchar) ( (n) >> 24 ); }
andrewboyson 6:819c17738dc2 72
andrewboyson 6:819c17738dc2 73 /*
andrewboyson 6:819c17738dc2 74 * AES forward and reverse encryption round processing macros
andrewboyson 6:819c17738dc2 75 */
andrewboyson 6:819c17738dc2 76 #define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
andrewboyson 6:819c17738dc2 77 { \
andrewboyson 6:819c17738dc2 78 X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 79 FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 80 FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 81 FT3[ ( Y3 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 82 \
andrewboyson 6:819c17738dc2 83 X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 84 FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 85 FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 86 FT3[ ( Y0 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 87 \
andrewboyson 6:819c17738dc2 88 X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 89 FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 90 FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 91 FT3[ ( Y1 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 92 \
andrewboyson 6:819c17738dc2 93 X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 94 FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 95 FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 96 FT3[ ( Y2 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 97 }
andrewboyson 6:819c17738dc2 98
andrewboyson 6:819c17738dc2 99 #define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
andrewboyson 6:819c17738dc2 100 { \
andrewboyson 6:819c17738dc2 101 X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 102 RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 103 RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 104 RT3[ ( Y1 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 105 \
andrewboyson 6:819c17738dc2 106 X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 107 RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 108 RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 109 RT3[ ( Y2 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 110 \
andrewboyson 6:819c17738dc2 111 X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 112 RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 113 RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 114 RT3[ ( Y3 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 115 \
andrewboyson 6:819c17738dc2 116 X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 117 RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 118 RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \
andrewboyson 6:819c17738dc2 119 RT3[ ( Y0 >> 24 ) & 0xFF ]; \
andrewboyson 6:819c17738dc2 120 }
andrewboyson 6:819c17738dc2 121
andrewboyson 6:819c17738dc2 122 /*
andrewboyson 6:819c17738dc2 123 * These macros improve the readability of the key
andrewboyson 6:819c17738dc2 124 * generation initialization code by collapsing
andrewboyson 6:819c17738dc2 125 * repetitive common operations into logical pieces.
andrewboyson 6:819c17738dc2 126 */
andrewboyson 6:819c17738dc2 127 #define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 )
andrewboyson 6:819c17738dc2 128 #define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
andrewboyson 6:819c17738dc2 129 #define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 )
andrewboyson 6:819c17738dc2 130 #define MIX(x,y) { y = ( (y << 1) | (y >> 7) ) & 0xFF; x ^= y; }
andrewboyson 6:819c17738dc2 131 #define CPY128 { *RK++ = *SK++; *RK++ = *SK++; \
andrewboyson 6:819c17738dc2 132 *RK++ = *SK++; *RK++ = *SK++; }
andrewboyson 6:819c17738dc2 133
andrewboyson 6:819c17738dc2 134 /******************************************************************************
andrewboyson 6:819c17738dc2 135 *
andrewboyson 6:819c17738dc2 136 * AES_INIT_KEYGEN_TABLES
andrewboyson 6:819c17738dc2 137 *
andrewboyson 6:819c17738dc2 138 * Fills the AES key expansion tables allocated above with their static
andrewboyson 6:819c17738dc2 139 * data. This is not "per key" data, but static system-wide read-only
andrewboyson 6:819c17738dc2 140 * table data. THIS FUNCTION IS NOT THREAD SAFE. It must be called once
andrewboyson 6:819c17738dc2 141 * at system initialization to setup the tables for all subsequent use.
andrewboyson 6:819c17738dc2 142 *
andrewboyson 6:819c17738dc2 143 ******************************************************************************/
andrewboyson 6:819c17738dc2 144 void aes_init_keygen_tables( void )
andrewboyson 6:819c17738dc2 145 {
andrewboyson 6:819c17738dc2 146 int i, x, y, z; // general purpose iteration and computation locals
andrewboyson 6:819c17738dc2 147 int pow[256];
andrewboyson 6:819c17738dc2 148 int log[256];
andrewboyson 6:819c17738dc2 149
andrewboyson 6:819c17738dc2 150 // fill the 'pow' and 'log' tables over GF(2^8)
andrewboyson 6:819c17738dc2 151 for( i = 0, x = 1; i < 256; i++ ) {
andrewboyson 6:819c17738dc2 152 pow[i] = x;
andrewboyson 6:819c17738dc2 153 log[x] = i;
andrewboyson 6:819c17738dc2 154 x = ( x ^ XTIME( x ) ) & 0xFF;
andrewboyson 6:819c17738dc2 155 }
andrewboyson 6:819c17738dc2 156 // compute the round constants
andrewboyson 6:819c17738dc2 157 for( i = 0, x = 1; i < 10; i++ ) {
andrewboyson 6:819c17738dc2 158 RCON[i] = (uint32_t) x;
andrewboyson 6:819c17738dc2 159 x = XTIME( x ) & 0xFF;
andrewboyson 6:819c17738dc2 160 }
andrewboyson 6:819c17738dc2 161 // fill the forward and reverse substitution boxes
andrewboyson 6:819c17738dc2 162 FSb[0x00] = 0x63;
andrewboyson 6:819c17738dc2 163 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 164 RSb[0x63] = 0x00;
andrewboyson 6:819c17738dc2 165 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 166
andrewboyson 6:819c17738dc2 167 for( i = 1; i < 256; i++ ) {
andrewboyson 6:819c17738dc2 168 x = y = pow[255 - log[i]];
andrewboyson 6:819c17738dc2 169 MIX(x,y);
andrewboyson 6:819c17738dc2 170 MIX(x,y);
andrewboyson 6:819c17738dc2 171 MIX(x,y);
andrewboyson 6:819c17738dc2 172 MIX(x,y);
andrewboyson 6:819c17738dc2 173 FSb[i] = (uchar) ( x ^= 0x63 );
andrewboyson 6:819c17738dc2 174 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 175 RSb[x] = (uchar) i;
andrewboyson 6:819c17738dc2 176 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 177
andrewboyson 6:819c17738dc2 178 }
andrewboyson 6:819c17738dc2 179 // generate the forward and reverse key expansion tables
andrewboyson 6:819c17738dc2 180 for( i = 0; i < 256; i++ ) {
andrewboyson 6:819c17738dc2 181 x = FSb[i];
andrewboyson 6:819c17738dc2 182 y = XTIME( x ) & 0xFF;
andrewboyson 6:819c17738dc2 183 z = ( y ^ x ) & 0xFF;
andrewboyson 6:819c17738dc2 184
andrewboyson 6:819c17738dc2 185 FT0[i] = ( (uint32_t) y ) ^ ( (uint32_t) x << 8 ) ^
andrewboyson 6:819c17738dc2 186 ( (uint32_t) x << 16 ) ^ ( (uint32_t) z << 24 );
andrewboyson 6:819c17738dc2 187
andrewboyson 6:819c17738dc2 188 FT1[i] = ROTL8( FT0[i] );
andrewboyson 6:819c17738dc2 189 FT2[i] = ROTL8( FT1[i] );
andrewboyson 6:819c17738dc2 190 FT3[i] = ROTL8( FT2[i] );
andrewboyson 6:819c17738dc2 191
andrewboyson 6:819c17738dc2 192 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 193 x = RSb[i];
andrewboyson 6:819c17738dc2 194
andrewboyson 6:819c17738dc2 195 RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^
andrewboyson 6:819c17738dc2 196 ( (uint32_t) MUL( 0x09, x ) << 8 ) ^
andrewboyson 6:819c17738dc2 197 ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^
andrewboyson 6:819c17738dc2 198 ( (uint32_t) MUL( 0x0B, x ) << 24 );
andrewboyson 6:819c17738dc2 199
andrewboyson 6:819c17738dc2 200 RT1[i] = ROTL8( RT0[i] );
andrewboyson 6:819c17738dc2 201 RT2[i] = ROTL8( RT1[i] );
andrewboyson 6:819c17738dc2 202 RT3[i] = ROTL8( RT2[i] );
andrewboyson 6:819c17738dc2 203 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 204 }
andrewboyson 6:819c17738dc2 205 aes_tables_inited = 1; // flag that the tables have been generated
andrewboyson 6:819c17738dc2 206 } // to permit subsequent use of the AES cipher
andrewboyson 6:819c17738dc2 207
andrewboyson 6:819c17738dc2 208 /******************************************************************************
andrewboyson 6:819c17738dc2 209 *
andrewboyson 6:819c17738dc2 210 * AES_SET_ENCRYPTION_KEY
andrewboyson 6:819c17738dc2 211 *
andrewboyson 6:819c17738dc2 212 * This is called by 'aes_setkey' when we're establishing a key for
andrewboyson 6:819c17738dc2 213 * subsequent encryption. We give it a pointer to the encryption
andrewboyson 6:819c17738dc2 214 * context, a pointer to the key, and the key's length in bytes.
andrewboyson 6:819c17738dc2 215 * Valid lengths are: 16, 24 or 32 bytes (128, 192, 256 bits).
andrewboyson 6:819c17738dc2 216 *
andrewboyson 6:819c17738dc2 217 ******************************************************************************/
andrewboyson 6:819c17738dc2 218 int aes_set_encryption_key( aes_context *ctx,
andrewboyson 6:819c17738dc2 219 const uchar *key,
andrewboyson 6:819c17738dc2 220 uint keysize )
andrewboyson 6:819c17738dc2 221 {
andrewboyson 6:819c17738dc2 222 uint i; // general purpose iteration local
andrewboyson 6:819c17738dc2 223 uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
andrewboyson 6:819c17738dc2 224
andrewboyson 6:819c17738dc2 225 for( i = 0; i < (keysize >> 2); i++ ) {
andrewboyson 6:819c17738dc2 226 GET_UINT32_LE( RK[i], key, i << 2 );
andrewboyson 6:819c17738dc2 227 }
andrewboyson 6:819c17738dc2 228
andrewboyson 6:819c17738dc2 229 switch( ctx->rounds )
andrewboyson 6:819c17738dc2 230 {
andrewboyson 6:819c17738dc2 231 case 10:
andrewboyson 6:819c17738dc2 232 for( i = 0; i < 10; i++, RK += 4 ) {
andrewboyson 6:819c17738dc2 233 RK[4] = RK[0] ^ RCON[i] ^
andrewboyson 6:819c17738dc2 234 ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 235 ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 236 ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 237 ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 238
andrewboyson 6:819c17738dc2 239 RK[5] = RK[1] ^ RK[4];
andrewboyson 6:819c17738dc2 240 RK[6] = RK[2] ^ RK[5];
andrewboyson 6:819c17738dc2 241 RK[7] = RK[3] ^ RK[6];
andrewboyson 6:819c17738dc2 242 }
andrewboyson 6:819c17738dc2 243 break;
andrewboyson 6:819c17738dc2 244
andrewboyson 6:819c17738dc2 245 case 12:
andrewboyson 6:819c17738dc2 246 for( i = 0; i < 8; i++, RK += 6 ) {
andrewboyson 6:819c17738dc2 247 RK[6] = RK[0] ^ RCON[i] ^
andrewboyson 6:819c17738dc2 248 ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 249 ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 250 ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 251 ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 252
andrewboyson 6:819c17738dc2 253 RK[7] = RK[1] ^ RK[6];
andrewboyson 6:819c17738dc2 254 RK[8] = RK[2] ^ RK[7];
andrewboyson 6:819c17738dc2 255 RK[9] = RK[3] ^ RK[8];
andrewboyson 6:819c17738dc2 256 RK[10] = RK[4] ^ RK[9];
andrewboyson 6:819c17738dc2 257 RK[11] = RK[5] ^ RK[10];
andrewboyson 6:819c17738dc2 258 }
andrewboyson 6:819c17738dc2 259 break;
andrewboyson 6:819c17738dc2 260
andrewboyson 6:819c17738dc2 261 case 14:
andrewboyson 6:819c17738dc2 262 for( i = 0; i < 7; i++, RK += 8 ) {
andrewboyson 6:819c17738dc2 263 RK[8] = RK[0] ^ RCON[i] ^
andrewboyson 6:819c17738dc2 264 ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 265 ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 266 ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 267 ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 268
andrewboyson 6:819c17738dc2 269 RK[9] = RK[1] ^ RK[8];
andrewboyson 6:819c17738dc2 270 RK[10] = RK[2] ^ RK[9];
andrewboyson 6:819c17738dc2 271 RK[11] = RK[3] ^ RK[10];
andrewboyson 6:819c17738dc2 272
andrewboyson 6:819c17738dc2 273 RK[12] = RK[4] ^
andrewboyson 6:819c17738dc2 274 ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 275 ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 276 ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 277 ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 278
andrewboyson 6:819c17738dc2 279 RK[13] = RK[5] ^ RK[12];
andrewboyson 6:819c17738dc2 280 RK[14] = RK[6] ^ RK[13];
andrewboyson 6:819c17738dc2 281 RK[15] = RK[7] ^ RK[14];
andrewboyson 6:819c17738dc2 282 }
andrewboyson 6:819c17738dc2 283 break;
andrewboyson 6:819c17738dc2 284 }
andrewboyson 6:819c17738dc2 285 return( 0 );
andrewboyson 6:819c17738dc2 286 }
andrewboyson 6:819c17738dc2 287
andrewboyson 6:819c17738dc2 288 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 289
andrewboyson 6:819c17738dc2 290 /******************************************************************************
andrewboyson 6:819c17738dc2 291 *
andrewboyson 6:819c17738dc2 292 * AES_SET_DECRYPTION_KEY
andrewboyson 6:819c17738dc2 293 *
andrewboyson 6:819c17738dc2 294 * This is called by 'aes_setkey' when we're establishing a
andrewboyson 6:819c17738dc2 295 * key for subsequent decryption. We give it a pointer to
andrewboyson 6:819c17738dc2 296 * the encryption context, a pointer to the key, and the key's
andrewboyson 6:819c17738dc2 297 * length in bits. Valid lengths are: 128, 192, or 256 bits.
andrewboyson 6:819c17738dc2 298 *
andrewboyson 6:819c17738dc2 299 ******************************************************************************/
andrewboyson 6:819c17738dc2 300 int aes_set_decryption_key( aes_context *ctx,
andrewboyson 6:819c17738dc2 301 const uchar *key,
andrewboyson 6:819c17738dc2 302 uint keysize )
andrewboyson 6:819c17738dc2 303 {
andrewboyson 6:819c17738dc2 304 int i, j;
andrewboyson 6:819c17738dc2 305 aes_context cty; // a calling aes context for set_encryption_key
andrewboyson 6:819c17738dc2 306 uint32_t *RK = ctx->rk; // initialize our RoundKey buffer pointer
andrewboyson 6:819c17738dc2 307 uint32_t *SK;
andrewboyson 6:819c17738dc2 308 int ret;
andrewboyson 6:819c17738dc2 309
andrewboyson 6:819c17738dc2 310 cty.rounds = ctx->rounds; // initialize our local aes context
andrewboyson 6:819c17738dc2 311 cty.rk = cty.buf; // round count and key buf pointer
andrewboyson 6:819c17738dc2 312
andrewboyson 6:819c17738dc2 313 if (( ret = aes_set_encryption_key( &cty, key, keysize )) != 0 )
andrewboyson 6:819c17738dc2 314 return( ret );
andrewboyson 6:819c17738dc2 315
andrewboyson 6:819c17738dc2 316 SK = cty.rk + cty.rounds * 4;
andrewboyson 6:819c17738dc2 317
andrewboyson 6:819c17738dc2 318 CPY128 // copy a 128-bit block from *SK to *RK
andrewboyson 6:819c17738dc2 319
andrewboyson 6:819c17738dc2 320 for( i = ctx->rounds - 1, SK -= 8; i > 0; i--, SK -= 8 ) {
andrewboyson 6:819c17738dc2 321 for( j = 0; j < 4; j++, SK++ ) {
andrewboyson 6:819c17738dc2 322 *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^
andrewboyson 6:819c17738dc2 323 RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^
andrewboyson 6:819c17738dc2 324 RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^
andrewboyson 6:819c17738dc2 325 RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ];
andrewboyson 6:819c17738dc2 326 }
andrewboyson 6:819c17738dc2 327 }
andrewboyson 6:819c17738dc2 328 CPY128 // copy a 128-bit block from *SK to *RK
andrewboyson 6:819c17738dc2 329 memset( &cty, 0, sizeof( aes_context ) ); // clear local aes context
andrewboyson 6:819c17738dc2 330 return( 0 );
andrewboyson 6:819c17738dc2 331 }
andrewboyson 6:819c17738dc2 332
andrewboyson 6:819c17738dc2 333 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 334
andrewboyson 6:819c17738dc2 335 /******************************************************************************
andrewboyson 6:819c17738dc2 336 *
andrewboyson 6:819c17738dc2 337 * AES_SETKEY
andrewboyson 6:819c17738dc2 338 *
andrewboyson 6:819c17738dc2 339 * Invoked to establish the key schedule for subsequent encryption/decryption
andrewboyson 6:819c17738dc2 340 *
andrewboyson 6:819c17738dc2 341 ******************************************************************************/
andrewboyson 6:819c17738dc2 342 int aes_setkey( aes_context *ctx, // AES context provided by our caller
andrewboyson 6:819c17738dc2 343 int mode, // ENCRYPT or DECRYPT flag
andrewboyson 6:819c17738dc2 344 const uchar *key, // pointer to the key
andrewboyson 6:819c17738dc2 345 uint keysize ) // key length in bytes
andrewboyson 6:819c17738dc2 346 {
andrewboyson 6:819c17738dc2 347 // since table initialization is not thread safe, we could either add
andrewboyson 6:819c17738dc2 348 // system-specific mutexes and init the AES key generation tables on
andrewboyson 6:819c17738dc2 349 // demand, or ask the developer to simply call "gcm_initialize" once during
andrewboyson 6:819c17738dc2 350 // application startup before threading begins. That's what we choose.
andrewboyson 6:819c17738dc2 351 if( !aes_tables_inited ) return ( 0 ); // fail the call when not inited.
andrewboyson 6:819c17738dc2 352
andrewboyson 6:819c17738dc2 353 ctx->mode = mode; // capture the key type we're creating
andrewboyson 6:819c17738dc2 354 ctx->rk = ctx->buf; // initialize our round key pointer
andrewboyson 6:819c17738dc2 355
andrewboyson 6:819c17738dc2 356 switch( keysize ) // set the rounds count based upon the keysize
andrewboyson 6:819c17738dc2 357 {
andrewboyson 6:819c17738dc2 358 case 16: ctx->rounds = 10; break; // 16-byte, 128-bit key
andrewboyson 6:819c17738dc2 359 case 24: ctx->rounds = 12; break; // 24-byte, 192-bit key
andrewboyson 6:819c17738dc2 360 case 32: ctx->rounds = 14; break; // 32-byte, 256-bit key
andrewboyson 6:819c17738dc2 361 }
andrewboyson 6:819c17738dc2 362
andrewboyson 6:819c17738dc2 363 #if AES_DECRYPTION
andrewboyson 6:819c17738dc2 364 if( mode == DECRYPT ) // expand our key for encryption or decryption
andrewboyson 6:819c17738dc2 365 return( aes_set_decryption_key( ctx, key, keysize ) );
andrewboyson 6:819c17738dc2 366 else /* ENCRYPT */
andrewboyson 6:819c17738dc2 367 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 368 return( aes_set_encryption_key( ctx, key, keysize ) );
andrewboyson 6:819c17738dc2 369 }
andrewboyson 6:819c17738dc2 370
andrewboyson 6:819c17738dc2 371 /******************************************************************************
andrewboyson 6:819c17738dc2 372 *
andrewboyson 6:819c17738dc2 373 * AES_CIPHER
andrewboyson 6:819c17738dc2 374 *
andrewboyson 6:819c17738dc2 375 * Perform AES encryption and decryption.
andrewboyson 6:819c17738dc2 376 * The AES context will have been setup with the encryption mode
andrewboyson 6:819c17738dc2 377 * and all keying information appropriate for the task.
andrewboyson 6:819c17738dc2 378 *
andrewboyson 6:819c17738dc2 379 ******************************************************************************/
andrewboyson 6:819c17738dc2 380 int aes_cipher( aes_context *ctx,
andrewboyson 6:819c17738dc2 381 const uchar input[16],
andrewboyson 6:819c17738dc2 382 uchar output[16] )
andrewboyson 6:819c17738dc2 383 {
andrewboyson 6:819c17738dc2 384 int i;
andrewboyson 6:819c17738dc2 385 uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; // general purpose locals
andrewboyson 6:819c17738dc2 386
andrewboyson 6:819c17738dc2 387 RK = ctx->rk;
andrewboyson 6:819c17738dc2 388
andrewboyson 6:819c17738dc2 389 GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; // load our 128-bit
andrewboyson 6:819c17738dc2 390 GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; // input buffer in a storage
andrewboyson 6:819c17738dc2 391 GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; // memory endian-neutral way
andrewboyson 6:819c17738dc2 392 GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++;
andrewboyson 6:819c17738dc2 393
andrewboyson 6:819c17738dc2 394 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 395
andrewboyson 6:819c17738dc2 396 if( ctx->mode == DECRYPT )
andrewboyson 6:819c17738dc2 397 {
andrewboyson 6:819c17738dc2 398 for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
andrewboyson 6:819c17738dc2 399 {
andrewboyson 6:819c17738dc2 400 AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
andrewboyson 6:819c17738dc2 401 AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
andrewboyson 6:819c17738dc2 402 }
andrewboyson 6:819c17738dc2 403
andrewboyson 6:819c17738dc2 404 AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
andrewboyson 6:819c17738dc2 405
andrewboyson 6:819c17738dc2 406 X0 = *RK++ ^ \
andrewboyson 6:819c17738dc2 407 ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 408 ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 409 ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 410 ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 411
andrewboyson 6:819c17738dc2 412 X1 = *RK++ ^ \
andrewboyson 6:819c17738dc2 413 ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 414 ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 415 ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 416 ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 417
andrewboyson 6:819c17738dc2 418 X2 = *RK++ ^ \
andrewboyson 6:819c17738dc2 419 ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 420 ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 421 ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 422 ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 423
andrewboyson 6:819c17738dc2 424 X3 = *RK++ ^ \
andrewboyson 6:819c17738dc2 425 ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 426 ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 427 ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 428 ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 429 }
andrewboyson 6:819c17738dc2 430 else /* ENCRYPT */
andrewboyson 6:819c17738dc2 431 {
andrewboyson 6:819c17738dc2 432 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 433
andrewboyson 6:819c17738dc2 434 for( i = (ctx->rounds >> 1) - 1; i > 0; i-- )
andrewboyson 6:819c17738dc2 435 {
andrewboyson 6:819c17738dc2 436 AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
andrewboyson 6:819c17738dc2 437 AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
andrewboyson 6:819c17738dc2 438 }
andrewboyson 6:819c17738dc2 439
andrewboyson 6:819c17738dc2 440 AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
andrewboyson 6:819c17738dc2 441
andrewboyson 6:819c17738dc2 442 X0 = *RK++ ^ \
andrewboyson 6:819c17738dc2 443 ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 444 ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 445 ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 446 ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 447
andrewboyson 6:819c17738dc2 448 X1 = *RK++ ^ \
andrewboyson 6:819c17738dc2 449 ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 450 ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 451 ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 452 ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 453
andrewboyson 6:819c17738dc2 454 X2 = *RK++ ^ \
andrewboyson 6:819c17738dc2 455 ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 456 ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 457 ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 458 ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 459
andrewboyson 6:819c17738dc2 460 X3 = *RK++ ^ \
andrewboyson 6:819c17738dc2 461 ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^
andrewboyson 6:819c17738dc2 462 ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^
andrewboyson 6:819c17738dc2 463 ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^
andrewboyson 6:819c17738dc2 464 ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 );
andrewboyson 6:819c17738dc2 465
andrewboyson 6:819c17738dc2 466 #if AES_DECRYPTION // whether AES decryption is supported
andrewboyson 6:819c17738dc2 467 }
andrewboyson 6:819c17738dc2 468 #endif /* AES_DECRYPTION */
andrewboyson 6:819c17738dc2 469
andrewboyson 6:819c17738dc2 470 PUT_UINT32_LE( X0, output, 0 );
andrewboyson 6:819c17738dc2 471 PUT_UINT32_LE( X1, output, 4 );
andrewboyson 6:819c17738dc2 472 PUT_UINT32_LE( X2, output, 8 );
andrewboyson 6:819c17738dc2 473 PUT_UINT32_LE( X3, output, 12 );
andrewboyson 6:819c17738dc2 474
andrewboyson 6:819c17738dc2 475 return( 0 );
andrewboyson 6:819c17738dc2 476 }
andrewboyson 6:819c17738dc2 477 /* end of aes.c */