forked from mirrors/linux
		
	crypto: af_alg - add async support to algif_aead
Following the async change for algif_skcipher this patch adds similar async read to algif_aead. changes in v3: - add call to aead_reset_ctx directly from aead_put_sgl instead of calling them separatelly one after the other - remove wait from aead_sock_destruct function as it is not needed when sock_hold is used changes in v2: - change internal data structures from fixed size arrays, limited to RSGL_MAX_ENTRIES, to linked list model with no artificial limitation. - use sock_kmalloc instead of kmalloc for memory allocation - use sock_hold instead of separate atomic ctr to wait for outstanding request Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									47cd30608f
								
							
						
					
					
						commit
						83094e5e9e
					
				
					 1 changed files with 237 additions and 31 deletions
				
			
		|  | @ -13,7 +13,7 @@ | ||||||
|  * any later version. |  * any later version. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include <crypto/aead.h> | #include <crypto/internal/aead.h> | ||||||
| #include <crypto/scatterwalk.h> | #include <crypto/scatterwalk.h> | ||||||
| #include <crypto/if_alg.h> | #include <crypto/if_alg.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
|  | @ -29,15 +29,24 @@ struct aead_sg_list { | ||||||
| 	struct scatterlist sg[ALG_MAX_PAGES]; | 	struct scatterlist sg[ALG_MAX_PAGES]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct aead_async_rsgl { | ||||||
|  | 	struct af_alg_sgl sgl; | ||||||
|  | 	struct list_head list; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct aead_async_req { | ||||||
|  | 	struct scatterlist *tsgl; | ||||||
|  | 	struct aead_async_rsgl first_rsgl; | ||||||
|  | 	struct list_head list; | ||||||
|  | 	struct kiocb *iocb; | ||||||
|  | 	unsigned int tsgls; | ||||||
|  | 	char iv[]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct aead_ctx { | struct aead_ctx { | ||||||
| 	struct aead_sg_list tsgl; | 	struct aead_sg_list tsgl; | ||||||
| 	/*
 | 	struct aead_async_rsgl first_rsgl; | ||||||
| 	 * RSGL_MAX_ENTRIES is an artificial limit where user space at maximum | 	struct list_head list; | ||||||
| 	 * can cause the kernel to allocate RSGL_MAX_ENTRIES * ALG_MAX_PAGES |  | ||||||
| 	 * pages |  | ||||||
| 	 */ |  | ||||||
| #define RSGL_MAX_ENTRIES ALG_MAX_PAGES |  | ||||||
| 	struct af_alg_sgl rsgl[RSGL_MAX_ENTRIES]; |  | ||||||
| 
 | 
 | ||||||
| 	void *iv; | 	void *iv; | ||||||
| 
 | 
 | ||||||
|  | @ -75,6 +84,17 @@ static inline bool aead_sufficient_data(struct aead_ctx *ctx) | ||||||
| 	return ctx->used >= ctx->aead_assoclen + as; | 	return ctx->used >= ctx->aead_assoclen + as; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void aead_reset_ctx(struct aead_ctx *ctx) | ||||||
|  | { | ||||||
|  | 	struct aead_sg_list *sgl = &ctx->tsgl; | ||||||
|  | 
 | ||||||
|  | 	sg_init_table(sgl->sg, ALG_MAX_PAGES); | ||||||
|  | 	sgl->cur = 0; | ||||||
|  | 	ctx->used = 0; | ||||||
|  | 	ctx->more = 0; | ||||||
|  | 	ctx->merge = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void aead_put_sgl(struct sock *sk) | static void aead_put_sgl(struct sock *sk) | ||||||
| { | { | ||||||
| 	struct alg_sock *ask = alg_sk(sk); | 	struct alg_sock *ask = alg_sk(sk); | ||||||
|  | @ -90,11 +110,7 @@ static void aead_put_sgl(struct sock *sk) | ||||||
| 		put_page(sg_page(sg + i)); | 		put_page(sg_page(sg + i)); | ||||||
| 		sg_assign_page(sg + i, NULL); | 		sg_assign_page(sg + i, NULL); | ||||||
| 	} | 	} | ||||||
| 	sg_init_table(sg, ALG_MAX_PAGES); | 	aead_reset_ctx(ctx); | ||||||
| 	sgl->cur = 0; |  | ||||||
| 	ctx->used = 0; |  | ||||||
| 	ctx->more = 0; |  | ||||||
| 	ctx->merge = 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void aead_wmem_wakeup(struct sock *sk) | static void aead_wmem_wakeup(struct sock *sk) | ||||||
|  | @ -349,23 +365,188 @@ static ssize_t aead_sendpage(struct socket *sock, struct page *page, | ||||||
| 	return err ?: size; | 	return err ?: size; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) | #define GET_ASYM_REQ(req, tfm) (struct aead_async_req *) \ | ||||||
|  | 		((char *)req + sizeof(struct aead_request) + \ | ||||||
|  | 		 crypto_aead_reqsize(tfm)) | ||||||
|  | 
 | ||||||
|  |  #define GET_REQ_SIZE(tfm) sizeof(struct aead_async_req) + \ | ||||||
|  | 	crypto_aead_reqsize(tfm) + crypto_aead_ivsize(tfm) + \ | ||||||
|  | 	sizeof(struct aead_request) | ||||||
|  | 
 | ||||||
|  | static void aead_async_cb(struct crypto_async_request *_req, int err) | ||||||
|  | { | ||||||
|  | 	struct sock *sk = _req->data; | ||||||
|  | 	struct alg_sock *ask = alg_sk(sk); | ||||||
|  | 	struct aead_ctx *ctx = ask->private; | ||||||
|  | 	struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req); | ||||||
|  | 	struct aead_request *req = aead_request_cast(_req); | ||||||
|  | 	struct aead_async_req *areq = GET_ASYM_REQ(req, tfm); | ||||||
|  | 	struct scatterlist *sg = areq->tsgl; | ||||||
|  | 	struct aead_async_rsgl *rsgl; | ||||||
|  | 	struct kiocb *iocb = areq->iocb; | ||||||
|  | 	unsigned int i, reqlen = GET_REQ_SIZE(tfm); | ||||||
|  | 
 | ||||||
|  | 	list_for_each_entry(rsgl, &areq->list, list) { | ||||||
|  | 		af_alg_free_sg(&rsgl->sgl); | ||||||
|  | 		if (rsgl != &areq->first_rsgl) | ||||||
|  | 			sock_kfree_s(sk, rsgl, sizeof(*rsgl)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for (i = 0; i < areq->tsgls; i++) | ||||||
|  | 		put_page(sg_page(sg + i)); | ||||||
|  | 
 | ||||||
|  | 	sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls); | ||||||
|  | 	sock_kfree_s(sk, req, reqlen); | ||||||
|  | 	__sock_put(sk); | ||||||
|  | 	iocb->ki_complete(iocb, err, err); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int aead_recvmsg_async(struct socket *sock, struct msghdr *msg, | ||||||
|  | 			      int flags) | ||||||
|  | { | ||||||
|  | 	struct sock *sk = sock->sk; | ||||||
|  | 	struct alg_sock *ask = alg_sk(sk); | ||||||
|  | 	struct aead_ctx *ctx = ask->private; | ||||||
|  | 	struct crypto_aead *tfm = crypto_aead_reqtfm(&ctx->aead_req); | ||||||
|  | 	struct aead_async_req *areq; | ||||||
|  | 	struct aead_request *req = NULL; | ||||||
|  | 	struct aead_sg_list *sgl = &ctx->tsgl; | ||||||
|  | 	struct aead_async_rsgl *last_rsgl = NULL, *rsgl; | ||||||
|  | 	unsigned int as = crypto_aead_authsize(tfm); | ||||||
|  | 	unsigned int i, reqlen = GET_REQ_SIZE(tfm); | ||||||
|  | 	int err = -ENOMEM; | ||||||
|  | 	unsigned long used; | ||||||
|  | 	size_t outlen; | ||||||
|  | 	size_t usedpages = 0; | ||||||
|  | 
 | ||||||
|  | 	lock_sock(sk); | ||||||
|  | 	if (ctx->more) { | ||||||
|  | 		err = aead_wait_for_data(sk, flags); | ||||||
|  | 		if (err) | ||||||
|  | 			goto unlock; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	used = ctx->used; | ||||||
|  | 	outlen = used; | ||||||
|  | 
 | ||||||
|  | 	if (!aead_sufficient_data(ctx)) | ||||||
|  | 		goto unlock; | ||||||
|  | 
 | ||||||
|  | 	req = sock_kmalloc(sk, reqlen, GFP_KERNEL); | ||||||
|  | 	if (unlikely(!req)) | ||||||
|  | 		goto unlock; | ||||||
|  | 
 | ||||||
|  | 	areq = GET_ASYM_REQ(req, tfm); | ||||||
|  | 	memset(&areq->first_rsgl, '\0', sizeof(areq->first_rsgl)); | ||||||
|  | 	INIT_LIST_HEAD(&areq->list); | ||||||
|  | 	areq->iocb = msg->msg_iocb; | ||||||
|  | 	memcpy(areq->iv, ctx->iv, crypto_aead_ivsize(tfm)); | ||||||
|  | 	aead_request_set_tfm(req, tfm); | ||||||
|  | 	aead_request_set_ad(req, ctx->aead_assoclen); | ||||||
|  | 	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, | ||||||
|  | 				  aead_async_cb, sk); | ||||||
|  | 	used -= ctx->aead_assoclen + (ctx->enc ? as : 0); | ||||||
|  | 
 | ||||||
|  | 	/* take over all tx sgls from ctx */ | ||||||
|  | 	areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * sgl->cur, | ||||||
|  | 				  GFP_KERNEL); | ||||||
|  | 	if (unlikely(!areq->tsgl)) | ||||||
|  | 		goto free; | ||||||
|  | 
 | ||||||
|  | 	sg_init_table(areq->tsgl, sgl->cur); | ||||||
|  | 	for (i = 0; i < sgl->cur; i++) | ||||||
|  | 		sg_set_page(&areq->tsgl[i], sg_page(&sgl->sg[i]), | ||||||
|  | 			    sgl->sg[i].length, sgl->sg[i].offset); | ||||||
|  | 
 | ||||||
|  | 	areq->tsgls = sgl->cur; | ||||||
|  | 
 | ||||||
|  | 	/* create rx sgls */ | ||||||
|  | 	while (iov_iter_count(&msg->msg_iter)) { | ||||||
|  | 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), | ||||||
|  | 				      (outlen - usedpages)); | ||||||
|  | 
 | ||||||
|  | 		if (list_empty(&areq->list)) { | ||||||
|  | 			rsgl = &areq->first_rsgl; | ||||||
|  | 
 | ||||||
|  | 		} else { | ||||||
|  | 			rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL); | ||||||
|  | 			if (unlikely(!rsgl)) { | ||||||
|  | 				err = -ENOMEM; | ||||||
|  | 				goto free; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		rsgl->sgl.npages = 0; | ||||||
|  | 		list_add_tail(&rsgl->list, &areq->list); | ||||||
|  | 
 | ||||||
|  | 		/* make one iovec available as scatterlist */ | ||||||
|  | 		err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); | ||||||
|  | 		if (err < 0) | ||||||
|  | 			goto free; | ||||||
|  | 
 | ||||||
|  | 		usedpages += err; | ||||||
|  | 
 | ||||||
|  | 		/* chain the new scatterlist with previous one */ | ||||||
|  | 		if (last_rsgl) | ||||||
|  | 			af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl); | ||||||
|  | 
 | ||||||
|  | 		last_rsgl = rsgl; | ||||||
|  | 
 | ||||||
|  | 		/* we do not need more iovecs as we have sufficient memory */ | ||||||
|  | 		if (outlen <= usedpages) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		iov_iter_advance(&msg->msg_iter, err); | ||||||
|  | 	} | ||||||
|  | 	err = -EINVAL; | ||||||
|  | 	/* ensure output buffer is sufficiently large */ | ||||||
|  | 	if (usedpages < outlen) | ||||||
|  | 		goto free; | ||||||
|  | 
 | ||||||
|  | 	aead_request_set_crypt(req, areq->tsgl, areq->first_rsgl.sgl.sg, used, | ||||||
|  | 			       areq->iv); | ||||||
|  | 	err = ctx->enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); | ||||||
|  | 	if (err) { | ||||||
|  | 		if (err == -EINPROGRESS) { | ||||||
|  | 			sock_hold(sk); | ||||||
|  | 			err = -EIOCBQUEUED; | ||||||
|  | 			aead_reset_ctx(ctx); | ||||||
|  | 			goto unlock; | ||||||
|  | 		} else if (err == -EBADMSG) { | ||||||
|  | 			aead_put_sgl(sk); | ||||||
|  | 		} | ||||||
|  | 		goto free; | ||||||
|  | 	} | ||||||
|  | 	aead_put_sgl(sk); | ||||||
|  | 
 | ||||||
|  | free: | ||||||
|  | 	list_for_each_entry(rsgl, &areq->list, list) { | ||||||
|  | 		af_alg_free_sg(&rsgl->sgl); | ||||||
|  | 		if (rsgl != &areq->first_rsgl) | ||||||
|  | 			sock_kfree_s(sk, rsgl, sizeof(*rsgl)); | ||||||
|  | 	} | ||||||
|  | 	if (areq->tsgl) | ||||||
|  | 		sock_kfree_s(sk, areq->tsgl, sizeof(*areq->tsgl) * areq->tsgls); | ||||||
|  | 	if (req) | ||||||
|  | 		sock_kfree_s(sk, req, reqlen); | ||||||
|  | unlock: | ||||||
|  | 	aead_wmem_wakeup(sk); | ||||||
|  | 	release_sock(sk); | ||||||
|  | 	return err ? err : outlen; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int aead_recvmsg_sync(struct socket *sock, struct msghdr *msg, int flags) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	struct alg_sock *ask = alg_sk(sk); | 	struct alg_sock *ask = alg_sk(sk); | ||||||
| 	struct aead_ctx *ctx = ask->private; | 	struct aead_ctx *ctx = ask->private; | ||||||
| 	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); | 	unsigned as = crypto_aead_authsize(crypto_aead_reqtfm(&ctx->aead_req)); | ||||||
| 	struct aead_sg_list *sgl = &ctx->tsgl; | 	struct aead_sg_list *sgl = &ctx->tsgl; | ||||||
| 	unsigned int i = 0; | 	struct aead_async_rsgl *last_rsgl = NULL; | ||||||
|  | 	struct aead_async_rsgl *rsgl, *tmp; | ||||||
| 	int err = -EINVAL; | 	int err = -EINVAL; | ||||||
| 	unsigned long used = 0; | 	unsigned long used = 0; | ||||||
| 	size_t outlen = 0; | 	size_t outlen = 0; | ||||||
| 	size_t usedpages = 0; | 	size_t usedpages = 0; | ||||||
| 	unsigned int cnt = 0; |  | ||||||
| 
 |  | ||||||
| 	/* Limit number of IOV blocks to be accessed below */ |  | ||||||
| 	if (msg->msg_iter.nr_segs > RSGL_MAX_ENTRIES) |  | ||||||
| 		return -ENOMSG; |  | ||||||
| 
 | 
 | ||||||
| 	lock_sock(sk); | 	lock_sock(sk); | ||||||
| 
 | 
 | ||||||
|  | @ -417,21 +598,33 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | ||||||
| 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), | 		size_t seglen = min_t(size_t, iov_iter_count(&msg->msg_iter), | ||||||
| 				      (outlen - usedpages)); | 				      (outlen - usedpages)); | ||||||
| 
 | 
 | ||||||
|  | 		if (list_empty(&ctx->list)) { | ||||||
|  | 			rsgl = &ctx->first_rsgl; | ||||||
|  | 		} else { | ||||||
|  | 			rsgl = sock_kmalloc(sk, sizeof(*rsgl), GFP_KERNEL); | ||||||
|  | 			if (unlikely(!rsgl)) { | ||||||
|  | 				err = -ENOMEM; | ||||||
|  | 				goto unlock; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		rsgl->sgl.npages = 0; | ||||||
|  | 		list_add_tail(&rsgl->list, &ctx->list); | ||||||
|  | 
 | ||||||
| 		/* make one iovec available as scatterlist */ | 		/* make one iovec available as scatterlist */ | ||||||
| 		err = af_alg_make_sg(&ctx->rsgl[cnt], &msg->msg_iter, | 		err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); | ||||||
| 				     seglen); |  | ||||||
| 		if (err < 0) | 		if (err < 0) | ||||||
| 			goto unlock; | 			goto unlock; | ||||||
| 		usedpages += err; | 		usedpages += err; | ||||||
| 		/* chain the new scatterlist with previous one */ | 		/* chain the new scatterlist with previous one */ | ||||||
| 		if (cnt) | 		if (last_rsgl) | ||||||
| 			af_alg_link_sg(&ctx->rsgl[cnt-1], &ctx->rsgl[cnt]); | 			af_alg_link_sg(&last_rsgl->sgl, &rsgl->sgl); | ||||||
|  | 
 | ||||||
|  | 		last_rsgl = rsgl; | ||||||
| 
 | 
 | ||||||
| 		/* we do not need more iovecs as we have sufficient memory */ | 		/* we do not need more iovecs as we have sufficient memory */ | ||||||
| 		if (outlen <= usedpages) | 		if (outlen <= usedpages) | ||||||
| 			break; | 			break; | ||||||
| 		iov_iter_advance(&msg->msg_iter, err); | 		iov_iter_advance(&msg->msg_iter, err); | ||||||
| 		cnt++; |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	err = -EINVAL; | 	err = -EINVAL; | ||||||
|  | @ -440,8 +633,7 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | ||||||
| 		goto unlock; | 		goto unlock; | ||||||
| 
 | 
 | ||||||
| 	sg_mark_end(sgl->sg + sgl->cur - 1); | 	sg_mark_end(sgl->sg + sgl->cur - 1); | ||||||
| 
 | 	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->first_rsgl.sgl.sg, | ||||||
| 	aead_request_set_crypt(&ctx->aead_req, sgl->sg, ctx->rsgl[0].sg, |  | ||||||
| 			       used, ctx->iv); | 			       used, ctx->iv); | ||||||
| 	aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen); | 	aead_request_set_ad(&ctx->aead_req, ctx->aead_assoclen); | ||||||
| 
 | 
 | ||||||
