@@ -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.
@@ -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
@@ -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
-------------
@@ -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 */
@@ -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:
@@ -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;
}