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:
parent
1a96b39cbc
commit
520f4bfa51
drivers/crypto/ccp
include/linux
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue