[PATCH] rsn_supp: Don't encrypt EAPOL-Key 4/4.

Andreas Hartmann andihartmann at 01019freenet.de
Thu Feb 9 07:14:02 EST 2012


Nicolas Cavallari schrieb:
> On 09/02/2012 11:40, Andreas Hartmann wrote:
>> Nicolas Cavallari schrieb:
>>> On 08/02/2012 17:18, Andreas Hartmann wrote:
[...]

>>>> Correctly - PTK rekeying.
>>>>
>>>> I checked something more now: I disabled hw encryption on the AP and
>>>> inserted debug output in net/mac80211/wpa.c
>>>> (ieee80211_crypto_ccmp_decrypt()) to see, where and when the frames are 
>>>> dropped during rekeying with payload.
>>>>
>>>> The dropping of the frames starts directly after 2/4 has been done and
>>>> 3/4 has been sent the first time (long before the first 4/4 timeout). I
>>>> could see, that the first few frames (mostly data frames I suppose) are
>>>> dropped here:
>>>>
>>>>         if (!(status->flag & RX_FLAG_DECRYPTED)) {
>>>>                 u8 scratch[6 * AES_BLOCK_SIZE];
>>>>                 /* hardware didn't decrypt/verify MIC */
>>>>                 ccmp_special_blocks(skb, pn, scratch, 1);
>>>>
>>>>                 if (ieee80211_aes_ccm_decrypt(
>>>>                             key->u.ccmp.tfm, scratch,
>>>>                             skb->data + hdrlen + CCMP_HDR_LEN, data_len,
>>>>                             skb->data + skb->len - CCMP_MIC_LEN,
>>>>                             skb->data + hdrlen + CCMP_HDR_LEN)) {
>>>>                         printk(KERN_INFO "ieee80211_crypto_ccmp_decrypt 10 RX_DROP_UNUSABLE\n");
>>>>                         return RX_DROP_UNUSABLE;
>>>>                         }
>>>>         }
>>>
>>> So the replay counter was acceptable but the key was wrong, strange
>>> indeed. I would proceed to debug the ieee80211_tx_h_select_key() on the
>>> supplicant, if it's possible.
>>
>> It looks like this:
>>
>> with patch
>>
>> Feb  9 09:46:59 notebook2 kernel: [18401.024008] ieee80211_tx_h_select_key DONT_ENCRYPT
>> Feb  9 09:46:59 notebook2 kernel: [18408.907037] ieee80211_tx_h_select_key DONT_ENCRYPT
>> Feb  9 09:46:59 notebook2 kernel: [18408.910235] ieee80211_tx_h_select_key 1
>> Feb  9 09:46:59 notebook2 kernel: [18408.925414] ieee80211_tx_h_select_key KEY is NULL
>>
> 
> And there were no packet that were sent unencrypted ? If so, this is
> likely a driver bug...

Which version of compat-wireless / kernel do you use? I'm using kernel
3.1.9 with compat-wireless 3.2.1 and wpa_supplicant 1.0 rc2 from git.

> By the way, i just tested on my side with an ath9k station connecting to
> an ath9k ap, and with my patch, 4/4 is sent unencrypted. (and in my
> case, rekeying works), but i don't have any rt devices around me to test.

You tested with payload (a few times consecutively - for testing, I set
ptk rekeying timeout to 70s)?
It works for me too, without payload (idle) at the same time - even
without your patch.

The problem comes up with parallel payload.

> Also, i don't know what the DONT_ENCRYPT traces correspond to, but
> IEEE80211_TX_INTFL_DONT_ENCRYPT should only be set for management frames
> and the likes.

You got it right! Which category from below code snippet would be
correct - or which category do you see?

