aes.c

Go to the documentation of this file.
00001 /*
00002  *  Copyright(C) 2006 Cameron Rich
00003  *
00004  *  This library is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU Lesser General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU Lesser General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Lesser General Public License
00015  *  along with this library; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 /**
00020  * AES implementation - this is a small code version. There are much faster
00021  * versions around but they are much larger in size (i.e. they use large 
00022  * submix tables).
00023  */
00024 
00025 #include <string.h>
00026 #include "crypto.h"
00027 
00028 /* all commented out in skeleton mode */
00029 #ifndef CONFIG_SSL_SKELETON_MODE
00030 
00031 #define rot1(x) (((x) << 24) | ((x) >> 8))
00032 #define rot2(x) (((x) << 16) | ((x) >> 16))
00033 #define rot3(x) (((x) <<  8) | ((x) >> 24))
00034 
00035 /* 
00036  * This cute trick does 4 'mul by two' at once.  Stolen from
00037  * Dr B. R. Gladman <brg@gladman.uk.net> but I'm sure the u-(u>>7) is
00038  * a standard graphics trick
00039  * The key to this is that we need to xor with 0x1b if the top bit is set.
00040  * a 1xxx xxxx   0xxx 0xxx First we mask the 7bit,
00041  * b 1000 0000   0000 0000 then we shift right by 7 putting the 7bit in 0bit,
00042  * c 0000 0001   0000 0000 we then subtract (c) from (b)
00043  * d 0111 1111   0000 0000 and now we and with our mask
00044  * e 0001 1011   0000 0000
00045  */
00046 #define mt  0x80808080
00047 #define ml  0x7f7f7f7f
00048 #define mh  0xfefefefe
00049 #define mm  0x1b1b1b1b
00050 #define mul2(x,t)       ((t)=((x)&mt), \
00051                         ((((x)+(x))&mh)^(((t)-((t)>>7))&mm)))
00052 
00053 #define inv_mix_col(x,f2,f4,f8,f9) (\
00054                         (f2)=mul2(x,f2), \
00055                         (f4)=mul2(f2,f4), \
00056                         (f8)=mul2(f4,f8), \
00057                         (f9)=(x)^(f8), \
00058                         (f8)=((f2)^(f4)^(f8)), \
00059                         (f2)^=(f9), \
00060                         (f4)^=(f9), \
00061                         (f8)^=rot3(f2), \
00062                         (f8)^=rot2(f4), \
00063                         (f8)^rot1(f9))
00064 
00065 /* some macros to do endian independent byte extraction */
00066 #define n2l(c,l) l=ntohl(*c); c++
00067 #define l2n(l,c) *c++=htonl(l)
00068 
00069 /*
00070  * AES S-box
00071  */
00072 static const uint8_t aes_sbox[256] =
00073 {
00074         0x63,0x7C,0x77,0x7B,0xF2,0x6B,0x6F,0xC5,
00075         0x30,0x01,0x67,0x2B,0xFE,0xD7,0xAB,0x76,
00076         0xCA,0x82,0xC9,0x7D,0xFA,0x59,0x47,0xF0,
00077         0xAD,0xD4,0xA2,0xAF,0x9C,0xA4,0x72,0xC0,
00078         0xB7,0xFD,0x93,0x26,0x36,0x3F,0xF7,0xCC,
00079         0x34,0xA5,0xE5,0xF1,0x71,0xD8,0x31,0x15,
00080         0x04,0xC7,0x23,0xC3,0x18,0x96,0x05,0x9A,
00081         0x07,0x12,0x80,0xE2,0xEB,0x27,0xB2,0x75,
00082         0x09,0x83,0x2C,0x1A,0x1B,0x6E,0x5A,0xA0,
00083         0x52,0x3B,0xD6,0xB3,0x29,0xE3,0x2F,0x84,
00084         0x53,0xD1,0x00,0xED,0x20,0xFC,0xB1,0x5B,
00085         0x6A,0xCB,0xBE,0x39,0x4A,0x4C,0x58,0xCF,
00086         0xD0,0xEF,0xAA,0xFB,0x43,0x4D,0x33,0x85,
00087         0x45,0xF9,0x02,0x7F,0x50,0x3C,0x9F,0xA8,
00088         0x51,0xA3,0x40,0x8F,0x92,0x9D,0x38,0xF5,
00089         0xBC,0xB6,0xDA,0x21,0x10,0xFF,0xF3,0xD2,
00090         0xCD,0x0C,0x13,0xEC,0x5F,0x97,0x44,0x17,
00091         0xC4,0xA7,0x7E,0x3D,0x64,0x5D,0x19,0x73,
00092         0x60,0x81,0x4F,0xDC,0x22,0x2A,0x90,0x88,
00093         0x46,0xEE,0xB8,0x14,0xDE,0x5E,0x0B,0xDB,
00094         0xE0,0x32,0x3A,0x0A,0x49,0x06,0x24,0x5C,
00095         0xC2,0xD3,0xAC,0x62,0x91,0x95,0xE4,0x79,
00096         0xE7,0xC8,0x37,0x6D,0x8D,0xD5,0x4E,0xA9,
00097         0x6C,0x56,0xF4,0xEA,0x65,0x7A,0xAE,0x08,
00098         0xBA,0x78,0x25,0x2E,0x1C,0xA6,0xB4,0xC6,
00099         0xE8,0xDD,0x74,0x1F,0x4B,0xBD,0x8B,0x8A,
00100         0x70,0x3E,0xB5,0x66,0x48,0x03,0xF6,0x0E,
00101         0x61,0x35,0x57,0xB9,0x86,0xC1,0x1D,0x9E,
00102         0xE1,0xF8,0x98,0x11,0x69,0xD9,0x8E,0x94,
00103         0x9B,0x1E,0x87,0xE9,0xCE,0x55,0x28,0xDF,
00104         0x8C,0xA1,0x89,0x0D,0xBF,0xE6,0x42,0x68,
00105         0x41,0x99,0x2D,0x0F,0xB0,0x54,0xBB,0x16,
00106 };
00107 
00108 /*
00109  * AES is-box
00110  */
00111 static const uint8_t aes_isbox[256] = 
00112 {
00113     0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,
00114     0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb,
00115     0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,
00116     0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb,
00117     0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,
00118     0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e,
00119     0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,
00120     0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25,
00121     0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,
00122     0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92,
00123     0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,
00124     0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84,
00125     0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,
00126     0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06,
00127     0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,
00128     0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b,
00129     0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,
00130     0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73,
00131     0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,
00132     0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e,
00133     0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,
00134     0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b,
00135     0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,
00136     0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4,
00137     0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,
00138     0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f,
00139     0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,
00140     0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef,
00141     0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,
00142     0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61,
00143     0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,
00144     0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d
00145 };
00146 
00147 static const unsigned char Rcon[30]=
00148 {
00149         0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
00150         0x1b,0x36,0x6c,0xd8,0xab,0x4d,0x9a,0x2f,
00151         0x5e,0xbc,0x63,0xc6,0x97,0x35,0x6a,0xd4,
00152         0xb3,0x7d,0xfa,0xef,0xc5,0x91,
00153 };
00154 
00155 /* Perform doubling in Galois Field GF(2^8) using the irreducible polynomial
00156    x^8+x^4+x^3+x+1 */
00157 static unsigned char AES_xtime(uint32_t x)
00158 {
00159         return x = (x&0x80) ? (x<<1)^0x1b : x<<1;
00160 }
00161 
00162 /**
00163  * Set up AES with the key/iv and cipher size.
00164  */
00165 void AES_set_key(AES_CTX *ctx, const uint8_t *key, 
00166         const uint8_t *iv, AES_MODE mode)
00167 {
00168     int i, ii;
00169     uint32_t *W, tmp, tmp2;
00170     const unsigned char *ip;
00171     int words;
00172 
00173     switch (mode)
00174     {
00175         case AES_MODE_128:
00176             i = 10;
00177             words = 4;
00178             break;
00179 
00180         case AES_MODE_256:
00181             i = 14;
00182             words = 8;
00183             break;
00184 
00185         default:        /* fail silently */
00186             return;
00187     }
00188 
00189     ctx->rounds = i;
00190     ctx->key_size = words;
00191     W = ctx->ks;
00192     for (i = 0; i < words; i+=2)
00193     {
00194         W[i+0]= ((uint32_t)key[ 0]<<24)|
00195             ((uint32_t)key[ 1]<<16)|
00196             ((uint32_t)key[ 2]<< 8)|
00197             ((uint32_t)key[ 3]    );
00198         W[i+1]= ((uint32_t)key[ 4]<<24)|
00199             ((uint32_t)key[ 5]<<16)|
00200             ((uint32_t)key[ 6]<< 8)|
00201             ((uint32_t)key[ 7]    );
00202         key += 8;
00203     }
00204 
00205     ip = Rcon;
00206     ii = 4 * (ctx->rounds+1);
00207     for (i = words; i<ii; i++)
00208     {
00209         tmp = W[i-1];
00210 
00211         if ((i % words) == 0)
00212         {
00213             tmp2 =(uint32_t)aes_sbox[(tmp    )&0xff]<< 8;
00214             tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<<16;
00215             tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<24;
00216             tmp2|=(uint32_t)aes_sbox[(tmp>>24)     ];
00217             tmp=tmp2^(((unsigned int)*ip)<<24);
00218             ip++;
00219         }
00220 
00221         if ((words == 8) && ((i % words) == 4))
00222         {
00223             tmp2 =(uint32_t)aes_sbox[(tmp    )&0xff]    ;
00224             tmp2|=(uint32_t)aes_sbox[(tmp>> 8)&0xff]<< 8;
00225             tmp2|=(uint32_t)aes_sbox[(tmp>>16)&0xff]<<16;
00226             tmp2|=(uint32_t)aes_sbox[(tmp>>24)     ]<<24;
00227             tmp=tmp2;
00228         }
00229 
00230         W[i]=W[i-words]^tmp;
00231     }
00232 
00233     /* copy the iv across */
00234     memcpy(ctx->iv, iv, 16);
00235 }
00236 
00237 /**
00238  * Change a key for decryption.
00239  */
00240 void AES_convert_key(AES_CTX *ctx)
00241 {
00242     int i;
00243     uint32_t *k,w,t1,t2,t3,t4;
00244 
00245     k = ctx->ks;
00246     k += 4;
00247 
00248     for (i=ctx->rounds*4; i>4; i--)
00249     {
00250         w= *k;
00251         w = inv_mix_col(w,t1,t2,t3,t4);
00252         *k++ =w;
00253     }
00254 }
00255 
00256 #if 0
00257 /**
00258  * Encrypt a byte sequence (with a block size 16) using the AES cipher.
00259  */
00260 void AES_cbc_encrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
00261 {
00262     uint32_t tin0, tin1, tin2, tin3;
00263     uint32_t tout0, tout1, tout2, tout3;
00264     uint32_t tin[4];
00265     uint32_t *iv = (uint32_t *)ctx->iv;
00266     uint32_t *msg_32 = (uint32_t *)msg;
00267     uint32_t *out_32 = (uint32_t *)out;
00268 
00269     n2l(iv, tout0);
00270     n2l(iv, tout1);
00271     n2l(iv, tout2);
00272     n2l(iv, tout3);
00273     iv -= 4;
00274 
00275     for (length -= 16; length >= 0; length -= 16)
00276     {
00277         n2l(msg_32, tin0);
00278         n2l(msg_32, tin1);
00279         n2l(msg_32, tin2);
00280         n2l(msg_32, tin3);
00281         tin[0] = tin0^tout0;
00282         tin[1] = tin1^tout1;
00283         tin[2] = tin2^tout2;
00284         tin[3] = tin3^tout3;
00285 
00286         AES_encrypt(ctx, tin);
00287 
00288         tout0 = tin[0]; 
00289         l2n(tout0, out_32);
00290         tout1 = tin[1]; 
00291         l2n(tout1, out_32);
00292         tout2 = tin[2]; 
00293         l2n(tout2, out_32);
00294         tout3 = tin[3]; 
00295         l2n(tout3, out_32);
00296     }
00297 
00298     l2n(tout0, iv);
00299     l2n(tout1, iv);
00300     l2n(tout2, iv);
00301     l2n(tout3, iv);
00302 }
00303 
00304 /**
00305  * Decrypt a byte sequence (with a block size 16) using the AES cipher.
00306  */
00307 void AES_cbc_decrypt(AES_CTX *ctx, const uint8_t *msg, uint8_t *out, int length)
00308 {
00309     uint32_t tin0, tin1, tin2, tin3;
00310     uint32_t xor0,xor1,xor2,xor3;
00311     uint32_t tout0,tout1,tout2,tout3;
00312     uint32_t data[4];
00313     uint32_t *iv = (uint32_t *)ctx->iv;
00314     uint32_t *msg_32 = (uint32_t *)msg;
00315     uint32_t *out_32 = (uint32_t *)out;
00316 
00317     n2l(iv ,xor0);
00318     n2l(iv, xor1);
00319     n2l(iv, xor2);
00320     n2l(iv, xor3);
00321     iv -= 4;
00322 
00323     for (length-=16; length >= 0; length -= 16)
00324     {
00325         n2l(msg_32, tin0);
00326         n2l(msg_32, tin1);
00327         n2l(msg_32, tin2);
00328         n2l(msg_32, tin3);
00329 
00330         data[0] = tin0;
00331         data[1] = tin1;
00332         data[2] = tin2;
00333         data[3] = tin3;
00334 
00335         AES_decrypt(ctx, data);
00336 
00337         tout0 = data[0]^xor0;
00338         tout1 = data[1]^xor1;
00339         tout2 = data[2]^xor2;
00340         tout3 = data[3]^xor3;
00341 
00342         xor0 = tin0;
00343         xor1 = tin1;
00344         xor2 = tin2;
00345         xor3 = tin3;
00346 
00347         l2n(tout0, out_32);
00348         l2n(tout1, out_32);
00349         l2n(tout2, out_32);
00350         l2n(tout3, out_32);
00351     }
00352 
00353     l2n(xor0, iv);
00354     l2n(xor1, iv);
00355     l2n(xor2, iv);
00356     l2n(xor3, iv);
00357 }
00358 #endif
00359 
00360 /**
00361  * Encrypt a single block (16 bytes) of data
00362  */
00363 void AES_encrypt(const AES_CTX *ctx, uint32_t *data)
00364 {
00365     /* To make this code smaller, generate the sbox entries on the fly.
00366      * This will have a really heavy effect upon performance.
00367      */
00368     uint32_t tmp[4];
00369     uint32_t tmp1, old_a0, a0, a1, a2, a3, row;
00370     int curr_rnd;
00371     int rounds = ctx->rounds; 
00372     const uint32_t *k = ctx->ks;
00373 
00374     /* Pre-round key addition */
00375     for (row = 0; row < 4; row++)
00376     {
00377         data[row] ^= *(k++);
00378     }
00379 
00380     /* Encrypt one block. */
00381     for (curr_rnd = 0; curr_rnd < rounds; curr_rnd++)
00382     {
00383         /* Perform ByteSub and ShiftRow operations together */
00384         for (row = 0; row < 4; row++)
00385         {
00386             a0 = (uint32_t)aes_sbox[(data[row%4]>>24)&0xFF];
00387             a1 = (uint32_t)aes_sbox[(data[(row+1)%4]>>16)&0xFF];
00388             a2 = (uint32_t)aes_sbox[(data[(row+2)%4]>>8)&0xFF]; 
00389             a3 = (uint32_t)aes_sbox[(data[(row+3)%4])&0xFF];
00390 
00391             /* Perform MixColumn iff not last round */
00392             if (curr_rnd < (rounds - 1))
00393             {
00394                 tmp1 = a0 ^ a1 ^ a2 ^ a3;
00395                 old_a0 = a0;
00396 
00397                 a0 ^= tmp1 ^ AES_xtime(a0 ^ a1);
00398                 a1 ^= tmp1 ^ AES_xtime(a1 ^ a2);
00399                 a2 ^= tmp1 ^ AES_xtime(a2 ^ a3);
00400                 a3 ^= tmp1 ^ AES_xtime(a3 ^ old_a0);
00401 
00402             }
00403 
00404             tmp[row] = ((a0 << 24) | (a1 << 16) | (a2 << 8) | a3);
00405         }
00406 
00407         /* KeyAddition - note that it is vital that this loop is separate from
00408            the MixColumn operation, which must be atomic...*/ 
00409         for (row = 0; row < 4; row++)
00410         {
00411             data[row] = tmp[row] ^ *(k++);
00412         }
00413     }
00414 }
00415 
00416 /**
00417  * Decrypt a single block (16 bytes) of data
00418  */
00419 void AES_decrypt(const AES_CTX *ctx, uint32_t *data)
00420 { 
00421     uint32_t tmp[4];
00422     uint32_t xt0,xt1,xt2,xt3,xt4,xt5,xt6;
00423     uint32_t a0, a1, a2, a3, row;
00424     int curr_rnd;
00425     int rounds = ctx->rounds;
00426     uint32_t *k = (uint32_t*)ctx->ks + ((rounds+1)*4);
00427 
00428     /* pre-round key addition */
00429     for (row=4; row > 0;row--)
00430     {
00431         data[row-1] ^= *(--k);
00432     }
00433 
00434     /* Decrypt one block */
00435     for (curr_rnd=0; curr_rnd < rounds; curr_rnd++)
00436     {
00437         /* Perform ByteSub and ShiftRow operations together */
00438         for (row = 4; row > 0; row--)
00439         {
00440             a0 = aes_isbox[(data[(row+3)%4]>>24)&0xFF];
00441             a1 = aes_isbox[(data[(row+2)%4]>>16)&0xFF];
00442             a2 = aes_isbox[(data[(row+1)%4]>>8)&0xFF];
00443             a3 = aes_isbox[(data[row%4])&0xFF];
00444 
00445             /* Perform MixColumn iff not last round */
00446             if (curr_rnd<(rounds-1))
00447             {
00448                 /* The MDS cofefficients (0x09, 0x0B, 0x0D, 0x0E)
00449                    are quite large compared to encryption; this 
00450                    operation slows decryption down noticeably. */
00451                 xt0 = AES_xtime(a0^a1);
00452                 xt1 = AES_xtime(a1^a2);
00453                 xt2 = AES_xtime(a2^a3);
00454                 xt3 = AES_xtime(a3^a0);
00455                 xt4 = AES_xtime(xt0^xt1);
00456                 xt5 = AES_xtime(xt1^xt2);
00457                 xt6 = AES_xtime(xt4^xt5);
00458 
00459                 xt0 ^= a1^a2^a3^xt4^xt6;
00460                 xt1 ^= a0^a2^a3^xt5^xt6;
00461                 xt2 ^= a0^a1^a3^xt4^xt6;
00462                 xt3 ^= a0^a1^a2^xt5^xt6;
00463                 tmp[row-1] = ((xt0<<24)|(xt1<<16)|(xt2<<8)|xt3);
00464             }
00465             else
00466                 tmp[row-1] = ((a0<<24)|(a1<<16)|(a2<<8)|a3);
00467         }
00468 
00469         for (row = 4; row > 0; row--)
00470         {
00471             data[row-1] = tmp[row-1] ^ *(--k);
00472         }
00473     }
00474 }
00475 
00476 #endif

Generated on Tue Apr 6 20:00:52 2010 for gPXE by  doxygen 1.5.7.1