diff options
author | Zhang Zhijie <zhangzj@rock-chips.com> | 2019-02-13 03:24:39 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2019-02-21 23:47:26 -0500 |
commit | c1c214adcb56d36433480c8fedf772498e7e539c (patch) | |
tree | d004bb086c251293f2c59ee96423307ff022c8f1 /drivers/crypto | |
parent | 4359669a087633132203c52d67dd8c31e09e7b2e (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.h | 1 | ||||
-rw-r--r-- | drivers/crypto/rockchip/rk3288_crypto_ablkcipher.c | 34 |
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 | ||
250 | enum alg_type { | 251 | enum 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) | |||
242 | static int rk_set_data_start(struct rk_crypto_info *dev) | 242 | static 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 | ||
300 | static 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", |