Question: Setting options indicate a setting that will be applied by the sender. <del> Most CSM Options are useful mainly as initial messages in the connection. </del> <ins> A Capability and Settings message MUST be sent by both endpoints at the start of the connection and MAY be sent at any other time by either endpoint over the lifetime of the connection. </ins> Both capability and settings options are cumulative.  A Capability and Settings message does not invalidate a previously sent capability

NAME added a related comment to (which is closed) From your message I understand that in HTTP/2 the client can send messages immediately without waiting for the server to respond either. To me it feels like we should be doing what has been done in the HTTP/2 case even though there is a risk that some problems occur when the client sends data in way that the server will subsequently not handle well. If that is the case, the client will have to re-send the data, I guess. For the currently defined options I don't see problems.
Michel Veillette points out that a peer that wants to use a new connection has an uncertainty whether a CSM message with capability indications will come or not, so it is hard to decide when to send the first request (either based on default capabilities or waiting for the CSM to come in). One way out of having to do arbitrary waits would be to require the exchange of a CSM message (even an option-less one) after connection setup. The burden is very low, as a minimal implementation would just need to send a constant message of 0x00 0xe1 at setup. This requirement could be stated without giving a sequence, effectively allowing both sides to send the initial CSM in parallel, or it could give the listener the opportunity to not send its CSM until the connection opener has sent theirs, trying to avoid the need to answer right away to a connection setup -- this makes it too easy to scan for ports (OK, we also have a default port, and making scanning harder does not by itself provide any security, but it sure makes life a little harder for the attacker). (To avoid deadlock, the connection opener would not have the opportunity to wait sending the CSM.)
+1 ... especially for Maximum-Message-Size. HTTP/2 has a similar flow for SETTINGS during connection including potentially empty settings: URL URL
No objections. I will create a pull request for review by the WG.


Question: an editorial update.  It contains updated text in areas which were found to be unclear as well as other editorial improvements.  In addition, it removes the use of the term "master" as applied to <del> secrets in favor of the term "main". </del> <ins> secrets in favor of the term "main" or shorter names where no term was neccessary. </ins> 1.3.

