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