Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC8613: Handling re-transmission requests #24

Open
mrdeep1 opened this issue Jun 15, 2022 · 8 comments
Open

RFC8613: Handling re-transmission requests #24

mrdeep1 opened this issue Jun 15, 2022 · 8 comments

Comments

@mrdeep1
Copy link

mrdeep1 commented Jun 15, 2022

If a CON request (or its ACK response) is lost, the CON request will get re-transmitted. If there are NON requests following the initial CON request, the sequence number of the re-transmission may then fall outside of the replay window as in

A -x B: CON with sequence number n
A -> B: NON with sequence number n + 1
A -> B: NON with sequence number n + 2
...
A -> B: CON with sequence number n

A way forward here could be to increment the sequence number for each transmission (including re-transmission) so that everything stays within the replay window.

Then however, if the ACK response to a CON request is received by the client after the CON request has been re-transmitted, then when decoding the ACK, the external_aad will contain the updated Partial IV of the re-transmitted packet, not the original packet and then have some sort of decryption failure.

A -> B: CON with sequence number n
A -- B: ACK initiated 
A -> B: CON re-transmit with sequence number n + 1
A <- B: ACK received for sequence n

What is the correct way to handle a mix of CON and NON requests for OSCORE in a lossy environment?

@chrysn
Copy link
Member

chrysn commented Jun 16, 2022

increment the sequence number for each transmission (including re-transmission)

That would be dangerous, as now the server couldn't do cryptographically checked deduplication any more: If it receives both the original request and a retransmit, and processes them both even though they're intended to be processed once. (Plus it negates a small performance advantage over DTLS that OSCORE has).

may then fall outside of the replay window

The default replay window is 32. The rate at which a client may send without seeing feedback from the server defaults to PROBING_RATE = 1 byte / second, and EXCHANGE_LIFETIME (maximum between start and when we expect a retransmit to come in) is 247 seconds. You can't send 32 OSCORE requests in 247 bytes.

(I don't think that PROBING_RATE is super tight, so one might send 3 or 4 or maybe even 10 (eg. Q-Block even though they use different parameters) NONs in a burst, but as the average PROBING_RATE is still limiting, that'd cause quite some silence later).

That's not a completely waterproof argument -- the NONs might get responses whereas all the CON retransmits fail, but that still requires an amount of unluckiness that's bordering a malicious agent on the network that deliberately slows down CONs -- and in that case, getting a "unprotect failed" sounds like the right behavior.


One option is always to increase the replay window. Beware that the size of the replay window (at least its worst case behavior, or best case behavior depending on point of view) needs to be agreed between the parties, so if you plan to alter the window on any but preconfigured OSCORE contexts, you might need to register parameters for choosing the replay window added to OSCORE_Input_Material of ace-oscore-profile (or however the contexts are configured).

@mrdeep1
Copy link
Author

mrdeep1 commented Jun 16, 2022

It was someone else that raised this as an issue, and I am not convinced that increasing the sequence number is the way to go.

If it receives both the original request and a retransmit, and processes them both even though they're intended
to be processed once

Same will happen if the returning ACK goes missing. The unwapped message would be an identical duplicate, so there should be no issues there.

That's not a completely waterproof argument ...

If someone updated NSTART to be > 1, then it is very easy to send a further 32 CON requests before the failing one gets re-transmitted.

Maybe that we have to make all OSCORE requests CON and only allow NSTART to be 1.

@chrysn
Copy link
Member

chrysn commented Jun 16, 2022 via email

@mrdeep1
Copy link
Author

mrdeep1 commented Jun 16, 2022

and I am not convinced that increasing the sequence number is the way
to go.

I don't understand; do you mean "increasing the replay window"?

I meant increasing the sequence number on a re-transmit - I am likewise not convinced that this is right. The replay window size is the thing to adjust.

Thanks for confirming with all the other information - I know which way to proceed short term.

@kkrentz
Copy link

kkrentz commented Jun 17, 2022

Unfortunately, the issue mentioned by mrdeep is not the only one that arises when not incrementing the sequence number of a retransmitted CON. Another consequence will be that if an ACK gets lost, retransmitted CONs get ignored. So, clients may retransmit pointlessly. I also wonder if this behavior can be turned into a denial-of-sleep attack as dropping a single ACK will cause a high energy consumption. Nevertheless, I now see the problem with the unprotected MIDs.

@chrysn
Copy link
Member

chrysn commented Jun 17, 2022 via email

@mrdeep1
Copy link
Author

mrdeep1 commented Jun 22, 2022

Storing the set of responses for the replay window size in case they are needed for the unlikely re-transmit case (and all the necessary garbage collection) seems to be an overkill.

How about making use of the separate response?
Request CON ->
<- Empty ACK (gets lost)
<- Response CON
Empty ACK ->
Request CON retry 1 ->
<- Response 4.01 (Replay detected)

The retry will not take place if the Response CON is received as there will be a token match. If the Response CON fails, then that will get retried.

The OSCORE encrypt logic can take the response from the server application and inject the empty ACK along with selecting a new MID for the actual response.

Obviously any unsolicited response does not send an initial empty ACK , as well as any application doing separate responses (i.e. a proxy).

@chrysn
Copy link
Member

chrysn commented Jun 22, 2022

Storing the set of responses is a general requirement of CoAP for non-idempotent requests. Sending a non-piggybacked response is generally a thing that a CoAP implementation that handles non-idempotent requests can do to keep the storage time low. OSCORE is just a special case of that, and the encrypt logic does not need to be involved. It's a choice of the CoAP stack below OSCORE to make.

The only input that an OSCORE implementation could give is to inform the CoAP stack that it does regard the request as an idempotent one, freeing the CoAP stack from all obligations to deduplicate or store responses. But to become idempotent it needs a replay optimization that'd need more review.

@cabo cabo transferred this issue from core-wg/corrclar-old Jul 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants