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
rijndaelEncrypt(const u32 rk[],int Nr,const u8 pt[16],u8 ct[16])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
aes_encrypt_init(const u8 * key,size_t len)98e28a4053SRui Paulo void * aes_encrypt_init(const u8 *key, size_t len)
99e28a4053SRui Paulo {
100e28a4053SRui Paulo u32 *rk;
101f05cddf9SRui Paulo int res;
102*4bc52338SCy Schubert
103*4bc52338SCy Schubert if (TEST_FAIL())
104*4bc52338SCy Schubert return NULL;
105*4bc52338SCy Schubert
106e28a4053SRui Paulo rk = os_malloc(AES_PRIV_SIZE);
107e28a4053SRui Paulo if (rk == NULL)
108e28a4053SRui Paulo return NULL;
109f05cddf9SRui Paulo res = rijndaelKeySetupEnc(rk, key, len * 8);
110f05cddf9SRui Paulo if (res < 0) {
111f05cddf9SRui Paulo os_free(rk);
112f05cddf9SRui Paulo return NULL;
113f05cddf9SRui Paulo }
114f05cddf9SRui Paulo rk[AES_PRIV_NR_POS] = res;
115e28a4053SRui Paulo return rk;
116e28a4053SRui Paulo }
117e28a4053SRui Paulo
118e28a4053SRui Paulo
aes_encrypt(void * ctx,const u8 * plain,u8 * crypt)11985732ac8SCy Schubert int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
120e28a4053SRui Paulo {
121f05cddf9SRui Paulo u32 *rk = ctx;
122f05cddf9SRui Paulo rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt);
12385732ac8SCy Schubert return 0;
124e28a4053SRui Paulo }
125e28a4053SRui Paulo
126e28a4053SRui Paulo
aes_encrypt_deinit(void * ctx)127e28a4053SRui Paulo void aes_encrypt_deinit(void *ctx)
128e28a4053SRui Paulo {
129e28a4053SRui Paulo os_memset(ctx, 0, AES_PRIV_SIZE);
130e28a4053SRui Paulo os_free(ctx);
131e28a4053SRui Paulo }
132