A simple library to support serving https.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Apr 01 12:48:52 2020 +0000
Revision:
24:cb43290fc439
Parent:
6:819c17738dc2
Added check so that if the client closes the TCP connection before the TLS connection is established then respond that we have finished and the TCP connection is to be closed.

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