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

Nicolas Cavallari Nicolas.Cavallari at lri.fr
Thu Feb 9 06:30:56 EST 2012


On 09/02/2012 11:40, Andreas Hartmann wrote:
> Nicolas Cavallari schrieb:
>> On 08/02/2012 17:18, Andreas Hartmann wrote:
>>> Nicolas Cavallari schrieb:
>>>> On 08/02/2012 12:31, Andreas Hartmann wrote:
>>>>> Nicolas Cavallari schrieb:
>>>>>> On 06/02/2012 21:05, Jouni Malinen wrote:
>>>>>>> On Mon, Feb 06, 2012 at 06:39:02PM +0100, Nicolas Cavallari wrote:
>>>>>>>> This is just a proposed solution to a problem that i'm having.  I don't
>>>>>>>> think it is the best nor it does not break something else, so i'm asking
>>>>>>>> what would be the right approach here.  I was also thinking about
>>>>>>>> reusing hostapd's eapol_send.
>>>>>>>
>>>>>>> Well, the proper approach would be to implement setprotection rather
>>>>>>> than this workaround..
>>>>>>
>>>>>> If i implement setprotection, there are still drivers that won't or
>>>>>> can't support it... that mean different code path depending on if the
>>>>>> driver support it or not, because if the driver does not support it but
>>>>>> we assume it does, we would set a key for rx and tx ... before sending
>>>>>> 4/4.  I already fell into that trap ;)
>>>>>> I'll start experimenting a setprotection implementation anyway...
>>>>>>
>>>>>>>> I'm currently experimenting with a IBSS RSN network of 4 station, but
>>>>>>>> while testing, there are always two or more handshakes that fails,
>>>>>>>> because of a lost EAPOL-Key 4/4 frame.  In IBSS mode, the two station
>>>>>>>> will not retry association, so the network will not recover and will
>>>>>>>> eventually split.
>>>>>>>>
>>>>>>>> Also, between the time where 3/4 was received by the supplicant and 4/4
>>>>>>>> was received by the authenticator, the opposite four way handshake is
>>>>>>>> stalled for the same reason.
>>>>>>>
>>>>>>> These are bit problematic to fix in any other way than by adding support
>>>>>>> for unidirectional (RX only) key operations, i.e., MLME-SETPROTECTION
>>>>>>> primitives. The AP (or well, Authenticator to include IBSS case) side
>>>>>>> may start transmitting encrypted frames immediately after receiving
>>>>>>> EAPOL-Key 4/4 and trying to remove/add keys on the STA/Supplicant side
>>>>>>> is opening a race condition here.
>>>>>>>
>>>>>>
>>>>>> This race condition already exists; the supplicant currently set the key
>>>>>> after sending 4/4, this patch does not change anything about that. The
>>>>>> same race also exist in the authenticator case, after receiving 4/4, and
>>>>>> we can't do much to protect against that one. Both are
>>>>>> equally feasible in IBSS mode, because the opposite four way hs is
>>>>>> occurring at the same time.
>>>>>
>>>>> Please, may I ask you a question?
>>>>>
>>>>> I do encounter here a similar (?) problem since ages. hostapd sends 3/4
>>>>> to supplicant, supplicant sends 4/4 and is ready and all is fine.
>>>>>
>>>>> But there is one problem: it only works, as long as there is no data
>>>>> stream (payload) active between supplicant and hostapd.
>>>>> If there is payload at the same time (e.g. created with netperf), 4/4 is
>>>>> sent by supplicant (can be seen in wireshark), but isn't seen by
>>>>> hostapd. hostapd therefore retries 3/4, but supplicant doesn't see these
>>>>> packages any more: connection is broken, because hostapd closes the
>>>>> connection because of missing 4/4!
>>>>
>>>> Which driver(s) do you use ?
>>>
>>> I'm using rt2800pci as AP and rt5572sta as STA (or rt2800usb or ath9k
>>> - the latter even as AP, too).
>>>
>>>> It could be the same problem or a different one. Do you have a trace
>>>> made from a separate interface in monitor mode ? that way we could see
>>>> which packets are encrypted or not, and which are acked... logs from the
>>>> both side might be useful too.
>>>
>>> I could provide them if you really need them, but I fear, they are
>>> incomplete.
>>>
>>>
>>> Rekeying behaviour without payload:
>>> I compared the 4 packets of the original and the patched wpa_supplicant
>>> (gathered on the supplicant itself with wireshark) but couldn't see any
>>> difference between them.
>>>
>>> If I trace it with an external interface, all of the 4 packets are 
>>> encrypted and shown as "QoS Data". IEEE 802.11 QoS Data / Frame
>>> Control / Flags / Protected flag is set (Data is protected). Each of
>>> the frame is acked.
>>>
>>> I expected that the 4/4 frame should have been unencrypted with your
>>> patch. But this seems not to be.
>>
>> Then my patch does not work... Or the kernel/driver does something
>> completely strange. I should check my patch more in infrastructure mode
>> to see if my 4/4 are encrypted ...
>>
>>>
>>> BTW: the first 4 way handshake, directly after the initialisation of the
>>> connection, is always sent completely unencrypted.
>>>
>>>
>>>> But the fact that the supplicant cannot receive the duplicated 3/4 frame
>>>> might indicate something. You are seeing this at key renegotiation time,
>>>> right ?
>>>
>>> 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...

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.

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.

