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