RFC 7170

Tunnel Extensible Authentication Protocol (TEAP) Version 1

📅 published May 2014, from ietf

RFC 7170: Tunnel Extensible Authentication Protocol (TEAP) Version 1 🦋

Part 1 of 18 💖

Okay bestie, this is RFC 7170, a Standards Track doc from the Internet Engineering Task Force (IETF) 🌸 It's titled Tunnel Extensible Authentication Protocol (TEAP) Version 1. The authors are H. Zhou, N. Cam-Winget, and J. Salowey from Cisco Systems, plus S. Hanna from Infineon Technologies. It was published in May 2014, and its ISSN is 2070-1721. The title block doesn't list anything it obsoletes or updates, so it's standing on its own 💅

Abstract ✨

Okay so this doc defines TEAP version 1 🦋 TEAP is a tunnel-based EAP method, which means a peer and a server can talk securely. It uses TLS (Transport Layer Security) to set up a mutually authenticated tunnel 🔐 Inside that tunnel, TLV objects carry the authentication-related data between the EAP peer and the EAP server. Iconic, honestly 💜

Status of This Memo 📜

This is an Internet Standards Track document 💅

This doc is a product of the IETF, so it represents the consensus of the IETF community. It got public review and was approved for publication by the Internet Engineering Steering Group (IESG) 🎀 For more on Internet Standards, see Section 2 of RFC 5741 📚 Info about the current status, any errata, and how to send feedback lives at http://www.rfc-editor.org/info/rfc7170.

Copyright (c) 2014 IETF Trust and the persons identified as the document authors. All rights reserved. 🫶

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) as in effect on the date of publication. Please read those carefully, because they spell out your rights and restrictions for this doc 🌈 Code Components extracted from this document must include Simplified BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Simplified BSD License.

Table of Contents 🌸

1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   5
  1.1.  Specification Requirements  . . . . . . . . . . . . . . .   5
  1.2.  Terminology . . . . . . . . . . . . . . . . . . . . . . .   6
2.  Protocol Overview . . . . . . . . . . . . . . . . . . . . . .   6
  2.1.  Architectural Model . . . . . . . . . . . . . . . . . . .   7
  2.2.  Protocol-Layering Model . . . . . . . . . . . . . . . . .   8
3.  TEAP Protocol . . . . . . . . . . . . . . . . . . . . . . . .   9
  3.1.  Version Negotiation . . . . . . . . . . . . . . . . . . .   9
  3.2.  TEAP Authentication Phase 1: Tunnel Establishment . . . .  10
    3.2.1.  TLS Session Resume Using Server State . . . . . . . .  11
    3.2.2.  TLS Session Resume Using a PAC  . . . . . . . . . . .  12
    3.2.3.  Transition between Abbreviated and Full TLS Handshake  13
  3.3.  TEAP Authentication Phase 2: Tunneled Authentication  . .  14
    3.3.1.  EAP Sequences . . . . . . . . . . . . . . . . . . . .  14
    3.3.2.  Optional Password Authentication  . . . . . . . . . .  15
    3.3.3.  Protected Termination and Acknowledged Result
            Indication  . . . . . . . . . . . . . . . . . . . . .  15
  3.4.  Determining Peer-Id and Server-Id . . . . . . . . . . . .  16
  3.5.  TEAP Session Identifier . . . . . . . . . . . . . . . . .  17
  3.6.  Error Handling  . . . . . . . . . . . . . . . . . . . . .  17
    3.6.1.  Outer-Layer Errors  . . . . . . . . . . . . . . . . .  18
    3.6.2.  TLS Layer Errors  . . . . . . . . . . . . . . . . . .  18
    3.6.3.  Phase 2 Errors  . . . . . . . . . . . . . . . . . . .  19
  3.7.  Fragmentation . . . . . . . . . . . . . . . . . . . . . .  19
  3.8.  Peer Services . . . . . . . . . . . . . . . . . . . . . .  20
    3.8.1.  PAC Provisioning  . . . . . . . . . . . . . . . . . .  21
    3.8.2.  Certificate Provisioning within the Tunnel  . . . . .  22
    3.8.3.  Server Unauthenticated Provisioning Mode  . . . . . .  23
    3.8.4.  Channel Binding . . . . . . . . . . . . . . . . . . .  23

4.  Message Formats . . . . . . . . . . . . . . . . . . . . . . .  24
  4.1.  TEAP Message Format . . . . . . . . . . . . . . . . . . .  24
  4.2.  TEAP TLV Format and Support . . . . . . . . . . . . . . .  26
    4.2.1.  General TLV Format  . . . . . . . . . . . . . . . . .  28
    4.2.2.  Authority-ID TLV  . . . . . . . . . . . . . . . . . .  29
    4.2.3.  Identity-Type TLV . . . . . . . . . . . . . . . . . .  30
    4.2.4.  Result TLV  . . . . . . . . . . . . . . . . . . . . .  31
    4.2.5.  NAK TLV . . . . . . . . . . . . . . . . . . . . . . .  32
    4.2.6.  Error TLV . . . . . . . . . . . . . . . . . . . . . .  33
    4.2.7.  Channel-Binding TLV . . . . . . . . . . . . . . . . .  36
    4.2.8.  Vendor-Specific TLV . . . . . . . . . . . . . . . . .  37
    4.2.9.  Request-Action TLV  . . . . . . . . . . . . . . . . .  38
    4.2.10. EAP-Payload TLV . . . . . . . . . . . . . . . . . . .  40
    4.2.11. Intermediate-Result TLV . . . . . . . . . . . . . . .  41
    4.2.12. PAC TLV Format  . . . . . . . . . . . . . . . . . . .  42
      4.2.12.1.  Formats for PAC Attributes . . . . . . . . . . .  43
      4.2.12.2.  PAC-Key  . . . . . . . . . . . . . . . . . . . .  44
      4.2.12.3.  PAC-Opaque . . . . . . . . . . . . . . . . . . .  44
      4.2.12.4.  PAC-Info . . . . . . . . . . . . . . . . . . . .  45
      4.2.12.5.  PAC-Acknowledgement TLV  . . . . . . . . . . . .  47
      4.2.12.6.  PAC-Type TLV . . . . . . . . . . . . . . . . . .  48
    4.2.13. Crypto-Binding TLV  . . . . . . . . . . . . . . . . .  48
    4.2.14. Basic-Password-Auth-Req TLV . . . . . . . . . . . . .  51
    4.2.15. Basic-Password-Auth-Resp TLV  . . . . . . . . . . . .  52
    4.2.16. PKCS#7 TLV  . . . . . . . . . . . . . . . . . . . . .  53
    4.2.17. PKCS#10 TLV . . . . . . . . . . . . . . . . . . . . .  54
    4.2.18. Trusted-Server-Root TLV . . . . . . . . . . . . . . .  55
  4.3.  TLV Rules . . . . . . . . . . . . . . . . . . . . . . . .  56
    4.3.1.  Outer TLVs  . . . . . . . . . . . . . . . . . . . . .  57
    4.3.2.  Inner TLVs  . . . . . . . . . . . . . . . . . . . . .  57
5.  Cryptographic Calculations  . . . . . . . . . . . . . . . . .  58
  5.1.  TEAP Authentication Phase 1: Key Derivations  . . . . . .  58
  5.2.  Intermediate Compound Key Derivations . . . . . . . . . .  59
  5.3.  Computing the Compound MAC  . . . . . . . . . . . . . . .  61
  5.4.  EAP Master Session Key Generation . . . . . . . . . . . .  61
6.  IANA Considerations . . . . . . . . . . . . . . . . . . . . .  62
7.  Security Considerations . . . . . . . . . . . . . . . . . . .  66
  7.1.  Mutual Authentication and Integrity Protection  . . . . .  67
  7.2.  Method Negotiation  . . . . . . . . . . . . . . . . . . .  67
  7.3.  Separation of Phase 1 and Phase 2 Servers . . . . . . . .  67
  7.4.  Mitigation of Known Vulnerabilities and Protocol
        Deficiencies  . . . . . . . . . . . . . . . . . . . . . .  68
    7.4.1.  User Identity Protection and Verification . . . . . .  69
    7.4.2.  Dictionary Attack Resistance  . . . . . . . . . . . .  70
    7.4.3.  Protection against Man-in-the-Middle Attacks  . . . .  70
    7.4.4.  PAC Binding to User Identity  . . . . . . . . . . . .  71

  7.5.  Protecting against Forged Cleartext EAP Packets . . . . .  71
  7.6.  Server Certificate Validation . . . . . . . . . . . . . .  72
  7.7.  Tunnel PAC Considerations . . . . . . . . . . . . . . . .  72
  7.8.  Security Claims . . . . . . . . . . . . . . . . . . . . .  73
8.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . .  74
9.  References  . . . . . . . . . . . . . . . . . . . . . . . . .  75
  9.1.  Normative References  . . . . . . . . . . . . . . . . . .  75
  9.2.  Informative References  . . . . . . . . . . . . . . . . .  76
Appendix A.  Evaluation against Tunnel-Based EAP Method
             Requirements . . . . . . . . . . . . . . . . . . . .  79
  A.1.  Requirement 4.1.1: RFC Compliance . . . . . . . . . . . .  79
  A.2.  Requirement 4.2.1: TLS Requirements . . . . . . . . . . .  79
  A.3.  Requirement 4.2.1.1.1: Ciphersuite Negotiation  . . . . .  79
  A.4.  Requirement 4.2.1.1.2: Tunnel Data Protection Algorithms   79
  A.5.  Requirement 4.2.1.1.3: Tunnel Authentication and Key
        Establishment . . . . . . . . . . . . . . . . . . . . . .  79
  A.6.  Requirement 4.2.1.2: Tunnel Replay Protection . . . . . .  79
  A.7.  Requirement 4.2.1.3: TLS Extensions . . . . . . . . . . .  80
  A.8.  Requirement 4.2.1.4: Peer Identity Privacy  . . . . . . .  80
  A.9.  Requirement 4.2.1.5: Session Resumption . . . . . . . . .  80
  A.10. Requirement 4.2.2: Fragmentation  . . . . . . . . . . . .  80
  A.11. Requirement 4.2.3: Protection of Data External to Tunnel   80
  A.12. Requirement 4.3.1: Extensible Attribute Types . . . . . .  80
  A.13. Requirement 4.3.2: Request/Challenge Response Operation .  80
  A.14. Requirement 4.3.3: Indicating Criticality of Attributes .  80
  A.15. Requirement 4.3.4: Vendor-Specific Support  . . . . . . .  81
  A.16. Requirement 4.3.5: Result Indication  . . . . . . . . . .  81
  A.17. Requirement 4.3.6: Internationalization of Display
        Strings . . . . . . . . . . . . . . . . . . . . . . . . .  81
  A.18. Requirement 4.4: EAP Channel-Binding Requirements . . . .  81
  A.19. Requirement 4.5.1.1: Confidentiality and Integrity  . . .  81
  A.20. Requirement 4.5.1.2: Authentication of Server . . . . . .  81
  A.21. Requirement 4.5.1.3: Server Certificate Revocation
        Checking  . . . . . . . . . . . . . . . . . . . . . . . .  81
  A.22. Requirement 4.5.2: Internationalization . . . . . . . . .  81
  A.23. Requirement 4.5.3: Metadata . . . . . . . . . . . . . . .  82
  A.24. Requirement 4.5.4: Password Change  . . . . . . . . . . .  82
  A.25. Requirement 4.6.1: Method Negotiation . . . . . . . . . .  82
  A.26. Requirement 4.6.2: Chained Methods  . . . . . . . . . . .  82
  A.27. Requirement 4.6.3: Cryptographic Binding with the TLS
        Tunnel  . . . . . . . . . . . . . . . . . . . . . . . . .  82
  A.28. Requirement 4.6.4: Peer-Initiated EAP Authentication  . .  82
  A.29. Requirement 4.6.5: Method Metadata  . . . . . . . . . . .  82
Appendix B.  Major Differences from EAP-FAST  . . . . . . . . . .  83
Appendix C.  Examples . . . . . . . . . . . . . . . . . . . . . .  83
  C.1.  Successful Authentication . . . . . . . . . . . . . . . .  83
  C.2.  Failed Authentication . . . . . . . . . . . . . . . . . .  85
  C.3.  Full TLS Handshake Using Certificate-Based Ciphersuite  .  86
  C.4.  Client Authentication during Phase 1 with Identity
        Privacy . . . . . . . . . . . . . . . . . . . . . . . . .  88
  C.5.  Fragmentation and Reassembly  . . . . . . . . . . . . . .  89
  C.6.  Sequence of EAP Methods . . . . . . . . . . . . . . . . .  91
  C.7.  Failed Crypto-Binding . . . . . . . . . . . . . . . . . .  94
  C.8.  Sequence of EAP Method with Vendor-Specific TLV Exchange   95
  C.9.  Peer Requests Inner Method after Server Sends Result TLV   97
  C.10. Channel Binding . . . . . . . . . . . . . . . . . . . . .  99

Up next: Section 1, Introduction ✨🦋💖

1. Introduction ✨

okay so a tunnel-based Extensible Authentication Protocol (EAP) method is an EAP method that first builds a secure tunnel and then runs other EAP methods inside that protected tunnel 🔒 it's giving layers, literally. A tunnel-based EAP method can ride on any lower-layer protocol that already supports EAP authentication 🦋 There are a few existing ones that use Transport Layer Security (TLS) [RFC5246] to build the tunnel: Protected EAP (PEAP) [PEAP], EAP Tunneled Transport Layer Security (EAP-TTLS) [RFC5281], and EAP Flexible Authentication via Secure Tunneling (EAP-FAST) [RFC4851]. BUT ngl, they're either vendor-specific or informational, and the industry is really begging for a Standards Track tunnel-based EAP method 🙏 [RFC6678] lays out the list of requirements for one.

EAP-FAST [RFC4851] has been adopted by tons of devices and platforms since it came out, so it's super popular 💅 The EMU working group picked it as the basis for the standard tunnel-based EAP method. This document describes the Tunnel Extensible Authentication Protocol (TEAP) version 1, which is based on EAP-FAST [RFC4851] with some small changes so it meets the requirements in [RFC6678] for a standard tunnel-based EAP method. Glow-up arc, bestie 🌸

1.1. Specification Requirements

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. 📜✨

1.2. Terminology

Most of the vocab in this doc comes from [RFC3748] 📚 A few extra terms are defined below, so read up before you dive in 🧚

Protected Access Credential (PAC)

Credentials handed to a peer so it can do faster, optimized network authentication later 🎀 A PAC has a minimum of two components: a shared secret and an opaque element. The shared secret component holds the pre-shared key between the peer and the authentication server. The opaque part is given to the peer and gets presented to the authentication server whenever the peer wants access to network resources. The opaque element and shared secret are used with TLS stateless session resumption defined in [RFC5077] to set up a protected TLS session. The secret key and opaque part may be distributed using [RFC5077] messages or using TLVs within the TEAP tunnel. Finally, a PAC may optionally include other information that may be useful to the peer 💜

Type-Length-Value (TLV)

The TEAP protocol runs on objects in TLV format. The TLV format is defined in Section 4.2 🍓

2. Protocol Overview 🌈

TEAP authentication happens in two phases after the initial EAP Identity request/response exchange. In the first phase, TEAP uses the TLS [RFC5246] handshake to do an authenticated key exchange and build a protected tunnel 🔐 Once the tunnel exists, phase two kicks off, where the peer and server keep chatting to set up the required authentication and authorization policies. TEAP uses TLV objects to carry the inner authentication, the results, and other info, like channel-binding information 💬

TEAP uses the TLS SessionTicket extension [RFC5077], which supports TLS session resumption without needing session-specific state stored on the server 👑 In this document, the SessionTicket is called the Protected Access Credential opaque data (or PAC-Opaque). The PAC-Opaque can be distributed through the NewSessionTicket message, or through a mechanism that uses TLVs within Phase 2 of TEAP. The secret key used to resume the session in TEAP is called the Protected Access Credential key (or PAC-Key). When the NewSessionTicket message distributes the PAC-Opaque, the PAC-Key is the master secret for the session. If TEAP Phase 2 is used to distribute the PAC-Opaque, then the PAC-Key gets distributed along with it. TEAP implementations MUST support the [RFC5077] mechanism for distributing a PAC-Opaque, and it is RECOMMENDED that implementations support the capability to distribute the ticket and secret key within the TEAP tunnel 🫶

The TEAP conversation is used to establish or resume an existing session, usually to get network connectivity between a peer and the network 🦋 When TEAP runs successfully, the EAP peer and EAP server both derive strong session key material. That key material can then be passed to the network access server (NAS) to set up a link-layer security association ✨

2.1. Architectural Model

Here's the network architectural model for TEAP usage 👀

 +----------+      +----------+      +----------+      +----------+
 |          |      |          |      |          |      |  Inner   |
 |   Peer   |<---->|  Authen- |<---->|   TEAP   |<---->|  Method  |
 |          |      |  ticator |      |  server  |      |  server  |
 |          |      |          |      |          |      |          |
 +----------+      +----------+      +----------+      +----------+

                      TEAP Architectural Model

The entities in the diagram above are logical entities, and they may or may not match separate network components 🧩 For example, the TEAP server and inner method server could be one entity; the authenticator and TEAP server could be one entity; or the functions of the authenticator, TEAP server, and inner method server could all be squished into one physical device. Typical IEEE 802.11 deployments put the authenticator in an access point (AP), while a RADIUS server may provide the TEAP and inner method server components 📡 The diagram shows how the work gets divided up in a general way and how a distributed system might be built, but real systems might be simpler than that 💖 Section 7.3 has more on what happens when you separate the TEAP server from the inner method server, so go check it out 🔥

2.2. Protocol-Layering Model

TEAP packets are encapsulated within EAP, and EAP in turn needs a transport protocol 🎀 TEAP packets encapsulate TLS, which then encapsulates the user authentication info. So TEAP messaging can be described with a layered model where each layer wraps the layer above it 🪆 Here's how the protocols relate:

 +---------------------------------------------------------------+
 |       Inner EAP Method     |     Other TLV information        |
 |---------------------------------------------------------------|
 |                 TLV Encapsulation (TLVs)                      |
 |---------------------------------------------------------------|
 |                TLS         |     Optional Outer TLVs          |
 |---------------------------------------------------------------|
 |                         TEAP                                  |
 |---------------------------------------------------------------|
 |                         EAP                                   |
 |---------------------------------------------------------------|
 |    Carrier Protocol (EAP over LAN, RADIUS, Diameter, etc.)    |
 +---------------------------------------------------------------+

                      Protocol-Layering Model

The TLV layer is a payload made of TLV objects, as defined in Section 4.2 🧁 TLV objects carry arbitrary parameters between an EAP peer and an EAP server. Every conversation inside the TEAP protected tunnel is wrapped in a TLV layer 🔐

