Skip to content

Commit

Permalink
crypto: rockchip - do not store mode globally
Browse files Browse the repository at this point in the history
[ Upstream commit 87e356c ]

Storing the mode globally does not work if 2 requests are handled in the
same time.
We should store it in a request context.

Fixes: ce0183c ("crypto: rockchip - switch to skcipher API")
Reviewed-by: John Keeping <john@metanate.com>
Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
montjoie authored and gregkh committed Dec 31, 2022
1 parent 2aecc50 commit d2ce292
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 22 deletions.
5 changes: 4 additions & 1 deletion drivers/crypto/rockchip/rk3288_crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,13 @@ struct rk_ahash_rctx {
struct rk_cipher_ctx {
struct rk_crypto_info *dev;
unsigned int keylen;
u32 mode;
u8 iv[AES_BLOCK_SIZE];
};

struct rk_cipher_rctx {
u32 mode;
};

enum alg_type {
ALG_TYPE_HASH,
ALG_TYPE_CIPHER,
Expand Down
58 changes: 37 additions & 21 deletions drivers/crypto/rockchip/rk3288_crypto_skcipher.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,119 +76,131 @@ static int rk_aes_ecb_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_AES_ECB_MODE;
rctx->mode = RK_CRYPTO_AES_ECB_MODE;
return rk_handle_req(dev, req);
}

static int rk_aes_ecb_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC;
rctx->mode = RK_CRYPTO_AES_ECB_MODE | RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}

static int rk_aes_cbc_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_AES_CBC_MODE;
rctx->mode = RK_CRYPTO_AES_CBC_MODE;
return rk_handle_req(dev, req);
}

static int rk_aes_cbc_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC;
rctx->mode = RK_CRYPTO_AES_CBC_MODE | RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}

static int rk_des_ecb_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = 0;
rctx->mode = 0;
return rk_handle_req(dev, req);
}

static int rk_des_ecb_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_DEC;
rctx->mode = RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}

static int rk_des_cbc_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC;
rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC;
return rk_handle_req(dev, req);
}

static int rk_des_cbc_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC;
rctx->mode = RK_CRYPTO_TDES_CHAINMODE_CBC | RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}

static int rk_des3_ede_ecb_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_SELECT;
rctx->mode = RK_CRYPTO_TDES_SELECT;
return rk_handle_req(dev, req);
}

static int rk_des3_ede_ecb_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC;
rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}

static int rk_des3_ede_cbc_encrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC;
rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC;
return rk_handle_req(dev, req);
}

static int rk_des3_ede_cbc_decrypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_crypto_info *dev = ctx->dev;

ctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC |
rctx->mode = RK_CRYPTO_TDES_SELECT | RK_CRYPTO_TDES_CHAINMODE_CBC |
RK_CRYPTO_DEC;
return rk_handle_req(dev, req);
}
Expand All @@ -199,29 +211,30 @@ static void rk_ablk_hw_init(struct rk_crypto_info *dev)
skcipher_request_cast(dev->async_req);
struct crypto_skcipher *cipher = crypto_skcipher_reqtfm(req);
struct crypto_tfm *tfm = crypto_skcipher_tfm(cipher);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(cipher);
u32 ivsize, block, conf_reg = 0;

block = crypto_tfm_alg_blocksize(tfm);
ivsize = crypto_skcipher_ivsize(cipher);

if (block == DES_BLOCK_SIZE) {
ctx->mode |= RK_CRYPTO_TDES_FIFO_MODE |
rctx->mode |= RK_CRYPTO_TDES_FIFO_MODE |
RK_CRYPTO_TDES_BYTESWAP_KEY |
RK_CRYPTO_TDES_BYTESWAP_IV;
CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, ctx->mode);
CRYPTO_WRITE(dev, RK_CRYPTO_TDES_CTRL, rctx->mode);
memcpy_toio(dev->reg + RK_CRYPTO_TDES_IV_0, req->iv, ivsize);
conf_reg = RK_CRYPTO_DESSEL;
} else {
ctx->mode |= RK_CRYPTO_AES_FIFO_MODE |
rctx->mode |= RK_CRYPTO_AES_FIFO_MODE |
RK_CRYPTO_AES_KEY_CHANGE |
RK_CRYPTO_AES_BYTESWAP_KEY |
RK_CRYPTO_AES_BYTESWAP_IV;
if (ctx->keylen == AES_KEYSIZE_192)
ctx->mode |= RK_CRYPTO_AES_192BIT_key;
rctx->mode |= RK_CRYPTO_AES_192BIT_key;
else if (ctx->keylen == AES_KEYSIZE_256)
ctx->mode |= RK_CRYPTO_AES_256BIT_key;
CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, ctx->mode);
rctx->mode |= RK_CRYPTO_AES_256BIT_key;
CRYPTO_WRITE(dev, RK_CRYPTO_AES_CTRL, rctx->mode);
memcpy_toio(dev->reg + RK_CRYPTO_AES_IV_0, req->iv, ivsize);
}
conf_reg |= RK_CRYPTO_BYTESWAP_BTFIFO |
Expand All @@ -246,6 +259,7 @@ static int rk_set_data_start(struct rk_crypto_info *dev)
struct skcipher_request *req =
skcipher_request_cast(dev->async_req);
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
u32 ivsize = crypto_skcipher_ivsize(tfm);
u8 *src_last_blk = page_address(sg_page(dev->sg_src)) +
Expand All @@ -254,7 +268,7 @@ static int rk_set_data_start(struct rk_crypto_info *dev)
/* Store the iv that need to be updated in chain mode.
* And update the IV buffer to contain the next IV for decryption mode.
*/
if (ctx->mode & RK_CRYPTO_DEC) {
if (rctx->mode & RK_CRYPTO_DEC) {
memcpy(ctx->iv, src_last_blk, ivsize);
sg_pcopy_to_buffer(dev->first, dev->src_nents, req->iv,
ivsize, dev->total - ivsize);
Expand Down Expand Up @@ -294,11 +308,12 @@ static void rk_iv_copyback(struct rk_crypto_info *dev)
struct skcipher_request *req =
skcipher_request_cast(dev->async_req);
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
u32 ivsize = crypto_skcipher_ivsize(tfm);

/* Update the IV buffer to contain the next IV for encryption mode. */
if (!(ctx->mode & RK_CRYPTO_DEC)) {
if (!(rctx->mode & RK_CRYPTO_DEC)) {
if (dev->aligned) {
memcpy(req->iv, sg_virt(dev->sg_dst) +
dev->sg_dst->length - ivsize, ivsize);
Expand All @@ -314,11 +329,12 @@ static void rk_update_iv(struct rk_crypto_info *dev)
struct skcipher_request *req =
skcipher_request_cast(dev->async_req);
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct rk_cipher_rctx *rctx = skcipher_request_ctx(req);
struct rk_cipher_ctx *ctx = crypto_skcipher_ctx(tfm);
u32 ivsize = crypto_skcipher_ivsize(tfm);
u8 *new_iv = NULL;

if (ctx->mode & RK_CRYPTO_DEC) {
if (rctx->mode & RK_CRYPTO_DEC) {
new_iv = ctx->iv;
} else {
new_iv = page_address(sg_page(dev->sg_dst)) +
Expand Down

0 comments on commit d2ce292

Please sign in to comment.