Lines Matching +full:rx +full:- +full:input
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * algif_aead: User-space interface for AEAD algorithms
7 * This file provides the user-space API for AEAD ciphers.
11 * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is
13 * up the TX SGL does not cause a crypto operation -- the data will only be
15 * provide a buffer which is tracked with the RX SGL.
21 * After the completion of the crypto operation, the RX SGL and the cipher
23 * the RX SGL release.
47 struct sock *psk = ask->parent; in aead_sufficient_data()
49 struct af_alg_ctx *ctx = ask->private; in aead_sufficient_data()
50 struct aead_tfm *aeadc = pask->private; in aead_sufficient_data()
51 struct crypto_aead *tfm = aeadc->aead; in aead_sufficient_data()
58 return ctx->used >= ctx->aead_assoclen + (ctx->enc ? 0 : as); in aead_sufficient_data()
63 struct sock *sk = sock->sk; in aead_sendmsg()
65 struct sock *psk = ask->parent; in aead_sendmsg()
67 struct aead_tfm *aeadc = pask->private; in aead_sendmsg()
68 struct crypto_aead *tfm = aeadc->aead; in aead_sendmsg()
91 struct sock *sk = sock->sk; in _aead_recvmsg()
93 struct sock *psk = ask->parent; in _aead_recvmsg()
95 struct af_alg_ctx *ctx = ask->private; in _aead_recvmsg()
96 struct aead_tfm *aeadc = pask->private; in _aead_recvmsg()
97 struct crypto_aead *tfm = aeadc->aead; in _aead_recvmsg()
98 struct crypto_sync_skcipher *null_tfm = aeadc->null_tfm; in _aead_recvmsg()
105 size_t outlen = 0; /* [out] RX bufs produced by kernel */ in _aead_recvmsg()
106 size_t usedpages = 0; /* [in] RX bufs to be used from user */ in _aead_recvmsg()
109 if (!ctx->init || ctx->more) { in _aead_recvmsg()
119 used = ctx->used; in _aead_recvmsg()
122 * Make sure sufficient data is present -- note, the same check is in _aead_recvmsg()
131 return -EINVAL; in _aead_recvmsg()
136 * larger by the tag length compared to the input buffer as the in _aead_recvmsg()
137 * encryption operation generates the tag. For decryption, the input in _aead_recvmsg()
141 if (ctx->enc) in _aead_recvmsg()
144 outlen = used - as; in _aead_recvmsg()
147 * The cipher operation input data is reduced by the associated data in _aead_recvmsg()
150 used -= ctx->aead_assoclen; in _aead_recvmsg()
158 /* convert iovecs of output buffers into RX SGL */ in _aead_recvmsg()
165 * less buffer space, only use the relative required input size. This in _aead_recvmsg()
168 * of the input data. in _aead_recvmsg()
171 size_t less = outlen - usedpages; in _aead_recvmsg()
174 err = -EINVAL; in _aead_recvmsg()
177 used -= less; in _aead_recvmsg()
178 outlen -= less; in _aead_recvmsg()
181 processed = used + ctx->aead_assoclen; in _aead_recvmsg()
182 list_for_each_entry_safe(tsgl, tmp, &ctx->tsgl_list, list) { in _aead_recvmsg()
183 for (i = 0; i < tsgl->cur; i++) { in _aead_recvmsg()
184 struct scatterlist *process_sg = tsgl->sg + i; in _aead_recvmsg()
186 if (!(process_sg->length) || !sg_page(process_sg)) in _aead_recvmsg()
195 err = -EFAULT; in _aead_recvmsg()
203 * when user space uses an in-place cipher operation, the kernel in _aead_recvmsg()
204 * will copy the data as it does not see whether such in-place operation in _aead_recvmsg()
208 * ciphers are invoked to perform a crypto operation in-place. This in _aead_recvmsg()
212 /* Use the RX SGL as source (and destination) for crypto op. */ in _aead_recvmsg()
213 rsgl_src = areq->first_rsgl.sgl.sg; in _aead_recvmsg()
215 if (ctx->enc) { in _aead_recvmsg()
217 * Encryption operation - The in-place cipher operation is in _aead_recvmsg()
224 * RX SGL: AAD || PT || Tag in _aead_recvmsg()
227 areq->first_rsgl.sgl.sg, processed); in _aead_recvmsg()
233 * Decryption operation - To achieve an in-place cipher in _aead_recvmsg()
240 * RX SGL: AAD || CT ----+ in _aead_recvmsg()
243 /* Copy AAD || CT to RX SGL buffer for in-place operation. */ in _aead_recvmsg()
245 areq->first_rsgl.sgl.sg, outlen); in _aead_recvmsg()
249 /* Create TX SGL for tag and chain it to RX SGL. */ in _aead_recvmsg()
250 areq->tsgl_entries = af_alg_count_tsgl(sk, processed, in _aead_recvmsg()
251 processed - as); in _aead_recvmsg()
252 if (!areq->tsgl_entries) in _aead_recvmsg()
253 areq->tsgl_entries = 1; in _aead_recvmsg()
254 areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl), in _aead_recvmsg()
255 areq->tsgl_entries), in _aead_recvmsg()
257 if (!areq->tsgl) { in _aead_recvmsg()
258 err = -ENOMEM; in _aead_recvmsg()
261 sg_init_table(areq->tsgl, areq->tsgl_entries); in _aead_recvmsg()
264 af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as); in _aead_recvmsg()
266 /* chain the areq TX SGL holding the tag with RX SGL */ in _aead_recvmsg()
268 /* RX SGL present */ in _aead_recvmsg()
269 struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl; in _aead_recvmsg()
271 sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); in _aead_recvmsg()
272 sg_chain(sgl_prev->sg, sgl_prev->npages + 1, in _aead_recvmsg()
273 areq->tsgl); in _aead_recvmsg()
275 /* no RX SGL present (e.g. authentication only) */ in _aead_recvmsg()
276 rsgl_src = areq->tsgl; in _aead_recvmsg()
280 aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, in _aead_recvmsg()
281 areq->first_rsgl.sgl.sg, used, ctx->iv); in _aead_recvmsg()
282 aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); in _aead_recvmsg()
283 aead_request_set_tfm(&areq->cra_u.aead_req, tfm); in _aead_recvmsg()
285 if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { in _aead_recvmsg()
288 areq->iocb = msg->msg_iocb; in _aead_recvmsg()
291 areq->outlen = outlen; in _aead_recvmsg()
293 aead_request_set_callback(&areq->cra_u.aead_req, in _aead_recvmsg()
296 err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) : in _aead_recvmsg()
297 crypto_aead_decrypt(&areq->cra_u.aead_req); in _aead_recvmsg()
300 if (err == -EINPROGRESS) in _aead_recvmsg()
301 return -EIOCBQUEUED; in _aead_recvmsg()
306 aead_request_set_callback(&areq->cra_u.aead_req, in _aead_recvmsg()
309 crypto_req_done, &ctx->wait); in _aead_recvmsg()
310 err = crypto_wait_req(ctx->enc ? in _aead_recvmsg()
311 crypto_aead_encrypt(&areq->cra_u.aead_req) : in _aead_recvmsg()
312 crypto_aead_decrypt(&areq->cra_u.aead_req), in _aead_recvmsg()
313 &ctx->wait); in _aead_recvmsg()
326 struct sock *sk = sock->sk; in aead_recvmsg()
334 * This error covers -EIOCBQUEUED which implies that we can in aead_recvmsg()
342 if (err == -EIOCBQUEUED || err == -EBADMSG || !ret) in aead_recvmsg()
382 struct sock *sk = sock->sk; in aead_check_key()
386 if (!atomic_read(&ask->nokey_refcnt)) in aead_check_key()
389 psk = ask->parent; in aead_check_key()
390 pask = alg_sk(ask->parent); in aead_check_key()
391 tfm = pask->private; in aead_check_key()
393 err = -ENOKEY; in aead_check_key()
395 if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) in aead_check_key()
398 atomic_dec(&pask->nokey_refcnt); in aead_check_key()
399 atomic_set(&ask->nokey_refcnt, 0); in aead_check_key()
475 return ERR_PTR(-ENOMEM); in aead_bind()
490 tfm->aead = aead; in aead_bind()
491 tfm->null_tfm = null_tfm; in aead_bind()
500 crypto_free_aead(tfm->aead); in aead_release()
509 return crypto_aead_setauthsize(tfm->aead, authsize); in aead_setauthsize()
516 return crypto_aead_setkey(tfm->aead, key, keylen); in aead_setkey()
522 struct af_alg_ctx *ctx = ask->private; in aead_sock_destruct()
523 struct sock *psk = ask->parent; in aead_sock_destruct()
525 struct aead_tfm *aeadc = pask->private; in aead_sock_destruct()
526 struct crypto_aead *tfm = aeadc->aead; in aead_sock_destruct()
529 af_alg_pull_tsgl(sk, ctx->used, NULL, 0); in aead_sock_destruct()
530 sock_kzfree_s(sk, ctx->iv, ivlen); in aead_sock_destruct()
531 sock_kfree_s(sk, ctx, ctx->len); in aead_sock_destruct()
540 struct crypto_aead *aead = tfm->aead; in aead_accept_parent_nokey()
546 return -ENOMEM; in aead_accept_parent_nokey()
549 ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL); in aead_accept_parent_nokey()
550 if (!ctx->iv) { in aead_accept_parent_nokey()
552 return -ENOMEM; in aead_accept_parent_nokey()
554 memset(ctx->iv, 0, ivlen); in aead_accept_parent_nokey()
556 INIT_LIST_HEAD(&ctx->tsgl_list); in aead_accept_parent_nokey()
557 ctx->len = len; in aead_accept_parent_nokey()
558 crypto_init_wait(&ctx->wait); in aead_accept_parent_nokey()
560 ask->private = ctx; in aead_accept_parent_nokey()
562 sk->sk_destruct = aead_sock_destruct; in aead_accept_parent_nokey()
571 if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) in aead_accept_parent()
572 return -ENOKEY; in aead_accept_parent()