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