1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * AES (Rijndael) cipher - decrypt
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_ci/**
24e5b75505Sopenharmony_ci * Expand the cipher key into the decryption key schedule.
25e5b75505Sopenharmony_ci *
26e5b75505Sopenharmony_ci * @return	the number of rounds for the given cipher key size.
27e5b75505Sopenharmony_ci */
28e5b75505Sopenharmony_cistatic int rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits)
29e5b75505Sopenharmony_ci{
30e5b75505Sopenharmony_ci	int Nr, i, j;
31e5b75505Sopenharmony_ci	u32 temp;
32e5b75505Sopenharmony_ci
33e5b75505Sopenharmony_ci	/* expand the cipher key: */
34e5b75505Sopenharmony_ci	Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
35e5b75505Sopenharmony_ci	if (Nr < 0)
36e5b75505Sopenharmony_ci		return Nr;
37e5b75505Sopenharmony_ci	/* invert the order of the round keys: */
38e5b75505Sopenharmony_ci	for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
39e5b75505Sopenharmony_ci		temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
40e5b75505Sopenharmony_ci		temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
41e5b75505Sopenharmony_ci		temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
42e5b75505Sopenharmony_ci		temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
43e5b75505Sopenharmony_ci	}
44e5b75505Sopenharmony_ci	/* apply the inverse MixColumn transform to all round keys but the
45e5b75505Sopenharmony_ci	 * first and the last: */
46e5b75505Sopenharmony_ci	for (i = 1; i < Nr; i++) {
47e5b75505Sopenharmony_ci		rk += 4;
48e5b75505Sopenharmony_ci		for (j = 0; j < 4; j++) {
49e5b75505Sopenharmony_ci			rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
50e5b75505Sopenharmony_ci				TD1_(TE4((rk[j] >> 16) & 0xff)) ^
51e5b75505Sopenharmony_ci				TD2_(TE4((rk[j] >>  8) & 0xff)) ^
52e5b75505Sopenharmony_ci				TD3_(TE4((rk[j]      ) & 0xff));
53e5b75505Sopenharmony_ci		}
54e5b75505Sopenharmony_ci	}
55e5b75505Sopenharmony_ci
56e5b75505Sopenharmony_ci	return Nr;
57e5b75505Sopenharmony_ci}
58e5b75505Sopenharmony_ci
59e5b75505Sopenharmony_civoid * aes_decrypt_init(const u8 *key, size_t len)
60e5b75505Sopenharmony_ci{
61e5b75505Sopenharmony_ci	u32 *rk;
62e5b75505Sopenharmony_ci	int res;
63e5b75505Sopenharmony_ci	rk = os_malloc(AES_PRIV_SIZE);
64e5b75505Sopenharmony_ci	if (rk == NULL)
65e5b75505Sopenharmony_ci		return NULL;
66e5b75505Sopenharmony_ci	res = rijndaelKeySetupDec(rk, key, len * 8);
67e5b75505Sopenharmony_ci	if (res < 0) {
68e5b75505Sopenharmony_ci		os_free(rk);
69e5b75505Sopenharmony_ci		return NULL;
70e5b75505Sopenharmony_ci	}
71e5b75505Sopenharmony_ci	rk[AES_PRIV_NR_POS] = res;
72e5b75505Sopenharmony_ci	return rk;
73e5b75505Sopenharmony_ci}
74e5b75505Sopenharmony_ci
75e5b75505Sopenharmony_cistatic void rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16],
76e5b75505Sopenharmony_ci			    u8 pt[16])
77e5b75505Sopenharmony_ci{
78e5b75505Sopenharmony_ci	u32 s0, s1, s2, s3, t0, t1, t2, t3;
79e5b75505Sopenharmony_ci#ifndef FULL_UNROLL
80e5b75505Sopenharmony_ci	int r;
81e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */
82e5b75505Sopenharmony_ci
83e5b75505Sopenharmony_ci	/*
84e5b75505Sopenharmony_ci	 * map byte array block to cipher state
85e5b75505Sopenharmony_ci	 * and add initial round key:
86e5b75505Sopenharmony_ci	 */
87e5b75505Sopenharmony_ci	s0 = GETU32(ct     ) ^ rk[0];
88e5b75505Sopenharmony_ci	s1 = GETU32(ct +  4) ^ rk[1];
89e5b75505Sopenharmony_ci	s2 = GETU32(ct +  8) ^ rk[2];
90e5b75505Sopenharmony_ci	s3 = GETU32(ct + 12) ^ rk[3];
91e5b75505Sopenharmony_ci
92e5b75505Sopenharmony_ci#define ROUND(i,d,s) \
93e5b75505Sopenharmony_cid##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
94e5b75505Sopenharmony_cid##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
95e5b75505Sopenharmony_cid##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
96e5b75505Sopenharmony_cid##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
97e5b75505Sopenharmony_ci
98e5b75505Sopenharmony_ci#ifdef FULL_UNROLL
99e5b75505Sopenharmony_ci
100e5b75505Sopenharmony_ci	ROUND(1,t,s);
101e5b75505Sopenharmony_ci	ROUND(2,s,t);
102e5b75505Sopenharmony_ci	ROUND(3,t,s);
103e5b75505Sopenharmony_ci	ROUND(4,s,t);
104e5b75505Sopenharmony_ci	ROUND(5,t,s);
105e5b75505Sopenharmony_ci	ROUND(6,s,t);
106e5b75505Sopenharmony_ci	ROUND(7,t,s);
107e5b75505Sopenharmony_ci	ROUND(8,s,t);
108e5b75505Sopenharmony_ci	ROUND(9,t,s);
109e5b75505Sopenharmony_ci	if (Nr > 10) {
110e5b75505Sopenharmony_ci		ROUND(10,s,t);
111e5b75505Sopenharmony_ci		ROUND(11,t,s);
112e5b75505Sopenharmony_ci		if (Nr > 12) {
113e5b75505Sopenharmony_ci			ROUND(12,s,t);
114e5b75505Sopenharmony_ci			ROUND(13,t,s);
115e5b75505Sopenharmony_ci		}
116e5b75505Sopenharmony_ci	}
117e5b75505Sopenharmony_ci
118e5b75505Sopenharmony_ci	rk += Nr << 2;
119e5b75505Sopenharmony_ci
120e5b75505Sopenharmony_ci#else  /* !FULL_UNROLL */
121e5b75505Sopenharmony_ci
122e5b75505Sopenharmony_ci	/* Nr - 1 full rounds: */
123e5b75505Sopenharmony_ci	r = Nr >> 1;
124e5b75505Sopenharmony_ci	for (;;) {
125e5b75505Sopenharmony_ci		ROUND(1,t,s);
126e5b75505Sopenharmony_ci		rk += 8;
127e5b75505Sopenharmony_ci		if (--r == 0)
128e5b75505Sopenharmony_ci			break;
129e5b75505Sopenharmony_ci		ROUND(0,s,t);
130e5b75505Sopenharmony_ci	}
131e5b75505Sopenharmony_ci
132e5b75505Sopenharmony_ci#endif /* ?FULL_UNROLL */
133e5b75505Sopenharmony_ci
134e5b75505Sopenharmony_ci#undef ROUND
135e5b75505Sopenharmony_ci
136e5b75505Sopenharmony_ci	/*
137e5b75505Sopenharmony_ci	 * apply last round and
138e5b75505Sopenharmony_ci	 * map cipher state to byte array block:
139e5b75505Sopenharmony_ci	 */
140e5b75505Sopenharmony_ci	s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
141e5b75505Sopenharmony_ci	PUTU32(pt     , s0);
142e5b75505Sopenharmony_ci	s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
143e5b75505Sopenharmony_ci	PUTU32(pt +  4, s1);
144e5b75505Sopenharmony_ci	s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
145e5b75505Sopenharmony_ci	PUTU32(pt +  8, s2);
146e5b75505Sopenharmony_ci	s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
147e5b75505Sopenharmony_ci	PUTU32(pt + 12, s3);
148e5b75505Sopenharmony_ci}
149e5b75505Sopenharmony_ci
150e5b75505Sopenharmony_ci
151e5b75505Sopenharmony_ciint aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
152e5b75505Sopenharmony_ci{
153e5b75505Sopenharmony_ci	u32 *rk = ctx;
154e5b75505Sopenharmony_ci	rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain);
155e5b75505Sopenharmony_ci	return 0;
156e5b75505Sopenharmony_ci}
157e5b75505Sopenharmony_ci
158e5b75505Sopenharmony_ci
159e5b75505Sopenharmony_civoid aes_decrypt_deinit(void *ctx)
160e5b75505Sopenharmony_ci{
161e5b75505Sopenharmony_ci	os_memset(ctx, 0, AES_PRIV_SIZE);
162e5b75505Sopenharmony_ci	os_free(ctx);
163e5b75505Sopenharmony_ci}
164