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
14 * -- the data will only be tracked by the kernel. Upon receipt of one recvmsg
15 * call, the caller must 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 also 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.sgt.sgl; 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.sgt.sgl, in _aead_recvmsg()
234 * Decryption operation - To achieve an in-place cipher in _aead_recvmsg()
241 * RX SGL: AAD || CT ----+ in _aead_recvmsg()
244 /* Copy AAD || CT to RX SGL buffer for in-place operation. */ in _aead_recvmsg()
246 areq->first_rsgl.sgl.sgt.sgl, in _aead_recvmsg()
251 /* Create TX SGL for tag and chain it to RX SGL. */ in _aead_recvmsg()
252 areq->tsgl_entries = af_alg_count_tsgl(sk, processed, in _aead_recvmsg()
253 processed - as); in _aead_recvmsg()
254 if (!areq->tsgl_entries) in _aead_recvmsg()
255 areq->tsgl_entries = 1; in _aead_recvmsg()
256 areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl), in _aead_recvmsg()
257 areq->tsgl_entries), in _aead_recvmsg()
259 if (!areq->tsgl) { in _aead_recvmsg()
260 err = -ENOMEM; in _aead_recvmsg()
263 sg_init_table(areq->tsgl, areq->tsgl_entries); in _aead_recvmsg()
266 af_alg_pull_tsgl(sk, processed, areq->tsgl, processed - as); in _aead_recvmsg()
268 /* chain the areq TX SGL holding the tag with RX SGL */ in _aead_recvmsg()
270 /* RX SGL present */ in _aead_recvmsg()
271 struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl; in _aead_recvmsg()
272 struct scatterlist *sg = sgl_prev->sgt.sgl; in _aead_recvmsg()
274 sg_unmark_end(sg + sgl_prev->sgt.nents - 1); in _aead_recvmsg()
275 sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl); in _aead_recvmsg()
277 /* no RX SGL present (e.g. authentication only) */ in _aead_recvmsg()
278 rsgl_src = areq->tsgl; in _aead_recvmsg()
282 aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, in _aead_recvmsg()
283 areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv); in _aead_recvmsg()
284 aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); in _aead_recvmsg()
285 aead_request_set_tfm(&areq->cra_u.aead_req, tfm); in _aead_recvmsg()
287 if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { in _aead_recvmsg()
290 areq->iocb = msg->msg_iocb; in _aead_recvmsg()
293 areq->outlen = outlen; in _aead_recvmsg()
295 aead_request_set_callback(&areq->cra_u.aead_req, in _aead_recvmsg()
298 err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) : in _aead_recvmsg()
299 crypto_aead_decrypt(&areq->cra_u.aead_req); in _aead_recvmsg()
302 if (err == -EINPROGRESS) in _aead_recvmsg()
303 return -EIOCBQUEUED; in _aead_recvmsg()
308 aead_request_set_callback(&areq->cra_u.aead_req, in _aead_recvmsg()
311 crypto_req_done, &ctx->wait); in _aead_recvmsg()
312 err = crypto_wait_req(ctx->enc ? in _aead_recvmsg()
313 crypto_aead_encrypt(&areq->cra_u.aead_req) : in _aead_recvmsg()
314 crypto_aead_decrypt(&areq->cra_u.aead_req), in _aead_recvmsg()
315 &ctx->wait); in _aead_recvmsg()
328 struct sock *sk = sock->sk; in aead_recvmsg()
336 * This error covers -EIOCBQUEUED which implies that we can in aead_recvmsg()
344 if (err == -EIOCBQUEUED || err == -EBADMSG || !ret) in aead_recvmsg()
383 struct sock *sk = sock->sk; in aead_check_key()
387 if (!atomic_read(&ask->nokey_refcnt)) in aead_check_key()
390 psk = ask->parent; in aead_check_key()
391 pask = alg_sk(ask->parent); in aead_check_key()
392 tfm = pask->private; in aead_check_key()
394 err = -ENOKEY; in aead_check_key()
396 if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) in aead_check_key()
399 atomic_dec(&pask->nokey_refcnt); in aead_check_key()
400 atomic_set(&ask->nokey_refcnt, 0); in aead_check_key()
463 return ERR_PTR(-ENOMEM); in aead_bind()
478 tfm->aead = aead; in aead_bind()
479 tfm->null_tfm = null_tfm; in aead_bind()
488 crypto_free_aead(tfm->aead); in aead_release()
497 return crypto_aead_setauthsize(tfm->aead, authsize); in aead_setauthsize()
504 return crypto_aead_setkey(tfm->aead, key, keylen); in aead_setkey()
510 struct af_alg_ctx *ctx = ask->private; in aead_sock_destruct()
511 struct sock *psk = ask->parent; in aead_sock_destruct()
513 struct aead_tfm *aeadc = pask->private; in aead_sock_destruct()
514 struct crypto_aead *tfm = aeadc->aead; in aead_sock_destruct()
517 af_alg_pull_tsgl(sk, ctx->used, NULL, 0); in aead_sock_destruct()
518 sock_kzfree_s(sk, ctx->iv, ivlen); in aead_sock_destruct()
519 sock_kfree_s(sk, ctx, ctx->len); in aead_sock_destruct()
528 struct crypto_aead *aead = tfm->aead; in aead_accept_parent_nokey()
534 return -ENOMEM; in aead_accept_parent_nokey()
537 ctx->iv = sock_kmalloc(sk, ivlen, GFP_KERNEL); in aead_accept_parent_nokey()
538 if (!ctx->iv) { in aead_accept_parent_nokey()
540 return -ENOMEM; in aead_accept_parent_nokey()
542 memset(ctx->iv, 0, ivlen); in aead_accept_parent_nokey()
544 INIT_LIST_HEAD(&ctx->tsgl_list); in aead_accept_parent_nokey()
545 ctx->len = len; in aead_accept_parent_nokey()
546 crypto_init_wait(&ctx->wait); in aead_accept_parent_nokey()
548 ask->private = ctx; in aead_accept_parent_nokey()
550 sk->sk_destruct = aead_sock_destruct; in aead_accept_parent_nokey()
559 if (crypto_aead_get_flags(tfm->aead) & CRYPTO_TFM_NEED_KEY) in aead_accept_parent()
560 return -ENOKEY; in aead_accept_parent()