From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by dpdk.org (Postfix) with ESMTP id B742A9147 for ; Tue, 15 Aug 2017 13:04:41 +0200 (CEST) Received: from orsmga004.jf.intel.com ([10.7.209.38]) by fmsmga105.fm.intel.com with ESMTP; 15 Aug 2017 04:04:40 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.41,377,1498546800"; d="scan'208";a="119085554" Received: from rnicolau-mobl.ger.corp.intel.com (HELO [10.237.221.79]) ([10.237.221.79]) by orsmga004.jf.intel.com with ESMTP; 15 Aug 2017 04:04:38 -0700 To: Akhil Goyal , dev@dpdk.org, declan.doherty@intel.com, thomas@monjalon.net, aviadye@mellanox.com, borisp@mellanox.com, pablo.de.lara.guarch@intel.com, sergio.gonzalez.monroy@intel.com Cc: hemant.agrawal@nxp.com, sandeep.malik@nxp.com References: <20170725112153.29699-1-akhil.goyal@nxp.com> <20170815063505.22032-1-akhil.goyal@nxp.com> <20170815063505.22032-2-akhil.goyal@nxp.com> From: Radu Nicolau Message-ID: <152bc1a3-b959-adf7-99d7-4ee552e72271@intel.com> Date: Tue, 15 Aug 2017 12:04:37 +0100 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Thunderbird/52.1.0 MIME-Version: 1.0 In-Reply-To: <20170815063505.22032-2-akhil.goyal@nxp.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-US Subject: Re: [dpdk-dev] [RFC PATCH 1/4] rte_security: API definitions X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Aug 2017 11:04:42 -0000 On 8/15/2017 7:35 AM, Akhil Goyal wrote: > Detailed description is added in the coverletter > > Signed-off-by: Akhil Goyal > --- > lib/librte_cryptodev/rte_security.c | 171 +++++++++++++++ > lib/librte_cryptodev/rte_security.h | 409 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 580 insertions(+) > create mode 100644 lib/librte_cryptodev/rte_security.c > create mode 100644 lib/librte_cryptodev/rte_security.h > > diff --git a/lib/librte_cryptodev/rte_security.c b/lib/librte_cryptodev/rte_security.c > new file mode 100644 > index 0000000..7c73c93 > --- /dev/null > +++ b/lib/librte_cryptodev/rte_security.c > @@ -0,0 +1,171 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright 2017 NXP. > + * > + * 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 NXP 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. > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "rte_crypto.h" > +#include "rte_cryptodev_pmd.h" > +#include "rte_security.h" > +#include "rte_ethdev.h" > +#include "rte_cryptodev.h" > + > + > +struct rte_security_session * > +rte_security_session_create(struct rte_mempool *mp) > +{ > + struct rte_security_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 *) * > + RTE_MAX(rte_eth_dev_count(), rte_cryptodev_count()))); > + > + return sess; > +} > + > +int > +rte_security_session_init(uint16_t dev_id, > + struct rte_security_session *sess, > + struct rte_security_sess_conf *conf, > + struct rte_mempool *mp) > +{ > + struct rte_cryptodev *cdev = NULL; > + struct rte_eth_dev *dev = NULL; > + uint8_t index; > + int ret; > + > + if (sess == NULL || conf == NULL) > + return -EINVAL; > + > + switch (conf->action_type) { > + case RTE_SECURITY_SESS_CRYPTO_PROTO_OFFLOAD: > + if (!rte_cryptodev_pmd_is_valid_dev(dev_id)) > + return -EINVAL; > + cdev = rte_cryptodev_pmd_get_dev(dev_id); > + index = cdev->driver_id; > + if (sess->sess_private_data[index] == NULL) { > + ret = cdev->sec_ops->session_configure(cdev, conf, sess, mp); > + if (ret < 0) { > + CDEV_LOG_ERR( > + "cdev_id %d failed to configure session details", > + dev_id); > + return ret; > + } > + } > + break; > + case RTE_SECURITY_SESS_ETH_INLINE_CRYPTO: > + case RTE_SECURITY_SESS_ETH_PROTO_OFFLOAD: > + dev = &rte_eth_devices[dev_id]; > + index = dev->data->port_id; > + if (sess->sess_private_data[index] == NULL) { > +// ret = dev->sec_ops->session_configure(dev, conf, sess, mp); > +// if (ret < 0) { > +// CDEV_LOG_ERR( > +// "dev_id %d failed to configure session details", > +// dev_id); > +// return ret; > +// } The commented lines above suggests that also eth devices will have a sec_ops field, (which makes sense). Is this correct? Also, if the above is correct, session_configure and session_clear should accept both crypto and eth devices as first parameter. > + } > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > + > +int > +rte_security_session_free(struct rte_security_session *sess) > +{ > + uint8_t i, nb_drivers = RTE_MAX(rte_eth_dev_count(), > + rte_cryptodev_count()); > + 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_sec_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; > +} > + > +int > +rte_security_session_clear(uint8_t dev_id, > + enum rte_security_session_action_type action_type, > + struct rte_security_session *sess) > +{ > + struct rte_cryptodev *cdev = NULL; > + struct rte_eth_dev *dev = NULL; > + switch (action_type) { > + case RTE_SECURITY_SESS_CRYPTO_PROTO_OFFLOAD: > + cdev = rte_cryptodev_pmd_get_dev(dev_id); > + if (cdev == NULL || sess == NULL) > + return -EINVAL; > + cdev->sec_ops->session_clear(cdev, sess); > + break; > + case RTE_SECURITY_SESS_ETH_INLINE_CRYPTO: > + case RTE_SECURITY_SESS_ETH_PROTO_OFFLOAD: > + dev = &rte_eth_devices[dev_id]; > + if (dev == NULL || sess == NULL) > + return -EINVAL; > +// dev->dev_ops->session_clear(dev, sess); > + break; > + default: > + return -EINVAL; > + } > + > + return 0; > +} > diff --git a/lib/librte_cryptodev/rte_security.h b/lib/librte_cryptodev/rte_security.h > new file mode 100644 > index 0000000..9747d5e > --- /dev/null > +++ b/lib/librte_cryptodev/rte_security.h > @@ -0,0 +1,409 @@ > +#ifndef _RTE_SECURITY_H_ > +#define _RTE_SECURITY_H_ > + > +/** > + * @file rte_security.h > + * > + * RTE Security Common Definitions > + * > + */ > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +#include > +#include > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +/** IPSec protocol mode */ > +enum rte_security_conf_ipsec_sa_mode { > + RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT, > + /**< IPSec Transport mode */ > + RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, > + /**< IPSec Tunnel mode */ > +}; > + > +/** IPSec Protocol */ > +enum rte_security_conf_ipsec_sa_protocol { > + RTE_SECURITY_IPSEC_SA_PROTO_AH, > + /**< AH protocol */ > + RTE_SECURITY_IPSEC_SA_PROTO_ESP, > + /**< ESP protocol */ > +}; > + > +/** IPSEC tunnel type */ > +enum rte_security_ipsec_tunnel_type { > + RTE_SECURITY_IPSEC_TUNNEL_IPV4 = 0, > + /**< Outer header is IPv4 */ > + RTE_SECURITY_IPSEC_TUNNEL_IPV6, > + /**< Outer header is IPv6 */ > +}; > + > +/** > + * IPSEC tunnel parameters > + * > + * These parameters are used to build outbound tunnel headers. > + */ > +struct rte_security_ipsec_tunnel_param { > + enum rte_security_ipsec_tunnel_type type; > + /**< Tunnel type: IPv4 or IPv6 */ > + > + union { > + struct { > + struct in_addr src_ip; > + /**< IPv4 source address */ > + struct in_addr dst_ip; > + /**< IPv4 destination address */ > + uint8_t dscp; > + /**< IPv4 Differentiated Services Code Point */ > + uint8_t df; > + /**< IPv4 Don't Fragment bit */ > + uint8_t ttl; > + /**< IPv4 Time To Live */ > + } ipv4; /**< IPv4 header parameters */ > + > + struct { > + struct in6_addr *src_addr; > + /**< IPv6 source address */ > + struct in6_addr *dst_addr; > + /**< IPv6 destination address */ > + uint8_t dscp; > + /**< IPv6 Differentiated Services Code Point */ > + uint32_t flabel; > + /**< IPv6 flow label */ > + uint8_t hlimit; > + /**< IPv6 hop limit */ > + } ipv6; /**< IPv6 header parameters */ > + }; /**< Various tunnel parameters */ > +}; > + > +/** > + * IPSEC SA option flags > + */ > +struct rte_security_ipsec_sa_options { > + /** Extended Sequence Numbers (ESN) > + * > + * * 1: Use extended (64 bit) sequence numbers > + * * 0: Use normal sequence numbers > + */ > + uint32_t esn : 1; > + > + /** UDP encapsulation > + * > + * * 1: Do UDP encapsulation/decapsulation so that IPSEC packets can > + * traverse through NAT boxes. > + * * 0: No UDP encapsulation > + */ > + uint32_t udp_encap : 1; > + > + /** Copy DSCP bits > + * > + * * 1: Copy IPv4 or IPv6 DSCP bits from inner IP header to > + * the outer IP header in encapsulation, and vice versa in > + * decapsulation. > + * * 0: Use values from odp_ipsec_tunnel_param_t in encapsulation and > + * do not change DSCP field in decapsulation. > + */ > + uint32_t copy_dscp : 1; > + > + /** Copy IPv6 Flow Label > + * > + * * 1: Copy IPv6 flow label from inner IPv6 header to the > + * outer IPv6 header. > + * * 0: Use value from odp_ipsec_tunnel_param_t > + */ > + uint32_t copy_flabel : 1; > + > + /** Copy IPv4 Don't Fragment bit > + * > + * * 1: Copy the DF bit from the inner IPv4 header to the outer > + * IPv4 header. > + * * 0: Use value from odp_ipsec_tunnel_param_t > + */ > + uint32_t copy_df : 1; > + > + /** Decrement inner packet Time To Live (TTL) field > + * > + * * 1: In tunnel mode, decrement inner packet IPv4 TTL or > + * IPv6 Hop Limit after tunnel decapsulation, or before tunnel > + * encapsulation. > + * * 0: Inner packet is not modified. > + */ > + uint32_t dec_ttl : 1; > + > +}; > + > +/** IPSec Operations */ > +enum rte_security_ipsec_operation { > + RTE_SECURITY_IPSEC_OP_ENCAP, > + /**< Encrypt and generate digest */ > + RTE_SECURITY_IPSEC_OP_DECAP, > + /**< Verify digest and decrypt */ > +}; > + > +/** > + * IPSec Setup Data. > + * > + * This structure contains data relating to IPSec > + * used to create a session. > + */ > +struct rte_security_ipsec_xform { > + enum rte_security_ipsec_operation op; > + /**< IPSec operation - Encap or Decap */ > + unsigned int spi; > + /**< SA security parameter index */ > + enum rte_crypto_cipher_algorithm cipher_alg; > + /**< Cipher Algorithm */ > + struct { > + uint8_t *data; /**< pointer to key data */ > + size_t length; /**< key length in bytes */ > + } cipher_key; > + enum rte_crypto_auth_algorithm auth_alg; > + /**< Authentication Algorithm */ > + struct { > + uint8_t *data; /**< pointer to key data */ > + size_t length; /**< key length in bytes */ > + } auth_key; > + uint32_t salt; /**< salt for this SA */ > + enum rte_security_conf_ipsec_sa_mode mode; > + /**< IPsec SA Mode - transport/tunnel */ > + enum rte_security_conf_ipsec_sa_protocol proto; > + /**< IPsec SA Protocol - AH/ESP */ > + struct rte_security_ipsec_tunnel_param tunnel; > + /**< Tunnel parameters, NULL for transport mode */ > + struct rte_security_ipsec_sa_options options; > + /**< various SA options */ > +}; > + > +/** IPsec Security Session Configuration */ > +struct rte_security_dtls_xform { > + /** To be Filled */ > +}; > + > +/** IPsec Security Session Configuration */ > +struct rte_security_macsec_xform { > + /** To be Filled */ > +}; > + > +/**< Security Session action type */ > +enum rte_security_session_action_type { > + RTE_SECURITY_SESS_NONE, > + /**< Non protocol offload. Application need to manage everything */ > + RTE_SECURITY_SESS_ETH_INLINE_CRYPTO, > + /**< Crypto operations are performed by Network interface */ > + RTE_SECURITY_SESS_ETH_PROTO_OFFLOAD, > + /**< Crypto operations with protocol support are performed > + * by Network/ethernet device. > + */ > + RTE_SECURITY_SESS_CRYPTO_PROTO_OFFLOAD, > + /**< Crypto operations with protocol support are performed > + * by Crypto device. > + */ > +}; > + > +/** Security Session Protocols */ > +enum rte_security_sess_protocol { > + RTE_SEC_CONF_DTLS, > + /**< DTLS Protocol */ > + RTE_SEC_CONF_IPSEC, > + /**< IPSec Protocol */ > + RTE_SEC_CONF_MACSEC, > + /**< MACSec Protocol */ > +}; > + > +/** > + * Security Session Configuration > + */ > +struct rte_security_sess_conf { > + enum rte_security_session_action_type action_type; > + /**< Type of action to be performed on the session */ > + enum rte_security_sess_protocol protocol; > + /**< Security protocol to be configured */ > + > + union { > + struct rte_security_ipsec_xform *ipsec_xform; > + struct rte_security_dtls_xform *dtls_xform; > + struct rte_security_macsec_xform *macsec_xform; > + }; > + /**< Configuration parameters for security session */ > +}; > + > +struct rte_security_session { > + __extension__ void *sess_private_data[0]; > + /**< Private session material */ > +}; > + > +/** > + * Create Security session header (generic with no private data) > + * > + * @param mempool Session mempool to allocate session objects from > + * @return > + * - On success, pointer to session > + * - On failure, NULL > + */ > +struct rte_security_session * > +rte_security_session_create(struct rte_mempool *mempool); > + > +/** > + * Fill out private data for the device, based on its device id and name. > + * > + * @param dev_id Device id that we want the session to be used on > + * @param dev_name Device name for which session is to be used > + * @param sess Session where the private data will be attached to > + * @param conf Security config to apply on flow > + * processed with this session > + * @param mempool Mempool where the private data is allocated. > + * > + * @return > + * - On success, zero. > + * - On failure, a negative value. > + */ > +int > +rte_security_session_init(uint16_t dev_id, > + struct rte_security_session *sess, > + struct rte_security_sess_conf *conf, > + struct rte_mempool *mempool); > + > +/** > + * Frees Security 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_security_session_free(struct rte_security_session *sess); > + > +/** > + * Frees private data for the device id, based on its device name, > + * returning it to its mempool. > + * > + * @param dev_id ID of device that uses the session. > + * @param action_type Action type for Security operation. > + * @param sess Session containing the reference to the private data > + * > + * @return > + * - 0 if successful. > + * - -EINVAL if device is invalid or session is NULL. > + */ > +int > +rte_security_session_clear(uint8_t dev_id, > + enum rte_security_session_action_type action_type, > + struct rte_security_session *sess); > + > +/** > + * Attach a session to a symmetric crypto operation > + * > + * @param sym_op crypto operation > + * @param sess security session > + */ > +static inline int > +__rte_security_attach_session(struct rte_crypto_sym_op *sym_op, > + struct rte_security_session *sess) > +{ > + sym_op->sec_session = sess; > + > + return 0; > +} > + > +static inline void * > +get_sec_session_private_data(const struct rte_security_session *sess, > + uint8_t driver_id) { > + return sess->sess_private_data[driver_id]; > +} > + > +static inline void > +set_sec_session_private_data(struct rte_security_session *sess, > + uint8_t driver_id, void *private_data) > +{ > + sess->sess_private_data[driver_id] = private_data; > +} > + > +/** > + * Attach a session to a crypto operation. > + * This API is needed only in case of RTE_SECURITY_SESS_CRYPTO_PROTO_OFFLOAD > + * For other rte_security_session_action_type, ol_flags in rte_mbuf may be > + * defined to perform security operations. > + * > + * @param op crypto operation > + * @param sess security session > + */ > +static inline int > +rte_security_attach_session(struct rte_crypto_op *op, > + struct rte_security_session *sess) > +{ > + if (unlikely(op->type != RTE_CRYPTO_OP_TYPE_SYMMETRIC)) > + return -1; > + > + op->sess_type = RTE_CRYPTO_OP_WITH_SESSION; > + > + return __rte_security_attach_session(op->sym, sess); > +} > + > +/** > + * Security Capability > + */ > +struct rte_security_capabilities { > + enum rte_security_sess_protocol protocol; > + RTE_STD_C11 > + union { > + struct { > + enum rte_crypto_auth_algorithm a_algo; > + /**< authentication algorithm */ > + enum rte_crypto_cipher_algorithm c_algo; > + /**< cipher algorithm */ > + uint16_t block_size; > + /**< algorithm block size */ > + struct rte_crypto_param_range c_key_size; > + /**< cipher key size range */ > + struct rte_crypto_param_range a_key_size; > + /**< auth key size range */ > + struct rte_crypto_param_range digest_size; > + /**< digest size range */ > + struct rte_crypto_param_range iv_size; > + /**< Initialisation vector data size range */ > + } ipsec; > + /**< IPSEC transform capabilities */ > + struct { > + /* To be Filled */ > + } dtls; > + /**< DTLS transform capabilities */ > + struct { > + /* To be Filled */ > + } macsec; > + /**< MACSEC transform capabilities */ > + }; > +}; > + > +/** > + * Provide capabilities available for defined device and algorithm > + * > + * @param dev_id The identifier of the device. > + * @param dev_name Device name for which capability is needed > + * @param protocol Protocol for which capability is required > + * > + * @return > + * - Return description of the security capability if exist. > + * - Return NULL if the capability not exist. > + */ > +const struct rte_security_capabilities * > +rte_security_capability_get(uint8_t dev_id, char *dev_name, > + enum rte_security_sess_protocol protocol); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* _RTE_SECURITY_H_ */