-
Notifications
You must be signed in to change notification settings - Fork 384
/
Copy pathephemeralpeer.proto
124 lines (110 loc) · 4.88 KB
/
ephemeralpeer.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
syntax = "proto3";
option go_package = "github.com/mullvad/wg-manager/tuncfg/api/ephemeralpeer";
package ephemeralpeer;
service EphemeralPeer {
// Derive an ephemeral peer with one or several options enabled, such as PQ or DAITA.
//
// The VPN server associates the ephemeral peer with the peer who performed the exchange. Any
// already existing ephemeral peer for the normal peer is replaced. Each normal peer can have
// at most one ephemeral peer.
//
// The ephemeral 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 ephemeral peer from WireGuard and vice versa.
//
// A new peer is negotiated to avoid a premature break of the tunnel used for negotiation.
// A tunnel would break prematurely if configuration such as preshared key were applied before the
// normal peer received the server's response. This cannot occur now because the client decides
// when to switch to the ephemeral tunnel. This design also allows the client to switch back to
// using a non-ephemeral tunnel at any point.
//
// The server gives no guarantees how long the ephemeral peer will be valid and working when it's
// no longer in use. The client should negotiate a new ephemeral peer every time it establishes a
// new tunnel to the server.
//
// The request from the VPN client should contain:
// * `wg_parent_pubkey` - The public key used by the current tunnel (that the request travels
// inside).
// * `wg_ephemeral_peer_pubkey` - A newly generated ephemeral WireGuard public key for the
// ephemeral peer. The server will associate the new configuration with this key.
// * One or more requests for different types of options. See the individual messages for more
// information. If a request is provided, a corresponding response may be returned in the
// server's response.
rpc RegisterPeerV1(EphemeralPeerRequestV1) returns (EphemeralPeerResponseV1) {}
}
message EphemeralPeerRequestV1 {
bytes wg_parent_pubkey = 1;
bytes wg_ephemeral_peer_pubkey = 2;
PostQuantumRequestV1 post_quantum = 3;
DaitaRequestV1 daita = 4;
DaitaRequestV2 daita_v2 = 5;
}
// The v1 request supports these three algorithms.
// The algorithms can appear soletary or mixed. Kyber1024 and ML-KEM-1024 cannot be used in the
// same request as they are just different versions of the same kem.
// - "Classic-McEliece-460896f", but explicitly identified as "Classic-McEliece-460896f-round3"
// - "Kyber1024", this is round3 of the Kyber KEM
// - "ML-KEM-1024". This is the standardized version of ML-KEM (FIPS 203) at the highest strength
message PostQuantumRequestV1 { repeated KemPubkeyV1 kem_pubkeys = 1; }
message KemPubkeyV1 {
string algorithm_name = 1;
bytes key_data = 2;
}
message DaitaRequestV1 { bool activate_daita = 1; }
enum DaitaPlatform {
undefined = 0;
windows_native = 1;
linux_wg_go = 2;
macos_wg_go = 3;
ios_wg_go = 4;
android_wg_go = 5;
windows_wg_go = 6;
}
enum DaitaLevel {
level_default = 0;
level_1 = 1;
level_2 = 2;
level_3 = 3;
level_4 = 4;
level_5 = 5;
level_6 = 6;
level_7 = 7;
level_8 = 8;
level_9 = 9;
level_10 = 10;
}
message DaitaRequestV2 {
uint32 version = 1;
DaitaPlatform platform = 2;
DaitaLevel level = 3;
}
message DaitaResponseV2 {
repeated string client_machines = 1;
double max_padding_frac = 2;
double max_blocking_frac = 3;
}
message EphemeralPeerResponseV1 {
// 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.
//
// 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.
PostQuantumResponseV1 post_quantum = 1;
DaitaResponseV2 daita = 2;
}
message PostQuantumResponseV1 { repeated bytes ciphertexts = 1; }