
From: lizhi <lizhi206@huawei.com> Upstream: Yes Bugfix or Feature: Bugfix DTS: DTS2024111417327 1. Support ecdh with secp256r1 curve. 2. The algorithm will be scheduled first for high-performance cores. 3. The result of configuration does not affect the task success or failure. Signed-off-by: lizhi <lizhi206@huawei.com> Signed-off-by: Qi Tao <taoqi10@huawei.com> --- drv/hisi_hpre.c | 90 +++++++++++++++++++++++++++++++++++++++- include/drv/wd_ecc_drv.h | 9 ++++ include/wd_ecc_curve.h | 27 ++++++++++++ wd_ecc.c | 60 +++++++++++++++++++++++++-- 4 files changed, 182 insertions(+), 4 deletions(-) diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c index 7c652d10..a18d358f 100644 --- a/drv/hisi_hpre.c +++ b/drv/hisi_hpre.c @@ -10,6 +10,7 @@ #include <sys/mman.h> #include <sys/types.h> #include "hisi_qm_udrv.h" +#include "../include/wd_ecc_curve.h" #include "../include/drv/wd_rsa_drv.h" #include "../include/drv/wd_dh_drv.h" #include "../include/drv/wd_ecc_drv.h" @@ -42,6 +43,10 @@ #define WD_TRANS_FAIL 0 +#define CURVE_PARAM_NUM 6 +#define SECP256R1_KEY_SIZE 32 +#define SECP256R1_PARAM_SIZE (CURVE_PARAM_NUM * SECP256R1_KEY_SIZE) + enum hpre_alg_type { HPRE_ALG_NC_NCRT = 0x0, HPRE_ALG_NC_CRT = 0x1, @@ -110,6 +115,10 @@ struct hisi_hpre_ctx { struct wd_ctx_config_internal config; }; +struct hpre_ecc_ctx { + __u32 enable_hpcore; +}; + static void dump_hpre_msg(void *msg, int alg) { struct wd_rsa_msg *rsa_msg; @@ -1358,6 +1367,7 @@ static int u_is_in_p(struct wd_ecc_msg *msg) static int ecc_prepare_in(struct wd_ecc_msg *msg, struct hisi_hpre_sqe *hw_msg, void **data) { + struct hpre_ecc_ctx *ecc_ctx = msg->drv_cfg; int ret = -WD_EINVAL; switch (msg->req.op_type) { @@ -1366,11 +1376,15 @@ static int ecc_prepare_in(struct wd_ecc_msg *msg, /* driver to identify sm2 algorithm when async receive */ hw_msg->sm2_mlen = msg->req.op_type; hw_msg->bd_rsv2 = 1; /* fall through */ - case WD_SM2_KG: /* fall through */ + case WD_SM2_KG: + ret = ecc_prepare_dh_gen_in(msg, hw_msg, data); + break; case WD_ECXDH_GEN_KEY: + hw_msg->bd_rsv2 = ecc_ctx->enable_hpcore; ret = ecc_prepare_dh_gen_in(msg, hw_msg, data); break; case WD_ECXDH_COMPUTE_KEY: + hw_msg->bd_rsv2 = ecc_ctx->enable_hpcore; ret = ecc_prepare_dh_compute_in(msg, hw_msg, data); if (!ret && (msg->curve_id == WD_X25519 || msg->curve_id == WD_X448)) @@ -2491,6 +2505,79 @@ static int hpre_get_usage(void *param) return WD_SUCCESS; } +static int ecc_sess_eops_init(void **params) +{ + struct hpre_ecc_ctx *ecc_ctx; + + if (!params) { + WD_ERR("invalid: extend ops init params address is NULL!\n"); + return -WD_EINVAL; + } + + if (*params) { + WD_ERR("invalid: extend ops init params repeatedly!\n"); + return -WD_EINVAL; + } + + ecc_ctx = calloc(1, sizeof(struct hpre_ecc_ctx)); + if (!ecc_ctx) + return -WD_ENOMEM; + + *params = ecc_ctx; + + return WD_SUCCESS; +} + +static void ecc_sess_eops_uninit(void *params) +{ + if (!params) { + WD_ERR("invalid: extend ops uninit params is NULL!\n"); + return; + } + + free(params); + params = NULL; +} + +static void ecc_sess_eops_params_cfg(struct wd_ecc_sess_setup *setup, + struct wd_ecc_curve *cv, void *params) +{ + __u8 data[SECP256R1_PARAM_SIZE] = SECG_P256_R1_PARAM; + struct hpre_ecc_ctx *ecc_ctx = params; + __u32 key_size; + int ret = 0; + + if (!ecc_ctx) { + WD_INFO("Info: eops config exits, but params is NULL!\n"); + return; + } + + if (strcmp(setup->alg, "ecdh")) + return; + + key_size = BITS_TO_BYTES(setup->key_bits); + if (key_size != SECP256R1_KEY_SIZE) + return; + + ret = memcmp(data, cv->p.data, SECP256R1_PARAM_SIZE); + if (!ret) + ecc_ctx->enable_hpcore = 1; +} + +static int hpre_ecc_get_extend_ops(void *ops) +{ + struct wd_ecc_extend_ops *ecc_ops = ops; + + if (!ecc_ops) + return -WD_EINVAL; + + ecc_ops->params = NULL; + ecc_ops->sess_init = ecc_sess_eops_init; + ecc_ops->eops_params_cfg = ecc_sess_eops_params_cfg; + ecc_ops->sess_uninit = ecc_sess_eops_uninit; + return WD_SUCCESS; +} + #define GEN_HPRE_ALG_DRIVER(hpre_alg_name) \ {\ .drv_name = "hisi_hpre",\ @@ -2505,6 +2592,7 @@ static int hpre_get_usage(void *param) .send = ecc_send,\ .recv = ecc_recv,\ .get_usage = hpre_get_usage,\ + .get_extend_ops = hpre_ecc_get_extend_ops,\ } static struct wd_alg_driver hpre_ecc_driver[] = { diff --git a/include/drv/wd_ecc_drv.h b/include/drv/wd_ecc_drv.h index f5805cdc..37908cd2 100644 --- a/include/drv/wd_ecc_drv.h +++ b/include/drv/wd_ecc_drv.h @@ -54,6 +54,7 @@ struct wd_ecc_msg { __u16 key_bytes; /* key bytes */ __u8 curve_id; /* Ec curve denoted by enum wd_ecc_curve_type */ __u8 result; /* alg op error code */ + void *drv_cfg; /* internal driver configuration */ }; struct wd_ecc_pubkey { @@ -175,6 +176,14 @@ struct wd_ecc_out { char data[]; }; +struct wd_ecc_extend_ops { + void *params; /* the params are passed to the following ops */ + int (*eops_params_cfg)(struct wd_ecc_sess_setup *setup, + struct wd_ecc_curve *cv, void *params); + int (*sess_init)(void **params); + void (*sess_uninit)(void *params); +}; + struct wd_ecc_msg *wd_ecc_get_msg(__u32 idx, __u32 tag); #ifdef __cplusplus diff --git a/include/wd_ecc_curve.h b/include/wd_ecc_curve.h index 20b017a8..1f83edcd 100644 --- a/include/wd_ecc_curve.h +++ b/include/wd_ecc_curve.h @@ -175,6 +175,33 @@ extern "C" { 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41\ } +#define SECG_P256_R1_PARAM {\ + /* p */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\ + /* a */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,\ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,\ + /* b */\ + 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,\ + 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,\ + 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,\ + /* x */\ + 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,\ + 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,\ + 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,\ + /* y */\ + 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,\ + 0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,\ + 0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5,\ + /* order */\ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,\ + 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,\ + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51,\ +} + #define BRAINPOOL_P320_R1_PARAM {\ /* p */\ 0xD3, 0x5E, 0x47, 0x20, 0x36, 0xBC, 0x4F, 0xB7, 0xE1, 0x3C, 0x78, 0x5E,\ diff --git a/wd_ecc.c b/wd_ecc.c index 4e6a9c57..7ae5f757 100644 --- a/wd_ecc.c +++ b/wd_ecc.c @@ -28,6 +28,7 @@ #define SM2_KEY_SIZE 32 #define GET_NEGATIVE(val) (0 - (val)) #define ZA_PARAM_NUM 6 +#define WD_SECP256R1 0x18 /* consistent with enum wd_ecc_curve_id */ static __thread __u64 balance; @@ -49,6 +50,7 @@ struct wd_ecc_sess { __u32 key_size; struct wd_ecc_key key; struct wd_ecc_sess_setup setup; + struct wd_ecc_extend_ops eops; void *sched_key; }; @@ -84,7 +86,8 @@ static const struct wd_ecc_curve_list curve_list[] = { { WD_BRAINPOOLP384R1, "bpP384r1", 384, BRAINPOOL_P384_R1_PARAM }, { WD_SECP384R1, "secp384r1", 384, SECG_P384_R1_PARAM }, { WD_SECP521R1, "secp521r1", 521, SECG_P521_R1_PARAM }, - { WD_SM2P256, "sm2", 256, SM2_P256_V1_PARAM } + { WD_SM2P256, "sm2", 256, SM2_P256_V1_PARAM }, + { WD_SECP256R1, "secp256r1", 256, SECG_P256_R1_PARAM }, }; static const struct curve_param_desc curve_pram_list[] = { @@ -1166,6 +1169,39 @@ static void del_sess_key(struct wd_ecc_sess *sess) } } +static int wd_ecc_sess_eops_init(struct wd_ecc_sess *sess) +{ + int ret; + + if (sess->eops.sess_init) { + if (!sess->eops.sess_uninit) { + WD_ERR("failed to get extend ops in session!\n"); + return -WD_EINVAL; + } + ret = sess->eops.sess_init(&sess->eops.params); + if (ret) { + WD_ERR("failed to init extend ops params in session!\n"); + return ret; + } + } + return WD_SUCCESS; +} + +static void wd_ecc_sess_eops_uninit(struct wd_ecc_sess *sess) +{ + if (sess->eops.sess_uninit) + sess->eops.sess_uninit(sess->eops.params); +} + +static void wd_ecc_sess_eops_cfg(struct wd_ecc_sess_setup *setup, + struct wd_ecc_sess *sess) +{ + if (sess->eops.sess_init && sess->eops.eops_params_cfg) { + /* the config result does not impact task sucesss or failure */ + sess->eops.eops_params_cfg(setup, sess->key.cv, sess->eops.params); + } +} + handle_t wd_ecc_alloc_sess(struct wd_ecc_sess_setup *setup) { struct wd_ecc_sess *sess; @@ -1187,12 +1223,26 @@ handle_t wd_ecc_alloc_sess(struct wd_ecc_sess_setup *setup) memcpy(&sess->setup, setup, sizeof(*setup)); sess->key_size = BITS_TO_BYTES(setup->key_bits); - ret = create_sess_key(setup, sess); + ret = wd_ecc_setting.driver->get_extend_ops(&sess->eops); + if (ret) { + WD_ERR("failed to get ecc sess extend ops!\n"); + goto sess_err; + } + + ret = wd_ecc_sess_eops_init(sess); if (ret) { - WD_ERR("failed to creat ecc sess keys!\n"); + WD_ERR("failed to init ecc sess extend eops!\n"); goto sess_err; } + ret = create_sess_key(setup, sess); + if (ret) { + WD_ERR("failed to create ecc sess keys!\n"); + goto eops_err; + } + + wd_ecc_sess_eops_cfg(setup, sess); + /* Some simple scheduler don't need scheduling parameters */ sess->sched_key = (void *)wd_ecc_setting.sched.sched_init( wd_ecc_setting.sched.h_sched_ctx, setup->sched_param); @@ -1205,6 +1255,8 @@ handle_t wd_ecc_alloc_sess(struct wd_ecc_sess_setup *setup) sched_err: del_sess_key(sess); +eops_err: + wd_ecc_sess_eops_uninit(sess); sess_err: free(sess); return (handle_t)0; @@ -1222,6 +1274,7 @@ void wd_ecc_free_sess(handle_t sess) if (sess_t->sched_key) free(sess_t->sched_key); del_sess_key(sess_t); + wd_ecc_sess_eops_uninit(sess); free(sess_t); } @@ -1494,6 +1547,7 @@ static int fill_ecc_msg(struct wd_ecc_msg *msg, struct wd_ecc_req *req, memcpy(&msg->hash, &sess->setup.hash, sizeof(msg->hash)); msg->key_bytes = sess->key_size; msg->curve_id = sess->setup.cv.cfg.id; + msg->drv_cfg = sess->eops.params; msg->result = WD_EINVAL; switch (req->op_type) { -- 2.33.0