RFC 9258

Importing External Pre-Shared Keys (PSKs) for TLS 1.3

๐Ÿ“… published July 2022, from ietf

Importing External Pre-Shared Keys (PSKs) for TLS 1.3 ๐ŸŽ€

okay bestie, this one is about getting outside keys into TLS 1.3 safely. here's the lineup:

  • RFC: 9258
  • Authors: D. Benjamin (Google, LLC.) and C. A. Wood (Cloudflare) ๐Ÿ‘ฉโ€๐Ÿ’ป
  • Category: Standards Track
  • ISSN: 2070-1721
  • Date: July 2022
  • Obsoletes / Updates: the header doesn't list anything it obsoletes or updates ๐Ÿงš

Abstract โœจ

okay so the whole point is this: it describes an interface for importing external Pre-Shared Keys (PSKs) into TLS 1.3. that's it, that's the tea ๐Ÿ“

Status of This Memo ๐Ÿ“‹

this is an Internet Standards Track document. it's a product of the IETF, it reflects what the IETF community agreed on, got public review, and was approved for publication by the IESG. if you want more on what Internet Standards are, check Section 2 of RFC 7841. for errata and how to send feedback, go to https://www.rfc-editor.org/info/rfc9258. ๐Ÿ’…

copyright (c) 2022 IETF Trust and the persons identified as the document authors. all rights reserved, obviously ๐Ÿซถ

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 stood on the publication date. please actually read those, because they spell out your rights and restrictions for this document. and if you pull code components out of this document, they have to include the Revised BSD License text described in Section 4.e of the Trust Legal Provisions. those code components come with no warranty, as the Revised BSD License describes.

Table of Contents ๐Ÿ—บ๏ธ

1.  Introduction
2.  Conventions and Definitions
3.  Terminology
4.  Overview
5.  PSK Importer
  5.1.  External PSK Diversification
  5.2.  Binder Key Derivation
6.  Deprecating Hash Functions
7.  Incremental Deployment
8.  Security Considerations
9.  Privacy Considerations
10. IANA Considerations
11. References
  11.1.  Normative References
  11.2.  Informative References
Appendix A.  Addressing Selfie
Acknowledgements
Authors' Addresses

1. Introduction ๐Ÿฆ‹

so TLS 1.3 [RFC8446] supports Pre-Shared Key (PSK) authentication, and those PSKs can come from session tickets on earlier connections or from some external, out-of-band mechanism. the protocol requires each PSK to be used with only one hash function, which was done to make protocol analysis simpler.

TLS 1.2 [RFC5246] is the opposite vibe. there's no such rule there, so a PSK can be used with any hash algorithm and the TLS 1.2 pseudorandom function (PRF) ๐ŸŒธ

there's no known way for the same external PSK to produce related output in TLS 1.3 and the older versions, but honestly only limited analysis has been done, so we're not gonna just assume it's fine. applications SHOULD provision separate PSKs for (D)TLS 1.3 and prior versions. and if that's not doable (say you already have external PSKs out in the wild, or provisioning is super limited), reusing external PSKs across different TLS versions might produce related outputs, which can lead to security problems. see Appendix E.7 of [RFC8446] for the scary details ๐Ÿ˜ญ

so to fix this, the document specifies a PSK importer interface. it lets you import external PSKs and then bind them to a specific key derivation function (KDF) and hash function for use in TLS 1.3 [RFC8446] and DTLS 1.3 [RFC9147]. the big trick: the importer mixes in the target KDF, the (D)TLS protocol version, and an optional context string so everything stays unique. the result is a set of candidate PSKs, each bound to a target KDF and protocol, and each kept separate from the ones used in (D)TLS 1.2 and earlier. so one PSK and identity turns into a whole set of PSKs and identities. iconic restructuring ๐Ÿ‘‘

2. Conventions and Definitions ๐Ÿ“–

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. so capitals = the official meaning, lowercase = just a normal word ๐Ÿ™ˆ

