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