crypto: rockchip - add aes ecb/cbc/xts for rv1126

Change-Id: I27f2949382d6bc17d97631efa8340a6fe50af6fb
Signed-off-by: Lin Jinhan <troy.lin@rock-chips.com>
This commit is contained in:
Lin Jinhan 2020-07-02 17:18:20 +08:00 committed by Tao Huang
parent 99122bd853
commit 5a8a8b4664
4 changed files with 107 additions and 18 deletions

View File

@ -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

View File

@ -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",

View File

@ -13,6 +13,7 @@
#include <crypto/sm3.h>
#include <crypto/sm4.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/skcipher.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
@ -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 {

View File

@ -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)