summaryrefslogtreecommitdiffstats
path: root/drivers/crypto
diff options
context:
space:
mode:
authorZhang Zhijie <zhangzj@rock-chips.com>2019-02-13 03:24:39 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2019-02-21 23:47:26 -0500
commitc1c214adcb56d36433480c8fedf772498e7e539c (patch)
treed004bb086c251293f2c59ee96423307ff022c8f1 /drivers/crypto
parent4359669a087633132203c52d67dd8c31e09e7b2e (diff)
crypto: rockchip - update new iv to device in multiple operations
For chain mode in cipher(eg. AES-CBC/DES-CBC), the iv is continuously updated in the operation. The new iv value should be written to device register by software. Reported-by: Eric Biggers <ebiggers@google.com> Fixes: 433cd2c617bf ("crypto: rockchip - add crypto driver for rk3288") Cc: <stable@vger.kernel.org> # v4.5+ Signed-off-by: Zhang Zhijie <zhangzj@rock-chips.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/crypto')
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto.h1
-rw-r--r--drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c34
2 files changed, 35 insertions, 0 deletions
diff --git a/drivers/crypto/rockchip/rk3288_crypto.h b/drivers/crypto/rockchip/rk3288_crypto.h
index 417c445d8dea..54ee5b3ed9db 100644
--- a/drivers/crypto/rockchip/rk3288_crypto.h
+++ b/drivers/crypto/rockchip/rk3288_crypto.h
@@ -245,6 +245,7 @@ struct rk_cipher_ctx {
245 struct rk_crypto_info *dev; 245 struct rk_crypto_info *dev;
246 unsigned int keylen; 246 unsigned int keylen;
247 u32 mode; 247 u32 mode;
248 u8 iv[AES_BLOCK_SIZE];
248}; 249};
249 250
250enum alg_type { 251enum alg_type {
diff --git a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
index fe2fc6c7b51b..02dac6ae7e53 100644
--- a/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
+++ b/drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c
@@ -242,6 +242,17 @@ static void crypto_dma_start(struct rk_crypto_info *dev)
242static int rk_set_data_start(struct rk_crypto_info *dev) 242static int rk_set_data_start(struct rk_crypto_info *dev)
243{ 243{
244 int err; 244 int err;
245 struct ablkcipher_request *req =
246 ablkcipher_request_cast(dev->async_req);
247 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
248 struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
249 u32 ivsize = crypto_ablkcipher_ivsize(tfm);
250 u8 *src_last_blk = page_address(sg_page(dev->sg_src)) +
251 dev->sg_src->offset + dev->sg_src->length - ivsize;
252
253 /* store the iv that need to be updated in chain mode */
254 if (ctx->mode & RK_CRYPTO_DEC)
255 memcpy(ctx->iv, src_last_blk, ivsize);
245 256
246 err = dev->load_data(dev, dev->sg_src, dev->sg_dst); 257 err = dev->load_data(dev, dev->sg_src, dev->sg_dst);
247 if (!err) 258 if (!err)
@@ -286,6 +297,28 @@ static void rk_iv_copyback(struct rk_crypto_info *dev)
286 memcpy_fromio(req->info, dev->reg + RK_CRYPTO_AES_IV_0, ivsize); 297 memcpy_fromio(req->info, dev->reg + RK_CRYPTO_AES_IV_0, ivsize);
287} 298}
288 299
300static void rk_update_iv(struct rk_crypto_info *dev)
301{
302 struct ablkcipher_request *req =
303 ablkcipher_request_cast(dev->async_req);
304 struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
305 struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm);
306 u32 ivsize = crypto_ablkcipher_ivsize(tfm);
307 u8 *new_iv = NULL;
308
309 if (ctx->mode & RK_CRYPTO_DEC) {
310 new_iv = ctx->iv;
311 } else {
312 new_iv = page_address(sg_page(dev->sg_dst)) +
313 dev->sg_dst->offset + dev->sg_dst->length - ivsize;
314 }
315
316 if (ivsize == DES_BLOCK_SIZE)
317 memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, new_iv, ivsize);
318 else if (ivsize == AES_BLOCK_SIZE)
319 memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, new_iv, ivsize);
320}
321
289/* return: 322/* return:
290 * true some err was occurred 323 * true some err was occurred
291 * fault no err, continue 324 * fault no err, continue
@@ -307,6 +340,7 @@ static int rk_ablk_rx(struct rk_crypto_info *dev)
307 } 340 }
308 } 341 }
309 if (dev->left_bytes) { 342 if (dev->left_bytes) {
343 rk_update_iv(dev);
310 if (dev->aligned) { 344 if (dev->aligned) {
311 if (sg_is_last(dev->sg_src)) { 345 if (sg_is_last(dev->sg_src)) {
312 dev_err(dev->dev, "[%s:%d] Lack of data\n", 346 dev_err(dev->dev, "[%s:%d] Lack of data\n",