> 
> 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 ?

> 
> 
> 
> The same 4/4 with the internal supplicant of ralink (which just works
> fine):
> 
> 
> No.     Time        Source                Destination           Protocol Length Info
>    1271 142.821706  src                   dst                   EAPOL    163    Key (msg 4/4)
> 
> Frame 1271: 163 bytes on wire (1304 bits), 163 bytes captured (1304 bits)
> Radiotap Header v0, Length 26
> IEEE 802.11 QoS Data, Flags: .......TC
>     Type/Subtype: QoS Data (0x28)
>     Frame Control: 0x0188 (Normal)
>         Version: 0
>         Type: Data frame (2)
>         Subtype: 8
>         Flags: 0x1
>             .... ..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
>             .0.. .... = Protected flag: Data is not protected
>             0... .... = Order flag: Not strictly ordered
>     Duration: 202
>     BSS Id: dst
>     Source address: src
>     Destination address: dst
>     Fragment number: 0
>     Sequence number: 3
>     Frame check sequence: 0xeda1aa68 [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)
> Logical-Link Control
>     DSAP: SNAP (0xaa)
>     IG Bit: Individual
>     SSAP: SNAP (0xaa)
>     CR Bit: Command
>     Control field: U, func=UI (0x03)
>         000. 00.. = Command: Unnumbered Information (0x00)
>         .... ..11 = Frame type: Unnumbered frame (0x03)
>     Organization Code: Encapsulated Ethernet (0x000000)
>     Type: 802.1X Authentication (0x888e)
> 802.1X Authentication
>     Version: 1
>     Type: Key (3)
>     Length: 95
>     Descriptor Type: EAPOL RSN key (2)
>     Key Information: 0x030a
>         .... .... .... .010 = Key Descriptor Version: HMAC-SHA1 for MIC and AES key wrap for encryption (2)
>         .... .... .... 1... = Key Type: Pairwise key
>         .... .... ..00 .... = Key Index: 0
>         .... .... .0.. .... = Install flag: Not set
>         .... .... 0... .... = Key Ack flag: Not set
>         .... ...1 .... .... = Key MIC flag: Set
>         .... ..1. .... .... = Secure flag: Set
>         .... .0.. .... .... = Error flag: Not set
>         .... 0... .... .... = Request flag: Not set
>         ...0 .... .... .... = Encrypted Key Data flag: Not set
>     Key Length: 0
>     Replay Counter: 4
>     Nonce: 000000000000000000000000000000000000000000000000...
>     Key IV: 00000000000000000000000000000000
>     WPA Key RSC: 0000000000000000
>     WPA Key ID: 0000000000000000
>     WPA Key MIC: f7435c2290b845547d14e6deae810b1b
>     WPA Key Length: 0
> 
> 
> Kind regards,
> Andreas
> 
> _______________________________________________
> HostAP mailing list
> HostAP at lists.shmoo.com
> http://lists.shmoo.com/mailman/listinfo/hostap



More information about the HostAP mailing list