newfeature: crypto: ccp: Support SM2 algorithm for hygon ccp.

In order to add SM2 driver for hygon ccp, relating to
SM2_sign, SM2_verify, SM2_encrypt and SM2_decrypt.

Signed-off-by: Yabin Li <liyabin@hygon.cn>
Signed-off-by: yangdepei <yangdepei@hygon.cn>
This commit is contained in:
Yabin Li 2022-05-07 18:13:46 +08:00 committed by Jianping Liu
parent 1a96b39cbc
commit 520f4bfa51
9 changed files with 1313 additions and 0 deletions

View File

@ -46,6 +46,13 @@ config CRYPTO_DEV_SP_PSP
along with software-based Trusted Execution Environment (TEE) to
enable third-party trusted applications.
config HYGON_GM
bool "Hygon GM (sm2/sm3/sm4) Interface"
default y
depends on CRYPTO_DEV_CCP_CRYPTO && X86_64
help
Hygon GM ccp driver
config CRYPTO_DEV_CCP_DEBUGFS
bool "Enable CCP Internals in DebugFS"
default n

View File

@ -23,3 +23,5 @@ ccp-crypto-objs := ccp-crypto-main.o \
ccp-crypto-des3.o \
ccp-crypto-rsa.o \
ccp-crypto-sha.o
ccp-crypto-$(CONFIG_HYGON_GM) += ccp-crypto-sm2-hygon.o

View File

