From patchwork Sun Jun 4 09:42:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gowrishankar Muthukrishnan X-Patchwork-Id: 128027 X-Patchwork-Delegate: gakhil@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 8629D42C26; Sun, 4 Jun 2023 11:43:19 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 4830A42D20; Sun, 4 Jun 2023 11:43:07 +0200 (CEST) Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by mails.dpdk.org (Postfix) with ESMTP id 1046B42D2C for ; Sun, 4 Jun 2023 11:43:04 +0200 (CEST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 3549KBwe031564; Sun, 4 Jun 2023 02:43:04 -0700 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=pfpt0220; bh=TtiDwRmT9RjEJJPY1yz/QFF4P11RG76Xnd6HGg08lDk=; b=DJGG5F3LY190yHYZcLpSYqUZRkfk34tVLjk/H6IKa970aLSPY4aP5rXAQDb/wMPLQ+4u n5AL/6VzbM/04KMuO238WvG8ZP9LYkBuJwjg9+2esOduPzhwVh0yc2lNi8PPMmpBCPbs SmlcuFij8gL6c1VuTlLWT6Qod4RUbfSa/Nlj17pojmTytBJg/aUOd6D5ta7/xgaWKAkA CgIB3oUz1DdS1GHDIlTAbDJwKn2hig5QG7tYrOVz4VHMeopvPzht7CRRRWHjCzEFPoTw /CuYXFlIN8Sjzj/1pCBS/PiiXfy05nuAcCkY7O7StsqQKdOLF1EKDofUB0Ugas2bZuna TA== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3r051k1vnp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Sun, 04 Jun 2023 02:43:04 -0700 Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Sun, 4 Jun 2023 02:43:02 -0700 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Sun, 4 Jun 2023 02:43:02 -0700 Received: from BG-LT91401.marvell.com (BG-LT91401.marvell.com [10.28.175.191]) by maili.marvell.com (Postfix) with ESMTP id 8CE823F70A3; Sun, 4 Jun 2023 02:42:59 -0700 (PDT) From: Gowrishankar Muthukrishnan To: CC: , Akhil Goyal , Arkadiusz Kusztal , Fan Zhang , Kai Ji , Gowrishankar Muthukrishnan Subject: [PATCH v3 3/3] crypto/openssl: add SM2 asymmetric crypto support Date: Sun, 4 Jun 2023 15:12:46 +0530 Message-ID: X-Mailer: git-send-email 2.21.0 In-Reply-To: References: MIME-Version: 1.0 X-Proofpoint-GUID: DvHeZIpb42NYXJuh5OAN6dWsTvO3RRCn X-Proofpoint-ORIG-GUID: DvHeZIpb42NYXJuh5OAN6dWsTvO3RRCn X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.957,Hydra:6.0.573,FMLib:17.11.176.26 definitions=2023-06-03_08,2023-06-02_02,2023-05-22_02 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add SM2 asymmetric algorithm support in openssl PMD. Signed-off-by: Gowrishankar Muthukrishnan --- doc/guides/cryptodevs/features/openssl.ini | 1 + doc/guides/cryptodevs/openssl.rst | 1 + doc/guides/rel_notes/release_23_07.rst | 4 + drivers/crypto/openssl/openssl_pmd_private.h | 6 + drivers/crypto/openssl/rte_openssl_pmd.c | 297 +++++++++++++++++++ drivers/crypto/openssl/rte_openssl_pmd_ops.c | 48 +++ 6 files changed, 357 insertions(+) diff --git a/doc/guides/cryptodevs/features/openssl.ini b/doc/guides/cryptodevs/features/openssl.ini index 4b0f9b162e..b64c8ec4a5 100644 --- a/doc/guides/cryptodevs/features/openssl.ini +++ b/doc/guides/cryptodevs/features/openssl.ini @@ -65,6 +65,7 @@ DSA = Y Modular Exponentiation = Y Modular Inversion = Y Diffie-hellman = Y +SM2 = Y ; ; Supported Operating systems of the 'openssl' crypto driver. diff --git a/doc/guides/cryptodevs/openssl.rst b/doc/guides/cryptodevs/openssl.rst index 03041ceda1..ff21d21b23 100644 --- a/doc/guides/cryptodevs/openssl.rst +++ b/doc/guides/cryptodevs/openssl.rst @@ -53,6 +53,7 @@ Supported Asymmetric Crypto algorithms: * ``RTE_CRYPTO_ASYM_XFORM_DH`` * ``RTE_CRYPTO_ASYM_XFORM_MODINV`` * ``RTE_CRYPTO_ASYM_XFORM_MODEX`` +* ``RTE_CRYPTO_ASYM_XFORM_SM2`` Installation diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst index 8b8e69d619..aeebcffb60 100644 --- a/doc/guides/rel_notes/release_23_07.rst +++ b/doc/guides/rel_notes/release_23_07.rst @@ -61,6 +61,10 @@ New Features along with prime field curve support. +* **Updated OpenSSL crypto driver for SM2 support.** + + Added SM2 algorithm support in asymmetric crypto operations. + Removed Items ------------- diff --git a/drivers/crypto/openssl/openssl_pmd_private.h b/drivers/crypto/openssl/openssl_pmd_private.h index ed6841e460..1edb669dfd 100644 --- a/drivers/crypto/openssl/openssl_pmd_private.h +++ b/drivers/crypto/openssl/openssl_pmd_private.h @@ -12,6 +12,7 @@ #include #include #include +#include #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) #include #include @@ -200,6 +201,11 @@ struct openssl_asym_session { OSSL_PARAM_BLD * param_bld; #endif } s; + struct { +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + OSSL_PARAM * params; +#endif + } sm2; } u; } __rte_cache_aligned; /** Set and validate OPENSSL crypto session parameters */ diff --git a/drivers/crypto/openssl/rte_openssl_pmd.c b/drivers/crypto/openssl/rte_openssl_pmd.c index 384d262621..9442d39907 100644 --- a/drivers/crypto/openssl/rte_openssl_pmd.c +++ b/drivers/crypto/openssl/rte_openssl_pmd.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "openssl_pmd_private.h" #include "compat.h" @@ -2662,6 +2663,286 @@ process_openssl_rsa_op_evp(struct rte_crypto_op *cop, return ret; } + +static int +process_openssl_sm2_op_evp(struct rte_crypto_op *cop, + struct openssl_asym_session *sess) +{ + EVP_PKEY_CTX *kctx = NULL, *sctx = NULL, *cctx = NULL; + struct rte_crypto_asym_op *op = cop->asym; + OSSL_PARAM_BLD *param_bld = NULL; + OSSL_PARAM *params = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *pkey_bn = NULL; + uint8_t pubkey[64]; + size_t len = 0; + int ret = -1; + + cop->status = RTE_CRYPTO_OP_STATUS_ERROR; + + if (cop->asym->sm2.k.data != NULL) + goto err_sm2; + + param_bld = OSSL_PARAM_BLD_new(); + if (!param_bld) { + OPENSSL_LOG(ERR, "failed to allocate params\n"); + goto err_sm2; + } + + ret = OSSL_PARAM_BLD_push_utf8_string(param_bld, + OSSL_PKEY_PARAM_GROUP_NAME, "SM2", 0); + if (!ret) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + pkey_bn = BN_bin2bn((const unsigned char *)op->sm2.pkey.data, + op->sm2.pkey.length, pkey_bn); + + memset(pubkey, 0, RTE_DIM(pubkey)); + pubkey[0] = 0x04; + len += 1; + memcpy(&pubkey[len], op->sm2.q.x.data, op->sm2.q.x.length); + len += op->sm2.q.x.length; + memcpy(&pubkey[len], op->sm2.q.y.data, op->sm2.q.y.length); + len += op->sm2.q.y.length; + + ret = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, + pkey_bn); + if (!ret) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + ret = OSSL_PARAM_BLD_push_octet_string(param_bld, + OSSL_PKEY_PARAM_PUB_KEY, pubkey, len); + if (!ret) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + params = OSSL_PARAM_BLD_to_param(param_bld); + if (!params) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + switch (op->sm2.op_type) { + case RTE_CRYPTO_ASYM_OP_ENCRYPT: + { + OSSL_PARAM *eparams = sess->u.sm2.params; + size_t output_len; + + kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL); + if (kctx == NULL || EVP_PKEY_fromdata_init(kctx) <= 0 || + EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) + goto err_sm2; + + cctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (!cctx) + goto err_sm2; + + if (!EVP_PKEY_encrypt_init(cctx)) + goto err_sm2; + + if (!EVP_PKEY_CTX_set_params(cctx, eparams)) + goto err_sm2; + + if (!EVP_PKEY_encrypt(cctx, op->sm2.cipher.data, &output_len, + op->sm2.message.data, + op->sm2.message.length)) + goto err_sm2; + op->sm2.cipher.length = output_len; + } + break; + case RTE_CRYPTO_ASYM_OP_DECRYPT: + { + OSSL_PARAM *eparams = sess->u.sm2.params; + + kctx = EVP_PKEY_CTX_new_id(EVP_PKEY_SM2, NULL); + if (kctx == NULL + || EVP_PKEY_fromdata_init(kctx) <= 0 + || EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) + goto err_sm2; + + cctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (!cctx) + goto err_sm2; + + if (!EVP_PKEY_decrypt_init(cctx)) + goto err_sm2; + + if (!EVP_PKEY_CTX_set_params(cctx, eparams)) + goto err_sm2; + + if (!EVP_PKEY_decrypt(cctx, op->sm2.message.data, &op->sm2.message.length, + op->sm2.cipher.data, op->sm2.cipher.length)) + goto err_sm2; + } + break; + case RTE_CRYPTO_ASYM_OP_SIGN: + { + unsigned char signbuf[128] = {0}; + const unsigned char *signptr; + EVP_MD_CTX *md_ctx = NULL; + const BIGNUM *r, *s; + ECDSA_SIG *ec_sign; + EVP_MD *check_md; + size_t signlen; + + kctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL); + if (kctx == NULL || EVP_PKEY_fromdata_init(kctx) <= 0 || + EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) + goto err_sm2; + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + goto err_sm2; + + sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (!sctx) + goto err_sm2; + + EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); + + check_md = EVP_MD_fetch(NULL, "sm3", NULL); + if (!check_md) + goto err_sm2; + + if (!EVP_DigestSignInit(md_ctx, NULL, check_md, NULL, pkey)) + goto err_sm2; + + if (EVP_PKEY_CTX_set1_id(sctx, op->sm2.id.data, op->sm2.id.length) <= 0) + goto err_sm2; + + if (!EVP_DigestSignUpdate(md_ctx, op->sm2.message.data, + op->sm2.message.length)) + goto err_sm2; + + if (!EVP_DigestSignFinal(md_ctx, NULL, &signlen)) + goto err_sm2; + + if (!EVP_DigestSignFinal(md_ctx, signbuf, &signlen)) + goto err_sm2; + + signptr = signbuf; + ec_sign = d2i_ECDSA_SIG(NULL, &signptr, signlen); + if (!ec_sign) + goto err_sm2; + + r = ECDSA_SIG_get0_r(ec_sign); + s = ECDSA_SIG_get0_s(ec_sign); + if (!r || !s) + goto err_sm2; + + op->sm2.r.length = BN_num_bytes(r); + op->sm2.s.length = BN_num_bytes(s); + BN_bn2bin(r, op->sm2.r.data); + BN_bn2bin(s, op->sm2.s.data); + + ECDSA_SIG_free(ec_sign); + } + break; + case RTE_CRYPTO_ASYM_OP_VERIFY: + { + unsigned char signbuf[128] = {0}; + BIGNUM *r = NULL, *s = NULL; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *ec_sign; + EVP_MD *check_md; + size_t signlen; + + kctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL); + if (kctx == NULL || EVP_PKEY_fromdata_init(kctx) <= 0 || + EVP_PKEY_fromdata(kctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) + goto err_sm2; + + if (!EVP_PKEY_is_a(pkey, "SM2")) + goto err_sm2; + + md_ctx = EVP_MD_CTX_new(); + if (!md_ctx) + goto err_sm2; + + sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (!sctx) + goto err_sm2; + + EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx); + + check_md = EVP_MD_fetch(NULL, "sm3", NULL); + if (!check_md) + goto err_sm2; + + if (!EVP_DigestVerifyInit(md_ctx, NULL, check_md, NULL, pkey)) + goto err_sm2; + + if (EVP_PKEY_CTX_set1_id(sctx, op->sm2.id.data, op->sm2.id.length) <= 0) + goto err_sm2; + + if (!EVP_DigestVerifyUpdate(md_ctx, op->sm2.message.data, + op->sm2.message.length)) + goto err_sm2; + + ec_sign = ECDSA_SIG_new(); + if (!ec_sign) + goto err_sm2; + + r = BN_bin2bn(op->sm2.r.data, op->sm2.r.length, r); + s = BN_bin2bn(op->sm2.s.data, op->sm2.s.length, s); + if (!r || !s) + goto err_sm2; + + if (!ECDSA_SIG_set0(ec_sign, r, s)) { + BN_free(r); + BN_free(s); + goto err_sm2; + } + + r = NULL; + s = NULL; + + signlen = i2d_ECDSA_SIG(ec_sign, (unsigned char **)&signbuf); + if (signlen <= 0) + goto err_sm2; + + if (!EVP_DigestVerifyFinal(md_ctx, signbuf, signlen)) + goto err_sm2; + + BN_free(r); + BN_free(s); + ECDSA_SIG_free(ec_sign); + } + break; + default: + /* allow ops with invalid args to be pushed to + * completion queue + */ + cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; + goto err_sm2; + } + + ret = 0; + cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS; +err_sm2: + if (kctx) + EVP_PKEY_CTX_free(kctx); + + if (sctx) + EVP_PKEY_CTX_free(sctx); + + if (cctx) + EVP_PKEY_CTX_free(cctx); + + if (pkey) + EVP_PKEY_free(pkey); + + if (param_bld) + OSSL_PARAM_BLD_free(param_bld); + + return ret; +} + #else static int process_openssl_rsa_op(struct rte_crypto_op *cop, @@ -2761,6 +3042,15 @@ process_openssl_rsa_op(struct rte_crypto_op *cop, return 0; } + +static int +process_openssl_sm2_op(struct rte_crypto_op *cop, + struct openssl_asym_session *sess) +{ + RTE_SET_USED(cop); + RTE_SET_USED(sess); + return -ENOTSUP; +} #endif static int @@ -2809,6 +3099,13 @@ process_asym_op(struct openssl_qp *qp, struct rte_crypto_op *op, process_openssl_dsa_verify_op(op, sess); else op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS; +#endif + break; + case RTE_CRYPTO_ASYM_XFORM_SM2: +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + retval = process_openssl_sm2_op_evp(op, sess); +#else + retval = process_openssl_sm2_op(op, sess); #endif break; default: diff --git a/drivers/crypto/openssl/rte_openssl_pmd_ops.c b/drivers/crypto/openssl/rte_openssl_pmd_ops.c index 29ad1b9505..fe38e4ebd8 100644 --- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c +++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c @@ -1282,6 +1282,50 @@ static int openssl_set_asym_session_parameters( BN_free(pub_key); return -1; } + case RTE_CRYPTO_ASYM_XFORM_SM2: + { +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + OSSL_PARAM_BLD *param_bld = NULL; + OSSL_PARAM *params = NULL; + int ret = -1; + + if (xform->sm2.hash != RTE_CRYPTO_AUTH_SM3) + return -1; + + param_bld = OSSL_PARAM_BLD_new(); + if (!param_bld) { + OPENSSL_LOG(ERR, "failed to allocate params\n"); + goto err_sm2; + } + + ret = OSSL_PARAM_BLD_push_utf8_string(param_bld, + OSSL_ASYM_CIPHER_PARAM_DIGEST, "SM3", 0); + if (!ret) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + params = OSSL_PARAM_BLD_to_param(param_bld); + if (!params) { + OPENSSL_LOG(ERR, "failed to push params\n"); + goto err_sm2; + } + + asym_session->u.sm2.params = params; + OSSL_PARAM_BLD_free(param_bld); + + asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_SM2; + break; +err_sm2: + if (param_bld) + OSSL_PARAM_BLD_free(param_bld); + + if (asym_session->u.sm2.params) + OSSL_PARAM_free(asym_session->u.sm2.params); + + return -1; +#endif + } default: return ret; } @@ -1366,6 +1410,10 @@ static void openssl_reset_asym_session(struct openssl_asym_session *sess) DSA_free(sess->u.s.dsa); #endif break; + case RTE_CRYPTO_ASYM_XFORM_SM2: +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) + OSSL_PARAM_free(sess->u.sm2.params); +#endif default: break; }