diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/cookie.c ./cookie.c --- ../../linux-source-6.2.0/drivers/net/wireguard/cookie.c 2023-11-10 18:10:29 +++ ./cookie.c 2023-11-23 18:59:07 @@ -179,13 +179,13 @@ void wg_cookie_message_create(struct message_handshake_cookie *dst, struct sk_buff *skb, __le32 index, - struct cookie_checker *checker) + struct cookie_checker *checker, u32 message_type) { struct message_macs *macs = (struct message_macs *) ((u8 *)skb->data + skb->len - sizeof(*macs)); u8 cookie[COOKIE_LEN]; - dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE); + dst->header.type = cpu_to_le32(message_type); dst->receiver_index = index; get_random_bytes_wait(dst->nonce, COOKIE_NONCE_LEN); diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/cookie.h ./cookie.h --- ../../linux-source-6.2.0/drivers/net/wireguard/cookie.h 2023-11-10 18:10:29 +++ ./cookie.h 2023-11-23 13:11:40 @@ -52,7 +52,7 @@ void wg_cookie_message_create(struct message_handshake_cookie *src, struct sk_buff *skb, __le32 index, - struct cookie_checker *checker); + struct cookie_checker *checker, u32 message_type); void wg_cookie_message_consume(struct message_handshake_cookie *src, struct wg_device *wg); diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/device.c ./device.c --- ../../linux-source-6.2.0/drivers/net/wireguard/device.c 2023-11-10 18:10:29 +++ ./device.c 2023-11-26 17:42:17 @@ -379,6 +379,11 @@ */ dev->priv_destructor = wg_destruct; + wg->advanced_security_config.init_packet_magic_header = MESSAGE_HANDSHAKE_INITIATION; + wg->advanced_security_config.response_packet_magic_header = MESSAGE_HANDSHAKE_RESPONSE; + wg->advanced_security_config.cookie_packet_magic_header = MESSAGE_HANDSHAKE_COOKIE; + wg->advanced_security_config.transport_packet_magic_header = MESSAGE_DATA; + pr_debug("%s: Interface created\n", dev->name); return ret; @@ -475,4 +480,118 @@ unregister_random_vmfork_notifier(&vm_notifier); unregister_pm_notifier(&pm_notifier); rcu_barrier(); +} + +int wg_device_handle_post_config(struct net_device *dev, struct amnezia_config *asc) +{ + struct wg_device *wg = netdev_priv(dev); + bool a_sec_on = false; + int ret = 0; + + if (!asc->advanced_security_enabled) + goto out; + + if (asc->junk_packet_count < 0) { + net_dbg_ratelimited("%s: JunkPacketCount should be non negative\n", dev->name); + ret = -EINVAL; + } + + wg->advanced_security_config.junk_packet_count = asc->junk_packet_count; + if (asc->junk_packet_count != 0) + a_sec_on = true; + + wg->advanced_security_config.junk_packet_min_size = asc->junk_packet_min_size; + if (asc->junk_packet_min_size != 0) + a_sec_on = true; + + if (asc->junk_packet_count > 0 && asc->junk_packet_min_size == asc->junk_packet_max_size) + asc->junk_packet_max_size++; + + if (asc->junk_packet_max_size >= MESSAGE_MAX_SIZE) { + wg->advanced_security_config.junk_packet_min_size = 0; + wg->advanced_security_config.junk_packet_max_size = 1; + + net_dbg_ratelimited("%s: JunkPacketMaxSize: %d; should be smaller than maxSegmentSize: %d\n", + dev->name, asc->junk_packet_max_size, + MESSAGE_MAX_SIZE); + ret = -EINVAL; + } else if (asc->junk_packet_max_size < asc->junk_packet_min_size) { + net_dbg_ratelimited("%s: maxSize: %d; should be greater than minSize: %d\n", + dev->name, asc->junk_packet_max_size, + asc->junk_packet_min_size); + ret = -EINVAL; + } else + wg->advanced_security_config.junk_packet_max_size = asc->junk_packet_max_size; + + if (asc->junk_packet_max_size != 0) + a_sec_on = true; + + if (asc->init_packet_junk_size + MESSAGE_INITIATION_SIZE >= MESSAGE_MAX_SIZE) { + net_dbg_ratelimited("%s: init header size (%d) + junkSize (%d) should be smaller than maxSegmentSize: %d\n", + dev->name, MESSAGE_INITIATION_SIZE, + asc->init_packet_junk_size, MESSAGE_MAX_SIZE); + ret = -EINVAL; + } else + wg->advanced_security_config.init_packet_junk_size = asc->init_packet_junk_size; + + if (asc->init_packet_junk_size != 0) + a_sec_on = true; + + if (asc->response_packet_junk_size + MESSAGE_RESPONSE_SIZE >= MESSAGE_MAX_SIZE) { + net_dbg_ratelimited("%s: response header size (%d) + junkSize (%d) should be smaller than maxSegmentSize: %d\n", + dev->name, MESSAGE_RESPONSE_SIZE, + asc->response_packet_junk_size, MESSAGE_MAX_SIZE); + ret = -EINVAL; + } else + wg->advanced_security_config.response_packet_junk_size = asc->response_packet_junk_size; + + if (asc->response_packet_junk_size != 0) + a_sec_on = true; + + if (asc->init_packet_magic_header > MESSAGE_DATA) { + a_sec_on = true; + wg->advanced_security_config.init_packet_magic_header = asc->init_packet_magic_header; + } + + if (asc->response_packet_magic_header > MESSAGE_DATA) { + a_sec_on = true; + wg->advanced_security_config.response_packet_magic_header = asc->response_packet_magic_header; + } + + if (asc->cookie_packet_magic_header > MESSAGE_DATA) { + a_sec_on = true; + wg->advanced_security_config.cookie_packet_magic_header = asc->cookie_packet_magic_header; + } + + if (asc->transport_packet_magic_header > MESSAGE_DATA) { + a_sec_on = true; + wg->advanced_security_config.transport_packet_magic_header = asc->transport_packet_magic_header; + } + + if (asc->init_packet_magic_header == asc->response_packet_magic_header || + asc->init_packet_magic_header == asc->cookie_packet_magic_header || + asc->init_packet_magic_header == asc->transport_packet_magic_header || + asc->response_packet_magic_header == asc->cookie_packet_magic_header || + asc->response_packet_magic_header == asc->transport_packet_magic_header || + asc->cookie_packet_magic_header == asc->transport_packet_magic_header) { + net_dbg_ratelimited("%s: magic headers should differ; got: init:%d; recv:%d; unde:%d; tran:%d\n", + dev->name, + asc->init_packet_magic_header, + asc->response_packet_magic_header, + asc->cookie_packet_magic_header, + asc->transport_packet_magic_header); + ret = -EINVAL; + } + + if (MESSAGE_INITIATION_SIZE + asc->init_packet_junk_size == MESSAGE_RESPONSE_SIZE + asc->response_packet_junk_size) { + net_dbg_ratelimited("%s: new init size:%d; and new response size:%d; should differ\n", + dev->name, + MESSAGE_INITIATION_SIZE + asc->init_packet_junk_size, + MESSAGE_RESPONSE_SIZE + asc->response_packet_junk_size); + ret = -EINVAL; + } + + wg->advanced_security_config.advanced_security_enabled = a_sec_on; +out: + return ret; } diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/device.h ./device.h --- ../../linux-source-6.2.0/drivers/net/wireguard/device.h 2023-11-10 18:10:29 +++ ./device.h 2023-11-23 18:48:52 @@ -37,6 +37,19 @@ atomic_t count; }; +struct amnezia_config { + bool advanced_security_enabled; + u16 junk_packet_count; + u16 junk_packet_min_size; + u16 junk_packet_max_size; + u16 init_packet_junk_size; + u16 response_packet_junk_size; + u32 init_packet_magic_header; + u32 response_packet_magic_header; + u32 cookie_packet_magic_header; + u32 transport_packet_magic_header; +}; + struct wg_device { struct net_device *dev; struct crypt_queue encrypt_queue, decrypt_queue, handshake_queue; @@ -50,6 +63,7 @@ struct allowedips peer_allowedips; struct mutex device_update_lock, socket_update_lock; struct list_head device_list, peer_list; + struct amnezia_config advanced_security_config; atomic_t handshake_queue_len; unsigned int num_peers, device_update_gen; u32 fwmark; @@ -58,5 +72,6 @@ int wg_device_init(void); void wg_device_uninit(void); +int wg_device_handle_post_config(struct net_device *dev, struct amnezia_config *asc); #endif /* _WG_DEVICE_H */ diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/main.c ./main.c --- ../../linux-source-6.2.0/drivers/net/wireguard/main.c 2023-11-10 18:10:29 +++ ./main.c 2023-11-22 16:37:56 @@ -3,14 +3,13 @@ * Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved. */ -#include "version.h" #include "device.h" #include "noise.h" #include "queueing.h" #include "ratelimiter.h" #include "netlink.h" -#include +#include "uapi/wireguard.h" #include #include @@ -45,7 +44,7 @@ if (ret < 0) goto err_netlink; - pr_info("WireGuard " WIREGUARD_VERSION " loaded. See www.wireguard.com for information.\n"); + pr_info("WireGuard " WIREGUARD_VERSION " (Amnezia VPN) loaded. See www.wireguard.com for information.\n"); pr_info("Copyright (C) 2015-2019 Jason A. Donenfeld . All Rights Reserved.\n"); return 0; @@ -71,7 +70,7 @@ module_init(wg_mod_init); module_exit(wg_mod_exit); MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("WireGuard secure network tunnel"); +MODULE_DESCRIPTION("WireGuard (Amnezia VPN) secure network tunnel"); MODULE_AUTHOR("Jason A. Donenfeld "); MODULE_VERSION(WIREGUARD_VERSION); MODULE_ALIAS_RTNL_LINK(KBUILD_MODNAME); diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/messages.h ./messages.h --- ../../linux-source-6.2.0/drivers/net/wireguard/messages.h 2023-11-10 18:10:29 +++ ./messages.h 2023-11-22 19:16:03 @@ -117,6 +117,14 @@ MESSAGE_MINIMUM_LENGTH = message_data_len(0) }; +enum message_size { + MESSAGE_INITIATION_SIZE = sizeof(struct message_handshake_initiation), + MESSAGE_RESPONSE_SIZE = sizeof(struct message_handshake_response), + MESSAGE_COOKIE_REPLY_SIZE = sizeof(struct message_handshake_cookie), + MESSAGE_TRANSPORT_SIZE = sizeof(struct message_data), + MESSAGE_MAX_SIZE = 65535 +}; + #define SKB_HEADER_LEN \ (max(sizeof(struct iphdr), sizeof(struct ipv6hdr)) + \ sizeof(struct udphdr) + NET_SKB_PAD) diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/netlink.c ./netlink.c --- ../../linux-source-6.2.0/drivers/net/wireguard/netlink.c 2023-11-10 18:10:29 +++ ./netlink.c 2023-11-26 17:34:30 @@ -10,7 +10,7 @@ #include "queueing.h" #include "messages.h" -#include +#include "uapi/wireguard.h" #include #include @@ -27,7 +27,16 @@ [WGDEVICE_A_FLAGS] = { .type = NLA_U32 }, [WGDEVICE_A_LISTEN_PORT] = { .type = NLA_U16 }, [WGDEVICE_A_FWMARK] = { .type = NLA_U32 }, - [WGDEVICE_A_PEERS] = { .type = NLA_NESTED } + [WGDEVICE_A_PEERS] = { .type = NLA_NESTED }, + [WGDEVICE_A_JC] = { .type = NLA_U16 }, + [WGDEVICE_A_JMIN] = { .type = NLA_U16 }, + [WGDEVICE_A_JMAX] = { .type = NLA_U16 }, + [WGDEVICE_A_S1] = { .type = NLA_U16 }, + [WGDEVICE_A_S2] = { .type = NLA_U16 }, + [WGDEVICE_A_H1] = { .type = NLA_U32 }, + [WGDEVICE_A_H2] = { .type = NLA_U32 }, + [WGDEVICE_A_H3] = { .type = NLA_U32 }, + [WGDEVICE_A_H4] = { .type = NLA_U32 } }; static const struct nla_policy peer_policy[WGPEER_A_MAX + 1] = { @@ -233,7 +242,25 @@ wg->incoming_port) || nla_put_u32(skb, WGDEVICE_A_FWMARK, wg->fwmark) || nla_put_u32(skb, WGDEVICE_A_IFINDEX, wg->dev->ifindex) || - nla_put_string(skb, WGDEVICE_A_IFNAME, wg->dev->name)) + nla_put_string(skb, WGDEVICE_A_IFNAME, wg->dev->name) || + nla_put_u16(skb, WGDEVICE_A_JC, + wg->advanced_security_config.junk_packet_count) || + nla_put_u16(skb, WGDEVICE_A_JMIN, + wg->advanced_security_config.junk_packet_min_size) || + nla_put_u16(skb, WGDEVICE_A_JMAX, + wg->advanced_security_config.junk_packet_max_size) || + nla_put_u16(skb, WGDEVICE_A_S1, + wg->advanced_security_config.init_packet_junk_size) || + nla_put_u16(skb, WGDEVICE_A_S2, + wg->advanced_security_config.response_packet_junk_size) || + nla_put_u32(skb, WGDEVICE_A_H1, + wg->advanced_security_config.init_packet_magic_header) || + nla_put_u32(skb, WGDEVICE_A_H2, + wg->advanced_security_config.response_packet_magic_header) || + nla_put_u32(skb, WGDEVICE_A_H3, + wg->advanced_security_config.cookie_packet_magic_header) || + nla_put_u32(skb, WGDEVICE_A_H4, + wg->advanced_security_config.transport_packet_magic_header)) goto out; down_read(&wg->static_identity.lock); @@ -493,6 +520,7 @@ static int wg_set_device(struct sk_buff *skb, struct genl_info *info) { struct wg_device *wg = lookup_interface(info->attrs, skb); + struct amnezia_config *asc = kzalloc(sizeof(*asc), GFP_KERNEL); u32 flags = 0; int ret; @@ -537,6 +565,51 @@ goto out; } + if (info->attrs[WGDEVICE_A_JC]) { + asc->advanced_security_enabled = true; + asc->junk_packet_count = nla_get_u16(info->attrs[WGDEVICE_A_JC]); + } + + if (info->attrs[WGDEVICE_A_JMIN]) { + asc->advanced_security_enabled = true; + asc->junk_packet_min_size = nla_get_u16(info->attrs[WGDEVICE_A_JMIN]); + } + + if (info->attrs[WGDEVICE_A_JMAX]) { + asc->advanced_security_enabled = true; + asc->junk_packet_max_size = nla_get_u16(info->attrs[WGDEVICE_A_JMAX]); + } + + if (info->attrs[WGDEVICE_A_S1]) { + asc->advanced_security_enabled = true; + asc->init_packet_junk_size = nla_get_u16(info->attrs[WGDEVICE_A_S1]); + } + + if (info->attrs[WGDEVICE_A_S2]) { + asc->advanced_security_enabled = true; + asc->response_packet_junk_size = nla_get_u16(info->attrs[WGDEVICE_A_S2]); + } + + if (info->attrs[WGDEVICE_A_H1]) { + asc->advanced_security_enabled = true; + asc->init_packet_magic_header = nla_get_u32(info->attrs[WGDEVICE_A_H1]); + } + + if (info->attrs[WGDEVICE_A_H2]) { + asc->advanced_security_enabled = true; + asc->response_packet_magic_header = nla_get_u32(info->attrs[WGDEVICE_A_H2]); + } + + if (info->attrs[WGDEVICE_A_H3]) { + asc->advanced_security_enabled = true; + asc->cookie_packet_magic_header = nla_get_u32(info->attrs[WGDEVICE_A_H3]); + } + + if (info->attrs[WGDEVICE_A_H4]) { + asc->advanced_security_enabled = true; + asc->transport_packet_magic_header = nla_get_u32(info->attrs[WGDEVICE_A_H4]); + } + if (flags & WGDEVICE_F_REPLACE_PEERS) wg_peer_remove_all(wg); @@ -597,10 +670,14 @@ ret = 0; out: + if (!ret) + ret = wg_device_handle_post_config(wg->dev, asc); + mutex_unlock(&wg->device_update_lock); rtnl_unlock(); dev_put(wg->dev); out_nodev: + kfree(asc); if (info->attrs[WGDEVICE_A_PRIVATE_KEY]) memzero_explicit(nla_data(info->attrs[WGDEVICE_A_PRIVATE_KEY]), nla_len(info->attrs[WGDEVICE_A_PRIVATE_KEY])); diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/noise.c ./noise.c --- ../../linux-source-6.2.0/drivers/net/wireguard/noise.c 2023-11-10 18:10:29 +++ ./noise.c 2023-11-23 18:58:26 @@ -515,7 +515,7 @@ bool wg_noise_handshake_create_initiation(struct message_handshake_initiation *dst, - struct noise_handshake *handshake) + struct noise_handshake *handshake, u32 message_type) { u8 timestamp[NOISE_TIMESTAMP_LEN]; u8 key[NOISE_SYMMETRIC_KEY_LEN]; @@ -532,7 +532,7 @@ if (unlikely(!handshake->static_identity->has_identity)) goto out; - dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION); + dst->header.type = cpu_to_le32(message_type); handshake_init(handshake->chaining_key, handshake->hash, handshake->remote_static); @@ -665,7 +665,7 @@ } bool wg_noise_handshake_create_response(struct message_handshake_response *dst, - struct noise_handshake *handshake) + struct noise_handshake *handshake, u32 message_type) { u8 key[NOISE_SYMMETRIC_KEY_LEN]; bool ret = false; @@ -681,7 +681,7 @@ if (handshake->state != HANDSHAKE_CONSUMED_INITIATION) goto out; - dst->header.type = cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE); + dst->header.type = cpu_to_le32(message_type); dst->receiver_index = handshake->remote_index; /* e */ diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/noise.h ./noise.h --- ../../linux-source-6.2.0/drivers/net/wireguard/noise.h 2023-11-10 18:10:29 +++ ./noise.h 2023-11-23 13:12:55 @@ -118,13 +118,13 @@ bool wg_noise_handshake_create_initiation(struct message_handshake_initiation *dst, - struct noise_handshake *handshake); + struct noise_handshake *handshake, u32 message_type); struct wg_peer * wg_noise_handshake_consume_initiation(struct message_handshake_initiation *src, struct wg_device *wg); bool wg_noise_handshake_create_response(struct message_handshake_response *dst, - struct noise_handshake *handshake); + struct noise_handshake *handshake, u32 message_type); struct wg_peer * wg_noise_handshake_consume_response(struct message_handshake_response *src, struct wg_device *wg); diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/receive.c ./receive.c --- ../../linux-source-6.2.0/drivers/net/wireguard/receive.c 2023-11-10 18:10:29 +++ ./receive.c 2023-11-23 19:15:51 @@ -25,25 +25,51 @@ #define SKB_TYPE_LE32(skb) (((struct message_header *)(skb)->data)->type) -static size_t validate_header_len(struct sk_buff *skb) +static size_t validate_header_len(struct sk_buff *skb, struct wg_device *wg) { if (unlikely(skb->len < sizeof(struct message_header))) return 0; - if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_DATA) && + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.transport_packet_magic_header) && skb->len >= MESSAGE_MINIMUM_LENGTH) return sizeof(struct message_data); - if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION) && - skb->len == sizeof(struct message_handshake_initiation)) - return sizeof(struct message_handshake_initiation); - if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE) && - skb->len == sizeof(struct message_handshake_response)) - return sizeof(struct message_handshake_response); - if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE) && - skb->len == sizeof(struct message_handshake_cookie)) - return sizeof(struct message_handshake_cookie); + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.init_packet_magic_header) && + skb->len == MESSAGE_INITIATION_SIZE) + return MESSAGE_INITIATION_SIZE; + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.response_packet_magic_header) && + skb->len == MESSAGE_RESPONSE_SIZE) + return MESSAGE_RESPONSE_SIZE; + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.cookie_packet_magic_header) && + skb->len == MESSAGE_COOKIE_REPLY_SIZE) + return MESSAGE_COOKIE_REPLY_SIZE; return 0; } +void prepare_advanced_secured_message(struct sk_buff *skb, struct wg_device *wg) +{ + u32 assumed_type = SKB_TYPE_LE32(skb); + u32 assumed_offset; + + if (wg->advanced_security_config.advanced_security_enabled) { + if (skb->len == MESSAGE_INITIATION_SIZE + wg->advanced_security_config.init_packet_junk_size) { + assumed_type = cpu_to_le32(wg->advanced_security_config.init_packet_magic_header); + assumed_offset = wg->advanced_security_config.init_packet_junk_size; + } else if (skb->len == MESSAGE_RESPONSE_SIZE + wg->advanced_security_config.response_packet_junk_size) { + assumed_type = cpu_to_le32(wg->advanced_security_config.response_packet_magic_header); + assumed_offset = wg->advanced_security_config.response_packet_junk_size; + } else + return; + + if (unlikely(assumed_offset <= 0) || unlikely(!pskb_may_pull(skb, assumed_offset))) + return; + + skb_pull(skb, assumed_offset); + + if (SKB_TYPE_LE32(skb) != assumed_type) { + skb_push(skb, assumed_offset); + } + } +} + static int prepare_skb_header(struct sk_buff *skb, struct wg_device *wg) { size_t data_offset, data_len, header_len; @@ -79,7 +105,8 @@ if (unlikely(skb->len != data_len)) /* Final len does not agree with calculated len */ return -EINVAL; - header_len = validate_header_len(skb); + prepare_advanced_secured_message(skb, wg); + header_len = validate_header_len(skb, wg); if (unlikely(!header_len)) return -EINVAL; __skb_push(skb, data_offset); @@ -101,7 +128,7 @@ bool packet_needs_cookie; bool under_load; - if (SKB_TYPE_LE32(skb) == cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE)) { + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.cookie_packet_magic_header)) { net_dbg_skb_ratelimited("%s: Receiving cookie response from %pISpfsc\n", wg->dev->name, skb); wg_cookie_message_consume( @@ -131,8 +158,7 @@ return; } - switch (SKB_TYPE_LE32(skb)) { - case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): { + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.init_packet_magic_header)) { struct message_handshake_initiation *message = (struct message_handshake_initiation *)skb->data; @@ -152,9 +178,8 @@ wg->dev->name, peer->internal_id, &peer->endpoint.addr); wg_packet_send_handshake_response(peer); - break; } - case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): { + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.response_packet_magic_header)) { struct message_handshake_response *message = (struct message_handshake_response *)skb->data; @@ -185,9 +210,7 @@ */ wg_packet_send_keepalive(peer); } - break; } - } if (unlikely(!peer)) { WARN(1, "Somehow a wrong type of packet wound up in the handshake queue!\n"); @@ -543,10 +566,10 @@ { if (unlikely(prepare_skb_header(skb, wg) < 0)) goto err; - switch (SKB_TYPE_LE32(skb)) { - case cpu_to_le32(MESSAGE_HANDSHAKE_INITIATION): - case cpu_to_le32(MESSAGE_HANDSHAKE_RESPONSE): - case cpu_to_le32(MESSAGE_HANDSHAKE_COOKIE): { + + if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.init_packet_magic_header) || + SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.response_packet_magic_header) || + SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.cookie_packet_magic_header)) { int cpu, ret = -EBUSY; if (unlikely(!rng_is_initialized())) @@ -559,23 +582,20 @@ } else ret = ptr_ring_produce_bh(&wg->handshake_queue.ring, skb); if (ret) { - drop: +drop: net_dbg_skb_ratelimited("%s: Dropping handshake packet from %pISpfsc\n", - wg->dev->name, skb); + wg->dev->name, skb); goto err; } atomic_inc(&wg->handshake_queue_len); cpu = wg_cpumask_next_online(&wg->handshake_queue.last_cpu); /* Queues up a call to packet_process_queued_handshake_packets(skb): */ queue_work_on(cpu, wg->handshake_receive_wq, - &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work); - break; - } - case cpu_to_le32(MESSAGE_DATA): + &per_cpu_ptr(wg->handshake_queue.worker, cpu)->work); + } else if (SKB_TYPE_LE32(skb) == cpu_to_le32(wg->advanced_security_config.transport_packet_magic_header)) { PACKET_CB(skb)->ds = ip_tunnel_get_dsfield(ip_hdr(skb), skb); wg_packet_consume_data(wg, skb); - break; - default: + } else { WARN(1, "Non-exhaustive parsing of packet header lead to unknown packet type!\n"); goto err; } diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/send.c ./send.c --- ../../linux-source-6.2.0/drivers/net/wireguard/send.c 2023-11-10 18:10:29 +++ ./send.c 2023-11-24 18:25:50 @@ -14,13 +14,24 @@ #include #include #include +#include #include #include #include +u32 wg_get_random_u32_inclusive(u32 floor, u32 ceil) +{ + u32 diff = ceil - floor + 1; + return floor + (get_random_u32() % diff); +} + static void wg_packet_send_handshake_initiation(struct wg_peer *peer) { struct message_handshake_initiation packet; + struct wg_device *wg = peer->device; + void *buffer; + u8 ds; + u16 junk_packet_count, junk_packet_size; if (!wg_birthdate_has_expired(atomic64_read(&peer->last_sent_handshake), REKEY_TIMEOUT)) @@ -31,14 +42,37 @@ peer->device->dev->name, peer->internal_id, &peer->endpoint.addr); - if (wg_noise_handshake_create_initiation(&packet, &peer->handshake)) { + if (wg->advanced_security_config.advanced_security_enabled) { + junk_packet_count = wg->advanced_security_config.junk_packet_count; + buffer = kzalloc(wg->advanced_security_config.junk_packet_max_size, GFP_KERNEL); + + while (junk_packet_count-- > 0) { + junk_packet_size = (u16) wg_get_random_u32_inclusive( + wg->advanced_security_config.junk_packet_min_size, + wg->advanced_security_config.junk_packet_max_size); + + get_random_bytes(buffer, junk_packet_size); + get_random_bytes(&ds, 1); + wg_socket_send_buffer_to_peer(peer, buffer, junk_packet_size, ds); + } + + kfree(buffer); + } + + if (wg_noise_handshake_create_initiation(&packet, &peer->handshake, wg->advanced_security_config.init_packet_magic_header)) { wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer); wg_timers_any_authenticated_packet_traversal(peer); wg_timers_any_authenticated_packet_sent(peer); atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns()); - wg_socket_send_buffer_to_peer(peer, &packet, sizeof(packet), - HANDSHAKE_DSCP); + + if (wg->advanced_security_config.advanced_security_enabled) { + wg_socket_send_junked_buffer_to_peer(peer, &packet, sizeof(packet), + HANDSHAKE_DSCP, wg->advanced_security_config.init_packet_junk_size); + } else { + wg_socket_send_buffer_to_peer(peer, &packet, sizeof(packet), + HANDSHAKE_DSCP); + } wg_timers_handshake_initiated(peer); } } @@ -85,13 +119,14 @@ void wg_packet_send_handshake_response(struct wg_peer *peer) { struct message_handshake_response packet; + struct wg_device *wg = peer->device; atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns()); net_dbg_ratelimited("%s: Sending handshake response to peer %llu (%pISpfsc)\n", peer->device->dev->name, peer->internal_id, &peer->endpoint.addr); - if (wg_noise_handshake_create_response(&packet, &peer->handshake)) { + if (wg_noise_handshake_create_response(&packet, &peer->handshake, wg->advanced_security_config.response_packet_magic_header)) { wg_cookie_add_mac_to_packet(&packet, sizeof(packet), peer); if (wg_noise_handshake_begin_session(&peer->handshake, &peer->keypairs)) { @@ -100,9 +135,16 @@ wg_timers_any_authenticated_packet_sent(peer); atomic64_set(&peer->last_sent_handshake, ktime_get_coarse_boottime_ns()); - wg_socket_send_buffer_to_peer(peer, &packet, - sizeof(packet), - HANDSHAKE_DSCP); + if (wg->advanced_security_config.advanced_security_enabled) { + wg_socket_send_junked_buffer_to_peer(peer, &packet, + sizeof(packet), + HANDSHAKE_DSCP, + wg->advanced_security_config.response_packet_junk_size); + } else { + wg_socket_send_buffer_to_peer(peer, &packet, + sizeof(packet), + HANDSHAKE_DSCP); + } } } } @@ -116,7 +158,7 @@ net_dbg_skb_ratelimited("%s: Sending cookie response for denied handshake message for %pISpfsc\n", wg->dev->name, initiating_skb); wg_cookie_message_create(&packet, initiating_skb, sender_index, - &wg->cookie_checker); + &wg->cookie_checker, wg->advanced_security_config.cookie_packet_magic_header); wg_socket_send_buffer_as_reply_to_skb(wg, initiating_skb, &packet, sizeof(packet)); } @@ -159,7 +201,7 @@ return padded_size - last_unit; } -static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair) +static bool encrypt_packet(struct sk_buff *skb, struct noise_keypair *keypair, u32 message_type) { unsigned int padding_len, plaintext_len, trailer_len; struct scatterlist sg[MAX_SKB_FRAGS + 8]; @@ -203,7 +245,7 @@ */ skb_set_inner_network_header(skb, 0); header = (struct message_data *)skb_push(skb, sizeof(*header)); - header->header.type = cpu_to_le32(MESSAGE_DATA); + header->header.type = cpu_to_le32(message_type); header->key_idx = keypair->remote_index; header->counter = cpu_to_le64(PACKET_CB(skb)->nonce); pskb_put(skb, trailer, trailer_len); @@ -289,13 +331,17 @@ struct crypt_queue *queue = container_of(work, struct multicore_worker, work)->ptr; struct sk_buff *first, *skb, *next; + struct wg_device *wg; while ((first = ptr_ring_consume_bh(&queue->ring)) != NULL) { enum packet_state state = PACKET_STATE_CRYPTED; skb_list_walk_safe(first, skb, next) { + wg = PACKET_PEER(first)->device; + if (likely(encrypt_packet(skb, - PACKET_CB(first)->keypair))) { + PACKET_CB(first)->keypair, + wg->advanced_security_config.transport_packet_magic_header))) { wg_reset_packet(skb, true); } else { state = PACKET_STATE_DEAD; diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/socket.c ./socket.c --- ../../linux-source-6.2.0/drivers/net/wireguard/socket.c 2023-11-10 18:10:29 +++ ./socket.c 2023-11-23 15:45:07 @@ -200,6 +200,18 @@ return wg_socket_send_skb_to_peer(peer, skb, ds); } +int wg_socket_send_junked_buffer_to_peer(struct wg_peer *peer, void *buffer, + size_t len, u8 ds, u16 junk_size) +{ + int ret; + void *new_buffer = kzalloc(len + junk_size, GFP_KERNEL); + get_random_bytes(new_buffer, junk_size); + memcpy(new_buffer + junk_size, buffer, len); + ret = wg_socket_send_buffer_to_peer(peer, new_buffer, len + junk_size, ds); + kfree(new_buffer); + return ret; +} + int wg_socket_send_buffer_as_reply_to_skb(struct wg_device *wg, struct sk_buff *in_skb, void *buffer, size_t len) diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/socket.h ./socket.h --- ../../linux-source-6.2.0/drivers/net/wireguard/socket.h 2023-11-10 18:10:29 +++ ./socket.h 2023-11-23 13:20:24 @@ -16,6 +16,8 @@ struct sock *new6); int wg_socket_send_buffer_to_peer(struct wg_peer *peer, void *data, size_t len, u8 ds); +int wg_socket_send_junked_buffer_to_peer(struct wg_peer *peer, void *data, + size_t len, u8 ds, u16 junk_size); int wg_socket_send_skb_to_peer(struct wg_peer *peer, struct sk_buff *skb, u8 ds); int wg_socket_send_buffer_as_reply_to_skb(struct wg_device *wg, diff --color -urN -x uapi -x compat -x crypto -x .idea -x tests -x Kbuild -x Kconfig -x Makefile -x dkms.conf ../../linux-source-6.2.0/drivers/net/wireguard/version.h ./version.h --- ../../linux-source-6.2.0/drivers/net/wireguard/version.h 2023-11-10 18:10:29 +++ ./version.h 1970-01-01 02:00:00 @@ -1 +0,0 @@ -#define WIREGUARD_VERSION "1.0.0"