[PATCH] rsn_supp: Don't encrypt EAPOL-Key 4/4.
Nicolas Cavallari
Nicolas.Cavallari
Thu Feb 9 03:30:56 PST 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