RFC 4366

Transport Layer Security (TLS) Extensions

πŸ“… published April 2006, from ietf

RFC 4366: Transport Layer Security (TLS) Extensions πŸ’–

Okay bestie, let's get into it! πŸŽ€ This is RFC 4366, published in April 2006 by the Network Working Group. It's a Standards Track doc, so it's an actual official spec. πŸ¦‹

The authors are S. Blake-Wilson (BCI), M. Nystrom (RSA Security), D. Hopwood (Independent Consultant), J. Mikkelsen (Transactionware), and T. Wright (Vodafone). The whole squad! πŸ‘‘

It obsoletes RFC 3546 and updates RFC 4346. Obsoletes means this one replaces 3546, and updates means it adds to 4346 without replacing it. Ngl, that's a lot of paperwork, but it's how the Internet keeps track of what's current. 🧚


Status of This Memo ✨

Okay so this part is basically the official label. This document is an Internet standards track protocol for the Internet community, and it wants discussion and suggestions for improvements. πŸ’…

If you want to know the current standardization state and status of this protocol, check the current edition of the "Internet Official Protocol Standards" (STD 1). Also, distribution of this memo is unlimited, so share it with everyone! 🌸

Copyright (C) The Internet Society (2006). That's it, that's the drama. πŸ™ˆ

Abstract πŸ¦‹

This doc is all about extensions that can add functionality to Transport Layer Security (TLS). It gives you two things: generic extension mechanisms for the TLS handshake client and server hellos, and specific extensions that use those generic mechanisms. Main character energy! ✨

The extensions can be used by TLS clients and servers. The best part is that they're backwards compatible, so a TLS client that supports them can still talk to a TLS server that doesn't, and the other way around. No one gets left on read! πŸ’œ

Table of Contents πŸ“š

   1. Introduction ....................................................3
      1.1. Conventions Used in This Document ..........................5
   2. General Extension Mechanisms ....................................5
      2.1. Extended Client Hello ......................................5
      2.2. Extended Server Hello ......................................6
      2.3. Hello Extensions ...........................................6
      2.4. Extensions to the Handshake Protocol .......................8
   3. Specific Extensions .............................................8
      3.1.  Server Name Indication ....................................9
      3.2.  Maximum Fragment Length Negotiation ......................11
      3.3.  Client Certificate URLs ..................................12
      3.4.  Trusted CA Indication ....................................15
      3.5. Truncated HMAC ............................................16
      3.6. Certificate Status Request ................................17
   4. Error Alerts ...................................................19
   5. Procedure for Defining New Extensions ..........................20
   6. Security Considerations ........................................21
      6.1. Security of server_name ...................................22
      6.2. Security of max_fragment_length ...........................22
      6.3. Security of client_certificate_url ........................22
      6.4. Security of trusted_ca_keys ...............................24
      6.5. Security of truncated_hmac ................................24
      6.6. Security of status_request ................................25
   7. Internationalization Considerations ............................25
   8. IANA Considerations ............................................25
   9. Acknowledgements ...............................................27
   10. Normative References ..........................................27
   11. Informative References ........................................28

1. Introduction 🌈

Okay so this section is the "why we're doing this" part. This doc describes extensions that can add functionality to Transport Layer Security (TLS). It gives generic extension mechanisms for the TLS handshake client and server hellos, plus specific extensions built on those mechanisms. ✨

TLS is now used in a ton of operational environments that the original design criteria never imagined. The extensions in this doc are meant to help TLS work as well as possible in new places, like wireless networks. πŸ¦‹

Wireless environments are kind of a mess, ngl. They often deal with constraints that wired ones don't, like bandwidth limits, computational power limits, memory limits, and battery life limits. Your phone is really out here struggling! πŸ™ˆ

The extensions here focus on extending what the TLS protocol message formats can do. Other stuff, like adding new cipher suites, is deferred for now. πŸ’…

Specifically, these extensions:

  • Allow TLS clients to provide to the TLS server the name of the server they are contacting. This is useful for making secure connections to servers that host multiple 'virtual' servers at a single underlying network address. πŸŽ€
  • Allow TLS clients and servers to negotiate the maximum fragment length to be sent. This is useful because some clients have memory constraints, and some access networks have bandwidth constraints. πŸ“
  • Allow TLS clients and servers to negotiate the use of client certificate URLs. This is useful for conserving memory on constrained clients. 🧚
  • Allow TLS clients to indicate to TLS servers which CA root keys they possess. This is useful for preventing multiple handshake failures involving TLS clients that can only store a small number of CA root keys because of memory limits. πŸ”₯
  • Allow TLS clients and servers to negotiate the use of truncated MACs. This is useful for conserving bandwidth in constrained access networks. πŸ’œ
  • Allow TLS clients and servers to negotiate that the server sends the client certificate status information (for example, an Online Certificate Status Protocol (OCSP) [OCSP] response) during a TLS handshake. This is useful for avoiding sending a Certificate Revocation List (CRL) over a constrained access network, which saves bandwidth. πŸ‘‘

To support all of the above, general extension mechanisms for the client hello message and the server hello message are introduced. Iconic! ⭐

The extensions in this doc may be used by TLS clients and servers. They're designed to be backwards compatible, meaning TLS clients that support the extensions can talk to TLS servers that don't, and vice versa. Because of this, the doc updates TLS 1.0 [TLS] and TLS 1.1 [TLSbis]. 🫢

Backwards compatibility mainly comes from two things:

  • Clients typically request the use of extensions via the extended client hello message described in Section 2.1. TLS requires servers to accept extended client hello messages, even if the server does not "understand" the extension. 🌸
  • For the specific extensions described here, no mandatory server response is required when clients request extended functionality. πŸ’…

Basically, backwards compatibility works because of a TLS requirement: servers that aren't "extensions-aware" ignore data added to client hellos that they don't recognize. For an example, see Section 7.4.1.2 of [TLS]. Not gonna lie, that's a genius move. 🧠✨

