162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * if_alg: User-space algorithm interface
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef _CRYPTO_IF_ALG_H
962306a36Sopenharmony_ci#define _CRYPTO_IF_ALG_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/compiler.h>
1262306a36Sopenharmony_ci#include <linux/completion.h>
1362306a36Sopenharmony_ci#include <linux/if_alg.h>
1462306a36Sopenharmony_ci#include <linux/scatterlist.h>
1562306a36Sopenharmony_ci#include <linux/types.h>
1662306a36Sopenharmony_ci#include <linux/atomic.h>
1762306a36Sopenharmony_ci#include <net/sock.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <crypto/aead.h>
2062306a36Sopenharmony_ci#include <crypto/skcipher.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define ALG_MAX_PAGES			16
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistruct alg_sock {
2562306a36Sopenharmony_ci	/* struct sock must be the first member of struct alg_sock */
2662306a36Sopenharmony_ci	struct sock sk;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	struct sock *parent;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	atomic_t refcnt;
3162306a36Sopenharmony_ci	atomic_t nokey_refcnt;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	const struct af_alg_type *type;
3462306a36Sopenharmony_ci	void *private;
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistruct af_alg_control {
3862306a36Sopenharmony_ci	struct af_alg_iv *iv;
3962306a36Sopenharmony_ci	int op;
4062306a36Sopenharmony_ci	unsigned int aead_assoclen;
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistruct af_alg_type {
4462306a36Sopenharmony_ci	void *(*bind)(const char *name, u32 type, u32 mask);
4562306a36Sopenharmony_ci	void (*release)(void *private);
4662306a36Sopenharmony_ci	int (*setkey)(void *private, const u8 *key, unsigned int keylen);
4762306a36Sopenharmony_ci	int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
4862306a36Sopenharmony_ci	int (*accept)(void *private, struct sock *sk);
4962306a36Sopenharmony_ci	int (*accept_nokey)(void *private, struct sock *sk);
5062306a36Sopenharmony_ci	int (*setauthsize)(void *private, unsigned int authsize);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	struct proto_ops *ops;
5362306a36Sopenharmony_ci	struct proto_ops *ops_nokey;
5462306a36Sopenharmony_ci	struct module *owner;
5562306a36Sopenharmony_ci	char name[14];
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct af_alg_sgl {
5962306a36Sopenharmony_ci	struct sg_table sgt;
6062306a36Sopenharmony_ci	struct scatterlist sgl[ALG_MAX_PAGES + 1];
6162306a36Sopenharmony_ci	bool need_unpin;
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/* TX SGL entry */
6562306a36Sopenharmony_cistruct af_alg_tsgl {
6662306a36Sopenharmony_ci	struct list_head list;
6762306a36Sopenharmony_ci	unsigned int cur;		/* Last processed SG entry */
6862306a36Sopenharmony_ci	struct scatterlist sg[];	/* Array of SGs forming the SGL */
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci#define MAX_SGL_ENTS ((4096 - sizeof(struct af_alg_tsgl)) / \
7262306a36Sopenharmony_ci		      sizeof(struct scatterlist) - 1)
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/* RX SGL entry */
7562306a36Sopenharmony_cistruct af_alg_rsgl {
7662306a36Sopenharmony_ci	struct af_alg_sgl sgl;
7762306a36Sopenharmony_ci	struct list_head list;
7862306a36Sopenharmony_ci	size_t sg_num_bytes;		/* Bytes of data in that SGL */
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci/**
8262306a36Sopenharmony_ci * struct af_alg_async_req - definition of crypto request
8362306a36Sopenharmony_ci * @iocb:		IOCB for AIO operations
8462306a36Sopenharmony_ci * @sk:			Socket the request is associated with
8562306a36Sopenharmony_ci * @first_rsgl:		First RX SG
8662306a36Sopenharmony_ci * @last_rsgl:		Pointer to last RX SG
8762306a36Sopenharmony_ci * @rsgl_list:		Track RX SGs
8862306a36Sopenharmony_ci * @tsgl:		Private, per request TX SGL of buffers to process
8962306a36Sopenharmony_ci * @tsgl_entries:	Number of entries in priv. TX SGL
9062306a36Sopenharmony_ci * @outlen:		Number of output bytes generated by crypto op
9162306a36Sopenharmony_ci * @areqlen:		Length of this data structure
9262306a36Sopenharmony_ci * @cra_u:		Cipher request
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_cistruct af_alg_async_req {
9562306a36Sopenharmony_ci	struct kiocb *iocb;
9662306a36Sopenharmony_ci	struct sock *sk;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	struct af_alg_rsgl first_rsgl;
9962306a36Sopenharmony_ci	struct af_alg_rsgl *last_rsgl;
10062306a36Sopenharmony_ci	struct list_head rsgl_list;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	struct scatterlist *tsgl;
10362306a36Sopenharmony_ci	unsigned int tsgl_entries;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	unsigned int outlen;
10662306a36Sopenharmony_ci	unsigned int areqlen;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	union {
10962306a36Sopenharmony_ci		struct aead_request aead_req;
11062306a36Sopenharmony_ci		struct skcipher_request skcipher_req;
11162306a36Sopenharmony_ci	} cra_u;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	/* req ctx trails this struct */
11462306a36Sopenharmony_ci};
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci/**
11762306a36Sopenharmony_ci * struct af_alg_ctx - definition of the crypto context
11862306a36Sopenharmony_ci *
11962306a36Sopenharmony_ci * The crypto context tracks the input data during the lifetime of an AF_ALG
12062306a36Sopenharmony_ci * socket.
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci * @tsgl_list:		Link to TX SGL
12362306a36Sopenharmony_ci * @iv:			IV for cipher operation
12462306a36Sopenharmony_ci * @aead_assoclen:	Length of AAD for AEAD cipher operations
12562306a36Sopenharmony_ci * @completion:		Work queue for synchronous operation
12662306a36Sopenharmony_ci * @used:		TX bytes sent to kernel. This variable is used to
12762306a36Sopenharmony_ci *			ensure that user space cannot cause the kernel
12862306a36Sopenharmony_ci *			to allocate too much memory in sendmsg operation.
12962306a36Sopenharmony_ci * @rcvused:		Total RX bytes to be filled by kernel. This variable
13062306a36Sopenharmony_ci *			is used to ensure user space cannot cause the kernel
13162306a36Sopenharmony_ci *			to allocate too much memory in a recvmsg operation.
13262306a36Sopenharmony_ci * @more:		More data to be expected from user space?
13362306a36Sopenharmony_ci * @merge:		Shall new data from user space be merged into existing
13462306a36Sopenharmony_ci *			SG?
13562306a36Sopenharmony_ci * @enc:		Cryptographic operation to be performed when
13662306a36Sopenharmony_ci *			recvmsg is invoked.
13762306a36Sopenharmony_ci * @init:		True if metadata has been sent.
13862306a36Sopenharmony_ci * @len:		Length of memory allocated for this data structure.
13962306a36Sopenharmony_ci * @inflight:		Non-zero when AIO requests are in flight.
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistruct af_alg_ctx {
14262306a36Sopenharmony_ci	struct list_head tsgl_list;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	void *iv;
14562306a36Sopenharmony_ci	size_t aead_assoclen;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	struct crypto_wait wait;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	size_t used;
15062306a36Sopenharmony_ci	atomic_t rcvused;
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	bool more;
15362306a36Sopenharmony_ci	bool merge;
15462306a36Sopenharmony_ci	bool enc;
15562306a36Sopenharmony_ci	bool init;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	unsigned int len;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	unsigned int inflight;
16062306a36Sopenharmony_ci};
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciint af_alg_register_type(const struct af_alg_type *type);
16362306a36Sopenharmony_ciint af_alg_unregister_type(const struct af_alg_type *type);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciint af_alg_release(struct socket *sock);
16662306a36Sopenharmony_civoid af_alg_release_parent(struct sock *sk);
16762306a36Sopenharmony_ciint af_alg_accept(struct sock *sk, struct socket *newsock, bool kern);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_civoid af_alg_free_sg(struct af_alg_sgl *sgl);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_cistatic inline struct alg_sock *alg_sk(struct sock *sk)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	return (struct alg_sock *)sk;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci/**
17762306a36Sopenharmony_ci * Size of available buffer for sending data from user space to kernel.
17862306a36Sopenharmony_ci *
17962306a36Sopenharmony_ci * @sk socket of connection to user space
18062306a36Sopenharmony_ci * @return number of bytes still available
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_cistatic inline int af_alg_sndbuf(struct sock *sk)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	struct alg_sock *ask = alg_sk(sk);
18562306a36Sopenharmony_ci	struct af_alg_ctx *ctx = ask->private;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
18862306a36Sopenharmony_ci			  ctx->used, 0);
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci/**
19262306a36Sopenharmony_ci * Can the send buffer still be written to?
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * @sk socket of connection to user space
19562306a36Sopenharmony_ci * @return true => writable, false => not writable
19662306a36Sopenharmony_ci */
19762306a36Sopenharmony_cistatic inline bool af_alg_writable(struct sock *sk)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	return PAGE_SIZE <= af_alg_sndbuf(sk);
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/**
20362306a36Sopenharmony_ci * Size of available buffer used by kernel for the RX user space operation.
20462306a36Sopenharmony_ci *
20562306a36Sopenharmony_ci * @sk socket of connection to user space
20662306a36Sopenharmony_ci * @return number of bytes still available
20762306a36Sopenharmony_ci */
20862306a36Sopenharmony_cistatic inline int af_alg_rcvbuf(struct sock *sk)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	struct alg_sock *ask = alg_sk(sk);
21162306a36Sopenharmony_ci	struct af_alg_ctx *ctx = ask->private;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci	return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) -
21462306a36Sopenharmony_ci		     atomic_read(&ctx->rcvused), 0);
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci/**
21862306a36Sopenharmony_ci * Can the RX buffer still be written to?
21962306a36Sopenharmony_ci *
22062306a36Sopenharmony_ci * @sk socket of connection to user space
22162306a36Sopenharmony_ci * @return true => writable, false => not writable
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_cistatic inline bool af_alg_readable(struct sock *sk)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	return PAGE_SIZE <= af_alg_rcvbuf(sk);
22662306a36Sopenharmony_ci}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ciunsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes, size_t offset);
22962306a36Sopenharmony_civoid af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst,
23062306a36Sopenharmony_ci		      size_t dst_offset);
23162306a36Sopenharmony_civoid af_alg_wmem_wakeup(struct sock *sk);
23262306a36Sopenharmony_ciint af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
23362306a36Sopenharmony_ciint af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
23462306a36Sopenharmony_ci		   unsigned int ivsize);
23562306a36Sopenharmony_civoid af_alg_free_resources(struct af_alg_async_req *areq);
23662306a36Sopenharmony_civoid af_alg_async_cb(void *data, int err);
23762306a36Sopenharmony_ci__poll_t af_alg_poll(struct file *file, struct socket *sock,
23862306a36Sopenharmony_ci			 poll_table *wait);
23962306a36Sopenharmony_cistruct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
24062306a36Sopenharmony_ci					   unsigned int areqlen);
24162306a36Sopenharmony_ciint af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
24262306a36Sopenharmony_ci		    struct af_alg_async_req *areq, size_t maxsize,
24362306a36Sopenharmony_ci		    size_t *outlen);
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci#endif	/* _CRYPTO_IF_ALG_H */
246