> 
>>
>> without patch
>>
>> Feb  9 09:50:43 notebook2 kernel: [18624.839406] ieee80211_tx_h_select_key DONT_ENCRYPT
>> Feb  9 09:50:43 notebook2 kernel: [18632.619828] ieee80211_tx_h_select_key DONT_ENCRYPT
>> Feb  9 09:50:43 notebook2 kernel: [18632.622989] ieee80211_tx_h_select_key 1
>> Feb  9 09:50:43 notebook2 kernel: [18632.624980] ieee80211_tx_h_select_key 1
>>
>>
>> The patched source from compat-wireless (net/mac80211/tx.c):
>>
>>
>>         if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
>>                 printk(KERN_DEBUG "ieee80211_tx_h_select_key DONT_ENCRYPT");
>>                 tx->key = NULL;
>>                 }
>>         else if (tx->sta && (key = rcu_dereference(tx->sta->ptk))) {
>>                 printk(KERN_DEBUG "ieee80211_tx_h_select_key 1");
>>                 tx->key = key;
>>                 }
>>         else if (ieee80211_is_mgmt(hdr->frame_control) &&
>>                  is_multicast_ether_addr(hdr->addr1) &&
>>                  ieee80211_is_robust_mgmt_frame(hdr) &&
>>                  (key = rcu_dereference(tx->sdata->default_mgmt_key))) {
>>                  printk(KERN_DEBUG "ieee80211_tx_h_select_key MGMT");
>>                 tx->key = key;
>>                 }
>>         else if (is_multicast_ether_addr(hdr->addr1) &&
>>                  (key = rcu_dereference(tx->sdata->default_multicast_key))) {
>>                  printk(KERN_DEBUG "ieee80211_tx_h_select_key MULTICAST");
>>                 tx->key = key;
>>                 }
>>         else if (!is_multicast_ether_addr(hdr->addr1) &&
>>                  (key = rcu_dereference(tx->sdata->default_unicast_key))) {
>>                  printk(KERN_DEBUG "ieee80211_tx_h_select_key UNICAST");
>>                 tx->key = key;
>>                 }
>>         else if (tx->sdata->drop_unencrypted &&
>>                  (tx->skb->protocol != tx->sdata->control_port_protocol) &&
>>                  !(info->flags & IEEE80211_TX_CTL_INJECTED) &&
>>                  (!ieee80211_is_robust_mgmt_frame(hdr) ||
>>                   (ieee80211_is_action(hdr->frame_control) &&
>>                    tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP)))) {
>>                 I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted);
>>                 printk(KERN_DEBUG "ieee80211_tx_h_select_key DROP_UNENCRYPTED");
>>                 return TX_DROP;
>>         } else {
>>                 tx->key = NULL;
>>                 printk(KERN_DEBUG "ieee80211_tx_h_select_key KEY is NULL");
>>                 }
>>
>>
>>
>>
>> The 4/4 seen by wireshark by a external device looks like this:
>>
>> No.     Time        Source                Destination           Protocol Length Info
>>    1004 89.983445   src                   dst                   802.11   179    QoS Data, SN=18, FN=0, Flags=.p.....TC
>>
>> Frame 1004: 179 bytes on wire (1432 bits), 179 bytes captured (1432 bits)
>> Radiotap Header v0, Length 26
>> IEEE 802.11 QoS Data, Flags: .p.....TC
>>     Type/Subtype: QoS Data (0x28)
>>     Frame Control: 0x4188 (Normal)
>>         Version: 0
>>         Type: Data frame (2)
>>         Subtype: 8
>>         Flags: 0x41
>>             .... ..01 = DS status: Frame from STA to DS via an AP (To DS: 1 From DS: 0) (0x01)
>>             .... .0.. = More Fragments: This is the last fragment
>>             .... 0... = Retry: Frame is not being retransmitted
>>             ...0 .... = PWR MGT: STA will stay up
>>             ..0. .... = More Data: No data buffered
>>             .1.. .... = Protected flag: Data is protected
>>             0... .... = Order flag: Not strictly ordered
>>     Duration: 202
>>     BSS Id: dst
>>     Source address: src
>>     Destination address: dst
>>     Fragment number: 0
>>     Sequence number: 18
>>     Frame check sequence: 0x15b1958f [correct]
>>         [Good: True]
>>         [Bad: False]
>>     QoS Control
>>         TID: 0
>>         Priority: 0 (Best Effort) (Best Effort)
>>         ...0 .... = QoS bit 4: Bits 8-15 of QoS Control field are TXOP Duration Requested
>>         Ack Policy: Normal Ack (0x00)
>>         Payload Type: MSDU
>>         TXOP Duration Requested: no TXOP requested (0)
>>     CCMP parameters
>>         CCMP Ext. Initialization Vector: 0x000000000009
>>         Key Index: 0
>> Data (115 bytes)
>>
>>     Data: ...........
>>     [Length: 115]
> 
> How do you know that this is 4/4 ?

Good question! I tested without any payload. Therefore, you can easily
see, which frame should be which step. One thing is sure: I didn't saw
any unencrypted frame ... . And PTK rekeying didn't work - it should
have worked, if it was unencrypted.


Regards,
Andreas


More information about the HostAP mailing list