Note, however, that even though backwards compatibility is supported, some constrained clients may be forced to reject communications with servers that don't support the extensions, because of their limited capabilities. Real talk, that's a tradeoff. πŸ™ˆ

This document is a revision of the RFC3546 [RFC3546]. The only major change is how new extensions get defined. New extensions can now be defined via the IETF Consensus Process, rather than requiring a standards track RFC. A few minor clarifications and editorial improvements were also made. πŸ¦‹

Here's how the rest of the doc is organized. Section 2 describes general extension mechanisms for the client hello and server hello handshake messages. Section 3 describes specific extensions to TLS. Section 4 describes new error alerts for use with the TLS extensions. The final sections cover IPR, security considerations, registration of the application/pkix-pkipath MIME type, acknowledgements, and references. πŸ“š

1.1. Conventions Used in This Document 🫧

Here's the key-words part, bestie. The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14, RFC 2119 [KEYWORDS]. These words are capitalized on purpose, so pay attention when you see them! πŸ‘€


2. General Extension Mechanisms 🧩

This section is where the general extension mechanisms for the TLS handshake client hello and server hello messages live. ✨

These general mechanisms are needed so clients and servers can negotiate whether to use specific extensions, and how to use them. The extension formats are based on [MAILINGLIST]. πŸ’œ

Section 2.1 specifies the extended client hello message format, Section 2.2 specifies the extended server hello message format, and Section 2.3 describes the actual extension format used with the extended client and server hellos. Let's go! πŸš€

2.1. Extended Client Hello πŸ’Œ

Clients MAY request extended functionality from servers by sending the extended client hello message format in place of the client hello message format. The extended client hello message format looks like this:

      struct {
          ProtocolVersion client_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suites<2..2^16-1>;
          CompressionMethod compression_methods<1..2^8-1>;
          Extension client_hello_extension_list<0..2^16-1>;
      } ClientHello;

Here the new "client_hello_extension_list" field contains a list of extensions. The actual "Extension" format is defined in Section 2.3. πŸŽ€

If a client asks for extra functionality using the extended client hello, and the server doesn't supply it, the client MAY abort the handshake. Fair enough, right? πŸ™ˆ

Note that [TLS], Section 7.4.1.2, allows additional information to be added to the client hello message. So using the extended client hello defined above should not "break" existing TLS servers. Phew! 🫢

A server that supports the extensions mechanism MUST accept only client hello messages in either the original or extended ClientHello format. And (as for all other messages) it MUST check that the amount of data in the message precisely matches one of these formats. If it doesn't, then it MUST send a fatal "decode_error" alert. This overrides the "Forward compatibility note" in [TLS]. Strict, but iykyk, it keeps things honest. πŸ‘‘β­


Part 1 of 6 done, bestie! πŸ’– More parts coming next, so stay tuned 🌸

2.2. Extended Server Hello ✨

okay so the extended server hello message format MAY be sent instead of the regular server hello, but only when the client asked for extra features using the extended client hello from Section 2.1 πŸŽ€ here's the layout:

   struct {
       ProtocolVersion server_version;
       Random random;
       SessionID session_id;
       CipherSuite cipher_suite;
       CompressionMethod compression_method;
       Extension server_hello_extension_list<0..2^16-1>;
   } ServerHello;

the new server_hello_extension_list field is where the list of extensions lives 🧚 the actual Extension format is explained in Section 2.3.

and this is the important bit, bestie πŸ’… the extended server hello is ONLY sent in response to an extended client hello. that's how it avoids the risk of accidentally "breaking" existing TLS clients 😭 iconic protection, honestly.

2.3. Hello Extensions πŸ¦‹

every extension, in both extended client hellos and extended server hellos, uses this format:

   struct {
       ExtensionType extension_type;
       opaque extension_data<0..2^16-1>;
   } Extension;

so basically:

  • extension_type tells you which extension it is πŸ”₯
  • extension_data holds the info that's specific to that extension type πŸ“

the extension types defined in this document are:

   enum {
       server_name(0), max_fragment_length(1),
       client_certificate_url(2), trusted_ca_keys(3),
       truncated_hmac(4), status_request(5), (65535)
   } ExtensionType;

the list of defined extension types is kept by the IANA, and the current one is at http://www.iana.org/assignments/tls-extensiontype-values. if you want the details on how new values get added, check out Sections 5 and 8 🌈

now, the big rule πŸ‘‘ for ALL extension types (even future ones), the extension type MUST NOT appear in the extended server hello unless that same type showed up in the matching client hello. so clients MUST abort the handshake if they get an extension type in the extended server hello that they never asked for in the associated (extended) client hello. no cap, that's a hard boundary ⭐

that said, "server-oriented" extensions might show up later in this framework πŸ‘€ the way that would work: such an extension (say, of type x) would need the client to first send an extension of type x in the (extended) client hello with empty extension_data, just to say "hey, I support this type." the client is basically offering the ability to understand the extension type, and the server is taking the client up on that offer 🫢

also, when there are multiple extensions of different types in the extended client hello or the extended server hello, they can show up in any order πŸ’– BUT there MUST NOT be more than one extension of the same type. literally no duplicates, periodt πŸ™…β€β™€οΈ

last one: an extended client hello can be sent both when starting a new session AND when asking to resume one ✨ a client asking to resume doesn't generally know if the server will say yes, so it SHOULD send an extended client hello if it would normally do that for a new session. and in general, the spec for each extension type has to talk about what the extension does during new sessions AND during resumed sessions 🧚

2.4. Extensions to the Handshake Protocol 🌸

