1*e28a4053SRui Paulo /* 2*e28a4053SRui Paulo * AES (Rijndael) cipher - encrypt 3*e28a4053SRui Paulo * 4*e28a4053SRui Paulo * Modifications to public domain implementation: 5*e28a4053SRui Paulo * - support only 128-bit keys 6*e28a4053SRui Paulo * - cleanup 7*e28a4053SRui Paulo * - use C pre-processor to make it easier to change S table access 8*e28a4053SRui Paulo * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at 9*e28a4053SRui Paulo * cost of reduced throughput (quite small difference on Pentium 4, 10*e28a4053SRui Paulo * 10-25% when using -O1 or -O2 optimization) 11*e28a4053SRui Paulo * 12*e28a4053SRui Paulo * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> 13*e28a4053SRui Paulo * 14*e28a4053SRui Paulo * This program is free software; you can redistribute it and/or modify 15*e28a4053SRui Paulo * it under the terms of the GNU General Public License version 2 as 16*e28a4053SRui Paulo * published by the Free Software Foundation. 17*e28a4053SRui Paulo * 18*e28a4053SRui Paulo * Alternatively, this software may be distributed under the terms of BSD 19*e28a4053SRui Paulo * license. 20*e28a4053SRui Paulo * 21*e28a4053SRui Paulo * See README and COPYING for more details. 22*e28a4053SRui Paulo */ 23*e28a4053SRui Paulo 24*e28a4053SRui Paulo #include "includes.h" 25*e28a4053SRui Paulo 26*e28a4053SRui Paulo #include "common.h" 27*e28a4053SRui Paulo #include "crypto.h" 28*e28a4053SRui Paulo #include "aes_i.h" 29*e28a4053SRui Paulo 30*e28a4053SRui Paulo void rijndaelEncrypt(const u32 rk[/*44*/], const u8 pt[16], u8 ct[16]) 31*e28a4053SRui Paulo { 32*e28a4053SRui Paulo u32 s0, s1, s2, s3, t0, t1, t2, t3; 33*e28a4053SRui Paulo const int Nr = 10; 34*e28a4053SRui Paulo #ifndef FULL_UNROLL 35*e28a4053SRui Paulo int r; 36*e28a4053SRui Paulo #endif /* ?FULL_UNROLL */ 37*e28a4053SRui Paulo 38*e28a4053SRui Paulo /* 39*e28a4053SRui Paulo * map byte array block to cipher state 40*e28a4053SRui Paulo * and add initial round key: 41*e28a4053SRui Paulo */ 42*e28a4053SRui Paulo s0 = GETU32(pt ) ^ rk[0]; 43*e28a4053SRui Paulo s1 = GETU32(pt + 4) ^ rk[1]; 44*e28a4053SRui Paulo s2 = GETU32(pt + 8) ^ rk[2]; 45*e28a4053SRui Paulo s3 = GETU32(pt + 12) ^ rk[3]; 46*e28a4053SRui Paulo 47*e28a4053SRui Paulo #define ROUND(i,d,s) \ 48*e28a4053SRui Paulo d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ 49*e28a4053SRui Paulo d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ 50*e28a4053SRui Paulo d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ 51*e28a4053SRui Paulo d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] 52*e28a4053SRui Paulo 53*e28a4053SRui Paulo #ifdef FULL_UNROLL 54*e28a4053SRui Paulo 55*e28a4053SRui Paulo ROUND(1,t,s); 56*e28a4053SRui Paulo ROUND(2,s,t); 57*e28a4053SRui Paulo ROUND(3,t,s); 58*e28a4053SRui Paulo ROUND(4,s,t); 59*e28a4053SRui Paulo ROUND(5,t,s); 60*e28a4053SRui Paulo ROUND(6,s,t); 61*e28a4053SRui Paulo ROUND(7,t,s); 62*e28a4053SRui Paulo ROUND(8,s,t); 63*e28a4053SRui Paulo ROUND(9,t,s); 64*e28a4053SRui Paulo 65*e28a4053SRui Paulo rk += Nr << 2; 66*e28a4053SRui Paulo 67*e28a4053SRui Paulo #else /* !FULL_UNROLL */ 68*e28a4053SRui Paulo 69*e28a4053SRui Paulo /* Nr - 1 full rounds: */ 70*e28a4053SRui Paulo r = Nr >> 1; 71*e28a4053SRui Paulo for (;;) { 72*e28a4053SRui Paulo ROUND(1,t,s); 73*e28a4053SRui Paulo rk += 8; 74*e28a4053SRui Paulo if (--r == 0) 75*e28a4053SRui Paulo break; 76*e28a4053SRui Paulo ROUND(0,s,t); 77*e28a4053SRui Paulo } 78*e28a4053SRui Paulo 79*e28a4053SRui Paulo #endif /* ?FULL_UNROLL */ 80*e28a4053SRui Paulo 81*e28a4053SRui Paulo #undef ROUND 82*e28a4053SRui Paulo 83*e28a4053SRui Paulo /* 84*e28a4053SRui Paulo * apply last round and 85*e28a4053SRui Paulo * map cipher state to byte array block: 86*e28a4053SRui Paulo */ 87*e28a4053SRui Paulo s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; 88*e28a4053SRui Paulo PUTU32(ct , s0); 89*e28a4053SRui Paulo s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; 90*e28a4053SRui Paulo PUTU32(ct + 4, s1); 91*e28a4053SRui Paulo s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; 92*e28a4053SRui Paulo PUTU32(ct + 8, s2); 93*e28a4053SRui Paulo s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; 94*e28a4053SRui Paulo PUTU32(ct + 12, s3); 95*e28a4053SRui Paulo } 96*e28a4053SRui Paulo 97*e28a4053SRui Paulo 98*e28a4053SRui Paulo void * aes_encrypt_init(const u8 *key, size_t len) 99*e28a4053SRui Paulo { 100*e28a4053SRui Paulo u32 *rk; 101*e28a4053SRui Paulo if (len != 16) 102*e28a4053SRui Paulo return NULL; 103*e28a4053SRui Paulo rk = os_malloc(AES_PRIV_SIZE); 104*e28a4053SRui Paulo if (rk == NULL) 105*e28a4053SRui Paulo return NULL; 106*e28a4053SRui Paulo rijndaelKeySetupEnc(rk, key); 107*e28a4053SRui Paulo return rk; 108*e28a4053SRui Paulo } 109*e28a4053SRui Paulo 110*e28a4053SRui Paulo 111*e28a4053SRui Paulo void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 112*e28a4053SRui Paulo { 113*e28a4053SRui Paulo rijndaelEncrypt(ctx, plain, crypt); 114*e28a4053SRui Paulo } 115*e28a4053SRui Paulo 116*e28a4053SRui Paulo 117*e28a4053SRui Paulo void aes_encrypt_deinit(void *ctx) 118*e28a4053SRui Paulo { 119*e28a4053SRui Paulo os_memset(ctx, 0, AES_PRIV_SIZE); 120*e28a4053SRui Paulo os_free(ctx); 121*e28a4053SRui Paulo } 122