TEAP packets can have TLVs both inside and outside the TLS tunnel. "Outer TLVs" refers to the optional TLVs outside the TLS tunnel, and they're only allowed in the first two messages of the TEAP protocol: the first EAP-server-to-peer message and the first peer-to-EAP-server message 👀 If a message gets fragmented, the whole set of messages counts as one message. "Inner TLVs" refers to TLVs sent inside the TLS tunnel. In TEAP Phase 1, Outer TLVs help build the TLS tunnel, but no Inner TLVs are used. In Phase 2, TLS records may wrap zero or more Inner TLVs, but no Outer TLVs at all 💅

Ways to encapsulate EAP inside carrier protocols are already defined 🙌 For instance, IEEE 802.1X [IEEE.802-1X.2013] can carry EAP between the peer and the authenticator, and RADIUS [RFC3579] or Diameter [RFC4072] can carry EAP between the authenticator and the EAP server 🚀

3. TEAP Protocol 💫

This section is all about how the protocol operates, including Phase 1 and Phase 2 🧠 The format of TEAP messages is in Section 4, and the cryptographic calculations are in Section 5 🔢

3.1. Version Negotiation

TEAP packets have a 3-bit Version field, right after the TLS Flags field, which lets future TEAP implementations stay backward compatible with older versions of the protocol 🦋 This spec documents TEAP version 1, and implementations of this specification MUST set the Version field to 1 💖

Here's how version negotiation goes 🎀

1. In the first EAP-Request sent with EAP type=TEAP, the EAP server MUST set the Version field to the highest version it supports.

2a. If the EAP peer supports this version of the protocol, it responds with an EAP-Response of EAP type=TEAP, including the version number proposed by the TEAP server.

2b. If the TEAP peer does not support the proposed version but supports a lower version, it responds with an EAP-Response of EAP type=TEAP and sets the Version field to its highest supported version.

2c. If the TEAP peer only supports versions higher than the version proposed by the TEAP server, then use of TEAP will not be possible. In this case, the TEAP peer sends back an EAP-Nak either to negotiate a different EAP type or to indicate no other EAP types are available 🙈

3a. If the TEAP server does not support the version number proposed by the TEAP peer, it MUST either terminate the conversation with an EAP Failure or negotiate a new EAP type.

3b. If the TEAP server does support the version proposed by the TEAP peer, then the conversation continues using the version proposed by the TEAP peer ✨

Version negotiation guarantees that the TEAP peer and server will agree on the latest version supported by both of them 👑 If it fails, TEAP is off the table, and another mutually acceptable EAP method will need to be negotiated if authentication is going to happen 😭

The TEAP version is not protected by TLS, so it can be modified in transit 💀 To detect a change to the TEAP version, the peers MUST exchange the TEAP version number received during version negotiation using the Crypto-Binding TLV described in Section 4.2.13 🔥 The receiver of the Crypto-Binding TLV MUST verify that the version in the Crypto-Binding TLV matches the version the receiver sent during TEAP version negotiation. If the Crypto-Binding TLV fails validation, that's a fatal error, handled as described in Section 3.6.3 🚨

3.2. TEAP Authentication Phase 1: Tunnel Establishment ✨

Okay bestie, TEAP leans on the TLS handshake [RFC5246] to build an authenticated, protected tunnel 🔐 The TLS version offered by the peer and server MUST be TLS version 1.2 [RFC5246] or later. This version of the TEAP implementation MUST support these TLS ciphersuites 💅

  • TLS_RSA_WITH_AES_128_CBC_SHA [RFC5246]
  • TLS_DHE_RSA_WITH_AES_128_CBC_SHA [RFC5246]

It SHOULD also support this one 🌸

  • TLS_RSA_WITH_AES_256_CBC_SHA [RFC5246]

Other ciphersuites MAY be supported too ✨ Now the anonymous ones, like TLS_DH_anon_WITH_AES_128_CBC_SHA [RFC5246]. It is REQUIRED that these only get used when the inner authentication method gives you mutual authentication, key generation, and resistance to man-in-the-middle and dictionary attacks. Anything that doesn't provide confidentiality MUST NOT be used, no exceptions 🙅‍♀️ During the TEAP Phase 1 conversation, the endpoints MAY negotiate TLS compression. During tunnel setup, TLS extensions MAY be used as well 🎀 For example, the Certificate Status Request extension [RFC6066] and the Multiple Certificate Status Request extension [RFC6961] can be used to tap into a certificate-status protocol like Online Certificate Status Protocol (OCSP) [RFC6960] so you can check whether server certificates are still valid. TLS renegotiation indications defined in RFC 5746 [RFC5746] MUST be supported, period 💖

The EAP server kicks things off with an EAP request carrying a TEAP/Start packet 🦋 That packet has the Start (S) bit set, the TEAP version from Section 3.1, and an authority identity TLV. The TLS payload in that first packet is empty. The Authority-ID TLV (Authority-ID TLV) gives the peer a hint about the server's identity, which can help it pick the right credential 🔑 If the peer supports TEAP, it replies with an EAP-Response with an EAP type of TEAP, the Start (S) bit clear, and the version from Section 3.1. That message wraps up one or more TLS handshake messages. If the version negotiation works out, the back-and-forth keeps going until the EAP server and EAP peer are ready for Phase 2 🧚 When a full TLS handshake happens, the first payload of TEAP Phase 2 MAY be sent along with a server-finished handshake message, which cuts down on round trips ⭐

TEAP implementations MUST support mutual peer authentication during tunnel establishment, using the TLS ciphersuites from this section 👑 The TEAP peer doesn't have to authenticate during the TLS exchange. It can get authenticated through extra exchanges in Phase 2 instead 🌈

The tunnel protects the peer identity info exchanged during Phase 2 from being seen outside the tunnel 🫶 If you want identity privacy for the peer, you have to think carefully about what gets disclosed outside the tunnel before Phase 2 even starts 👀 TEAP implementations SHOULD support immediate renegotiation of a TLS session, starting a new handshake message exchange under the protection of the current ciphersuite. That's how you protect the peer's identity when TLS client authentication is in use 😭 Appendix C has an example of exchanges using TLS renegotiation to protect privacy.

The next sections cover resuming a TLS session based on server-side or client-side state 🍓

3.2.1. TLS Session Resume Using Server State

TEAP resumes sessions the same way TLS does 💜 To support this, the server and peer minimally cache the Session ID, master secret, and ciphersuite. The peer tries to resume by putting a valid Session ID from an earlier TLS handshake into its ClientHello. If the server finds a match and is willing to set up a new connection using that session state, it responds with the same Session ID and moves on to TEAP Phase 1 tunnel establishment using a TLS abbreviated handshake 🎉 Once Phase 1 wraps up successfully, the conversation continues on to Phase 2 ✨

3.2.2. TLS Session Resume Using a PAC

TEAP supports resuming sessions where the server state is stored on the client side, using the TLS SessionTicket extension techniques from [RFC5077] 🎟️ This version of TEAP supports provisioning a ticket called a Protected Access Credential (PAC) through the NewSessionTicket handshake described in [RFC5077], and also through provisioning a PAC inside the protected tunnel. Implementations MUST support the TLS Ticket extension [RFC5077] mechanism for distributing a PAC, and they MAY offer other ways to provision it, like manual configuration 🛠️ Since this PAC is used to set up the TLS tunnel, it's more specifically called the Tunnel PAC. The Tunnel PAC is a security credential that the EAP server gives a peer, and it's made up of:

  1. PAC-Key: this is the key the peer uses as the TLS master secret to establish the TEAP Phase 1 tunnel. The PAC-Key is a strong, high-entropy, at-minimum 48-octet key, and it's usually the master secret from a previous TLS session. The PAC-Key is a secret and MUST be treated that way 🤫 If it leaks, user credentials could get compromised when they're sent inside a tunnel set up with the PAC-Key. If a PAC-Key is provisioned to the peer some other way, it MUST have its confidentiality and integrity protected by a mechanism, such as the TEAP Phase 2 tunnel. The PAC-Key MUST be stored securely by the peer 🔐
  2. PAC-Opaque: this is a variable-length field holding the ticket that gets sent to the EAP server during TEAP Phase 1 tunnel establishment, based on [RFC5077]. Only the EAP server can interpret the PAC-Opaque, to recover what it needs to validate the peer's identity and authentication. The PAC-Opaque includes the PAC-Key and other TLS session parameters, and it may contain the PAC's peer identity. The format and contents are specific to the server that issued the PAC. The PAC-Opaque may be presented in the clear, so an attacker MUST NOT be able to get useful information from the PAC-Opaque itself 🚨 The issuing server needs to make sure it's protected with strong cryptographic keys and algorithms. The PAC-Opaque may be distributed using the NewSessionTicket message defined in [RFC5077], or through another mechanism like the Phase 2 TLVs defined in this document 💌
  3. PAC-Info: this is an optional variable-length field used to provide, at minimum, the authority identity of the PAC issuer. Other useful but not mandatory info, like the PAC-Key lifetime, can also be passed along by the PAC-issuing server during PAC provisioning or refreshment. PAC-Info is not included if the NewSessionTicket message is used to provision the PAC 📝

Using the PAC is based on the SessionTicket extension from [RFC5077]. The EAP server starts the TEAP conversation as normal 🌷 When the peer gets the Authority-ID TLV from the server, it checks whether it already has a valid PAC-Key and PAC-Opaque for that server. If it does, it grabs the PAC-Opaque and puts it in the SessionTicket extension in the ClientHello. It is RECOMMENDED in TEAP that the peer include an empty Session ID in a ClientHello containing a PAC-Opaque 🧁 This version of TEAP supports the NewSessionTicket Handshake message from [RFC5077] for distributing a new PAC, as well as provisioning a PAC inside the protected tunnel. If the PAC-Opaque in the SessionTicket extension is valid and the EAP server allows the abbreviated TLS handshake, the server picks the ciphersuite from the info inside the PAC-Opaque and finishes the abbreviated handshake 🙌 If the server gets both a Session ID and a PAC-Opaque in the SessionTicket extension of a ClientHello, it should put that same Session ID in the ServerHello when it resumes based on the PAC-Opaque. From there the conversation follows [RFC5077] until the handshake completes or a fatal error happens. Once the abbreviated handshake is done, the peer and server are ready to start Phase 2 🚀

3.2.3. Transition between Abbreviated and Full TLS Handshake

If session resumption based on server-side or client-side state fails, the server can gracefully fall back to a full TLS handshake 🔄 If the ServerHello the peer gets has an empty Session ID, or a Session ID that's different from the one in the ClientHello, the server may fall back to a full handshake. The peer can tell whether the server wants a full or abbreviated handshake by checking the next TLS handshake messages in the server's response to the ClientHello. If ChangeCipherSpec follows the ServerHello, the server accepted the session resumption and intends to do the abbreviated handshake. Otherwise, it intends to negotiate the full TLS handshake 👀 A peer can ask for a new PAC to be provisioned after a full TLS handshake and mutual authentication of the peer and server. A peer SHOULD NOT request a new PAC after the abbreviated handshake, since requesting a new session ticket based on a resumed session is not permitted 🙅‍♀️ To make falling back to a full handshake easier, the peer SHOULD include ciphersuites that allow a full handshake and possibly PAC provisioning, so the server can pick one of those if session resumption fails 💅 An example of the transition is in Appendix C.

3.3. TEAP Authentication Phase 2: Tunneled Authentication 🎀

The second part of TEAP authentication happens right after Phase 1 completes successfully 🦋 Phase 2 happens even if both peer and authenticator were already authenticated during the Phase 1 TLS negotiation. Phase 2 MUST NOT occur if the Phase 1 TLS handshake fails, because the security is compromised when the tunnel hasn't been set up successfully 🚫 Phase 2 is a series of requests and responses wrapped in TLV objects defined in Section 4.2. Phase 2 MUST always end with a Crypto-Binding TLV exchange, described in Section 4.2.13, and a protected termination exchange, described in Section 3.3.3 🔒 The TLV exchange can include zero or more EAP methods run inside the protected tunnel, as described in Section 3.3.1. A server MAY go straight to the protected termination exchange if it doesn't want to request any more authentication from the peer 🏁 But the peer and server MUST NOT assume that either one will skip inner EAP methods or other TLV exchanges, since the other side might have a different security policy 👑 The peer might have roamed to a network with a different authentication policy, or it might ask the server to take extra action (for example, channel binding) using the Request-Action TLV defined in Section 4.2.9 🌈

3.3.1. EAP Sequences ✨

okay so EAP [RFC3748] bans using multiple auth methods inside one EAP conversation 🙅‍♀️, all to limit the damage a man-in-the-middle attacker can do. TEAP handles those MITM vibes with cryptographic protection of the inner EAP exchange and cryptographic binding of the inner authentication method(s) to the protected tunnel 🔐. EAP methods run one after another in a sequence. This version of TEAP does not support starting multiple EAP methods at the same time in parallel. The methods need not be distinct, which is giving EAP-TLS running twice as an inner method, first with machine credentials and then with user credentials 💜.

EAP method messages ride along inside EAP-Payload TLVs defined in Section 4.2.10 🎀. If more than one method is going to run in the tunnel, the server MUST send an Intermediate-Result TLV when a method finishes, saying how it went. The peer MUST respond to that Intermediate-Result TLV with its own result 🫶. If the result is success, the Intermediate-Result TLV MUST be accompanied by a Crypto-Binding TLV. We'll talk more about the Crypto-Binding TLV in Sections 4.2.13 and 5.3 🧚. Intermediate-Result TLVs can be bundled with other TLVs, like EAP-Payload TLVs that start a new EAP conversation, or with the Result TLV used in the protected termination exchange ✨.

If both peer and server say success, the method is complete 🌈. If either one says failure, the method is failed 💀. Failing one method doesn't always mean the whole authentication has failed. If one method fails, the server may try authenticating the peer with a different method 🦋.

3.3.2. Optional Password Authentication 🔑

Using EAP-FAST-GTC as defined in RFC 5421 [RFC5421] is NOT RECOMMENDED with TEAPv1, because EAP-FAST-GTC isn't compliant with EAP-GTC defined in [RFC3748] 😭. Implementations should instead use the password authentication TLVs defined in this specification 💅. The authentication server kicks things off by sending a Basic-Password-Auth-Req TLV defined in Section 4.2.14 🌸. If the peer wants to take part in password authentication, it replies with a Basic-Password-Auth-Resp TLV as defined in Section 4.2.15, containing the username and password. If it doesn't want to do password auth, it replies with a NAK TLV rejecting the Basic-Password-Auth-Req TLV 🙈. After getting that response, the server shows the success or failure of the exchange with an Intermediate-Result TLV ✅.

Multiple round trips of password authentication requests and responses MAY be used for some "housecleaning" stuff, like a password or PIN change before the user is authenticated 🧹✨.

3.3.3. Protected Termination and Acknowledged Result Indication 💖

A successful TEAP Phase 2 conversation MUST always end with a successful Crypto-Binding TLV and Result TLV exchange 🏁. A TEAP server may kick off the Crypto-Binding TLV and Result TLV exchange without starting any EAP conversation in TEAP Phase 2 ✨. After the final Result TLV exchange, the TLS tunnel gets torn down, and the server sends a cleartext EAP Success or EAP Failure 🎀. Peers implementing TEAP MUST NOT accept a cleartext EAP Success or failure packet before the peer and server have reached synchronized protected result indication 🚫.

The Crypto-Binding TLV exchange proves that both the peer and the server took part in setting up the tunnel and the sequence of authentications 🔗. It also verifies the TEAP type, the version that was negotiated, and the Outer TLVs exchanged before the TLS tunnel was set up 🕵️‍♀️. The Crypto-Binding TLV MUST be exchanged and verified before the final Result TLV exchange, whether or not there's an inner EAP method authentication 🙌. The Crypto-Binding TLV and Intermediate-Result TLV MUST be included to do cryptographic binding after each successful EAP method in a sequence of one or more EAP methods 💜. The server may send the final Result TLV together with an Intermediate-Result TLV and a Crypto-Binding TLV to signal that it wants to wrap up the conversation 🎬. If the peer doesn't need anything more from the server, it responds with a Result TLV indicating success, along with a Crypto-Binding TLV and an Intermediate-Result TLV if needed. Then the server tears down the tunnel and sends a cleartext EAP Success or EAP Failure 👑.

Here's a fun twist: if the peer gets a Result TLV saying success from the server, but its authentication policies aren't satisfied (for example, it needs a particular authentication mechanism to run, or it wants to request a PAC), it can ask the server for more action using the Request-Action TLV 🧐. The Request-Action TLV is sent with a Status field showing what EAP Success/Failure result the peer would expect if the requested action isn't granted. The Action field shows what the peer would like to do next 💅. The format and values for the Request-Action TLV are defined in Section 4.2.9 🌈.

When the server gets a Request-Action TLV, it may process the request or ignore it, based on its policy 🤷‍♀️. If the server ignores the request, it goes ahead and terminates the tunnel, then sends the cleartext EAP Success or Failure message based on the Status field of the peer's Request-Action TLV 🫠. If the server honors and processes the request, it continues with the requested action. The conversation finishes with a Result TLV exchange. The Result TLV may be included with the TLV that completes the requested action 🎉.

Error handling for Phase 2 is discussed in Section 3.6.3 🛠️.


3.4. Determining Peer-Id and Server-Id 🪪

The Peer-Id and Server-Id [RFC5247] may be determined based on the types of credentials used during either the TEAP tunnel creation or authentication 🔍. If there are multiple peer authentications, all authenticated peer identities and their matching identity types (Section 4.2.3) need to be exported 📤. If there are multiple server authentications, all authenticated server identities need to be exported 📤✨.

When X.509 certificates are used for peer authentication, the Peer-Id is determined by the subject and subjectAltName fields in the peer certificate 📜. As RFC 5280 notes:

The subject field identifies the entity associated with the public key stored in the subject public key field. The subject name MAY be carried in the subject field and/or the subjectAltName extension. . . . If subject naming information is present only in the subjectAltName extension (e.g., a key bound only to an email address or URI), then the subject name MUST be an empty sequence and the subjectAltName extension MUST be critical. Where it is non-empty, the subject field MUST contain an X.500 distinguished name (DN).

If an inner EAP method is run, the Peer-Id comes from the inner method 🎀.

When the server uses an X.509 certificate to set up the TLS tunnel, the Server-Id is worked out in a similar way to the Peer-Id above. For example, the subject and subjectAltName fields in the server certificate define the Server-Id 🌸.


3.5. TEAP Session Identifier 🌷

The EAP session identifier [RFC5247] is built from the tls-unique value of the Phase 1 outer tunnel at the start of Phase 2, as defined by Section 3.1 of [RFC5929] 🦋. The Session-Id is defined like this:

  Session-Id = teap_type || tls-unique

  where teap_type is the EAP Type assigned to TEAP

  tls-unique = tls-unique from the Phase 1 outer tunnel at the
  beginning of Phase 2 as defined by Section 3.1 of [RFC5929]

  || means concatenation