this document suggests two new handshake messages: "CertificateURL" and "CertificateStatus" πŸ’œ they're described in Section 3.3 and Section 3.6 respectively. so the new handshake message structure becomes:

   enum {
       hello_request(0), client_hello(1), server_hello(2),
       certificate(11), server_key_exchange (12),
       certificate_request(13), server_hello_done(14),
       certificate_verify(15), client_key_exchange(16),
       finished(20), certificate_url(21), certificate_status(22),
       (255)
   } HandshakeType;

   struct {
       HandshakeType msg_type;    /* handshake type */
       uint24 length;             /* bytes in message */
       select (HandshakeType) {
           case hello_request:       HelloRequest;
           case client_hello:        ClientHello;
           case server_hello:        ServerHello;
           case certificate:         Certificate;
           case server_key_exchange: ServerKeyExchange;
           case certificate_request: CertificateRequest;
           case server_hello_done:   ServerHelloDone;
           case certificate_verify:  CertificateVerify;
           case client_key_exchange: ClientKeyExchange;
           case finished:            Finished;
           case certificate_url:     CertificateURL;
           case certificate_status:  CertificateStatus;
       } body;
   } Handshake;

3. Specific Extensions πŸŽ€

this section covers the specific TLS extensions that this document defines πŸ’…

first, a must-know: any messages tied to these extensions that get sent during the TLS handshake MUST be included in the hash calculations used for "Finished" messages πŸ”₯

also, all the extensions in this section only matter when a session is being initiated 🧚 so if a client puts one or more of the defined extension types in an extended client hello while asking to resume a session:

  • if the resumption request gets denied, the extensions are negotiated as normal πŸ¦‹
  • if the older session IS resumed, then the server MUST ignore the extensions and send a server hello containing none of the extension types πŸ‘€ the functionality that was negotiated during the original session initiation gets applied to the resumed session instead ✨

quick map of what's coming: Section 3.1 is about letting a client say which server it's contacting. Section 3.2 is about maximum fragment length negotiation. Section 3.3 is about client certificate URLs. Section 3.4 is about letting a client say which CA root keys it has. Section 3.5 is about truncated HMAC. And Section 3.6 is about bringing certificate status info into TLS handshakes 🌈

3.1. Server Name Indication 🌸

okay so the problem: TLS has no way for a client to tell a server which server name it's trying to reach 😭 that's a real issue, because a lot of servers host multiple "virtual" servers at one single network address, and clients need a way to get secure connections to the right one. so this is the fix πŸ’–

to provide the server name, clients MAY include an extension of type "server_name" in the (extended) client hello. its "extension_data" field SHALL contain a "ServerNameList", and it's structured like this:

   struct {
       NameType name_type;
       select (name_type) {
           case host_name: HostName;
       } name;
   } ServerName;

   enum {
       host_name(0), (255)
   } NameType;

   opaque HostName<1..2^16-1>;

   struct {
       ServerName server_name_list<1..2^16-1>
   } ServerNameList;

right now, the only server names supported are DNS hostnames 🧚 BUT this doesn't mean TLS depends on DNS, and other name types might get added later (by an RFC that updates this document) ✨ TLS MAY treat the provided server names as opaque data and just pass the names and types along to the application 🫢

"HostName" is the fully qualified DNS hostname of the server, as the client understands it πŸ’… it's a byte string in UTF-8 encoding [UTF8], and it has no trailing dot πŸ“

here's where it gets detailed, so pay attention bestie πŸ™ˆ if the hostname labels only contain US-ASCII characters, then the client MUST make sure the labels are separated ONLY by the byte 0x2E, which is the dot character U+002E (requirement 1 in Section 3.1 of [IDNA] notwithstanding) πŸ”₯ if the server needs to match the HostName against names that contain non-US-ASCII characters, it MUST do the conversion operation described in Section 4 of [IDNA], treating the HostName as a "query string" (so the AllowUnassigned flag MUST be set) πŸ’œ side note that IDNA lets labels be separated by any of the Unicode characters U+002E, U+3002, U+FF0E, and U+FF61, so servers MUST accept any of those as a label separator πŸ‘‘ and if the server only needs to match names made of exclusively ASCII characters, it MUST compare ASCII names case-insensitively 🌈

literal IPv4 and IPv6 addresses are not permitted in "HostName" πŸ™…β€β™€οΈ no addresses in this field, sorry not sorry.

it is RECOMMENDED that clients include an extension of type "server_name" in the client hello whenever they locate a server by a supported name type ✨ basically, always send it when you can πŸ’–

a server that gets a client hello with the "server_name" extension MAY use that info to help pick the right certificate to send back, and/or other parts of its security policy 🧚 when it does, the server SHALL include an extension of type "server_name" in the (extended) server hello, and that extension's "extension_data" field SHALL be empty πŸ¦‹

if the server understood the client hello extension but doesn't recognize the server name, it SHOULD send an "unrecognized_name" alert (which MAY be fatal) 😭 not ideal, but that's life.

last one, and it's a good one πŸŽ€ if an application negotiates a server name using an application protocol and THEN upgrades to TLS, and a server_name extension gets sent, then the extension SHOULD contain the same name that was negotiated in the application protocol πŸ’… and if the server_name is established in the TLS session handshake, the client SHOULD NOT try to request a different server name at the application layer πŸ™…β€β™€οΈ consistency is everything, periodt πŸ’–

3.2. Maximum Fragment Length Negotiation βœ‚οΈ

Okay so by default TLS just says the maximum plaintext fragment length is 2^14 bytes, and that's it πŸ™ƒ But constrained clients might be low on memory or bandwidth, so being able to negotiate something smaller is lowkey essential πŸ’…

To ask for a smaller limit, clients MAY include an extension of type max_fragment_length in the (extended) client hello. The extension_data field of this extension SHALL contain:

enum{
    2^9(1), 2^10(2), 2^11(3), 2^12(4), (255)
} MaxFragmentLength;

Whatever value goes in there is the maximum fragment length you want. The only allowed values are 2^9, 2^10, 2^11, and 2^12 πŸŽ€

Servers that get an extended client hello with a max_fragment_length extension MAY accept the request by putting an extension of type max_fragment_length in the (extended) server hello. The extension_data field of that one SHALL contain a MaxFragmentLength whose value matches the requested maximum fragment length 🫢

