Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259/* SPDX-License-Identifier: GPL-2.0-or-later *//* * if_alg: User-space algorithm interface * * Copyright (c) 2010 Herbert Xu <herbert@gondor.apana.org.au> */
#ifndef _CRYPTO_IF_ALG_H#define _CRYPTO_IF_ALG_H
#include <linux/compiler.h>#include <linux/completion.h>#include <linux/if_alg.h>#include <linux/scatterlist.h>#include <linux/types.h>#include <linux/atomic.h>#include <net/sock.h>
#include <crypto/aead.h>#include <crypto/skcipher.h>
#define ALG_MAX_PAGES 16
struct alg_sock { /* struct sock must be the first member of struct alg_sock */ struct sock sk;
struct sock *parent;
atomic_t refcnt; atomic_t nokey_refcnt;
const struct af_alg_type *type; void *private;};
struct af_alg_control { struct af_alg_iv *iv; int op; unsigned int aead_assoclen;};
struct af_alg_type { void *(*bind)(const char *name); void (*release)(void *private); int (*setkey)(void *private, const u8 *key, unsigned int keylen); int (*setentropy)(void *private, sockptr_t entropy, unsigned int len); int (*accept)(void *private, struct sock *sk); int (*accept_nokey)(void *private, struct sock *sk); int (*setauthsize)(void *private, unsigned int authsize);
struct proto_ops *ops; struct proto_ops *ops_nokey; struct module *owner; char name[14];};
struct af_alg_sgl { struct sg_table sgt; struct scatterlist sgl[ALG_MAX_PAGES + 1]; bool need_unpin;};
/* TX SGL entry */struct af_alg_tsgl { struct list_head list; unsigned int cur; /* Last processed SG entry */ struct scatterlist sg[]; /* Array of SGs forming the SGL */};
#define MAX_SGL_ENTS ((4096 - sizeof(struct af_alg_tsgl)) / \ sizeof(struct scatterlist) - 1)
/* RX SGL entry */struct af_alg_rsgl { struct af_alg_sgl sgl; struct list_head list; size_t sg_num_bytes; /* Bytes of data in that SGL */};
/** * struct af_alg_async_req - definition of crypto request * @sk: Socket the request is associated with * @first_rsgl: First RX SG * @last_rsgl: Pointer to last RX SG * @rsgl_list: Track RX SGs * @tsgl: Private, per request TX SGL of buffers to process * @tsgl_entries: Number of entries in priv. TX SGL * @outlen: Number of output bytes generated by crypto op * @areqlen: Length of this data structure * @cra_u: Cipher request */struct af_alg_async_req { struct sock *sk;
struct af_alg_rsgl first_rsgl; struct af_alg_rsgl *last_rsgl; struct list_head rsgl_list;
struct scatterlist *tsgl; unsigned int tsgl_entries;
unsigned int outlen; unsigned int areqlen;
union { struct aead_request aead_req; struct skcipher_request skcipher_req; } cra_u;
/* req ctx trails this struct */};
/** * struct af_alg_ctx - definition of the crypto context * * The crypto context tracks the input data during the lifetime of an AF_ALG * socket. * * @tsgl_list: Link to TX SGL * @iv: IV for cipher operation * @state: Existing state for continuing operation * @aead_assoclen: Length of AAD for AEAD cipher operations * @completion: Work queue for synchronous operation * @used: TX bytes sent to kernel. This variable is used to * ensure that user space cannot cause the kernel * to allocate too much memory in sendmsg operation. * @rcvused: Total RX bytes to be filled by kernel. This variable * is used to ensure user space cannot cause the kernel * to allocate too much memory in a recvmsg operation. * @more: More data to be expected from user space? * @merge: Shall new data from user space be merged into existing * SG? * @enc: Cryptographic operation to be performed when * recvmsg is invoked. * @write: True if we are in the middle of a write. * @init: True if metadata has been sent. * @len: Length of memory allocated for this data structure. * @inflight: Non-zero when requests are in flight, for debugging only. */struct af_alg_ctx { struct list_head tsgl_list;
void *iv; void *state; size_t aead_assoclen;
struct crypto_wait wait;
size_t used; atomic_t rcvused;
bool more:1, merge:1, enc:1, write:1, init:1;
unsigned int len;
unsigned int inflight;};
int af_alg_register_type(const struct af_alg_type *type);int af_alg_unregister_type(const struct af_alg_type *type);
int af_alg_release(struct socket *sock);void af_alg_release_parent(struct sock *sk);int af_alg_accept(struct sock *sk, struct socket *newsock, struct proto_accept_arg *arg);
void af_alg_free_sg(struct af_alg_sgl *sgl);
static inline struct alg_sock *alg_sk(struct sock *sk){ return (struct alg_sock *)sk;}
/** * Size of available buffer for sending data from user space to kernel. * * @sk socket of connection to user space * @return number of bytes still available */static inline int af_alg_sndbuf(struct sock *sk){ struct alg_sock *ask = alg_sk(sk); struct af_alg_ctx *ctx = ask->private;
return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) - ctx->used, 0);}
/** * Can the send buffer still be written to? * * @sk socket of connection to user space * @return true => writable, false => not writable */static inline bool af_alg_writable(struct sock *sk){ return PAGE_SIZE <= af_alg_sndbuf(sk);}
/** * Size of available buffer used by kernel for the RX user space operation. * * @sk socket of connection to user space * @return number of bytes still available */static inline int af_alg_rcvbuf(struct sock *sk){ struct alg_sock *ask = alg_sk(sk); struct af_alg_ctx *ctx = ask->private;
return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) - atomic_read(&ctx->rcvused), 0);}
/** * Can the RX buffer still be written to? * * @sk socket of connection to user space * @return true => writable, false => not writable */static inline bool af_alg_readable(struct sock *sk){ return PAGE_SIZE <= af_alg_rcvbuf(sk);}
unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes);void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst);void af_alg_wmem_wakeup(struct sock *sk);int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, unsigned int ivsize);void af_alg_free_resources(struct af_alg_async_req *areq);__poll_t af_alg_poll(struct file *file, struct socket *sock, poll_table *wait);struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk, unsigned int areqlen);int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, struct af_alg_async_req *areq, size_t maxsize, size_t *outlen);
/* * Mask used to disable unsupported algorithm implementations. * * This is the same as FSCRYPT_CRYPTOAPI_MASK in fs/crypto/fscrypt_private.h. * In additions to the motivations there, this API is exposed to userspace * that might not be fully trusted. */#define AF_ALG_CRYPTOAPI_MASK \ (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \ CRYPTO_ALG_KERN_DRIVER_ONLY)
#endif /* _CRYPTO_IF_ALG_H */