From 5a8a8b46649bcade04c98262346fe9646eec5950 Mon Sep 17 00:00:00 2001 From: Lin Jinhan Date: Thu, 2 Jul 2020 17:18:20 +0800 Subject: [PATCH] crypto: rockchip - add aes ecb/cbc/xts for rv1126 Change-Id: I27f2949382d6bc17d97631efa8340a6fe50af6fb Signed-off-by: Lin Jinhan --- drivers/crypto/Kconfig | 3 + drivers/crypto/rockchip/rk_crypto_core.c | 31 +++++-- drivers/crypto/rockchip/rk_crypto_core.h | 6 ++ .../crypto/rockchip/rk_crypto_v2_ablkcipher.c | 85 +++++++++++++++++-- 4 files changed, 107 insertions(+), 18 deletions(-) diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index e33934f36969..f7be4cb1e276 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -645,6 +645,9 @@ config CRYPTO_DEV_ROCKCHIP tristate "Rockchip's Cryptographic Engine driver" depends on OF && ARCH_ROCKCHIP select CRYPTO_AES + select CRYPTO_ECB + select CRYPTO_CBC + select CRYPTO_XTS select CRYPTO_DES select CRYPTO_MD5 select CRYPTO_SHA1 diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index de7b73c61504..0005f09290e1 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -24,6 +24,7 @@ #include "rk_crypto_v2.h" #define RK_CRYPTO_V1_SOC_DATA_INIT(names) {\ + .use_soft_aes192 = false,\ .valid_algs_name = (names),\ .valid_algs_num = ARRAY_SIZE(names),\ .total_algs = crypto_v1_algs,\ @@ -37,7 +38,8 @@ .hw_info_size = sizeof(struct rk_hw_crypto_v1_info),\ } -#define RK_CRYPTO_V2_SOC_DATA_INIT(names) {\ +#define RK_CRYPTO_V2_SOC_DATA_INIT(names, soft_aes_192) {\ + .use_soft_aes192 = soft_aes_192,\ .valid_algs_name = (names),\ .valid_algs_num = ARRAY_SIZE(names),\ .total_algs = crypto_v2_algs,\ @@ -286,11 +288,14 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) unsigned int i, k; char **algs_name; struct rk_crypto_tmp *tmp_algs; + struct rk_crypto_soc_data *soc_data; int err = 0; - algs_name = crypto_info->soc_data->valid_algs_name; + soc_data = crypto_info->soc_data; - for (i = 0; i < crypto_info->soc_data->valid_algs_num; i++, algs_name++) { + algs_name = soc_data->valid_algs_name; + + for (i = 0; i < soc_data->valid_algs_num; i++, algs_name++) { tmp_algs = rk_crypto_find_algs(crypto_info, *algs_name); if (!tmp_algs) { CRYPTO_TRACE("%s not matched!!!\n", *algs_name); @@ -301,12 +306,18 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) tmp_algs->dev = crypto_info; - if (tmp_algs->type == ALG_TYPE_CIPHER) + if (tmp_algs->type == ALG_TYPE_CIPHER) { + if (tmp_algs->algo == CIPHER_ALGO_AES && + tmp_algs->mode != CIPHER_MODE_XTS && + soc_data->use_soft_aes192) + tmp_algs->alg.crypto.cra_flags |= CRYPTO_ALG_NEED_FALLBACK; + err = crypto_register_alg(&tmp_algs->alg.crypto); - else if (tmp_algs->type == ALG_TYPE_HASH || tmp_algs->type == ALG_TYPE_HMAC) + } else if (tmp_algs->type == ALG_TYPE_HASH || tmp_algs->type == ALG_TYPE_HMAC) { err = crypto_register_ahash(&tmp_algs->alg.hash); - else + } else { continue; + } if (err) goto err_cipher_algs; @@ -316,7 +327,8 @@ static int rk_crypto_register(struct rk_crypto_info *crypto_info) return 0; err_cipher_algs: - algs_name = crypto_info->soc_data->valid_algs_name; + algs_name = soc_data->valid_algs_name; + for (k = 0; k < i; k++, algs_name++) { tmp_algs = rk_crypto_find_algs(crypto_info, *algs_name); if (tmp_algs->type == ALG_TYPE_CIPHER) @@ -400,6 +412,7 @@ static char *px30_algs_name[] = { static char *rv1126_algs_name[] = { "ecb(sm4)", "cbc(sm4)", "xts(sm4)", + "ecb(aes)", "cbc(aes)", "xts(aes)", "ecb(des)", "cbc(des)", "ecb(des3_ede)", "cbc(des3_ede)", "sha1", "sha256", "sha512", "md5", "sm3", @@ -407,10 +420,10 @@ static char *rv1126_algs_name[] = { }; static const struct rk_crypto_soc_data px30_soc_data = - RK_CRYPTO_V2_SOC_DATA_INIT(px30_algs_name); + RK_CRYPTO_V2_SOC_DATA_INIT(px30_algs_name, false); static const struct rk_crypto_soc_data rv1126_soc_data = - RK_CRYPTO_V2_SOC_DATA_INIT(rv1126_algs_name); + RK_CRYPTO_V2_SOC_DATA_INIT(rv1126_algs_name, true); static const char * const crypto_v1_clks[] = { "hclk", diff --git a/drivers/crypto/rockchip/rk_crypto_core.h b/drivers/crypto/rockchip/rk_crypto_core.h index b1c8f23f4fe1..67864c09191b 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.h +++ b/drivers/crypto/rockchip/rk_crypto_core.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,8 @@ struct rk_crypto_soc_data { int clks_num; int rsts_num; unsigned int hw_info_size; + bool use_soft_aes192; + int (*hw_init)(struct device *dev, void *hw_info); void (*hw_deinit)(struct device *dev, void *hw_info); }; @@ -101,6 +104,9 @@ struct rk_cipher_ctx { unsigned int keylen; u32 mode; u8 iv[AES_BLOCK_SIZE]; + + /* for fallback */ + struct crypto_skcipher *fallback_tfm; }; enum alg_type { diff --git a/drivers/crypto/rockchip/rk_crypto_v2_ablkcipher.c b/drivers/crypto/rockchip/rk_crypto_v2_ablkcipher.c index 93e5e186cb8b..033b50a3fc97 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2_ablkcipher.c +++ b/drivers/crypto/rockchip/rk_crypto_v2_ablkcipher.c @@ -155,6 +155,11 @@ static struct rk_crypto_tmp *rk_cipher_get_algt(struct crypto_ablkcipher *tfm) return container_of(alg, struct rk_crypto_tmp, alg.crypto); } +static bool is_use_fallback(struct rk_cipher_ctx *ctx) +{ + return ctx->keylen == AES_KEYSIZE_192 && ctx->fallback_tfm; +} + static void rk_crypto_complete(struct crypto_async_request *base, int err) { if (base->complete) @@ -177,6 +182,7 @@ static int rk_cipher_setkey(struct crypto_ablkcipher *cipher, struct rk_crypto_tmp *algt = rk_cipher_get_algt(cipher); struct rk_cipher_ctx *ctx = crypto_tfm_ctx(tfm); u32 tmp[DES_EXPKEY_WORDS]; + int ret = -EINVAL; CRYPTO_MSG("algo = %x, mode = %x, key_len = %d\n", algt->algo, algt->mode, keylen); @@ -227,11 +233,20 @@ static int rk_cipher_setkey(struct crypto_ablkcipher *cipher, if (algt->mode == CIPHER_MODE_XTS) ctx->keylen /= 2; + if (is_use_fallback(ctx)) { + CRYPTO_MSG("use fallback tfm"); + ret = crypto_skcipher_setkey(ctx->fallback_tfm, key, keylen); + if (ret) { + CRYPTO_MSG("soft fallback crypto_skcipher_setkey err = %d\n", ret); + goto error; + } + } + return 0; error: crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; + return ret; } static int rk_cipher_encrypt(struct ablkcipher_request *req) @@ -239,12 +254,29 @@ static int rk_cipher_encrypt(struct ablkcipher_request *req) struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm); struct rk_crypto_tmp *algt = rk_cipher_get_algt(tfm); + int ret = -EINVAL; - ctx->mode = cipher_algo2bc[algt->algo] | cipher_mode2bc[algt->mode]; + CRYPTO_TRACE(); - CRYPTO_MSG("ctx->mode = %x\n", ctx->mode); + if (is_use_fallback(ctx)) { + SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback_tfm); - return rk_handle_req(ctx->dev, req); + CRYPTO_MSG("use fallback tfm"); + + skcipher_request_set_tfm(subreq, ctx->fallback_tfm); + skcipher_request_set_callback(subreq, req->base.flags, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, + req->nbytes, req->info); + ret = crypto_skcipher_encrypt(subreq); + skcipher_request_zero(subreq); + } else { + ctx->mode = cipher_algo2bc[algt->algo] | cipher_mode2bc[algt->mode]; + CRYPTO_MSG("ctx->mode = %x\n", ctx->mode); + ret = rk_handle_req(ctx->dev, req); + } + + return ret; } static int rk_cipher_decrypt(struct ablkcipher_request *req) @@ -252,14 +284,31 @@ static int rk_cipher_decrypt(struct ablkcipher_request *req) struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req); struct rk_cipher_ctx *ctx = crypto_ablkcipher_ctx(tfm); struct rk_crypto_tmp *algt = rk_cipher_get_algt(tfm); + int ret = -EINVAL; - ctx->mode = cipher_algo2bc[algt->algo] | - cipher_mode2bc[algt->mode] | - CRYPTO_BC_DECRYPT; + CRYPTO_TRACE(); - CRYPTO_MSG("ctx->mode = %x\n", ctx->mode); + if (is_use_fallback(ctx)) { + SKCIPHER_REQUEST_ON_STACK(subreq, ctx->fallback_tfm); - return rk_handle_req(ctx->dev, req); + CRYPTO_MSG("use soft fallback tfm"); + + skcipher_request_set_tfm(subreq, ctx->fallback_tfm); + skcipher_request_set_callback(subreq, req->base.flags, + NULL, NULL); + skcipher_request_set_crypt(subreq, req->src, req->dst, + req->nbytes, req->info); + ret = crypto_skcipher_decrypt(subreq); + skcipher_request_zero(subreq); + } else { + ctx->mode = cipher_algo2bc[algt->algo] | + cipher_mode2bc[algt->mode] | + CRYPTO_BC_DECRYPT; + CRYPTO_MSG("ctx->mode = %x\n", ctx->mode); + ret = rk_handle_req(ctx->dev, req); + } + + return ret; } static void rk_ablk_hw_init(struct rk_crypto_info *dev) @@ -443,6 +492,7 @@ static int rk_ablk_cra_init(struct crypto_tfm *tfm) { struct rk_crypto_tmp *algt = rk_cipher_get_algt(__crypto_ablkcipher_cast(tfm)); struct rk_cipher_ctx *ctx = crypto_tfm_ctx(tfm); + const char *alg_name = crypto_tfm_alg_name(tfm); CRYPTO_TRACE(); @@ -453,6 +503,18 @@ static int rk_ablk_cra_init(struct crypto_tfm *tfm) ctx->dev->complete = rk_crypto_complete; ctx->dev->irq_handle = rk_crypto_irq_handle; + if (algt->alg.crypto.cra_flags & CRYPTO_ALG_NEED_FALLBACK) { + CRYPTO_MSG("alloc fallback tfm, name = %s", alg_name); + ctx->fallback_tfm = crypto_alloc_skcipher(alg_name, 0, + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_NEED_FALLBACK); + if (IS_ERR(ctx->fallback_tfm)) { + dev_err(ctx->dev->dev, "Could not load fallback driver %s : %ld.\n", + alg_name, PTR_ERR(ctx->fallback_tfm)); + return PTR_ERR(ctx->fallback_tfm); + } + } + ctx->dev->enable_clk(ctx->dev); return 0; @@ -468,6 +530,11 @@ static void rk_ablk_cra_exit(struct crypto_tfm *tfm) CRYPTO_WRITE(ctx->dev, CRYPTO_BC_CTL, 0 | CRYPTO_WRITE_MASK_ALL); ctx->dev->disable_clk(ctx->dev); + + if (ctx->fallback_tfm) { + CRYPTO_MSG("free fallback tfm"); + crypto_free_skcipher(ctx->fallback_tfm); + } } int rk_hw_crypto_v2_init(struct device *dev, void *hw_info)