Change:
5. <del> For clarity, the following table specifies PSK importer labels for varying instances of the TLS handshake. 6. </del> If a client or server wish to deprecate a hash function and no longer <del> 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. </del> <ins> 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. </ins> <del> 7. </del> <ins> 6. </ins> Recall that TLS 1.2 permits computing the TLS PRF with any hash <del> 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 </del> <ins> 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 </ins> does not preclude endpoints from using non-imported PSKs for TLS 1.2. Indeed, this is necessary for incremental deployment. <ins> 7. DISCLAIMER: This is a WIP draft and has not yet seen significant security analysis. </ins> 8. <del> This is a WIP draft and has not yet seen significant security analysis. </del> <ins> 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. </ins> 9. <del> DISCLAIMER: This section contains a sketch of a design for protecting external PSK identities.  It is not meant to be implementable as written. </del> <ins> This specification introduces a new registry for TLS KDF identifiers and defines the following target KDF values: </ins> <del> External PSK identities are typically static by design so that endpoints may use them to lookup keying material.  For some systems and use cases, this identity may become a persistent tracking identifier.  One mitigation to this problem is encryption.  Future drafts may specify a way for encrypting PSK identities using a mechanism similar to that of the Encrypted SNI proposal I-D.ietf-tls- esni.  Another approach is to replace the identity with an unpredictable or "obfuscated" value derived from the corresponding PSK.  One such proposal, derived from a design outlined in I-D.ietf- dnssd-privacy, is as follows.  Let ipskx be the imported PSK with identity ImportedIdentity, and N be a unique nonce of length equal to that of ImportedIdentity.hash.  With these values, construct the following "obfuscated" identity: ObfuscatedIdentity.nonce carries N, ObfuscatedIdentity.obfuscated_identity carries HMAC(ipskx, N), where HMAC is computed with ImportedIdentity.hash, and ObfuscatedIdentity.hash is ImportedIdentity.hash. 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. 10. This document makes no IANA requests. </del> <ins> +-------------+-----+ | Description | Value | +-------------+-----+ | Reserved | 0x0000 | | | | | HKDF_SHA256 | 0x0001 | | | | | HKDF_SHA384 | 0x0002 | +-------------+-----+ 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. </ins>

Discussion:
Also, remove PSK identity encryption sketch. This was underspecified and can always be done in a separate draft if desired. cc NAME
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 KDF (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?
Hmm, my understanding is that we don'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 don'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" (Chris' 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 don'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 doesn'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 don'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. NAME NAME what do you think? [1] URL
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. NAME 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 URL, which I think i the Nh value associated with the HPKE-like identifier.
Correct! I can'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 URL 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.
NAME NAME I made the proposed change in . Please have a look!
Works for me