Hi Gowrishankar,

> -----Original Message-----
> From: Gowrishankar Muthukrishnan <gmuthukri...@marvell.com>
> Sent: Friday, October 4, 2024 10:26 AM
> To: dev@dpdk.org; Ji, Kai <kai...@intel.com>
> Cc: Anoob Joseph <ano...@marvell.com>; Richardson, Bruce
> <bruce.richard...@intel.com>; jer...@marvell.com; fanzhang....@gmail.com;
> Kusztal, ArkadiuszX <arkadiuszx.kusz...@intel.com>; jack.bond-
> pres...@foss.arm.com; Marchand, David <david.march...@redhat.com>;
> hemant.agra...@nxp.com; De Lara Guarch, Pablo
> <pablo.de.lara.gua...@intel.com>; Trahe, Fiona <fiona.tr...@intel.com>;
> Doherty, Declan <declan.dohe...@intel.com>; ma...@nvidia.com;
> ruifeng.w...@arm.com; Akhil Goyal <gak...@marvell.com>; Gowrishankar
> Muthukrishnan <gmuthukri...@marvell.com>
> Subject: [PATCH v6 2/6] crypto/openssl: support EDDSA
> 
> Support EDDSA crypto algorithm in OpenSSL PMD.
> 
> Signed-off-by: Gowrishankar Muthukrishnan <gmuthukri...@marvell.com>
> ---
>  doc/guides/cryptodevs/features/openssl.ini   |   1 +
>  drivers/crypto/openssl/openssl_pmd_private.h |  13 ++
>  drivers/crypto/openssl/rte_openssl_pmd.c     | 223 +++++++++++++++++++
>  drivers/crypto/openssl/rte_openssl_pmd_ops.c | 131 +++++++++++
>  4 files changed, 368 insertions(+)
> 
> diff --git a/doc/guides/cryptodevs/features/openssl.ini
> b/doc/guides/cryptodevs/features/openssl.ini
> index b64c8ec4a5..0540c075dc 100644
> --- a/doc/guides/cryptodevs/features/openssl.ini
> +++ b/doc/guides/cryptodevs/features/openssl.ini
> @@ -66,6 +66,7 @@ Modular Exponentiation = Y  Modular Inversion = Y  Diffie-
> hellman = Y
>  SM2 = Y
> +EDDSA = Y
> 
>  ;
>  ; Supported Operating systems of the 'openssl' crypto driver.
> diff --git a/drivers/crypto/openssl/openssl_pmd_private.h
> b/drivers/crypto/openssl/openssl_pmd_private.h
> index 0282b3d829..7dd97f1c72 100644
> --- a/drivers/crypto/openssl/openssl_pmd_private.h
> +++ b/drivers/crypto/openssl/openssl_pmd_private.h
> @@ -231,10 +231,23 @@ struct __rte_cache_aligned openssl_asym_session {
> #endif
>               } s;
>               struct {
> +                     uint8_t curve_id;
> +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
> +                     EC_GROUP * group;
> +                     BIGNUM *priv_key;
> +#endif
> +             } ec;
> +             struct {
>  #if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
>                       OSSL_PARAM * params;
>  #endif
>               } sm2;
> +             struct {
> +                     uint8_t curve_id;
> +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
> +                     OSSL_PARAM * params;
> +#endif
> +             } eddsa;
>       } u;
>  };
>  /** 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 e10a172f46..4e4d06403b 100644
> --- a/drivers/crypto/openssl/rte_openssl_pmd.c
> +++ b/drivers/crypto/openssl/rte_openssl_pmd.c
> @@ -2849,6 +2849,45 @@ process_openssl_rsa_op_evp(struct rte_crypto_op
> *cop,
> 
>  }
> 
> +static int
> +process_openssl_ecfpm_op_evp(struct rte_crypto_op *cop,
> +             struct openssl_asym_session *sess)
> +{
> +     const EC_GROUP *ecgrp = sess->u.ec.group;
> +     EC_POINT *ecpt = NULL;
> +     BN_CTX *ctx = NULL;
> +     BIGNUM *n = NULL;
> +     int ret = -1;
> +
> +     n = BN_bin2bn((const unsigned char *)
> +                     cop->asym->ecpm.scalar.data,
> +                     cop->asym->ecpm.scalar.length,
> +                     BN_new());
> +
> +     ctx = BN_CTX_new();
> +     if (!ctx)
> +             goto err_ecfpm;
> +
> +     if (!EC_POINT_mul(ecgrp, ecpt, n, NULL, NULL, ctx))
> +             goto err_ecfpm;
> +
> +     if (cop->asym->flags &
> RTE_CRYPTO_ASYM_FLAG_PUB_KEY_COMPRESSED) {
> +             unsigned char *buf = cop->asym->ecpm.r.x.data;
> +             size_t sz;
> +
> +             sz = EC_POINT_point2oct(ecgrp, ecpt,
> POINT_CONVERSION_COMPRESSED, buf, 0, ctx);
> +             if (!sz)
> +                     goto err_ecfpm;
> +
> +             cop->asym->ecpm.r.x.length = sz;
> +     }
> +
> +err_ecfpm:
> +     BN_CTX_free(ctx);
> +     BN_free(n);
> +     return ret;
> +}
> +
>  static int
>  process_openssl_sm2_op_evp(struct rte_crypto_op *cop,
>               struct openssl_asym_session *sess)
> @@ -3074,6 +3113,158 @@ process_openssl_sm2_op_evp(struct
> rte_crypto_op *cop,
>       return ret;
>  }
> 
> +static int
> +process_openssl_eddsa_op_evp(struct rte_crypto_op *cop,
> +             struct openssl_asym_session *sess)
> +{
> +     static const char * const instance[] = {"Ed25519", "Ed25519ctx",
> "Ed25519ph",
> +                                             "Ed448", "Ed448ph"};
> +     EVP_PKEY_CTX *kctx = NULL, *sctx = NULL, *cctx = NULL;
> +     const uint8_t curve_id = sess->u.eddsa.curve_id;
> +     struct rte_crypto_asym_op *op = cop->asym;
> +     OSSL_PARAM *params = sess->u.eddsa.params;
> +     OSSL_PARAM_BLD *iparam_bld = NULL;
> +     OSSL_PARAM *iparams = NULL;
> +     uint8_t signbuf[128] = {0};
> +     EVP_MD_CTX *md_ctx = NULL;
> +     EVP_PKEY *pkey = NULL;
> +     size_t signlen;
> +     int ret = -1;
> +
> +     cop->status = RTE_CRYPTO_OP_STATUS_ERROR;
> +
> +     iparam_bld = OSSL_PARAM_BLD_new();
> +     if (!iparam_bld)
> +             goto err_eddsa;
> +
> +     if (op->eddsa.instance == RTE_CRYPTO_EDCURVE_25519CTX) {
> +             OSSL_PARAM_BLD_push_octet_string(iparam_bld, "context-
> string",
> +                     op->eddsa.context.data, op->eddsa.context.length);
> +
> +     }
> +
> +     OSSL_PARAM_BLD_push_utf8_string(iparam_bld, "instance",
> +             instance[op->eddsa.instance], strlen(instance[op-
> >eddsa.instance]));
> +
> +     iparams = OSSL_PARAM_BLD_to_param(iparam_bld);
> +     if (!iparams)
> +             goto err_eddsa;
> +
> +     switch (op->eddsa.op_type) {
> +     case RTE_CRYPTO_ASYM_OP_SIGN:
> +             {
> +                     if (curve_id == RTE_CRYPTO_EC_GROUP_ED25519)
> +                             kctx = EVP_PKEY_CTX_new_from_name(NULL,
> "ED25519", NULL);

I see this is a pattern in this PMD, but there are plenty of operations that 
should be done in session instead on the datapath.
EVP_PKEY_CTX_new_from_name
EVP_PKEY_fromdata
EVP_MD_CTX_new
EVP_MD_CTX_set_pkey_ctx
Should rather be done once per session than per every operation in with-session 
case.

> +                     else
> +                             kctx = EVP_PKEY_CTX_new_from_name(NULL,
> "ED448", NULL);
> +
> +                     if (kctx == NULL || EVP_PKEY_fromdata_init(kctx) <= 0
> ||
> +                             EVP_PKEY_fromdata(kctx, &pkey,
> EVP_PKEY_KEYPAIR, params) <= 0)
> +                             goto err_eddsa;
> +
> +                     md_ctx = EVP_MD_CTX_new();
> +                     if (!md_ctx)
> +                             goto err_eddsa;
> +
> +                     sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey,
> NULL);
> +                     if (!sctx)
> +                             goto err_eddsa;
> +
> +                     EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx);
> +
> +#if (OPENSSL_VERSION_NUMBER >= 0x30300000L)
> +                     if (!EVP_DigestSignInit_ex(md_ctx, NULL, NULL, NULL,
> NULL, pkey, iparams))
> +                             goto err_eddsa;
> +#else
> +                     if (op->eddsa.instance ==
> RTE_CRYPTO_EDCURVE_25519 ||
> +                             op->eddsa.instance ==
> RTE_CRYPTO_EDCURVE_448) {
> +                             if (!EVP_DigestSignInit(md_ctx, NULL, NULL,
> NULL, pkey))
> +                                     goto err_eddsa;
> +                     } else
> +                             goto err_eddsa;
> +#endif
> +
> +                     if (!EVP_DigestSign(md_ctx, NULL, &signlen, op-
> >eddsa.message.data,
> +                                     op->eddsa.message.length))
> +                             goto err_eddsa;
> +
> +                     if (signlen > RTE_DIM(signbuf))
> +                             goto err_eddsa;
> +
> +                     if (!EVP_DigestSign(md_ctx, signbuf, &signlen, op-
> >eddsa.message.data,
> +                                     op->eddsa.message.length))
> +                             goto err_eddsa;
> +
> +                     memcpy(op->eddsa.sign.data, &signbuf[0], signlen);
> +                     op->eddsa.sign.length = signlen;
> +             }
> +             break;
> +     case RTE_CRYPTO_ASYM_OP_VERIFY:
> +             {
> +                     if (curve_id == RTE_CRYPTO_EC_GROUP_ED25519)
> +                             kctx = EVP_PKEY_CTX_new_from_name(NULL,
> "ED25519", NULL);
> +                     else
> +                             kctx = EVP_PKEY_CTX_new_from_name(NULL,
> "ED448", NULL);
> +
> +                     if (kctx == NULL || EVP_PKEY_fromdata_init(kctx) <= 0
> ||
> +                             EVP_PKEY_fromdata(kctx, &pkey,
> EVP_PKEY_PUBLIC_KEY, params) <= 0)
> +                             goto err_eddsa;
> +
> +                     md_ctx = EVP_MD_CTX_new();
> +                     if (!md_ctx)
> +                             goto err_eddsa;
> +
> +                     sctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey,
> NULL);
> +                     if (!sctx)
> +                             goto err_eddsa;
> +
> +                     EVP_MD_CTX_set_pkey_ctx(md_ctx, sctx);
> +
> +#if (OPENSSL_VERSION_NUMBER >= 0x30300000L)
> +                     if (!EVP_DigestVerifyInit_ex(md_ctx, NULL, NULL,
> NULL, NULL, pkey, iparams))
> +                             goto err_eddsa;
> +#else
> +                     if (op->eddsa.instance ==
> RTE_CRYPTO_EDCURVE_25519 ||
> +                             op->eddsa.instance ==
> RTE_CRYPTO_EDCURVE_448) {
> +                             if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL,
> NULL, pkey))
> +                                     goto err_eddsa;
> +                     } else
> +                             goto err_eddsa;
> +#endif
> +
> +                     signlen = op->eddsa.sign.length;
> +                     memcpy(&signbuf[0], op->eddsa.sign.data, op-
> >eddsa.sign.length);
> +
> +                     ret = EVP_DigestVerify(md_ctx, signbuf, signlen, op-
> >eddsa.message.data,
> +                                     op->eddsa.message.length);
> +                     if (ret == 0)
> +                             goto err_eddsa;
> +             }
> +             break;
> +     default:
> +             /* allow ops with invalid args to be pushed to
> +              * completion queue
> +              */
> +             cop->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
> +             goto err_eddsa;
> +     }
> +
> +     ret = 0;
> +     cop->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
> +err_eddsa:
> +     OSSL_PARAM_BLD_free(iparam_bld);
> +
> +     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, @@ -3174,6 +3365,15 @@
> process_openssl_rsa_op(struct rte_crypto_op *cop,
>       return 0;
>  }
> 
> +static int
> +process_openssl_ecfpm_op(struct rte_crypto_op *cop,
> +             struct openssl_asym_session *sess)
> +{
> +     RTE_SET_USED(cop);
> +     RTE_SET_USED(sess);
> +     return -ENOTSUP;
> +}
> +
>  static int
>  process_openssl_sm2_op(struct rte_crypto_op *cop,
>               struct openssl_asym_session *sess)
> @@ -3182,6 +3382,15 @@ process_openssl_sm2_op(struct rte_crypto_op
> *cop,
>       RTE_SET_USED(sess);
>       return -ENOTSUP;
>  }
> +
> +static int
> +process_openssl_eddsa_op(struct rte_crypto_op *cop,
> +             struct openssl_asym_session *sess)
> +{
> +     RTE_SET_USED(cop);
> +     RTE_SET_USED(sess);
> +     return -ENOTSUP;
> +}
>  #endif
> 
>  static int
> @@ -3230,6 +3439,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_ECFPM:
> +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
> +             retval = process_openssl_ecfpm_op_evp(op, sess); #else
> +             retval = process_openssl_ecfpm_op(op, sess);
>  #endif
>               break;
>       case RTE_CRYPTO_ASYM_XFORM_SM2:
> @@ -3237,6 +3453,13 @@ process_asym_op(struct openssl_qp *qp, struct
> rte_crypto_op *op,
>               retval = process_openssl_sm2_op_evp(op, sess);  #else
>               retval = process_openssl_sm2_op(op, sess);
> +#endif
> +             break;
> +     case RTE_CRYPTO_ASYM_XFORM_EDDSA:
> +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
> +             retval = process_openssl_eddsa_op_evp(op, sess); #else
> +             retval = process_openssl_eddsa_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 b7b612fc57..0725184653 100644
> --- a/drivers/crypto/openssl/rte_openssl_pmd_ops.c
> +++ b/drivers/crypto/openssl/rte_openssl_pmd_ops.c
> @@ -593,6 +593,16 @@ static const struct rte_cryptodev_capabilities
> openssl_pmd_capabilities[] = {
>               },
>               }
>       },
> +     {       /* ECFPM */
> +             .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
> +             {.asym = {
> +                     .xform_capa = {
> +                             .xform_type =
> RTE_CRYPTO_ASYM_XFORM_ECFPM,
> +                             .op_types = 0
> +                             }
> +                     }
> +             }
> +     },
>       {       /* SM2 */
>               .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
>               {.asym = {
> @@ -610,6 +620,20 @@ static const struct rte_cryptodev_capabilities
> openssl_pmd_capabilities[] = {
>               }
>               }
>       },
> +     {       /* EDDSA */
> +             .op = RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
> +             {.asym = {
> +                     .xform_capa = {
> +                             .xform_type =
> RTE_CRYPTO_ASYM_XFORM_EDDSA,
> +                             .hash_algos = (1 <<
> RTE_CRYPTO_AUTH_SHA512 |
> +                                            1 <<
> RTE_CRYPTO_AUTH_SHAKE_256),
> +                             .op_types =
> +                             ((1<<RTE_CRYPTO_ASYM_OP_SIGN) |
> +                              (1 << RTE_CRYPTO_ASYM_OP_VERIFY)),
> +                     }
> +             }
> +             }
> +     },
> 
>       RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST()
>  };
> @@ -1356,6 +1380,47 @@ static int openssl_set_asym_session_parameters(
>               BN_free(pub_key);
>               return -1;
>       }
> +     case RTE_CRYPTO_ASYM_XFORM_ECFPM:
> +     {
> +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
> +             EC_GROUP *ecgrp = NULL;
> +
> +             asym_session->xfrm_type = xform->xform_type;
> +
> +             switch (xform->ec.curve_id) {
> +             case RTE_CRYPTO_EC_GROUP_SECP192R1:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_secp192k1);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_SECP224R1:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_secp224r1);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_SECP256R1:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_secp256k1);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_SECP384R1:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_secp384r1);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_SECP521R1:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_secp521r1);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_ED25519:
> +                     ecgrp =
> EC_GROUP_new_by_curve_name(NID_ED25519);
> +                     break;
> +             case RTE_CRYPTO_EC_GROUP_ED448:
> +                     ecgrp = EC_GROUP_new_by_curve_name(NID_ED448);
> +                     break;
> +             default:
> +                     break;
> +             }
> +
> +             asym_session->u.ec.curve_id = xform->ec.curve_id;
> +             asym_session->u.ec.group = ecgrp;
> +             break;
> +#else
> +             OPENSSL_LOG(WARNING, "ECFPM unsupported for OpenSSL
> Version < 3.0");
> +             return -ENOTSUP;
> +#endif
> +     }
>       case RTE_CRYPTO_ASYM_XFORM_SM2:
>       {
>  #if (OPENSSL_VERSION_NUMBER >= 0x30000000L) @@ -1440,6 +1505,66 @@
> static int openssl_set_asym_session_parameters(
>  #else
>               OPENSSL_LOG(WARNING, "SM2 unsupported for OpenSSL
> Version < 3.0");
>               return -ENOTSUP;
> +#endif
> +     }
> +     case RTE_CRYPTO_ASYM_XFORM_EDDSA:
> +     {
> +#if (OPENSSL_VERSION_NUMBER >= 0x30300000L)
> +             OSSL_PARAM_BLD *param_bld = NULL;
> +             OSSL_PARAM *params = NULL;
> +             int ret = -1;
> +
> +             asym_session->u.eddsa.curve_id = xform->ec.curve_id;
> +
> +             param_bld = OSSL_PARAM_BLD_new();
> +             if (!param_bld) {
> +                     OPENSSL_LOG(ERR, "failed to allocate params");
> +                     goto err_eddsa;
> +             }
> +
> +             ret = OSSL_PARAM_BLD_push_utf8_string(param_bld,
> +                       OSSL_PKEY_PARAM_GROUP_NAME, "ED25519",
> sizeof("ED25519"));
> +             if (!ret) {
> +                     OPENSSL_LOG(ERR, "failed to push params");
> +                     goto err_eddsa;
> +             }
> +
> +             ret = OSSL_PARAM_BLD_push_octet_string(param_bld,
> OSSL_PKEY_PARAM_PRIV_KEY,
> +                             xform->ec.pkey.data, xform->ec.pkey.length);
> +             if (!ret) {
> +                     OPENSSL_LOG(ERR, "failed to push params");
> +                     goto err_eddsa;
> +             }
> +
> +             ret = OSSL_PARAM_BLD_push_octet_string(param_bld,
> OSSL_PKEY_PARAM_PUB_KEY,
> +                             xform->ec.q.x.data, xform->ec.q.x.length);
> +             if (!ret) {
> +                     OPENSSL_LOG(ERR, "failed to push params");
> +                     goto err_eddsa;
> +             }
> +
> +             params = OSSL_PARAM_BLD_to_param(param_bld);
> +             if (!params) {
> +                     OPENSSL_LOG(ERR, "failed to push params");
> +                     goto err_eddsa;
> +             }
> +
> +             asym_session->u.eddsa.params = params;
> +             OSSL_PARAM_BLD_free(param_bld);
> +
> +             asym_session->xfrm_type =
> RTE_CRYPTO_ASYM_XFORM_EDDSA;
> +             break;
> +err_eddsa:
> +             if (param_bld)
> +                     OSSL_PARAM_BLD_free(param_bld);
> +
> +             if (asym_session->u.eddsa.params)
> +                     OSSL_PARAM_free(asym_session->u.eddsa.params);
> +
> +             return -1;
> +#else
> +             OPENSSL_LOG(WARNING, "EDDSA unsupported for OpenSSL
> Version < 3.3");
> +             return -ENOTSUP;
>  #endif
>       }
>       default:
> @@ -1538,6 +1663,12 @@ static void openssl_reset_asym_session(struct
> openssl_asym_session *sess)  #if (OPENSSL_VERSION_NUMBER >=
> 0x30000000L)
>               OSSL_PARAM_free(sess->u.sm2.params);
>  #endif
> +             break;
> +     case RTE_CRYPTO_ASYM_XFORM_EDDSA:
> +#if (OPENSSL_VERSION_NUMBER >= 0x30300000L)
> +             OSSL_PARAM_free(sess->u.eddsa.params);
> +#endif
> +             break;
>       default:
>               break;
>       }
> --
> 2.21.0

Reply via email to