Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
/* SPDX-License-Identifier: GPL-2.0 */

/* Copyright (c) 2018 Rockchip Electronics Co. Ltd. */

#ifndef __RK_CRYPTO_CORE_H__
#define __RK_CRYPTO_CORE_H__

#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/algapi.h>
#include <crypto/md5.h>
#include <crypto/sha.h>
#include <crypto/sm3.h>
#include <crypto/sm4.h>
#include <crypto/gcm.h>
#include <crypto/skcipher.h>
#include <crypto/internal/aead.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/hash.h>
#include <crypto/internal/rsa.h>
#include <crypto/internal/des.h>
#include <crypto/internal/skcipher.h>

#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/timer.h>

#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