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
19void 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
28enum { COOKIE_KEY_LABEL_LEN = 8 };
29static const u8 mac1_key_label[COOKIE_KEY_LABEL_LEN] = "mac1----";
30static const u8 cookie_key_label[COOKIE_KEY_LABEL_LEN] = "cookie--";
31
32static 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 */
45void 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
61void 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
69void wg_cookie_init(struct cookie *cookie)
70{
71 memset(cookie, 0, sizeof(*cookie));
72 init_rwsem(&cookie->lock);
73}
74
75static 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
83static 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
91static 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
119enum 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
152out:
153 return ret;
154}
155
156void 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
180void 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
198void 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
234out:
235 wg_peer_put(peer);
236}
237

source code of linux/drivers/net/wireguard/cookie.c