diff mbox

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

Message ID 1328549942-10112-1-git-send-email-cavallar@lri.fr
State Changes Requested
Headers show

Commit Message

Nicolas Cavallari Feb. 6, 2012, 5:39 p.m. UTC
When the 4/4 pairwise handshake is lost, the authenticator
will retry 3/4 and we would resent 4/4, but encrypted.

802.11 spec implies that EAPOL 4/4 should not be encrypted, but
because setprotection is not implemented by any (non-testing) driver,
clear the key before sending EAPOL-Key 4/4 and reset the key
just after.

Signed-hostap: Nicolas Cavallari <cavallar@lri.fr>

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

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.

Comments

Jouni Malinen Feb. 6, 2012, 8:05 p.m. UTC | #1
On Mon, Feb 06, 2012 at 06:39:02PM +0100, Nicolas Cavallari wrote:
> When the 4/4 pairwise handshake is lost, the authenticator
> will retry 3/4 and we would resent 4/4, but encrypted.
> 
> 802.11 spec implies that EAPOL 4/4 should not be encrypted, but
> because setprotection is not implemented by any (non-testing) driver,
> clear the key before sending EAPOL-Key 4/4 and reset the key
> just after.


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

> 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.
Nicolas Cavallari Feb. 7, 2012, 11:52 a.m. UTC | #2
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.
Nicolas Cavallari Feb. 8, 2012, 2:07 p.m. UTC | #3
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 ?

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.

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 ?
Nicolas Cavallari Feb. 8, 2012, 5:33 p.m. UTC | #4
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.

> 
> 
> All other frames are even dropped before:
> 
>         if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
>                 key->u.ccmp.replays++;
>                 printk(KERN_INFO "ieee80211_crypto_ccmp_decrypt 9 RX_DROP_UNUSABLE\n");
>                 return RX_DROP_UNUSABLE;
>         }

During my test, when either side changes the key, it resets the replay
counter to 0, so if one has still the old key, it detects the frame as a
replay, but really is a key conflict.
Andreas Hartmann Feb. 9, 2012, 10:40 a.m. UTC | #5
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
Nicolas Cavallari Feb. 9, 2012, 11:30 a.m. UTC | #6
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@lists.shmoo.com
> http://lists.shmoo.com/mailman/listinfo/hostap
Andreas Hartmann Feb. 9, 2012, 12:14 p.m. UTC | #7
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
Nicolas Cavallari Feb. 9, 2012, 3:27 p.m. UTC | #8
On 09/02/2012 13:14, Andreas Hartmann wrote:
> 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.

I was testing with multicast payload ... silly me. I reproducted the
problem with unicast payload.

i'm going to dissect and test more...

> 
>> 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
> _______________________________________________
> HostAP mailing list
> HostAP@lists.shmoo.com
> http://lists.shmoo.com/mailman/listinfo/hostap
Jouni Malinen Feb. 12, 2012, 2:39 p.m. UTC | #9
On Tue, Feb 07, 2012 at 12:52:54PM +0100, Nicolas Cavallari wrote:
> 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...

Well, how many of drivers support RSN IBSS in the first place? For
infrastructure BSS, re-association seems like a reasonable workaround
for recovering from this.

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

Fair enough. Though, this patch does break PTK rekeying since it clears
the PTK in the middle of 4-way handshake that was supposed to be
completed using encrypted EAPOL frames.

IBSS cases can be somewhat complex. I haven't really went through all
the details for them, but in general, setprotection mechanism is
something that I've wanted to see for a long time (i.e., way before RSN
IBSS supported was added).

Even if you were to be able to work around some initial connection
cases by forcing EAPOL frames to be unencrypted, rekeying is likely to
have similar race conditions.
Nicolas Cavallari Feb. 12, 2012, 5:20 p.m. UTC | #10
On 12/02/2012 15:39, Jouni Malinen wrote:
> On Tue, Feb 07, 2012 at 12:52:54PM +0100, Nicolas Cavallari wrote:
>> 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...
> Well, how many of drivers support RSN IBSS in the first place? For
> infrastructure BSS, re-association seems like a reasonable workaround
> for recovering from this.
carl9170, ath9k, ath5k, ath9k_htc, and all mac80211-based drivers with
pure software crypto...
>
>> 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.
> Fair enough. Though, this patch does break PTK rekeying since it clears
> the PTK in the middle of 4-way handshake that was supposed to be
> completed using encrypted EAPOL frames.
It clears a key just before sending 4/4, and the new PTK will be set
just after sending 4/4.
So clearing the key or not will make no difference, apart from
respecting the standard when we do (and when it works), because the
standard actually use setprotection(rx) instead. It will likely not
change the various races that exists when sending frames while changing
keys that Andreas is likely experiencing.

