-.. BSD LICENSE
- Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
-
- 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 Intel Corporation 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.
-
+.. SPDX-License-Identifier: BSD-3-Clause
+ Copyright(c) 2016-2017 Intel Corporation.
Cryptography Device Library
===========================
.. code-block:: console
- --vdev 'cryptodev_aesni_mb_pmd0,max_nb_queue_pairs=2,max_nb_sessions=1024,socket_id=0'
+ --vdev 'crypto_aesni_mb0,max_nb_queue_pairs=2,max_nb_sessions=1024,socket_id=0'
+
+.. Note::
+
+ * If DPDK application requires multiple software crypto PMD devices then required
+ number of ``--vdev`` with appropriate libraries are to be added.
+
+ * An Application with crypto PMD instaces sharing the same library requires unique ID.
+
+ Example: ``--vdev 'crypto_aesni_mb0' --vdev 'crypto_aesni_mb1'``
Our using the rte_vdev_init API within the application code.
.. code-block:: c
- rte_vdev_init("cryptodev_aesni_mb_pmd",
+ rte_vdev_init("crypto_aesni_mb",
"max_nb_queue_pairs=2,max_nb_sessions=1024,socket_id=0")
All virtual Crypto devices support the following initialization parameters:
enqueue call.
+Private data
+~~~~~~~~~~~~
+For session-based operations, the set and get API provides a mechanism for an
+application to store and retrieve the private data information stored along with
+the crypto session.
+
+For example, suppose an application is submitting a crypto operation with a session
+associated and wants to indicate private data information which is required to be
+used after completion of the crypto operation. In this case, the application can use
+the set API to set the private data and retrieve it using get API.
+
+.. code-block:: c
+
+ int rte_cryptodev_sym_session_set_private_data(
+ struct rte_cryptodev_sym_session *sess, void *data, uint16_t size);
+
+ void * rte_cryptodev_sym_session_get_private_data(
+ struct rte_cryptodev_sym_session *sess);
+
+
+For session-less mode, the private data information can be placed along with the
+``struct rte_crypto_op``. The ``rte_crypto_op::private_data_offset`` indicates the
+start of private data information. The offset is counted from the start of the
+rte_crypto_op including other crypto information such as the IVs (since there can
+be an IV also for authentication).
+
+
Enqueue / Dequeue Burst APIs
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Session and Session Management
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sessions are used in symmetric cryptographic processing to store the immutable
data defined in a cryptographic transform which is used in the operation
struct {
uint8_t *data;
- phys_addr_t phys_addr;
+ rte_iova_t phys_addr;
} digest; /**< Digest parameters */
struct {
uint8_t *data;
- phys_addr_t phys_addr;
+ rte_iova_t phys_addr;
} aad;
/**< Additional authentication parameters */
} aead;
struct {
uint8_t *data;
- phys_addr_t phys_addr;
+ rte_iova_t phys_addr;
} digest; /**< Digest parameters */
} auth;
};
};
};
+Sample code
+-----------
+
+There are various sample applications that show how to use the cryptodev library,
+such as the L2fwd with Crypto sample application (L2fwd-crypto) and
+the IPSec Security Gateway application (ipsec-secgw).
+
+While these applications demonstrate how an application can be created to perform
+generic crypto operation, the required complexity hides the basic steps of
+how to use the cryptodev APIs.
+
+The following sample code shows the basic steps to encrypt several buffers
+with AES-CBC (although performing other crypto operations is similar),
+using one of the crypto PMDs available in DPDK.
+
+.. code-block:: c
+
+ /*
+ * Simple example to encrypt several buffers with AES-CBC using
+ * the Cryptodev APIs.
+ */
+
+ #define MAX_SESSIONS 1024
+ #define NUM_MBUFS 1024
+ #define POOL_CACHE_SIZE 128
+ #define BURST_SIZE 32
+ #define BUFFER_SIZE 1024
+ #define AES_CBC_IV_LENGTH 16
+ #define AES_CBC_KEY_LENGTH 16
+ #define IV_OFFSET (sizeof(struct rte_crypto_op) + \
+ sizeof(struct rte_crypto_sym_op))
+
+ struct rte_mempool *mbuf_pool, *crypto_op_pool, *session_pool;
+ unsigned int session_size;
+ int ret;
+
+ /* Initialize EAL. */
+ ret = rte_eal_init(argc, argv);
+ if (ret < 0)
+ rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n");
+
+ uint8_t socket_id = rte_socket_id();
+
+ /* Create the mbuf pool. */
+ mbuf_pool = rte_pktmbuf_pool_create("mbuf_pool",
+ NUM_MBUFS,
+ POOL_CACHE_SIZE,
+ 0,
+ RTE_MBUF_DEFAULT_BUF_SIZE,
+ socket_id);
+ if (mbuf_pool == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n");
+
+ /*
+ * The IV is always placed after the crypto operation,
+ * so some private data is required to be reserved.
+ */
+ unsigned int crypto_op_private_data = AES_CBC_IV_LENGTH;
+
+ /* 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 (crypto_op_pool == NULL)
+ rte_exit(EXIT_FAILURE, "Cannot create crypto op pool\n");
+
+ /* Create the virtual crypto device. */
+ char args[128];
+ const char *crypto_name = "crypto_aesni_mb0";
+ snprintf(args, sizeof(args), "socket_id=%d", socket_id);
+ ret = rte_vdev_init(crypto_name, args);
+ if (ret != 0)
+ rte_exit(EXIT_FAILURE, "Cannot create virtual device");
+
+ uint8_t cdev_id = rte_cryptodev_get_dev_id(crypto_name);
+
+ /* Get private session data size. */
+ session_size = rte_cryptodev_get_private_session_size(cdev_id);
+
+ /*
+ * Create session mempool, with two objects per session,
+ * one for the session header and another one for the
+ * private session data for the crypto device.
+ */
+ session_pool = rte_mempool_create("session_pool",
+ MAX_SESSIONS * 2,
+ session_size,
+ POOL_CACHE_SIZE,
+ 0, NULL, NULL, NULL,
+ NULL, socket_id,
+ 0);
+
+ /* Configure the crypto device. */
+ struct rte_cryptodev_config conf = {
+ .nb_queue_pairs = 1,
+ .socket_id = socket_id
+ };
+ struct rte_cryptodev_qp_conf qp_conf = {
+ .nb_descriptors = 2048
+ };
+
+ if (rte_cryptodev_configure(cdev_id, &conf) < 0)
+ rte_exit(EXIT_FAILURE, "Failed to configure cryptodev %u", cdev_id);
+
+ if (rte_cryptodev_queue_pair_setup(cdev_id, 0, &qp_conf,
+ socket_id, session_pool) < 0)
+ rte_exit(EXIT_FAILURE, "Failed to setup queue pair\n");
+
+ if (rte_cryptodev_start(cdev_id) < 0)
+ rte_exit(EXIT_FAILURE, "Failed to start device\n");
+
+ /* Create the crypto transform. */
+ uint8_t cipher_key[16] = {0};
+ struct rte_crypto_sym_xform cipher_xform = {
+ .next = NULL,
+ .type = RTE_CRYPTO_SYM_XFORM_CIPHER,
+ .cipher = {
+ .op = RTE_CRYPTO_CIPHER_OP_ENCRYPT,
+ .algo = RTE_CRYPTO_CIPHER_AES_CBC,
+ .key = {
+ .data = cipher_key,
+ .length = AES_CBC_KEY_LENGTH
+ },
+ .iv = {
+ .offset = IV_OFFSET,
+ .length = AES_CBC_IV_LENGTH
+ }
+ }
+ };
+
+ /* Create crypto session and initialize it for the crypto device. */
+ struct rte_cryptodev_sym_session *session;
+ session = rte_cryptodev_sym_session_create(session_pool);
+ if (session == NULL)
+ rte_exit(EXIT_FAILURE, "Session could not be created\n");
+
+ if (rte_cryptodev_sym_session_init(cdev_id, session,
+ &cipher_xform, session_pool) < 0)
+ rte_exit(EXIT_FAILURE, "Session could not be initialized "
+ "for the crypto device\n");
+
+ /* Get a burst of crypto operations. */
+ struct rte_crypto_op *crypto_ops[BURST_SIZE];
+ 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");
+
+ /* Get a burst of mbufs. */
+ struct rte_mbuf *mbufs[BURST_SIZE];
+ 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. */
+ unsigned int i;
+ for (i = 0; i < BURST_SIZE; i++) {
+ if (rte_pktmbuf_append(mbufs[i], BUFFER_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];
+ /* Modify bytes of the IV at the end of the crypto operation */
+ uint8_t *iv_ptr = rte_crypto_op_ctod_offset(op, uint8_t *,
+ IV_OFFSET);
+
+ generate_random_bytes(iv_ptr, AES_CBC_IV_LENGTH);
+
+ op->sym->cipher.data.offset = 0;
+ op->sym->cipher.data.length = BUFFER_SIZE;
+
+ /* Attach the crypto session to the operation */
+ rte_crypto_op_attach_sym_session(op, session);
+ }
+
+ /* Enqueue the crypto operations in the crypto device. */
+ uint16_t num_enqueued_ops = rte_cryptodev_enqueue_burst(cdev_id, 0,
+ crypto_ops, BURST_SIZE);
+
+ /*
+ * Dequeue the crypto operations until all the operations
+ * are proccessed in the crypto device.
+ */
+ uint16_t num_dequeued_ops, total_num_dequeued_ops = 0;
+ do {
+ struct rte_crypto_op *dequeued_ops[BURST_SIZE];
+ num_dequeued_ops = rte_cryptodev_dequeue_burst(cdev_id, 0,
+ dequeued_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 (dequeued_ops[i]->status != RTE_CRYPTO_OP_STATUS_SUCCESS)
+ rte_exit(EXIT_FAILURE,
+ "Some operations were not processed correctly");
+ }
+
+ rte_mempool_put_bulk(crypto_op_pool, (void **)dequeued_ops,
+ num_dequeued_ops);
+ } while (total_num_dequeued_ops < num_enqueued_ops);
+
Asymmetric Cryptography
-----------------------