1/*
2 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
3 * All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 *
20 * File: aes_ccmp.c
21 *
22 * Purpose: AES_CCMP decryption
23 *
24 * Author: Warren Hsu
25 *
26 * Date: Feb 15, 2005
27 *
28 * Functions:
29 *      AESbGenCCMP - Parsing RX-packet
30 *
31 *
32 * Revision History:
33 *
34 */
35
36#include "device.h"
37#include "80211hdr.h"
38#include "aes_ccmp.h"
39
40/*---------------------  Static Definitions -------------------------*/
41
42/*---------------------  Static Classes  ----------------------------*/
43
44/*---------------------  Static Variables  --------------------------*/
45
46/*
47 * SBOX Table
48 */
49
50static unsigned char sbox_table[256] = {
51	0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
52	0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
53	0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
54	0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
55	0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
56	0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
57	0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
58	0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
59	0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
60	0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
61	0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
62	0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
63	0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
64	0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
65	0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
66	0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
67};
68
69static unsigned char dot2_table[256] = {
70	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
71	0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
72	0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
73	0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
74	0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
75	0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
76	0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
77	0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
78	0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
79	0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
80	0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
81	0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
82	0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
83	0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
84	0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
85	0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
86};
87
88static unsigned char dot3_table[256] = {
89	0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
90	0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
91	0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
92	0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
93	0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
94	0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
95	0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
96	0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
97	0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
98	0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
99	0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
100	0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
101	0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
102	0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
103	0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
104	0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
105};
106
107/*---------------------  Static Functions  --------------------------*/
108
109/*---------------------  Export Variables  --------------------------*/
110
111/*---------------------  Export Functions  --------------------------*/
112
113static void xor_128(unsigned char *a, unsigned char *b, unsigned char *out)
114{
115	unsigned long *dwPtrA = (unsigned long *)a;
116	unsigned long *dwPtrB = (unsigned long *)b;
117	unsigned long *dwPtrOut = (unsigned long *)out;
118
119	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
120	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
121	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
122	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
123}
124
125static void xor_32(unsigned char *a, unsigned char *b, unsigned char *out)
126{
127	unsigned long *dwPtrA = (unsigned long *)a;
128	unsigned long *dwPtrB = (unsigned long *)b;
129	unsigned long *dwPtrOut = (unsigned long *)out;
130
131	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
132}
133
134static void AddRoundKey(unsigned char *key, int round)
135{
136	unsigned char sbox_key[4];
137	unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
138
139	sbox_key[0] = sbox_table[key[13]];
140	sbox_key[1] = sbox_table[key[14]];
141	sbox_key[2] = sbox_table[key[15]];
142	sbox_key[3] = sbox_table[key[12]];
143
144	key[0] = key[0] ^ rcon_table[round];
145	xor_32(&key[0], sbox_key, &key[0]);
146
147	xor_32(&key[4], &key[0], &key[4]);
148	xor_32(&key[8], &key[4], &key[8]);
149	xor_32(&key[12], &key[8], &key[12]);
150}
151
152static void SubBytes(unsigned char *in, unsigned char *out)
153{
154	int i;
155
156	for (i = 0; i < 16; i++)
157		out[i] = sbox_table[in[i]];
158}
159
160static void ShiftRows(unsigned char *in, unsigned char *out)
161{
162	out[0]  = in[0];
163	out[1]  = in[5];
164	out[2]  = in[10];
165	out[3]  = in[15];
166	out[4]  = in[4];
167	out[5]  = in[9];
168	out[6]  = in[14];
169	out[7]  = in[3];
170	out[8]  = in[8];
171	out[9]  = in[13];
172	out[10] = in[2];
173	out[11] = in[7];
174	out[12] = in[12];
175	out[13] = in[1];
176	out[14] = in[6];
177	out[15] = in[11];
178}
179
180static void MixColumns(unsigned char *in, unsigned char *out)
181{
182	out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
183	out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
184	out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]];
185	out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
186}
187
188static void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
189{
190	int  i;
191	int  round;
192	unsigned char TmpdataA[16];
193	unsigned char TmpdataB[16];
194	unsigned char abyRoundKey[16];
195
196	for (i = 0; i < 16; i++)
197		abyRoundKey[i] = key[i];
198
199	for (round = 0; round < 11; round++) {
200		if (round == 0) {
201			xor_128(abyRoundKey, data, ciphertext);
202			AddRoundKey(abyRoundKey, round);
203		} else if (round == 10) {
204			SubBytes(ciphertext, TmpdataA);
205			ShiftRows(TmpdataA, TmpdataB);
206			xor_128(TmpdataB, abyRoundKey, ciphertext);
207		} else /* round 1 ~ 9 */{
208			SubBytes(ciphertext, TmpdataA);
209			ShiftRows(TmpdataA, TmpdataB);
210			MixColumns(&TmpdataB[0], &TmpdataA[0]);
211			MixColumns(&TmpdataB[4], &TmpdataA[4]);
212			MixColumns(&TmpdataB[8], &TmpdataA[8]);
213			MixColumns(&TmpdataB[12], &TmpdataA[12]);
214			xor_128(TmpdataA, abyRoundKey, ciphertext);
215			AddRoundKey(abyRoundKey, round);
216		}
217	}
218}
219
220/*
221 * Description: AES decryption
222 *
223 * Parameters:
224 *  In:
225 *      pbyRxKey            - The key used to decrypt
226 *      pbyFrame            - Starting address of packet header
227 *      wFrameSize          - Total packet size including CRC
228 *  Out:
229 *      none
230 *
231 * Return Value: MIC compare result
232 *
233 */
234bool AESbGenCCMP(unsigned char *pbyRxKey, unsigned char *pbyFrame, unsigned short wFrameSize)
235{
236	unsigned char abyNonce[13];
237	unsigned char MIC_IV[16];
238	unsigned char MIC_HDR1[16];
239	unsigned char MIC_HDR2[16];
240	unsigned char abyMIC[16];
241	unsigned char abyCTRPLD[16];
242	unsigned char abyTmp[16];
243	unsigned char abyPlainText[16];
244	unsigned char abyLastCipher[16];
245
246	PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
247	unsigned char *pbyIV;
248	unsigned char *pbyPayload;
249	unsigned short wHLen = 22;
250	unsigned short wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;/* 8 is IV, 8 is MIC, 4 is CRC */
251	bool bA4 = false;
252	unsigned char byTmp;
253	unsigned short wCnt;
254	int ii, jj, kk;
255
256	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
257	if (WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
258	    WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame)) {
259		bA4 = true;
260		pbyIV += 6;             /* 6 is 802.11 address4 */
261		wHLen += 6;
262		wPayloadSize -= 6;
263	}
264	pbyPayload = pbyIV + 8; /* IV-length */
265
266	abyNonce[0]  = 0x00; /* now is 0, if Qos here will be priority */
267	memcpy(&(abyNonce[1]), pMACHeader->abyAddr2, ETH_ALEN);
268	abyNonce[7]  = pbyIV[7];
269	abyNonce[8]  = pbyIV[6];
270	abyNonce[9]  = pbyIV[5];
271	abyNonce[10] = pbyIV[4];
272	abyNonce[11] = pbyIV[1];
273	abyNonce[12] = pbyIV[0];
274
275	/* MIC_IV */
276	MIC_IV[0] = 0x59;
277	memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13);
278	MIC_IV[14] = (unsigned char)(wPayloadSize >> 8);
279	MIC_IV[15] = (unsigned char)(wPayloadSize & 0xff);
280
281	/* MIC_HDR1 */
282	MIC_HDR1[0] = (unsigned char)(wHLen >> 8);
283	MIC_HDR1[1] = (unsigned char)(wHLen & 0xff);
284	byTmp = (unsigned char)(pMACHeader->wFrameCtl & 0xff);
285	MIC_HDR1[2] = byTmp & 0x8f;
286	byTmp = (unsigned char)(pMACHeader->wFrameCtl >> 8);
287	byTmp &= 0x87;
288	MIC_HDR1[3] = byTmp | 0x40;
289	memcpy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, ETH_ALEN);
290	memcpy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, ETH_ALEN);
291
292	/* MIC_HDR2 */
293	memcpy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, ETH_ALEN);
294	byTmp = (unsigned char)(pMACHeader->wSeqCtl & 0xff);
295	MIC_HDR2[6] = byTmp & 0x0f;
296	MIC_HDR2[7] = 0;
297	if (bA4) {
298		memcpy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, ETH_ALEN);
299	} else {
300		MIC_HDR2[8]  = 0x00;
301		MIC_HDR2[9]  = 0x00;
302		MIC_HDR2[10] = 0x00;
303		MIC_HDR2[11] = 0x00;
304		MIC_HDR2[12] = 0x00;
305		MIC_HDR2[13] = 0x00;
306	}
307	MIC_HDR2[14] = 0x00;
308	MIC_HDR2[15] = 0x00;
309
310	/* CCMP */
311	AESv128(pbyRxKey, MIC_IV, abyMIC);
312	for (kk = 0; kk < 16; kk++)
313		abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk];
314	AESv128(pbyRxKey, abyTmp, abyMIC);
315	for (kk = 0; kk < 16; kk++)
316		abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk];
317	AESv128(pbyRxKey, abyTmp, abyMIC);
318
319	wCnt = 1;
320	abyCTRPLD[0] = 0x01;
321	memcpy(&(abyCTRPLD[1]), &(abyNonce[0]), 13);
322
323	for (jj = wPayloadSize; jj > 16; jj = jj - 16) {
324		abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
325		abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
326
327		AESv128(pbyRxKey, abyCTRPLD, abyTmp);
328
329		for (kk = 0; kk < 16; kk++)
330			abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk];
331		for (kk = 0; kk < 16; kk++)
332			abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
333		AESv128(pbyRxKey, abyTmp, abyMIC);
334
335		memcpy(pbyPayload, abyPlainText, 16);
336		wCnt++;
337		pbyPayload += 16;
338	} /* for wPayloadSize */
339
340	/* last payload */
341	memcpy(&(abyLastCipher[0]), pbyPayload, jj);
342	for (ii = jj; ii < 16; ii++)
343		abyLastCipher[ii] = 0x00;
344
345	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
346	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
347
348	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
349	for (kk = 0; kk < 16; kk++)
350		abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk];
351	memcpy(pbyPayload, abyPlainText, jj);
352	pbyPayload += jj;
353
354	/* for MIC calculation */
355	for (ii = jj; ii < 16; ii++)
356		abyPlainText[ii] = 0x00;
357	for (kk = 0; kk < 16; kk++)
358		abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
359	AESv128(pbyRxKey, abyTmp, abyMIC);
360
361	/* =>above is the calculate MIC */
362	/* -------------------------------------------- */
363
364	wCnt = 0;
365	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
366	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
367	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
368	for (kk = 0; kk < 8; kk++)
369		abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk];
370	/* =>above is the dec-MIC from packet */
371	/* -------------------------------------------- */
372
373	return !memcmp(abyMIC, abyTmp, 8);
374}
375