2 * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
3 * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 #include <sys/cdefs.h>
19 __FBSDID("$FreeBSD$");
21 #include <sys/types.h>
22 #include <sys/systm.h>
23 #include <sys/param.h>
24 #include <sys/rwlock.h>
25 #include <sys/malloc.h> /* Because systm doesn't include M_NOWAIT, M_DEVBUF */
26 #include <sys/socket.h>
28 #include <sys/wg_cookie.h>
29 #include <zinc/chacha20poly1305.h>
31 static void cookie_precompute_key(uint8_t *,
32 const uint8_t[COOKIE_INPUT_SIZE], const char *);
33 static void cookie_macs_mac1(struct cookie_macs *, const void *, size_t,
34 const uint8_t[COOKIE_KEY_SIZE]);
35 static void cookie_macs_mac2(struct cookie_macs *, const void *, size_t,
36 const uint8_t[COOKIE_COOKIE_SIZE]);
37 static int cookie_timer_expired(struct timespec *, time_t, long);
38 static void cookie_checker_make_cookie(struct cookie_checker *,
39 uint8_t[COOKIE_COOKIE_SIZE], struct sockaddr *);
40 static void ratelimit_gc(struct ratelimit *, int);
41 static int ratelimit_allow(struct ratelimit *, struct sockaddr *);
43 /* Public Functions */
45 cookie_maker_init(struct cookie_maker *cp, const uint8_t key[COOKIE_INPUT_SIZE])
47 bzero(cp, sizeof(*cp));
48 cookie_precompute_key(cp->cp_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
49 cookie_precompute_key(cp->cp_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
50 rw_init(&cp->cp_lock, "cookie_maker");
54 cookie_checker_init(struct cookie_checker *cc, uma_zone_t zone)
56 struct ratelimit *rl = &cc->cc_ratelimit;
57 bzero(cc, sizeof(*cc));
59 rw_init(&cc->cc_key_lock, "cookie_checker_key");
60 rw_init(&cc->cc_secret_lock, "cookie_checker_secret");
62 rw_init(&rl->rl_lock, "ratelimit_lock");
63 arc4random_buf(&rl->rl_secret, sizeof(rl->rl_secret));
64 rl->rl_table = hashinit(RATELIMIT_SIZE, M_DEVBUF, &rl->rl_table_mask);
71 cookie_checker_update(struct cookie_checker *cc,
72 uint8_t key[COOKIE_INPUT_SIZE])
74 rw_enter_write(&cc->cc_key_lock);
76 cookie_precompute_key(cc->cc_mac1_key, key, COOKIE_MAC1_KEY_LABEL);
77 cookie_precompute_key(cc->cc_cookie_key, key, COOKIE_COOKIE_KEY_LABEL);
79 bzero(cc->cc_mac1_key, sizeof(cc->cc_mac1_key));
80 bzero(cc->cc_cookie_key, sizeof(cc->cc_cookie_key));
82 rw_exit_write(&cc->cc_key_lock);
86 cookie_checker_deinit(struct cookie_checker *cc)
88 struct ratelimit *rl = &cc->cc_ratelimit;
90 rw_enter_write(&rl->rl_lock);
92 hashdestroy(rl->rl_table, M_DEVBUF, rl->rl_table_mask);
93 rw_exit_write(&rl->rl_lock);
97 cookie_checker_create_payload(struct cookie_checker *cc,
98 struct cookie_macs *cm, uint8_t nonce[COOKIE_XNONCE_SIZE],
99 uint8_t ecookie[COOKIE_ENCRYPTED_SIZE], struct sockaddr *sa)
101 uint8_t cookie[COOKIE_COOKIE_SIZE];
103 cookie_checker_make_cookie(cc, cookie, sa);
104 arc4random_buf(nonce, COOKIE_XNONCE_SIZE);
106 rw_enter_read(&cc->cc_key_lock);
107 xchacha20poly1305_encrypt(ecookie, cookie, COOKIE_COOKIE_SIZE,
108 cm->mac1, COOKIE_MAC_SIZE, nonce, cc->cc_cookie_key);
109 rw_exit_read(&cc->cc_key_lock);
111 explicit_bzero(cookie, sizeof(cookie));
115 cookie_maker_consume_payload(struct cookie_maker *cp,
116 uint8_t nonce[COOKIE_XNONCE_SIZE], uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])
119 uint8_t cookie[COOKIE_COOKIE_SIZE];
121 rw_enter_write(&cp->cp_lock);
123 if (cp->cp_mac1_valid == 0) {
128 if (xchacha20poly1305_decrypt(cookie, ecookie, COOKIE_ENCRYPTED_SIZE,
129 cp->cp_mac1_last, COOKIE_MAC_SIZE, nonce, cp->cp_cookie_key) == 0) {
134 memcpy(cp->cp_cookie, cookie, COOKIE_COOKIE_SIZE);
135 getnanouptime(&cp->cp_birthdate);
136 cp->cp_mac1_valid = 0;
139 rw_exit_write(&cp->cp_lock);
144 cookie_maker_mac(struct cookie_maker *cp, struct cookie_macs *cm, void *buf,
147 rw_enter_read(&cp->cp_lock);
149 cookie_macs_mac1(cm, buf, len, cp->cp_mac1_key);
151 memcpy(cp->cp_mac1_last, cm->mac1, COOKIE_MAC_SIZE);
152 cp->cp_mac1_valid = 1;
154 if (!cookie_timer_expired(&cp->cp_birthdate,
155 COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY, 0))
156 cookie_macs_mac2(cm, buf, len, cp->cp_cookie);
158 bzero(cm->mac2, COOKIE_MAC_SIZE);
160 rw_exit_read(&cp->cp_lock);
164 cookie_checker_validate_macs(struct cookie_checker *cc, struct cookie_macs *cm,
165 void *buf, size_t len, int busy, struct sockaddr *sa)
167 struct cookie_macs our_cm;
168 uint8_t cookie[COOKIE_COOKIE_SIZE];
170 /* Validate incoming MACs */
171 rw_enter_read(&cc->cc_key_lock);
172 cookie_macs_mac1(&our_cm, buf, len, cc->cc_mac1_key);
173 rw_exit_read(&cc->cc_key_lock);
175 /* If mac1 is invald, we want to drop the packet */
176 if (timingsafe_bcmp(our_cm.mac1, cm->mac1, COOKIE_MAC_SIZE) != 0)
180 cookie_checker_make_cookie(cc, cookie, sa);
181 cookie_macs_mac2(&our_cm, buf, len, cookie);
183 /* If the mac2 is invalid, we want to send a cookie response */
184 if (timingsafe_bcmp(our_cm.mac2, cm->mac2, COOKIE_MAC_SIZE) != 0)
187 /* If the mac2 is valid, we may want rate limit the peer.
188 * ratelimit_allow will return either 0 or ECONNREFUSED,
189 * implying there is no ratelimiting, or we should ratelimit
190 * (refuse) respectively. */
191 return ratelimit_allow(&cc->cc_ratelimit, sa);
196 /* Private functions */
198 cookie_precompute_key(uint8_t *key, const uint8_t input[COOKIE_INPUT_SIZE],
201 struct blake2s_state blake;
203 blake2s_init(&blake, COOKIE_KEY_SIZE);
204 blake2s_update(&blake, label, strlen(label));
205 blake2s_update(&blake, input, COOKIE_INPUT_SIZE);
206 blake2s_final(&blake, key, COOKIE_KEY_SIZE);
210 cookie_macs_mac1(struct cookie_macs *cm, const void *buf, size_t len,
211 const uint8_t key[COOKIE_KEY_SIZE])
213 struct blake2s_state state;
214 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_KEY_SIZE);
215 blake2s_update(&state, buf, len);
216 blake2s_final(&state, cm->mac1, COOKIE_MAC_SIZE);
220 cookie_macs_mac2(struct cookie_macs *cm, const void *buf, size_t len,
221 const uint8_t key[COOKIE_COOKIE_SIZE])
223 struct blake2s_state state;
224 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_COOKIE_SIZE);
225 blake2s_update(&state, buf, len);
226 blake2s_update(&state, cm->mac1, COOKIE_MAC_SIZE);
227 blake2s_final(&state, cm->mac2, COOKIE_MAC_SIZE);
231 cookie_timer_expired(struct timespec *birthdate, time_t sec, long nsec)
233 struct timespec uptime;
234 struct timespec expire = { .tv_sec = sec, .tv_nsec = nsec };
236 if (birthdate->tv_sec == 0 && birthdate->tv_nsec == 0)
239 getnanouptime(&uptime);
240 timespecadd(birthdate, &expire, &expire);
241 return timespeccmp(&uptime, &expire, >) ? ETIMEDOUT : 0;
245 cookie_checker_make_cookie(struct cookie_checker *cc,
246 uint8_t cookie[COOKIE_COOKIE_SIZE], struct sockaddr *sa)
248 struct blake2s_state state;
250 rw_enter_write(&cc->cc_secret_lock);
251 if (cookie_timer_expired(&cc->cc_secret_birthdate,
252 COOKIE_SECRET_MAX_AGE, 0)) {
253 arc4random_buf(cc->cc_secret, COOKIE_SECRET_SIZE);
254 getnanouptime(&cc->cc_secret_birthdate);
256 blake2s_init_key(&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
258 rw_exit_write(&cc->cc_secret_lock);
260 if (sa->sa_family == AF_INET) {
261 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_addr,
262 sizeof(struct in_addr));
263 blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port,
265 blake2s_final(&state, cookie, COOKIE_COOKIE_SIZE);
266 } else if (sa->sa_family == AF_INET6) {
267 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_addr,
268 sizeof(struct in6_addr));
269 blake2s_update(&state, (uint8_t *)&satosin6(sa)->sin6_port,
271 blake2s_final(&state, cookie, COOKIE_COOKIE_SIZE);
273 arc4random_buf(cookie, COOKIE_COOKIE_SIZE);
278 ratelimit_gc(struct ratelimit *rl, int force)
281 struct ratelimit_entry *r, *tr;
282 struct timespec expiry;
284 rw_assert(&rl->rl_lock, RA_WLOCKED);
287 for (i = 0; i < RATELIMIT_SIZE; i++) {
288 LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) {
290 LIST_REMOVE(r, r_entry);
291 uma_zfree(rl->rl_zone, r);
297 if ((cookie_timer_expired(&rl->rl_last_gc, ELEMENT_TIMEOUT, 0) &&
298 rl->rl_table_num > 0)) {
299 getnanouptime(&rl->rl_last_gc);
300 getnanouptime(&expiry);
301 expiry.tv_sec -= ELEMENT_TIMEOUT;
303 for (i = 0; i < RATELIMIT_SIZE; i++) {
304 LIST_FOREACH_SAFE(r, &rl->rl_table[i], r_entry, tr) {
305 if (timespeccmp(&r->r_last_time, &expiry, <)) {
307 LIST_REMOVE(r, r_entry);
308 uma_zfree(rl->rl_zone, r);
316 ratelimit_allow(struct ratelimit *rl, struct sockaddr *sa)
318 uint64_t key, tokens;
319 struct timespec diff;
320 struct ratelimit_entry *r;
321 int ret = ECONNREFUSED;
323 if (sa->sa_family == AF_INET)
324 key = siphash24(&rl->rl_secret, &satosin(sa)->sin_addr,
326 else if (sa->sa_family == AF_INET6)
327 key = siphash24(&rl->rl_secret, &satosin6(sa)->sin6_addr,
332 rw_enter_write(&rl->rl_lock);
334 LIST_FOREACH(r, &rl->rl_table[key & rl->rl_table_mask], r_entry) {
335 if (r->r_af != sa->sa_family)
338 if (r->r_af == AF_INET && bcmp(&r->r_in,
339 &satosin(sa)->sin_addr, IPV4_MASK_SIZE) != 0)
342 if (r->r_af == AF_INET6 && bcmp(&r->r_in6,
343 &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE) != 0)
346 /* If we get to here, we've found an entry for the endpoint.
347 * We apply standard token bucket, by calculating the time
348 * lapsed since our last_time, adding that, ensuring that we
349 * cap the tokens at TOKEN_MAX. If the endpoint has no tokens
350 * left (that is tokens <= INITIATION_COST) then we block the
351 * request, otherwise we subtract the INITITIATION_COST and
353 diff = r->r_last_time;
354 getnanouptime(&r->r_last_time);
355 timespecsub(&r->r_last_time, &diff, &diff);
357 tokens = r->r_tokens + diff.tv_sec * NSEC_PER_SEC + diff.tv_nsec;
359 if (tokens > TOKEN_MAX)
362 if (tokens > INITIATION_COST) {
363 r->r_tokens = tokens - INITIATION_COST;
366 r->r_tokens = tokens;
371 /* If we get to here, we didn't have an entry for the endpoint. */
374 /* Hard limit on number of entries */
375 if (rl->rl_table_num >= RATELIMIT_SIZE_MAX * 8)
378 /* Goto error if out of memory */
379 if ((r = uma_zalloc(rl->rl_zone, M_NOWAIT)) == NULL)
384 /* Insert entry into the hashtable and ensure it's initialised */
385 LIST_INSERT_HEAD(&rl->rl_table[key & rl->rl_table_mask], r, r_entry);
386 r->r_af = sa->sa_family;
387 if (r->r_af == AF_INET)
388 memcpy(&r->r_in, &satosin(sa)->sin_addr, IPV4_MASK_SIZE);
389 else if (r->r_af == AF_INET6)
390 memcpy(&r->r_in6, &satosin6(sa)->sin6_addr, IPV6_MASK_SIZE);
392 getnanouptime(&r->r_last_time);
393 r->r_tokens = TOKEN_MAX - INITIATION_COST;
397 rw_exit_write(&rl->rl_lock);