[PATCH] EAP-TEAP peer: keep inner EAP method when processing Identity method

Alexander Clouter alex+hostapd at coremem.com
Wed Nov 30 07:53:15 PST 2022

On Tue, 29 Nov 2022, at 21:30, Jouni Malinen wrote:
>> When EAP chaining (eg. EAP-TLS[machine] followed by EAP-MSCHAPv2[user]) in TEAP, the server sends to the client (along with the cryptobinding and interediate-status TLVs) an EAP Identity-Type to ask the peer for the correct type of identity.
> OK, but that Identity-Type TLV is not another instance of Identity
> method (behavior of which is what this patch is proposing to change)..

I probably muddled the explanation, sorry.

>> This is something that is described in RFC7170, in section 4.2.3, 4.3 and in particular is shown in appendix C.6.
> That Appendix C.6 example is explicitly noting that an identity request
> is not sent before negotiating EAP-Type=Y.

I thought RFC7170 appendix C.6 did show the second EAP Identity response, but a second non-glancing look found you are right, it does not.

The EAP Identity response though is needed for Win10/11...well it was the only way I could get this working for sequenced authentication.

>> Windows 11 needs to be prompted on what to use, otherwise it replies with a null identity which opens a whole world of pain.
> I'm not completely sure what "replies with a null identity" means in
> this context. Are you about EAP Payload TLV, not Identity-Type TLV here?
> I.e., there is actually two instances of EAP-Request/Identity within the
> tunnel?

Whilst doing interop with Windows, I noticed that if I did not start the next method in the sequence without EAP Identity (inside the EAP-Payload TLV), Windows replied with a zero byte length identity and refused to go any further.

But, let me go back and reproduce this to refresh my brain, it was a month or two ago when I figured this out.

There are two instances of EAP-Identity in the tunnel.

1. server->peer: Identity-Type-TLV + EAP-Payload-TLV[EAP-Identity]
2. peer<->server: EAP-Payload-TLV[do EAP-<anything>]
3. server->peer: {Intermediate-Success,Cryptobinding}-TLV + Identity-Type-TLV + EAP-Payload-TLV[EAP-Identity]
4. server<-peer: {Intermediate-Success,Cryptobinding}-TLV + Identity-Type-TLV + EAP-Payload-TLV[EAP-Identity]
5. peer<->server: EAP-Payload-TLV[do EAP-<anything>]
6. server->peer: {Success,Cryptobinding}-TLV
7. server<-peer: {Success,Cryptobinding}-TLV

I will get some PCAPs of this though, this is from memory.

>> Back to hostapd though, the presence of that second inner EAP Identity causes it to remove reference to the phase2 method just completed (ie. EAP-TLS) and so results in the fall back onto using eap_teap_derive_cmk_basic_pw_auth() when calculating the CMK in eap_teap.c:eap_teap_get_cmk().
> Would you be able to share a debug log showing this?

Sure, give me a few days to find the time and put back together my rig.

I also submitted patches to Wireshark which made it into version 4 so you get TEAP decoding and inner EAP-TLS decryption. The SSLKEYLOGFILE support I submitted and you merged into hostapd the other month combined with creating an embedded pcapng with the keying material makes things a lot easier to collaborate on.


You want the debug logs and/or PCAPs here on the list, or offline?

> I'm testing this with EAP-MSCHAPv2 for user authentication followed by
> EAP-MSCHAPv2 for machine authentication and when the second
> EAP-Request/Identity message is processed between those, the IMSK for
> the first EAP-MSCHAPv2 has already been fetched and used for CMK
> calculation. As such, this works fine with the first phase 2
> authentication method being cleared after that point. I do not see how
> eap_teap_derive_cmk_basic_pw_auth() would come into picture here since
> CMK was already derived before processing the EAP-Request/Identity.

The problem is though I got Windows 10/11 working with FreeRADIUS, I needed to get eapol_test invited to the party too.

What got my attention from the eapol_test logs was 'CMK[no-inner-EAP]' after the machine inner EAP-TLS authentication had just completed successfully.

Digging around I  I found the problem seemed to be that data->phase2_method was NULL and a bit more debugging found that it was that EAP identity was blanking it.

Removing the deinit when an EAP-Identity was processed fixed the problem, it made sense to me at the time why too.

Though maybe not the right fix, at least it is better than "does not work", right? :)

I have not looked into or tested using hostapd as a server for sequences against Win10/11.

> It sounds like there is something else happening in the sequence if
> eap_teap_get_cmk() is reached with data->phase2_method == NULL.. Maybe
> you are sending out the second EAP-Request/Identity in an
> EAP-Payload-TLV before the Crypto-Binding-TLV for the previously
> completed EAP authentication method? If so, I would suggest reordering
> that (see that C.6 example for an example when moving from EAP-Type X to
> Y) so that the crypto binding and CMK derivation is completed prior to
> starting any additional EAP methods, including the Identity method.

I do not think this will work, for non-technical reasons.

RFC7170 has only one ordering requirement I could find and that is to process the Identity-Type TLV before the EAP-Payload as it could affect routing.


Depending on a state machine implementation of the peer (or vice versa) I can see that a server pushing the Crypto-Binding TLV to the front of the list is helpful but that is definitely not mentioned in the RFC so it would be unsporting to beat people up over this.

If you would prefer to see an ordering fix here, then I think applying a change to hostapd to search and process any Crypto-Binding TLV first, then then Identity-Type TLV and then anything afterwards could work?

Your state machine is nice to work with...be a shame to muck it up with TEAP.

Alan has just posted to EMU that the TEAP RFC really does need to be fixed up:


Maybe you want to chip in?


More information about the Hostap mailing list