RFC 8672
TLS Server Identity Pinning with Tickets
TLS Server Identity Pinning with Tickets ๐
Okay bestie, this is RFC 8672 ๐. It's an Independent Submission by Y. Sheffer (Intuit) and D. Migault (Ericsson) ๐, it's Experimental ๐งช, and it came out in October 2019 โจ. The ISSN is 2070-1721. The header doesn't list any RFCs it obsoletes or updates, so it's flying solo ๐ฆ.
Abstract โจ
Okay so the problem is that misissued public-key certificates can stop TLS clients from properly authenticating the TLS server ๐ญ. People have proposed a few fixes to catch this and stop a client from setting up a TLS session with an endpoint that's using an illegitimate certificate ๐ . The catch is that those fixes are either not widely deployed or only for public web browsing ๐.
This doc proposes experimental TLS extensions with opaque pinning tickets as a way to pin the server's identity ๐ง. During the first TLS session, the server hands over an original encrypted pinning ticket. In later sessions, once it receives that ticket, the server proves it can decrypt it, which means it owns the pinning protection key ๐. The client can then safely conclude it's talking to the same server as the original session ๐ซถ. And the best part? No manual management actions are required ๐.
Status of This Memo ๐
This document is not an Internet Standards Track specification. It's published for examination, experimental implementation, and evaluation ๐.
It defines an Experimental Protocol for the Internet community. It's a contribution to the RFC Series, independent of any other RFC stream ๐. The RFC Editor chose to publish it at their discretion and makes no statement about its value for implementation or deployment. Documents the RFC Editor approves for publication are not candidates for any level of Internet Standard, so check Section 2 of RFC 7841 for the details ๐.
Info about the current status of this document, any errata, and how to send feedback is at https://www.rfc-editor.org/info/rfc8672 ๐ฆ.
Copyright Notice ๐
Copyright (c) 2019 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 (https://trustee.ietf.org/license-info) as they're in effect on the publication date. Please read these carefully, because they spell out your rights and restrictions for this document ๐.
Table of Contents ๐๏ธ
1. Introduction
1.1. Conventions Used in This Document
1.2. Scope of Experimentation
2. Protocol Overview
2.1. Initial Connection
2.2. Subsequent Connections
2.3. Indexing the Pins
3. Message Definitions
4. Cryptographic Operations
4.1. Pinning Secret
4.2. Pinning Ticket
4.3. Pinning Protection Key
4.4. Pinning Proof
5. Operational Considerations
5.1. Protection Key Synchronization
5.2. Ticket Lifetime
5.3. Certificate Renewal
5.4. Certificate Revocation
5.5. Disabling Pinning
5.6. Server Compromise
5.7. Disaster Recovery
6. Security Considerations
6.1. Trust-on-First-Use (TOFU) and MITM Attacks
6.2. Pervasive Monitoring
6.3. Server-Side Error Detection
6.4. Client Policy and SSL Proxies
6.5. Client-Side Error Behavior
6.6. Stolen and Forged Tickets
6.7. Client Privacy
6.8. Ticket Protection Key Management
7. IANA Considerations
8. References
8.1. Normative References
8.2. Informative References
Appendix A. Previous Work
A.1. Comparison: HPKP
A.2. Comparison: TACK
Acknowledgments
Authors' Addresses
1. Introduction โจ
Misissued public-key certificates can stop TLS [RFC8446] clients from properly authenticating the TLS server ๐ฌ. This is a big deal for the global public key infrastructure (PKI), and it's a similar problem for large-scale certificate deployments inside enterprises ๐ข.
This document proposes experimental TLS extensions with opaque pinning tickets as a way to pin the server's identity ๐. The approach is meant to be easy to implement and deploy, and it reuses some of the ideas behind TLS session resumption [RFC5077] ๐.
Ticket pinning is a second-factor server authentication method. It's not meant to replace the authentication method in the TLS key exchange ๐ โโ๏ธ. To be specific, the client only uses the pinning identity method after the TLS key exchange has successfully completed. So the pinning identity method only ever runs over an already-authenticated TLS session ๐. Also, ticket pinning doesn't pin certificate information, which makes it a truly independent second-factor authentication ๐ง .
Ticket pinning is a trust-on-first-use (TOFU) mechanism ๐ฐ๏ธ. The first server authentication is based only on PKI certificate validation. For any follow-on sessions, though, the client also checks the server's identity, using the server's ability to decrypt the ticket on top of normal PKI certificate authentication ๐ .
During the initial TLS session, the client requests a pinning ticket from the server. When the server gets that request, it generates a pinning secret that's expected to be unpredictable to anyone except the client or the server ๐คซ. In this case, the pinning secret comes from parameters exchanged during the TLS key exchange, so the client and server can each generate it locally and independently ๐งฉ. The server builds the pinning ticket with the info it needs to retrieve the pinning secret, then encrypts the ticket and sends it back to the client along with an associated pinning lifetime โณ.
The pinning lifetime value says how long the server promises to keep the server-side ticket-encryption key. That's what lets it finish the protocol exchange correctly and prove its identity ๐งพ. This server commitment (and the ticket lifetime) is typically on the order of weeks ๐ .
Once the key exchange is done and the server is deemed authenticated, the client generates the pinning secret locally. It then caches the server's identifiers to index the pinning secret, along with the pinning ticket and its associated lifetime ๐๏ธ.
When the client sets up a new TLS session with the server, it sends the pinning ticket to the server ๐จ. When the server receives it, the server returns a proof that it knows the pinning secret ๐ช. Once the key exchange is done and the server has been authenticated, the client checks the pinning proof from the server using its stored pinning secret โ . If the proof matches, the client can conclude that the server it's currently connecting to is, in fact, the correct server ๐.
This document only applies to TLS 1.3 ๐. The idea could probably be retrofitted into earlier versions of the protocol too, but that would take significant changes ๐ ๏ธ. For example, TLS 1.2 [RFC5246] and earlier don't provide a generic facility for encrypted handshake extensions, which is what's used here to carry the ticket ๐.
The main advantages of this protocol over earlier pinning solutions are:
- The protocol lives at the TLS level, so it isn't limited to HTTP at the application level ๐ธ.
- The protocol is robust to changes in server IP address, certification authority (CA), and public key ๐ช. The server is identified by its ownership of the pinning protection key, which is never given to the client ๐๏ธ. Server config parameters like the CA and the public key can change without affecting the pinning ticket protocol ๐.
- Once a single parameter is configured (the ticket's lifetime), everything runs automatically ๐ค. The server admin doesn't have to deal with backup certificates or explicit pins ๐.
- For server clusters, we reuse the existing infrastructure [RFC5077] wherever it already exists ๐๏ธ.
- Pinning errors, which presumably come from man-in-the-middle (MITM) attacks, can be detected by both the client and the server ๐. That allows server-side detection of MITM attacks using large-scale analytics, with no need for clients to explicitly report the error ๐.
A quick note on terminology: unlike other solutions in this space, we don't do "certificate pinning" (or "public key pinning"), since the protocol doesn't care about the server's certificate ๐. We prefer the term "server identity pinning" for this new solution ๐. In our solution, the server proves its identity by generating a proof that it can read and decrypt an encrypted ticket ๐๏ธ. So the identity proof depends on proving ownership of the pinning protection key. But this key is never exchanged with the client or known by it, so it can't itself be pinned ๐.
1.1. Conventions Used in This Document ๐
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 BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here ๐.
1.2. Scope of Experimentation ๐งช
This document describes an experimental extension to the TLS protocol ๐ฌ. This section sets constraints on the experiment and explains how it can yield useful info, which could eventually lead to a standard ๐.
The protocol is designed so that if the server doesn't support it, the client and server fall back to a normal TLS exchange. The one exception is a single PinningTicket extension that the client sends first ๐ฎ. The protocol is also designed only to strengthen the validation of the server's identity (a "second factor") ๐ช. So implementation or even protocol errors shouldn't weaken security compared to a normal TLS exchange ๐ก๏ธ. Given those two points, experimentation can run on the open Internet between consenting client and server implementations ๐.
The goal of the experiment is to prove that:
- Non-supporting clients and servers are unaffected ๐.
- Connectivity between supporting clients and servers is kept under normal circumstances, whether the client connects to the server often (relative to the ticket's lifetime) or very rarely ๐.
- Enterprise middleboxes don't interrupt that connectivity ๐ข.
- Misissued certificates and rogue TLS-aware middleboxes do break connectivity, and these cases get detected on the client and/or server side ๐จ. Clients and servers can recover even after such events, and normal connectivity is restored ๐.
After two years of successful deployment, the authors will publish a document summarizing the experiment's findings, and will resubmit the protocol for consideration as a Proposed Standard ๐.
2. Protocol Overview โจ
okay so the protocol has two phases ๐: the very first time a client connects to a server, and then every connection after that ๐ฆ
it supports full TLS handshakes AND 0-RTT handshakes ๐ง. We walk through it with a full handshake, but behavior in 0-RTT handshakes should be identical.
this document has some vibes in common with the ticket resumption mechanism from [RFC5077] ๐. BUT the scope is different. The pinning ticket does NOT carry any state tied to a TLS session, so it can't be used for session resumption or client authentication ๐ โโ๏ธ. It only contains the encrypted pinning secret. The server uses the ticket to prove it can decrypt it, which implies it owns the pinning protection key ๐
[RFC5077] got obsoleted by [RFC8446], and ticket resumption is now defined in Section 2.2 of [RFC8446]. This document still cites [RFC5077] as an informational document, because it has a more thorough discussion of stateless ticket resumption ๐. Ticket resumption also benefits from a lot of operational experience with TLS 1.2, which is still widely deployed at the time of writing. That experience, plus deployment experience, can totally be re-used for identity pinning ๐ธ
with TLS 1.3, session resumption is based on a Pre-Shared Key (PSK) ๐๏ธ. That's orthogonal to this protocol, meaning it's a separate thing that doesn't get in the way. You can establish a TLS session using PKI and a pinning ticket, and later resume it with a PSK โจ
BUT (and this is the important part ๐จ) this protocol is about the problem of misissued certificates. So it's not expected to be used outside a certificate-based TLS key exchange, like in PSK. That means PSK handshakes MUST NOT include the extension defined here ๐
2.1. Initial Connection
when a client first connects to a server, it asks for a pinning ticket by sending an empty PinningTicket extension ๐. Then it gets the ticket back as part of the server's first response, inside the returned PinningTicket extension ๐
Client Server
ClientHello
+ key_share
+ signature_algorithms
+ PinningTicket -------->
ServerHello
+ key_share
{EncryptedExtensions
+ PinningTicket}
{CertificateRequest*}
{Certificate*}
{CertificateVerify*}
<-------- {Finished}
{Certificate*}
{CertificateVerify*}
{Finished} -------->
[Application Data] <-------> [Application Data]
* Indicates optional or situation-dependent
messages that are not always sent.
{} Indicates messages protected using keys
derived from the ephemeral secret.
[] Indicates messages protected using keys
derived from the master secret.
if a client supports the PinningTicket extension and doesn't have any pinning ticket for the server, the exchange counts as an initial connection ๐. Other reasons a client might not have a pinning ticket: it flushed its pinning ticket store, or the committed lifetime of the ticket already expired ๐งน
when the server gets the PinningTicket extension, it computes a pinning secret (Section 4.1) ๐งฎ and sends the pinning ticket (Section 4.2) encrypted with the pinning protection key (Section 4.3) ๐. The ticket comes with a lifetime value, and the server takes on the responsibility of keeping the pinning protection key and being able to decrypt incoming pinning tickets for the period set by the committed lifetime. That's a big commitment, bestie ๐
once the ticket is generated, the server returns the pinning ticket and the committed lifetime in a PinningTicket extension inside the EncryptedExtensions message ๐ฆ. Also, a PinningTicket extension MUST NOT be sent as part of a HelloRetryRequest. No exceptions ๐ซ
now for the client side ๐. When it receives the pinning ticket, it MUST NOT accept it until the key exchange is completed and the server is authenticated ๐. If the key exchange doesn't complete successfully, the client MUST ignore the received pinning ticket. Otherwise, the client computes the pinning secret and SHOULD cache the pinning secret and the pinning ticket for the duration of the pinning ticket lifetime ๐๏ธ. And when that lifetime ends, the client SHOULD clean up the cached values ๐งฝ
2.2. Subsequent Connections
when the client connects to a server it has seen before (see Section 2.3 on identifying servers), it SHOULD send the pinning ticket for that server ๐๏ธ. The pinning ticket, pinning secret, and pinning ticket lifetime that were computed during the previous TLS session are called the "original" ones in this document. That's so they can be told apart from a new ticket that might get generated during the current session ๐ท๏ธ
the server MUST extract the original pinning_secret value from the ticket and MUST respond with a PinningTicket extension, which includes:
- A proof that the server can understand the ticket the client sent. This proof also binds the pinning ticket to the server's (current) public key, as well as the ongoing TLS session ๐. The proof is mandatory and MUST be included if the client sent a pinning ticket.
- A fresh pinning ticket. The main reason for refreshing the ticket on every connection is privacy ๐ต๏ธโโ๏ธ: it stops the ticket from acting as a fixed client identifier. A fresh pinning ticket might be zero length, but it is RECOMMENDED to include a fresh ticket with a nonzero length with each response ๐
if the server can't validate the received ticket, that might mean there was an earlier MITM attack on this client ๐ฑ. In that case the server MUST abort the connection with a handshake_failure alert and SHOULD log this failure ๐จ.
the client MUST verify the proof. If it fails to, the client MUST issue a handshake_failure alert and abort the connection (see also Section 6.5) ๐. It's super important that the client does NOT try to "fall back" by leaving out the PinningTicket extension. Don't you dare, periodt ๐ โโ๏ธ
once the connection is set up successfully, meaning after the Finished message is verified, the client SHOULD store the new ticket along with the matching pinning_secret, replacing the original ticket ๐
even though this is an extension, if the client already has a ticket for a server, the client MUST interpret a missing PinningTicket extension in the server's response as an attack ๐ฉ. That's because the server already made a prior commitment to respect the ticket. The client MUST abort the connection in this case. See also Section 5.5 on ramping down support for this extension ๐
2.3. Indexing the Pins
every pin is associated with a set of identifiers that include, among others, hostname, protocol (TLS or DTLS), and port number ๐๏ธ. So the pin for port TCP/443 may be different from the pin for DTLS, or from the pin for port TCP/8443. These identifiers are expected to be relevant for characterizing the identity of the server, as well as the TLS session being established โจ. When a hostname is used, it MUST be the value sent inside the Server Name Indication (SNI) extension ๐ท๏ธ. This is similar to the concept of a Web Origin [RFC6454], but it doesn't assume a URL exists.
the whole point of ticket pinning is to pin the server identity ๐. So any information that's orthogonal to the server's identity MUST NOT be considered when indexing ๐ โโ๏ธ. Specifically, IP addresses are ephemeral and forbidden in SNI, so pins MUST NOT be associated with IP addresses ๐ฌ๏ธ. Similarly, CA names or public keys associated with the server MUST NOT be used for indexing, because they may change over time ๐
3. Message Definitions ๐
this section defines the format of the PinningTicket extension ๐งพ. We follow the message notation of [RFC8446].
opaque pinning_ticket<0..2^16-1>;
opaque pinning_proof<0..2^8-1>;
struct {
select (Role) {
case client:
pinning_ticket ticket<0..2^16-1>; //omitted on 1st connection
case server:
pinning_proof proof<0..2^8-1>; //no proof on 1st connection
pinning_ticket ticket<0..2^16-1>; //omitted on ramp down
uint32 lifetime;
}
} PinningTicketExtension;
here's what each field means ๐ซถ:
ticket a pinning ticket sent by the client or returned by the
server. The ticket is opaque to the client. The extension
MUST contain exactly 0 or 1 tickets.
proof a demonstration by the server that it understands the
received ticket and therefore that it is in possession of
the secret that was used to generate it originally. The
extension MUST contain exactly 0 or 1 proofs.
lifetime the duration (in seconds) that the server commits to accept
offered tickets in the future.
4. Cryptographic Operations ๐
this section gives the details on the cryptographic operations the protocol peers perform ๐งโ๐ฌ.
4.1. Pinning Secret
the pinning secret is generated locally by the client AND the server, which means they have to use the same inputs to generate it ๐ค. This value must be generated before the ServerHello message is sent, because the server includes the matching pinning ticket in the same flight as the ServerHello message ๐ซ. On top of that, the pinning secret must be unpredictable to anyone other than the client and the server ๐ต๏ธ.
the pinning secret is derived with the Derive-Secret function provided by TLS 1.3, described in Section 7.1 of [RFC8446] ๐งช.
pinning secret = Derive-Secret(Handshake Secret, "pinning secret",
ClientHello...ServerHello)
4.2. Pinning Ticket
the pinning ticket contains the pinning secret ๐. The client gives the pinning ticket to the server, which decrypts it to extract the pinning secret, and then responds with a pinning proof ๐ซ. So the characteristics of the pinning ticket are:
- Pinning tickets MUST be encrypted and integrity-protected using strong cryptographic algorithms ๐ก๏ธ.
- Pinning tickets MUST be protected with a long-term pinning protection key ๐.
- Pinning tickets MUST include a pinning protection key ID or serial number, so that the pinning protection key can be refreshed ๐.
- The pinning ticket MAY include other information in addition to the pinning secret ๐. When extra information is included, a careful review needs to happen to evaluate its impact on privacy ๐.
the pinning ticket's format isn't specified by this document, but a format similar to the one proposed by [RFC5077] is RECOMMENDED ๐ธ.
4.3. Pinning Protection Key โจ
okay so the pinning protection key is only used by the server ๐, which means it stays server implementation specific. [RFC5077] recommends using two keys, but with Authenticated Encryption with Associated Data (AEAD) algorithms you only need a single key. so chill ๐
when one server terminates TLS for multiple virtual servers using the SNI mechanism, it is strongly RECOMMENDED that it use a separate protection key for each one ๐. that way you can move virtual servers between different servers and pinning keeps working. main character energy for sure ๐
as noted in Section 5.1, if the server is actually a cluster of machines, the protection key MUST be synchronized between all the nodes that accept TLS connections to the same server name ๐ซถ. an easy way to do this when [RFC5077] is deployed is to derive the protection key from the session-ticket protection key, which is already synchronized. like this:
pinning_protection_key = HKDF-Expand(resumption_protection_key,
"pinning protection", L)
where resumption_protection_key is the ticket protection key defined in [RFC5077]. both resumption_protection_key and pinning_protection_key are only used by the server ๐ง
ngl this solution tries to minimize code changes around managing resumption_protection_key ๐. the drawback is that this one key gets used both to directly encrypt session tickets AND to derive the pinning_protection_key, and mixing one key like that is not in line with cryptographic best practices ๐. so where possible, it is RECOMMENDED that resumption_protection_key be unrelated to pinning_protection_key and that they be shared separately among the relevant servers ๐ฆ
4.4. Pinning Proof ๐ฅ
the pinning proof is sent by the server to show that it managed to decrypt the pinning ticket and get the pinning secret. the proof must be unpredictable and must not be replayed ๐ โโ๏ธ. just like the pinning ticket, the server sends it in the ServerHello message. and it must not be possible for a MITM server with a fake certificate to grab a pinning proof from the original server ๐ญ
so to hit all of these requirements, the pinning proof is bound to the TLS session AND the server's public key:
pinning_proof_secret=Derive-Secret(Handshake Secret,
"pinning proof 1", ClientHello...ServerHello)
proof = HMAC(original_pinning_secret, "pinning proof 2" +
pinning_proof_secret + Hash(server_public_key))
where HMAC [RFC2104] uses the Hash algorithm that was negotiated in the handshake, and that same hash is also used over the server's public key ๐ธ. the original_pinning_secret is the secret value pulled out of the ticket the client sent, so it's not mixed up with a new pinning secret that might get computed in the current exchange ๐. the server_public_key is the DER representation of the public key, specifically the SubjectPublicKeyInfo structure as-is โจ
5. Operational Considerations ๐
the whole point of this protocol is to get identity pinning without needing manual operations ๐. manual stuff is super prone to human error, and with public key pinning it can totally result in "server bricking", where the server becomes unreachable for some or all of its users ๐. so to avoid that, the operations in identity pinning only happen within the current TLS session, and nothing depends on TLS configuration parameters like CA identity or public keys. which means config changes are unlikely to desync the state between the client and the server ๐ซถ
5.1. Protection Key Synchronization ๐
the only operational requirement when deploying this protocol is that, if the server is part of a cluster, the protection keys (the keys used to encrypt tickets) MUST be synchronized between all cluster members ๐ง. the protocol is designed so that if resumption ticket protection keys [RFC5077] are already synchronized between cluster members, you literally don't have to do anything else ๐
also, synchronization doesn't have to be instant ๐ฐ๏ธ. protection keys can be distributed a few minutes or hours before they roll over. in those situations, each cluster member MUST be able to accept tickets protected with a new version of the protection key, even while it's still using an old version to generate keys. this way, when a client gets a "new" ticket, it won't next hit a cluster member that still rejects it ๐
misconfiguration can make the server's clock way off ๐ฌ. say a server's clock is misconfigured to be 1 year in the future, and the system is allowed to delete expired keys automatically. the server would then delete a bunch of outstanding keys, since they're now long expired, and it would end up rejecting valid tickets that clients are storing. that could make the server inaccessible to a huge number of clients ๐ญ๐จ
the decision to delete a key should at least consider the largest value of the ticket lifetime, plus the expected time desynchronization between the servers of the cluster and the time it takes to distribute the new key among the different cluster servers ๐ง
5.2. Ticket Lifetime โณ
the ticket lifetime is a commitment by the server to keep the ticket's matching protection key for this long, so the server can prove to the client that it knows the secret embedded in the ticket ๐. for production systems, the lifetime SHOULD be between 7 and 31 days ๐๏ธ
5.3. Certificate Renewal ๐
the protocol makes sure the client keeps talking to the correct server even when the server's certificate gets renewed ๐ฆ. in this sense pinning isn't tied to certificates, which is exactly why we call the protocol described in this document "server identity pinning" ๐
and this property isn't affected by using the server's public key in the pinning proof, because the public key is only scoped to the current TLS session โจ
5.4. Certificate Revocation ๐ซ
the protocol is orthogonal to certificate validation. so if the server's certificate has been revoked or is invalid for some other reason, the client MUST refuse to connect to it, no matter what's going on with tickets ๐ โโ๏ธ
5.5. Disabling Pinning ๐ฅ
a server implementing this protocol MUST have a "ramp down" mode of operation where:
- The server keeps accepting valid pinning tickets and responds correctly with a proof ๐ซถ
- The server does not send back a new pinning ticket ๐
after a while, no clients will be holding valid tickets, and then the feature can be disabled ๐. clients that don't get a new pinning ticket don't necessarily have to throw out the original one. instead, the client can keep using the ticket until its lifetime expires ๐ฐ๏ธ. but as detailed in Section 6.7, if the client reuses a ticket, that can cause privacy concerns, since the ticket value may be used to correlate TLS sessions ๐
issuing a new pinning ticket with a shorter lifetime would only delay the ramp down process ๐ข. the shorter lifetime can only affect clients that actually started a new connection, and everyone else would still see the original lifetime for their pinning tickets ๐ฉ
5.6. Server Compromise ๐จ
if a server compromise is detected, the pinning protection key MUST be rotated immediately. but the server MUST still accept valid tickets that use the old, compromised key ๐ค. clients still holding old pinning tickets will stay vulnerable to MITM attacks, but the ones that connect to the correct server will immediately get new tickets protected with the newly generated pinning protection key ๐
the same procedure applies if the pinning protection key is compromised directly, for example if a backup copy is accidentally made public ๐
5.7. Disaster Recovery ๐
all web servers in production need to be backed up, so they can be recovered if a disaster (including malicious activity) ever wipes them out ๐พ. backups often include the certificate and its private key, which must be backed up securely. the pinning secret, including earlier versions that are still being accepted, must be backed up regularly ๐. however, since it's only used as an authentication second factor, it doesn't need the same level of confidentiality as the server's private key ๐ซง
readers should note that [RFC5077] session resumption keys are more security sensitive and should normally not be backed up, and should be treated as ephemeral keys instead ๐. even when servers derive pinning secrets from resumption keys (Section 4.1), they MUST NOT back up resumption keys ๐ โโ๏ธ
6. Security Considerations ๐
this section reviews a few security aspects of the proposed extension ๐ง
6.1. Trust-on-First-Use (TOFU) and MITM Attacks ๐ฑ
this protocol is a trust-on-first-use protocol ๐ผ. if a client initially connects to the "right" server, it'll be protected against MITM attackers for the lifetime of each received ticket. and if it connects regularly (depending, of course, on the server-selected lifetime), it stays constantly protected against fake certificates ๐ก๏ธ
BUT if it initially connects to an attacker, then subsequent connections to the "right" server will fail ๐. server operators might want to advise clients on how to remove corrupted pins, once these large-scale attacks get detected and remediated ๐งน
the protocol is designed so that it isn't vulnerable to an active MITM attacker who has real-time access to the original server ๐. the pinning proof includes a hash of the server's public key, so the client can be sure the proof was actually generated by the server it's connecting to โ
6.2. Pervasive Monitoring ๐๏ธ
some organizations, and even some countries, do pervasive monitoring on their constituents [RFC7258]. this often looks like always-active SSL proxies ๐ซ . because of the TOFU property, this protocol doesn't provide any security in those cases ๐ญ
pervasive monitoring may also cause the privacy concerns detailed in Section 6.7 ๐ต๏ธโโ๏ธ
6.3. Server-Side Error Detection ๐ต๏ธ
this one's unique: the protocol lets the server detect clients that present incorrect tickets, which means those clients can be assumed to be victims of a MITM attack ๐คฏ. server operators can treat these cases as indications of ongoing attacks, kind of like the fake certificate attacks that happened in a few countries in the past ๐ฉ
6.4. Client Policy and SSL Proxies ๐ง
like it or not, some clients are normally deployed behind an SSL proxy ๐ฅฒ. similar to [RFC7469], it's acceptable to let pinning be disabled for some hosts according to local policy โจ. for example, a User Agent (UA) MAY disable pinning for hosts whose validated certificate chain terminates at a user-defined trust anchor, rather than a trust anchor built into the UA (or the underlying platform) ๐ซง. and a client MAY accept an empty PinningTicket extension from such hosts as a valid response ๐
6.5. Client-Side Error Behavior ๐
okay so if a client gets a malformed or empty PinningTicket extension from a pinned server, it MUST abort the handshake ๐. And if the client retries the request, it MUST NOT leave the PinningTicket out of the retry message ๐ โโ๏ธ. Skipping it would basically hand attackers a free pass for trivial fallback attacks, kinda like the ones in [RFC7507] ๐ค.
ngl though, this rule can be a lot for clients that move from behind SSL proxies out to the open Internet, and back again, if the advice in Section 6.4 isn't followed ๐ฅบ. So it is RECOMMENDED that browser and library vendors provide a documented way to remove stored pins ๐งน๐.
6.6. Stolen and Forged Tickets ๐ฆนโโ๏ธ
main character attacker energy, but it doesn't work ๐. An attacker gets zero benefit from stealing pinning tickets, even with other pinning parameters like the associated pinning secret, because pinning tickets are there to secure the client rather than the server ๐ก๏ธ. Forging a ticket for a particular server is also totally useless ๐.
6.7. Client Privacy ๐ต๏ธโโ๏ธ
This protocol is designed so an external attacker can't link different requests to a single client, as long as the client requests and receives a fresh ticket on each connection ๐ฆ. This could be a concern especially during ramp down, if the server doesn't hand out a new ticket and the client keeps reusing the same one ๐ฌ. To reduce or avoid these privacy concerns, it is RECOMMENDED for the server to issue a fresh ticket with a reduced lifetime ๐ธ. That would at least shrink the window in which the client's TLS sessions can be linked โณ. The server MAY also issue tickets with a zero-second lifetime until it's confident all tickets are expired ๐ง.
On the other hand ๐, the server the client is connecting to can easily track the client ๐ซฃ. This can be an issue when the client expects to connect to the server (e.g., a mail server) with multiple identities ๐ง. Implementations SHOULD allow the user to opt out of pinning, either in general or for particular servers ๐.
This document doesn't define the exact content of tickets. Putting client-specific information in tickets would raise privacy concerns, so it is NOT RECOMMENDED ๐ซ.
6.8. Ticket Protection Key Management ๐
The ticket format isn't mandated by this document, but protecting the ticket with authenticated encryption is RECOMMENDED ๐. Some algorithms commonly used for authenticated encryption, e.g., Galois/Counter Mode (GCM), are highly vulnerable to nonce reuse, and this problem gets magnified in a cluster setting ๐ญ. Therefore, implementations that choose AES-GCM or any AEAD equivalent MUST adopt one of these three alternatives ๐ซถ:
- Partition the nonce namespace between cluster members and use monotonic counters on each member, e.g., by setting the nonce to the concatenation of the cluster member ID and an incremental counter ๐งฎ.
- Generate random nonces but avoid the so-called birthday bound. In other words, never generate more than the maximum allowed number of encrypted tickets (
2**64for AES-128-GCM) for the same ticket pinning protection key ๐. - An alternative design attributed to Karthik Bhargavan ๐. Start with a 128-bit master key
K_master, and then for each encryption, generate a 256-bit random nonce and computeK = HKDF(K_master, Nonce || "key"), thenN = HKDF(K_master, Nonce || "nonce"). Use these values to encrypt the ticket withAES-GCM(K, N, data). The nonce then has to be stored and sent along with the ticket ๐ง .
7. IANA Considerations ๐
The IANA has allocated a TicketPinning extension value in the "TLS ExtensionType Values" registry ๐.
[RFC8447] defines the procedure, requirements, and the necessary information for the IANA to update the "TLS ExtensionType Values" registry [TLS-EXT]. The registration procedure is "Specification Required" [RFC8126] ๐.
The TicketPinning extension is registered as follows. (The extension isn't limited to Private Use, so its first byte is in the range 0-254 โจ.)
Value: 32
Name: ticket_pinning
Recommended: No
TLS 1.3: CH, EE (to indicate that the extension is present in
ClientHello and EncryptedExtensions messages)
8. References ๐
8.1. Normative References ๐
- [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997,
https://www.rfc-editor.org/info/rfc2119. - [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for Writing an IANA Considerations Section in RFCs", BCP 26, RFC 8126, DOI 10.17487/RFC8126, June 2017,
https://www.rfc-editor.org/info/rfc8126. - [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, May 2017,
https://www.rfc-editor.org/info/rfc8174. - [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
https://www.rfc-editor.org/info/rfc8446. - [RFC8447] Salowey, J. and S. Turner, "IANA Registry Updates for TLS and DTLS", RFC 8447, DOI 10.17487/RFC8447, August 2018,
https://www.rfc-editor.org/info/rfc8447.
8.2. Informative References ๐
- [Netcraft] Mutton, P., "HTTP Public Key Pinning: You're doing it wrong!", March 2016,
https://news.netcraft.com/archives/2016/03/30/http-public-key-pinning-youre-doing-it-wrong.html. - [Oreo] Berkman, O., Pinkas, B., and M. Yung, "Firm Grip Handshakes: A Tool for Bidirectional Vouching", Cryptology and Network Security pp. 142-157, 2012.
- [RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, DOI 10.17487/RFC2104, February 1997,
https://www.rfc-editor.org/info/rfc2104. - [RFC5077] Salowey, J., Zhou, H., Eronen, P., and H. Tschofenig, "Transport Layer Security (TLS) Session Resumption without Server-Side State", RFC 5077, DOI 10.17487/RFC5077, January 2008,
https://www.rfc-editor.org/info/rfc5077. - [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008,
https://www.rfc-editor.org/info/rfc5246. - [RFC6454] Barth, A., "The Web Origin Concept", RFC 6454, DOI 10.17487/RFC6454, December 2011,
https://www.rfc-editor.org/info/rfc6454. - [RFC6962] Laurie, B., Langley, A., and E. Kasper, "Certificate Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
https://www.rfc-editor.org/info/rfc6962. - [RFC7258] Farrell, S. and H. Tschofenig, "Pervasive Monitoring Is an Attack", BCP 188, RFC 7258, DOI 10.17487/RFC7258, May 2014,
https://www.rfc-editor.org/info/rfc7258. - [RFC7469] Evans, C., Palmer, C., and R. Sleevi, "Public Key Pinning Extension for HTTP", RFC 7469, DOI 10.17487/RFC7469, April 2015,
https://www.rfc-editor.org/info/rfc7469. - [RFC7507] Moeller, B. and A. Langley, "TLS Fallback Signaling Cipher Suite Value (SCSV) for Preventing Protocol Downgrade Attacks", RFC 7507, DOI 10.17487/RFC7507, April 2015,
https://www.rfc-editor.org/info/rfc7507. - [RFC8555] Barnes, R., Hoffman-Andrews, J., McCarney, D., and J. Kasten, "Automatic Certificate Management Environment (ACME)", RFC 8555, DOI 10.17487/RFC8555, March 2019,
https://www.rfc-editor.org/info/rfc8555. - [TLS-EXT] IANA, "TLS Extension Type Value",
https://www.iana.org/assignments/tls-extensiontype-values/. - [TLS-TACK] Marlinspike, M., "Trust Assertions for Certificate Keys", Work in Progress, Internet-Draft, draft-perrin-tls-tack-02, 7 January 2013,
https://tools.ietf.org/html/draft-perrin-tls-tack-02.
Appendix A. Previous Work ๐ฆ
The global PKI system relies on CAs being trusted to issue certificates. That means a corrupted trusted CA can issue a certificate for any organization without that organization's approval (a misissued or "fake" certificate), and then use it to impersonate the organization ๐ฑ. People have tried a bunch of fixes for these weaknesses, including the Certificate Transparency (CT) protocol [RFC6962], HTTP Public Key Pinning (HPKP) [RFC7469], and Trust Assertions for Certificate Keys (TACK) [TLS-TACK] ๐ ๏ธ.
CT needs a big chunk of the hundreds of existing certificate authorities (CAs) to cooperate before it can be used "for real", in enforcing mode ๐ข. It's worth noting that the relevant industry forum (CA/Browser Forum) is definitely pushing for that kind of wide adoption ๐ฃ. However, CT's public nature often makes it inappropriate for enterprise use, because lots of organizations aren't willing to expose their internal infrastructure publicly ๐.
TACK has some similarities to the current proposal, but work on it seems to have stalled ๐ฅ. Appendix A.2 compares our proposal to TACK ๐.
HPKP is an IETF standard, but so far it has proven hard to deploy ๐ฉ. HPKP pins (fixes) a public key, one of the public keys listed in the certificate chain. That means HPKP has to be coordinated with the certificate management process, and certificate management affects HPKP, which makes HPKP failures more likely ๐. That risk is even higher because, even though the Automated Certificate Management Environment (ACME) working group has done work to automate certificate management, in many or even most cases certificates are still managed manually ๐งโ๐ป. So HPKP can't be fully automated, which leads to error-prone manual configuration, and those errors could stop some clients from reaching the web server at all ๐. HPKP also uses an HTTP header, which makes it HTTPS-specific rather than generic to TLS ๐ฅฑ. On the other hand, the current document provides a solution that doesn't depend on the server's certificate management and can be entirely and easily automated ๐คโจ. Appendix A.1 compares HPKP to the current document in more detail ๐ .
The ticket pinning proposal builds on these mechanisms with a much easier-to-implement and easier-to-deploy solution for server identity pinning, by reusing some of the ideas behind TLS session resumption ๐ธ๐ง.
This section compares ticket pinning to two earlier proposals, HPKP and TACK ๐.
A.1. Comparison: HPKP ๐
okay so the current IETF standard for pinning web server identity is HPKP [RFC7469] ๐
The main differences between HPKP and this doc are:
- HPKP only cares about HTTPS ๐, but this doc covers all applications above TLS โจ
- HPKP pins the server's public key (or another public key along the certificate chain), so it's super dependent on certificate management ๐ซ . That adds a lot of room for error, especially since certificate management isn't really automated yet. This proposal is independent of certificate management, and that's the slay ๐
- HPKP pins public keys that are public and used for the standard TLS authentication. Identity pinning depends on owning the pinning key, which is kept private and isn't part of standard TLS authentication. So identity pinning is a totally separate, second-factor authentication mechanism ๐
- HPKP relies on a backup key to recover from a misissued key. The authors think backup mechanisms add way too much complexity and cost ๐ค. This mechanism's reliability comes mostly from being highly automated ๐ค
- HPKP relies on the client to report errors to the report-uri. This doc doesn't need any out-of-band mechanism, because the server is informed automatically. That makes health monitoring easier and more reliable ๐
ngl though, HPKP and identity pinning have some things in common too ๐ซถ:
- Both give you hard failure. With HPKP, only the client knows about the failure. With this proposal, both the client and the server get informed, which leaves room for more mechanisms to automatically recover from failures ๐ฆ
- Both are vulnerable to a server compromise where users get an invalid ticket (like a random one) or an HTTP header with a very long lifetime ๐. For identity pinning, that lifetime SHOULD NOT be longer than 31 days. Either way, clients can't reconnect to the server during that lifetime. With this proposal the attacker has to compromise the TLS layer, while with HPKP they have to compromise the HTTP server. Arguably, TLS-level compromise is usually harder for the attacker ๐ง
Unfortunately, HPKP hasn't seen wide deployment yet ๐ญ. As of March 2016, fewer than 3000 servers were using HPKP [Netcraft]. That might just be inertia, but the authors think the main reason is how HPKP interacts with the manual certificate management needed to implement it on enterprise servers ๐ข. The penalty for messing up (like deploying new pins too early or too late) is that the server becomes unusable for some clients ๐.
To show what I mean, here are the steps for deploying HPKP on a security-sensitive web server ๐:
- Generate two public/private key pairs on a computer that is not the live server. The second one is the "backup1" key pair.
openssl genrsa -out "example.com.key" 2048;
openssl genrsa -out "example.com.backup1.key" 2048;
- Generate hashes for both public keys. These go in the HPKP header:
openssl rsa -in "example.com.key" -outform der -pubout | \
openssl dgst -sha256 -binary | openssl enc -base64
openssl rsa -in "example.com.backup1.key" -outform der \
-pubout | openssl dgst -sha256 -binary | openssl enc -base64
- Generate a single CSR (Certificate Signing Request) for the first key pair, with the domain name in the CN (Common Name) field:
openssl req -new -subj "/C=GB/ST=Area/L=Town/O=Org/ \
CN=example.com" -key "example.com.key" -out "example.com.csr";
- Send this CSR to the CA and go through the whole dance to prove you own the domain ๐. The CA will give you a single certificate that typically expires within a year or two.
- On the live server, upload and set up the first key pair and its certificate. At this point, you can add the "Public-Key-Pins" header, using the two hashes from step 2 โจ.
Note that only the first key pair has been uploaded to the server so far.
- Store the second (backup1) key pair somewhere safe, probably somewhere encrypted like a password manager ๐. It won't expire, since it's just a key pair. It just needs to be ready for when you need your next certificate.
- Time passes ๐ฐ๏ธ. That's probably just under a year (if you're waiting for a certificate to expire), or maybe sooner if you find your server has been compromised and you need to replace the key pair and certificate ๐ฑ.
- Create a new CSR using the "backup1" key pair, and get a new certificate from your CA.
- Generate a new backup key pair (backup2), get its hash, and store it somewhere safe (again, not on the live server) ๐ง.
- Replace your old certificate and old key pair, update the "Public-Key-Pins" header to remove the old hash, and add the new "backup2" key pair ๐.
Note that in the steps above, both the certificate issuance and the storage of the backup key pair involve manual steps ๐ฅฒ. Even with an automated CA that runs the ACME protocol [RFC8555], key backup would be a challenge to automate.
A.2. Comparison: TACK ๐ฆ
Compared with HPKP, TACK [TLS-TACK] is way more similar to this doc. Some would even argue this document is a symmetric-cryptography variant of TACK ๐ง . That said, there are still a few big differences:
- Probably the most important one is that with TACK, validating the server certificate is no longer required. In fact, TACK specifies it as a "MAY" requirement ([TLS-TACK], Section 5.3) ๐ณ. With ticket pinning, certificate validation by the client remains a MUST requirement, and the ticket only acts as a second factor ๐ก๏ธ. If the pinning secret gets compromised, the server's security isn't immediately at risk ๐.
- TACK and this doc are both mostly orthogonal to the server certificate's life cycle, so both can be deployed with no manual steps ๐คโจ.
- TACK uses Elliptic Curve Digital Signature Algorithm (ECDSA) to sign the server's public key. This lets cooperating clients share server assertions between themselves ๐ค. That's an optional TACK feature, and it's one that can't be done with pinning tickets.
- TACK lets multiple servers share its public keys. This doc doesn't allow that sharing ๐ซ.
- TACK doesn't let the server track a particular client, so it has better privacy properties than this doc ๐ต๏ธโโ๏ธ๐.
- TACK has an interesting way to decide the pin's lifetime: it's set to the time period since the pin was first observed, with a hard upper bound of 30 days โณ. This doc makes the lifetime explicit, which might be more flexible to deploy ๐. For example, websites that users only visit rarely might opt for a longer period than sites that expect daily visits ๐.
Acknowledgments ๐ซถ
The original idea behind this proposal was published in [Oreo] by Moti Yung, Benny Pinkas, and Omer Berkman ๐. The current protocol is only a distant relative of the original Oreo protocol, and any errors are the responsibility of the authors of this document alone ๐.
Big thanks to Adrian Farrel, Dave Garrett, Daniel Kahn Gillmor, Alexey Melnikov, Yoav Nir, Eric Rescorla, Benjamin Kaduk, and Rich Salz for their comments on this document ๐. Special thanks to Craig Francis for contributing the HPKP deployment script ๐, and to Ralph Holz for several fruitful discussions ๐ง.
Authors' Addresses ๐ฌ
Yaron Sheffer
Intuit
Email: yaronf.ietf@gmail.com
Daniel Migault
Ericsson
Email: daniel.migault@ericsson.com
๐ฆ where this page comes from
- ietf: rfc8672 2019-10
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms