void AirPDcapTkipMixingPhase1( UINT16 *TTAK, const UINT8 *TK, const UINT8 *TA, UINT32 TSC) { UINT16 i, j; /* Initialize the 80-bit TTAK from TSC (TSC) and TA[0..5] */ TTAK[0] = Lo16(TSC); TTAK[1] = Hi16(TSC); TTAK[2] = Mk16(TA[1], TA[0]); TTAK[3] = Mk16(TA[3], TA[2]); TTAK[4] = Mk16(TA[5], TA[4]); for (i = 0; i < PHASE1_LOOP_COUNT; i++) { j = (UINT16)(2 * (i & 1)); TTAK[0] = (UINT16)(TTAK[0] + _S_((UINT16)(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])))); TTAK[1] = (UINT16)(TTAK[1] + _S_((UINT16)(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])))); TTAK[2] = (UINT16)(TTAK[2] + _S_((UINT16)(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])))); TTAK[3] = (UINT16)(TTAK[3] + _S_((UINT16)(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])))); TTAK[4] = (UINT16)(TTAK[4] + _S_((UINT16)(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j]))) + i); } }
/* * Routine: Phase 1 -- generate P1K, given TA, TK, IV32 * * Inputs: * TK[] = temporal key [128 bits] * TA[] = transmitter's MAC address [ 48 bits] * IV32 = upper 32 bits of IV [ 32 bits] * Output: * P1K[] = Phase 1 key [ 80 bits] * * Note: * This function only needs to be called every 2**16 packets, * although in theory it could be called every packet. * */ void BCMROMFN(tkhash_phase1)(uint16 *P1K, const uint8 *TK, const uint8 *TA, uint32 IV32) { uint16 i; /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ P1K[0] = Lo16(IV32); P1K[1] = Hi16(IV32); P1K[2] = Mk16(TA[1], TA[0]); /* use TA[] as little-endian */ P1K[3] = Mk16(TA[3], TA[2]); P1K[4] = Mk16(TA[5], TA[4]); /* Now compute an unbalanced Feistel cipher with 80-bit block */ /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add operation here is mod 2**16 */ P1K[0] += _S_(P1K[4] ^ TK16((i & 1) + 0)); P1K[1] += _S_(P1K[0] ^ TK16((i & 1) + 2)); P1K[2] += _S_(P1K[1] ^ TK16((i & 1) + 4)); P1K[3] += _S_(P1K[2] ^ TK16((i & 1) + 6)); P1K[4] += _S_(P1K[3] ^ TK16((i & 1) + 0)); P1K[4] += i; /* avoid "slide attacks" */ } }
VOID CKIP_key_permute ( OUT UCHAR *PK, /* output permuted key */ IN UCHAR *CK, /* input CKIP key */ IN UCHAR toDsFromDs, /* input toDs/FromDs bits */ IN UCHAR *piv /* input pointer to IV */ ) { int i; USHORT H[2], tmp; /* H=32-bits of per-packet hash value */ USHORT L[8], R[8]; /* L=u16 array of CK, R=u16 array of PK */ /* build L from input key */ memset(L, 0, sizeof(L)); for (i=0; i<16; i++) { L[i>>1] |= ( ((USHORT)(CK[i])) << ( i & 1 ? 8 : 0) ); } H[0] = (((USHORT)piv[0]) << 8) + piv[1]; H[1] = ( ((USHORT)toDsFromDs) << 8) | piv[2]; for (i=0; i<8; i++) { H[0] ^= L[i]; /* 16-bits of key material */ tmp = _S_(H[0]); /* 16x16 permutation */ H[0] = tmp ^ H[1]; /* set up for next round */ H[1] = tmp; R[i] = H[0]; /* store into key array */ } /* sweep in the other direction */ tmp=L[0]; for (i=7; i>0; i--) { R[i] = tmp = rotLeft_1(tmp) + R[i]; } /* IV of the permuted key is unchanged */ PK[0] = piv[0]; PK[1] = piv[1]; PK[2] = piv[2]; /* key portion of the permuted key is changed */ for (i=3; i<16; i++) { PK[i] = (UCHAR) (R[i>>1] >> (i & 1 ? 8 : 0)); } }
/* * * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 * * Inputs: * TK[] = Temporal key [128 bits] * P1K[] = Phase 1 output key [ 80 bits] * IV16 = low 16 bits of IV counter [ 16 bits] * Output: * RC4KEY[] = the key used to encrypt the packet [128 bits] * * Note: * The value {TA,IV32,IV16} for Phase1/Phase2 must be unique * across all packets using the same key TK value. Then, for a * given value of TK[], this TKIP48 construction guarantees that * the final RC4KEY value is unique across all packets. * * Suggested implementation optimization: if PPK[] is "overlaid" * appropriately on RC4KEY[], there is no need for the final * for loop below that copies the PPK[] result into RC4KEY[]. * */ void BCMROMFN(tkhash_phase2)(uint8 *RC4KEY, const uint8 *TK, const uint16 *P1K, uint16 IV16) { uint16 i; uint16 PPK[6]; /* temporary key for mixing */ /* Note: all adds in the PPK[] equations below are mod 2**16 */ for (i = 0; i < 5; i++) PPK[i]=P1K[i]; /* first, copy P1K to PPK */ PPK[5] = P1K[4] + IV16; /* next, add in IV16 */ /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ PPK[1] += _S_(PPK[0] ^ TK16(1)); PPK[2] += _S_(PPK[1] ^ TK16(2)); PPK[3] += _S_(PPK[2] ^ TK16(3)); PPK[4] += _S_(PPK[3] ^ TK16(4)); PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ PPK[0] += RotR1(PPK[5] ^ TK16(6)); PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ PPK[2] += RotR1(PPK[1]); PPK[3] += RotR1(PPK[2]); PPK[4] += RotR1(PPK[3]); PPK[5] += RotR1(PPK[4]); /* Note: At this point, for a given key TK[0..15], the 96-bit output */ /* value PPK[0..5] is guaranteed to be unique, as a function */ /* of the 96-bit "input" value {TA,IV32,IV16}. That is, P1K */ /* is now a keyed permutation of {TA,IV32,IV16}. */ /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ RC4KEY[0] = Hi8(IV16); /* RC4KEY[0..2] is the WEP IV */ RC4KEY[1] =(Hi8(IV16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ RC4KEY[2] = Lo8(IV16); RC4KEY[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ for (i = 0; i < 6; i++) { RC4KEY[4 + 2 * i] = Lo8(PPK[i]); RC4KEY[5 + 2 * i] = Hi8(PPK[i]); } }
static void AirPDcapTkipMixingPhase2( UINT8 *wep_seed, const UINT8 *TK, UINT16 *TTAK, UINT16 TSC16) { INT i; TTAK[5] = (UINT16)(TTAK[4] + TSC16); /* Step 2 - 96-bit bijective mixing using S-box */ TTAK[0] = (UINT16)(TTAK[0] + _S_((UINT16)(TTAK[5] ^ Mk16_le(&TK[0])))); TTAK[1] = (UINT16)(TTAK[1] + _S_((UINT16)(TTAK[0] ^ Mk16_le(&TK[2])))); TTAK[2] = (UINT16)(TTAK[2] + _S_((UINT16)(TTAK[1] ^ Mk16_le(&TK[4])))); TTAK[3] = (UINT16)(TTAK[3] + _S_((UINT16)(TTAK[2] ^ Mk16_le(&TK[6])))); TTAK[4] = (UINT16)(TTAK[4] + _S_((UINT16)(TTAK[3] ^ Mk16_le(&TK[8])))); TTAK[5] = (UINT16)(TTAK[5] + _S_((UINT16)(TTAK[4] ^ Mk16_le(&TK[10])))); TTAK[0] = (UINT16)(TTAK[0] + RotR1((UINT16)(TTAK[5] ^ Mk16_le(&TK[12])))); TTAK[1] = (UINT16)(TTAK[1] + RotR1((UINT16)(TTAK[0] ^ Mk16_le(&TK[14])))); TTAK[2] = (UINT16)(TTAK[2] + RotR1(TTAK[1])); TTAK[3] = (UINT16)(TTAK[3] + RotR1(TTAK[2])); TTAK[4] = (UINT16)(TTAK[4] + RotR1(TTAK[3])); TTAK[5] = (UINT16)(TTAK[5] + RotR1(TTAK[4])); /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value * wep_seed[0..2] is transmitted as WEP IV */ wep_seed[0] = Hi8(TSC16); wep_seed[1] = (UINT8)((Hi8(TSC16) | 0x20) & 0x7F); wep_seed[2] = Lo8(TSC16); wep_seed[3] = Lo8((UINT16)((TTAK[5] ^ Mk16_le(&TK[0])) >> 1)); for (i = 0; i < 6; i++) { wep_seed[4 + ( 2 * i)] = Lo8( TTAK[i] ); wep_seed[5 + ( 2 * i)] = Hi8( TTAK[i] ); } }