As input, the PSK importer interface takes an EPSK with External Identity
external_identity and base key
epsk (as defined in
Section 3) along with an optional context. It then transforms the input into a set of PSKs and imported identities for use in a connection based on target protocols and KDFs. In particular, for each supported target protocol
target_protocol and KDF
target_kdf, the importer constructs an ImportedIdentity structure as follows:
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 maintained by IANA as described in
Section 10. External PSKs
MUST NOT be imported for (D)TLS 1.2 or prior versions. See
Section 7 for discussion on how imported PSKs for TLS 1.3 and non-imported PSKs for earlier versions coexist for incremental deployment.
ImportedIdentity.context
MUST include the context used to determine the EPSK, if any exists. For example, ImportedIdentity.context may include information 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 sequence of protocols, ImportedIdentity.context
MUST include a channel binding for the deriving protocols [
RFC 5056]. 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 [
RFC 8446] 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 corresponding EPSK with base key
epsk, an imported PSK IPSK with base key
ipskx is computed as follows:
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
RFC 8446 or "dtls13" for DTLS 1.3, as per
Section 5.10 of
RFC 9147).
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) [
RFC 5869] is that which is 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 [
RFC 8446]. 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 [
RFC 7301], QUIC transport parameters (if used for QUIC), and any other relevant parameters that are negotiated for early data
MUST be provisioned alongside these EPSKs.
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.