2007-05-05 22:45:53 +04:00
/*
* Copyright 2002 - 2004 , Instant802 Networks , Inc .
* Copyright 2005 , Devicescape Software , Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/netdevice.h>
# include <net/mac80211.h>
# include "ieee80211_key.h"
# include "tkip.h"
# include "wep.h"
/* TKIP key mixing functions */
# define PHASE1_LOOP_COUNT 8
/* 2-byte by 2-byte subset of the full AES S-box table; second part of this
* table is identical to first part but byte - swapped */
static const u16 tkip_sbox [ 256 ] =
{
0xC6A5 , 0xF884 , 0xEE99 , 0xF68D , 0xFF0D , 0xD6BD , 0xDEB1 , 0x9154 ,
0x6050 , 0x0203 , 0xCEA9 , 0x567D , 0xE719 , 0xB562 , 0x4DE6 , 0xEC9A ,
0x8F45 , 0x1F9D , 0x8940 , 0xFA87 , 0xEF15 , 0xB2EB , 0x8EC9 , 0xFB0B ,
0x41EC , 0xB367 , 0x5FFD , 0x45EA , 0x23BF , 0x53F7 , 0xE496 , 0x9B5B ,
0x75C2 , 0xE11C , 0x3DAE , 0x4C6A , 0x6C5A , 0x7E41 , 0xF502 , 0x834F ,
0x685C , 0x51F4 , 0xD134 , 0xF908 , 0xE293 , 0xAB73 , 0x6253 , 0x2A3F ,
0x080C , 0x9552 , 0x4665 , 0x9D5E , 0x3028 , 0x37A1 , 0x0A0F , 0x2FB5 ,
0x0E09 , 0x2436 , 0x1B9B , 0xDF3D , 0xCD26 , 0x4E69 , 0x7FCD , 0xEA9F ,
0x121B , 0x1D9E , 0x5874 , 0x342E , 0x362D , 0xDCB2 , 0xB4EE , 0x5BFB ,
0xA4F6 , 0x764D , 0xB761 , 0x7DCE , 0x527B , 0xDD3E , 0x5E71 , 0x1397 ,
0xA6F5 , 0xB968 , 0x0000 , 0xC12C , 0x4060 , 0xE31F , 0x79C8 , 0xB6ED ,
0xD4BE , 0x8D46 , 0x67D9 , 0x724B , 0x94DE , 0x98D4 , 0xB0E8 , 0x854A ,
0xBB6B , 0xC52A , 0x4FE5 , 0xED16 , 0x86C5 , 0x9AD7 , 0x6655 , 0x1194 ,
0x8ACF , 0xE910 , 0x0406 , 0xFE81 , 0xA0F0 , 0x7844 , 0x25BA , 0x4BE3 ,
0xA2F3 , 0x5DFE , 0x80C0 , 0x058A , 0x3FAD , 0x21BC , 0x7048 , 0xF104 ,
0x63DF , 0x77C1 , 0xAF75 , 0x4263 , 0x2030 , 0xE51A , 0xFD0E , 0xBF6D ,
0x814C , 0x1814 , 0x2635 , 0xC32F , 0xBEE1 , 0x35A2 , 0x88CC , 0x2E39 ,
0x9357 , 0x55F2 , 0xFC82 , 0x7A47 , 0xC8AC , 0xBAE7 , 0x322B , 0xE695 ,
0xC0A0 , 0x1998 , 0x9ED1 , 0xA37F , 0x4466 , 0x547E , 0x3BAB , 0x0B83 ,
0x8CCA , 0xC729 , 0x6BD3 , 0x283C , 0xA779 , 0xBCE2 , 0x161D , 0xAD76 ,
0xDB3B , 0x6456 , 0x744E , 0x141E , 0x92DB , 0x0C0A , 0x486C , 0xB8E4 ,
0x9F5D , 0xBD6E , 0x43EF , 0xC4A6 , 0x39A8 , 0x31A4 , 0xD337 , 0xF28B ,
0xD532 , 0x8B43 , 0x6E59 , 0xDAB7 , 0x018C , 0xB164 , 0x9CD2 , 0x49E0 ,
0xD8B4 , 0xACFA , 0xF307 , 0xCF25 , 0xCAAF , 0xF48E , 0x47E9 , 0x1018 ,
0x6FD5 , 0xF088 , 0x4A6F , 0x5C72 , 0x3824 , 0x57F1 , 0x73C7 , 0x9751 ,
0xCB23 , 0xA17C , 0xE89C , 0x3E21 , 0x96DD , 0x61DC , 0x0D86 , 0x0F85 ,
0xE090 , 0x7C42 , 0x71C4 , 0xCCAA , 0x90D8 , 0x0605 , 0xF701 , 0x1C12 ,
0xC2A3 , 0x6A5F , 0xAEF9 , 0x69D0 , 0x1791 , 0x9958 , 0x3A27 , 0x27B9 ,
0xD938 , 0xEB13 , 0x2BB3 , 0x2233 , 0xD2BB , 0xA970 , 0x0789 , 0x33A7 ,
0x2DB6 , 0x3C22 , 0x1592 , 0xC920 , 0x8749 , 0xAAFF , 0x5078 , 0xA57A ,
0x038F , 0x59F8 , 0x0980 , 0x1A17 , 0x65DA , 0xD731 , 0x84C6 , 0xD0B8 ,
0x82C3 , 0x29B0 , 0x5A77 , 0x1E11 , 0x7BCB , 0xA8FC , 0x6DD6 , 0x2C3A ,
} ;
static inline u16 Mk16 ( u8 x , u8 y )
{
return ( ( u16 ) x < < 8 ) | ( u16 ) y ;
}
static inline u8 Hi8 ( u16 v )
{
return v > > 8 ;
}
static inline u8 Lo8 ( u16 v )
{
return v & 0xff ;
}
static inline u16 Hi16 ( u32 v )
{
return v > > 16 ;
}
static inline u16 Lo16 ( u32 v )
{
return v & 0xffff ;
}
static inline u16 RotR1 ( u16 v )
{
return ( v > > 1 ) | ( ( v & 0x0001 ) < < 15 ) ;
}
static inline u16 tkip_S ( u16 val )
{
u16 a = tkip_sbox [ Hi8 ( val ) ] ;
return tkip_sbox [ Lo8 ( val ) ] ^ Hi8 ( a ) ^ ( Lo8 ( a ) < < 8 ) ;
}
/* P1K := Phase1(TA, TK, TSC)
* TA = transmitter address ( 48 bits )
* TK = dot11DefaultKeyValue or dot11KeyMappingValue ( 128 bits )
* TSC = TKIP sequence counter ( 48 bits , only 32 msb bits used )
* P1K : 80 bits
*/
static void tkip_mixing_phase1 ( const u8 * ta , const u8 * tk , u32 tsc_IV32 ,
u16 * p1k )
{
int i , j ;
p1k [ 0 ] = Lo16 ( tsc_IV32 ) ;
p1k [ 1 ] = Hi16 ( tsc_IV32 ) ;
p1k [ 2 ] = Mk16 ( ta [ 1 ] , ta [ 0 ] ) ;
p1k [ 3 ] = Mk16 ( ta [ 3 ] , ta [ 2 ] ) ;
p1k [ 4 ] = Mk16 ( ta [ 5 ] , ta [ 4 ] ) ;
for ( i = 0 ; i < PHASE1_LOOP_COUNT ; i + + ) {
j = 2 * ( i & 1 ) ;
p1k [ 0 ] + = tkip_S ( p1k [ 4 ] ^ Mk16 ( tk [ 1 + j ] , tk [ 0 + j ] ) ) ;
p1k [ 1 ] + = tkip_S ( p1k [ 0 ] ^ Mk16 ( tk [ 5 + j ] , tk [ 4 + j ] ) ) ;
p1k [ 2 ] + = tkip_S ( p1k [ 1 ] ^ Mk16 ( tk [ 9 + j ] , tk [ 8 + j ] ) ) ;
p1k [ 3 ] + = tkip_S ( p1k [ 2 ] ^ Mk16 ( tk [ 13 + j ] , tk [ 12 + j ] ) ) ;
p1k [ 4 ] + = tkip_S ( p1k [ 3 ] ^ Mk16 ( tk [ 1 + j ] , tk [ 0 + j ] ) ) + i ;
}
}
static void tkip_mixing_phase2 ( const u16 * p1k , const u8 * tk , u16 tsc_IV16 ,
u8 * rc4key )
{
u16 ppk [ 6 ] ;
int i ;
ppk [ 0 ] = p1k [ 0 ] ;
ppk [ 1 ] = p1k [ 1 ] ;
ppk [ 2 ] = p1k [ 2 ] ;
ppk [ 3 ] = p1k [ 3 ] ;
ppk [ 4 ] = p1k [ 4 ] ;
ppk [ 5 ] = p1k [ 4 ] + tsc_IV16 ;
ppk [ 0 ] + = tkip_S ( ppk [ 5 ] ^ Mk16 ( tk [ 1 ] , tk [ 0 ] ) ) ;
ppk [ 1 ] + = tkip_S ( ppk [ 0 ] ^ Mk16 ( tk [ 3 ] , tk [ 2 ] ) ) ;
ppk [ 2 ] + = tkip_S ( ppk [ 1 ] ^ Mk16 ( tk [ 5 ] , tk [ 4 ] ) ) ;
ppk [ 3 ] + = tkip_S ( ppk [ 2 ] ^ Mk16 ( tk [ 7 ] , tk [ 6 ] ) ) ;
ppk [ 4 ] + = tkip_S ( ppk [ 3 ] ^ Mk16 ( tk [ 9 ] , tk [ 8 ] ) ) ;
ppk [ 5 ] + = tkip_S ( ppk [ 4 ] ^ Mk16 ( tk [ 11 ] , tk [ 10 ] ) ) ;
ppk [ 0 ] + = RotR1 ( ppk [ 5 ] ^ Mk16 ( tk [ 13 ] , tk [ 12 ] ) ) ;
ppk [ 1 ] + = RotR1 ( ppk [ 0 ] ^ Mk16 ( tk [ 15 ] , tk [ 14 ] ) ) ;
ppk [ 2 ] + = RotR1 ( ppk [ 1 ] ) ;
ppk [ 3 ] + = RotR1 ( ppk [ 2 ] ) ;
ppk [ 4 ] + = RotR1 ( ppk [ 3 ] ) ;
ppk [ 5 ] + = RotR1 ( ppk [ 4 ] ) ;
rc4key [ 0 ] = Hi8 ( tsc_IV16 ) ;
rc4key [ 1 ] = ( Hi8 ( tsc_IV16 ) | 0x20 ) & 0x7f ;
rc4key [ 2 ] = Lo8 ( tsc_IV16 ) ;
rc4key [ 3 ] = Lo8 ( ( ppk [ 5 ] ^ Mk16 ( tk [ 1 ] , tk [ 0 ] ) ) > > 1 ) ;
for ( i = 0 ; i < 6 ; i + + ) {
rc4key [ 4 + 2 * i ] = Lo8 ( ppk [ i ] ) ;
rc4key [ 5 + 2 * i ] = Hi8 ( ppk [ i ] ) ;
}
}
/* Add TKIP IV and Ext. IV at @pos. @iv0, @iv1, and @iv2 are the first octets
* of the IV . Returns pointer to the octet following IVs ( i . e . , beginning of
* the packet payload ) . */
u8 * ieee80211_tkip_add_iv ( u8 * pos , struct ieee80211_key * key ,
u8 iv0 , u8 iv1 , u8 iv2 )
{
* pos + + = iv0 ;
* pos + + = iv1 ;
* pos + + = iv2 ;
2007-08-29 01:01:54 +04:00
* pos + + = ( key - > conf . keyidx < < 6 ) | ( 1 < < 5 ) /* Ext IV */ ;
2007-05-05 22:45:53 +04:00
* pos + + = key - > u . tkip . iv32 & 0xff ;
* pos + + = ( key - > u . tkip . iv32 > > 8 ) & 0xff ;
* pos + + = ( key - > u . tkip . iv32 > > 16 ) & 0xff ;
* pos + + = ( key - > u . tkip . iv32 > > 24 ) & 0xff ;
return pos ;
}
void ieee80211_tkip_gen_phase1key ( struct ieee80211_key * key , u8 * ta ,
u16 * phase1key )
{
2007-08-29 01:01:54 +04:00
tkip_mixing_phase1 ( ta , & key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
2007-05-05 22:45:53 +04:00
key - > u . tkip . iv32 , phase1key ) ;
}
void ieee80211_tkip_gen_rc4key ( struct ieee80211_key * key , u8 * ta ,
u8 * rc4key )
{
/* Calculate per-packet key */
if ( key - > u . tkip . iv16 = = 0 | | ! key - > u . tkip . tx_initialized ) {
/* IV16 wrapped around - perform TKIP phase 1 */
2007-08-29 01:01:54 +04:00
tkip_mixing_phase1 ( ta , & key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
2007-05-05 22:45:53 +04:00
key - > u . tkip . iv32 , key - > u . tkip . p1k ) ;
key - > u . tkip . tx_initialized = 1 ;
}
2007-08-29 01:01:54 +04:00
tkip_mixing_phase2 ( key - > u . tkip . p1k ,
& key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
2007-05-05 22:45:53 +04:00
key - > u . tkip . iv16 , rc4key ) ;
}
2008-03-20 16:06:41 +03:00
void ieee80211_get_tkip_key ( struct ieee80211_key_conf * keyconf ,
struct sk_buff * skb , enum ieee80211_tkip_key_type type ,
u8 * outkey )
{
struct ieee80211_key * key = ( struct ieee80211_key * )
container_of ( keyconf , struct ieee80211_key , conf ) ;
struct ieee80211_hdr * hdr = ( struct ieee80211_hdr * ) skb - > data ;
u8 * data = ( u8 * ) hdr ;
u16 fc = le16_to_cpu ( hdr - > frame_control ) ;
int hdr_len = ieee80211_get_hdrlen ( fc ) ;
u8 * ta = hdr - > addr2 ;
u16 iv16 ;
u32 iv32 ;
iv16 = data [ hdr_len ] < < 8 ;
iv16 + = data [ hdr_len + 2 ] ;
iv32 = data [ hdr_len + 4 ] +
( data [ hdr_len + 5 ] > > 8 ) +
( data [ hdr_len + 6 ] > > 16 ) +
( data [ hdr_len + 7 ] > > 24 ) ;
# ifdef CONFIG_TKIP_DEBUG
printk ( KERN_DEBUG " TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x \n " ,
iv16 , iv32 ) ;
if ( iv32 ! = key - > u . tkip . iv32 ) {
printk ( KERN_DEBUG " skb: iv32 = 0x%08x key: iv32 = 0x%08x \n " ,
iv32 , key - > u . tkip . iv32 ) ;
printk ( KERN_DEBUG " Wrap around of iv16 in the middle of a "
" fragmented packet \n " ) ;
}
# endif /* CONFIG_TKIP_DEBUG */
/* Update the p1k only when the iv16 in the packet wraps around, this
* might occur after the wrap around of iv16 in the key in case of
* fragmented packets . */
if ( iv16 = = 0 | | ! key - > u . tkip . tx_initialized ) {
/* IV16 wrapped around - perform TKIP phase 1 */
tkip_mixing_phase1 ( ta , & key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
iv32 , key - > u . tkip . p1k ) ;
key - > u . tkip . tx_initialized = 1 ;
}
if ( type = = IEEE80211_TKIP_P1_KEY ) {
memcpy ( outkey , key - > u . tkip . p1k , sizeof ( u16 ) * 5 ) ;
return ;
}
tkip_mixing_phase2 ( key - > u . tkip . p1k ,
& key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] , iv16 , outkey ) ;
}
EXPORT_SYMBOL ( ieee80211_get_tkip_key ) ;
2007-05-05 22:45:53 +04:00
/* Encrypt packet payload with TKIP using @key. @pos is a pointer to the
* beginning of the buffer containing payload . This payload must include
* headroom of eight octets for IV and Ext . IV and taildroom of four octets
* for ICV . @ payload_len is the length of payload ( _not_ including extra
* headroom and tailroom ) . @ ta is the transmitter addresses . */
void ieee80211_tkip_encrypt_data ( struct crypto_blkcipher * tfm ,
struct ieee80211_key * key ,
u8 * pos , size_t payload_len , u8 * ta )
{
u8 rc4key [ 16 ] ;
ieee80211_tkip_gen_rc4key ( key , ta , rc4key ) ;
pos = ieee80211_tkip_add_iv ( pos , key , rc4key [ 0 ] , rc4key [ 1 ] , rc4key [ 2 ] ) ;
ieee80211_wep_encrypt_data ( tfm , rc4key , 16 , pos , payload_len ) ;
}
/* Decrypt packet payload with TKIP using @key. @pos is a pointer to the
* beginning of the buffer containing IEEE 802.11 header payload , i . e . ,
* including IV , Ext . IV , real data , Michael MIC , ICV . @ payload_len is the
* length of payload , including IV , Ext . IV , MIC , ICV . */
int ieee80211_tkip_decrypt_data ( struct crypto_blkcipher * tfm ,
struct ieee80211_key * key ,
u8 * payload , size_t payload_len , u8 * ta ,
2008-03-20 16:06:42 +03:00
u8 * ra , int only_iv , int queue ,
2007-09-26 17:19:45 +04:00
u32 * out_iv32 , u16 * out_iv16 )
2007-05-05 22:45:53 +04:00
{
u32 iv32 ;
u32 iv16 ;
u8 rc4key [ 16 ] , keyid , * pos = payload ;
int res ;
if ( payload_len < 12 )
return - 1 ;
iv16 = ( pos [ 0 ] < < 8 ) | pos [ 2 ] ;
keyid = pos [ 3 ] ;
iv32 = pos [ 4 ] | ( pos [ 5 ] < < 8 ) | ( pos [ 6 ] < < 16 ) | ( pos [ 7 ] < < 24 ) ;
pos + = 8 ;
# ifdef CONFIG_TKIP_DEBUG
{
int i ;
printk ( KERN_DEBUG " TKIP decrypt: data(len=%zd) " , payload_len ) ;
for ( i = 0 ; i < payload_len ; i + + )
printk ( " %02x " , payload [ i ] ) ;
printk ( " \n " ) ;
printk ( KERN_DEBUG " TKIP decrypt: iv16=%04x iv32=%08x \n " ,
iv16 , iv32 ) ;
}
# endif /* CONFIG_TKIP_DEBUG */
if ( ! ( keyid & ( 1 < < 5 ) ) )
return TKIP_DECRYPT_NO_EXT_IV ;
2007-08-29 01:01:54 +04:00
if ( ( keyid > > 6 ) ! = key - > conf . keyidx )
2007-05-05 22:45:53 +04:00
return TKIP_DECRYPT_INVALID_KEYIDX ;
if ( key - > u . tkip . rx_initialized [ queue ] & &
( iv32 < key - > u . tkip . iv32_rx [ queue ] | |
( iv32 = = key - > u . tkip . iv32_rx [ queue ] & &
iv16 < = key - > u . tkip . iv16_rx [ queue ] ) ) ) {
# ifdef CONFIG_TKIP_DEBUG
2007-10-04 04:59:30 +04:00
DECLARE_MAC_BUF ( mac ) ;
2007-05-05 22:45:53 +04:00
printk ( KERN_DEBUG " TKIP replay detected for RX frame from "
2007-10-04 04:59:30 +04:00
" %s (RX IV (%04x,%02x) <= prev. IV (%04x,%02x) \n " ,
print_mac ( mac , ta ) ,
2007-05-05 22:45:53 +04:00
iv32 , iv16 , key - > u . tkip . iv32_rx [ queue ] ,
key - > u . tkip . iv16_rx [ queue ] ) ;
# endif /* CONFIG_TKIP_DEBUG */
return TKIP_DECRYPT_REPLAY ;
}
if ( only_iv ) {
res = TKIP_DECRYPT_OK ;
key - > u . tkip . rx_initialized [ queue ] = 1 ;
goto done ;
}
if ( ! key - > u . tkip . rx_initialized [ queue ] | |
key - > u . tkip . iv32_rx [ queue ] ! = iv32 ) {
key - > u . tkip . rx_initialized [ queue ] = 1 ;
/* IV16 wrapped around - perform TKIP phase 1 */
2007-08-29 01:01:54 +04:00
tkip_mixing_phase1 ( ta , & key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
2007-05-05 22:45:53 +04:00
iv32 , key - > u . tkip . p1k_rx [ queue ] ) ;
# ifdef CONFIG_TKIP_DEBUG
{
int i ;
2007-10-04 04:59:30 +04:00
DECLARE_MAC_BUF ( mac ) ;
printk ( KERN_DEBUG " TKIP decrypt: Phase1 TA=%s "
" TK= " , print_mac ( mac , ta ) ) ;
2007-05-05 22:45:53 +04:00
for ( i = 0 ; i < 16 ; i + + )
printk ( " %02x " ,
2007-08-29 01:01:54 +04:00
key - > conf . key [
ALG_TKIP_TEMP_ENCR_KEY + i ] ) ;
2007-05-05 22:45:53 +04:00
printk ( " \n " ) ;
printk ( KERN_DEBUG " TKIP decrypt: P1K= " ) ;
for ( i = 0 ; i < 5 ; i + + )
printk ( " %04x " , key - > u . tkip . p1k_rx [ queue ] [ i ] ) ;
printk ( " \n " ) ;
}
# endif /* CONFIG_TKIP_DEBUG */
2008-03-20 16:06:42 +03:00
if ( key - > local - > ops - > update_tkip_key & &
key - > flags & KEY_FLAG_UPLOADED_TO_HARDWARE ) {
u8 bcast [ ETH_ALEN ] =
{ 0xff , 0xff , 0xff , 0xff , 0xff , 0xff } ;
u8 * sta_addr = key - > sta - > addr ;
if ( is_multicast_ether_addr ( ra ) )
sta_addr = bcast ;
key - > local - > ops - > update_tkip_key (
local_to_hw ( key - > local ) , & key - > conf ,
sta_addr , iv32 , key - > u . tkip . p1k_rx [ queue ] ) ;
}
2007-05-05 22:45:53 +04:00
}
tkip_mixing_phase2 ( key - > u . tkip . p1k_rx [ queue ] ,
2007-08-29 01:01:54 +04:00
& key - > conf . key [ ALG_TKIP_TEMP_ENCR_KEY ] ,
2007-05-05 22:45:53 +04:00
iv16 , rc4key ) ;
# ifdef CONFIG_TKIP_DEBUG
{
int i ;
printk ( KERN_DEBUG " TKIP decrypt: Phase2 rc4key= " ) ;
for ( i = 0 ; i < 16 ; i + + )
printk ( " %02x " , rc4key [ i ] ) ;
printk ( " \n " ) ;
}
# endif /* CONFIG_TKIP_DEBUG */
res = ieee80211_wep_decrypt_data ( tfm , rc4key , 16 , pos , payload_len - 12 ) ;
done :
if ( res = = TKIP_DECRYPT_OK ) {
2007-09-26 17:19:45 +04:00
/*
* Record previously received IV , will be copied into the
* key information after MIC verification . It is possible
* that we don ' t catch replays of fragments but that ' s ok
* because the Michael MIC verication will then fail .
*/
* out_iv32 = iv32 ;
* out_iv16 = iv16 ;
2007-05-05 22:45:53 +04:00
}
return res ;
}