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

0RTT, Early data, session ticketing, key verification, stateless reset #147

Closed
wants to merge 15 commits into from

Conversation

dr7ana
Copy link
Collaborator

@dr7ana dr7ana commented Aug 29, 2024

Scope:

  • 0rtt/early data: Can be enabled with opt::enable_0rtt_ticketing at the endpoint level, and will apply for all connections in/out of that endpoint.
  • Session ticketing storage mode: Enabled through the same struct by passing the optional verify/put/get callbacks. The default mode is internal storage managed by libquic, but the application can take responsibility by providing all of the callbacks
  • Key verification on/off: Can be disabled with opt::disable_key_verification at the connection level by passing the struct to calls to Endpoint::{listen,connect}(...)
  • Stateless reset can be disabled with opt::disable_stateless_verification at the endpoint level

@dr7ana dr7ana changed the title [WIP] - 0RTT [WIP] - 0RTT, Early data, session ticketing, key verification Sep 5, 2024
@dr7ana dr7ana requested review from jagerman and tewinget September 5, 2024 17:05
@dr7ana dr7ana marked this pull request as ready for review September 5, 2024 17:05
@dr7ana dr7ana force-pushed the 0rtt branch 3 times, most recently from 65b8374 to 060c58b Compare September 9, 2024 15:51
@dr7ana dr7ana changed the title [WIP] - 0RTT, Early data, session ticketing, key verification 0RTT, Early data, session ticketing, key verification, stateless reset Sep 9, 2024
@dr7ana dr7ana force-pushed the 0rtt branch 2 times, most recently from 79bc67b to e89c643 Compare September 11, 2024 18:23
- By passing `opt::disable_key_verification` in calls to `Endpoint::{listen,connect}(...)` the application can decide whether to use key verification for inbound or outbound connections.
- can be toggled on/off, bespoke types for handling generation and storage
- improvements, better handling, callbacks
@dr7ana dr7ana force-pushed the 0rtt branch 5 times, most recently from 667fa64 to 7244dff Compare September 13, 2024 21:48
- ping binaries added to test timing
- more thoughtful compile time checking
src/connection.cpp Outdated Show resolved Hide resolved
src/connection.cpp Outdated Show resolved Hide resolved
@@ -3,11 +3,13 @@
#include <oxenc/base64.h>
Copy link
Member

@jagerman jagerman Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(This comment isn't necessary for this PR) Now that we have three separate cpp files implementing the stuff in this header, I'm thinking we should split the header up into something like gnutls/crypto.hpp/gnutls/session.hpp/gnutls/creds.hpp to match the cpp split.

include/oxen/quic/opt.hpp Outdated Show resolved Hide resolved
}
} // namespace detail

struct connection_callbacks
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct rename seems fine, but what is the point of moving them into internal.hpp when they are entirely local to connection.cpp?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to aggregate all the callback declarations (including session and tls callbacks) internally, as they're defined regardless in the *.cpp files

src/endpoint.cpp Outdated Show resolved Hide resolved
conn.reference_id());
associate_cid(qcid, conn);

// We only hold one reset token per connection at a time!
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question (about the protocol, not the code): why is there only one at a time?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would think that it would be one per active connection ID (which is like default 8 per connection?)

Copy link
Collaborator Author

@dr7ana dr7ana Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked about this off-band: My understanding is stateless reset is tied to the connection itself and renewed with every new DCID. That is why the cb defined by ngtcp2 is on_dcid_status

https://github.com/ngtcp2/ngtcp2/blob/67047340bc3f0cffd3217f8be649405a3927065c/lib/ngtcp2_cid.h#L93-L96

Whenever a the new connection id hook is invoked by ngtcp2, it copies the cid token to the current cid stored in the connection, overwriting the old one:
https://github.com/ngtcp2/ngtcp2/blob/67047340bc3f0cffd3217f8be649405a3927065c/lib/ngtcp2_conn.c#L7854-L7857

That's why there's a second map (reset_token_map and reset_token_lookup) to reference all the other quic cid's

log::trace(
log_cat, "{} associating CID:{} to {}", conn.is_inbound() ? "SERVER" : "CLIENT", qcid, conn.reference_id());

conn_lookup.emplace(qcid, conn.reference_id());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any possibility of a duplicate here that should be worried about?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be many quic_cid's to one ConnectionID (default is 8:1), so I would guess not? Apologies if I'm misunderstanding

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably there's an astronomically unlikely chance that there could be a collision, but I think CIDs are sent encrypted in both directions so a MITM shouldn't be able to force a collision, and either side of a connection intentionally making a new connection and re-using a CID is just messing up their own connection, so it should be fine. At least, if I understand the question correctly.

@jagerman
Copy link
Member

I've now reviewed this all and left various comments. I think this mostly looks good!

- added RAII gnutls_datum object, used where needed. Must be careful, can double free if the memory is owned by another object or held within ngtcp2
- misc fixes from oxen-io#147
@dr7ana dr7ana mentioned this pull request Dec 4, 2024
@dr7ana dr7ana closed this Dec 4, 2024
@dr7ana
Copy link
Collaborator Author

dr7ana commented Dec 4, 2024

Closed and reopened #153 because github is stupid and broke updating this PR when trying to drop a commit

dr7ana added a commit to dr7ana/libquic that referenced this pull request Dec 11, 2024
- added RAII gnutls_datum object, used where needed. Must be careful, can double free if the memory is owned by another object or held within ngtcp2
- misc fixes from oxen-io#147
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

Successfully merging this pull request may close these issues.

3 participants