Now the drama. If a server gets a maximum fragment length request for a value that isn't one of the allowed values, it MUST abort the handshake with an illegal_parameter alert πŸ’€ Same deal on the client side: if a client gets a response that differs from the length it asked for, it MUST also abort the handshake with an illegal_parameter alert. No vibes, only rules 🌸

Once a maximum fragment length other than 2^14 has been successfully negotiated, the client and server MUST immediately begin fragmenting messages (including handshake messages), so that no fragment larger than the negotiated length gets sent. Also, TLS already requires clients and servers to support fragmentation of handshake messages, so this part is covered 🧚

The negotiated length sticks around for the whole session, including session resumptions πŸ‘‘

The negotiated length limits how much input the record layer can process without fragmenting it. That's the maximum value of TLSPlaintext.length, see [TLS], Section 6.2.1. Here's the twist: the record layer's output can be bigger than that 😭 For example, say the negotiated length is 2^9=512. For the cipher suites defined right now (those defined in [TLS], [KERB], and [AESSUITES]), and when null compression is used, the record layer output can be at most 793 bytes. That's 5 bytes of headers, 512 bytes of application data, 256 bytes of padding, and 20 bytes of MAC.

So in this case, a TLS record layer peer that receives a TLS record layer message bigger than 793 bytes may discard the message and send a record_overflow alert, all without decrypting the message. Not even reading it, bestie πŸ™ˆ

3.3. Client Certificate URLs πŸ¦‹

Without this extension, TLS says that when client authentication happens, clients send their client certificates to servers during the TLS handshake. Constrained clients might want to send certificate URLs instead, so they don't have to store their certificates and can save memory 🧠

To negotiate sending certificate URLs to a server, clients MAY include an extension of type client_certificate_url in the (extended) client hello. The extension_data field of this extension SHALL be empty.

(Note that it is necessary to negotiate use of client certificate URLs in order to avoid "breaking" existing TLS servers. Not optional, babe ⚠️)

Servers that get an extended client hello with a client_certificate_url extension MAY say they're willing to accept certificate URLs by including an extension of type client_certificate_url in the (extended) server hello. The extension_data field of this extension SHALL be empty.

Once negotiating certificate URLs has been completed successfully (by exchanging hellos that include client_certificate_url extensions), clients MAY send a CertificateURL message in place of a Certificate message ✨

   enum {
       individual_certs(0), pkipath(1), (255)
   } CertChainType;

   enum {
       false(0), true(1)
   } Boolean;
   struct {
       CertChainType type;
       URLAndOptionalHash url_and_hash_list<1..2^16-1>;
   } CertificateURL;

   struct {
       opaque url<1..2^16-1>;
       Boolean hash_present;
       select (hash_present) {
           case false: struct {};
           case true: SHA1Hash;
       } hash;
   } URLAndOptionalHash;

   opaque SHA1Hash[20];

Here, url_and_hash_list holds a sequence of URLs and optional hashes 🌈

When X.509 certificates are used, there are two options:

  • If CertificateURL.type is individual_certs, each URL refers to a single DER-encoded X.509v3 certificate, and the URL for the client's certificate comes first.
  • If CertificateURL.type is pkipath, the list holds one URL that refers to a DER-encoded certificate chain, using the PkiPath type described in Section 8.

When any other certificate format is used, the specification that describes using that format in TLS should define the encoding format of the certificates or certificate chains, plus any constraints on their ordering πŸ“œ

The hash for each URL is at the client's discretion. It's either not present, or it's the SHA-1 hash of the certificate or certificate chain (for X.509 certificates, that means the DER-encoded certificate or the DER-encoded PkiPath) πŸ”

Heads up on ordering: when a list of URLs for X.509 certificates is used, the URLs go in the same order as the TLS Certificate message (see [TLS], Section 7.4.2). That's the opposite of the order certificates are encoded in PkiPath πŸ™ƒ Either way, the self-signed root certificate MAY be omitted from the chain, on the assumption that the server must already have it in order to validate things 🫠

Servers receiving CertificateURL SHALL try to retrieve the client's certificate chain from the URLs, and then process the chain as usual. A cached copy of the content of any URL in the chain MAY be used, as long as a SHA-1 hash is present for that URL and it matches the hash of the cached copy πŸ’Ύ

Servers that support this extension MUST support the http: URL scheme for certificate URLs, and they MAY support other schemes. Using schemes other than http, https, or ftp may cause unexpected problems πŸ‘€

If the protocol being used is HTTP, the HTTP server can be set up to use the Cache-Control and Expires directives described in [HTTP] to say whether certificates or certificate chains should be cached, and for how long πŸ•°οΈ

The TLS server doesn't have to follow HTTP redirects when retrieving the certificates or certificate chain. So the URLs used in this extension SHOULD be picked so they don't depend on those redirects 🧭

If the protocol used to retrieve certificates or certificate chains returns a MIME-formatted response (like HTTP does), then these MIME Content-Types SHALL be used: when a single X.509v3 certificate comes back, the Content-Type is application/pkix-cert [PKIOP], and when a chain of X.509v3 certificates comes back, the Content-Type is application/pkix-pkipath (see Section 8) πŸŽ€

If a SHA-1 hash is present for a URL, the server MUST check that the SHA-1 hash of the contents of the object retrieved from that URL (after decoding any MIME Content-Transfer-Encoding) matches the given hash. If any retrieved object doesn't have the correct SHA-1 hash, the server MUST abort the handshake with a bad_certificate_hash_value alert 🚫

Clients can send either Certificate or CertificateURL after successfully negotiating the option to send certificate URLs. Having the option to send a certificate is there so clients with multiple certificates have some flexibility πŸ’œ

If a server runs into an unreasonable delay getting certificates from a given CertificateURL, it SHOULD time out and signal a certificate_unobtainable error alert ⏳


3.4. Trusted CA Indication πŸ”‘

Constrained clients that only have a small number of CA root keys (because of memory limits) might want to tell servers which root keys they've got, so they can avoid repeated handshake failures πŸ₯Ή

To say which CA root keys they have, clients MAY include an extension of type trusted_ca_keys in the (extended) client hello. The extension_data field of this extension SHALL contain TrustedAuthorities, where:

   struct {
       TrustedAuthority trusted_authorities_list<0..2^16-1>;
   } TrustedAuthorities;

   struct {
       IdentifierType identifier_type;
       select (identifier_type) {
           case pre_agreed: struct {};
           case key_sha1_hash: SHA1Hash;
           case x509_name: DistinguishedName;
           case cert_sha1_hash: SHA1Hash;
       } identifier;
   } TrustedAuthority;

   enum {
       pre_agreed(0), key_sha1_hash(1), x509_name(2),
       cert_sha1_hash(3), (255)
   } IdentifierType;

   opaque DistinguishedName<1..2^16-1>;

Here, TrustedAuthorities gives a list of CA root key identifiers that the client has. Each CA root key is identified in one of these ways 🌟

  • pre_agreed: no CA root key identity is supplied.
  • key_sha1_hash: contains the SHA-1 hash of the CA root key. For Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA) keys, this is the hash of the subjectPublicKey value. For RSA keys, the hash is of the big-endian byte string representation of the modulus, without any initial 0-valued bytes. (This copies the key hash formats deployed in other environments.)
  • x509_name: contains the DER-encoded X.509 DistinguishedName of the CA.
  • cert_sha1_hash: contains the SHA-1 hash of a DER-encoded Certificate containing the CA root key.

Clients can include none, some, or all of the CA root keys they have in this extension πŸ§ƒ

Also, a key hash or a Distinguished Name alone might not uniquely identify a certificate issuer (for example, if a particular CA has multiple key pairs). Still, we're assuming that's the case here, since TLS already uses Distinguished Names to identify certificate issuers πŸ€·β€β™€οΈ

The option to include no CA root keys is there so the client can say it has some pre-defined set of CA root keys πŸ’–

Servers that receive a client hello containing the trusted_ca_keys extension MAY use the information in it to guide their choice of an appropriate certificate chain to send back to the client. If they do, the server SHALL include an extension of type trusted_ca_keys in the (extended) server hello. The extension_data field of this extension SHALL be empty ✨

3.5. Truncated HMAC πŸ¦‹

okay so the cipher suites we've got right now use HMAC with either MD5 or SHA-1 [HMAC] to authenticate record layer stuff. TLS normally uses the entire hash output as the MAC tag, but in constrained environments you might want to save bandwidth by chopping that output down to 80 bits when forming MAC tags. πŸŽ€

To negotiate 80-bit truncated HMAC, clients MAY include an extension of type truncated_hmac in the extended client hello. Its extension_data field SHALL be empty. πŸ’…

Servers that get an extended hello with a truncated_hmac extension MAY agree to truncated HMAC by including an extension of type truncated_hmac, with empty extension_data, in the extended server hello. ✨

ngl this next bit is a big one πŸ™ˆ. If someone adds new cipher suites that don't use HMAC, and the session ends up negotiating one of them, this extension does literally nothing. It's strongly recommended that any new suites using other MACs treat the MAC size as an integral part of the cipher suite definition, weighing both security and bandwidth.

Once HMAC truncation has been successfully negotiated during a TLS handshake, and the negotiated cipher suite uses HMAC, both the client and the server pass this fact to the TLS record layer along with the other negotiated security parameters. From then on, clients and servers MUST use truncated HMACs, calculated as specified in [HMAC]. That means CipherSpec.hash_size is 10 bytes, and only the first 10 bytes of the HMAC output are transmitted and checked. πŸ”₯

Also, this extension doesn't touch the pseudo-random function (PRF) used for handshaking or key derivation. Totally separate vibes. 🌸

The negotiated HMAC truncation size sticks around for the whole session, including session resumptions. πŸ‘‘


3.6. Certificate Status Request 🧚

okay so constrained clients might want to use a certificate-status protocol like OCSP [OCSP] to check whether server certificates are still valid. The whole point is to avoid downloading CRLs and save bandwidth on constrained networks. This extension lets that info ride along in the TLS handshake, which saves roundtrips and resources. iconic πŸ’–

To say they want certificate status info, clients MAY include an extension of type status_request in the (extended) client hello. The extension_data field of this extension SHALL contain CertificateStatusRequest, which looks like this:

struct {
    CertificateStatusType status_type;
    select (status_type) {
        case ocsp: OCSPStatusRequest;
    } request;
} CertificateStatusRequest;

enum { ocsp(1), (255) } CertificateStatusType;

struct {
    ResponderID responder_id_list<0..2^16-1>;
    Extensions  request_extensions;
} OCSPStatusRequest;

opaque ResponderID<1..2^16-1>;
opaque Extensions<0..2^16-1>;

In the OCSPStatusRequest, the ResponderIDs give a list of OCSP responders that the client trusts. A zero-length responder_id_list has a special meaning: the responders are implicitly known to the server, like through a prior arrangement. Extensions is a DER encoding of OCSP request extensions. πŸŽ€

Both ResponderID and Extensions are DER-encoded ASN.1 types, as defined in [OCSP]. Extensions is imported from [PKIX]. A zero-length request_extensions value means there are no extensions. That's different from a zero-length ASN.1 SEQUENCE, which isn't valid for the Extensions type. πŸ™ƒ

For the id-pkix-ocsp-nonce OCSP extension, [OCSP] is kinda unclear about its encoding, so here's the clarification: the nonce MUST be a DER-encoded OCTET STRING, which gets encapsulated as another OCTET STRING. Implementations based on an existing OCSP client will need to be checked for conformance to this, so bestie, go check. πŸ‘€

Servers that receive a client hello containing the status_request extension MAY send a suitable certificate status response to the client along with their certificate. If OCSP is requested, they SHOULD use the information in the extension when picking an OCSP responder, and SHOULD include request_extensions in the OCSP request. πŸ’…

