@@ -4,12 +4,17 @@
; Refer to default.ini for the full list of available PMD features.
;
[Features]
+Symmetric crypto = Y
HW Accelerated = Y
+Cipher multiple data units = Y
+Cipher wrapped key = Y
;
; Supported crypto algorithms of a mlx5 crypto driver.
;
[Cipher]
+AES XTS (128) = Y
+AES XTS (256) = Y
;
; Supported authentication algorithms of a mlx5 crypto driver.
@@ -53,6 +53,16 @@ Supported NICs
* Mellanox\ |reg| ConnectX\ |reg|-6 200G MCX654106A-HCAT (2x200G)
+
+Limitations
+-----------
+
+- AES-XTS keys provided in xform must include keytag and should be wrappend.
+- The supported data-unit lengths are 512B and 1KB. In case the `dataunit_len`
+ is not provided in the cipher xform, the OP length is limited to the above
+ values and 1MB.
+
+
Prerequisites
-------------
@@ -3,6 +3,7 @@
*/
#include <rte_malloc.h>
+#include <rte_mempool.h>
#include <rte_errno.h>
#include <rte_log.h>
#include <rte_pci.h>
@@ -20,7 +21,9 @@
#define MLX5_CRYPTO_LOG_NAME pmd.crypto.mlx5
#define MLX5_CRYPTO_FEATURE_FLAGS \
- RTE_CRYPTODEV_FF_HW_ACCELERATED
+ (RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO | RTE_CRYPTODEV_FF_HW_ACCELERATED | \
+ RTE_CRYPTODEV_FF_CIPHER_WRAPPED_KEY | \
+ RTE_CRYPTODEV_FF_CIPHER_MULTIPLE_DATA_UNITS)
TAILQ_HEAD(mlx5_crypto_privs, mlx5_crypto_priv) mlx5_crypto_priv_list =
TAILQ_HEAD_INITIALIZER(mlx5_crypto_priv_list);
@@ -30,6 +33,32 @@ int mlx5_crypto_logtype;
uint8_t mlx5_crypto_driver_id;
+const struct rte_cryptodev_capabilities mlx5_crypto_caps[] = {
+ { /* AES XTS */
+ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+ {.sym = {
+ .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ {.cipher = {
+ .algo = RTE_CRYPTO_CIPHER_AES_XTS,
+ .block_size = 16,
+ .key_size = {
+ .min = 32,
+ .max = 64,
+ .increment = 32
+ },
+ .iv_size = {
+ .min = 16,
+ .max = 16,
+ .increment = 0
+ },
+ .dataunit_set =
+ RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_512_BYTES |
+ RTE_CRYPTO_CIPHER_DATA_UNIT_LEN_4096_BYTES,
+ }, }
+ }, }
+ },
+};
+
static const char mlx5_crypto_drv_name[] = RTE_STR(MLX5_CRYPTO_DRIVER_NAME);
static const struct rte_driver mlx5_drv = {
@@ -39,6 +68,49 @@ static const struct rte_driver mlx5_drv = {
static struct cryptodev_driver mlx5_cryptodev_driver;
+struct mlx5_crypto_session {
+ uint32_t bs_bpt_eo_es;
+ /*
+ * bsf_size, bsf_p_type, encryption_order and encryption standard,
+ * saved in big endian format.
+ */
+ uint32_t bsp_res;
+ /*
+ * crypto_block_size_pointer and reserved 24 bits saved in big endian
+ * format.
+ */
+ uint32_t iv_offset:16;
+ /* Starting point for Initialisation Vector. */
+ struct mlx5_crypto_dek *dek; /* Pointer to dek struct. */
+ uint32_t dek_id; /* DEK ID */
+} __rte_packed;
+
+static void
+mlx5_crypto_dev_infos_get(struct rte_cryptodev *dev,
+ struct rte_cryptodev_info *dev_info)
+{
+ RTE_SET_USED(dev);
+ if (dev_info != NULL) {
+ dev_info->driver_id = mlx5_crypto_driver_id;
+ dev_info->feature_flags = MLX5_CRYPTO_FEATURE_FLAGS;
+ dev_info->capabilities = mlx5_crypto_caps;
+ dev_info->max_nb_queue_pairs = 0;
+ dev_info->min_mbuf_headroom_req = 0;
+ dev_info->min_mbuf_tailroom_req = 0;
+ dev_info->sym.max_nb_sessions = 0;
+ /*
+ * If 0, the device does not have any limitation in number of
+ * sessions that can be used.
+ */
+ }
+}
+
+static unsigned int
+mlx5_crypto_sym_session_get_size(struct rte_cryptodev *dev __rte_unused)
+{
+ return sizeof(struct mlx5_crypto_session);
+}
+
static int
mlx5_crypto_dev_configure(struct rte_cryptodev *dev,
struct rte_cryptodev_config *config __rte_unused)
@@ -61,19 +133,109 @@ mlx5_crypto_dev_close(struct rte_cryptodev *dev)
return 0;
}
+static int
+mlx5_crypto_sym_session_configure(struct rte_cryptodev *dev,
+ struct rte_crypto_sym_xform *xform,
+ struct rte_cryptodev_sym_session *session,
+ struct rte_mempool *mp)
+{
+ struct mlx5_crypto_priv *priv = dev->data->dev_private;
+ struct mlx5_crypto_session *sess_private_data;
+ struct rte_crypto_cipher_xform *cipher;
+ uint8_t encryption_order;
+ int ret;
+
+ if (unlikely(xform->next != NULL)) {
+ DRV_LOG(ERR, "Xform next is not supported.");
+ return -ENOTSUP;
+ }
+ if (unlikely((xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER) ||
+ (xform->cipher.algo != RTE_CRYPTO_CIPHER_AES_XTS))) {
+ DRV_LOG(ERR, "Only AES-XTS algorithm is supported.");
+ return -ENOTSUP;
+ }
+ ret = rte_mempool_get(mp, (void *)&sess_private_data);
+ if (ret != 0) {
+ DRV_LOG(ERR,
+ "Failed to get session %p private data from mempool.",
+ sess_private_data);
+ return -ENOMEM;
+ }
+ cipher = &xform->cipher;
+ sess_private_data->dek = mlx5_crypto_dek_prepare(priv, cipher);
+ if (sess_private_data->dek == NULL) {
+ rte_mempool_put(mp, sess_private_data);
+ DRV_LOG(ERR, "Failed to prepare dek.");
+ return -ENOMEM;
+ }
+ if (cipher->op == RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+ encryption_order = MLX5_ENCRYPTION_ORDER_ENCRYPTED_RAW_MEMORY;
+ else
+ encryption_order = MLX5_ENCRYPTION_ORDER_ENCRYPTED_RAW_WIRE;
+ sess_private_data->bs_bpt_eo_es = rte_cpu_to_be_32
+ (MLX5_BSF_SIZE_64B << MLX5_BSF_SIZE_OFFSET |
+ MLX5_BSF_P_TYPE_CRYPTO << MLX5_BSF_P_TYPE_OFFSET |
+ encryption_order << MLX5_ENCRYPTION_ORDER_OFFSET |
+ MLX5_ENCRYPTION_STANDARD_AES_XTS);
+ switch (xform->cipher.dataunit_len) {
+ case 0:
+ sess_private_data->bsp_res = 0;
+ break;
+ case 512:
+ sess_private_data->bsp_res = rte_cpu_to_be_32
+ ((uint32_t)MLX5_BLOCK_SIZE_512B <<
+ MLX5_BLOCK_SIZE_OFFSET);
+ break;
+ case 4096:
+ sess_private_data->bsp_res = rte_cpu_to_be_32
+ ((uint32_t)MLX5_BLOCK_SIZE_4096B <<
+ MLX5_BLOCK_SIZE_OFFSET);
+ break;
+ default:
+ DRV_LOG(ERR, "Cipher data unit length is not supported.");
+ return -ENOTSUP;
+ }
+ sess_private_data->iv_offset = cipher->iv.offset;
+ sess_private_data->dek_id =
+ rte_cpu_to_be_32(sess_private_data->dek->obj->id &
+ 0xffffff);
+ set_sym_session_private_data(session, dev->driver_id,
+ sess_private_data);
+ DRV_LOG(DEBUG, "Session %p was configured.", sess_private_data);
+ return 0;
+}
+
+static void
+mlx5_crypto_sym_session_clear(struct rte_cryptodev *dev,
+ struct rte_cryptodev_sym_session *sess)
+{
+ struct mlx5_crypto_priv *priv = dev->data->dev_private;
+ struct mlx5_crypto_session *spriv = get_sym_session_private_data(sess,
+ dev->driver_id);
+
+ if (unlikely(spriv == NULL)) {
+ DRV_LOG(ERR, "Failed to get session %p private data.", spriv);
+ return;
+ }
+ mlx5_crypto_dek_destroy(priv, spriv->dek);
+ set_sym_session_private_data(sess, dev->driver_id, NULL);
+ rte_mempool_put(rte_mempool_from_obj(spriv), spriv);
+ DRV_LOG(DEBUG, "Session %p was cleared.", spriv);
+}
+
static struct rte_cryptodev_ops mlx5_crypto_ops = {
.dev_configure = mlx5_crypto_dev_configure,
.dev_start = NULL,
.dev_stop = NULL,
.dev_close = mlx5_crypto_dev_close,
- .dev_infos_get = NULL,
+ .dev_infos_get = mlx5_crypto_dev_infos_get,
.stats_get = NULL,
.stats_reset = NULL,
.queue_pair_setup = NULL,
.queue_pair_release = NULL,
- .sym_session_get_size = NULL,
- .sym_session_configure = NULL,
- .sym_session_clear = NULL,
+ .sym_session_get_size = mlx5_crypto_sym_session_get_size,
+ .sym_session_configure = mlx5_crypto_sym_session_configure,
+ .sym_session_clear = mlx5_crypto_sym_session_clear,
.sym_get_raw_dp_ctx_size = NULL,
.sym_configure_raw_dp_ctx = NULL,
};