3.6. Error Handling 🚨

TEAP uses the error-handling rules summarized below 💅:

  1. Errors in the outer EAP packet layer are handled as defined in Section 3.6.1 📦.
  2. Errors in the TLS layer are communicated via TLS alert messages in all phases of TEAP 🔔.
  3. The Intermediate-Result TLVs carry success or failure indications of the individual EAP methods in TEAP Phase 2. Errors within the EAP conversation in Phase 2 are expected to be handled by individual EAP methods 🧩.
  4. Violations of the Inner TLV rules are handled using Result TLVs together with Error TLVs 🙅‍♀️.
  5. Tunnel-compromised errors (errors caused by a failed or missing Crypto-Binding) are handled using Result TLVs and Error TLVs 🔥.

3.6.1. Outer-Layer Errors 📦

Errors on the TEAP outer-packet layer get handled in these ways 🫧:

  1. If Outer TLVs are invalid or contain unknown values, they will be ignored 🙈.
  2. The entire TEAP packet will be ignored if other fields (version, length, flags, etc.) are inconsistent with this specification 💀.

3.6.2. TLS Layer Errors ⚠️

If the TEAP server detects an error at any point in the TLS handshake or the TLS layer, the server SHOULD send a TEAP request encapsulating a TLS record containing the appropriate TLS alert message. It doesn't just terminate the conversation right away, so the peer can tell the user what caused the failure and possibly allow the conversation to restart 🔄. The peer MUST send a TEAP response to an alert message 📨. The EAP-Response packet sent by the peer may encapsulate a TLS ClientHello handshake message. In that case, the TEAP server MAY allow the TEAP conversation to be restarted. Or the peer MAY contain a TEAP response with a zero-length message, in which case the server MUST terminate the conversation with an EAP Failure packet 💔. It's up to the TEAP server whether to allow restarts and, if it does, how many times the conversation can restart 🧠. Per TLS [RFC5246], TLS restart is only allowed for non-fatal alerts 🚦. A TEAP server implementing restart capability SHOULD impose a limit on the number of restarts, so it's protected against denial-of-service attacks 🛡️. If the TEAP server doesn't allow restarts, it MUST terminate the conversation with an EAP Failure packet 🚪.

If the TEAP peer detects an error at any point in the TLS layer, the TEAP peer SHOULD send a TEAP response encapsulating a TLS record containing the appropriate TLS alert message 🧾. The server may restart the conversation by sending a TEAP request packet that encapsulates the TLS HelloRequest handshake message 🔁. The peer may allow the TEAP conversation to be restarted, or it may end the conversation by sending a TEAP response with a zero-length message 🌙.

3.6.3. Phase 2 Errors 💅

okay bestie, so if the peer or the server hits a fatal error outside the TLS layer during Phase 2 TLV processing, it MUST send a Result TLV saying failure, plus an Error TLV with the right error code 🚨. If the problem is with the order of the exchanges, like breaking the TLV rules (think: sending multiple EAP-Payload TLVs), the code is Unexpected TLVs Exchanged. If the tunnel might be compromised, the code is Tunnel Compromise Error 🔐. And once the sender has put a Result TLV with a fatal Error TLV out there, it terminates the TLS tunnel. ngl that's a whole vibe check 💀

Also, the server still waits for a message from the peer after it sends a failure, but it doesn't have to actually process what the peer sends back 🙈

For the inner method, retransmission is not needed and SHOULD NOT be attempted, because the Outer TLS tunnel counts as a reliable transport 🦋 Now if there's a non-fatal error while handling the inner method, the receiving side SHOULD NOT just silently drop the request or response and go quiet. Instead it SHOULD send an Error TLV with the error code Inner Method Error to say "hey, something went wrong with this inner method" 🫶 Then the side that gets that Error TLV MAY decide to start a new inner method instead, or send back a Result TLV to end the TEAP authentication session. Options, options 🌸

Last bit, the failure endings. If a server gets a Result TLV of failure with a fatal Error TLV, it MUST send a cleartext EAP Failure 😭 If a peer gets a Result TLV of failure, it MUST respond with a Result TLV indicating failure. And if the server already sent a Result TLV of failure, it ignores the peer's response and it MUST send a cleartext EAP Failure. The ending is always the same, no drama 👑


3.7. Fragmentation 🎀

okay so a single TLS record can be up to 16384 octets, but a TLS message can span multiple TLS records, and a TLS certificate message may, in principle, be as long as 16 MB 😳 That is way bigger than the max size for a message on most media types, so fragmentation is definitely desirable. Also, to protect against reassembly lockup and denial-of-service attacks, it may be desirable for an implementation to set a maximum size for one of these groups of TLS messages. A typical certificate chain is rarely longer than a few thousand octets, and no other field is likely to be anywhere near that long, so a reasonable max acceptable message length might be 64 KB 🧚 That's still a pretty big packet size, so a TEAP implementation MUST provide its own support for fragmentation and reassembly ✨ For more on this, check out Section 3.1 of [RFC3748] (it talks about figuring out the MTU usable by EAP) and Section 4.3 (it covers retransmissions in EAP) 📚

Since EAP is a lock-step protocol, fragmentation support can be added in a simple way 💖 In EAP, fragments that get lost or damaged in transit will be retransmitted, and because the Identifier field in EAP gives you the sequencing info, there's no need for a fragment offset field. Iconic, no notes 🦋

TEAP fragmentation support comes from adding flag bits to the EAP-Response and EAP-Request packets, plus a Message Length field that's four octets long 🌈 The flags are the Length included (L), More fragments (M), and TEAP Start (S) bits. The L flag says the four-octet Message Length field is present, and it MUST be set for the first fragment of a fragmented TLS message or set of messages. It MUST NOT be present for any other message. The M flag gets set on all but the last fragment. The S flag only gets set in the TEAP start message that goes from the EAP server to the peer. And the Message Length field gives the total length of the message that might be fragmented over the data fields of multiple packets, which makes buffer allocation way easier 🧺

Now the ACK dance 💃 When a TEAP peer gets an EAP-Request with the M bit set, it MUST respond with an EAP-Response with EAP Type of TEAP and no data. That's the fragment ACK. The EAP server MUST wait until it gets that EAP-Response before it sends another fragment. To keep fragment processing from going sideways, the EAP server MUST increment the Identifier field for each fragment inside an EAP-Request, and the peer MUST include that Identifier value in the fragment ACK inside its EAP-Response. Retransmitted fragments keep the same Identifier value 🔁

It's the mirror image in the other direction. When the TEAP server gets an EAP-Response with the M bit set, it responds with an EAP-Request with EAP Type of TEAP and no data, which is its fragment ACK. The EAP peer MUST wait until it gets that EAP-Request before sending another fragment. And to avoid processing errors, the EAP server MUST increment the Identifier value for each fragment ACK inside an EAP-Request, while the peer MUST include that Identifier value in the next fragment inside an EAP-Response. Ping-pong, but make it protocol 🏓


3.8. Peer Services 🌸

A bunch of TEAP services depend on the peer trusting the TEAP server, like server unauthenticated provisioning, PAC provisioning, certificate provisioning, and channel binding 🔐 So peers MUST authenticate the server before any of these peer services get used. TEAP peer implementations MUST have a configuration where authentication fails if server authentication can't be achieved. In lots of cases the server will also want to authenticate the peer before giving out these services, so it's a two-way street 🫶

TEAP peers MUST track whether or not server authentication has taken place 👀 Server authentication happens if the peer trusts the server certificate it gets. Usually that means validating the certificate against a trust anchor AND confirming that the entity named in the certificate is the intended server. Server authentication also happens when the procedures in Section 3.2 are used to resume a session where the peer and server were already mutually authenticated 🔄 Another route: peer services can be used if an inner EAP method gives mutual authentication and an Extended Master Session Key (EMSK), AND the cryptographic binding with the EMSK Compound Message Authentication Code (MAC) gets correctly validated (Section 4.2.13). There's more on this in Section 3.8.3 ✨

Here's a plot twist 🎭 A tunnel method can authenticate multiple parties, like both the peer machine and the peer user to the EAP server. Depending on how the authentication is done, only some of those parties might have confidence in it. For example, if a strong shared secret is used to mutually authenticate the user and the EAP server, the machine might not be confident that the EAP server is the party it's talking to, especially if the machine can't trust the user not to leak the shared secret to an attacker 😱 So when you're deciding whether to use peer services, you need to think about which parties actually took part in the authentication 🧐

3.8.1. PAC Provisioning 🧸

To request PAC provisioning, a peer sends a PAC TLV as defined in Section 4.2.12, containing a PAC Attribute (see Section 4.2.12.1) with its PAC-Type set to the right value. The peer MUST successfully authenticate the EAP server and validate the Crypto-Binding TLV as defined in Section 4.2.13 before it makes the request 🙌 It MUST send separate PAC TLVs for each type of PAC it wants provisioned. You can put multiple PAC TLVs in the same packet or spread them across different packets. The EAP server sends the PACs once its internal policy is satisfied, but it MAY ignore the request, or it MAY request additional authentications if its policy calls for that. The server MAY also cache the request and provision the requested PACs after all its internal policies are satisfied 💫 If a peer gets a PAC with an unknown type, it MUST ignore it.

A PAC TLV containing a PAC-Acknowledge attribute MUST be sent by the peer to acknowledge receipt of the Tunnel PAC 🎀 But a PAC TLV with a PAC-Acknowledge attribute MUST NOT be used by the peer to acknowledge other types of PACs. Lastly, if the peer gets a PAC TLV with an unknown attribute, it SHOULD ignore that unknown attribute 🌈

3.8.2. Certificate Provisioning within the Tunnel 📜

Certificate provisioning for a peer is supported in TEAP by running the Simple PKI Request/Response from [RFC5272], using PKCS#10 and PKCS#7 TLVs respectively 🦋 The peer sends the Simple PKI Request as a PKCS#10 CertificateRequest [RFC2986] encoded into the body of a PKCS#10 TLV (see Section 4.2.17). The TEAP server issues the Simple PKI Response as a PKCS#7 [RFC2315] degenerate "Certificates Only" message encoded into the body of a PKCS#7 TLV (see Section 4.2.16). It only does this after an authentication method has run and provided an identity proof on the peer, before a certificate gets issued 🔥

Now, to link identity and proof-of-possession, the signed certification request should include info specific to the current authenticated TLS session 🔗 So the peer generating the request SHOULD get the tls-unique value from the TLS subsystem, as defined in "Channel Bindings for TLS" [RFC5929]. Everything between grabbing the tls_unique value, generating the Certification Signing Request (CSR) that contains the current tls_unique value, and the TEAP server verifying it later are the "phases of the application protocol during which application-layer authentication occurs". Those phases are protected by the synchronization interoperability mechanism from the interoperability note in "Channel Bindings for TLS" ([RFC5929], Section 3.1) 🧠 And when renegotiation happens, TLS "secure_renegotiation" [RFC5746] MUST be used 🙏

The tls-unique value gets base-64-encoded as specified in Section 4 of [RFC4648], and the resulting string goes in the certification request challengePassword field ([RFC2985], Section 5.4.1). That challengePassword field is limited to 255 octets (Section 7.4.9 of [RFC5246] says no existing ciphersuite would run into an issue with this limit) 📏 If tls-unique info isn't embedded in the certification request, the challengePassword field MUST be empty, which tells the server the peer didn't include the optional channel-binding info (any value submitted gets verified by the server as tls-unique info) 🙈

The server SHOULD verify the tls-unique information 🔍 That makes sure the authenticated TEAP peer actually has the private key used to sign the certification request. Periodt 💅

The Simple PKI Request/Response generation and processing rules of [RFC5272] SHALL apply to TEAP, except for error conditions. If there's an error, the TEAP server SHOULD respond with an Error TLV using the most descriptive error code possible, but it MAY ignore the PKCS#10 request that caused the error 💖

3.8.3. Server Unauthenticated Provisioning Mode 🦋

okay so in Server Unauthenticated Provisioning Mode, an unauthenticated tunnel gets set up in Phase 1 🫶. Then the peer and server agree on an EAP method in Phase 2 that does mutual authentication and key derivation, and that holds up against attacks like man-in-the-middle and dictionary attacks 🔥. Why does this matter? It lets peers get bootstrapped even when they can't authenticate the server during Phase 1 😭. That covers two situations: the negotiated ciphersuite doesn't provide any authentication at all, OR it does but the peer just can't validate the server's identity for some reason 💀

Once the EAP method finishes successfully in Phase 2, the peer and server swap a Crypto-Binding TLV. This ties the inner method to the outer tunnel and makes sure nobody sneaky ran a man-in-the-middle attack 👀✨

Supporting this mode is optional, so it's not a must-have, bestie 💅. TLS_DH_anon_WITH_AES_128_CBC_SHA is RECOMMENDED when you use this mode, but other anonymous ciphersuites MAY be supported too, as long as the TLS pre-master secret is generated from contribution from both peers 🌸. The Phase 2 EAP methods used in this mode MUST provide mutual authentication, provide key generation, and be resistant to dictionary attack 🔐. Example inner methods are EAP-pwd [RFC5931] and EAP-EKE [RFC6124] 🧚.

3.8.4. Channel Binding 🎀

[RFC6677] defines EAP channel bindings to solve the "lying NAS" and "lying provider" problems 🕵️‍♀️. The way it works: the EAP peer shares info about the characteristics of the service the authenticator provides with the Authentication, Authorization, and Accounting (AAA) server, and that info stays protected inside the EAP method. This lets the server check that the authenticator is telling the peer the same thing it got from the authenticator itself, plus what it already has stored about that authenticator. Iconic accountability 💅.

TEAP supports EAP channel binding using the Channel-Binding TLV defined in Section 4.2.7 🦋. If the TEAP server wants the channel-binding info from the peer, it sends an empty Channel-Binding TLV to say "hey, send me that." The peer answers with a Channel-Binding TLV holding a channel-binding message as defined in [RFC6677]. The server validates that message and sends back a Channel-Binding TLV with a result code ✅. If the server didn't start the request but the peer still wants to send channel-binding info, the peer can do it by using the Request-Action TLV along with the Channel-Binding TLV 🙌. One rule here, and it's a big one: the peer MUST only send channel-binding information after it has successfully authenticated the server and established the protected tunnel 🔒.


4. Message Formats ✨

The following sections describe the message formats used in TEAP 🍓. The fields are transmitted from left to right, in network byte order.

4.1. TEAP Message Format 💌

Here's a summary of the TEAP Request/Response packet format 👀:

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Code      |   Identifier  |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |     Type      |   Flags | Ver |        Message Length         :
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :         Message Length        |         Outer TLV Length
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   :     Outer TLV Length          |         TLS Data...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |       Outer TLVs...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Code 🧚

The Code field is one octet in length and is defined as follows:

  • 1 Request
  • 2 Response

Identifier 🔢

The Identifier field is one octet and helps match responses with requests. The Identifier field MUST be changed on each Request packet 🔄. The Identifier field in the Response packet MUST match the Identifier field from the corresponding request 🎯.

Length 📏

The Length field is two octets and tells you the length of the EAP packet, including the Code, Identifier, Length, Type, Flags, Ver, Message Length, TLS Data, and Outer TLVs fields. Octets outside the range of the Length field should be treated as Data Link Layer padding and should be ignored on reception 🫧.

Type 🏷️

55 for TEAP 💜

Flags 🚩

    0 1 2 3 4
   +-+-+-+-+-+
   |L M S O R|
   +-+-+-+-+-+
  • L Length included: set to indicate the presence of the four-octet Message Length field. It MUST be present for the first fragment of a fragmented message. It MUST NOT be present for any other message 🚫.
  • M More fragments: set on all but the last fragment 📦.
  • S TEAP start: set in a TEAP Start message sent from the server to the peer 🚀.
  • O Outer TLV length included: set to indicate the presence of the four-octet Outer TLV Length field. It MUST be present only in the initial request and response messages. If the initial message is fragmented, then it MUST be present only on the first fragment 🧩.
  • R Reserved (MUST be zero and ignored upon receipt) 🤫.

Ver 🎀

This field contains the version of the protocol. This document describes version 1 (001 in binary) of TEAP ✨.

Message Length 📨

The Message Length field is four octets and is present only if the L bit is set. It gives the total length of the message, which may be fragmented over the data fields of multiple packets 🧵.

Outer TLV Length 🌈

The Outer TLV Length field is four octets and is present only if the O bit is set. It gives the total length of the Outer TLVs, if present 💖.

TLS Data 🔐

When the TLS Data field is present, it holds an encapsulated TLS packet in TLS record format. A TEAP packet with Flags and Version fields, but with a zero length TLS Data field, is used to indicate TEAP acknowledgement for either a fragmented message, a TLS Alert message, or a TLS Finished message 🫶.

Outer TLVs 🍬

The Outer TLVs hold the optional data used to help establish the TLS tunnel, in TLV format. They are only allowed in the first two messages in the TEAP protocol. That's the first EAP-server-to-peer message and the first peer-to-EAP-server message 🥇. The start of the Outer TLVs can be derived from the EAP Length field and the Outer TLV Length field 🧮.

4.2. TEAP TLV Format and Support 🧸

The TLVs defined here are TLV objects. TLV objects can carry arbitrary parameters between an EAP peer and EAP server, inside the protected TLS tunnel 🔒.

The EAP peer may not implement every TLV the EAP server supports 🤷‍♀️. For interoperability, TLVs are designed so an EAP server can find out whether the EAP peer supports a TLV, using the NAK TLV. The mandatory bit in a TLV says whether support for that TLV is required. If the peer or server doesn't support a TLV marked mandatory, it MUST send a NAK TLV in the response, and all the other TLVs in the message MUST be ignored 🚨. If an EAP peer or server finds an unsupported TLV marked as optional, it can ignore that TLV. It MUST NOT send a NAK TLV for a TLV that is not marked mandatory 🙅‍♀️. If all TLVs in a message are marked optional and none are understood by the peer, then a NAK TLV or Result TLV could be sent to the other side to keep the conversation going 💬.

Heads up: a peer or server may support a TLV with the mandatory bit set but still not understand its contents 👀. The appropriate response to a supported TLV with content it doesn't understand is defined by the individual TLV specification 📜.

EAP implementations compliant with this specification MUST support TLV exchanges, as well as the processing of mandatory/optional settings on the TLV 🧠. Implementations conforming to this specification MUST support the following TLVs 💅:

  • Authority-ID TLV
  • Identity-Type TLV
  • Result TLV
  • NAK TLV
  • Error TLV
  • Request-Action TLV
  • EAP-Payload TLV
  • Intermediate-Result TLV
  • Crypto-Binding TLV
  • Basic-Password-Auth-Req TLV
  • Basic-Password-Auth-Resp TLV