Servers send a certificate response along with their certificate by sending a CertificateStatus message immediately after the Certificate message (and before any ServerKeyExchange or CertificateRequest messages). If a server does return a CertificateStatus message, then the server MUST have included an extension of type status_request with empty extension_data in the extended server hello. no skipping this part, periodt πŸ’œ

struct {
    CertificateStatusType status_type;
    select (status_type) {
        case ocsp: OCSPResponse;
    } response;
} CertificateStatus;

opaque OCSPResponse<1..2^24-1>;

An ocsp_response contains a complete, DER-encoded OCSP response (using the ASN.1 type OCSPResponse defined in [OCSP]). Note that only one OCSP response may be sent. πŸ¦‹

The CertificateStatus message is conveyed using the handshake message type certificate_status. 🧚

A server MAY also choose not to send a CertificateStatus message, even if it receives a status_request extension in the client hello. That's totally allowed, no drama. 🌈

Heads up though: servers MUST NOT send the CertificateStatus message unless they received a status_request extension in the client hello message. ⚠️

Clients that request an OCSP response and then receive one in a CertificateStatus message MUST check that OCSP response, and abort the handshake if the response is not satisfactory. This is the one where you do not get to vibe check your way out of it. πŸ’€

4. Error Alerts 🚨

This section defines new error alerts for use with the TLS extensions defined in this document.

The following new error alerts are defined. To avoid "breaking" existing clients and servers, these alerts MUST NOT be sent unless the sending party has received an extended hello message from the party they're communicating with. 🫢

  • unsupported_extension: this alert is sent by clients that receive an extended server hello containing an extension they didn't put in the corresponding client hello (see Section 2.3). This message is always fatal.
  • unrecognized_name: this alert is sent by servers that receive a server_name extension request but don't recognize the server name. This message MAY be fatal.
  • certificate_unobtainable: this alert is sent by servers who can't retrieve a certificate chain from the URL the client supplied (see Section 3.3). This message MAY be fatal. For example, if client authentication is required by the server for the handshake to continue and the server can't retrieve the certificate chain, it may send a fatal alert. 😭
  • bad_certificate_status_response: this alert is sent by clients that receive an invalid certificate status response (see Section 3.6). This message is always fatal.
  • bad_certificate_hash_value: this alert is sent by servers when a certificate hash doesn't match a client-provided certificate_hash. This message is always fatal.

These error alerts are conveyed using the following syntax:

enum {
    close_notify(0),
    unexpected_message(10),
    bad_record_mac(20),
    decryption_failed(21),
    record_overflow(22),
    decompression_failure(30),
    handshake_failure(40),
    /* 41 is not defined, for historical reasons */
    bad_certificate(42),
    unsupported_certificate(43),
    certificate_revoked(44),
    certificate_expired(45),
    certificate_unknown(46),
    illegal_parameter(47),
    unknown_ca(48),
    access_denied(49),
    decode_error(50),
    decrypt_error(51),
    export_restriction(60),
    protocol_version(70),
    insufficient_security(71),
    internal_error(80),
    user_canceled(90),
    no_renegotiation(100),
    unsupported_extension(110),           /* new */
    certificate_unobtainable(111),        /* new */
    unrecognized_name(112),               /* new */
    bad_certificate_status_response(113), /* new */
    bad_certificate_hash_value(114),      /* new */
    (255)
} AlertDescription;

5. Procedure for Defining New Extensions πŸŽ€

The list of extension types, as defined in Section 2.3, is maintained by the Internet Assigned Numbers Authority (IANA). So if you want a new extension type value, you've gotta apply to the IANA. Since there are subtle (and not-so-subtle) interactions between new features and existing ones that could seriously cut down overall security, new values SHALL be defined only through the IETF Consensus process specified in [IANA].

(This means new assignments can be made only via RFCs approved by the IESG.) 🧐

The following considerations should be taken into account when designing new extensions:

  • All of the extensions defined in this document follow the convention that for each extension a client requests and the server understands, the server replies with an extension of the same type. πŸ’–
  • Some cases where a server doesn't agree to an extension are error conditions, and some are simply a refusal to support a particular feature. In general, error alerts should be used for the former, and a field in the server extension response for the latter. πŸ™Œ
  • Extensions should, as far as possible, be designed to prevent any attack that forces use (or non-use) of a particular feature by manipulating handshake messages. This principle should be followed regardless of whether the feature is believed to cause a security problem.

Often the fact that the extension fields are included in the inputs to the Finished message hashes will be sufficient, but extreme care is needed when the extension changes the meaning of messages sent in the handshake phase. Designers and implementors should be aware that, until the handshake has been authenticated, active attackers can modify messages and insert, remove, or replace extensions. πŸ‘€

  • It would be technically possible to use extensions to change major aspects of the TLS design, for example the design of cipher suite negotiation. This is not recommended. It would be more appropriate to define a new version of TLS, especially since the TLS handshake algorithms have specific protection against version rollback attacks based on the version number. The possibility of version rollback should be a significant consideration in any major design change. 🚫

6. Security Considerations πŸ”

Security considerations for the extension mechanism in general, and for the design of new extensions, are described in the previous section. A security analysis of each extension defined in this document is given below.

In general, implementers should continue to monitor the state of the art and address any weaknesses identified. πŸ”₯

Additional security considerations are described in the TLS 1.0 RFC [TLS] and the TLS 1.1 RFC [TLSbis]. πŸ’…

6.1. Security of server_name πŸŽ€

Okay so bestie, if one server hosts a bunch of domains, each domain owner has to make sure the setup meets their security needs πŸ’… That part's on them. Apart from that, server_name doesn't really cause big security drama 🌸

Implementations MUST ensure that a buffer overflow does not occur, whatever the values of the length fields in server_name. 🚨 Not optional, babe. Please don't skip this one.

