brintos

brintos / linux-shallow public Read only

0
0
Text · 7.0 KiB · f89581b Raw
237 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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(checker->secret, 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(&blake, NOISE_SYMMETRIC_KEY_LEN);39	blake2s_update(&blake, label, COOKIE_KEY_LABEL_LEN);40	blake2s_update(&blake, pubkey, NOISE_PUBLIC_KEY_LEN);41	blake2s_final(&blake, 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(checker->cookie_encryption_key,49			       checker->device->static_identity.static_public,50			       cookie_key_label);51		precompute_key(checker->message_mac1_key,52			       checker->device->static_identity.static_public,53			       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(peer->latest_cookie.cookie_decryption_key,64		       peer->handshake.remote_static, cookie_key_label);65	precompute_key(peer->latest_cookie.message_mac1_key,66		       peer->handshake.remote_static, 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(mac1, message, key, COOKIE_LEN, len, 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(mac2, message, cookie, COOKIE_LEN, len, 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(checker->secret_birthdate,97				     COOKIE_SECRET_MAX_AGE)) {98		down_write(&checker->secret_lock);99		checker->secret_birthdate = ktime_get_coarse_boottime_ns();100		get_random_bytes(checker->secret, NOISE_HASH_LEN);101		up_write(&checker->secret_lock);102	}103 104	down_read(&checker->secret_lock);105 106	blake2s_init_key(&state, COOKIE_LEN, checker->secret, NOISE_HASH_LEN);107	if (skb->protocol == htons(ETH_P_IP))108		blake2s_update(&state, (u8 *)&ip_hdr(skb)->saddr,109			       sizeof(struct in_addr));110	else if (skb->protocol == htons(ETH_P_IPV6))111		blake2s_update(&state, (u8 *)&ipv6_hdr(skb)->saddr,112			       sizeof(struct in6_addr));113	blake2s_update(&state, (u8 *)&udp_hdr(skb)->source, sizeof(__be16));114	blake2s_final(&state, cookie);115 116	up_read(&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(computed_mac, skb->data, skb->len,131		     checker->message_mac1_key);132	if (crypto_memneq(computed_mac, macs->mac1, 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(computed_mac, skb->data, skb->len, cookie);143	if (crypto_memneq(computed_mac, macs->mac2, COOKIE_LEN))144		goto out;145 146	ret = VALID_MAC_WITH_COOKIE_BUT_RATELIMITED;147	if (!wg_ratelimiter_allow(skb, dev_net(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(&peer->latest_cookie.lock);163	compute_mac1(macs->mac1, message, len,164		     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(&peer->latest_cookie.lock);168 169	down_read(&peer->latest_cookie.lock);170	if (peer->latest_cookie.is_valid &&171	    !wg_birthdate_has_expired(peer->latest_cookie.birthdate,172				COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY))173		compute_mac2(macs->mac2, message, len,174			     peer->latest_cookie.cookie);175	else176		memset(macs->mac2, 0, COOKIE_LEN);177	up_read(&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(dst->nonce, COOKIE_NONCE_LEN);191 192	make_cookie(cookie, skb, checker);193	xchacha20poly1305_encrypt(dst->encrypted_cookie, cookie, COOKIE_LEN,194				  macs->mac1, COOKIE_LEN, dst->nonce,195				  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(&peer->latest_cookie.lock);212	if (unlikely(!peer->latest_cookie.have_sent_mac1)) {213		up_read(&peer->latest_cookie.lock);214		goto out;215	}216	ret = xchacha20poly1305_decrypt(217		cookie, src->encrypted_cookie, sizeof(src->encrypted_cookie),218		peer->latest_cookie.last_mac1_sent, COOKIE_LEN, src->nonce,219		peer->latest_cookie.cookie_decryption_key);220	up_read(&peer->latest_cookie.lock);221 222	if (ret) {223		down_write(&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(&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