Draft: draft-ietf-tls-external-psk-importer

Commentary: Also , remove PSK identity encryption sketch . This was underspecified and can always be done in a separate draft if desired . cc 
 Note , we might want to simply consider merging and into the same field , since we have the registry . That 'd save us two bytes . It seems to boil down to whether keeping protocol and KDF separate is better ( long term ) than merging them . I 'm not sure what 's the best answer there . 
 In reviewing the draft , it was not clear that the input PSK was also bound to a hash function , but that the process could produce a derived PSK bound to any hash function . As this is the primary function of the document , that seems problematic . This seems to be the answer to this : I assume that this means KDF rather than hash function throughout ( the KDF - bound thing seems right ) . But it never really comes out and says that : 
 It 's optionally bound to a hash function . In defining external PSKs , the document states that the " associated  ( and hash function ) may be undefined . " Do you think it would be more clear to put this in the introduction ? ( Minimally , as you point out , the introduction should not assume that the KDF - bound PSK as input is not quite right , so that should probably change . ) As for the second comment ( KDF output ) , that 's not quite the goal . The importer binds input PSKs to a hash via HKDF , not via the TLS KDF . ( The TLS 1.2 PRF is not used . ) To summarize , my view is that the contract is more or less : optional hash - bound PSK in , hash - bound PSK out . Does that seem incorrect to you ? 
  , my understanding is that we do n't have any support for optional bindings on input . I 'm inclined to say that we need stricter constraints on input . Namely that they are bound to a specific KDF and that KDF needs to take a context struct in the form this document describes . Yes , limiting the concrete instantiation of this to HKDF is fine ( and the only sensible option ) . However , if you do n't bind the input key more tightly , you will end up shifting the problem you set out to solve one step further out . 
 I 'm not sure I follow anymore ! In my view , the problem we aim to solve is one where the external PSK was not provisioned " correctly , " i.e. , with the right hash ( KDF ) function in mind . It 's just a plain old n - bit key . The importer is designed to bind this key to a specific hash ( KDF ) . If the machinery that produced external PSKs was forced to change to accommodate a KDF , then it seems that machinery could also vend PSKs that do precisely what the importer does . Namely , differentiate by ( context , protocol , hash / KDF ) . Perhaps I 'm misunderstanding your point . Can you please clarify ? If you 're looking for a specific change , could you please make a suggestion ? 
 In TLS 1.2 and earlier , PSKs were not bound to a KDF . Now in TLS 1.3 , a PSK is required to be bound to a KDF . I thought the goal was to start with a PSK that is not bound to a KDF and produce a PSK that can be used in the desired context . So , the input is always a " plain old n - bit key " (  ' words ) . The output , when the desired context is TLS 1.3 , must include the KDF . 
 This is exactly what the importer does . Do you disagree ? 
 It is not clear to me what the importer does if I want the context to be TLS 1.2 . 
 It changes the info ( or proposed field ) value and runs the key through a KDF . 
 Right , I get that , which I think will bind the resulting key to TLS 1.2 but allow any KDF . I think the document should be explicit if that is the case . 
 Looking at , I think that you want to bind this to the TLS 1.2 KDF differently by using a different KDF identifier . The identifiers you have are only good for TLS 1.3 . You probably also want security considerations addressing the fact that the TLS 1.2 has this odd characteristic . 
 Can you please elaborate on why you think this is necessary ? As an example , let 's assume I have an external PSK and I want to import it for TLS 1.2 and 1.3 , and I only want to support one hash function ( or KDF ) . Let 's say that KDF is HKDFSHA256 . I would then import with the tuples ( 0x0303 , HKDFSHA256 ) and ( 0x0304 , HKDF_SHA256 ) , and it seems I 'd have the desired separation . In other words , I do n't see a technical reason why importing PSKs for TLS 1.2 requires use of the TLS 1.2 KDF ( PRF ) . 
 I think we are saying the same thing , except that when the protocol version is TLS 1.2 that it will be used with the PRF that is negotiated in the TLS 1.2 handshake . I just think the document should say that explicitly . 
 This is not what I 'm saying ! I 'm saying do not use the TLS 1.2 PRF . Rather , use HKDF . Can you clarify why you think the TLS 1.2 PRF should be used instead ? 
 There are two thongs that are being confused here . First , the one used to create the protocol - version - specific key . This is the one that you want to always use HKDF . That is fine with me . Second , with TLS 1.3 , it is bound to a particular hash function . I am saying that when a key is derived for TLS 1.2 the document should say that it will be used with whatever PRF is negotiated in the TLS handshake . Right now , I do d not see anything about that in the document at all . 
 Thanks for clarifying ! If I use an external PSK for TLS 1.2 today , without any import step , it 's already the case that it 's used with whatever PRF is negotiated in the handshake . The importer does not change that , and therefore I think does n't need to say anything about that . 
 I just think it would be better say it since TLS 1.3 had a binding but TLS 1.2 does not . You now understand my point , so I will leave it to you as author . 
 Why is this a string and not the protocol version number ? It sure would be easier that way . 
 In writing up , I realize now that the combination of label and hash is what is being used to identify a KDF . I think that you need to allow for the HashAlgorithm to be replaced by something else in future , or for different applications other than TLS . It might pay to instead reduce the tuple of ( tls version , hash ) to a single identifier that says tls12sha256 , tls13hkdf_sha256 , which might broaden applicability . That could be crazy - talk though . Either way , it would be good to understand this better in the abstract so as to make a less ad hoc decision about what is being identified and then how . 
 I agree that the info string should probably just be a version . I imagine there will be a use case where someone wants to , say , import with the label " tls1.3 special sauce " . In this case , they could KDF their PSK with the the " special sauce " string and then import with the " tls13 " label . And at this point , it might as well be the version number . Let 's assume this will be done , and the new field will be called " protocol " . So that leaves the question about what to do for the hash algorithm . As you point out , removing the HashAlgorithm dependency would be good for the future . ( We have a TODO in the draft to that effect . ) So the question then becomes , do we merge whatever this new field is with " protocol , " or do we keeep them separate . I do n't think we need to merge these for " level matching " or other purposes , so I 'm inclined to keep them separate . Thus , how about thee following structure : Where is a uint16 codepoint , and is an HPKE - like identifier [ 1 ] for a KDF , such as HKDF - SHA256 or HKDF - SHA512 . We could then define the importer with respect to this KDF , rather than baking in a hard dependency on HKDF . what do you think ? [ 1 ] 
 That seems reasonable - I think that there is some reason to separate target protocol ( and version , as a tuple ) from the KDF that is used . There 's a trick in terms of finding the right level of identification to use for the protocol . I suspect that seeding a registry with 0x0304 and 0x0303 is probably the right way to do this . That has the effect of constraining TLS a little in how it chooses version numbers , but I think that 's workable . ( As a reminder , in case you thought this was too easy , QUIC uses a 32 - bit identifier for versions . We 'd need a mapping QUIC . just makes this look simple . ) 
 Currently the context binds the info string ( or proposed field ) to the version of TLS , not to the calling application or protocol ( QUIC ) . 
 Do we want to allow the output of the KDF to be anything other that Nh ? Right now , L is always , which I think i the Nh value associated with the HPKE - like identifier . 
 Correct ! I ca n't see a reason why we 'd want the KDF output to be something different . Do you have a use case in mind ? 
 If we want this to apply to other contexts , like your special sauce above , it is unclear to me that is always the right answer . 
 The point of the importer is to produce a PSK for use in TLS . Why would the context affect the length ? 
 The discussion of is opening this for other protocol contexts too . 
 I made the proposed change in . Please have a look ! 
 Works for me
Paragraph (version A):
To mitigate these problems, external PSKs can be bound to a specific
hash function when used in TLS 1.3, even if they are associated with
a different KDF (and hash function) when provisioned.  This document
specifies an interface by which external PSKs may be imported for use
in a TLS 1.3 connection to achieve this goal.  In particular, it
describes how KDF-bound PSKs can be differentiated by different hash
algorithms to produce a set of candidate PSKs, each of which are
bound to a specific hash function.  This expands what would normally
have been a single PSK identity into a set of PSK identities.
However, it requires no change to the TLS 1.3 key schedule.
Paragraph (version A):
Intuitively, key importers mirror the concept of key exporters in TLS
in that they diversify a key based on some contextual information
before use in a connection.  In contrast to key exporters, wherein
differentiation is done via an explicit label and context string, the
key importer defined herein uses a label and set of hash algorithms
to differentiate an external PSK into one or more PSKs for use.
Paragraph (version A):
External PSK (EPSK): A PSK established or provisioned out-of-band,
i.e., not from a TLS connection, which is a tuple of (Base Key,
External Identity, KDF).  The associated KDF (and hash function)
may be undefined.
Paragraph (version A):
Imported Identity: The identity of a PSK as sent on the wire.
Paragraph (version A):
ImportedIdentity.label MUST be bound to the protocol for which the
key is imported.  Thus, TLS 1.3 and QUICv1 I-D.ietf-quic-transport
MUST use "tls13" as the label.  Similarly, TLS 1.2 and all prior TLS
versions should use "tls12" as ImportedIdentity.label, as well as
SHA256 as ImportedIdentity.hash.  Note that this means future
versions of TLS will increase the number of PSKs derived from an
external PSK.
Paragraph (version A):
ImportedIdentity.context MUST include the context used to derive the
EPSK, if any exists.  If the EPSK is a key derived from some other
protocol or sequence of protocols, ImportedIdentity.context MUST
include a channel binding for the deriving protocols RFC5056.  If any
secrets are agreed in earlier protocols they SHOULD be included in
ImportedIdentity.context CCB.
Paragraph (version A):
The hash function used for HKDF RFC5869 is that which is associated
with the external PSK.  It is not bound to ImportedIdentity.hash.  If
no hash function is specified, SHA-256 MUST be used.  Differentiating
epsk by ImportedIdentity.hash ensures that each imported PSK is only
used with at most one hash function, thus satisfying the requirements
in RFC8446.  Endpoints MUST import and derive an ipsk for each hash
function used by each ciphersuite they support.  For example,
importing a key for TLS_AES_128_GCM_SHA256 and TLS_AES_256_GCM_SHA384
would yield two PSKs, one for SHA256 and another for SHA384.  In
contrast, if TLS_AES_128_GCM_SHA256 and TLS_CHACHA20_POLY1305_SHA256
are supported, only one derived key is necessary.
Paragraph (version A):
The resulting IPSK base key 'ipskx' is then used as the binder key in
TLS 1.3 with identity ImportedIdentity.  With knowledge of the
supported hash functions, one may import PSKs before the start of a
connection.
Paragraph (version B):
Key importers mirror the concept of key exporters in TLS in that they
diversify a key based on some contextual information before use in a
connection.  In contrast to key exporters, wherein differentiation is
done via an explicit label and context string, the key importer
defined herein uses an optional context string along with a target
protocol and KDF identifier to differentiate an external PSK into one
or more PSKs for use.
Paragraph (version B):
Imported keys do not require negotiation for use, as a client and
server will not agree upon identities if not imported correctly.
Thus, importers induce no protocol changes with the exception of
expanding the set of PSK identities sent on the wire.  Endpoints may
incrementally deploy PSK importer support by offering non-imported
keys for TLS versions prior to TLS 1.3.  Non-imported and imported
PSKs are distinct since their identities are different on the wire.
See rollout for more details.
Paragraph (version B):
Clients which import external keys TLS MUST NOT use these keys for
any other purpose.  Moreover, each external PSK MUST be associated
with at most one hash function.
Paragraph (version B):
External PSK (EPSK): A PSK established or provisioned out-of-band,
i.e., not from a TLS connection, which is a tuple of (Base Key,
External Identity, Hash).
Paragraph (version B):
Target protocol: The protocol for which a PSK is imported for use.
Paragraph (version B):
Target KDF: The KDF for which a PSK is imported for use.
Paragraph (version B):
Imported PSK (IPSK): A PSK derived from an EPSK, external
identity, optional context string, and target protocol and KDF.
Paragraph (version B):
Imported Identity: The identity of an Imported PSK as sent on the
wire.
Paragraph (version B):
The list of "target_kdf" values is maintained by IANA as described in
IANA.  External PSKs MUST NOT be imported for versions of (D)TLS 1.2
or prior versions.  See rollout for discussion on how imported PSKs
for TLS 1.3 and non-imported PSKs for earlier versions co-exist for
incremental deployment.
Paragraph (version B):
ImportedIdentity.context MUST include the context used to derive the
EPSK, if any exists.  For example, ImportedIdentity.context may
include information about peer roles or identities to mitigate
Selfie-style reflection attacks.  See mitigate-selfie for more
details.  If the EPSK is a key derived from some other protocol or
sequence of protocols, ImportedIdentity.context MUST include a
channel binding for the deriving protocols RFC5056.
Paragraph (version B):
ImportedIdentity.target_protocol MUST be the (D)TLS protocol version
for which the PSK is being imported.  For example, TLS 1.3 RFC8446
and QUICv1 QUIC use 0x0304.  Note that this means future versions of
TLS will increase the number of PSKs derived from an external PSK.
Paragraph (version B):
L is corresponds to the KDF output length of
ImportedIdentity.target_kdf as defined in IANA.  For hash-based KDFs,
such as HKDF_SHA256(0x0001), this is the length of the hash function
output, i.e., 32 octets.  This is required for the IPSK to be of
length suitable for supported ciphersuites.
Paragraph (version B):
The identity of 'ipskx' as sent on the wire is ImportedIdentity.
Paragraph (version B):
The hash function used for HKDF RFC5869 is that which is associated
with the EPSK.  It is not the hash function associated with
ImportedIdentity.target_kdf.  If no hash function is specified,
SHA-256 MUST be used.  Diversifying EPSK by
ImportedIdentity.target_kdf ensures that an IPSK is only used as
input keying material to at most one KDF, thus satisfying the
requirements in RFC8446.
Paragraph (version B):
Endpoints 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.
Paragraph (version B):
The resulting IPSK base key 'ipskx' is then used as the binder key in
TLS 1.3 with identity ImportedIdentity.  With knowledge of the
supported KDFs, one may import PSKs before the start of a connection.
Paragraph (version A):
For clarity, the following table specifies PSK importer labels for
varying instances of the TLS handshake.
Paragraph (version A):
If a client or server wish to deprecate a hash function and no longer
use it for TLS 1.3, they may remove this hash function from the set
of hashes used during while importing keys.  This does not affect the
KDF operation used to derive concrete PSKs.
Paragraph (version A):
Recall that TLS 1.2 permits computing the TLS PRF with any hash
algorithm and PSK.  Thus, an external PSK may be used with the same
KDF (and underlying HMAC hash algorithm) as TLS 1.3 with importers.
However, critically, the derived PSK will not be the same since the
importer differentiates the PSK via the identity and hash function.
Thus, PSKs imported for TLS 1.3 are distinct from those used in TLS
1.2, and thereby avoid cross-protocol collisions.  Note that this
does not preclude endpoints from using non-imported PSKs for TLS 1.2.
Indeed, this is necessary for incremental deployment.
Paragraph (version A):
This is a WIP draft and has not yet seen significant security
analysis.
Paragraph (version A):
DISCLAIMER: This section contains a sketch of a design for protecting
external PSK identities.  It is not meant to be implementable as
written.
Paragraph (version A):
ObfuscatedIdentity.nonce carries N,
ObfuscatedIdentity.obfuscated_identity carries HMAC(ipskx, N), where
HMAC is computed with ImportedIdentity.hash, and
ObfuscatedIdentity.hash is ImportedIdentity.hash.
Paragraph (version A):
Upon receipt of such an obfuscated identity, a peer must lookup the
corresponding PSK by exhaustively trying to compute
ObfuscatedIdentity.obfuscated_identity using ObfuscatedIdentity.nonce
and each of its known imported PSKs.  If N is chosen in a predictable
fashion, e.g., as a timestamp, it may be possible for peers to
precompute these obfuscated identities to ease the burden of trial
decryption.
Paragraph (version B):
If a client or server wish to deprecate a hash function and no longer
use it for TLS 1.3, they remove 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.
Paragraph (version B):
Recall that TLS 1.2 permits computing the TLS PRF with any hash
algorithm and PSK.  Thus, an EPSK may be used with the same KDF (and
underlying HMAC hash algorithm) as TLS 1.3 with importers.  However,
critically, the derived PSK will not be the same since the importer
differentiates the PSK via the identity, target protocol, and target
KDF.  Thus, PSKs imported for TLS 1.3 are distinct from those used in
TLS 1.2, and thereby avoid cross-protocol collisions.  Note that this
does not preclude endpoints from using non-imported PSKs for TLS 1.2.
Indeed, this is necessary for incremental deployment.
Paragraph (version B):
DISCLAIMER: This is a WIP draft and has not yet seen significant
security analysis.
Paragraph (version B):
External PSK identities are typically static by design so that
endpoints may use them to lookup keying material.  However, for some
systems and use cases, this identity may become a persistent tracking
identifier.
Paragraph (version B):
Values in the range 0x0000-0xfeff are assigned via Specification
Required RFC8126.