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
next prev 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).