3. Terminology ๐Ÿ’œ

these are the terms used all throughout the doc:

  • External PSK (EPSK): a PSK that's set up or provisioned out of band, meaning not from a TLS connection. it's a tuple of (Base Key, External Identity, Hash).
  • Base Key: the secret value of an EPSK.
  • External Identity: a sequence of bytes used to identify an EPSK.
  • Target protocol: the protocol a PSK gets imported for.
  • Target KDF: the KDF a PSK gets imported for.
  • Imported PSK (IPSK): a TLS PSK derived from an EPSK, an optional context string, a target protocol, and a target KDF.
  • Non-imported PSK: an EPSK used directly as a TLS PSK without being imported.
  • Imported Identity: a sequence of bytes used to identify an IPSK.

this document uses presentation language from Section 3 of [RFC8446] too โœจ

4. Overview ๐ŸŒˆ

the PSK importer interface is basically a cousin of the TLS exporter interface (see [RFC8446]). both diversify a key using some contextual info. the difference is that the exporter gets its uniqueness from an explicit label and context string, while the importer takes an external PSK and identity and "imports" them into TLS. that makes a set of "derived" PSKs and identities that are each unique ๐Ÿงš

each derived PSK is bound to a target protocol, a KDF identifier, and an optional context string. the resulting PSK binder keys also get a new derivation label, so they can't get mixed up with non-imported PSKs. importing external PSKs with different identities gives you distinct PSK binder keys, which is so clean ๐Ÿซถ

imported keys don't need any negotiation to be used, since a client and server simply won't agree on identities if an import was done wrong. endpoints can roll out PSK importer support gradually by offering non-imported PSKs for TLS versions before 1.3. non-imported and imported PSKs aren't equivalent, because their identities are different. see Section 7 for more on that.

endpoints that import external keys MUST NOT use the input keys for anything other than the import process, and they MUST NOT use the derived keys for anything other than TLS PSKs. also, every external PSK fed into the importer MUST be associated with one hash function at most. this lines up with the rules in Section 4.2.11 of [RFC8446]. see Section 8 for the deeper dive โš ๏ธ

5. PSK Importer ๐Ÿ”ฅ

this section covers the PSK importer interface, the diversification mechanism underneath it, and the change to how binder keys are computed.

5.1. External PSK Diversification

okay so the PSK importer takes in an EPSK, which has an External Identity external_identity and a base key epsk (from Section 3 โœจ), plus an optional context ๐ŸŽ€. then it transforms all of that into a set of PSKs and imported identities for a connection, based on the target protocols and KDFs. specifically, for each supported target protocol target_protocol and KDF target_kdf, the importer builds an ImportedIdentity structure like this ๐Ÿ’…:

struct {
   opaque external_identity<1...2^16-1>;
   opaque context<0..2^16-1>;
   uint16 target_protocol;
   uint16 target_kdf;
} ImportedIdentity;

the list of ImportedIdentity.target_kdf values is kept by IANA, as explained in Section 10 ๐Ÿ“‹. External PSKs MUST NOT be imported for (D)TLS 1.2 or prior versions ๐Ÿ™…โ€โ™€๏ธ. see Section 7 for the tea on how imported PSKs for TLS 1.3 and non-imported PSKs for earlier versions coexist during incremental deployment ๐Ÿ“.

ImportedIdentity.context MUST include the context used to determine the EPSK, if any exists. for example, it can include info about peer roles or identities to mitigate Selfie-style reflection attacks [Selfie] ๐Ÿฆ‹. see Appendix A for more details. since the EPSK is a key derived from an external protocol or a sequence of protocols, ImportedIdentity.context MUST include a channel binding for the deriving protocols [RFC5056] ๐Ÿซถ. the details of this binding are protocol specific and out of scope for this document ๐Ÿ™ˆ.

