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

Andreas Hartmann andihartmann
Thu Feb 9 02:40:08 PST 2012


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


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]



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




More information about the Hostap mailing list