This document gives an encoding for internationalized hostnames in the server_name extension, but it doesn't deal with the security problems that come with internationalized hostnames in TLS πŸ‘€ The big one is "spoofed" names that look exactly like another name when they're displayed or printed. It is recommended that server certificates not be issued for internationalized hostnames unless procedures are in place to mitigate the risk of spoofed hostnames. πŸ™ˆ

6.2. Security of max_fragment_length 🧚

The maximum fragment length takes effect immediately, including for handshake messages. Good news though: that doesn't add any new security complications, because TLS already requires implementations to handle fragmented handshake messages ✨

Note that, as covered in Section 3.2, once a non-null cipher suite has been activated, the effective maximum fragment length depends on the cipher suite and compression method, as well as on the negotiated max_fragment_length. This must be taken into account when sizing buffers, and checking for buffer overflow. 🧠

6.3. Security of client_certificate_url πŸ”₯

Okay, this one is lowkey the drama of the whole document 😭 There are two major issues.

The first major issue is whether or not clients should include certificate hashes when they send certificate URLs. When client authentication is used without the client_certificate_url extension, the client certificate chain is covered by the Finished message hashes. Including hashes and checking them against the retrieved certificate chain is how we make sure the same property holds with this extension. In other words, everything in the chain the server fetched is exactly what the client meant to send πŸ’–

On the flip side, leaving out certificate hashes unlocks stuff that's really useful in some situations. For example, clients can be issued daily certificates that live at a fixed URL and don't have to be handed to the client directly πŸ¦‹ But clients that leave out hashes should know about an attack where the attacker gets a valid certificate on the client's key that's different from the one the client meant to provide. πŸ’€ Although TLS uses both MD5 and SHA-1 hashes in several other places, this was not believed to be necessary here. The property required of SHA-1 is second pre-image resistance.

The second major issue is that supporting client_certificate_url means the server is acting as a client in another URL protocol. So the server picks up many of the same security concerns that clients of the URL scheme deal with, plus an extra one: the client can try to prompt the server to connect to some possibly weird-looking URL πŸ‘€

Generally speaking, this means an attacker might use the server to indirectly attack another host that has some security flaw. It also opens the door to denial of service attacks, where an attacker makes tons of connections to the server and each one makes the server try to connect to the attack's target 🚫

Also, the server may be sitting behind a firewall or otherwise able to reach hosts that aren't directly accessible from the public Internet. That could make the security and denial of service problems above even worse, and it could let people confirm the existence of internal hosts that would otherwise stay hidden πŸ™ˆ

The detailed concerns depend on which URL schemes the server supports. For HTTP, the concerns are similar to those for a publicly accessible HTTP proxy server. For HTTPS, loops and deadlocks may be created, and this should be addressed. For FTP, attacks arise that are similar to FTP bounce attacks. 😬

So because of all this, it is RECOMMENDED that the client_certificate_url extension should have to be specifically enabled by a server administrator, rather than be enabled by default. πŸ›‘οΈ It is also RECOMMENDED that URI protocols be enabled by the administrator individually, and that only a minimal set of protocols be enabled. Unusual protocols that offer limited security or whose security is not well-understood SHOULD be avoided. 🚫

As discussed in [URI], URLs that specify ports other than the default may cause problems, and so may very long URLs, which are more likely to be useful in exploiting buffer overflow bugs πŸ“

Last thing: HTTP caching proxies are super common on the Internet, and some of them don't check for the latest version of an object correctly. If a request using HTTP (or another caching protocol) goes through a misconfigured or otherwise broken proxy, the proxy may return an out-of-date response. πŸ₯€

6.4. Security of trusted_ca_keys 🌈

It's possible that which CA root keys a client has could be treated as confidential information, so the CA root key indication extension should be used with care 🀫

The SHA-1 certificate hash alternative makes sure each certificate is specified unambiguously. Same as the previous extension, it was not believed necessary to use both MD5 and SHA-1 hashes. πŸ’…

6.5. Security of truncated_hmac πŸ¦‹

Okay, so it's possible that truncated MACs are weaker than "un-truncated" MACs. But no significant weaknesses are currently known, or expected to exist, for HMAC with MD5 or SHA-1 truncated to 80 bits ✨

Also, the output length of a MAC doesn't need to be as long as a symmetric cipher key. Why? Forging MAC values can't be done off-line. In TLS, a single failed MAC guess causes the immediate termination of the TLS session πŸ”’

Here's the iconic part: the MAC algorithm only takes effect after all handshake messages that affect extension parameters have been authenticated by the hashes in the Finished messages. So an active attacker can't force negotiation of the truncated HMAC extension where it wouldn't otherwise be used (as long as the handshake authentication is secure) πŸ‘‘ And if some security problem with truncated HMAC gets found in the future, then if either the client or the server for a session has been updated to take the problem into account, it would be able to veto use of this extension. Main character energy for the protocol πŸ™Œ

6.6. Security of status_request πŸ’€

If a client requests an OCSP response, it must take into account that an attacker's server using a compromised key could (and probably would) pretend not to support the extension. 😱 So in that case, a client that requires OCSP validation of certificates SHOULD either contact the OCSP server directly or abort the handshake.

The OCSP nonce request extension (id-pkix-ocsp-nonce) may improve security against attacks that try to replay OCSP responses. See Section 4.4.1 of [OCSP] for further details 🧚

7. Internationalization Considerations 🌍

None of the extensions defined here directly use strings that are subject to localization. Domain Name System (DNS) hostnames are encoded using UTF-8. If future extensions use text strings, then internationalization should be considered in their design πŸ’œ

8. IANA Considerations πŸ“‹

Sections 2.3 and 5 describe a registry of ExtensionType values to be maintained by the IANA. ExtensionType values get assigned via IETF Consensus, as defined in RFC 2434 [IANA]. The initial registry corresponds to the definition of "ExtensionType" in Section 2.3. 🌸

The MIME type "application/pkix-pkipath" has been registered by the IANA using the following template:

To: ietf-types@iana.org
Subject: Registration of MIME media type application/pkix-pkipath

MIME media type name: application
MIME subtype name: pkix-pkipath
Required parameters: none

