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