ImportedIdentity.target_protocol MUST be the (D)TLS protocol version for which the PSK is being imported. for example, TLS 1.3 [RFC8446] uses 0x0304, which will therefore also be used by QUICv1 [QUIC] ๐ŸŒˆ. note that this means the number of PSKs derived from an EPSK is a function of the number of target protocols ๐Ÿ‘‘.

given an ImportedIdentity and the corresponding EPSK with base key epsk, an imported PSK IPSK with base key ipskx is computed like this โœจ:

epskx = HKDF-Extract(0, epsk)
ipskx = HKDF-Expand-Label(epskx, "derived psk",
                          Hash(ImportedIdentity), L)

L corresponds to the KDF output length of ImportedIdentity.target_kdf as defined in Section 10. for hash-based KDFs, such as HKDF_SHA256 (0x0001), this is the length of the hash function output, e.g., 32 octets for SHA256. this is required for the IPSK to be of length suitable for supported ciphersuites ๐Ÿ”ฅ. internally, HKDF-Expand-Label uses a label corresponding to ImportedIdentity.target_protocol (e.g., "tls13" for TLS 1.3, as per Section 7.1 of [RFC8446] or "dtls13" for DTLS 1.3, as per Section 5.10 of [RFC9147]) ๐Ÿงš.

the identity of ipskx as sent on the wire is ImportedIdentity, i.e., the serialized content of ImportedIdentity is used as the content of PskIdentity.identity in the PSK extension. the corresponding PSK input for the TLS 1.3 key schedule is "ipskx" ๐ŸŽ€.

as the maximum size of the PSK extension is 2^16 - 1 octets, an Imported Identity that exceeds this size is likely to cause a decoding error ๐Ÿ˜ญ. therefore, the PSK importer interface SHOULD reject any ImportedIdentity that exceeds this size ๐Ÿšซ.

the hash function used for HMAC-based Key Derivation Function (HKDF) [RFC5869] is the one associated with the EPSK ๐Ÿ’œ. it is NOT the hash function associated with ImportedIdentity.target_kdf. if the EPSK does not have such an associated hash function, SHA-256 [SHA2] SHOULD be used ๐ŸŒธ. diversifying EPSK by ImportedIdentity.target_kdf ensures that an IPSK is only used as input keying material to one KDF at most, thus satisfying the requirements in [RFC8446]. see Section 8 for more details ๐Ÿฆ‹.

Endpoints SHOULD generate a compatible ipskx for each target ciphersuite they offer ๐Ÿ’–. for example, importing a key for TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384 would yield two PSKs: one for HKDF-SHA256 and another for HKDF-SHA384. in contrast, if TLS_AES_128_GCM_SHA256 and TLS_CHACHA20_POLY1305_SHA256 are supported, only one derived key is necessary. each ciphersuite uniquely identifies the target KDF. future specifications that change the way the KDF is negotiated will need to update this specification to make clear how target KDFs are determined for the import process ๐Ÿ”ฎ.

EPSKs MAY be imported before the start of a connection if the target KDFs, protocols, and context string(s) are known a priori โญ. EPSKs MAY also be imported for early data use if they are bound to the protocol settings and configuration that are required for sending early data ๐Ÿ“. minimally, this means that the Application-Layer Protocol Negotiation (ALPN) value [RFC7301], QUIC transport parameters (if used for QUIC), and any other relevant parameters that are negotiated for early data MUST be provisioned alongside these EPSKs ๐Ÿ’….


5.2. Binder Key Derivation

to prevent confusion between imported and non-imported PSKs, imported PSKs change the PSK binder key derivation label ๐ŸŽ€. in particular, the standard TLS 1.3 PSK binder key computation is defined as follows:

           0
           |
           v
 PSK ->  HKDF-Extract = Early Secret
           |
           +-----> Derive-Secret(., "ext binder" | "res binder", "")
           |                     = binder_key
           V