> IBSS cases can be somewhat complex. I haven't really went through all
> the details for them, but in general, setprotection mechanism is
> something that I've wanted to see for a long time (i.e., way before RSN
> IBSS supported was added).
In terms of PTK, IBSS isn't much different from the PTK releying case:
there is just traffic going on during the negociation. The opposite four
way handshake is just here to exchange a GTK.
As for my current setprotection() call, it will likely only implement
the Tx part (choosing between Rx only and Rx_Tx), and won't necessarily
solve race conditions, so i'm not that much motivated to try it.
>
> Even if you were to be able to work around some initial connection
> cases by forcing EAPOL frames to be unencrypted, rekeying is likely to
> have similar race conditions.
Yes : If a 4/4 is lost during rekeying, the retransmitted 3/4 cannot be
interpreted by the supplicant anymore. The standard somewhat "authorize"
stations to store more than one PTK for a TA/RA pair, but does not
define how to use them...
Jouni Malinen Feb. 12, 2012, 6:25 p.m. UTC | #11
On Sun, Feb 12, 2012 at 06:20:09PM +0100, Nicolas Cavallari wrote:
> It clears a key just before sending 4/4, and the new PTK will be set
> just after sending 4/4.
> So clearing the key or not will make no difference, apart from
> respecting the standard when we do (and when it works), because the
> standard actually use setprotection(rx) instead. It will likely not
> change the various races that exists when sending frames while changing
> keys that Andreas is likely experiencing.

It would not make difference for the initial 4-way handshake at the
beginning of the association, but it breaks PTK rekeying, i.e., another
4-way handshake during the association. In that exchange, all EAPOL
frames need to be encrypted with the old key.

> Yes : If a 4/4 is lost during rekeying, the retransmitted 3/4 cannot be
> interpreted by the supplicant anymore. The standard somewhat "authorize"
> stations to store more than one PTK for a TA/RA pair, but does not
> define how to use them...

Yes, this is not exactly completely defined, but in theory, something
that could be implemented.
Nicolas Cavallari Feb. 12, 2012, 6:35 p.m. UTC | #12
On 12/02/2012 19:25, Jouni Malinen wrote:
> On Sun, Feb 12, 2012 at 06:20:09PM +0100, Nicolas Cavallari wrote:
>> It clears a key just before sending 4/4, and the new PTK will be set
>> just after sending 4/4.
>> So clearing the key or not will make no difference, apart from
>> respecting the standard when we do (and when it works), because the
>> standard actually use setprotection(rx) instead. It will likely not
>> change the various races that exists when sending frames while changing
>> keys that Andreas is likely experiencing.
> It would not make difference for the initial 4-way handshake at the
> beginning of the association, but it breaks PTK rekeying, i.e., another
> 4-way handshake during the association. In that exchange, all EAPOL
> frames need to be encrypted with the old key.
Where is that specified ? My interpretation of the standard is that
setprotection(rx) is called before sending 4/4, so Tx encryption
should be disabled for 4/4 ...

If you don't want to not encrypt 4/4, there is no need to implement
setprotection(rx)...
Jouni Malinen Feb. 12, 2012, 7:43 p.m. UTC | #13
On Sun, Feb 12, 2012 at 07:35:40PM +0100, Nicolas Cavallari wrote:
> On 12/02/2012 19:25, Jouni Malinen wrote:
> > It would not make difference for the initial 4-way handshake at the
> > beginning of the association, but it breaks PTK rekeying, i.e., another
> > 4-way handshake during the association. In that exchange, all EAPOL
> > frames need to be encrypted with the old key.
> Where is that specified ? My interpretation of the standard is that
> setprotection(rx) is called before sending 4/4, so Tx encryption
> should be disabled for 4/4 ...

In the IEEE 802.11 standard obviously.. ,-)  Though, it may be a bit
difficult to find this and some reading between lines may also be
needed.

> If you don't want to not encrypt 4/4, there is no need to implement
> setprotection(rx)...

