@@ -8,6 +8,7 @@ Symmetric crypto = Y
Sym operation chaining = Y
Symmetric sessionless = Y
Non-Byte aligned data = Y
+Digest encrypted = Y
OOP LB In LB Out = Y
;
@@ -113,6 +113,13 @@ New Features
* Added support for ZUC-EEA3-256 and ZUC-EIA3-256.
+* **Added digest appended ops support for Snow3G PMD.**
+
+ * Added support for out-of-place auth-cipher operations that encrypt
+ the digest along with the rest of the raw data.
+ * Added support for partially encrypted digest when using auth-cipher
+ operations.
+
* **Updated Marvell cnxk ethdev driver.**
* Added rte_flow support for dual VLAN insert and strip actions.
@@ -73,6 +73,24 @@ snow3g_session_configure(IMB_MGR *mgr, void *priv_sess,
return 0;
}
+/** Check if conditions are met for digest-appended operations */
+static uint8_t *
+snow3g_digest_appended_in_src(struct rte_crypto_op *op)
+{
+ unsigned int auth_size, cipher_size;
+
+ auth_size = (op->sym->auth.data.offset >> 3) +
+ (op->sym->auth.data.length >> 3);
+ cipher_size = (op->sym->cipher.data.offset >> 3) +
+ (op->sym->cipher.data.length >> 3);
+
+ if (auth_size < cipher_size)
+ return rte_pktmbuf_mtod_offset(op->sym->m_src,
+ uint8_t *, auth_size);
+
+ return NULL;
+}
+
/** Encrypt/decrypt mbufs with same cipher key. */
static uint8_t
process_snow3g_cipher_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
@@ -81,29 +99,75 @@ process_snow3g_cipher_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
{
uint32_t i;
uint8_t processed_ops = 0;
- const void *src[SNOW3G_MAX_BURST];
- void *dst[SNOW3G_MAX_BURST];
- const void *iv[SNOW3G_MAX_BURST];
- uint32_t num_bytes[SNOW3G_MAX_BURST];
+ const void *src[SNOW3G_MAX_BURST] = {NULL};
+ void *dst[SNOW3G_MAX_BURST] = {NULL};
+ uint8_t *digest_appended[SNOW3G_MAX_BURST] = {NULL};
+ const void *iv[SNOW3G_MAX_BURST] = {NULL};
+ uint32_t num_bytes[SNOW3G_MAX_BURST] = {0};
+ uint32_t cipher_off, cipher_len;
+ int unencrypted_bytes = 0;
for (i = 0; i < num_ops; i++) {
- src[i] = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
- (ops[i]->sym->cipher.data.offset >> 3);
- dst[i] = ops[i]->sym->m_dst ?
- 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);
+
+ cipher_off = ops[i]->sym->cipher.data.offset >> 3;
+ cipher_len = ops[i]->sym->cipher.data.length >> 3;
+ src[i] = rte_pktmbuf_mtod_offset(
+ ops[i]->sym->m_src, uint8_t *, cipher_off);
+
+ /* If out-of-place operation */
+ if (ops[i]->sym->m_dst &&
+ ops[i]->sym->m_src != ops[i]->sym->m_dst) {
+ dst[i] = rte_pktmbuf_mtod_offset(
+ ops[i]->sym->m_dst, uint8_t *, cipher_off);
+
+ /* In case of out-of-place, auth-cipher operation
+ * with partial encryption of the digest, copy
+ * the remaining, unencrypted part.
+ */
+ if (session->op == IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT
+ || session->op == IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT)
+ unencrypted_bytes =
+ (ops[i]->sym->auth.data.offset >> 3) +
+ (ops[i]->sym->auth.data.length >> 3) +
+ (SNOW3G_DIGEST_LENGTH) -
+ cipher_off - cipher_len;
+ if (unencrypted_bytes > 0)
+ rte_memcpy(
+ rte_pktmbuf_mtod_offset(
+ ops[i]->sym->m_dst, uint8_t *,
+ cipher_off + cipher_len),
+ rte_pktmbuf_mtod_offset(
+ ops[i]->sym->m_src, uint8_t *,
+ cipher_off + cipher_len),
+ unencrypted_bytes);
+ } else
+ dst[i] = rte_pktmbuf_mtod_offset(ops[i]->sym->m_src,
+ uint8_t *, cipher_off);
+
iv[i] = rte_crypto_op_ctod_offset(ops[i], uint8_t *,
session->cipher_iv_offset);
- num_bytes[i] = ops[i]->sym->cipher.data.length >> 3;
-
+ num_bytes[i] = cipher_len;
processed_ops++;
}
IMB_SNOW3G_F8_N_BUFFER(qp->mb_mgr, &session->pKeySched_cipher, iv,
src, dst, num_bytes, processed_ops);
+ /* Take care of the raw digest data in src buffer */
+ for (i = 0; i < num_ops; i++) {
+ if ((session->op == IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT ||
+ session->op == IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT) &&
+ ops[i]->sym->m_dst != NULL) {
+ digest_appended[i] =
+ snow3g_digest_appended_in_src(ops[i]);
+ /* Clear unencrypted digest from
+ * the src buffer
+ */
+ if (digest_appended[i] != NULL)
+ memset(digest_appended[i],
+ 0, SNOW3G_DIGEST_LENGTH);
+ }
+ }
return processed_ops;
}
@@ -116,6 +180,7 @@ process_snow3g_cipher_op_bit(struct ipsec_mb_qp *qp,
uint8_t *src, *dst;
uint8_t *iv;
uint32_t length_in_bits, offset_in_bits;
+ int unencrypted_bytes = 0;
offset_in_bits = op->sym->cipher.data.offset;
src = rte_pktmbuf_mtod(op->sym->m_src, uint8_t *);
@@ -124,10 +189,32 @@ process_snow3g_cipher_op_bit(struct ipsec_mb_qp *qp,
IPSEC_MB_LOG(ERR, "bit-level in-place not supported\n");
return 0;
}
+ length_in_bits = op->sym->cipher.data.length;
dst = rte_pktmbuf_mtod(op->sym->m_dst, uint8_t *);
+ /* In case of out-of-place, auth-cipher operation
+ * with partial encryption of the digest, copy
+ * the remaining, unencrypted part.
+ */
+ if (session->op == IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT ||
+ session->op == IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT)
+ unencrypted_bytes =
+ (op->sym->auth.data.offset >> 3) +
+ (op->sym->auth.data.length >> 3) +
+ (SNOW3G_DIGEST_LENGTH) -
+ (offset_in_bits >> 3) -
+ (length_in_bits >> 3);
+ if (unencrypted_bytes > 0)
+ rte_memcpy(
+ rte_pktmbuf_mtod_offset(
+ op->sym->m_dst, uint8_t *,
+ (length_in_bits >> 3)),
+ rte_pktmbuf_mtod_offset(
+ op->sym->m_src, uint8_t *,
+ (length_in_bits >> 3)),
+ unencrypted_bytes);
+
iv = rte_crypto_op_ctod_offset(op, uint8_t *,
session->cipher_iv_offset);
- length_in_bits = op->sym->cipher.data.length;
IMB_SNOW3G_F8_1_BUFFER_BIT(qp->mb_mgr, &session->pKeySched_cipher, iv,
src, dst, length_in_bits, offset_in_bits);
@@ -146,6 +233,7 @@ process_snow3g_hash_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
uint8_t *src, *dst;
uint32_t length_in_bits;
uint8_t *iv;
+ uint8_t digest_appended = 0;
struct snow3g_qp_data *qp_data = ipsec_mb_get_qp_private_data(qp);
for (i = 0; i < num_ops; i++) {
@@ -156,6 +244,8 @@ process_snow3g_hash_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
break;
}
+ dst = NULL;
+
length_in_bits = ops[i]->sym->auth.data.length;
src = rte_pktmbuf_mtod(ops[i]->sym->m_src, uint8_t *) +
@@ -165,6 +255,15 @@ process_snow3g_hash_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
if (session->auth_op == RTE_CRYPTO_AUTH_OP_VERIFY) {
dst = qp_data->temp_digest;
+ /* Handle auth cipher verify oop case*/
+ if ((session->op ==
+ IPSEC_MB_OP_ENCRYPT_THEN_HASH_GEN ||
+ session->op ==
+ IPSEC_MB_OP_DECRYPT_THEN_HASH_VERIFY) &&
+ ops[i]->sym->m_dst != NULL)
+ src = rte_pktmbuf_mtod_offset(
+ ops[i]->sym->m_dst, uint8_t *,
+ ops[i]->sym->auth.data.offset >> 3);
IMB_SNOW3G_F9_1_BUFFER(qp->mb_mgr,
&session->pKeySched_hash,
@@ -174,12 +273,26 @@ process_snow3g_hash_op(struct ipsec_mb_qp *qp, struct rte_crypto_op **ops,
SNOW3G_DIGEST_LENGTH) != 0)
ops[i]->status =
RTE_CRYPTO_OP_STATUS_AUTH_FAILED;
- } else {
- dst = ops[i]->sym->auth.digest.data;
+ } else {
+ if (session->op ==
+ IPSEC_MB_OP_HASH_VERIFY_THEN_DECRYPT ||
+ session->op ==
+ IPSEC_MB_OP_HASH_GEN_THEN_ENCRYPT)
+ dst = snow3g_digest_appended_in_src(ops[i]);
+
+ if (dst != NULL)
+ digest_appended = 1;
+ else
+ dst = ops[i]->sym->auth.digest.data;
IMB_SNOW3G_F9_1_BUFFER(qp->mb_mgr,
&session->pKeySched_hash,
iv, src, length_in_bits, dst);
+
+ /* Copy back digest from src to auth.digest.data */
+ if (digest_appended)
+ rte_memcpy(ops[i]->sym->auth.digest.data,
+ dst, SNOW3G_DIGEST_LENGTH);
}
processed_ops++;
}
@@ -480,7 +593,8 @@ RTE_INIT(ipsec_mb_register_snow3g)
RTE_CRYPTODEV_FF_SYM_OPERATION_CHAINING |
RTE_CRYPTODEV_FF_NON_BYTE_ALIGNED_DATA |
RTE_CRYPTODEV_FF_SYM_SESSIONLESS |
- RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT;
+ RTE_CRYPTODEV_FF_OOP_LB_IN_LB_OUT |
+ RTE_CRYPTODEV_FF_DIGEST_ENCRYPTED;
snow3g_data->internals_priv_size = 0;
snow3g_data->ops = &snow3g_pmd_ops;
snow3g_data->qp_priv_size = sizeof(struct snow3g_qp_data);