DPDK patches and discussions
 help / color / mirror / Atom feed
From: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
To: <dev@dpdk.org>
Cc: <anoobj@marvell.com>, Akhil Goyal <gakhil@marvell.com>,
	Fan Zhang <fanzhang.oss@gmail.com>,
	Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Subject: [v1, 3/3] crypto/openssl: add SM2 asymmetric crypto support
Date: Fri, 28 Apr 2023 14:58:21 +0530	[thread overview]
Message-ID: <d0c3d7bb32e29ca56681b80ec46109997f804b19.1682652719.git.gmuthukrishn@marvell.com> (raw)
In-Reply-To: <cover.1682652719.git.gmuthukrishn@marvell.com>

Add SM2 asymmetric algorithm support in openssl PMD.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 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 |   7 +
 drivers/crypto/openssl/rte_openssl_pmd.c     | 245 +++++++++++++++++++
 drivers/crypto/openssl/rte_openssl_pmd_ops.c | 101 ++++++++
 6 files changed, 359 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 b920840038..8868b0bb32 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -59,6 +59,10 @@ New Features
 
   Added SM2 algorithm 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..d7990c8333 100644
--- a/drivers/crypto/openssl/openssl_pmd_private.h
+++ b/drivers/crypto/openssl/openssl_pmd_private.h
@@ -12,6 +12,7 @@
 #include <openssl/rsa.h>
 #include <openssl/dh.h>
 #include <openssl/dsa.h>
+#include <openssl/ec.h>
 #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
 #include <openssl/provider.h>
 #include <openssl/core_names.h>
@@ -200,6 +201,12 @@ struct openssl_asym_session {
 			OSSL_PARAM_BLD * param_bld;
 #endif
 		} s;
+		struct {
+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
+			OSSL_PARAM *key_params;
+			OSSL_PARAM *enc_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..25feb88ac3 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd.c
@@ -13,6 +13,7 @@
 #include <openssl/cmac.h>
 #include <openssl/hmac.h>
 #include <openssl/evp.h>
+#include <openssl/ec.h>
 
 #include "openssl_pmd_private.h"
 #include "compat.h"
@@ -2662,6 +2663,234 @@ 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;
+	OSSL_PARAM *kparams = sess->u.sm2.key_params;
+	struct rte_crypto_asym_op *op = cop->asym;
+	EVP_PKEY *pkey = NULL;
+	int ret = -1;
+
+	cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
+
+	if (!kparams)
+		return ret;
+
+	switch (op->sm2.op_type) {
+	case RTE_CRYPTO_ASYM_OP_ENCRYPT:
+		{
+			OSSL_PARAM *eparams = sess->u.sm2.enc_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, kparams) <= 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.enc_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, kparams) <= 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 = signbuf;
+			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, kparams) <= 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;
+
+			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};
+			EVP_MD_CTX *md_ctx = NULL;
+			BIGNUM *r = NULL, *s = 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, kparams) <= 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);
+
+	return ret;
+}
+
 #else
 static int
 process_openssl_rsa_op(struct rte_crypto_op *cop,
@@ -2761,6 +2990,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 +3047,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..7a1e1e8e8c 100644
--- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
+++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
@@ -1282,6 +1282,102 @@ 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;
+		BIGNUM *pkey = NULL;
+		uint8_t pubkey[64];
+		size_t len = 0;
+		int ret = -1;
+
+		pkey = BN_bin2bn((const unsigned char *)xform->sm2.pkey.data,
+				 xform->sm2.pkey.length, pkey);
+
+		memset(pubkey, 0, RTE_DIM(pubkey));
+		pubkey[0] = 0x04;
+		len += 1;
+		memcpy(&pubkey[len], xform->sm2.q.x.data, xform->sm2.q.x.length);
+		len += xform->sm2.q.x.length;
+		memcpy(&pubkey[len], xform->sm2.q.y.data, xform->sm2.q.y.length);
+		len += xform->sm2.q.y.length;
+
+		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;
+		}
+
+		ret = OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_PRIV_KEY, pkey);
+		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;
+		}
+
+		asym_session->u.sm2.key_params = params;
+		OSSL_PARAM_BLD_free(param_bld);
+
+		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 h params\n");
+			goto err_sm2;
+		}
+
+		asym_session->u.sm2.enc_params = params;
+		OSSL_PARAM_BLD_free(param_bld);
+
+		asym_session->xfrm_type = RTE_CRYPTO_ASYM_XFORM_SM2;
+		break;
+err_sm2:
+		if (pkey)
+			BN_free(pkey);
+
+		if (param_bld)
+			OSSL_PARAM_BLD_free(param_bld);
+
+		if (asym_session->u.sm2.key_params)
+			OSSL_PARAM_free(asym_session->u.sm2.key_params);
+
+		if (asym_session->u.sm2.enc_params)
+			OSSL_PARAM_free(asym_session->u.sm2.enc_params);
+
+		return -1;
+#endif
+	}
 	default:
 		return ret;
 	}
@@ -1366,6 +1462,11 @@ 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.key_params);
+		OSSL_PARAM_free(sess->u.sm2.enc_params);
+#endif
 	default:
 		break;
 	}
-- 
2.25.1


  parent reply	other threads:[~2023-04-28  9:28 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-28  9:28 [v1, 0/3] SM2 crypto algorithm support Gowrishankar Muthukrishnan
2023-04-28  9:28 ` [v1, 1/3] cryptodev: add SM2 asymmetric crypto algorithm Gowrishankar Muthukrishnan
2023-05-16 11:49   ` Akhil Goyal
2023-04-28  9:28 ` [v1, 2/3] test/test_cryptodev_asym: add SM2 tests Gowrishankar Muthukrishnan
2023-05-16 12:10   ` Akhil Goyal
2023-05-26  7:31     ` Gowrishankar Muthukrishnan
2023-05-26  8:42       ` Akhil Goyal
2023-04-28  9:28 ` Gowrishankar Muthukrishnan [this message]
2023-04-28 15:17   ` [v1, 3/3] crypto/openssl: add SM2 asymmetric crypto support Gowrishankar Muthukrishnan
2023-05-16 12:14   ` Akhil Goyal

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d0c3d7bb32e29ca56681b80ec46109997f804b19.1682652719.git.gmuthukrishn@marvell.com \
    --to=gmuthukrishn@marvell.com \
    --cc=anoobj@marvell.com \
    --cc=dev@dpdk.org \
    --cc=fanzhang.oss@gmail.com \
    --cc=gakhil@marvell.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).