Optional parameters: version (default value is "1")

Encoding considerations:
   This MIME type is a DER encoding of the ASN.1 type PkiPath,
   defined as follows:
     PkiPath ::= SEQUENCE OF Certificate
     PkiPath is used to represent a certification path.  Within the
     sequence, the order of certificates is such that the subject of
     the first certificate is the issuer of the second certificate,
     etc.

   This is identical to the definition published in [X509-4th-TC1];
   note that it is different from that in [X509-4th].

   All Certificates MUST conform to [PKIX].  (This should be
   interpreted as a requirement to encode only PKIX-conformant
   certificates using this type.  It does not necessarily require
   that all certificates that are not strictly PKIX-conformant must
   be rejected by relying parties, although the security consequences
   of accepting any such certificates should be considered
   carefully.)

   DER (as opposed to BER) encoding MUST be used.  If this type is
   sent over a 7-bit transport, base64 encoding SHOULD be used.

Security considerations:
   The security considerations of [X509-4th] and [PKIX] (or any
   updates to them) apply, as well as those of any protocol that uses
   this type (e.g., TLS).

   Note that this type only specifies a certificate chain that can be
   assessed for validity according to the relying party's existing
   configuration of trusted CAs; it is not intended to be used to
   specify any change to that configuration.

Interoperability considerations:
   No specific interoperability problems are known with this type,
   but for recommendations relating to X.509 certificates in general,
   see [PKIX].

Published specification: RFC 4366 (this memo), and [PKIX].

Applications which use this media type: TLS.  It may also be used by
   other protocols, or for general interchange of PKIX certificate
   chains.

Additional information:
   Magic number(s): DER-encoded ASN.1 can be easily recognized.
     Further parsing is required to distinguish it from other ASN.1
     types.
   File extension(s): .pkipath
   Macintosh File Type Code(s): not specified

Person & email address to contact for further information:
   Magnus Nystrom <magnus@rsasecurity.com>

Intended usage: COMMON
Change controller:
   IESG <iesg@ietf.org>

9. Acknowledgements 🫢

The authors wish to thank the TLS Working Group and the WAP Security Group. This document is based on discussion within these groups. Big love to both groups for the teamwork πŸ’–πŸŒˆ

10. Normative References πŸ“šβœ¨

okay so these are the docs this spec literally can't function without, bestie πŸ’… you need to have read them to get the full picture.

  • [HMAC] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997.
  • [HTTP] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P., and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, June 1999.
  • [IANA] Narten, T. and H. Alvestrand, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 2434, October 1998.
  • [IDNA] Faltstrom, P., Hoffman, P., and A. Costello, "Internationalizing Domain Names in Applications (IDNA)", RFC 3490, March 2003.
  • [KEYWORDS] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
  • [OCSP] Myers, M., Ankney, R., Malpani, A., Galperin, S., and C. Adams, "X.509 Internet Public Key Infrastructure Online Certificate Status Protocol - OCSP", RFC 2560, June 1999.
  • [PKIOP] Housley, R. and P. Hoffman, "Internet X.509 Public Key Infrastructure Operational Protocols: FTP and HTTP", RFC 2585, May 1999.
  • [PKIX] Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, April 2002.
  • [TLS] Dierks, T. and C. Allen, "The TLS Protocol Version 1.0", RFC 2246, January 1999.
  • [TLSbis] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.1", RFC 4346, April 2006.
  • [URI] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform Resource Identifier (URI): Generic Syntax", STD 66, RFC 3986, January 2005.
  • [UTF8] Yergeau, F., "UTF-8, a transformation format of ISO 10646", STD 63, RFC 3629, November 2003.
  • [X509-4th] ITU-T Recommendation X.509 (2000) | ISO/IEC 9594-8:2001, "Information Systems - Open Systems Interconnection - The Directory: Public key and attribute certificate frameworks."
  • [X509-4th-TC1] ITU-T Recommendation X.509(2000) Corrigendum 1(2001) | ISO/IEC 9594-8:2001/Cor.1:2002, Technical Corrigendum 1 to ISO/IEC 9594:8:2001.

11. Informative References 🧚

these ones are the extra reading, the "ooh, go deeper" list 🌸 not required, but lowkey worth bookmarking.

  • [AESSUITES] Chown, P., "Advanced Encryption Standard (AES) Ciphersuites for Transport Layer Security (TLS)", RFC 3268, June 2002.
  • [KERB] Medvinsky, A. and M. Hur, "Addition of Kerberos Cipher Suites to Transport Layer Security (TLS)", RFC 2712, October 1999.
  • [MAILINGLIST] J. Mikkelsen, R. Eberhard, and J. Kistler, "General ClientHello extension mechanism and virtual hosting," ietf-tls mailing list posting, August 14, 2000.
  • [RFC3546] Blake-Wilson, S., Nystrom, M., Hopwood, D., Mikkelsen, J., and T. Wright, "Transport Layer Security (TLS) Extensions", RFC 3546, June 2003.

Authors' Addresses πŸŽ€

meet the squad who wrote this 🫢 these are the people to thank (or message, if you're feeling brave πŸ’€).

Simon Blake-Wilson BCI

EMail: sblakewilson@bcisse.com

Magnus Nystrom RSA Security

EMail: magnus@rsasecurity.com

David Hopwood Independent Consultant

EMail: david.hopwood@blueyonder.co.uk

Jan Mikkelsen Transactionware

EMail: janm@transactionware.com

Tim Wright Vodafone

EMail: timothy.wright@vodafone.com

okay the legal bit, but it matters 😭 read it, it's short.

Copyright (C) The Internet Society (2006).

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

Intellectual Property πŸ”₯

the IPR rules, bestie. here's the vibe check on patents and licences.

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.

Acknowledgement 🌈

last stop, and a shoutout to the folks keeping the lights on ✨

Funding for the RFC Editor function is provided by the IETF Administrative Support Activity (IASA).

πŸ“¦ where this page comes from