diff --git a/drivers/crypto/rockchip/rk_crypto_core.c b/drivers/crypto/rockchip/rk_crypto_core.c index d045c49ba32e..a48b9e268492 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.c +++ b/drivers/crypto/rockchip/rk_crypto_core.c @@ -443,6 +443,8 @@ static int rk_crypto_register(struct rk_crypto_dev *rk_dev) algs_name = soc_data->valid_algs_name; + rk_dev->request_crypto(rk_dev, __func__); + for (i = 0; i < soc_data->valid_algs_num; i++, algs_name++) { tmp_algs = rk_crypto_find_algs(rk_dev, *algs_name); if (!tmp_algs) { @@ -450,6 +452,11 @@ static int rk_crypto_register(struct rk_crypto_dev *rk_dev) continue; } + if (soc_data->hw_is_algo_valid && !soc_data->hw_is_algo_valid(rk_dev, tmp_algs)) { + CRYPTO_TRACE("%s skipped!!!\n", *algs_name); + continue; + } + CRYPTO_TRACE("%s matched!!!\n", *algs_name); tmp_algs->rk_dev = rk_dev; @@ -482,6 +489,9 @@ static int rk_crypto_register(struct rk_crypto_dev *rk_dev) CRYPTO_TRACE("%s register OK!!!\n", *algs_name); } + + rk_dev->release_crypto(rk_dev, __func__); + return 0; err_cipher_algs: @@ -499,6 +509,9 @@ err_cipher_algs: else if (tmp_algs->type == ALG_TYPE_ASYM) crypto_unregister_akcipher(&tmp_algs->alg.asym); } + + rk_dev->release_crypto(rk_dev, __func__); + return err; } @@ -510,6 +523,8 @@ static void rk_crypto_unregister(struct rk_crypto_dev *rk_dev) algs_name = rk_dev->soc_data->valid_algs_name; + rk_dev->request_crypto(rk_dev, __func__); + for (i = 0; i < rk_dev->soc_data->valid_algs_num; i++, algs_name++) { tmp_algs = rk_crypto_find_algs(rk_dev, *algs_name); if (!tmp_algs) @@ -522,6 +537,8 @@ static void rk_crypto_unregister(struct rk_crypto_dev *rk_dev) else if (tmp_algs->type == ALG_TYPE_ASYM) crypto_unregister_akcipher(&tmp_algs->alg.asym); } + + rk_dev->release_crypto(rk_dev, __func__); } static void rk_crypto_request(struct rk_crypto_dev *rk_dev, const char *name) @@ -575,15 +592,6 @@ static char *crypto_full_algs_name[] = { "rsa" }; -static char *crypto_rv1106_algs_name[] = { - "ecb(aes)", "cbc(aes)", "cfb(aes)", "ofb(aes)", "ctr(aes)", - "ecb(des)", "cbc(des)", "cfb(des)", "ofb(des)", - "ecb(des3_ede)", "cbc(des3_ede)", "cfb(des3_ede)", "ofb(des3_ede)", - "sha1", "sha224", "sha256", "md5", - "hmac(sha1)", "hmac(sha256)", "hmac(md5)", - "rsa" -}; - static const struct rk_crypto_soc_data px30_soc_data = RK_CRYPTO_V2_SOC_DATA_INIT(crypto_no_sm_algs_name, false); @@ -594,7 +602,7 @@ static const struct rk_crypto_soc_data full_soc_data = RK_CRYPTO_V2_SOC_DATA_INIT(crypto_full_algs_name, false); static const struct rk_crypto_soc_data cryto_v3_soc_data = - RK_CRYPTO_V3_SOC_DATA_INIT(crypto_rv1106_algs_name); + RK_CRYPTO_V3_SOC_DATA_INIT(crypto_full_algs_name); static char *rk3288_cipher_algs[] = { "ecb(aes)", "cbc(aes)", diff --git a/drivers/crypto/rockchip/rk_crypto_core.h b/drivers/crypto/rockchip/rk_crypto_core.h index d855625b75d0..012614e00640 100644 --- a/drivers/crypto/rockchip/rk_crypto_core.h +++ b/drivers/crypto/rockchip/rk_crypto_core.h @@ -46,19 +46,6 @@ #define RK_FLAG_FINAL BIT(0) #define RK_FLAG_UPDATE BIT(1) -struct rk_crypto_soc_data { - const char *crypto_ver; - char **valid_algs_name; - int valid_algs_num; - unsigned int hw_info_size; - bool use_soft_aes192; - int default_pka_offset; - int (*hw_init)(struct device *dev, void *hw_info); - void (*hw_deinit)(struct device *dev, void *hw_info); - const char * const *(*hw_get_rsts)(uint32_t *num); - struct rk_crypto_algt **(*hw_get_algts)(uint32_t *num); -}; - struct rk_crypto_dev { struct device *dev; struct reset_control *rst; @@ -94,6 +81,21 @@ struct rk_crypto_dev { struct crypto_async_request *async_req); }; +struct rk_crypto_soc_data { + const char *crypto_ver; + char **valid_algs_name; + int valid_algs_num; + unsigned int hw_info_size; + bool use_soft_aes192; + int default_pka_offset; + int (*hw_init)(struct device *dev, void *hw_info); + void (*hw_deinit)(struct device *dev, void *hw_info); + const char * const *(*hw_get_rsts)(uint32_t *num); + struct rk_crypto_algt **(*hw_get_algts)(uint32_t *num); + bool (*hw_is_algo_valid)(struct rk_crypto_dev *rk_dev, + struct rk_crypto_algt *aglt); +}; + struct rk_alg_ops { int (*start)(struct rk_crypto_dev *rk_dev); int (*update)(struct rk_crypto_dev *rk_dev); @@ -213,6 +215,8 @@ enum rk_hash_algo { HASH_ALGO_SHA384, HASH_ALGO_SHA512, HASH_ALGO_SM3, + HASH_ALGO_SHA512_224, + HASH_ALGO_SHA512_256, }; enum rk_cipher_algo { @@ -229,6 +233,11 @@ enum rk_cipher_mode { CIPHER_MODE_OFB, CIPHER_MODE_CTR, CIPHER_MODE_XTS, + CIPHER_MODE_CTS, + CIPHER_MODE_CCM, + CIPHER_MODE_GCM, + CIPHER_MODE_CMAC, + CIPHER_MODE_CBCMAC, }; #define DES_MIN_KEY_SIZE DES_KEY_SIZE diff --git a/drivers/crypto/rockchip/rk_crypto_v1.c b/drivers/crypto/rockchip/rk_crypto_v1.c index fcc6eeb7383e..14347c4900bc 100644 --- a/drivers/crypto/rockchip/rk_crypto_v1.c +++ b/drivers/crypto/rockchip/rk_crypto_v1.c @@ -53,3 +53,8 @@ struct rk_crypto_algt **rk_hw_crypto_v1_get_algts(uint32_t *num) return crypto_v1_algs; } +bool rk_hw_crypto_v1_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt) +{ + return true; +} + diff --git a/drivers/crypto/rockchip/rk_crypto_v1.h b/drivers/crypto/rockchip/rk_crypto_v1.h index b7180fbc6574..961b13ae6e52 100644 --- a/drivers/crypto/rockchip/rk_crypto_v1.h +++ b/drivers/crypto/rockchip/rk_crypto_v1.h @@ -20,6 +20,7 @@ struct rk_hw_crypto_v1_info { .hw_deinit = rk_hw_crypto_v1_deinit,\ .hw_get_rsts = rk_hw_crypto_v1_get_rsts,\ .hw_get_algts = rk_hw_crypto_v1_get_algts,\ + .hw_is_algo_valid = rk_hw_crypto_v1_algo_valid,\ .hw_info_size = sizeof(struct rk_hw_crypto_v1_info),\ .default_pka_offset = 0,\ } @@ -43,6 +44,7 @@ int rk_hw_crypto_v1_init(struct device *dev, void *hw_info); void rk_hw_crypto_v1_deinit(struct device *dev, void *hw_info); const char * const *rk_hw_crypto_v1_get_rsts(uint32_t *num); struct rk_crypto_algt **rk_hw_crypto_v1_get_algts(uint32_t *num); +bool rk_hw_crypto_v1_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt); #else @@ -50,6 +52,11 @@ static inline int rk_hw_crypto_v1_init(struct device *dev, void *hw_info) { retu static inline void rk_hw_crypto_v1_deinit(struct device *dev, void *hw_info) {} static inline const char * const *rk_hw_crypto_v1_get_rsts(uint32_t *num) { return NULL; } static inline struct rk_crypto_algt **rk_hw_crypto_v1_get_algts(uint32_t *num) { return NULL; } +static inline bool rk_hw_crypto_v1_algo_valid(struct rk_crypto_dev *rk_dev, + struct rk_crypto_algt *aglt) +{ + return false; +} #endif /* end of IS_ENABLED(CONFIG_CRYPTO_DEV_ROCKCHIP_V1) */ diff --git a/drivers/crypto/rockchip/rk_crypto_v2.c b/drivers/crypto/rockchip/rk_crypto_v2.c index c7caa867632a..07f4265b12ed 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2.c +++ b/drivers/crypto/rockchip/rk_crypto_v2.c @@ -100,3 +100,8 @@ struct rk_crypto_algt **rk_hw_crypto_v2_get_algts(uint32_t *num) return crypto_v2_algs; } +bool rk_hw_crypto_v2_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt) +{ + return true; +} + diff --git a/drivers/crypto/rockchip/rk_crypto_v2.h b/drivers/crypto/rockchip/rk_crypto_v2.h index fc1ac8a40886..8ad0b3cfeac1 100644 --- a/drivers/crypto/rockchip/rk_crypto_v2.h +++ b/drivers/crypto/rockchip/rk_crypto_v2.h @@ -32,6 +32,7 @@ struct rk_hw_crypto_v2_info { .hw_deinit = rk_hw_crypto_v2_deinit,\ .hw_get_rsts = rk_hw_crypto_v2_get_rsts,\ .hw_get_algts = rk_hw_crypto_v2_get_algts,\ + .hw_is_algo_valid = rk_hw_crypto_v2_algo_valid,\ .hw_info_size = sizeof(struct rk_hw_crypto_v2_info),\ .default_pka_offset = 0x0480,\ } @@ -82,6 +83,7 @@ int rk_hw_crypto_v2_init(struct device *dev, void *hw_info); void rk_hw_crypto_v2_deinit(struct device *dev, void *hw_info); const char * const *rk_hw_crypto_v2_get_rsts(uint32_t *num); struct rk_crypto_algt **rk_hw_crypto_v2_get_algts(uint32_t *num); +bool rk_hw_crypto_v2_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt); #else @@ -89,6 +91,11 @@ static inline int rk_hw_crypto_v2_init(struct device *dev, void *hw_info) { retu static inline void rk_hw_crypto_v2_deinit(struct device *dev, void *hw_info) {} static inline const char * const *rk_hw_crypto_v2_get_rsts(uint32_t *num) { return NULL; } static inline struct rk_crypto_algt **rk_hw_crypto_v2_get_algts(uint32_t *num) { return NULL; } +static inline bool rk_hw_crypto_v2_algo_valid(struct rk_crypto_dev *rk_dev, + struct rk_crypto_algt *aglt) +{ + return false; +} #endif /* end of IS_ENABLED(CONFIG_CRYPTO_DEV_ROCKCHIP_V2) */ diff --git a/drivers/crypto/rockchip/rk_crypto_v3.c b/drivers/crypto/rockchip/rk_crypto_v3.c index aa0544f8d6b6..2b7bd1c24fe9 100644 --- a/drivers/crypto/rockchip/rk_crypto_v3.c +++ b/drivers/crypto/rockchip/rk_crypto_v3.c @@ -12,6 +12,40 @@ #include "rk_crypto_v3.h" #include "rk_crypto_v3_reg.h" +static const u32 cipher_mode2bit_mask[] = { + [CIPHER_MODE_ECB] = CRYPTO_ECB_FLAG, + [CIPHER_MODE_CBC] = CRYPTO_CBC_FLAG, + [CIPHER_MODE_CFB] = CRYPTO_CFB_FLAG, + [CIPHER_MODE_OFB] = CRYPTO_OFB_FLAG, + [CIPHER_MODE_CTR] = CRYPTO_CTR_FLAG, + [CIPHER_MODE_XTS] = CRYPTO_XTS_FLAG, + [CIPHER_MODE_CTS] = CRYPTO_CTS_FLAG, + [CIPHER_MODE_CCM] = CRYPTO_CCM_FLAG, + [CIPHER_MODE_GCM] = CRYPTO_GCM_FLAG, + [CIPHER_MODE_CMAC] = CRYPTO_CMAC_FLAG, + [CIPHER_MODE_CBCMAC] = CRYPTO_CBCMAC_FLAG, +}; + +static const u32 hash_algo2bit_mask[] = { + [HASH_ALGO_SHA1] = CRYPTO_HASH_SHA1_FLAG, + [HASH_ALGO_SHA224] = CRYPTO_HASH_SHA224_FLAG, + [HASH_ALGO_SHA256] = CRYPTO_HASH_SHA256_FLAG, + [HASH_ALGO_SHA384] = CRYPTO_HASH_SHA384_FLAG, + [HASH_ALGO_SHA512] = CRYPTO_HASH_SHA512_FLAG, + [HASH_ALGO_SHA512_224] = CRYPTO_HASH_SHA512_224_FLAG, + [HASH_ALGO_SHA512_256] = CRYPTO_HASH_SHA512_256_FLAG, + [HASH_ALGO_MD5] = CRYPTO_HASH_MD5_FLAG, + [HASH_ALGO_SM3] = CRYPTO_HASH_SM3_FLAG, +}; + +static const u32 hmac_algo2bit_mask[] = { + [HASH_ALGO_SHA1] = CRYPTO_HMAC_SHA1_FLAG, + [HASH_ALGO_SHA256] = CRYPTO_HMAC_SHA256_FLAG, + [HASH_ALGO_SHA512] = CRYPTO_HMAC_SHA512_FLAG, + [HASH_ALGO_MD5] = CRYPTO_HMAC_MD5_FLAG, + [HASH_ALGO_SM3] = CRYPTO_HMAC_SM3_FLAG, +}; + static const char * const crypto_v3_rsts[] = { "crypto-rst", }; @@ -59,6 +93,71 @@ static struct rk_crypto_algt *crypto_v3_algs[] = { &rk_v2_asym_rsa, /* rsa */ }; +static bool rk_is_cipher_support(struct rk_crypto_dev *rk_dev, u32 algo, u32 mode, u32 key_len) +{ + u32 version = 0; + u32 mask = 0; + bool key_len_valid = true; + + switch (algo) { + case CIPHER_ALGO_DES: + case CIPHER_ALGO_DES3_EDE: + version = CRYPTO_READ(rk_dev, CRYPTO_DES_VERSION); + + if (key_len == 8) + key_len_valid = true; + else if (key_len == 16 || key_len == 24) + key_len_valid = version & CRYPTO_TDES_FLAG; + else + key_len_valid = false; + break; + case CIPHER_ALGO_AES: + version = CRYPTO_READ(rk_dev, CRYPTO_AES_VERSION); + + if (key_len == 16) + key_len_valid = version & CRYPTO_AES128_FLAG; + else if (key_len == 24) + key_len_valid = version & CRYPTO_AES192_FLAG; + else if (key_len == 32) + key_len_valid = version & CRYPTO_AES256_FLAG; + else + key_len_valid = false; + break; + case CIPHER_ALGO_SM4: + version = CRYPTO_READ(rk_dev, CRYPTO_SM4_VERSION); + + key_len_valid = (key_len == SM4_KEY_SIZE) ? true : false; + break; + default: + return false; + } + + mask = cipher_mode2bit_mask[mode]; + + if (key_len == 0) + key_len_valid = true; + + return (version & mask) && key_len_valid; +} + +static bool rk_is_hash_support(struct rk_crypto_dev *rk_dev, u32 algo, u32 type) +{ + u32 version = 0; + u32 mask = 0; + + if (type == ALG_TYPE_HMAC) { + version = CRYPTO_READ(rk_dev, CRYPTO_HMAC_VERSION); + mask = hmac_algo2bit_mask[algo]; + } else if (type == ALG_TYPE_HASH) { + version = CRYPTO_READ(rk_dev, CRYPTO_HASH_VERSION); + mask = hash_algo2bit_mask[algo]; + } else { + return false; + } + + return version & mask; +} + int rk_hw_crypto_v3_init(struct device *dev, void *hw_info) { int err = 0; @@ -102,3 +201,19 @@ struct rk_crypto_algt **rk_hw_crypto_v3_get_algts(uint32_t *num) return crypto_v3_algs; } +bool rk_hw_crypto_v3_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt) +{ + if (aglt->type == ALG_TYPE_CIPHER) { + CRYPTO_TRACE("CIPHER"); + return rk_is_cipher_support(rk_dev, aglt->algo, aglt->mode, 0); + } else if (aglt->type == ALG_TYPE_HASH || aglt->type == ALG_TYPE_HMAC) { + CRYPTO_TRACE("HASH/HMAC"); + return rk_is_hash_support(rk_dev, aglt->algo, aglt->type); + } else if (aglt->type == ALG_TYPE_ASYM) { + CRYPTO_TRACE("RSA"); + return true; + } else { + return false; + } +} + diff --git a/drivers/crypto/rockchip/rk_crypto_v3.h b/drivers/crypto/rockchip/rk_crypto_v3.h index 91939e6807e3..6580ed00bca2 100644 --- a/drivers/crypto/rockchip/rk_crypto_v3.h +++ b/drivers/crypto/rockchip/rk_crypto_v3.h @@ -23,6 +23,7 @@ struct rk_hw_crypto_v3_info { .hw_deinit = rk_hw_crypto_v3_deinit,\ .hw_get_rsts = rk_hw_crypto_v3_get_rsts,\ .hw_get_algts = rk_hw_crypto_v3_get_algts,\ + .hw_is_algo_valid = rk_hw_crypto_v3_algo_valid,\ .hw_info_size = sizeof(struct rk_hw_crypto_v3_info),\ .default_pka_offset = 0x0480,\ } @@ -74,6 +75,7 @@ int rk_hw_crypto_v3_init(struct device *dev, void *hw_info); void rk_hw_crypto_v3_deinit(struct device *dev, void *hw_info); const char * const *rk_hw_crypto_v3_get_rsts(uint32_t *num); struct rk_crypto_algt **rk_hw_crypto_v3_get_algts(uint32_t *num); +bool rk_hw_crypto_v3_algo_valid(struct rk_crypto_dev *rk_dev, struct rk_crypto_algt *aglt); #else @@ -81,6 +83,11 @@ static inline int rk_hw_crypto_v3_init(struct device *dev, void *hw_info) { retu static inline void rk_hw_crypto_v3_deinit(struct device *dev, void *hw_info) {} static inline const char * const *rk_hw_crypto_v3_get_rsts(uint32_t *num) { return NULL; } static inline struct rk_crypto_algt **rk_hw_crypto_v3_get_algts(uint32_t *num) { return NULL; } +static inline bool rk_hw_crypto_v3_algo_valid(struct rk_crypto_dev *rk_dev, + struct rk_crypto_algt *aglt) +{ + return false; +} #endif /* end of IS_ENABLED(CONFIG_CRYPTO_DEV_ROCKCHIP_V3) */