[RFC,WIP] implement PQC PSK key exchange handshake#5
[RFC,WIP] implement PQC PSK key exchange handshake#5jonasjelonek wants to merge 10 commits intoopenwrt:pqcfrom
Conversation
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Try getrandom/arc4random first, only fall back to /dev/urandom when necessary Signed-off-by: Felix Fietkau <nbd@nbd.name>
This will be used for quantum safe handshakes Signed-off-by: Felix Fietkau <nbd@nbd.name>
Used for ML-DSA Signed-off-by: Felix Fietkau <nbd@nbd.name>
Used for post-quantum signatures Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
nbd168
left a comment
There was a problem hiding this comment.
Seems like a good start! Added a few comments...
implements PQC PSK key exchange for unetd THIS IS UNFINISHED AND DOES NOT WORK YET! Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
jonasjelonek
left a comment
There was a problem hiding this comment.
addressed all comments, split up messages, removed unnecessary (for now) changes
| return last == 0 || now - last > HANDSHAKE_INTERVAL; | ||
| } | ||
|
|
||
| /* This should be called regularly by some kind of timer */ |
There was a problem hiding this comment.
@nbd168 should this get its own timer or can we reuse one of the existing timers like request_update_timer or connect_timer?
There was a problem hiding this comment.
I think it should get its own timer.
| resp->last_handshake_time = peer->state.last_psk_handshake; | ||
| resp->need_handshake = psk_kex_need_handshake(peer); | ||
|
|
||
| pex_msg_send_ext(net, peer, /* address outside of tunnel */ addr); |
There was a problem hiding this comment.
@nbd168 how may I get the address to send this to the "peer" outside of the tunnel on global pex port?
There was a problem hiding this comment.
You should go through all addresses in peer->state.next_endpoint, possibly checking for duplicates.
There was a problem hiding this comment.
For my understanding:
- what's the point of the different endpoint types?
- why couldn't I just use
peer->state.endpointorpeer->state.next_endpoint[ENDPOINT_TYPE_PEX]as destination?
There was a problem hiding this comment.
ENDPOINT_TYPE_PEX is an endpoint address received from another host.
ENDPOINT_TYPE_ENDPOINT_NOTIFY and ENDPOINT_TYPE_ENDPOINT_PORT_NOTIFY are endpoint addresses received from peers directly (former from the PEX port, latter from the wireguard port).
If you don't have any peer connection yet, the ENDPOINT_TYPE_PEX will not be filled. Peers for other hosts are only exchanged over the tunnel.
As for the other types, availability depends on which packets make it through, especially in the NAT case. When the basic work on the handshake is done, we may need to add some improvements to NAT handling, since there will be some limitations compared to non-PEX handshake.
| default: return; | ||
| } | ||
|
|
||
| // TBD: do we need to explicitly trigger a network update to use the new PSK or does that work automatically? |
There was a problem hiding this comment.
You can do a wg_peer_update(net, peer, WG_PEER_UPDATE) call directly in order to upload the new psk for the peer to wireguard. Afterwards it should work on the next automatic handshake attempt.
| return last == 0 || now - last > HANDSHAKE_INTERVAL; | ||
| } | ||
|
|
||
| /* This should be called regularly by some kind of timer */ |
There was a problem hiding this comment.
I think it should get its own timer.
| if (peer->kex_ctx.role != PSK_KEX_ROLE_INITIATOR) | ||
| return; | ||
|
|
||
| /* TBD: Can we send two messages in a row without issues? */ |
There was a problem hiding this comment.
I would recommend splitting the sending of messages from initializing the key exchange state. Messages may have to be retransmitted over unreliable networks, and it would be good to not have to redo the keygen part each time.
I also think it might be useful to encrypt the initial messages with a key derived from curve25519 DH, which can be calculated once per peer ahead of time. That reduces the DoS potential of expensive PQ crypto, as long as the non-PQ crypto has not been cracked yet.
| resp->last_handshake_time = peer->state.last_psk_handshake; | ||
| resp->need_handshake = psk_kex_need_handshake(peer); | ||
|
|
||
| pex_msg_send_ext(net, peer, /* address outside of tunnel */ addr); |
There was a problem hiding this comment.
You should go through all addresses in peer->state.next_endpoint, possibly checking for duplicates.
| default: return; | ||
| } | ||
|
|
||
| // TBD: do we need to explicitly trigger a network update to use the new PSK or does that work automatically? |
There was a problem hiding this comment.
You can do a wg_peer_update(net, peer, WG_PEER_UPDATE) call directly in order to upload the new psk for the peer to wireguard. Afterwards it should work on the next automatic handshake attempt.
implements PQC PSK key exchange for unetd
Just as RFC for the handshake/key exchange process and how it's implemented.
This is still missing proper integration into unetd's internals, especially pex message send/recv flow.
This doesn't compile nor run yet.