[dpdk-dev,RFC,v1,1/1] lib/cryptodev: add support of asymmetric crypto

Message ID 1516701263-13154-2-git-send-email-shally.verma@caviumnetworks.com (mailing list archive)
State RFC, archived
Delegated to: Pablo de Lara Guarch
Headers

Checks

Context Check Description
ci/checkpatch warning coding style issues
ci/Intel-compilation fail Compilation issues

Commit Message

Shally Verma Jan. 23, 2018, 9:54 a.m. UTC
  From: Shally Verma <sverma@caviumnetworks.com>

Add support for asymmetric crypto operations in DPDK lib cryptodev

Key feature include:
- Only session based asymmetric crypto operations
- new get and set APIs for symmetric and asymmetric session private
  data and other informations
- APIs to create, configure and attch queue pair to asymmetric sessions
- new capabilities in struct device_info to indicate
  -- number of dedicated queue pairs available for symmetric and
     asymmetric operations, if any
  -- number of asymmetric sessions possible per qp

Proposed asymmetric cryptographic operations are:
- rsa
- dsa
- deffie-hellman key pair generation and shared key computation
- ecdeffie-hellman
- fundamental elliptic curve operations
- elliptic curve DSA
- modular exponentiation and inversion

This patch primarily defines PMD operations and device capabilities
to perform asymmetric crypto ops on queue pairs and intend to
invite feedbacks on current proposal so as to ensure it encompass
all kind of crypto devices with different capabilities and queue
pair management.

List of TBDs:
- Currently, patch only updated for RSA xform and associated params.
  Other algoritms to be added in subsequent versions.
- per-service stats update

Signed-off-by: Shally Verma <sverma@caviumnetworks.com>
---

It is derivative of RFC v2 asymmetric crypto patch series initiated by 
Umesh Kartha(mailto:umesh.kartha@caviumnetworks.com):

 http://dpdk.org/dev/patchwork/patch/24245/
 http://dpdk.org/dev/patchwork/patch/24246/
 http://dpdk.org/dev/patchwork/patch/24247/

And inclusive of all review comments given on RFC v2.
 ( See complete discussion thread here:
http://dev.dpdk.narkive.com/yqTFFLHw/dpdk-dev-rfc-specifications-for-asymmetric-crypto-algorithms#post12)

Some of the RFCv2 Review comments pending for closure:
> " [Fiona] The count fn isn't used at all for sym - probably no need to add for asym
     better instead to remove the sym fn." 

     It is still present in dpdk-next-crypto for sym, so what has been decision
     on it?

>"[Fiona] if each qp can handle only a specific service, i.e. a subset off the capabilities
    Indicated by the device capability list, there's a need for a new API to query
    the capability of a qp."

    Current proposal doesn’t distinguish between device capability and qp capability.
    It rather leave such differences handling internal to PMDs. Thus no capability
    or API added for qp in current version. It is subject to revisit based on review
    feedback on current proposal.

- Sessionless Support.
    Current proposal only support Session-based because:
     1. All one-time setup i.e.  algos and associated params, such as, public-private keys 
        or modulus length can be done in control path using session-init API 
     2. it’s an easier way to dedicate qp to do specific service (using queue_pair_attach())
        which cannot be case in sessionless  
     3. Couldn’t find any significant advantage going sessionless way. Also existing most of PMDs are session-based. 

    It could be added in subsequent versions, if requirement is identified, based on review comment
    on this RFC.

Summary
-------

This section provides an overview of key feature enabled in current specification.
It comprise of key design challenges as have been identified on RFCv2 and 
summary description of new interfaces and definitions added to handle same.

Description
-----------

This API set assumes that the max_nb_queue_pairs on a
device can be allocated to any mix of sym or asym. Some devices
may have a fixed max per service. Thus, rte_cryptodev_info 
is updated with max_sym_nb_queues and max_asym_nb_queues with rule:

max_nb_queue_pair = max_nb_sym_qp + max_nb_asym_qp.

If device has no restrictions on qp to be used per service, such PMDs can leave
max_nb_sym_qp = max_nb_asym_qp = 0. In such case, application can setup any of
the service upto limit defined by max_nb_queue_pair.

Here, max_nb_sym_qp and max_nb_asym_qp, if non-zero, just define limit on qp which are
available for each service and *are not* ids to be used during qp setup and enqueue i.e.
if device supports both symmetric and asymmetric with n qp, then any of them
can be configured for symmetric or asymmetric subject to limit defined by
max_nb_sym_qp and max_nb_asym_qp. For example,
if device has 6 queues and 5 for symmetric and 1 for asymmetric that imply
application can setup only 1 out of any 6 qp for asymmetric and rest for
symmetric.

Additionally, application can dedicate qp to perform specific service via optional 
queue_pair_attach_sym/asym_session() API.

Except the ones mentioned above, specification doesn't define any restrictions on 
enqueue/dequeue API for different crypto services. Application can enqueue both symmetric
and asymmetric operations to same device and qp if device info indicate support of both
symmetric and asymmetric and qp is not dedicated to any. However in practice, it could 
result in head-of-line blocking due to the asym ops taking longer than the symmetric ops.

Some HW accelerators avoid this issue by supporting sym and asym ops
on different qps on the same device.  Such devices can set max_nb_sym_qp and
max_nb_asym_qp to number of queues available for each respective service.

This may give problem in indexing on enqueue/dequeue i.e.
if 2 asym qps and 2 sym qps are created on the same device,
the queue_pair_ids are duplicated. To handle such scenario,
2 alternatives are proposed for PMD design:

1. Allow all qp to input any operation type virtually. Say,

    Consider device with symmetric and asymmetric capability having 
    max_nb_queue_pair as 6, then by design, all 6 are capable to input
    both op types.

    If PMD uses fixed set of qp, then internally, can map qp id to
    actual physical qp id to be used according to session/op type.
    If such mapping is done on data path, may impact performance of PMDs.
    Thus, to handle such mapping out of data path, library provides an API
    queue_pair_attach_sym/asym_session() which facilitate application to 
    dedicate qp id to perform specific (sym/asym) service in control path
    and should be called before 1st call to enqueue_burst().
    Here PMD can bind app provided logical qp id to actual physical qp id to use
    depending on session type , OR alternatively 

2. PMDs can split it into two PMDs, one with symmetric ONLY capability and other 
    with asymmetric ONLY capability (also proposed by Fiona in RFCv2).
    This may require some  changes to EAL to facilitate pci device sharing between 
    PMDs, enabling separation of sym and  asym services onto different PMDs. 
    As per RFCv2 feedback, Intel  proposed to submit a patch to  enable this.

3. Some of the other alternatives were also suggested on RFCv2 as summarised here:
    "[Fiona] One alternative is to use different qp_ids for sym and asym.
      Remove the queue_pair_id from the xxx_queue_pair_setup fns
      and instead return the id. So e.g. if sym_queue_pair_setup() is called, then
      asym_queue_pair_setup(), then sym_queue_pair_setup() qp_id 0 and 2 would be
      sym qps and qp_id 1 would be an asym qp. Instead of separate 
      dev->data->asym_queue_pairs and dev->data->sym_queue_pairs arrays there 
      would be one common array. Another alternative is to use separate APIs i.e.
      rte_cryptodev_sym_enqueue_burst rte_cryptodev_asym_enqueue_burst."

     We believe eithr of above proposed 1st two solutions(against point 1 and 2) suffice to achieve purpose. 
     Thus, we don’t realize need to change notion of qp_setup() or add new enqueue_burst() variant 
     for asym at current stage. However it is subject to revisit, if any requirement is identified.

---
 lib/librte_cryptodev/Makefile                  |   1 +
 lib/librte_cryptodev/rte_crypto.h              |  39 +-
 lib/librte_cryptodev/rte_crypto_asym.h         | 949 +++++++++++++++++++++++++
 lib/librte_cryptodev/rte_cryptodev.c           | 287 ++++++++
 lib/librte_cryptodev/rte_cryptodev.h           | 358 +++++++++-
 lib/librte_cryptodev/rte_cryptodev_pmd.c       |  19 +-
 lib/librte_cryptodev/rte_cryptodev_pmd.h       | 154 +++-
 lib/librte_cryptodev/rte_cryptodev_version.map |  21 +
 8 files changed, 1811 insertions(+), 17 deletions(-)
  

Comments

Fiona Trahe Feb. 9, 2018, 6:13 p.m. UTC | #1
Hi Shally,
Comments below.

> -----Original Message-----

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

> Sent: Tuesday, January 23, 2018 9:54 AM

> To: Doherty, Declan <declan.doherty@intel.com>

> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

> <sverma@caviumnetworks.com>

> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> 

> From: Shally Verma <sverma@caviumnetworks.com>

> 

> Add support for asymmetric crypto operations in DPDK lib cryptodev

> 

> Key feature include:

> - Only session based asymmetric crypto operations

> - new get and set APIs for symmetric and asymmetric session private

>   data and other informations

> - APIs to create, configure and attch queue pair to asymmetric sessions

> - new capabilities in struct device_info to indicate

>   -- number of dedicated queue pairs available for symmetric and

>      asymmetric operations, if any

>   -- number of asymmetric sessions possible per qp

> 

[Fiona] Though it's probably premature to include on the API have you considered 
providing for pre-loaded keys in future, i.e. the ability to wrap keys or refer to keys
already stored securely on the device, as an alternative to passing the keys on the API?


> Proposed asymmetric cryptographic operations are:

> - rsa

> - dsa

> - deffie-hellman key pair generation and shared key computation

> - ecdeffie-hellman

> - fundamental elliptic curve operations

> - elliptic curve DSA

> - modular exponentiation and inversion

> 

> This patch primarily defines PMD operations and device capabilities

> to perform asymmetric crypto ops on queue pairs and intend to

> invite feedbacks on current proposal so as to ensure it encompass

> all kind of crypto devices with different capabilities and queue

> pair management.

> 

> List of TBDs:

> - Currently, patch only updated for RSA xform and associated params.

>   Other algoritms to be added in subsequent versions.

> - per-service stats update

> 

> Signed-off-by: Shally Verma <sverma@caviumnetworks.com>

> ---

> 

> It is derivative of RFC v2 asymmetric crypto patch series initiated by

> Umesh Kartha(mailto:umesh.kartha@caviumnetworks.com):

> 

>  http://dpdk.org/dev/patchwork/patch/24245/

>  http://dpdk.org/dev/patchwork/patch/24246/

>  http://dpdk.org/dev/patchwork/patch/24247/

> 

> And inclusive of all review comments given on RFC v2.

>  ( See complete discussion thread here:

> http://dev.dpdk.narkive.com/yqTFFLHw/dpdk-dev-rfc-specifications-for-asymmetric-crypto-

> algorithms#post12)

> 

> Some of the RFCv2 Review comments pending for closure:

> > " [Fiona] The count fn isn't used at all for sym - probably no need to add for asym

>      better instead to remove the sym fn."

> 

>      It is still present in dpdk-next-crypto for sym, so what has been decision

>      on it?

[Fiona] No change. The rte_cryptodev_ops fn is still not called so useless and should be removed.
rte_cryptodev_queue_pair_count() returns the num_qps configured in 
rte_cryptodev_configure(), but never calls the PMD dev_ops.queue_pair_count().
So cryptodev_sym_queue_pair_count_t should be deprecated.
And no point in adding one for asym.

> 

> >"[Fiona] if each qp can handle only a specific service, i.e. a subset off the capabilities

>     Indicated by the device capability list, there's a need for a new API to query

>     the capability of a qp."

> 

>     Current proposal doesn’t distinguish between device capability and qp capability.

>     It rather leave such differences handling internal to PMDs. Thus no capability

>     or API added for qp in current version. It is subject to revisit based on review

>     feedback on current proposal.

[Fiona] This would not work for some devices, comments below.

> 

> - Sessionless Support.

>     Current proposal only support Session-based because:

>      1. All one-time setup i.e.  algos and associated params, such as, public-private keys

>         or modulus length can be done in control path using session-init API

>      2. it’s an easier way to dedicate qp to do specific service (using queue_pair_attach())

>         which cannot be case in sessionless

>      3. Couldn’t find any significant advantage going sessionless way. Also existing most of PMDs are

> session-based.

> 

>     It could be added in subsequent versions, if requirement is identified, based on review comment

>     on this RFC.

[Fiona] Our preference would be for sessionless, as it would need fewer API calls (no session_create/session_clear) 
and e.g. DH and ECDH sessions are likely to be only used for a single op. However this is not a blocker for
this API, we can POC it later and propose an extension to the API if it gives a performance improvement.
 
> 

> Summary

> -------

> 

> This section provides an overview of key feature enabled in current specification.

> It comprise of key design challenges as have been identified on RFCv2 and

> summary description of new interfaces and definitions added to handle same.

> 

> Description

> -----------

> 

> This API set assumes that the max_nb_queue_pairs on a

> device can be allocated to any mix of sym or asym. Some devices

> may have a fixed max per service. Thus, rte_cryptodev_info

> is updated with max_sym_nb_queues and max_asym_nb_queues with rule:

> 

> max_nb_queue_pair = max_nb_sym_qp + max_nb_asym_qp.

> 

> If device has no restrictions on qp to be used per service, such PMDs can leave

> max_nb_sym_qp = max_nb_asym_qp = 0. In such case, application can setup any of

> the service upto limit defined by max_nb_queue_pair.

[Fiona] This seems awkward if a genuine 0  e.g. An appl wants to set up a sym qp, and
sees that max_nb_queue_pair=4. Can't trust this - needs to look deeper. Sees 
max_nb_sym_qp=0. Doesn't know if that means it can set up 4 sym qps or no qps
until it also checks max_nb_asym_qp. If=4 then it can't set up any sym qp, if=0 it can set up 4.
Would it be better if   
	max_nb_queue_pair = max(max_nb_sym_qp, max_nb_asym_qp).
	max_nb_sym_qp = 0..max_nb_queue_pair
	max_nb_asym_qp = 0..max_nb_queue_pair

> Here, max_nb_sym_qp and max_nb_asym_qp, if non-zero, just define limit on qp which are

> available for each service and *are not* ids to be used during qp setup and enqueue i.e.

> if device supports both symmetric and asymmetric with n qp, then any of them

> can be configured for symmetric or asymmetric subject to limit defined by

> max_nb_sym_qp and max_nb_asym_qp. For example,

> if device has 6 queues and 5 for symmetric and 1 for asymmetric that imply

> application can setup only 1 out of any 6 qp for asymmetric and rest for

> symmetric.

> 

> Additionally, application can dedicate qp to perform specific service via optional

> queue_pair_attach_sym/asym_session() API.

[Fiona] This is too late - some devices have qps which need to know at setup which
service they'll be used for, as they reserve resources based on the service.
e.g. a device reports in info that it can support qps(max 4, max_sym 2, max asym 2)
An application just wants to use 1 sym qp and 1 asym, so configures device with 
qps(max 2, max_sym 1, max asym 1)
Now appl calls qp_setup for qp index 0. Wants to start with running asymmetric
service and will set up the symmetric later, maybe in a separate thread.
Our devices need to know at setup time which service will be used on the qp.
So haven't been given enough information to setup the qp.

Even if the PMD could set up service-agnostic qps and just map later, you 
suggest the qp_attach_sym/asym_session() would be optional. How could the appl
make the decision whether to call it or not in above case? It needs to know whether
the created qp is agnostic or not, so a capability must be reported by the PMD. 
OR the API should not be optional, must be called for every session. 
But that's perf impacting and not helpful if a device could support service-agnostic qps.

I don't have a solution for service-agnostic qps. For our devices that's not necessary.
Is it likely that anyone wants to set up a qp to process both sym and asym ops?
Is it sufficient to accommodate qps which can support either
service, but one must be picked at setup after which the qp supports only that service?
How about the following - :
 - device reports in info qps(max, max_sym, max asym) where
	max = max(max_sym, max_asym).
	max_sym = 0..max
	max_asym = 0..max
	So if a device reports 4,2,2, it has 4 total, 2 can be setup for sym, 2 for asym
	Or if it reports 4,4,4, all 4 of them can be setup as sym or all 4 as
	asym or a mix, but total setup can't be more than 4. 
 - appl configures qps(max, max_sym, max_asym)
	If it specifies 4,1,3 it wants to use 4 in total, 1 for sym, 3 for asym.
	If it specifies 1,1,0 it wants to use 1 in total, 1 for sym, 0 for asym.
	The numbers it configures must be <= those reported in info.
 - appl calls qp_setup(dev, qp, service) where service = sym or asym
	qp index must be between 0..max-1
	The PMD maps that index to an internal qp which can support the requested service.
	If qp_setup is called on an index and the max configured qps have already
	been setup for that service then the setup fails.
In case the appl forgets which qp it set up for which service, I think it would be necessary to add a new API
	rte_cryptodev_qp_info() which would return what service is configured on the qp
 
If it's necessary to support service-agnostic qps, then one way would be to specify a third service above as 
 - sym+asym.
And have devices report max_sym_asym_qps?

It's difficult to find a solution for this without breaking the current API - see simpler
alternative below.
 
> Except the ones mentioned above, specification doesn't define any restrictions on

> enqueue/dequeue API for different crypto services. Application can enqueue both symmetric

> and asymmetric operations to same device and qp if device info indicate support of both

> symmetric and asymmetric and qp is not dedicated to any. However in practice, it could

> result in head-of-line blocking due to the asym ops taking longer than the symmetric ops.

> 

> Some HW accelerators avoid this issue by supporting sym and asym ops

> on different qps on the same device.  Such devices can set max_nb_sym_qp and

> max_nb_asym_qp to number of queues available for each respective service.

> 

> This may give problem in indexing on enqueue/dequeue i.e.

> if 2 asym qps and 2 sym qps are created on the same device,

> the queue_pair_ids are duplicated. To handle such scenario,

> 2 alternatives are proposed for PMD design:

> 

> 1. Allow all qp to input any operation type virtually. Say,

> 

>     Consider device with symmetric and asymmetric capability having

>     max_nb_queue_pair as 6, then by design, all 6 are capable to input

>     both op types.

> 

>     If PMD uses fixed set of qp, then internally, can map qp id to

>     actual physical qp id to be used according to session/op type.

>     If such mapping is done on data path, may impact performance of PMDs.

>     Thus, to handle such mapping out of data path, library provides an API

>     queue_pair_attach_sym/asym_session() which facilitate application to

>     dedicate qp id to perform specific (sym/asym) service in control path

>     and should be called before 1st call to enqueue_burst().

>     Here PMD can bind app provided logical qp id to actual physical qp id to use

>     depending on session type , OR alternatively

> 

> 2. PMDs can split it into two PMDs, one with symmetric ONLY capability and other

>     with asymmetric ONLY capability (also proposed by Fiona in RFCv2).

>     This may require some  changes to EAL to facilitate pci device sharing between

>     PMDs, enabling separation of sym and  asym services onto different PMDs.

>     As per RFCv2 feedback, Intel  proposed to submit a patch to  enable this.

[Fiona] The eal changes were problematic, and feedback from the Dublin userspace 
event last September was that several others have tried similar but reverted to resolving
the problem within the PMD. This is what we are also in the process of doing.
With this we intend to avoid all the above complications.
i.e. one pci device, in its probe fn, can create multiple API device instances.
One instance of cryptodev will provide a sym crypto service, one instance of 
compressdev will provide a compression service and a second cryptodev instance will
provide the asymmetric service. All qps on each API device instance can then support all 
of the capabilities reported by that device.

A suggestion for keeping the simplicity on the API would be to follow the same pattern.
i.e. don't provide any support for specification of sym or asym qps. Expect all
qps on each device to support all capabilities reported. 


> 3. Some of the other alternatives were also suggested on RFCv2 as summarised here:

>     "[Fiona] One alternative is to use different qp_ids for sym and asym.

>       Remove the queue_pair_id from the xxx_queue_pair_setup fns

>       and instead return the id. So e.g. if sym_queue_pair_setup() is called, then

>       asym_queue_pair_setup(), then sym_queue_pair_setup() qp_id 0 and 2 would be

>       sym qps and qp_id 1 would be an asym qp. Instead of separate

>       dev->data->asym_queue_pairs and dev->data->sym_queue_pairs arrays there

>       would be one common array. Another alternative is to use separate APIs i.e.

>       rte_cryptodev_sym_enqueue_burst rte_cryptodev_asym_enqueue_burst."

> 

>      We believe eithr of above proposed 1st two solutions(against point 1 and 2) suffice to achieve purpose.

>      Thus, we don’t realize need to change notion of qp_setup() or add new enqueue_burst() variant

>      for asym at current stage. However it is subject to revisit, if any requirement is identified.

> 

> ---

>  lib/librte_cryptodev/Makefile                  |   1 +

>  lib/librte_cryptodev/rte_crypto.h              |  39 +-

>  lib/librte_cryptodev/rte_crypto_asym.h         | 949 +++++++++++++++++++++++++

>  lib/librte_cryptodev/rte_cryptodev.c           | 287 ++++++++

>  lib/librte_cryptodev/rte_cryptodev.h           | 358 +++++++++-

>  lib/librte_cryptodev/rte_cryptodev_pmd.c       |  19 +-

>  lib/librte_cryptodev/rte_cryptodev_pmd.h       | 154 +++-

>  lib/librte_cryptodev/rte_cryptodev_version.map |  21 +

>  8 files changed, 1811 insertions(+), 17 deletions(-)

> 

> diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile

> index bba8dee..dec325b 100644

> --- a/lib/librte_cryptodev/Makefile

> +++ b/lib/librte_cryptodev/Makefile

> @@ -21,6 +21,7 @@ SRCS-y += rte_cryptodev.c rte_cryptodev_pmd.c

>  # export include files

>  SYMLINK-y-include += rte_crypto.h

>  SYMLINK-y-include += rte_crypto_sym.h

> +SYMLINK-y-include += rte_crypto_asym.h

>  SYMLINK-y-include += rte_cryptodev.h

>  SYMLINK-y-include += rte_cryptodev_pmd.h

> 

> diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h

> index 95cf861..e8c0bac 100644

> --- a/lib/librte_cryptodev/rte_crypto.h

> +++ b/lib/librte_cryptodev/rte_crypto.h

> @@ -23,6 +23,7 @@

>  #include <rte_common.h>

> 

>  #include "rte_crypto_sym.h"

> +#include "rte_crypto_asym.h"

> 

>  /** Crypto operation types */

>  enum rte_crypto_op_type {

> @@ -30,6 +31,8 @@ enum rte_crypto_op_type {

>  	/**< Undefined operation type */

>  	RTE_CRYPTO_OP_TYPE_SYMMETRIC,

>  	/**< Symmetric operation */

> +	RTE_CRYPTO_OP_TYPE_ASYMMETRIC

> +	/**< Asymmetric operation */

>  };

> 

>  /** Status of crypto operation */

> @@ -97,6 +100,10 @@ struct rte_crypto_op {

>  	union {

>  		struct rte_crypto_sym_op sym[0];

>  		/**< Symmetric operation parameters */

> +

> +		struct rte_crypto_asym_op asym[0];

> +		/**< Asymmetric operation parameters */

> +

>  	}; /**< operation specific parameters */

>  };

> 

> @@ -117,6 +124,9 @@ struct rte_crypto_op {

>  	case RTE_CRYPTO_OP_TYPE_SYMMETRIC:

>  		__rte_crypto_sym_op_reset(op->sym);

>  		break;

> +	case RTE_CRYPTO_OP_TYPE_ASYMMETRIC:

> +		__rte_crypto_asym_op_reset(op->asym);

> +		break;

>  	case RTE_CRYPTO_OP_TYPE_UNDEFINED:

>  	default:

>  		break;

> @@ -124,7 +134,7 @@ struct rte_crypto_op {

>  }

> 

>  /**

> - * Private data structure belonging to a crypto symmetric operation pool.

> + * Private data structure belonging to a crypto operation pool.

>   */

>  struct rte_crypto_op_pool_private {

>  	enum rte_crypto_op_type type;

> @@ -283,9 +293,14 @@ struct rte_crypto_op_pool_private {

>  	if (likely(op->mempool != NULL)) {

>  		priv_size = __rte_crypto_op_get_priv_data_size(op->mempool);

> 

> -		if (likely(priv_size >= size))

> -			return (void *)((uint8_t *)(op + 1) +

> +		if (likely(priv_size >= size)) {

> +			if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)

> +				return (void *)((uint8_t *)(op + 1) +

>  					sizeof(struct rte_crypto_sym_op));

> +			if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC)

> +				return (void *)((uint8_t *)(op+1) +

> +					sizeof(struct rte_crypto_asym_op));

> +		}

>  	}

> 

>  	return NULL;

> @@ -388,6 +403,24 @@ struct rte_crypto_op_pool_private {

>  	return __rte_crypto_sym_op_attach_sym_session(op->sym, sess);

>  }

> 

> +/**

> + * Attach a asymmetric session to a crypto operation

> + *

> + * @param	op	crypto operation, must be of type asymmetric

> + * @param	sess	cryptodev session

> + */

> +static inline int

> +rte_crypto_op_attach_asym_session(struct rte_crypto_op *op,

> +		struct rte_cryptodev_asym_session *sess)

> +{

> +	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_ASYMMETRIC))

> +		return -1;

> +

> +	op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;

> +

> +	return __rte_crypto_op_attach_asym_session(op->asym, sess);

> +}

> +

>  #ifdef __cplusplus

>  }

>  #endif

> diff --git a/lib/librte_cryptodev/rte_crypto_asym.h b/lib/librte_cryptodev/rte_crypto_asym.h

> new file mode 100644

> index 0000000..27caf55

> --- /dev/null

> +++ b/lib/librte_cryptodev/rte_crypto_asym.h

> @@ -0,0 +1,949 @@

> +/*

> + *   BSD LICENSE

> + *

[Fiona] Use SPDX license

> + *   Copyright (C) Cavium networks Ltd. 2017.

> + *

> + *   Redistribution and use in source and binary forms, with or without

> + *   modification, are permitted provided that the following conditions

> + *   are met:

> + *

> + *     * Redistributions of source code must retain the above copyright

> + *       notice, this list of conditions and the following disclaimer.

> + *     * Redistributions in binary form must reproduce the above copyright

> + *       notice, this list of conditions and the following disclaimer in

> + *       the documentation and/or other materials provided with the

> + *       distribution.

> + *     * Neither the name of Cavium Networks nor the names of its

> + *       contributors may be used to endorse or promote products derived

> + *       from this software without specific prior written permission.

> + *

> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

> + */

> +

> +#ifndef _RTE_CRYPTO_ASYM_H_

> +#define _RTE_CRYPTO_ASYM_H_

> +

> +/**

> + * @file rte_crypto_asym.h

> + *

> + * RTE Definitions for Asymmetric Cryptography

> + *

> + * Defines asymmetric algorithms and modes, as well as supported

> + * asymmetric crypto operations.

> + */

> +

> +#ifdef __cplusplus

> +extern "C" {

> +#endif

> +

> +#include <string.h>

> +#include <stdint.h>

> +#include <rte_mbuf.h>

> +#include <rte_memory.h>

> +#include <rte_mempool.h>

> +#include <rte_common.h>

> +

> +typedef struct rte_crypto_xform_param_t {

> +	uint8_t *data;

> +	phys_addr_t phys_addr;

[Fiona] Use iova

> +	size_t length;

> +} rte_crypto_xform_param;

> +

> +typedef struct rte_crypto_op_param_t {

> +	uint8_t *data;

> +	phys_addr_t phys_addr;

> +	size_t length;

> +} rte_crypto_op_param;

> +

[Fiona]  specify that above lengths are bytes - asym uses bit lengths in some contexts.
Above structs are identical - why not use a single struct? 
rte_crypto_param_t

mention 
> +/**

> + * Asymmetric crypto transformation types.

> + * Each xform type maps to one asymmetric algorithm

> + * performing specific operation

> + *

> + */

> +enum rte_crypto_asym_xform_type {

> +	RTE_CRYPTO_ASYM_XFORM_NONE = 0,

> +	/**< Xform type None. May be supported by

> +	 * PMD to support passthrough op for debugging

> +	 * purpose.

> +	 * if xform_type none , op_type is disregarded.

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_RSA,

> +	/**< RSA. Performs Encrypt, Decrypt, Sign and Verify

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_MODEX,

> +	/**< Modular Exponentiation

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_DH,

> +	/**< Deffie-Hellman. Perform Key Generate, Key Compute

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_ECDH,

> +	/**< Elliptic Curve Deffie-Hellman.

> +	 * Perform Key Genearate, Key Check and Key Compute

[Fiona] typo: generate

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_DSA,

> +	/**< Digital Signature Algorithm

> +	 * Performs Signature verification and Generation

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_ECDSA,

> +	/**< Elliptic Curve Digital Signature Algorithm.

> +	 * Performs Signature Generation, and Verification.

> +	 * Refer to rte_crypto_asym_op_type

> +	 */

[Fiona] typo in both above: Signature Generation and Verification

> +	RTE_CRYPTO_ASYM_XFORM_FECC,

> +	/**< Fundamental Elliptic curve operations.

> +	 * Perform elliptic curve operation:

> +	 * add, double point, multiplication

> +	 * Refer to enum rte_crypto_fecc_optype

> +	 */

> +	RTE_CRYPTO_ASYM_XFORM_MODINV,

> +	/**< Modular Inverse */

[Fiona] would be nicer to group modinv with modexp

> +	RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END

> +	/**< End of list */

> +};

> +

> +/**

> + * Asymmetric cryptogr operation type variants

[Fiona] typo: Use crypto or cryptographic

> + */

> +enum rte_crypto_asym_op_type {

> +	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,

[Fiona] Why does this start at 1?
And is it necessary?

> +	/**< Operation unspecified */

> +	RTE_CRYPTO_ASYM_OP_ENCRYPT,

> +	/**< Asymmetric encrypt operation */

> +	RTE_CRYPTO_ASYM_OP_DECRYPT,

> +	/**< Asymmetric Decrypt operation */

> +	RTE_CRYPTO_ASYM_OP_SIGN,

> +	/**< Signature generation operation */

> +	RTE_CRYPTO_ASYM_OP_VERIFY,

> +	/**< Signature verification operation */

> +	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,

> +	/**< Public/Private key pair generation operation */

[Fiona] In the comment, clarify that this is for DH and ECDH, and for the
 generation of the public key (and optionally the private key?)

> +	RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION,

> +	/**< DH private key computation operation */

[Fiona] In the comment, replace "private key" with "shared secret key". 
Also clarify that this is for both DH and ECDH
 
> +	RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK,

> +	/**< ECDH public key validity check operation */

> +	RTE_CRYPTO_ASYM_OP_LIST_END

> +};

> +

> +/**

> + * Padding types for RSA signature.

> + */

> +enum rte_crypto_rsa_padding_type {

> +	RTE_CRYPTO_RSA_PADDING_NOT_SPECIFIED = 1,

> +	/**< RSA no padding scheme */

> +	RTE_CRYPTO_RSA_PADDING_BT1,

> +	/**< RSA PKCS#1 padding BT1 scheme */

> +	RTE_CRYPTO_RSA_PADDING_BT2,

> +	/**< RSA PKCS#1 padding BT2 scheme */

[Fiona] In the name, I would add _PKCS1_V1.5_, to make this clearer. Also in the comment, clarify that BT is
for "block type". Also clarify how these map to the block type in PKCS#1 v1.5
(https://tools.ietf.org/html/rfc2313), which specifies three values for block type.

> +	RTE_CRYPTO_RSA_PADDING_OAEP,

> +	/**< RSA PKCS#1 OAEP padding scheme */

> +	RTE_CRYPTO_RSA_PADDING_PSS,

> +	/**< RSA PKCS#1 PSS padding scheme */

> +	RTE_CRYPTO_RSA_PADDING_TYPE_LIST_END

> +};

> +

> +

> +/**

> + * Fundamental ECC operation type variants.

> + */

> +enum rte_crypto_fecc_optype {

> +	RTE_CRYPTO_FECC_OP_NOT_SPECIFIED = 1,

> +	/**< FECC operation type unspecified */

[Fiona] as above. Why 1? And is it needed?

> +	RTE_CRYPTO_FECC_OP_POINT_ADD,

> +	/**< Fundamental ECC point addition operation */

> +	RTE_CRYPTO_FECC_OP_POINT_DBL,

> +	/**< Fundamental ECC point doubling operation */

> +	RTE_CRYPTO_FECC_OP_POINT_MULTIPLY,

> +	/**< Fundamental ECC point multiplication operation */

> +	RTE_CRYPTO_FECC_OP_LIST_END

> +};

> +

> +#define RTE_CRYPTO_EC_CURVE_NOT_SPECIFIED  -1

[Fiona] Wouldn't it be better to put this back in as the initial value in the enum as originally done?
Else will there not be a compiler warning if a param of that enum type is 
initialised to above #define?
And are _BINARY and _PRIME values needed in this case?

> +/**

> + * ECC list of curves.

> + */

> +enum rte_crypto_ec_prime_curve {

> +	/**< Unspecified or empty curve id */

[Fiona] Remove stray comment
> +	RTE_CRYPTO_EC_CURVE_secp112r1,

> +	/**< SECG/WTLS curve over a 112 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp112r2,

> +	/**< SECG curve over a 112 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp128r1,

> +	/**< SECG curve over a 128 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp128r2,

> +	/**< SECG curve over a 128 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp160k1,

> +	/**< SECG curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp160r1,

> +	/**< SECG curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp160r2,

> +	/**< SECG/WTLS curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp192k1,

> +	/**< SECG curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp224k1,

> +	/**< SECG curve over a 224 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp224r1,

> +	/**< NIST/SECG curve over a 224 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp256k1,

> +	/**< SECG curve over a 256 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp384r1,

> +	/**< NIST/SECG curve over a 384 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_secp521r1,

> +	/**< NIST/SECG curve over a 521 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime192v1,

> +	/**< NIST/X9.62/SECG curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime192v2,

> +	/**< X9.62 curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime192v3,

> +	/**< X9.62 curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime239v1,

> +	/**< X9.62 curve over a 239 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime239v2,

> +	/**< X9.62 curve over a 239 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime239v3,

> +	/**< X9.62 curve over a 239 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_prime256v1,

> +	/**< X9.62/SECG curve over a 256 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls6,

> +	/**< SECG/WTLS curve over a 112 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls7,

> +	/**< SECG/WTLS curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls8,

> +	/**< WTLS curve over a 112 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls9,

> +	/**< WTLS curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls12,

> +	/**< WTLS curve over a 224 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP160r1,

> +	/**< RFC 5639 curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP160t1,

> +	/**< RFC 5639 curve over a 160 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP192r1,

> +	/**< RFC 5639 curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP192t1,

> +	/**< RFC 5639 curve over a 192 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP224r1,

> +	/**< RFC 5639 curve over a 224 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP224t1,

> +	/**< RFC 5639 curve over a 224 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP256r1,

> +	/**< RFC 5639 curve over a 256 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP256t1,

> +	/**< RFC 5639 curve over a 256 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP320r1,

> +	/**< RFC 5639 curve over a 320 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP320t1,

> +	/**< RFC 5639 curve over a 320 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP384r1,

> +	/**< RFC 5639 curve over a 384 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP384t1,

> +	/**< RFC 5639 curve over a 384 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP512r1,

> +	/**< RFC 5639 curve over a 512 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_brainpoolP512t1,

> +	/**< RFC 5639 curve over a 512 bit prime field */

> +	RTE_CRYPTO_EC_CURVE_x25519,

> +	/**< Curve 25519 */

> +	RTE_CRYPTO_EC_PCURVE_LIST_END

> +};

> +

> +enum rte_crypto_ec_binary_curve {

> +	/**< Unspecified or empty curve id */

[Fiona] remove stray comment
> +	RTE_CRYPTO_EC_CURVE_sect113r1,

> +	/**< SECG curve over a 113 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect113r2,

> +	/**< SECG curve over a 113 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect131r1,

> +	/**< SECG/WTLS curve over a 131 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect131r2,

> +	/**< SECG curve over a 131 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect163k1,

> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect163r1,

> +	/**< SECG curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect163r2,

> +	/**< NIST/SECG curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect193r1,

> +	/**< SECG curve over a 193 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect193r2,

> +	/**< SECG curve over a 193 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect233k1,

> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect233r1,

> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect239k1,

> +	/**< SECG curve over a 239 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect283k1,

> +	/**< NIST/SECG curve over a 283 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect283r1,

> +	/**< NIST/SECG curve over a 283 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect409k1,

> +	/**< NIST/SECG curve over a 409 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect409r1,

> +	/**< NIST/SECG curve over a 409 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect571k1,

> +	/**< NIST/SECG curve over a 571 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_sect571r1,

> +	/**< NIST/SECG curve over a 571 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb163v1,

> +	/**< X9.62 curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb163v2,

> +	/**< X9.62 curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb163v3,

> +	/**< X9.62 curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb176v1,

> +	/**< X9.62 curve over a 176 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb191v1,

> +	/**< X9.62 curve over a 191 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb191v2,

> +	/**< X9.62 curve over a 191 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb191v3,

> +	/**< X9.62 curve over a 191 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb208w1,

> +	/**< X9.62 curve over a 208 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb239v1,

> +	/**< X9.62 curve over a 239 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb239v2,

> +	/**< X9.62 curve over a 239 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb239v3,

> +	/**< X9.62 curve over a 239 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb272w1,

> +	/**< X9.62 curve over a 272 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb304w1,

> +	/**< X9.62 curve over a 304 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb359v1,

> +	/**< X9.62 curve over a 359 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2pnb368w1,

> +	/**< X9.62 curve over a 368 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_c2tnb431r1,

> +	/**< X9.62 curve over a 431 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls1,

> +	/**< WTLS curve over a 113 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls3,

> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls4,

> +	/**< SECG curve over a 113 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls5,

> +	/**< X9.62 curve over a 163 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls10,

> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls11,

> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> +	RTE_CRYPTO_EC_BCURVE_LIST_END

> +};

[Fiona] Do we really want to specify curves < 224 bits? Even 224 is woefully insecure these days.
Also do we want to list all "published" curves, or allow customers to specify 
their own curve parameters, at least on the FECC API? Adding an API to specify a curve with
its params would allow new curves to be used without affecting the API and
would avoid the need for such an extensive list.
Do we need a "capabilities" mask to say which curves are supported by a device?
What about SM2?

> +/**

> + * Elliptic curve point format

> + */

> +struct rte_crypto_ec_point {

> +	struct {

> +		int length;

> +		uint8_t *data;

> +		phys_addr_t phys_addr;

> +		/**< phys_addr is used only for points passed in the

> +		 * asym_op structure.

> +		 */

> +	} x;

> +	/**< X co-ordinate */

> +

[Fiona] If generic rte_crypto_param_t is defined then it could be used here too.

> +	struct {

> +		int length;

> +		uint8_t *data;

> +		phys_addr_t phys_addr;

> +		/**< phys_addr is used only for points passed in the

> +		 * operation structure

> +		 */

> +	} y;

> +	/**< Y co-ordinate */

> +};

> +

> +/**

> + * Elliptic curve type

> + */

> +enum rte_crypto_ec_curve_type {

> +	RTE_CRYPTO_EC_CURVE_TYPE_UNDEFINED,

> +	/**< Curve type undefined */

> +	RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD,

> +	/**< EC curve defined over a prime field */

> +	RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD,

> +	/**< EC curve defined over a binary field */

> +	RTE_CRYPTO_EC_CURVE_LIST_END

> +};

> +

> +/** asym xform type name strings */

> +extern const char *

> +rte_crypto_asym_xform_strings[];

> +

> +/** asym operations type name strings */

> +extern const char *

> +rte_crypto_asym_op_strings[];

> +

> +/**

> + * Elliptic curve id

> + */

> +struct rte_crypto_ec_curve_id {

> +	RTE_STD_C11

> +	union {

> +		enum rte_crypto_ec_prime_curve pcurve;

> +		enum rte_crypto_ec_binary_curve bcurve;

> +	};

> +};

[Fiona] Because the values of these two enums overlap, if you specify the curve type incorrectly, you'll still
have a potentially valid curve enum specified. I suggest it's safer to include the type here with the union,
rather than in the wrapper xform struct, i.e. 
struct rte_crypto_ec_curve {
	enum rte_crypto_ec_curve_type curve_type;
	/**< curve type: Prime vs Binary */
	union {
	enum rte_crypto_ec_prime_curve pcurve_id;
	enum rte_crypto_ec_binary_curve bcurve_id;
	};
};
> +/**

> + * Asymmetric RSA transform data

> + *

> + * This structure contains data required to perform RSA crypto

> + * transform.

> + *

> + */

> +struct rte_crypto_rsa_xform {

> +

> +	rte_crypto_xform_param n;

> +	/**< n - Prime modulus

> +	 * Prime modulus data of RSA operation in Octet-string network

> +	 * byte order format.

> +	 */

> +

> +	rte_crypto_xform_param e;

> +	/**< e - Public key exponent

> +	 * Public key exponent used for RSA public key operations in Octet-

> +	 * string network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param d;

> +	/**< d - Private key exponent

> +	 * Private key exponent used for RSA private key operations in

> +	 * Octet-string  network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param p;

> +	/**< p - Private key component P

> +	 * Private key component of RSA parameter  required for CRT method

> +	 * of private key operations in Octet-string network byte order

> +	 * format.

> +	 */

> +

> +	rte_crypto_xform_param q;

> +	/**< q - Private key component Q

> +	 * Private key component of RSA parameter  required for CRT method

> +	 * of private key operations in Octet-string network byte order

> +	 * format.

> +	 */

> +

> +	rte_crypto_xform_param dP;

> +	/**< dP - Private CRT component

> +	 * Private CRT component of RSA parameter  required for CRT method

> +	 * RSA private key operations in Octet-string network byte order

> +	 * format.

> +	 * dP = d mod ( p - 1 )

> +	 */

> +

> +	rte_crypto_xform_param dQ;

> +	/**< dQ - Private CRT component

> +	 * Private CRT component of RSA parameter  required for CRT method

> +	 * RSA private key operations in Octet-string network byte order

> +	 * format.

> +	 * dQ = d mod ( q - 1 )

> +	 */

> +

> +	rte_crypto_xform_param qInv;

> +	/**< qInv - Private CRT component

> +	 * Private CRT component of RSA parameter  required for CRT method

> +	 * RSA private key operations in Octet-string network byte order

> +	 * format.

> +	 * qInv = inv q mod p

> +	 */

> +};

[Fiona] This allows both representations of the private key to be specified
with the possibility of confusion if both are specified.
Would it be better to have a union of 2 different structures, one with {n,d} and 
the other with {p,q,dP,dQ,qInv}?

> +/**

> + * Asymmetric Modular exponentiation transform data

> + *

> + * This structure contains data required to perform modular exponentation

> + * crypto transform.

> + *

> + */

> +struct rte_crypto_modex_xform {

> +

> +	rte_crypto_xform_param modulus;

> +	/**< modulus

> +	 * Prime modulus of the modexp transform operation in Octet-string

> +	 * network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param exponent;

> +	/**< exponent

> +	 * Private exponent of the modexp transform operation in

> +	 * Octet-string network byte order format.

> +	 */

> +};

> +

> +/**

> + * Asymmetric DH transform data

> + *

> + * This structure contains data used to perform DH key

> + * operations.

> + *

> + */

> +struct rte_crypto_dh_xform {

> +	rte_crypto_xform_param p;

> +	/**< p : Prime modulus data

> +	 * DH prime modulous data in Octet-string network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param g;

> +	/**< g : Generator

> +	 * DH group generator data in Octet-string network byte order

> +	 * format.

> +	 */

> +};

> +

> +/**

> + * Asymmetric ECDH transform data

> + *

> + * This structure contains data required to perform ECDH crypto

> + * transform.

> + *

> + */

> +struct rte_crypto_ecdh_xform {

> +

> +	enum rte_crypto_ec_curve_type curve_type;

> +	/**< ECDH curve type: Prime vs Binary */

> +

> +	struct rte_crypto_ec_curve_id curve_id;

> +

> +	rte_crypto_xform_param p;

> +	/**< p:

> +	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD:

> +	 * p holds the prime modulus data in Octet string format.

> +	 *

> +	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD:

> +	 * p holds reduction polynomial co-efficients and degree.

> +	 */

> +

> +	rte_crypto_xform_param a;

> +	/**< Curve Parameter Co-efficient 'a' of curve equation data in

> +	 * Octet-string network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param b;

> +	/**< Curve Parameter Co-efficient 'b' of curve equation data in

> +	 * Octet-string network byte order format.

> +	 */

> +

> +	struct  rte_crypto_ec_point G;

> +	/**< G: EC curve generator point

> +	 * EC curve generator point data in Octet-string network byte order

> +	 * format.

> +	 */

> +

> +	rte_crypto_xform_param n;

> +	/**< n : order of G

> +	 * ECDH curve order data in Octet-string network byte order format.

> +	 */

> +

> +	int h;

> +	/**< Co-factor of the curve */

> +

> +	rte_crypto_xform_param pkey;

> +	/**< pkey: Private key

> +	 * Private key data for ECDH operation in Octet-string network byte

> +	 * order format.

> +	 */

> +

> +	struct rte_crypto_ec_point Q;

> +	/**< Q: Public key point

> +	 * Public key point data of ECDH operation in Octet-string network

> +	 * byte order format.

> +	 */

> +};

> +

> +/**

> + * Asymmetric Digital Signature transform operation

> + *

> + * This structure contain signer key information for DSA signature

> + * generation and verification.

> + * App which does both Signature Generation and Verification should

> + * create two separate session carrying its own and peer key information

> + *

> + */

> +struct rte_crypto_dsa_xform {

> +	rte_crypto_xform_param p;

> +	/**< p - Prime modulus

> +	 * Prime modulus data for DSA operation in Octet-string network byte

> +	 * order format.

> +	 */

> +	rte_crypto_xform_param q;

> +	/**< q : Order of the subgroup.

> +	 * Order of the subgroup data in Octet-string network byte order

> +	 * format.

> +	 * (p-1) % q = 0

> +	 */

> +	rte_crypto_xform_param g;

> +	/**< g: Generator of the subgroup

> +	 * Generator  data in Octet-string network byte order format.

> +	 */

> +	rte_crypto_xform_param x;

> +	/**< x: Private key of the signer

> +	 * Private key data in Octet-string network byte order format.

> +	 * Private key is valid only for signature generation operation.

> +	 */

> +	rte_crypto_xform_param y;

> +	/**< y : Public key of the signer.

> +	 * Public key data of the signer in Octet-string network byte order

> +	 * format.

> +	 * y = g^x mod p

> +	 */

> +};

> +

> +/**

> + * Asymmetric ECDSA transform data

> + *

> + * This structure contains data required to perform ECDSA crypto

> + * transform.

> + */

> +struct rte_crypto_ecdsa_xform {

> +	/** TBD */

> +};

> +

> +/**

> + * Asymmetric modular inverse transform operation

> + *

> + * This structure contains data required to perform

> + * asymmetric modular inverse crypto transform

> + */

> +struct rte_crypto_modinv_xform {

> +	/** TBD */

> +};

> +

> +/** Asymmetric Fundamental ECC transform operation

> + *

> + * This structure contains data required to perform asymmetric

> + * fundamental ECC crypto transform.

> + */

> +struct rte_crypto_fecc_xform {

> +

> +	enum rte_crypto_ec_curve_type curve_type;

> +	/**< FECC curve type: Prime vs Binary */

> +

> +	struct rte_crypto_ec_curve_id curve_id;

> +	/**< EC curve ID */

> +

> +	rte_crypto_xform_param order;

> +	/**< order : ECC curve order

> +	 * Curve order data in Octet-string network byte order format.

> +	 */

> +

> +	rte_crypto_xform_param prime;

> +	/**< prime : Curve prime modulus data

> +	 * Prime modulus data in Octet-string network byte order format.

> +	 */

> +

> +	struct rte_crypto_ec_point G;

> +	/**< G: curve generator point

> +	 * Curve generator point data in Octet-string network byte order

> +	 * format.

> +	 */

> +

> +	rte_crypto_xform_param a;

> +	/**< Co-efficient 'a' of curve equation data in Octet-string network

> +	 * byte order format.

> +	 */

> +

> +	rte_crypto_xform_param b;

> +	/**< Co-efficient 'a' of curve equation data in Octet-string network

> +	 * byte order format.

> +	 */

> +

> +	int h;

> +	/**< Co-factor of the curve */

> +

> +};

> +

> +/**

> + * Asymmetric crypto transform data

> + *

> + * This structure contains the data required to perform the

> + * asymmetric crypto transformation operation. The field op

> + * determines the asymmetric algorithm for transformation.

[Fiona] clarify comment. The xform only contains some of the data, the rest will be provided in the op.
And there's no field op here. 
> + */

> +struct rte_crypto_asym_xform {

> +	struct rte_crypto_asym_xform *next;

[Fiona] Is there any reason for a chain of xforms?
I'd suggest removing unless needed.

> +	enum rte_crypto_asym_xform_type xform_type;

> +	/**< Asymmetric algorithm for crypto transform */

> +

> +	RTE_STD_C11

> +	union {

> +		struct rte_crypto_rsa_xform rsa;

> +		/**< RSA xform parameters */

> +

> +		struct rte_crypto_fecc_xform fecc;

> +		/**< Fundamental Elliptic Curve xform parameters */

> +

> +		struct rte_crypto_modex_xform modex;

> +		/**< Modular Exponentiation xform parameters */

> +

> +		struct rte_crypto_modinv_xform modinv;

> +		/**< Modulus Inverse xform parameters */

> +

> +		struct rte_crypto_ecdsa_xform ecdsa;

> +		/**< ECDSA xform parameters */

> +

> +		struct rte_crypto_ecdh_xform ecdh;

> +		/**< ECDH xform parameters */

> +

> +		struct rte_crypto_dsa_xform dsa;

> +		/**< DSA xform parameters */

> +	};

> +};

> +

> +struct rte_cryptodev_asym_session;

> +

> +/**

> + * RSA operation params

> + *

> + */

> +struct rte_crypto_rsa_op_param {

> +	enum rte_crypto_asym_op_type op_type;

> +	/**< Type of RSA operation for transform */;

> +

> +	rte_crypto_op_param message;

> +	/**<

> +	 * Pointer to data

> +	 * - to be encrypted for RSA public encrypt.

> +	 * - to be decrypted for RSA private decrypt.

> +	 * - to be signed for RSA sign generation.

> +	 * - to be authenticated for RSA sign verification.

> +	 */

> +

> +	rte_crypto_op_param sign;

> +	/**<

> +	 * Pointer to RSA signature data. If operation is RSA

> +	 * sign @ref RTE_CRYPTO_RSA_OP_SIGN, buffer will be

> +	 * over-written with generated signature.

> +	 *

> +	 * Length of the signature data will be equal to the

> +	 * RSA prime modulus length.

> +	 */

> +

> +	enum rte_crypto_rsa_padding_type pad;

> +	/**< RSA padding scheme to be used for transform */

> +

> +	enum rte_crypto_auth_algorithm md;

> +	/**< Hash algorithm to be used for data hash if padding

> +	 * scheme is either OAEP or PSS. Valid hash algorithms

> +	 * are:

> +	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512

> +	 */

> +

> +	enum rte_crypto_auth_algorithm mgf1md;

> +	/**<

> +	 * Hash algorithm to be used for mask generation if

> +	 * padding scheme is either OAEP or PSS. If padding

> +	 * scheme is unspecified data hash algorithm is used

> +	 * for mask generation. Valid hash algorithms are:

> +	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512

> +	 */

> +};

> +

> +/**

> + * Deffie-Hellman Operations params

> + *

> + */

> +struct rte_crypto_dh_op_param {

> +	enum rte_crypto_asym_op_type op_type;

> +	/**< Asymmetric op type: Key Generation / Computation */

> +

> +	rte_crypto_op_param pub_key;

> +	/**<

> +	 * Output native app public key when DH operation type is

> +	 * KEY_GENERATION.

> +	 * Input peer public key when DH operation is shared key

> +	 * KEY_COMPUTATION

> +	 * An Octet-string network byte order format.

> +	 *

> +	 */

> +

> +	rte_crypto_op_param priv_key;

> +	/**<

> +	 * Output native app private key if operation type

> +	 * KEY_GENERATION.

> +	 * Input native app private key when operation type

> +	 * is KEY_COMPUTATION. priv_key is in

> +	 * in Octet-string network byte order format.

> +	 */

> +

> +	rte_crypto_op_param shared_key;

> +	/*

> +	 * Output when DH operation type is KEY_COMPUTATION:

> +	 * computed. shared_key is written as

> +	 * Octet-string network byte order format.

> +	 * Ignored for KEY_GENERATION.

> +	 */

> +};

> +

> +/**

> + * DSA Operations params

> + *

> + */

> +struct rte_crypto_dsa_op_param {

> +	/** TBD */

> +};

> +

> +/**

> + * Mod Exp Operations params

> + *

> + */

> +struct rte_crypto_modex_op_param {

> +	rte_crypto_op_param base;

> +	/**<

> +	 * Pointer to base of modular exponentiation data in

> +	 * Octet-string network byte order format.

> +	 */

> +};

> +

> +/**

> + * Elliptic curve Deffie-Hellman Operations params

> + *

> + */

> +struct rte_crypto_ecdh_op_param {

> +	enum rte_crypto_asym_op_type op_type;

> +	/**< Asymmetric operation: key generation, computation */

> +

> +	rte_crypto_op_param priv_key;

> +	/**<

> +	 * Output if operation type is KEY_PAIR_GENERATION,

> +	 * output native app private key.

> +	 * Input and output, If ECDH operation type is SHARED_KEY_COMPUTATION,

> +	 * priv_key will hold the 'X' co-ordinate of the shared

> +	 * secret EC point. priv_key is in Octet-string network

> +	 * byte order.

> +	 */

> +

> +	struct rte_crypto_ec_point pub_key;

> +	/**<

> +	 * Output if operation type is KEY_PAIR_GENERATION,

> +	 * store native app public key.

> +	 * Input if operation type is SHARED_KEY_COMPUTATION,

> +	 *

> +	 * KEY_COMPUTATION:

> +	 *  pub_key is in Octet-string network byte order.

> +	 */

> +};

> +

> +/**

> + * Elliptic Curve DSA Operations params

> + *

> + */

> +struct rte_crypto_ecdsa_op_param {

> +

> +	enum rte_crypto_asym_op_type ecdsa_op;

> +	/**< ECDSA crypto xform operation type: Signature

> +	 *  generation/Verification

> +	 */

> +	/** TBD */

> +};

> +

> +/**

> + * Fundamental Elliptic Curve Operations params

> + *

> + */

> +struct rte_crypto_fecc_op_param {

> +	enum rte_crypto_fecc_optype fecc_op;

> +	/**< FECC crypto xform operation type */

> +

> +	/** TBD */

> +};

> +

> +/**

> + * Mod Inv Operations params

> + *

> + */

> +struct rte_crypto_modinv_op_param {

> +	rte_crypto_op_param prime;

> +	/**<

> +	 * Pointer to the prime modulus data for modular

> +	 * inverse operation in Octet-string network byte

> +	 * order format.

> +	 */

> +

> +	rte_crypto_op_param base;

> +	/**<

> +	 * Pointer to the base for the modular inverse

> +	 * operation in Octet-string network byte order

> +	 * format.

> +	 */

> +};

> +

> +/**

> + * Asymmetric Cryptographic Operation.

> + *

> + * This structure contains data relating to performing asymmetric cryptographic

> + * operation.

> + *

> + */

> +struct rte_crypto_asym_op {

> +	enum rte_crypto_asym_xform_type type;

> +	/**< RSA, DH, ECDH, DSA etc */

> +

> +	struct rte_cryptodev_asym_session *session;

> +	/**< Handle for the initialised session context */

> +

> +	RTE_STD_C11

> +	union {

> +		struct rte_crypto_rsa_op_param rsa;

> +		struct rte_crypto_dh_op_param dh;

> +		struct rte_crypto_modex_op_param modex;

> +		struct rte_crypto_ecdh_op_param ecdh;

> +		struct rte_crypto_ecdsa_op_param ecdsa;

> +		struct rte_crypto_dsa_op_param dsa;

> +		struct rte_crypto_fecc_op_param fecc;

> +		struct rte_crypto_modinv_op_param modinv;

> +	};

> +} __rte_cache_aligned;

> +

> +/**

> + * Reset the fields of an asymmetric operation to their default values.

> + *

> + * @param	op	The crypto operation to be reset.

> + */

> +static inline void

> +__rte_crypto_asym_op_reset(struct rte_crypto_asym_op *op)

> +{

> +	memset(op, 0, sizeof(*op));

> +}

> +

> +

> +/**

> + * Attach a session to an asymmetric crypto operation

> + *

> + * @param	asym_op	crypto operation

> + * @param	sess	cryptodev session

> + */

> +static inline int

> +__rte_crypto_op_attach_asym_session(struct rte_crypto_asym_op *asym_op,

> +		struct rte_cryptodev_asym_session *sess)

> +{

> +	asym_op->session = sess;

> +	return 0;

> +}

> +

> +#ifdef __cplusplus

> +}

> +#endif

> +

> +#endif /* _RTE_CRYPTO_ASYM_H_ */

> diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c

> index 7726d15..bad18c3 100644

> --- a/lib/librte_cryptodev/rte_cryptodev.c

> +++ b/lib/librte_cryptodev/rte_cryptodev.c

> @@ -166,6 +166,33 @@ struct rte_cryptodev_callback {

>  	[RTE_CRYPTO_AEAD_OP_DECRYPT]	= "decrypt"

>  };

> 

> +/**

> + * Asymmetric crypto transform operation strings identifiers.

> + */

> +const char *rte_crypto_asym_xform_strings[] = {

> +	[RTE_CRYPTO_ASYM_XFORM_RSA]	= "rsa",

> +	[RTE_CRYPTO_ASYM_XFORM_MODEX]	= "modexp",

> +	[RTE_CRYPTO_ASYM_XFORM_DH]	= "dh",

> +	[RTE_CRYPTO_ASYM_XFORM_ECDH]	= "ecdh",

> +	[RTE_CRYPTO_ASYM_XFORM_DSA]	= "dsa",

> +	[RTE_CRYPTO_ASYM_XFORM_ECDSA]	= "ecdsa",

> +	[RTE_CRYPTO_ASYM_XFORM_MODINV]	= "modinv",

> +	[RTE_CRYPTO_ASYM_XFORM_FECC]	= "fecc"

> +};

> +

> +/**

> + * Asymmetric crypto operation strings identifiers.

> + */

> +const char *rte_crypto_asym_op_strings[] = {

> +	[RTE_CRYPTO_ASYM_OP_ENCRYPT]	= "encrypt",

> +	[RTE_CRYPTO_ASYM_OP_DECRYPT]	= "decrypt",

> +	[RTE_CRYPTO_ASYM_OP_SIGN]	= "sign",

> +	[RTE_CRYPTO_ASYM_OP_VERIFY]	= "verify",

> +	[RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION]	= "keypair_generate",

> +	[RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION] = "sharedkey_computation",

> +	[RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK]	= "ecdh_keycheck",

> +};

> +

>  int

>  rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,

>  		const char *algo_string)

> @@ -217,6 +244,24 @@ struct rte_cryptodev_callback {

>  	return -1;

>  }

> 

> +int

> +rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,

> +		const char *xform_string)

> +{

> +	unsigned int i;

> +

> +	for (i = 1; i < RTE_DIM(rte_crypto_asym_xform_strings); i++) {

> +		if (strcmp(xform_string,

> +			   rte_crypto_asym_xform_strings[i]) == 0) {

> +			*xform_enum = (enum rte_crypto_asym_xform_type) i;

> +			return 0;

> +		}

> +	}

> +

> +	/* Invalid string */

> +	return -1;

> +}

> +

>  /**

>   * The crypto auth operation strings identifiers.

>   * It could be used in application command line.

> @@ -262,6 +307,28 @@ struct rte_cryptodev_callback {

> 

>  }

> 

> +const struct rte_cryptodev_asymmetric_capability *

> +rte_cryptodev_asym_capability_get(uint8_t dev_id,

> +		const struct rte_cryptodev_asym_capability_idx *idx)

> +{

> +	const struct rte_cryptodev_capabilities *capability;

> +	struct rte_cryptodev_info dev_info;

> +	unsigned int i = 0;

> +

> +	memset(&dev_info, 0, sizeof(rte_cryptodev_info));

> +	rte_cryptodev_info_get(dev_id, &dev_info);

> +

> +	while ((capability = &dev_info.capabilities[i++])->op !=

> +			RTE_CRYPTO_OP_TYPE_UNDEFINED) {

> +		if (capability->op != RTE_CRYPTO_OP_TYPE_ASYMMETRIC)

> +			continue;

> +

> +		if (capability->asym.xform_type == idx->type)

> +			return &capability->asym;

> +	}

> +	return NULL;

> +};

> +

>  #define param_range_check(x, y) \

>  	(((x < y.min) || (x > y.max)) || \

>  	(y.increment != 0 && (x % y.increment) != 0))

> @@ -601,6 +668,24 @@ struct rte_cryptodev *

>  	return dev->data->nb_queue_pairs;

>  }

> 

> +uint16_t

> +rte_cryptodev_asym_queue_pair_count(uint8_t dev_id)

> +{

> +	struct rte_cryptodev *dev;

> +

> +	dev = &rte_crypto_devices[dev_id];

> +	return dev->data->nb_asym_qp;

> +}

> +

> +uint16_t

> +rte_cryptodev_sym_queue_pair_count(uint8_t dev_id)

> +{

> +	struct rte_cryptodev *dev;

> +

> +	dev = &rte_crypto_devices[dev_id];

> +	return dev->data->nb_sym_qp;

> +}

> +

>  static int

>  rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,

>  		int socket_id)

> @@ -1088,6 +1173,38 @@ struct rte_cryptodev *

>  	return 0;

>  }

> 

> +int

> +rte_cryptodev_asym_session_init(uint8_t dev_id,

> +		struct rte_cryptodev_asym_session *sess,

> +		struct rte_crypto_asym_xform *xforms,

> +		struct rte_mempool *mp)

> +{

> +	struct rte_cryptodev *dev;

> +	uint8_t index;

> +	int ret;

> +

> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

> +

> +	if (sess == NULL || xforms == NULL || dev == NULL)

> +		return -EINVAL;

> +

> +	index = dev->driver_id;

> +

> +	if (sess->sess_private_data[index] == NULL) {

> +		ret = dev->dev_ops->asym_session_configure(dev,

> +							   xforms,

> +							   sess, mp);

> +		if (ret < 0) {

> +			CDEV_LOG_ERR(

> +				"dev_id %d failed to configure session details",

> +				dev_id);

> +			return ret;

> +		}

> +	}

> +

> +	return 0;

> +}

> +

>  struct rte_cryptodev_sym_session *

>  rte_cryptodev_sym_session_create(struct rte_mempool *mp)

>  {

> @@ -1105,6 +1222,23 @@ struct rte_cryptodev_sym_session *

>  	return sess;

>  }

> 

> +struct rte_cryptodev_asym_session *

> +rte_cryptodev_asym_session_create(struct rte_mempool *mp)

> +{

> +	struct rte_cryptodev_asym_session *sess;

> +

> +	/* Allocate a session structure from the session pool */

> +	if (rte_mempool_get(mp, (void *)&sess)) {

> +		CDEV_LOG_ERR("couldn't get object from session mempool");

> +		return NULL;

> +	}

> +

> +	/* Clear device session pointer */

> +	memset(sess, 0, (sizeof(void *) * nb_drivers));

> +

> +	return sess;

> +}

> +

>  int

>  rte_cryptodev_queue_pair_attach_sym_session(uint8_t dev_id, uint16_t qp_id,

>  		struct rte_cryptodev_sym_session *sess)

> @@ -1160,6 +1294,60 @@ struct rte_cryptodev_sym_session *

>  }

> 

>  int

> +rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,

> +		struct rte_cryptodev_asym_session *sess)

> +{

> +	struct rte_cryptodev *dev;

> +

> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {

> +		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);

> +		return -EINVAL;

> +	}

> +

> +	dev = &rte_crypto_devices[dev_id];

> +

> +	/* The API is optional, not returning error if driver do not suuport */

> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_attach_session, 0);

> +

> +	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);

> +

> +	if (dev->dev_ops->asym_qp_attach_session(dev, qp_id, sess_priv)) {

> +		CDEV_LOG_ERR("dev_id %d failed to attach qp: %d with session",

> +				dev_id, qp_id);

> +		return -EPERM;

> +	}

> +

> +	return 0;

> +}

> +

> +int

> +rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,

> +		struct rte_cryptodev_asym_session *sess)

> +{

> +	struct rte_cryptodev *dev;

> +

> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {

> +		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);

> +		return -EINVAL;

> +	}

> +

> +	dev = &rte_crypto_devices[dev_id];

> +

> +	/* The API is optional, not returning error if driver do not suuport */

> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_detach_session, 0);

> +

> +	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);

> +

> +	if (dev->dev_ops->asym_qp_detach_session(dev, qp_id, sess_priv)) {

> +		CDEV_LOG_ERR("dev_id %d failed to detach qp: %d from session",

> +				dev_id, qp_id);

> +		return -EPERM;

> +	}

> +

> +	return 0;

> +}

> +

> +int

>  rte_cryptodev_sym_session_clear(uint8_t dev_id,

>  		struct rte_cryptodev_sym_session *sess)

>  {

> @@ -1176,6 +1364,22 @@ struct rte_cryptodev_sym_session *

>  }

> 

>  int

> +rte_cryptodev_asym_session_clear(uint8_t dev_id,

> +		struct rte_cryptodev_asym_session *sess)

> +{

> +	struct rte_cryptodev *dev;

> +

> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

> +

> +	if (dev == NULL || sess == NULL)

> +		return -EINVAL;

> +

> +	dev->dev_ops->asym_session_clear(dev, sess);

> +

> +	return 0;

> +}

> +

> +int

>  rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess)

>  {

>  	uint8_t i;

> @@ -1199,6 +1403,31 @@ struct rte_cryptodev_sym_session *

>  	return 0;

>  }

> 

> +int

> +rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess)

> +{

> +	uint8_t i;

> +	void *sess_priv;

> +	struct rte_mempool *sess_mp;

> +

> +	if (sess == NULL)

> +		return -EINVAL;

> +

> +	/* Check that all device private data has been freed */

> +	for (i = 0; i < nb_drivers; i++) {

> +		sess_priv = get_asym_session_private_data(sess, i);

> +		if (sess_priv != NULL)

> +			return -EBUSY;

> +	}

> +

> +	/* Return session to mempool */

> +	sess_mp = rte_mempool_from_obj(sess);

> +	rte_mempool_put(sess_mp, sess);

> +

> +	return 0;

> +}

> +

> +

>  unsigned int

>  rte_cryptodev_get_header_session_size(void)

>  {

> @@ -1235,6 +1464,57 @@ struct rte_cryptodev_sym_session *

>  		return header_size;

> 

>  	return priv_sess_size;

> +}

> +

> +unsigned int

> +rte_cryptodev_get_sym_session_private_size(uint8_t dev_id)

> +{

> +	struct rte_cryptodev *dev;

> +	unsigned int header_size = sizeof(void *) * nb_drivers;

> +	unsigned int priv_sess_size;

> +

> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))

> +		return 0;

> +

> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

> +

> +	if (*dev->dev_ops->sym_session_get_size == NULL)

> +		return 0;

> +

> +	priv_sess_size = (*dev->dev_ops->sym_session_get_size)(dev);

> +

> +	/*

> +	 * If size is less than session header size,

> +	 * return the latter, as this guarantees that

> +	 * sessionless operations will work

> +	 */

> +	if (priv_sess_size < header_size)

> +		return header_size;

> +

> +	return priv_sess_size;

> +}

> +

> +

> +unsigned int

> +rte_cryptodev_get_asym_session_private_size(uint8_t dev_id)

> +{

> +	struct rte_cryptodev *dev;

> +	unsigned int header_size = sizeof(void *) * nb_drivers;

> +	unsigned int priv_sess_size;

> +

> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))

> +		return 0;

> +

> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

> +

> +	if (*dev->dev_ops->asym_session_get_size == NULL)

> +		return 0;

> +

> +	priv_sess_size = (*dev->dev_ops->asym_session_get_size)(dev);

> +	if (priv_sess_size < header_size)

> +		return header_size;

> +

> +	return priv_sess_size;

> 

>  }

> 

> @@ -1268,6 +1548,13 @@ struct rte_mempool *

>  			sizeof(struct rte_crypto_sym_op) +

>  			priv_size;

> 

> +	if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {

> +		/* override size by size of asym op */

> +		elt_size = sizeof(struct rte_crypto_op) +

> +			   sizeof(struct rte_crypto_asym_op) +

> +			   priv_size;

> +	}

> +

>  	/* lookup mempool in case already allocated */

>  	struct rte_mempool *mp = rte_mempool_lookup(name);

> 

> diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h

> index c8fa689..728483c 100644

> --- a/lib/librte_cryptodev/rte_cryptodev.h

> +++ b/lib/librte_cryptodev/rte_cryptodev.h

> @@ -178,15 +178,41 @@ struct rte_cryptodev_symmetric_capability {

>  	};

>  };

> 

> +/**

> + * Asymmetric Crypto Capability

> + *

> + */

> +struct rte_cryptodev_asymmetric_capability {

> +	enum rte_crypto_asym_xform_type xform_type;

> +	/**< Transform type: RSA/MODEXP/DH/ECDH/DSA/ECDSA/FECC/MODINV */

> +

[Fiona] Is there a fixed set of rte_cryptodev_asym_op_type for each xform type?
If any variant possible then there would need to be a capability field for this.

	RTE_STD_C11
> +	union {

> +		struct rte_crypto_param_range modlen;

> +		/**< Range of modulus length supported for modulus based

> +		 * algos:

> +		 * RSA

> +		 * MODEXP

> +		 * MODINV

> +		 * DH

> +		 *

> +		 * Value 0 to min and/or max means no specific limit and limit

> +		 * is implementation dependent

> +		 *

> +		 */

> +	};

> +};

> +

>  /** Structure used to capture a capability of a crypto device */

>  struct rte_cryptodev_capabilities {

>  	enum rte_crypto_op_type op;

> -	/**< Operation type */

> +	/**< Operation type: symmetric/asymmetric */

> 

>  	RTE_STD_C11

>  	union {

>  		struct rte_cryptodev_symmetric_capability sym;

>  		/**< Symmetric operation capability parameters */

> +		struct rte_cryptodev_asymmetric_capability asym;

> +		/**< Asymmetric operation capability parameters */

>  	};

>  };

> 

> @@ -201,7 +227,17 @@ struct rte_cryptodev_sym_capability_idx {

>  };

> 

>  /**

> - *  Provide capabilities available for defined device and algorithm

> + * Structure used to describe asymmetric crypto xforms

> + * Each xform maps to one asym algorithm.

> + *

> + */

> +struct rte_cryptodev_asym_capability_idx {

> +	enum rte_crypto_asym_xform_type type;

> +	/**< Asymmetric xform (algo) type */

> +};

> +

> +/**

> + * Provide capabilities available for defined device and algorithm

>   *

>   * @param	dev_id		The identifier of the device.

>   * @param	idx		Description of crypto algorithms.

> @@ -215,6 +251,20 @@ struct rte_cryptodev_sym_capability_idx {

>  		const struct rte_cryptodev_sym_capability_idx *idx);

> 

>  /**

> + *  Provide capabilities available for defined device and algorithm

> + *

> + * @param	dev_id		The identifier of the device.

> + * @param	algo		Description of crypto algorithms.

> + *

> + * @return

> + *   - Return description of the asymmetric crypto capability if exist.

> + *   - Return NULL if the capability not exist.

> + */

> +const struct rte_cryptodev_asymmetric_capability *

> +rte_cryptodev_asym_capability_get(uint8_t dev_id,

> +		const struct rte_cryptodev_asym_capability_idx *idx);

> +

> +/**

>   * Check if key size and initial vector are supported

>   * in crypto cipher capability

>   *

> @@ -270,6 +320,21 @@ struct rte_cryptodev_sym_capability_idx {

>  		uint16_t iv_size);

> 

>  /**

> + * Check if modulus length is in supported range

> + *

> + * @param	capability	Description of the asymmetric crypto capability.

> + * @param	modlen		modulus length.

> + *

> + * @return

> + *   - Return 0 if the parameters are in range of the capability.

> + *   - Return -1 if the parameters are out of range of the capability.

> + */

> +int

> +rte_cryptodev_asym_capability_check_modlen(

> +		const struct rte_cryptodev_asymmetric_capability *capability,

> +		uint16_t modlen);

> +

> +/**

>   * Provide the cipher algorithm enum, given an algorithm string

>   *

>   * @param	algo_enum	A pointer to the cipher algorithm

> @@ -314,6 +379,22 @@ struct rte_cryptodev_sym_capability_idx {

>  rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,

>  		const char *algo_string);

> 

> +/**

> + * Provide the Asymmetric xform enum, given an xform string

> + *

> + * @param	xform_enum	A pointer to the xform type

> + *				enum to be filled

> + * @param	xform_string	xform string

> + *

> + * @return

> + * - Return -1 if string is not valid

> + * - Return 0 is the string is valid

> + */

> +int

> +rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,

> +		const char *xform_string);

> +

> +

>  /** Macro used at end of crypto PMD list */

>  #define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \

>  	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }

> @@ -379,16 +460,99 @@ struct rte_cryptodev_info {

>  	/**< Array of devices supported capabilities */

> 

>  	unsigned max_nb_queue_pairs;

> -	/**< Maximum number of queues pairs supported by device. */

> +	/**< Maximum number of queues pairs supported by device.

> +	 *

> +	 * This is total number of queues supported by device and inclusive

> +	 * of numbers used for both symmetric and asymmetric for PMD that

> +	 * support symmetric and asymmetric op i.e.

> +	 *

> +	 * max_nb_queue_pairs = max_nb_symm_qp + max_nb_asymm_qp

> +	 *

> +	 * Following table demonstarte what the values should be for device

> +	 * with max num of 'n' queue pair (x = don't care):

> +	 *

> +	 *  -------------------------------------------------------------------

> +	 * |dev_capa                | max_nb_asymm_qp| max_nb_symm_qp | max_qp|

> +	 *  -------------------------------------------------------------------

> +	 * | Symm only              |    x           | 0              | n     |

> +	 * | Asymm only             |    0           | x              | n     |

> +	 * | symm+asymm w/ fixed qp |    p           | n-p            | n     |

> +	 * | symm+asymm w/ all qp   |    0           | 0              | n     |

> +	 *  -------------------------------------------------------------------

> +	 *

> +	 * - if device supports only asymmetric, then max_nb_queue_pair

> +	 *   indicates max qp available for asymmetric operations.

> +	 *

> +	 * - if device support only symmetric, then max_nb_queue_pair

> +	 *   indicates max qp available for symmetric operations.

> +	 *

> +	 * - if device support both symmetric and asymmetric crypto op,

> +	 *   then max_nb_queue_pair indicates total number of available

> +	 *   qp for both operations.

> +	 *

> +	 * **Special note on devices supporting symm and asymm:

> +	 *

> +	 * Such dual function devices may manage qp in various possible ways.

> +	 * They can either:

> +	 *

> +	 * 1. Use all max_nb_queue_pair for any operation type.

> +	 *    In such case, app can configure any of the available qp

> +	 *    for any operaiton. Thus,

> +	 *    dev_info should return num queue pair distribution as mentioned

> +	 *    in row 'symm+asymm w/ all qp' in table above

> +	 *

> +	 * 2. Or, use dedicated set of qp for each op

> +	 *    Such device PMDs, can take 2 approaches:

> +	 *    1. Either, it can show up as 2 separate PMDs where one as

> +	 *	 symmetric only and other asymmetric only. in such case,

> +	 *	 device info will return num queue pair distribution as

> +	 *	 mentioned in row 'symmetric/asymmetric only' device

> +	 *

> +	 *    2. Or, can appear as one PMD with number of queue pair dedicated

> +	 *	 to each operation in max_nb_symm_qp and max_nb_asymm_qp

> +	 *

> +	 */

> 

>  	struct {

>  		unsigned max_nb_sessions;

> -		/**< Maximum number of sessions supported by device. */

> +		/**< Maximum number of sessions supported

> +		 * for symmetric operations.

> +		 */

>  		unsigned int max_nb_sessions_per_qp;

> -		/**< Maximum number of sessions per queue pair.

> +		/**< Maximum number of symmetric sessions

> +		 * per queue pair.

>  		 * Default 0 for infinite sessions

>  		 */

> +		 unsigned int max_nb_sym_qp;

> +		/**< Maximum num of qp dedicated to symmetric op.

> +		 * NA for device that support symmetric only.

> +		 * 0 means device can use all max_nb_queue_pair

> +		 * for symm op.

> +		 * Please note, this variable only tells number of queue pairs

> +		 * that can be enqueued with symmetric ops and doesn't reveal

> +		 * specific IDs used by PMDs for this operation

> +		 *

> +		 */

>  	} sym;

> +

> +	struct {

> +		unsigned int max_nb_asym_sessions;

> +		/**< Maximum number of asymmetric sessions supported by device.

> +		 * 0 infinite as long as resources are available

> +		 */

> +		unsigned int max_nb_asym_sessions_per_qp;

> +		/**< Maximum number of asymmetric sessions per queue pair.

> +		 * 0 means infinite as long as resources are available

> +		 */

> +		unsigned int max_nb_asym_qp;

> +		/**< Maximum number of qp dedicated for asymm operation.

> +		 * 0 means device can use all max_nb_queue_pair for asymm op.

> +		 * Please note, this variable only tells number of queue pairs

> +		 * that can be enqueued with asymmetric ops and doesn't reveal

> +		 * specific IDs used by PMDs for this operation

> +		 *

> +		 */

> +	} asym;

>  };

> 

>  #define RTE_CRYPTODEV_DETACHED  (0)

> @@ -513,6 +677,24 @@ struct rte_cryptodev_config {

>  	int socket_id;			/**< Socket to allocate resources on */

>  	uint16_t nb_queue_pairs;

>  	/**< Number of queue pairs to configure on device */

> +

> +	uint16_t nb_symm_qp;

> +	/**< Number of queue pair to be used for symmetric operations.

> +	 * Optional input.

> +	 * Valid for device supporting both symmetric and asymmetric.

> +	 * Should be less than equal to rte_cryptodev_info:max_nb_symm_qp.

> +	 * please note this number only tells how many queue pair to be used

> +	 * for symmetric op and does *not* tell specific IDs to be used.

> +	 */

> +

> +	uint16_t nb_asymm_qp;

> +	/**< Number of queue pair to be used for asymmetric operations.

> +	 * Optional input.

> +	 * Valid for device supporting both asymmetric and symmetric.

> +	 * Should be less than equal to rte_cryptodev_info:max_nb_asymm_qp

> +	 * Please note this number only tells how many queue pair to be

> +	 * used for asymmetric and does *not* specifically tell qp ID

> +	 */

>  };

> 

[Fiona] The params from config structure above should be used to set the values in the data structure
This code is missing.

>  /**

> @@ -595,6 +777,9 @@ struct rte_cryptodev_config {

>   * @return

>   *   - 0: Success, queue pair correctly set up.

>   *   - <0: Queue pair configuration failed

> + *

> + * @note: queue pair to be setup independent of operation type.

> + *

>   */

>  extern int

>  rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,

> @@ -644,6 +829,26 @@ struct rte_cryptodev_config {

>  extern uint16_t

>  rte_cryptodev_queue_pair_count(uint8_t dev_id);

> 

> +/**

> + * Get the number of symmetric queue pairs on this crypto device

> + *

> + * @param	dev_id		Crypto device identifier.

> + * @return

> + *   - The number of configured symmetric queue pairs.

> + */

> +extern uint16_t

> +rte_cryptodev_sym_queue_pair_count(uint8_t dev_id);

> +

> +

> +/**

> + * Get the number of asymmetric queue pairs on this crypto device

> + *

> + * @param	dev_id		Crypto device identifier.

> + * @return

> + *   - The number of configured asymmetric queue pairs.

> + */

> +extern uint16_t

> +rte_cryptodev_asym_queue_pair_count(uint8_t dev_id);

> 

>  /**

>   * Retrieve the general I/O statistics of a device.

> @@ -795,6 +1000,10 @@ struct rte_cryptodev_data {

>  	/**< Array of pointers to queue pairs. */

>  	uint16_t nb_queue_pairs;

>  	/**< Number of device queue pairs. */

> +	uint16_t nb_sym_qp;

> +	/**< Number of symmetric queue pairs. */

> +	uint16_t nb_asym_qp;

> +	/**< Number of asymmetric queue pairs. */

> 

>  	void *dev_private;

>  	/**< PMD-specific private data */

> @@ -900,6 +1109,11 @@ struct rte_cryptodev_sym_session {

>  	/**< Private session material */

>  };

> 

> +/** Cryptodev asymmetric crypto session */

> +struct rte_cryptodev_asym_session {

> +	__extension__ void *sess_private_data[0];

> +	/**< Private asymmetric session material */

> +};

> 

>  /**

>   * Create symmetric crypto session header (generic with no private data)

> @@ -914,6 +1128,18 @@ struct rte_cryptodev_sym_session *

>  rte_cryptodev_sym_session_create(struct rte_mempool *mempool);

> 

>  /**

> + * Create asymmetric crypto session header (generic with no private data)

> + *

> + * @param   mempool    mempool to allocate asymmetric session

> + *                     objects from

> + * @return

> + *  - On success return pointer to asym-session

> + *  - On failure returns NULL

> + */

> +struct rte_cryptodev_asym_session *

> +rte_cryptodev_asym_session_create(struct rte_mempool *mempool);

> +

> +/**

>   * Frees symmetric crypto session header, after checking that all

>   * the device private data has been freed, returning it

>   * to its original mempool.

> @@ -929,6 +1155,21 @@ struct rte_cryptodev_sym_session *

>  rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess);

> 

>  /**

> + * Frees asymmetric crypto session header, after checking that all

> + * the device private data has been freed, returning it

> + * to its original mempool.

> + *

> + * @param   sess     Session header to be freed.

> + *

> + * @return

> + *  - 0 if successful.

> + *  - -EINVAL if session is NULL.

> + *  - -EBUSY if not all device private data has been freed.

> + */

> +int

> +rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess);

> +

> +/**

>   * Fill out private data for the device id, based on its device type.

>   *

>   * @param   dev_id   ID of device that we want the session to be used on

> @@ -950,6 +1191,27 @@ struct rte_cryptodev_sym_session *

>  			struct rte_mempool *mempool);

> 

>  /**

> + * Initialize asymmetric session on a device with specific asymmetric xform

> + *

> + * @param   dev_id   ID of device that we want the session to be used on

> + * @param   sess     Session to be set up on a device

> + * @param   xforms   Asymmetric crypto transform operations to apply on flow

> + *                   processed with this session

> + * @param   mempool  Mempool to be used for internal allocation.

> + *

> + * @return

> + *  - On success, zero.

> + *  - -EINVAL if input parameters are invalid.

> + *  - -ENOTSUP if crypto device does not support the crypto transform.

> + *  - -ENOMEM if the private session could not be allocated.

> + */

> +int

> +rte_cryptodev_asym_session_init(uint8_t dev_id,

> +			struct rte_cryptodev_asym_session *sess,

> +			struct rte_crypto_asym_xform *xforms,

> +			struct rte_mempool *mempool);

> +

> +/**

>   * Frees private data for the device id, based on its device type,

>   * returning it to its mempool.

>   *

> @@ -965,7 +1227,23 @@ struct rte_cryptodev_sym_session *

>  			struct rte_cryptodev_sym_session *sess);

> 

>  /**

> + * Frees resources held by asymmetric session during rte_cryptodev_session_init

> + *

> + * @param   dev_id   ID of device that uses the asymmetric session.

> + * @param   sess     Asymmetric session setup on device using

> + *					 rte_cryptodev_session_init

> + * @return

> + *  - 0 if successful.

> + *  - -EINVAL if device is invalid or session is NULL.

> + */

> +int

> +rte_cryptodev_asym_session_clear(uint8_t dev_id,

> +			struct rte_cryptodev_asym_session *sess);

> +

> +/**

>   * Get the size of the header session, for all registered drivers.

> + * For devices supporting both symmetric and asymmetric, it should

> + * return header size inclusive of both

[Fiona] ? This API is not called on a device.
As the hdr size is just a list of pointers, it's independent of sym/asym

>   *

>   * @return

>   *   Size of the header session.

> @@ -975,6 +1253,8 @@ struct rte_cryptodev_sym_session *

> 

>  /**

>   * Get the size of the private session data for a device.

> + * if device support both symmetric and asymmetric, it

> + * return size inclusive of both

[Fiona] Are you suggesting the same session pool might be used
for both sym and asym sessions?
Seems unlikely, but if an application chose to, it seems better
 that it would do it explicitly,
e.g. get asym and sym private sizes, same as it gets size from the other 
drivers and sizes for the maximum.
If meaning is changed as you suggest then sym applications already
implemented will likely end up with pools sized for a session size they don’t need.

As I think the combined pool case unlikely, it makes more sense to me that this
fn should have comment changed to say it returns only sym session size
for backwards capability reasons, but will be deprecated
and appls should use get_sym_session_private_size instead.

>   *

>   * @param	dev_id		The device identifier.

>   *

> @@ -986,6 +1266,32 @@ struct rte_cryptodev_sym_session *

>  rte_cryptodev_get_private_session_size(uint8_t dev_id);

> 

>  /**

> + * Get the size of the private data for symmetric session

> + * on device

> + *

> + * @param	dev_id		The device identifier.

> + *

> + * @return

> + *   - Size of the symmetric session private data, if successful

> + *   - 0 if device is invalid or does not have private session

> + */

> +unsigned int

> +rte_cryptodev_get_sym_session_private_size(uint8_t dev_id);

> +

> +/**

> + * Get the size of the private data for asymmetric session

> + * on device

> + *

> + * @param	dev_id		The device identifier.

> + *

> + * @return

> + *   - Size of the asymmetric private data, if successful

> + *   - 0 if device is invalid or does not have private session

> + */

> +unsigned int

> +rte_cryptodev_get_asym_session_private_size(uint8_t dev_id);

> +

> +/**

>   * Attach queue pair with sym session.

>   *

>   * @param	dev_id		Device to which the session will be attached.

> @@ -1002,6 +1308,31 @@ struct rte_cryptodev_sym_session *

>  		struct rte_cryptodev_sym_session *session);

> 

>  /**

> + * Attach queue pair with asym session.

> + *

> + * @param	dev_id		Device to which the session is attached.

> + * @param	qp_id		Queue pair to which the session will be

> + *				attached.

> + * @param	session		Asymmetric Session pointer previously

> + *				allocated by

> + *				*rte_cryptodev_asym_session_create*.

> + *

> + * @return

> + *  - On success, zero.

> + *  - On failure, a negative value.

> + *

> + * @note : app can dedicate a qp_id to specific operation type:symm/asymm

> + * by calling rte_cryptodev_queue_pair_attach_sym/asym_session() before

> + * enqueue_burst() call. PMD with SYMMETRIC & ASYMMETRIC feature flag set,

> + * can internally bind the logical qp_id to actual physical qp_id here and

> + * dedicate specific qp_id to perform specific op_type(symmetric or

> + * asymmetric).

> + */

> +int

> +rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,

> +		struct rte_cryptodev_asym_session *session);

> +

> +/**

>   * Detach queue pair with sym session.

>   *

>   * @param	dev_id		Device to which the session is attached.

> @@ -1018,6 +1349,23 @@ struct rte_cryptodev_sym_session *

>  		struct rte_cryptodev_sym_session *session);

> 

>  /**

> + * Detach queue pair from asym session.

> + *

> + * @param	dev_id		Device to which the session is attached.

> + * @param	qp_id		Queue pair to which the session is attached.

> + * @param	session		Asymmetric Session pointer previously attached

> + *				by calling

> + *				*rte_cryptodev_queue_pair_attach_asym_session*.

> + *

> + * @return

> + *  - On success, zero.

> + *  - On failure, a negative value.

> + */

> +int

> +rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,

> +		struct rte_cryptodev_asym_session *session);

> +

> +/**

>   * Provide driver identifier.

>   *

>   * @param name

> diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.c b/lib/librte_cryptodev/rte_cryptodev_pmd.c

> index f2aac24..4439a8e 100644

> --- a/lib/librte_cryptodev/rte_cryptodev_pmd.c

> +++ b/lib/librte_cryptodev/rte_cryptodev_pmd.c

> @@ -66,6 +66,20 @@

>  			goto free_kvlist;

> 

>  		ret = rte_kvargs_process(kvlist,

> +				RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,

> +				&rte_cryptodev_pmd_parse_uint_arg,

> +				&params->max_nb_asym_qp);

> +		if (ret < 0)

> +			goto free_kvlist;

> +

> +		ret = rte_kvargs_process(kvlist,

> +				RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG,

> +				&rte_cryptodev_pmd_parse_uint_arg,

> +				&params->max_nb_sym_qp);

> +		if (ret < 0)

> +			goto free_kvlist;

> +

[Fiona] "max_nb_queue_pair" is passed in to args and parsed. Stored in init_params,
passed to device creation. And then ignored, not used at all. So no need to add new 
max_nb_asym_qp and max_nb_sym_qp to either args or init_params. They're not
used either in this RFC.
We should deprecate the current param from args and init_params.

PMDs hardcode the value they return in rte_cryptodev_info.
> +		ret = rte_kvargs_process(kvlist,

>  				RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,

>  				&rte_cryptodev_pmd_parse_uint_arg,

>  				&params->max_nb_sessions);

> @@ -109,9 +123,12 @@ struct rte_cryptodev *

>  			device->driver->name, name);

> 

>  	CDEV_LOG_INFO("[%s] - Initialisation parameters - name: %s,"

> -			"socket id: %d, max queue pairs: %u, max sessions: %u",

> +			"socket id: %d, max queue pairs: %u, "

> +			"max sym queue paid: %u, max asym queue pair %u, "

> +			"max sessions: %u",

>  			device->driver->name, name,

>  			params->socket_id, params->max_nb_queue_pairs,

> +			params->max_nb_asym_qp, params->max_nb_sym_qp,

>  			params->max_nb_sessions);

> 

>  	/* allocate device structure */

> diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h

> index 089848e..272b489 100644

> --- a/lib/librte_cryptodev/rte_cryptodev_pmd.h

> +++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h

> @@ -60,18 +60,25 @@

> 

>  #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS	8

>  #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SESSIONS	2048

> +/* Allow all qp to be used for sym */

> +#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SYM_QP		0

> +/* Allow all qp to be used for asym */

> +#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_ASYM_QP	0

> 

>  #define RTE_CRYPTODEV_PMD_NAME_ARG			("name")

>  #define RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG			("max_nb_queue_pairs")

>  #define RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG		("max_nb_sessions")

>  #define RTE_CRYPTODEV_PMD_SOCKET_ID_ARG			("socket_id")

> -

> +#define RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG		("max_nb_asym_qp")

> +#define RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG		("max_nb_sym_qp")

> 

>  static const char * const cryptodev_pmd_valid_params[] = {

>  	RTE_CRYPTODEV_PMD_NAME_ARG,

>  	RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,

>  	RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,

> -	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG

> +	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,

> +	RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,

> +	RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG

>  };

> 

>  /**

> @@ -84,6 +91,10 @@ struct rte_cryptodev_pmd_init_params {

>  	int socket_id;

>  	unsigned int max_nb_queue_pairs;

>  	unsigned int max_nb_sessions;

> +	unsigned int max_nb_asym_qp;

> +	/**< maximum number of qp to be used for asymmetric ops */

> +	unsigned int max_nb_sym_qp;

> +	/**< maximum number of qp to be used for symmetric ops */

>  };

> 

>  /** Global structure used for maintaining state of allocated crypto devices */

> @@ -275,7 +286,29 @@ typedef int (*cryptodev_queue_pair_release_t)(struct rte_cryptodev *dev,

>  typedef uint32_t (*cryptodev_queue_pair_count_t)(struct rte_cryptodev *dev);

> 

>  /**

> - * Create a session mempool to allocate sessions from

> + * Get number of available symmetric queue pairs of a device.

> + *

> + * @param	dev	Crypto device pointer

> + *

> + * @return

> + * - Returns number of symmetric queue pairs

> + */

> +typedef uint32_t (*cryptodev_sym_queue_pair_count_t)(

> +			struct rte_cryptodev *dev);

> +

> +/**

> + * Get number of available asymmetric queue pairs of a device.

> + *

> + * @param	dev	Crypto device pointer

> + *

> + * @return

> + * - Returns number of symmetric queue pairs

> + */

> +typedef uint32_t (*cryptodev_asym_queue_pair_count_t)(

> +			struct rte_cryptodev *dev);

> +

[Fiona] Is something calling either of above fns? If not better to remove the asym one.
The sym one should be deprecated and removed in a separate patch. 

> +/**

> + * Create a symmetric session mempool to allocate sessions from

>   *

>   * @param	dev		Crypto device pointer

>   * @param	nb_objs		number of sessions objects in mempool

> @@ -290,6 +323,21 @@ typedef int (*cryptodev_sym_create_session_pool_t)(

>  		struct rte_cryptodev *dev, unsigned nb_objs,

>  		unsigned obj_cache_size, int socket_id);

> 

> +/**

> + * Create a asymmetric session mempool to allocate sessions from

> + *

> + * @param	dev		Crypto device pointer

> + * @param	nb_objs		Number of asymmetric sessions objects in mempool

> + * @param	obj_cache	l-core object cache size, see *rte_ring_create*

> + * @param	socket_id	Socket Id to allocate  mempool on.

> + *

> + * @return

> + * - On success returns a pointer to a rte_mempool

> + * - On failure returns a NULL pointer

> + */

> +typedef int (*cryptodev_asym_create_session_pool_t)(

> +		struct rte_cryptodev *dev, unsigned nb_objs,

> +		unsigned obj_cache_size, int socket_id);

> 

[Fiona] session pools are not created now per device so this is never called for sym and 
should be deprecated. So no need to add for asym
 
>  /**

>   * Get the size of a cryptodev session

> @@ -302,6 +350,17 @@ typedef int (*cryptodev_sym_create_session_pool_t)(

>   */

>  typedef unsigned (*cryptodev_sym_get_session_private_size_t)(

>  		struct rte_cryptodev *dev);

> +/**

> + * Get the size of a asymmetric cryptodev session

> + *

> + * @param	dev		Crypto device pointer

> + *

> + * @return

> + *  - On success returns the size of the session structure for device

> + *  - On failure returns 0

> + */

> +typedef unsigned (*cryptodev_asym_get_session_private_size_t)(

> +		struct rte_cryptodev *dev);

> 

>  /**

>   * Configure a Crypto session on a device.

> @@ -321,7 +380,24 @@ typedef int (*cryptodev_sym_configure_session_t)(struct rte_cryptodev *dev,

>  		struct rte_crypto_sym_xform *xform,

>  		struct rte_cryptodev_sym_session *session,

>  		struct rte_mempool *mp);

> -

> +/**

> + * Configure a Crypto asymmetric session on a device.

> + *

> + * @param	dev		Crypto device pointer

> + * @param	xform		Single or chain of crypto xforms

> + * @param	priv_sess	Pointer to cryptodev's private session structure

> + * @param	mp		Mempool where the private session is allocated

> + *

> + * @return

> + *  - Returns 0 if private session structure have been created successfully.

> + *  - Returns -EINVAL if input parameters are invalid.

> + *  - Returns -ENOTSUP if crypto device does not support the crypto transform.

> + *  - Returns -ENOMEM if the private session could not be allocated.

> + */

> +typedef int (*cryptodev_asym_configure_session_t)(struct rte_cryptodev *dev,

> +		struct rte_crypto_asym_xform *xform,

> +		struct rte_cryptodev_asym_session *session,

> +		struct rte_mempool *mp);

>  /**

>   * Free driver private session data.

>   *

> @@ -332,6 +408,15 @@ typedef void (*cryptodev_sym_free_session_t)(struct rte_cryptodev *dev,

>  		struct rte_cryptodev_sym_session *sess);

> 

>  /**

> + * Free asymmetric session private data.

> + *

> + * @param	dev		Crypto device pointer

> + * @param	sess		Cryptodev session structure

> + */

> +typedef void (*cryptodev_asym_free_session_t)(struct rte_cryptodev *dev,

> +		struct rte_cryptodev_asym_session *sess);

> +

> +/**

>   * Optional API for drivers to attach sessions with queue pair.

>   * @param	dev		Crypto device pointer

>   * @param	qp_id		queue pair id for attaching session

> @@ -343,6 +428,18 @@ typedef int (*cryptodev_sym_queue_pair_attach_session_t)(

>  		  struct rte_cryptodev *dev,

>  		  uint16_t qp_id,

>  		  void *session_private);

> +/**

> + * Optional API for drivers to attach asymmetric session with queue pair.

> + * @param	dev		Crypto device pointer

> + * @param	qp_id		Queue pair id for attaching session

> + * @param	priv_sess       Pointer to cryptodev's private session structure

> + * @return

> + *  - Return 0 on success

> + */

> +typedef int (*cryptodev_asym_queue_pair_attach_session_t)(

> +		  struct rte_cryptodev *dev,

> +		  uint16_t qp_id,

> +		  void *session_private);

> 

>  /**

>   * Optional API for drivers to detach sessions from queue pair.

> @@ -357,6 +454,19 @@ typedef int (*cryptodev_sym_queue_pair_detach_session_t)(

>  		  uint16_t qp_id,

>  		  void *session_private);

> 

> +/**

> + * Optional API for drivers to detach asymmetric session from queue pair.

> + * @param	dev		Crypto device pointer

> + * @param	qp_id		queue pair id for detaching session

> + * @param	priv_sess       Pointer to cryptodev's private session structure

> + * @return

> + *  - Return 0 on success

> + */

> +typedef int (*cryptodev_asym_queue_pair_detach_session_t)(

> +		  struct rte_cryptodev *dev,

> +		  uint16_t qp_id,

> +		  void *session_private);

> +

>  /** Crypto device operations function pointer table */

>  struct rte_cryptodev_ops {

>  	cryptodev_configure_t dev_configure;	/**< Configure device. */

> @@ -380,17 +490,32 @@ struct rte_cryptodev_ops {

>  	cryptodev_queue_pair_stop_t queue_pair_stop;

>  	/**< Stop a queue pair. */

>  	cryptodev_queue_pair_count_t queue_pair_count;

> -	/**< Get count of the queue pairs. */

> -

> +	/**< Get total count of the queue pairs(symmetric+asymmetric). */

> +	cryptodev_sym_queue_pair_count_t sym_queue_pair_count;

> +	/**< Get count of the symmetric queue pairs. */

> +	cryptodev_asym_queue_pair_count_t asym_queue_pair_count;

> +	/**< Get count of the asymmetric queue pairs. */

>  	cryptodev_sym_get_session_private_size_t session_get_size;

> -	/**< Return private session. */

> +	/**< Return private size for a session */

> +	cryptodev_sym_get_session_private_size_t sym_session_get_size;

> +	/**< Return private size for symmetric crypto. */

> +	cryptodev_sym_get_session_private_size_t asym_session_get_size;

> +	/**< Return private size for asymmetric crypto. */

>  	cryptodev_sym_configure_session_t session_configure;

>  	/**< Configure a Crypto session. */

[Fiona] This should really be renamed sym_session_configure, same for session_clear,
qp_attach_session and qp_detach_session

> +	cryptodev_asym_configure_session_t asym_session_configure;

> +	/**< Configure asymmetric Crypto session. */

>  	cryptodev_sym_free_session_t session_clear;

>  	/**< Clear a Crypto sessions private data. */

> +	cryptodev_asym_free_session_t asym_session_clear;

> +	/**< Clear a Crypto sessions private data. */

>  	cryptodev_sym_queue_pair_attach_session_t qp_attach_session;

>  	/**< Attach session to queue pair. */

> -	cryptodev_sym_queue_pair_detach_session_t qp_detach_session;

> +	cryptodev_asym_queue_pair_attach_session_t asym_qp_attach_session;

> +	/**< Attach asymmetric session to queue pair. */

> +	cryptodev_sym_queue_pair_attach_session_t qp_detach_session;

> +	/**< Detach session from queue pair. */

[Fiona] typo (based on a typo I think was fixed in a recent patch)
> +	cryptodev_asym_queue_pair_attach_session_t asym_qp_detach_session;

>  	/**< Detach session from queue pair. */

>  };

> 

> @@ -535,6 +660,19 @@ uint8_t rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,

>  	sess->sess_private_data[driver_id] = private_data;

>  }

> 

> +static inline void *

> +get_asym_session_private_data(const struct rte_cryptodev_asym_session *sess,

> +		uint8_t driver_id) {

> +	return sess->sess_private_data[driver_id];

> +}

> +

> +static inline void

> +set_asym_session_private_data(struct rte_cryptodev_asym_session *sess,

> +		uint8_t driver_id, void *private_data)

> +{

> +	sess->sess_private_data[driver_id] = private_data;

> +}

> +

>  #ifdef __cplusplus

>  }

>  #endif

> diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map

> b/lib/librte_cryptodev/rte_cryptodev_version.map

> index eb47308..323294a 100644

> --- a/lib/librte_cryptodev/rte_cryptodev_version.map

> +++ b/lib/librte_cryptodev/rte_cryptodev_version.map

> @@ -85,3 +85,24 @@ DPDK_17.11 {

>  	rte_cryptodev_pmd_parse_input_args;

> 

>  } DPDK_17.08;

> +

> +EXPERIMENTAL {

> +	global:

> +

[Fiona] the implementation of all these APIs also needs the _experimental tag.

> +	rte_cryptodev_asym_capability_get;

> +	rte_cryptodev_asym_capability_modlen;

> +	rte_cryptodev_asym_queue_pair_count;

> +	rte_cryptodev_asym_session_create;

> +	rte_cryptodev_asym_session_clear;

> +	rte_cryptodev_asym_session_free;

> +	rte_cryptodev_asym_session_init;

> +	rte_cryptodev_get_asym_session_private_size;

> +	rte_cryptodev_get_sym_session_private_size;

> +	rte_cryptodev_get_xform_algo_enum;

> +	rte_cryptodev_queue_pair_attach_asym_session;

> +	rte_cryptodev_queue_pair_detach_asym_session;

> +	rte_cryptodev_sym_queue_pair_count;

> +	rte_crypto_asym_xform_strings;

> +	rte_crypto_asym_operation_strings;

> +

> +};

> --

> 1.9.1
  
Verma, Shally Feb. 15, 2018, 5:32 a.m. UTC | #2
HI Fiona

Thanks for your feedback. Response below.

>-----Original Message-----

>From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

>Sent: 09 February 2018 23:43

>To: dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>; Murthy, Nidadavolu

><Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish <Ashish.Gupta@cavium.com>; Verma,

>Shally <Shally.Verma@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>;

>Griffin, John <john.griffin@intel.com>

>Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

>Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>

>Hi Shally,

>Comments below.

>

>> -----Original Message-----

>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

>> Sent: Tuesday, January 23, 2018 9:54 AM

>> To: Doherty, Declan <declan.doherty@intel.com>

>> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

>> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

>> <sverma@caviumnetworks.com>

>> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>>

>> From: Shally Verma <sverma@caviumnetworks.com>

>>

>> Add support for asymmetric crypto operations in DPDK lib cryptodev

>>

>> Key feature include:

>> - Only session based asymmetric crypto operations

>> - new get and set APIs for symmetric and asymmetric session private

>>   data and other informations

>> - APIs to create, configure and attch queue pair to asymmetric sessions

>> - new capabilities in struct device_info to indicate

>>   -- number of dedicated queue pairs available for symmetric and

>>      asymmetric operations, if any

>>   -- number of asymmetric sessions possible per qp

>>

>[Fiona] Though it's probably premature to include on the API have you considered

>providing for pre-loaded keys in future, i.e. the ability to wrap keys or refer to keys

>already stored securely on the device, as an alternative to passing the keys on the API?

>

[Shally] Current intention of DPDK asym spec is to expose HW capabilities to application to offload these compute intensive ops. 
Though your use-case is very much a practical requirement , but to achieve this I believe we need a layer above this spec and need different interfaces. Such as, some public/secure key library which provide interfaces to generate / store/ perform op using an opaque key handles which internally can use DPDK to do part of it. For such case, I envision dpdk (or library above) will likely run on some secure processor. Thus, currently I kept such use-case out of current spec scope.

>

>> Proposed asymmetric cryptographic operations are:

>> - rsa

>> - dsa

>> - deffie-hellman key pair generation and shared key computation

>> - ecdeffie-hellman

>> - fundamental elliptic curve operations

>> - elliptic curve DSA

>> - modular exponentiation and inversion

>>

>> This patch primarily defines PMD operations and device capabilities

>> to perform asymmetric crypto ops on queue pairs and intend to

>> invite feedbacks on current proposal so as to ensure it encompass

>> all kind of crypto devices with different capabilities and queue

>> pair management.

>>

>> List of TBDs:

>> - Currently, patch only updated for RSA xform and associated params.

>>   Other algoritms to be added in subsequent versions.

>> - per-service stats update

>>

>> Signed-off-by: Shally Verma <sverma@caviumnetworks.com>

>> ---

>>

>> It is derivative of RFC v2 asymmetric crypto patch series initiated by

>> Umesh Kartha(mailto:umesh.kartha@caviumnetworks.com):

>>

>>  http://dpdk.org/dev/patchwork/patch/24245/

>>  http://dpdk.org/dev/patchwork/patch/24246/

>>  http://dpdk.org/dev/patchwork/patch/24247/

>>

>> And inclusive of all review comments given on RFC v2.

>>  ( See complete discussion thread here:

>> http://dev.dpdk.narkive.com/yqTFFLHw/dpdk-dev-rfc-specifications-for-asymmetric-crypto-

>> algorithms#post12)

>>

>> Some of the RFCv2 Review comments pending for closure:

>> > " [Fiona] The count fn isn't used at all for sym - probably no need to add for asym

>>      better instead to remove the sym fn."

>>

>>      It is still present in dpdk-next-crypto for sym, so what has been decision

>>      on it?

>[Fiona] No change. The rte_cryptodev_ops fn is still not called so useless and should be removed.

>rte_cryptodev_queue_pair_count() returns the num_qps configured in

>rte_cryptodev_configure(), but never calls the PMD dev_ops.queue_pair_count().

>So cryptodev_sym_queue_pair_count_t should be deprecated.

>And no point in adding one for asym.

>


[Shally] Ok

>>

>> >"[Fiona] if each qp can handle only a specific service, i.e. a subset off the capabilities

>>     Indicated by the device capability list, there's a need for a new API to query

>>     the capability of a qp."

>>

>>     Current proposal doesn’t distinguish between device capability and qp capability.

>>     It rather leave such differences handling internal to PMDs. Thus no capability

>>     or API added for qp in current version. It is subject to revisit based on review

>>     feedback on current proposal.

>[Fiona] This would not work for some devices, comments below.

>

>>

>> - Sessionless Support.

>>     Current proposal only support Session-based because:

>>      1. All one-time setup i.e.  algos and associated params, such as, public-private keys

>>         or modulus length can be done in control path using session-init API

>>      2. it’s an easier way to dedicate qp to do specific service (using queue_pair_attach())

>>         which cannot be case in sessionless

>>      3. Couldn’t find any significant advantage going sessionless way. Also existing most of PMDs are

>> session-based.

>>

>>     It could be added in subsequent versions, if requirement is identified, based on review comment

>>     on this RFC.

>[Fiona] Our preference would be for sessionless, as it would need fewer API calls (no session_create/session_clear)

>and e.g. DH and ECDH sessions are likely to be only used for a single op. However this is not a blocker for

>this API, we can POC it later and propose an extension to the API if it gives a performance improvement.

>


[Shally] You mean you recommend to have session-less support along with session-based? 

>>

>> Summary

>> -------

>>

>> This section provides an overview of key feature enabled in current specification.

>> It comprise of key design challenges as have been identified on RFCv2 and

>> summary description of new interfaces and definitions added to handle same.

>>

>> Description

>> -----------

>>

>> This API set assumes that the max_nb_queue_pairs on a

>> device can be allocated to any mix of sym or asym. Some devices

>> may have a fixed max per service. Thus, rte_cryptodev_info

>> is updated with max_sym_nb_queues and max_asym_nb_queues with rule:

>>

>> max_nb_queue_pair = max_nb_sym_qp + max_nb_asym_qp.

>>

>> If device has no restrictions on qp to be used per service, such PMDs can leave

>> max_nb_sym_qp = max_nb_asym_qp = 0. In such case, application can setup any of

>> the service upto limit defined by max_nb_queue_pair.

>[Fiona] This seems awkward if a genuine 0  e.g. An appl wants to set up a sym qp, and

>sees that max_nb_queue_pair=4. Can't trust this - needs to look deeper. Sees

>max_nb_sym_qp=0. Doesn't know if that means it can set up 4 sym qps or no qps

>until it also checks max_nb_asym_qp. If=4 then it can't set up any sym qp, if=0 it can set up 4.

>Would it be better if

>	max_nb_queue_pair = max(max_nb_sym_qp, max_nb_asym_qp).

>	max_nb_sym_qp = 0..max_nb_queue_pair

>	max_nb_asym_qp = 0..max_nb_queue_pair

>


[Shally] Ok. I can change definition to replace 0 by max num for no-limit case with slight modification  to the condition i.e.
max_nb_queue_pair >=  max(max_nb_sym_qp, max_nb_asym_qp) 

because device can have distribution of (max_nb_queue_pair, max_nb_sym_qp, max_nb_asym_qp) as (4,4,4) or (4,3,1)
where total number of qp setup by application cannot exceed max_nb_queue_pairs.

>> Here, max_nb_sym_qp and max_nb_asym_qp, if non-zero, just define limit on qp which are

>> available for each service and *are not* ids to be used during qp setup and enqueue i.e.

>> if device supports both symmetric and asymmetric with n qp, then any of them

>> can be configured for symmetric or asymmetric subject to limit defined by

>> max_nb_sym_qp and max_nb_asym_qp. For example,

>> if device has 6 queues and 5 for symmetric and 1 for asymmetric that imply

>> application can setup only 1 out of any 6 qp for asymmetric and rest for

>> symmetric.

>>

>> Additionally, application can dedicate qp to perform specific service via optional

>> queue_pair_attach_sym/asym_session() API.

>[Fiona] This is too late - some devices have qps which need to know at setup which

>service they'll be used for, as they reserve resources based on the service.

>e.g. a device reports in info that it can support qps(max 4, max_sym 2, max asym 2)

>An application just wants to use 1 sym qp and 1 asym, so configures device with

>qps(max 2, max_sym 1, max asym 1)

>Now appl calls qp_setup for qp index 0. Wants to start with running asymmetric

>service and will set up the symmetric later, maybe in a separate thread.

>Our devices need to know at setup time which service will be used on the qp.

>So haven't been given enough information to setup the qp.

>

>Even if the PMD could set up service-agnostic qps and just map later, you

>suggest the qp_attach_sym/asym_session() would be optional. How could the appl

>make the decision whether to call it or not in above case? It needs to know whether

>the created qp is agnostic or not, so a capability must be reported by the PMD.

>OR the API should not be optional, must be called for every session.

>But that's perf impacting and not helpful if a device could support service-agnostic qps.

>

>I don't have a solution for service-agnostic qps. For our devices that's not necessary.

>Is it likely that anyone wants to set up a qp to process both sym and asym ops?

>Is it sufficient to accommodate qps which can support either

>service, but one must be picked at setup after which the qp supports only that service?

>How about the following - :

> - device reports in info qps(max, max_sym, max asym) where

>	max = max(max_sym, max_asym).

>	max_sym = 0..max

>	max_asym = 0..max

>	So if a device reports 4,2,2, it has 4 total, 2 can be setup for sym, 2 for asym

>	Or if it reports 4,4,4, all 4 of them can be setup as sym or all 4 as

>	asym or a mix, but total setup can't be more than 4.

> - appl configures qps(max, max_sym, max_asym)

>	If it specifies 4,1,3 it wants to use 4 in total, 1 for sym, 3 for asym.

>	If it specifies 1,1,0 it wants to use 1 in total, 1 for sym, 0 for asym.

>	The numbers it configures must be <= those reported in info.

> - appl calls qp_setup(dev, qp, service) where service = sym or asym

>	qp index must be between 0..max-1

>	The PMD maps that index to an internal qp which can support the requested service.

>	If qp_setup is called on an index and the max configured qps have already

>	been setup for that service then the setup fails.

>In case the appl forgets which qp it set up for which service, I think it would be necessary to add a new API

>	rte_cryptodev_qp_info() which would return what service is configured on the qp

>

>If it's necessary to support service-agnostic qps, then one way would be to specify a third service above as

> - sym+asym.

>And have devices report max_sym_asym_qps?

>

>It's difficult to find a solution for this without breaking the current API - see simpler

>alternative below.

>

>> Except the ones mentioned above, specification doesn't define any restrictions on

>> enqueue/dequeue API for different crypto services. Application can enqueue both symmetric

>> and asymmetric operations to same device and qp if device info indicate support of both

>> symmetric and asymmetric and qp is not dedicated to any. However in practice, it could

>> result in head-of-line blocking due to the asym ops taking longer than the symmetric ops.

>>

>> Some HW accelerators avoid this issue by supporting sym and asym ops

>> on different qps on the same device.  Such devices can set max_nb_sym_qp and

>> max_nb_asym_qp to number of queues available for each respective service.

>>

>> This may give problem in indexing on enqueue/dequeue i.e.

>> if 2 asym qps and 2 sym qps are created on the same device,

>> the queue_pair_ids are duplicated. To handle such scenario,

>> 2 alternatives are proposed for PMD design:

>>

>> 1. Allow all qp to input any operation type virtually. Say,

>>

>>     Consider device with symmetric and asymmetric capability having

>>     max_nb_queue_pair as 6, then by design, all 6 are capable to input

>>     both op types.

>>

>>     If PMD uses fixed set of qp, then internally, can map qp id to

>>     actual physical qp id to be used according to session/op type.

>>     If such mapping is done on data path, may impact performance of PMDs.

>>     Thus, to handle such mapping out of data path, library provides an API

>>     queue_pair_attach_sym/asym_session() which facilitate application to

>>     dedicate qp id to perform specific (sym/asym) service in control path

>>     and should be called before 1st call to enqueue_burst().

>>     Here PMD can bind app provided logical qp id to actual physical qp id to use

>>     depending on session type , OR alternatively

>>

>> 2. PMDs can split it into two PMDs, one with symmetric ONLY capability and other

>>     with asymmetric ONLY capability (also proposed by Fiona in RFCv2).

>>     This may require some  changes to EAL to facilitate pci device sharing between

>>     PMDs, enabling separation of sym and  asym services onto different PMDs.

>>     As per RFCv2 feedback, Intel  proposed to submit a patch to  enable this.

>[Fiona] The eal changes were problematic, and feedback from the Dublin userspace

>event last September was that several others have tried similar but reverted to resolving

>the problem within the PMD. This is what we are also in the process of doing.

>With this we intend to avoid all the above complications.

>i.e. one pci device, in its probe fn, can create multiple API device instances.

>One instance of cryptodev will provide a sym crypto service, one instance of

>compressdev will provide a compression service and a second cryptodev instance will

>provide the asymmetric service. All qps on each API device instance can then support all

>of the capabilities reported by that device.

>

>A suggestion for keeping the simplicity on the API would be to follow the same pattern.

>i.e. don't provide any support for specification of sym or asym qps. Expect all

>qps on each device to support all capabilities reported.

>

>


[Shally] Initially I had thought of same proposal to add an input field in qp_conf so that PMD can know at qp_setup time which service it going to be used for.
However looking that spec already had qp_attach_sym/asym APIs and also the possibility that some device can support service - agnostic qp, I initiated with current proposal.
I marked them optional with a disclaimer that , if not attached, then PMD will then need to map logical qpid to physical during enqueue_burst() which might result in impacted performance. 
This is particularly applicable to devices which internally have fixed qps per each service and set max_nb_sym/asym_qp to indicate same.
And thus for such devices, I primarily recommended that they should appear as two separate PMDs where one support sym and other asym. 
However, only point to is to see how well suited is this for each device driver design as it might rather turn to be simpler for some implementation to just have single way to dedicate a qp to a service via attach or qp_setup change than having two separate instances.

But, I concur from your thoughts. We can start with simple definition and remove concept of max_nb_sym_qp and max_nb_asym_qp in first version and say 
-if device support service agnostic qp, that means all of its qp can be set up for any service. PMD can show in its feature flag support for symmetric and asymmetric crypto. Application can set up qp the way it want, spec define no recommended way of usage here 
-if device has fixed set of qp per each service, then it should split itself into two : symmetric only and asymmetric only. 

This is well suited for session-less also.  IMO, If any issues reported with these rules, then we can add this support later based on the then identified requirement. However, if we end up adding the support back of max_nb_sym/asym_qp in spec later, then attach/detach_qp APIs will not be sufficient as they are session specific. Given that, having an input param during qp_setup() is more generic way that suit both session and sessionless way. Does this all sounds right?
 
I will wait to close on this design discussion first before giving feedback to rest of the comment further below. But consider all feedback regarding typo and licensing as acknowledged.

Thanks
Shally

>> 3. Some of the other alternatives were also suggested on RFCv2 as summarised here:

>>     "[Fiona] One alternative is to use different qp_ids for sym and asym.

>>       Remove the queue_pair_id from the xxx_queue_pair_setup fns

>>       and instead return the id. So e.g. if sym_queue_pair_setup() is called, then

>>       asym_queue_pair_setup(), then sym_queue_pair_setup() qp_id 0 and 2 would be

>>       sym qps and qp_id 1 would be an asym qp. Instead of separate

>>       dev->data->asym_queue_pairs and dev->data->sym_queue_pairs arrays there

>>       would be one common array. Another alternative is to use separate APIs i.e.

>>       rte_cryptodev_sym_enqueue_burst rte_cryptodev_asym_enqueue_burst."

>>

>>      We believe eithr of above proposed 1st two solutions(against point 1 and 2) suffice to achieve purpose.

>>      Thus, we don’t realize need to change notion of qp_setup() or add new enqueue_burst() variant

>>      for asym at current stage. However it is subject to revisit, if any requirement is identified.

>>

>> ---

>>  lib/librte_cryptodev/Makefile                  |   1 +

>>  lib/librte_cryptodev/rte_crypto.h              |  39 +-

>>  lib/librte_cryptodev/rte_crypto_asym.h         | 949 +++++++++++++++++++++++++

>>  lib/librte_cryptodev/rte_cryptodev.c           | 287 ++++++++

>>  lib/librte_cryptodev/rte_cryptodev.h           | 358 +++++++++-

>>  lib/librte_cryptodev/rte_cryptodev_pmd.c       |  19 +-

>>  lib/librte_cryptodev/rte_cryptodev_pmd.h       | 154 +++-

>>  lib/librte_cryptodev/rte_cryptodev_version.map |  21 +

>>  8 files changed, 1811 insertions(+), 17 deletions(-)

>>

>> diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile

>> index bba8dee..dec325b 100644

>> --- a/lib/librte_cryptodev/Makefile

>> +++ b/lib/librte_cryptodev/Makefile

>> @@ -21,6 +21,7 @@ SRCS-y += rte_cryptodev.c rte_cryptodev_pmd.c

>>  # export include files

>>  SYMLINK-y-include += rte_crypto.h

>>  SYMLINK-y-include += rte_crypto_sym.h

>> +SYMLINK-y-include += rte_crypto_asym.h

>>  SYMLINK-y-include += rte_cryptodev.h

>>  SYMLINK-y-include += rte_cryptodev_pmd.h

>>

>> diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h

>> index 95cf861..e8c0bac 100644

>> --- a/lib/librte_cryptodev/rte_crypto.h

>> +++ b/lib/librte_cryptodev/rte_crypto.h

>> @@ -23,6 +23,7 @@

>>  #include <rte_common.h>

>>

>>  #include "rte_crypto_sym.h"

>> +#include "rte_crypto_asym.h"

>>

>>  /** Crypto operation types */

>>  enum rte_crypto_op_type {

>> @@ -30,6 +31,8 @@ enum rte_crypto_op_type {

>>  	/**< Undefined operation type */

>>  	RTE_CRYPTO_OP_TYPE_SYMMETRIC,

>>  	/**< Symmetric operation */

>> +	RTE_CRYPTO_OP_TYPE_ASYMMETRIC

>> +	/**< Asymmetric operation */

>>  };

>>

>>  /** Status of crypto operation */

>> @@ -97,6 +100,10 @@ struct rte_crypto_op {

>>  	union {

>>  		struct rte_crypto_sym_op sym[0];

>>  		/**< Symmetric operation parameters */

>> +

>> +		struct rte_crypto_asym_op asym[0];

>> +		/**< Asymmetric operation parameters */

>> +

>>  	}; /**< operation specific parameters */

>>  };

>>

>> @@ -117,6 +124,9 @@ struct rte_crypto_op {

>>  	case RTE_CRYPTO_OP_TYPE_SYMMETRIC:

>>  		__rte_crypto_sym_op_reset(op->sym);

>>  		break;

>> +	case RTE_CRYPTO_OP_TYPE_ASYMMETRIC:

>> +		__rte_crypto_asym_op_reset(op->asym);

>> +		break;

>>  	case RTE_CRYPTO_OP_TYPE_UNDEFINED:

>>  	default:

>>  		break;

>> @@ -124,7 +134,7 @@ struct rte_crypto_op {

>>  }

>>

>>  /**

>> - * Private data structure belonging to a crypto symmetric operation pool.

>> + * Private data structure belonging to a crypto operation pool.

>>   */

>>  struct rte_crypto_op_pool_private {

>>  	enum rte_crypto_op_type type;

>> @@ -283,9 +293,14 @@ struct rte_crypto_op_pool_private {

>>  	if (likely(op->mempool != NULL)) {

>>  		priv_size = __rte_crypto_op_get_priv_data_size(op->mempool);

>>

>> -		if (likely(priv_size >= size))

>> -			return (void *)((uint8_t *)(op + 1) +

>> +		if (likely(priv_size >= size)) {

>> +			if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)

>> +				return (void *)((uint8_t *)(op + 1) +

>>  					sizeof(struct rte_crypto_sym_op));

>> +			if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC)

>> +				return (void *)((uint8_t *)(op+1) +

>> +					sizeof(struct rte_crypto_asym_op));

>> +		}

>>  	}

>>

>>  	return NULL;

>> @@ -388,6 +403,24 @@ struct rte_crypto_op_pool_private {

>>  	return __rte_crypto_sym_op_attach_sym_session(op->sym, sess);

>>  }

>>

>> +/**

>> + * Attach a asymmetric session to a crypto operation

>> + *

>> + * @param	op	crypto operation, must be of type asymmetric

>> + * @param	sess	cryptodev session

>> + */

>> +static inline int

>> +rte_crypto_op_attach_asym_session(struct rte_crypto_op *op,

>> +		struct rte_cryptodev_asym_session *sess)

>> +{

>> +	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_ASYMMETRIC))

>> +		return -1;

>> +

>> +	op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;

>> +

>> +	return __rte_crypto_op_attach_asym_session(op->asym, sess);

>> +}

>> +

>>  #ifdef __cplusplus

>>  }

>>  #endif

>> diff --git a/lib/librte_cryptodev/rte_crypto_asym.h b/lib/librte_cryptodev/rte_crypto_asym.h

>> new file mode 100644

>> index 0000000..27caf55

>> --- /dev/null

>> +++ b/lib/librte_cryptodev/rte_crypto_asym.h

>> @@ -0,0 +1,949 @@

>> +/*

>> + *   BSD LICENSE

>> + *

>[Fiona] Use SPDX license

>

>> + *   Copyright (C) Cavium networks Ltd. 2017.

>> + *

>> + *   Redistribution and use in source and binary forms, with or without

>> + *   modification, are permitted provided that the following conditions

>> + *   are met:

>> + *

>> + *     * Redistributions of source code must retain the above copyright

>> + *       notice, this list of conditions and the following disclaimer.

>> + *     * Redistributions in binary form must reproduce the above copyright

>> + *       notice, this list of conditions and the following disclaimer in

>> + *       the documentation and/or other materials provided with the

>> + *       distribution.

>> + *     * Neither the name of Cavium Networks nor the names of its

>> + *       contributors may be used to endorse or promote products derived

>> + *       from this software without specific prior written permission.

>> + *

>> + *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS

>> + *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT

>> + *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR

>> + *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT

>> + *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,

>> + *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT

>> + *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,

>> + *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY

>> + *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT

>> + *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

>> + *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

>> + */

>> +

>> +#ifndef _RTE_CRYPTO_ASYM_H_

>> +#define _RTE_CRYPTO_ASYM_H_

>> +

>> +/**

>> + * @file rte_crypto_asym.h

>> + *

>> + * RTE Definitions for Asymmetric Cryptography

>> + *

>> + * Defines asymmetric algorithms and modes, as well as supported

>> + * asymmetric crypto operations.

>> + */

>> +

>> +#ifdef __cplusplus

>> +extern "C" {

>> +#endif

>> +

>> +#include <string.h>

>> +#include <stdint.h>

>> +#include <rte_mbuf.h>

>> +#include <rte_memory.h>

>> +#include <rte_mempool.h>

>> +#include <rte_common.h>

>> +

>> +typedef struct rte_crypto_xform_param_t {

>> +	uint8_t *data;

>> +	phys_addr_t phys_addr;

>[Fiona] Use iova

>

>> +	size_t length;

>> +} rte_crypto_xform_param;

>> +

>> +typedef struct rte_crypto_op_param_t {

>> +	uint8_t *data;

>> +	phys_addr_t phys_addr;

>> +	size_t length;

>> +} rte_crypto_op_param;

>> +

>[Fiona]  specify that above lengths are bytes - asym uses bit lengths in some contexts.

>Above structs are identical - why not use a single struct?

>rte_crypto_param_t

>

>mention

>> +/**

>> + * Asymmetric crypto transformation types.

>> + * Each xform type maps to one asymmetric algorithm

>> + * performing specific operation

>> + *

>> + */

>> +enum rte_crypto_asym_xform_type {

>> +	RTE_CRYPTO_ASYM_XFORM_NONE = 0,

>> +	/**< Xform type None. May be supported by

>> +	 * PMD to support passthrough op for debugging

>> +	 * purpose.

>> +	 * if xform_type none , op_type is disregarded.

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_RSA,

>> +	/**< RSA. Performs Encrypt, Decrypt, Sign and Verify

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_MODEX,

>> +	/**< Modular Exponentiation

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_DH,

>> +	/**< Deffie-Hellman. Perform Key Generate, Key Compute

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_ECDH,

>> +	/**< Elliptic Curve Deffie-Hellman.

>> +	 * Perform Key Genearate, Key Check and Key Compute

>[Fiona] typo: generate

>

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_DSA,

>> +	/**< Digital Signature Algorithm

>> +	 * Performs Signature verification and Generation

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_ECDSA,

>> +	/**< Elliptic Curve Digital Signature Algorithm.

>> +	 * Performs Signature Generation, and Verification.

>> +	 * Refer to rte_crypto_asym_op_type

>> +	 */

>[Fiona] typo in both above: Signature Generation and Verification

>

>> +	RTE_CRYPTO_ASYM_XFORM_FECC,

>> +	/**< Fundamental Elliptic curve operations.

>> +	 * Perform elliptic curve operation:

>> +	 * add, double point, multiplication

>> +	 * Refer to enum rte_crypto_fecc_optype

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_MODINV,

>> +	/**< Modular Inverse */

>[Fiona] would be nicer to group modinv with modexp

>

>> +	RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END

>> +	/**< End of list */

>> +};

>> +

>> +/**

>> + * Asymmetric cryptogr operation type variants

>[Fiona] typo: Use crypto or cryptographic

>

>> + */

>> +enum rte_crypto_asym_op_type {

>> +	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,

>[Fiona] Why does this start at 1?

>And is it necessary?

>

>> +	/**< Operation unspecified */

>> +	RTE_CRYPTO_ASYM_OP_ENCRYPT,

>> +	/**< Asymmetric encrypt operation */

>> +	RTE_CRYPTO_ASYM_OP_DECRYPT,

>> +	/**< Asymmetric Decrypt operation */

>> +	RTE_CRYPTO_ASYM_OP_SIGN,

>> +	/**< Signature generation operation */

>> +	RTE_CRYPTO_ASYM_OP_VERIFY,

>> +	/**< Signature verification operation */

>> +	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,

>> +	/**< Public/Private key pair generation operation */

>[Fiona] In the comment, clarify that this is for DH and ECDH, and for the

> generation of the public key (and optionally the private key?)

>

>> +	RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION,

>> +	/**< DH private key computation operation */

>[Fiona] In the comment, replace "private key" with "shared secret key".

>Also clarify that this is for both DH and ECDH

>

>> +	RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK,

>> +	/**< ECDH public key validity check operation */

>> +	RTE_CRYPTO_ASYM_OP_LIST_END

>> +};

>> +

>> +/**

>> + * Padding types for RSA signature.

>> + */

>> +enum rte_crypto_rsa_padding_type {

>> +	RTE_CRYPTO_RSA_PADDING_NOT_SPECIFIED = 1,

>> +	/**< RSA no padding scheme */

>> +	RTE_CRYPTO_RSA_PADDING_BT1,

>> +	/**< RSA PKCS#1 padding BT1 scheme */

>> +	RTE_CRYPTO_RSA_PADDING_BT2,

>> +	/**< RSA PKCS#1 padding BT2 scheme */

>[Fiona] In the name, I would add _PKCS1_V1.5_, to make this clearer. Also in the comment, clarify that BT is

>for "block type". Also clarify how these map to the block type in PKCS#1 v1.5

>(https://tools.ietf.org/html/rfc2313), which specifies three values for block type.

>

>> +	RTE_CRYPTO_RSA_PADDING_OAEP,

>> +	/**< RSA PKCS#1 OAEP padding scheme */

>> +	RTE_CRYPTO_RSA_PADDING_PSS,

>> +	/**< RSA PKCS#1 PSS padding scheme */

>> +	RTE_CRYPTO_RSA_PADDING_TYPE_LIST_END

>> +};

>> +

>> +

>> +/**

>> + * Fundamental ECC operation type variants.

>> + */

>> +enum rte_crypto_fecc_optype {

>> +	RTE_CRYPTO_FECC_OP_NOT_SPECIFIED = 1,

>> +	/**< FECC operation type unspecified */

>[Fiona] as above. Why 1? And is it needed?

>

>> +	RTE_CRYPTO_FECC_OP_POINT_ADD,

>> +	/**< Fundamental ECC point addition operation */

>> +	RTE_CRYPTO_FECC_OP_POINT_DBL,

>> +	/**< Fundamental ECC point doubling operation */

>> +	RTE_CRYPTO_FECC_OP_POINT_MULTIPLY,

>> +	/**< Fundamental ECC point multiplication operation */

>> +	RTE_CRYPTO_FECC_OP_LIST_END

>> +};

>> +

>> +#define RTE_CRYPTO_EC_CURVE_NOT_SPECIFIED  -1

>[Fiona] Wouldn't it be better to put this back in as the initial value in the enum as originally done?

>Else will there not be a compiler warning if a param of that enum type is

>initialised to above #define?

>And are _BINARY and _PRIME values needed in this case?

>

>> +/**

>> + * ECC list of curves.

>> + */

>> +enum rte_crypto_ec_prime_curve {

>> +	/**< Unspecified or empty curve id */

>[Fiona] Remove stray comment

>> +	RTE_CRYPTO_EC_CURVE_secp112r1,

>> +	/**< SECG/WTLS curve over a 112 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp112r2,

>> +	/**< SECG curve over a 112 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp128r1,

>> +	/**< SECG curve over a 128 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp128r2,

>> +	/**< SECG curve over a 128 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp160k1,

>> +	/**< SECG curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp160r1,

>> +	/**< SECG curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp160r2,

>> +	/**< SECG/WTLS curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp192k1,

>> +	/**< SECG curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp224k1,

>> +	/**< SECG curve over a 224 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp224r1,

>> +	/**< NIST/SECG curve over a 224 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp256k1,

>> +	/**< SECG curve over a 256 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp384r1,

>> +	/**< NIST/SECG curve over a 384 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_secp521r1,

>> +	/**< NIST/SECG curve over a 521 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime192v1,

>> +	/**< NIST/X9.62/SECG curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime192v2,

>> +	/**< X9.62 curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime192v3,

>> +	/**< X9.62 curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime239v1,

>> +	/**< X9.62 curve over a 239 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime239v2,

>> +	/**< X9.62 curve over a 239 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime239v3,

>> +	/**< X9.62 curve over a 239 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_prime256v1,

>> +	/**< X9.62/SECG curve over a 256 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls6,

>> +	/**< SECG/WTLS curve over a 112 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls7,

>> +	/**< SECG/WTLS curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls8,

>> +	/**< WTLS curve over a 112 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls9,

>> +	/**< WTLS curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls12,

>> +	/**< WTLS curve over a 224 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP160r1,

>> +	/**< RFC 5639 curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP160t1,

>> +	/**< RFC 5639 curve over a 160 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP192r1,

>> +	/**< RFC 5639 curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP192t1,

>> +	/**< RFC 5639 curve over a 192 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP224r1,

>> +	/**< RFC 5639 curve over a 224 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP224t1,

>> +	/**< RFC 5639 curve over a 224 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP256r1,

>> +	/**< RFC 5639 curve over a 256 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP256t1,

>> +	/**< RFC 5639 curve over a 256 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP320r1,

>> +	/**< RFC 5639 curve over a 320 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP320t1,

>> +	/**< RFC 5639 curve over a 320 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP384r1,

>> +	/**< RFC 5639 curve over a 384 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP384t1,

>> +	/**< RFC 5639 curve over a 384 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP512r1,

>> +	/**< RFC 5639 curve over a 512 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_brainpoolP512t1,

>> +	/**< RFC 5639 curve over a 512 bit prime field */

>> +	RTE_CRYPTO_EC_CURVE_x25519,

>> +	/**< Curve 25519 */

>> +	RTE_CRYPTO_EC_PCURVE_LIST_END

>> +};

>> +

>> +enum rte_crypto_ec_binary_curve {

>> +	/**< Unspecified or empty curve id */

>[Fiona] remove stray comment

>> +	RTE_CRYPTO_EC_CURVE_sect113r1,

>> +	/**< SECG curve over a 113 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect113r2,

>> +	/**< SECG curve over a 113 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect131r1,

>> +	/**< SECG/WTLS curve over a 131 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect131r2,

>> +	/**< SECG curve over a 131 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect163k1,

>> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect163r1,

>> +	/**< SECG curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect163r2,

>> +	/**< NIST/SECG curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect193r1,

>> +	/**< SECG curve over a 193 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect193r2,

>> +	/**< SECG curve over a 193 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect233k1,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect233r1,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect239k1,

>> +	/**< SECG curve over a 239 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect283k1,

>> +	/**< NIST/SECG curve over a 283 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect283r1,

>> +	/**< NIST/SECG curve over a 283 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect409k1,

>> +	/**< NIST/SECG curve over a 409 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect409r1,

>> +	/**< NIST/SECG curve over a 409 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect571k1,

>> +	/**< NIST/SECG curve over a 571 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_sect571r1,

>> +	/**< NIST/SECG curve over a 571 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb163v1,

>> +	/**< X9.62 curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb163v2,

>> +	/**< X9.62 curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb163v3,

>> +	/**< X9.62 curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb176v1,

>> +	/**< X9.62 curve over a 176 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb191v1,

>> +	/**< X9.62 curve over a 191 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb191v2,

>> +	/**< X9.62 curve over a 191 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb191v3,

>> +	/**< X9.62 curve over a 191 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb208w1,

>> +	/**< X9.62 curve over a 208 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb239v1,

>> +	/**< X9.62 curve over a 239 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb239v2,

>> +	/**< X9.62 curve over a 239 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb239v3,

>> +	/**< X9.62 curve over a 239 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb272w1,

>> +	/**< X9.62 curve over a 272 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb304w1,

>> +	/**< X9.62 curve over a 304 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb359v1,

>> +	/**< X9.62 curve over a 359 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2pnb368w1,

>> +	/**< X9.62 curve over a 368 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_c2tnb431r1,

>> +	/**< X9.62 curve over a 431 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls1,

>> +	/**< WTLS curve over a 113 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls3,

>> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls4,

>> +	/**< SECG curve over a 113 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls5,

>> +	/**< X9.62 curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls10,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls11,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_BCURVE_LIST_END

>> +};

>[Fiona] Do we really want to specify curves < 224 bits? Even 224 is woefully insecure these days.

>Also do we want to list all "published" curves, or allow customers to specify

>their own curve parameters, at least on the FECC API? Adding an API to specify a curve with

>its params would allow new curves to be used without affecting the API and

>would avoid the need for such an extensive list.

>Do we need a "capabilities" mask to say which curves are supported by a device?

>What about SM2?

>

>> +/**

>> + * Elliptic curve point format

>> + */

>> +struct rte_crypto_ec_point {

>> +	struct {

>> +		int length;

>> +		uint8_t *data;

>> +		phys_addr_t phys_addr;

>> +		/**< phys_addr is used only for points passed in the

>> +		 * asym_op structure.

>> +		 */

>> +	} x;

>> +	/**< X co-ordinate */

>> +

>[Fiona] If generic rte_crypto_param_t is defined then it could be used here too.

>

>> +	struct {

>> +		int length;

>> +		uint8_t *data;

>> +		phys_addr_t phys_addr;

>> +		/**< phys_addr is used only for points passed in the

>> +		 * operation structure

>> +		 */

>> +	} y;

>> +	/**< Y co-ordinate */

>> +};

>> +

>> +/**

>> + * Elliptic curve type

>> + */

>> +enum rte_crypto_ec_curve_type {

>> +	RTE_CRYPTO_EC_CURVE_TYPE_UNDEFINED,

>> +	/**< Curve type undefined */

>> +	RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD,

>> +	/**< EC curve defined over a prime field */

>> +	RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD,

>> +	/**< EC curve defined over a binary field */

>> +	RTE_CRYPTO_EC_CURVE_LIST_END

>> +};

>> +

>> +/** asym xform type name strings */

>> +extern const char *

>> +rte_crypto_asym_xform_strings[];

>> +

>> +/** asym operations type name strings */

>> +extern const char *

>> +rte_crypto_asym_op_strings[];

>> +

>> +/**

>> + * Elliptic curve id

>> + */

>> +struct rte_crypto_ec_curve_id {

>> +	RTE_STD_C11

>> +	union {

>> +		enum rte_crypto_ec_prime_curve pcurve;

>> +		enum rte_crypto_ec_binary_curve bcurve;

>> +	};

>> +};

>[Fiona] Because the values of these two enums overlap, if you specify the curve type incorrectly, you'll still

>have a potentially valid curve enum specified. I suggest it's safer to include the type here with the union,

>rather than in the wrapper xform struct, i.e.

>struct rte_crypto_ec_curve {

>	enum rte_crypto_ec_curve_type curve_type;

>	/**< curve type: Prime vs Binary */

>	union {

>	enum rte_crypto_ec_prime_curve pcurve_id;

>	enum rte_crypto_ec_binary_curve bcurve_id;

>	};

>};

>> +/**

>> + * Asymmetric RSA transform data

>> + *

>> + * This structure contains data required to perform RSA crypto

>> + * transform.

>> + *

>> + */

>> +struct rte_crypto_rsa_xform {

>> +

>> +	rte_crypto_xform_param n;

>> +	/**< n - Prime modulus

>> +	 * Prime modulus data of RSA operation in Octet-string network

>> +	 * byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param e;

>> +	/**< e - Public key exponent

>> +	 * Public key exponent used for RSA public key operations in Octet-

>> +	 * string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param d;

>> +	/**< d - Private key exponent

>> +	 * Private key exponent used for RSA private key operations in

>> +	 * Octet-string  network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param p;

>> +	/**< p - Private key component P

>> +	 * Private key component of RSA parameter  required for CRT method

>> +	 * of private key operations in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param q;

>> +	/**< q - Private key component Q

>> +	 * Private key component of RSA parameter  required for CRT method

>> +	 * of private key operations in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param dP;

>> +	/**< dP - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * dP = d mod ( p - 1 )

>> +	 */

>> +

>> +	rte_crypto_xform_param dQ;

>> +	/**< dQ - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * dQ = d mod ( q - 1 )

>> +	 */

>> +

>> +	rte_crypto_xform_param qInv;

>> +	/**< qInv - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * qInv = inv q mod p

>> +	 */

>> +};

>[Fiona] This allows both representations of the private key to be specified

>with the possibility of confusion if both are specified.

>Would it be better to have a union of 2 different structures, one with {n,d} and

>the other with {p,q,dP,dQ,qInv}?

>

>> +/**

>> + * Asymmetric Modular exponentiation transform data

>> + *

>> + * This structure contains data required to perform modular exponentation

>> + * crypto transform.

>> + *

>> + */

>> +struct rte_crypto_modex_xform {

>> +

>> +	rte_crypto_xform_param modulus;

>> +	/**< modulus

>> +	 * Prime modulus of the modexp transform operation in Octet-string

>> +	 * network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param exponent;

>> +	/**< exponent

>> +	 * Private exponent of the modexp transform operation in

>> +	 * Octet-string network byte order format.

>> +	 */

>> +};

>> +

>> +/**

>> + * Asymmetric DH transform data

>> + *

>> + * This structure contains data used to perform DH key

>> + * operations.

>> + *

>> + */

>> +struct rte_crypto_dh_xform {

>> +	rte_crypto_xform_param p;

>> +	/**< p : Prime modulus data

>> +	 * DH prime modulous data in Octet-string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param g;

>> +	/**< g : Generator

>> +	 * DH group generator data in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +};

>> +

>> +/**

>> + * Asymmetric ECDH transform data

>> + *

>> + * This structure contains data required to perform ECDH crypto

>> + * transform.

>> + *

>> + */

>> +struct rte_crypto_ecdh_xform {

>> +

>> +	enum rte_crypto_ec_curve_type curve_type;

>> +	/**< ECDH curve type: Prime vs Binary */

>> +

>> +	struct rte_crypto_ec_curve_id curve_id;

>> +

>> +	rte_crypto_xform_param p;

>> +	/**< p:

>> +	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD:

>> +	 * p holds the prime modulus data in Octet string format.

>> +	 *

>> +	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD:

>> +	 * p holds reduction polynomial co-efficients and degree.

>> +	 */

>> +

>> +	rte_crypto_xform_param a;

>> +	/**< Curve Parameter Co-efficient 'a' of curve equation data in

>> +	 * Octet-string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param b;

>> +	/**< Curve Parameter Co-efficient 'b' of curve equation data in

>> +	 * Octet-string network byte order format.

>> +	 */

>> +

>> +	struct  rte_crypto_ec_point G;

>> +	/**< G: EC curve generator point

>> +	 * EC curve generator point data in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param n;

>> +	/**< n : order of G

>> +	 * ECDH curve order data in Octet-string network byte order format.

>> +	 */

>> +

>> +	int h;

>> +	/**< Co-factor of the curve */

>> +

>> +	rte_crypto_xform_param pkey;

>> +	/**< pkey: Private key

>> +	 * Private key data for ECDH operation in Octet-string network byte

>> +	 * order format.

>> +	 */

>> +

>> +	struct rte_crypto_ec_point Q;

>> +	/**< Q: Public key point

>> +	 * Public key point data of ECDH operation in Octet-string network

>> +	 * byte order format.

>> +	 */

>> +};

>> +

>> +/**

>> + * Asymmetric Digital Signature transform operation

>> + *

>> + * This structure contain signer key information for DSA signature

>> + * generation and verification.

>> + * App which does both Signature Generation and Verification should

>> + * create two separate session carrying its own and peer key information

>> + *

>> + */

>> +struct rte_crypto_dsa_xform {

>> +	rte_crypto_xform_param p;

>> +	/**< p - Prime modulus

>> +	 * Prime modulus data for DSA operation in Octet-string network byte

>> +	 * order format.

>> +	 */

>> +	rte_crypto_xform_param q;

>> +	/**< q : Order of the subgroup.

>> +	 * Order of the subgroup data in Octet-string network byte order

>> +	 * format.

>> +	 * (p-1) % q = 0

>> +	 */

>> +	rte_crypto_xform_param g;

>> +	/**< g: Generator of the subgroup

>> +	 * Generator  data in Octet-string network byte order format.

>> +	 */

>> +	rte_crypto_xform_param x;

>> +	/**< x: Private key of the signer

>> +	 * Private key data in Octet-string network byte order format.

>> +	 * Private key is valid only for signature generation operation.

>> +	 */

>> +	rte_crypto_xform_param y;

>> +	/**< y : Public key of the signer.

>> +	 * Public key data of the signer in Octet-string network byte order

>> +	 * format.

>> +	 * y = g^x mod p

>> +	 */

>> +};

>> +

>> +/**

>> + * Asymmetric ECDSA transform data

>> + *

>> + * This structure contains data required to perform ECDSA crypto

>> + * transform.

>> + */

>> +struct rte_crypto_ecdsa_xform {

>> +	/** TBD */

>> +};

>> +

>> +/**

>> + * Asymmetric modular inverse transform operation

>> + *

>> + * This structure contains data required to perform

>> + * asymmetric modular inverse crypto transform

>> + */

>> +struct rte_crypto_modinv_xform {

>> +	/** TBD */

>> +};

>> +

>> +/** Asymmetric Fundamental ECC transform operation

>> + *

>> + * This structure contains data required to perform asymmetric

>> + * fundamental ECC crypto transform.

>> + */

>> +struct rte_crypto_fecc_xform {

>> +

>> +	enum rte_crypto_ec_curve_type curve_type;

>> +	/**< FECC curve type: Prime vs Binary */

>> +

>> +	struct rte_crypto_ec_curve_id curve_id;

>> +	/**< EC curve ID */

>> +

>> +	rte_crypto_xform_param order;

>> +	/**< order : ECC curve order

>> +	 * Curve order data in Octet-string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param prime;

>> +	/**< prime : Curve prime modulus data

>> +	 * Prime modulus data in Octet-string network byte order format.

>> +	 */

>> +

>> +	struct rte_crypto_ec_point G;

>> +	/**< G: curve generator point

>> +	 * Curve generator point data in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param a;

>> +	/**< Co-efficient 'a' of curve equation data in Octet-string network

>> +	 * byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param b;

>> +	/**< Co-efficient 'a' of curve equation data in Octet-string network

>> +	 * byte order format.

>> +	 */

>> +

>> +	int h;

>> +	/**< Co-factor of the curve */

>> +

>> +};

>> +

>> +/**

>> + * Asymmetric crypto transform data

>> + *

>> + * This structure contains the data required to perform the

>> + * asymmetric crypto transformation operation. The field op

>> + * determines the asymmetric algorithm for transformation.

>[Fiona] clarify comment. The xform only contains some of the data, the rest will be provided in the op.

>And there's no field op here.

>> + */

>> +struct rte_crypto_asym_xform {

>> +	struct rte_crypto_asym_xform *next;

>[Fiona] Is there any reason for a chain of xforms?

>I'd suggest removing unless needed.

>

>> +	enum rte_crypto_asym_xform_type xform_type;

>> +	/**< Asymmetric algorithm for crypto transform */

>> +

>> +	RTE_STD_C11

>> +	union {

>> +		struct rte_crypto_rsa_xform rsa;

>> +		/**< RSA xform parameters */

>> +

>> +		struct rte_crypto_fecc_xform fecc;

>> +		/**< Fundamental Elliptic Curve xform parameters */

>> +

>> +		struct rte_crypto_modex_xform modex;

>> +		/**< Modular Exponentiation xform parameters */

>> +

>> +		struct rte_crypto_modinv_xform modinv;

>> +		/**< Modulus Inverse xform parameters */

>> +

>> +		struct rte_crypto_ecdsa_xform ecdsa;

>> +		/**< ECDSA xform parameters */

>> +

>> +		struct rte_crypto_ecdh_xform ecdh;

>> +		/**< ECDH xform parameters */

>> +

>> +		struct rte_crypto_dsa_xform dsa;

>> +		/**< DSA xform parameters */

>> +	};

>> +};

>> +

>> +struct rte_cryptodev_asym_session;

>> +

>> +/**

>> + * RSA operation params

>> + *

>> + */

>> +struct rte_crypto_rsa_op_param {

>> +	enum rte_crypto_asym_op_type op_type;

>> +	/**< Type of RSA operation for transform */;

>> +

>> +	rte_crypto_op_param message;

>> +	/**<

>> +	 * Pointer to data

>> +	 * - to be encrypted for RSA public encrypt.

>> +	 * - to be decrypted for RSA private decrypt.

>> +	 * - to be signed for RSA sign generation.

>> +	 * - to be authenticated for RSA sign verification.

>> +	 */

>> +

>> +	rte_crypto_op_param sign;

>> +	/**<

>> +	 * Pointer to RSA signature data. If operation is RSA

>> +	 * sign @ref RTE_CRYPTO_RSA_OP_SIGN, buffer will be

>> +	 * over-written with generated signature.

>> +	 *

>> +	 * Length of the signature data will be equal to the

>> +	 * RSA prime modulus length.

>> +	 */

>> +

>> +	enum rte_crypto_rsa_padding_type pad;

>> +	/**< RSA padding scheme to be used for transform */

>> +

>> +	enum rte_crypto_auth_algorithm md;

>> +	/**< Hash algorithm to be used for data hash if padding

>> +	 * scheme is either OAEP or PSS. Valid hash algorithms

>> +	 * are:

>> +	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512

>> +	 */

>> +

>> +	enum rte_crypto_auth_algorithm mgf1md;

>> +	/**<

>> +	 * Hash algorithm to be used for mask generation if

>> +	 * padding scheme is either OAEP or PSS. If padding

>> +	 * scheme is unspecified data hash algorithm is used

>> +	 * for mask generation. Valid hash algorithms are:

>> +	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512

>> +	 */

>> +};

>> +

>> +/**

>> + * Deffie-Hellman Operations params

>> + *

>> + */

>> +struct rte_crypto_dh_op_param {

>> +	enum rte_crypto_asym_op_type op_type;

>> +	/**< Asymmetric op type: Key Generation / Computation */

>> +

>> +	rte_crypto_op_param pub_key;

>> +	/**<

>> +	 * Output native app public key when DH operation type is

>> +	 * KEY_GENERATION.

>> +	 * Input peer public key when DH operation is shared key

>> +	 * KEY_COMPUTATION

>> +	 * An Octet-string network byte order format.

>> +	 *

>> +	 */

>> +

>> +	rte_crypto_op_param priv_key;

>> +	/**<

>> +	 * Output native app private key if operation type

>> +	 * KEY_GENERATION.

>> +	 * Input native app private key when operation type

>> +	 * is KEY_COMPUTATION. priv_key is in

>> +	 * in Octet-string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_op_param shared_key;

>> +	/*

>> +	 * Output when DH operation type is KEY_COMPUTATION:

>> +	 * computed. shared_key is written as

>> +	 * Octet-string network byte order format.

>> +	 * Ignored for KEY_GENERATION.

>> +	 */

>> +};

>> +

>> +/**

>> + * DSA Operations params

>> + *

>> + */

>> +struct rte_crypto_dsa_op_param {

>> +	/** TBD */

>> +};

>> +

>> +/**

>> + * Mod Exp Operations params

>> + *

>> + */

>> +struct rte_crypto_modex_op_param {

>> +	rte_crypto_op_param base;

>> +	/**<

>> +	 * Pointer to base of modular exponentiation data in

>> +	 * Octet-string network byte order format.

>> +	 */

>> +};

>> +

>> +/**

>> + * Elliptic curve Deffie-Hellman Operations params

>> + *

>> + */

>> +struct rte_crypto_ecdh_op_param {

>> +	enum rte_crypto_asym_op_type op_type;

>> +	/**< Asymmetric operation: key generation, computation */

>> +

>> +	rte_crypto_op_param priv_key;

>> +	/**<

>> +	 * Output if operation type is KEY_PAIR_GENERATION,

>> +	 * output native app private key.

>> +	 * Input and output, If ECDH operation type is SHARED_KEY_COMPUTATION,

>> +	 * priv_key will hold the 'X' co-ordinate of the shared

>> +	 * secret EC point. priv_key is in Octet-string network

>> +	 * byte order.

>> +	 */

>> +

>> +	struct rte_crypto_ec_point pub_key;

>> +	/**<

>> +	 * Output if operation type is KEY_PAIR_GENERATION,

>> +	 * store native app public key.

>> +	 * Input if operation type is SHARED_KEY_COMPUTATION,

>> +	 *

>> +	 * KEY_COMPUTATION:

>> +	 *  pub_key is in Octet-string network byte order.

>> +	 */

>> +};

>> +

>> +/**

>> + * Elliptic Curve DSA Operations params

>> + *

>> + */

>> +struct rte_crypto_ecdsa_op_param {

>> +

>> +	enum rte_crypto_asym_op_type ecdsa_op;

>> +	/**< ECDSA crypto xform operation type: Signature

>> +	 *  generation/Verification

>> +	 */

>> +	/** TBD */

>> +};

>> +

>> +/**

>> + * Fundamental Elliptic Curve Operations params

>> + *

>> + */

>> +struct rte_crypto_fecc_op_param {

>> +	enum rte_crypto_fecc_optype fecc_op;

>> +	/**< FECC crypto xform operation type */

>> +

>> +	/** TBD */

>> +};

>> +

>> +/**

>> + * Mod Inv Operations params

>> + *

>> + */

>> +struct rte_crypto_modinv_op_param {

>> +	rte_crypto_op_param prime;

>> +	/**<

>> +	 * Pointer to the prime modulus data for modular

>> +	 * inverse operation in Octet-string network byte

>> +	 * order format.

>> +	 */

>> +

>> +	rte_crypto_op_param base;

>> +	/**<

>> +	 * Pointer to the base for the modular inverse

>> +	 * operation in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +};

>> +

>> +/**

>> + * Asymmetric Cryptographic Operation.

>> + *

>> + * This structure contains data relating to performing asymmetric cryptographic

>> + * operation.

>> + *

>> + */

>> +struct rte_crypto_asym_op {

>> +	enum rte_crypto_asym_xform_type type;

>> +	/**< RSA, DH, ECDH, DSA etc */

>> +

>> +	struct rte_cryptodev_asym_session *session;

>> +	/**< Handle for the initialised session context */

>> +

>> +	RTE_STD_C11

>> +	union {

>> +		struct rte_crypto_rsa_op_param rsa;

>> +		struct rte_crypto_dh_op_param dh;

>> +		struct rte_crypto_modex_op_param modex;

>> +		struct rte_crypto_ecdh_op_param ecdh;

>> +		struct rte_crypto_ecdsa_op_param ecdsa;

>> +		struct rte_crypto_dsa_op_param dsa;

>> +		struct rte_crypto_fecc_op_param fecc;

>> +		struct rte_crypto_modinv_op_param modinv;

>> +	};

>> +} __rte_cache_aligned;

>> +

>> +/**

>> + * Reset the fields of an asymmetric operation to their default values.

>> + *

>> + * @param	op	The crypto operation to be reset.

>> + */

>> +static inline void

>> +__rte_crypto_asym_op_reset(struct rte_crypto_asym_op *op)

>> +{

>> +	memset(op, 0, sizeof(*op));

>> +}

>> +

>> +

>> +/**

>> + * Attach a session to an asymmetric crypto operation

>> + *

>> + * @param	asym_op	crypto operation

>> + * @param	sess	cryptodev session

>> + */

>> +static inline int

>> +__rte_crypto_op_attach_asym_session(struct rte_crypto_asym_op *asym_op,

>> +		struct rte_cryptodev_asym_session *sess)

>> +{

>> +	asym_op->session = sess;

>> +	return 0;

>> +}

>> +

>> +#ifdef __cplusplus

>> +}

>> +#endif

>> +

>> +#endif /* _RTE_CRYPTO_ASYM_H_ */

>> diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c

>> index 7726d15..bad18c3 100644

>> --- a/lib/librte_cryptodev/rte_cryptodev.c

>> +++ b/lib/librte_cryptodev/rte_cryptodev.c

>> @@ -166,6 +166,33 @@ struct rte_cryptodev_callback {

>>  	[RTE_CRYPTO_AEAD_OP_DECRYPT]	= "decrypt"

>>  };

>>

>> +/**

>> + * Asymmetric crypto transform operation strings identifiers.

>> + */

>> +const char *rte_crypto_asym_xform_strings[] = {

>> +	[RTE_CRYPTO_ASYM_XFORM_RSA]	= "rsa",

>> +	[RTE_CRYPTO_ASYM_XFORM_MODEX]	= "modexp",

>> +	[RTE_CRYPTO_ASYM_XFORM_DH]	= "dh",

>> +	[RTE_CRYPTO_ASYM_XFORM_ECDH]	= "ecdh",

>> +	[RTE_CRYPTO_ASYM_XFORM_DSA]	= "dsa",

>> +	[RTE_CRYPTO_ASYM_XFORM_ECDSA]	= "ecdsa",

>> +	[RTE_CRYPTO_ASYM_XFORM_MODINV]	= "modinv",

>> +	[RTE_CRYPTO_ASYM_XFORM_FECC]	= "fecc"

>> +};

>> +

>> +/**

>> + * Asymmetric crypto operation strings identifiers.

>> + */

>> +const char *rte_crypto_asym_op_strings[] = {

>> +	[RTE_CRYPTO_ASYM_OP_ENCRYPT]	= "encrypt",

>> +	[RTE_CRYPTO_ASYM_OP_DECRYPT]	= "decrypt",

>> +	[RTE_CRYPTO_ASYM_OP_SIGN]	= "sign",

>> +	[RTE_CRYPTO_ASYM_OP_VERIFY]	= "verify",

>> +	[RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION]	= "keypair_generate",

>> +	[RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION] = "sharedkey_computation",

>> +	[RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK]	= "ecdh_keycheck",

>> +};

>> +

>>  int

>>  rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,

>>  		const char *algo_string)

>> @@ -217,6 +244,24 @@ struct rte_cryptodev_callback {

>>  	return -1;

>>  }

>>

>> +int

>> +rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,

>> +		const char *xform_string)

>> +{

>> +	unsigned int i;

>> +

>> +	for (i = 1; i < RTE_DIM(rte_crypto_asym_xform_strings); i++) {

>> +		if (strcmp(xform_string,

>> +			   rte_crypto_asym_xform_strings[i]) == 0) {

>> +			*xform_enum = (enum rte_crypto_asym_xform_type) i;

>> +			return 0;

>> +		}

>> +	}

>> +

>> +	/* Invalid string */

>> +	return -1;

>> +}

>> +

>>  /**

>>   * The crypto auth operation strings identifiers.

>>   * It could be used in application command line.

>> @@ -262,6 +307,28 @@ struct rte_cryptodev_callback {

>>

>>  }

>>

>> +const struct rte_cryptodev_asymmetric_capability *

>> +rte_cryptodev_asym_capability_get(uint8_t dev_id,

>> +		const struct rte_cryptodev_asym_capability_idx *idx)

>> +{

>> +	const struct rte_cryptodev_capabilities *capability;

>> +	struct rte_cryptodev_info dev_info;

>> +	unsigned int i = 0;

>> +

>> +	memset(&dev_info, 0, sizeof(rte_cryptodev_info));

>> +	rte_cryptodev_info_get(dev_id, &dev_info);

>> +

>> +	while ((capability = &dev_info.capabilities[i++])->op !=

>> +			RTE_CRYPTO_OP_TYPE_UNDEFINED) {

>> +		if (capability->op != RTE_CRYPTO_OP_TYPE_ASYMMETRIC)

>> +			continue;

>> +

>> +		if (capability->asym.xform_type == idx->type)

>> +			return &capability->asym;

>> +	}

>> +	return NULL;

>> +};

>> +

>>  #define param_range_check(x, y) \

>>  	(((x < y.min) || (x > y.max)) || \

>>  	(y.increment != 0 && (x % y.increment) != 0))

>> @@ -601,6 +668,24 @@ struct rte_cryptodev *

>>  	return dev->data->nb_queue_pairs;

>>  }

>>

>> +uint16_t

>> +rte_cryptodev_asym_queue_pair_count(uint8_t dev_id)

>> +{

>> +	struct rte_cryptodev *dev;

>> +

>> +	dev = &rte_crypto_devices[dev_id];

>> +	return dev->data->nb_asym_qp;

>> +}

>> +

>> +uint16_t

>> +rte_cryptodev_sym_queue_pair_count(uint8_t dev_id)

>> +{

>> +	struct rte_cryptodev *dev;

>> +

>> +	dev = &rte_crypto_devices[dev_id];

>> +	return dev->data->nb_sym_qp;

>> +}

>> +

>>  static int

>>  rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,

>>  		int socket_id)

>> @@ -1088,6 +1173,38 @@ struct rte_cryptodev *

>>  	return 0;

>>  }

>>

>> +int

>> +rte_cryptodev_asym_session_init(uint8_t dev_id,

>> +		struct rte_cryptodev_asym_session *sess,

>> +		struct rte_crypto_asym_xform *xforms,

>> +		struct rte_mempool *mp)

>> +{

>> +	struct rte_cryptodev *dev;

>> +	uint8_t index;

>> +	int ret;

>> +

>> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

>> +

>> +	if (sess == NULL || xforms == NULL || dev == NULL)

>> +		return -EINVAL;

>> +

>> +	index = dev->driver_id;

>> +

>> +	if (sess->sess_private_data[index] == NULL) {

>> +		ret = dev->dev_ops->asym_session_configure(dev,

>> +							   xforms,

>> +							   sess, mp);

>> +		if (ret < 0) {

>> +			CDEV_LOG_ERR(

>> +				"dev_id %d failed to configure session details",

>> +				dev_id);

>> +			return ret;

>> +		}

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>>  struct rte_cryptodev_sym_session *

>>  rte_cryptodev_sym_session_create(struct rte_mempool *mp)

>>  {

>> @@ -1105,6 +1222,23 @@ struct rte_cryptodev_sym_session *

>>  	return sess;

>>  }

>>

>> +struct rte_cryptodev_asym_session *

>> +rte_cryptodev_asym_session_create(struct rte_mempool *mp)

>> +{

>> +	struct rte_cryptodev_asym_session *sess;

>> +

>> +	/* Allocate a session structure from the session pool */

>> +	if (rte_mempool_get(mp, (void *)&sess)) {

>> +		CDEV_LOG_ERR("couldn't get object from session mempool");

>> +		return NULL;

>> +	}

>> +

>> +	/* Clear device session pointer */

>> +	memset(sess, 0, (sizeof(void *) * nb_drivers));

>> +

>> +	return sess;

>> +}

>> +

>>  int

>>  rte_cryptodev_queue_pair_attach_sym_session(uint8_t dev_id, uint16_t qp_id,

>>  		struct rte_cryptodev_sym_session *sess)

>> @@ -1160,6 +1294,60 @@ struct rte_cryptodev_sym_session *

>>  }

>>

>>  int

>> +rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,

>> +		struct rte_cryptodev_asym_session *sess)

>> +{

>> +	struct rte_cryptodev *dev;

>> +

>> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {

>> +		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);

>> +		return -EINVAL;

>> +	}

>> +

>> +	dev = &rte_crypto_devices[dev_id];

>> +

>> +	/* The API is optional, not returning error if driver do not suuport */

>> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_attach_session, 0);

>> +

>> +	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);

>> +

>> +	if (dev->dev_ops->asym_qp_attach_session(dev, qp_id, sess_priv)) {

>> +		CDEV_LOG_ERR("dev_id %d failed to attach qp: %d with session",

>> +				dev_id, qp_id);

>> +		return -EPERM;

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>> +int

>> +rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,

>> +		struct rte_cryptodev_asym_session *sess)

>> +{

>> +	struct rte_cryptodev *dev;

>> +

>> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {

>> +		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);

>> +		return -EINVAL;

>> +	}

>> +

>> +	dev = &rte_crypto_devices[dev_id];

>> +

>> +	/* The API is optional, not returning error if driver do not suuport */

>> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_detach_session, 0);

>> +

>> +	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);

>> +

>> +	if (dev->dev_ops->asym_qp_detach_session(dev, qp_id, sess_priv)) {

>> +		CDEV_LOG_ERR("dev_id %d failed to detach qp: %d from session",

>> +				dev_id, qp_id);

>> +		return -EPERM;

>> +	}

>> +

>> +	return 0;

>> +}

>> +

>> +int

>>  rte_cryptodev_sym_session_clear(uint8_t dev_id,

>>  		struct rte_cryptodev_sym_session *sess)

>>  {

>> @@ -1176,6 +1364,22 @@ struct rte_cryptodev_sym_session *

>>  }

>>

>>  int

>> +rte_cryptodev_asym_session_clear(uint8_t dev_id,

>> +		struct rte_cryptodev_asym_session *sess)

>> +{

>> +	struct rte_cryptodev *dev;

>> +

>> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

>> +

>> +	if (dev == NULL || sess == NULL)

>> +		return -EINVAL;

>> +

>> +	dev->dev_ops->asym_session_clear(dev, sess);

>> +

>> +	return 0;

>> +}

>> +

>> +int

>>  rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess)

>>  {

>>  	uint8_t i;

>> @@ -1199,6 +1403,31 @@ struct rte_cryptodev_sym_session *

>>  	return 0;

>>  }

>>

>> +int

>> +rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess)

>> +{

>> +	uint8_t i;

>> +	void *sess_priv;

>> +	struct rte_mempool *sess_mp;

>> +

>> +	if (sess == NULL)

>> +		return -EINVAL;

>> +

>> +	/* Check that all device private data has been freed */

>> +	for (i = 0; i < nb_drivers; i++) {

>> +		sess_priv = get_asym_session_private_data(sess, i);

>> +		if (sess_priv != NULL)

>> +			return -EBUSY;

>> +	}

>> +

>> +	/* Return session to mempool */

>> +	sess_mp = rte_mempool_from_obj(sess);

>> +	rte_mempool_put(sess_mp, sess);

>> +

>> +	return 0;

>> +}

>> +

>> +

>>  unsigned int

>>  rte_cryptodev_get_header_session_size(void)

>>  {

>> @@ -1235,6 +1464,57 @@ struct rte_cryptodev_sym_session *

>>  		return header_size;

>>

>>  	return priv_sess_size;

>> +}

>> +

>> +unsigned int

>> +rte_cryptodev_get_sym_session_private_size(uint8_t dev_id)

>> +{

>> +	struct rte_cryptodev *dev;

>> +	unsigned int header_size = sizeof(void *) * nb_drivers;

>> +	unsigned int priv_sess_size;

>> +

>> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))

>> +		return 0;

>> +

>> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

>> +

>> +	if (*dev->dev_ops->sym_session_get_size == NULL)

>> +		return 0;

>> +

>> +	priv_sess_size = (*dev->dev_ops->sym_session_get_size)(dev);

>> +

>> +	/*

>> +	 * If size is less than session header size,

>> +	 * return the latter, as this guarantees that

>> +	 * sessionless operations will work

>> +	 */

>> +	if (priv_sess_size < header_size)

>> +		return header_size;

>> +

>> +	return priv_sess_size;

>> +}

>> +

>> +

>> +unsigned int

>> +rte_cryptodev_get_asym_session_private_size(uint8_t dev_id)

>> +{

>> +	struct rte_cryptodev *dev;

>> +	unsigned int header_size = sizeof(void *) * nb_drivers;

>> +	unsigned int priv_sess_size;

>> +

>> +	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))

>> +		return 0;

>> +

>> +	dev = rte_cryptodev_pmd_get_dev(dev_id);

>> +

>> +	if (*dev->dev_ops->asym_session_get_size == NULL)

>> +		return 0;

>> +

>> +	priv_sess_size = (*dev->dev_ops->asym_session_get_size)(dev);

>> +	if (priv_sess_size < header_size)

>> +		return header_size;

>> +

>> +	return priv_sess_size;

>>

>>  }

>>

>> @@ -1268,6 +1548,13 @@ struct rte_mempool *

>>  			sizeof(struct rte_crypto_sym_op) +

>>  			priv_size;

>>

>> +	if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {

>> +		/* override size by size of asym op */

>> +		elt_size = sizeof(struct rte_crypto_op) +

>> +			   sizeof(struct rte_crypto_asym_op) +

>> +			   priv_size;

>> +	}

>> +

>>  	/* lookup mempool in case already allocated */

>>  	struct rte_mempool *mp = rte_mempool_lookup(name);

>>

>> diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h

>> index c8fa689..728483c 100644

>> --- a/lib/librte_cryptodev/rte_cryptodev.h

>> +++ b/lib/librte_cryptodev/rte_cryptodev.h

>> @@ -178,15 +178,41 @@ struct rte_cryptodev_symmetric_capability {

>>  	};

>>  };

>>

>> +/**

>> + * Asymmetric Crypto Capability

>> + *

>> + */

>> +struct rte_cryptodev_asymmetric_capability {

>> +	enum rte_crypto_asym_xform_type xform_type;

>> +	/**< Transform type: RSA/MODEXP/DH/ECDH/DSA/ECDSA/FECC/MODINV */

>> +

>[Fiona] Is there a fixed set of rte_cryptodev_asym_op_type for each xform type?

>If any variant possible then there would need to be a capability field for this.

>

>	RTE_STD_C11

>> +	union {

>> +		struct rte_crypto_param_range modlen;

>> +		/**< Range of modulus length supported for modulus based

>> +		 * algos:

>> +		 * RSA

>> +		 * MODEXP

>> +		 * MODINV

>> +		 * DH

>> +		 *

>> +		 * Value 0 to min and/or max means no specific limit and limit

>> +		 * is implementation dependent

>> +		 *

>> +		 */

>> +	};

>> +};

>> +

>>  /** Structure used to capture a capability of a crypto device */

>>  struct rte_cryptodev_capabilities {

>>  	enum rte_crypto_op_type op;

>> -	/**< Operation type */

>> +	/**< Operation type: symmetric/asymmetric */

>>

>>  	RTE_STD_C11

>>  	union {

>>  		struct rte_cryptodev_symmetric_capability sym;

>>  		/**< Symmetric operation capability parameters */

>> +		struct rte_cryptodev_asymmetric_capability asym;

>> +		/**< Asymmetric operation capability parameters */

>>  	};

>>  };

>>

>> @@ -201,7 +227,17 @@ struct rte_cryptodev_sym_capability_idx {

>>  };

>>

>>  /**

>> - *  Provide capabilities available for defined device and algorithm

>> + * Structure used to describe asymmetric crypto xforms

>> + * Each xform maps to one asym algorithm.

>> + *

>> + */

>> +struct rte_cryptodev_asym_capability_idx {

>> +	enum rte_crypto_asym_xform_type type;

>> +	/**< Asymmetric xform (algo) type */

>> +};

>> +

>> +/**

>> + * Provide capabilities available for defined device and algorithm

>>   *

>>   * @param	dev_id		The identifier of the device.

>>   * @param	idx		Description of crypto algorithms.

>> @@ -215,6 +251,20 @@ struct rte_cryptodev_sym_capability_idx {

>>  		const struct rte_cryptodev_sym_capability_idx *idx);

>>

>>  /**

>> + *  Provide capabilities available for defined device and algorithm

>> + *

>> + * @param	dev_id		The identifier of the device.

>> + * @param	algo		Description of crypto algorithms.

>> + *

>> + * @return

>> + *   - Return description of the asymmetric crypto capability if exist.

>> + *   - Return NULL if the capability not exist.

>> + */

>> +const struct rte_cryptodev_asymmetric_capability *

>> +rte_cryptodev_asym_capability_get(uint8_t dev_id,

>> +		const struct rte_cryptodev_asym_capability_idx *idx);

>> +

>> +/**

>>   * Check if key size and initial vector are supported

>>   * in crypto cipher capability

>>   *

>> @@ -270,6 +320,21 @@ struct rte_cryptodev_sym_capability_idx {

>>  		uint16_t iv_size);

>>

>>  /**

>> + * Check if modulus length is in supported range

>> + *

>> + * @param	capability	Description of the asymmetric crypto capability.

>> + * @param	modlen		modulus length.

>> + *

>> + * @return

>> + *   - Return 0 if the parameters are in range of the capability.

>> + *   - Return -1 if the parameters are out of range of the capability.

>> + */

>> +int

>> +rte_cryptodev_asym_capability_check_modlen(

>> +		const struct rte_cryptodev_asymmetric_capability *capability,

>> +		uint16_t modlen);

>> +

>> +/**

>>   * Provide the cipher algorithm enum, given an algorithm string

>>   *

>>   * @param	algo_enum	A pointer to the cipher algorithm

>> @@ -314,6 +379,22 @@ struct rte_cryptodev_sym_capability_idx {

>>  rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,

>>  		const char *algo_string);

>>

>> +/**

>> + * Provide the Asymmetric xform enum, given an xform string

>> + *

>> + * @param	xform_enum	A pointer to the xform type

>> + *				enum to be filled

>> + * @param	xform_string	xform string

>> + *

>> + * @return

>> + * - Return -1 if string is not valid

>> + * - Return 0 is the string is valid

>> + */

>> +int

>> +rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,

>> +		const char *xform_string);

>> +

>> +

>>  /** Macro used at end of crypto PMD list */

>>  #define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \

>>  	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }

>> @@ -379,16 +460,99 @@ struct rte_cryptodev_info {

>>  	/**< Array of devices supported capabilities */

>>

>>  	unsigned max_nb_queue_pairs;

>> -	/**< Maximum number of queues pairs supported by device. */

>> +	/**< Maximum number of queues pairs supported by device.

>> +	 *

>> +	 * This is total number of queues supported by device and inclusive

>> +	 * of numbers used for both symmetric and asymmetric for PMD that

>> +	 * support symmetric and asymmetric op i.e.

>> +	 *

>> +	 * max_nb_queue_pairs = max_nb_symm_qp + max_nb_asymm_qp

>> +	 *

>> +	 * Following table demonstarte what the values should be for device

>> +	 * with max num of 'n' queue pair (x = don't care):

>> +	 *

>> +	 *  -------------------------------------------------------------------

>> +	 * |dev_capa                | max_nb_asymm_qp| max_nb_symm_qp | max_qp|

>> +	 *  -------------------------------------------------------------------

>> +	 * | Symm only              |    x           | 0              | n     |

>> +	 * | Asymm only             |    0           | x              | n     |

>> +	 * | symm+asymm w/ fixed qp |    p           | n-p            | n     |

>> +	 * | symm+asymm w/ all qp   |    0           | 0              | n     |

>> +	 *  -------------------------------------------------------------------

>> +	 *

>> +	 * - if device supports only asymmetric, then max_nb_queue_pair

>> +	 *   indicates max qp available for asymmetric operations.

>> +	 *

>> +	 * - if device support only symmetric, then max_nb_queue_pair

>> +	 *   indicates max qp available for symmetric operations.

>> +	 *

>> +	 * - if device support both symmetric and asymmetric crypto op,

>> +	 *   then max_nb_queue_pair indicates total number of available

>> +	 *   qp for both operations.

>> +	 *

>> +	 * **Special note on devices supporting symm and asymm:

>> +	 *

>> +	 * Such dual function devices may manage qp in various possible ways.

>> +	 * They can either:

>> +	 *

>> +	 * 1. Use all max_nb_queue_pair for any operation type.

>> +	 *    In such case, app can configure any of the available qp

>> +	 *    for any operaiton. Thus,

>> +	 *    dev_info should return num queue pair distribution as mentioned

>> +	 *    in row 'symm+asymm w/ all qp' in table above

>> +	 *

>> +	 * 2. Or, use dedicated set of qp for each op

>> +	 *    Such device PMDs, can take 2 approaches:

>> +	 *    1. Either, it can show up as 2 separate PMDs where one as

>> +	 *	 symmetric only and other asymmetric only. in such case,

>> +	 *	 device info will return num queue pair distribution as

>> +	 *	 mentioned in row 'symmetric/asymmetric only' device

>> +	 *

>> +	 *    2. Or, can appear as one PMD with number of queue pair dedicated

>> +	 *	 to each operation in max_nb_symm_qp and max_nb_asymm_qp

>> +	 *

>> +	 */

>>

>>  	struct {

>>  		unsigned max_nb_sessions;

>> -		/**< Maximum number of sessions supported by device. */

>> +		/**< Maximum number of sessions supported

>> +		 * for symmetric operations.

>> +		 */

>>  		unsigned int max_nb_sessions_per_qp;

>> -		/**< Maximum number of sessions per queue pair.

>> +		/**< Maximum number of symmetric sessions

>> +		 * per queue pair.

>>  		 * Default 0 for infinite sessions

>>  		 */

>> +		 unsigned int max_nb_sym_qp;

>> +		/**< Maximum num of qp dedicated to symmetric op.

>> +		 * NA for device that support symmetric only.

>> +		 * 0 means device can use all max_nb_queue_pair

>> +		 * for symm op.

>> +		 * Please note, this variable only tells number of queue pairs

>> +		 * that can be enqueued with symmetric ops and doesn't reveal

>> +		 * specific IDs used by PMDs for this operation

>> +		 *

>> +		 */

>>  	} sym;

>> +

>> +	struct {

>> +		unsigned int max_nb_asym_sessions;

>> +		/**< Maximum number of asymmetric sessions supported by device.

>> +		 * 0 infinite as long as resources are available

>> +		 */

>> +		unsigned int max_nb_asym_sessions_per_qp;

>> +		/**< Maximum number of asymmetric sessions per queue pair.

>> +		 * 0 means infinite as long as resources are available

>> +		 */

>> +		unsigned int max_nb_asym_qp;

>> +		/**< Maximum number of qp dedicated for asymm operation.

>> +		 * 0 means device can use all max_nb_queue_pair for asymm op.

>> +		 * Please note, this variable only tells number of queue pairs

>> +		 * that can be enqueued with asymmetric ops and doesn't reveal

>> +		 * specific IDs used by PMDs for this operation

>> +		 *

>> +		 */

>> +	} asym;

>>  };

>>

>>  #define RTE_CRYPTODEV_DETACHED  (0)

>> @@ -513,6 +677,24 @@ struct rte_cryptodev_config {

>>  	int socket_id;			/**< Socket to allocate resources on */

>>  	uint16_t nb_queue_pairs;

>>  	/**< Number of queue pairs to configure on device */

>> +

>> +	uint16_t nb_symm_qp;

>> +	/**< Number of queue pair to be used for symmetric operations.

>> +	 * Optional input.

>> +	 * Valid for device supporting both symmetric and asymmetric.

>> +	 * Should be less than equal to rte_cryptodev_info:max_nb_symm_qp.

>> +	 * please note this number only tells how many queue pair to be used

>> +	 * for symmetric op and does *not* tell specific IDs to be used.

>> +	 */

>> +

>> +	uint16_t nb_asymm_qp;

>> +	/**< Number of queue pair to be used for asymmetric operations.

>> +	 * Optional input.

>> +	 * Valid for device supporting both asymmetric and symmetric.

>> +	 * Should be less than equal to rte_cryptodev_info:max_nb_asymm_qp

>> +	 * Please note this number only tells how many queue pair to be

>> +	 * used for asymmetric and does *not* specifically tell qp ID

>> +	 */

>>  };

>>

>[Fiona] The params from config structure above should be used to set the values in the data structure

>This code is missing.

>

>>  /**

>> @@ -595,6 +777,9 @@ struct rte_cryptodev_config {

>>   * @return

>>   *   - 0: Success, queue pair correctly set up.

>>   *   - <0: Queue pair configuration failed

>> + *

>> + * @note: queue pair to be setup independent of operation type.

>> + *

>>   */

>>  extern int

>>  rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,

>> @@ -644,6 +829,26 @@ struct rte_cryptodev_config {

>>  extern uint16_t

>>  rte_cryptodev_queue_pair_count(uint8_t dev_id);

>>

>> +/**

>> + * Get the number of symmetric queue pairs on this crypto device

>> + *

>> + * @param	dev_id		Crypto device identifier.

>> + * @return

>> + *   - The number of configured symmetric queue pairs.

>> + */

>> +extern uint16_t

>> +rte_cryptodev_sym_queue_pair_count(uint8_t dev_id);

>> +

>> +

>> +/**

>> + * Get the number of asymmetric queue pairs on this crypto device

>> + *

>> + * @param	dev_id		Crypto device identifier.

>> + * @return

>> + *   - The number of configured asymmetric queue pairs.

>> + */

>> +extern uint16_t

>> +rte_cryptodev_asym_queue_pair_count(uint8_t dev_id);

>>

>>  /**

>>   * Retrieve the general I/O statistics of a device.

>> @@ -795,6 +1000,10 @@ struct rte_cryptodev_data {

>>  	/**< Array of pointers to queue pairs. */

>>  	uint16_t nb_queue_pairs;

>>  	/**< Number of device queue pairs. */

>> +	uint16_t nb_sym_qp;

>> +	/**< Number of symmetric queue pairs. */

>> +	uint16_t nb_asym_qp;

>> +	/**< Number of asymmetric queue pairs. */

>>

>>  	void *dev_private;

>>  	/**< PMD-specific private data */

>> @@ -900,6 +1109,11 @@ struct rte_cryptodev_sym_session {

>>  	/**< Private session material */

>>  };

>>

>> +/** Cryptodev asymmetric crypto session */

>> +struct rte_cryptodev_asym_session {

>> +	__extension__ void *sess_private_data[0];

>> +	/**< Private asymmetric session material */

>> +};

>>

>>  /**

>>   * Create symmetric crypto session header (generic with no private data)

>> @@ -914,6 +1128,18 @@ struct rte_cryptodev_sym_session *

>>  rte_cryptodev_sym_session_create(struct rte_mempool *mempool);

>>

>>  /**

>> + * Create asymmetric crypto session header (generic with no private data)

>> + *

>> + * @param   mempool    mempool to allocate asymmetric session

>> + *                     objects from

>> + * @return

>> + *  - On success return pointer to asym-session

>> + *  - On failure returns NULL

>> + */

>> +struct rte_cryptodev_asym_session *

>> +rte_cryptodev_asym_session_create(struct rte_mempool *mempool);

>> +

>> +/**

>>   * Frees symmetric crypto session header, after checking that all

>>   * the device private data has been freed, returning it

>>   * to its original mempool.

>> @@ -929,6 +1155,21 @@ struct rte_cryptodev_sym_session *

>>  rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess);

>>

>>  /**

>> + * Frees asymmetric crypto session header, after checking that all

>> + * the device private data has been freed, returning it

>> + * to its original mempool.

>> + *

>> + * @param   sess     Session header to be freed.

>> + *

>> + * @return

>> + *  - 0 if successful.

>> + *  - -EINVAL if session is NULL.

>> + *  - -EBUSY if not all device private data has been freed.

>> + */

>> +int

>> +rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess);

>> +

>> +/**

>>   * Fill out private data for the device id, based on its device type.

>>   *

>>   * @param   dev_id   ID of device that we want the session to be used on

>> @@ -950,6 +1191,27 @@ struct rte_cryptodev_sym_session *

>>  			struct rte_mempool *mempool);

>>

>>  /**

>> + * Initialize asymmetric session on a device with specific asymmetric xform

>> + *

>> + * @param   dev_id   ID of device that we want the session to be used on

>> + * @param   sess     Session to be set up on a device

>> + * @param   xforms   Asymmetric crypto transform operations to apply on flow

>> + *                   processed with this session

>> + * @param   mempool  Mempool to be used for internal allocation.

>> + *

>> + * @return

>> + *  - On success, zero.

>> + *  - -EINVAL if input parameters are invalid.

>> + *  - -ENOTSUP if crypto device does not support the crypto transform.

>> + *  - -ENOMEM if the private session could not be allocated.

>> + */

>> +int

>> +rte_cryptodev_asym_session_init(uint8_t dev_id,

>> +			struct rte_cryptodev_asym_session *sess,

>> +			struct rte_crypto_asym_xform *xforms,

>> +			struct rte_mempool *mempool);

>> +

>> +/**

>>   * Frees private data for the device id, based on its device type,

>>   * returning it to its mempool.

>>   *

>> @@ -965,7 +1227,23 @@ struct rte_cryptodev_sym_session *

>>  			struct rte_cryptodev_sym_session *sess);

>>

>>  /**

>> + * Frees resources held by asymmetric session during rte_cryptodev_session_init

>> + *

>> + * @param   dev_id   ID of device that uses the asymmetric session.

>> + * @param   sess     Asymmetric session setup on device using

>> + *					 rte_cryptodev_session_init

>> + * @return

>> + *  - 0 if successful.

>> + *  - -EINVAL if device is invalid or session is NULL.

>> + */

>> +int

>> +rte_cryptodev_asym_session_clear(uint8_t dev_id,

>> +			struct rte_cryptodev_asym_session *sess);

>> +

>> +/**

>>   * Get the size of the header session, for all registered drivers.

>> + * For devices supporting both symmetric and asymmetric, it should

>> + * return header size inclusive of both

>[Fiona] ? This API is not called on a device.

>As the hdr size is just a list of pointers, it's independent of sym/asym

>

>>   *

>>   * @return

>>   *   Size of the header session.

>> @@ -975,6 +1253,8 @@ struct rte_cryptodev_sym_session *

>>

>>  /**

>>   * Get the size of the private session data for a device.

>> + * if device support both symmetric and asymmetric, it

>> + * return size inclusive of both

>[Fiona] Are you suggesting the same session pool might be used

>for both sym and asym sessions?

>Seems unlikely, but if an application chose to, it seems better

> that it would do it explicitly,

>e.g. get asym and sym private sizes, same as it gets size from the other

>drivers and sizes for the maximum.

>If meaning is changed as you suggest then sym applications already

>implemented will likely end up with pools sized for a session size they don’t need.

>

>As I think the combined pool case unlikely, it makes more sense to me that this

>fn should have comment changed to say it returns only sym session size

>for backwards capability reasons, but will be deprecated

>and appls should use get_sym_session_private_size instead.

>

>>   *

>>   * @param	dev_id		The device identifier.

>>   *

>> @@ -986,6 +1266,32 @@ struct rte_cryptodev_sym_session *

>>  rte_cryptodev_get_private_session_size(uint8_t dev_id);

>>

>>  /**

>> + * Get the size of the private data for symmetric session

>> + * on device

>> + *

>> + * @param	dev_id		The device identifier.

>> + *

>> + * @return

>> + *   - Size of the symmetric session private data, if successful

>> + *   - 0 if device is invalid or does not have private session

>> + */

>> +unsigned int

>> +rte_cryptodev_get_sym_session_private_size(uint8_t dev_id);

>> +

>> +/**

>> + * Get the size of the private data for asymmetric session

>> + * on device

>> + *

>> + * @param	dev_id		The device identifier.

>> + *

>> + * @return

>> + *   - Size of the asymmetric private data, if successful

>> + *   - 0 if device is invalid or does not have private session

>> + */

>> +unsigned int

>> +rte_cryptodev_get_asym_session_private_size(uint8_t dev_id);

>> +

>> +/**

>>   * Attach queue pair with sym session.

>>   *

>>   * @param	dev_id		Device to which the session will be attached.

>> @@ -1002,6 +1308,31 @@ struct rte_cryptodev_sym_session *

>>  		struct rte_cryptodev_sym_session *session);

>>

>>  /**

>> + * Attach queue pair with asym session.

>> + *

>> + * @param	dev_id		Device to which the session is attached.

>> + * @param	qp_id		Queue pair to which the session will be

>> + *				attached.

>> + * @param	session		Asymmetric Session pointer previously

>> + *				allocated by

>> + *				*rte_cryptodev_asym_session_create*.

>> + *

>> + * @return

>> + *  - On success, zero.

>> + *  - On failure, a negative value.

>> + *

>> + * @note : app can dedicate a qp_id to specific operation type:symm/asymm

>> + * by calling rte_cryptodev_queue_pair_attach_sym/asym_session() before

>> + * enqueue_burst() call. PMD with SYMMETRIC & ASYMMETRIC feature flag set,

>> + * can internally bind the logical qp_id to actual physical qp_id here and

>> + * dedicate specific qp_id to perform specific op_type(symmetric or

>> + * asymmetric).

>> + */

>> +int

>> +rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,

>> +		struct rte_cryptodev_asym_session *session);

>> +

>> +/**

>>   * Detach queue pair with sym session.

>>   *

>>   * @param	dev_id		Device to which the session is attached.

>> @@ -1018,6 +1349,23 @@ struct rte_cryptodev_sym_session *

>>  		struct rte_cryptodev_sym_session *session);

>>

>>  /**

>> + * Detach queue pair from asym session.

>> + *

>> + * @param	dev_id		Device to which the session is attached.

>> + * @param	qp_id		Queue pair to which the session is attached.

>> + * @param	session		Asymmetric Session pointer previously attached

>> + *				by calling

>> + *				*rte_cryptodev_queue_pair_attach_asym_session*.

>> + *

>> + * @return

>> + *  - On success, zero.

>> + *  - On failure, a negative value.

>> + */

>> +int

>> +rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,

>> +		struct rte_cryptodev_asym_session *session);

>> +

>> +/**

>>   * Provide driver identifier.

>>   *

>>   * @param name

>> diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.c b/lib/librte_cryptodev/rte_cryptodev_pmd.c

>> index f2aac24..4439a8e 100644

>> --- a/lib/librte_cryptodev/rte_cryptodev_pmd.c

>> +++ b/lib/librte_cryptodev/rte_cryptodev_pmd.c

>> @@ -66,6 +66,20 @@

>>  			goto free_kvlist;

>>

>>  		ret = rte_kvargs_process(kvlist,

>> +				RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,

>> +				&rte_cryptodev_pmd_parse_uint_arg,

>> +				&params->max_nb_asym_qp);

>> +		if (ret < 0)

>> +			goto free_kvlist;

>> +

>> +		ret = rte_kvargs_process(kvlist,

>> +				RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG,

>> +				&rte_cryptodev_pmd_parse_uint_arg,

>> +				&params->max_nb_sym_qp);

>> +		if (ret < 0)

>> +			goto free_kvlist;

>> +

>[Fiona] "max_nb_queue_pair" is passed in to args and parsed. Stored in init_params,

>passed to device creation. And then ignored, not used at all. So no need to add new

>max_nb_asym_qp and max_nb_sym_qp to either args or init_params. They're not

>used either in this RFC.

>We should deprecate the current param from args and init_params.

>

>PMDs hardcode the value they return in rte_cryptodev_info.

>> +		ret = rte_kvargs_process(kvlist,

>>  				RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,

>>  				&rte_cryptodev_pmd_parse_uint_arg,

>>  				&params->max_nb_sessions);

>> @@ -109,9 +123,12 @@ struct rte_cryptodev *

>>  			device->driver->name, name);

>>

>>  	CDEV_LOG_INFO("[%s] - Initialisation parameters - name: %s,"

>> -			"socket id: %d, max queue pairs: %u, max sessions: %u",

>> +			"socket id: %d, max queue pairs: %u, "

>> +			"max sym queue paid: %u, max asym queue pair %u, "

>> +			"max sessions: %u",

>>  			device->driver->name, name,

>>  			params->socket_id, params->max_nb_queue_pairs,

>> +			params->max_nb_asym_qp, params->max_nb_sym_qp,

>>  			params->max_nb_sessions);

>>

>>  	/* allocate device structure */

>> diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h

>> index 089848e..272b489 100644

>> --- a/lib/librte_cryptodev/rte_cryptodev_pmd.h

>> +++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h

>> @@ -60,18 +60,25 @@

>>

>>  #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS	8

>>  #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SESSIONS	2048

>> +/* Allow all qp to be used for sym */

>> +#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SYM_QP		0

>> +/* Allow all qp to be used for asym */

>> +#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_ASYM_QP	0

>>

>>  #define RTE_CRYPTODEV_PMD_NAME_ARG			("name")

>>  #define RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG			("max_nb_queue_pairs")

>>  #define RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG		("max_nb_sessions")

>>  #define RTE_CRYPTODEV_PMD_SOCKET_ID_ARG			("socket_id")

>> -

>> +#define RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG		("max_nb_asym_qp")

>> +#define RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG		("max_nb_sym_qp")

>>

>>  static const char * const cryptodev_pmd_valid_params[] = {

>>  	RTE_CRYPTODEV_PMD_NAME_ARG,

>>  	RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,

>>  	RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,

>> -	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG

>> +	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,

>> +	RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,

>> +	RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG

>>  };

>>

>>  /**

>> @@ -84,6 +91,10 @@ struct rte_cryptodev_pmd_init_params {

>>  	int socket_id;

>>  	unsigned int max_nb_queue_pairs;

>>  	unsigned int max_nb_sessions;

>> +	unsigned int max_nb_asym_qp;

>> +	/**< maximum number of qp to be used for asymmetric ops */

>> +	unsigned int max_nb_sym_qp;

>> +	/**< maximum number of qp to be used for symmetric ops */

>>  };

>>

>>  /** Global structure used for maintaining state of allocated crypto devices */

>> @@ -275,7 +286,29 @@ typedef int (*cryptodev_queue_pair_release_t)(struct rte_cryptodev *dev,

>>  typedef uint32_t (*cryptodev_queue_pair_count_t)(struct rte_cryptodev *dev);

>>

>>  /**

>> - * Create a session mempool to allocate sessions from

>> + * Get number of available symmetric queue pairs of a device.

>> + *

>> + * @param	dev	Crypto device pointer

>> + *

>> + * @return

>> + * - Returns number of symmetric queue pairs

>> + */

>> +typedef uint32_t (*cryptodev_sym_queue_pair_count_t)(

>> +			struct rte_cryptodev *dev);

>> +

>> +/**

>> + * Get number of available asymmetric queue pairs of a device.

>> + *

>> + * @param	dev	Crypto device pointer

>> + *

>> + * @return

>> + * - Returns number of symmetric queue pairs

>> + */

>> +typedef uint32_t (*cryptodev_asym_queue_pair_count_t)(

>> +			struct rte_cryptodev *dev);

>> +

>[Fiona] Is something calling either of above fns? If not better to remove the asym one.

>The sym one should be deprecated and removed in a separate patch.

>

>> +/**

>> + * Create a symmetric session mempool to allocate sessions from

>>   *

>>   * @param	dev		Crypto device pointer

>>   * @param	nb_objs		number of sessions objects in mempool

>> @@ -290,6 +323,21 @@ typedef int (*cryptodev_sym_create_session_pool_t)(

>>  		struct rte_cryptodev *dev, unsigned nb_objs,

>>  		unsigned obj_cache_size, int socket_id);

>>

>> +/**

>> + * Create a asymmetric session mempool to allocate sessions from

>> + *

>> + * @param	dev		Crypto device pointer

>> + * @param	nb_objs		Number of asymmetric sessions objects in mempool

>> + * @param	obj_cache	l-core object cache size, see *rte_ring_create*

>> + * @param	socket_id	Socket Id to allocate  mempool on.

>> + *

>> + * @return

>> + * - On success returns a pointer to a rte_mempool

>> + * - On failure returns a NULL pointer

>> + */

>> +typedef int (*cryptodev_asym_create_session_pool_t)(

>> +		struct rte_cryptodev *dev, unsigned nb_objs,

>> +		unsigned obj_cache_size, int socket_id);

>>

>[Fiona] session pools are not created now per device so this is never called for sym and

>should be deprecated. So no need to add for asym

>

>>  /**

>>   * Get the size of a cryptodev session

>> @@ -302,6 +350,17 @@ typedef int (*cryptodev_sym_create_session_pool_t)(

>>   */

>>  typedef unsigned (*cryptodev_sym_get_session_private_size_t)(

>>  		struct rte_cryptodev *dev);

>> +/**

>> + * Get the size of a asymmetric cryptodev session

>> + *

>> + * @param	dev		Crypto device pointer

>> + *

>> + * @return

>> + *  - On success returns the size of the session structure for device

>> + *  - On failure returns 0

>> + */

>> +typedef unsigned (*cryptodev_asym_get_session_private_size_t)(

>> +		struct rte_cryptodev *dev);

>>

>>  /**

>>   * Configure a Crypto session on a device.

>> @@ -321,7 +380,24 @@ typedef int (*cryptodev_sym_configure_session_t)(struct rte_cryptodev *dev,

>>  		struct rte_crypto_sym_xform *xform,

>>  		struct rte_cryptodev_sym_session *session,

>>  		struct rte_mempool *mp);

>> -

>> +/**

>> + * Configure a Crypto asymmetric session on a device.

>> + *

>> + * @param	dev		Crypto device pointer

>> + * @param	xform		Single or chain of crypto xforms

>> + * @param	priv_sess	Pointer to cryptodev's private session structure

>> + * @param	mp		Mempool where the private session is allocated

>> + *

>> + * @return

>> + *  - Returns 0 if private session structure have been created successfully.

>> + *  - Returns -EINVAL if input parameters are invalid.

>> + *  - Returns -ENOTSUP if crypto device does not support the crypto transform.

>> + *  - Returns -ENOMEM if the private session could not be allocated.

>> + */

>> +typedef int (*cryptodev_asym_configure_session_t)(struct rte_cryptodev *dev,

>> +		struct rte_crypto_asym_xform *xform,

>> +		struct rte_cryptodev_asym_session *session,

>> +		struct rte_mempool *mp);

>>  /**

>>   * Free driver private session data.

>>   *

>> @@ -332,6 +408,15 @@ typedef void (*cryptodev_sym_free_session_t)(struct rte_cryptodev *dev,

>>  		struct rte_cryptodev_sym_session *sess);

>>

>>  /**

>> + * Free asymmetric session private data.

>> + *

>> + * @param	dev		Crypto device pointer

>> + * @param	sess		Cryptodev session structure

>> + */

>> +typedef void (*cryptodev_asym_free_session_t)(struct rte_cryptodev *dev,

>> +		struct rte_cryptodev_asym_session *sess);

>> +

>> +/**

>>   * Optional API for drivers to attach sessions with queue pair.

>>   * @param	dev		Crypto device pointer

>>   * @param	qp_id		queue pair id for attaching session

>> @@ -343,6 +428,18 @@ typedef int (*cryptodev_sym_queue_pair_attach_session_t)(

>>  		  struct rte_cryptodev *dev,

>>  		  uint16_t qp_id,

>>  		  void *session_private);

>> +/**

>> + * Optional API for drivers to attach asymmetric session with queue pair.

>> + * @param	dev		Crypto device pointer

>> + * @param	qp_id		Queue pair id for attaching session

>> + * @param	priv_sess       Pointer to cryptodev's private session structure

>> + * @return

>> + *  - Return 0 on success

>> + */

>> +typedef int (*cryptodev_asym_queue_pair_attach_session_t)(

>> +		  struct rte_cryptodev *dev,

>> +		  uint16_t qp_id,

>> +		  void *session_private);

>>

>>  /**

>>   * Optional API for drivers to detach sessions from queue pair.

>> @@ -357,6 +454,19 @@ typedef int (*cryptodev_sym_queue_pair_detach_session_t)(

>>  		  uint16_t qp_id,

>>  		  void *session_private);

>>

>> +/**

>> + * Optional API for drivers to detach asymmetric session from queue pair.

>> + * @param	dev		Crypto device pointer

>> + * @param	qp_id		queue pair id for detaching session

>> + * @param	priv_sess       Pointer to cryptodev's private session structure

>> + * @return

>> + *  - Return 0 on success

>> + */

>> +typedef int (*cryptodev_asym_queue_pair_detach_session_t)(

>> +		  struct rte_cryptodev *dev,

>> +		  uint16_t qp_id,

>> +		  void *session_private);

>> +

>>  /** Crypto device operations function pointer table */

>>  struct rte_cryptodev_ops {

>>  	cryptodev_configure_t dev_configure;	/**< Configure device. */

>> @@ -380,17 +490,32 @@ struct rte_cryptodev_ops {

>>  	cryptodev_queue_pair_stop_t queue_pair_stop;

>>  	/**< Stop a queue pair. */

>>  	cryptodev_queue_pair_count_t queue_pair_count;

>> -	/**< Get count of the queue pairs. */

>> -

>> +	/**< Get total count of the queue pairs(symmetric+asymmetric). */

>> +	cryptodev_sym_queue_pair_count_t sym_queue_pair_count;

>> +	/**< Get count of the symmetric queue pairs. */

>> +	cryptodev_asym_queue_pair_count_t asym_queue_pair_count;

>> +	/**< Get count of the asymmetric queue pairs. */

>>  	cryptodev_sym_get_session_private_size_t session_get_size;

>> -	/**< Return private session. */

>> +	/**< Return private size for a session */

>> +	cryptodev_sym_get_session_private_size_t sym_session_get_size;

>> +	/**< Return private size for symmetric crypto. */

>> +	cryptodev_sym_get_session_private_size_t asym_session_get_size;

>> +	/**< Return private size for asymmetric crypto. */

>>  	cryptodev_sym_configure_session_t session_configure;

>>  	/**< Configure a Crypto session. */

>[Fiona] This should really be renamed sym_session_configure, same for session_clear,

>qp_attach_session and qp_detach_session

>

>> +	cryptodev_asym_configure_session_t asym_session_configure;

>> +	/**< Configure asymmetric Crypto session. */

>>  	cryptodev_sym_free_session_t session_clear;

>>  	/**< Clear a Crypto sessions private data. */

>> +	cryptodev_asym_free_session_t asym_session_clear;

>> +	/**< Clear a Crypto sessions private data. */

>>  	cryptodev_sym_queue_pair_attach_session_t qp_attach_session;

>>  	/**< Attach session to queue pair. */

>> -	cryptodev_sym_queue_pair_detach_session_t qp_detach_session;

>> +	cryptodev_asym_queue_pair_attach_session_t asym_qp_attach_session;

>> +	/**< Attach asymmetric session to queue pair. */

>> +	cryptodev_sym_queue_pair_attach_session_t qp_detach_session;

>> +	/**< Detach session from queue pair. */

>[Fiona] typo (based on a typo I think was fixed in a recent patch)

>> +	cryptodev_asym_queue_pair_attach_session_t asym_qp_detach_session;

>>  	/**< Detach session from queue pair. */

>>  };

>>

>> @@ -535,6 +660,19 @@ uint8_t rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,

>>  	sess->sess_private_data[driver_id] = private_data;

>>  }

>>

>> +static inline void *

>> +get_asym_session_private_data(const struct rte_cryptodev_asym_session *sess,

>> +		uint8_t driver_id) {

>> +	return sess->sess_private_data[driver_id];

>> +}

>> +

>> +static inline void

>> +set_asym_session_private_data(struct rte_cryptodev_asym_session *sess,

>> +		uint8_t driver_id, void *private_data)

>> +{

>> +	sess->sess_private_data[driver_id] = private_data;

>> +}

>> +

>>  #ifdef __cplusplus

>>  }

>>  #endif

>> diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map

>> b/lib/librte_cryptodev/rte_cryptodev_version.map

>> index eb47308..323294a 100644

>> --- a/lib/librte_cryptodev/rte_cryptodev_version.map

>> +++ b/lib/librte_cryptodev/rte_cryptodev_version.map

>> @@ -85,3 +85,24 @@ DPDK_17.11 {

>>  	rte_cryptodev_pmd_parse_input_args;

>>

>>  } DPDK_17.08;

>> +

>> +EXPERIMENTAL {

>> +	global:

>> +

>[Fiona] the implementation of all these APIs also needs the _experimental tag.

>

>> +	rte_cryptodev_asym_capability_get;

>> +	rte_cryptodev_asym_capability_modlen;

>> +	rte_cryptodev_asym_queue_pair_count;

>> +	rte_cryptodev_asym_session_create;

>> +	rte_cryptodev_asym_session_clear;

>> +	rte_cryptodev_asym_session_free;

>> +	rte_cryptodev_asym_session_init;

>> +	rte_cryptodev_get_asym_session_private_size;

>> +	rte_cryptodev_get_sym_session_private_size;

>> +	rte_cryptodev_get_xform_algo_enum;

>> +	rte_cryptodev_queue_pair_attach_asym_session;

>> +	rte_cryptodev_queue_pair_detach_asym_session;

>> +	rte_cryptodev_sym_queue_pair_count;

>> +	rte_crypto_asym_xform_strings;

>> +	rte_crypto_asym_operation_strings;

>> +

>> +};

>> --

>> 1.9.1
  
Fiona Trahe Feb. 15, 2018, 11:46 a.m. UTC | #3
Hi Shally,

> -----Original Message-----

> From: Verma, Shally [mailto:Shally.Verma@cavium.com]

> Sent: Thursday, February 15, 2018 5:33 AM

> To: Trahe, Fiona <fiona.trahe@intel.com>; dev@dpdk.org; Athreya, Narayana Prasad

> <NarayanaPrasad.Athreya@cavium.com>; Murthy, Nidadavolu <Nidadavolu.Murthy@cavium.com>;

> Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish <Ashish.Gupta@cavium.com>; Doherty, Declan

> <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>; Griffin, John

> <john.griffin@intel.com>

> Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

> Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> 

> HI Fiona

> 

> Thanks for your feedback. Response below.

> 

> >-----Original Message-----

> >From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

> >Sent: 09 February 2018 23:43

> >To: dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>; Murthy,

> Nidadavolu

> ><Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish

> <Ashish.Gupta@cavium.com>; Verma,

> >Shally <Shally.Verma@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A

> <brian.a.keating@intel.com>;

> >Griffin, John <john.griffin@intel.com>

> >Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

> >Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> >

> >Hi Shally,

> >Comments below.

> >

> >> -----Original Message-----

> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

> >> Sent: Tuesday, January 23, 2018 9:54 AM

> >> To: Doherty, Declan <declan.doherty@intel.com>

> >> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

> >> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

> >> <sverma@caviumnetworks.com>

> >> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> >>

> >> From: Shally Verma <sverma@caviumnetworks.com>

> >>

> >> Add support for asymmetric crypto operations in DPDK lib cryptodev

> >>

> >> Key feature include:

> >> - Only session based asymmetric crypto operations

> >> - new get and set APIs for symmetric and asymmetric session private

> >>   data and other informations

> >> - APIs to create, configure and attch queue pair to asymmetric sessions

> >> - new capabilities in struct device_info to indicate

> >>   -- number of dedicated queue pairs available for symmetric and

> >>      asymmetric operations, if any

> >>   -- number of asymmetric sessions possible per qp

> >>

> >[Fiona] Though it's probably premature to include on the API have you considered

> >providing for pre-loaded keys in future, i.e. the ability to wrap keys or refer to keys

> >already stored securely on the device, as an alternative to passing the keys on the API?

> >

> [Shally] Current intention of DPDK asym spec is to expose HW capabilities to application to offload these

> compute intensive ops.

> Though your use-case is very much a practical requirement , but to achieve this I believe we need a layer

> above this spec and need different interfaces. Such as, some public/secure key library which provide

> interfaces to generate / store/ perform op using an opaque key handles which internally can use DPDK

> to do part of it. For such case, I envision dpdk (or library above) will likely run on some secure processor.

> Thus, currently I kept such use-case out of current spec scope.

[Fiona] ok

> >

> >> Proposed asymmetric cryptographic operations are:

> >> - rsa

> >> - dsa

> >> - deffie-hellman key pair generation and shared key computation

> >> - ecdeffie-hellman

> >> - fundamental elliptic curve operations

> >> - elliptic curve DSA

> >> - modular exponentiation and inversion

> >>

> >> This patch primarily defines PMD operations and device capabilities

> >> to perform asymmetric crypto ops on queue pairs and intend to

> >> invite feedbacks on current proposal so as to ensure it encompass

> >> all kind of crypto devices with different capabilities and queue

> >> pair management.

> >>

> >> List of TBDs:

> >> - Currently, patch only updated for RSA xform and associated params.

> >>   Other algoritms to be added in subsequent versions.

> >> - per-service stats update

> >>

> >> Signed-off-by: Shally Verma <sverma@caviumnetworks.com>

> >> ---

> >>

> >> It is derivative of RFC v2 asymmetric crypto patch series initiated by

> >> Umesh Kartha(mailto:umesh.kartha@caviumnetworks.com):

> >>

> >>  http://dpdk.org/dev/patchwork/patch/24245/

> >>  http://dpdk.org/dev/patchwork/patch/24246/

> >>  http://dpdk.org/dev/patchwork/patch/24247/

> >>

> >> And inclusive of all review comments given on RFC v2.

> >>  ( See complete discussion thread here:

> >> http://dev.dpdk.narkive.com/yqTFFLHw/dpdk-dev-rfc-specifications-for-asymmetric-crypto-

> >> algorithms#post12)

> >>

> >> Some of the RFCv2 Review comments pending for closure:

> >> > " [Fiona] The count fn isn't used at all for sym - probably no need to add for asym

> >>      better instead to remove the sym fn."

> >>

> >>      It is still present in dpdk-next-crypto for sym, so what has been decision

> >>      on it?

> >[Fiona] No change. The rte_cryptodev_ops fn is still not called so useless and should be removed.

> >rte_cryptodev_queue_pair_count() returns the num_qps configured in

> >rte_cryptodev_configure(), but never calls the PMD dev_ops.queue_pair_count().

> >So cryptodev_sym_queue_pair_count_t should be deprecated.

> >And no point in adding one for asym.

> >

> 

> [Shally] Ok

> 

> >>

> >> >"[Fiona] if each qp can handle only a specific service, i.e. a subset off the capabilities

> >>     Indicated by the device capability list, there's a need for a new API to query

> >>     the capability of a qp."

> >>

> >>     Current proposal doesn’t distinguish between device capability and qp capability.

> >>     It rather leave such differences handling internal to PMDs. Thus no capability

> >>     or API added for qp in current version. It is subject to revisit based on review

> >>     feedback on current proposal.

> >[Fiona] This would not work for some devices, comments below.

> >

> >>

> >> - Sessionless Support.

> >>     Current proposal only support Session-based because:

> >>      1. All one-time setup i.e.  algos and associated params, such as, public-private keys

> >>         or modulus length can be done in control path using session-init API

> >>      2. it’s an easier way to dedicate qp to do specific service (using queue_pair_attach())

> >>         which cannot be case in sessionless

> >>      3. Couldn’t find any significant advantage going sessionless way. Also existing most of PMDs are

> >> session-based.

> >>

> >>     It could be added in subsequent versions, if requirement is identified, based on review comment

> >>     on this RFC.

> >[Fiona] Our preference would be for sessionless, as it would need fewer API calls (no

> session_create/session_clear)

> >and e.g. DH and ECDH sessions are likely to be only used for a single op. However this is not a blocker

> for

> >this API, we can POC it later and propose an extension to the API if it gives a performance

> improvement.

> >

> [Shally] You mean you recommend to have session-less support along with session-based?

[Fiona] Yes. But as stated, it's ok to start without it and add later.


> >>

> >> Summary

> >> -------

> >>

> >> This section provides an overview of key feature enabled in current specification.

> >> It comprise of key design challenges as have been identified on RFCv2 and

> >> summary description of new interfaces and definitions added to handle same.

> >>

> >> Description

> >> -----------

> >>

> >> This API set assumes that the max_nb_queue_pairs on a

> >> device can be allocated to any mix of sym or asym. Some devices

> >> may have a fixed max per service. Thus, rte_cryptodev_info

> >> is updated with max_sym_nb_queues and max_asym_nb_queues with rule:

> >>

> >> max_nb_queue_pair = max_nb_sym_qp + max_nb_asym_qp.

> >>

> >> If device has no restrictions on qp to be used per service, such PMDs can leave

> >> max_nb_sym_qp = max_nb_asym_qp = 0. In such case, application can setup any of

> >> the service upto limit defined by max_nb_queue_pair.

> >[Fiona] This seems awkward if a genuine 0  e.g. An appl wants to set up a sym qp, and

> >sees that max_nb_queue_pair=4. Can't trust this - needs to look deeper. Sees

> >max_nb_sym_qp=0. Doesn't know if that means it can set up 4 sym qps or no qps

> >until it also checks max_nb_asym_qp. If=4 then it can't set up any sym qp, if=0 it can set up 4.

> >Would it be better if

> >	max_nb_queue_pair = max(max_nb_sym_qp, max_nb_asym_qp).

> >	max_nb_sym_qp = 0..max_nb_queue_pair

> >	max_nb_asym_qp = 0..max_nb_queue_pair

> >

> 

> [Shally] Ok. I can change definition to replace 0 by max num for no-limit case with slight modification  to

> the condition i.e.

> max_nb_queue_pair >=  max(max_nb_sym_qp, max_nb_asym_qp)

> 

> because device can have distribution of (max_nb_queue_pair, max_nb_sym_qp, max_nb_asym_qp) as

> (4,4,4) or (4,3,1)

> where total number of qp setup by application cannot exceed max_nb_queue_pairs.

> 

> >> Here, max_nb_sym_qp and max_nb_asym_qp, if non-zero, just define limit on qp which are

> >> available for each service and *are not* ids to be used during qp setup and enqueue i.e.

> >> if device supports both symmetric and asymmetric with n qp, then any of them

> >> can be configured for symmetric or asymmetric subject to limit defined by

> >> max_nb_sym_qp and max_nb_asym_qp. For example,

> >> if device has 6 queues and 5 for symmetric and 1 for asymmetric that imply

> >> application can setup only 1 out of any 6 qp for asymmetric and rest for

> >> symmetric.

> >>

> >> Additionally, application can dedicate qp to perform specific service via optional

> >> queue_pair_attach_sym/asym_session() API.

> >[Fiona] This is too late - some devices have qps which need to know at setup which

> >service they'll be used for, as they reserve resources based on the service.

> >e.g. a device reports in info that it can support qps(max 4, max_sym 2, max asym 2)

> >An application just wants to use 1 sym qp and 1 asym, so configures device with

> >qps(max 2, max_sym 1, max asym 1)

> >Now appl calls qp_setup for qp index 0. Wants to start with running asymmetric

> >service and will set up the symmetric later, maybe in a separate thread.

> >Our devices need to know at setup time which service will be used on the qp.

> >So haven't been given enough information to setup the qp.

> >

> >Even if the PMD could set up service-agnostic qps and just map later, you

> >suggest the qp_attach_sym/asym_session() would be optional. How could the appl

> >make the decision whether to call it or not in above case? It needs to know whether

> >the created qp is agnostic or not, so a capability must be reported by the PMD.

> >OR the API should not be optional, must be called for every session.

> >But that's perf impacting and not helpful if a device could support service-agnostic qps.

> >

> >I don't have a solution for service-agnostic qps. For our devices that's not necessary.

> >Is it likely that anyone wants to set up a qp to process both sym and asym ops?

> >Is it sufficient to accommodate qps which can support either

> >service, but one must be picked at setup after which the qp supports only that service?

> >How about the following - :

> > - device reports in info qps(max, max_sym, max asym) where

> >	max = max(max_sym, max_asym).

> >	max_sym = 0..max

> >	max_asym = 0..max

> >	So if a device reports 4,2,2, it has 4 total, 2 can be setup for sym, 2 for asym

> >	Or if it reports 4,4,4, all 4 of them can be setup as sym or all 4 as

> >	asym or a mix, but total setup can't be more than 4.

> > - appl configures qps(max, max_sym, max_asym)

> >	If it specifies 4,1,3 it wants to use 4 in total, 1 for sym, 3 for asym.

> >	If it specifies 1,1,0 it wants to use 1 in total, 1 for sym, 0 for asym.

> >	The numbers it configures must be <= those reported in info.

> > - appl calls qp_setup(dev, qp, service) where service = sym or asym

> >	qp index must be between 0..max-1

> >	The PMD maps that index to an internal qp which can support the requested service.

> >	If qp_setup is called on an index and the max configured qps have already

> >	been setup for that service then the setup fails.

> >In case the appl forgets which qp it set up for which service, I think it would be necessary to add a new

> API

> >	rte_cryptodev_qp_info() which would return what service is configured on the qp

> >

> >If it's necessary to support service-agnostic qps, then one way would be to specify a third service above

> as

> > - sym+asym.

> >And have devices report max_sym_asym_qps?

> >

> >It's difficult to find a solution for this without breaking the current API - see simpler

> >alternative below.

> >

> >> Except the ones mentioned above, specification doesn't define any restrictions on

> >> enqueue/dequeue API for different crypto services. Application can enqueue both symmetric

> >> and asymmetric operations to same device and qp if device info indicate support of both

> >> symmetric and asymmetric and qp is not dedicated to any. However in practice, it could

> >> result in head-of-line blocking due to the asym ops taking longer than the symmetric ops.

> >>

> >> Some HW accelerators avoid this issue by supporting sym and asym ops

> >> on different qps on the same device.  Such devices can set max_nb_sym_qp and

> >> max_nb_asym_qp to number of queues available for each respective service.

> >>

> >> This may give problem in indexing on enqueue/dequeue i.e.

> >> if 2 asym qps and 2 sym qps are created on the same device,

> >> the queue_pair_ids are duplicated. To handle such scenario,

> >> 2 alternatives are proposed for PMD design:

> >>

> >> 1. Allow all qp to input any operation type virtually. Say,

> >>

> >>     Consider device with symmetric and asymmetric capability having

> >>     max_nb_queue_pair as 6, then by design, all 6 are capable to input

> >>     both op types.

> >>

> >>     If PMD uses fixed set of qp, then internally, can map qp id to

> >>     actual physical qp id to be used according to session/op type.

> >>     If such mapping is done on data path, may impact performance of PMDs.

> >>     Thus, to handle such mapping out of data path, library provides an API

> >>     queue_pair_attach_sym/asym_session() which facilitate application to

> >>     dedicate qp id to perform specific (sym/asym) service in control path

> >>     and should be called before 1st call to enqueue_burst().

> >>     Here PMD can bind app provided logical qp id to actual physical qp id to use

> >>     depending on session type , OR alternatively

> >>

> >> 2. PMDs can split it into two PMDs, one with symmetric ONLY capability and other

> >>     with asymmetric ONLY capability (also proposed by Fiona in RFCv2).

> >>     This may require some  changes to EAL to facilitate pci device sharing between

> >>     PMDs, enabling separation of sym and  asym services onto different PMDs.

> >>     As per RFCv2 feedback, Intel  proposed to submit a patch to  enable this.

> >[Fiona] The eal changes were problematic, and feedback from the Dublin userspace

> >event last September was that several others have tried similar but reverted to resolving

> >the problem within the PMD. This is what we are also in the process of doing.

> >With this we intend to avoid all the above complications.

> >i.e. one pci device, in its probe fn, can create multiple API device instances.

> >One instance of cryptodev will provide a sym crypto service, one instance of

> >compressdev will provide a compression service and a second cryptodev instance will

> >provide the asymmetric service. All qps on each API device instance can then support all

> >of the capabilities reported by that device.

> >

> >A suggestion for keeping the simplicity on the API would be to follow the same pattern.

> >i.e. don't provide any support for specification of sym or asym qps. Expect all

> >qps on each device to support all capabilities reported.

> >

> >

> 

> [Shally] Initially I had thought of same proposal to add an input field in qp_conf so that PMD can know

> at qp_setup time which service it going to be used for.

> However looking that spec already had qp_attach_sym/asym APIs and also the possibility that some

> device can support service - agnostic qp, I initiated with current proposal.

> I marked them optional with a disclaimer that , if not attached, then PMD will then need to map logical

> qpid to physical during enqueue_burst() which might result in impacted performance.

> This is particularly applicable to devices which internally have fixed qps per each service and set

> max_nb_sym/asym_qp to indicate same.

> And thus for such devices, I primarily recommended that they should appear as two separate PMDs

> where one support sym and other asym.

> However, only point to is to see how well suited is this for each device driver design as it might rather

> turn to be simpler for some implementation to just have single way to dedicate a qp to a service via

> attach or qp_setup change than having two separate instances.

> 

> But, I concur from your thoughts. We can start with simple definition and remove concept of

> max_nb_sym_qp and max_nb_asym_qp in first version and say

> -if device support service agnostic qp, that means all of its qp can be set up for any service. PMD can

> show in its feature flag support for symmetric and asymmetric crypto. Application can set up qp the way

> it want, spec define no recommended way of usage here.

[Fiona] I would word this differently, as no mechanism is provided for an appl to setup a qp for a specific service.
If PMD shows in its feature flag that it supports both sym and asym then it must support those on all its qps.
Application may choose to direct all asym ops to one qp and all asym to a different qp to avoid
head-of-line blocking, but there is nothing in the qp setup or capabilities to prevent the application
from sending an enqueue_burst() with a mix of asym and sym ops all to the same qp and it should work.

> -if device has fixed set of qp per each service, then it should split itself into two : symmetric only and

> asymmetric only.

[Fiona] For us this is ok, but it would be good to get feedback from other providers of hw acceleration
as it is quite a constraint.

> This is well suited for session-less also.  IMO, If any issues reported with these rules, then we can add

> this support later based on the then identified requirement. However, if we end up adding the support

> back of max_nb_sym/asym_qp in spec later, then attach/detach_qp APIs will not be sufficient as they

> are session specific. Given that, having an input param during qp_setup() is more generic way that suit

> both session and sessionless way. Does this all sounds right?

[Fiona] agreed.

> 

> I will wait to close on this design discussion first before giving feedback to rest of the comment further

> below. But consider all feedback regarding typo and licensing as acknowledged.

> 

> Thanks

> Shally

>
  
Verma, Shally Feb. 22, 2018, 5:50 a.m. UTC | #4
HI Fiona

>-----Original Message-----

>From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

>Sent: 15 February 2018 17:16

>To: Verma, Shally <Shally.Verma@cavium.com>; dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>;

>Murthy, Nidadavolu <Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish

><Ashish.Gupta@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>; Griffin,

>John <john.griffin@intel.com>

>Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona <fiona.trahe@intel.com>

>Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>

>Hi Shally,

>

>> -----Original Message-----

>> From: Verma, Shally [mailto:Shally.Verma@cavium.com]

>> Sent: Thursday, February 15, 2018 5:33 AM

>> To: Trahe, Fiona <fiona.trahe@intel.com>; dev@dpdk.org; Athreya, Narayana Prasad

>> <NarayanaPrasad.Athreya@cavium.com>; Murthy, Nidadavolu <Nidadavolu.Murthy@cavium.com>;

>> Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish <Ashish.Gupta@cavium.com>; Doherty, Declan

>> <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>; Griffin, John

>> <john.griffin@intel.com>

>> Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

>> Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>>

>> HI Fiona

>>

>> Thanks for your feedback. Response below.

>>

>> >-----Original Message-----

>> >From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

>> >Sent: 09 February 2018 23:43

>> >To: dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>; Murthy,

>> Nidadavolu

>> ><Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish

>> <Ashish.Gupta@cavium.com>; Verma,

>> >Shally <Shally.Verma@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A

>> <brian.a.keating@intel.com>;

>> >Griffin, John <john.griffin@intel.com>

>> >Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

>> >Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>> >

>> >Hi Shally,

>> >Comments below.

>> >

>> >> -----Original Message-----

>> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

>> >> Sent: Tuesday, January 23, 2018 9:54 AM

>> >> To: Doherty, Declan <declan.doherty@intel.com>

>> >> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

>> >> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

>> >> <sverma@caviumnetworks.com>

>> >> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>> >>

>> >> From: Shally Verma <sverma@caviumnetworks.com>

>> >>

>> >> Add support for asymmetric crypto operations in DPDK lib cryptodev

>> >>

>> >> Key feature include:

>> >> - Only session based asymmetric crypto operations

>> >> - new get and set APIs for symmetric and asymmetric session private

>> >>   data and other informations

>> >> - APIs to create, configure and attch queue pair to asymmetric sessions

>> >> - new capabilities in struct device_info to indicate

>> >>   -- number of dedicated queue pairs available for symmetric and

>> >>      asymmetric operations, if any

>> >>   -- number of asymmetric sessions possible per qp

>> >>

>> >[Fiona] Though it's probably premature to include on the API have you considered

>> >providing for pre-loaded keys in future, i.e. the ability to wrap keys or refer to keys

>> >already stored securely on the device, as an alternative to passing the keys on the API?

>> >

>> [Shally] Current intention of DPDK asym spec is to expose HW capabilities to application to offload these

>> compute intensive ops.

>> Though your use-case is very much a practical requirement , but to achieve this I believe we need a layer

>> above this spec and need different interfaces. Such as, some public/secure key library which provide

>> interfaces to generate / store/ perform op using an opaque key handles which internally can use DPDK

>> to do part of it. For such case, I envision dpdk (or library above) will likely run on some secure processor.

>> Thus, currently I kept such use-case out of current spec scope.

>[Fiona] ok

>

>> >

>> >> Proposed asymmetric cryptographic operations are:

>> >> - rsa

>> >> - dsa

>> >> - deffie-hellman key pair generation and shared key computation

>> >> - ecdeffie-hellman

>> >> - fundamental elliptic curve operations

>> >> - elliptic curve DSA

>> >> - modular exponentiation and inversion

>> >>

>> >> This patch primarily defines PMD operations and device capabilities

>> >> to perform asymmetric crypto ops on queue pairs and intend to

>> >> invite feedbacks on current proposal so as to ensure it encompass

>> >> all kind of crypto devices with different capabilities and queue

>> >> pair management.

>> >>

>> >> List of TBDs:

>> >> - Currently, patch only updated for RSA xform and associated params.

>> >>   Other algoritms to be added in subsequent versions.

>> >> - per-service stats update

>> >>

>> >> Signed-off-by: Shally Verma <sverma@caviumnetworks.com>

>> >> ---

>> >>

>> >> It is derivative of RFC v2 asymmetric crypto patch series initiated by

>> >> Umesh Kartha(mailto:umesh.kartha@caviumnetworks.com):

>> >>

>> >>  http://dpdk.org/dev/patchwork/patch/24245/

>> >>  http://dpdk.org/dev/patchwork/patch/24246/

>> >>  http://dpdk.org/dev/patchwork/patch/24247/

>> >>

>> >> And inclusive of all review comments given on RFC v2.

>> >>  ( See complete discussion thread here:

>> >> http://dev.dpdk.narkive.com/yqTFFLHw/dpdk-dev-rfc-specifications-for-asymmetric-crypto-

>> >> algorithms#post12)

>> >>

>> >> Some of the RFCv2 Review comments pending for closure:

>> >> > " [Fiona] The count fn isn't used at all for sym - probably no need to add for asym

>> >>      better instead to remove the sym fn."

>> >>

>> >>      It is still present in dpdk-next-crypto for sym, so what has been decision

>> >>      on it?

>> >[Fiona] No change. The rte_cryptodev_ops fn is still not called so useless and should be removed.

>> >rte_cryptodev_queue_pair_count() returns the num_qps configured in

>> >rte_cryptodev_configure(), but never calls the PMD dev_ops.queue_pair_count().

>> >So cryptodev_sym_queue_pair_count_t should be deprecated.

>> >And no point in adding one for asym.

>> >

>>

>> [Shally] Ok

>>

>> >>

>> >> >"[Fiona] if each qp can handle only a specific service, i.e. a subset off the capabilities

>> >>     Indicated by the device capability list, there's a need for a new API to query

>> >>     the capability of a qp."

>> >>

>> >>     Current proposal doesn’t distinguish between device capability and qp capability.

>> >>     It rather leave such differences handling internal to PMDs. Thus no capability

>> >>     or API added for qp in current version. It is subject to revisit based on review

>> >>     feedback on current proposal.

>> >[Fiona] This would not work for some devices, comments below.

>> >

>> >>

>> >> - Sessionless Support.

>> >>     Current proposal only support Session-based because:

>> >>      1. All one-time setup i.e.  algos and associated params, such as, public-private keys

>> >>         or modulus length can be done in control path using session-init API

>> >>      2. it’s an easier way to dedicate qp to do specific service (using queue_pair_attach())

>> >>         which cannot be case in sessionless

>> >>      3. Couldn’t find any significant advantage going sessionless way. Also existing most of PMDs are

>> >> session-based.

>> >>

>> >>     It could be added in subsequent versions, if requirement is identified, based on review comment

>> >>     on this RFC.

>> >[Fiona] Our preference would be for sessionless, as it would need fewer API calls (no

>> session_create/session_clear)

>> >and e.g. DH and ECDH sessions are likely to be only used for a single op. However this is not a blocker

>> for

>> >this API, we can POC it later and propose an extension to the API if it gives a performance

>> improvement.

>> >

>> [Shally] You mean you recommend to have session-less support along with session-based?

>[Fiona] Yes. But as stated, it's ok to start without it and add later.

>

>

>> >>

>> >> Summary

>> >> -------

>> >>

>> >> This section provides an overview of key feature enabled in current specification.

>> >> It comprise of key design challenges as have been identified on RFCv2 and

>> >> summary description of new interfaces and definitions added to handle same.

>> >>

>> >> Description

>> >> -----------

>> >>

>> >> This API set assumes that the max_nb_queue_pairs on a

>> >> device can be allocated to any mix of sym or asym. Some devices

>> >> may have a fixed max per service. Thus, rte_cryptodev_info

>> >> is updated with max_sym_nb_queues and max_asym_nb_queues with rule:

>> >>

>> >> max_nb_queue_pair = max_nb_sym_qp + max_nb_asym_qp.

>> >>

>> >> If device has no restrictions on qp to be used per service, such PMDs can leave

>> >> max_nb_sym_qp = max_nb_asym_qp = 0. In such case, application can setup any of

>> >> the service upto limit defined by max_nb_queue_pair.

>> >[Fiona] This seems awkward if a genuine 0  e.g. An appl wants to set up a sym qp, and

>> >sees that max_nb_queue_pair=4. Can't trust this - needs to look deeper. Sees

>> >max_nb_sym_qp=0. Doesn't know if that means it can set up 4 sym qps or no qps

>> >until it also checks max_nb_asym_qp. If=4 then it can't set up any sym qp, if=0 it can set up 4.

>> >Would it be better if

>> >	max_nb_queue_pair = max(max_nb_sym_qp, max_nb_asym_qp).

>> >	max_nb_sym_qp = 0..max_nb_queue_pair

>> >	max_nb_asym_qp = 0..max_nb_queue_pair

>> >

>>

>> [Shally] Ok. I can change definition to replace 0 by max num for no-limit case with slight modification  to

>> the condition i.e.

>> max_nb_queue_pair >=  max(max_nb_sym_qp, max_nb_asym_qp)

>>

>> because device can have distribution of (max_nb_queue_pair, max_nb_sym_qp, max_nb_asym_qp) as

>> (4,4,4) or (4,3,1)

>> where total number of qp setup by application cannot exceed max_nb_queue_pairs.

>>

>> >> Here, max_nb_sym_qp and max_nb_asym_qp, if non-zero, just define limit on qp which are

>> >> available for each service and *are not* ids to be used during qp setup and enqueue i.e.

>> >> if device supports both symmetric and asymmetric with n qp, then any of them

>> >> can be configured for symmetric or asymmetric subject to limit defined by

>> >> max_nb_sym_qp and max_nb_asym_qp. For example,

>> >> if device has 6 queues and 5 for symmetric and 1 for asymmetric that imply

>> >> application can setup only 1 out of any 6 qp for asymmetric and rest for

>> >> symmetric.

>> >>

>> >> Additionally, application can dedicate qp to perform specific service via optional

>> >> queue_pair_attach_sym/asym_session() API.

>> >[Fiona] This is too late - some devices have qps which need to know at setup which

>> >service they'll be used for, as they reserve resources based on the service.

>> >e.g. a device reports in info that it can support qps(max 4, max_sym 2, max asym 2)

>> >An application just wants to use 1 sym qp and 1 asym, so configures device with

>> >qps(max 2, max_sym 1, max asym 1)

>> >Now appl calls qp_setup for qp index 0. Wants to start with running asymmetric

>> >service and will set up the symmetric later, maybe in a separate thread.

>> >Our devices need to know at setup time which service will be used on the qp.

>> >So haven't been given enough information to setup the qp.

>> >

>> >Even if the PMD could set up service-agnostic qps and just map later, you

>> >suggest the qp_attach_sym/asym_session() would be optional. How could the appl

>> >make the decision whether to call it or not in above case? It needs to know whether

>> >the created qp is agnostic or not, so a capability must be reported by the PMD.

>> >OR the API should not be optional, must be called for every session.

>> >But that's perf impacting and not helpful if a device could support service-agnostic qps.

>> >

>> >I don't have a solution for service-agnostic qps. For our devices that's not necessary.

>> >Is it likely that anyone wants to set up a qp to process both sym and asym ops?

>> >Is it sufficient to accommodate qps which can support either

>> >service, but one must be picked at setup after which the qp supports only that service?

>> >How about the following - :

>> > - device reports in info qps(max, max_sym, max asym) where

>> >	max = max(max_sym, max_asym).

>> >	max_sym = 0..max

>> >	max_asym = 0..max

>> >	So if a device reports 4,2,2, it has 4 total, 2 can be setup for sym, 2 for asym

>> >	Or if it reports 4,4,4, all 4 of them can be setup as sym or all 4 as

>> >	asym or a mix, but total setup can't be more than 4.

>> > - appl configures qps(max, max_sym, max_asym)

>> >	If it specifies 4,1,3 it wants to use 4 in total, 1 for sym, 3 for asym.

>> >	If it specifies 1,1,0 it wants to use 1 in total, 1 for sym, 0 for asym.

>> >	The numbers it configures must be <= those reported in info.

>> > - appl calls qp_setup(dev, qp, service) where service = sym or asym

>> >	qp index must be between 0..max-1

>> >	The PMD maps that index to an internal qp which can support the requested service.

>> >	If qp_setup is called on an index and the max configured qps have already

>> >	been setup for that service then the setup fails.

>> >In case the appl forgets which qp it set up for which service, I think it would be necessary to add a new

>> API

>> >	rte_cryptodev_qp_info() which would return what service is configured on the qp

>> >

>> >If it's necessary to support service-agnostic qps, then one way would be to specify a third service above

>> as

>> > - sym+asym.

>> >And have devices report max_sym_asym_qps?

>> >

>> >It's difficult to find a solution for this without breaking the current API - see simpler

>> >alternative below.

>> >

>> >> Except the ones mentioned above, specification doesn't define any restrictions on

>> >> enqueue/dequeue API for different crypto services. Application can enqueue both symmetric

>> >> and asymmetric operations to same device and qp if device info indicate support of both

>> >> symmetric and asymmetric and qp is not dedicated to any. However in practice, it could

>> >> result in head-of-line blocking due to the asym ops taking longer than the symmetric ops.

>> >>

>> >> Some HW accelerators avoid this issue by supporting sym and asym ops

>> >> on different qps on the same device.  Such devices can set max_nb_sym_qp and

>> >> max_nb_asym_qp to number of queues available for each respective service.

>> >>

>> >> This may give problem in indexing on enqueue/dequeue i.e.

>> >> if 2 asym qps and 2 sym qps are created on the same device,

>> >> the queue_pair_ids are duplicated. To handle such scenario,

>> >> 2 alternatives are proposed for PMD design:

>> >>

>> >> 1. Allow all qp to input any operation type virtually. Say,

>> >>

>> >>     Consider device with symmetric and asymmetric capability having

>> >>     max_nb_queue_pair as 6, then by design, all 6 are capable to input

>> >>     both op types.

>> >>

>> >>     If PMD uses fixed set of qp, then internally, can map qp id to

>> >>     actual physical qp id to be used according to session/op type.

>> >>     If such mapping is done on data path, may impact performance of PMDs.

>> >>     Thus, to handle such mapping out of data path, library provides an API

>> >>     queue_pair_attach_sym/asym_session() which facilitate application to

>> >>     dedicate qp id to perform specific (sym/asym) service in control path

>> >>     and should be called before 1st call to enqueue_burst().

>> >>     Here PMD can bind app provided logical qp id to actual physical qp id to use

>> >>     depending on session type , OR alternatively

>> >>

>> >> 2. PMDs can split it into two PMDs, one with symmetric ONLY capability and other

>> >>     with asymmetric ONLY capability (also proposed by Fiona in RFCv2).

>> >>     This may require some  changes to EAL to facilitate pci device sharing between

>> >>     PMDs, enabling separation of sym and  asym services onto different PMDs.

>> >>     As per RFCv2 feedback, Intel  proposed to submit a patch to  enable this.

>> >[Fiona] The eal changes were problematic, and feedback from the Dublin userspace

>> >event last September was that several others have tried similar but reverted to resolving

>> >the problem within the PMD. This is what we are also in the process of doing.

>> >With this we intend to avoid all the above complications.

>> >i.e. one pci device, in its probe fn, can create multiple API device instances.

>> >One instance of cryptodev will provide a sym crypto service, one instance of

>> >compressdev will provide a compression service and a second cryptodev instance will

>> >provide the asymmetric service. All qps on each API device instance can then support all

>> >of the capabilities reported by that device.

>> >

>> >A suggestion for keeping the simplicity on the API would be to follow the same pattern.

>> >i.e. don't provide any support for specification of sym or asym qps. Expect all

>> >qps on each device to support all capabilities reported.

>> >

>> >

>>

>> [Shally] Initially I had thought of same proposal to add an input field in qp_conf so that PMD can know

>> at qp_setup time which service it going to be used for.

>> However looking that spec already had qp_attach_sym/asym APIs and also the possibility that some

>> device can support service - agnostic qp, I initiated with current proposal.

>> I marked them optional with a disclaimer that , if not attached, then PMD will then need to map logical

>> qpid to physical during enqueue_burst() which might result in impacted performance.

>> This is particularly applicable to devices which internally have fixed qps per each service and set

>> max_nb_sym/asym_qp to indicate same.

>> And thus for such devices, I primarily recommended that they should appear as two separate PMDs

>> where one support sym and other asym.

>> However, only point to is to see how well suited is this for each device driver design as it might rather

>> turn to be simpler for some implementation to just have single way to dedicate a qp to a service via

>> attach or qp_setup change than having two separate instances.

>>

>> But, I concur from your thoughts. We can start with simple definition and remove concept of

>> max_nb_sym_qp and max_nb_asym_qp in first version and say

>> -if device support service agnostic qp, that means all of its qp can be set up for any service. PMD can

>> show in its feature flag support for symmetric and asymmetric crypto. Application can set up qp the way

>> it want, spec define no recommended way of usage here.

>[Fiona] I would word this differently, as no mechanism is provided for an appl to setup a qp for a specific service.

>If PMD shows in its feature flag that it supports both sym and asym then it must support those on all its qps.

>Application may choose to direct all asym ops to one qp and all asym to a different qp to avoid

>head-of-line blocking, but there is nothing in the qp setup or capabilities to prevent the application

>from sending an enqueue_burst() with a mix of asym and sym ops all to the same qp and it should work.

>


[Shally] Clear.

>> -if device has fixed set of qp per each service, then it should split itself into two : symmetric only and

>> asymmetric only.

>[Fiona] For us this is ok, but it would be good to get feedback from other providers of hw acceleration

>as it is quite a constraint.

>


[Shally] That's the intention but until then I assume we agree to current proposal?!

If yes, then just to align and close on our discussion on this here’s the summary :
- There's no differentiation to device capability and qp capability.  If PMD shows in its feature flag that it supports both sym and asym then it must support those on all its qps.
- if PMD support both but internally has hw with dedicated qp for each service then it *can* split itself into two: symmetric only and asymmetric only PMD instances.
- Currently we don’t see a requirement to dedicate qp to a service, thus no need for max_nb_sym/asym_qp or service_type info during qp_setup. However this is open for review and discussion and can be added later, if any requirement is identified for same.

Is that correct?

Thanks
Shally
>> This is well suited for session-less also.  IMO, If any issues reported with these rules, then we can add

>> this support later based on the then identified requirement. However, if we end up adding the support

>> back of max_nb_sym/asym_qp in spec later, then attach/detach_qp APIs will not be sufficient as they

>> are session specific. Given that, having an input param during qp_setup() is more generic way that suit

>> both session and sessionless way. Does this all sounds right?

>[Fiona] agreed.

>

>>

>> I will wait to close on this design discussion first before giving feedback to rest of the comment further

>> below. But consider all feedback regarding typo and licensing as acknowledged.

>>

>> Thanks

>> Shally

>>
  
Fiona Trahe Feb. 22, 2018, 10:38 a.m. UTC | #5
Hi Shally,

> [Shally] That's the intention but until then I assume we agree to current proposal?!

> 

> If yes, then just to align and close on our discussion on this here’s the summary :

> - There's no differentiation to device capability and qp capability.  If PMD shows in its feature flag that it

> supports both sym and asym then it must support those on all its qps.

> - if PMD support both but internally has hw with dedicated qp for each service then it *can* split itself

> into two: symmetric only and asymmetric only PMD instances.

> - Currently we don’t see a requirement to dedicate qp to a service, thus no need for

> max_nb_sym/asym_qp or service_type info during qp_setup. However this is open for review and

> discussion and can be added later, if any requirement is identified for same.

> 

> Is that correct?

[Fiona] Yes.
  
Verma, Shally March 7, 2018, 12:16 p.m. UTC | #6
Hi Fiona


>-----Original Message-----

>From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

>Sent: 09 February 2018 23:43

>To: dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>; Murthy, Nidadavolu

><Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish <Ashish.Gupta@cavium.com>; Verma,

>Shally <Shally.Verma@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>;

>Griffin, John <john.griffin@intel.com>

>Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

>Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>

>Hi Shally,

>Comments below.

>

>> -----Original Message-----

>> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

>> Sent: Tuesday, January 23, 2018 9:54 AM

>> To: Doherty, Declan <declan.doherty@intel.com>

>> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

>> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

>> <sverma@caviumnetworks.com>

>> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>>


//snip

>

>> +	RTE_CRYPTO_ASYM_XFORM_FECC,

>> +	/**< Fundamental Elliptic curve operations.

>> +	 * Perform elliptic curve operation:

>> +	 * add, double point, multiplication

>> +	 * Refer to enum rte_crypto_fecc_optype

>> +	 */

>> +	RTE_CRYPTO_ASYM_XFORM_MODINV,

>> +	/**< Modular Inverse */

>[Fiona] would be nicer to group modinv with modexp


[Shally] I thought of it but having a xform RTE_CRYPTO_XFORM_MOD with two ops RTE_CRYPTO_OP_MOD_EXP and MOD_INV 
doesn’t seem to provide any benefit. Or do you have something else in mind?
In addition, I am thinking probably we don’t need sessions for modexp or modinv ops. I am thinking to change their support as sessionless only.
App can directly attach xform to compute modexp or inverse to op. What do you suggest?

>

>> +	RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END

>> +	/**< End of list */

>> +};

>> +

>> +/**

>> + * Asymmetric cryptogr operation type variants

>[Fiona] typo: Use crypto or cryptographic

>

>> + */

>> +enum rte_crypto_asym_op_type {

>> +	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,

>[Fiona] Why does this start at 1?

>And is it necessary?

>

[Shally]  We need to indicate list of supported op in xform capability structure. Because an implementation may support RSA encrypt and decrypt but not RSA Sign and verify. Or, Can support DSA Sign compute but not verify.
So, it was added to indicate end-of-array marker (though doesn’t need to be 1 for that reason). but now when I think to re-design its support, then it won't be needed. 
So, I thought rather than carrying op_type array, I can add an op_type bitmask in xform capability to show supported ops.

Example capability check code then would look like:
int rte_crypto_asym_check_op_type ( const rte_crypto_asym_capabilties *capa, int op_type) {
	If(capa->op_types & (1 << op_type))
		return 0;
	return -1;
}

Please let me know your feedback, if you have any preferences here.

>> +	/**< Operation unspecified */

>> +	RTE_CRYPTO_ASYM_OP_ENCRYPT,

>> +	/**< Asymmetric encrypt operation */

>> +	RTE_CRYPTO_ASYM_OP_DECRYPT,

>> +	/**< Asymmetric Decrypt operation */

>> +	RTE_CRYPTO_ASYM_OP_SIGN,

>> +	/**< Signature generation operation */

>> +	RTE_CRYPTO_ASYM_OP_VERIFY,

>> +	/**< Signature verification operation */

>> +	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,

>> +	/**< Public/Private key pair generation operation */

>[Fiona] In the comment, clarify that this is for DH and ECDH, and for the

> generation of the public key (and optionally the private key?)

>


[Shally] so far, I was assuming it will generate both but when you say private key optional, where you expect it to be coming from? - from app or generated internally? Is their hw variant which may not generate private key?

//snip

>> +/**

>> + * Fundamental ECC operation type variants.

>> + */

>> +enum rte_crypto_fecc_optype {

>> +	RTE_CRYPTO_FECC_OP_NOT_SPECIFIED = 1,

>> +	/**< FECC operation type unspecified */

>[Fiona] as above. Why 1? And is it needed?


[Shally] This is for same reason to indicate in fecc xform capability list of supported op type in fundamental EC operation. And if we agree to use proposal above to use bitmask, it won't be needed.
>

>> +	RTE_CRYPTO_FECC_OP_POINT_ADD,

>> +	/**< Fundamental ECC point addition operation */

>> +	RTE_CRYPTO_FECC_OP_POINT_DBL,

>> +	/**< Fundamental ECC point doubling operation */

>> +	RTE_CRYPTO_FECC_OP_POINT_MULTIPLY,

>> +	/**< Fundamental ECC point multiplication operation */

>> +	RTE_CRYPTO_FECC_OP_LIST_END

>> +};

>> +

>> +#define RTE_CRYPTO_EC_CURVE_NOT_SPECIFIED  -1

>[Fiona] Wouldn't it be better to put this back in as the initial value in the enum as originally done?

>Else will there not be a compiler warning if a param of that enum type is

>initialised to above #define?

>And are _BINARY and _PRIME values needed in this case?


[Shally] Agreed. We would need to use typecast to avoid warning so I will revert and define _Primary and Binary variant. But before that I have one question on published list. See below.

>

>> +/**

>> + * ECC list of curves.

>> + */

//snip

>> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls4,

>> +	/**< SECG curve over a 113 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls5,

>> +	/**< X9.62 curve over a 163 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls10,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls11,

>> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

>> +	RTE_CRYPTO_EC_BCURVE_LIST_END

>> +};

>[Fiona] Do we really want to specify curves < 224 bits? Even 224 is woefully insecure these days.

>Also do we want to list all "published" curves, or allow customers to specify

>their own curve parameters, at least on the FECC API? Adding an API to specify a curve with

>its params would allow new curves to be used without affecting the API and

>would avoid the need for such an extensive list.


[Shally] I would take this question in-parts:

" Also do we want to list all "published" curves, or allow customers to specify their own curve parameters,"
- Currently specification allow app to do both i.e. it can either setup these published curve ids or specify its own domain params to all elliptic curve based xforms (ecdh, ecdsa, and fecc).
  If input curve has curve_type = UNSPECIFIED, PMD uses domain parameters else it uses curveid given by app from this published list. 
  So, is this missing any requirement that need to be supported?!

" Adding an API to specify a curve with its params would allow new curves to be used without affecting the API and would avoid the need for such an extensive list."
- help me understand a bit here. Are you suggesting, we can remove this publish list and add a new API such as 

int rte_crypto_asym_new_curve(int curveid, rte_crypto_asym_ec_domain_params params) 

which app can call to create its curveid with its own domain parameters in PMD? 

If yes, then how it would help remove published list? Does that mean that we assume app to retrieve domain params from these standard and re-create again on PMD? 

"do we have to publish curves < 224 bits"
- We just listed all based on previous feedback to include non-nist curve id. But agree it can be narrowed down to few (may be to one used by ssl)

>Do we need a "capabilities" mask to say which curves are supported by a device?


[Shally] Yes, if we are supporting published id.

>What about SM2?

[Shally] app can setup ec params as mentioned in sm2 spec. does it need any explicit support on API?

>

//snip

>> +

>> +/**

>> + * Elliptic curve id

>> + */

>> +struct rte_crypto_ec_curve_id {

>> +	RTE_STD_C11

>> +	union {

>> +		enum rte_crypto_ec_prime_curve pcurve;

>> +		enum rte_crypto_ec_binary_curve bcurve;

>> +	};

>> +};

>[Fiona] Because the values of these two enums overlap, if you specify the curve type incorrectly, you'll still

>have a potentially valid curve enum specified. I suggest it's safer to include the type here with the union,

>rather than in the wrapper xform struct, i.e.

>struct rte_crypto_ec_curve {

>	enum rte_crypto_ec_curve_type curve_type;

>	/**< curve type: Prime vs Binary */

>	union {

>	enum rte_crypto_ec_prime_curve pcurve_id;

>	enum rte_crypto_ec_binary_curve bcurve_id;

>	};

>};

[Shally] We would need curve type if we need to define a new curve based on domain params. Let's cover it later once we clarify above feedback.

>> +/**

>> + * Asymmetric RSA transform data

>> + *

>> + * This structure contains data required to perform RSA crypto

>> + * transform.

>> + *

>> + */

>> +struct rte_crypto_rsa_xform {

>> +

>> +	rte_crypto_xform_param n;

>> +	/**< n - Prime modulus

>> +	 * Prime modulus data of RSA operation in Octet-string network

>> +	 * byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param e;

>> +	/**< e - Public key exponent

>> +	 * Public key exponent used for RSA public key operations in Octet-

>> +	 * string network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param d;

>> +	/**< d - Private key exponent

>> +	 * Private key exponent used for RSA private key operations in

>> +	 * Octet-string  network byte order format.

>> +	 */

>> +

>> +	rte_crypto_xform_param p;

>> +	/**< p - Private key component P

>> +	 * Private key component of RSA parameter  required for CRT method

>> +	 * of private key operations in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param q;

>> +	/**< q - Private key component Q

>> +	 * Private key component of RSA parameter  required for CRT method

>> +	 * of private key operations in Octet-string network byte order

>> +	 * format.

>> +	 */

>> +

>> +	rte_crypto_xform_param dP;

>> +	/**< dP - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * dP = d mod ( p - 1 )

>> +	 */

>> +

>> +	rte_crypto_xform_param dQ;

>> +	/**< dQ - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * dQ = d mod ( q - 1 )

>> +	 */

>> +

>> +	rte_crypto_xform_param qInv;

>> +	/**< qInv - Private CRT component

>> +	 * Private CRT component of RSA parameter  required for CRT method

>> +	 * RSA private key operations in Octet-string network byte order

>> +	 * format.

>> +	 * qInv = inv q mod p

>> +	 */

>> +};

>[Fiona] This allows both representations of the private key to be specified

>with the possibility of confusion if both are specified.

>Would it be better to have a union of 2 different structures, one with {n,d} and

>the other with {p,q,dP,dQ,qInv}?

>


[Shally] Ok.

//snip

>> +

>> +/**

>> + * Asymmetric crypto transform data

>> + *

>> + * This structure contains the data required to perform the

>> + * asymmetric crypto transformation operation. The field op

>> + * determines the asymmetric algorithm for transformation.

>[Fiona] clarify comment. The xform only contains some of the data, the rest will be provided in the op.

>And there's no field op here.


[Shally] Ok

>> + */

>> +struct rte_crypto_asym_xform {

>> +	struct rte_crypto_asym_xform *next;

>[Fiona] Is there any reason for a chain of xforms?

>I'd suggest removing unless needed.

>


[Shally] Yes. One possible chain ECDH key generation followed by ECDSA sign compute. Similar with DH key generation + DSA sign compute.
Currently these are only valid chain I foresee that can be setup to be performed on an op using that session. Can add other if we identify more such dependent
set of operation.

>> +	enum rte_crypto_asym_xform_type xform_type;

>> +	/**< Asymmetric algorithm for crypto transform */

>> +

>> +	RTE_STD_C11

>> +	union {

>> +		struct rte_crypto_rsa_xform rsa;

>> +		/**< RSA xform parameters */

>> +

>> +		struct rte_crypto_fecc_xform fecc;

>> +		/**< Fundamental Elliptic Curve xform parameters */

>> +

>> +		struct rte_crypto_modex_xform modex;

>> +		/**< Modular Exponentiation xform parameters */

>> +

>> +		struct rte_crypto_modinv_xform modinv;

>> +		/**< Modulus Inverse xform parameters */

>> +

>> +		struct rte_crypto_ecdsa_xform ecdsa;

>> +		/**< ECDSA xform parameters */

>> +

>> +		struct rte_crypto_ecdh_xform ecdh;

>> +		/**< ECDH xform parameters */

>> +

>> +		struct rte_crypto_dsa_xform dsa;

>> +		/**< DSA xform parameters */

>> +	};

>> +};


//snip 

>>  #define RTE_CRYPTODEV_DETACHED  (0)

>> @@ -513,6 +677,24 @@ struct rte_cryptodev_config {

>>  	int socket_id;			/**< Socket to allocate resources on */

>>  	uint16_t nb_queue_pairs;

>>  	/**< Number of queue pairs to configure on device */

>> +

>> +	uint16_t nb_symm_qp;

>> +	/**< Number of queue pair to be used for symmetric operations.

>> +	 * Optional input.

>> +	 * Valid for device supporting both symmetric and asymmetric.

>> +	 * Should be less than equal to rte_cryptodev_info:max_nb_symm_qp.

>> +	 * please note this number only tells how many queue pair to be used

>> +	 * for symmetric op and does *not* tell specific IDs to be used.

>> +	 */

>> +

>> +	uint16_t nb_asymm_qp;

>> +	/**< Number of queue pair to be used for asymmetric operations.

>> +	 * Optional input.

>> +	 * Valid for device supporting both asymmetric and symmetric.

>> +	 * Should be less than equal to rte_cryptodev_info:max_nb_asymm_qp

>> +	 * Please note this number only tells how many queue pair to be

>> +	 * used for asymmetric and does *not* specifically tell qp ID

>> +	 */

>>  };

>>

>[Fiona] The params from config structure above should be used to set the values in the data structure

>This code is missing.


[Shally] as discussed , such changes about sym/asym qp would be removed

>

//snip 

>> @@ -975,6 +1253,8 @@ struct rte_cryptodev_sym_session *

>>

>>  /**

>>   * Get the size of the private session data for a device.

>> + * if device support both symmetric and asymmetric, it

>> + * return size inclusive of both

>[Fiona] Are you suggesting the same session pool might be used

>for both sym and asym sessions?

>Seems unlikely, but if an application chose to, it seems better

> that it would do it explicitly,

>e.g. get asym and sym private sizes, same as it gets size from the other

>drivers and sizes for the maximum.

>If meaning is changed as you suggest then sym applications already

>implemented will likely end up with pools sized for a session size they don’t need.

>

>As I think the combined pool case unlikely, it makes more sense to me that this

>fn should have comment changed to say it returns only sym session size

>for backwards capability reasons, but will be deprecated

>and appls should use get_sym_session_private_size instead.


[Shally] Ok agree. I will revert to its original definition.
>


// snip

//snip

>> +/**

>> + * Create a asymmetric session mempool to allocate sessions from

>> + *

>> + * @param	dev		Crypto device pointer

>> + * @param	nb_objs		Number of asymmetric sessions objects in mempool

>> + * @param	obj_cache	l-core object cache size, see *rte_ring_create*

>> + * @param	socket_id	Socket Id to allocate  mempool on.

>> + *

>> + * @return

>> + * - On success returns a pointer to a rte_mempool

>> + * - On failure returns a NULL pointer

>> + */

>> +typedef int (*cryptodev_asym_create_session_pool_t)(

>> +		struct rte_cryptodev *dev, unsigned nb_objs,

>> +		unsigned obj_cache_size, int socket_id);

>>

>[Fiona] session pools are not created now per device so this is never called for sym and

>should be deprecated. So no need to add for asym


[Shally] Ok

>

//snip

>> +	cryptodev_sym_get_session_private_size_t sym_session_get_size;

>> +	/**< Return private size for symmetric crypto. */

>> +	cryptodev_sym_get_session_private_size_t asym_session_get_size;

>> +	/**< Return private size for asymmetric crypto. */

>>  	cryptodev_sym_configure_session_t session_configure;

>>  	/**< Configure a Crypto session. */

>[Fiona] This should really be renamed sym_session_configure, same for session_clear,

>qp_attach_session and qp_detach_session

>


[Shally] I thought to keep it backward compatible for now. I think we can take this change later as it need announcement first

>> +	cryptodev_asym_configure_session_t asym_session_configure;

>> +	/**< Configure asymmetric Crypto session. */


//snip 

>> +

>> +EXPERIMENTAL {

>> +	global:

>> +

>[Fiona] the implementation of all these APIs also needs the _experimental tag.

>


[Shally] Got that.

>> +	rte_cryptodev_asym_capability_get;

>> +	rte_cryptodev_asym_capability_modlen;

>> +	rte_cryptodev_asym_queue_pair_count;

>> +	rte_cryptodev_asym_session_create;

>> +	rte_cryptodev_asym_session_clear;

>> +	rte_cryptodev_asym_session_free;

>> +	rte_cryptodev_asym_session_init;

>> +	rte_cryptodev_get_asym_session_private_size;

>> +	rte_cryptodev_get_sym_session_private_size;

>> +	rte_cryptodev_get_xform_algo_enum;

>> +	rte_cryptodev_queue_pair_attach_asym_session;

>> +	rte_cryptodev_queue_pair_detach_asym_session;

>> +	rte_cryptodev_sym_queue_pair_count;

>> +	rte_crypto_asym_xform_strings;

>> +	rte_crypto_asym_operation_strings;

>> +

>> +};

>> --

>> 1.9.1


Thanks
Shally
  
Fiona Trahe March 14, 2018, 12:12 p.m. UTC | #7
Hi Shally,

> -----Original Message-----

> From: Verma, Shally [mailto:Shally.Verma@cavium.com]

> Sent: Wednesday, March 7, 2018 12:16 PM

> To: Trahe, Fiona <fiona.trahe@intel.com>; dev@dpdk.org; Athreya, Narayana Prasad

> <NarayanaPrasad.Athreya@cavium.com>; Murthy, Nidadavolu <Nidadavolu.Murthy@cavium.com>; Sahu,

> Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish <Ashish.Gupta@cavium.com>; Doherty, Declan

> <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>; Griffin, John

> <john.griffin@intel.com>

> Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

> Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> 

> Hi Fiona

> 

> 

> >-----Original Message-----

> >From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

> >Sent: 09 February 2018 23:43

> >To: dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>; Murthy,

> Nidadavolu

> ><Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish

> <Ashish.Gupta@cavium.com>; Verma,

> >Shally <Shally.Verma@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A

> <brian.a.keating@intel.com>;

> >Griffin, John <john.griffin@intel.com>

> >Cc: Trahe, Fiona <fiona.trahe@intel.com>; De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>

> >Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> >

> >Hi Shally,

> >Comments below.

> >

> >> -----Original Message-----

> >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Shally Verma

> >> Sent: Tuesday, January 23, 2018 9:54 AM

> >> To: Doherty, Declan <declan.doherty@intel.com>

> >> Cc: dev@dpdk.org; pathreya@caviumnetworks.com; nmurthy@caviumnetworks.com;

> >> ssahu@caviumnetworks.com; agupta@caviumnetworks.com; Shally Verma

> >> <sverma@caviumnetworks.com>

> >> Subject: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

> >>

> 

> //snip

> 

> >

> >> +	RTE_CRYPTO_ASYM_XFORM_FECC,

> >> +	/**< Fundamental Elliptic curve operations.

> >> +	 * Perform elliptic curve operation:

> >> +	 * add, double point, multiplication

> >> +	 * Refer to enum rte_crypto_fecc_optype

> >> +	 */

> >> +	RTE_CRYPTO_ASYM_XFORM_MODINV,

> >> +	/**< Modular Inverse */

> >[Fiona] would be nicer to group modinv with modexp

> 

> [Shally] I thought of it but having a xform RTE_CRYPTO_XFORM_MOD with two ops

> RTE_CRYPTO_OP_MOD_EXP and MOD_INV

> doesn’t seem to provide any benefit. Or do you have something else in mind?

[Fiona] I only meant to list them beside each other in the enum.  

> In addition, I am thinking probably we don’t need sessions for modexp or modinv ops. I am thinking to

> change their support as sessionless only.

> App can directly attach xform to compute modexp or inverse to op. What do you suggest?

[Fiona] That's ok for me.

> >> +	RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END

> >> +	/**< End of list */

> >> +};

> >> +

> >> +/**

> >> + * Asymmetric cryptogr operation type variants

> >[Fiona] typo: Use crypto or cryptographic

> >

> >> + */

> >> +enum rte_crypto_asym_op_type {

> >> +	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,

> >[Fiona] Why does this start at 1?

> >And is it necessary?

> >

> [Shally]  We need to indicate list of supported op in xform capability structure. Because an implementation

> may support RSA encrypt and decrypt but not RSA Sign and verify. Or, Can support DSA Sign compute but

> not verify.

> So, it was added to indicate end-of-array marker (though doesn’t need to be 1 for that reason). but now

> when I think to re-design its support, then it won't be needed.

> So, I thought rather than carrying op_type array, I can add an op_type bitmask in xform capability to show

> supported ops.

[Fiona] I think a bitmask is ok. Would only need an array if there were other params whose capabilities would
 vary depending on the op_type. E.g. like range of digest_size in sym depends on the algo. But does code below
not need a xform_type input? Or is capa the capability for one specific xform_type?

> Example capability check code then would look like:

> int rte_crypto_asym_check_op_type ( const rte_crypto_asym_capabilties *capa, int op_type) {

> 	If(capa->op_types & (1 << op_type))

> 		return 0;

> 	return -1;

> }

> 

> Please let me know your feedback, if you have any preferences here.

> 

> >> +	/**< Operation unspecified */

> >> +	RTE_CRYPTO_ASYM_OP_ENCRYPT,

> >> +	/**< Asymmetric encrypt operation */

> >> +	RTE_CRYPTO_ASYM_OP_DECRYPT,

> >> +	/**< Asymmetric Decrypt operation */

> >> +	RTE_CRYPTO_ASYM_OP_SIGN,

> >> +	/**< Signature generation operation */

> >> +	RTE_CRYPTO_ASYM_OP_VERIFY,

> >> +	/**< Signature verification operation */

> >> +	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,

> >> +	/**< Public/Private key pair generation operation */

> >[Fiona] In the comment, clarify that this is for DH and ECDH, and for the

> > generation of the public key (and optionally the private key?)

> >

> 

> [Shally] so far, I was assuming it will generate both but when you say private key optional, where you

> expect it to be coming from? - from app or generated internally? Is their hw variant which may not

> generate private key?

> 

[Fiona] In our native driver the private key, which is usually just a random number conforming to 
0 < private_key < (primeP - 1), is passed in by the application and only the public key is generated.
Some hw accelerators may have RNG capabilities, others may not or the application may prefer to generate
its own RN.


> //snip

> 

> >> +/**

> >> + * Fundamental ECC operation type variants.

> >> + */

> >> +enum rte_crypto_fecc_optype {

> >> +	RTE_CRYPTO_FECC_OP_NOT_SPECIFIED = 1,

> >> +	/**< FECC operation type unspecified */

> >[Fiona] as above. Why 1? And is it needed?

> 

> [Shally] This is for same reason to indicate in fecc xform capability list of supported op type in fundamental

> EC operation. And if we agree to use proposal above to use bitmask, it won't be needed.

[Fiona] ok

> >

> >> +	RTE_CRYPTO_FECC_OP_POINT_ADD,

> >> +	/**< Fundamental ECC point addition operation */

> >> +	RTE_CRYPTO_FECC_OP_POINT_DBL,

> >> +	/**< Fundamental ECC point doubling operation */

> >> +	RTE_CRYPTO_FECC_OP_POINT_MULTIPLY,

> >> +	/**< Fundamental ECC point multiplication operation */

> >> +	RTE_CRYPTO_FECC_OP_LIST_END

> >> +};

> >> +

> >> +#define RTE_CRYPTO_EC_CURVE_NOT_SPECIFIED  -1

> >[Fiona] Wouldn't it be better to put this back in as the initial value in the enum as originally done?

> >Else will there not be a compiler warning if a param of that enum type is

> >initialised to above #define?

> >And are _BINARY and _PRIME values needed in this case?

> 

> [Shally] Agreed. We would need to use typecast to avoid warning so I will revert and define _Primary and

> Binary variant. But before that I have one question on published list. See below.

> 

> >

> >> +/**

> >> + * ECC list of curves.

> >> + */

> //snip

> 

> >> +	/**< NIST/SECG/WTLS curve over a 163 bit binary field */

> >> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls4,

> >> +	/**< SECG curve over a 113 bit binary field */

> >> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls5,

> >> +	/**< X9.62 curve over a 163 bit binary field */

> >> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls10,

> >> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> >> +	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls11,

> >> +	/**< NIST/SECG/WTLS curve over a 233 bit binary field */

> >> +	RTE_CRYPTO_EC_BCURVE_LIST_END

> >> +};

> >[Fiona] Do we really want to specify curves < 224 bits? Even 224 is woefully insecure these days.

> >Also do we want to list all "published" curves, or allow customers to specify

> >their own curve parameters, at least on the FECC API? Adding an API to specify a curve with

> >its params would allow new curves to be used without affecting the API and

> >would avoid the need for such an extensive list.

> 

> [Shally] I would take this question in-parts:

> 

> " Also do we want to list all "published" curves, or allow customers to specify their own curve parameters,"

> - Currently specification allow app to do both i.e. it can either setup these published curve ids or specify its

> own domain params to all elliptic curve based xforms (ecdh, ecdsa, and fecc).

>   If input curve has curve_type = UNSPECIFIED, PMD uses domain parameters else it uses curveid given by

> app from this published list.

>   So, is this missing any requirement that need to be supported?!

[Fiona] So you mean the params in ECDH xform (a,b,G,n,h) are only specified if curve_type = UNSPECIFIED,
else not needed? And in FECC the params (order,G,a,b,h) ?
Ecdsa xform not yet specified, but it will have a similar set?
Then I would suggest creating a struct to hold this param set and using same struct in all 3 xforms.

> 

> " Adding an API to specify a curve with its params would allow new curves to be used without affecting the

> API and would avoid the need for such an extensive list."

> - help me understand a bit here. Are you suggesting, we can remove this publish list and add a new API

> such as

> 

> int rte_crypto_asym_new_curve(int curveid, rte_crypto_asym_ec_domain_params params)

> 

> which app can call to create its curveid with its own domain parameters in PMD?

[Fiona] Yes, I was thinking of something like that. But above approach to pass in on the xforms is ok
and probably easier to manage.
> 

> If yes, then how it would help remove published list? Does that mean that we assume app to retrieve

> domain params from these standard and re-create again on PMD?

> 

> "do we have to publish curves < 224 bits"

> - We just listed all based on previous feedback to include non-nist curve id. But agree it can be narrowed

> down to few (may be to one used by ssl)

[Fiona] I'm looking for feedback internally on this - will get back to you later.
But I think it could be trimmed to at least removing those curves < 224 bits.
The xform params can be used to cover unlikely curves trimmed from the list.
 
> >Do we need a "capabilities" mask to say which curves are supported by a device?

> 

> [Shally] Yes, if we are supporting published id.

[Fiona] ok
 
> >What about SM2?

> [Shally] app can setup ec params as mentioned in sm2 spec. does it need any explicit support on API?

[Fiona] ok

> 

> >

> //snip

> 

> >> +

> >> +/**

> >> + * Elliptic curve id

> >> + */

> >> +struct rte_crypto_ec_curve_id {

> >> +	RTE_STD_C11

> >> +	union {

> >> +		enum rte_crypto_ec_prime_curve pcurve;

> >> +		enum rte_crypto_ec_binary_curve bcurve;

> >> +	};

> >> +};

> >[Fiona] Because the values of these two enums overlap, if you specify the curve type incorrectly, you'll still

> >have a potentially valid curve enum specified. I suggest it's safer to include the type here with the union,

> >rather than in the wrapper xform struct, i.e.

> >struct rte_crypto_ec_curve {

> >	enum rte_crypto_ec_curve_type curve_type;

> >	/**< curve type: Prime vs Binary */

> >	union {

> >	enum rte_crypto_ec_prime_curve pcurve_id;

> >	enum rte_crypto_ec_binary_curve bcurve_id;

> >	};

> >};

> [Shally] We would need curve type if we need to define a new curve based on domain params. Let's cover

> it later once we clarify above feedback.

[Fiona] So how about adding the struct with curve params I mentioned above as a 3rd element in the union?

> 

> >> +/**

> >> + * Asymmetric RSA transform data

> >> + *

> >> + * This structure contains data required to perform RSA crypto

> >> + * transform.

> >> + *

> >> + */

> >> +struct rte_crypto_rsa_xform {

> >> +

> >> +	rte_crypto_xform_param n;

> >> +	/**< n - Prime modulus

> >> +	 * Prime modulus data of RSA operation in Octet-string network

> >> +	 * byte order format.

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param e;

> >> +	/**< e - Public key exponent

> >> +	 * Public key exponent used for RSA public key operations in Octet-

> >> +	 * string network byte order format.

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param d;

> >> +	/**< d - Private key exponent

> >> +	 * Private key exponent used for RSA private key operations in

> >> +	 * Octet-string  network byte order format.

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param p;

> >> +	/**< p - Private key component P

> >> +	 * Private key component of RSA parameter  required for CRT method

> >> +	 * of private key operations in Octet-string network byte order

> >> +	 * format.

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param q;

> >> +	/**< q - Private key component Q

> >> +	 * Private key component of RSA parameter  required for CRT method

> >> +	 * of private key operations in Octet-string network byte order

> >> +	 * format.

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param dP;

> >> +	/**< dP - Private CRT component

> >> +	 * Private CRT component of RSA parameter  required for CRT method

> >> +	 * RSA private key operations in Octet-string network byte order

> >> +	 * format.

> >> +	 * dP = d mod ( p - 1 )

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param dQ;

> >> +	/**< dQ - Private CRT component

> >> +	 * Private CRT component of RSA parameter  required for CRT method

> >> +	 * RSA private key operations in Octet-string network byte order

> >> +	 * format.

> >> +	 * dQ = d mod ( q - 1 )

> >> +	 */

> >> +

> >> +	rte_crypto_xform_param qInv;

> >> +	/**< qInv - Private CRT component

> >> +	 * Private CRT component of RSA parameter  required for CRT method

> >> +	 * RSA private key operations in Octet-string network byte order

> >> +	 * format.

> >> +	 * qInv = inv q mod p

> >> +	 */

> >> +};

> >[Fiona] This allows both representations of the private key to be specified

> >with the possibility of confusion if both are specified.

> >Would it be better to have a union of 2 different structures, one with {n,d} and

> >the other with {p,q,dP,dQ,qInv}?

> >

> 

> [Shally] Ok.

> 

> //snip

> 

> >> +

> >> +/**

> >> + * Asymmetric crypto transform data

> >> + *

> >> + * This structure contains the data required to perform the

> >> + * asymmetric crypto transformation operation. The field op

> >> + * determines the asymmetric algorithm for transformation.

> >[Fiona] clarify comment. The xform only contains some of the data, the rest will be provided in the op.

> >And there's no field op here.

> 

> [Shally] Ok

> 

> >> + */

> >> +struct rte_crypto_asym_xform {

> >> +	struct rte_crypto_asym_xform *next;

> >[Fiona] Is there any reason for a chain of xforms?

> >I'd suggest removing unless needed.

> >

> 

> [Shally] Yes. One possible chain ECDH key generation followed by ECDSA sign compute. Similar with DH key

> generation + DSA sign compute.

> Currently these are only valid chain I foresee that can be setup to be performed on an op using that

> session. Can add other if we identify more such dependent

> set of operation.

[Fiona] ok

> 

> >> +	enum rte_crypto_asym_xform_type xform_type;

> >> +	/**< Asymmetric algorithm for crypto transform */

> >> +

> >> +	RTE_STD_C11

> >> +	union {

> >> +		struct rte_crypto_rsa_xform rsa;

> >> +		/**< RSA xform parameters */

> >> +

> >> +		struct rte_crypto_fecc_xform fecc;

> >> +		/**< Fundamental Elliptic Curve xform parameters */

> >> +

> >> +		struct rte_crypto_modex_xform modex;

> >> +		/**< Modular Exponentiation xform parameters */

> >> +

> >> +		struct rte_crypto_modinv_xform modinv;

> >> +		/**< Modulus Inverse xform parameters */

> >> +

> >> +		struct rte_crypto_ecdsa_xform ecdsa;

> >> +		/**< ECDSA xform parameters */

> >> +

> >> +		struct rte_crypto_ecdh_xform ecdh;

> >> +		/**< ECDH xform parameters */

> >> +

> >> +		struct rte_crypto_dsa_xform dsa;

> >> +		/**< DSA xform parameters */

> >> +	};

> >> +};

> 

> //snip

> 

> >>  #define RTE_CRYPTODEV_DETACHED  (0)

> >> @@ -513,6 +677,24 @@ struct rte_cryptodev_config {

> >>  	int socket_id;			/**< Socket to allocate resources on */

> >>  	uint16_t nb_queue_pairs;

> >>  	/**< Number of queue pairs to configure on device */

> >> +

> >> +	uint16_t nb_symm_qp;

> >> +	/**< Number of queue pair to be used for symmetric operations.

> >> +	 * Optional input.

> >> +	 * Valid for device supporting both symmetric and asymmetric.

> >> +	 * Should be less than equal to rte_cryptodev_info:max_nb_symm_qp.

> >> +	 * please note this number only tells how many queue pair to be used

> >> +	 * for symmetric op and does *not* tell specific IDs to be used.

> >> +	 */

> >> +

> >> +	uint16_t nb_asymm_qp;

> >> +	/**< Number of queue pair to be used for asymmetric operations.

> >> +	 * Optional input.

> >> +	 * Valid for device supporting both asymmetric and symmetric.

> >> +	 * Should be less than equal to rte_cryptodev_info:max_nb_asymm_qp

> >> +	 * Please note this number only tells how many queue pair to be

> >> +	 * used for asymmetric and does *not* specifically tell qp ID

> >> +	 */

> >>  };

> >>

> >[Fiona] The params from config structure above should be used to set the values in the data structure

> >This code is missing.

> 

> [Shally] as discussed , such changes about sym/asym qp would be removed

> 

> >

> //snip

> 

> >> @@ -975,6 +1253,8 @@ struct rte_cryptodev_sym_session *

> >>

> >>  /**

> >>   * Get the size of the private session data for a device.

> >> + * if device support both symmetric and asymmetric, it

> >> + * return size inclusive of both

> >[Fiona] Are you suggesting the same session pool might be used

> >for both sym and asym sessions?

> >Seems unlikely, but if an application chose to, it seems better

> > that it would do it explicitly,

> >e.g. get asym and sym private sizes, same as it gets size from the other

> >drivers and sizes for the maximum.

> >If meaning is changed as you suggest then sym applications already

> >implemented will likely end up with pools sized for a session size they don’t need.

> >

> >As I think the combined pool case unlikely, it makes more sense to me that this

> >fn should have comment changed to say it returns only sym session size

> >for backwards capability reasons, but will be deprecated

> >and appls should use get_sym_session_private_size instead.

> 

> [Shally] Ok agree. I will revert to its original definition.

> >

> 

> // snip

> 

> //snip

> 

> >> +/**

> >> + * Create a asymmetric session mempool to allocate sessions from

> >> + *

> >> + * @param	dev		Crypto device pointer

> >> + * @param	nb_objs		Number of asymmetric sessions objects in mempool

> >> + * @param	obj_cache	l-core object cache size, see *rte_ring_create*

> >> + * @param	socket_id	Socket Id to allocate  mempool on.

> >> + *

> >> + * @return

> >> + * - On success returns a pointer to a rte_mempool

> >> + * - On failure returns a NULL pointer

> >> + */

> >> +typedef int (*cryptodev_asym_create_session_pool_t)(

> >> +		struct rte_cryptodev *dev, unsigned nb_objs,

> >> +		unsigned obj_cache_size, int socket_id);

> >>

> >[Fiona] session pools are not created now per device so this is never called for sym and

> >should be deprecated. So no need to add for asym

> 

> [Shally] Ok

> 

> >

> //snip

> 

> >> +	cryptodev_sym_get_session_private_size_t sym_session_get_size;

> >> +	/**< Return private size for symmetric crypto. */

> >> +	cryptodev_sym_get_session_private_size_t asym_session_get_size;

> >> +	/**< Return private size for asymmetric crypto. */

> >>  	cryptodev_sym_configure_session_t session_configure;

> >>  	/**< Configure a Crypto session. */

> >[Fiona] This should really be renamed sym_session_configure, same for session_clear,

> >qp_attach_session and qp_detach_session

> >

> 

> [Shally] I thought to keep it backward compatible for now. I think we can take this change later as it need

> announcement first

[Fiona] As these are on the internal API between PMDs and API layer, rather than the application<->cryptodev
interface I think they don't need an announcement.
But would need to be done in a standalone patch, with all PMDs changed

> >> +	cryptodev_asym_configure_session_t asym_session_configure;

> >> +	/**< Configure asymmetric Crypto session. */

> 

> //snip

> 

> >> +

> >> +EXPERIMENTAL {

> >> +	global:

> >> +

> >[Fiona] the implementation of all these APIs also needs the _experimental tag.

> >

> 

> [Shally] Got that.

> 

> >> +	rte_cryptodev_asym_capability_get;

> >> +	rte_cryptodev_asym_capability_modlen;

> >> +	rte_cryptodev_asym_queue_pair_count;

> >> +	rte_cryptodev_asym_session_create;

> >> +	rte_cryptodev_asym_session_clear;

> >> +	rte_cryptodev_asym_session_free;

> >> +	rte_cryptodev_asym_session_init;

> >> +	rte_cryptodev_get_asym_session_private_size;

> >> +	rte_cryptodev_get_sym_session_private_size;

> >> +	rte_cryptodev_get_xform_algo_enum;

> >> +	rte_cryptodev_queue_pair_attach_asym_session;

> >> +	rte_cryptodev_queue_pair_detach_asym_session;

> >> +	rte_cryptodev_sym_queue_pair_count;

> >> +	rte_crypto_asym_xform_strings;

> >> +	rte_crypto_asym_operation_strings;

> >> +

> >> +};

> >> --

> >> 1.9.1

> 

> Thanks

> Shally
  
Verma, Shally March 16, 2018, 8:02 a.m. UTC | #8
Hi Fiona

Thanks for feedback. PSB.

>-----Original Message-----

>From: Trahe, Fiona [mailto:fiona.trahe@intel.com]

>Sent: 14 March 2018 17:42

>To: Verma, Shally <Shally.Verma@cavium.com>; dev@dpdk.org; Athreya, Narayana Prasad <NarayanaPrasad.Athreya@cavium.com>;

>Murthy, Nidadavolu <Nidadavolu.Murthy@cavium.com>; Sahu, Sunila <Sunila.Sahu@cavium.com>; Gupta, Ashish

><Ashish.Gupta@cavium.com>; Doherty, Declan <declan.doherty@intel.com>; Keating, Brian A <brian.a.keating@intel.com>; Griffin,

>John <john.griffin@intel.com>; Tadepalli, Hari K <hari.k.tadepalli@intel.com>

>Cc: De Lara Guarch, Pablo <pablo.de.lara.guarch@intel.com>; Trahe, Fiona <fiona.trahe@intel.com>

>Subject: RE: [dpdk-dev] [RFC v1 1/1] lib/cryptodev: add support of asymmetric crypto

>


//snip

>> >> +enum rte_crypto_asym_op_type {

>> >> +	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,

>> >[Fiona] Why does this start at 1?

>> >And is it necessary?

>> >

>> [Shally]  We need to indicate list of supported op in xform capability structure. Because an implementation

>> may support RSA encrypt and decrypt but not RSA Sign and verify. Or, Can support DSA Sign compute but

>> not verify.

>> So, it was added to indicate end-of-array marker (though doesn’t need to be 1 for that reason). but now

>> when I think to re-design its support, then it won't be needed.

>> So, I thought rather than carrying op_type array, I can add an op_type bitmask in xform capability to show

>> supported ops.

>[Fiona] I think a bitmask is ok. Would only need an array if there were other params whose capabilities would

> vary depending on the op_type. E.g. like range of digest_size in sym depends on the algo. But does code below

>not need a xform_type input? Or is capa the capability for one specific xform_type?


[Shally] Yes. capability here is of one xform. I will change variable name to rte_crypto_asym_xform_capabilities to be more clear here.

>

>> Example capability check code then would look like:

>> int rte_crypto_asym_check_op_type ( const rte_crypto_asym_capabilties *capa, int op_type) {

>> 	If(capa->op_types & (1 << op_type))

>> 		return 0;

>> 	return -1;

>> }


//snip

>> >> +	/**< Signature verification operation */

>> >> +	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,

>> >> +	/**< Public/Private key pair generation operation */

>> >[Fiona] In the comment, clarify that this is for DH and ECDH, and for the

>> > generation of the public key (and optionally the private key?)

>> >

>>

>> [Shally] so far, I was assuming it will generate both but when you say private key optional, where you

>> expect it to be coming from? - from app or generated internally? Is their hw variant which may not

>> generate private key?

>>

>[Fiona] In our native driver the private key, which is usually just a random number conforming to

>0 < private_key < (primeP - 1), is passed in by the application and only the public key is generated.

>Some hw accelerators may have RNG capabilities, others may not or the application may prefer to generate

>its own RN.

>


[Shally] Ok. I will work around to add this support.

//snip

>>

>> [Shally] I would take this question in-parts:

>>

>> " Also do we want to list all "published" curves, or allow customers to specify their own curve parameters,"

>> - Currently specification allow app to do both i.e. it can either setup these published curve ids or specify its

>> own domain params to all elliptic curve based xforms (ecdh, ecdsa, and fecc).

>>   If input curve has curve_type = UNSPECIFIED, PMD uses domain parameters else it uses curveid given by

>> app from this published list.

>>   So, is this missing any requirement that need to be supported?!

>[Fiona] So you mean the params in ECDH xform (a,b,G,n,h) are only specified if curve_type = UNSPECIFIED,

>else not needed? And in FECC the params (order,G,a,b,h) ?

>Ecdsa xform not yet specified, but it will have a similar set?

>Then I would suggest creating a struct to hold this param set and using same struct in all 3 xforms.

>

[Shally] Ok. Sounds better. See new proposed struct below.

//snip 

>> "do we have to publish curves < 224 bits"

>> - We just listed all based on previous feedback to include non-nist curve id. But agree it can be narrowed

>> down to few (may be to one used by ssl)

>[Fiona] I'm looking for feedback internally on this - will get back to you later.

>But I think it could be trimmed to at least removing those curves < 224 bits.

>The xform params can be used to cover unlikely curves trimmed from the list.

>

[Shally] I look forward to it.

//snip

>> >> +

>> >> +/**

>> >> + * Elliptic curve id

>> >> + */

>> >> +struct rte_crypto_ec_curve_id {

>> >> +	RTE_STD_C11

>> >> +	union {

>> >> +		enum rte_crypto_ec_prime_curve pcurve;

>> >> +		enum rte_crypto_ec_binary_curve bcurve;

>> >> +	};

>> >> +};

>> >[Fiona] Because the values of these two enums overlap, if you specify the curve type incorrectly, you'll still

>> >have a potentially valid curve enum specified. I suggest it's safer to include the type here with the union,

>> >rather than in the wrapper xform struct, i.e.

>> >struct rte_crypto_ec_curve {

>> >	enum rte_crypto_ec_curve_type curve_type;

>> >	/**< curve type: Prime vs Binary */

>> >	union {

>> >	enum rte_crypto_ec_prime_curve pcurve_id;

>> >	enum rte_crypto_ec_binary_curve bcurve_id;

>> >	};

>> >};

>> [Shally] We would need curve type if we need to define a new curve based on domain params. Let's cover

>> it later once we clarify above feedback.

>[Fiona] So how about adding the struct with curve params I mentioned above as a 3rd element in the union?

>


[Shally] Yes agreed. So new structs looks like:

struct rte_crypto_ec_domain_params { g, a , b, n ,h };

struct rte_crypto_ec_curve {
	enum rte_crypto_ec_curve_type curve_type;
	/**< curve type: Prime vs Binary */
	union {
	enum rte_crypto_ec_prime_curve pcurve_id;
	enum rte_crypto_ec_binary_curve bcurve_id;
	struct rte_crypto_ec_domain_params dparams;
	};
};
//snip

>> >>  	cryptodev_sym_configure_session_t session_configure;

>> >>  	/**< Configure a Crypto session. */

>> >[Fiona] This should really be renamed sym_session_configure, same for session_clear,

>> >qp_attach_session and qp_detach_session

>> >

>>

>> [Shally] I thought to keep it backward compatible for now. I think we can take this change later as it need

>> announcement first

>[Fiona] As these are on the internal API between PMDs and API layer, rather than the application<->cryptodev

>interface I think they don't need an announcement.

>But would need to be done in a standalone patch, with all PMDs changed

>


[Shally] ok.

So, I will cover elliptic curve and session_configure change in separate patches and send 1st patch with features covered and agreed.


//snip

Thanks
Shally
  

Patch

diff --git a/lib/librte_cryptodev/Makefile b/lib/librte_cryptodev/Makefile
index bba8dee..dec325b 100644
--- a/lib/librte_cryptodev/Makefile
+++ b/lib/librte_cryptodev/Makefile
@@ -21,6 +21,7 @@  SRCS-y += rte_cryptodev.c rte_cryptodev_pmd.c
 # export include files
 SYMLINK-y-include += rte_crypto.h
 SYMLINK-y-include += rte_crypto_sym.h
+SYMLINK-y-include += rte_crypto_asym.h
 SYMLINK-y-include += rte_cryptodev.h
 SYMLINK-y-include += rte_cryptodev_pmd.h
 
diff --git a/lib/librte_cryptodev/rte_crypto.h b/lib/librte_cryptodev/rte_crypto.h
index 95cf861..e8c0bac 100644
--- a/lib/librte_cryptodev/rte_crypto.h
+++ b/lib/librte_cryptodev/rte_crypto.h
@@ -23,6 +23,7 @@ 
 #include <rte_common.h>
 
 #include "rte_crypto_sym.h"
+#include "rte_crypto_asym.h"
 
 /** Crypto operation types */
 enum rte_crypto_op_type {
@@ -30,6 +31,8 @@  enum rte_crypto_op_type {
 	/**< Undefined operation type */
 	RTE_CRYPTO_OP_TYPE_SYMMETRIC,
 	/**< Symmetric operation */
+	RTE_CRYPTO_OP_TYPE_ASYMMETRIC
+	/**< Asymmetric operation */
 };
 
 /** Status of crypto operation */
@@ -97,6 +100,10 @@  struct rte_crypto_op {
 	union {
 		struct rte_crypto_sym_op sym[0];
 		/**< Symmetric operation parameters */
+
+		struct rte_crypto_asym_op asym[0];
+		/**< Asymmetric operation parameters */
+
 	}; /**< operation specific parameters */
 };
 
@@ -117,6 +124,9 @@  struct rte_crypto_op {
 	case RTE_CRYPTO_OP_TYPE_SYMMETRIC:
 		__rte_crypto_sym_op_reset(op->sym);
 		break;
+	case RTE_CRYPTO_OP_TYPE_ASYMMETRIC:
+		__rte_crypto_asym_op_reset(op->asym);
+		break;
 	case RTE_CRYPTO_OP_TYPE_UNDEFINED:
 	default:
 		break;
@@ -124,7 +134,7 @@  struct rte_crypto_op {
 }
 
 /**
- * Private data structure belonging to a crypto symmetric operation pool.
+ * Private data structure belonging to a crypto operation pool.
  */
 struct rte_crypto_op_pool_private {
 	enum rte_crypto_op_type type;
@@ -283,9 +293,14 @@  struct rte_crypto_op_pool_private {
 	if (likely(op->mempool != NULL)) {
 		priv_size = __rte_crypto_op_get_priv_data_size(op->mempool);
 
-		if (likely(priv_size >= size))
-			return (void *)((uint8_t *)(op + 1) +
+		if (likely(priv_size >= size)) {
+			if (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC)
+				return (void *)((uint8_t *)(op + 1) +
 					sizeof(struct rte_crypto_sym_op));
+			if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC)
+				return (void *)((uint8_t *)(op+1) +
+					sizeof(struct rte_crypto_asym_op));
+		}
 	}
 
 	return NULL;
@@ -388,6 +403,24 @@  struct rte_crypto_op_pool_private {
 	return __rte_crypto_sym_op_attach_sym_session(op->sym, sess);
 }
 
+/**
+ * Attach a asymmetric session to a crypto operation
+ *
+ * @param	op	crypto operation, must be of type asymmetric
+ * @param	sess	cryptodev session
+ */
+static inline int
+rte_crypto_op_attach_asym_session(struct rte_crypto_op *op,
+		struct rte_cryptodev_asym_session *sess)
+{
+	if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_ASYMMETRIC))
+		return -1;
+
+	op->sess_type = RTE_CRYPTO_OP_WITH_SESSION;
+
+	return __rte_crypto_op_attach_asym_session(op->asym, sess);
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_cryptodev/rte_crypto_asym.h b/lib/librte_cryptodev/rte_crypto_asym.h
new file mode 100644
index 0000000..27caf55
--- /dev/null
+++ b/lib/librte_cryptodev/rte_crypto_asym.h
@@ -0,0 +1,949 @@ 
+/*
+ *   BSD LICENSE
+ *
+ *   Copyright (C) Cavium networks Ltd. 2017.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Cavium Networks nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_CRYPTO_ASYM_H_
+#define _RTE_CRYPTO_ASYM_H_
+
+/**
+ * @file rte_crypto_asym.h
+ *
+ * RTE Definitions for Asymmetric Cryptography
+ *
+ * Defines asymmetric algorithms and modes, as well as supported
+ * asymmetric crypto operations.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <string.h>
+#include <stdint.h>
+#include <rte_mbuf.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_common.h>
+
+typedef struct rte_crypto_xform_param_t {
+	uint8_t *data;
+	phys_addr_t phys_addr;
+	size_t length;
+} rte_crypto_xform_param;
+
+typedef struct rte_crypto_op_param_t {
+	uint8_t *data;
+	phys_addr_t phys_addr;
+	size_t length;
+} rte_crypto_op_param;
+
+/**
+ * Asymmetric crypto transformation types.
+ * Each xform type maps to one asymmetric algorithm
+ * performing specific operation
+ *
+ */
+enum rte_crypto_asym_xform_type {
+	RTE_CRYPTO_ASYM_XFORM_NONE = 0,
+	/**< Xform type None. May be supported by
+	 * PMD to support passthrough op for debugging
+	 * purpose.
+	 * if xform_type none , op_type is disregarded.
+	 */
+	RTE_CRYPTO_ASYM_XFORM_RSA,
+	/**< RSA. Performs Encrypt, Decrypt, Sign and Verify
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_MODEX,
+	/**< Modular Exponentiation
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_DH,
+	/**< Deffie-Hellman. Perform Key Generate, Key Compute
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_ECDH,
+	/**< Elliptic Curve Deffie-Hellman.
+	 * Perform Key Genearate, Key Check and Key Compute
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_DSA,
+	/**< Digital Signature Algorithm
+	 * Performs Signature verification and Generation
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_ECDSA,
+	/**< Elliptic Curve Digital Signature Algorithm.
+	 * Performs Signature Generation, and Verification.
+	 * Refer to rte_crypto_asym_op_type
+	 */
+	RTE_CRYPTO_ASYM_XFORM_FECC,
+	/**< Fundamental Elliptic curve operations.
+	 * Perform elliptic curve operation:
+	 * add, double point, multiplication
+	 * Refer to enum rte_crypto_fecc_optype
+	 */
+	RTE_CRYPTO_ASYM_XFORM_MODINV,
+	/**< Modular Inverse */
+	RTE_CRYPTO_ASYM_XFORM_TYPE_LIST_END
+	/**< End of list */
+};
+
+/**
+ * Asymmetric cryptogr operation type variants
+ */
+enum rte_crypto_asym_op_type {
+	RTE_CRYPTO_ASYM_OP_NOT_SPECIFIED = 1,
+	/**< Operation unspecified */
+	RTE_CRYPTO_ASYM_OP_ENCRYPT,
+	/**< Asymmetric encrypt operation */
+	RTE_CRYPTO_ASYM_OP_DECRYPT,
+	/**< Asymmetric Decrypt operation */
+	RTE_CRYPTO_ASYM_OP_SIGN,
+	/**< Signature generation operation */
+	RTE_CRYPTO_ASYM_OP_VERIFY,
+	/**< Signature verification operation */
+	RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION,
+	/**< Public/Private key pair generation operation */
+	RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION,
+	/**< DH private key computation operation */
+	RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK,
+	/**< ECDH public key validity check operation */
+	RTE_CRYPTO_ASYM_OP_LIST_END
+};
+
+/**
+ * Padding types for RSA signature.
+ */
+enum rte_crypto_rsa_padding_type {
+	RTE_CRYPTO_RSA_PADDING_NOT_SPECIFIED = 1,
+	/**< RSA no padding scheme */
+	RTE_CRYPTO_RSA_PADDING_BT1,
+	/**< RSA PKCS#1 padding BT1 scheme */
+	RTE_CRYPTO_RSA_PADDING_BT2,
+	/**< RSA PKCS#1 padding BT2 scheme */
+	RTE_CRYPTO_RSA_PADDING_OAEP,
+	/**< RSA PKCS#1 OAEP padding scheme */
+	RTE_CRYPTO_RSA_PADDING_PSS,
+	/**< RSA PKCS#1 PSS padding scheme */
+	RTE_CRYPTO_RSA_PADDING_TYPE_LIST_END
+};
+
+
+/**
+ * Fundamental ECC operation type variants.
+ */
+enum rte_crypto_fecc_optype {
+	RTE_CRYPTO_FECC_OP_NOT_SPECIFIED = 1,
+	/**< FECC operation type unspecified */
+	RTE_CRYPTO_FECC_OP_POINT_ADD,
+	/**< Fundamental ECC point addition operation */
+	RTE_CRYPTO_FECC_OP_POINT_DBL,
+	/**< Fundamental ECC point doubling operation */
+	RTE_CRYPTO_FECC_OP_POINT_MULTIPLY,
+	/**< Fundamental ECC point multiplication operation */
+	RTE_CRYPTO_FECC_OP_LIST_END
+};
+
+#define RTE_CRYPTO_EC_CURVE_NOT_SPECIFIED  -1
+/**
+ * ECC list of curves.
+ */
+enum rte_crypto_ec_prime_curve {
+	/**< Unspecified or empty curve id */
+	RTE_CRYPTO_EC_CURVE_secp112r1,
+	/**< SECG/WTLS curve over a 112 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp112r2,
+	/**< SECG curve over a 112 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp128r1,
+	/**< SECG curve over a 128 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp128r2,
+	/**< SECG curve over a 128 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp160k1,
+	/**< SECG curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp160r1,
+	/**< SECG curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp160r2,
+	/**< SECG/WTLS curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp192k1,
+	/**< SECG curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp224k1,
+	/**< SECG curve over a 224 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp224r1,
+	/**< NIST/SECG curve over a 224 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp256k1,
+	/**< SECG curve over a 256 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp384r1,
+	/**< NIST/SECG curve over a 384 bit prime field */
+	RTE_CRYPTO_EC_CURVE_secp521r1,
+	/**< NIST/SECG curve over a 521 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime192v1,
+	/**< NIST/X9.62/SECG curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime192v2,
+	/**< X9.62 curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime192v3,
+	/**< X9.62 curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime239v1,
+	/**< X9.62 curve over a 239 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime239v2,
+	/**< X9.62 curve over a 239 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime239v3,
+	/**< X9.62 curve over a 239 bit prime field */
+	RTE_CRYPTO_EC_CURVE_prime256v1,
+	/**< X9.62/SECG curve over a 256 bit prime field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls6,
+	/**< SECG/WTLS curve over a 112 bit prime field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls7,
+	/**< SECG/WTLS curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls8,
+	/**< WTLS curve over a 112 bit prime field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls9,
+	/**< WTLS curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls12,
+	/**< WTLS curve over a 224 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP160r1,
+	/**< RFC 5639 curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP160t1,
+	/**< RFC 5639 curve over a 160 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP192r1,
+	/**< RFC 5639 curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP192t1,
+	/**< RFC 5639 curve over a 192 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP224r1,
+	/**< RFC 5639 curve over a 224 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP224t1,
+	/**< RFC 5639 curve over a 224 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP256r1,
+	/**< RFC 5639 curve over a 256 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP256t1,
+	/**< RFC 5639 curve over a 256 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP320r1,
+	/**< RFC 5639 curve over a 320 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP320t1,
+	/**< RFC 5639 curve over a 320 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP384r1,
+	/**< RFC 5639 curve over a 384 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP384t1,
+	/**< RFC 5639 curve over a 384 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP512r1,
+	/**< RFC 5639 curve over a 512 bit prime field */
+	RTE_CRYPTO_EC_CURVE_brainpoolP512t1,
+	/**< RFC 5639 curve over a 512 bit prime field */
+	RTE_CRYPTO_EC_CURVE_x25519,
+	/**< Curve 25519 */
+	RTE_CRYPTO_EC_PCURVE_LIST_END
+};
+
+enum rte_crypto_ec_binary_curve {
+	/**< Unspecified or empty curve id */
+	RTE_CRYPTO_EC_CURVE_sect113r1,
+	/**< SECG curve over a 113 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect113r2,
+	/**< SECG curve over a 113 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect131r1,
+	/**< SECG/WTLS curve over a 131 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect131r2,
+	/**< SECG curve over a 131 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect163k1,
+	/**< NIST/SECG/WTLS curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect163r1,
+	/**< SECG curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect163r2,
+	/**< NIST/SECG curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect193r1,
+	/**< SECG curve over a 193 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect193r2,
+	/**< SECG curve over a 193 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect233k1,
+	/**< NIST/SECG/WTLS curve over a 233 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect233r1,
+	/**< NIST/SECG/WTLS curve over a 233 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect239k1,
+	/**< SECG curve over a 239 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect283k1,
+	/**< NIST/SECG curve over a 283 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect283r1,
+	/**< NIST/SECG curve over a 283 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect409k1,
+	/**< NIST/SECG curve over a 409 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect409r1,
+	/**< NIST/SECG curve over a 409 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect571k1,
+	/**< NIST/SECG curve over a 571 bit binary field */
+	RTE_CRYPTO_EC_CURVE_sect571r1,
+	/**< NIST/SECG curve over a 571 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb163v1,
+	/**< X9.62 curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb163v2,
+	/**< X9.62 curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb163v3,
+	/**< X9.62 curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb176v1,
+	/**< X9.62 curve over a 176 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb191v1,
+	/**< X9.62 curve over a 191 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb191v2,
+	/**< X9.62 curve over a 191 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb191v3,
+	/**< X9.62 curve over a 191 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb208w1,
+	/**< X9.62 curve over a 208 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb239v1,
+	/**< X9.62 curve over a 239 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb239v2,
+	/**< X9.62 curve over a 239 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb239v3,
+	/**< X9.62 curve over a 239 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb272w1,
+	/**< X9.62 curve over a 272 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb304w1,
+	/**< X9.62 curve over a 304 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb359v1,
+	/**< X9.62 curve over a 359 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2pnb368w1,
+	/**< X9.62 curve over a 368 bit binary field */
+	RTE_CRYPTO_EC_CURVE_c2tnb431r1,
+	/**< X9.62 curve over a 431 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls1,
+	/**< WTLS curve over a 113 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls3,
+	/**< NIST/SECG/WTLS curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls4,
+	/**< SECG curve over a 113 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls5,
+	/**< X9.62 curve over a 163 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls10,
+	/**< NIST/SECG/WTLS curve over a 233 bit binary field */
+	RTE_CRYPTO_EC_CURVE_wap_wsg_idm_ecid_wtls11,
+	/**< NIST/SECG/WTLS curve over a 233 bit binary field */
+	RTE_CRYPTO_EC_BCURVE_LIST_END
+};
+
+/**
+ * Elliptic curve point format
+ */
+struct rte_crypto_ec_point {
+	struct {
+		int length;
+		uint8_t *data;
+		phys_addr_t phys_addr;
+		/**< phys_addr is used only for points passed in the
+		 * asym_op structure.
+		 */
+	} x;
+	/**< X co-ordinate */
+
+	struct {
+		int length;
+		uint8_t *data;
+		phys_addr_t phys_addr;
+		/**< phys_addr is used only for points passed in the
+		 * operation structure
+		 */
+	} y;
+	/**< Y co-ordinate */
+};
+
+/**
+ * Elliptic curve type
+ */
+enum rte_crypto_ec_curve_type {
+	RTE_CRYPTO_EC_CURVE_TYPE_UNDEFINED,
+	/**< Curve type undefined */
+	RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD,
+	/**< EC curve defined over a prime field */
+	RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD,
+	/**< EC curve defined over a binary field */
+	RTE_CRYPTO_EC_CURVE_LIST_END
+};
+
+/** asym xform type name strings */
+extern const char *
+rte_crypto_asym_xform_strings[];
+
+/** asym operations type name strings */
+extern const char *
+rte_crypto_asym_op_strings[];
+
+/**
+ * Elliptic curve id
+ */
+struct rte_crypto_ec_curve_id {
+	RTE_STD_C11
+	union {
+		enum rte_crypto_ec_prime_curve pcurve;
+		enum rte_crypto_ec_binary_curve bcurve;
+	};
+};
+
+/**
+ * Asymmetric RSA transform data
+ *
+ * This structure contains data required to perform RSA crypto
+ * transform.
+ *
+ */
+struct rte_crypto_rsa_xform {
+
+	rte_crypto_xform_param n;
+	/**< n - Prime modulus
+	 * Prime modulus data of RSA operation in Octet-string network
+	 * byte order format.
+	 */
+
+	rte_crypto_xform_param e;
+	/**< e - Public key exponent
+	 * Public key exponent used for RSA public key operations in Octet-
+	 * string network byte order format.
+	 */
+
+	rte_crypto_xform_param d;
+	/**< d - Private key exponent
+	 * Private key exponent used for RSA private key operations in
+	 * Octet-string  network byte order format.
+	 */
+
+	rte_crypto_xform_param p;
+	/**< p - Private key component P
+	 * Private key component of RSA parameter  required for CRT method
+	 * of private key operations in Octet-string network byte order
+	 * format.
+	 */
+
+	rte_crypto_xform_param q;
+	/**< q - Private key component Q
+	 * Private key component of RSA parameter  required for CRT method
+	 * of private key operations in Octet-string network byte order
+	 * format.
+	 */
+
+	rte_crypto_xform_param dP;
+	/**< dP - Private CRT component
+	 * Private CRT component of RSA parameter  required for CRT method
+	 * RSA private key operations in Octet-string network byte order
+	 * format.
+	 * dP = d mod ( p - 1 )
+	 */
+
+	rte_crypto_xform_param dQ;
+	/**< dQ - Private CRT component
+	 * Private CRT component of RSA parameter  required for CRT method
+	 * RSA private key operations in Octet-string network byte order
+	 * format.
+	 * dQ = d mod ( q - 1 )
+	 */
+
+	rte_crypto_xform_param qInv;
+	/**< qInv - Private CRT component
+	 * Private CRT component of RSA parameter  required for CRT method
+	 * RSA private key operations in Octet-string network byte order
+	 * format.
+	 * qInv = inv q mod p
+	 */
+};
+
+/**
+ * Asymmetric Modular exponentiation transform data
+ *
+ * This structure contains data required to perform modular exponentation
+ * crypto transform.
+ *
+ */
+struct rte_crypto_modex_xform {
+
+	rte_crypto_xform_param modulus;
+	/**< modulus
+	 * Prime modulus of the modexp transform operation in Octet-string
+	 * network byte order format.
+	 */
+
+	rte_crypto_xform_param exponent;
+	/**< exponent
+	 * Private exponent of the modexp transform operation in
+	 * Octet-string network byte order format.
+	 */
+};
+
+/**
+ * Asymmetric DH transform data
+ *
+ * This structure contains data used to perform DH key
+ * operations.
+ *
+ */
+struct rte_crypto_dh_xform {
+	rte_crypto_xform_param p;
+	/**< p : Prime modulus data
+	 * DH prime modulous data in Octet-string network byte order format.
+	 */
+
+	rte_crypto_xform_param g;
+	/**< g : Generator
+	 * DH group generator data in Octet-string network byte order
+	 * format.
+	 */
+};
+
+/**
+ * Asymmetric ECDH transform data
+ *
+ * This structure contains data required to perform ECDH crypto
+ * transform.
+ *
+ */
+struct rte_crypto_ecdh_xform {
+
+	enum rte_crypto_ec_curve_type curve_type;
+	/**< ECDH curve type: Prime vs Binary */
+
+	struct rte_crypto_ec_curve_id curve_id;
+
+	rte_crypto_xform_param p;
+	/**< p:
+	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_PRIME_FIELD:
+	 * p holds the prime modulus data in Octet string format.
+	 *
+	 * If the curve_type is @ref RTE_CRYPTO_EC_CURVE_TYPE_BINARY_FIELD:
+	 * p holds reduction polynomial co-efficients and degree.
+	 */
+
+	rte_crypto_xform_param a;
+	/**< Curve Parameter Co-efficient 'a' of curve equation data in
+	 * Octet-string network byte order format.
+	 */
+
+	rte_crypto_xform_param b;
+	/**< Curve Parameter Co-efficient 'b' of curve equation data in
+	 * Octet-string network byte order format.
+	 */
+
+	struct  rte_crypto_ec_point G;
+	/**< G: EC curve generator point
+	 * EC curve generator point data in Octet-string network byte order
+	 * format.
+	 */
+
+	rte_crypto_xform_param n;
+	/**< n : order of G
+	 * ECDH curve order data in Octet-string network byte order format.
+	 */
+
+	int h;
+	/**< Co-factor of the curve */
+
+	rte_crypto_xform_param pkey;
+	/**< pkey: Private key
+	 * Private key data for ECDH operation in Octet-string network byte
+	 * order format.
+	 */
+
+	struct rte_crypto_ec_point Q;
+	/**< Q: Public key point
+	 * Public key point data of ECDH operation in Octet-string network
+	 * byte order format.
+	 */
+};
+
+/**
+ * Asymmetric Digital Signature transform operation
+ *
+ * This structure contain signer key information for DSA signature
+ * generation and verification.
+ * App which does both Signature Generation and Verification should
+ * create two separate session carrying its own and peer key information
+ *
+ */
+struct rte_crypto_dsa_xform {
+	rte_crypto_xform_param p;
+	/**< p - Prime modulus
+	 * Prime modulus data for DSA operation in Octet-string network byte
+	 * order format.
+	 */
+	rte_crypto_xform_param q;
+	/**< q : Order of the subgroup.
+	 * Order of the subgroup data in Octet-string network byte order
+	 * format.
+	 * (p-1) % q = 0
+	 */
+	rte_crypto_xform_param g;
+	/**< g: Generator of the subgroup
+	 * Generator  data in Octet-string network byte order format.
+	 */
+	rte_crypto_xform_param x;
+	/**< x: Private key of the signer
+	 * Private key data in Octet-string network byte order format.
+	 * Private key is valid only for signature generation operation.
+	 */
+	rte_crypto_xform_param y;
+	/**< y : Public key of the signer.
+	 * Public key data of the signer in Octet-string network byte order
+	 * format.
+	 * y = g^x mod p
+	 */
+};
+
+/** 
+ * Asymmetric ECDSA transform data
+ *
+ * This structure contains data required to perform ECDSA crypto
+ * transform.
+ */
+struct rte_crypto_ecdsa_xform {
+	/** TBD */
+};
+
+/**
+ * Asymmetric modular inverse transform operation
+ *
+ * This structure contains data required to perform
+ * asymmetric modular inverse crypto transform
+ */
+struct rte_crypto_modinv_xform {
+	/** TBD */
+};
+
+/** Asymmetric Fundamental ECC transform operation
+ *
+ * This structure contains data required to perform asymmetric
+ * fundamental ECC crypto transform.
+ */
+struct rte_crypto_fecc_xform {
+
+	enum rte_crypto_ec_curve_type curve_type;
+	/**< FECC curve type: Prime vs Binary */
+
+	struct rte_crypto_ec_curve_id curve_id;
+	/**< EC curve ID */
+
+	rte_crypto_xform_param order;
+	/**< order : ECC curve order
+	 * Curve order data in Octet-string network byte order format.
+	 */
+
+	rte_crypto_xform_param prime;
+	/**< prime : Curve prime modulus data
+	 * Prime modulus data in Octet-string network byte order format.
+	 */
+
+	struct rte_crypto_ec_point G;
+	/**< G: curve generator point
+	 * Curve generator point data in Octet-string network byte order
+	 * format.
+	 */
+
+	rte_crypto_xform_param a;
+	/**< Co-efficient 'a' of curve equation data in Octet-string network
+	 * byte order format.
+	 */
+
+	rte_crypto_xform_param b;
+	/**< Co-efficient 'a' of curve equation data in Octet-string network
+	 * byte order format.
+	 */
+
+	int h;
+	/**< Co-factor of the curve */
+
+};
+
+/**
+ * Asymmetric crypto transform data
+ *
+ * This structure contains the data required to perform the
+ * asymmetric crypto transformation operation. The field op
+ * determines the asymmetric algorithm for transformation.
+ */
+struct rte_crypto_asym_xform {
+	struct rte_crypto_asym_xform *next;
+	enum rte_crypto_asym_xform_type xform_type;
+	/**< Asymmetric algorithm for crypto transform */
+
+	RTE_STD_C11
+	union {
+		struct rte_crypto_rsa_xform rsa;
+		/**< RSA xform parameters */
+
+		struct rte_crypto_fecc_xform fecc;
+		/**< Fundamental Elliptic Curve xform parameters */
+
+		struct rte_crypto_modex_xform modex;
+		/**< Modular Exponentiation xform parameters */
+
+		struct rte_crypto_modinv_xform modinv;
+		/**< Modulus Inverse xform parameters */
+
+		struct rte_crypto_ecdsa_xform ecdsa;
+		/**< ECDSA xform parameters */
+
+		struct rte_crypto_ecdh_xform ecdh;
+		/**< ECDH xform parameters */
+
+		struct rte_crypto_dsa_xform dsa;
+		/**< DSA xform parameters */
+	};
+};
+
+struct rte_cryptodev_asym_session;
+
+/**
+ * RSA operation params
+ *
+ */
+struct rte_crypto_rsa_op_param {
+	enum rte_crypto_asym_op_type op_type;
+	/**< Type of RSA operation for transform */;
+
+	rte_crypto_op_param message;
+	/**<
+	 * Pointer to data
+	 * - to be encrypted for RSA public encrypt.
+	 * - to be decrypted for RSA private decrypt.
+	 * - to be signed for RSA sign generation.
+	 * - to be authenticated for RSA sign verification.
+	 */
+
+	rte_crypto_op_param sign;
+	/**<
+	 * Pointer to RSA signature data. If operation is RSA
+	 * sign @ref RTE_CRYPTO_RSA_OP_SIGN, buffer will be
+	 * over-written with generated signature.
+	 *
+	 * Length of the signature data will be equal to the
+	 * RSA prime modulus length.
+	 */
+
+	enum rte_crypto_rsa_padding_type pad;
+	/**< RSA padding scheme to be used for transform */
+
+	enum rte_crypto_auth_algorithm md;
+	/**< Hash algorithm to be used for data hash if padding
+	 * scheme is either OAEP or PSS. Valid hash algorithms
+	 * are:
+	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512
+	 */
+
+	enum rte_crypto_auth_algorithm mgf1md;
+	/**<
+	 * Hash algorithm to be used for mask generation if
+	 * padding scheme is either OAEP or PSS. If padding
+	 * scheme is unspecified data hash algorithm is used
+	 * for mask generation. Valid hash algorithms are:
+	 * MD5, SHA1, SHA224, SHA256, SHA384, SHA512
+	 */
+};
+
+/**
+ * Deffie-Hellman Operations params
+ *
+ */
+struct rte_crypto_dh_op_param {
+	enum rte_crypto_asym_op_type op_type;
+	/**< Asymmetric op type: Key Generation / Computation */
+
+	rte_crypto_op_param pub_key;
+	/**<
+	 * Output native app public key when DH operation type is
+	 * KEY_GENERATION.
+	 * Input peer public key when DH operation is shared key
+	 * KEY_COMPUTATION
+	 * An Octet-string network byte order format.
+	 *
+	 */
+
+	rte_crypto_op_param priv_key;
+	/**<
+	 * Output native app private key if operation type
+	 * KEY_GENERATION.
+	 * Input native app private key when operation type
+	 * is KEY_COMPUTATION. priv_key is in
+	 * in Octet-string network byte order format.
+	 */
+
+	rte_crypto_op_param shared_key;
+	/*
+	 * Output when DH operation type is KEY_COMPUTATION:
+	 * computed. shared_key is written as
+	 * Octet-string network byte order format.
+	 * Ignored for KEY_GENERATION.
+	 */
+};
+
+/**
+ * DSA Operations params
+ *
+ */
+struct rte_crypto_dsa_op_param {
+	/** TBD */
+};
+
+/**
+ * Mod Exp Operations params
+ *
+ */
+struct rte_crypto_modex_op_param {
+	rte_crypto_op_param base;
+	/**<
+	 * Pointer to base of modular exponentiation data in
+	 * Octet-string network byte order format.
+	 */
+};
+
+/**
+ * Elliptic curve Deffie-Hellman Operations params
+ *
+ */
+struct rte_crypto_ecdh_op_param {
+	enum rte_crypto_asym_op_type op_type;
+	/**< Asymmetric operation: key generation, computation */
+
+	rte_crypto_op_param priv_key;
+	/**<
+	 * Output if operation type is KEY_PAIR_GENERATION,
+	 * output native app private key.
+	 * Input and output, If ECDH operation type is SHARED_KEY_COMPUTATION,
+	 * priv_key will hold the 'X' co-ordinate of the shared
+	 * secret EC point. priv_key is in Octet-string network
+	 * byte order.
+	 */
+
+	struct rte_crypto_ec_point pub_key;
+	/**<
+	 * Output if operation type is KEY_PAIR_GENERATION,
+	 * store native app public key.
+	 * Input if operation type is SHARED_KEY_COMPUTATION,
+	 * 
+	 * KEY_COMPUTATION:
+	 *  pub_key is in Octet-string network byte order.
+	 */
+};
+
+/**
+ * Elliptic Curve DSA Operations params
+ *
+ */
+struct rte_crypto_ecdsa_op_param {
+
+	enum rte_crypto_asym_op_type ecdsa_op;
+	/**< ECDSA crypto xform operation type: Signature
+	 *  generation/Verification
+	 */
+	/** TBD */
+};
+
+/**
+ * Fundamental Elliptic Curve Operations params
+ *
+ */
+struct rte_crypto_fecc_op_param {
+	enum rte_crypto_fecc_optype fecc_op;
+	/**< FECC crypto xform operation type */
+
+	/** TBD */
+};
+
+/**
+ * Mod Inv Operations params
+ *
+ */
+struct rte_crypto_modinv_op_param {
+	rte_crypto_op_param prime;
+	/**<
+	 * Pointer to the prime modulus data for modular
+	 * inverse operation in Octet-string network byte
+	 * order format.
+	 */
+
+	rte_crypto_op_param base;
+	/**<
+	 * Pointer to the base for the modular inverse
+	 * operation in Octet-string network byte order
+	 * format.
+	 */
+};
+
+/**
+ * Asymmetric Cryptographic Operation.
+ *
+ * This structure contains data relating to performing asymmetric cryptographic
+ * operation.
+ *
+ */
+struct rte_crypto_asym_op {
+	enum rte_crypto_asym_xform_type type;
+	/**< RSA, DH, ECDH, DSA etc */
+
+	struct rte_cryptodev_asym_session *session;
+	/**< Handle for the initialised session context */
+
+	RTE_STD_C11
+	union {
+		struct rte_crypto_rsa_op_param rsa;
+		struct rte_crypto_dh_op_param dh;
+		struct rte_crypto_modex_op_param modex;
+		struct rte_crypto_ecdh_op_param ecdh;
+		struct rte_crypto_ecdsa_op_param ecdsa;
+		struct rte_crypto_dsa_op_param dsa;
+		struct rte_crypto_fecc_op_param fecc;
+		struct rte_crypto_modinv_op_param modinv;
+	};
+} __rte_cache_aligned;
+
+/**
+ * Reset the fields of an asymmetric operation to their default values.
+ *
+ * @param	op	The crypto operation to be reset.
+ */
+static inline void
+__rte_crypto_asym_op_reset(struct rte_crypto_asym_op *op)
+{
+	memset(op, 0, sizeof(*op));
+}
+
+
+/**
+ * Attach a session to an asymmetric crypto operation
+ *
+ * @param	asym_op	crypto operation
+ * @param	sess	cryptodev session
+ */
+static inline int
+__rte_crypto_op_attach_asym_session(struct rte_crypto_asym_op *asym_op,
+		struct rte_cryptodev_asym_session *sess)
+{
+	asym_op->session = sess;
+	return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _RTE_CRYPTO_ASYM_H_ */
diff --git a/lib/librte_cryptodev/rte_cryptodev.c b/lib/librte_cryptodev/rte_cryptodev.c
index 7726d15..bad18c3 100644
--- a/lib/librte_cryptodev/rte_cryptodev.c
+++ b/lib/librte_cryptodev/rte_cryptodev.c
@@ -166,6 +166,33 @@  struct rte_cryptodev_callback {
 	[RTE_CRYPTO_AEAD_OP_DECRYPT]	= "decrypt"
 };
 
+/**
+ * Asymmetric crypto transform operation strings identifiers.
+ */
+const char *rte_crypto_asym_xform_strings[] = {
+	[RTE_CRYPTO_ASYM_XFORM_RSA]	= "rsa",
+	[RTE_CRYPTO_ASYM_XFORM_MODEX]	= "modexp",
+	[RTE_CRYPTO_ASYM_XFORM_DH]	= "dh",
+	[RTE_CRYPTO_ASYM_XFORM_ECDH]	= "ecdh",
+	[RTE_CRYPTO_ASYM_XFORM_DSA]	= "dsa",
+	[RTE_CRYPTO_ASYM_XFORM_ECDSA]	= "ecdsa",
+	[RTE_CRYPTO_ASYM_XFORM_MODINV]	= "modinv",
+	[RTE_CRYPTO_ASYM_XFORM_FECC]	= "fecc"
+};
+
+/**
+ * Asymmetric crypto operation strings identifiers.
+ */
+const char *rte_crypto_asym_op_strings[] = {
+	[RTE_CRYPTO_ASYM_OP_ENCRYPT]	= "encrypt",
+	[RTE_CRYPTO_ASYM_OP_DECRYPT]	= "decrypt",
+	[RTE_CRYPTO_ASYM_OP_SIGN]	= "sign",
+	[RTE_CRYPTO_ASYM_OP_VERIFY]	= "verify",
+	[RTE_CRYPTO_ASYM_OP_KEY_PAIR_GENERATION]	= "keypair_generate",
+	[RTE_CRYPTO_ASYM_OP_SHARED_KEY_COMPUTATION] = "sharedkey_computation",
+	[RTE_CRYPTO_ASYM_OP_ECDH_OP_KEY_CHECK]	= "ecdh_keycheck",
+};
+
 int
 rte_cryptodev_get_cipher_algo_enum(enum rte_crypto_cipher_algorithm *algo_enum,
 		const char *algo_string)
@@ -217,6 +244,24 @@  struct rte_cryptodev_callback {
 	return -1;
 }
 
+int
+rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
+		const char *xform_string)
+{
+	unsigned int i;
+
+	for (i = 1; i < RTE_DIM(rte_crypto_asym_xform_strings); i++) {
+		if (strcmp(xform_string,
+			   rte_crypto_asym_xform_strings[i]) == 0) {
+			*xform_enum = (enum rte_crypto_asym_xform_type) i;
+			return 0;
+		}
+	}
+
+	/* Invalid string */
+	return -1;
+}
+
 /**
  * The crypto auth operation strings identifiers.
  * It could be used in application command line.
@@ -262,6 +307,28 @@  struct rte_cryptodev_callback {
 
 }
 
+const struct rte_cryptodev_asymmetric_capability *
+rte_cryptodev_asym_capability_get(uint8_t dev_id,
+		const struct rte_cryptodev_asym_capability_idx *idx)
+{
+	const struct rte_cryptodev_capabilities *capability;
+	struct rte_cryptodev_info dev_info;
+	unsigned int i = 0;
+
+	memset(&dev_info, 0, sizeof(rte_cryptodev_info));
+	rte_cryptodev_info_get(dev_id, &dev_info);
+
+	while ((capability = &dev_info.capabilities[i++])->op !=
+			RTE_CRYPTO_OP_TYPE_UNDEFINED) {
+		if (capability->op != RTE_CRYPTO_OP_TYPE_ASYMMETRIC)
+			continue;
+
+		if (capability->asym.xform_type == idx->type)
+			return &capability->asym;
+	}
+	return NULL;
+};
+
 #define param_range_check(x, y) \
 	(((x < y.min) || (x > y.max)) || \
 	(y.increment != 0 && (x % y.increment) != 0))
@@ -601,6 +668,24 @@  struct rte_cryptodev *
 	return dev->data->nb_queue_pairs;
 }
 
+uint16_t
+rte_cryptodev_asym_queue_pair_count(uint8_t dev_id)
+{
+	struct rte_cryptodev *dev;
+
+	dev = &rte_crypto_devices[dev_id];
+	return dev->data->nb_asym_qp;
+}
+
+uint16_t
+rte_cryptodev_sym_queue_pair_count(uint8_t dev_id)
+{
+	struct rte_cryptodev *dev;
+
+	dev = &rte_crypto_devices[dev_id];
+	return dev->data->nb_sym_qp;
+}
+
 static int
 rte_cryptodev_queue_pairs_config(struct rte_cryptodev *dev, uint16_t nb_qpairs,
 		int socket_id)
@@ -1088,6 +1173,38 @@  struct rte_cryptodev *
 	return 0;
 }
 
+int
+rte_cryptodev_asym_session_init(uint8_t dev_id,
+		struct rte_cryptodev_asym_session *sess,
+		struct rte_crypto_asym_xform *xforms,
+		struct rte_mempool *mp)
+{
+	struct rte_cryptodev *dev;
+	uint8_t index;
+	int ret;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+
+	if (sess == NULL || xforms == NULL || dev == NULL)
+		return -EINVAL;
+
+	index = dev->driver_id;
+
+	if (sess->sess_private_data[index] == NULL) {
+		ret = dev->dev_ops->asym_session_configure(dev,
+							   xforms,
+							   sess, mp);
+		if (ret < 0) {
+			CDEV_LOG_ERR(
+				"dev_id %d failed to configure session details",
+				dev_id);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 struct rte_cryptodev_sym_session *
 rte_cryptodev_sym_session_create(struct rte_mempool *mp)
 {
@@ -1105,6 +1222,23 @@  struct rte_cryptodev_sym_session *
 	return sess;
 }
 
+struct rte_cryptodev_asym_session *
+rte_cryptodev_asym_session_create(struct rte_mempool *mp)
+{
+	struct rte_cryptodev_asym_session *sess;
+
+	/* Allocate a session structure from the session pool */
+	if (rte_mempool_get(mp, (void *)&sess)) {
+		CDEV_LOG_ERR("couldn't get object from session mempool");
+		return NULL;
+	}
+
+	/* Clear device session pointer */
+	memset(sess, 0, (sizeof(void *) * nb_drivers));
+
+	return sess;
+}
+
 int
 rte_cryptodev_queue_pair_attach_sym_session(uint8_t dev_id, uint16_t qp_id,
 		struct rte_cryptodev_sym_session *sess)
@@ -1160,6 +1294,60 @@  struct rte_cryptodev_sym_session *
 }
 
 int
+rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,
+		struct rte_cryptodev_asym_session *sess)
+{
+	struct rte_cryptodev *dev;
+
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
+		return -EINVAL;
+	}
+
+	dev = &rte_crypto_devices[dev_id];
+
+	/* The API is optional, not returning error if driver do not suuport */
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_attach_session, 0);
+
+	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);
+
+	if (dev->dev_ops->asym_qp_attach_session(dev, qp_id, sess_priv)) {
+		CDEV_LOG_ERR("dev_id %d failed to attach qp: %d with session",
+				dev_id, qp_id);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+int
+rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,
+		struct rte_cryptodev_asym_session *sess)
+{
+	struct rte_cryptodev *dev;
+
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) {
+		CDEV_LOG_ERR("Invalid dev_id=%d", dev_id);
+		return -EINVAL;
+	}
+
+	dev = &rte_crypto_devices[dev_id];
+
+	/* The API is optional, not returning error if driver do not suuport */
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->asym_qp_detach_session, 0);
+
+	void *sess_priv = get_asym_session_private_data(sess, dev->driver_id);
+
+	if (dev->dev_ops->asym_qp_detach_session(dev, qp_id, sess_priv)) {
+		CDEV_LOG_ERR("dev_id %d failed to detach qp: %d from session",
+				dev_id, qp_id);
+		return -EPERM;
+	}
+
+	return 0;
+}
+
+int
 rte_cryptodev_sym_session_clear(uint8_t dev_id,
 		struct rte_cryptodev_sym_session *sess)
 {
@@ -1176,6 +1364,22 @@  struct rte_cryptodev_sym_session *
 }
 
 int
+rte_cryptodev_asym_session_clear(uint8_t dev_id,
+		struct rte_cryptodev_asym_session *sess)
+{
+	struct rte_cryptodev *dev;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+
+	if (dev == NULL || sess == NULL)
+		return -EINVAL;
+
+	dev->dev_ops->asym_session_clear(dev, sess);
+
+	return 0;
+}
+
+int
 rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess)
 {
 	uint8_t i;
@@ -1199,6 +1403,31 @@  struct rte_cryptodev_sym_session *
 	return 0;
 }
 
+int
+rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess)
+{
+	uint8_t i;
+	void *sess_priv;
+	struct rte_mempool *sess_mp;
+
+	if (sess == NULL)
+		return -EINVAL;
+
+	/* Check that all device private data has been freed */
+	for (i = 0; i < nb_drivers; i++) {
+		sess_priv = get_asym_session_private_data(sess, i);
+		if (sess_priv != NULL)
+			return -EBUSY;
+	}
+
+	/* Return session to mempool */
+	sess_mp = rte_mempool_from_obj(sess);
+	rte_mempool_put(sess_mp, sess);
+
+	return 0;
+}
+
+
 unsigned int
 rte_cryptodev_get_header_session_size(void)
 {
@@ -1235,6 +1464,57 @@  struct rte_cryptodev_sym_session *
 		return header_size;
 
 	return priv_sess_size;
+}
+
+unsigned int
+rte_cryptodev_get_sym_session_private_size(uint8_t dev_id)
+{
+	struct rte_cryptodev *dev;
+	unsigned int header_size = sizeof(void *) * nb_drivers;
+	unsigned int priv_sess_size;
+
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
+		return 0;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+
+	if (*dev->dev_ops->sym_session_get_size == NULL)
+		return 0;
+
+	priv_sess_size = (*dev->dev_ops->sym_session_get_size)(dev);
+
+	/*
+	 * If size is less than session header size,
+	 * return the latter, as this guarantees that
+	 * sessionless operations will work
+	 */
+	if (priv_sess_size < header_size)
+		return header_size;
+
+	return priv_sess_size;
+}
+
+
+unsigned int
+rte_cryptodev_get_asym_session_private_size(uint8_t dev_id)
+{
+	struct rte_cryptodev *dev;
+	unsigned int header_size = sizeof(void *) * nb_drivers;
+	unsigned int priv_sess_size;
+
+	if (!rte_cryptodev_pmd_is_valid_dev(dev_id))
+		return 0;
+
+	dev = rte_cryptodev_pmd_get_dev(dev_id);
+
+	if (*dev->dev_ops->asym_session_get_size == NULL)
+		return 0;
+
+	priv_sess_size = (*dev->dev_ops->asym_session_get_size)(dev);
+	if (priv_sess_size < header_size)
+		return header_size;
+
+	return priv_sess_size;
 
 }
 
@@ -1268,6 +1548,13 @@  struct rte_mempool *
 			sizeof(struct rte_crypto_sym_op) +
 			priv_size;
 
+	if (type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {
+		/* override size by size of asym op */
+		elt_size = sizeof(struct rte_crypto_op) +
+			   sizeof(struct rte_crypto_asym_op) +
+			   priv_size;
+	}
+
 	/* lookup mempool in case already allocated */
 	struct rte_mempool *mp = rte_mempool_lookup(name);
 
diff --git a/lib/librte_cryptodev/rte_cryptodev.h b/lib/librte_cryptodev/rte_cryptodev.h
index c8fa689..728483c 100644
--- a/lib/librte_cryptodev/rte_cryptodev.h
+++ b/lib/librte_cryptodev/rte_cryptodev.h
@@ -178,15 +178,41 @@  struct rte_cryptodev_symmetric_capability {
 	};
 };
 
+/**
+ * Asymmetric Crypto Capability
+ *
+ */
+struct rte_cryptodev_asymmetric_capability {
+	enum rte_crypto_asym_xform_type xform_type;
+	/**< Transform type: RSA/MODEXP/DH/ECDH/DSA/ECDSA/FECC/MODINV */
+	RTE_STD_C11
+	union {
+		struct rte_crypto_param_range modlen;
+		/**< Range of modulus length supported for modulus based
+		 * algos:
+		 * RSA
+		 * MODEXP
+		 * MODINV
+		 * DH
+		 *
+		 * Value 0 to min and/or max means no specific limit and limit
+		 * is implementation dependent
+		 *
+		 */
+	};
+};
+
 /** Structure used to capture a capability of a crypto device */
 struct rte_cryptodev_capabilities {
 	enum rte_crypto_op_type op;
-	/**< Operation type */
+	/**< Operation type: symmetric/asymmetric */
 
 	RTE_STD_C11
 	union {
 		struct rte_cryptodev_symmetric_capability sym;
 		/**< Symmetric operation capability parameters */
+		struct rte_cryptodev_asymmetric_capability asym;
+		/**< Asymmetric operation capability parameters */
 	};
 };
 
@@ -201,7 +227,17 @@  struct rte_cryptodev_sym_capability_idx {
 };
 
 /**
- *  Provide capabilities available for defined device and algorithm
+ * Structure used to describe asymmetric crypto xforms
+ * Each xform maps to one asym algorithm.
+ *
+ */
+struct rte_cryptodev_asym_capability_idx {
+	enum rte_crypto_asym_xform_type type;
+	/**< Asymmetric xform (algo) type */
+};
+
+/**
+ * Provide capabilities available for defined device and algorithm
  *
  * @param	dev_id		The identifier of the device.
  * @param	idx		Description of crypto algorithms.
@@ -215,6 +251,20 @@  struct rte_cryptodev_sym_capability_idx {
 		const struct rte_cryptodev_sym_capability_idx *idx);
 
 /**
+ *  Provide capabilities available for defined device and algorithm
+ *
+ * @param	dev_id		The identifier of the device.
+ * @param	algo		Description of crypto algorithms.
+ *
+ * @return
+ *   - Return description of the asymmetric crypto capability if exist.
+ *   - Return NULL if the capability not exist.
+ */
+const struct rte_cryptodev_asymmetric_capability *
+rte_cryptodev_asym_capability_get(uint8_t dev_id,
+		const struct rte_cryptodev_asym_capability_idx *idx);
+
+/**
  * Check if key size and initial vector are supported
  * in crypto cipher capability
  *
@@ -270,6 +320,21 @@  struct rte_cryptodev_sym_capability_idx {
 		uint16_t iv_size);
 
 /**
+ * Check if modulus length is in supported range
+ *
+ * @param	capability	Description of the asymmetric crypto capability.
+ * @param	modlen		modulus length.
+ *
+ * @return
+ *   - Return 0 if the parameters are in range of the capability.
+ *   - Return -1 if the parameters are out of range of the capability.
+ */
+int
+rte_cryptodev_asym_capability_check_modlen(
+		const struct rte_cryptodev_asymmetric_capability *capability,
+		uint16_t modlen);
+
+/**
  * Provide the cipher algorithm enum, given an algorithm string
  *
  * @param	algo_enum	A pointer to the cipher algorithm
@@ -314,6 +379,22 @@  struct rte_cryptodev_sym_capability_idx {
 rte_cryptodev_get_aead_algo_enum(enum rte_crypto_aead_algorithm *algo_enum,
 		const char *algo_string);
 
+/**
+ * Provide the Asymmetric xform enum, given an xform string
+ *
+ * @param	xform_enum	A pointer to the xform type
+ *				enum to be filled
+ * @param	xform_string	xform string
+ *
+ * @return
+ * - Return -1 if string is not valid
+ * - Return 0 is the string is valid
+ */
+int
+rte_cryptodev_get_asym_xform_enum(enum rte_crypto_asym_xform_type *xform_enum,
+		const char *xform_string);
+
+
 /** Macro used at end of crypto PMD list */
 #define RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() \
 	{ RTE_CRYPTO_OP_TYPE_UNDEFINED }
@@ -379,16 +460,99 @@  struct rte_cryptodev_info {
 	/**< Array of devices supported capabilities */
 
 	unsigned max_nb_queue_pairs;
-	/**< Maximum number of queues pairs supported by device. */
+	/**< Maximum number of queues pairs supported by device.
+	 *
+	 * This is total number of queues supported by device and inclusive
+	 * of numbers used for both symmetric and asymmetric for PMD that
+	 * support symmetric and asymmetric op i.e.
+	 *
+	 * max_nb_queue_pairs = max_nb_symm_qp + max_nb_asymm_qp
+	 *
+	 * Following table demonstarte what the values should be for device
+	 * with max num of 'n' queue pair (x = don't care):
+	 *
+	 *  -------------------------------------------------------------------
+	 * |dev_capa                | max_nb_asymm_qp| max_nb_symm_qp | max_qp|
+	 *  -------------------------------------------------------------------
+	 * | Symm only              |    x           | 0              | n     |
+	 * | Asymm only             |    0           | x              | n     |
+	 * | symm+asymm w/ fixed qp |    p           | n-p            | n     |
+	 * | symm+asymm w/ all qp   |    0           | 0              | n     |
+	 *  -------------------------------------------------------------------
+	 *
+	 * - if device supports only asymmetric, then max_nb_queue_pair
+	 *   indicates max qp available for asymmetric operations.
+	 *
+	 * - if device support only symmetric, then max_nb_queue_pair
+	 *   indicates max qp available for symmetric operations.
+	 *
+	 * - if device support both symmetric and asymmetric crypto op,
+	 *   then max_nb_queue_pair indicates total number of available
+	 *   qp for both operations.
+	 *
+	 * **Special note on devices supporting symm and asymm:
+	 *
+	 * Such dual function devices may manage qp in various possible ways.
+	 * They can either:
+	 *
+	 * 1. Use all max_nb_queue_pair for any operation type.
+	 *    In such case, app can configure any of the available qp
+	 *    for any operaiton. Thus,
+	 *    dev_info should return num queue pair distribution as mentioned
+	 *    in row 'symm+asymm w/ all qp' in table above
+	 *
+	 * 2. Or, use dedicated set of qp for each op
+	 *    Such device PMDs, can take 2 approaches:
+	 *    1. Either, it can show up as 2 separate PMDs where one as
+	 *	 symmetric only and other asymmetric only. in such case,
+	 *	 device info will return num queue pair distribution as
+	 *	 mentioned in row 'symmetric/asymmetric only' device
+	 *
+	 *    2. Or, can appear as one PMD with number of queue pair dedicated
+	 *	 to each operation in max_nb_symm_qp and max_nb_asymm_qp
+	 *
+	 */
 
 	struct {
 		unsigned max_nb_sessions;
-		/**< Maximum number of sessions supported by device. */
+		/**< Maximum number of sessions supported
+		 * for symmetric operations.
+		 */
 		unsigned int max_nb_sessions_per_qp;
-		/**< Maximum number of sessions per queue pair.
+		/**< Maximum number of symmetric sessions
+		 * per queue pair.
 		 * Default 0 for infinite sessions
 		 */
+		 unsigned int max_nb_sym_qp;
+		/**< Maximum num of qp dedicated to symmetric op.
+		 * NA for device that support symmetric only.
+		 * 0 means device can use all max_nb_queue_pair
+		 * for symm op.
+		 * Please note, this variable only tells number of queue pairs
+		 * that can be enqueued with symmetric ops and doesn't reveal
+		 * specific IDs used by PMDs for this operation
+		 *
+		 */
 	} sym;
+
+	struct {
+		unsigned int max_nb_asym_sessions;
+		/**< Maximum number of asymmetric sessions supported by device.
+		 * 0 infinite as long as resources are available
+		 */
+		unsigned int max_nb_asym_sessions_per_qp;
+		/**< Maximum number of asymmetric sessions per queue pair.
+		 * 0 means infinite as long as resources are available
+		 */
+		unsigned int max_nb_asym_qp;
+		/**< Maximum number of qp dedicated for asymm operation.
+		 * 0 means device can use all max_nb_queue_pair for asymm op.
+		 * Please note, this variable only tells number of queue pairs
+		 * that can be enqueued with asymmetric ops and doesn't reveal
+		 * specific IDs used by PMDs for this operation
+		 *
+		 */
+	} asym;
 };
 
 #define RTE_CRYPTODEV_DETACHED  (0)
@@ -513,6 +677,24 @@  struct rte_cryptodev_config {
 	int socket_id;			/**< Socket to allocate resources on */
 	uint16_t nb_queue_pairs;
 	/**< Number of queue pairs to configure on device */
+
+	uint16_t nb_symm_qp;
+	/**< Number of queue pair to be used for symmetric operations.
+	 * Optional input.
+	 * Valid for device supporting both symmetric and asymmetric.
+	 * Should be less than equal to rte_cryptodev_info:max_nb_symm_qp.
+	 * please note this number only tells how many queue pair to be used
+	 * for symmetric op and does *not* tell specific IDs to be used.
+	 */
+
+	uint16_t nb_asymm_qp;
+	/**< Number of queue pair to be used for asymmetric operations.
+	 * Optional input.
+	 * Valid for device supporting both asymmetric and symmetric.
+	 * Should be less than equal to rte_cryptodev_info:max_nb_asymm_qp
+	 * Please note this number only tells how many queue pair to be
+	 * used for asymmetric and does *not* specifically tell qp ID
+	 */
 };
 
 /**
@@ -595,6 +777,9 @@  struct rte_cryptodev_config {
  * @return
  *   - 0: Success, queue pair correctly set up.
  *   - <0: Queue pair configuration failed
+ *
+ * @note: queue pair to be setup independent of operation type.
+ *
  */
 extern int
 rte_cryptodev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id,
@@ -644,6 +829,26 @@  struct rte_cryptodev_config {
 extern uint16_t
 rte_cryptodev_queue_pair_count(uint8_t dev_id);
 
+/**
+ * Get the number of symmetric queue pairs on this crypto device
+ *
+ * @param	dev_id		Crypto device identifier.
+ * @return
+ *   - The number of configured symmetric queue pairs.
+ */
+extern uint16_t
+rte_cryptodev_sym_queue_pair_count(uint8_t dev_id);
+
+
+/**
+ * Get the number of asymmetric queue pairs on this crypto device
+ *
+ * @param	dev_id		Crypto device identifier.
+ * @return
+ *   - The number of configured asymmetric queue pairs.
+ */
+extern uint16_t
+rte_cryptodev_asym_queue_pair_count(uint8_t dev_id);
 
 /**
  * Retrieve the general I/O statistics of a device.
@@ -795,6 +1000,10 @@  struct rte_cryptodev_data {
 	/**< Array of pointers to queue pairs. */
 	uint16_t nb_queue_pairs;
 	/**< Number of device queue pairs. */
+	uint16_t nb_sym_qp;
+	/**< Number of symmetric queue pairs. */
+	uint16_t nb_asym_qp;
+	/**< Number of asymmetric queue pairs. */
 
 	void *dev_private;
 	/**< PMD-specific private data */
@@ -900,6 +1109,11 @@  struct rte_cryptodev_sym_session {
 	/**< Private session material */
 };
 
+/** Cryptodev asymmetric crypto session */
+struct rte_cryptodev_asym_session {
+	__extension__ void *sess_private_data[0];
+	/**< Private asymmetric session material */
+};
 
 /**
  * Create symmetric crypto session header (generic with no private data)
@@ -914,6 +1128,18 @@  struct rte_cryptodev_sym_session *
 rte_cryptodev_sym_session_create(struct rte_mempool *mempool);
 
 /**
+ * Create asymmetric crypto session header (generic with no private data)
+ *
+ * @param   mempool    mempool to allocate asymmetric session
+ *                     objects from
+ * @return
+ *  - On success return pointer to asym-session
+ *  - On failure returns NULL
+ */
+struct rte_cryptodev_asym_session *
+rte_cryptodev_asym_session_create(struct rte_mempool *mempool);
+
+/**
  * Frees symmetric crypto session header, after checking that all
  * the device private data has been freed, returning it
  * to its original mempool.
@@ -929,6 +1155,21 @@  struct rte_cryptodev_sym_session *
 rte_cryptodev_sym_session_free(struct rte_cryptodev_sym_session *sess);
 
 /**
+ * Frees asymmetric crypto session header, after checking that all
+ * the device private data has been freed, returning it
+ * to its original mempool.
+ *
+ * @param   sess     Session header to be freed.
+ *
+ * @return
+ *  - 0 if successful.
+ *  - -EINVAL if session is NULL.
+ *  - -EBUSY if not all device private data has been freed.
+ */
+int
+rte_cryptodev_asym_session_free(struct rte_cryptodev_asym_session *sess);
+
+/**
  * Fill out private data for the device id, based on its device type.
  *
  * @param   dev_id   ID of device that we want the session to be used on
@@ -950,6 +1191,27 @@  struct rte_cryptodev_sym_session *
 			struct rte_mempool *mempool);
 
 /**
+ * Initialize asymmetric session on a device with specific asymmetric xform
+ *
+ * @param   dev_id   ID of device that we want the session to be used on
+ * @param   sess     Session to be set up on a device
+ * @param   xforms   Asymmetric crypto transform operations to apply on flow
+ *                   processed with this session
+ * @param   mempool  Mempool to be used for internal allocation.
+ *
+ * @return
+ *  - On success, zero.
+ *  - -EINVAL if input parameters are invalid.
+ *  - -ENOTSUP if crypto device does not support the crypto transform.
+ *  - -ENOMEM if the private session could not be allocated.
+ */
+int
+rte_cryptodev_asym_session_init(uint8_t dev_id,
+			struct rte_cryptodev_asym_session *sess,
+			struct rte_crypto_asym_xform *xforms,
+			struct rte_mempool *mempool);
+
+/**
  * Frees private data for the device id, based on its device type,
  * returning it to its mempool.
  *
@@ -965,7 +1227,23 @@  struct rte_cryptodev_sym_session *
 			struct rte_cryptodev_sym_session *sess);
 
 /**
+ * Frees resources held by asymmetric session during rte_cryptodev_session_init
+ *
+ * @param   dev_id   ID of device that uses the asymmetric session.
+ * @param   sess     Asymmetric session setup on device using
+ *					 rte_cryptodev_session_init
+ * @return
+ *  - 0 if successful.
+ *  - -EINVAL if device is invalid or session is NULL.
+ */
+int
+rte_cryptodev_asym_session_clear(uint8_t dev_id,
+			struct rte_cryptodev_asym_session *sess);
+
+/**
  * Get the size of the header session, for all registered drivers.
+ * For devices supporting both symmetric and asymmetric, it should
+ * return header size inclusive of both
  *
  * @return
  *   Size of the header session.
@@ -975,6 +1253,8 @@  struct rte_cryptodev_sym_session *
 
 /**
  * Get the size of the private session data for a device.
+ * if device support both symmetric and asymmetric, it
+ * return size inclusive of both
  *
  * @param	dev_id		The device identifier.
  *
@@ -986,6 +1266,32 @@  struct rte_cryptodev_sym_session *
 rte_cryptodev_get_private_session_size(uint8_t dev_id);
 
 /**
+ * Get the size of the private data for symmetric session
+ * on device
+ *
+ * @param	dev_id		The device identifier.
+ *
+ * @return
+ *   - Size of the symmetric session private data, if successful
+ *   - 0 if device is invalid or does not have private session
+ */
+unsigned int
+rte_cryptodev_get_sym_session_private_size(uint8_t dev_id);
+
+/**
+ * Get the size of the private data for asymmetric session
+ * on device
+ *
+ * @param	dev_id		The device identifier.
+ *
+ * @return
+ *   - Size of the asymmetric private data, if successful
+ *   - 0 if device is invalid or does not have private session
+ */
+unsigned int
+rte_cryptodev_get_asym_session_private_size(uint8_t dev_id);
+
+/**
  * Attach queue pair with sym session.
  *
  * @param	dev_id		Device to which the session will be attached.
@@ -1002,6 +1308,31 @@  struct rte_cryptodev_sym_session *
 		struct rte_cryptodev_sym_session *session);
 
 /**
+ * Attach queue pair with asym session.
+ *
+ * @param	dev_id		Device to which the session is attached.
+ * @param	qp_id		Queue pair to which the session will be
+ *				attached.
+ * @param	session		Asymmetric Session pointer previously
+ *				allocated by
+ *				*rte_cryptodev_asym_session_create*.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ *
+ * @note : app can dedicate a qp_id to specific operation type:symm/asymm
+ * by calling rte_cryptodev_queue_pair_attach_sym/asym_session() before
+ * enqueue_burst() call. PMD with SYMMETRIC & ASYMMETRIC feature flag set,
+ * can internally bind the logical qp_id to actual physical qp_id here and
+ * dedicate specific qp_id to perform specific op_type(symmetric or
+ * asymmetric).
+ */
+int
+rte_cryptodev_queue_pair_attach_asym_session(uint8_t dev_id, uint16_t qp_id,
+		struct rte_cryptodev_asym_session *session);
+
+/**
  * Detach queue pair with sym session.
  *
  * @param	dev_id		Device to which the session is attached.
@@ -1018,6 +1349,23 @@  struct rte_cryptodev_sym_session *
 		struct rte_cryptodev_sym_session *session);
 
 /**
+ * Detach queue pair from asym session.
+ *
+ * @param	dev_id		Device to which the session is attached.
+ * @param	qp_id		Queue pair to which the session is attached.
+ * @param	session		Asymmetric Session pointer previously attached
+ *				by calling
+ *				*rte_cryptodev_queue_pair_attach_asym_session*.
+ *
+ * @return
+ *  - On success, zero.
+ *  - On failure, a negative value.
+ */
+int
+rte_cryptodev_queue_pair_detach_asym_session(uint8_t dev_id, uint16_t qp_id,
+		struct rte_cryptodev_asym_session *session);
+
+/**
  * Provide driver identifier.
  *
  * @param name
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.c b/lib/librte_cryptodev/rte_cryptodev_pmd.c
index f2aac24..4439a8e 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.c
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.c
@@ -66,6 +66,20 @@ 
 			goto free_kvlist;
 
 		ret = rte_kvargs_process(kvlist,
+				RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,
+				&rte_cryptodev_pmd_parse_uint_arg,
+				&params->max_nb_asym_qp);
+		if (ret < 0)
+			goto free_kvlist;
+
+		ret = rte_kvargs_process(kvlist,
+				RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG,
+				&rte_cryptodev_pmd_parse_uint_arg,
+				&params->max_nb_sym_qp);
+		if (ret < 0)
+			goto free_kvlist;
+
+		ret = rte_kvargs_process(kvlist,
 				RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,
 				&rte_cryptodev_pmd_parse_uint_arg,
 				&params->max_nb_sessions);
@@ -109,9 +123,12 @@  struct rte_cryptodev *
 			device->driver->name, name);
 
 	CDEV_LOG_INFO("[%s] - Initialisation parameters - name: %s,"
-			"socket id: %d, max queue pairs: %u, max sessions: %u",
+			"socket id: %d, max queue pairs: %u, "
+			"max sym queue paid: %u, max asym queue pair %u, "
+			"max sessions: %u",
 			device->driver->name, name,
 			params->socket_id, params->max_nb_queue_pairs,
+			params->max_nb_asym_qp, params->max_nb_sym_qp,
 			params->max_nb_sessions);
 
 	/* allocate device structure */
diff --git a/lib/librte_cryptodev/rte_cryptodev_pmd.h b/lib/librte_cryptodev/rte_cryptodev_pmd.h
index 089848e..272b489 100644
--- a/lib/librte_cryptodev/rte_cryptodev_pmd.h
+++ b/lib/librte_cryptodev/rte_cryptodev_pmd.h
@@ -60,18 +60,25 @@ 
 
 #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS	8
 #define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SESSIONS	2048
+/* Allow all qp to be used for sym */
+#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_SYM_QP		0
+/* Allow all qp to be used for asym */
+#define RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_ASYM_QP	0
 
 #define RTE_CRYPTODEV_PMD_NAME_ARG			("name")
 #define RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG			("max_nb_queue_pairs")
 #define RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG		("max_nb_sessions")
 #define RTE_CRYPTODEV_PMD_SOCKET_ID_ARG			("socket_id")
-
+#define RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG		("max_nb_asym_qp")
+#define RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG		("max_nb_sym_qp")
 
 static const char * const cryptodev_pmd_valid_params[] = {
 	RTE_CRYPTODEV_PMD_NAME_ARG,
 	RTE_CRYPTODEV_PMD_MAX_NB_QP_ARG,
 	RTE_CRYPTODEV_PMD_MAX_NB_SESS_ARG,
-	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG
+	RTE_CRYPTODEV_PMD_SOCKET_ID_ARG,
+	RTE_CRYPTODEV_PMD_MAX_NB_ASYM_QP_ARG,
+	RTE_CRYPTODEV_PMD_MAX_NB_SYM_QP_ARG
 };
 
 /**
@@ -84,6 +91,10 @@  struct rte_cryptodev_pmd_init_params {
 	int socket_id;
 	unsigned int max_nb_queue_pairs;
 	unsigned int max_nb_sessions;
+	unsigned int max_nb_asym_qp;
+	/**< maximum number of qp to be used for asymmetric ops */
+	unsigned int max_nb_sym_qp;
+	/**< maximum number of qp to be used for symmetric ops */
 };
 
 /** Global structure used for maintaining state of allocated crypto devices */
@@ -275,7 +286,29 @@  typedef int (*cryptodev_queue_pair_release_t)(struct rte_cryptodev *dev,
 typedef uint32_t (*cryptodev_queue_pair_count_t)(struct rte_cryptodev *dev);
 
 /**
- * Create a session mempool to allocate sessions from
+ * Get number of available symmetric queue pairs of a device.
+ *
+ * @param	dev	Crypto device pointer
+ *
+ * @return
+ * - Returns number of symmetric queue pairs
+ */
+typedef uint32_t (*cryptodev_sym_queue_pair_count_t)(
+			struct rte_cryptodev *dev);
+
+/**
+ * Get number of available asymmetric queue pairs of a device.
+ *
+ * @param	dev	Crypto device pointer
+ *
+ * @return
+ * - Returns number of symmetric queue pairs
+ */
+typedef uint32_t (*cryptodev_asym_queue_pair_count_t)(
+			struct rte_cryptodev *dev);
+
+/**
+ * Create a symmetric session mempool to allocate sessions from
  *
  * @param	dev		Crypto device pointer
  * @param	nb_objs		number of sessions objects in mempool
@@ -290,6 +323,21 @@  typedef int (*cryptodev_sym_create_session_pool_t)(
 		struct rte_cryptodev *dev, unsigned nb_objs,
 		unsigned obj_cache_size, int socket_id);
 
+/**
+ * Create a asymmetric session mempool to allocate sessions from
+ *
+ * @param	dev		Crypto device pointer
+ * @param	nb_objs		Number of asymmetric sessions objects in mempool
+ * @param	obj_cache	l-core object cache size, see *rte_ring_create*
+ * @param	socket_id	Socket Id to allocate  mempool on.
+ *
+ * @return
+ * - On success returns a pointer to a rte_mempool
+ * - On failure returns a NULL pointer
+ */
+typedef int (*cryptodev_asym_create_session_pool_t)(
+		struct rte_cryptodev *dev, unsigned nb_objs,
+		unsigned obj_cache_size, int socket_id);
 
 /**
  * Get the size of a cryptodev session
@@ -302,6 +350,17 @@  typedef int (*cryptodev_sym_create_session_pool_t)(
  */
 typedef unsigned (*cryptodev_sym_get_session_private_size_t)(
 		struct rte_cryptodev *dev);
+/**
+ * Get the size of a asymmetric cryptodev session
+ *
+ * @param	dev		Crypto device pointer
+ *
+ * @return
+ *  - On success returns the size of the session structure for device
+ *  - On failure returns 0
+ */
+typedef unsigned (*cryptodev_asym_get_session_private_size_t)(
+		struct rte_cryptodev *dev);
 
 /**
  * Configure a Crypto session on a device.
@@ -321,7 +380,24 @@  typedef int (*cryptodev_sym_configure_session_t)(struct rte_cryptodev *dev,
 		struct rte_crypto_sym_xform *xform,
 		struct rte_cryptodev_sym_session *session,
 		struct rte_mempool *mp);
-
+/**
+ * Configure a Crypto asymmetric session on a device.
+ *
+ * @param	dev		Crypto device pointer
+ * @param	xform		Single or chain of crypto xforms
+ * @param	priv_sess	Pointer to cryptodev's private session structure
+ * @param	mp		Mempool where the private session is allocated
+ *
+ * @return
+ *  - Returns 0 if private session structure have been created successfully.
+ *  - Returns -EINVAL if input parameters are invalid.
+ *  - Returns -ENOTSUP if crypto device does not support the crypto transform.
+ *  - Returns -ENOMEM if the private session could not be allocated.
+ */
+typedef int (*cryptodev_asym_configure_session_t)(struct rte_cryptodev *dev,
+		struct rte_crypto_asym_xform *xform,
+		struct rte_cryptodev_asym_session *session,
+		struct rte_mempool *mp);
 /**
  * Free driver private session data.
  *
@@ -332,6 +408,15 @@  typedef void (*cryptodev_sym_free_session_t)(struct rte_cryptodev *dev,
 		struct rte_cryptodev_sym_session *sess);
 
 /**
+ * Free asymmetric session private data.
+ *
+ * @param	dev		Crypto device pointer
+ * @param	sess		Cryptodev session structure
+ */
+typedef void (*cryptodev_asym_free_session_t)(struct rte_cryptodev *dev,
+		struct rte_cryptodev_asym_session *sess);
+
+/**
  * Optional API for drivers to attach sessions with queue pair.
  * @param	dev		Crypto device pointer
  * @param	qp_id		queue pair id for attaching session
@@ -343,6 +428,18 @@  typedef int (*cryptodev_sym_queue_pair_attach_session_t)(
 		  struct rte_cryptodev *dev,
 		  uint16_t qp_id,
 		  void *session_private);
+/**
+ * Optional API for drivers to attach asymmetric session with queue pair.
+ * @param	dev		Crypto device pointer
+ * @param	qp_id		Queue pair id for attaching session
+ * @param	priv_sess       Pointer to cryptodev's private session structure
+ * @return
+ *  - Return 0 on success
+ */
+typedef int (*cryptodev_asym_queue_pair_attach_session_t)(
+		  struct rte_cryptodev *dev,
+		  uint16_t qp_id,
+		  void *session_private);
 
 /**
  * Optional API for drivers to detach sessions from queue pair.
@@ -357,6 +454,19 @@  typedef int (*cryptodev_sym_queue_pair_detach_session_t)(
 		  uint16_t qp_id,
 		  void *session_private);
 
+/**
+ * Optional API for drivers to detach asymmetric session from queue pair.
+ * @param	dev		Crypto device pointer
+ * @param	qp_id		queue pair id for detaching session
+ * @param	priv_sess       Pointer to cryptodev's private session structure
+ * @return
+ *  - Return 0 on success
+ */
+typedef int (*cryptodev_asym_queue_pair_detach_session_t)(
+		  struct rte_cryptodev *dev,
+		  uint16_t qp_id,
+		  void *session_private);
+
 /** Crypto device operations function pointer table */
 struct rte_cryptodev_ops {
 	cryptodev_configure_t dev_configure;	/**< Configure device. */
@@ -380,17 +490,32 @@  struct rte_cryptodev_ops {
 	cryptodev_queue_pair_stop_t queue_pair_stop;
 	/**< Stop a queue pair. */
 	cryptodev_queue_pair_count_t queue_pair_count;
-	/**< Get count of the queue pairs. */
-
+	/**< Get total count of the queue pairs(symmetric+asymmetric). */
+	cryptodev_sym_queue_pair_count_t sym_queue_pair_count;
+	/**< Get count of the symmetric queue pairs. */
+	cryptodev_asym_queue_pair_count_t asym_queue_pair_count;
+	/**< Get count of the asymmetric queue pairs. */
 	cryptodev_sym_get_session_private_size_t session_get_size;
-	/**< Return private session. */
+	/**< Return private size for a session */
+	cryptodev_sym_get_session_private_size_t sym_session_get_size;
+	/**< Return private size for symmetric crypto. */
+	cryptodev_sym_get_session_private_size_t asym_session_get_size;
+	/**< Return private size for asymmetric crypto. */
 	cryptodev_sym_configure_session_t session_configure;
 	/**< Configure a Crypto session. */
+	cryptodev_asym_configure_session_t asym_session_configure;
+	/**< Configure asymmetric Crypto session. */
 	cryptodev_sym_free_session_t session_clear;
 	/**< Clear a Crypto sessions private data. */
+	cryptodev_asym_free_session_t asym_session_clear;
+	/**< Clear a Crypto sessions private data. */
 	cryptodev_sym_queue_pair_attach_session_t qp_attach_session;
 	/**< Attach session to queue pair. */
-	cryptodev_sym_queue_pair_detach_session_t qp_detach_session;
+	cryptodev_asym_queue_pair_attach_session_t asym_qp_attach_session;
+	/**< Attach asymmetric session to queue pair. */
+	cryptodev_sym_queue_pair_attach_session_t qp_detach_session;
+	/**< Detach session from queue pair. */
+	cryptodev_asym_queue_pair_attach_session_t asym_qp_detach_session;
 	/**< Detach session from queue pair. */
 };
 
@@ -535,6 +660,19 @@  uint8_t rte_cryptodev_allocate_driver(struct cryptodev_driver *crypto_drv,
 	sess->sess_private_data[driver_id] = private_data;
 }
 
+static inline void *
+get_asym_session_private_data(const struct rte_cryptodev_asym_session *sess,
+		uint8_t driver_id) {
+	return sess->sess_private_data[driver_id];
+}
+
+static inline void
+set_asym_session_private_data(struct rte_cryptodev_asym_session *sess,
+		uint8_t driver_id, void *private_data)
+{
+	sess->sess_private_data[driver_id] = private_data;
+}
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/librte_cryptodev/rte_cryptodev_version.map b/lib/librte_cryptodev/rte_cryptodev_version.map
index eb47308..323294a 100644
--- a/lib/librte_cryptodev/rte_cryptodev_version.map
+++ b/lib/librte_cryptodev/rte_cryptodev_version.map
@@ -85,3 +85,24 @@  DPDK_17.11 {
 	rte_cryptodev_pmd_parse_input_args;
 
 } DPDK_17.08;
+
+EXPERIMENTAL {
+	global:
+
+	rte_cryptodev_asym_capability_get;
+	rte_cryptodev_asym_capability_modlen;
+	rte_cryptodev_asym_queue_pair_count;
+	rte_cryptodev_asym_session_create;
+	rte_cryptodev_asym_session_clear;
+	rte_cryptodev_asym_session_free;
+	rte_cryptodev_asym_session_init;
+	rte_cryptodev_get_asym_session_private_size;
+	rte_cryptodev_get_sym_session_private_size;
+	rte_cryptodev_get_xform_algo_enum;
+	rte_cryptodev_queue_pair_attach_asym_session;
+	rte_cryptodev_queue_pair_detach_asym_session;
+	rte_cryptodev_sym_queue_pair_count;
+	rte_crypto_asym_xform_strings;
+	rte_crypto_asym_operation_strings;
+
+};