lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250317061759.2368549-1-dqfext@gmail.com>
Date: Mon, 17 Mar 2025 14:17:59 +0800
From: Qingfang Deng <dqfext@...il.com>
To: antonio@...nvpn.net
Cc: andrew+netdev@...n.ch,
	donald.hunter@...il.com,
	edumazet@...gle.com,
	horms@...nel.org,
	kuba@...nel.org,
	linux-kernel@...r.kernel.org,
	linux-kselftest@...r.kernel.org,
	netdev@...r.kernel.org,
	pabeni@...hat.com,
	ryazanov.s.a@...il.com,
	sd@...asysnail.net,
	shaw.leon@...il.com,
	shuah@...nel.org
Subject: Re: [PATCH net-next v23 09/23] ovpn: implement packet processing

On Wed, 12 Mar 2025 21:54:18 +0100, Antonio Quartulli wrote:
> --- a/drivers/net/ovpn/io.c
> +++ b/drivers/net/ovpn/io.c
> @@ -7,6 +7,7 @@
>   *		Antonio Quartulli <antonio@...nvpn.net>
>   */
>  
> +#include <crypto/aead.h>
>  #include <linux/netdevice.h>
>  #include <linux/skbuff.h>
>  #include <net/gro_cells.h>
> @@ -15,6 +16,9 @@
>  #include "ovpnpriv.h"
>  #include "peer.h"
>  #include "io.h"
> +#include "bind.h"
> +#include "crypto.h"
> +#include "crypto_aead.h"
>  #include "netlink.h"
>  #include "proto.h"
>  #include "udp.h"
> @@ -44,7 +48,7 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
>  	skb_set_queue_mapping(skb, 0);
>  	skb_scrub_packet(skb, true);
>  
> -	skb_reset_network_header(skb);
> +	/* network header reset in ovpn_decrypt_post() */
>  	skb_reset_transport_header(skb);
>  	skb_reset_inner_headers(skb);
>  
> @@ -56,34 +60,147 @@ static void ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
>  		dev_sw_netstats_rx_add(peer->ovpn->dev, pkt_len);
>  }
>  
> -static void ovpn_decrypt_post(struct sk_buff *skb, int ret)
> +void ovpn_decrypt_post(void *data, int ret)
>  {
> -	struct ovpn_peer *peer = ovpn_skb_cb(skb)->peer;
> +	struct ovpn_crypto_key_slot *ks;
> +	unsigned int payload_offset = 0;
> +	struct sk_buff *skb = data;
> +	struct ovpn_peer *peer;
> +	__be16 proto;
> +	__be32 *pid;
> +
> +	/* crypto is happening asynchronously. this function will be called
> +	 * again later by the crypto callback with a proper return code
> +	 */
> +	if (unlikely(ret == -EINPROGRESS))
> +		return;
> +
> +	payload_offset = ovpn_skb_cb(skb)->payload_offset;
> +	ks = ovpn_skb_cb(skb)->ks;
> +	peer = ovpn_skb_cb(skb)->peer;
> +
> +	/* crypto is done, cleanup skb CB and its members */
> +
> +	if (likely(ovpn_skb_cb(skb)->iv))
> +		kfree(ovpn_skb_cb(skb)->iv);
> +
> +	if (likely(ovpn_skb_cb(skb)->sg))
> +		kfree(ovpn_skb_cb(skb)->sg);
> +
> +	if (likely(ovpn_skb_cb(skb)->req))
> +		aead_request_free(ovpn_skb_cb(skb)->req);
>  
>  	if (unlikely(ret < 0))
>  		goto drop;
>  
> +	/* PID sits after the op */
> +	pid = (__force __be32 *)(skb->data + OVPN_OPCODE_SIZE);
> +	ret = ovpn_pktid_recv(&ks->pid_recv, ntohl(*pid), 0);
> +	if (unlikely(ret < 0)) {
> +		net_err_ratelimited("%s: PKT ID RX error for peer %u: %d\n",
> +				    netdev_name(peer->ovpn->dev), peer->id,
> +				    ret);
> +		goto drop;
> +	}
> +
> +	/* point to encapsulated IP packet */
> +	__skb_pull(skb, payload_offset);
> +
> +	/* check if this is a valid datapacket that has to be delivered to the
> +	 * ovpn interface
> +	 */
> +	skb_reset_network_header(skb);
> +	proto = ovpn_ip_check_protocol(skb);
> +	if (unlikely(!proto)) {
> +		/* check if null packet */
> +		if (unlikely(!pskb_may_pull(skb, 1))) {
> +			net_info_ratelimited("%s: NULL packet received from peer %u\n",
> +					     netdev_name(peer->ovpn->dev),
> +					     peer->id);
> +			goto drop;
> +		}
> +
> +		net_info_ratelimited("%s: unsupported protocol received from peer %u\n",
> +				     netdev_name(peer->ovpn->dev), peer->id);
> +		goto drop;
> +	}
> +	skb->protocol = proto;
> +
> +	/* perform Reverse Path Filtering (RPF) */
> +	if (unlikely(!ovpn_peer_check_by_src(peer->ovpn, skb, peer))) {
> +		if (skb->protocol == htons(ETH_P_IPV6))
> +			net_dbg_ratelimited("%s: RPF dropped packet from peer %u, src: %pI6c\n",
> +					    netdev_name(peer->ovpn->dev),
> +					    peer->id, &ipv6_hdr(skb)->saddr);
> +		else
> +			net_dbg_ratelimited("%s: RPF dropped packet from peer %u, src: %pI4\n",
> +					    netdev_name(peer->ovpn->dev),
> +					    peer->id, &ip_hdr(skb)->saddr);
> +		goto drop;
> +	}
> +
>  	ovpn_netdev_write(peer, skb);
>  	/* skb is passed to upper layer - don't free it */
>  	skb = NULL;
>  drop:
>  	if (unlikely(skb))
>  		dev_core_stats_rx_dropped_inc(peer->ovpn->dev);
> -	ovpn_peer_put(peer);
> +	if (likely(peer))
> +		ovpn_peer_put(peer);
> +	if (likely(ks))
> +		ovpn_crypto_key_slot_put(ks);
>  	kfree_skb(skb);
>  }
>  
>  /* RX path entry point: decrypt packet and forward it to the device */
>  void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb)
>  {
> -	ovpn_skb_cb(skb)->peer = peer;
> -	ovpn_decrypt_post(skb, 0);
> +	struct ovpn_crypto_key_slot *ks;
> +	u8 key_id;
> +
> +	/* get the key slot matching the key ID in the received packet */
> +	key_id = ovpn_key_id_from_skb(skb);
> +	ks = ovpn_crypto_key_id_to_slot(&peer->crypto, key_id);
> +	if (unlikely(!ks)) {
> +		net_info_ratelimited("%s: no available key for peer %u, key-id: %u\n",
> +				     netdev_name(peer->ovpn->dev), peer->id,
> +				     key_id);
> +		dev_core_stats_rx_dropped_inc(peer->ovpn->dev);
> +		kfree_skb(skb);
> +		ovpn_peer_put(peer);
> +		return;
> +	}
> +
> +	memset(ovpn_skb_cb(skb), 0, sizeof(struct ovpn_cb));
> +	ovpn_decrypt_post(skb, ovpn_aead_decrypt(peer, ks, skb));
>  }
>  
> -static void ovpn_encrypt_post(struct sk_buff *skb, int ret)
> +void ovpn_encrypt_post(void *data, int ret)
>  {
> -	struct ovpn_peer *peer = ovpn_skb_cb(skb)->peer;
> +	struct ovpn_crypto_key_slot *ks;
> +	struct sk_buff *skb = data;
>  	struct ovpn_socket *sock;
> +	struct ovpn_peer *peer;
> +
> +	/* encryption is happening asynchronously. This function will be
> +	 * called later by the crypto callback with a proper return value
> +	 */
> +	if (unlikely(ret == -EINPROGRESS))
> +		return;
> +
> +	ks = ovpn_skb_cb(skb)->ks;
> +	peer = ovpn_skb_cb(skb)->peer;
> +
> +	/* crypto is done, cleanup skb CB and its members */
> +
> +	if (likely(ovpn_skb_cb(skb)->iv))
> +		kfree(ovpn_skb_cb(skb)->iv);
> +
> +	if (likely(ovpn_skb_cb(skb)->sg))
> +		kfree(ovpn_skb_cb(skb)->sg);
> +
> +	if (likely(ovpn_skb_cb(skb)->req))
> +		aead_request_free(ovpn_skb_cb(skb)->req);
>  
>  	if (unlikely(ret < 0))
>  		goto err;
> @@ -110,23 +227,40 @@ static void ovpn_encrypt_post(struct sk_buff *skb, int ret)
>  err:
>  	if (unlikely(skb))
>  		dev_core_stats_tx_dropped_inc(peer->ovpn->dev);
> -	ovpn_peer_put(peer);
> +	if (likely(peer))
> +		ovpn_peer_put(peer);
> +	if (likely(ks))
> +		ovpn_crypto_key_slot_put(ks);
>  	kfree_skb(skb);
>  }
>  
>  static bool ovpn_encrypt_one(struct ovpn_peer *peer, struct sk_buff *skb)
>  {
> -	ovpn_skb_cb(skb)->peer = peer;
> +	struct ovpn_crypto_key_slot *ks;
> +
> +	if (unlikely(skb->ip_summed == CHECKSUM_PARTIAL &&

This if statement is now not necessary as you do not advertise
NETIF_F_HW_CSUM.

> +		     skb_checksum_help(skb))) {
> +		net_warn_ratelimited("%s: cannot compute checksum for outgoing packet for peer %u\n",
> +				     netdev_name(peer->ovpn->dev), peer->id);
> +		return false;
> +	}
> +
> +	/* get primary key to be used for encrypting data */
> +	ks = ovpn_crypto_key_slot_primary(&peer->crypto);
> +	if (unlikely(!ks))
> +		return false;
>  
>  	/* take a reference to the peer because the crypto code may run async.
>  	 * ovpn_encrypt_post() will release it upon completion
>  	 */
>  	if (unlikely(!ovpn_peer_hold(peer))) {
>  		DEBUG_NET_WARN_ON_ONCE(1);
> +		ovpn_crypto_key_slot_put(ks);
>  		return false;
>  	}
>  
> -	ovpn_encrypt_post(skb, 0);
> +	memset(ovpn_skb_cb(skb), 0, sizeof(struct ovpn_cb));
> +	ovpn_encrypt_post(skb, ovpn_aead_encrypt(peer, ks, skb));
>  	return true;
>  }
>  
> diff --git a/drivers/net/ovpn/io.h b/drivers/net/ovpn/io.h
> index 1cfa66873a2d4840ce57e337f8b4e8143e8b8e79..5143104b2c4b896a030ec4a8c8aea7015f40ef02 100644
> --- a/drivers/net/ovpn/io.h
> +++ b/drivers/net/ovpn/io.h
> @@ -23,4 +23,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev);
>  
>  void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb);
>  
> +void ovpn_encrypt_post(void *data, int ret);
> +void ovpn_decrypt_post(void *data, int ret);
> +
>  #endif /* _NET_OVPN_OVPN_H_ */
> diff --git a/drivers/net/ovpn/peer.c b/drivers/net/ovpn/peer.c
> index 10eabd62ae7237162a36a333b41c748901a7d888..23eaab1b465b8b88a84cf9f1039621923b640b47 100644
> --- a/drivers/net/ovpn/peer.c
> +++ b/drivers/net/ovpn/peer.c
> @@ -12,6 +12,8 @@
>  
>  #include "ovpnpriv.h"
>  #include "bind.h"
> +#include "pktid.h"
> +#include "crypto.h"
>  #include "io.h"
>  #include "main.h"
>  #include "netlink.h"
> @@ -56,6 +58,7 @@ struct ovpn_peer *ovpn_peer_new(struct ovpn_priv *ovpn, u32 id)
>  	peer->vpn_addrs.ipv6 = in6addr_any;
>  
>  	RCU_INIT_POINTER(peer->bind, NULL);
> +	ovpn_crypto_state_init(&peer->crypto);
>  	spin_lock_init(&peer->lock);
>  	kref_init(&peer->refcount);
>  
> @@ -94,7 +97,10 @@ static void ovpn_peer_release_rcu(struct rcu_head *head)
>   */
>  static void ovpn_peer_release(struct ovpn_peer *peer)
>  {
> +	ovpn_crypto_state_release(&peer->crypto);
> +	spin_lock_bh(&peer->lock);
>  	ovpn_bind_reset(peer, NULL);
> +	spin_unlock_bh(&peer->lock);
>  	call_rcu(&peer->rcu, ovpn_peer_release_rcu);
>  	netdev_put(peer->ovpn->dev, &peer->dev_tracker);
>  }
> @@ -326,6 +332,29 @@ struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn,
>  	return peer;
>  }
>  
> +/**
> + * ovpn_peer_check_by_src - check that skb source is routed via peer
> + * @ovpn: the openvpn instance to search
> + * @skb: the packet to extract source address from
> + * @peer: the peer to check against the source address
> + *
> + * Return: true if the peer is matching or false otherwise
> + */
> +bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
> +			    struct ovpn_peer *peer)
> +{
> +	bool match = false;
> +
> +	if (ovpn->mode == OVPN_MODE_P2P) {
> +		/* in P2P mode, no matter the destination, packets are always
> +		 * sent to the single peer listening on the other side
> +		 */
> +		match = (peer == rcu_access_pointer(ovpn->peer));
> +	}
> +
> +	return match;
> +}
> +
>  /**
>   * ovpn_peer_add_p2p - add peer to related tables in a P2P instance
>   * @ovpn: the instance to add the peer to
> diff --git a/drivers/net/ovpn/peer.h b/drivers/net/ovpn/peer.h
> index fef04311c1593db4ccfa3c417487b3d4faaae9d7..a9113a969f94d66fa17208d563d0bbd255c23fa9 100644
> --- a/drivers/net/ovpn/peer.h
> +++ b/drivers/net/ovpn/peer.h
> @@ -12,6 +12,7 @@
>  
>  #include <net/dst_cache.h>
>  
> +#include "crypto.h"
>  #include "socket.h"
>  
>  /**
> @@ -23,6 +24,7 @@
>   * @vpn_addrs.ipv4: IPv4 assigned to peer on the tunnel
>   * @vpn_addrs.ipv6: IPv6 assigned to peer on the tunnel
>   * @sock: the socket being used to talk to this peer
> + * @crypto: the crypto configuration (ciphers, keys, etc..)
>   * @dst_cache: cache for dst_entry used to send to peer
>   * @bind: remote peer binding
>   * @delete_reason: why peer was deleted (i.e. timeout, transport error, ..)
> @@ -40,6 +42,7 @@ struct ovpn_peer {
>  		struct in6_addr ipv6;
>  	} vpn_addrs;
>  	struct ovpn_socket __rcu *sock;
> +	struct ovpn_crypto_state crypto;
>  	struct dst_cache dst_cache;
>  	struct ovpn_bind __rcu *bind;
>  	enum ovpn_del_peer_reason delete_reason;
> @@ -82,5 +85,7 @@ struct ovpn_peer *ovpn_peer_get_by_transp_addr(struct ovpn_priv *ovpn,
>  struct ovpn_peer *ovpn_peer_get_by_id(struct ovpn_priv *ovpn, u32 peer_id);
>  struct ovpn_peer *ovpn_peer_get_by_dst(struct ovpn_priv *ovpn,
>  				       struct sk_buff *skb);
> +bool ovpn_peer_check_by_src(struct ovpn_priv *ovpn, struct sk_buff *skb,
> +			    struct ovpn_peer *peer);
>  
>  #endif /* _NET_OVPN_OVPNPEER_H_ */
> diff --git a/drivers/net/ovpn/pktid.c b/drivers/net/ovpn/pktid.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..2e73d1c1ec8b6c4fe2fc10ebc1a4f3008362df21
> --- /dev/null
> +++ b/drivers/net/ovpn/pktid.c
> @@ -0,0 +1,129 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*  OpenVPN data channel offload
> + *
> + *  Copyright (C) 2020-2025 OpenVPN, Inc.
> + *
> + *  Author:	Antonio Quartulli <antonio@...nvpn.net>
> + *		James Yonan <james@...nvpn.net>
> + */
> +
> +#include <linux/atomic.h>
> +#include <linux/jiffies.h>
> +#include <linux/net.h>
> +#include <linux/netdevice.h>
> +#include <linux/types.h>
> +
> +#include "ovpnpriv.h"
> +#include "main.h"
> +#include "pktid.h"
> +
> +void ovpn_pktid_xmit_init(struct ovpn_pktid_xmit *pid)
> +{
> +	atomic64_set(&pid->seq_num, 1);
> +}
> +
> +void ovpn_pktid_recv_init(struct ovpn_pktid_recv *pr)
> +{
> +	memset(pr, 0, sizeof(*pr));
> +	spin_lock_init(&pr->lock);
> +}
> +
> +/* Packet replay detection.
> + * Allows ID backtrack of up to REPLAY_WINDOW_SIZE - 1.
> + */
> +int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time)
> +{
> +	const unsigned long now = jiffies;
> +	int ret;
> +
> +	/* ID must not be zero */
> +	if (unlikely(pkt_id == 0))
> +		return -EINVAL;
> +
> +	spin_lock_bh(&pr->lock);
> +
> +	/* expire backtracks at or below pr->id after PKTID_RECV_EXPIRE time */
> +	if (unlikely(time_after_eq(now, pr->expire)))
> +		pr->id_floor = pr->id;
> +
> +	/* time changed? */
> +	if (unlikely(pkt_time != pr->time)) {
> +		if (pkt_time > pr->time) {
> +			/* time moved forward, accept */
> +			pr->base = 0;
> +			pr->extent = 0;
> +			pr->id = 0;
> +			pr->time = pkt_time;
> +			pr->id_floor = 0;
> +		} else {
> +			/* time moved backward, reject */
> +			ret = -ETIME;
> +			goto out;
> +		}
> +	}
> +
> +	if (likely(pkt_id == pr->id + 1)) {
> +		/* well-formed ID sequence (incremented by 1) */
> +		pr->base = REPLAY_INDEX(pr->base, -1);
> +		pr->history[pr->base / 8] |= (1 << (pr->base % 8));
> +		if (pr->extent < REPLAY_WINDOW_SIZE)
> +			++pr->extent;
> +		pr->id = pkt_id;
> +	} else if (pkt_id > pr->id) {
> +		/* ID jumped forward by more than one */
> +		const unsigned int delta = pkt_id - pr->id;
> +
> +		if (delta < REPLAY_WINDOW_SIZE) {
> +			unsigned int i;
> +
> +			pr->base = REPLAY_INDEX(pr->base, -delta);
> +			pr->history[pr->base / 8] |= (1 << (pr->base % 8));
> +			pr->extent += delta;
> +			if (pr->extent > REPLAY_WINDOW_SIZE)
> +				pr->extent = REPLAY_WINDOW_SIZE;
> +			for (i = 1; i < delta; ++i) {
> +				unsigned int newb = REPLAY_INDEX(pr->base, i);
> +
> +				pr->history[newb / 8] &= ~BIT(newb % 8);
> +			}
> +		} else {
> +			pr->base = 0;
> +			pr->extent = REPLAY_WINDOW_SIZE;
> +			memset(pr->history, 0, sizeof(pr->history));
> +			pr->history[0] = 1;
> +		}
> +		pr->id = pkt_id;
> +	} else {
> +		/* ID backtrack */
> +		const unsigned int delta = pr->id - pkt_id;
> +
> +		if (delta > pr->max_backtrack)
> +			pr->max_backtrack = delta;
> +		if (delta < pr->extent) {
> +			if (pkt_id > pr->id_floor) {
> +				const unsigned int ri = REPLAY_INDEX(pr->base,
> +								     delta);
> +				u8 *p = &pr->history[ri / 8];
> +				const u8 mask = (1 << (ri % 8));
> +
> +				if (*p & mask) {
> +					ret = -EINVAL;
> +					goto out;
> +				}
> +				*p |= mask;
> +			} else {
> +				ret = -EINVAL;
> +				goto out;
> +			}
> +		} else {
> +			ret = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
> +	pr->expire = now + PKTID_RECV_EXPIRE;
> +	ret = 0;
> +out:
> +	spin_unlock_bh(&pr->lock);
> +	return ret;
> +}
> diff --git a/drivers/net/ovpn/pktid.h b/drivers/net/ovpn/pktid.h
> new file mode 100644
> index 0000000000000000000000000000000000000000..0e5fd91d488359f675f500a7368027f7a148f5c6
> --- /dev/null
> +++ b/drivers/net/ovpn/pktid.h
> @@ -0,0 +1,87 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*  OpenVPN data channel offload
> + *
> + *  Copyright (C) 2020-2025 OpenVPN, Inc.
> + *
> + *  Author:	Antonio Quartulli <antonio@...nvpn.net>
> + *		James Yonan <james@...nvpn.net>
> + */
> +
> +#ifndef _NET_OVPN_OVPNPKTID_H_
> +#define _NET_OVPN_OVPNPKTID_H_
> +
> +#include "proto.h"
> +
> +/* If no packets received for this length of time, set a backtrack floor
> + * at highest received packet ID thus far.
> + */
> +#define PKTID_RECV_EXPIRE (30 * HZ)
> +
> +/* Packet-ID state for transmitter */
> +struct ovpn_pktid_xmit {
> +	atomic64_t seq_num;
> +};
> +
> +/* replay window sizing in bytes = 2^REPLAY_WINDOW_ORDER */
> +#define REPLAY_WINDOW_ORDER 8
> +
> +#define REPLAY_WINDOW_BYTES BIT(REPLAY_WINDOW_ORDER)
> +#define REPLAY_WINDOW_SIZE  (REPLAY_WINDOW_BYTES * 8)
> +#define REPLAY_INDEX(base, i) (((base) + (i)) & (REPLAY_WINDOW_SIZE - 1))
> +
> +/* Packet-ID state for receiver.
> + * Other than lock member, can be zeroed to initialize.
> + */
> +struct ovpn_pktid_recv {
> +	/* "sliding window" bitmask of recent packet IDs received */
> +	u8 history[REPLAY_WINDOW_BYTES];
> +	/* bit position of deque base in history */
> +	unsigned int base;
> +	/* extent (in bits) of deque in history */
> +	unsigned int extent;
> +	/* expiration of history in jiffies */
> +	unsigned long expire;
> +	/* highest sequence number received */
> +	u32 id;
> +	/* highest time stamp received */
> +	u32 time;
> +	/* we will only accept backtrack IDs > id_floor */
> +	u32 id_floor;
> +	unsigned int max_backtrack;
> +	/* protects entire pktd ID state */
> +	spinlock_t lock;
> +};
> +
> +/* Get the next packet ID for xmit */
> +static inline int ovpn_pktid_xmit_next(struct ovpn_pktid_xmit *pid, u32 *pktid)
> +{
> +	const s64 seq_num = atomic64_fetch_add_unless(&pid->seq_num, 1,
> +						      0x100000000LL);
> +	/* when the 32bit space is over, we return an error because the packet
> +	 * ID is used to create the cipher IV and we do not want to reuse the
> +	 * same value more than once
> +	 */
> +	if (unlikely(seq_num == 0x100000000LL))
> +		return -ERANGE;
> +
> +	*pktid = (u32)seq_num;
> +
> +	return 0;
> +}
> +
> +/* Write 12-byte AEAD IV to dest */
> +static inline void ovpn_pktid_aead_write(const u32 pktid,
> +					 const u8 nt[],
> +					 unsigned char *dest)
> +{
> +	*(__force __be32 *)(dest) = htonl(pktid);
> +	BUILD_BUG_ON(4 + OVPN_NONCE_TAIL_SIZE != OVPN_NONCE_SIZE);
> +	memcpy(dest + 4, nt, OVPN_NONCE_TAIL_SIZE);
> +}
> +
> +void ovpn_pktid_xmit_init(struct ovpn_pktid_xmit *pid);
> +void ovpn_pktid_recv_init(struct ovpn_pktid_recv *pr);
> +
> +int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time);
> +
> +#endif /* _NET_OVPN_OVPNPKTID_H_ */
> diff --git a/drivers/net/ovpn/proto.h b/drivers/net/ovpn/proto.h
> index 591b97a9925fd9b91f996d6d591fac41b1aa6148..b7322c7c515e5c0744719e11ca81fece3ca28569 100644
> --- a/drivers/net/ovpn/proto.h
> +++ b/drivers/net/ovpn/proto.h
> @@ -83,4 +83,36 @@ static inline u32 ovpn_peer_id_from_skb(const struct sk_buff *skb, u16 offset)
>  	return FIELD_GET(OVPN_OPCODE_PEERID_MASK, opcode);
>  }
>  
> +/**
> + * ovpn_key_id_from_skb - extract key ID from the skb head
> + * @skb: the packet to extract the key ID code from
> + *
> + * Note: this function assumes that the skb head was pulled enough
> + * to access the first byte.
> + *
> + * Return: the key ID
> + */
> +static inline u8 ovpn_key_id_from_skb(const struct sk_buff *skb)
> +{
> +	u32 opcode = be32_to_cpu(*(__be32 *)skb->data);
> +
> +	return FIELD_GET(OVPN_OPCODE_KEYID_MASK, opcode);
> +}
> +
> +/**
> + * ovpn_opcode_compose - combine OP code, key ID and peer ID to wire format
> + * @opcode: the OP code
> + * @key_id: the key ID
> + * @peer_id: the peer ID
> + *
> + * Return: a 4 bytes integer obtained combining all input values following the
> + * OpenVPN wire format. This integer can then be written to the packet header.
> + */
> +static inline u32 ovpn_opcode_compose(u8 opcode, u8 key_id, u32 peer_id)
> +{
> +	return FIELD_PREP(OVPN_OPCODE_PKTTYPE_MASK, opcode) |
> +	       FIELD_PREP(OVPN_OPCODE_KEYID_MASK, key_id) |
> +	       FIELD_PREP(OVPN_OPCODE_PEERID_MASK, peer_id);
> +}
> +
>  #endif /* _NET_OVPN_OVPNPROTO_H_ */
> diff --git a/drivers/net/ovpn/skb.h b/drivers/net/ovpn/skb.h
> index 9db7a9adebdb4cc493f162f89fb2e9c6301fa213..bd3cbcfc770d2c28d234fcdd081b4d02e6496ea0 100644
> --- a/drivers/net/ovpn/skb.h
> +++ b/drivers/net/ovpn/skb.h
> @@ -20,6 +20,11 @@
>  
>  struct ovpn_cb {
>  	struct ovpn_peer *peer;
> +	struct ovpn_crypto_key_slot *ks;
> +	struct aead_request *req;
> +	struct scatterlist *sg;
> +	u8 *iv;
> +	unsigned int payload_offset;
>  };
>  
>  static inline struct ovpn_cb *ovpn_skb_cb(struct sk_buff *skb)
> 
> -- 
> 2.48.1
> 
> 

-- Qingfang

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