69 lines
2.1 KiB
Diff
69 lines
2.1 KiB
Diff
diff --git a/drivers/crypto/qce/ablkcipher.c b/drivers/crypto/qce/ablkcipher.c
|
|
index 7a98bf5cc967..b935ce0acc1c 100644
|
|
--- a/drivers/crypto/qce/ablkcipher.c
|
|
+++ b/drivers/crypto/qce/ablkcipher.c
|
|
@@ -14,6 +14,20 @@
|
|
|
|
static LIST_HEAD(ablkcipher_algs);
|
|
|
|
+static void qce_update_ctr_iv(u8 *iv, unsigned int ivsize, u32 add)
|
|
+{
|
|
+ __be32 *a = (__be32 *)(iv + ivsize);
|
|
+ u32 b;
|
|
+
|
|
+ for (; ivsize >= 4; ivsize -= 4) {
|
|
+ b = be32_to_cpu(*--a) + add;
|
|
+ *a = cpu_to_be32(b);
|
|
+ if (b >= add)
|
|
+ return;
|
|
+ add = 1;
|
|
+ }
|
|
+}
|
|
+
|
|
static void qce_ablkcipher_done(void *data)
|
|
{
|
|
struct crypto_async_request *async_req = data;
|
|
@@ -39,6 +53,18 @@ static void qce_ablkcipher_done(void *data)
|
|
dma_unmap_sg(qce->dev, rctx->src_sg, rctx->src_nents, dir_src);
|
|
dma_unmap_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst);
|
|
|
|
+ if (IS_CBC(rctx->flags)) {
|
|
+ if (IS_ENCRYPT(rctx->flags))
|
|
+ sg_pcopy_to_buffer(rctx->dst_sg, rctx->dst_nents,
|
|
+ rctx->iv, rctx->ivsize,
|
|
+ rctx->cryptlen - rctx->ivsize);
|
|
+ else
|
|
+ memcpy(rctx->iv, rctx->saved_iv, rctx->ivsize);
|
|
+ } else if (IS_CTR(rctx->flags) && IS_AES(rctx->flags)) {
|
|
+ qce_update_ctr_iv(rctx->iv, rctx->ivsize,
|
|
+ DIV_ROUND_UP(rctx->cryptlen, AES_BLOCK_SIZE));
|
|
+ }
|
|
+
|
|
sg_free_table(&rctx->dst_tbl);
|
|
|
|
error = qce_check_status(qce, &status);
|
|
@@ -131,6 +157,11 @@ qce_ablkcipher_async_req_handle(struct crypto_async_request *async_req)
|
|
|
|
qce_dma_issue_pending(&qce->dma);
|
|
|
|
+ if (IS_CBC(rctx->flags) && IS_DECRYPT(rctx->flags))
|
|
+ sg_pcopy_to_buffer(rctx->src_sg, rctx->src_nents,
|
|
+ rctx->saved_iv, rctx->ivsize,
|
|
+ rctx->cryptlen - rctx->ivsize);
|
|
+
|
|
ret = qce_start(async_req, tmpl->crypto_alg_type, req->nbytes, 0);
|
|
if (ret)
|
|
goto error_terminate;
|
|
diff --git a/drivers/crypto/qce/cipher.h b/drivers/crypto/qce/cipher.h
|
|
index 5cab8f0706a8..a919022e28df 100644
|
|
--- a/drivers/crypto/qce/cipher.h
|
|
+++ b/drivers/crypto/qce/cipher.h
|
|
@@ -43,6 +43,7 @@ struct qce_cipher_reqctx {
|
|
struct sg_table src_tbl;
|
|
struct scatterlist *src_sg;
|
|
unsigned int cryptlen;
|
|
+ u8 saved_iv[QCE_MAX_IV_SIZE];
|
|
};
|
|
|
|
static inline struct qce_alg_template *to_cipher_tmpl(struct crypto_tfm *tfm)
|