Hi,
I would like to restart the discussion on the ML here again as I keep
forgetting what we established and what the way forward is and I think
it is better to discuss this "out in the open".
Our current "PingPong" KX in CORE seems quite odd and complex to me and
the requirements fuzzy.
In a nutshell, the protocol tries to establish a DH secret and it goes
something like:
0. MyPeerID: Generate an "ephemeral" DH key pair and sign it with
PeerID private key. Lets call this "cert"
1. MyPeerID: If MyPeerID > OtherPeerID goto 2; otherwise wait T time
and then goto 2
2. PyPeerID: Send "cert" to OtherPeerID (Ping)
3. OtherPeerID: Calculates the DH secret from ephemeral public key in
"cert" and its own ephemeral DH key (from 0)
4. OtherPeerID: Confirms handshake by sending message back; sending its
own "cert" (Pong).
5. MyPeerID calculates the DH secret from ephemeral public key of
OtherPeerID in "cert".
Now, I have various issues with the protocol:
a. Freshness: We should use nonces, which we don't and can't for
reasons including the following
b. Static DH key: The "ephemeral" DH key is actually static across
handshakes with other peers and across the rekey interval (or key
validity period, whatever you want to call it).
c. The KX transcript is not signed/verified
d. The roles are not clear.
Now, the issues seem to stem from the idea that we do not know which
peer initiates the handshake, so we cannot know which role a peer is
in.
In fact, the KX could be initiatet theoretically from both peers at the
same time, and we need to take this into account.
Peers determine a KX initiation based on various factors, for example a
peer may just have learned of the existance of the other peer, just
started, etc.
This is why the protocol (Steps 0-5) may (within the key validity
period overlap of both PeerIDs) converge to the same DH secret
regardless of role and KX flow (and yes, this is bad from
security/crypto view).
The state machine to make this happen is implemented, as far as I can
see, but I am not sure how well this actually works in practice given
that we see some erratic behaviour from CORE and regular bug reports
regarding connectivity (even to the bootstrap peer).
Now, I would really like to converge to a semi-standard, known secure
KX protocol for CORE that has clear requirements and is much more
streamlined.
As already discussed, I have drafted a KEMTLS-inspired handshake here
with 1.5 RTT:
https://docs.gnunet.org/master/developers/apis/cong.html#handshake-protocol-draft
I also started to document the current protocol, but it is very complex
due to its state machine and 3RTT+.
My Idea: IF we can agree that transport only notifies CORE of a
connection if it can send AND receive messages from that peer (bi-
directional connectivity, which afair is the case in transport right
now), I strongly believe that we can simply rely on protocol Step 1
that a KX is initiated _at all_.
It can still happen that two KX are initiated one from each peer at the
same time.
But in this case, since we assume that we have bi-directional comms, we
can simply drop the "late" initiator message on one side based on the
same condition in Step 1.
Wdyt? Any comments?
BR
Martin