4.2.1. General TLV Format 🌷

TLVs are defined as described below. The fields are transmitted from left to right 👉.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|            TLV Type       |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                              Value...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M 0 Optional TLV 🫧
  • M 1 Mandatory TLV 🔥
  • R Reserved, set to zero (0) 🤫

TLV Type is a 14-bit field denoting the TLV type. Allocated types include:

0  Unassigned
1  Authority-ID TLV (Section 4.2.2)
2  Identity-Type TLV (Section 4.2.3)
3  Result TLV (Section 4.2.4)
4  NAK TLV (Section 4.2.5)
5  Error TLV (Section 4.2.6)
6  Channel-Binding TLV (Section 4.2.7)
7  Vendor-Specific TLV (Section 4.2.8)
8  Request-Action TLV (Section 4.2.9)
9  EAP-Payload TLV (Section 4.2.10)
10 Intermediate-Result TLV (Section 4.2.11)
11 PAC TLV (Section 4.2.12)
12 Crypto-Binding TLV (Section 4.2.13)
13 Basic-Password-Auth-Req TLV (Section 4.2.14)
14 Basic-Password-Auth-Resp TLV (Section 4.2.15)
15 PKCS#7 TLV (Section 4.2.16)
16 PKCS#10 TLV (Section 4.2.17)
17 Trusted-Server-Root TLV (Section 4.2.18)

Length is the length of the Value field in octets 📐. Value is the value of the TLV 💝.

4.2.2. Authority-ID TLV 🪪

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                              ID...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M Mandatory, set to one (1) 🔥
  • R Reserved, set to zero (0) 🤫
  • TLV Type 1 - Authority-ID 🏷️
  • Length The Length field is two octets and contains the length of the ID field in octets 📏.
  • ID A hint of the identity of the server, to help the peer match the credentials available for the server 🗝️. It should be unique across the deployment 💫.

4.2.3. Identity-Type TLV 🎀

okay so the Identity-Type TLV lets an EAP server drop a little hint so the EAP peer can pick the right kind of identity, like user or machine 🧚. TEAPv1 implementations MUST support this TLV. Only one Identity-Type TLV SHOULD be present in the TEAP request or response packet. The Identity-Type TLV request MUST come with an EAP-Payload TLV or Basic-Password-Auth-Req TLV. If the EAP peer does have an identity matching the requested type, then the peer SHOULD respond with an Identity-Type TLV carrying that requested type ✨. If the Identity-Type field doesn't contain one of the known values, or the EAP peer doesn't have an identity for the requested type, then the peer SHOULD respond with an Identity-Type TLV holding one of the identity types it has available 💅. If the server gets an identity type in the response that doesn't match the one it asked for, then the peer doesn't have the requested credential type. In that case the server SHOULD either proceed with authentication for the credential type the peer proposed, proceed by requesting another credential type, or just apply network policy based on the configured policy (like sending a Result TLV with Failure) 💀.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |         Identity-Type         |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M: 0 (Optional)
  • R: Reserved, set to zero (0)
  • TLV Type: 2 - Identity-Type TLV
  • Length: 2
  • Identity-Type: The Identity-Type field is two octets. Values include:
    • 1 User
    • 2 Machine

4.2.4. Result TLV 🦋

the Result TLV gives us acknowledged success and failure messages for protected termination inside TEAP, no cap 🫶. If the Status field doesn't contain one of the known values, then the peer or EAP server MUST treat this as a fatal error of Unexpected TLVs Exchanged. The behavior of the Result TLV is discussed further in Sections 3.3.3 and 3.6.3. A Result TLV indicating failure MUST NOT be accompanied by the following TLVs: NAK, EAP-Payload TLV, or Crypto-Binding TLV 🙅‍♀️.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |             Status            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M: Mandatory, set to one (1)
  • R: Reserved, set to zero (0)
  • TLV Type: 3 - Result TLV
  • Length: 2
  • Status: The Status field is two octets. Values include:
    • 1 Success
    • 2 Failure

4.2.5. NAK TLV 🙈

the NAK TLV lets a peer detect TLVs that aren't supported by the other peer 🔍. A TEAP packet can contain 0 or more NAK TLVs. A NAK TLV should not be accompanied by other TLVs. A NAK TLV MUST NOT be sent in response to a message containing a Result TLV. Instead, a Result TLV of failure should be sent to indicate failure, along with an Error TLV of Unexpected TLVs Exchanged.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                          Vendor-Id                            |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            NAK-Type           |           TLVs...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M: Mandatory, set to one (1)
  • R: Reserved, set to zero (0)
  • TLV Type: 4 - NAK TLV
  • Length: >=6
  • Vendor-Id: The Vendor-Id field is four octets and contains the Vendor-Id of the TLV that was not supported. The high-order octet is 0, and the low-order three octets are the Structure of Management Information (SMI) Network Management Private Enterprise Number of the Vendor in network byte order. The Vendor-Id field MUST be zero for TLVs that are not Vendor-Specific TLVs.
  • NAK-Type: The NAK-Type field is two octets. The field contains the type of the TLV that was not supported. A TLV of this type MUST have been included in the previous packet.
  • TLVs: This field contains a list of zero or more TLVs, each of which MUST NOT have the mandatory bit set. These optional TLVs are for future extensibility, to communicate why the offending TLV was determined to be unsupported.

4.2.6. Error TLV 💖

the Error TLV lets an EAP peer or server tell the other party about errors 🚨. A TEAP packet can contain 0 or more Error TLVs. The Error-Code field describes the type of error. Error codes 1-999 represent successful outcomes (informative messages), 1000-1999 represent warnings, and 2000-2999 represent fatal errors. A fatal Error TLV MUST be accompanied by a Result TLV indicating failure, and the conversation is terminated as described in Section 3.6.3.

Lots of the error codes below refer to errors in inner method processing, which may be retrieved if the inner method makes them available. Implementations MUST take care that error messages do not reveal too much information to an attacker. For example, using error message 1031 (User account credentials incorrect) is NOT RECOMMENDED, because it lets an attacker determine valid usernames by differentiating this response from other responses. It should only be used for troubleshooting purposes.

🚨 Security alert: error messages can leak info to attackers, so be careful about what you send back, bestie. Error 1031 is the big one to avoid outside of troubleshooting. 🙈
    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                           Error-Code                          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M: Mandatory, set to one (1)
  • R: Reserved, set to zero (0)
  • TLV Type: 5 - Error TLV
  • Length: 4
  • Error-Code: The Error-Code field is four octets. Currently defined values for Error-Code include:
1     User account expires soon

2     User account credential expires soon

3     User account authorizations change soon

4     Clock skew detected

5     Contact administrator

6     User account credentials change required

1001  Inner Method Error

1002  Unspecified authentication infrastructure problem

1003  Unspecified authentication failure

1004  Unspecified authorization failure

1005  User account credentials unavailable

1006  User account expired

1007  User account locked: try again later

1008  User account locked: admin intervention required
1009  Authentication infrastructure unavailable

1010  Authentication infrastructure not trusted

1011  Clock skew too great

1012  Invalid inner realm

1013  Token out of sync: administrator intervention required

1014  Token out of sync: PIN change required

1015  Token revoked

1016  Tokens exhausted

1017  Challenge expired

1018  Challenge algorithm mismatch

1019  Client certificate not supplied

1020  Client certificate rejected

1021  Realm mismatch between inner and outer identity

1022  Unsupported Algorithm In Certificate Signing Request

1023  Unsupported Extension In Certificate Signing Request

1024  Bad Identity In Certificate Signing Request

1025  Bad Certificate Signing Request

1026  Internal CA Error

1027  General PKI Error

1028  Inner method's channel-binding data required but not
      supplied

1029  Inner method's channel-binding data did not include required
      information

1030  Inner method's channel binding failed

1031  User account credentials incorrect [USAGE NOT RECOMMENDED]
2001  Tunnel Compromise Error

2002  Unexpected TLVs Exchanged

4.2.7. Channel-Binding TLV 🌈

the Channel-Binding TLV is the mechanism for carrying channel-binding data from the peer to the EAP server, and a channel-binding response from the EAP server back to the peer, as described in [RFC6677] 🦋. TEAPv1 implementations MAY support this TLV, and it cannot be responded to with a NAK TLV. If the Channel-Binding data field does not contain one of the known values, or if the EAP server does not support this TLV, then the server MUST ignore the value.

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |            Data ...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • M: 0 (Optional)
  • R: Reserved, set to zero (0)
  • TLV Type: 6 - Channel-Binding TLV
  • Length: variable
  • Data: The data field contains a channel-binding message as defined in Section 5.3 of [RFC6677].

4.2.8. Vendor-Specific TLV ✨

okay so the Vendor-Specific TLV is basically the VIP room 🎀 for vendors who want their own extended attributes that aren't really meant for everyone. one Vendor-Specific TLV can hold one or more TLVs, called Vendor TLVs. each Vendor TLV's type is up to the vendor, and every Vendor TLV inside a single Vendor-Specific TLV belongs to the same vendor. you can have several Vendor-Specific TLVs from different vendors in one message, no problem 💅. error handling inside a Vendor TLV can use the vendor's own error-handling mechanism, or the standard TEAP error codes, whichever they like 🧚

Vendor TLVs can be optional or mandatory. Vendor TLVs sent with Result TLVs MUST be marked as optional 🫶. if the Vendor-Specific TLV is marked as mandatory, the receiving side is expected to recognize the vendor ID, parse all the Vendor TLVs inside, and handle errors within the Vendor-Specific TLV the way the vendor defined 🔥

here's the layout:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          Vendor-Id                            |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                         Vendor TLVs....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M is 0 or 1, so it can be either. R is reserved and set to zero (0) 💜. the TLV Type is 7, which means Vendor-Specific TLV 🌸. the Length is 4 + cumulative length of all included Vendor TLVs, so you add up everything inside and then add 4 for the Vendor-Id 🍓

the Vendor-Id is four octets. the high-order octet is 0, and the low-order 3 octets are the SMI Network Management Private Enterprise Number of the Vendor, in network byte order. so it's the vendor's enterprise number, neat 🦋

Vendor TLVs is indefinite length and holds the Vendor-Specific TLVs, in whatever format the vendor defined ✨

4.2.9. Request-Action TLV ✨

the Request-Action TLV MAY be sent by both the peer and the server in response to a successful or failed Result TLV 🫶. it's how one side asks the other to negotiate more EAP methods or process TLVs that are in the response packet. the receiving side MUST process this TLV 💖. here's how processing goes:

  • the receiving entity MAY choose to process any of the TLVs included in the message.
  • if the receiving entity chooses not to process any TLV in the list, it sends back a Result TLV with the same code in the Status field of the Request-Action TLV 💀
  • if there are multiple Request-Action TLVs in the request, the session can continue if any of the TLVs in any Request-Action TLV get processed ⭐
  • if there are multiple Request-Action TLVs and none of them get processed, then the most fatal status should be used in the Result TLV returned. if a status code in the Request-Action TLV isn't understood by the receiving entity, it should be treated as a fatal error 😭
  • after processing the TLVs or EAP method in the request, another round of Result TLV exchange happens to sync the final status on both sides 🔥

the peer or the server MAY send multiple Request-Action TLVs to the other side. two Request-Action TLVs MUST NOT occur in the same TEAP packet if they have the same Status value 🙈. the order of processing multiple Request-Action TLVs is up to the implementation. if the receiving side handles the optional (non-fatal) items first, the fatal items might vanish later on. if it handles the fatal items first, the communication time will be shorter 🏃‍♀️

the peer or the server MAY return a new set of Request-Action TLVs after one or more of the requested items has been processed and the other side has signaled that it wants to end the EAP conversation 🌈

the layout:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Status   |      Action    |                TLVs....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+-+-+-+-+-+-+-+-+-+-+-+-

M is Mandatory, set to one (1). R is reserved and set to zero (0). the TLV Type is 8, for Request-Action TLV. the Length is 2 + cumulative length of all included TLVs 🎀

the Status field is one octet, and it shows the result if the server doesn't process the action the peer asked for. the values are:

1  Success
2  Failure

the Action field is one octet. the values are:

1  Process-TLV
2  Negotiate-EAP

TLVs is indefinite length and holds the TLVs the peer wants the server to process 💅

4.2.10. EAP-Payload TLV ✨

so to piggyback an EAP request or response along with other TLVs, there's the EAP-Payload TLV 🦋. it carries an encapsulated EAP packet plus a list of optional TLVs. those optional TLVs are there for future extensibility, to give hints about the current EAP authentication. only one EAP-Payload TLV is allowed in a message 🫶

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                          EAP packet...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                             TLVs...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M is Mandatory, set to one (1). R is reserved and set to zero (0). the TLV Type is 9, for EAP-Payload TLV. the Length is length of embedded EAP packet + cumulative length of additional TLVs 🌸

the EAP packet field has a complete EAP packet, including the EAP header (Code, Identifier, Length, Type) fields. its length comes from the Length field of the encapsulated EAP packet ✨

TLVs is an optional field holding a list of TLVs linked to the EAP packet field. the TLVs MUST NOT have the mandatory bit set 💀. the total length of this field equals the Length field of the EAP-Payload TLV, minus the Length field in the EAP header of the EAP packet field 🍓

4.2.11. Intermediate-Result TLV ✨

the Intermediate-Result TLV gives you acknowledged intermediate Success and Failure messages between multiple inner EAP methods inside EAP 👑. an Intermediate-Result TLV that indicates success MUST be accompanied by a Crypto-Binding TLV 🔥. its optional associated TLVs are for future extensibility too, to hint at the current result 🧚

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|             Status            |        TLVs...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M is Mandatory, set to one (1). R is reserved and set to zero (0). the TLV Type is 10, for Intermediate-Result TLV. the Length is 2 + cumulative length of the embedded associated TLVs 🦋

the Status field is two octets. the values are:

1  Success
2  Failure

TLVs is indeterminate length and holds zero or more of the TLVs tied to the Intermediate Result TLV. the TLVs in this field MUST NOT have the mandatory bit set 🙈

4.2.12. PAC TLV Format ✨

the PAC TLV is how you provision the Protected Access Credential (PAC) 🔐. it carries the PAC and its related info inside PAC attribute fields. the PAC TLV MAY also be used by the peer to request provisioning of a PAC of the type named in the PAC-Type PAC attribute 🌈. the PAC TLV MUST only be used in a protected tunnel that provides encryption and integrity protection 💖. the general format looks like this:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        PAC Attributes...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M is 0 or 1. R is reserved and set to zero (0). the TLV Type is 11, for PAC TLV. the Length is two octets holding the length of the PAC Attributes field in octets. PAC Attributes is a list of PAC attributes in TLV format 🍓

4.2.12.1. Formats for PAC Attributes ✨

each PAC attribute inside a PAC TLV is formatted as a TLV like this:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              Value...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

the Type field is two octets and denotes the attribute type. the allocated types are:

1 - PAC-Key
2 - PAC-Opaque
3 - PAC-Lifetime
4 - A-ID
5 - I-ID
6 - Reserved
7 - A-ID-Info
8 - PAC-Acknowledgement
9 - PAC-Info
10 - PAC-Type

the Length is two octets containing the length of the Value field in octets 💅

the Value is the value of the PAC attribute 🌸

4.2.12.2. PAC-Key 🔑

okay so the PAC-Key is a secret key that gets handed out inside a PAC attribute of type PAC-Key 💖 The server includes it in the PAC TLV whenever it wants to issue or renew a PAC that's bound to a key (like a Tunnel PAC) 🎀 It's a randomly generated octet string that's 48 octets long ✨ And the issuer of the credential is the one who makes this key, which the Authority Identifier (A-ID) tells you 🦋

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
~                              Key                              ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type 🌸 1 - PAC-Key

Length 🌸 2-octet length indicating the length of the key.

Key 🌸 The value of the PAC-Key.

4.2.12.3. PAC-Opaque 🧚

the PAC-Opaque attribute gets included in the PAC TLV whenever the server wants to issue or renew a PAC 💅

the PAC-Opaque is opaque to the peer, which means the peer MUST NOT attempt to interpret it 🙈 the peer just stores whatever it got and sends it back to the server according to its PAC-Type 💜 The Tunnel PAC gets used in the ClientHello SessionTicket extension field defined in [RFC5077] 🫶 If a peer has opaque data from multiple servers, it stores each server's data separately, keyed by the A-ID 🍓 That's what lets the peer treat each opaque datum as its own independent PAC pairing, with a PAC-Key mapping to a PAC-Opaque identified by the A-ID ✨ There's a one-to-one correspondence between the PAC-Key and the PAC-Opaque, so the peer figures out which pair to use by matching the A-ID from the TEAP/Start message with the A-ID from the PAC-Info it got when it was provisioned with a PAC-Opaque 👑

the PAC-Opaque attribute format looks like this:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                              Value ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type 🌸 2 - PAC-Opaque

Length 🌸 The Length field is two octets, which contains the length of the Value field in octets.

Value 🌸 The Value field contains the actual data for the PAC-Opaque. It is specific to the server implementation.

4.2.12.4. PAC-Info 📋

the PAC-Info is made up of a set of PAC attributes, the ones defined in Section 4.2.12.1 🎀 The PAC-Info attribute MUST contain the A-ID, A-ID-Info, and PAC-Type attributes 💅 Other attributes MAY be included in the PAC-Info to give the peer more info ✨ But the PAC-Info attribute MUST NOT contain the PAC-Key, PAC-Acknowledgement, PAC-Info, or PAC-Opaque attributes 🙅‍♀️ It gets included in the PAC TLV whenever the server wants to issue or renew a PAC 🦋

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           Attributes...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type 🌸 9 - PAC-Info

Length 🌸 2-octet field containing the length of the Attributes field in octets.

Attributes 🌸 The Attributes field contains a list of PAC attributes. Each mandatory and optional field type is defined as follows:

3 - PAC-Lifetime 🕰️ This is a 4-octet quantity representing the expiration time of the credential, expressed as the number of seconds, excluding leap seconds, after midnight UTC, January 1, 1970. This attribute MAY be provided to the peer as part of the PAC-Info.

4 - A-ID 🆔 The A-ID is the identity of the authority that issued the PAC. It's meant to be unique across all issuing servers so there are no namespace collisions 💖 The peer uses the A-ID to figure out which PAC to use. The A-ID is treated as an opaque octet string. This attribute MUST be included in the PAC-Info attribute. The A-ID MUST match the Authority-ID the server used to establish the tunnel. One way to generate the A-ID is to use a high-quality random number generator to produce a random number. An alternate method is to take the hash of the public key or public key certificate belonging to a server represented by the A-ID.

5 - I-ID 🪪 Initiator Identifier (I-ID) is the peer identity associated with the credential. This identity is derived from the inner authentication, or from the client-side authentication during tunnel establishment if inner authentication isn't used. The server uses the I-ID in the TEAP Phase 2 conversation to check that the same peer identity used in TEAP Phase 1 is also used in at least one inner authentication in TEAP Phase 2 🫶 If the server is enforcing I-ID validation on the inner authentication, then the I-ID MUST be included in the PAC-Info, so the peer can also enforce a unique PAC for each unique user 👑 If the I-ID is missing from the PAC-Info, it's assumed that the Tunnel PAC can be used for multiple users, and the peer won't enforce the unique-Tunnel-PAC-per-user policy.

7 - A-ID-Info 🏷️ Authority Identifier Information is meant to give the A-ID a user-friendly name. It may contain the enterprise name and server name in a human-readable format. This TLV helps the peer tell the end user more about the A-ID 🌈 The name is encoded in UTF-8 [RFC3629] format. This attribute MUST be included in the PAC-Info.

10 - PAC-Type 🎟️ The PAC-Type is meant to give the type of PAC. This attribute SHOULD be included in the PAC-Info. If the PAC-Type isn't present, it defaults to a Tunnel PAC (Type 1) 💜

4.2.12.5. PAC-Acknowledgement TLV 🥂

the PAC-Acknowledgement is used to acknowledge that the peer received the Tunnel PAC 🎉 The peer includes the PAC-Acknowledgement TLV in a PAC TLV sent to the server to show the result of processing and storing a newly provisioned Tunnel PAC. This TLV is only used when a Tunnel PAC is provisioned 🫧

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Result             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type 🌸 8 - PAC-Acknowledgement

Length 🌸 The length of this field is two octets containing a value of 2.

Result 🌸 The resulting value MUST be one of the following:

  • 1 - Success
  • 2 - Failure

4.2.12.6. PAC-Type TLV 🎀

the PAC-Type TLV is meant to specify the PAC-Type 💖 It's included in a PAC TLV sent by the peer to request PAC provisioning from the server. Here's the format:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            Type               |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|         PAC-Type              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Type 🌸 10 - PAC-Type

Length 🌸 2-octet field with a value of 2.

PAC-Type 🌸 This 2-octet field defines the type of PAC being requested or provisioned. The following values are defined:

  • 1 - Tunnel PAC

4.2.13. Crypto-Binding TLV ✨

okay so the Crypto-Binding TLV is the proof that both the peer AND the server showed up to the tunnel setup and the whole sequence of authentications 🎀. it also double-checks the TEAP type, the version that got negotiated, and the Outer TLVs that got swapped before the TLS tunnel even existed 💅

The Crypto-Binding TLV MUST be exchanged and verified before the final Result TLV exchange, regardless of whether there is an inner EAP method authentication or not. It MUST be included with the Intermediate-Result TLV to perform cryptographic binding after each successful EAP method in a sequence of EAP methods, before proceeding with another inner EAP method. The Crypto-Binding TLV is valid only if the following checks pass:

  • The Crypto-Binding TLV version is supported.
  • The MAC verifies correctly.
  • The received version in the Crypto-Binding TLV matches the version sent by the receiver during the EAP version negotiation.
  • The subtype is set to the correct value.

If any of the above checks fails, then the TLV is invalid. An invalid Crypto-Binding TLV is a fatal error and is handled as described in Section 3.6.3 💀

The Crypto-Binding TLV is defined as follows:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|    Reserved   |    Version    |  Received Ver.| Flags|Sub-Type|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
~                             Nonce                             ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
~                   EMSK Compound MAC                           ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                                               |
~                    MSK Compound MAC                           ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M

Mandatory, set to one (1)

R

Reserved, set to zero (0)

TLV Type

12 - Crypto-Binding TLV

Length

76

Reserved

Reserved, set to zero (0)

Version

The Version field is a single octet, which is set to the version of Crypto-Binding TLV the TEAP method is using. For an implementation compliant with this version of TEAP, the version number MUST be set to one (1).

Received Ver

The Received Ver field is a single octet and MUST be set to the TEAP version number received during version negotiation. Note that this field only provides protection against downgrade attacks, where a version of EAP requiring support for this TLV is required on both sides. 🛡️

Flags

The Flags field is four bits. Defined values include:

  • 1 EMSK Compound MAC is present
  • 2 MSK Compound MAC is present
  • 3 Both EMSK and MSK Compound MAC are present

Sub-Type

The Sub-Type field is four bits. Defined values include:

  • 0 Binding Request
  • 1 Binding Response

Nonce

The Nonce field is 32 octets. It contains a 256-bit nonce that is temporally unique, used for Compound MAC key derivation at each end. The nonce in a request MUST have its least significant bit set to zero (0), and the nonce in a response MUST have the same value as the request nonce except the least significant bit MUST be set to one (1). 🔑

EMSK Compound MAC

The EMSK Compound MAC field is 20 octets. This can be the Server MAC (B1_MAC) or the Client MAC (B2_MAC). The computation of the MAC is described in Section 5.3.

MSK Compound MAC

The MSK Compound MAC field is 20 octets. This can be the Server MAC (B1_MAC) or the Client MAC (B2_MAC). The computation of the MAC is described in Section 5.3.


4.2.14. Basic-Password-Auth-Req TLV 🔐

okay so the Basic-Password-Auth-Req TLV is how the authentication server asks the peer for a username and password 🙋‍♀️. it can carry an optional user prompt message along for the ask. the peer is expected to gather the username and password and send them back in a Basic-Password-Auth-Resp TLV.

The Basic-Password-Auth-Req TLV is defined as follows:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Prompt ....
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M

0 (Optional)

R

Reserved, set to zero (0)

TLV Type

13 - Basic-Password-Auth-Req TLV

Length

variable

Prompt

optional user prompt message in UTF-8 [RFC3629] format


4.2.15. Basic-Password-Auth-Resp TLV 🎀

okay this one is the reply 💌. the peer uses the Basic-Password-Auth-Resp TLV to answer a Basic-Password-Auth-Req TLV, and it carries a username and password. both are in UTF-8 [RFC3629] format.

The Basic-Password-Auth-Resp TLV is defined as follows:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Userlen     |             Username
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      ...     Username    ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|   Passlen     |             Password
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      ...     Password    ...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

M

0 (Optional)

R

Reserved, set to zero (0)

TLV Type

14 - Basic-Password-Auth-Resp TLV

Length

variable

Userlen

Length of Username field in octets

Username

Username in UTF-8 [RFC3629] format

Passlen

Length of Password field in octets

Password

Password in UTF-8 [RFC3629] format


4.2.16. PKCS#7 TLV 📜

okay so the PKCS#7 TLV is how the EAP server slides certificate(s) over to the peer 💅. the format holds a certificate or certificate chain in binary DER encoding [X.690], wrapped in a degenerate Certificates Only PKCS#7 SignedData Content as defined in [RFC5652].

When the peer asked for something with a Trusted-Server-Root TLV, the EAP server MUST send the PKCS#7 TLV inside a Trusted-Server-Root TLV. When the peer sent a PKCS#10 certificate enrollment request, the EAP server MUST send the PKCS#7 TLV without a Trusted-Server-Root TLV. The PKCS#7 TLV is always marked as optional, which cannot be responded to with a NAK TLV. TEAP implementations that support the Trusted-Server-Root TLV or the PKCS#10 TLV MUST support this TLV. Peers MUST NOT assume that the certificates in a PKCS#7 TLV are in any order. 🙃

TEAP servers MAY return self-signed certificates. Peers that handle self-signed certificates or trust anchors MUST NOT implicitly trust these certificates merely due to their presence in the certificate bag.

Note: Peers are advised to take great care in deciding whether to use a received certificate as a trust anchor. The authenticated nature of the tunnel in which a PKCS#7 bag is received can provide a level of authenticity to the certificates contained therein. Peers are advised to take into account the implied authority of the EAP server and to constrain the trust it can achieve through the trust anchor received in a PKCS#7 TLV. 🚨

The PKCS#7 TLV is defined as follows:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           PKCS#7 Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

M

0 - Optional TLV

R

Reserved, set to zero (0)

TLV Type

15 - PKCS#7 TLV

Length

The length of the PKCS#7 Data field.

PKCS#7 Data

This field contains the DER-encoded X.509 certificate or certificate chain in a Certificates-Only PKCS#7 SignedData message.


4.2.17. PKCS#10 TLV 🧚

okay last one in this chunk 🥹. the peer uses the PKCS#10 TLV to kick off the "simple PKI" Request/Response from [RFC5272]. the request format follows Section 6.4 of [RFC4945]. it's always marked as optional, which means it cannot be responded to with a NAK TLV.

The PKCS#10 TLV is defined as follows:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|M|R|         TLV Type          |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           PKCS#10 Data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

M

0 - Optional TLV

R

Reserved, set to zero (0)

TLV Type

16 - PKCS#10 TLV

Length

The length of the PKCS#10 Data field.

PKCS#10 Data

This field contains the DER-encoded PKCS#10 certificate request.

4.2.18. Trusted-Server-Root TLV ✨

Okay so the Trusted-Server-Root TLV is how a peer asks for, and gets handed, a trusted server root certificate 🎀 It can show up in regular TEAP authentication mode or in provisioning mode 💖 It's always marked as optional, and it can't be answered with a Negative Acknowledgement (NAK) TLV 🙈 And it MUST only be sent as an Inner TLV (inside the protection of the tunnel) 🔒

Once the peer has decided it successfully authenticated the EAP server and has validated the Crypto-Binding TLV, it MAY send one or more Trusted-Server-Root TLVs (marked as optional) to ask the EAP server for trusted server root certificates 🧚 The EAP server MAY send one or more root certificates packaged in a Public Key Cryptographic System #7 (PKCS#7) TLV inside the Trusted-Server-Root TLV 💅 The EAP server MAY also choose not to honor the request 💀

Basically the Trusted-Server-Root TLV lets the peer ask the EAP server for a list of trusted roots 🌸 The server might answer with one or more root certificates in PKCS#7 [RFC2315] format 🦋

If the EAP server sets the credential format to PKCS#7-Server-Certificate-Root, then the Trusted-Server-Root TLV should contain the root of the certificate chain for the certificate issued to the EAP server, packaged in a PKCS#7 TLV 🫶 If the server certificate is self-signed, then the root is that self-signed certificate 👑

If the Trusted-Server-Root TLV credential format has a value the peer doesn't know, then the EAP peer should ignore the TLV 🙈

The Trusted-Server-Root TLV is laid out like this 🍓

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |M|R|         TLV Type          |            Length             |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Credential-Format   |     Cred TLVs...
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

Here's what each field means:

  • M: 0 means Optional TLV.
  • R: Reserved, set to zero (0).
  • TLV Type: 17 means Trusted-Server-Root TLV.
  • Length: >=2 octets.
  • Credential-Format: This field is two octets. The values include 1, which means PKCS#7-Server-Certificate-Root.
  • Cred TLVs: This field is of indefinite length and holds TLVs tied to the credential format. The peer can leave it empty when it's using this TLV to request server trust roots 💖

4.3. TLV Rules 🎀

To save round trips, you can send multiple TLVs in a single TEAP packet 🚀 But multiple EAP Payload TLVs, multiple Basic Password Authentication TLVs, or an EAP Payload TLV together with a Basic Password Authentication TLV in one single TEAP packet aren't supported in this version, and they MUST NOT be sent 🙅‍♀️ If the peer or EAP server gets multiple EAP Payload TLVs, then it MUST terminate the connection with the Result TLV 💀 The order of TLVs in TEAP doesn't matter, with one exception: you should always process the Identity-Type TLV before the EAP TLV or Basic Password Authentication TLV, because the Identity-Type TLV is a hint about the type of identity that's going to be authenticated 🧠

Here's what the table entries mean in the sections below 🌈

  • 0: This TLV MUST NOT be present in the message.
  • 0+: Zero or more instances of this TLV MAY be present in the message.
  • 0-1: Zero or one instance of this TLV MAY be present in the message.
  • 1: Exactly one instance of this TLV MUST be present in the message.

4.3.1. Outer TLVs 🦋

Here's a guide to which TLVs can go outside the TLS channel in the TEAP packet, what kind of packets they can go in, and how many of each 💅

Request  Response    Success   Failure   TLVs
0-1      0           0         0         Authority-ID
0-1      0-1         0         0         Identity-Type
0+       0+          0         0         Vendor-Specific

Outer TLVs MUST be marked as optional ✨ Vendor-TLVs inside a Vendor-Specific TLV MUST be marked as optional when they're included in Outer TLVs 🫶 Outer TLVs MUST NOT be included in messages after the first two TEAP messages, which are the first EAP-server-to-peer message and the first peer-to-EAP-server message 🙈 If a message is fragmented, the whole set of messages counts as one message 🧩 And if Outer TLVs do show up in messages after the first two TEAP messages, they MUST be ignored 👑

4.3.2. Inner TLVs 🌸

This is a guide to which Inner TLVs can be encapsulated in TLS during TEAP Phase 2, what kind of packets they can go in, and how many of each 💖 Request is a TEAP Request, Response is a TEAP Response, Success is a message with a successful Result TLV, and Failure is a message with a failed Result TLV 🍓

Request  Response    Success   Failure   TLVs
0-1      0-1         0         0         Identity-Type
0-1      0-1         1         1         Result
0+       0+          0         0         NAK
0+       0+          0+        0+        Error
0-1      0-1         0         0         Channel-Binding
0+       0+          0+        0+        Vendor-Specific
0+       0+          0+        0+        Request-Action
0-1      0-1         0         0         EAP-Payload
0-1      0-1         0-1       0-1       Intermediate-Result
0+       0+          0+        0         PAC TLV
0-1      0-1         0-1       0-1       Crypto-Binding
0-1      0           0         0         Basic-Password-Auth-Req
0        0-1         0         0         Basic-Password-Auth-Resp
0-1      0           0-1       0         PKCS#7
0        0-1         0         0         PKCS#10
0-1      0-1         0-1       0         Trusted-Server-Root
NOTE: Vendor TLVs (included in Vendor-Specific TLVs) sent with a Result TLV MUST be marked as optional 🚨

5. Cryptographic Calculations ✨

For key derivation and crypto-binding, TEAP uses the Pseudorandom Function (PRF) and MAC algorithms that were negotiated in the underlying TLS session 🔐 Since those algorithms depend on the TLS version and ciphersuite, TEAP implementations need a way to figure out the version and ciphersuite in use for a particular session 🕵️‍♀️ The implementation can then use that info to decide which PRF and MAC algorithm to use 💅

5.1. TEAP Authentication Phase 1: Key Derivations 🎀

With TEAPv1, the TLS master secret is generated the way TLS specifies 💖 If a PAC is used, then the master secret is obtained as described in [RFC5077] 🌈

TEAPv1 uses the TLS Keying Material Exporters defined in [RFC5705] to derive the session_key_seed 🦋 The label used in the derivation is EXPORTER: teap session key seed ✨ The session key seed material is 40 octets long 🍓 No context data is used in the export process 🙈

The session_key_seed is used by the TEAP authentication Phase 2 conversation for two jobs: cryptographically binding the inner method(s) to the tunnel, and generating the resulting TEAP session keys 👑 The other TLS keying materials are derived and used as defined in [RFC5246] 🧚

5.2. Intermediate Compound Key Derivations 🫧

The session_key_seed derived during TEAP Phase 2 is used in TEAP Phase 2 to generate an Intermediate Compound Key (IMCK) 🔑 The IMCK verifies the integrity of the TLS tunnel after each successful inner authentication, and it feeds into the Master Session Key (MSK) and Extended Master Session Key (EMSK) defined in [RFC3748] 💜 Heads up: the IMCK MUST be recalculated after each successful inner EAP method 🔥

The first step is generating the base compound key, IMCK[n], from the session_key_seed and any session keys derived from the successful execution of the nth inner EAP method 🧩 The inner EAP method(s) may provide Inner Method Session Keys (IMSKs), IMSK1..IMSKn, which correspond to inner method 1 through n 🌸

If an inner method supports export of an Extended Master Session Key (EMSK), then the IMSK SHOULD be derived from the EMSK as defined in [RFC5295] 🦋 The usage label is TEAPbindkey@ietf.org, and the length is 64 octets 💖 The optional data parameter isn't used in the derivation ✨

  IMSK = First 32 octets of TLS-PRF(EMSK, "TEAPbindkey@ietf.org" |
  "\0" | 64)

  where "|" denotes concatenation, EMSK is the EMSK from the inner
  method, "TEAPbindkey@ietf.org" consists the ASCII value for the
  label "TEAPbindkey@ietf.org" (without quotes), "\0" = is a NULL
  octet (0x00 in hex), length is the 2-octet unsigned integer in
  network byte order, and TLS-PRF is the PRF negotiated as part of
  TLS handshake [RFC5246].

If an inner method doesn't support export of an EMSK, then the IMSK is the MSK of the inner method 🍓 The MSK gets truncated at 32 octets if it's longer than 32 octets, or padded with zeros up to 32 octets if it's shorter 🧸

However, the peer and server sides might not have the same ability to export an EMSK 🥺 To keep things maximally flexible while preventing downgrading attacks, the following mechanism is in place 🛡️

On the sender of the Crypto-Binding TLV side:

  • If the EMSK isn't available, then the sender computes the Compound MAC using the MSK of the inner method.
  • If the EMSK is available and the sender's policy accepts MSK-based MAC, then the sender computes two Compound MAC values. The first is computed with the EMSK. The second is computed using the MSK. Both MACs are then sent to the other side.
  • If the EMSK is available but the sender's policy doesn't allow downgrading to an MSK-generated MAC, then the sender SHOULD only send an EMSK-based MAC 🚫

On the receiver of the Crypto-Binding TLV side:

  • If the EMSK isn't available and an MSK-based Compound MAC was sent, then the receiver validates the Compound MAC and sends back an MSK-based Compound MAC response 🔁
  • If the EMSK isn't available and no MSK-based Compound MAC was sent, then the receiver handles it like an invalid Crypto-Binding TLV with a fatal error 💀
  • If the EMSK is available and an EMSK-based Compound MAC was sent, then the receiver validates it and creates a response Compound MAC using the EMSK ✨
  • If the EMSK is available but no EMSK-based Compound MAC was sent, and its policy accepts MSK-based MAC, then the receiver validates it using the MSK and, if that works, generates and returns an MSK-based Compound MAC 🎀
  • If the EMSK is available but no EMSK Compound MAC was sent, and its policy doesn't accept MSK-based MAC, then the receiver handles it like an invalid Crypto-Binding TLV with a fatal error 🙅‍♀️

If the ith inner method doesn't generate an EMSK or MSK, then IMSKi is set to zero (e.g., MSKi = 32 octets of 0x00s) 🫠 If an inner method fails, it isn't included in this calculation 🙈 The derivation of S-IMCK goes like this 👇

   S-IMCK[0] = session_key_seed
   For j = 1 to n-1 do
        IMCK[j] = TLS-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",
             IMSK[j], 60)
        S-IMCK[j] = first 40 octets of IMCK[j]
        CMK[j] = last 20 octets of IMCK[j]