imported PSKs use the string "imp binder" rather than "ext binder" or "res binder" when deriving binder_key. this means the binder key is computed as follows โœจ:

           0
           |
           v
 PSK ->  HKDF-Extract = Early Secret
           |
           +-----> Derive-Secret(., "ext binder"
           |                      | "res binder"
           |                      | "imp binder", "")
           |                     = binder_key
           V

this new label ensures a client and server will negotiate use of an external PSK if and only if (a) both endpoints import the PSK or (b) neither endpoint imports the PSK ๐Ÿค. as binder_key is a leaf key, changing its computation does not affect any other key ๐Ÿง .


6. Deprecating Hash Functions

if a client or server wishes to deprecate a hash function and no longer use it for TLS 1.3, it removes the corresponding KDF from the set of target KDFs used for importing keys ๐Ÿ—‘๏ธ. this does not affect the KDF operation used to derive imported PSKs ๐Ÿ’….

7. Incremental Deployment

in deployments that already have PSKs provisioned and in use with TLS 1.2, attempting to incrementally deploy the importer mechanism would result in concurrent use of the already-provisioned PSK directly as both a TLS 1.2 PSK and an EPSK ๐Ÿ˜ฌ. this, in turn, could mean that the same KDF and key would be used in two different protocol contexts. this is not a recommended configuration; see Section 8 for more details ๐Ÿ™ˆ. however, the benefits of using TLS 1.3 and PSK importers may prove sufficiently compelling that existing deployments choose to enable this noncompliant configuration for a brief transition period while new software (using TLS 1.3 and importers) is deployed โœจ. operators are advised to make any such transition period as short as possible โณ.

8. Security Considerations

okay this section is SERIOUS bestie ๐Ÿšจ๐Ÿ˜ญ. the PSK importer security goals can be roughly stated as follows: avoid PSK reuse across KDFs while properly authenticating endpoints ๐Ÿ”. when modeled as computational extractors, KDFs assume that input keying material (IKM) is sampled from some "source" probability distribution and that any two IKM values are chosen independently of each other [Kraw10]. this source-independence requirement implies that the same IKM value cannot be used for two different KDFs ๐Ÿ’€.

PSK-based authentication is functionally equivalent to session resumption, in that a connection uses existing key material to authenticate both endpoints. following the work of [BAA15], this is a form of compound authentication ๐Ÿงฉ. loosely speaking, compound authentication is the property that an execution of multiple authentication protocols, wherein at least one is uncompromised, jointly authenticates all protocols. therefore, authenticating with an externally provisioned PSK should ideally authenticate both the TLS connection and the external provisioning process ๐Ÿ’œ. typically, the external provisioning process produces a PSK and a corresponding context from which the PSK was derived and in which it should be used. if available, this is used as the ImportedIdentity.context value ๐ŸŽ€. we refer to an external PSK without such context as "context-free" ๐ŸŒธ.

thus, in considering the source-independence and compound authentication requirements, the PSK importer interface described in this document aims to achieve the following goals ๐ŸŽฏ:

  1. Externally provisioned PSKs imported into a TLS connection achieve compound authentication of the provisioning process and connection.
  2. Context-free PSKs only achieve authentication within the context of a single connection.
  3. Imported PSKs are not used as IKM for two different KDFs.
  4. Imported PSKs do not collide with future protocol versions and KDFs.

there are no known related outputs or security issues caused from the process for computing imported PSKs from an external PSK and the processing of existing external PSKs used in (D)TLS 1.2 and below, as noted in Section 7 ๐Ÿคž. however, only limited analysis has been done, which is an additional reason why applications SHOULD provision separate PSKs for (D)TLS 1.3 and prior versions, even when the importer interface is used in (D)TLS 1.3 ๐Ÿ™.

the PSK importer does not prevent applications from constructing non-importer PSK identities that collide with imported PSK identities ๐Ÿ˜ฑ.

9. Privacy Considerations

External PSK identities are commonly static by design so that endpoints may use them to look up keying material ๐Ÿ”. as a result, for some systems and use cases, this identity may become a persistent tracking identifier ๐Ÿ‘€.

