1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. |
4 | */ |
5 | |
6 | #include "cookie.h" |
7 | #include "peer.h" |
8 | #include "device.h" |
9 | #include "messages.h" |
10 | #include "ratelimiter.h" |
11 | #include "timers.h" |
12 | |
13 | #include <crypto/blake2s.h> |
14 | #include <crypto/chacha20poly1305.h> |
15 | #include <crypto/utils.h> |
16 | |
17 | #include <net/ipv6.h> |
18 | |
19 | void wg_cookie_checker_init(struct cookie_checker *checker, |
20 | struct wg_device *wg) |
21 | { |
22 | init_rwsem(&checker->secret_lock); |
23 | checker->secret_birthdate = ktime_get_coarse_boottime_ns(); |
24 | get_random_bytes(buf: checker->secret, len: NOISE_HASH_LEN); |
25 | checker->device = wg; |
26 | } |
27 | |
28 | enum { COOKIE_KEY_LABEL_LEN = 8 }; |
29 | static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----" ; |
30 | static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--" ; |
31 | |
32 | static void precompute_key(u8 key[NOISE_SYMMETRIC_KEY_LEN], |
33 | const u8 pubkey[NOISE_PUBLIC_KEY_LEN], |
34 | const u8 label[COOKIE_KEY_LABEL_LEN]) |
35 | { |
36 | struct blake2s_state blake; |
37 | |
38 | blake2s_init(state: &blake, outlen: NOISE_SYMMETRIC_KEY_LEN); |
39 | blake2s_update(state: &blake, in: label, inlen: COOKIE_KEY_LABEL_LEN); |
40 | blake2s_update(state: &blake, in: pubkey, inlen: NOISE_PUBLIC_KEY_LEN); |
41 | blake2s_final(state: &blake, out: key); |
42 | } |
43 | |
44 | /* Must hold peer->handshake.static_identity->lock */ |
45 | void wg_cookie_checker_precompute_device_keys(struct cookie_checker *checker) |
46 | { |
47 | if (likely(checker->device->static_identity.has_identity)) { |
48 | precompute_key(key: checker->cookie_encryption_key, |
49 | pubkey: checker->device->static_identity.static_public, |
50 | label: cookie_key_label); |
51 | precompute_key(key: checker->message_mac1_key, |
52 | pubkey: checker->device->static_identity.static_public, |
53 | label: mac1_key_label); |
54 | } else { |
55 | memset(checker->cookie_encryption_key, 0, |
56 | NOISE_SYMMETRIC_KEY_LEN); |
57 | memset(checker->message_mac1_key, 0, NOISE_SYMMETRIC_KEY_LEN); |
58 | } |
59 | } |
60 | |
61 | void wg_cookie_checker_precompute_peer_keys(struct wg_peer *peer) |
62 | { |
63 | precompute_key(key: peer->latest_cookie.cookie_decryption_key, |
64 | pubkey: peer->handshake.remote_static, label: cookie_key_label); |
65 | precompute_key(key: peer->latest_cookie.message_mac1_key, |
66 | pubkey: peer->handshake.remote_static, label: mac1_key_label); |
67 | } |
68 | |
69 | void wg_cookie_init(struct cookie *cookie) |
70 | { |
71 | memset(cookie, 0, sizeof(*cookie)); |
72 | init_rwsem(&cookie->lock); |
73 | } |
74 | |
75 | static void compute_mac1(u8 mac1[COOKIE_LEN], const void *message, size_t len, |
76 | const u8 key[NOISE_SYMMETRIC_KEY_LEN]) |
77 | { |
78 | len = len - sizeof(struct message_macs) + |
79 | offsetof(struct message_macs, mac1); |
80 | blake2s(out: mac1, in: message, key, outlen: COOKIE_LEN, inlen: len, keylen: NOISE_SYMMETRIC_KEY_LEN); |
81 | } |
82 | |
83 | static void compute_mac2(u8 mac2[COOKIE_LEN], const void *message, size_t len, |
84 | const u8 cookie[COOKIE_LEN]) |
85 | { |
86 | len = len - sizeof(struct message_macs) + |
87 | offsetof(struct message_macs, mac2); |
88 | blake2s(out: mac2, in: message, key: cookie, outlen: COOKIE_LEN, inlen: len, keylen: COOKIE_LEN); |
89 | } |
90 | |
91 | static void make_cookie(u8 cookie[COOKIE_LEN], struct sk_buff *skb, |
92 | struct cookie_checker *checker) |
93 | { |
94 | struct blake2s_state state; |
95 | |
96 | if (wg_birthdate_has_expired(birthday_nanoseconds: checker->secret_birthdate, |
97 | expiration_seconds: COOKIE_SECRET_MAX_AGE)) { |
98 | down_write(sem: &checker->secret_lock); |
99 | checker->secret_birthdate = ktime_get_coarse_boottime_ns(); |
100 | get_random_bytes(buf: checker->secret, len: NOISE_HASH_LEN); |
101 | up_write(sem: &checker->secret_lock); |
102 | } |
103 | |
104 | down_read(sem: &checker->secret_lock); |
105 | |
106 | blake2s_init_key(state: &state, outlen: COOKIE_LEN, key: checker->secret, keylen: NOISE_HASH_LEN); |
107 | if (skb->protocol == htons(ETH_P_IP)) |
108 | blake2s_update(state: &state, in: (u8 *)&ip_hdr(skb)->saddr, |
109 | inlen: sizeof(struct in_addr)); |
110 | else if (skb->protocol == htons(ETH_P_IPV6)) |
111 | blake2s_update(state: &state, in: (u8 *)&ipv6_hdr(skb)->saddr, |
112 | inlen: sizeof(struct in6_addr)); |
113 | blake2s_update(state: &state, in: (u8 *)&udp_hdr(skb)->source, inlen: sizeof(__be16)); |
114 | blake2s_final(state: &state, out: cookie); |
115 | |
116 | up_read(sem: &checker->secret_lock); |
117 | } |
118 | |
119 | enum cookie_mac_state wg_cookie_validate_packet(struct cookie_checker *checker, |
120 | struct sk_buff *skb, |
121 | bool check_cookie) |
122 | { |
123 | struct message_macs *macs = (struct message_macs *) |
124 | (skb->data + skb->len - sizeof(*macs)); |
125 | enum cookie_mac_state ret; |
126 | u8 computed_mac[COOKIE_LEN]; |
127 | u8 cookie[COOKIE_LEN]; |
128 | |
129 | ret = INVALID_MAC; |
130 | compute_mac1(mac1: computed_mac, message: skb->data, len: skb->len, |
131 | key: checker->message_mac1_key); |
132 | if (crypto_memneq(a: computed_mac, b: macs->mac1, size: COOKIE_LEN)) |
133 | goto out; |
134 | |
135 | ret = VALID_MAC_BUT_NO_COOKIE; |
136 | |
137 | if (!check_cookie) |
138 | goto out; |
139 | |
140 | make_cookie(cookie, skb, checker); |
141 | |
142 | compute_mac2(mac2: computed_mac, message: skb->data, len: skb->len, cookie); |
143 | if (crypto_memneq(a: computed_mac, b: macs->mac2, size: COOKIE_LEN)) |
144 | goto out; |
145 | |
146 | ret = VALID_MAC_WITH_COOKIE_BUT_RATELIMITED; |
147 | if (!wg_ratelimiter_allow(skb, net: dev_net(dev: checker->device->dev))) |
148 | goto out; |
149 | |
150 | ret = VALID_MAC_WITH_COOKIE; |
151 | |
152 | out: |
153 | return ret; |
154 | } |
155 | |
156 | void wg_cookie_add_mac_to_packet(void *message, size_t len, |
157 | struct wg_peer *peer) |
158 | { |
159 | struct message_macs *macs = (struct message_macs *) |
160 | ((u8 *)message + len - sizeof(*macs)); |
161 | |
162 | down_write(sem: &peer->latest_cookie.lock); |
163 | compute_mac1(mac1: macs->mac1, message, len, |
164 | key: peer->latest_cookie.message_mac1_key); |
165 | memcpy(peer->latest_cookie.last_mac1_sent, macs->mac1, COOKIE_LEN); |
166 | peer->latest_cookie.have_sent_mac1 = true; |
167 | up_write(sem: &peer->latest_cookie.lock); |
168 | |
169 | down_read(sem: &peer->latest_cookie.lock); |
170 | if (peer->latest_cookie.is_valid && |
171 | !wg_birthdate_has_expired(birthday_nanoseconds: peer->latest_cookie.birthdate, |
172 | expiration_seconds: COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY)) |
173 | compute_mac2(mac2: macs->mac2, message, len, |
174 | cookie: peer->latest_cookie.cookie); |
175 | else |
176 | memset(macs->mac2, 0, COOKIE_LEN); |
177 | up_read(sem: &peer->latest_cookie.lock); |
178 | } |
179 | |
180 | void wg_cookie_message_create(struct message_handshake_cookie *dst, |
181 | struct sk_buff *skb, __le32 index, |
182 | struct cookie_checker *checker) |
183 | { |
184 | struct message_macs *macs = (struct message_macs *) |
185 | ((u8 *)skb->data + skb->len - sizeof(*macs)); |
186 | u8 cookie[COOKIE_LEN]; |
187 | |
188 | dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE); |
189 | dst->receiver_index = index; |
190 | get_random_bytes_wait(buf: dst->nonce, nbytes: COOKIE_NONCE_LEN); |
191 | |
192 | make_cookie(cookie, skb, checker); |
193 | xchacha20poly1305_encrypt(dst: dst->encrypted_cookie, src: cookie, src_len: COOKIE_LEN, |
194 | ad: macs->mac1, ad_len: COOKIE_LEN, nonce: dst->nonce, |
195 | key: checker->cookie_encryption_key); |
196 | } |
197 | |
198 | void wg_cookie_message_consume(struct message_handshake_cookie *src, |
199 | struct wg_device *wg) |
200 | { |
201 | struct wg_peer *peer = NULL; |
202 | u8 cookie[COOKIE_LEN]; |
203 | bool ret; |
204 | |
205 | if (unlikely(!wg_index_hashtable_lookup(wg->index_hashtable, |
206 | INDEX_HASHTABLE_HANDSHAKE | |
207 | INDEX_HASHTABLE_KEYPAIR, |
208 | src->receiver_index, &peer))) |
209 | return; |
210 | |
211 | down_read(sem: &peer->latest_cookie.lock); |
212 | if (unlikely(!peer->latest_cookie.have_sent_mac1)) { |
213 | up_read(sem: &peer->latest_cookie.lock); |
214 | goto out; |
215 | } |
216 | ret = xchacha20poly1305_decrypt( |
217 | dst: cookie, src: src->encrypted_cookie, src_len: sizeof(src->encrypted_cookie), |
218 | ad: peer->latest_cookie.last_mac1_sent, ad_len: COOKIE_LEN, nonce: src->nonce, |
219 | key: peer->latest_cookie.cookie_decryption_key); |
220 | up_read(sem: &peer->latest_cookie.lock); |
221 | |
222 | if (ret) { |
223 | down_write(sem: &peer->latest_cookie.lock); |
224 | memcpy(peer->latest_cookie.cookie, cookie, COOKIE_LEN); |
225 | peer->latest_cookie.birthdate = ktime_get_coarse_boottime_ns(); |
226 | peer->latest_cookie.is_valid = true; |
227 | peer->latest_cookie.have_sent_mac1 = false; |
228 | up_write(sem: &peer->latest_cookie.lock); |
229 | } else { |
230 | net_dbg_ratelimited("%s: Could not decrypt invalid cookie response\n" , |
231 | wg->dev->name); |
232 | } |
233 | |
234 | out: |
235 | wg_peer_put(peer); |
236 | } |
237 | |