where TLS-PRF is the PRF negotiated as part of the TLS handshake [RFC5246] 🦋

5.3. Computing the Compound MAC

okay so for authentication methods that generate keying material, you get extra protection against man-in-the-middle attacks 🕵️‍♀️ from cryptographically binding keying material that gets set up in BOTH the TEAP Phase 1 and TEAP Phase 2 conversations. After each successful inner EAP authentication, the EAP EMSK and/or MSKs get mixed with key material from TEAP Phase 1 to make a Compound Session Key (CMK) 🔑. The CMK is used to calculate the Compound MAC inside the Crypto-Binding TLV from Section 4.2.13, which helps prove the same entities are involved in all communications in TEAP 🫶. While the Compound MAC is being calculated, the MAC field is filled with zeros 🤍

the Compound MAC computation goes like this:

CMK = CMK[j]
Compound-MAC = MAC( CMK, BUFFER )

where j is the number of the last successfully executed inner EAP method, MAC is the MAC function negotiated in TLS 1.2 [RFC5246], and BUFFER gets built by concatenating these fields in this exact order:

  1. The entire Crypto-Binding TLV attribute with both the EMSK and MSK Compound MAC fields zeroed out.
  2. The EAP Type sent by the other party in the first TEAP message.
  3. All the Outer TLVs from the first TEAP message sent by EAP server to peer. If a single TEAP message is fragmented into multiple TEAP packets, then the Outer TLVs in all the fragments of that message MUST be included. 📦
  4. All the Outer TLVs from the first TEAP message sent by the peer to the EAP server. If a single TEAP message is fragmented into multiple TEAP packets, then the Outer TLVs in all the fragments of that message MUST be included. 📦

5.4. EAP Master Session Key Generation

okay this part is giving key hierarchy vibes 👑 TEAP authentication makes sure the Master Session Key (MSK) and Extended Master Session Key (EMSK) from the EAP method are the result of ALL the authentication conversations, by generating an Intermediate Compound Key (IMCK) ✨. The IMCK is mutually derived by the peer and the server, as described in Section 5.2, by combining the MSKs from inner EAP methods with key material from TEAP Phase 1. The resulting MSK and EMSK get generated as part of the IMCKn key hierarchy like this:

MSK  = TLS-PRF(S-IMCK[j], "Session Key Generating Function", 64)
EMSK = TLS-PRF(S-IMCK[j],
     "Extended Session Key Generating Function", 64)

where j is the number of the last successfully executed inner EAP method.

The EMSK is typically only known to the TEAP peer and server and is not provided to a third party 🤐. The derivation of additional keys, and the transportation of those keys to a third party, are outside the scope of this document.

If no EAP methods have been negotiated inside the tunnel, or no EAP methods have been successfully completed inside the tunnel, the MSK and EMSK will be generated directly from the session_key_seed, meaning S-IMCK = session_key_seed. 🧚


6. IANA Considerations 📋

This section gives guidance to the Internet Assigned Numbers Authority (IANA) about registering values related to the TEAP protocol, following BCP 26 [RFC5226] 💅

The EAP Method Type number 55 has been assigned for TEAP. 🎀

The document defines a registry for TEAP TLV types, which may be assigned by Specification Required as defined in [RFC5226]. Section 4.2 defines the TLV types that initially fill the registry. Here's a quick summary of the TEAP TLV types:

0  Unassigned

1  Authority-ID TLV

2  Identity-Type TLV

3  Result TLV

4  NAK TLV

5  Error TLV

6  Channel-Binding TLV
7  Vendor-Specific TLV

8  Request-Action TLV

9  EAP-Payload TLV

10 Intermediate-Result TLV

11 PAC TLV

12 Crypto-Binding TLV

13 Basic-Password-Auth-Req TLV

14 Basic-Password-Auth-Resp TLV

15 PKCS#7 TLV

16 PKCS#10 TLV

17 Trusted-Server-Root TLV

The Identity-Type defined in Section 4.2.3 contains an identity type code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial types defined are:

1  User

2  Machine

The Result TLV defined in Section 4.2.4, Request-Action TLV defined in Section 4.2.9, and Intermediate-Result TLV defined in Section 4.2.11 contain a Status code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial types defined are:

1  Success

2  Failure

The Error-TLV defined in Section 4.2.6 requires an error code. TEAP Error-TLV error codes are assigned based on a Specification Required basis as defined in [RFC5226]. The initial list of error codes is as follows:

1     User account expires soon

2     User account credential expires soon
3     User account authorizations change soon

4     Clock skew detected

5     Contact administrator

6     User account credentials change required

1001  Inner Method Error

1002  Unspecified authentication infrastructure problem

1003  Unspecified authentication failure

1004  Unspecified authorization failure

1005  User account credentials unavailable

1006  User account expired

1007  User account locked: try again later

1008  User account locked: admin intervention required

1009  Authentication infrastructure unavailable

1010  Authentication infrastructure not trusted

1011  Clock skew too great

1012  Invalid inner realm

1013  Token out of sync: administrator intervention required

1014  Token out of sync: PIN change required

1015  Token revoked

1016  Tokens exhausted

1017  Challenge expired

1018  Challenge algorithm mismatch

1019  Client certificate not supplied

1020  Client certificate rejected
1021  Realm mismatch between inner and outer identity

1022  Unsupported Algorithm In Certificate Signing Request

1023  Unsupported Extension In Certificate Signing Request

1024  Bad Identity In Certificate Signing Request

1025  Bad Certificate Signing Request

1026  Internal CA Error

1027  General PKI Error

1028  Inner method's channel-binding data required but not supplied

1029  Inner method's channel-binding data did not include required
      information

1030  Inner method's channel binding failed

1031  User account credentials incorrect [USAGE NOT RECOMMENDED]

2001  Tunnel Compromise Error

2002  Unexpected TLVs Exchanged

The Request-Action TLV defined in Section 4.2.9 contains an action code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial actions defined are:

1  Process-TLV

2  Negotiate-EAP

The PAC Attribute defined in Section 4.2.12.1 contains a Type code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial types defined are:

1   PAC-Key

2   PAC-Opaque

3   PAC-Lifetime

4   A-ID

5   I-ID
6   Reserved

7   A-ID-Info

8   PAC-Acknowledgement

9   PAC-Info

10  PAC-Type

The PAC-Type defined in Section 4.2.12.6 contains a type code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial type defined is:

1  Tunnel PAC

The Trusted-Server-Root TLV defined in Section 4.2.18 contains a Credential-Format code that is assigned on a Specification Required basis as defined in [RFC5226]. The initial type defined is:

1  PKCS#7-Server-Certificate-Root

The various values under the Vendor-Specific TLV are assigned by Private Use and do not need to be assigned by IANA. 🌸

TEAP registers the label "EXPORTER: teap session key seed" in the TLS Exporter Label Registry [RFC5705]. This label is used in derivation as defined in Section 5.1. 🏷️

TEAP registers a TEAP binding usage label from the "User Specific Root Keys (USRK) Key Labels" name space defined in [RFC5295] with a value "TEAPbindkey@ietf.org". 🦋


7. Security Considerations 🚨

okay this section is SERIOUS bestie, so pay attention 😭 TEAP is designed with a focus on wireless media, where the medium itself is inherently open to eavesdropping 📡. With wired media an attacker would have to gain physical access to the wire, but with wireless media ANYONE can capture information as it's transmitted over the air, which means passive attacks 👀. So physical security can not be assumed, and security vulnerabilities are way bigger. The threat model used for the security evaluation of TEAP is defined in EAP [RFC3748].

7.1. Mutual Authentication and Integrity Protection

As a whole, TEAP provides message and integrity protection by setting up a secure tunnel that protects the authentication method(s) 🔒. The confidentiality and integrity protection is defined by TLS, and gives the same security strengths that TLS gives when it uses a strong entropy shared master secret 💪. The integrity of the key generating authentication methods run inside the TEAP tunnel is verified through the calculation of the Crypto-Binding TLV. This makes sure the tunnel endpoints are the same as the inner method endpoints 🫶.

The Result TLV is protected and carries the true Success or Failure of TEAP, and it should be used as the indicator of its success or failure, respectively. ✅ However, EAP ends with either a cleartext EAP Success or Failure, so a peer will also receive a cleartext EAP Success or Failure. The received cleartext EAP Success or Failure MUST match the one received in the Result TLV, and the peer SHOULD silently discard any cleartext EAP Success or Failure messages that do not match the status sent in the protected Result TLV. 🙅‍♀️

7.2. Method Negotiation

As is true for any negotiated EAP protocol, NAK packets used to suggest an alternate authentication method are sent unprotected, so they're open to spoofing 🥷. During unprotected EAP method negotiation, NAK packets may be injected as active attacks to negotiate down to a weaker form of authentication, such as EAP-MD5 (which only provides one-way authentication and does not derive a key) 💀. Both the peer and server should have a method selection policy that stops them from negotiating down to weaker methods. Inner method negotiation resists attacks because it is protected by the mutually authenticated TLS tunnel that's been set up. Choosing TEAP as an authentication method doesn't limit the potential inner authentication methods, so TEAP should be selected when available. 🌈

An attacker can't readily determine the inner EAP method used, except perhaps through traffic analysis 🔍. It's also important that peer implementations limit the use of credentials with an unauthenticated or unauthorized server 🛡️

7.3. Separation of Phase 1 and Phase 2 Servers 🧚

okay bestie, splitting the Phase 1 convo and the Phase 2 convo across different servers is NOT RECOMMENDED 🙅‍♀️. If the two servers don't have a proper trust relationship, and the protocol isn't protected between them, you're basically inviting drama 💀. Here's the drama list:

  • Loss of identity protection
  • Offline dictionary attacks
  • Lack of policy enforcement
  • Man-in-the-middle attacks (as described in [RFC7029])

That said, there are situations where the two servers DO trust each other, like on a campus or between two offices of the same company. In those cases, letting the peer's inner identity and credentials be seen by the stuff sitting between the two servers isn't a real danger 🌸. So a proxy setup without end-to-end protection of TEAP MAY be used. Even then, the TEAP encrypting/decrypting gateway MUST, at a minimum, provide support for IPsec, TLS, or similar protection so the conversation between the gateway and the EAP server stays confidential 🔒.

Splitting the inner and outer method servers also means the crypto-binding based on the inner method MSK can get thwarted, as described in [RFC7029] 😬. So implementation and deployment SHOULD adopt various mitigation strategies described in [RFC7029] 🛡️. And if the inner method is deriving EMSK, we're good, because TEAP uses the mutual crypto-binding based on EMSK as described in [RFC7029] ✨. Threat mitigated, iconic behavior 👑.

7.4. Mitigation of Known Vulnerabilities and Protocol Deficiencies 💅

TEAP goes after the known deficiencies and weaknesses in the EAP method, and honestly it's a glow-up 🦋. By using a shared secret between the peer and the server to set up a secured tunnel, TEAP gives you:

  • Per-packet confidentiality and integrity protection
  • User identity protection
  • Better support for notification messages
  • Protected EAP inner method negotiation
  • Sequencing of EAP methods
  • Strong mutually derived MSKs
  • Acknowledged success/failure indication
  • Faster re-authentications through session resumption
  • Mitigation of dictionary attacks
  • Mitigation of man-in-the-middle attacks
  • Mitigation of some denial-of-service attacks

Now, the not-so-cute part 🥲. Like a lot of authentication protocols, TEAP can still get hit with a denial-of-service attack, where adversaries send erroneous traffic to mess up the protocol. This is a problem for plenty of authentication and key agreement protocols, so yeah, it's noted for TEAP too ⚠️.

TEAP was built around protected authentication methods that usually rely on weak credentials, like password-based secrets 🔐. So the TEAP authentication helps knock out vulnerabilities like dictionary attacks by wrapping that weak-credential method in protection. That protection comes from strong cryptographic algorithms in TLS, which give you message confidentiality and integrity 🧁. The keys for that protection rely on strong random challenges from both the peer and the server, plus an established key with strong entropy. Implementations should follow the recommendation in [RFC4086] when generating random numbers 🎲.

7.4.1. User Identity Protection and Verification 🙈

The initial identity request/response exchange goes out in cleartext, outside the protection of TEAP, so anyone can peek at it 👀. Usually the Network Access Identifier (NAI) [RFC4282] in the identity response is only useful for working out the realm, which is what routes the authentication requests to the right EAP server 🗺️. So the identity response might just contain an anonymous identity along with realm information. And sometimes the identity exchange can be skipped entirely, if there are other ways to figure out the destination realm of the request 🪄.

In no case should an intermediary place any trust in the identity information in the identity response, since it's unauthenticated and might have nothing to do with the identity that actually gets authenticated 🚫. TEAP implementations should not attempt to compare any identity disclosed in the initial cleartext EAP Identity response packet with the identities authenticated in Phase 2.

Identity request/response exchanges that happen after the TEAP tunnel is established are protected from modification and eavesdropping by attackers 🔒✨.

Now, here's the tea ☕. TLS client certificates get sent in the clear, so if identity protection is required, the TLS authentication can be renegotiated after the first server authentication. To do that, the server typically won't request a certificate in the server_hello. Then, after the server_finished message is sent and before TEAP Phase 2, the server MAY send a TLS hello_request. That lets the peer do client authentication by sending a client_hello if it wants to, or send a no_renegotiation alert to the server to say it wants to keep going with TEAP Phase 2 instead 🙋‍♀️. If the peer allows renegotiation by sending a client_hello, the server responds with server_hello, certificate, and certificate_request messages. The peer then replies with certificate, client_key_exchange, and certificate_verify messages 📜. Since all of this happens inside the encrypted TLS channel, the client certificate details stay hidden 🤫. And if you'd rather not do TLS handshake renegotiation, certificate authentication can happen in TEAP Phase 2 using an EAP method (for example, EAP-TLS) inside the TLS session instead 💖.

7.4.2. Dictionary Attack Resistance 🧩

TEAP was built around protected authentication methods that usually rely on weak credentials, like password-based secrets 🔑. It stops dictionary attacks by setting up a mutually authenticated, encrypted TLS tunnel. That tunnel gives confidentiality and integrity to protect the weak credential-based authentication method, so the attacker's guessing game gets a lot harder 🙅‍♀️.

7.4.3. Protection against Man-in-the-Middle Attacks 🕵️‍♀️

Letting methods run both with and without the protection of a secure tunnel opens the door to a man-in-the-middle attack 🚪. To avoid that, it is recommended to always deploy authentication methods with the protection of TEAP. Even if a deployment chooses to run inner EAP methods both with and without TEAP protection, TEAP still protects against man-in-the-middle attacks 💜. It does this in two ways:

  1. By using the PAC-Key to mutually authenticate the peer and server during TEAP authentication Phase 1 establishment of a secure tunnel.
  2. By using the keys generated by the inner authentication method (if the inner methods are key generating) in the crypto-binding exchange and in the generation of the key material exported by the EAP method described in Section 5.

Here's a caveat 🚨. TEAP crypto binding does NOT guarantee man-in-the-middle protection if the client allows a connection to an untrusted server, like when the client doesn't properly validate the server's certificate. If the TLS ciphersuite derives the master secret solely from secret data contributed by one side of the conversation (like ciphersuites based on RSA key transport), then an attacker who can convince the client to connect and engage in authentication can impersonate the client to another server, even if a strong inner method runs inside the tunnel 😱. If the TLS ciphersuite derives the master secret from secrets contributed by both sides (like ciphersuites based on Diffie-Hellman), then crypto binding can detect an attacker in the conversation when a strong inner method is used 🫶.

7.4.4. PAC Binding to User Identity 🎀

A PAC may be bound to a user identity 💕. A compliant implementation of TEAP MUST validate that an identity obtained in the PAC-Opaque field matches at minimum one of the identities provided in the TEAP Phase 2 authentication method. This validation adds another binding, making sure the intended peer (based on identity) has successfully completed TEAP Phase 1 and proved their identity in the Phase 2 conversations 👑.

7.5. Protecting against Forged Cleartext EAP Packets 🛑

EAP Success and EAP Failure packets are, in general, sent in cleartext, so an attacker can forge them without anyone noticing 😭. Forged EAP Failure packets can be used to try to convince an EAP peer to disconnect. Forged EAP Success packets can be used to try to convince a peer that authentication worked, even though the authenticator never actually authenticated itself to the peer 🥴.

TEAP fixes this with message confidentiality and integrity, so these attacks don't work 🦋. Once the peer and authentication server (AS) start TEAP authentication Phase 2, compliant TEAP implementations MUST silently discard all cleartext EAP messages, unless both the TEAP peer and server have indicated success or failure using a protected mechanism. Protected mechanisms include the TLS alert mechanism and the protected termination mechanism described in Section 3.3.3 ✨.

The success/failure decisions inside the TEAP tunnel are the final word on the TEAP authentication conversation 📣. After a success/failure result has been indicated by a protected mechanism, the TEAP peer can process unprotected EAP Success and EAP Failure messages. However, the peer MUST ignore any unprotected EAP Success or Failure messages where the result doesn't match the result of the protected mechanism 🙅‍♀️.

Here's the wrinkle 🧵. To abide by [RFC3748], the server sends a cleartext EAP Success or EAP Failure packet to terminate the EAP conversation. But EAP Success and EAP Failure packets don't get retransmitted, so the final packet might get lost. A TEAP-protected EAP Success or EAP Failure packet should not be the final packet in a TEAP conversation, but based on the conditions above it can still happen. So an EAP peer should not rely upon the unprotected EAP Success and Failure messages 🌈.

7.6. Server Certificate Validation 📜

As part of the TLS negotiation, the server presents a certificate to the peer 🎁. The peer SHOULD verify the validity of the EAP server certificate, and SHOULD also examine the EAP server name presented in the certificate, to figure out whether the EAP server can be trusted 🔍. When doing server certificate validation, implementations MUST provide support for the rules in [RFC5280] for validating certificates against a known trust anchor. On top of that, implementations MUST support matching the realm portion of the peer's NAI against a SubjectAltName of type dNSName within the server certificate. Heads up though, in certain deployments this might not be turned on 🙃.

Also, when EAP authentication is remote, the EAP server won't live on the same machine as the authenticator. So the name in the EAP server's certificate can't be expected to match the intended destination 🌍. In that case, a better test might be checking whether the EAP server's certificate is signed by a certification authority (CA) that controls the intended domain, and whether the authenticator can be authorized by a server in that domain 💖.

7.7. Tunnel PAC Considerations 🔐

okay so the Tunnel PAC lives on the peer, which means the peer has to be extra careful with it 💅 The Tunnel PAC MUST be securely stored by the peer so nobody can steal it or forge any of its parts. Main thing: the peer MUST securely store the PAC-Key and protect it from being disclosed or modified 🫶 If someone leaks the PAC-Key, they can set up the TEAP tunnel, but they still can't learn who the peer or server is, and they can't mess with any other peer's PAC credentials 🙈 Changing the PAC-Key or the PAC-Opaque can also cause denial of service, because tunnel establishment will just fail 😭

