2017-12-19 15:49:01 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2018-07-03 04:37:22 +00:00
|
|
|
* Copyright(c) 2016-2018 Intel Corporation
|
2016-03-10 16:33:12 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <rte_common.h>
|
|
|
|
#include <rte_hexdump.h>
|
|
|
|
#include <rte_cryptodev.h>
|
|
|
|
#include <rte_cryptodev_pmd.h>
|
2017-11-07 06:54:21 +00:00
|
|
|
#include <rte_bus_vdev.h>
|
2016-03-10 16:33:12 +00:00
|
|
|
#include <rte_malloc.h>
|
|
|
|
#include <rte_cpuflags.h>
|
|
|
|
|
|
|
|
#include "rte_snow3g_pmd_private.h"
|
|
|
|
|
2016-06-20 14:44:54 +00:00
|
|
|
#define SNOW3G_IV_LENGTH 16
|
2016-03-10 16:33:12 +00:00
|
|
|
#define SNOW3G_MAX_BURST 8
|
2016-03-10 17:44:10 +00:00
|
|
|
#define BYTE_LEN 8
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-06-30 14:34:21 +00:00
|
|
|
static uint8_t cryptodev_driver_id;
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
/** Get xform chain order. */
|
|
|
|
static enum snow3g_operation
|
|
|
|
snow3g_get_mode(const struct rte_crypto_sym_xform *xform)
|
|
|
|
{
|
|
|
|
if (xform == NULL)
|
|
|
|
return SNOW3G_OP_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
if (xform->next)
|
|
|
|
if (xform->next->next != NULL)
|
|
|
|
return SNOW3G_OP_NOT_SUPPORTED;
|
|
|
|
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
|
|
|
|
if (xform->next == NULL)
|
|
|
|
return SNOW3G_OP_ONLY_AUTH;
|
|
|
|
else if (xform->next->type == RTE_CRYPTO_SYM_XFORM_CIPHER)
|
|
|
|
return SNOW3G_OP_AUTH_CIPHER;
|
|
|
|
else
|
|
|
|
return SNOW3G_OP_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
|
|
|
|
if (xform->next == NULL)
|
|
|
|
return SNOW3G_OP_ONLY_CIPHER;
|
|
|
|
else if (xform->next->type == RTE_CRYPTO_SYM_XFORM_AUTH)
|
|
|
|
return SNOW3G_OP_CIPHER_AUTH;
|
|
|
|
else
|
|
|
|
return SNOW3G_OP_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SNOW3G_OP_NOT_SUPPORTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Parse crypto xform chain and set private session parameters. */
|
|
|
|
int
|
|
|
|
snow3g_set_session_parameters(struct snow3g_session *sess,
|
|
|
|
const struct rte_crypto_sym_xform *xform)
|
|
|
|
{
|
|
|
|
const struct rte_crypto_sym_xform *auth_xform = NULL;
|
|
|
|
const struct rte_crypto_sym_xform *cipher_xform = NULL;
|
2016-09-28 00:31:27 +00:00
|
|
|
enum snow3g_operation mode;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
/* Select Crypto operation - hash then cipher / cipher then hash */
|
|
|
|
mode = snow3g_get_mode(xform);
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case SNOW3G_OP_CIPHER_AUTH:
|
|
|
|
auth_xform = xform->next;
|
|
|
|
|
|
|
|
/* Fall-through */
|
|
|
|
case SNOW3G_OP_ONLY_CIPHER:
|
|
|
|
cipher_xform = xform;
|
|
|
|
break;
|
|
|
|
case SNOW3G_OP_AUTH_CIPHER:
|
|
|
|
cipher_xform = xform->next;
|
|
|
|
/* Fall-through */
|
|
|
|
case SNOW3G_OP_ONLY_AUTH:
|
|
|
|
auth_xform = xform;
|
2016-09-28 00:31:27 +00:00
|
|
|
break;
|
|
|
|
case SNOW3G_OP_NOT_SUPPORTED:
|
|
|
|
default:
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "Unsupported operation chain order parameter");
|
2017-07-25 06:16:50 +00:00
|
|
|
return -ENOTSUP;
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (cipher_xform) {
|
|
|
|
/* Only SNOW 3G UEA2 supported */
|
|
|
|
if (cipher_xform->cipher.algo != RTE_CRYPTO_CIPHER_SNOW3G_UEA2)
|
2017-07-25 06:16:50 +00:00
|
|
|
return -ENOTSUP;
|
2017-07-02 05:41:14 +00:00
|
|
|
|
|
|
|
if (cipher_xform->cipher.iv.length != SNOW3G_IV_LENGTH) {
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "Wrong IV length");
|
2017-07-02 05:41:14 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
2017-07-02 05:41:16 +00:00
|
|
|
sess->cipher_iv_offset = cipher_xform->cipher.iv.offset;
|
2017-07-02 05:41:14 +00:00
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
/* Initialize key */
|
2017-02-07 22:49:58 +00:00
|
|
|
sso_snow3g_init_key_sched(cipher_xform->cipher.key.data,
|
2016-03-10 16:33:12 +00:00
|
|
|
&sess->pKeySched_cipher);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (auth_xform) {
|
|
|
|
/* Only SNOW 3G UIA2 supported */
|
|
|
|
if (auth_xform->auth.algo != RTE_CRYPTO_AUTH_SNOW3G_UIA2)
|
2017-07-25 06:16:50 +00:00
|
|
|
return -ENOTSUP;
|
2017-07-02 05:41:18 +00:00
|
|
|
|
|
|
|
if (auth_xform->auth.digest_length != SNOW3G_DIGEST_LENGTH) {
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "Wrong digest length");
|
2017-07-02 05:41:18 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
sess->auth_op = auth_xform->auth.op;
|
2017-07-02 05:41:16 +00:00
|
|
|
|
|
|
|
if (auth_xform->auth.iv.length != SNOW3G_IV_LENGTH) {
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "Wrong IV length");
|
2017-07-02 05:41:16 +00:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
sess->auth_iv_offset = auth_xform->auth.iv.offset;
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
/* Initialize key */
|
2017-02-07 22:49:58 +00:00
|
|
|
sso_snow3g_init_key_sched(auth_xform->auth.key.data,
|
2016-03-10 16:33:12 +00:00
|
|
|
&sess->pKeySched_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sess->op = mode;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Get SNOW 3G session. */
|
|
|
|
static struct snow3g_session *
|
|
|
|
snow3g_get_session(struct snow3g_qp *qp, struct rte_crypto_op *op)
|
|
|
|
{
|
2017-07-05 05:26:17 +00:00
|
|
|
struct snow3g_session *sess = NULL;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-07-02 05:41:02 +00:00
|
|
|
if (op->sess_type == RTE_CRYPTO_OP_WITH_SESSION) {
|
2017-07-05 05:26:17 +00:00
|
|
|
if (likely(op->sym->session != NULL))
|
|
|
|
sess = (struct snow3g_session *)
|
2018-07-05 02:08:04 +00:00
|
|
|
get_sym_session_private_data(
|
2017-07-05 05:26:17 +00:00
|
|
|
op->sym->session,
|
|
|
|
cryptodev_driver_id);
|
|
|
|
} else {
|
|
|
|
void *_sess = NULL;
|
|
|
|
void *_sess_private_data = NULL;
|
|
|
|
|
|
|
|
if (rte_mempool_get(qp->sess_mp, (void **)&_sess))
|
|
|
|
return NULL;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2019-01-10 14:50:11 +00:00
|
|
|
if (rte_mempool_get(qp->sess_mp_priv,
|
|
|
|
(void **)&_sess_private_data))
|
2016-03-10 16:33:12 +00:00
|
|
|
return NULL;
|
|
|
|
|
2017-07-05 05:26:17 +00:00
|
|
|
sess = (struct snow3g_session *)_sess_private_data;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
if (unlikely(snow3g_set_session_parameters(sess,
|
2017-07-05 05:26:17 +00:00
|
|
|
op->sym->xform) != 0)) {
|
|
|
|
rte_mempool_put(qp->sess_mp, _sess);
|
2019-01-10 14:50:11 +00:00
|
|
|
rte_mempool_put(qp->sess_mp_priv, _sess_private_data);
|
2017-07-05 05:26:17 +00:00
|
|
|
sess = NULL;
|
|
|
|
}
|
|
|
|
op->sym->session = (struct rte_cryptodev_sym_session *)_sess;
|
2018-07-05 02:08:04 +00:00
|
|
|
set_sym_session_private_data(op->sym->session,
|
|
|
|
cryptodev_driver_id, _sess_private_data);
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
2017-07-05 05:26:17 +00:00
|
|
|
if (unlikely(sess == NULL))
|
|
|
|
op->status = RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
|
|
|
|
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
return sess;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Encrypt/decrypt mbufs with same cipher key. */
|
|
|
|
static uint8_t
|
|
|
|
process_snow3g_cipher_op(struct rte_crypto_op **ops,
|
|
|
|
struct snow3g_session *session,
|
|
|
|
uint8_t num_ops)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
uint8_t processed_ops = 0;
|
|
|
|
uint8_t *src[SNOW3G_MAX_BURST], *dst[SNOW3G_MAX_BURST];
|
2017-07-02 05:41:13 +00:00
|
|
|
uint8_t *iv[SNOW3G_MAX_BURST];
|
2016-03-10 16:33:12 +00:00
|
|
|
uint32_t num_bytes[SNOW3G_MAX_BURST];
|
|
|
|
|
|
|
|
for (i = 0; i < num_ops; i++) {
|
|
|
|
src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
|
2016-03-10 17:44:10 +00:00
|
|
|
(ops[i]->sym->cipher.data.offset >> 3);
|
2016-03-10 16:33:12 +00:00
|
|
|
dst[i] = ops[i]->sym->m_dst ?
|
2016-03-10 17:44:10 +00:00
|
|
|
rte_pktmbuf_mtod(ops[i]->sym->m_dst, uint8_t *) +
|
|
|
|
(ops[i]->sym->cipher.data.offset >> 3) :
|
|
|
|
rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
|
|
|
|
(ops[i]->sym->cipher.data.offset >> 3);
|
2017-07-02 05:41:13 +00:00
|
|
|
iv[i] = rte_crypto_op_ctod_offset(ops[i], uint8_t *,
|
2017-07-02 05:41:16 +00:00
|
|
|
session->cipher_iv_offset);
|
2016-03-10 17:44:10 +00:00
|
|
|
num_bytes[i] = ops[i]->sym->cipher.data.length >> 3;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
processed_ops++;
|
|
|
|
}
|
|
|
|
|
2017-07-02 05:41:13 +00:00
|
|
|
sso_snow3g_f8_n_buffer(&session->pKeySched_cipher, iv, src, dst,
|
2016-03-10 16:33:12 +00:00
|
|
|
num_bytes, processed_ops);
|
|
|
|
|
|
|
|
return processed_ops;
|
|
|
|
}
|
|
|
|
|
2016-06-20 14:44:55 +00:00
|
|
|
/** Encrypt/decrypt mbuf (bit level function). */
|
|
|
|
static uint8_t
|
|
|
|
process_snow3g_cipher_op_bit(struct rte_crypto_op *op,
|
|
|
|
struct snow3g_session *session)
|
|
|
|
{
|
|
|
|
uint8_t *src, *dst;
|
2017-07-02 05:41:13 +00:00
|
|
|
uint8_t *iv;
|
2016-06-20 14:44:55 +00:00
|
|
|
uint32_t length_in_bits, offset_in_bits;
|
|
|
|
|
|
|
|
offset_in_bits = op->sym->cipher.data.offset;
|
|
|
|
src = rte_pktmbuf_mtod(op->sym->m_src, uint8_t *);
|
|
|
|
if (op->sym->m_dst == NULL) {
|
|
|
|
op->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "bit-level in-place not supported\n");
|
2016-06-20 14:44:55 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
dst = rte_pktmbuf_mtod(op->sym->m_dst, uint8_t *);
|
2017-07-02 05:41:13 +00:00
|
|
|
iv = rte_crypto_op_ctod_offset(op, uint8_t *,
|
2017-07-02 05:41:16 +00:00
|
|
|
session->cipher_iv_offset);
|
2016-06-20 14:44:55 +00:00
|
|
|
length_in_bits = op->sym->cipher.data.length;
|
|
|
|
|
2017-07-02 05:41:13 +00:00
|
|
|
sso_snow3g_f8_1_buffer_bit(&session->pKeySched_cipher, iv,
|
2016-06-20 14:44:55 +00:00
|
|
|
src, dst, length_in_bits, offset_in_bits);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
/** Generate/verify hash from mbufs with same hash key. */
|
|
|
|
static int
|
2017-09-05 02:20:04 +00:00
|
|
|
process_snow3g_hash_op(struct snow3g_qp *qp, struct rte_crypto_op **ops,
|
2016-03-10 16:33:12 +00:00
|
|
|
struct snow3g_session *session,
|
|
|
|
uint8_t num_ops)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
uint8_t processed_ops = 0;
|
|
|
|
uint8_t *src, *dst;
|
|
|
|
uint32_t length_in_bits;
|
2017-07-02 05:41:16 +00:00
|
|
|
uint8_t *iv;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
for (i = 0; i < num_ops; i++) {
|
2016-06-20 14:44:55 +00:00
|
|
|
/* Data must be byte aligned */
|
|
|
|
if ((ops[i]->sym->auth.data.offset % BYTE_LEN) != 0) {
|
2016-03-10 17:44:10 +00:00
|
|
|
ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "Offset");
|
2016-03-10 17:44:10 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
length_in_bits = ops[i]->sym->auth.data.length;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
src = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
|
2016-03-10 17:44:10 +00:00
|
|
|
(ops[i]->sym->auth.data.offset >> 3);
|
2017-07-02 05:41:16 +00:00
|
|
|
iv = rte_crypto_op_ctod_offset(ops[i], uint8_t *,
|
|
|
|
session->auth_iv_offset);
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
if (session->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
|
2017-09-05 02:20:04 +00:00
|
|
|
dst = qp->temp_digest;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
sso_snow3g_f9_1_buffer(&session->pKeySched_hash,
|
2017-07-02 05:41:16 +00:00
|
|
|
iv, src,
|
2016-03-10 16:33:12 +00:00
|
|
|
length_in_bits, dst);
|
|
|
|
/* Verify digest. */
|
|
|
|
if (memcmp(dst, ops[i]->sym->auth.digest.data,
|
2017-07-02 05:41:18 +00:00
|
|
|
SNOW3G_DIGEST_LENGTH) != 0)
|
2016-03-10 16:33:12 +00:00
|
|
|
ops[i]->status = RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
|
|
|
|
} else {
|
|
|
|
dst = ops[i]->sym->auth.digest.data;
|
|
|
|
|
|
|
|
sso_snow3g_f9_1_buffer(&session->pKeySched_hash,
|
2017-07-02 05:41:16 +00:00
|
|
|
iv, src,
|
2016-03-10 16:33:12 +00:00
|
|
|
length_in_bits, dst);
|
|
|
|
}
|
|
|
|
processed_ops++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return processed_ops;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Process a batch of crypto ops which shares the same session. */
|
|
|
|
static int
|
|
|
|
process_ops(struct rte_crypto_op **ops, struct snow3g_session *session,
|
2016-06-20 14:44:55 +00:00
|
|
|
struct snow3g_qp *qp, uint8_t num_ops,
|
|
|
|
uint16_t *accumulated_enqueued_ops)
|
2016-03-10 16:33:12 +00:00
|
|
|
{
|
|
|
|
unsigned i;
|
2016-06-20 14:44:55 +00:00
|
|
|
unsigned enqueued_ops, processed_ops;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-01-13 15:23:15 +00:00
|
|
|
#ifdef RTE_LIBRTE_PMD_SNOW3G_DEBUG
|
|
|
|
for (i = 0; i < num_ops; i++) {
|
|
|
|
if (!rte_pktmbuf_is_contiguous(ops[i]->sym->m_src) ||
|
|
|
|
(ops[i]->sym->m_dst != NULL &&
|
|
|
|
!rte_pktmbuf_is_contiguous(
|
|
|
|
ops[i]->sym->m_dst))) {
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "PMD supports only contiguous mbufs, "
|
2017-01-13 15:23:15 +00:00
|
|
|
"op (%p) provides noncontiguous mbuf as "
|
|
|
|
"source/destination buffer.\n", ops[i]);
|
|
|
|
ops[i]->status = RTE_CRYPTO_OP_STATUS_INVALID_ARGS;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
switch (session->op) {
|
|
|
|
case SNOW3G_OP_ONLY_CIPHER:
|
|
|
|
processed_ops = process_snow3g_cipher_op(ops,
|
|
|
|
session, num_ops);
|
|
|
|
break;
|
|
|
|
case SNOW3G_OP_ONLY_AUTH:
|
2017-09-05 02:20:04 +00:00
|
|
|
processed_ops = process_snow3g_hash_op(qp, ops, session,
|
2016-03-10 16:33:12 +00:00
|
|
|
num_ops);
|
|
|
|
break;
|
|
|
|
case SNOW3G_OP_CIPHER_AUTH:
|
|
|
|
processed_ops = process_snow3g_cipher_op(ops, session,
|
|
|
|
num_ops);
|
2017-09-05 02:20:04 +00:00
|
|
|
process_snow3g_hash_op(qp, ops, session, processed_ops);
|
2016-03-10 16:33:12 +00:00
|
|
|
break;
|
|
|
|
case SNOW3G_OP_AUTH_CIPHER:
|
2017-09-05 02:20:04 +00:00
|
|
|
processed_ops = process_snow3g_hash_op(qp, ops, session,
|
2016-03-10 16:33:12 +00:00
|
|
|
num_ops);
|
|
|
|
process_snow3g_cipher_op(ops, session, processed_ops);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Operation not supported. */
|
|
|
|
processed_ops = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < num_ops; i++) {
|
|
|
|
/*
|
|
|
|
* If there was no error/authentication failure,
|
|
|
|
* change status to successful.
|
|
|
|
*/
|
|
|
|
if (ops[i]->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
|
|
|
|
ops[i]->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
|
|
|
|
/* Free session if a session-less crypto op. */
|
2017-07-02 05:41:02 +00:00
|
|
|
if (ops[i]->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
|
2017-07-05 05:26:17 +00:00
|
|
|
memset(session, 0, sizeof(struct snow3g_session));
|
|
|
|
memset(ops[i]->sym->session, 0,
|
2019-01-10 14:50:18 +00:00
|
|
|
rte_cryptodev_sym_get_existing_header_session_size(
|
|
|
|
ops[i]->sym->session));
|
2019-01-10 14:50:11 +00:00
|
|
|
rte_mempool_put(qp->sess_mp_priv, session);
|
2016-03-10 16:33:12 +00:00
|
|
|
rte_mempool_put(qp->sess_mp, ops[i]->sym->session);
|
|
|
|
ops[i]->sym->session = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-20 14:44:55 +00:00
|
|
|
enqueued_ops = rte_ring_enqueue_burst(qp->processed_ops,
|
2017-03-29 15:21:24 +00:00
|
|
|
(void **)ops, processed_ops, NULL);
|
2016-06-20 14:44:55 +00:00
|
|
|
qp->qp_stats.enqueued_count += enqueued_ops;
|
|
|
|
*accumulated_enqueued_ops += enqueued_ops;
|
|
|
|
|
|
|
|
return enqueued_ops;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Process a crypto op with length/offset in bits. */
|
|
|
|
static int
|
|
|
|
process_op_bit(struct rte_crypto_op *op, struct snow3g_session *session,
|
|
|
|
struct snow3g_qp *qp, uint16_t *accumulated_enqueued_ops)
|
|
|
|
{
|
|
|
|
unsigned enqueued_op, processed_op;
|
|
|
|
|
|
|
|
switch (session->op) {
|
|
|
|
case SNOW3G_OP_ONLY_CIPHER:
|
|
|
|
processed_op = process_snow3g_cipher_op_bit(op,
|
|
|
|
session);
|
|
|
|
break;
|
|
|
|
case SNOW3G_OP_ONLY_AUTH:
|
2017-09-05 02:20:04 +00:00
|
|
|
processed_op = process_snow3g_hash_op(qp, &op, session, 1);
|
2016-06-20 14:44:55 +00:00
|
|
|
break;
|
|
|
|
case SNOW3G_OP_CIPHER_AUTH:
|
|
|
|
processed_op = process_snow3g_cipher_op_bit(op, session);
|
|
|
|
if (processed_op == 1)
|
2017-09-05 02:20:04 +00:00
|
|
|
process_snow3g_hash_op(qp, &op, session, 1);
|
2016-06-20 14:44:55 +00:00
|
|
|
break;
|
|
|
|
case SNOW3G_OP_AUTH_CIPHER:
|
2017-09-05 02:20:04 +00:00
|
|
|
processed_op = process_snow3g_hash_op(qp, &op, session, 1);
|
2016-06-20 14:44:55 +00:00
|
|
|
if (processed_op == 1)
|
|
|
|
process_snow3g_cipher_op_bit(op, session);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
/* Operation not supported. */
|
|
|
|
processed_op = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there was no error/authentication failure,
|
|
|
|
* change status to successful.
|
|
|
|
*/
|
|
|
|
if (op->status == RTE_CRYPTO_OP_STATUS_NOT_PROCESSED)
|
|
|
|
op->status = RTE_CRYPTO_OP_STATUS_SUCCESS;
|
|
|
|
|
|
|
|
/* Free session if a session-less crypto op. */
|
2017-07-02 05:41:02 +00:00
|
|
|
if (op->sess_type == RTE_CRYPTO_OP_SESSIONLESS) {
|
2017-07-05 05:26:17 +00:00
|
|
|
memset(op->sym->session, 0, sizeof(struct snow3g_session));
|
|
|
|
rte_cryptodev_sym_session_free(op->sym->session);
|
2016-06-20 14:44:55 +00:00
|
|
|
op->sym->session = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
enqueued_op = rte_ring_enqueue_burst(qp->processed_ops,
|
2017-03-29 15:21:24 +00:00
|
|
|
(void **)&op, processed_op, NULL);
|
2016-06-20 14:44:55 +00:00
|
|
|
qp->qp_stats.enqueued_count += enqueued_op;
|
|
|
|
*accumulated_enqueued_ops += enqueued_op;
|
|
|
|
|
|
|
|
return enqueued_op;
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t
|
|
|
|
snow3g_pmd_enqueue_burst(void *queue_pair, struct rte_crypto_op **ops,
|
|
|
|
uint16_t nb_ops)
|
|
|
|
{
|
|
|
|
struct rte_crypto_op *c_ops[SNOW3G_MAX_BURST];
|
|
|
|
struct rte_crypto_op *curr_c_op;
|
|
|
|
|
|
|
|
struct snow3g_session *prev_sess = NULL, *curr_sess = NULL;
|
|
|
|
struct snow3g_qp *qp = queue_pair;
|
2016-06-20 14:44:55 +00:00
|
|
|
unsigned i;
|
2016-03-10 16:33:12 +00:00
|
|
|
uint8_t burst_size = 0;
|
|
|
|
uint16_t enqueued_ops = 0;
|
|
|
|
uint8_t processed_ops;
|
|
|
|
|
|
|
|
for (i = 0; i < nb_ops; i++) {
|
|
|
|
curr_c_op = ops[i];
|
|
|
|
|
|
|
|
/* Set status as enqueued (not processed yet) by default. */
|
|
|
|
curr_c_op->status = RTE_CRYPTO_OP_STATUS_NOT_PROCESSED;
|
|
|
|
|
|
|
|
curr_sess = snow3g_get_session(qp, curr_c_op);
|
|
|
|
if (unlikely(curr_sess == NULL ||
|
|
|
|
curr_sess->op == SNOW3G_OP_NOT_SUPPORTED)) {
|
|
|
|
curr_c_op->status =
|
|
|
|
RTE_CRYPTO_OP_STATUS_INVALID_SESSION;
|
2016-06-20 14:44:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If length/offset is at bit-level, process this buffer alone. */
|
|
|
|
if (((curr_c_op->sym->cipher.data.length % BYTE_LEN) != 0)
|
|
|
|
|| ((curr_c_op->sym->cipher.data.offset
|
|
|
|
% BYTE_LEN) != 0)) {
|
|
|
|
/* Process the ops of the previous session. */
|
|
|
|
if (prev_sess != NULL) {
|
|
|
|
processed_ops = process_ops(c_ops, prev_sess,
|
|
|
|
qp, burst_size, &enqueued_ops);
|
|
|
|
if (processed_ops < burst_size) {
|
|
|
|
burst_size = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
burst_size = 0;
|
|
|
|
prev_sess = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
processed_ops = process_op_bit(curr_c_op, curr_sess,
|
|
|
|
qp, &enqueued_ops);
|
|
|
|
if (processed_ops != 1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
continue;
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Batch ops that share the same session. */
|
|
|
|
if (prev_sess == NULL) {
|
|
|
|
prev_sess = curr_sess;
|
|
|
|
c_ops[burst_size++] = curr_c_op;
|
|
|
|
} else if (curr_sess == prev_sess) {
|
|
|
|
c_ops[burst_size++] = curr_c_op;
|
|
|
|
/*
|
|
|
|
* When there are enough ops to process in a batch,
|
|
|
|
* process them, and start a new batch.
|
|
|
|
*/
|
|
|
|
if (burst_size == SNOW3G_MAX_BURST) {
|
2016-06-20 14:44:55 +00:00
|
|
|
processed_ops = process_ops(c_ops, prev_sess,
|
|
|
|
qp, burst_size, &enqueued_ops);
|
|
|
|
if (processed_ops < burst_size) {
|
|
|
|
burst_size = 0;
|
|
|
|
break;
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 14:44:55 +00:00
|
|
|
burst_size = 0;
|
2016-03-10 16:33:12 +00:00
|
|
|
prev_sess = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Different session, process the ops
|
|
|
|
* of the previous session.
|
|
|
|
*/
|
2016-06-20 14:44:55 +00:00
|
|
|
processed_ops = process_ops(c_ops, prev_sess,
|
|
|
|
qp, burst_size, &enqueued_ops);
|
|
|
|
if (processed_ops < burst_size) {
|
|
|
|
burst_size = 0;
|
|
|
|
break;
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 14:44:55 +00:00
|
|
|
burst_size = 0;
|
2016-03-10 16:33:12 +00:00
|
|
|
prev_sess = curr_sess;
|
2016-06-20 14:44:55 +00:00
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
c_ops[burst_size++] = curr_c_op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (burst_size != 0) {
|
|
|
|
/* Process the crypto ops of the last session. */
|
2016-06-20 14:44:55 +00:00
|
|
|
processed_ops = process_ops(c_ops, prev_sess,
|
|
|
|
qp, burst_size, &enqueued_ops);
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
2016-06-20 14:44:55 +00:00
|
|
|
qp->qp_stats.enqueue_err_count += nb_ops - enqueued_ops;
|
2016-03-10 16:33:12 +00:00
|
|
|
return enqueued_ops;
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint16_t
|
|
|
|
snow3g_pmd_dequeue_burst(void *queue_pair,
|
|
|
|
struct rte_crypto_op **c_ops, uint16_t nb_ops)
|
|
|
|
{
|
|
|
|
struct snow3g_qp *qp = queue_pair;
|
|
|
|
|
|
|
|
unsigned nb_dequeued;
|
|
|
|
|
|
|
|
nb_dequeued = rte_ring_dequeue_burst(qp->processed_ops,
|
2017-03-29 15:21:25 +00:00
|
|
|
(void **)c_ops, nb_ops, NULL);
|
2016-03-10 16:33:12 +00:00
|
|
|
qp->qp_stats.dequeued_count += nb_dequeued;
|
|
|
|
|
|
|
|
return nb_dequeued;
|
|
|
|
}
|
|
|
|
|
2017-04-11 15:44:13 +00:00
|
|
|
static int cryptodev_snow3g_remove(struct rte_vdev_device *vdev);
|
2016-03-10 16:33:12 +00:00
|
|
|
|
|
|
|
static int
|
2017-04-18 14:34:20 +00:00
|
|
|
cryptodev_snow3g_create(const char *name,
|
|
|
|
struct rte_vdev_device *vdev,
|
2017-10-25 12:00:35 +00:00
|
|
|
struct rte_cryptodev_pmd_init_params *init_params)
|
2016-03-10 16:33:12 +00:00
|
|
|
{
|
|
|
|
struct rte_cryptodev *dev;
|
|
|
|
struct snow3g_private *internals;
|
2017-06-20 15:23:06 +00:00
|
|
|
uint64_t cpu_flags = RTE_CRYPTODEV_FF_CPU_SSE;
|
2016-06-20 14:44:56 +00:00
|
|
|
|
2017-10-25 12:00:35 +00:00
|
|
|
dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
|
2016-03-10 16:33:12 +00:00
|
|
|
if (dev == NULL) {
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "failed to create cryptodev vdev");
|
2016-03-10 16:33:12 +00:00
|
|
|
goto init_error;
|
|
|
|
}
|
|
|
|
|
2017-06-30 14:34:21 +00:00
|
|
|
dev->driver_id = cryptodev_driver_id;
|
2016-03-10 16:33:12 +00:00
|
|
|
dev->dev_ops = rte_snow3g_pmd_ops;
|
|
|
|
|
|
|
|
/* Register RX/TX burst functions for data path. */
|
|
|
|
dev->dequeue_burst = snow3g_pmd_dequeue_burst;
|
|
|
|
dev->enqueue_burst = snow3g_pmd_enqueue_burst;
|
|
|
|
|
2016-03-11 01:36:54 +00:00
|
|
|
dev->feature_flags = RTE_CRYPTODEV_FF_SYMMETRIC_CRYPTO |
|
2016-06-20 14:44:56 +00:00
|
|
|
RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
|
|
|
|
cpu_flags;
|
2016-03-11 01:36:54 +00:00
|
|
|
|
2016-03-10 16:33:12 +00:00
|
|
|
internals = dev->data->dev_private;
|
|
|
|
|
|
|
|
internals->max_nb_queue_pairs = init_params->max_nb_queue_pairs;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
init_error:
|
2018-07-03 04:37:22 +00:00
|
|
|
SNOW3G_LOG(ERR, "driver %s: cryptodev_snow3g_create failed",
|
cryptodev: add user defined name for vdev
This patch adds a user defined name initializing parameter to cryptodev
library.
Originally, for software cryptodev PMD, the vdev name parameter is
treated as the driver identifier, and will create an unique name for each
device automatically, which is not necessarily as same as the vdev
parameter.
This patch allows the user to either create a unique name for his software
cryptodev, or by default, let the system creates a unique one. This should
help the user managing the created cryptodevs easily.
Examples:
CLI command fragment 1: --vdev "crypto_aesni_gcm_pmd"
The above command will result in creating a AESNI-GCM PMD with name of
"crypto_aesni_gcm_X", where postfix X is the number assigned by the system,
starting from 0. This fragment can be placed in the same CLI command
multiple times, resulting the postfixs incremented by one for each new
device.
CLI command fragment 2: --vdev "crypto_aesni_gcm_pmd,name=gcm1"
The above command will result in creating a AESNI-GCM PMD with name of
"gcm1". This fragment can be placed in the same CLI command multiple
times, as long as each having a unique name value.
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Declan Doherty <declan.doherty@intel.com>
2017-01-16 14:14:54 +00:00
|
|
|
init_params->name);
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-04-11 15:44:13 +00:00
|
|
|
cryptodev_snow3g_remove(vdev);
|
2016-03-10 16:33:12 +00:00
|
|
|
return -EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-04-11 15:44:13 +00:00
|
|
|
cryptodev_snow3g_probe(struct rte_vdev_device *vdev)
|
2016-03-10 16:33:12 +00:00
|
|
|
{
|
2017-10-25 12:00:35 +00:00
|
|
|
struct rte_cryptodev_pmd_init_params init_params = {
|
|
|
|
"",
|
|
|
|
sizeof(struct snow3g_private),
|
cryptodev: add user defined name for vdev
This patch adds a user defined name initializing parameter to cryptodev
library.
Originally, for software cryptodev PMD, the vdev name parameter is
treated as the driver identifier, and will create an unique name for each
device automatically, which is not necessarily as same as the vdev
parameter.
This patch allows the user to either create a unique name for his software
cryptodev, or by default, let the system creates a unique one. This should
help the user managing the created cryptodevs easily.
Examples:
CLI command fragment 1: --vdev "crypto_aesni_gcm_pmd"
The above command will result in creating a AESNI-GCM PMD with name of
"crypto_aesni_gcm_X", where postfix X is the number assigned by the system,
starting from 0. This fragment can be placed in the same CLI command
multiple times, resulting the postfixs incremented by one for each new
device.
CLI command fragment 2: --vdev "crypto_aesni_gcm_pmd,name=gcm1"
The above command will result in creating a AESNI-GCM PMD with name of
"gcm1". This fragment can be placed in the same CLI command multiple
times, as long as each having a unique name value.
Signed-off-by: Fan Zhang <roy.fan.zhang@intel.com>
Acked-by: Declan Doherty <declan.doherty@intel.com>
2017-01-16 14:14:54 +00:00
|
|
|
rte_socket_id(),
|
2018-07-05 02:07:58 +00:00
|
|
|
RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
|
2016-03-10 16:33:12 +00:00
|
|
|
};
|
2017-04-11 15:44:13 +00:00
|
|
|
const char *name;
|
|
|
|
const char *input_args;
|
|
|
|
|
|
|
|
name = rte_vdev_device_name(vdev);
|
2017-04-18 14:34:19 +00:00
|
|
|
if (name == NULL)
|
|
|
|
return -EINVAL;
|
2017-04-11 15:44:13 +00:00
|
|
|
input_args = rte_vdev_device_args(vdev);
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-10-25 12:00:35 +00:00
|
|
|
rte_cryptodev_pmd_parse_input_args(&init_params, input_args);
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-04-18 14:34:20 +00:00
|
|
|
return cryptodev_snow3g_create(name, vdev, &init_params);
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2017-04-11 15:44:13 +00:00
|
|
|
cryptodev_snow3g_remove(struct rte_vdev_device *vdev)
|
2016-03-10 16:33:12 +00:00
|
|
|
{
|
2017-10-25 12:00:35 +00:00
|
|
|
struct rte_cryptodev *cryptodev;
|
2017-04-11 15:44:13 +00:00
|
|
|
const char *name;
|
|
|
|
|
|
|
|
name = rte_vdev_device_name(vdev);
|
2016-03-10 16:33:12 +00:00
|
|
|
if (name == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2017-10-25 12:00:35 +00:00
|
|
|
cryptodev = rte_cryptodev_pmd_get_named_dev(name);
|
|
|
|
if (cryptodev == NULL)
|
|
|
|
return -ENODEV;
|
2016-03-10 16:33:12 +00:00
|
|
|
|
2017-10-25 12:00:35 +00:00
|
|
|
return rte_cryptodev_pmd_destroy(cryptodev);
|
2016-03-10 16:33:12 +00:00
|
|
|
}
|
|
|
|
|
2016-09-20 12:41:29 +00:00
|
|
|
static struct rte_vdev_driver cryptodev_snow3g_pmd_drv = {
|
2016-10-06 13:54:03 +00:00
|
|
|
.probe = cryptodev_snow3g_probe,
|
|
|
|
.remove = cryptodev_snow3g_remove
|
2016-03-10 16:33:12 +00:00
|
|
|
};
|
|
|
|
|
2017-08-16 02:41:51 +00:00
|
|
|
static struct cryptodev_driver snow3g_crypto_drv;
|
|
|
|
|
2016-10-10 05:43:15 +00:00
|
|
|
RTE_PMD_REGISTER_VDEV(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd_drv);
|
2016-10-24 16:22:23 +00:00
|
|
|
RTE_PMD_REGISTER_ALIAS(CRYPTODEV_NAME_SNOW3G_PMD, cryptodev_snow3g_pmd);
|
2016-10-10 05:43:15 +00:00
|
|
|
RTE_PMD_REGISTER_PARAM_STRING(CRYPTODEV_NAME_SNOW3G_PMD,
|
2016-07-09 01:06:12 +00:00
|
|
|
"max_nb_queue_pairs=<int> "
|
|
|
|
"socket_id=<int>");
|
2018-03-09 17:44:38 +00:00
|
|
|
RTE_PMD_REGISTER_CRYPTO_DRIVER(snow3g_crypto_drv,
|
|
|
|
cryptodev_snow3g_pmd_drv.driver, cryptodev_driver_id);
|
2018-07-03 04:37:22 +00:00
|
|
|
|
2018-06-18 12:32:21 +00:00
|
|
|
RTE_INIT(snow3g_init_log)
|
2018-07-03 04:37:22 +00:00
|
|
|
{
|
|
|
|
snow3g_logtype_driver = rte_log_register("pmd.crypto.snow3g");
|
|
|
|
}
|