aes_ccmp.c revision 659b4d97fff5c9acb8596d85777ae0023e2539b8
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
39/*---------------------  Static Definitions -------------------------*/
40
41/*---------------------  Static Classes  ----------------------------*/
42
43/*---------------------  Static Variables  --------------------------*/
44
45/*
46 * SBOX Table
47 */
48
49unsigned char sbox_table[256] =
50{
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
69unsigned 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
88unsigned 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
113void 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
125
126void xor_32(unsigned char *a, unsigned char *b, unsigned char *out)
127{
128	unsigned long *dwPtrA = (unsigned long *)a;
129	unsigned long *dwPtrB = (unsigned long *)b;
130	unsigned long *dwPtrOut = (unsigned long *)out;
131
132	(*dwPtrOut++) = (*dwPtrA++) ^ (*dwPtrB++);
133}
134
135void AddRoundKey(unsigned char *key, int round)
136{
137	unsigned char sbox_key[4];
138	unsigned char rcon_table[10] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
139
140	sbox_key[0] = sbox_table[key[13]];
141	sbox_key[1] = sbox_table[key[14]];
142	sbox_key[2] = sbox_table[key[15]];
143	sbox_key[3] = sbox_table[key[12]];
144
145	key[0] = key[0] ^ rcon_table[round];
146	xor_32(&key[0], sbox_key, &key[0]);
147
148	xor_32(&key[4], &key[0], &key[4]);
149	xor_32(&key[8], &key[4], &key[8]);
150	xor_32(&key[12], &key[8], &key[12]);
151}
152
153void SubBytes(unsigned char *in, unsigned char *out)
154{
155	int i;
156
157	for (i = 0; i < 16; i++)
158	{
159		out[i] = sbox_table[in[i]];
160	}
161}
162
163void ShiftRows(unsigned char *in, unsigned char *out)
164{
165	out[0]  = in[0];
166	out[1]  = in[5];
167	out[2]  = in[10];
168	out[3]  = in[15];
169	out[4]  = in[4];
170	out[5]  = in[9];
171	out[6]  = in[14];
172	out[7]  = in[3];
173	out[8]  = in[8];
174	out[9]  = in[13];
175	out[10] = in[2];
176	out[11] = in[7];
177	out[12] = in[12];
178	out[13] = in[1];
179	out[14] = in[6];
180	out[15] = in[11];
181}
182
183void MixColumns(unsigned char *in, unsigned char *out)
184{
185
186	out[0] = dot2_table[in[0]] ^ dot3_table[in[1]] ^ in[2] ^ in[3];
187	out[1] = in[0] ^ dot2_table[in[1]] ^ dot3_table[in[2]] ^ in[3];
188	out[2] = in[0] ^ in[1] ^ dot2_table[in[2]] ^ dot3_table[in[3]];
189	out[3] = dot3_table[in[0]] ^ in[1] ^ in[2] ^ dot2_table[in[3]];
190}
191
192
193void AESv128(unsigned char *key, unsigned char *data, unsigned char *ciphertext)
194{
195	int  i;
196	int  round;
197	unsigned char TmpdataA[16];
198	unsigned char TmpdataB[16];
199	unsigned char abyRoundKey[16];
200
201	for (i = 0; i < 16; i++)
202		abyRoundKey[i] = key[i];
203
204	for (round = 0; round < 11; round++)
205	{
206		if (round == 0)
207		{
208			xor_128(abyRoundKey, data, ciphertext);
209			AddRoundKey(abyRoundKey, round);
210		}
211		else if (round == 10)
212		{
213			SubBytes(ciphertext, TmpdataA);
214			ShiftRows(TmpdataA, TmpdataB);
215			xor_128(TmpdataB, abyRoundKey, ciphertext);
216		}
217		else // round 1 ~ 9
218		{
219			SubBytes(ciphertext, TmpdataA);
220			ShiftRows(TmpdataA, TmpdataB);
221			MixColumns(&TmpdataB[0], &TmpdataA[0]);
222			MixColumns(&TmpdataB[4], &TmpdataA[4]);
223			MixColumns(&TmpdataB[8], &TmpdataA[8]);
224			MixColumns(&TmpdataB[12], &TmpdataA[12]);
225			xor_128(TmpdataA, abyRoundKey, ciphertext);
226			AddRoundKey(abyRoundKey, round);
227		}
228	}
229
230}
231
232/*
233 * Description: AES decryption
234 *
235 * Parameters:
236 *  In:
237 *      pbyRxKey            - The key used to decrypt
238 *      pbyFrame            - Starting address of packet header
239 *      wFrameSize          - Total packet size including CRC
240 *  Out:
241 *      none
242 *
243 * Return Value: MIC compare result
244 *
245 */
246bool AESbGenCCMP(unsigned char *pbyRxKey, unsigned char *pbyFrame, unsigned short wFrameSize)
247{
248	unsigned char abyNonce[13];
249	unsigned char MIC_IV[16];
250	unsigned char MIC_HDR1[16];
251	unsigned char MIC_HDR2[16];
252	unsigned char abyMIC[16];
253	unsigned char abyCTRPLD[16];
254	unsigned char abyTmp[16];
255	unsigned char abyPlainText[16];
256	unsigned char abyLastCipher[16];
257
258	PS802_11Header  pMACHeader = (PS802_11Header) pbyFrame;
259	unsigned char *pbyIV;
260	unsigned char *pbyPayload;
261	unsigned short wHLen = 22;
262	unsigned short wPayloadSize = wFrameSize - 8 - 8 - 4 - WLAN_HDR_ADDR3_LEN;//8 is IV, 8 is MIC, 4 is CRC
263	bool bA4 = false;
264	unsigned char byTmp;
265	unsigned short wCnt;
266	int ii, jj, kk;
267
268
269	pbyIV = pbyFrame + WLAN_HDR_ADDR3_LEN;
270	if (WLAN_GET_FC_TODS(*(unsigned short *)pbyFrame) &&
271	    WLAN_GET_FC_FROMDS(*(unsigned short *)pbyFrame)) {
272		bA4 = true;
273		pbyIV += 6;             // 6 is 802.11 address4
274		wHLen += 6;
275		wPayloadSize -= 6;
276	}
277	pbyPayload = pbyIV + 8; //IV-length
278
279	abyNonce[0]  = 0x00; //now is 0, if Qos here will be priority
280	memcpy(&(abyNonce[1]), pMACHeader->abyAddr2, ETH_ALEN);
281	abyNonce[7]  = pbyIV[7];
282	abyNonce[8]  = pbyIV[6];
283	abyNonce[9]  = pbyIV[5];
284	abyNonce[10] = pbyIV[4];
285	abyNonce[11] = pbyIV[1];
286	abyNonce[12] = pbyIV[0];
287
288	//MIC_IV
289	MIC_IV[0] = 0x59;
290	memcpy(&(MIC_IV[1]), &(abyNonce[0]), 13);
291	MIC_IV[14] = (unsigned char)(wPayloadSize >> 8);
292	MIC_IV[15] = (unsigned char)(wPayloadSize & 0xff);
293
294	//MIC_HDR1
295	MIC_HDR1[0] = (unsigned char)(wHLen >> 8);
296	MIC_HDR1[1] = (unsigned char)(wHLen & 0xff);
297	byTmp = (unsigned char)(pMACHeader->wFrameCtl & 0xff);
298	MIC_HDR1[2] = byTmp & 0x8f;
299	byTmp = (unsigned char)(pMACHeader->wFrameCtl >> 8);
300	byTmp &= 0x87;
301	MIC_HDR1[3] = byTmp | 0x40;
302	memcpy(&(MIC_HDR1[4]), pMACHeader->abyAddr1, ETH_ALEN);
303	memcpy(&(MIC_HDR1[10]), pMACHeader->abyAddr2, ETH_ALEN);
304
305	//MIC_HDR2
306	memcpy(&(MIC_HDR2[0]), pMACHeader->abyAddr3, ETH_ALEN);
307	byTmp = (unsigned char)(pMACHeader->wSeqCtl & 0xff);
308	MIC_HDR2[6] = byTmp & 0x0f;
309	MIC_HDR2[7] = 0;
310	if (bA4) {
311		memcpy(&(MIC_HDR2[8]), pMACHeader->abyAddr4, ETH_ALEN);
312	} else {
313		MIC_HDR2[8]  = 0x00;
314		MIC_HDR2[9]  = 0x00;
315		MIC_HDR2[10] = 0x00;
316		MIC_HDR2[11] = 0x00;
317		MIC_HDR2[12] = 0x00;
318		MIC_HDR2[13] = 0x00;
319	}
320	MIC_HDR2[14] = 0x00;
321	MIC_HDR2[15] = 0x00;
322
323	//CCMP
324	AESv128(pbyRxKey, MIC_IV, abyMIC);
325	for (kk = 0; kk < 16; kk++) {
326		abyTmp[kk] = MIC_HDR1[kk] ^ abyMIC[kk];
327	}
328	AESv128(pbyRxKey, abyTmp, abyMIC);
329	for (kk = 0; kk < 16; kk++) {
330		abyTmp[kk] = MIC_HDR2[kk] ^ abyMIC[kk];
331	}
332	AESv128(pbyRxKey, abyTmp, abyMIC);
333
334	wCnt = 1;
335	abyCTRPLD[0] = 0x01;
336	memcpy(&(abyCTRPLD[1]), &(abyNonce[0]), 13);
337
338	for (jj = wPayloadSize; jj > 16; jj = jj - 16) {
339
340		abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
341		abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
342
343		AESv128(pbyRxKey, abyCTRPLD, abyTmp);
344
345		for (kk = 0; kk < 16; kk++) {
346			abyPlainText[kk] = abyTmp[kk] ^ pbyPayload[kk];
347		}
348		for (kk = 0; kk < 16; kk++) {
349			abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
350		}
351		AESv128(pbyRxKey, abyTmp, abyMIC);
352
353		memcpy(pbyPayload, abyPlainText, 16);
354		wCnt++;
355		pbyPayload += 16;
356	} //for wPayloadSize
357
358	//last payload
359	memcpy(&(abyLastCipher[0]), pbyPayload, jj);
360	for (ii = jj; ii < 16; ii++) {
361		abyLastCipher[ii] = 0x00;
362	}
363
364	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
365	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
366
367	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
368	for (kk = 0; kk < 16; kk++) {
369		abyPlainText[kk] = abyTmp[kk] ^ abyLastCipher[kk];
370	}
371	memcpy(pbyPayload, abyPlainText, jj);
372	pbyPayload += jj;
373
374	//for MIC calculation
375	for (ii = jj; ii < 16; ii++) {
376		abyPlainText[ii] = 0x00;
377	}
378	for (kk = 0; kk < 16; kk++) {
379		abyTmp[kk] = abyMIC[kk] ^ abyPlainText[kk];
380	}
381	AESv128(pbyRxKey, abyTmp, abyMIC);
382
383	//=>above is the calculate MIC
384	//--------------------------------------------
385
386	wCnt = 0;
387	abyCTRPLD[14] = (unsigned char)(wCnt >> 8);
388	abyCTRPLD[15] = (unsigned char)(wCnt & 0xff);
389	AESv128(pbyRxKey, abyCTRPLD, abyTmp);
390	for (kk = 0; kk < 8; kk++) {
391		abyTmp[kk] = abyTmp[kk] ^ pbyPayload[kk];
392	}
393	//=>above is the dec-MIC from packet
394	//--------------------------------------------
395
396	if (!memcmp(abyMIC, abyTmp, 8)) {
397		return true;
398	} else {
399		return false;
400	}
401
402}
403