[1/5] crypto/cnxk: support AH mode

Message ID 1650865105-66-2-git-send-email-anoobj@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: akhil goyal
Headers
Series Fixes and improvements to cnxk crypto PMDs |

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Anoob Joseph April 25, 2022, 5:38 a.m. UTC
  From: Archana Muniganti <marchana@marvell.com>

Added IPsec AH mode support in CN9K and CN10K PMD

Signed-off-by: Archana Muniganti <marchana@marvell.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
---
 doc/guides/cryptodevs/cnxk.rst                    |  2 +
 doc/guides/rel_notes/release_22_07.rst            |  4 ++
 drivers/common/cnxk/cnxk_security.c               | 61 ++++++++--------
 drivers/crypto/cnxk/cn10k_ipsec.c                 |  2 +-
 drivers/crypto/cnxk/cn9k_ipsec.c                  | 85 +++++++++++++----------
 drivers/crypto/cnxk/cnxk_cryptodev.h              |  2 +-
 drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c | 44 ++++++++++++
 drivers/crypto/cnxk/cnxk_ipsec.h                  | 73 ++++++++++++++-----
 8 files changed, 188 insertions(+), 85 deletions(-)
  

Patch

diff --git a/doc/guides/cryptodevs/cnxk.rst b/doc/guides/cryptodevs/cnxk.rst
index 46431dd..19c4a8b 100644
--- a/doc/guides/cryptodevs/cnxk.rst
+++ b/doc/guides/cryptodevs/cnxk.rst
@@ -252,6 +252,7 @@  CN9XX Features supported
 * Tunnel mode
 * Transport mode(IPv4)
 * UDP Encapsulation
+* AH
 
 AEAD algorithms
 +++++++++++++++
@@ -284,6 +285,7 @@  CN10XX Features supported
 * Tunnel mode
 * Transport mode
 * UDP Encapsulation
+* AH
 
 AEAD algorithms
 +++++++++++++++
diff --git a/doc/guides/rel_notes/release_22_07.rst b/doc/guides/rel_notes/release_22_07.rst
index 42a5f2d..68857d4 100644
--- a/doc/guides/rel_notes/release_22_07.rst
+++ b/doc/guides/rel_notes/release_22_07.rst
@@ -55,6 +55,10 @@  New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+* **Updated Marvell cnxk crypto PMD.**
+
+  * Added AH mode support in lookaside protocol (IPsec) for CN9K & CN10K.
+
 
 Removed Items
 -------------