The PAC-Opaque is basically the TLS ticket extension that makes tunnel setup work using the techniques from [RFC5077], so all the security considerations in [RFC5077] also apply to it 🧚 The PAC-Info may hold stuff about the Tunnel PAC, like who issued the PAC and how long it lasts, which helps with managing it 🌸 The PAC-Info should be securely stored by the peer so it can't be disclosed or modified 💜


7.8. Security Claims 📋

This part lays out the security claims that EAP [RFC3748] needs, and honestly, the table below is the whole vibe ✨ Everything is in a code block so it stays exact:

Auth. mechanism:         Certificate-based, shared-secret-based, and
                         various tunneled authentication mechanisms.

Ciphersuite negotiation: Yes

Mutual authentication:   Yes

Integrity protection:    Yes.  Any method executed within the TEAP
                         tunnel is integrity protected.  The
                         cleartext EAP headers outside the tunnel are
                         not integrity protected.

Replay protection:       Yes

Confidentiality:         Yes

Key derivation:          Yes

Key strength:            See Note 1 below.

Dictionary attack prot.: Yes

Fast reconnect:          Yes

Cryptographic binding:   Yes

Session independence:    Yes

Fragmentation:           Yes

Key Hierarchy:           Yes

Channel binding:         Yes

Notes

  1. BCP 86 [RFC3766] gives advice on picking good key sizes, and the National Institute for Standards and Technology (NIST) has its own advice on that in [NIST-SP-800-57] 🔥 [RFC3766], Section 5 says which RSA or DH modulus sizes and DSA subgroup sizes (in bits) you need for a given level of attack resistance (also in bits) 💖 Going by the table below, you need a 2048-bit RSA key to get 112-bit equivalent key strength 👑
Attack Resistance     RSA or DH Modulus            DSA subgroup
 (bits)                  size (bits)                size (bits)
-----------------     -----------------            ------------
   70                        947                        129
   80                       1228                        148
   90                       1553                        167
  100                       1926                        186
  150                       4575                        284
  200                       8719                        383
  250                      14596                        482

8. Acknowledgements 🫶

okay the big shoutout here: TEAP is based on EAP-FAST [RFC4851], which came from the ideas and hard work of Nancy Cam-Winget, David McGrew, Joe Salowey, Hao Zhou, Pad Jakkahalli, Mark Krischer, Doug Smith, and Glen Zorn of Cisco Systems, Inc. 🌈

The TLV processing was inspired by work on the Protected Extensible Authentication Protocol version 2 (PEAPv2) with Ashwin Palekar, Dan Smith, Sean Turner, and Simon Josefsson 🦋

The way we link identity and proof-of-possession, by putting the tls-unique value in the challengePassword field of the CSR as described in Section 3.8.2, was inspired by "Enrollment over Secure Transport" [RFC7030] 💜

Thanks also to Russ Housley, Jari Arkko, Ilan Frenkel, Jeremy Steiglitz, Dan Harkins, Sam Hartman, Jim Schaad, Barry Leiba, Stephen Farrell, Chris Lonvick, and Josh Howlett for the helpful review comments 🎀


9. References 📚

9.1. Normative References

  • [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [RFC3748] Aboba, B., Blunk, L., Vollbrecht, J., Carlson, J., and H. Levkowetz, "Extensible Authentication Protocol (EAP)", RFC 3748, June 2004.
  • [RFC5077] Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig, "Transport Layer Security (TLS) Session Resumption without Server-Side State", RFC 5077, January 2008.
  • [RFC5226] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 5226, May 2008.
  • [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, August 2008.
  • [RFC5295] Salowey, J., Dondeti, L., Narayanan, V., and M. Nakhjiri, "Specification for the Derivation of Root Keys from an Extended Master Session Key (EMSK)", RFC 5295, August 2008.
  • [RFC5705] Rescorla, E., "Keying Material Exporters for Transport Layer Security (TLS)", RFC 5705, March 2010.
  • [RFC5746] Rescorla, E., Ray, M., Dispensa, S., and N. Oskov, "Transport Layer Security (TLS) Renegotiation Indication Extension", RFC 5746, February 2010.
  • [RFC5929] Altman, J., Williams, N., and L. Zhu, "Channel Bindings for TLS", RFC 5929, July 2010.
  • [RFC6677] Hartman, S., Clancy, T., and K. Hoeper, "Channel-Binding Support for Extensible Authentication Protocol (EAP) Methods", RFC 6677, July 2012.

9.2. Informative References

  • [IEEE.802-1X.2013] IEEE, "Local and Metropolitan Area Networks: Port-Based Network Access Control", IEEE Standard 802.1X, December 2013.
  • [NIST-SP-800-57] National Institute of Standards and Technology, "Recommendation for Key Management", NIST Special Publication 800-57, July 2012.
  • [PEAP] Microsoft Corporation, "[MS-PEAP]: Protected Extensible Authentication Protocol (PEAP)", February 2014.
  • [RFC2315] Kaliski, B., "PKCS #7: Cryptographic Message Syntax Version 1.5", RFC 2315, March 1998.
  • [RFC2985] Nystrom, M. and B. Kaliski, "PKCS #9: Selected Object Classes and Attribute Types Version 2.0", RFC 2985, November 2000.
  • [RFC2986] Nystrom, M. and B. Kaliski, "PKCS #10: Certification Request Syntax Specification Version 1.7", RFC 2986, November 2000.
  • [RFC3579] Aboba, B. and P. Calhoun, "RADIUS (Remote Authentication Dial In User Service) Support For Extensible Authentication Protocol (EAP)", RFC 3579, September 2003.
  • [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
  • [RFC3766] Orman, H. and P. Hoffman, "Determining Strengths For Public Keys Used For Exchanging Symmetric Keys", BCP 86, RFC 3766, April 2004.
  • [RFC4017] Stanley, D., Walker, J., and B. Aboba, "Extensible Authentication Protocol (EAP) Method Requirements for Wireless LANs", RFC 4017, March 2005.
  • [RFC4072] Eronen, P., Hiller, T., and G. Zorn, "Diameter Extensible Authentication Protocol (EAP) Application", RFC 4072, August 2005.
  • [RFC4086] Eastlake, D., Schiller, J., and S. Crocker, "Randomness Requirements for Security", BCP 106, RFC 4086, June 2005.
  • [RFC4282] Aboba, B., Beadles, M., Arkko, J., and P. Eronen, "The Network Access Identifier", RFC 4282, December 2005.
  • [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, October 2006.
  • [RFC4851] Cam-Winget, N., McGrew, D., Salowey, J., and H. Zhou, "The Flexible Authentication via Secure Tunneling Extensible Authentication Protocol Method (EAP-FAST)", RFC 4851, May 2007.
  • [RFC4945] Korver, B., "The Internet IP Security PKI Profile of IKEv1/ISAKMP, IKEv2, and PKIX", RFC 4945, August 2007.
  • [RFC4962] Housley, R. and B. Aboba, "Guidance for Authentication, Authorization, and Accounting (AAA) Key Management", BCP 132, RFC 4962, July 2007.
  • [RFC5247] Aboba, B., Simon, D., and P. Eronen, "Extensible Authentication Protocol (EAP) Key Management Framework", RFC 5247, August 2008.
  • [RFC5272] Schaad, J. and M. Myers, "Certificate Management over CMS (CMC)", RFC 5272, June 2008.
  • [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, May 2008.
  • [RFC5281] Funk, P. and S. Blake-Wilson, "Extensible Authentication Protocol Tunneled Transport Layer Security Authenticated Protocol Version 0 (EAP-TTLSv0)", RFC 5281, August 2008.
  • [RFC5421] Cam-Winget, N. and H. Zhou, "Basic Password Exchange within the Flexible Authentication via Secure Tunneling Extensible Authentication Protocol (EAP-FAST)", RFC 5421, March 2009.
  • [RFC5652] Housley, R., "Cryptographic Message Syntax (CMS)", STD 70, RFC 5652, September 2009.
  • [RFC5931] Harkins, D. and G. Zorn, "Extensible Authentication Protocol (EAP) Authentication Using Only a Password", RFC 5931, August 2010.
  • [RFC6066] Eastlake, D., "Transport Layer Security (TLS) Extensions: Extension Definitions", RFC 6066, January 2011.
  • [RFC6124] Sheffer, Y., Zorn, G., Tschofenig, H., and S. Fluhrer, "An EAP Authentication Method Based on the Encrypted Key Exchange (EKE) Protocol", RFC 6124, February 2011.
  • [RFC6678] Hoeper, K., Hanna, S., Zhou, H., and J. Salowey, "Requirements for a Tunnel-Based Extensible Authentication Protocol (EAP) Method", RFC 6678, July 2012.
  • [RFC6960] Santesson, S., Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 6960, June 2013.
  • [RFC6961] Pettersen, Y., "The Transport Layer Security (TLS) Multiple Certificate Status Request Extension", RFC 6961, June 2013.
  • [RFC7029] Hartman, S., Wasserman, M., and D. Zhang, "Extensible Authentication Protocol (EAP) Mutual Cryptographic Binding", RFC 7029, October 2013.
  • [RFC7030] Pritikin, M., Yee, P., and D. Harkins, "Enrollment over Secure Transport", RFC 7030, October 2013.
  • [X.690] ITU-T, "ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)", ITU-T Recommendation X.690, November 2008.

Appendix A. Evaluation against Tunnel-Based EAP Method Requirements 🎀

This section checks every tunnel-based EAP method requirement from [RFC6678] against TEAP version 1 ✨

A.1. Requirement 4.1.1: RFC Compliance

Okay so TEAPv1 totally checks this one off ✅ because it's compliant with RFC 3748 [RFC3748], RFC 4017 [RFC4017], RFC 5247 [RFC5247], and RFC 4962 [RFC4962]. 💖 It also handles the "cryptographic algorithm agility" requirement by leaning on TLS 1.2 for all of its algorithm negotiation. Iconic. 💅

A.2. Requirement 4.2.1: TLS Requirements

TEAPv1 meets this one by mandating TLS version 1.2 support, as defined in Section 3.2. 🎀

A.3. Requirement 4.2.1.1.1: Ciphersuite Negotiation

TEAPv1 gets this done by using TLS to provide protected ciphersuite negotiation. 🔐✨

A.4. Requirement 4.2.1.1.2: Tunnel Data Protection Algorithms

TEAPv1 meets this by mandating TLS_RSA_WITH_AES_128_CBC_SHA as a mandatory-to-implement ciphersuite, as defined in Section 3.2. 🦋

A.5. Requirement 4.2.1.1.3: Tunnel Authentication and Key Establishment

Here TEAPv1 mandates TLS_RSA_WITH_AES_128_CBC_SHA as a mandatory-to-implement ciphersuite that provides certificate-based authentication of the server and is approved by NIST. 🙌 The mandatory-to-implement ciphersuites only include ciphersuites that use strong cryptographic algorithms, so no weak stuff sneaking in. They do not include ciphersuites providing mutually anonymous authentication or static Diffie-Hellman ciphersuites, as defined in Section 3.2. 🚫🌸

A.6. Requirement 4.2.1.2: Tunnel Replay Protection

TEAPv1 meets this by using TLS to provide sufficient replay protection. 🛡️💜

A.7. Requirement 4.2.1.3: TLS Extensions

TEAPv1 meets this by allowing TLS extensions, like the TLS Certificate Status Request extension [RFC6066] and the SessionTicket extension [RFC5077], to be used during TLS tunnel establishment. 🧚

A.8. Requirement 4.2.1.4: Peer Identity Privacy

TEAPv1 meets this by establishing the TLS tunnel and protecting identities specific to the inner method. 🫶 On top of that, the peer certificate can be sent confidentially, which means encrypted. 🤫

A.9. Requirement 4.2.1.5: Session Resumption

TEAPv1 meets this by mandating support of TLS session resumption, as defined in Section 3.2.1, and TLS session resume using a PAC, as defined in Section 3.2.2 . 🔁✨

A.10. Requirement 4.2.2: Fragmentation

TEAPv1 meets this by leaning on the fragmentation support that TLS already provides, as defined in Section 3.7. 🧩

A.11. Requirement 4.2.3: Protection of Data External to Tunnel

TEAPv1 meets this by including the TEAP version number it received in the computation of the Crypto-Binding TLV, as defined in Section 4.2.13. 🔗

A.12. Requirement 4.3.1: Extensible Attribute Types

TEAPv1 meets this by using an extensible TLV data layer inside the tunnel, as defined in Section 4.2. 🌈

A.13. Requirement 4.3.2: Request/Challenge Response Operation

TEAPv1 meets this by allowing multiple TLVs to be sent in a single EAP request or response packet, while still keeping the half-duplex operation that's typical of EAP. 📦💅

A.14. Requirement 4.3.3: Indicating Criticality of Attributes

TEAPv1 meets this by having a mandatory bit in each TLV that says whether it's mandatory to support or not, as defined in Section 4.2. 🚩

A.15. Requirement 4.3.4: Vendor-Specific Support

TEAPv1 meets this with a Vendor-Specific TLV, which lets vendors define their own attributes, as defined in Section 4.2.8. 🏷️✨

A.16. Requirement 4.3.5: Result Indication

TEAPv1 meets this with a Result TLV that exchanges the final result of the EAP authentication, so the peer and server both have a synchronized state, as defined in Section 4.2.4. 🤝👑

A.17. Requirement 4.3.6: Internationalization of Display Strings

TEAPv1 meets this by supporting UTF-8 format in the Basic-Password-Auth-Req TLV, as defined in Section 4.2.14, and the Basic-Password-Auth-Resp TLV, as defined in Section 4.2.15. 🌍💖

A.18. Requirement 4.4: EAP Channel-Binding Requirements

TEAPv1 meets this with a Channel-Binding TLV that exchanges the EAP channel-binding data, as defined in Section 4.2.7. 🔒🎀

A.19. Requirement 4.5.1.1: Confidentiality and Integrity

TEAPv1 meets this by running the password authentication inside a protected TLS tunnel. 🥰🔐

A.20. Requirement 4.5.1.2: Authentication of Server

TEAPv1 meets this by mandating authentication of the server before the protected TLS is established, and then running inner password authentication, as defined in Section 3.2. 🙌

A.21. Requirement 4.5.1.3: Server Certificate Revocation Checking

TEAPv1 meets this by supporting the TLS Certificate Status Request extension [RFC6066] during tunnel establishment. 📜✅

A.22. Requirement 4.5.2: Internationalization

TEAPv1 meets this by supporting UTF-8 format in the Basic-Password-Auth-Req TLV, as defined in Section 4.2.14, and the Basic-Password-Auth-Resp TLV, as defined in Section 4.2.15. 🌏🌸

A.23. Requirement 4.5.3: Metadata

TEAPv1 meets this by supporting the Identity-Type TLV, as defined in Section 4.2.3, to indicate whether the authentication is for a user or a machine. 🧑‍💻🤖

A.24. Requirement 4.5.4: Password Change

TEAPv1 meets this by supporting multiple Basic-Password-Auth-Req TLV and Basic-Password-Auth-Resp TLV exchanges within a single EAP authentication. That lets "housekeeping"" functions, like password change, happen. 🧹💅

A.25. Requirement 4.6.1: Method Negotiation

TEAPv1 meets this by supporting inner EAP method negotiation within the protected TLS tunnel. 🤓🌟

A.26. Requirement 4.6.2: Chained Methods

TEAPv1 meets this by supporting inner EAP method chaining within protected TLS tunnels, as defined in Section 3.3.1. ⛓️✨

A.27. Requirement 4.6.3: Cryptographic Binding with the TLS Tunnel

TEAPv1 meets this by supporting cryptographic binding of the inner EAP method keys with the keys derived from the TLS tunnel, as defined in Section 4.2.13. 💜🔗

A.28. Requirement 4.6.4: Peer-Initiated EAP Authentication

TEAPv1 meets this by supporting the Request-Action TLV, as defined in Section 4.2.9, which lets a peer start another inner EAP method itself. 🙋‍♀️🦋

A.29. Requirement 4.6.5: Method Metadata

TEAPv1 meets this by supporting the Identity-Type TLV, as defined in Section 4.2.3, to indicate whether the authentication is for a user or a machine. 🏁💖


Appendix B. Major Differences from EAP-FAST

Bestie, this document is a brand-new standard tunnel EAP method. 🎉 It's based on a revision of EAP-FAST version 1 [RFC4851] and is way more flexible, especially when it comes to negotiating cryptographic algorithms. 🔄✨ Here are the major changes:

  1. The EAP method name changed from EAP-FAST to TEAP, which means a new EAP Type has to be assigned. 🏷️
  2. This version of TEAP MUST support TLS 1.2 [RFC5246]. 🔐
  3. The key derivation now uses TLS keying material exporters [RFC5705] and the PRF and hash function negotiated in TLS. This keeps implementation simple and supports cryptographic algorithm agility even better. 🧠💖
  4. TEAP is in full conformance with the TLS ticket extension [RFC5077], as described in Section 3.2.2. 🎫
  5. Support is provided for passing optional Outer TLVs in the first two message exchanges, on top of the Authority-ID TLV data that EAP-FAST already had. 📬
  6. Basic password authentication on the TLV level has been added, alongside the existing inner EAP method. 🔑🌈
  7. Additional TLV types have been defined to support EAP channel binding and metadata. They are the Identity-Type TLV and Channel-Binding TLVs, defined in Section 4.2. 🧩🌸

Appendix C. Examples

C.1. Successful Authentication

Let's look at a successful TEAP authentication with basic password authentication and optional PAC refreshment. 🥳 The conversation goes like this:

    Authenticating Peer     Authenticator
    -------------------     -------------
                            <- EAP-Request/
                            Identity
    EAP-Response/
    Identity (MyID1) ->

                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TEAP Start, S bit set, Authority-ID)

    EAP-Response/
    EAP-Type=TEAP, V=1
    (TLS client_hello with
     PAC-Opaque in SessionTicket extension)->

                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TLS server_hello,
                            (TLS change_cipher_spec,
                             TLS finished)

    EAP-Response/
    EAP-Type=TEAP, V=1 ->
    (TLS change_cipher_spec,
     TLS finished)

    TLS channel established
    (messages sent within the TLS channel)

                           <- Basic-Password-Auth-Req TLV, Challenge

    Basic-Password-Auth-Resp TLV, Response with both
    username and password) ->

    optional additional exchanges (new pin mode,
    password change, etc.) ...

                         <- Crypto-Binding TLV (Request),
                             Result TLV (Success),
                             (Optional PAC TLV)

    Crypto-Binding TLV(Response),
    Result TLV (Success),
    (PAC-Acknowledgement TLV) ->

    TLS channel torn down
    (messages sent in cleartext)

                            <- EAP-Success

C.2. Failed Authentication

Now the sad version 😭: this one shows a failed TEAP authentication because of wrong user credentials. Here's how that conversation goes:

    Authenticating Peer     Authenticator
    -------------------     -------------
                            <- EAP-Request/Identity

    EAP-Response/
    Identity (MyID1) ->


                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TEAP Start, S bit set, Authority-ID)

    EAP-Response/
    EAP-Type=TEAP, V=1
    (TLS client_hello with
     PAC-Opaque in SessionTicket extension)->

                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TLS server_hello,
                            (TLS change_cipher_spec,
                             TLS finished)

    EAP-Response/
    EAP-Type=TEAP, V=1 ->
    (TLS change_cipher_spec,
     TLS finished)

    TLS channel established
    (messages sent within the TLS channel)

                           <- Basic-Password-Auth-Req TLV, Challenge

    Basic-Password-Auth-Resp TLV, Response with both
    username and password) ->

                            <- Result TLV (Failure)

    Result TLV (Failure) ->

    TLS channel torn down
    (messages sent in cleartext)

                            <- EAP-Failure

C.3. Full TLS Handshake Using Certificate-Based Ciphersuite ✨

okay so picture this 🎀 in TEAP Phase 1, the peer first tries the quick abbreviated TLS handshake, it flops, and everyone falls back to the full certificate-based TLS handshake. here's how the chat goes 💅

      Authenticating Peer    Authenticator
      -------------------    -------------
                             <- EAP-Request/Identity
      EAP-Response/
      Identity (MyID1) ->

      // Identity sent in the clear.  May be a hint to help route
         the authentication request to EAP server, instead of the
         full user identity.

                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TEAP Start, S bit set, Authority-ID)
      EAP-Response/
      EAP-Type=TEAP, V=1
      (TLS client_hello with
      PAC-Opaque in SessionTicket extension)->

      // Peer sends PAC-Opaque of Tunnel PAC along with a list of
         ciphersuites supported.  If the server rejects the PAC-
         Opaque, it falls through to the full TLS handshake.

                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS server_hello,
                               TLS certificate,
                              [TLS server_key_exchange,]
                              [TLS certificate_request,]
                               TLS server_hello_done)

      EAP-Response/
      EAP-Type=TEAP, V=1
      ([TLS certificate,]
       TLS client_key_exchange,
      [TLS certificate_verify,]
       TLS change_cipher_spec,
       TLS finished) ->
                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS change_cipher_spec,
                               TLS finished,
                               EAP-Payload-TLV[EAP-Request/
                               Identity])

      // TLS channel established
         (messages sent within the TLS channel)

      // First EAP Payload TLV is piggybacked to the TLS Finished as
         Application Data and protected by the TLS tunnel.

      EAP-Payload-TLV
      [EAP-Response/Identity (MyID2)]->

      // identity protected by TLS.

                               <- EAP-Payload-TLV
                               [EAP-Request/EAP-Type=X]

      EAP-Payload-TLV
      [EAP-Response/EAP-Type=X] ->

      // Method X exchanges followed by Protected Termination

                           <- Intermediate-Result-TLV (Success),
                               Crypto-Binding TLV (Request),
                               Result TLV (Success)

      Intermediate-Result-TLV (Success),
      Crypto-Binding TLV (Response),
      Result-TLV (Success) ->

      // TLS channel torn down
      (messages sent in cleartext)

                              <- EAP-Success