While we're renaming these anyway, exportersecret and resumptionsecret are just as descriptive.
exportermainsecret and resumptionmainsecret strike me as not needing an adjective in the middle at all. Perhaps exportersecret and resumptionsecret? For the exporter secret, dropping "main" avoids the acronym collision with the EMS extension, and there are no other secrets associated with exporters, so there's no use in designating this as the main one. For the resumption secret, there is a potential confusion between resumption[main]secret and the derived PSK associated with the ticket (section {#NSTMessage}), but we don't seem to give the latter a name in the first place so I think that's fine. This also gives us nice short KDF labels when we're able to change those: "exporter" and "resumption". (Or perhaps even "export" and "resume" if those don't fit in a hash block.)


Question: no other dNSName entries of the form "*.acme.invalid" are present in the subjectAltName extension. <del> It is RECOMMENDED that the ACME server verify a random subset of the N iterations with an appropriate sized to ensure that an attacker who can provision certs for a default virtual host, but not for arbitrary simultaneous virtual hosts, cannot pass the challenge.  For instance, testing a subset of 5 of N=25 domains ensures that such an attacker has only a one in 25/5 chance of success if they post certs Zn in random succession.  (This probability is enforced by the requirement that each certificate have only one Zi value.) </del> It is RECOMMENDED that the ACME server validation TLS connections from multiple vantage points to reduce the risk of DNS hijacking attacks.

Simplify the TLS SNI challenge by removing the iterations concept, which I believe is not necessary in practice and complicates the protocol needlessly.
Implementing TLS SNI is currently really complicated, yes.
FYI, URL implements protocol according to the contents of this PR - i.e. without iterations.
(so does current Boulder)
I think this will be OK to land once lands. We should consider whether we want to bump the version number in the challenge. Principle would dictate that we should, since this breaks compatibility with what was published in -01. But since I'm not aware of any implementation of "tls-sni-01" as specified in -01 (vs. the off-spec implementation in boulder), I'm inclined to just leave it.
FWIW on the client side of things, xenolf/lego did not implement the iterations for the tls-sni-01 challenge.
URL implements iterations but takes the absence of an "n" parameter to be equivalent to an "n" parameter of 1, which is compatible.
Great, I'm taking this as sufficient evidence that a version bump is not needed :)


Question: The recipient of an update processes it with the following steps: <del> Compute the updated path secrets * Identify a node in the direct path for which the local member is in the subtree of the non- updated child * Identify a node in the resolution of the copath node for which this node has a private key * Decrypt the path secret for the parent of the copath node using the private key from the resolution node * Derive path secrets for ancestors of that node using the algorithm described above * The recipient SHOULD verify that the received public keys agree with the public keys derived from the new node_secret values Merge the updated path secrets into the tree * Replace the public keys for nodes on the direct path with the received public keys * For nodes where an updated path secret was computed in step 1, compute the corresponding node secret and node key pair and replace the values stored at the node with the computed values. </del> <ins> Compute the updated path secrets. Identify a node in the direct path for which the local member is in the subtree of the non-updated child. Identify a node in the resolution of the copath node for which this node has a private key. Decrypt the path secret for the parent of the copath node using the private key from the resolution node. Derive path secrets for ancestors of that node using the algorithm described above. The recipient SHOULD verify that the received public keys agree with the public keys derived from the new node_secret values. Merge the updated path secrets into the tree. Replace the public keys for nodes on the direct path with the received public keys. For nodes where an updated path secret was computed in step 1, compute the corresponding node secret and node key pair and replace the values stored at the node with the computed values. </ins> For example, in order to communicate the example update described in the previous section, the sender would transmit the following values: <del> In this table, the value pk(X) represents the public key corresponding derived from the node secret X.  The value E(K, S) represents the public-key encryption of the path secret S to the public key K. </del> <ins> In this table, the value pk(X) represents the public key derived from the node secret X.  The value E(K, S) represents the public-key encryption of the path secret S to the public key K. </ins> 6.

Here's the Weekly Digest for : - - Last week 2 issues were created. Of these, 0 issues have been closed and 2 issues are still open. :greenheart: , by :greenheart: , by - - Last week, 8 pull requests were created, updated or merged. Last week, 1 pull request was opened. :greenheart: , by Last week, 5 pull requests were updated. :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by :yellowheart: , by Last week, 2 pull requests were merged. :purpleheart: , by :purpleheart: , by - - Last week there were 2 commits. :hammerandwrench: by :hammerandwrench: by - - Last week there was 1 contributor. :bustinsilhouette: - - Last week there was 1 stargazer. :star: You are the star! :star2: - - Last week there were no releases. - - That's all for last week, please :eyes: Watch and :star: Star the repository to receive next weekly updates. :smiley: You can also .


Question: This API changes the local media state; among other things, it sets up local resources for sending and encoding media. <del> If setRemoteDescription was previously called with an offer, and setLocalDescription is called with an answer (provisional or final), </del> <ins> If setLocalDescription was previously called with an offer, and setRemoteDescription is called with an answer (provisional or final), </ins> and the media directions are compatible, and media are available to send, this will result in the starting of media transmission.

I was reading this draft and noticed a couple of minor wording issues that made the text not as clear as it could be. I don't believe the changes are controversial, or change the intention of the draft.
These changes look good - I agree the rewrite of the offer/answer paragraph is a nice improvement.
Looks fine to me


Question: Even when redirected, the User Equipment securely authenticates with API servers. <del> 5.4. </del> <ins> 5.5. </ins> The ICMP messaging informs the User Equipment that it is being held captive.  There is no requirement that the User Equipment do

We want to make TLS a requirement, not a suggestion, so I've chagned the wording around TLS to reflect this. I also added a section to the security section discussing the motivation behind the requirement.
Can you forward to the list please?


Question: on its configuration. The registration message is a list of links to registration resources <del> of the endpoints that belong to that group.  The endpoints MAY be hosted by a different RD than the the group hosting RD.  In that case the endpoint link points to the registration resource on the other RD. </del> <ins> of the endpoints that belong to that group.  The registration resources MAY be located on different hosts than the group hosting RD.  In that case the endpoint link points to the registration resource on the other RD.  The commissioning tool SHOULD NOT attempt to enter a foreign registration in a group unless it found it in the group RD's lookup results, or has other reasons to assume that the foreign registration will be accepted. </ins> The commissioning tool SHOULD not send any target attributes with the links to the registration resources, and the resource directory

This contains what I think of the easy fixes to the requirements of replicated RDs. See URL for more discussion, please comment on whether you think those changes are acceptable.
The minimum for interoperability IMO is that client's don't always pick the first choice -- because if they do, no fault tolerance is possible. Do you think that that even this is too much specification of behavior, or did I write more in the PR than what would be needed to satisfy that minimum requirement?
chrysn schreef op 2018-02-01 17:03: Is that so? The first choice of one client is not necessarily the first choice of another when we are confronted with RDs which have contact problems. Several protocols have handled this problem: like dhcp for example. Why not copy that behavior?
I think we're talking about different "first"s here. I'm not concerned with what happens when multiple servers answer the multicast CoAP request. (Led to an interesting chat with PIM people but is not a matter that should concern the RD). What I do think we should give guidance is what happens if the RDAO announces multiple addresses (something explicitly allowed in the current draft), or the URI discovery response contains more than one rt="URL" link Both are within what I think we describe as acceptable server behavior. If clients are unaware and just always pick the first line (because it looks like a zero-or-one situation to the implementers), interoperability issues will arise when two are announced an the first one fails.
Ok, got it, see below chrysn schreef op 2018-02-02 12:11: Yeah, that's a nuisance. Someone seems to know what they want that for, annd probably have some intelligent algorithm to break ties.......... One might say that client MAY choose their RD randomly. I assume that is a multicast response? Then the first response is probably the closest and the best choice. And when one MC response contains multiple RD links, We are not responsible, and something clever is being thought out somewhere, we hope. I think DHCP specifies clients to wait so many seconds before choosing a server. When the first one fails, the client will try the second one, und so weiter ... What am I missing still?
for interoperability, the client behavior when multiple URIs are discovered, or the RD does not answer, need not be specified. The text starts to look more and more like Bonjour


Question: for encrypted DNS protocols when the name of an encrypted resolver is known.  This mechanism is designed to be limited to cases where unencrypted resolvers and their designated resolvers are operated by <del> the same entity. </del> <ins> the same entity or cooperating entities. </ins> 1.

changed equivalence instances for designated and added the possibility of multiple entities so long as they are cooperating This is to address issue
I am not sure we need to introduce "Equivalence" nor to develop who is operating the resolvers - especially as many entities may be involved in the operation of a resolver. I am not sure we need to introduce Equivalence. If so I would propose the following text: OLD: "Equivalence" in this context means that the resolvers are operated by the same entity; for example, the resolvers are accessible on the same IP address, or there is a certificate that claims ownership over both resolvers. NEW: "Equivalence" in this context means that Encrypted and Unencrypted resolvers are either accessible on the same IP address, or there is a certificate that claims ownership over both resolvers. If Equivalence is not introduced - which I prefer -I would propose the following text: NEW: In this context the discovery process ensures that Encrypted and Unencrypted resolvers are either accessible on the same IP address, or there is a certificate that claims ownership over both resolvers.
I agree that we do not need to introduce "equivalence" in this document. It is a remnant of the DEER draft DDR is based on. Per WG discussion, we want to use the term "designation" to describe the relationship between the unencrypted resolver and the encrypted resolver to which the client is transferring. I'm editing accordingly. I have also added references to the possibility of multiple "entities" as that is definitely possible. (PR coming later tonight)
good.


Question: can be mounted using spoofed source addresses.  In determining this limit, servers only count the size of successfully processed packets. <del> Clients MUST ensure that UDP datagrams containing Initial packets are sized to at least 1200 bytes, adding padding to packets in the datagram as necessary.  Once a client has received an acknowledgment for a Handshake packet it MAY send smaller datagrams.  Sending padded datagrams ensures that the server is not overly constrained by the amplification restriction. </del> <ins> Clients MUST ensure that UDP datagrams containing only Initial packets are sized to at least 1200 bytes, adding padding to packets in the datagram as necessary.  Sending padded datagrams ensures that the server is not overly constrained by the amplification restriction. </ins> Packet loss, in particular loss of a Handshake packet from the server, can cause a situation in which the server cannot send when

Builds on .
Initial packets need to be in 1200 byte datagrams for DoS amplification reasons. We have an exception for the case where an ACK for a Handshake packet has been received from the peer. In that case, we remove the requirement to pad. That condition is extraordinarily obscure, especially if we are suggesting that endpoints not send any more Initial packets once they have Handshake keys. Removing this text is the right answer.
+1 to the proposed resolution.


Question: 5.1. <del> Clients encapsulate a request "request" with an HPKE public key "pkR", whose Key Identifier is "keyID" as follows: </del> <ins> Clients encapsulate a request "request" using values from a key configuration: the key identifier from the configuration, "keyID", the public key from the configuration, "pkR", and a selected combination of KDF, identified by "kdfID", and AEAD, identified by "aeadID". The client then constructs an encapsulated request, "enc_request", as follows: </ins> Compute an HPKE context using "pkR", yielding "context" and encapsulation key "enc". <del> Encrypt (seal) "request" with "keyID" as associated data using </del> <ins> Construct associated data, "aad", by concatenating the values of "keyID", "kdfID", and "aeadID", as 8-, 16- and 16-bit integers respectively, each in network byte order. Encrypt (seal) "request" with "aad" as associated data using </ins> "context", yielding ciphertext "ct". <del> Concatenate the length of "keyID" as a variable-length integer, "keyID", "enc", and "ct", yielding an Encapsulated Request "enc_request".  Note that "enc" is of fixed-length, so there is no ambiguity in parsing "enc" and "ct". </del> <ins> Concatenate the three values of "aad", "enc", and "ct", yielding an Encapsulated Request "enc_request". Note that "enc" is of fixed-length, so there is no ambiguity in parsing this structure. </ins> In pseudocode, this procedure is as follows: Servers decrypt an Encapsulated Request by reversing this process. Given an Encapsulated Request "enc_request", a server: <del> Parses "enc_request" into "keyID", "enc", and "ct" (indicated using the function "parse()" in pseudocode).  The server is then able to find the HPKE private key, "skR", corresponding to "keyID".  If no such key exists, the server returns an error; see errors. </del> <ins> Parses "enc_request" into "keyID", "kdfID", "aeadID", "enc", and "ct" (indicated using the function "parse()" in pseudocode).  The server is then able to find the HPKE private key, "skR", corresponding to "keyID". a.  If "keyID" does not identify a key, the server returns an error. b.  If "kdfID" and "aeadID" identify a combination of KDF and AEAD that the server is unwilling to use with "skR", the server returns an error. </ins> Compute an HPKE context using "skR" and the encapsulated key "enc", yielding "context". <del> Construct additional associated data, "aad", as the Key Identifier "keyID" from "enc_request". </del> <ins> Construct additional associated data, "aad", from "keyID", "kdfID", and "aeadID" or as the first five bytes of "enc_request". </ins> Decrypt "ct" using "aad" as associated data, yielding "request" or an error on failure.  If decryption fails, the server returns an

Switches to an 8-bit key identifier here as well. This format now doesn't need varints. Yay. Implemented this in my ohttp library and it's fine.
Splitting this from . It seems likely that a single KEM key will support multiple KDF or AEAD options (NSS will soon support 3 of the former, and 2 of the latter, maybe 3 of each). Having a configuration that includes a single set of (KEM, key, and key identifier) with a list of KDF+AEAD pairs, akin to ECH, would make it easier to support that sort of deployment. Without that, key identifiers need to carry information about the KDF and AEAD. To support this, the format needs to be adjusted to carry the KDF and AEAD identifier. In doing so, we probably want to encode the choice of KDF and AEAD in the key schedule or AAD accordingly.
Should the key ID length be explicitly authenticated, e.g., by including it in the AAD, or should the AEAD implicitly authenticate things? Unclear!
Should we even bother with an AAD at all? The best reason is that the keyID determines which key the server uses, which is information that factors into decisions. (A related question might be why doesn't HPKE take variables as input so that things like key identifiers can be integrated into the key schedule.)
My take: yes. I need to think through the implications of no additional authentication at all, and in the mean time, I'd be more comfortable with simply authenticating everything possible. I think it was discussed, but it makes the interface a mess. And since applications can accomplish the same thing by shoving what they want authenticated into the AAD, it was voted down.
Yeah, you and I both know that putting stuff in the AAD isn't a real substitute for having it in the key schedule. I completely understand how this would mess with the purity of the design, but TLS managed by wrapping its labels better (which also addresses a known problem with HKDF not being injective).
Fixed by virtue of making the key ID fixed length in .


Question: Closing a single QUIC stream, presented to the application as a Connection, does not imply closing the underlying QUIC connection itself.  Rather, the implementation may choose to close the QUIC <del> connection once all streams have been closed (possibly after some </del> <ins> connection once all streams have been closed (often after some </ins> timeout), or after an individual stream Connection sends an Abort. <del> Messages over a direct QUIC stream should be represented similarly to the TCP stream (one Message per direction, see tcp), unless a framing mapping is used on top of QUIC. </del> <ins> Connectedness: Multiplexing Connected Data Unit: Stream Connection objects represent a single QUIC stream on a QUIC connection. </ins> 9.7.

Starting to address This is an early review, to check if we like the structure. I'd also like help filling out the SCTP section!
I can also help with SCTP, which I would do in the same style that I suggest above (for TCP, in my example of "Abort") - also later.
We've updated Implementation mapping details for most protocols with , but we didn't tackle SCTP yet.
I'm fine with this being assigned to me. However, it's more than just writing the SCTP text. Here's the relevant part of what I wrote in PR : I don't suggest to delete much of the text that's there but definitely amend it with the RFC reference at least for what's covered in RFC 8303. There's a very direct line from this type of text in RFC 8303 to the original specs, so I do believe that should be helpful. That's (obviously) post-Montreal though!
NAME please send a PR along these lines.
LGTM modulo mwelzl changes.I think this is a good step forward. This said, I think we should describe things focusing on the transport's API call to be made (in line with the spec - that's why we have RFCs 8303 and 8304) rather than protocol internals. E.g., rather than saying that Abort on a TCP connection transmits a RST, I think we should simply say that Abort calls ABORT.TCP [RFC 8303, Section 4.1]. I can take care of these things, later. I'd still like to focus more on the API doc at this time.


Question: number of acknowledgments allows connection throughput to scale much further. <del> Unfortunately, there are undesirable consequences to simply reducing the acknowledgement frequency, especially to an arbitrary fixed value, as follows: A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, see QUIC-RECOVERY. Consequently, how often a receiver sends acknowledgments dictates how long it takes for losses to be detected at the sender. Starting a connection up quickly without inducing excess queue is important for latency reduction, for both short and long flows. The sender often needs more frequent acknowledgments during this phase. Congestion controllers that are purely window based and strictly adherent to packet conservation, such as the one defined in QUIC- RECOVERY, rely on receipt of acknowledgments to move the congestion window forward and release additional data.  Such controllers suffer performance penalties when acknowledgements are not sent frequently enough.  On the other hand, for long-running flows, congestion controllers that are not window-based, such as BBR, can perform well with very few acknowledgements per RTT. New sender startup mechanisms will need a way for the sender to increase the frequency of acknowledgements when fine-grained feedback is required. </del> <ins> As discussed in implementation, there are undesirable consequences to congestion control and loss recovery if a receiver uniltaerally reduces the acknowledgment frequency.  Consequently, a sender needs the ability to express its constraints on the acknowledgement frequency to maximize congestion controller performance. </ins> QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every

I think the motivations section as-is is too long. It spends a lot of time talking about what are effectively the tradeoffs. IMO the motivations section should specify why it's useful to have the sender control the receiver's ACK frequency, and then we can have a separate section for the tradeoffs. This takes a stab at that section, lifting things from motivations and adding some new text specifically addressing the nascent stages of a connection. I also made some editorial changes to the existing text. I am happy to add any additional considerations we think might need to be called out. This attempts to
Thanks for the PR, NAME ! I like the new text you propose (I've proposed some changes), but I think you might be assuming that ACK_FREQUENCY is only used for delaying acks further. An important point that bears bringing out in the motivation is that a sender might want more frequent acks as well, for example during startup. That's worth capturing in the modified motivation section.
NAME this PR is almost done, any chance you can do another round of updates and we can get it in?
NAME sorry, I'll do some updates today.
NAME NAME I've updated the PR, I'll watch and iterate on any remaining feedback quickly this time.
thanks NAME Something about vim and the macbook pro keyboard apparently makes me incapable of spelling things properly. I want my desk keyboard back
As discussed on in the base draft, we have some confidence in a particular heuristic (default tolerance of 2 for the first 100 packets, followed by a tolerance of 10) which we know to work fairly well in multiple deployments serving "typical" Internet resources to typical users. Do we want to make that recommendation explicit, or otherwise give guidance in this extension?
I think it's a good idea to describe the values for which we have experience, while encouraging experimentation. We don't need to recommend the strategy, we just need to document it as an example strategy.
I think a section on considerations and maybe past experience would be very helpful. I think it's going to be a bit of a challenge to write, but I'm happy to take a stab if no one else wants to.
What I'd want to see is just a simple explanation of what a sender could do... I would not describe results from experience, since those are anecdotal and are going to change over time. This could be a fairly short section.


Question: number of acknowledgments allows connection throughput to scale much further. <del> Unfortunately, there are undesirable consequences to simply reducing the acknowledgement frequency, especially to an arbitrary fixed value, as follows: A sender relies on receipt of acknowledgements to determine the amount of data in flight and to detect losses, see QUIC-RECOVERY. Consequently, how often a receiver sends acknowledgments dictates how long it takes for losses to be detected at the sender. Starting a connection up quickly without inducing excess queue is important for latency reduction, for both short and long flows. The sender often needs more frequent acknowledgments during this phase. Congestion controllers that are purely window based and strictly adherent to packet conservation, such as the one defined in QUIC- RECOVERY, rely on receipt of acknowledgments to move the congestion window forward and release additional data.  Such controllers suffer performance penalties when acknowledgements are not sent frequently enough.  On the other hand, for long-running flows, congestion controllers that are not window-based, such as BBR, can perform well with very few acknowledgements per RTT. New sender startup mechanisms will need a way for the sender to increase the frequency of acknowledgements when fine-grained feedback is required. </del> <ins> As discussed in implementation, there are undesirable consequences to congestion control and loss recovery if a receiver uniltaerally reduces the acknowledgment frequency.  Consequently, a sender needs the ability to express its constraints on the acknowledgement frequency to maximize congestion controller performance. </ins> QUIC-TRANSPORT currently specifies a simple delayed acknowledgement mechanism that a receiver can use: send an acknowledgement for every

NAME NAME I can take a stab at writing something and we can go from there.
Thanks, NAME !
I do think the pitfalls of e.g. should be conveyed in such "cautionary" text as well. I will submit a PR this week time permitting between interop.
Thanks, NAME


Question: "encrypted_extensions", "end_of_early_data", "key_update", and "handshake_hash" values. <del> This document also uses a registry originally created in RFC4366. IANA has updated it to reference this document.  The registry and its allocation policy is listed below: </del> <ins> This document also uses the TLS ExtensionType Registry originally created in RFC4366.  IANA has updated it to reference this document. The registry and its allocation policy is listed below: </ins> IANA [SHALL update/has updated] this registry to include the "key_share", "pre_shared_key", "psk_key_exchange_modes",

Need to be explicit say that it's the ExtensionType registry from RFC 4366.
I literally was making the same change in my editor when the notification came in! (Should it be the "TLS Extensions ExtensionType registry"?)


Question: 12.2. A group member creating a commit and a group member processing a <del> commit MUST verify that the list of committed proposals is valid </del> <ins> Commit MUST verify that the list of committed proposals is valid </ins> using one of the following procedures, depending on whether the <del> commit is external or not. </del> <ins> commit is external or not.  If the list of proposals is invalid, then the Commit message MUST be rejected as invalid. </ins> For a regular, i.e. not external, commit the list is invalid if any of the following occurs:

URL This definition of a handshake message is being defined in terms of a Proposal or Commit object, neither of which are defined in this session. Furthermore, PublicMessage or PrivateMessage aren’t defined either as this point in the text. To improve clarity, consider defining these key terms. The use of "respectively" in the text is suggesting that PrivateMessages don’t have integrity protection which is not accurate. (see the Cryptographic Dependencies section of the HPKE specification for more information). Is this Section 4 of RFC9180?  If so, why not say that? What would be the circumstance where the application_id extension would be treated with equal standing as something from the AS?  Why can’t this be a "MUST"? Unsaid is what to do if the proposal list is not valid.  Please clarify. Is this normative behavior required, or could it be left up to application?  The mixing of updates/removes on the same node and the SHOULD guidance already means that this "recovery from an invalid node" may not be consistent across clients/DS-es. Same observation on recovering from ReInit with any other proposals. Is there any additional retry mechanism?  Let’s say the sender of the proposal doesn’t see it reflect in the epoch after it sent proposal.  And then not in the next epoch.  Does it try resending indefinitely? This setup seems a little simplistic. If the application data is encrypted to begin with, how does the adversary know the question being posed by Alice?


Question: one ep (endpoint with a unique name) <del> one con (a string describing the scheme://authority part) </del> <ins> one con (a string typically describing the scheme://authority part) </ins> one lt (lifetime),

This allows for gateway devices that register their mapped legacy devices individually. Closes: URL The delta is smaller than I expected because at some places, paths were already allowed (eg. in the IANA table for "con"). One place where I'm unsure if we should change it because I don't know what it actually means is the "scheme, IP, port" annotation in fig-hierarchy -- what does it mean there?
what is a path no scheme form? An example might help here.
path-noscheme form is one of the possible ABNF forms for a relative reference from ; it basically means "relative references that does not even start with a slash". I'm conflicted about having an example in the draft (our examples already feel like a test suite), but I'll give one here and we can still consider moving it in: ~
Merging this with a clarification for the ABNF item, so we have a single version to talk about later today.
I'm aware this is a discussion we've already had, but back then we dropped it for its complexity and because we had no use cases. Matthias has brought up use cases for allowing a path in the con as part of the -13 reviews. He argues that a gateway bridging into a non-CoAP world would want to register its proxees (is that a word?) individually, and if it doesn't use name-based virtual hosting (which is kind of rare in CoAP and needs wildcard DNS records), could go for path-based hosting. As I see it, this would be a trivial addition from the RD point of view ("just allow it"). The onus is on the endpoint / gateway to do it right, ie. to never use path-absolute URI references unless they mean it. What does make this a bit more complicated is that none of the content formats we currently describe allows using that meaningfully -- but we are not limiting the RD to those content formats, and they may (and hopefully will) still change while we're finishing RD. On the editing track, I would keep those cases out of the examples (I'm game for building a test suite, but the examples shouldn't be that). Then, the editing becomes a matter of replacing "specified URI MUST NOT have a path component" with "typically does not have a path component", adding the one or the other "typically", and being done with it.


Question: one ep (endpoint with a unique name) <del> one con (a string describing the scheme://authority part) </del> <ins> one con (a string typically describing the scheme://authority part) </ins> one lt (lifetime),

(This would also make URL obsolete, as those components would be allowed). NAME (and possibly NAME I'd assume you won't be too happy with (based on previous discussions of that topic), but do you see Matthias' point, or could point out concrete issues you see from allowing this?
I would prefer that not be made obsolete on this. You should be able to have a URI w/ a path and a relative URI which are then combined. If we need to combine things like query parameters then it is going to get really messy really fast because there are not good rules about that. I don't have any problems w/ allowing for the con to have a path and resolving with it. I just think that we need to establish what the rules are in the RD document rather than using the horrible link format rules.
There are very good rules about that query parts and fragments in the Base URI: Anything that is not an empty string or starts with a "#" removes the fragment identifier and the query parameters. The Base URI's fragment identifier is never kept. (Derived from RFC3986 Section 5.2). I'll try to write text on this issue on the weekend (NAME a "no we can't have that because" would be more appreciated today than later), let's talk about again when we have that. Dear list RD allows the "con" parameter to provide a base URI for relative resource URIs, when the registration is done from a different source address then the registered endpoint itself. "con" is restricted to the scheme and authority part of a URI, that is, no path segments are allowed. This came from the assumption that all CoRE devices will naturally correlate with socket-address endpoints. However, a registered device(=endpoint, "ep") might not be a natural endpoint. When using gateways or device proxies, the base URI will have path segments and multiple logically different endpoints will share the same socket-address (e.g., URL, URL, URL). This makes it expensive to move such logical endpoints, as updating "con" will not help. All links have to be removed, changed to the new prefix, and registered anew. This is a problem for some applications (including a bigger alliance using CoAP), in particular because the patch mechanism is still to be defined - yet rewriting URI prefixes still will not be really efficient even when having patch registration updates.


Question: one ep (endpoint with a unique name) <del> one con (a string describing the scheme://authority part) </del> <ins> one con (a string typically describing the scheme://authority part) </ins> one lt (lifetime),

I thus propose to generalize "con" to be any base URI that will be applied to all relative links an endpoint registered. If there is a conflict with a deployed mechanism, we could look into adopting "anchor" and let RD use it similarly to "con", but allowing full base URIs (including paths). Or we align with RFC 8288 altogether and replace "con" with "anchor": URL Ciao, Matthias


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

NAME let's discuss that on . I'd like to merge this PR first then decide on a plan for before submitting the next revision to the datatracker
Splitting {ADDRESSREQUESTROUTEADVERTISEMENT} into ...V4 and ..._V6 would result in smaller capsules that have fewer error conditions. It would also keep IPv4 and IPv6 logic distinct.
I don't think the size of these capsules matters given their rarity. I can see the error condition argument but it's pretty minor and would come at the cost of making the specification longer. I don't feel too strongly here, but I think I have a slight preference for keeping things as they are.
I agree with David that size is problem not a big concern. I think having one set of capsule is less complex.
I also have a preference for keeping the capsules as they are with versions included; it also allows the route advertisement capsule to include routes for both v4 and v6 in one capsule, which I think is very important. I wouldn't want to lose that feature.
I similarly have a preference for keeping v4 and v6 in one capsule and agree size is not a big concern.
I just chatted with NAME to see what error conditions he was thinking of. Upon discussion (v6 route advertised when only v4 address is available), we concluded that this is not an error case, it's just a route that's not yet usable. We've concluded that this is something that we're comfortable leaving as-is.
Implementing this on the client I was wondering if there should be a way for the client to ask for the server for an address without specifying what address it wants. This could allow a VPN client to mention that it wants an IPv6 address or not. If we think this could be useful, we could encode it as or .
I believe asking for the Any address is what we discussed previously, so +1
You mean ADDRESS_REQUEST(IPv4-0.0.0.0/32) don't you. I think the format of the request works fine. But we do need to before we implement this into the specification.
Yes — if we have this, one option is to always have an ADDRESS_REQUEST expected from clients, and then there doesn't need to be signaling. Or we do the simple solution to 54 to say "I expect to send N capsules with my request".


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

You're right this could be a potential solution to . Let's discuss them together tomorrow
Regarding IPv6, I think a standard request that would make sense is asking for any /64. I guess that works fine with this idea too?
Oh that's interesting, if the IP Address is or , the prefix length is a hint for the requested length. I like that.
IETF 114: Add an editorial sentence to "remember, what you ask for may not be what you get, especially with regards to address families". A request should be paired with a response, multiple requests can just say "you have the same ones you had before". Clarify that it's cumulative. Also solves unassign/removal of addresses.
So there appear to exist some downside with the timing of the interactions when one want to use Address-Request capsule. So the basic problem is simply that the proxy will assign an address prior to the Address-Request capsule has been received, thus preventing the proxy from processing the request in the right context. So lets assume that the client has already created one connect-IP request with a limited scope and been assigned IP-A. Then it want to make an additional request for another limited scope proxying and would like to get the same address assigned. Due to the separation between the HTTP request for the Connect-IP and the capsule Address-Request a server can actually process the whole HTTP request prior to receiving the Address-Request. Resulting potentially in that another IP address assignment (IP-B) be provided to the client, despite it asking for IP-A to be assigned also to the request. So does the HTTP request needs an indicator parameter to tell the proxy to wait for one or more "request" capsules from the client before processing the request?
Out of curiosity, in what scenario would the client "like to get the same address assigned"? It makes sense for the proxy to decide to reuse addresses to save its address pool when the scoping allows it, but why would the client care?
I could imagine this happening if the client was trying to resume some previous session that it lost due to an outage? Seems to be niche, but it's certainly possible.
So the most obvious use case for this is to request iproto= CMP in combination with for example UDP.


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

Then getting ICMP for another IP address then the one you already have UDP for is mostly useless if you intended to use the ICMP messages for hints when things fails for you UDP based protocol. I would note that for an endpoint liking to do P2P NAT traversal stuff getting an IP address rather than using Connect-UDP does make sense as it ensure the client has control. It enables the IP address for its UDP traffic to be Endpoint-Independent Mapping (RFC4787). This might be niche usages but I would like to avoid creating artificial barriers that makes things impossible or at least hard to realise.
Thanks, this makes sense. Should we suggest that clients bundle the ADDRESS_REQUEST in the same packet as the HTTP headers and suggest that servers check for those before responding?
I am still worried that this creates issues as your request may not fit in a single packet to begin with. My solution would be to actually move the address request part into the HTTP request itself as header field. That would ensure an atomic operation and no risk for errors.
Magnus, is your proposal to require, or to allow as an option, for the address request to be moved into the HTTP request? Why not bundle the capsules over a reliable delivery mechanism instead?
I first of all want to ensure that you can do a request that ensures that for those cases when it is necessary to interpret the Connect-IP request in the context of desired IP address it can done. Without uncertainties or requiring to have wait time to see if there are capsules incoming. So I think primarily allow as an option. I think a question back to your usages, do you have cases where one would need additional capsules to correctly interpret the option. Should we look for an other solution than the one I proposed to better cover the necessary functionality?
I want to be able to continue to do ADDRESS_ASSIGN capsules during the lifetime of the connection to support e.g., IPv6 Privacy extensions but without having to delegate the entire subnet. So I don't want to move to header-only.
I think NAME is describing something similar to the / capsules that we had in the original Google . The only difference is that we would add an HTTP header to say "start off in atomic mode and wait for atomic end before sending addresses and such". While I think this does sound useful, does it need to be in the core spec or could it be an extension?


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

Is there any reason to not bring back the capsules?
The only reason I can think of is to keep the core spec as short and simple as possible. But if we think this is an important feature then I'm not opposed to bringing back .
I agree with the sentiment of keeping the core spec short and simple, but the trade-off is also knowing what the minimum viable featureset we can always rely on is. If we conclude that capsules are in that set, that IMHO weighs towards including them. Given that both Magnus and I have now presented use-cases for atomicity, I think this finally swings towards including?
I agree with that
So why I used atomic here, was due to the split between HTTP and Capsules. So I don't see this issue currently motivates the need for ATOMIC capsules. I really would prefer that the necessary parameters for the CONNECT-IP request are in the HTTP request, either in the URI or in an HTTP field. To be clear, I understand the need for the capsules as they are useful for doing things after the initial request, but creating this binding between the HTTP request and the capsules are creating its sets of complexities. Likely bigger than duplicating the carrying of the necessary information results in, especially when they may be use cases related.
I agree I with Magnus and think we should specify a ay to add the address request to the http request. If there is a timing dependency it's better to put all needed information into the same request than specifying extra and complex logic to achieve the same in hindsight. That doesn't mean that we don't need the address request capsule (for later use in the connection). I think we need both.
I dislike having two ways of conveying the same thing. How about a simple HTTP header that tells the receiver that there are 4 capsules coming right after the HTTP headers?
I'd prefer to avoid "atomic capsule" starts and ends. If we need a way to guarantee inclusion of the local address in the first request, having it be in the HTTP request makes sense, either as another URI parameter, a header to say what address you want, or a header to say you will have capsules that need to be parsed before responding. That latter option is flexible, certainly, but could be over-engineered. Another option is to tightly scope a header to the use case we think is relevant.


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

If the use case is "please use the same address as this other request stream I already have for connect-ip or connect-UDP", we could just have a header to say for any connect- request that it is entangled with another and should share some properties. I could imagine this even without CONNECT-IP. Today with private relay, we have to ask the proxies to prefer to use the same local IP for everything in a connection from the client, but letting the client choose what gets grouped might be even nicer. This option also lets you issue multiple requests, say they should share, without needing to know exactly which IP any of them will get assigned first.
Unfortunately requests and headers are end-to-end but streams are hop-by-hop so there is no easy HTTP way to have a request refer to another request. I'd be supportive of adding the header but I'd push back on adding a header that duplicates a capsule. This is starting to feel like something best-served by an extension
You could solve the correlation by having a "group" ID that you attach to all related requests. No need to refer by stream ID.
What is the scope of a group ID? Connection? If so it's the same as stream IDs.
I think this should be some extension, but it could be a UUID too, doesn't need to be connection specific.
Ah, thanks. Yeah UUID would work. Back to the issue at hand, I propose this feature request get moved to an extension.
All of these alternatives strike me as much more complex that the semantics of . I'd rather we have a single mechanism even if it's slightly more powerful and restrain it's use than try to invent new ways to solve each problem that arises.
Atomic doesn't help coordinate between requests on different streams, etc, so it's not really solving the full problem here. Either way, I think this is something to defer to an extension.
Headers don't solve that problem either, so I'm not sure that argument really makes sense in this context. Cross stream coordination seems out of scope to me.
So you are taking this into directions I did not intended. I am just asking for how to ensure that the server does not answers the client's request prior to having received any capsules if they are coming.


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

And the real issue is that the server can't know unless the client either includes the corresponding data in the HTTP request or includes an indication that there will be capsules that are relevant to the requests. So, my main worry is if waiting for capsule to answer will actually work if there are an HTTP 1.x intermediary connection on the path between the client and the server. I guess its is sending the capsule after the request and hope it makes it. Because to my understanding in HTTP datagram the peer does not expect any data to arrive so it must be upgraded. Thus, one can end up in cases where the capsule protocol does not make it, where the HTTP request does arrive.
While we might want to have a more generic extension to relate information to multiple requests, I think the problem Magnus describes needs a solution now. The problem is that there is a dependency between replying/react to a connect request and potentially information send in capsules. The best solution is to send this information together with the connection request instead. I don't see any concern to have a http request or URI parameter and the capsule. What's the problem about that?
Magnus, what is "the client's request" here? Is it the extended-connect itself, or a response to a capsule? If it's the former, the server can't know what capsules, if any, are coming at this time, as we haven't yet established we are using the capsule protocol. If it's the latter, capsules trivially solve this, as you cannot process any of the requests until the capsule is received. Mirja, I'd like to avoid having 2 ways to do things, especially since putting it on the HTTP request is a less-generic mechanism and cannot be reused during the connection, whereas capsules can. If we believe this feature is important, I'd like us to solve it generically, rather than special-casing one use case we are aware of right now.
So the client's request is the HTTP request that is only complete in semantics when combined with the request-address capsule.
Sorry Magnus, I'm not sure I understand what you're trying to say. I don't think we can enforce a semantic that a higher-level HTTP request is only complete after some bytes on the then-negotiated protocol have been exchanged.


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

But this is really the issue, there is currently no way for a client to ask the server to only provide a targeted connect-IP forwarding if the IP address it can provide is the one the client asks for in a consistent way. My interpretation of the specification is that either; 1) the server will never take the request-addr into account initially for the request, and interpret the request-addr after it has created a Connect-IP forwarding 2) the server will sometime take the request-addr into account by have a short delay awaiting for the request-addr capsule, which may or may not make it in time for the implementation specific timer. This non-consistency or failure to address a use case that I think several was interested in resolving is a real problem. A problem I think we will have to take with us to the meeting.
This ultimately stems from us not having an explicit capsule/message to indicate that forwarding should actually begin. Right now it's implicit as soon as the capsule is assembled with the IP addressing information. This is leading to your proposal to stick more things onto the initial request, whereas I believe the correct solution is to add more capabilities to the capsule protocol to express these scenarios.
I will consider what you are saying. However, I will note that we might have different goals. I do have a need for identifiable streams that can be referred to in extension signalling. Using capsules does not achieve that with the current design as the stream identifier comes from the HTTP request, not the subsequent capsule signalling.
I hope so, constructive discussion relies on all of us considering what the others are saying Given that we're all trying to solve slightly different problems here, I see two outcomes: we have one simple generic solution that happens to work for everyone we punt this to more specific extensions since these problems are not generic
So I think the issue here is what we consider core functionality. My observation here is that Alex is promoting functionality that will make it easy to make quite rich things for the network tunnelling use case that you are promoting. While I am bringing up something that to me appear core for the single endpoint tunnelling. So I think we actually need to understand the issues as well as what usage and how usable this is in common and how to handle where the different use cases actually benefits from having the functionality in different places.


Question: receiving the response to its IP proxying request, noting however that those may not be processed by the proxy if it responds to the request with a failure, or if the datagrams are received by the proxy <del> before the request. </del> <ins> before the request.  Since receiving addresses and routes is required in order to know that a packet can be sent through the tunnel, such optimistic packets might be dropped by the proxy if it chooses to provide different addressing or routing information than what the client assumed. </ins> When a CONNECT-IP endpoint receives an HTTP Datagram containing an IP packet, it will parse the packet's IP header, perform any local

I'll reiterate my suggestion from the meeting: it would be better to have IP-version-specific capsule types for each capsule. It saves a byte and also avoids problems with version mismatches.Thanks! I left 2 minor editorial questions, but feel free to merge as-is.


Question: that it chooses. A server MUST discard an Initial packet that is carried in a UDP <del> datagram with a payload that is less than the smallest allowed maximum packet size of 1200 bytes.  A server MAY also immediately </del> <ins> datagram with a payload that is smaller than the smallest allowed maximum datagram size of 1200 bytes.  A server MAY also immediately </ins> close the connection by sending a CONNECTION_CLOSE frame with an error code of PROTOCOL_VIOLATION; see immediate-close-hs.

Addresses . NAME points out in that we use in the transport draft and in the recovery draft. In reading carefully, I realized that in the transport draft was actually historical, and is the more appropriate term. This is an entirely editorial PR, and it's largely simple changes, despite the fact that it looks a bit big. It is a bit subtle though. Sorry about that.
This issue will list a number of minor editorial things that should be checked and likely addressed with some editorial fixes: Section 5.3: "These delays are computed using the ACK Delay field of the ACK frame as described in Section 19.3 of [QUIC-TRANSPORT]." This text implies that the computation of the delay is described in Section 19.3 of QUIC-TRANSPORT. However, I don't think it is described the calculation, only the definition of the field. Please reformulate to imply only field definition not calculation. Section 5.3: "On the first RTT sample for the network path, that sample is used as rttsample. This ensures that the first measurement erases the history of any persisted or default values." I think this intended to cover cases where path changes are detected. But it is not well expressed. Does this need a reformulation and a reference into QUIC-TRANSPORT where it states when such a reset should occur? Section 6.1: "Either its packet number is kPacketThreshold smaller than an acknowledged packet" Nitpicking, assuming no PN gaps in transmission. Does that need a note? Section 6.2.4: "An endpoint MAY send up to two full-sized datagrams containing ack-eliciting packets, to avoid an expensive consecutive PTO expiration due to a single lost datagram or transmit data from multiple packet number spaces." This last part, I assume intended to generate additional datagrams to prevent single loss to impact. However, due to coalescing this is unclear in this context. Section 7: "Endpoints can unilaterally choose a different algorithm to use, such as Cubic ([RFC8312])." I think this sentence should be explicit that in needs to be sender-based algorithms. I think we need to have the requirement on performing congestion control on the sender unless there has been explicit agreement with the receiver that they will do it.


Question: that it chooses. A server MUST discard an Initial packet that is carried in a UDP <del> datagram with a payload that is less than the smallest allowed maximum packet size of 1200 bytes.  A server MAY also immediately </del> <ins> datagram with a payload that is smaller than the smallest allowed maximum datagram size of 1200 bytes.  A server MAY also immediately </ins> close the connection by sending a CONNECTION_CLOSE frame with an error code of PROTOCOL_VIOLATION; see immediate-close-hs.

Section 7.2: "Endpoints SHOULD use an initial congestion window of 10 times the maximum datagram size (maxdatagramsize), limited to the larger of 14720 bytes or twice the maximum datagram size." "maximum datagram size" is not used in Transport there need to be alignment here of what name to use. Transport has Maximum Packet Size, which appears to match the definition in the appendix of maxdatagram_size.
Thanks for your careful review, NAME -- these are good finds! I've addressed your comments below and in . I'll address point 6 in a separate PR. Section 19.3 has the following text, which does tell how to compute acknowledgement delay from the ACK Delay field: I've replaced "computed" with "decoded" in the recovery document to make it clearer. Coalescing applies to packets, not to datagrams. We've explicitly stated that a sender could send 2 datagrams to avoid any effects of coalescing. I think the text is pretty clear on this: "An endpoint MAY send up to two full-sized datagrams containing ack-eliciting packets". I've added "sender-side" to make the controller more explicit. To your point about making this a sender requirement, that is covered in the transport doc (end of ):
Based on and , labeling this as "editorial"
I think these issues are resolved once the two PRs are completely ready.
Except for the one erronous exchange of packet this looks good.


Question: strings.  The initial contents of the registry is shown in fig- method-types. <del> 9.3. </del> <ins> 9.4. </ins> IANA has created a new registry entitled "EDHOC Error Codes" under the new heading "EDHOC".  The registration procedure is

(Last two commits on wrong branch.)
The prototype of EDHOC-Exporter() has remained EDHOC-Exporter(label, length), while it should be EDHOC-Exporter(label, context, length) as per Alternative 3 discussed in issue URL Correct?
Thanks NAME your comment is addressed in the latest commit. I merge this now.
The text use both the terms "session" and "protocol instance", would be good to settle for one term.
Just chose one, I don't think this needs an issue
In the security considerations "session" makes most sense to me. There is also the term "connection". I will make a proposal.
The spec should likely forbid multiple calls to the EDHOC-Exporter interface with the same label, in order to prevent the same key being reused. Discussed with NAME and NAME
Good catch. Yes, we should have some text about that, but it should probably more be a requirement on the application using EDHOC that on EDHOC itself. Two different application should defintly not use the same label. The same application might rederive the same key several times as long as it keep track of its AEAD nonces and replay window. I thought that we had already IANA registry proposed for this, but that is not the case. We should probably have one. If we have a IANA registry the labels get more fixed and it might be that we need a context input parameter as well.
If we make a IANA registrer for labels, I think we need to let the application add additional information in some way. Two alternatives: We make an IANA register for label prefixes, and let the application append information to the label prefix. This was recently planned for EAP-TLS (and methods built on EAP-TLS) but was changes because the TLS export labels are not really ment to be labels. This would not change the current exporter interface. We expand the interface with a context parameter. This is similar to the TLS exporter. A problem with the TLS exporter is that some implementations decided to not even support context.
NAME how is the context parameter intended to be used? Could you give an example? Would this be some sort of "salt" when deriving the key?
Don't register labels, register label prefixes.


Question: strings.  The initial contents of the registry is shown in fig- method-types. <del> 9.3. </del> <ins> 9.4. </ins> IANA has created a new registry entitled "EDHOC Error Codes" under the new heading "EDHOC".  The registration procedure is

The motivation for "context" or "label postfixes" is to increase the flexibility for the application. Restricting the application to IANA registered labels is very limiting. An application might want to use the EDHOC exporter to derive a number of keys and we should encourage that. The alternative is that the application needs to implement its own key derivation, which might be less secure and might be outside of the TEE. I called it "context" just because TLS calls the paramater in its exporter context.
"Be like TLS" is of course a good motivation. Technically, a label prefix is not different from a context, it just saves the need to separate prefix and suffix.
(And of course there is nothing wrong with multiple calls with the same label; the application has a "right to forget" :-)
The solutions should be equal when it comes to security. The choice should be made based on what is easiest for implementators and apllications using EDHOC. Alt 1. We make an IANA register for label prefixes: "OSCORE Master Secret" "OSCORE Master Salt" The Export function stays the same: EDHOC-Exporter(label, length) = EDHOC-KDF(PRK4x3m, TH4, label, length) An application is allowed to append things to the label prefix: "OSCORE Master Secret" "OSCORE Master Secret PickleRick" Alt 2. We make an IANA register for labels: label = "OSCORE Master Secret" label = "OSCORE Master Salt" The Export function needs to change: EDHOC-Exporter(label, ctx, length) = EDHOC-KDF(PRK4x3m, TH4, [label, ctx] , length) An application is not allowed to append things to the label and uses the ctx instead: label = "OSCORE Master Secret" ctx = "" label = "OSCORE Master Secret" ctx = "PickleRick"
No major opinion. Alt 2 breaks the test vector for the OSCORE security context. It would be good to get more input.
Any preference NAME NAME NAME ?
If desired the CTX is more convenient it can always be added in a wrapper on top of EDHOC-Exporter(). (I assume re-use of label+ctx in Alt 2 is equivalent to re-use of label in Alt 1?)
I prefer to have explicitly specified.


Question: strings.  The initial contents of the registry is shown in fig- method-types. <del> 9.3. </del> <ins> 9.4. </ins> IANA has created a new registry entitled "EDHOC Error Codes" under the new heading "EDHOC".  The registration procedure is

We can pass to the concatenation of and . When is undefined/empty, test vectors are not affected. I guess this is what NAME is referring to?
label is a CBOR byte string. While alt 2 use an CBOR array. Definging alt2 as a wrapper seems more complication in my view.
Would be good if people stated alt 1. or alt 2. or made a concrete suggestion for alt 3.
Alt 3 (CBOR sequence) We make an IANA register for labels: label = "OSCORE Master Secret" label = "OSCORE Master Salt" The Export function needs to change: EDHOC-Exporter(label, ctx, length) = EDHOC-KDF(PRK4x3m, TH4, labelcontext, length) where is a CBOR sequence: If you want to keep the test vectors intact, then you could make optional in the CDDL, but not sure how to specify an optional parameter in the interface definition.
Thanks. That is a valid alt 3. but ctx should probably be a bstr
I don't think keeping the test vectors intact is an important goal at all. Let's decide on what is simplest for a user of the exporter interface.
Something like that, yes. Later post do differentiate the type of "label" and "ctx" and in light of that and changing test vectors Alt3 seems clean.
I am fine with alt 3. I can start making PR for that unless somebody has different ideas. I don't alt 1 is a good alternative anymore as is restricts context to being a unicode string. Which would require some base64 encoding or similar for a general context.
Please review alt. 3 as specified in . Unless there are any comments we would like to merge this.
This is included in -07 so I close the issue.
Comment by Martin Disch in URL "The draft does a good job of pointing to the right places in RFC 8152, but I still ended up trying to understand another ~100 page document just to implement the few constructs I actually needed." Should we provide more details about COSE constructs, e.g. in appendix A.2?
(pasting my response from the mailing list here for completeness) Thanks for following up on this. Yes, in my opinion expanding on the COSE constructs would be helpful.


Question: strings.  The initial contents of the registry is shown in fig- method-types. <del> 9.3. </del> <ins> 9.4. </ins> IANA has created a new registry entitled "EDHOC Error Codes" under the new heading "EDHOC".  The registration procedure is

But I also sympathize with not wanting to duplicate what is already defined in another RFC (and possibly getting it wrong, as Carsten points out). Considering that there are quite a few implementers already and besides mine you have only received one other similar comment, maybe this isn't an issue for a meaningful majority. In any case, the draft has made great strides already in terms of accessibility and is in a good state now, so I don't see improvements in this area as an absolute necessity.
The two COSE constructs that are used in EHDOC, and are fairly simple. They don't use the recursive structure or embed . I think it is possible to add some additional clarifications on the structure of the COSE messages in the EHDOC draft without having to copy too much text from RFC 8152. As part of a thesis I built a proof-of-concept implementation of EDHOC in the Rust programming language available at URL The naming of the repository is due to the subject being both EDHOC and OSCORE on embedded devices, but the following refers only to the EDHOC implementation. It's based on draft-selander-ace-cose-ecdhe-14 and as such, sadly, outdated. Since it was just one part of the overall work, I only managed to implement the subset I needed, which is RPK and the signature-signature based scheme (corresponding to what draft-selander-lake-edhoc calls method 0). I also took some other shortcuts, such as not supporting auxiliary data. Fortunately, test vectors were about to be introduced just around the time I was working on it, so I've been able to successfully verify my implementation against them when John shared them with me for some preliminary testing. Since I didn't have any prior experience implementing this kind of software, I would definitely consider it more of an experiment, but it's out there and it works, in case it can be useful to anybody. I'm convinced that EDHOC will be valuable particularly in the context of OSCORE, possibly even beyond that. As for the draft itself, I would like to mention one aspect that I think could be improved from the perspective of an implementer. Part of the promise of EDHOC is that it's simple and lightweight due to reusing COSE.


Question: strings.  The initial contents of the registry is shown in fig- method-types. <del> 9.3. </del> <ins> 9.4. </ins> IANA has created a new registry entitled "EDHOC Error Codes" under the new heading "EDHOC".  The registration procedure is

That is certainly the case, but breaks down somewhat when working on a system where no fully featured library for it is available. This was the case for me and I personally found it difficult to quickly figure out which aspects of COSE I needed to implement. The draft does a good job of pointing to the right places in RFC 8152, but I still ended up trying to understand another ~100 page document just to implement the few constructs I actually needed. I know the authors are aware of this and there has been some effort to inline more information directly in the specification, which I greatly appreciate. It would be very nice to have an entirely self-contained document to work with. But I have to again point out my lack of experience in that area, it's entirely possible that this draft is in fact much better than others in this regard and I just don't know it yet. With that I would like to support the adoption and am looking forward to seeing how it develops. Kind regards, Martin


Question: have been lost or discarded by the server.  A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet. <del> A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message.  Sending packets with the same packet number in that case is likely to compromise the packet </del> <ins> A client MUST NOT reset the packet number it uses for 0-RTT packets, since the keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet.  Sending packets with the same packet number in that case is likely to compromise the packet </ins> protection for all 0-RTT packets because the same key and nonce could be used to protect different content.

As of , the client MUST use the same handshake message.
NAME That's quite complicated, and I'm not sure if we've chosen the right design here. I'd like to keep this PR editorial though. I opened to discuss this.
In URL, NAME points out that after a Retry, all 0-RTT packets sent in the first flight are still valid, although they will probably have been dropped by the server (unless there's significant reordering). That means that a client SHOULD retransmit all 0-RTT packets in the second flight. We now have two different scenarios: In the case of a HelloRetryRequest, the client is prohibited from sending 0-RTT, and has to cancel retransmissions for all outstanding 0-RTT packets. In the case of Retry, the 0-RTT packets from the first flight are declared lost (without any effect on the cwnd though) and retransmitted. Considering that Retry adds a roundtrip anyway (and thereby limits the usefulness of 0-RTT), and that we only expect it to be used by a server that's under attack (which makes it likely to refuse 0-RTT later in the handshake), does it really make sense to send 0-RTT in that case?
NAME I am not sure if I agree with the observation. The transport draft states that a server MAY send Retry packets in response to Initial and 0-RTT packets. A server can either discard or buffer 0-RTT packets that it receives (). Notice that the server is allowed to "buffer" 0-RTT packets. I am not sure if I like this ambiguity (because I think most if not all of us will be dropping 0-RTT packets that carry the original DCID when sending a Retry), but IMO the draft is clear.
NAME thanks for pointing that out. My point is that we should change the draft (i.e. this is a design issue, not an editorial issue).


Question: have been lost or discarded by the server.  A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet. <del> A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message.  Sending packets with the same packet number in that case is likely to compromise the packet </del> <ins> A client MUST NOT reset the packet number it uses for 0-RTT packets, since the keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet.  Sending packets with the same packet number in that case is likely to compromise the packet </ins> protection for all 0-RTT packets because the same key and nonce could be used to protect different content.

The reason a server (or a LB) performs a Retry is that it either has reasons to suspect that the client isn't reachable at the 2-tuple it sent the packet from, or that it is under load, and either uses the Retry to redirect traffic to a different backend server, or just to buy itself some time Under both circumstances, a server wouldn't want to allocate additional state for buffering 0-RTT packets. I'm therefore suggesting to change the draft such that: A server that performs a Retry MUST discard 0-RTT packets. A client MUST NOT use 0-RTT after a Retry was performed. Does that make sense to you?
Yeah, I can envision a server that considers buffering some number of packets to be cheaper than doing a TLS handshake. For such servers, delaying the TLS handshake until client proves it's existence but buffering the 0-RTT packets in the meantime would make sense. That said, I'd be fine with this, assuming that the discarded 0-RTT packets are the ones that carry the original DCID. I would prefer not having this requirement. Once the client is known to exist, a server needs to communicate with the client. Use of 0-RTT helps reduce the server load, because when used, average lifetime of connections becomes 1-RTT less. That leads us to having less concurrent connections.
When our implementation does Retry, it's because we've hit a memory pressure limit and we want to protect ourselves from attack. If a client supplies us with a valid token, we will accept 0-RTT still, but we won't buffer it from the previous Initial (without a token). So, if the client gets a Retry and still wants to do 0-RTT, they need to retransmit it, with the new CID, in a new packet (with a new packet number). I don't see why that design should be prevented.
Ok, I see that there's value in doing 0-RTT after a Retry, and furthermore, there seem to be good reasons (prevention of tampering by middle boxes) to disallow 0-RTT after a HelloRetryRequest in TLS 1.3, as NAME pointed out OOB. Since we can assume that most (all?)


Question: have been lost or discarded by the server.  A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet. <del> A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message.  Sending packets with the same packet number in that case is likely to compromise the packet </del> <ins> A client MUST NOT reset the packet number it uses for 0-RTT packets, since the keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet.  Sending packets with the same packet number in that case is likely to compromise the packet </ins> protection for all 0-RTT packets because the same key and nonce could be used to protect different content.

server implementation will drop 0-RTT packets when sending a Retry, the only reasonable thing to do for a client is to treat all 0-RTT packets as lost and retransmit them. Considering that, it would make sense to require servers to drop all Retry packets from the first flight, as NAME suggests.
NAME Thank you for suggesting a path forward. I think my weak preference goes to something slightly different. I think we are in agreement that most if not all the servers would not buffer the 0-RTT packets carrying the original DCIDs when they send Retrys. It makes sense to acknowledge the fact in the specification and suggest clients to retransmit 0-RTT data it has already sent. What I am not sure is if there is a reason to forbid servers from buffering such 0-RTT packets. From client's point of view, sending 0-RTT data once per connection is an optimization. Retransmitting 0-RTT data when the server sends a Retry is further optimization. If we think that way, servers that buffer 0-RTT packets when sending a Retry has increased chance of utilizing 0-RTT data. Compared to that, there is no reason to mandate servers to drop 0-RTT packets. To summarize, I think all we need to clarify is that servers responding with Retries are likely to discard 0-RTT packets that carry the original DCIDs and therefore that retransmitting 0-RTT data makes sense. But nothing more.
What if client takes action on Retry, and the old 0-RTT state lingers - wouldn't that make servers more vulnerable to DDoS attacks from packet sniffers?
This also bears on . If the DCID doesn't change, then the server won't be able to differentiate the first flight of 0-RTT packets, which you're proposing to drop, from the second flight of 0-RTT packets which it accepts. The current text says that the server MAY buffer and process them later; you're saying that servers probably won't. I think that's fine, but some might -- hence, I favor NAME suggestion to retain the permission to buffer but the caution to the client that the packets were quite possibly lost/dropped.


Question: have been lost or discarded by the server.  A client MAY attempt to resend data in 0-RTT packets after it sends a new Initial packet. <del> A client MUST NOT reset the packet number it uses for 0-RTT packets. The keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet unless the client also regenerates the cryptographic handshake message.  Sending packets with the same packet number in that case is likely to compromise the packet </del> <ins> A client MUST NOT reset the packet number it uses for 0-RTT packets, since the keys used to protect 0-RTT packets will not change as a result of responding to a Retry packet.  Sending packets with the same packet number in that case is likely to compromise the packet </ins> protection for all 0-RTT packets because the same key and nonce could be used to protect different content.

In terms of actual spec change, I think that means this text in : ...becomes a SHOULD instead of a MAY.
It seems like you have sorted this out. I have no problem with using "SHOULD" over "MAY" here. Note that the reason we have this distinction is logical separation of the mechanism of Retry and 0-RTT acceptance. Retry strictly precedes the connection attempt. No point in blocking 0-RTT if you have to Retry. HelloRetryRequest is different in that certain characteristics it might cause to reset affect whether the 0-RTT works. Retry is required to use the same ClientHello, so there is no need to have the two interact; you can treat a Retry almost as a loss event for the first Initial and everything works fine.
So, the effect of not changing the handshake message is that all previously-sent 0-RTT data is still valid, but has potentially/probably been lost rather than queued. Clients obviously MUST NOT reuse the packet number for different data, but in their not-resetting, they also can't change the data that they've already sent in those packets. They'll need to retransmit it, because otherwise there's a potential DoS attack by delaying/replaying a 0-RTT packet by one RTT against a server that does Retries.This PR looks good to me as an editorial improvement. Regarding NAME point, the transport draft explicitly states that a server sending a Retry can buffer 0-RTT packets that carried the original DCID, and process them after receiving a response to the Retry. To put it differently, I think we are clear on the semantics and that there are ways to implement this without having security concerns. That said, I understand that NAME has opened a design issue () to discuss if that is the design we want to have.LGTM


Question: a local description.  If an error is returned, the session MUST be restored to the state it was in before performing these steps. <del> First, the parsed parameters are checked to ensure that they are identical to those generated in the last call to createOffer/ createAnswer, and thus have not been altered, as discussed in sec.modifying-sdp; otherwise, processing MUST stop and an error MUST be returned. </del> Next, m= sections are processed.  For each m= section, the following steps MUST be performed; if any parameters are out of bounds, or cannot be applied, processing MUST stop and an error MUST be

In Section 5.4, JSEP says: " The SDP returned from createOffer or createAnswer MUST NOT be changed before passing it to setLocalDescription." However in Section 5.8, it says: "First, the parsed parameters are checked to ensure that they are identical to those generated in the last call to createOffer/ createAnswer, and thus have not been altered, as discussed in Section 5.4; otherwise, processing MUST stop and an error MUST be returned." [BA] So is any change to URL unacceptable (e.g. must be byte for byte identical)? Or is the text trying to say that the parsed representation must be the same (e.g. "a=" lines appearing in a different order shouldn't matter)?
I believe the expectation was that the description is entirely immutable. Verifying isomorphism in the face of minor modifications seems like something that is not entirely trivial, and TBH I don't quite understand why it would be needed.
Thanks. PR URL assumes that URL is immutable.
I will update 5.8 accordingly.


Question: signature is represented as a DER-encoded X690 ECDSA-Sig-Value structure as defined in RFC4492. <del> Indicates a signature algorithm using RSASSA-PSS RFC8017 with mask generation function 1.  The digest used in the mask generation function and the digest being signed are both the corresponding hash algorithm as defined in SHS.  The length of the Salt MUST be equal to the length of the output of the digest algorithm.  If the public key is carried in an X.509 certificate, it MUST use the rsaEncryption OID RFC5280. </del> <ins> Indicates a signature algorithm using RSASSA-PSS with a mask generation function of MGF1, as defined in RFC8017.  The digest used in MGF1 and the digest being signed are both the corresponding hash algorithm as defined in SHS.  The length of the Salt MUST be equal to the length of the output of the digest algorithm.  If the public key is carried in an X.509 certificate, it MUST use the rsaEncryption OID RFC5280. </ins> Indicates a signature algorithm using EdDSA as defined in RFC8032 or its successors.  Note that these correspond to the "PureEdDSA" algorithms and not the "prehash" variants. <del> Indicates a signature algorithm using RSASSA-PSS RFC8017 with mask generation function 1.  The digest used in the mask generation function and the digest being signed are both the corresponding hash algorithm as defined in SHS.  The length of the Salt MUST be equal to the length of the digest algorithm.  If the public key is carried in an X.509 certificate, it MUST use the RSASSA-PSS OID RFC5756.  When used in certificate signatures, the algorithm parameters MUST be DER encoded.  If the corresponding public key's parameters are present, then the parameters in the signature MUST be identical to those in the public key. </del> <ins> Indicates a signature algorithm using RSASSA-PSS with a mask generation function of MGF1, as defined in RFC8017.  The digest used in MGF1 and the digest being signed are both the corresponding hash algorithm as defined in SHS.  The length of the Salt MUST be equal to the length of the digest algorithm.  If the public key is carried in an X.509 certificate, it MUST use the RSASSA-PSS OID RFC5756.  When used in certificate signatures, the algorithm parameters MUST be DER encoded.  If the corresponding public key's parameters are present, then the parameters in the signature MUST be identical to those in the public key. </ins> Indicates algorithms which are being deprecated because they use algorithms with known weaknesses, specifically SHA-1 which is used

MGF1 got unhelpfully spelled out as "mask generation function 1" in RFC 8446. I'm guessing this is the result of an acronym expansion editting pass, but the function is simply called "MGF1". There is no such thing as "mask generation function 1". Correct this back to MGF1. In hopes this doesn't get hit the same editing pass later, I've tweaked the wording and moved the citation so that "mask generation function" is still uttered before MGF1, and it's clearer that both primitives are defined in RFC 8017.


Question: Understanding what causes deadlocking might help implementations avoid deadlocks. <del> Large messages can produce deadlocking if the recipient does not process the message incrementally.  If the message is larger than the flow control credit available and the recipient does not release additional flow control credit until the entire message is received and delivered, a deadlock can occur.  This is possible even where stream flow control limits are not reached because connection flow control limits can be consumed by other streams. A common flow control implementation technique is for a receiver to extend credit to the sender as a the data consumer reads data.  In this setting, a length-prefixed message format makes it easier for the data consumer to leave data unread in the receiver's buffers and thereby withhold flow control credit.  If flow control limits prevent the remainder of a message from being sent, a deadlock will result. A length prefix might also enable the detection of this sort of deadlock.  Where protocols have messages that might be processed as a </del> <ins> The size and rate of transport flow control credit updates can affect performance.  Applications that use QUIC often have a data consumer that reads data from transport buffers.  Some implementations might have independent transport-layer and application-layer receive buffers.  Consuming data does not always imply it is immediately processed.  However, a common flow control implementation technique is to extend credit to the sender, by emitting MAX_DATA and/or MAX_STREAM_DATA frames, as data is consumed.  Delivery of these frames is affected by the latency of the back channel from the receiver to the data sender.  If credit is not extended in a timely manner, the sending application can be blocked, effectively throttling the sender. Large application messages can produce deadlocking if the recipient does not read data from the transport incrementally.  If the message is larger than the flow control credit available and the recipient does not release additional flow control credit until the entire message is received and delivered, a deadlock can occur.  This is possible even where stream flow control limits are not reached because connection flow control limits can be consumed by other streams. A length-prefixed message format makes it easier for a data consumer to leave data unread in the transport buffer and thereby withhold flow control credit.  If flow control limits prevent the remainder of a message from being sent, a deadlock will result.  A length prefix might also enable the detection of this sort of deadlock.  Where application protocols have messages that might be processed as a </ins> single unit, reserving flow control credit for the entire message atomically makes this style of deadlock less likely. <del> A data consumer can read all data as it becomes available to cause the receiver to extend flow control credit to the sender and reduce the chances of a deadlock.  However, releasing flow control credit might mean that the data consumer might need other means for holding a peer accountable for the state it keeps for partially processed messages. </del> <ins> A data consumer can eagerly read all data as it becomes available, in order to make the receiver extend flow control credit and reduce the chances of a deadlock.  However, such a data consumer might need other means for holding a peer accountable for the additional state it keeps for partially processed messages. </ins> Deadlocking can also occur if data on different streams is interdependent.  Suppose that data on one stream arrives before the

This mainly wiggles the existing text around and tries to fully qualify transport vs application to help explain the ways an implementation might do things, which is independent of how an application protocol might be designed (for example H3 doesn't require incremental processing but most people come to a realizatopm that it is the best way to do things).
The new text is good and clear, but it doesn't really explain that the when credit is released at the receiver, could we say a little more: it takes 1/2 RTT for cerdit to reach the sender, that causes new data to be released, for a large RTT, this means that credit has to be sufficient to avoid blocking or to be sent promptly, otherwise transfers will stall for periods of an RTT. (I know TCP does this stuff for the app and grows the window, but QUIC I suspect needs something to happen to release the credit). I know people closer to the Apps can write this sentence better than me; from my perspective I just see the effects when an app blocks or release credit in big chunks... over a large path RTT and the network performance suffers.
Thanks Gorry. I think I agree. How about I tweak "Timely updates can improve performance" paragraph to say "Timing of updates can affect performance". I can add a mention that the extension of credits on the data recever side is enacted by emitting MAXDATA/MAXSTREAM_DATA frames, which take at least a 1/2 RTT to reach the data sender side. I think the useful additional applicability statement to be made based on the above is that the data consumer read rate may be disjoint from the delivery rate and responsiveness of signalling channel back. For a highly asymmetric link, the download rate can be application-limited well below the theoretical bandwidth simply because an application is spending too much share of the time reading packets and not giving enough time to emit QUIC packets. Does that sound ok, or am I missing your ask?
This is definitely heading in the direction I was hoping, it helps avoid people developing on a LAN and then discovering the effects on other paths later. Please add something.
I've reworked the paragraph with my attempt to address NAME comment. I've introduced the terms uplink and downlink, which I'm not totally happy with. If someone has a better suggestion I'm all ears.
Issue: Sect 4.3.