@@ -96,9 +96,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
9696 struct aead_tfm * aeadc = pask -> private ;
9797 struct crypto_aead * tfm = aeadc -> aead ;
9898 struct crypto_sync_skcipher * null_tfm = aeadc -> null_tfm ;
99- unsigned int i , as = crypto_aead_authsize (tfm );
99+ unsigned int as = crypto_aead_authsize (tfm );
100100 struct af_alg_async_req * areq ;
101- struct af_alg_tsgl * tsgl , * tmp ;
102101 struct scatterlist * rsgl_src , * tsgl_src = NULL ;
103102 int err = 0 ;
104103 size_t used = 0 ; /* [in] TX bufs to be en/decrypted */
@@ -178,23 +177,24 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
178177 outlen -= less ;
179178 }
180179
180+ /*
181+ * Create a per request TX SGL for this request which tracks the
182+ * SG entries from the global TX SGL.
183+ */
181184 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 ;
185+ areq -> tsgl_entries = af_alg_count_tsgl (sk , processed );
186+ if (!areq -> tsgl_entries )
187+ areq -> tsgl_entries = 1 ;
188+ areq -> tsgl = sock_kmalloc (sk , array_size (sizeof (* areq -> tsgl ),
189+ areq -> tsgl_entries ),
190+ GFP_KERNEL );
191+ if (!areq -> tsgl ) {
192+ err = - ENOMEM ;
196193 goto free ;
197194 }
195+ sg_init_table (areq -> tsgl , areq -> tsgl_entries );
196+ af_alg_pull_tsgl (sk , processed , areq -> tsgl );
197+ tsgl_src = areq -> tsgl ;
198198
199199 /*
200200 * Copy of AAD from source to destination
@@ -203,81 +203,18 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
203203 * when user space uses an in-place cipher operation, the kernel
204204 * will copy the data as it does not see whether such in-place operation
205205 * 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.
210206 */
211207
212- /* Use the RX SGL as source (and destination) for crypto op . */
208+ /* Use the RX SGL as destination; TX SGL as crypto source . */
213209 rsgl_src = areq -> first_rsgl .sgl .sg ;
214210
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 .sg , processed );
228- if (err )
229- goto free ;
230- af_alg_pull_tsgl (sk , processed , NULL , 0 );
231- } else {
232- /*
233- * Decryption operation - To achieve an in-place cipher
234- * operation, the following SGL structure is used:
235- *
236- * TX SGL: AAD || CT || Tag
237- * | | ^
238- * | copy | | Create SGL link.
239- * v v |
240- * RX SGL: AAD || CT ----+
241- */
242-
243- /* Copy AAD || CT to RX SGL buffer for in-place operation. */
244- err = crypto_aead_copy_sgl (null_tfm , tsgl_src ,
245- areq -> first_rsgl .sgl .sg , outlen );
246- if (err )
247- goto free ;
248-
249- /* Create TX SGL for tag and chain it to RX SGL. */
250- areq -> tsgl_entries = af_alg_count_tsgl (sk , processed ,
251- processed - as );
252- if (!areq -> tsgl_entries )
253- areq -> tsgl_entries = 1 ;
254- areq -> tsgl = sock_kmalloc (sk , array_size (sizeof (* areq -> tsgl ),
255- areq -> tsgl_entries ),
256- GFP_KERNEL );
257- if (!areq -> tsgl ) {
258- err = - ENOMEM ;
259- goto free ;
260- }
261- sg_init_table (areq -> tsgl , areq -> tsgl_entries );
262-
263- /* Release TX SGL, except for tag data and reassign tag data. */
264- af_alg_pull_tsgl (sk , processed , areq -> tsgl , processed - as );
265-
266- /* chain the areq TX SGL holding the tag with RX SGL */
267- if (usedpages ) {
268- /* RX SGL present */
269- struct af_alg_sgl * sgl_prev = & areq -> last_rsgl -> sgl ;
270-
271- sg_unmark_end (sgl_prev -> sg + sgl_prev -> npages - 1 );
272- sg_chain (sgl_prev -> sg , sgl_prev -> npages + 1 ,
273- areq -> tsgl );
274- } else
275- /* no RX SGL present (e.g. authentication only) */
276- rsgl_src = areq -> tsgl ;
277- }
211+ err = crypto_aead_copy_sgl (null_tfm , tsgl_src , rsgl_src ,
212+ ctx -> aead_assoclen );
213+ if (err )
214+ goto free ;
278215
279216 /* Initialize the crypto operation */
280- aead_request_set_crypt (& areq -> cra_u .aead_req , rsgl_src ,
217+ aead_request_set_crypt (& areq -> cra_u .aead_req , tsgl_src ,
281218 areq -> first_rsgl .sgl .sg , used , ctx -> iv );
282219 aead_request_set_ad (& areq -> cra_u .aead_req , ctx -> aead_assoclen );
283220 aead_request_set_tfm (& areq -> cra_u .aead_req , tfm );
@@ -526,7 +463,7 @@ static void aead_sock_destruct(struct sock *sk)
526463 struct crypto_aead * tfm = aeadc -> aead ;
527464 unsigned int ivlen = crypto_aead_ivsize (tfm );
528465
529- af_alg_pull_tsgl (sk , ctx -> used , NULL , 0 );
466+ af_alg_pull_tsgl (sk , ctx -> used , NULL );
530467 sock_kzfree_s (sk , ctx -> iv , ivlen );
531468 sock_kfree_s (sk , ctx , ctx -> len );
532469 af_alg_release_parent (sk );
0 commit comments