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.
17 * ======== wg_cookie.h ========
19 * This file provides a thread safe interface to the WireGuard cookie
20 * mechanism. It is split into three parts:
23 * Used to create MACs for messages.
25 * Used to validate MACs for messages.
27 * The MACs that authenticate the message.
29 * The MACs provide two properties:
30 * * mac1 - That the remote end knows a value.
31 * * mac2 - That the remote end has a specific IP address.
33 * void cookie_maker_init(cookie_maker, ipl, input)
34 * - Initialise cookie_maker, should only be called once and before use.
35 * input is the shared value used for mac1.
37 * int cookie_checker_init(cookie_checker, ipl)
38 * - Initialise cookie_checker, should only be called once and before use. It
39 * will return ENOBUFS if it cannot allocate required memory.
41 * void cookie_checker_update(cookie_checker, input)
42 * - Set the input value to check mac1 against.
44 * void cookie_checker_deinit(cookie_checker)
45 * - Destroy all values associated with cookie_checker. cookie_checker must
46 * not be used after calling this function.
48 * void cookie_checker_create_payload(cookie_checker, cookie_macs, nonce,
50 * - Create a specific payload derived from the sockaddr. The payload is an
51 * encrypted shared secret, that the cookie_maker will decrypt and used to
54 * int cookie_maker_consume_payload(cookie_maker, nonce, payload)
55 * - Have cookie_maker consume the payload.
57 * void cookie_maker_mac(cookie_maker, cookie_macs, message, len)
58 * - Create cookie_macs for the message of length len. It will always compute
59 * mac1, however will only compute mac2 if we have recently received a
60 * payload to key it with.
62 * int cookie_checker_validate_macs(cookie_checker, cookie_macs, message, len,
64 * - Use cookie_checker to validate the cookie_macs of message with length
65 * len. If busy, then ratelimiting will be applied to the sockaddr.
67 * ==========================
74 #include <sys/types.h>
76 #include <sys/rwlock.h>
77 #include <sys/queue.h>
78 #include <sys/support.h>
80 #include <netinet/in.h>
82 #include <crypto/blake2s.h>
84 #define COOKIE_MAC_SIZE 16
85 #define COOKIE_KEY_SIZE 32
86 #define COOKIE_XNONCE_SIZE 24
87 #define COOKIE_COOKIE_SIZE 16
88 #define COOKIE_SECRET_SIZE 32
89 #define COOKIE_INPUT_SIZE 32
90 #define COOKIE_ENCRYPTED_SIZE (COOKIE_COOKIE_SIZE + COOKIE_MAC_SIZE)
92 #define COOKIE_MAC1_KEY_LABEL "mac1----"
93 #define COOKIE_COOKIE_KEY_LABEL "cookie--"
94 #define COOKIE_SECRET_MAX_AGE 120
95 #define COOKIE_SECRET_LATENCY 5
97 /* Constants for initiation rate limiting */
98 #define RATELIMIT_SIZE (1 << 10)
99 #define RATELIMIT_SIZE_MAX (RATELIMIT_SIZE * 8)
100 #define NSEC_PER_SEC 1000000000LL
101 #define INITIATIONS_PER_SECOND 50
102 #define INITIATIONS_BURSTABLE 10
103 #define INITIATION_COST (NSEC_PER_SEC / INITIATIONS_PER_SECOND)
104 #define TOKEN_MAX (INITIATION_COST * INITIATIONS_BURSTABLE)
105 #define ELEMENT_TIMEOUT 1
106 #define IPV4_MASK_SIZE 4 /* Use all 4 bytes of IPv4 address */
107 #define IPV6_MASK_SIZE 8 /* Use top 8 bytes (/64) of IPv6 address */
110 uint8_t mac1[COOKIE_MAC_SIZE];
111 uint8_t mac2[COOKIE_MAC_SIZE];
114 struct ratelimit_entry {
115 LIST_ENTRY(ratelimit_entry) r_entry;
119 struct in6_addr r_in6;
121 struct timespec r_last_time; /* nanouptime */
126 SIPHASH_KEY rl_secret;
129 struct rwlock rl_lock;
130 LIST_HEAD(, ratelimit_entry) *rl_table;
131 u_long rl_table_mask;
133 struct timespec rl_last_gc; /* nanouptime */
136 struct cookie_maker {
137 uint8_t cp_mac1_key[COOKIE_KEY_SIZE];
138 uint8_t cp_cookie_key[COOKIE_KEY_SIZE];
140 struct rwlock cp_lock;
141 uint8_t cp_cookie[COOKIE_COOKIE_SIZE];
142 struct timespec cp_birthdate; /* nanouptime */
144 uint8_t cp_mac1_last[COOKIE_MAC_SIZE];
147 struct cookie_checker {
148 struct ratelimit cc_ratelimit;
150 struct rwlock cc_key_lock;
151 uint8_t cc_mac1_key[COOKIE_KEY_SIZE];
152 uint8_t cc_cookie_key[COOKIE_KEY_SIZE];
154 struct rwlock cc_secret_lock;
155 struct timespec cc_secret_birthdate; /* nanouptime */
156 uint8_t cc_secret[COOKIE_SECRET_SIZE];
159 void cookie_maker_init(struct cookie_maker *, const uint8_t[COOKIE_INPUT_SIZE]);
160 int cookie_checker_init(struct cookie_checker *, uma_zone_t);
161 void cookie_checker_update(struct cookie_checker *,
162 uint8_t[COOKIE_INPUT_SIZE]);
163 void cookie_checker_deinit(struct cookie_checker *);
164 void cookie_checker_create_payload(struct cookie_checker *,
165 struct cookie_macs *cm, uint8_t[COOKIE_XNONCE_SIZE],
166 uint8_t [COOKIE_ENCRYPTED_SIZE], struct sockaddr *);
167 int cookie_maker_consume_payload(struct cookie_maker *,
168 uint8_t[COOKIE_XNONCE_SIZE], uint8_t[COOKIE_ENCRYPTED_SIZE]);
169 void cookie_maker_mac(struct cookie_maker *, struct cookie_macs *,
171 int cookie_checker_validate_macs(struct cookie_checker *,
172 struct cookie_macs *, void *, size_t, int, struct sockaddr *);
174 #endif /* __COOKIE_H__ */