diff --git a/drivers/common/cnxk/cnxk_security.c b/drivers/common/cnxk/cnxk_security.c
index ec808c0..afefbd2 100644
--- a/drivers/common/cnxk/cnxk_security.c
+++ b/drivers/common/cnxk/cnxk_security.c
@@ -57,25 +57,23 @@  ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
 			      struct rte_crypto_sym_xform *crypto_xfrm)
 {
 	struct rte_crypto_sym_xform *auth_xfrm, *cipher_xfrm;
-	const uint8_t *key;
+	const uint8_t *key = NULL;
 	uint32_t *tmp_salt;
 	uint64_t *tmp_key;
-	int length, i;
+	int i, length = 0;
 
 	/* Set direction */
-	switch (ipsec_xfrm->direction) {
-	case RTE_SECURITY_IPSEC_SA_DIR_INGRESS:
+	if (ipsec_xfrm->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
+	else
 		w2->s.dir = ROC_IE_SA_DIR_INBOUND;
+
+	if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
 		auth_xfrm = crypto_xfrm;
 		cipher_xfrm = crypto_xfrm->next;
-		break;
-	case RTE_SECURITY_IPSEC_SA_DIR_EGRESS:
-		w2->s.dir = ROC_IE_SA_DIR_OUTBOUND;
+	} else {
 		cipher_xfrm = crypto_xfrm;
 		auth_xfrm = crypto_xfrm->next;
-		break;
-	default:
-		return -EINVAL;
 	}
 
 	/* Set protocol - ESP vs AH */
@@ -119,18 +117,23 @@  ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
 			return -ENOTSUP;
 		}
 	} else {
-		switch (cipher_xfrm->cipher.algo) {
-		case RTE_CRYPTO_CIPHER_NULL:
-			w2->s.enc_type = ROC_IE_OT_SA_ENC_NULL;
-			break;
-		case RTE_CRYPTO_CIPHER_AES_CBC:
-			w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_CBC;
-			break;
-		case RTE_CRYPTO_CIPHER_AES_CTR:
-			w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_CTR;
-			break;
-		default:
-			return -ENOTSUP;
+		if (cipher_xfrm != NULL) {
+			switch (cipher_xfrm->cipher.algo) {
+			case RTE_CRYPTO_CIPHER_NULL:
+				w2->s.enc_type = ROC_IE_OT_SA_ENC_NULL;
+				break;
+			case RTE_CRYPTO_CIPHER_AES_CBC:
+				w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_CBC;
+				break;
+			case RTE_CRYPTO_CIPHER_AES_CTR:
+				w2->s.enc_type = ROC_IE_OT_SA_ENC_AES_CTR;
+				break;
+			default:
+				return -ENOTSUP;
+			}
+
+			key = cipher_xfrm->cipher.key.data;
+			length = cipher_xfrm->cipher.key.length;
 		}
 
 		switch (auth_xfrm->auth.algo) {
@@ -169,8 +172,6 @@  ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
 		     i++)
 			tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
 
-		key = cipher_xfrm->cipher.key.data;
-		length = cipher_xfrm->cipher.key.length;
 	}
 
 	/* Set encapsulation type */
@@ -179,11 +180,13 @@  ot_ipsec_sa_common_param_fill(union roc_ot_ipsec_sa_word2 *w2,
 
 	w2->s.spi = ipsec_xfrm->spi;
 
-	/* Copy encryption key */
-	memcpy(cipher_key, key, length);
-	tmp_key = (uint64_t *)cipher_key;
-	for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
-		tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
+	if (key != NULL && length != 0) {
+		/* Copy encryption key */
+		memcpy(cipher_key, key, length);
+		tmp_key = (uint64_t *)cipher_key;
+		for (i = 0; i < (int)(ROC_CTX_MAX_CKEY_LEN / sizeof(uint64_t)); i++)
+			tmp_key[i] = rte_be_to_cpu_64(tmp_key[i]);
+	}
 
 	/* Set AES key length */
 	if (w2->s.enc_type == ROC_IE_OT_SA_ENC_AES_CBC ||
diff --git a/drivers/crypto/cnxk/cn10k_ipsec.c b/drivers/crypto/cnxk/cn10k_ipsec.c
index 15ebd57..0c9e244 100644
--- a/drivers/crypto/cnxk/cn10k_ipsec.c
+++ b/drivers/crypto/cnxk/cn10k_ipsec.c
@@ -74,7 +74,7 @@  cn10k_ipsec_outb_sa_create(struct roc_cpt *roc_cpt, struct roc_cpt_lf *lf,
 		if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 			sa->iv_offset = crypto_xfrm->aead.iv.offset;
 			sa->iv_length = crypto_xfrm->aead.iv.length;
-		} else {
+		} else if (crypto_xfrm->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
 			sa->iv_offset = crypto_xfrm->cipher.iv.offset;
 			sa->iv_length = crypto_xfrm->cipher.iv.length;
 		}
diff --git a/drivers/crypto/cnxk/cn9k_ipsec.c b/drivers/crypto/cnxk/cn9k_ipsec.c
index 737bafd..eaa3698 100644
--- a/drivers/crypto/cnxk/cn9k_ipsec.c
+++ b/drivers/crypto/cnxk/cn9k_ipsec.c
@@ -120,18 +120,19 @@  ipsec_sa_ctl_set(struct rte_security_ipsec_xform *ipsec,
 	struct rte_crypto_sym_xform *cipher_xform, *auth_xform;
 	int aes_key_len = 0;
 
-	if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS) {
-		ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
-		cipher_xform = crypto_xform;
-		auth_xform = crypto_xform->next;
-	} else if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
-		ctl->direction = ROC_IE_SA_DIR_INBOUND;
+	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH) {
 		auth_xform = crypto_xform;
 		cipher_xform = crypto_xform->next;
 	} else {
-		return -EINVAL;
+		cipher_xform = crypto_xform;
+		auth_xform = crypto_xform->next;
 	}
 
+	if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_EGRESS)
+		ctl->direction = ROC_IE_SA_DIR_OUTBOUND;
+	else
+		ctl->direction = ROC_IE_SA_DIR_INBOUND;
+
 	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
 		if (ipsec->tunnel.type == RTE_SECURITY_IPSEC_TUNNEL_IPV4)
 			ctl->outer_ip_ver = ROC_IE_SA_IP_VERSION_4;
@@ -167,21 +168,23 @@  ipsec_sa_ctl_set(struct rte_security_ipsec_xform *ipsec,
 			return -ENOTSUP;
 		}
 	} else {
-		switch (cipher_xform->cipher.algo) {
-		case RTE_CRYPTO_CIPHER_NULL:
-			ctl->enc_type = ROC_IE_ON_SA_ENC_NULL;
-			break;
-		case RTE_CRYPTO_CIPHER_AES_CBC:
-			ctl->enc_type = ROC_IE_ON_SA_ENC_AES_CBC;
-			aes_key_len = cipher_xform->cipher.key.length;
-			break;
-		case RTE_CRYPTO_CIPHER_AES_CTR:
-			ctl->enc_type = ROC_IE_ON_SA_ENC_AES_CTR;
-			aes_key_len = cipher_xform->cipher.key.length;
-			break;
-		default:
-			plt_err("Unsupported cipher algorithm");
-			return -ENOTSUP;
+		if (cipher_xform != NULL) {
+			switch (cipher_xform->cipher.algo) {
+			case RTE_CRYPTO_CIPHER_NULL:
+				ctl->enc_type = ROC_IE_ON_SA_ENC_NULL;
+				break;
+			case RTE_CRYPTO_CIPHER_AES_CBC:
+				ctl->enc_type = ROC_IE_ON_SA_ENC_AES_CBC;
+				aes_key_len = cipher_xform->cipher.key.length;
+				break;
+			case RTE_CRYPTO_CIPHER_AES_CTR:
+				ctl->enc_type = ROC_IE_ON_SA_ENC_AES_CTR;
+				aes_key_len = cipher_xform->cipher.key.length;
+				break;
+			default:
+				plt_err("Unsupported cipher algorithm");
+				return -ENOTSUP;
+			}
 		}
 
 		switch (auth_xform->auth.algo) {
@@ -267,15 +270,23 @@  fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
 	int cipher_key_len = 0;
 	int ret;
 
+	ret = ipsec_sa_ctl_set(ipsec, crypto_xform, &common_sa->ctl);
+	if (ret)
+		return ret;
+
+	if (ipsec->esn.value) {
+		common_sa->esn_low = ipsec->esn.low;
+		common_sa->esn_hi = ipsec->esn.hi;
+	}
+
+	if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
+		return 0;
+
 	if (ipsec->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
 		cipher_xform = crypto_xform->next;
 	else
 		cipher_xform = crypto_xform;
 
-	ret = ipsec_sa_ctl_set(ipsec, crypto_xform, &common_sa->ctl);
-	if (ret)
-		return ret;
-
 	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 		if (crypto_xform->aead.algo == RTE_CRYPTO_AEAD_AES_GCM)
 			memcpy(common_sa->iv.gcm.nonce, &ipsec->salt, 4);
@@ -289,11 +300,6 @@  fill_ipsec_common_sa(struct rte_security_ipsec_xform *ipsec,
 	if (cipher_key_len != 0)
 		memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
 
-	if (ipsec->esn.value) {
-		common_sa->esn_low = ipsec->esn.low;
-		common_sa->esn_hi = ipsec->esn.hi;
-	}
-
 	return 0;
 }
 
@@ -303,9 +309,9 @@  cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
 			  struct rte_crypto_sym_xform *crypto_xform,
 			  struct rte_security_session *sec_sess)
 {
-	struct rte_crypto_sym_xform *auth_xform = crypto_xform->next;
 	struct roc_ie_on_ip_template *template = NULL;
 	struct roc_cpt *roc_cpt = qp->lf.roc_cpt;
+	struct rte_crypto_sym_xform *auth_xform;
 	union roc_on_ipsec_outb_param1 param1;
 	struct cnxk_cpt_inst_tmpl *inst_tmpl;
 	struct roc_ie_on_outb_sa *out_sa;
@@ -338,6 +344,11 @@  cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
 	if (ipsec->esn.value)
 		sa->esn = ipsec->esn.value;
 
+	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AUTH)
+		auth_xform = crypto_xform;
+	else
+		auth_xform = crypto_xform->next;
+
 	ret = fill_ipsec_common_sa(ipsec, crypto_xform, &out_sa->common_sa);
 	if (ret)
 		return ret;
@@ -381,7 +392,10 @@  cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
 		template->ip4.udp_src = rte_be_to_cpu_16(4500);
 		template->ip4.udp_dst = rte_be_to_cpu_16(4500);
 	} else {
-		ip4->next_proto_id = IPPROTO_ESP;
+		if (ipsec->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH)
+			ip4->next_proto_id = IPPROTO_AH;
+		else
+			ip4->next_proto_id = IPPROTO_ESP;
 	}
 
 	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TUNNEL) {
@@ -480,7 +494,7 @@  cn9k_ipsec_outb_sa_create(struct cnxk_cpt_qp *qp,
 		if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD) {
 			sa->cipher_iv_off = crypto_xform->aead.iv.offset;
 			sa->cipher_iv_len = crypto_xform->aead.iv.length;
-		} else {
+		} else if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
 			sa->cipher_iv_off = crypto_xform->cipher.iv.offset;
 			sa->cipher_iv_len = crypto_xform->cipher.iv.length;
 		}
@@ -621,7 +635,8 @@  cn9k_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec,
 	    ipsec->life.packets_soft_limit != 0)
 		return -ENOTSUP;
 
