-
Notifications
You must be signed in to change notification settings - Fork 389
/
Copy pathtunnel_config.proto
83 lines (77 loc) · 4.22 KB
/
tunnel_config.proto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
syntax = "proto3";
option go_package = "github.com/mullvad/wg-manager/server/tuncfg";
package tunnel_config;
service PostQuantumSecure {
// Allows deriving a preshared key (PSK) using one or multiple PQ-secure key-encapsulation
// mechanisms (KEM). The preshared key is added to WireGuard's preshared-key field in a new
// ephemeral peer (PQ-peer). This makes the tunnel resistant towards attacks using
// quantum computers.
//
// The VPN server associates the PQ-peer with the peer who performed the exchange. Any
// already existing PQ-peer for the normal peer is replaced. Each normal peer can have
// at most one PQ-peer.
//
// The PQ-peer is mutually exclusive to the normal peer. The server keeps both peers in memory,
// but only one of them is loaded into WireGuard at any point in time. A handshake from the
// normal peer unloads the corresponding PQ-peer from WireGuard and vice versa.
//
// A new peer is negotiated for PQ to avoid a premature break of the tunnel used for negotiation.
// A tunnel would break prematurely if the preshared key is applied before the normal peer
// received the server's contribution to the KEM exchange. This cannot occur now because
// the client decides when to switch to the PQ-secure tunnel. This design also allows
// the client to switch back to using a non-PQ-secure tunnel at any point.
//
// The negotiated PQ-peer is ephemeral. The server gives no guarantees how long it will be
// valid and working. The client should negotiate a new PQ-peer every time it establishes a new
// tunnel to the server.
//
// The full exchange requires just a single request-response round trip between the VPN client
// and the VPN server.
//
// # Request-response format
//
// The request from the VPN client contains:
// * `wg_pubkey` - The public key used by the current tunnel (that the request travels inside).
// * `wg_psk_pubkey` - A newly generated ephemeral WireGuard public key for the PQ-peer.
// The server will associate the derived PSK with this public key.
// * `kem_pubkeys` - A list describing the KEM algorithms. Must have at least one entry.
// The same KEM must not be listed more than once. Each list item contains:
// * `algorithm_name` - The name of the KEM, including which variant. Should be the same
// name/format that `liboqs` uses.
// * `key_data` - The client's public key for this KEM. Will be used by the server to
// encapsulate the shared secret for this KEM.
//
// The response from the VPN server contains:
// * `ciphertexts` - A list of the ciphertexts (the encapsulated shared secrets) for all
// public keys in `kem_pubkeys` in the request, in the same order as in the request.
//
// # Deriving the WireGuard PSK
//
// The PSK to be used in WireGuard's preshared-key field is computed by XORing the resulting
// shared secrets of all the KEM algorithms. All currently supported and planned to be
// supported algorithms output 32 bytes, so this is trivial.
//
// Since the PSK provided to WireGuard is directly fed into a HKDF, it is not important that
// the entropy in the PSK is uniformly distributed. The actual keys used for encrypting the
// data channel will have uniformly distributed entropy anyway, thanks to the HKDF.
// But even if that was not true, since both CME and Kyber run SHAKE256 as the last step
// of their internal key derivation, the output they produce are uniformly distributed.
//
// If we later want to support another type of KEM that produce longer or shorter output,
// we can hash that secret into a 32 byte hash before proceeding to the XOR step.
//
// Mixing with XOR (A = B ^ C) is fine since nothing about A is revealed even if one of B or C
// is known. Both B *and* C must be known to compute any bit in A. This means all involved
// KEM algorithms must be broken before the PSK can be computed by an attacker.
rpc PskExchangeV1(PskRequestV1) returns (PskResponseV1) {}
}
message PskRequestV1 {
bytes wg_pubkey = 1;
bytes wg_psk_pubkey = 2;
repeated KemPubkeyV1 kem_pubkeys = 3;
}
message KemPubkeyV1 {
string algorithm_name = 1;
bytes key_data = 2;
}
message PskResponseV1 { repeated bytes ciphertexts = 1; }