There is. The key point here is that the 4-way handshake (including
retries) is expected to be completed with the PTK that was in use at the
beginning of the handshake. In other words, all four EAPOL messages in
the 4-way handshake at the beginning of the association are unprotected
while all four EAPOL messages (including retries) in the PTK rekeying
4-way handshakes are encrypted using the old PTK.
Nicolas Cavallari Feb. 12, 2012, 8:27 p.m. UTC | #14
On 12/02/2012 20:43, Jouni Malinen wrote:
> On Sun, Feb 12, 2012 at 07:35:40PM +0100, Nicolas Cavallari wrote:
>> On 12/02/2012 19:25, Jouni Malinen wrote:
>>> It would not make difference for the initial 4-way handshake at the
>>> beginning of the association, but it breaks PTK rekeying, i.e., another
>>> 4-way handshake during the association. In that exchange, all EAPOL
>>> frames need to be encrypted with the old key.
>> Where is that specified ? My interpretation of the standard is that
>> setprotection(rx) is called before sending 4/4, so Tx encryption
>> should be disabled for 4/4 ...
> In the IEEE 802.11 standard obviously.. ,-)  Though, it may be a bit
> difficult to find this and some reading between lines may also be
> needed.
I would be interested to know more about those between-lines-readings
... because i still don't understand how rsn is supposed to not break.
>> If you don't want to not encrypt 4/4, there is no need to implement
>> setprotection(rx)...
> There is. The key point here is that the 4-way handshake (including
> retries) is expected to be completed with the PTK that was in use at the
> beginning of the handshake. In other words, all four EAPOL messages in
> the 4-way handshake at the beginning of the association are unprotected
> while all four EAPOL messages (including retries) in the PTK rekeying
> 4-way handshakes are encrypted using the old PTK.
Then ... what do you expect "setprotection(rx)" to actually do,
if not instead of not crypting in the tx path ? Considering that the
standard does not require supporting more than one PTK per station, and
that the linux kernel does not support it either...

Anyway, it won't solve Andreas' problem : the 4/4 frame is queued behind
a handful of data frames, control is resumed to wpa_supplicant, which
sets the key just after. When the kernel flush his queue, it already
uses the new key, so sends 4/4 encrypted with the new PTK ...   Solving
this might require something more than just "setprotection".
Jouni Malinen Feb. 12, 2012, 8:47 p.m. UTC | #15
On Sun, Feb 12, 2012 at 09:27:25PM +0100, Nicolas Cavallari wrote:
> Then ... what do you expect "setprotection(rx)" to actually do,
> if not instead of not crypting in the tx path ? Considering that the
> standard does not require supporting more than one PTK per station, and
> that the linux kernel does not support it either...

Well, this is not really described in the MLME primitives, or well, not
really in the standard in general, but the only way to implement this
correctly seems to require support for two PTKs that can be in use for
the small amount of time during rekeying. I'm not aware of any
implementation doing this either.

> Anyway, it won't solve Andreas' problem : the 4/4 frame is queued behind
> a handful of data frames, control is resumed to wpa_supplicant, which
> sets the key just after. When the kernel flush his queue, it already
> uses the new key, so sends 4/4 encrypted with the new PTK ...   Solving
> this might require something more than just "setprotection".

What were those other data frames? If this is during the initial 4-way
handshake, the port (PAE) should be unauthorized and other data frames
apart from EAPOL frames should be blocked. Sure, we may not yet support
PAE in station mode, but in theory, that's the way it is supposed to
work. As far as rekeying is concerned, this gets quite a bit more
complex (until the newly defined non-zero key index PTK gets into use).
Andreas Hartmann Feb. 13, 2012, 7:20 a.m. UTC | #16
Jouni Malinen schrieb:
> On Sun, Feb 12, 2012 at 09:27:25PM +0100, Nicolas Cavallari wrote:
>> Then ... what do you expect "setprotection(rx)" to actually do,
>> if not instead of not crypting in the tx path ? Considering that the
>> standard does not require supporting more than one PTK per station, and
>> that the linux kernel does not support it either...
> 
> Well, this is not really described in the MLME primitives, or well, not
> really in the standard in general, but the only way to implement this
> correctly seems to require support for two PTKs that can be in use for
> the small amount of time during rekeying. I'm not aware of any
> implementation doing this either.
> 
>> Anyway, it won't solve Andreas' problem : the 4/4 frame is queued behind
>> a handful of data frames, control is resumed to wpa_supplicant, which
>> sets the key just after. When the kernel flush his queue, it already
>> uses the new key, so sends 4/4 encrypted with the new PTK ...   Solving
>> this might require something more than just "setprotection".
> 
> What were those other data frames? If this is during the initial 4-way
> handshake, the port (PAE) should be unauthorized and other data frames
> apart from EAPOL frames should be blocked. Sure, we may not yet support
> PAE in station mode, but in theory, that's the way it is supposed to
> work. As far as rekeying is concerned, this gets quite a bit more
> complex (until the newly defined non-zero key index PTK gets into use).

