1175365Sgallatin/* 2175365Sgallatin * AES (Rijndael) cipher - encrypt 3175365Sgallatin * 4175365Sgallatin * Modifications to public domain implementation: 5175365Sgallatin * - cleanup 6175365Sgallatin * - use C pre-processor to make it easier to change S table access 7175365Sgallatin * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at 8175365Sgallatin * cost of reduced throughput (quite small difference on Pentium 4, 9175365Sgallatin * 10-25% when using -O1 or -O2 optimization) 10175365Sgallatin * 11175365Sgallatin * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> 12175365Sgallatin * 13175365Sgallatin * This software may be distributed under the terms of the BSD license. 14175365Sgallatin * See README for more details. 15175365Sgallatin */ 16175365Sgallatin 17175365Sgallatin#include "includes.h" 18175365Sgallatin 19175365Sgallatin#include "common.h" 20175365Sgallatin#include "crypto.h" 21175365Sgallatin#include "aes_i.h" 22175365Sgallatin 23175365Sgallatinstatic void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16]) 24175365Sgallatin{ 25175365Sgallatin u32 s0, s1, s2, s3, t0, t1, t2, t3; 26175365Sgallatin#ifndef FULL_UNROLL 27175365Sgallatin int r; 28175365Sgallatin#endif /* ?FULL_UNROLL */ 29175365Sgallatin 30175365Sgallatin /* 31175365Sgallatin * map byte array block to cipher state 32175365Sgallatin * and add initial round key: 33175365Sgallatin */ 34175365Sgallatin s0 = GETU32(pt ) ^ rk[0]; 35175365Sgallatin s1 = GETU32(pt + 4) ^ rk[1]; 36175365Sgallatin s2 = GETU32(pt + 8) ^ rk[2]; 37175365Sgallatin s3 = GETU32(pt + 12) ^ rk[3]; 38175365Sgallatin 39175365Sgallatin#define ROUND(i,d,s) \ 40175365Sgallatind##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ 41175365Sgallatind##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ 42175365Sgallatind##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ 43175365Sgallatind##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] 44175365Sgallatin 45175365Sgallatin#ifdef FULL_UNROLL 46175365Sgallatin 47175365Sgallatin ROUND(1,t,s); 48175365Sgallatin ROUND(2,s,t); 49175365Sgallatin ROUND(3,t,s); 50175365Sgallatin ROUND(4,s,t); 51175365Sgallatin ROUND(5,t,s); 52175365Sgallatin ROUND(6,s,t); 53175365Sgallatin ROUND(7,t,s); 54175365Sgallatin ROUND(8,s,t); 55175365Sgallatin ROUND(9,t,s); 56175365Sgallatin if (Nr > 10) { 57175365Sgallatin ROUND(10,s,t); 58175365Sgallatin ROUND(11,t,s); 59175365Sgallatin if (Nr > 12) { 60175365Sgallatin ROUND(12,s,t); 61175365Sgallatin ROUND(13,t,s); 62175365Sgallatin } 63175365Sgallatin } 64175365Sgallatin 65175365Sgallatin rk += Nr << 2; 66175365Sgallatin 67175365Sgallatin#else /* !FULL_UNROLL */ 68175365Sgallatin 69175365Sgallatin /* Nr - 1 full rounds: */ 70175365Sgallatin r = Nr >> 1; 71175365Sgallatin for (;;) { 72175365Sgallatin ROUND(1,t,s); 73175365Sgallatin rk += 8; 74175365Sgallatin if (--r == 0) 75175365Sgallatin break; 76175365Sgallatin ROUND(0,s,t); 77175365Sgallatin } 78175365Sgallatin 79175365Sgallatin#endif /* ?FULL_UNROLL */ 80175365Sgallatin 81175365Sgallatin#undef ROUND 82175365Sgallatin 83175365Sgallatin /* 84175365Sgallatin * apply last round and 85175365Sgallatin * map cipher state to byte array block: 86175365Sgallatin */ 87175365Sgallatin s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; 88175365Sgallatin PUTU32(ct , s0); 89175365Sgallatin s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; 90175365Sgallatin PUTU32(ct + 4, s1); 91175365Sgallatin s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; 92175365Sgallatin PUTU32(ct + 8, s2); 93175365Sgallatin s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; 94175365Sgallatin PUTU32(ct + 12, s3); 95175365Sgallatin} 96175365Sgallatin 97175365Sgallatin 98175365Sgallatinvoid * aes_encrypt_init(const u8 *key, size_t len) 99175365Sgallatin{ 100175365Sgallatin u32 *rk; 101175365Sgallatin int res; 102175365Sgallatin rk = os_malloc(AES_PRIV_SIZE); 103175365Sgallatin if (rk == NULL) 104175365Sgallatin return NULL; 105175365Sgallatin res = rijndaelKeySetupEnc(rk, key, len * 8); 106175365Sgallatin if (res < 0) { 107175365Sgallatin os_free(rk); 108175365Sgallatin return NULL; 109175365Sgallatin } 110175365Sgallatin rk[AES_PRIV_NR_POS] = res; 111175365Sgallatin return rk; 112175365Sgallatin} 113175365Sgallatin 114175365Sgallatin 115175365Sgallatinvoid aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) 116175365Sgallatin{ 117175365Sgallatin u32 *rk = ctx; 118175365Sgallatin rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); 119175365Sgallatin} 120175365Sgallatin 121175365Sgallatin 122175365Sgallatinvoid aes_encrypt_deinit(void *ctx) 123175365Sgallatin{ 124175365Sgallatin os_memset(ctx, 0, AES_PRIV_SIZE); 125175365Sgallatin os_free(ctx); 126175365Sgallatin} 127175365Sgallatin