/* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */ #ifndef __RK_CRYPTO_CORE_H__ #define __RK_CRYPTO_CORE_H__ /* adapts to branch 4.19 */ #ifndef CRYPTO_TFM_REQ_FORBID_WEAK_KEYS #define CRYPTO_TFM_REQ_FORBID_WEAK_KEYS CRYPTO_TFM_REQ_WEAK_KEY #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rk_crypto_bignum.h" /* * Change to the lowest priority, and hardware encryption is * invoked explicitly only at the User layer. */ #define RK_CRYPTO_PRIORITY 0 /* Increase the addr_vir buffer size from 1 to 8 pages */ #define RK_BUFFER_ORDER 3 #define RK_BUFFER_SIZE (PAGE_SIZE << RK_BUFFER_ORDER) #define RK_DMA_ALIGNMENT 128 #define sha384_state sha512_state #define sha224_state sha256_state #define RK_FLAG_FINAL BIT(0) #define RK_FLAG_UPDATE BIT(1) struct rk_crypto_stat { unsigned long long busy_cnt; unsigned long long equeue_cnt; unsigned long long dequeue_cnt; unsigned long long complete_cnt; unsigned long long done_cnt; unsigned long long fake_cnt; unsigned long long irq_cnt; unsigned long long timeout_cnt; unsigned long long error_cnt; unsigned long long ever_queue_max; int last_error; }; struct rk_crypto_dev { struct device *dev; struct reset_control *rst; void __iomem *reg; void __iomem *pka_reg; int irq; struct crypto_queue queue; struct tasklet_struct queue_task; struct tasklet_struct done_task; int err; void *hw_info; struct rk_crypto_soc_data *soc_data; int clks_num; struct clk_bulk_data *clk_bulks; const char *name; struct proc_dir_entry *procfs; struct rk_crypto_stat stat; /* device lock */ spinlock_t lock; /* the public variable */ struct crypto_async_request *async_req; void *addr_vir; u32 vir_max; void *addr_aad; int aad_max; struct scatterlist src[2]; struct scatterlist dst[2]; struct timer_list timer; bool busy; void (*request_crypto)(struct rk_crypto_dev *rk_dev, const char *name); void (*release_crypto)(struct rk_crypto_dev *rk_dev, const char *name); int (*load_data)(struct rk_crypto_dev *rk_dev, struct scatterlist *sg_src, struct scatterlist *sg_dst); int (*unload_data)(struct rk_crypto_dev *rk_dev); int (*enqueue)(struct rk_crypto_dev *rk_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; bool use_lli_chain; 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); void (*complete)(struct crypto_async_request *base, int err); int (*irq_handle)(int irq, void *dev_id); int (*hw_write_key)(struct rk_crypto_dev *rk_dev, const u8 *key, u32 key_len); void (*hw_write_iv)(struct rk_crypto_dev *rk_dev, const u8 *iv, u32 iv_len); int (*hw_init)(struct rk_crypto_dev *rk_dev, u32 algo, u32 type); int (*hw_dma_start)(struct rk_crypto_dev *rk_dev, uint32_t flag); int (*hw_get_result)(struct rk_crypto_dev *rk_dev, uint8_t *data, uint32_t data_len); }; struct rk_alg_ctx { struct rk_alg_ops ops; struct scatterlist *sg_src; struct scatterlist *sg_dst; struct scatterlist sg_tmp; struct scatterlist sg_aad; struct scatterlist *req_src; struct scatterlist *req_dst; size_t src_nents; size_t dst_nents; size_t map_nents; int is_aead; unsigned int total; unsigned int assoclen; unsigned int count; unsigned int left_bytes; dma_addr_t addr_in; dma_addr_t addr_out; dma_addr_t addr_aad_in; bool aligned; bool is_dma; int align_size; int chunk_size; }; /* the private variable of hash */ struct rk_ahash_ctx { struct rk_alg_ctx algs_ctx; struct rk_crypto_dev *rk_dev; u8 authkey[SHA512_BLOCK_SIZE]; u32 authkey_len; struct scatterlist hash_sg[2]; u8 *hash_tmp; u32 hash_tmp_len; bool hash_tmp_mapped; u32 calc_cnt; u8 lastc[RK_DMA_ALIGNMENT]; u32 lastc_len; void *priv; /* for fallback */ struct crypto_ahash *fallback_tfm; }; /* the privete variable of hash for fallback */ struct rk_ahash_rctx { struct ahash_request fallback_req; u32 mode; u32 flag; }; /* the private variable of cipher */ struct rk_cipher_ctx { struct rk_alg_ctx algs_ctx; struct rk_crypto_dev *rk_dev; unsigned char key[AES_MAX_KEY_SIZE * 2]; unsigned int keylen; u32 mode; u8 iv[AES_BLOCK_SIZE]; u32 iv_len; u8 lastc[AES_BLOCK_SIZE]; bool is_enc; void *priv; /* for fallback */ bool fallback_key_inited; struct crypto_skcipher *fallback_tfm; struct skcipher_request fallback_req; // keep at the end struct crypto_aead *fallback_aead; }; struct rk_rsa_ctx { struct rk_alg_ctx algs_ctx; struct rk_bignum *n; struct rk_bignum *e; struct rk_bignum *d; struct rk_crypto_dev *rk_dev; }; enum alg_type { ALG_TYPE_HASH, ALG_TYPE_HMAC, ALG_TYPE_CIPHER, ALG_TYPE_ASYM, ALG_TYPE_AEAD, ALG_TYPE_MAX, }; struct rk_crypto_algt { struct rk_crypto_dev *rk_dev; union { struct skcipher_alg crypto; struct ahash_alg hash; struct akcipher_alg asym; struct aead_alg aead; } alg; enum alg_type type; u32 algo; u32 mode; char *name; bool use_soft_aes192; bool valid_flag; }; enum rk_hash_algo { HASH_ALGO_MD5, HASH_ALGO_SHA1, HASH_ALGO_SHA224, HASH_ALGO_SHA256, HASH_ALGO_SHA384, HASH_ALGO_SHA512, HASH_ALGO_SM3, HASH_ALGO_SHA512_224, HASH_ALGO_SHA512_256, }; enum rk_cipher_algo { CIPHER_ALGO_DES, CIPHER_ALGO_DES3_EDE, CIPHER_ALGO_AES, CIPHER_ALGO_SM4, }; enum rk_cipher_mode { CIPHER_MODE_ECB, CIPHER_MODE_CBC, CIPHER_MODE_CFB, 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 #define DES_MAX_KEY_SIZE DES_KEY_SIZE #define DES3_EDE_MIN_KEY_SIZE DES3_EDE_KEY_SIZE #define DES3_EDE_MAX_KEY_SIZE DES3_EDE_KEY_SIZE #define SM4_MIN_KEY_SIZE SM4_KEY_SIZE #define SM4_MAX_KEY_SIZE SM4_KEY_SIZE #define MD5_BLOCK_SIZE SHA1_BLOCK_SIZE #define RK_AEAD_ALGO_INIT(cipher_algo, cipher_mode, algo_name, driver_name) {\ .name = #algo_name,\ .type = ALG_TYPE_AEAD,\ .algo = CIPHER_ALGO_##cipher_algo,\ .mode = CIPHER_MODE_##cipher_mode,\ .alg.aead = {\ .base.cra_name = #algo_name,\ .base.cra_driver_name = #driver_name,\ .base.cra_priority = RK_CRYPTO_PRIORITY,\ .base.cra_flags = CRYPTO_ALG_TYPE_AEAD |\ CRYPTO_ALG_KERN_DRIVER_ONLY |\ CRYPTO_ALG_ASYNC |\ CRYPTO_ALG_NEED_FALLBACK,\ .base.cra_blocksize = 1,\ .base.cra_ctxsize = sizeof(struct rk_cipher_ctx),\ .base.cra_alignmask = 0x07,\ .base.cra_module = THIS_MODULE,\ .init = rk_aead_init_tfm,\ .exit = rk_aead_exit_tfm,\ .ivsize = GCM_AES_IV_SIZE,\ .chunksize = cipher_algo##_BLOCK_SIZE,\ .maxauthsize = AES_BLOCK_SIZE,\ .setkey = rk_aead_setkey,\ .setauthsize = rk_aead_gcm_setauthsize,\ .encrypt = rk_aead_encrypt,\ .decrypt = rk_aead_decrypt,\ } \ } #define RK_CIPHER_ALGO_INIT(cipher_algo, cipher_mode, algo_name, driver_name) {\ .name = #algo_name,\ .type = ALG_TYPE_CIPHER,\ .algo = CIPHER_ALGO_##cipher_algo,\ .mode = CIPHER_MODE_##cipher_mode,\ .alg.crypto = {\ .base.cra_name = #algo_name,\ .base.cra_driver_name = #driver_name,\ .base.cra_priority = RK_CRYPTO_PRIORITY,\ .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |\ CRYPTO_ALG_ASYNC |\ CRYPTO_ALG_NEED_FALLBACK,\ .base.cra_blocksize = cipher_algo##_BLOCK_SIZE,\ .base.cra_ctxsize = sizeof(struct rk_cipher_ctx),\ .base.cra_alignmask = 0x07,\ .base.cra_module = THIS_MODULE,\ .init = rk_ablk_init_tfm,\ .exit = rk_ablk_exit_tfm,\ .min_keysize = cipher_algo##_MIN_KEY_SIZE,\ .max_keysize = cipher_algo##_MAX_KEY_SIZE,\ .ivsize = cipher_algo##_BLOCK_SIZE,\ .chunksize = cipher_algo##_BLOCK_SIZE,\ .setkey = rk_cipher_setkey,\ .encrypt = rk_cipher_encrypt,\ .decrypt = rk_cipher_decrypt,\ } \ } #define RK_CIPHER_ALGO_XTS_INIT(cipher_algo, algo_name, driver_name) {\ .name = #algo_name,\ .type = ALG_TYPE_CIPHER,\ .algo = CIPHER_ALGO_##cipher_algo,\ .mode = CIPHER_MODE_XTS,\ .alg.crypto = {\ .base.cra_name = #algo_name,\ .base.cra_driver_name = #driver_name,\ .base.cra_priority = RK_CRYPTO_PRIORITY,\ .base.cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |\ CRYPTO_ALG_ASYNC |\ CRYPTO_ALG_NEED_FALLBACK,\ .base.cra_blocksize = cipher_algo##_BLOCK_SIZE,\ .base.cra_ctxsize = sizeof(struct rk_cipher_ctx),\ .base.cra_alignmask = 0x07,\ .base.cra_module = THIS_MODULE,\ .init = rk_ablk_init_tfm,\ .exit = rk_ablk_exit_tfm,\ .min_keysize = cipher_algo##_MAX_KEY_SIZE,\ .max_keysize = cipher_algo##_MAX_KEY_SIZE * 2,\ .ivsize = cipher_algo##_BLOCK_SIZE,\ .chunksize = cipher_algo##_BLOCK_SIZE,\ .setkey = rk_cipher_setkey,\ .encrypt = rk_cipher_encrypt,\ .decrypt = rk_cipher_decrypt,\ } \ } #define RK_HASH_ALGO_INIT(hash_algo, algo_name) {\ .name = #algo_name,\ .type = ALG_TYPE_HASH,\ .algo = HASH_ALGO_##hash_algo,\ .alg.hash = {\ .init = rk_ahash_init,\ .update = rk_ahash_update,\ .final = rk_ahash_final,\ .finup = rk_ahash_finup,\ .export = rk_ahash_export,\ .import = rk_ahash_import,\ .digest = rk_ahash_digest,\ .halg = {\ .digestsize = hash_algo##_DIGEST_SIZE,\ .statesize = sizeof(struct algo_name##_state),\ .base = {\ .cra_name = #algo_name,\ .cra_driver_name = #algo_name"-rk",\ .cra_priority = RK_CRYPTO_PRIORITY,\ .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |\ CRYPTO_ALG_ASYNC |\ CRYPTO_ALG_NEED_FALLBACK,\ .cra_blocksize = hash_algo##_BLOCK_SIZE,\ .cra_ctxsize = sizeof(struct rk_ahash_ctx),\ .cra_alignmask = 0,\ .cra_init = rk_cra_hash_init,\ .cra_exit = rk_cra_hash_exit,\ .cra_module = THIS_MODULE,\ } \ } \ } \ } #define RK_HMAC_ALGO_INIT(hash_algo, algo_name) {\ .name = "hmac(" #algo_name ")",\ .type = ALG_TYPE_HMAC,\ .algo = HASH_ALGO_##hash_algo,\ .alg.hash = {\ .init = rk_ahash_init,\ .update = rk_ahash_update,\ .final = rk_ahash_final,\ .finup = rk_ahash_finup,\ .export = rk_ahash_export,\ .import = rk_ahash_import,\ .digest = rk_ahash_digest,\ .setkey = rk_ahash_hmac_setkey,\ .halg = {\ .digestsize = hash_algo##_DIGEST_SIZE,\ .statesize = sizeof(struct algo_name##_state),\ .base = {\ .cra_name = "hmac(" #algo_name ")",\ .cra_driver_name = "hmac-" #algo_name "-rk",\ .cra_priority = RK_CRYPTO_PRIORITY,\ .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY |\ CRYPTO_ALG_ASYNC |\ CRYPTO_ALG_NEED_FALLBACK,\ .cra_blocksize = hash_algo##_BLOCK_SIZE,\ .cra_ctxsize = sizeof(struct rk_ahash_ctx),\ .cra_alignmask = 0,\ .cra_init = rk_cra_hash_init,\ .cra_exit = rk_cra_hash_exit,\ .cra_module = THIS_MODULE,\ } \ } \ } \ } #define IS_TYPE_HMAC(type) ((type) == ALG_TYPE_HMAC) #define CRYPTO_READ(dev, offset) \ readl_relaxed(((dev)->reg + (offset))) #define CRYPTO_WRITE(dev, offset, val) \ writel_relaxed((val), ((dev)->reg + (offset))) #ifdef DEBUG #define CRYPTO_TRACE(format, ...) pr_err("[%s, %05d]-trace: " format "\n", \ __func__, __LINE__, ##__VA_ARGS__) #define CRYPTO_MSG(format, ...) pr_err("[%s, %05d]-msg:" format "\n", \ __func__, __LINE__, ##__VA_ARGS__) #define CRYPTO_DUMPHEX(var_name, data, len) print_hex_dump(KERN_CONT, (var_name), \ DUMP_PREFIX_OFFSET, \ 16, 1, (data), (len), false) #else #define CRYPTO_TRACE(format, ...) #define CRYPTO_MSG(format, ...) #define CRYPTO_DUMPHEX(var_name, data, len) #endif #endif