drivers/net/ovpn/crypto.h

Source file repositories/reference/linux-study-clean/drivers/net/ovpn/crypto.h

File Facts

System
Linux kernel
Corpus path
drivers/net/ovpn/crypto.h
Extension
.h
Size
3617 bytes
Lines
146
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ovpn_key_direction {
	const u8 *cipher_key;
	size_t cipher_key_size;
	const u8 *nonce_tail; /* only needed for GCM modes */
	size_t nonce_tail_size; /* only needed for GCM modes */
};

/* all info for a particular symmetric key (primary or secondary) */
struct ovpn_key_config {
	enum ovpn_cipher_alg cipher_alg;
	u8 key_id;
	struct ovpn_key_direction encrypt;
	struct ovpn_key_direction decrypt;
};

/* used to pass settings from netlink to the crypto engine */
struct ovpn_peer_key_reset {
	enum ovpn_key_slot slot;
	struct ovpn_key_config key;
};

struct ovpn_crypto_key_slot {
	u8 key_id;

	struct crypto_aead *encrypt;
	struct crypto_aead *decrypt;
	u8 nonce_tail_xmit[OVPN_NONCE_TAIL_SIZE];
	u8 nonce_tail_recv[OVPN_NONCE_TAIL_SIZE];

	struct ovpn_pktid_recv pid_recv ____cacheline_aligned_in_smp;
	struct ovpn_pktid_xmit pid_xmit ____cacheline_aligned_in_smp;
	struct kref refcount;
	struct rcu_head rcu;
};

struct ovpn_crypto_state {
	struct ovpn_crypto_key_slot __rcu *slots[2];
	u8 primary_idx;

	/* protects primary and secondary slots */
	spinlock_t lock;
};

static inline bool ovpn_crypto_key_slot_hold(struct ovpn_crypto_key_slot *ks)
{
	return kref_get_unless_zero(&ks->refcount);
}

static inline void ovpn_crypto_state_init(struct ovpn_crypto_state *cs)
{
	RCU_INIT_POINTER(cs->slots[0], NULL);
	RCU_INIT_POINTER(cs->slots[1], NULL);
	cs->primary_idx = 0;
	spin_lock_init(&cs->lock);
}

static inline struct ovpn_crypto_key_slot *
ovpn_crypto_key_id_to_slot(const struct ovpn_crypto_state *cs, u8 key_id)
{
	struct ovpn_crypto_key_slot *ks;
	u8 idx;

	if (unlikely(!cs))
		return NULL;

	rcu_read_lock();
	idx = READ_ONCE(cs->primary_idx);
	ks = rcu_dereference(cs->slots[idx]);
	if (ks && ks->key_id == key_id) {
		if (unlikely(!ovpn_crypto_key_slot_hold(ks)))
			ks = NULL;
		goto out;
	}

	ks = rcu_dereference(cs->slots[!idx]);
	if (ks && ks->key_id == key_id) {
		if (unlikely(!ovpn_crypto_key_slot_hold(ks)))
			ks = NULL;
		goto out;
	}

	/* when both key slots are occupied but no matching key ID is found, ks
	 * has to be reset to NULL to avoid carrying a stale pointer
	 */
	ks = NULL;
out:
	rcu_read_unlock();

	return ks;
}

Annotation

Implementation Notes