|  | @ -454,23 +646,35 @@ static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | ||||||
| 		/* EBADMSG implies a valid cipher operation took place */ | 		/* EBADMSG implies a valid cipher operation took place */ | ||||||
| 		if (err == -EBADMSG) | 		if (err == -EBADMSG) | ||||||
| 			aead_put_sgl(sk); | 			aead_put_sgl(sk); | ||||||
|  | 
 | ||||||
| 		goto unlock; | 		goto unlock; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	aead_put_sgl(sk); | 	aead_put_sgl(sk); | ||||||
| 
 |  | ||||||
| 	err = 0; | 	err = 0; | ||||||
| 
 | 
 | ||||||
| unlock: | unlock: | ||||||
| 	for (i = 0; i < cnt; i++) | 	list_for_each_entry_safe(rsgl, tmp, &ctx->list, list) { | ||||||
| 		af_alg_free_sg(&ctx->rsgl[i]); | 		af_alg_free_sg(&rsgl->sgl); | ||||||
| 
 | 		if (rsgl != &ctx->first_rsgl) | ||||||
|  | 			sock_kfree_s(sk, rsgl, sizeof(*rsgl)); | ||||||
|  | 		list_del(&rsgl->list); | ||||||
|  | 	} | ||||||
|  | 	INIT_LIST_HEAD(&ctx->list); | ||||||
| 	aead_wmem_wakeup(sk); | 	aead_wmem_wakeup(sk); | ||||||
| 	release_sock(sk); | 	release_sock(sk); | ||||||
| 
 | 
 | ||||||
| 	return err ? err : outlen; | 	return err ? err : outlen; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int aead_recvmsg(struct socket *sock, struct msghdr *msg, size_t ignored, | ||||||
|  | 			int flags) | ||||||
|  | { | ||||||
|  | 	return (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) ? | ||||||
|  | 		aead_recvmsg_async(sock, msg, flags) : | ||||||
|  | 		aead_recvmsg_sync(sock, msg, flags); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static unsigned int aead_poll(struct file *file, struct socket *sock, | static unsigned int aead_poll(struct file *file, struct socket *sock, | ||||||
| 			      poll_table *wait) | 			      poll_table *wait) | ||||||
| { | { | ||||||
|  | @ -540,6 +744,7 @@ static void aead_sock_destruct(struct sock *sk) | ||||||
| 	unsigned int ivlen = crypto_aead_ivsize( | 	unsigned int ivlen = crypto_aead_ivsize( | ||||||
| 				crypto_aead_reqtfm(&ctx->aead_req)); | 				crypto_aead_reqtfm(&ctx->aead_req)); | ||||||
| 
 | 
 | ||||||
|  | 	WARN_ON(atomic_read(&sk->sk_refcnt) != 0); | ||||||
| 	aead_put_sgl(sk); | 	aead_put_sgl(sk); | ||||||
| 	sock_kzfree_s(sk, ctx->iv, ivlen); | 	sock_kzfree_s(sk, ctx->iv, ivlen); | ||||||
| 	sock_kfree_s(sk, ctx, ctx->len); | 	sock_kfree_s(sk, ctx, ctx->len); | ||||||
|  | @ -574,6 +779,7 @@ static int aead_accept_parent(void *private, struct sock *sk) | ||||||
| 	ctx->aead_assoclen = 0; | 	ctx->aead_assoclen = 0; | ||||||
| 	af_alg_init_completion(&ctx->completion); | 	af_alg_init_completion(&ctx->completion); | ||||||
| 	sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES); | 	sg_init_table(ctx->tsgl.sg, ALG_MAX_PAGES); | ||||||
|  | 	INIT_LIST_HEAD(&ctx->list); | ||||||
| 
 | 
 | ||||||
| 	ask->private = ctx; | 	ask->private = ctx; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Tadeusz Struk
						Tadeusz Struk