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