The problem comes up always during PTK rekeying with parallel payload
(use netperf to force it easily) - a totally normal and trivial daily
use case (streaming, nfs, X11, some internet download, ...), which is
handled by ralink supplicant e.g. without any problem.

I traced the problem on AP side at this point:

I disabled hw encryption and inserted debug output in
net/mac80211/wpa.c (ieee80211_crypto_ccmp_decrypt() - compat-wireless)
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;
                        }
        }

All other frames are even dropped before:

        if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) {
                key->u.ccmp.replays++;
                printk(KERN_INFO "ieee80211_crypto_ccmp_decrypt 9 RX_DROP_UNUSABLE\n");
                return RX_DROP_UNUSABLE;
        }

One of the dropped frame is the 4/4 frame from wpa_supplicant.

If the legacy ralink driver internal supplicant is used, the connection
isn't interrupted, because ralink sends 4/4 unencrypted (the behavior of
the data frames is the same as wrote above, but this is no problem,
as they are just resent after a few millisecs and the connection
doesn't break down).

That's the 4/4 frame as it can be seen traced with an external third
device sent by ralink:

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


As it is sent unencrypted (the same way as during initial rekeying), I
hope that the sent data is already internally encrypted (or it is just
useless for any attacker, even if he get them unencrypted), so it
shouldn't be a problem, if the frame itself isn't encrypted.

I think, Nicolas analysis of the breakage sounds correctly to me.
That's why even his patch doesn't work.

Why isn't it just possible to send one of thousands of frames
unencrypted? Just tag it with "unencrypted", so the driver knows, that
this frame musn't be encrypted at all - independently if there is a
key for encryption present or not.


