From: Sardar Shamsher Singh <shamshersingh.sar...@amd.com>

test application to test Cipher/Authentication/AEAD in AMD CCP
a crypto controller. This test application can be used as
reference to develop/test crypto algo.

Signed-off-by: Sardar Shamsher Singh <shamshersingh.sar...@amd.com>
---
 doc/guides/sample_app_ug/ccp_crypto.rst | 114 +++
 examples/crypto/Makefile                |  63 ++
 examples/crypto/main.c                  | 899 ++++++++++++++++++++++++
 3 files changed, 1076 insertions(+)
 create mode 100644 doc/guides/sample_app_ug/ccp_crypto.rst
 create mode 100644 examples/crypto/Makefile
 create mode 100644 examples/crypto/main.c

diff --git a/doc/guides/sample_app_ug/ccp_crypto.rst 
b/doc/guides/sample_app_ug/ccp_crypto.rst
new file mode 100644
index 000000000..0f56b444b
--- /dev/null
+++ b/doc/guides/sample_app_ug/ccp_crypto.rst
@@ -0,0 +1,114 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+   Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
+
+
+.. _crypto_app:
+
+Crypto Sample Application
+============================================
+
+The Crypto sample application is a simple example to test Crypto algorithm 
using
+CCP, the Data Plane Development Kit (DPDK), in conjunction with the Cryptodev 
library.
+
+Overview
+--------
+
+The Crypto sample application performs a Crypto operation (Cipher/Auth) 
specified by the user
+from command line, with a Crypto device (like CCP) capable of doing that 
operation.
+
+Compiling the Application
+-------------------------
+
+To compile the sample application see :doc:`compiling`.
+
+The application is located in the `examples/crypto` sub-directory.
+
+Running the Application
+-----------------------
+
+The application requires a number of command line options:
+
+.. code-block:: console
+
+       ./build/crypto [EAL options] -- [-l core list] [-n number of channels] /
+       [--vdev "crypto_ccp"] [--cdev_type HW/SW/ANY] [--cipher_op ENCRYPT / 
DECRYPT] /
+       [--cipher_algo ALGO] [--plain_text ] [--cipher_key KEY] [--cipher_iv 
IV] /
+       [--auth_op GENERATE / VERIFY] [ --auth_algo ALGO] [--auth_key KEY] /
+       [--aead_algo ALGO] [--aead_op ENCRYPT / DECRYPT] [--aead_key KEY] 
[--aead_iv IV] /
+       [--aad AAD] [ --digest]
+
+
+where,
+
+* l <core list>        : List of cores to run on
+
+* n NUM                : Number of memory channels
+
+* vdev             : Add a virtual device
+
+* cdev_type: select preferred crypto device type: HW, SW or anything (ANY)
+
+* cipher_op: select the ciphering operation to perform: ENCRYPT or DECRYPT
+
+* cipher_algo: select the ciphering algorithm (EX: aes-cbc/aes-ecb/aes-ctr/)
+
+* cipher_key: set the ciphering key to be used. Bytes has to be separated with 
":"
+
+* cipher_iv: set the cipher IV to be used. Bytes has to be separated with ":"
+
+* plain_text: set the plain text to be operated. Bytes has to be separated 
with ":"
+
+* auth_op: select the authentication operation to perform: GENERATE or VERIFY
+
+* auth_algo: select the authentication algorithm
+
+* auth_key: set the authentication key to be used. Bytes has to be separated 
with ":"
+
+* aead_algo: select the AEAD algorithm
+
+* aead_op: select the AEAD operation to perform: ENCRYPT or DECRYPT
+
+* aead_key: set the AEAD key to be used. Bytes has to be separated with ":"
+
+* aead_iv: set the AEAD IV to be used. Bytes has to be separated with ":"
+
+* aad: set the AAD to be used. Bytes has to be separated with ":"
+
+* digest : set the DIGEST values to be used. Bytes has to be separated with ":"
+
+
+The application requires that crypto devices capable of performing
+the specified crypto operation are available on application initialization.
+This means that HW crypto device/s must be bound to a DPDK driver or
+a SW crypto device/s (virtual crypto PMD) must be created (using --vdev).
+
+Below are few example to run the application in linux environment with 2 
lcores,
+       4 Memory channel and 1 crypto device, issue the command:
+
+.. code-block:: console
+
+    Example 1:
+       $sudo ./build/crypto -l1,2 -n 4 --vdev "crypto_ccp" -- --cipher_op 
ENCRYPT \
+       --cipher_algo aes-cbc --plain_text 
f3:44:81:ec:3c:c6:27:ba:cd:5d:c3:fb:08:f2:73:e6 \
+       --cipher_key 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 \
+       --cipher_iv 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
+
+    Example 2:
+       $sudo ./build/crypto -l1,2 -n 4 --vdev "crypto_ccp" -- --auth_op 
GENERATE \
+       --auth_algo sha3-224 --plain_text 01
+
+    Example 3:
+       $sudo ./build/crypto -l1,2 -n 4 --vdev "crypto_ccp" \
+       -- --aead_op ENCRYPT --aead_algo aes-gcm \
+       --plain_text c3:b3:c4:1f:11:3a:31:b7:3d:9a:5c:d4:32:10:30:69 \
+       --aead_key c9:39:cc:13:39:7c:1d:37:de:6a:e0:e1:cb:7c:42:3c \
+       --aead_iv 01:00:00:00:e2:67:0f:9e:b3:89:bb:7c:01:cc:d8:b3 \
+       --aad 24:82:56:02:bd:12:a9:84:e0:09:2d:3e:44:8e:da:5f \
+       --digest 00:00:00:00:00:00:00:80:00:00:00:00:00:00:00:80
+
+Refer to the *DPDK Getting Started Guide* for general information on running 
applications
+and the Environment Abstraction Layer (EAL) options.
+
+.. Note::
+
+    * All crypto devices shall use the same session.
diff --git a/examples/crypto/Makefile b/examples/crypto/Makefile
new file mode 100644
index 000000000..9b1be69ef
--- /dev/null
+++ b/examples/crypto/Makefile
@@ -0,0 +1,63 @@
+#SPDX-License-Identifier: BSD-3-Clause
+#Copyright(c) 2019 Advanced Micro Devices, Inc. All rights reserved.
+
+# binary name
+APP = crypto
+
+SRCS-y := main.c
+
+# Build using pkg-config variables if possible
+$(shell pkg-config --exists libdpdk)
+ifeq ($(shell pkg-config --exists libdpdk && echo 0),0)
+
+#ifeq ($(.SHELLSTATUS),0)
+
+all: shared
+.PHONY: shared static
+shared: build/$(APP)-shared
+       ln -sf $(APP)-shared build/$(APP)
+static: build/$(APP)-static
+       ln -sf $(APP)-static build/$(APP)
+
+PC_FILE := $(shell pkg-config --path libdpdk)
+CFLAGS += -O3 $(shell pkg-config --cflags libdpdk)
+LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
+LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
+
+build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
+       $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
+
+build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build
+       $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC)
+
+build:
+       @mkdir -p $@
+
+.PHONY: clean
+clean:
+       rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared
+       rmdir --ignore-fail-on-non-empty build
+
+else # Build using legacy build system
+
+ifeq ($(RTE_SDK),)
+$(error "Please define RTE_SDK environment variable")
+endif
+
+# Default target, can be overridden by command line or environment
+RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard 
$(RTE_SDK)/*/.config)))))
+
+include $(RTE_SDK)/mk/rte.vars.mk
+
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+CFLAGS += -O3
+CFLAGS += $(WERROR_FLAGS)
+
+ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y)
+ifeq ($(CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER),y)
+LDLIBS += -lrte_pmd_crypto_scheduler
+endif
+endif
+
+include $(RTE_SDK)/mk/rte.extapp.mk
+endif
diff --git a/examples/crypto/main.c b/examples/crypto/main.c
new file mode 100644
index 000000000..47a53fbac
--- /dev/null
+++ b/examples/crypto/main.c
@@ -0,0 +1,899 @@
+/*   SPDX-License-Identifier: BSD-3-Clause
+ *   Copyright(c) 2019 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <time.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <errno.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <rte_atomic.h>
+#include <rte_branch_prediction.h>
+#include <rte_common.h>
+#include <rte_cryptodev.h>
+#include <rte_cycles.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_interrupts.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_memory.h>
+#include <rte_mempool.h>
+#include <rte_per_lcore.h>
+#include <rte_prefetch.h>
+#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER
+#include <rte_cryptodev_scheduler.h>
+#endif
+
+#define MAX_STR_LEN 32
+#define MAX_KEY_SIZE 512
+#define MAX_PT_SIZE 65535
+#define MAX_IV_SIZE 256
+#define MAX_AAD_SIZE 65535
+#define MAX_DIGEST_SIZE 16
+#define SESSION_POOL_CACHE_SIZE 0
+#define IV_OFFSET              (sizeof(struct rte_crypto_op) + \
+                               sizeof(struct rte_crypto_sym_op))
+#define BURST_SIZE           1
+#define BUFFER_SIZE          64
+#define NUM_MBUFS            1024
+#define POOL_CACHE_SIZE      128
+
+#define AES_CBC_IV_LENGTH    16
+#define AES_CBC_KEY_LENGTH   16
+
+#define SHA_DIGEST_LENGTH 20
+#define SHA224_DIGEST_LENGTH    28
+#define SHA256_DIGEST_LENGTH    32
+#define SHA384_DIGEST_LENGTH    48
+#define SHA512_DIGEST_LENGTH    64
+
+
+enum cdev_type {
+       CDEV_TYPE_ANY,
+       CDEV_TYPE_HW,
+       CDEV_TYPE_SW
+};
+
+struct cdev_iv {
+       uint8_t *data;
+       uint16_t length;
+};
+struct cdev_aad_key {
+       uint8_t *data;
+       uint16_t length;
+};
+struct cdev_aad_digest {
+       uint8_t *data;
+       uint16_t length;
+};
+
+/** crypto application command line options */
+struct ccp_crypto_options {
+       enum cdev_type type;
+       unsigned int crypto_op_private_data;
+
+       struct rte_crypto_sym_xform cipher_xform;
+       struct cdev_iv cipher_iv;
+       uint8_t cipher_key[MAX_KEY_SIZE];
+
+       struct rte_crypto_sym_xform auth_xform;
+       uint8_t auth_key[MAX_KEY_SIZE];
+
+       struct rte_crypto_sym_xform aead_xform;
+       struct cdev_iv aead_iv;
+       struct cdev_aad_key aad;
+       uint8_t aead_key[MAX_KEY_SIZE];
+       struct cdev_aad_digest aad_digest;
+       int digest_size;
+
+       char string_type[MAX_STR_LEN];
+};
+uint8_t *pt;
+int pt_length;
+struct rte_mempool *session_pool_socket[RTE_MAX_NUMA_NODES] = { 0 };
+int buffer_size = BUFFER_SIZE;
+
+/* Display command line arguments usage */
+static void
+ccp_crypto_usage(const char *prgname)
+{
+       printf("%s [EAL options] --\n"
+       "  --cdev_type HW / SW / ANY\n"
+       "  --cipher_op ENCRYPT / DECRYPT\n"
+       "  --cipher_algo ALGO\n"
+       "  --plain_text  (bytes separated with \":\")\n"
+       "  --cipher_key KEY (bytes separated with \":\")\n"
+       "  --cipher_iv  (bytes separated with \":\")\n"
+       "  --auth_op GENERATE / VERIFY\n"
+       "  --auth_algo ALGO\n"
+       "  --auth_key KEY (bytes separated with \":\")\n"
+       "  --aead_algo ALGO\n"
+       "  --aead_op ENCRYPT / DECRYPT\n"
+       "  --aead_key KEY (bytes separated with \":\")\n"
+       "  --aead_iv IV (bytes separated with \":\")\n"
+       "  --aad AAD (bytes separated with \":\")\n"
+       "  --digest (16-bytes separated with \":\")\n",
+       prgname);
+}
+
+/** Parse crypto device type command line argument */
+static int
+parse_cryptodev_type(enum cdev_type *type, char *optarg)
+{
+       if (strcmp("HW", optarg) == 0) {
+               *type = CDEV_TYPE_HW;
+               return 0;
+       } else if (strcmp("SW", optarg) == 0) {
+               *type = CDEV_TYPE_SW;
+               return 0;
+       } else if (strcmp("ANY", optarg) == 0) {
+               *type = CDEV_TYPE_ANY;
+               return 0;
+       }
+       return -1;
+}
+
+/** Parse crypto cipher operation command line argument */
+static int
+parse_cipher_op(enum rte_crypto_cipher_operation *op, char *optarg)
+{
+       if (strcmp("ENCRYPT", optarg) == 0) {
+               *op = RTE_CRYPTO_CIPHER_OP_ENCRYPT;
+               return 0;
+       } else if (strcmp("DECRYPT", optarg) == 0) {
+               *op = RTE_CRYPTO_CIPHER_OP_DECRYPT;
+               return 0;
+       }
+       printf("Cipher operation not supported!\n");
+       return -1;
+}
+
+/** Parse crypto cipher algo option command line argument */
+static int
+parse_cipher_algo(enum rte_crypto_cipher_algorithm *algo, char *optarg)
+{
+       if (rte_cryptodev_get_cipher_algo_enum(algo, optarg) < 0) {
+               printf("Cipher algorithm specified not supported!\n");
+       return -1;
+       }
+       return 0;
+}
+/** Parse bytes from command line argument */
+static int
+parse_bytes(uint8_t *data, char *input_arg, uint16_t max_size)
+{
+       int byte_count;
+       char *token;
+
+       errno = 0;
+       for (byte_count = 0, token = strtok(input_arg, ":");
+               (byte_count < max_size) && (token != NULL);
+               token = strtok(NULL, ":")) {
+               int number = (int)strtol(token, NULL, 16);
+               if (errno == EINVAL || errno == ERANGE || number > 0xFF)
+                       return -1;
+               data[byte_count++] = (uint8_t)number;
+       }
+       return byte_count;
+}
+
+/** Parse crypto cipher operation command line argument */
+static int
+parse_auth_algo(enum rte_crypto_auth_algorithm *algo, char *optarg)
+{
+       if (rte_cryptodev_get_auth_algo_enum(algo, optarg) < 0) {
+               printf("Authentication algorithm specified not supported!\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+parse_auth_op(enum rte_crypto_auth_operation *op, char *optarg)
+{
+       if (strcmp("VERIFY", optarg) == 0) {
+               *op = RTE_CRYPTO_AUTH_OP_VERIFY;
+               return 0;
+       } else if (strcmp("GENERATE", optarg) == 0) {
+               *op = RTE_CRYPTO_AUTH_OP_GENERATE;
+               return 0;
+       }
+       printf("Authentication operation specified not supported!\n");
+       return -1;
+}
+
+static int
+parse_aead_algo(enum rte_crypto_aead_algorithm *algo, char *optarg)
+{
+       if (rte_cryptodev_get_aead_algo_enum(algo, optarg) < 0) {
+               printf("AEAD algorithm specified not supported!\n");
+               return -1;
+       }
+       return 0;
+}
+
+static int
+parse_aead_op(enum rte_crypto_aead_operation *op, char *optarg)
+{
+       if (strcmp("ENCRYPT", optarg) == 0) {
+               *op = RTE_CRYPTO_AEAD_OP_ENCRYPT;
+               return 0;
+       } else if (strcmp("DECRYPT", optarg) == 0) {
+               *op = RTE_CRYPTO_AEAD_OP_DECRYPT;
+               return 0;
+       }
+       printf("AEAD operation specified not supported!\n");
+       return -1;
+}
+
+/** Parse long options */
+static int
+ccp_crypto_parse_args_long_options(struct ccp_crypto_options *options,
+               struct option *lgopts, int option_index)
+{
+       int retval;
+
+       if (strcmp(lgopts[option_index].name, "cdev_type") == 0) {
+               retval = parse_cryptodev_type(&options->type, optarg);
+               if (retval == 0)
+                       snprintf(options->string_type, MAX_STR_LEN,
+                               "%s", optarg);
+               return retval;
+       } else if (strcmp(lgopts[option_index].name, "plain_text") == 0) {
+               pt_length =
+                       parse_bytes(pt, optarg, MAX_PT_SIZE);
+               buffer_size = pt_length;
+               if (pt_length > 0)
+                       return 0;
+               else
+                       return -1;
+       } else if (strcmp(lgopts[option_index].name, "cipher_op") == 0)
+               return parse_cipher_op(&options->cipher_xform.cipher.op,
+                       optarg);
+       else if (strcmp(lgopts[option_index].name, "cipher_algo") == 0)
+               return parse_cipher_algo(&options->cipher_xform.cipher.algo,
+                       optarg);
+       else if (strcmp(lgopts[option_index].name, "cipher_key") == 0) {
+               options->cipher_xform.cipher.key.length =
+               parse_bytes(options->cipher_key, optarg, MAX_KEY_SIZE);
+               if (options->cipher_xform.cipher.key.length > 0)
+                       return 0;
+               else
+                       return -1;
+       } else if (strcmp(lgopts[option_index].name, "cipher_iv") == 0) {
+               options->cipher_iv.length =
+                       parse_bytes(options->cipher_iv.data,
+                                       optarg, MAX_IV_SIZE);
+               options->cipher_xform.cipher.iv.length =
+                       options->cipher_iv.length;
+               options->cipher_xform.cipher.iv.offset =  IV_OFFSET;
+               if (options->cipher_iv.length > 0)
+                       return 0;
+               else
+                       return -1;
+       }
+
+       /* Authentication options */
+       else if (strcmp(lgopts[option_index].name, "auth_op") == 0)
+               return parse_auth_op(&options->auth_xform.auth.op,
+                                       optarg);
+       else if (strcmp(lgopts[option_index].name, "auth_algo") == 0) {
+               return parse_auth_algo(&options->auth_xform.auth.algo,
+                                       optarg);
+       } else if (strcmp(lgopts[option_index].name, "auth_key") == 0) {
+               options->auth_xform.auth.key.length =
+                       parse_bytes(options->auth_key, optarg, MAX_KEY_SIZE);
+               if (options->auth_xform.auth.key.length > 0)
+                       return 0;
+               else
+                       return -1;
+       }
+       /* AEAD options */
+       else if (strcmp(lgopts[option_index].name, "aead_algo") == 0) {
+               return parse_aead_algo(&options->aead_xform.aead.algo,
+                                       optarg);
+       } else if (strcmp(lgopts[option_index].name, "aead_op") == 0)
+               return parse_aead_op(&options->aead_xform.aead.op,
+                                       optarg);
+       else if (strcmp(lgopts[option_index].name, "aead_key") == 0) {
+               options->aead_xform.aead.key.length =
+                       parse_bytes(options->aead_key, optarg, MAX_KEY_SIZE);
+               if (options->aead_xform.aead.key.length > 0)
+                       return 0;
+               else
+                       return -1;
+       } else if (strcmp(lgopts[option_index].name, "aead_iv") == 0) {
+               options->aead_iv.length =
+                       parse_bytes(options->aead_iv.data,
+                                       optarg, MAX_IV_SIZE);
+               options->aead_xform.aead.iv.length = options->aead_iv.length;
+               options->aead_xform.aead.iv.offset =  IV_OFFSET;
+               if (options->aead_xform.aead.iv.length > 0)
+                       return 0;
+               else
+                       return -1;
+       } else if (strcmp(lgopts[option_index].name, "aad") == 0) {
+               options->aad.length =
+                       parse_bytes(options->aad.data, optarg, MAX_AAD_SIZE);
+               options->aead_xform.aead.aad_length = options->aad.length;
+               if (options->aad.length > 0)
+                       return 0;
+               else
+                       return -1;
+       } else if (strcmp(lgopts[option_index].name, "digest") == 0) {
+               options->digest_size =
+                       parse_bytes(options->aad_digest.data,
+                                       optarg, MAX_DIGEST_SIZE);
+               options->aead_xform.aead.digest_length = options->digest_size;
+               if (options->digest_size > 0)
+                       return 0;
+               else
+                       return -1;
+       }
+       return -1;
+}
+
+static void
+ccp_crypto_default_options(struct ccp_crypto_options *options)
+{
+       options->type = CDEV_TYPE_ANY;
+       options->crypto_op_private_data = AES_CBC_IV_LENGTH;
+
+       /* Cipher Data */
+       options->cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
+       options->cipher_xform.next = NULL;
+       options->cipher_xform.cipher.key.length = 0;
+       options->cipher_xform.cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
+       options->cipher_xform.cipher.op = -1;
+       options->cipher_xform.cipher.iv.offset = IV_OFFSET;
+       options->cipher_xform.cipher.iv.length = AES_CBC_IV_LENGTH;
+
+        /* Authentication Data */
+       options->auth_xform.type = RTE_CRYPTO_SYM_XFORM_AUTH;
+       options->auth_xform.next = NULL;
+       options->auth_xform.auth.key.length = 20;
+       options->auth_xform.auth.digest_length = 20;
+       options->auth_xform.auth.algo = RTE_CRYPTO_AUTH_SHA1_HMAC;
+       options->auth_xform.auth.op = -1;
+
+       /* AEAD Data */
+       options->aead_xform.type = RTE_CRYPTO_SYM_XFORM_AEAD;
+       options->aead_xform.next = NULL;
+       options->aead_xform.aead.key.length = 0;
+       options->aead_xform.aead.digest_length = 0;
+       options->aead_iv.length = 16;
+       options->aead_xform.aead.iv.offset =  IV_OFFSET;
+       options->aead_xform.aead.algo = RTE_CRYPTO_AEAD_AES_GCM;
+       options->aead_xform.aead.op = -1;
+       options->aad.length = 0;
+       options->digest_size = -1;
+}
+
+static int
+ccp_crypto_parse_args(struct ccp_crypto_options *options,
+       int argc, char **argv)
+{
+       int opt, retval, option_index;
+       char **argvopt = argv, *prgname = argv[0];
+
+       static struct option lgopts[] = {
+               { "cdev_type", required_argument, 0, 0 },
+               { "cipher_op", required_argument, 0, 0 },
+               { "cipher_algo", required_argument, 0, 0 },
+               { "plain_text", required_argument, 0, 0 },
+               { "cipher_key", required_argument, 0, 0 },
+               { "cipher_iv", required_argument, 0, 0 },
+
+               { "auth_op", required_argument, 0, 0 },
+               { "auth_algo", required_argument, 0, 0 },
+               { "auth_key", required_argument, 0, 0 },
+
+               { "aead_algo", required_argument, 0, 0 },
+               { "aead_op", required_argument, 0, 0 },
+               { "aead_key", required_argument, 0, 0 },
+               { "aead_iv", required_argument, 0, 0 },
+               { "aad", required_argument, 0, 0 },
+               { "digest", required_argument, 0, 0 },
+
+               { NULL, 0, 0, 0 }
+       };
+
+       ccp_crypto_default_options(options);
+
+       while ((opt = getopt_long(argc, argvopt, "ac:", lgopts,
+                       &option_index)) != EOF) {
+               switch (opt) {
+               case 0:
+                       retval = ccp_crypto_parse_args_long_options(options,
+                                               lgopts, option_index);
+                       if (retval < 0) {
+                               ccp_crypto_usage(prgname);
+                               return -1;
+                       }
+               break;
+               default:
+                       ccp_crypto_usage(prgname);
+                       return -1;
+               }
+       }
+       if (optind >= 0)
+               argv[optind-1] = prgname;
+
+       retval = optind-1;
+       optind = 1;
+
+       return retval;
+}
+
+static void
+reserve_key_memory(struct ccp_crypto_options *options)
+{
+       pt = rte_malloc("plain_text", MAX_PT_SIZE, 0);
+       if (pt == NULL)
+               rte_exit(EXIT_FAILURE,
+                              "Failed to allocate memory for plain text");
+
+       options->cipher_xform.cipher.key.data = options->cipher_key;
+
+       options->cipher_iv.data = rte_malloc("cipher iv", MAX_IV_SIZE, 0);
+       if (options->cipher_iv.data == NULL)
+               rte_exit(EXIT_FAILURE,
+                              "Failed to allocate memory for cipher IV");
+
+       options->auth_xform.auth.key.data = options->auth_key;
+
+       options->aead_iv.data = rte_malloc("aead_iv", MAX_IV_SIZE, 0);
+       if (options->aead_iv.data == NULL)
+               rte_exit(EXIT_FAILURE, "Failed to allocate memory for AEAD iv");
+
+       options->aead_xform.aead.key.data = options->aead_key;
+       options->aad.data = rte_malloc("aad", MAX_AAD_SIZE, 0);
+       if (options->aad.data == NULL)
+               rte_exit(EXIT_FAILURE, "Failed to allocate memory for AAD");
+
+       options->aad_digest.data = rte_malloc("digest", MAX_DIGEST_SIZE, 0);
+       if (options->aad_digest.data == NULL)
+               rte_exit(EXIT_FAILURE, "Failed to allocate memory for Digest");
+}
+
+static struct rte_cryptodev_sym_session *
+initialize_crypto_session(struct ccp_crypto_options *options,
+                       struct rte_mempool *sess_mp,
+                       struct rte_mempool *sess_mp_priv,
+                       uint8_t cdev_id)
+{
+       struct rte_crypto_sym_xform *xform;
+       struct rte_cryptodev_sym_session *session;
+       int retval = rte_cryptodev_socket_id(cdev_id);
+
+       if (retval < 0)
+               return NULL;
+
+       if (options->cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT ||
+               options->cipher_xform.cipher.op ==
+                       RTE_CRYPTO_CIPHER_OP_DECRYPT) {
+               xform = &options->cipher_xform;
+       } else if (options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_GENERATE ||
+               options->auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+               xform = &options->auth_xform;
+       } else if (options->aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT ||
+               options->aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
+               xform = &options->aead_xform;
+       } else {
+               xform = &options->cipher_xform;
+       }
+
+       session = rte_cryptodev_sym_session_create(sess_mp);
+
+       if (session == NULL) {
+               printf("session NULL\n");
+               return NULL;
+       }
+
+       if (rte_cryptodev_sym_session_init(cdev_id, session,
+                       xform, sess_mp_priv) < 0) {
+               printf("sym session init fails");
+               return NULL;
+       }
+       return session;
+}
+
+int
+main(int argc, char **argv)
+{
+       int ret, save_file = 1;
+       uint8_t  cdev_id = 0, cdev_count;
+       unsigned int sess_sz;
+
+       struct rte_cryptodev_qp_conf qp_conf;
+       struct rte_cryptodev_info dev_info;
+       struct rte_cryptodev_sym_session *session;
+       struct rte_mempool *mbuf_pool, *crypto_op_pool;
+       struct ccp_crypto_options options;
+
+       char mp_name[RTE_MEMPOOL_NAMESIZE], mp_name2[RTE_MEMPOOL_NAMESIZE];
+       struct rte_mempool *sess_mp, *sess_mp_priv;
+       int retval = rte_cryptodev_socket_id(cdev_id);
+       uint8_t socket_id = (uint8_t) retval;
+       uint8_t *input_file = NULL;
+       long flen = 0;
+       unsigned int crypto_op_private_data = AES_CBC_IV_LENGTH;
+       struct rte_crypto_op *crypto_ops[BURST_SIZE];
+       struct rte_mbuf *mbufs[BURST_SIZE];
+       unsigned int i;
+       int buff_size;
+       int md_size;
+       int log_size;
+       int loop = 0;
+
+       ret = rte_eal_init(argc, argv);
+       if (ret < 0)
+               rte_panic("Cannot init EAL\n");
+       argc -= ret;
+       argv += ret;
+
+       /* reserve memory for Plain_text/Cipher/Auth key/IV and AEAD*/
+       reserve_key_memory(&options);
+
+       /* parse application arguments (after the EAL ones) */
+       ret = ccp_crypto_parse_args(&options, argc, argv);
+       if (ret < 0)
+               rte_exit(EXIT_FAILURE, "Invalid CCP-CRYPTO arguments\n");
+
+       cdev_count = rte_cryptodev_count();
+       printf("cdev_count: %d\n", cdev_count);
+
+       sess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id);
+
+       rte_cryptodev_info_get(cdev_id, &dev_info);
+       printf("crypto dev name: %s\n", dev_info.driver_name);
+
+       retval = rte_cryptodev_socket_id(cdev_id);
+       socket_id = (uint8_t) retval;
+
+       snprintf(mp_name, RTE_MEMPOOL_NAMESIZE, "sess_mp_%u", socket_id);
+       snprintf(mp_name2, RTE_MEMPOOL_NAMESIZE, "sess_mp_priv%u", socket_id);
+
+       sess_mp = rte_cryptodev_sym_session_pool_create(mp_name,
+                               sess_sz, 0, 0, 0, socket_id);
+       if (sess_mp == NULL) {
+               printf("Cannot create session pool on socket %d\n", socket_id);
+                               return -ENOMEM;
+       }
+       sess_mp_priv = rte_mempool_create(mp_name2, 2, sess_sz,
+                                       SESSION_POOL_CACHE_SIZE,
+                                       0, NULL, NULL, NULL,
+                                       NULL, socket_id, 0);
+       if (sess_mp == NULL) {
+               printf("Cannot create session pool on socket %d\n", socket_id);
+               return -ENOMEM;
+       }
+
+       struct rte_cryptodev_config conf = {
+                       .nb_queue_pairs = 1,
+                       .socket_id = socket_id,
+       };
+       retval = rte_cryptodev_configure(cdev_id, &conf);
+       qp_conf.nb_descriptors = 2048;
+       qp_conf.mp_session = sess_mp;
+       qp_conf.mp_session_private = sess_mp_priv;
+
+       retval = rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
+                       socket_id);
+       if (retval < 0) {
+               printf("Failed to setup queue pair %u on cryptodev %u",
+                               0, cdev_id);
+               return -1;
+       }
+
+       retval = rte_cryptodev_start(cdev_id);
+       if (retval < 0) {
+               printf("Failed to start device %u: error %d\n",
+                       cdev_id, retval);
+               return -1;
+       }
+       /* Create crypto operation pool. */
+       crypto_op_pool = rte_crypto_op_pool_create("crypto_op_pool",
+                                               RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+                                               NUM_MBUFS,
+                                               POOL_CACHE_SIZE,
+                                               crypto_op_private_data,
+                                               socket_id);
+
+       if (options.cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_DECRYPT
+               || options.aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
+               FILE *f = fopen("encoded.data", "rb");
+               fseek(f, 0L, SEEK_END);
+               flen = ftell(f);
+               input_file = malloc(flen);
+               rewind(f);
+               size_t result = fread(input_file, flen, 1, f);
+               if (!result) {
+                       fputs("Reading error", stderr); exit(3);
+               }
+               fclose(f);
+       }
+
+       if (options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+               FILE *f = fopen("sha.data", "rb");
+               fseek(f, 0L, SEEK_END);
+               flen = ftell(f);
+               input_file = malloc(flen);
+               rewind(f);
+               size_t result = fread(input_file, flen, 1, f);
+               if (!result) {
+                       fputs("Reading error", stderr); exit(3);
+               }
+               fclose(f);
+       }
+       if ((options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
+               || (options.auth_xform.auth.op ==
+                      RTE_CRYPTO_AUTH_OP_GENERATE)) {
+               switch (options.auth_xform.auth.algo) {
+               case RTE_CRYPTO_AUTH_SHA1:
+               case RTE_CRYPTO_AUTH_SHA1_HMAC:
+                       md_size = SHA_DIGEST_LENGTH;
+                       break;
+               case RTE_CRYPTO_AUTH_SHA224:
+               case RTE_CRYPTO_AUTH_SHA224_HMAC:
+               case RTE_CRYPTO_AUTH_SHA3_224:
+               case RTE_CRYPTO_AUTH_SHA3_224_HMAC:
+                       md_size = SHA224_DIGEST_LENGTH;
+                       break;
+               case RTE_CRYPTO_AUTH_SHA256:
+               case RTE_CRYPTO_AUTH_SHA256_HMAC:
+               case RTE_CRYPTO_AUTH_SHA3_256:
+               case RTE_CRYPTO_AUTH_SHA3_256_HMAC:
+                       md_size = SHA256_DIGEST_LENGTH;
+                       break;
+               case RTE_CRYPTO_AUTH_SHA384:
+               case RTE_CRYPTO_AUTH_SHA384_HMAC:
+               case RTE_CRYPTO_AUTH_SHA3_384:
+               case RTE_CRYPTO_AUTH_SHA3_384_HMAC:
+                       md_size = SHA384_DIGEST_LENGTH;
+                       break;
+               case RTE_CRYPTO_AUTH_SHA512:
+               case RTE_CRYPTO_AUTH_SHA512_HMAC:
+               case RTE_CRYPTO_AUTH_SHA3_512:
+               case RTE_CRYPTO_AUTH_SHA3_512_HMAC:
+                       md_size = SHA512_DIGEST_LENGTH;
+                       break;
+               default:
+                       md_size = 20;
+                       printf("Non-supported mode !!!\n");
+                       break;
+               }
+               options.auth_xform.auth.digest_length = md_size;
+       }
+
+       session = initialize_crypto_session(&options,
+                               sess_mp, sess_mp_priv, cdev_id);
+       if (session == NULL) {
+               printf("session NULL\n");
+               return 0;
+       }
+
+       /* Get a burst of crypto operations. */
+       if (rte_crypto_op_bulk_alloc(crypto_op_pool,
+                                       RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+                                       crypto_ops, BURST_SIZE) == 0)
+               rte_exit(EXIT_FAILURE,
+                               "Not enough crypto operations available\n");
+
+       /* Create the mbuf pool. */
+       mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NUM_MBUFS,
+                               POOL_CACHE_SIZE, 0,
+                               (RTE_MBUF_DEFAULT_BUF_SIZE+1024*60), socket_id);
+       if (mbuf_pool == NULL)
+               rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+       buff_size = buffer_size;
+       if (options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
+               buff_size = flen;
+
+       if (rte_pktmbuf_alloc_bulk(mbuf_pool, mbufs, BURST_SIZE) < 0)
+               rte_exit(EXIT_FAILURE, "Not enough mbufs available");
+
+       /* Initialize the mbufs and append them to the crypto operations. */
+       for (i = 0; i < BURST_SIZE; i++) {
+               if (rte_pktmbuf_append(mbufs[i], buff_size) == NULL)
+                       rte_exit(EXIT_FAILURE, "Not enough room in the mbuf\n");
+               crypto_ops[i]->sym->m_src = mbufs[i];
+       }
+       /* Set up the crypto operations. */
+       for (i = 0; i < BURST_SIZE; i++) {
+               struct rte_crypto_op *op = crypto_ops[i];
+               if ((options.cipher_xform.cipher.op ==
+                       RTE_CRYPTO_CIPHER_OP_DECRYPT) ||
+                       (options.cipher_xform.cipher.op
+                               == RTE_CRYPTO_CIPHER_OP_ENCRYPT)) {
+                       op->sym->cipher.data.offset = 0;
+                       op->sym->cipher.data.length = buffer_size;
+                       if ((options.cipher_xform.cipher.algo !=
+                               RTE_CRYPTO_CIPHER_3DES_ECB) ||
+                               (options.cipher_xform.cipher.algo !=
+                                       RTE_CRYPTO_CIPHER_AES_ECB)) {
+                               uint8_t *iv_ptr =
+                                       rte_crypto_op_ctod_offset(op,
+                                                       uint8_t *, IV_OFFSET);
+                               rte_memcpy(iv_ptr, options.cipher_iv.data,
+                                               options.cipher_iv.length);
+                       }
+               }
+               op->sym->auth.data.offset = 0;
+               if (options.aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
+                       uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op,
+                                       uint8_t *, IV_OFFSET);
+                       rte_memcpy(iv_ptr, options.aead_iv.data,
+                                       options.aead_iv.length);
+                       op->sym->aead.data.offset = 0;
+                       op->sym->aead.data.length = buffer_size;
+                       op->sym->aead.aad.data = options.aad.data;
+                       op->sym->aead.digest.data =
+                              (uint8_t *)rte_pktmbuf_append(mbufs[i],
+                                               options.digest_size);
+                       rte_memcpy(op->sym->aead.digest.data,
+                                       options.aad_digest.data,
+                                       options.aead_xform.aead.digest_length);
+               }
+               if (options.aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_DECRYPT) {
+                       uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op,
+                                                       uint8_t *, IV_OFFSET);
+                       rte_memcpy(iv_ptr, options.aead_iv.data,
+                                       options.aead_iv.length);
+                       op->sym->aead.data.offset = 0;
+                       op->sym->aead.data.length = flen;
+                       op->sym->aead.aad.data = options.aad.data;
+                       op->sym->aead.digest.data =
+                               (uint8_t *)rte_pktmbuf_mtod(mbufs[i], uint8_t *)
+                                       +flen - options.digest_size;
+               }
+               if (options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_GENERATE) {
+                       op->sym->auth.data.length = buffer_size;
+                       op->sym->auth.digest.data =
+                         (uint8_t *)rte_pktmbuf_append(mbufs[i], md_size);
+               }
+               if (options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY) {
+                       op->sym->auth.data.length = flen-md_size;
+                       op->sym->auth.digest.data =
+                               rte_pktmbuf_mtod(mbufs[i], uint8_t *)
+                                 + (rte_pktmbuf_data_len(mbufs[i])-md_size);
+               }
+               /* Attach the crypto session to the operation */
+               rte_crypto_op_attach_sym_session(op, session);
+       }
+       while (loop < 1) {
+               if ((options.cipher_xform.cipher.op ==
+                               RTE_CRYPTO_CIPHER_OP_ENCRYPT)
+                       || (options.auth_xform.auth.op ==
+                               RTE_CRYPTO_AUTH_OP_GENERATE)
+                       || (options.aead_xform.aead.op ==
+                               RTE_CRYPTO_AEAD_OP_ENCRYPT)) {
+                       char *ch;
+                       for (int j = 0; j < BURST_SIZE; j++) {
+                               ch  = rte_pktmbuf_mtod(mbufs[j], char *);
+                               for (int k = 0; k < pt_length; k++)
+                                       memset(ch+k, pt[k], sizeof(char));
+                       }
+                       printf("I/P =\n");
+                       ch  = rte_pktmbuf_mtod(mbufs[0], char *);
+                       for (int k = 1;
+                               k <= crypto_ops[0]->sym->m_src->data_len;
+                                       k++) {
+                               printf("%02x", ch[k-1] & 0xff);
+                               if (k%16 == 0)
+                                       printf("\n");
+                       }
+                       printf("\n");
+               }
+               if ((options.cipher_xform.cipher.op ==
+                                       RTE_CRYPTO_CIPHER_OP_DECRYPT)
+                       || (options.auth_xform.auth.op ==
+                               RTE_CRYPTO_AUTH_OP_VERIFY)
+                       || (options.aead_xform.aead.op ==
+                               RTE_CRYPTO_AEAD_OP_DECRYPT)) {
+                       char *ch;
+                       for (int j = 0; j < BURST_SIZE; j++) {
+                               ch  = rte_pktmbuf_mtod(mbufs[j], char *);
+                               rte_memcpy(ch, input_file, flen);
+                       }
+                       printf("I/P =\n");
+                       ch  = rte_pktmbuf_mtod(mbufs[0], char *);
+                       for (int k = 1;
+                               k <= crypto_ops[0]->sym->m_src->data_len; k++) {
+                               printf("%02x", ch[k-1] & 0xff);
+                               if (k%16 == 0)
+                                       printf("\n");
+                       }
+                       printf("\n");
+               }
+               /* Enqueue the crypto operations in the crypto device. */
+               uint16_t num_enqueued_ops =
+                               rte_cryptodev_enqueue_burst(cdev_id,
+                                               0, crypto_ops, BURST_SIZE);
+               if (num_enqueued_ops == 0) {
+                       printf("continuing\n");
+                       continue;
+               }
+               uint16_t num_dequeued_ops, total_num_dequeued_ops = 0;
+
+               do {
+                       num_dequeued_ops = rte_cryptodev_dequeue_burst(cdev_id,
+                                               0, crypto_ops, BURST_SIZE);
+                       total_num_dequeued_ops += num_dequeued_ops;
+                       /* Check if operation was processed successfully */
+                       for (i = 0; i < num_dequeued_ops; i++) {
+                               if (crypto_ops[i]->status !=
+                                               RTE_CRYPTO_OP_STATUS_SUCCESS) {
+                                       printf("error @ i: %d\n", i);
+                               }
+                       }
+                       printf("%s",
+                               (char *)crypto_ops[0]->sym->m_src->buf_addr);
+                       rte_mempool_put_bulk(crypto_op_pool,
+                                       (void **)crypto_ops, num_dequeued_ops);
+               } while (total_num_dequeued_ops < num_enqueued_ops);
+               char *ch;
+               ch  = rte_pktmbuf_mtod(crypto_ops[0]->sym->m_src, char *);
+               printf("O/P =\n");
+               if (options.auth_xform.auth.op == RTE_CRYPTO_AUTH_OP_VERIFY)
+                       log_size = crypto_ops[0]->sym->m_src->data_len-md_size;
+               else
+                       log_size = crypto_ops[0]->sym->m_src->data_len;
+               for (int k = 1; k <= log_size; k++) {
+                       printf("%02x", ch[k-1] & 0xff);
+                       if (k%16 == 0)
+                               printf("\n");
+               }
+               printf("\n");
+               if (options.auth_xform.auth.op ==
+                               RTE_CRYPTO_AUTH_OP_GENERATE) {
+                       if (save_file) {
+                               char *ch;
+                               ch  = rte_pktmbuf_mtod(
+                                       crypto_ops[0]->sym->m_src, char *);
+                               FILE *f = fopen("sha.data", "wb");
+                               fwrite(ch, sizeof(char),
+                                       crypto_ops[0]->sym->m_src->data_len, f);
+                               fclose(f);
+                               printf("\n sha buff:\n");
+                               ch  = rte_pktmbuf_mtod(
+                                       crypto_ops[0]->sym->m_src, char *);
+                               for (int i = 0; i < md_size; i++)
+                                       printf("%02x",
+                                               ch[buffer_size+i] & 0xff);
+                               printf("\n");
+                       }
+       }
+       if (options.cipher_xform.cipher.op == RTE_CRYPTO_CIPHER_OP_ENCRYPT
+               ||  options.aead_xform.aead.op == RTE_CRYPTO_AEAD_OP_ENCRYPT) {
+               if (save_file) {
+                       char *ch;
+                       ch  = rte_pktmbuf_mtod(
+                                       crypto_ops[0]->sym->m_src, char *);
+                       FILE *f = fopen("encoded.data", "wb");
+                       fwrite(ch, sizeof(char),
+                               crypto_ops[0]->sym->m_src->data_len, f);
+                       fclose(f);
+               }
+       }
+       loop++;
+       }
+       return 0;
+}
-- 
2.17.1

Reply via email to