mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 22:52:35 +02:00
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:
parent
99122bd853
commit
5a8a8b4664
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user