-	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT) {
+	if (ipsec->mode == RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT &&
+	    ipsec->proto != RTE_SECURITY_IPSEC_SA_PROTO_AH) {
 		enum rte_crypto_sym_xform_type type = crypto->type;
 
 		if (type == RTE_CRYPTO_SYM_XFORM_AEAD) {
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev.h b/drivers/crypto/cnxk/cnxk_cryptodev.h
index 16e7572..542c93b 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev.h
+++ b/drivers/crypto/cnxk/cnxk_cryptodev.h
@@ -12,7 +12,7 @@ 
 
 #define CNXK_CPT_MAX_CAPS	 34
 #define CNXK_SEC_CRYPTO_MAX_CAPS 11
-#define CNXK_SEC_MAX_CAPS	 5
+#define CNXK_SEC_MAX_CAPS	 9
 #define CNXK_AE_EC_ID_MAX	 8
 /**
  * Device private data
diff --git a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
index 5cb27aa..efd53db 100644
--- a/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
+++ b/drivers/crypto/cnxk/cnxk_cryptodev_capabilities.c
@@ -988,6 +988,50 @@  static const struct rte_security_capability sec_caps_templ[] = {
 		},
 		.crypto_capabilities = NULL,
 	},
+	{	/* IPsec Lookaside Protocol AH Tunnel Ingress */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+		.ipsec = {
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_AH,
+			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+			.options = { 0 },
+		},
+		.crypto_capabilities = NULL,
+	},
+	{	/* IPsec Lookaside Protocol AH Tunnel Egress */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+		.ipsec = {
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_AH,
+			.mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
+			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+			.options = { 0 },
+		},
+		.crypto_capabilities = NULL,
+	},
+	{	/* IPsec Lookaside Protocol AH Transport Ingress */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+		.ipsec = {
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_AH,
+			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
+			.options = { 0 },
+		},
+		.crypto_capabilities = NULL,
+	},
+	{	/* IPsec Lookaside Protocol AH Transport Egress */
+		.action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL,
+		.protocol = RTE_SECURITY_PROTOCOL_IPSEC,
+		.ipsec = {
+			.proto = RTE_SECURITY_IPSEC_SA_PROTO_AH,
+			.mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
+			.direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
+			.options = { 0 },
+		},
+		.crypto_capabilities = NULL,
+	},
 	{
 		.action = RTE_SECURITY_ACTION_TYPE_NONE
 	}
diff --git a/drivers/crypto/cnxk/cnxk_ipsec.h b/drivers/crypto/cnxk/cnxk_ipsec.h
index f50d9fa..1524217 100644
--- a/drivers/crypto/cnxk/cnxk_ipsec.h
+++ b/drivers/crypto/cnxk/cnxk_ipsec.h
@@ -122,28 +122,63 @@  cnxk_ipsec_xform_verify(struct rte_security_ipsec_xform *ipsec_xform,
 	if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_AEAD)
 		return ipsec_xform_aead_verify(ipsec_xform, crypto_xform);
 
-	if (crypto_xform->next == NULL)
-		return -EINVAL;
-
-	if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
-		/* Ingress */
-		if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
-		    crypto_xform->next->type != RTE_CRYPTO_SYM_XFORM_CIPHER)
-			return -EINVAL;
-		auth_xform = crypto_xform;
-		cipher_xform = crypto_xform->next;
+	if (ipsec_xform->proto == RTE_SECURITY_IPSEC_SA_PROTO_AH) {
+		if (ipsec_xform->direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+			/* Ingress */
+			auth_xform = crypto_xform;
+			cipher_xform = crypto_xform->next;
+
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+				return -EINVAL;
+
+			if ((cipher_xform != NULL) && ((cipher_xform->type !=
+			    RTE_CRYPTO_SYM_XFORM_CIPHER) ||
+			    (cipher_xform->cipher.algo !=
+			    RTE_CRYPTO_CIPHER_NULL)))
+				return -EINVAL;
+		} else {
+				/* Egress */
+			if (crypto_xform->type == RTE_CRYPTO_SYM_XFORM_CIPHER) {
+				cipher_xform = crypto_xform;
+				auth_xform = crypto_xform->next;
+
+				if (auth_xform == NULL ||
+				    cipher_xform->cipher.algo !=
+				    RTE_CRYPTO_CIPHER_NULL)
+					return -EINVAL;
+			} else if (crypto_xform->type ==
+				   RTE_CRYPTO_SYM_XFORM_AUTH)
+				auth_xform = crypto_xform;
+			else
+				return -EINVAL;
+		}
 	} else {
-		/* Egress */
-		if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
-		    crypto_xform->next->type != RTE_CRYPTO_SYM_XFORM_AUTH)
+		if (crypto_xform->next == NULL)
 			return -EINVAL;
-		cipher_xform = crypto_xform;
-		auth_xform = crypto_xform->next;
-	}
 
-	ret = ipsec_xform_cipher_verify(cipher_xform);
-	if (ret)
-		return ret;
+		if (ipsec_xform->direction ==
+		    RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
+			/* Ingress */
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AUTH ||
+			    crypto_xform->next->type !=
+				    RTE_CRYPTO_SYM_XFORM_CIPHER)
+				return -EINVAL;
+			auth_xform = crypto_xform;
+			cipher_xform = crypto_xform->next;
+		} else {
+			/* Egress */
+			if (crypto_xform->type != RTE_CRYPTO_SYM_XFORM_CIPHER ||
+			    crypto_xform->next->type !=
+				    RTE_CRYPTO_SYM_XFORM_AUTH)
+				return -EINVAL;
+			cipher_xform = crypto_xform;
+			auth_xform = crypto_xform->next;
+		}
+
+		ret = ipsec_xform_cipher_verify(cipher_xform);
+		if (ret)
+			return ret;
+	}
 
 	return ipsec_xform_auth_verify(auth_xform);
 }