@ -39,6 +39,10 @@ static unsigned int rsa_disable;
module_param(rsa_disable, uint, 0444);
MODULE_PARM_DESC(rsa_disable, "Disable use of RSA - any non-zero value");
static unsigned int sm_disable;
module_param(sm_disable, uint, 0444);
MODULE_PARM_DESC(sm_disable, "Disable use of SM2/SM3/SM4 - any non-zero value");
/* List heads for the supported algorithms */
static LIST_HEAD(hash_algs);
static LIST_HEAD(skcipher_algs);
@ -322,6 +326,17 @@ static int ccp_register_algs(void)
{
int ret;
#ifdef CONFIG_HYGON_GM
if (!sm_disable && boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
ret = ccp_register_sm2_hygon_algs(&akcipher_algs);
if (ret)
return ret;
/* Return on hygon platform */
return 0;
}
#endif
if (!aes_disable) {
ret = ccp_register_aes_algs(&skcipher_algs);
if (ret)

File diff suppressed because it is too large Load Diff

View File

@ -258,6 +258,43 @@ struct ccp_rsa_req_ctx {
#define CCP_RSA_MAXMOD (4 * 1024 / 8)
#define CCP5_RSA_MAXMOD (16 * 1024 / 8)
/***** SM2 related defines *****/
#define CCP_SM2_OPERAND_LEN 32
#define CCP_SM2_PRIVATE_KEY_LEN CCP_SM2_OPERAND_LEN
#define CCP_SM2_PUBLIC_KEY_LEN (CCP_SM2_OPERAND_LEN * 2)
#define CCP_SM2_ENCRYPT_EXT_LEN (CCP_SM2_PUBLIC_KEY_LEN + SM3_DIGEST_SIZE)
#define CCP_SM2_MMUL_LEN (CCP_SM2_OPERAND_LEN * 2)
struct ccp_sm2_ctx {
u32 pri_key_len;
u32 pub_key_len;
u8 pri_key[CCP_SM2_PRIVATE_KEY_LEN];
u8 pub_key[CCP_SM2_PUBLIC_KEY_LEN];
};
enum ccp_sm2_op_phase {
CCP_SM2_SIGN_PH_SIGN,
CCP_SM2_VERIFY_PH_VERIFY,
CCP_SM2_ENC_PH_KG,
CCP_SM2_ENC_PH_LP,
CCP_SM2_DEC_PH_LP
};
struct ccp_sm2_req_ctx {
enum ccp_sm2_op_phase phase;
struct akcipher_request *req;
u8 src[CCP_SM2_VERIFY_SRC_SIZE];
u8 dst[CCP_SM2_DST_SIZE];
struct scatterlist src_sg;
struct scatterlist dst_sg;
struct work_struct work;
struct ccp_cmd cmd;
};
/***** Common Context Structure *****/
struct ccp_ctx {
int (*complete)(struct crypto_async_request *req, int ret);
@ -267,6 +304,7 @@ struct ccp_ctx {
struct ccp_rsa_ctx rsa;
struct ccp_sha_ctx sha;
struct ccp_des3_ctx des3;
struct ccp_sm2_ctx sm2;
} u;
};
@ -282,5 +320,6 @@ int ccp_register_aes_aeads(struct list_head *head);
int ccp_register_sha_algs(struct list_head *head);
int ccp_register_des3_algs(struct list_head *head);
int ccp_register_rsa_algs(struct list_head *head);
int ccp_register_sm2_hygon_algs(struct list_head *head);
#endif

View File

@ -131,6 +131,11 @@ union ccp_function {
u16 type:2;
u16 mode:3;
} ecc;
struct {
u16 rand:1;
u16 rsvd:11;
u16 mode:3;
} sm2;
u16 raw;
};
@ -151,6 +156,8 @@ union ccp_function {
#define CCP_PT_BITWISE(p) ((p)->pt.bitwise)
#define CCP_ECC_MODE(p) ((p)->ecc.mode)
#define CCP_ECC_AFFINE(p) ((p)->ecc.one)
#define CCP_SM2_RAND(p) ((p)->sm2.rand)
#define CCP_SM2_MODE(p) ((p)->sm2.mode)
/* Word 0 */
#define CCP5_CMD_DW0(p) ((p)->dw0)
@ -584,6 +591,43 @@ static int ccp5_perform_ecc(struct ccp_op *op)
return ccp5_do_cmd(&desc, op->cmd_q);
}
static int ccp5_perform_sm2(struct ccp_op *op)
{
struct ccp5_desc desc;
union ccp_function function;
struct ccp_dma_info *saddr = &op->src.u.dma;
struct ccp_dma_info *daddr = &op->dst.u.dma;
op->cmd_q->total_sm2_ops++;
memset(&desc, 0, Q_DESC_SIZE);
CCP5_CMD_ENGINE(&desc) = CCP_ENGINE_SM2;
CCP5_CMD_SOC(&desc) = 0;
CCP5_CMD_IOC(&desc) = 1;
CCP5_CMD_INIT(&desc) = 1;
CCP5_CMD_EOM(&desc) = 1;
CCP5_CMD_PROT(&desc) = 0;
function.raw = 0;
CCP_SM2_RAND(&function) = op->u.sm2.rand;
CCP_SM2_MODE(&function) = op->u.sm2.mode;
CCP5_CMD_FUNCTION(&desc) = function.raw;
/* Length of source data must match with mode */
CCP5_CMD_LEN(&desc) = saddr->length;
CCP5_CMD_SRC_LO(&desc) = ccp_addr_lo(saddr);
CCP5_CMD_SRC_HI(&desc) = ccp_addr_hi(saddr);
CCP5_CMD_SRC_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
CCP5_CMD_DST_LO(&desc) = ccp_addr_lo(daddr);
CCP5_CMD_DST_HI(&desc) = ccp_addr_hi(daddr);
CCP5_CMD_DST_MEM(&desc) = CCP_MEMTYPE_SYSTEM;
return ccp5_do_cmd(&desc, op->cmd_q);
}
static int ccp_find_lsb_regions(struct ccp_cmd_queue *cmd_q, u64 status)
{
int q_mask = 1 << cmd_q->id;
@ -1103,6 +1147,7 @@ static const struct ccp_actions ccp5_actions = {
.rsa = ccp5_perform_rsa,
.passthru = ccp5_perform_passthru,
.ecc = ccp5_perform_ecc,
.sm2 = ccp5_perform_sm2,
.sballoc = ccp_lsb_alloc,
.sbfree = ccp_lsb_free,
.init = ccp5_init,

View File

@ -334,6 +334,7 @@ struct ccp_cmd_queue {
unsigned long total_rsa_ops;
unsigned long total_pt_ops;
unsigned long total_ecc_ops;
unsigned long total_sm2_ops;
} ____cacheline_aligned;
struct ccp_device {
@ -528,6 +529,11 @@ struct ccp_ecc_op {
enum ccp_ecc_function function;
};
struct ccp_sm2_op {
u32 rand;
enum ccp_sm2_mode mode;
};
struct ccp_op {
struct ccp_cmd_queue *cmd_q;
@ -551,6 +557,7 @@ struct ccp_op {
struct ccp_rsa_op rsa;
struct ccp_passthru_op passthru;
struct ccp_ecc_op ecc;
struct ccp_sm2_op sm2;
} u;
};
@ -657,6 +664,7 @@ struct ccp_actions {
int (*rsa)(struct ccp_op *);
int (*passthru)(struct ccp_op *);
int (*ecc)(struct ccp_op *);
int (*sm2)(struct ccp_op *op);
u32 (*sballoc)(struct ccp_cmd_queue *, unsigned int);
void (*sbfree)(struct ccp_cmd_queue *, unsigned int, unsigned int);
unsigned int (*get_free_slots)(struct ccp_cmd_queue *);

View File

@ -2463,6 +2463,97 @@ ccp_run_ecc_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
}
}
static int ccp_run_sm2_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
{
struct ccp_sm2_engine *sm2 = &cmd->u.sm2;
struct ccp_data src, dst;
struct ccp_op op;
int ret;
if (!sm2->src || !sm2->dst)
return -EINVAL;
memset(&op, 0, sizeof(op));
op.cmd_q = cmd_q;
op.jobid = CCP_NEW_JOBID(cmd_q->ccp);
op.ioc = 1;
op.init = 1;
op.eom = 1;
op.u.sm2.rand = sm2->rand & 0x1;
op.u.sm2.mode = sm2->mode;
memset(&src, 0, sizeof(src));
ret = ccp_init_sg_workarea(&src.sg_wa, cmd_q->ccp->dev,
sm2->src, sm2->src_len, DMA_TO_DEVICE);
if (ret)
return ret;
/* if src isn't contiguous, should copy to a contiguous buffer */
if (src.sg_wa.dma_count == 1) {
op.src.u.dma.address = sg_dma_address(src.sg_wa.sg);
} else {
ccp_sg_free(&src.sg_wa);
ret = ccp_init_dm_workarea(&src.dm_wa, cmd_q, sm2->src_len,
DMA_TO_DEVICE);
if (ret)
goto e_src;
ccp_set_dm_area(&src.dm_wa, 0, sm2->src, 0, sm2->src_len);
op.src.u.dma.address = src.dm_wa.dma.address;
}
op.src.type = CCP_MEMTYPE_SYSTEM;
op.src.u.dma.offset = 0;
op.src.u.dma.length = sm2->src_len;
op.src.u.dma.dir = DMA_TO_DEVICE;
memset(&dst, 0, sizeof(dst));
ret = ccp_init_sg_workarea(&dst.sg_wa, cmd_q->ccp->dev,
sm2->dst, sm2->dst_len, DMA_FROM_DEVICE);
if (ret)
goto e_src;
/* if dst isn't contiguous, should copy to a contiguous buffer */
if (dst.sg_wa.dma_count == 1) {
op.dst.u.dma.address = sg_dma_address(dst.sg_wa.sg);
} else {
ccp_sg_free(&dst.sg_wa);
ret = ccp_init_dm_workarea(&dst.dm_wa, cmd_q, sm2->dst_len,
DMA_FROM_DEVICE);
if (ret)
goto e_dst;
op.dst.u.dma.address = dst.dm_wa.dma.address;
}
op.dst.type = CCP_MEMTYPE_SYSTEM;
op.dst.u.dma.offset = 0;
op.dst.u.dma.length = sm2->dst_len;
op.dst.u.dma.dir = DMA_FROM_DEVICE;
ret = cmd_q->ccp->vdata->perform->sm2(&op);
if (ret) {
cmd->engine_error = cmd_q->cmd_error;
goto e_dst;
}
if (dst.dm_wa.address) {
ccp_get_dm_area(&dst.dm_wa, 0, sm2->dst, 0, sm2->dst_len);
memset(dst.dm_wa.address, 0, sm2->dst_len);
}
e_dst:
ccp_free_data(&dst, cmd_q);
e_src:
if (src.dm_wa.address)
memset(src.dm_wa.address, 0, sm2->src_len);
ccp_free_data(&src, cmd_q);
return ret;
}
int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
{
int ret;
@ -2507,6 +2598,9 @@ int ccp_run_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd)
case CCP_ENGINE_ECC:
ret = ccp_run_ecc_cmd(cmd_q, cmd);
break;
case CCP_ENGINE_SM2:
ret = ccp_run_sm2_cmd(cmd_q, cmd);
break;
default:
ret = -EINVAL;
}

View File

@ -17,6 +17,7 @@
#include <crypto/aes.h>
#include <crypto/sha1.h>
#include <crypto/sha2.h>
#include <crypto/sm3.h>
struct ccp_device;
struct ccp_cmd;
@ -587,6 +588,51 @@ struct ccp_ecc_engine {
u16 ecc_result;
};
/***** SM2 engine *****/
#define CCP_SM2_VERIFY_SRC_SIZE 160
#define CCP_SM2_LP_SRC_SIZE 96
#define CCP_SM2_KG_SRC_SIZE 32
#define CCP_SM2_SIGN_SRC_SIZE 96
#define CCP_SM2_MMUL_SRC_SIZE 64
#define CCP_SM2_DST_SIZE 128
/**
* ccp_sm2_mode - SM2 operation mode
*
* @CCP_SM2_MODE_VERIFY: Verify mode
* @CCP_SM2_MODE_LP: LP mode
* @CCP_SM2_MODE_KG: KG mode
* @CCP_SM2_MODE_SIGN: SIGN mode
* @CCP_SM2_MODE_MMUL: MMUL mode
*/
enum ccp_sm2_mode {
CCP_SM2_MODE_VERIFY,
CCP_SM2_MODE_LP,
CCP_SM2_MODE_KG,
CCP_SM2_MODE_SIGN,
CCP_SM2_MODE_MMUL,
CCP_SM2_MODE__LAST,
};
/**
* struct ccp_sm2_engine - CCP SM2 operation
* @mode: SM2 operation mode
* @rand: indicateing that operand_k is from TRNG or not
* @src: data to be used for this operation
* @dst: data produced by this operation
* @src_len: length in bytes of data used for this operation
* @dst_len: length in bytes of data produced by this operation
*/
struct ccp_sm2_engine {
enum ccp_sm2_mode mode;
u32 rand;
struct scatterlist *src;
u32 src_len;
struct scatterlist *dst;
u32 dst_len;
};
/**
* ccp_engine - CCP operation identifiers
@ -599,6 +645,7 @@ struct ccp_ecc_engine {
* @CCP_ENGINE_PASSTHRU: pass-through operation
* @CCP_ENGINE_ZLIB_DECOMPRESS: unused
* @CCP_ENGINE_ECC: ECC operation
* @CCP_ENGINE_SM2: SM2 operation
*/
enum ccp_engine {
CCP_ENGINE_AES = 0,
@ -609,6 +656,7 @@ enum ccp_engine {
CCP_ENGINE_PASSTHRU,
CCP_ENGINE_ZLIB_DECOMPRESS,
CCP_ENGINE_ECC,
CCP_ENGINE_SM2 = 8, /* fixed value */
CCP_ENGINE__LAST,
};
@ -657,6 +705,7 @@ struct ccp_cmd {
struct ccp_passthru_engine passthru;
struct ccp_passthru_nomap_engine passthru_nomap;
struct ccp_ecc_engine ecc;
struct ccp_sm2_engine sm2;
} u;
/* Completion callback support */