| 1 |
|
| 2 | |
| 3 | * if_alg: User-space algorithm interface
|
| 4 | *
|
| 5 | * Copyright (c) 2010 Herbert Xu <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | #ifndef _CRYPTO_IF_ALG_H
|
| 9 | #define _CRYPTO_IF_ALG_H
|
| 10 |
|
| 11 | #include <linux/bits.h>
|
| 12 | #include <linux/compiler.h>
|
| 13 | #include <linux/completion.h>
|
| 14 | #include <linux/if_alg.h>
|
| 15 | #include <linux/scatterlist.h>
|
| 16 | #include <linux/types.h>
|
| 17 | #include <linux/atomic.h>
|
| 18 | #include <net/sock.h>
|
| 19 |
|
| 20 | #include <crypto/aead.h>
|
| 21 | #include <crypto/skcipher.h>
|
| 22 |
|
| 23 | #define ALG_MAX_PAGES 16
|
| 24 |
|
| 25 | struct alg_sock {
|
| 26 |
|
| 27 | struct sock sk;
|
| 28 |
|
| 29 | struct sock *parent;
|
| 30 |
|
| 31 | atomic_t refcnt;
|
| 32 | atomic_t nokey_refcnt;
|
| 33 |
|
| 34 | const struct af_alg_type *type;
|
| 35 | void *private;
|
| 36 | };
|
| 37 |
|
| 38 | struct af_alg_control {
|
| 39 | struct af_alg_iv *iv;
|
| 40 | int op;
|
| 41 | unsigned int aead_assoclen;
|
| 42 | };
|
| 43 |
|
| 44 | struct af_alg_type {
|
| 45 | void *(*bind)(const char *name);
|
| 46 | void (*release)(void *private);
|
| 47 | int (*setkey)(void *private, const u8 *key, unsigned int keylen);
|
| 48 | int (*setentropy)(void *private, sockptr_t entropy, unsigned int len);
|
| 49 | int (*accept)(void *private, struct sock *sk);
|
| 50 | int (*accept_nokey)(void *private, struct sock *sk);
|
| 51 | int (*setauthsize)(void *private, unsigned int authsize);
|
| 52 |
|
| 53 | struct proto_ops *ops;
|
| 54 | struct proto_ops *ops_nokey;
|
| 55 | struct module *owner;
|
| 56 | char name[14];
|
| 57 | };
|
| 58 |
|
| 59 | struct af_alg_sgl {
|
| 60 | struct sg_table sgt;
|
| 61 | struct scatterlist sgl[ALG_MAX_PAGES + 1];
|
| 62 | bool need_unpin;
|
| 63 | };
|
| 64 |
|
| 65 |
|
| 66 | struct af_alg_tsgl {
|
| 67 | struct list_head list;
|
| 68 | unsigned int cur;
|
| 69 | struct scatterlist sg[];
|
| 70 | };
|
| 71 |
|
| 72 | #define MAX_SGL_ENTS ((4096 - sizeof(struct af_alg_tsgl)) / \
|
| 73 | sizeof(struct scatterlist) - 1)
|
| 74 |
|
| 75 |
|
| 76 | struct af_alg_rsgl {
|
| 77 | struct af_alg_sgl sgl;
|
| 78 | struct list_head list;
|
| 79 | size_t sg_num_bytes;
|
| 80 | };
|
| 81 |
|
| 82 | |
| 83 | * struct af_alg_async_req - definition of crypto request
|
| 84 | * @sk: Socket the request is associated with
|
| 85 | * @first_rsgl: First RX SG
|
| 86 | * @last_rsgl: Pointer to last RX SG
|
| 87 | * @rsgl_list: Track RX SGs
|
| 88 | * @tsgl: Private, per request TX SGL of buffers to process
|
| 89 | * @tsgl_entries: Number of entries in priv. TX SGL
|
| 90 | * @outlen: Number of output bytes generated by crypto op
|
| 91 | * @areqlen: Length of this data structure
|
| 92 | * @cra_u: Cipher request
|
| 93 |
|
| 94 | struct af_alg_async_req {
|
| 95 | struct sock *sk;
|
| 96 |
|
| 97 | struct af_alg_rsgl first_rsgl;
|
| 98 | struct af_alg_rsgl *last_rsgl;
|
| 99 | struct list_head rsgl_list;
|
| 100 |
|
| 101 | struct scatterlist *tsgl;
|
| 102 | unsigned int tsgl_entries;
|
| 103 |
|
| 104 | unsigned int outlen;
|
| 105 | unsigned int areqlen;
|
| 106 |
|
| 107 | union {
|
| 108 | struct aead_request aead_req;
|
| 109 | struct skcipher_request skcipher_req;
|
| 110 | } cra_u;
|
| 111 |
|
| 112 |
|
| 113 | };
|
| 114 |
|
| 115 | |
| 116 | * struct af_alg_ctx - definition of the crypto context
|
| 117 | *
|
| 118 | * The crypto context tracks the input data during the lifetime of an AF_ALG
|
| 119 | * socket.
|
| 120 | *
|
| 121 | * @tsgl_list: Link to TX SGL
|
| 122 | * @iv: IV for cipher operation
|
| 123 | * @state: Existing state for continuing operation
|
| 124 | * @aead_assoclen: Length of AAD for AEAD cipher operations
|
| 125 | * @wait: For waiting for completion of async crypto ops
|
| 126 | * @used: TX bytes sent to kernel. This variable is used to
|
| 127 | * ensure that user space cannot cause the kernel
|
| 128 | * to allocate too much memory in sendmsg operation.
|
| 129 | * @rcvused: Total RX bytes to be filled by kernel. This variable
|
| 130 | * is used to ensure user space cannot cause the kernel
|
| 131 | * to allocate too much memory in a recvmsg operation.
|
| 132 | * @more: More data to be expected from user space?
|
| 133 | * @merge: Shall new data from user space be merged into existing
|
| 134 | * SG?
|
| 135 | * @enc: Cryptographic operation to be performed when
|
| 136 | * recvmsg is invoked.
|
| 137 | * @write: True if we are in the middle of a write.
|
| 138 | * @init: True if metadata has been sent.
|
| 139 | * @len: Length of memory allocated for this data structure.
|
| 140 | * @inflight: Non-zero when requests are in flight, for debugging only.
|
| 141 |
|
| 142 | struct af_alg_ctx {
|
| 143 | struct list_head tsgl_list;
|
| 144 |
|
| 145 | void *iv;
|
| 146 | void *state;
|
| 147 | size_t aead_assoclen;
|
| 148 |
|
| 149 | struct crypto_wait wait;
|
| 150 |
|
| 151 | size_t used;
|
| 152 | atomic_t rcvused;
|
| 153 |
|
| 154 | bool more:1,
|
| 155 | merge:1,
|
| 156 | enc:1,
|
| 157 | write:1,
|
| 158 | init:1;
|
| 159 |
|
| 160 | unsigned int len;
|
| 161 |
|
| 162 | unsigned int inflight;
|
| 163 | };
|
| 164 |
|
| 165 |
|
| 166 | #define AF_ALG_UNPRIVILEGED BIT(0)
|
| 167 |
|
| 168 | struct af_alg_allowlist_entry {
|
| 169 | const char *name;
|
| 170 | u32 flags;
|
| 171 | };
|
| 172 |
|
| 173 | int af_alg_register_type(const struct af_alg_type *type);
|
| 174 | int af_alg_unregister_type(const struct af_alg_type *type);
|
| 175 |
|
| 176 | int af_alg_check_restriction(const char *name,
|
| 177 | const struct af_alg_allowlist_entry allowlist[]);
|
| 178 |
|
| 179 | int af_alg_release(struct socket *sock);
|
| 180 | void af_alg_release_parent(struct sock *sk);
|
| 181 | int af_alg_accept(struct sock *sk, struct socket *newsock,
|
| 182 | struct proto_accept_arg *arg);
|
| 183 |
|
| 184 | void af_alg_free_sg(struct af_alg_sgl *sgl);
|
| 185 |
|
| 186 | static inline struct alg_sock *alg_sk(struct sock *sk)
|
| 187 | {
|
| 188 | return (struct alg_sock *)sk;
|
| 189 | }
|
| 190 |
|
| 191 | |
| 192 | * af_alg_sndbuf - Size of available buffer for sending data from user space to kernel.
|
| 193 | *
|
| 194 | * @sk: socket of connection to user space
|
| 195 | *
|
| 196 | * Returns: number of bytes still available
|
| 197 |
|
| 198 | static inline int af_alg_sndbuf(struct sock *sk)
|
| 199 | {
|
| 200 | struct alg_sock *ask = alg_sk(sk);
|
| 201 | struct af_alg_ctx *ctx = ask->private;
|
| 202 |
|
| 203 | return max_t(int, max_t(int, sk->sk_sndbuf & PAGE_MASK, PAGE_SIZE) -
|
| 204 | ctx->used, 0);
|
| 205 | }
|
| 206 |
|
| 207 | |
| 208 | * af_alg_writable - Can the send buffer still be written to?
|
| 209 | *
|
| 210 | * @sk: socket of connection to user space
|
| 211 | *
|
| 212 | * Returns: true => writable, false => not writable
|
| 213 |
|
| 214 | static inline bool af_alg_writable(struct sock *sk)
|
| 215 | {
|
| 216 | return PAGE_SIZE <= af_alg_sndbuf(sk);
|
| 217 | }
|
| 218 |
|
| 219 | |
| 220 | * af_alg_rcvbuf - Size of available buffer used by kernel for the RX user space operation.
|
| 221 | *
|
| 222 | * @sk: socket of connection to user space
|
| 223 | *
|
| 224 | * Returns: number of bytes still available
|
| 225 |
|
| 226 | static inline int af_alg_rcvbuf(struct sock *sk)
|
| 227 | {
|
| 228 | struct alg_sock *ask = alg_sk(sk);
|
| 229 | struct af_alg_ctx *ctx = ask->private;
|
| 230 |
|
| 231 | return max_t(int, max_t(int, sk->sk_rcvbuf & PAGE_MASK, PAGE_SIZE) -
|
| 232 | atomic_read(&ctx->rcvused), 0);
|
| 233 | }
|
| 234 |
|
| 235 | |
| 236 | * af_alg_readable - Can the RX buffer still be read from?
|
| 237 | *
|
| 238 | * @sk: socket of connection to user space
|
| 239 | *
|
| 240 | * Returns: true => readable, false => not readable
|
| 241 |
|
| 242 | static inline bool af_alg_readable(struct sock *sk)
|
| 243 | {
|
| 244 | return PAGE_SIZE <= af_alg_rcvbuf(sk);
|
| 245 | }
|
| 246 |
|
| 247 | unsigned int af_alg_count_tsgl(struct sock *sk, size_t bytes);
|
| 248 | void af_alg_pull_tsgl(struct sock *sk, size_t used, struct scatterlist *dst);
|
| 249 | void af_alg_wmem_wakeup(struct sock *sk);
|
| 250 | int af_alg_wait_for_data(struct sock *sk, unsigned flags, unsigned min);
|
| 251 | int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
|
| 252 | unsigned int ivsize);
|
| 253 | void af_alg_free_resources(struct af_alg_async_req *areq);
|
| 254 | __poll_t af_alg_poll(struct file *file, struct socket *sock,
|
| 255 | poll_table *wait);
|
| 256 | struct af_alg_async_req *af_alg_alloc_areq(struct sock *sk,
|
| 257 | unsigned int areqlen);
|
| 258 | int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags,
|
| 259 | struct af_alg_async_req *areq, size_t maxsize,
|
| 260 | size_t *outlen);
|
| 261 |
|
| 262 | |
| 263 | * Mask used to disable unsupported algorithm implementations.
|
| 264 | *
|
| 265 | * This is the same as FSCRYPT_CRYPTOAPI_MASK in fs/crypto/fscrypt_private.h.
|
| 266 | * In additions to the motivations there, this API is exposed to userspace
|
| 267 | * that might not be fully trusted.
|
| 268 |
|
| 269 | #define AF_ALG_CRYPTOAPI_MASK \
|
| 270 | (CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | \
|
| 271 | CRYPTO_ALG_KERN_DRIVER_ONLY)
|
| 272 |
|
| 273 |
|
| 274 | #endif
|