C.4. Client Authentication during Phase 1 with Identity Privacy 🔐

so this one is for when a certificate-based TLS handshake happens inside TEAP Phase 1, and the client wants both certificate authentication AND identity privacy 🙈 that means TLS renegotiation is what carries the peer credentials through the protected TLS tunnel. the conversation goes like this:

      Authenticating Peer     Authenticator
      -------------------     -------------
                             <- EAP-Request/Identity
      EAP-Response/
      Identity (MyID1) ->

      // Identity sent in the clear.  May be a hint to help route
         the authentication request to EAP server, instead of the
         full user identity.

                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TEAP Start, S bit set, Authority-ID)
      EAP-Response/
      EAP-Type=TEAP, V=1
      (TLS client_hello)->
                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS server_hello,
                               TLS certificate,
                              [TLS server_key_exchange,]
                              [TLS certificate_request,]
                               TLS server_hello_done)
      EAP-Response/
      EAP-Type=TEAP, V=1
      (TLS client_key_exchange,
       TLS change_cipher_spec,
       TLS finished) ->
                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS change_cipher_spec,
                               TLS finished,
                               EAP-Payload-TLV[EAP-Request/
                               Identity])

      // TLS channel established
         (EAP Payload messages sent within the TLS channel)

      // peer sends TLS client_hello to request TLS renegotiation
      TLS client_hello ->

                              <- TLS server_hello,
                               TLS certificate,
                               [TLS server_key_exchange,]
                               [TLS certificate_request,]
                               TLS server_hello_done
      [TLS certificate,]
       TLS client_key_exchange,
      [TLS certificate_verify,]
       TLS change_cipher_spec,
       TLS finished ->

                              <- TLS change_cipher_spec,
                                 TLS finished,
                                 Crypto-Binding TLV (Request),
                                 Result TLV (Success)

      Crypto-Binding TLV (Response),
      Result-TLV (Success)) ->

      //TLS channel torn down
      (messages sent in cleartext)

                              <- EAP-Success

C.5. Fragmentation and Reassembly 🧩

last one, and it's the big-message glow-up 🌈 this is the convo for when TEAP fragmentation is needed, so the messages get chopped up and stitched back together:

      Authenticating Peer     Authenticator
      -------------------     -------------
                              <- EAP-Request/
                              Identity
      EAP-Response/
      Identity (MyID) ->
                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TEAP Start, S bit set, Authority-ID)

      EAP-Response/
      EAP-Type=TEAP, V=1
      (TLS client_hello)->

                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS server_hello,
                               TLS certificate,
                              [TLS server_key_exchange,]
                              [TLS certificate_request,]
                               TLS server_hello_done)
                              (Fragment 1: L, M bits set)

      EAP-Response/
      EAP-Type=TEAP, V=1 ->

                              <- EAP-Request/
                                 EAP-Type=TEAP, V=1
                              (Fragment 2: M bit set)
      EAP-Response/
      EAP-Type=TEAP, V=1 ->
                              <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (Fragment 3)
      EAP-Response/
      EAP-Type=TEAP, V=1
      ([TLS certificate,]
       TLS client_key_exchange,
      [TLS certificate_verify,]
       TLS change_cipher_spec,
       TLS finished)
       (Fragment 1: L, M bits set)->

                               <- EAP-Request/
                              EAP-Type=TEAP, V=1
      EAP-Response/
      EAP-Type=TEAP, V=1
      (Fragment 2)->
                             <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS change_cipher_spec,
                               TLS finished,
                              [EAP-Payload-TLV[
                              EAP-Request/Identity]])

      // TLS channel established
         (messages sent within the TLS channel)

      // First EAP Payload TLV is piggybacked to the TLS Finished as
         Application Data and protected by the TLS tunnel.

      EAP-Payload-TLV
      [EAP-Response/Identity (MyID2)]->

      // identity protected by TLS.

                               <- EAP-Payload-TLV
                               [EAP-Request/EAP-Type=X]

      EAP-Payload-TLV
      [EAP-Response/EAP-Type=X] ->

      // Method X exchanges followed by Protected Termination

                           <- Intermediate-Result-TLV (Success),
                               Crypto-Binding TLV (Request),
                               Result TLV (Success)

      Intermediate-Result-TLV (Success),
      Crypto-Binding TLV (Response),
      Result-TLV (Success) ->

      // TLS channel torn down
      (messages sent in cleartext)

                              <- EAP-Success

C.6. Sequence of EAP Methods 🧚

okay bestie, here's how the convo goes when TEAP is negotiated with a sequence of EAP method X followed by method Y 💅

   Authenticating Peer     Authenticator
   -------------------     -------------
                           <- EAP-Request/
                              Identity
   EAP-Response/
   Identity (MyID1) ->
                           <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TEAP Start, S bit set, Authority-ID)

   EAP-Response/
   EAP-Type=TEAP, V=1
   (TLS client_hello)->

                           <- EAP-Request/
                              EAP-Type=TEAP, V=1
                              (TLS server_hello,
                               TLS certificate,
                              [TLS server_key_exchange,]
                              [TLS certificate_request,]
                               TLS server_hello_done)
   EAP-Response/
   EAP-Type=TEAP, V=1
   ([TLS certificate,]
    TLS client_key_exchange,
   [TLS certificate_verify,]
    TLS change_cipher_spec,
    TLS finished) ->
                          <- EAP-Request/
                             EAP-Type=TEAP, V=1
                             (TLS change_cipher_spec,
                              TLS finished,
                              Identity-Type TLV,
                             EAP-Payload-TLV[
                             EAP-Request/Identity])

   // TLS channel established
      (messages sent within the TLS channel)

   // First EAP Payload TLV is piggybacked to the TLS Finished as
      Application Data and protected by the TLS tunnel

   Identity_Type TLV
   EAP-Payload-TLV
   [EAP-Response/Identity] ->

                           <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X] ->

          // Optional additional X Method exchanges...

                          <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X]->

                           <- Intermediate Result TLV (Success),
                            Crypto-Binding TLV (Request),
                            Identity-Type TLV,
                            EAP Payload TLV [EAP-Type=Y],

   // Next EAP conversation started after successful completion
      of previous method X.  The Intermediate-Result and Crypto-
      Binding TLVs are sent in next packet to minimize round
      trips.  In this example, an identity request is not sent
      before negotiating EAP-Type=Y.

   // Compound MAC calculated using keys generated from
      EAP method X and the TLS tunnel.

   Intermediate Result TLV (Success),
   Crypto-Binding TLV (Response),
   EAP-Payload-TLV [EAP-Type=Y] ->

          // Optional additional Y Method exchanges...

                          <- EAP Payload TLV [
                          EAP-Type=Y]

   EAP Payload TLV
   [EAP-Type=Y] ->

                          <- Intermediate-Result-TLV (Success),
                            Crypto-Binding TLV (Request),
                            Result TLV (Success)

   Intermediate-Result-TLV (Success),
   Crypto-Binding TLV (Response),
   Result-TLV (Success) ->

   // Compound MAC calculated using keys generated from EAP
      methods X and Y and the TLS tunnel.  Compound keys are
      generated using keys generated from EAP methods X and Y
      and the TLS tunnel.

   // TLS channel torn down (messages sent in cleartext)

                           <- EAP-Success

C.7. Failed Crypto-Binding 💔

these exchanges show what happens when the crypto-binding validation fails 🙈 the convo goes like this:

   Authenticating Peer     Authenticator
   -------------------     -------------
                           <- EAP-Request/
                           Identity
   EAP-Response/
   Identity (MyID1) ->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TEAP Start, S bit set, Authority-ID)

   EAP-Response/
   EAP-Type=TEAP, V=1
   (TLS client_hello without
   PAC-Opaque in SessionTicket extension)->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS Server Key Exchange
                            TLS Server Hello Done)
   EAP-Response/
   EAP-Type=TEAP, V=1 ->
   (TLS Client Key Exchange
    TLS change_cipher_spec,
    TLS finished)

                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS change_cipher_spec
                            TLS finished)
                            EAP-Payload-TLV[
                            EAP-Request/Identity])

      // TLS channel established
         (messages sent within the TLS channel)

      // First EAP Payload TLV is piggybacked to the TLS Finished as
         Application Data and protected by the TLS tunnel.

   EAP-Payload TLV/
   EAP Identity Response ->

                          <-  EAP Payload TLV, EAP-Request,
                              (EAP-MSCHAPV2, Challenge)

   EAP Payload TLV, EAP-Response,
   (EAP-MSCHAPV2, Response) ->

                          <-  EAP Payload TLV, EAP-Request,
                              (EAP-MSCHAPV2, Success Request)

   EAP Payload TLV, EAP-Response,
   (EAP-MSCHAPV2, Success Response) ->

                        <- Intermediate-Result-TLV (Success),
                            Crypto-Binding TLV (Request),
                               Result TLV (Success)

      Intermediate-Result-TLV (Success),
      Result TLV (Failure)
      Error TLV with
      (Error Code = 2001) ->

   // TLS channel torn down
      (messages sent in cleartext)

                           <- EAP-Failure

C.8. Sequence of EAP Method with Vendor-Specific TLV Exchange 🎀

this one is a sequence of EAP methods followed by a Vendor-Specific TLV exchange ✨ when TEAP is negotiated like that, the convo goes:

   Authenticating Peer     Authenticator
   -------------------     -------------
                           <- EAP-Request/
                           Identity
   EAP-Response/
   Identity (MyID1) ->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TEAP Start, S bit set, Authority-ID)

   EAP-Response/
   EAP-Type=TEAP, V=1
   (TLS client_hello)->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS server_hello,
                            TLS certificate,
                    [TLS server_key_exchange,]
                    [TLS certificate_request,]
                        TLS server_hello_done)

   EAP-Response/
   EAP-Type=TEAP, V=1
   ([TLS certificate,]
    TLS client_key_exchange,
   [TLS certificate_verify,]
    TLS change_cipher_spec,
    TLS finished) ->
                          <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS change_cipher_spec,
                            TLS finished,
                           EAP-Payload-TLV[
                           EAP-Request/Identity])

   // TLS channel established
      (messages sent within the TLS channel)

   // First EAP Payload TLV is piggybacked to the TLS Finished as
      Application Data and protected by the TLS tunnel.

   EAP-Payload-TLV
   [EAP-Response/Identity] ->

                         <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X] ->

                          <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X]->

                           <- Intermediate Result TLV (Success),
                            Crypto-Binding TLV (Request),
                            Vendor-Specific TLV,

   // Vendor-Specific TLV exchange started after successful
      completion of previous method X.  The Intermediate-Result
      and Crypto-Binding TLVs are sent with Vendor-Specific TLV
      in next packet to minimize round trips.

   // Compound MAC calculated using keys generated from
      EAP method X and the TLS tunnel.

   Intermediate Result TLV (Success),
   Crypto-Binding TLV (Response),
   Vendor-Specific TLV ->

       // Optional additional Vendor-Specific TLV exchanges...

                          <- Vendor-Specific TLV

   Vendor-Specific TLV ->
                          <- Result TLV (Success)

   Result-TLV (Success) ->

   // TLS channel torn down (messages sent in cleartext)

                           <- EAP-Success

C.9. Peer Requests Inner Method after Server Sends Result TLV 🦋

this is the plot twist era 😭 in this case the peer is authenticated during Phase 1 and the server sends back a Result TLV, but the peer still wants to request another inner method. the convo looks like this:

   Authenticating Peer    Authenticator
   -------------------    -------------
                          <- EAP-Request/Identity
   EAP-Response/
   Identity (MyID1) ->

   // Identity sent in the clear.  May be a hint to help route
      the authentication request to EAP server, instead of the
      full user identity.

                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TEAP Start, S bit set, Authority-ID)
   EAP-Response/
   EAP-Type=TEAP, V=1
   (TLS client_hello)->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS server_hello,
                            TLS certificate,
                           [TLS server_key_exchange,]
                           [TLS certificate_request,]
                            TLS server_hello_done)

   EAP-Response/
   EAP-Type=TEAP, V=1
   [TLS certificate,]
    TLS client_key_exchange,
   [TLS certificate_verify,]
    TLS change_cipher_spec,
    TLS finished ->
                           <- EAP-Request/
                           EAP-Type=TEAP, V=1
                           (TLS change_cipher_spec,
                            TLS finished,
                            Crypto-Binding TLV (Request),
                             Result TLV (Success))

   // TLS channel established
      (TLV Payload messages sent within the TLS channel)

    Crypto-Binding TLV(Response),
    Request-Action TLV
    (Status=Failure, Action=Negotiate-EAP)->

                         <- EAP-Payload-TLV
                             [EAP-Request/Identity]

   EAP-Payload-TLV
   [EAP-Response/Identity] ->

                         <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X] ->

                          <- EAP-Payload-TLV
                         [EAP-Request/EAP-Type=X]

   EAP-Payload-TLV
   [EAP-Response/EAP-Type=X]->

                           <- Intermediate Result TLV (Success),
                              Crypto-Binding TLV (Request),
                              Result TLV (Success)

   Intermediate Result TLV (Success),
   Crypto-Binding TLV (Response),
   Result-TLV (Success)) ->
   // TLS channel torn down
   (messages sent in cleartext)

                           <- EAP-Success

C.10. Channel Binding ✨

okay so this one is giving full main character energy 💅 It shows a successful TEAP authentication using basic password authentication and channel binding, with a Request-Action TLV doing the heavy lifting. Here's how the conversation plays out 🦋

    Authenticating Peer     Authenticator
    -------------------     -------------
                            <- EAP-Request/
                            Identity
    EAP-Response/
    Identity (MyID1) ->

                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TEAP Start, S bit set, Authority-ID)

    EAP-Response/
    EAP-Type=TEAP, V=1
    (TLS client_hello with
     PAC-Opaque in SessionTicket extension)->

                            <- EAP-Request/
                            EAP-Type=TEAP, V=1
                            (TLS server_hello,
                            (TLS change_cipher_spec,
                             TLS finished)

    EAP-Response/
    EAP-Type=TEAP, V=1 ->
    (TLS change_cipher_spec,
     TLS finished)

    TLS channel established
    (messages sent within the TLS channel)

                           <- Basic-Password-Auth-Req TLV, Challenge

    Basic-Password-Auth-Resp TLV, Response with both
    username and password) ->

    optional additional exchanges (new pin mode,
    password change, etc.) ...

                         <- Crypto-Binding TLV (Request),
                             Result TLV (Success),

    Crypto-Binding TLV(Response),
    Request-Action TLV
    (Status=Failure, Action=Process-TLV,
     TLV=Channel-Binding TLV)->

                             <- Channel-Binding TLV (Response),
                             Result TLV (Success),

    Result-TLV (Success) ->

    TLS channel torn down
    (messages sent in cleartext)

                            <- EAP-Success

Authors' Addresses 🎀

these are the squad who wrote it, so here are their deets 🫶

Hao Zhou
Cisco Systems
4125 Highlander Parkway
Richfield, OH  44286
US

EMail: hzhou@cisco.com
Nancy Cam-Winget
Cisco Systems
3625 Cisco Way
San Jose, CA  95134
US

EMail: ncamwing@cisco.com
Joseph Salowey
Cisco Systems
2901 3rd Ave
Seattle, WA  98121
US

EMail: jsalowey@cisco.com
Stephen Hanna
Infineon Technologies
79 Parsons Street
Brighton, MA  02135
US

EMail: steve.hanna@infineon.com

that's the whole RFC, bestie 🌈👑

📦 where this page comes from