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