]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/if_wg/include/sys/wg_cookie.h
service(8): use an environment more consistent with init(8)
[FreeBSD/FreeBSD.git] / sys / dev / if_wg / include / sys / wg_cookie.h
1 /*
2  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
3  * Copyright (C) 2019-2020 Matt Dunwoodie <ncon@noconroy.net>
4  *
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.
8  *
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.
16  *
17  * ======== wg_cookie.h ========
18  *
19  * This file provides a thread safe interface to the WireGuard cookie
20  * mechanism. It is split into three parts:
21  *
22  *    * cookie_maker
23  *            Used to create MACs for messages.
24  *    * cookie_checker
25  *            Used to validate MACs for messages.
26  *    * cookie_macs
27  *            The MACs that authenticate the message.
28  *
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.
32  *
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.
36  *
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.
40  *
41  * void cookie_checker_update(cookie_checker, input)
42  *   - Set the input value to check mac1 against.
43  *
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.
47  *
48  * void cookie_checker_create_payload(cookie_checker, cookie_macs, nonce,
49  *         payload, sockaddr)
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
52  *     key the mac2 value.
53  *
54  * int  cookie_maker_consume_payload(cookie_maker, nonce, payload)
55  *   - Have cookie_maker consume the payload.
56  *
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.
61  *
62  * int  cookie_checker_validate_macs(cookie_checker, cookie_macs, message, len,
63  *         busy, sockaddr)
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.
66  *
67  * ==========================
68  * $FreeBSD$
69  */
70
71 #ifndef __COOKIE_H__
72 #define __COOKIE_H__
73
74 #include <sys/types.h>
75 #include <sys/time.h>
76 #include <sys/rwlock.h>
77 #include <sys/queue.h>
78 #include <sys/support.h>
79
80 #include <netinet/in.h>
81
82 #include <crypto/blake2s.h>
83
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)
91
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
96
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 */
108
109 struct cookie_macs {
110         uint8_t mac1[COOKIE_MAC_SIZE];
111         uint8_t mac2[COOKIE_MAC_SIZE];
112 } __packed;
113
114 struct ratelimit_entry {
115         LIST_ENTRY(ratelimit_entry)      r_entry;
116         sa_family_t                      r_af;
117         union {
118                 struct in_addr           r_in;
119                 struct in6_addr          r_in6;
120         };
121         struct timespec                  r_last_time;   /* nanouptime */
122         uint64_t                         r_tokens;
123 };
124
125 struct ratelimit {
126         SIPHASH_KEY                      rl_secret;
127         uma_zone_t                      rl_zone;
128
129         struct rwlock                    rl_lock;
130         LIST_HEAD(, ratelimit_entry)    *rl_table;
131         u_long                           rl_table_mask;
132         size_t                           rl_table_num;
133         struct timespec                  rl_last_gc;    /* nanouptime */
134 };
135
136 struct cookie_maker {
137         uint8_t         cp_mac1_key[COOKIE_KEY_SIZE];
138         uint8_t         cp_cookie_key[COOKIE_KEY_SIZE];
139
140         struct rwlock   cp_lock;
141         uint8_t         cp_cookie[COOKIE_COOKIE_SIZE];
142         struct timespec cp_birthdate;   /* nanouptime */
143         int             cp_mac1_valid;
144         uint8_t         cp_mac1_last[COOKIE_MAC_SIZE];
145 };
146
147 struct cookie_checker {
148         struct ratelimit        cc_ratelimit;
149
150         struct rwlock           cc_key_lock;
151         uint8_t                 cc_mac1_key[COOKIE_KEY_SIZE];
152         uint8_t                 cc_cookie_key[COOKIE_KEY_SIZE];
153
154         struct rwlock           cc_secret_lock;
155         struct timespec         cc_secret_birthdate;    /* nanouptime */
156         uint8_t                 cc_secret[COOKIE_SECRET_SIZE];
157 };
158
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 *,
170             void *, size_t);
171 int     cookie_checker_validate_macs(struct cookie_checker *,
172             struct cookie_macs *, void *, size_t, int, struct sockaddr *);
173
174 #endif /* __COOKIE_H__ */