Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: omap-aes-gcm - fix failure with assocdata only

If we only have assocdata with an omap-aes-gcm, it currently just
completes it directly without passing it over to the crypto HW. This
produces wrong results.

Fix by passing the request down to the crypto HW, and fix the DMA
support code to accept a case where we don't expect any output data.
In the case where only assocdata is provided, it just passes through
the accelerator and provides authentication results, without any
encrypted/decrypted buffer via DMA.

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Tero Kristo and committed by
Herbert Xu
5d5f3eed f0956d42

+42 -27
+1 -1
drivers/crypto/omap-aes-gcm.c
··· 244 244 245 245 err = omap_aes_write_ctrl(dd); 246 246 if (!err) { 247 - if (dd->in_sg_len && dd->out_sg_len) 247 + if (dd->in_sg_len) 248 248 err = omap_aes_crypt_dma_start(dd); 249 249 else 250 250 omap_aes_gcm_dma_out_callback(dd);
+41 -26
drivers/crypto/omap-aes.c
··· 269 269 struct scatterlist *out_sg, 270 270 int in_sg_len, int out_sg_len) 271 271 { 272 - struct dma_async_tx_descriptor *tx_in, *tx_out; 272 + struct dma_async_tx_descriptor *tx_in, *tx_out = NULL, *cb_desc; 273 273 struct dma_slave_config cfg; 274 274 int ret; 275 275 276 276 if (dd->pio_only) { 277 277 scatterwalk_start(&dd->in_walk, dd->in_sg); 278 - scatterwalk_start(&dd->out_walk, dd->out_sg); 278 + if (out_sg_len) 279 + scatterwalk_start(&dd->out_walk, dd->out_sg); 279 280 280 281 /* Enable DATAIN interrupt and let it take 281 282 care of the rest */ ··· 313 312 314 313 /* No callback necessary */ 315 314 tx_in->callback_param = dd; 315 + tx_in->callback = NULL; 316 316 317 317 /* OUT */ 318 - ret = dmaengine_slave_config(dd->dma_lch_out, &cfg); 319 - if (ret) { 320 - dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", 321 - ret); 322 - return ret; 323 - } 318 + if (out_sg_len) { 319 + ret = dmaengine_slave_config(dd->dma_lch_out, &cfg); 320 + if (ret) { 321 + dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", 322 + ret); 323 + return ret; 324 + } 324 325 325 - tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, out_sg_len, 326 - DMA_DEV_TO_MEM, 327 - DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 328 - if (!tx_out) { 329 - dev_err(dd->dev, "OUT prep_slave_sg() failed\n"); 330 - return -EINVAL; 326 + tx_out = dmaengine_prep_slave_sg(dd->dma_lch_out, out_sg, 327 + out_sg_len, 328 + DMA_DEV_TO_MEM, 329 + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 330 + if (!tx_out) { 331 + dev_err(dd->dev, "OUT prep_slave_sg() failed\n"); 332 + return -EINVAL; 333 + } 334 + 335 + cb_desc = tx_out; 336 + } else { 337 + cb_desc = tx_in; 331 338 } 332 339 333 340 if (dd->flags & FLAGS_GCM) 334 - tx_out->callback = omap_aes_gcm_dma_out_callback; 341 + cb_desc->callback = omap_aes_gcm_dma_out_callback; 335 342 else 336 - tx_out->callback = omap_aes_dma_out_callback; 337 - tx_out->callback_param = dd; 343 + cb_desc->callback = omap_aes_dma_out_callback; 344 + cb_desc->callback_param = dd; 345 + 338 346 339 347 dmaengine_submit(tx_in); 340 - dmaengine_submit(tx_out); 348 + if (tx_out) 349 + dmaengine_submit(tx_out); 341 350 342 351 dma_async_issue_pending(dd->dma_lch_in); 343 - dma_async_issue_pending(dd->dma_lch_out); 352 + if (out_sg_len) 353 + dma_async_issue_pending(dd->dma_lch_out); 344 354 345 355 /* start DMA */ 346 356 dd->pdata->trigger(dd, dd->total); ··· 373 361 return -EINVAL; 374 362 } 375 363 376 - err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len, 377 - DMA_FROM_DEVICE); 378 - if (!err) { 379 - dev_err(dd->dev, "dma_map_sg() error\n"); 380 - return -EINVAL; 364 + if (dd->out_sg_len) { 365 + err = dma_map_sg(dd->dev, dd->out_sg, dd->out_sg_len, 366 + DMA_FROM_DEVICE); 367 + if (!err) { 368 + dev_err(dd->dev, "dma_map_sg() error\n"); 369 + return -EINVAL; 370 + } 381 371 } 382 372 } 383 373 ··· 387 373 dd->out_sg_len); 388 374 if (err && !dd->pio_only) { 389 375 dma_unmap_sg(dd->dev, dd->in_sg, dd->in_sg_len, DMA_TO_DEVICE); 390 - dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, 391 - DMA_FROM_DEVICE); 376 + if (dd->out_sg_len) 377 + dma_unmap_sg(dd->dev, dd->out_sg, dd->out_sg_len, 378 + DMA_FROM_DEVICE); 392 379 } 393 380 394 381 return err;