wireguard: initial implementation of wireguard protocol
[vpp.git] / src / plugins / wireguard / wireguard_noise.h
1 /*
2  * Copyright (c) 2020 Doc.ai and/or its affiliates.
3  * Copyright (c) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>.
4  * Copyright (c) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>.
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at:
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 #ifndef __included_wg_noise_h__
19 #define __included_wg_noise_h__
20
21 #include <vlib/vlib.h>
22 #include <vnet/crypto/crypto.h>
23 #include <wireguard/blake/blake2s.h>
24 #include <wireguard/wireguard_key.h>
25
26 #define NOISE_PUBLIC_KEY_LEN    CURVE25519_KEY_SIZE
27 #define NOISE_SYMMETRIC_KEY_LEN   32    // CHACHA20POLY1305_KEY_SIZE
28 #define NOISE_TIMESTAMP_LEN     (sizeof(uint64_t) + sizeof(uint32_t))
29 #define NOISE_AUTHTAG_LEN       16      //CHACHA20POLY1305_AUTHTAG_SIZE
30 #define NOISE_HASH_LEN          BLAKE2S_HASH_SIZE
31
32 /* Protocol string constants */
33 #define NOISE_HANDSHAKE_NAME    "Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s"
34 #define NOISE_IDENTIFIER_NAME   "WireGuard v1 zx2c4 Jason@zx2c4.com"
35
36 /* Constants for the counter */
37 #define COUNTER_BITS_TOTAL      8192
38 #define COUNTER_BITS            (sizeof(unsigned long) * 8)
39 #define COUNTER_NUM             (COUNTER_BITS_TOTAL / COUNTER_BITS)
40 #define COUNTER_WINDOW_SIZE     (COUNTER_BITS_TOTAL - COUNTER_BITS)
41
42 /* Constants for the keypair */
43 #define REKEY_AFTER_MESSAGES    (1ull << 60)
44 #define REJECT_AFTER_MESSAGES   (UINT64_MAX - COUNTER_WINDOW_SIZE - 1)
45 #define REKEY_AFTER_TIME        120
46 #define REKEY_AFTER_TIME_RECV   165
47 #define REJECT_AFTER_TIME       180
48 #define REJECT_INTERVAL         (0.02)  /* fifty times per sec */
49 /* 24 = floor(log2(REJECT_INTERVAL)) */
50 #define REJECT_INTERVAL_MASK    (~((1ull<<24)-1))
51
52 enum noise_state_crypt
53 {
54   SC_OK = 0,
55   SC_CONN_RESET,
56   SC_KEEP_KEY_FRESH,
57   SC_FAILED,
58 };
59
60 enum noise_state_hs
61 {
62   HS_ZEROED = 0,
63   CREATED_INITIATION,
64   CONSUMED_INITIATION,
65   CREATED_RESPONSE,
66   CONSUMED_RESPONSE,
67 };
68
69 typedef struct noise_handshake
70 {
71   enum noise_state_hs hs_state;
72   uint32_t hs_local_index;
73   uint32_t hs_remote_index;
74   uint8_t hs_e[NOISE_PUBLIC_KEY_LEN];
75   uint8_t hs_hash[NOISE_HASH_LEN];
76   uint8_t hs_ck[NOISE_HASH_LEN];
77 } noise_handshake_t;
78
79 typedef struct noise_counter
80 {
81   uint64_t c_send;
82   uint64_t c_recv;
83   unsigned long c_backtrack[COUNTER_NUM];
84 } noise_counter_t;
85
86 typedef struct noise_keypair
87 {
88   int kp_valid;
89   int kp_is_initiator;
90   uint32_t kp_local_index;
91   uint32_t kp_remote_index;
92   vnet_crypto_key_index_t kp_send_index;
93   vnet_crypto_key_index_t kp_recv_index;
94   f64 kp_birthdate;
95   noise_counter_t kp_ctr;
96 } noise_keypair_t;
97
98 typedef struct noise_local noise_local_t;
99 typedef struct noise_remote
100 {
101   uint32_t r_peer_idx;
102   uint8_t r_public[NOISE_PUBLIC_KEY_LEN];
103   noise_local_t *r_local;
104   uint8_t r_ss[NOISE_PUBLIC_KEY_LEN];
105
106   noise_handshake_t r_handshake;
107   uint8_t r_psk[NOISE_SYMMETRIC_KEY_LEN];
108   uint8_t r_timestamp[NOISE_TIMESTAMP_LEN];
109   f64 r_last_init;
110
111   noise_keypair_t *r_next, *r_current, *r_previous;
112 } noise_remote_t;
113
114 typedef struct noise_local
115 {
116   bool l_has_identity;
117   uint8_t l_public[NOISE_PUBLIC_KEY_LEN];
118   uint8_t l_private[NOISE_PUBLIC_KEY_LEN];
119
120   struct noise_upcall
121   {
122     void *u_arg;
123     noise_remote_t *(*u_remote_get) (uint8_t[NOISE_PUBLIC_KEY_LEN]);
124       uint32_t (*u_index_set) (noise_remote_t *);
125     void (*u_index_drop) (uint32_t);
126   } l_upcall;
127 } noise_local_t;
128
129 /* Set/Get noise parameters */
130 void noise_local_init (noise_local_t *, struct noise_upcall *);
131 bool noise_local_set_private (noise_local_t *,
132                               const uint8_t[NOISE_PUBLIC_KEY_LEN]);
133 bool noise_local_keys (noise_local_t *, uint8_t[NOISE_PUBLIC_KEY_LEN],
134                        uint8_t[NOISE_PUBLIC_KEY_LEN]);
135
136 void noise_remote_init (noise_remote_t *, uint32_t,
137                         const uint8_t[NOISE_PUBLIC_KEY_LEN], noise_local_t *);
138 bool noise_remote_set_psk (noise_remote_t *,
139                            uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
140 bool noise_remote_keys (noise_remote_t *, uint8_t[NOISE_PUBLIC_KEY_LEN],
141                         uint8_t[NOISE_SYMMETRIC_KEY_LEN]);
142
143 /* Should be called anytime noise_local_set_private is called */
144 void noise_remote_precompute (noise_remote_t *);
145
146 /* Cryptographic functions */
147 bool noise_create_initiation (vlib_main_t * vm, noise_remote_t *,
148                               uint32_t * s_idx,
149                               uint8_t ue[NOISE_PUBLIC_KEY_LEN],
150                               uint8_t es[NOISE_PUBLIC_KEY_LEN +
151                                          NOISE_AUTHTAG_LEN],
152                               uint8_t ets[NOISE_TIMESTAMP_LEN +
153                                           NOISE_AUTHTAG_LEN]);
154
155 bool noise_consume_initiation (vlib_main_t * vm, noise_local_t *,
156                                noise_remote_t **,
157                                uint32_t s_idx,
158                                uint8_t ue[NOISE_PUBLIC_KEY_LEN],
159                                uint8_t es[NOISE_PUBLIC_KEY_LEN +
160                                           NOISE_AUTHTAG_LEN],
161                                uint8_t ets[NOISE_TIMESTAMP_LEN +
162                                            NOISE_AUTHTAG_LEN]);
163
164 bool noise_create_response (vlib_main_t * vm, noise_remote_t *,
165                             uint32_t * s_idx,
166                             uint32_t * r_idx,
167                             uint8_t ue[NOISE_PUBLIC_KEY_LEN],
168                             uint8_t en[0 + NOISE_AUTHTAG_LEN]);
169
170 bool noise_consume_response (vlib_main_t * vm, noise_remote_t *,
171                              uint32_t s_idx,
172                              uint32_t r_idx,
173                              uint8_t ue[NOISE_PUBLIC_KEY_LEN],
174                              uint8_t en[0 + NOISE_AUTHTAG_LEN]);
175
176 bool noise_remote_begin_session (vlib_main_t * vm, noise_remote_t * r);
177 void noise_remote_clear (vlib_main_t * vm, noise_remote_t * r);
178 void noise_remote_expire_current (noise_remote_t * r);
179
180 bool noise_remote_ready (noise_remote_t *);
181
182 enum noise_state_crypt
183 noise_remote_encrypt (vlib_main_t * vm, noise_remote_t *,
184                       uint32_t * r_idx,
185                       uint64_t * nonce,
186                       uint8_t * src, size_t srclen, uint8_t * dst);
187 enum noise_state_crypt
188 noise_remote_decrypt (vlib_main_t * vm, noise_remote_t *,
189                       uint32_t r_idx,
190                       uint64_t nonce,
191                       uint8_t * src, size_t srclen, uint8_t * dst);
192
193
194 #endif /* __included_wg_noise_h__ */
195
196 /*
197  * fd.io coding-style-patch-verification: ON
198  *
199  * Local Variables:
200  * eval: (c-set-style "gnu")
201  * End:
202  */