2626#include <crypto/internal/aead.h>
2727#include <crypto/scatterwalk.h>
2828#include <crypto/if_alg.h>
29- #include <crypto/skcipher.h>
3029#include <crypto/null.h>
3130#include <linux/init.h>
3231#include <linux/list.h>
@@ -96,9 +95,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
9695 struct aead_tfm * aeadc = pask -> private ;
9796 struct crypto_aead * tfm = aeadc -> aead ;
9897 struct crypto_sync_skcipher * null_tfm = aeadc -> null_tfm ;
99- unsigned int i , as = crypto_aead_authsize (tfm );
98+ unsigned int as = crypto_aead_authsize (tfm );
10099 struct af_alg_async_req * areq ;
101- struct af_alg_tsgl * tsgl , * tmp ;
102100 struct scatterlist * rsgl_src , * tsgl_src = NULL ;
103101 int err = 0 ;
104102 size_t used = 0 ; /* [in] TX bufs to be en/decrypted */
@@ -178,23 +176,24 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
178176 outlen -= less ;
179177 }
180178
179+ /*
180+ * Create a per request TX SGL for this request which tracks the
181+ * SG entries from the global TX SGL.
182+ */
181183 processed = used + ctx -> aead_assoclen ;
182- list_for_each_entry_safe (tsgl , tmp , & ctx -> tsgl_list , list ) {
183- for (i = 0 ; i < tsgl -> cur ; i ++ ) {
184- struct scatterlist * process_sg = tsgl -> sg + i ;
185-
186- if (!(process_sg -> length ) || !sg_page (process_sg ))
187- continue ;
188- tsgl_src = process_sg ;
189- break ;
190- }
191- if (tsgl_src )
192- break ;
193- }
194- if (processed && !tsgl_src ) {
195- err = - EFAULT ;
184+ areq -> tsgl_entries = af_alg_count_tsgl (sk , processed );
185+ if (!areq -> tsgl_entries )
186+ areq -> tsgl_entries = 1 ;
187+ areq -> tsgl = sock_kmalloc (sk , array_size (sizeof (* areq -> tsgl ),
188+ areq -> tsgl_entries ),
189+ GFP_KERNEL );
190+ if (!areq -> tsgl ) {
191+ err = - ENOMEM ;
196192 goto free ;
197193 }
194+ sg_init_table (areq -> tsgl , areq -> tsgl_entries );
195+ af_alg_pull_tsgl (sk , processed , areq -> tsgl );
196+ tsgl_src = areq -> tsgl ;
198197
199198 /*
200199 * Copy of AAD from source to destination
@@ -203,83 +202,18 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
203202 * when user space uses an in-place cipher operation, the kernel
204203 * will copy the data as it does not see whether such in-place operation
205204 * is initiated.
206- *
207- * To ensure efficiency, the following implementation ensure that the
208- * ciphers are invoked to perform a crypto operation in-place. This
209- * is achieved by memory management specified as follows.
210205 */
211206
212- /* Use the RX SGL as source (and destination) for crypto op . */
207+ /* Use the RX SGL as destination; TX SGL as crypto source . */
213208 rsgl_src = areq -> first_rsgl .sgl .sgt .sgl ;
214209
215- if (ctx -> enc ) {
216- /*
217- * Encryption operation - The in-place cipher operation is
218- * achieved by the following operation:
219- *
220- * TX SGL: AAD || PT
221- * | |
222- * | copy |
223- * v v
224- * RX SGL: AAD || PT || Tag
225- */
226- err = crypto_aead_copy_sgl (null_tfm , tsgl_src ,
227- areq -> first_rsgl .sgl .sgt .sgl ,
228- processed );
229- if (err )
230- goto free ;
231- af_alg_pull_tsgl (sk , processed , NULL , 0 );
232- } else {
233- /*
234- * Decryption operation - To achieve an in-place cipher
235- * operation, the following SGL structure is used:
236- *
237- * TX SGL: AAD || CT || Tag
238- * | | ^
239- * | copy | | Create SGL link.
240- * v v |
241- * RX SGL: AAD || CT ----+
242- */
243-
244- /* Copy AAD || CT to RX SGL buffer for in-place operation. */
245- err = crypto_aead_copy_sgl (null_tfm , tsgl_src ,
246- areq -> first_rsgl .sgl .sgt .sgl ,
247- outlen );
248- if (err )
249- goto free ;
250-
251- /* Create TX SGL for tag and chain it to RX SGL. */
252- areq -> tsgl_entries = af_alg_count_tsgl (sk , processed ,
253- processed - as );
254- if (!areq -> tsgl_entries )
255- areq -> tsgl_entries = 1 ;
256- areq -> tsgl = sock_kmalloc (sk , array_size (sizeof (* areq -> tsgl ),
257- areq -> tsgl_entries ),
258- GFP_KERNEL );
259- if (!areq -> tsgl ) {
260- err = - ENOMEM ;
261- goto free ;
262- }
263- sg_init_table (areq -> tsgl , areq -> tsgl_entries );
264-
265- /* Release TX SGL, except for tag data and reassign tag data. */
266- af_alg_pull_tsgl (sk , processed , areq -> tsgl , processed - as );
267-
268- /* chain the areq TX SGL holding the tag with RX SGL */
269- if (usedpages ) {
270- /* RX SGL present */
271- struct af_alg_sgl * sgl_prev = & areq -> last_rsgl -> sgl ;
272- struct scatterlist * sg = sgl_prev -> sgt .sgl ;
273-
274- sg_unmark_end (sg + sgl_prev -> sgt .nents - 1 );
275- sg_chain (sg , sgl_prev -> sgt .nents + 1 , areq -> tsgl );
276- } else
277- /* no RX SGL present (e.g. authentication only) */
278- rsgl_src = areq -> tsgl ;
279- }
210+ err = crypto_aead_copy_sgl (null_tfm , tsgl_src , rsgl_src ,
211+ ctx -> aead_assoclen );
212+ if (err )
213+ goto free ;
280214
281215 /* Initialize the crypto operation */
282- aead_request_set_crypt (& areq -> cra_u .aead_req , rsgl_src ,
216+ aead_request_set_crypt (& areq -> cra_u .aead_req , tsgl_src ,
283217 areq -> first_rsgl .sgl .sgt .sgl , used , ctx -> iv );
284218 aead_request_set_ad (& areq -> cra_u .aead_req , ctx -> aead_assoclen );
285219 aead_request_set_tfm (& areq -> cra_u .aead_req , tfm );
@@ -514,7 +448,7 @@ static void aead_sock_destruct(struct sock *sk)
514448 struct crypto_aead * tfm = aeadc -> aead ;
515449 unsigned int ivlen = crypto_aead_ivsize (tfm );
516450
517- af_alg_pull_tsgl (sk , ctx -> used , NULL , 0 );
451+ af_alg_pull_tsgl (sk , ctx -> used , NULL );
518452 sock_kzfree_s (sk , ctx -> iv , ivlen );
519453 sock_kfree_s (sk , ctx , ctx -> len );
520454 af_alg_release_parent (sk );
0 commit comments