note also that ImportedIdentity.context is visible in cleartext on the wire as part of the PSK identity ๐Ÿ“ข. unless otherwise protected by a mechanism such as TLS Encrypted ClientHello [ECH], applications SHOULD NOT put sensitive information in this field ๐Ÿ™…โ€โ™€๏ธ๐Ÿ”’.

10. IANA Considerations

IANA has created the "TLS KDF Identifiers" registry under the existing "Transport Layer Security (TLS) Parameters" registry ๐Ÿ“‹โœจ.

the entries in the registry are as follows ๐Ÿ’…:

+========+=================+===========+
| Value  | KDF Description | Reference |
+========+=================+===========+
| 0x0000 | Reserved        | RFC 9258  |
+--------+-----------------+-----------+
| 0x0001 | HKDF_SHA256     | [RFC5869] |
+--------+-----------------+-----------+
| 0x0002 | HKDF_SHA384     | [RFC5869] |
+--------+-----------------+-----------+

Table 1: TLS KDF Identifiers Registry

new target KDF values are allocated according to the following process ๐ŸŒˆ:

  • Values in the range 0x0000-0xfeff are assigned via Specification Required [RFC8126].
  • Values in the range 0xff00-0xffff are reserved for Private Use [RFC8126].

the procedures for requesting values in the Specification Required space are specified in Section 17 of [RFC8447] ๐Ÿ“.

11. References

the reference list continues in the next part ๐Ÿ’–๐ŸŽ€

11. References ๐Ÿ“š

11.1. Normative References ๐Ÿ’…

11.2. Informative References ๐Ÿฆ‹


Appendix A. Addressing Selfie ๐Ÿ™ˆ

okay so the Selfie attack [Selfie] is literally a case of misusing the PSK interface ๐Ÿ˜ญ. The PSK interface quietly assumes that each PSK is only known to one client and one server. If multiple clients or multiple servers with distinct roles share a PSK, TLS only authenticates the whole group, not the specific role. A node successfully authenticates its peer as being in the group, even when that peer is actually itself. ngl that's a wild one. This can also happen when there are two nodes sharing a PSK and they don't have predetermined roles.

Apps that need to check finer-grained roles while still setting up one shared PSK across all the nodes can fix this mismatch in one of two ways. They can swap roles over the TLS connection after the handshake, or they can put the roles of both the client and the server into the IPSK context string ๐ŸŽ€. For example, if an app identifies each node by its Media Access Control (MAC) address, it could use this context string:

  struct {
    opaque client_mac<0..2^8-1>;
    opaque server_mac<0..2^8-1>;
  } Context;

If an attacker then redirects a ClientHello meant for one node to a different node, including the node that made the ClientHello, the receiver computes a different context string and the handshake won't complete. iconic defense ๐Ÿ’–

Just note that in this setup there's still a single shared PSK across all the nodes, so each node has to be trusted not to impersonate another node's role. no cap, that part is on the nodes ๐Ÿซถ

Acknowledgements ๐ŸŒธ

Big thank yous to Eric Rescorla and Martin Thomson for the chats that got this doc going ๐Ÿ’œ, and to Christian Huitema for input on privacy considerations of external PSKs โœจ. John PreuรŸ Mattsson gave input on PSK importer deployment considerations ๐Ÿงš. Hugo Krawczyk guided the security considerations ๐Ÿ”ฅ. Martin Thomson, Jonathan Hoyland, Scott Hollenbeck, Benjamin Kaduk, and others all reviewed the document and gave feedback and suggestions to make it better ๐Ÿ‘‘. literally the squad ๐ŸŒˆ

Authors' Addresses ๐Ÿ“

David Benjamin Google, LLC. Email: davidben@google.com

Christopher A. Wood Cloudflare Email: caw@heapingbits.net

๐Ÿ“ฆ where this page comes from