Kind regards,
Andreas
Jouni Malinen Feb. 13, 2012, 9:26 a.m. UTC | #17
On Mon, Feb 13, 2012 at 08:20:53AM +0100, Andreas Hartmann wrote:
> 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)) {
>                 /* hardware didn't decrypt/verify MIC */
>                 if (ieee80211_aes_ccm_decrypt(
>                         return RX_DROP_UNUSABLE;

Huh.. The key should not have changed yet on either the AP or the
station..

> One of the dropped frame is the 4/4 frame from wpa_supplicant.

Just to make sure.. This happened even for the case where only a single
3/4 had been transmitted and the first attempt at sending 4/4 was
dropped?

> If the legacy ralink driver internal supplicant is used, the connection
> isn't interrupted, because ralink sends 4/4 unencrypted (the behavior of
> the data frames is the same as wrote above, but this is no problem,
> as they are just resent after a few millisecs and the connection
> doesn't break down).

The AP behaves incorrectly, if it accepts unencrypted EAPOL frame during
PTK rekeying. Sure, with that kind of AP behavior, it would be trivial
to avoid the issue by not encrypting the frame, but this is not the way
RSN is supposed to work.

> As it is sent unencrypted (the same way as during initial rekeying), I
> hope that the sent data is already internally encrypted (or it is just
> useless for any attacker, even if he get them unencrypted), so it
> shouldn't be a problem, if the frame itself isn't encrypted.

There are no know security attacks even if the frame were sent
unencrypted. However, the RX rules on the other device (AP in this case)
should force the frame to be dropped because a TK was configured for the
transmitting STA and the frame was not protected.

> Why isn't it just possible to send one of thousands of frames
> unencrypted? Just tag it with "unencrypted", so the driver knows, that
> this frame musn't be encrypted at all - independently if there is a
> key for encryption present or not.

It is not that much of a problem of being able to do this, but the
problem of this not being the correct way of handling this.. If that AP
was indeed using mac80211, too, I think we need to fix the AP behavior
to drop such a frame.

I would like to better understand which key is used for each frame
during PTK rekeying. I'd guess that wireless capture file here can get
pretty huge, so it may be easier if I try to reproduce that myself.

If you are interested in running it through an analysis, I would suggest
using wlantest (in the wlantest directory of hostap.git). If you provide
it the needed keys (e.g., passphrase for WPA2-Personal), it will go
through a wireless capture file and decrypt all the frames and decrypt
the keys from both the initial 4-way handshake and PTK rekeys. It will
complain about incorrectly protected frames, so it would be interesting
to see what it says about the rekeying 4-way handshake.
Andreas Hartmann Feb. 13, 2012, 10:25 a.m. UTC | #18
Jouni Malinen schrieb:
> On Mon, Feb 13, 2012 at 08:20:53AM +0100, Andreas Hartmann wrote:
>> 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)) {
>>                 /* hardware didn't decrypt/verify MIC */
>>                 if (ieee80211_aes_ccm_decrypt(
>>                         return RX_DROP_UNUSABLE;
> 
> Huh.. The key should not have changed yet on either the AP or the
> station..
> 
>> One of the dropped frame is the 4/4 frame from wpa_supplicant.
> 
> Just to make sure.. This happened even for the case where only a single
> 3/4 had been transmitted and the first attempt at sending 4/4 was
> dropped?

Yes.

>> If the legacy ralink driver internal supplicant is used, the connection
>> isn't interrupted, because ralink sends 4/4 unencrypted (the behavior of
>> the data frames is the same as wrote above, but this is no problem,
>> as they are just resent after a few millisecs and the connection
>> doesn't break down).
> 
> The AP behaves incorrectly, if it accepts unencrypted EAPOL frame during
> PTK rekeying. Sure, with that kind of AP behavior, it would be trivial
> to avoid the issue by not encrypting the frame, but this is not the way
> RSN is supposed to work.

It is hostap-d3f57d0, hostap-1rc behaves exactly the same. Driver is
nl80211, 80211.n (g behaves exactly the same). I can see it with ath9k
and rt2800pci (didn't test any more) on AP side. Same problem can be
seen with Linksys WAP610N as AP.

>> As it is sent unencrypted (the same way as during initial rekeying), I
>> hope that the sent data is already internally encrypted (or it is just
>> useless for any attacker, even if he get them unencrypted), so it
>> shouldn't be a problem, if the frame itself isn't encrypted.
> 
> There are no know security attacks even if the frame were sent
> unencrypted. However, the RX rules on the other device (AP in this case)
> should force the frame to be dropped because a TK was configured for the
> transmitting STA and the frame was not protected.

If it works the protected way - but what is with supplicants sending
unencrypted frames (I believe windows does the same, as I didn't have
this problem with windows stations, too).

>> Why isn't it just possible to send one of thousands of frames
>> unencrypted? Just tag it with "unencrypted", so the driver knows, that
>> this frame musn't be encrypted at all - independently if there is a
>> key for encryption present or not.
> 
> It is not that much of a problem of being able to do this, but the
> problem of this not being the correct way of handling this.. If that AP
> was indeed using mac80211, too, I think we need to fix the AP behavior
> to drop such a frame.

I think this would be a bad idea, because it would break compatibility
(see above) and it would be against the defined standard (according
Nicolas).

> I would like to better understand which key is used for each frame
> during PTK rekeying. I'd guess that wireless capture file here can get
> pretty huge, so it may be easier if I try to reproduce that myself.

That's right - the files get really huge :-(.

> If you are interested in running it through an analysis, I would suggest
> using wlantest (in the wlantest directory of hostap.git). If you provide
> it the needed keys (e.g., passphrase for WPA2-Personal), it will go

I'm using eap-tls, but psk shows exactly the same problem.

> through a wireless capture file and decrypt all the frames and decrypt
> the keys from both the initial 4-way handshake and PTK rekeys. It will
> complain about incorrectly protected frames, so it would be interesting
> to see what it says about the rekeying 4-way handshake.

I'll try my best. But it should be really easy for you to reproduce this
problem yourself, as it comes up here in 99%.


Kind regards,
Andreas
Nicolas Cavallari Feb. 13, 2012, 10:39 a.m. UTC | #19
>> Anyway, it won't solve Andreas' problem : the 4/4 frame is queued behind
>> a handful of data frames, control is resumed to wpa_supplicant, which
>> sets the key just after. When the kernel flush his queue, it already
>> uses the new key, so sends 4/4 encrypted with the new PTK ...   Solving
>> this might require something more than just "setprotection".
> 
> What were those other data frames? If this is during the initial 4-way
> handshake, the port (PAE) should be unauthorized and other data frames
> apart from EAPOL frames should be blocked.

Only the specific port corresponding to that particular authenticator is
blocked. Other ports from other authenticators may be open. This is not
the case for Andreas, as he is in Infrastructure mode. But for me it is,
in IBSS mode...

> As far as rekeying is concerned, this gets quite a bit more
> complex (until the newly defined non-zero key index PTK gets into use).

Which standard is this ? I might want to implement this for my
private IBSS network.
Jouni Malinen Feb. 13, 2012, 10:48 a.m. UTC | #20
On Mon, Feb 13, 2012 at 11:25:02AM +0100, Andreas Hartmann wrote:
> Jouni Malinen schrieb:
> > It is not that much of a problem of being able to do this, but the
> > problem of this not being the correct way of handling this.. If that AP
> > was indeed using mac80211, too, I think we need to fix the AP behavior
> > to drop such a frame.
> 
> I think this would be a bad idea, because it would break compatibility
> (see above) and it would be against the defined standard (according
> Nicolas).

Sure, the interoperability part needs to be researched more. However, as
far as the standard is concerned, I would claim that the defined
behavior is to encrypt EAPOL frames whenever a PTK is in configured and
that is very much the case during the PTK rekeying.

There has been number of poor WPA implementations that did not exactly
follow the rules correctly, but as far as RSN (WPA2) is concerned, these
frames should really be encrypted.

> I'll try my best. But it should be really easy for you to reproduce this
> problem yourself, as it comes up here in 99%.

For some reason, I did not seem to hit this in my tests when I was
testing some of the EAPOL retransmission timeouts with heavy background
traffic some time ago. I'll try this again, but I'm not sure when I'll
find the time for this.
Jouni Malinen Feb. 13, 2012, 12:51 p.m. UTC | #21
On Mon, Feb 13, 2012 at 11:39:26AM +0100, Nicolas Cavallari wrote:
> > What were those other data frames? If this is during the initial 4-way
> > handshake, the port (PAE) should be unauthorized and other data frames
> > apart from EAPOL frames should be blocked.
> 
> Only the specific port corresponding to that particular authenticator is
> blocked. Other ports from other authenticators may be open. This is not
> the case for Andreas, as he is in Infrastructure mode. But for me it is,
> in IBSS mode...

Sure, though even in that case, the non-EAPOL Data frames that get
through should be for other destinations. I'm not sure I've fully
understood this specific part of the issue, though.

> > As far as rekeying is concerned, this gets quite a bit more
> > complex (until the newly defined non-zero key index PTK gets into use).
> 
> Which standard is this ? I might want to implement this for my
> private IBSS network.

It was added in P802.11-REVmb/D3.0 and will be included in the IEEE Std
802.11-2012 that should get published in a couple of months (it is
included in the latest draft: P802.11-REVmb/D12).

These 802.11 submissions may be helpful in understanding the changes:

https://mentor.ieee.org/802.11/dcn/10/11-10-0313-01-000m-rekeying-protocol-fix.ppt
https://mentor.ieee.org/802.11/dcn/10/11-10-0314-00-000m-rekeying-protocol-fix-text.doc
Andreas Hartmann Sept. 1, 2012, 1:15 p.m. UTC | #22
Nicolas Cavallari wrote:
> On 08/02/2012 17:18, Andreas Hartmann wrote:
[...]
>> 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 ...

I retested your patch again using 802.11g and could see this behaviour:

1. test: network idle
The 4/4 package is sent unencrypted as proposed. The rekeying did work
(but works fine too, without your patch).

2. test: network with high payload (netperf)
The 4/4 package couldn't be seen, but therefore 6(!) packages of payload
going from supplicant -> AP *unencrypted* . The rekeying didn't work
nevertheless.


Therefore: Big fat warning: don't use this patch at all!


Kind regards,
Andreas
Andreas Hartmann Sept. 1, 2012, 1:18 p.m. UTC | #23
Jouni Malinen schrieb:
> On Mon, Feb 13, 2012 at 11:39:26AM +0100, Nicolas Cavallari wrote:
>>> What were those other data frames? If this is during the initial 4-way
>>> handshake, the port (PAE) should be unauthorized and other data frames
>>> apart from EAPOL frames should be blocked.
>>
>> Only the specific port corresponding to that particular authenticator is
>> blocked. Other ports from other authenticators may be open. This is not
>> the case for Andreas, as he is in Infrastructure mode. But for me it is,
>> in IBSS mode...
> 
> Sure, though even in that case, the non-EAPOL Data frames that get
> through should be for other destinations. I'm not sure I've fully
> understood this specific part of the issue, though.
> 
>>> As far as rekeying is concerned, this gets quite a bit more
>>> complex (until the newly defined non-zero key index PTK gets into use).
>>
>> Which standard is this ? I might want to implement this for my
>> private IBSS network.
> 
> It was added in P802.11-REVmb/D3.0 and will be included in the IEEE Std
> 802.11-2012 that should get published in a couple of months (it is
> included in the latest draft: P802.11-REVmb/D12).
> 
> These 802.11 submissions may be helpful in understanding the changes:
> 
> https://mentor.ieee.org/802.11/dcn/10/11-10-0313-01-000m-rekeying-protocol-fix.ppt
> https://mentor.ieee.org/802.11/dcn/10/11-10-0314-00-000m-rekeying-protocol-fix-text.doc

May I kindly ask if these protocol changes have already been implemented
in wpa_supplicant / hostapd? The actual situation is really annoying :-(.


Thanks,
kind regards,
Andreas Hartmann
Jouni Malinen Sept. 1, 2012, 9:08 p.m. UTC | #24
On Sat, Sep 01, 2012 at 03:18:08PM +0200, Andreas Hartmann wrote:
> Jouni Malinen schrieb:
> > https://mentor.ieee.org/802.11/dcn/10/11-10-0313-01-000m-rekeying-protocol-fix.ppt

> May I kindly ask if these protocol changes have already been implemented
> in wpa_supplicant / hostapd? The actual situation is really annoying :-(.

Not yet. Though, even if they were, you would also need to get a
wireless LAN driver/firmware that supports non-zero Key ID for pairwise
keys, so this this require some more work.

For most use cases, CCMP is strong enough to be used for quite some time
without any rekeying, so the easiest workaround for rekeying related
issues is to increase the rekey interval. I would assume that the new
Key ID mechanism for unicast frames will eventually get deployed, but it
may take same time to get there.
Andreas Hartmann Sept. 2, 2012, 6:59 a.m. UTC | #25
Jouni Malinen wrote:
> On Sat, Sep 01, 2012 at 03:18:08PM +0200, Andreas Hartmann wrote:
>> Jouni Malinen schrieb:
>>> https://mentor.ieee.org/802.11/dcn/10/11-10-0313-01-000m-rekeying-protocol-fix.ppt
> 
>> May I kindly ask if these protocol changes have already been implemented
>> in wpa_supplicant / hostapd? The actual situation is really annoying :-(.
> 
> Not yet. Though, even if they were, you would also need to get a
> wireless LAN driver/firmware that supports non-zero Key ID for pairwise
> keys, so this this require some more work.

Would the firmware change be necessary, too, if nl80211 is used w/o
hardware but software encryption (for both AP and supplicant)?

> For most use cases, CCMP is strong enough to be used for quite some time
> without any rekeying, so the easiest workaround for rekeying related
> issues is to increase the rekey interval.

The recommended value for the eap reauth period is 3600 seconds.

You wrote about increasing the period and "quite some time".

What would be the risk of the increase? Or better: which kinds of
(known) attacks are complicated by forcing a regularly reauth? Why are
3600 seconds recommended and not, e.g., 1800? What would be a higher but
still risk less time of period when using eap-tls and ccmp (using
freeradius)?
If it was your own network, which higher value would you use?

I would be glad to get some basic points to be able to estimate the
potential risk. A link would be fine, too.


Thanks,
kind regards,
Andreas
Nicolas Cavallari Sept. 2, 2012, 9:30 a.m. UTC | #26
Le 01/09/2012 15:18, Andreas Hartmann a écrit :
> Jouni Malinen schrieb:
>> On Mon, Feb 13, 2012 at 11:39:26AM +0100, Nicolas Cavallari wrote:
>>>> As far as rekeying is concerned, this gets quite a bit more
>>>> complex (until the newly defined non-zero key index PTK gets into use).
>>> Which standard is this ? I might want to implement this for my
>>> private IBSS network.
>> It was added in P802.11-REVmb/D3.0 and will be included in the IEEE Std
>> 802.11-2012 that should get published in a couple of months (it is
>> included in the latest draft: P802.11-REVmb/D12).
>>
>> These 802.11 submissions may be helpful in understanding the changes:
>>
>> https://mentor.ieee.org/802.11/dcn/10/11-10-0313-01-000m-rekeying-protocol-fix.ppt
>> https://mentor.ieee.org/802.11/dcn/10/11-10-0314-00-000m-rekeying-protocol-fix-text.doc
> May I kindly ask if these protocol changes have already been implemented
> in wpa_supplicant / hostapd? The actual situation is really annoying :-(.

The hard part is implementing this in drivers. It's not even guaranteed 
that it will work with your cards. And if it does, it's because someone 
invested some of his time to implement it in mac80211.

I started working on this, but i found an acceptable hack^Walternative 
solution for my case, and forgot about this. But i might want to 
reconsider it.
Jouni Malinen Sept. 2, 2012, 10:22 a.m. UTC | #27
On Sun, Sep 02, 2012 at 08:59:27AM +0200, Andreas Hartmann wrote:
> Jouni Malinen wrote:
> > Not yet. Though, even if they were, you would also need to get a
> > wireless LAN driver/firmware that supports non-zero Key ID for pairwise
> > keys, so this this require some more work.
> 
> Would the firmware change be necessary, too, if nl80211 is used w/o
> hardware but software encryption (for both AP and supplicant)?

It may be needed depending on which WLAN hardware you are using, but
maybe not for most cases where software encryption is used.

> > For most use cases, CCMP is strong enough to be used for quite some time
> > without any rekeying, so the easiest workaround for rekeying related
> > issues is to increase the rekey interval.
> 
> The recommended value for the eap reauth period is 3600 seconds.
> 
> You wrote about increasing the period and "quite some time".
> 
> What would be the risk of the increase? Or better: which kinds of
> (known) attacks are complicated by forcing a regularly reauth? Why are
> 3600 seconds recommended and not, e.g., 1800? What would be a higher but
> still risk less time of period when using eap-tls and ccmp (using
> freeradius)?
> If it was your own network, which higher value would you use?

If EAP-TLS is used with a strong cipher and the network is configured to
use only CCMP, I don't think I would need EAP reauthentication or PTK
rekeying at all for practical purposes. Sure, you would need to stop
using the key if the CCM nonce wraps around, so rekeying would be needed
at that point, but that needs 2^48 frames to reach so until you get to
802.11ac or 802.11ad networks, it is a bit difficult to hit that in
practice.

That said, there may be other reasons for forcing EAP reauthentication,
e.g., to enforce some session limits or to allow removal of a station
from the network in reasonable amount of time even if the AP network
does not support RADIUS server initiated disconnection requests. Anyway,
I would consider CCMP strong enough to not require rekeying before CCM
nonce wraparound based on what's known and what kind of CPU resources
are available today, so the reason for setting rekeying based on some
time limit is coming from some other need than maintaining secure
encryption keys in the network.
Andreas Hartmann Sept. 5, 2012, 4:33 p.m. UTC | #28
Jouni Malinen wrote:
> On Sun, Sep 02, 2012 at 08:59:27AM +0200, Andreas Hartmann wrote:
>> Jouni Malinen wrote:
[...]
>>> For most use cases, CCMP is strong enough to be used for quite some time
>>> without any rekeying, so the easiest workaround for rekeying related
>>> issues is to increase the rekey interval.
>>
>> The recommended value for the eap reauth period is 3600 seconds.
>>
>> You wrote about increasing the period and "quite some time".
>>
>> What would be the risk of the increase? Or better: which kinds of
>> (known) attacks are complicated by forcing a regularly reauth? Why are
>> 3600 seconds recommended and not, e.g., 1800? What would be a higher but
>> still risk less time of period when using eap-tls and ccmp (using
>> freeradius)?
>> If it was your own network, which higher value would you use?
> 
> If EAP-TLS is used with a strong cipher and the network is configured to
> use only CCMP, I don't think I would need EAP reauthentication or PTK
> rekeying at all for practical purposes. Sure, you would need to stop
> using the key if the CCM nonce wraps around, so rekeying would be needed
> at that point, but that needs 2^48 frames to reach so until you get to
> 802.11ac or 802.11ad networks, it is a bit difficult to hit that in
> practice.

Thanks for your explanation! But: what's a strong cipher? If freeradius
cipher_list (-> openssl) is set to DEFAULT, the suite
TLS_DHE_RSA_WITH_AES_256_CBC_SHA is used. If set to high,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA is used. According nmap, both suites
are considered strong :-). Which one is stronger or more safe? CPU
resources are not relevant at all.

I'm using now 12 hours for rekeying timeout. I think this is feasible
for me.

> That said, there may be other reasons for forcing EAP reauthentication,
> e.g., to enforce some session limits or to allow removal of a station
> from the network in reasonable amount of time even if the AP network
> does not support RADIUS server initiated disconnection requests. Anyway,
> I would consider CCMP strong enough to not require rekeying before CCM
> nonce wraparound based on what's known and what kind of CPU resources
> are available today, so the reason for setting rekeying based on some
> time limit is coming from some other need than maintaining secure
> encryption keys in the network.

Thanks again for your considerations! They helped me a lot!


Kind regards,
Andreas Hartmann
diff mbox

Patch

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 225489e..b24cc53 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1141,6 +1141,9 @@  static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
 		break;
 	}
 
+	// Reset the PTK just before sending, so we don't sent 4/4 encrypted.
+	wpa_sm_set_key(sm, WPA_ALG_NONE, sm->bssid, 0, 0, NULL, 0, NULL, 0);
+
 	if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info,
 				       NULL, 0, &sm->ptk)) {
 		goto failed;