[v3,02/24] drivers/crypto: support PDCP u-plane with integrity

Message ID 20190930144104.12742-3-akhil.goyal@nxp.com (mailing list archive)
State Accepted, archived
Delegated to: akhil goyal
Headers
Series crypto/dpaaX_sec: Support Wireless algos |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Akhil Goyal Sept. 30, 2019, 2:40 p.m. UTC
  From: Vakul Garg <vakul.garg@nxp.com>

PDCP u-plane may optionally support integrity as well.
This patch add support for supporting integrity along with
confidentiality.

Signed-off-by: Vakul Garg <vakul.garg@nxp.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
---
 drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c |  67 +++++------
 drivers/crypto/dpaa2_sec/hw/desc/pdcp.h     |  75 ++++++++++---
 drivers/crypto/dpaa_sec/dpaa_sec.c          | 116 +++++++++-----------
 3 files changed, 144 insertions(+), 114 deletions(-)
  

Patch

diff --git a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
index fae216825..75a4fe0fa 100644
--- a/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
+++ b/drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
@@ -2591,6 +2591,7 @@  dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 	struct ctxt_priv *priv;
 	struct dpaa2_sec_dev_private *dev_priv = dev->data->dev_private;
 	struct alginfo authdata, cipherdata;
+	struct alginfo *p_authdata = NULL;
 	int bufsize = -1;
 	struct sec_flow_context *flc;
 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
@@ -2693,39 +2694,32 @@  dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 		goto out;
 	}
 
-	/* Auth is only applicable for control mode operation. */
-	if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
-		if (pdcp_xform->sn_size != RTE_SECURITY_PDCP_SN_SIZE_5 &&
-		    pdcp_xform->sn_size != RTE_SECURITY_PDCP_SN_SIZE_12) {
-			DPAA2_SEC_ERR(
-				"PDCP Seq Num size should be 5/12 bits for cmode");
-			goto out;
-		}
-		if (auth_xform) {
-			session->auth_key.data = rte_zmalloc(NULL,
-							auth_xform->key.length,
-							RTE_CACHE_LINE_SIZE);
-			if (session->auth_key.data == NULL &&
-					auth_xform->key.length > 0) {
-				DPAA2_SEC_ERR("No Memory for auth key");
-				rte_free(session->cipher_key.data);
-				rte_free(priv);
-				return -ENOMEM;
-			}
-			session->auth_key.length = auth_xform->key.length;
-			memcpy(session->auth_key.data, auth_xform->key.data,
-					auth_xform->key.length);
-			session->auth_alg = auth_xform->algo;
-		} else {
-			session->auth_key.data = NULL;
-			session->auth_key.length = 0;
-			session->auth_alg = RTE_CRYPTO_AUTH_NULL;
+	if (auth_xform) {
+		session->auth_key.data = rte_zmalloc(NULL,
+						     auth_xform->key.length,
+						     RTE_CACHE_LINE_SIZE);
+		if (!session->auth_key.data &&
+		    auth_xform->key.length > 0) {
+			DPAA2_SEC_ERR("No Memory for auth key");
+			rte_free(session->cipher_key.data);
+			rte_free(priv);
+			return -ENOMEM;
 		}
-		authdata.key = (size_t)session->auth_key.data;
-		authdata.keylen = session->auth_key.length;
-		authdata.key_enc_flags = 0;
-		authdata.key_type = RTA_DATA_IMM;
+		session->auth_key.length = auth_xform->key.length;
+		memcpy(session->auth_key.data, auth_xform->key.data,
+		       auth_xform->key.length);
+		session->auth_alg = auth_xform->algo;
+	} else {
+		session->auth_key.data = NULL;
+		session->auth_key.length = 0;
+		session->auth_alg = 0;
+	}
+	authdata.key = (size_t)session->auth_key.data;
+	authdata.keylen = session->auth_key.length;
+	authdata.key_enc_flags = 0;
+	authdata.key_type = RTA_DATA_IMM;
 
+	if (session->auth_alg) {
 		switch (session->auth_alg) {
 		case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
 			authdata.algtype = PDCP_AUTH_TYPE_SNOW;
@@ -2745,6 +2739,13 @@  dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 			goto out;
 		}
 
+		p_authdata = &authdata;
+	} else if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
+		DPAA2_SEC_ERR("Crypto: Integrity must for c-plane");
+		goto out;
+	}
+
+	if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
 		if (session->dir == DIR_ENC)
 			bufsize = cnstr_shdsc_pdcp_c_plane_encap(
 					priv->flc_desc[0].desc, 1, swap,
@@ -2774,7 +2775,7 @@  dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 					pdcp_xform->bearer,
 					pdcp_xform->pkt_dir,
 					pdcp_xform->hfn_threshold,
-					&cipherdata, 0);
+					&cipherdata, p_authdata, 0);
 		else if (session->dir == DIR_DEC)
 			bufsize = cnstr_shdsc_pdcp_u_plane_decap(
 					priv->flc_desc[0].desc, 1, swap,
@@ -2783,7 +2784,7 @@  dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
 					pdcp_xform->bearer,
 					pdcp_xform->pkt_dir,
 					pdcp_xform->hfn_threshold,
-					&cipherdata, 0);
+					&cipherdata, p_authdata, 0);
 	}
 
 	if (bufsize < 0) {
diff --git a/drivers/crypto/dpaa2_sec/hw/desc/pdcp.h b/drivers/crypto/dpaa2_sec/hw/desc/pdcp.h
index 607c587e2..a636640c4 100644
--- a/drivers/crypto/dpaa2_sec/hw/desc/pdcp.h
+++ b/drivers/crypto/dpaa2_sec/hw/desc/pdcp.h
@@ -1801,9 +1801,16 @@  static inline int
 pdcp_insert_uplane_15bit_op(struct program *p,
 			    bool swap __maybe_unused,
 			    struct alginfo *cipherdata,
+			    struct alginfo *authdata,
 			    unsigned int dir)
 {
 	int op;
+
+	/* Insert auth key if requested */
+	if (authdata && authdata->algtype)
+		KEY(p, KEY2, authdata->key_enc_flags, authdata->key,
+		    authdata->keylen, INLINE_KEY(authdata));
+
 	/* Insert Cipher Key */
 	KEY(p, KEY1, cipherdata->key_enc_flags, cipherdata->key,
 	    cipherdata->keylen, INLINE_KEY(cipherdata));
@@ -2478,6 +2485,7 @@  cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
 			       unsigned short direction,
 			       uint32_t hfn_threshold,
 			       struct alginfo *cipherdata,
+			       struct alginfo *authdata,
 			       unsigned char era_2_sw_hfn_ovrd)
 {
 	struct program prg;
@@ -2490,6 +2498,11 @@  cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
 		return -EINVAL;
 	}
 
+	if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
+		pr_err("Cannot use u-plane auth with era < 8");
+		return -EINVAL;
+	}
+
 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
 	if (swap)
 		PROGRAM_SET_BSWAP(p);
@@ -2509,6 +2522,13 @@  cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
 	if (err)
 		return err;
 
+	/* Insert auth key if requested */
+	if (authdata && authdata->algtype) {
+		KEY(p, KEY2, authdata->key_enc_flags,
+		    (uint64_t)authdata->key, authdata->keylen,
+		    INLINE_KEY(authdata));
+	}
+
 	switch (sn_size) {
 	case PDCP_SN_SIZE_7:
 	case PDCP_SN_SIZE_12:
@@ -2518,20 +2538,24 @@  cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
 				pr_err("Invalid era for selected algorithm\n");
 				return -ENOTSUP;
 			}
+			/* fallthrough */
 		case PDCP_CIPHER_TYPE_AES:
 		case PDCP_CIPHER_TYPE_SNOW:
+		case PDCP_CIPHER_TYPE_NULL:
 			/* Insert Cipher Key */
 			KEY(p, KEY1, cipherdata->key_enc_flags,
 			    (uint64_t)cipherdata->key, cipherdata->keylen,
 			    INLINE_KEY(cipherdata));
-			PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
-				 OP_PCLID_LTE_PDCP_USER,
-				 (uint16_t)cipherdata->algtype);
-			break;
-		case PDCP_CIPHER_TYPE_NULL:
-			insert_copy_frame_op(p,
-					     cipherdata,
-					     OP_TYPE_ENCAP_PROTOCOL);
+
+			if (authdata)
+				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
+					 OP_PCLID_LTE_PDCP_USER_RN,
+					 ((uint16_t)cipherdata->algtype << 8) |
+					 (uint16_t)authdata->algtype);
+			else
+				PROTOCOL(p, OP_TYPE_ENCAP_PROTOCOL,
+					 OP_PCLID_LTE_PDCP_USER,
+					 (uint16_t)cipherdata->algtype);
 			break;
 		default:
 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
@@ -2551,7 +2575,7 @@  cnstr_shdsc_pdcp_u_plane_encap(uint32_t *descbuf,
 
 		default:
 			err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
-				OP_TYPE_ENCAP_PROTOCOL);
+					authdata, OP_TYPE_ENCAP_PROTOCOL);
 			if (err)
 				return err;
 			break;
@@ -2605,6 +2629,7 @@  cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 			       unsigned short direction,
 			       uint32_t hfn_threshold,
 			       struct alginfo *cipherdata,
+			       struct alginfo *authdata,
 			       unsigned char era_2_sw_hfn_ovrd)
 {
 	struct program prg;
@@ -2617,6 +2642,11 @@  cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 		return -EINVAL;
 	}
 
+	if (authdata && !authdata->algtype && rta_sec_era < RTA_SEC_ERA_8) {
+		pr_err("Cannot use u-plane auth with era < 8");
+		return -EINVAL;
+	}
+
 	PROGRAM_CNTXT_INIT(p, descbuf, 0);
 	if (swap)
 		PROGRAM_SET_BSWAP(p);
@@ -2636,6 +2666,12 @@  cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 	if (err)
 		return err;
 
+	/* Insert auth key if requested */
+	if (authdata && authdata->algtype)
+		KEY(p, KEY2, authdata->key_enc_flags,
+		    (uint64_t)authdata->key, authdata->keylen,
+		    INLINE_KEY(authdata));
+
 	switch (sn_size) {
 	case PDCP_SN_SIZE_7:
 	case PDCP_SN_SIZE_12:
@@ -2645,20 +2681,23 @@  cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 				pr_err("Invalid era for selected algorithm\n");
 				return -ENOTSUP;
 			}
+			/* fallthrough */
 		case PDCP_CIPHER_TYPE_AES:
 		case PDCP_CIPHER_TYPE_SNOW:
+		case PDCP_CIPHER_TYPE_NULL:
 			/* Insert Cipher Key */
 			KEY(p, KEY1, cipherdata->key_enc_flags,
 			    cipherdata->key, cipherdata->keylen,
 			    INLINE_KEY(cipherdata));
-			PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
-				 OP_PCLID_LTE_PDCP_USER,
-				 (uint16_t)cipherdata->algtype);
-			break;
-		case PDCP_CIPHER_TYPE_NULL:
-			insert_copy_frame_op(p,
-					     cipherdata,
-					     OP_TYPE_DECAP_PROTOCOL);
+			if (authdata)
+				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
+					 OP_PCLID_LTE_PDCP_USER_RN,
+					 ((uint16_t)cipherdata->algtype << 8) |
+					 (uint16_t)authdata->algtype);
+			else
+				PROTOCOL(p, OP_TYPE_DECAP_PROTOCOL,
+					 OP_PCLID_LTE_PDCP_USER,
+					 (uint16_t)cipherdata->algtype);
 			break;
 		default:
 			pr_err("%s: Invalid encrypt algorithm selected: %d\n",
@@ -2678,7 +2717,7 @@  cnstr_shdsc_pdcp_u_plane_decap(uint32_t *descbuf,
 
 		default:
 			err = pdcp_insert_uplane_15bit_op(p, swap, cipherdata,
-				OP_TYPE_DECAP_PROTOCOL);
+				authdata, OP_TYPE_DECAP_PROTOCOL);
 			if (err)
 				return err;
 			break;
diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.c b/drivers/crypto/dpaa_sec/dpaa_sec.c
index 1532eebc5..c3fbcc11d 100644
--- a/drivers/crypto/dpaa_sec/dpaa_sec.c
+++ b/drivers/crypto/dpaa_sec/dpaa_sec.c
@@ -384,6 +384,7 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 {
 	struct alginfo authdata = {0}, cipherdata = {0};
 	struct sec_cdb *cdb = &ses->cdb;
+	struct alginfo *p_authdata = NULL;
 	int32_t shared_desc_len = 0;
 	int err;
 #if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
@@ -416,7 +417,11 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 	cipherdata.key_enc_flags = 0;
 	cipherdata.key_type = RTA_DATA_IMM;
 
-	if (ses->pdcp.domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
+	cdb->sh_desc[0] = cipherdata.keylen;
+	cdb->sh_desc[1] = 0;
+	cdb->sh_desc[2] = 0;
+
+	if (ses->auth_alg) {
 		switch (ses->auth_alg) {
 		case RTE_CRYPTO_AUTH_SNOW3G_UIA2:
 			authdata.algtype = PDCP_AUTH_TYPE_SNOW;
@@ -441,32 +446,36 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 		authdata.key_enc_flags = 0;
 		authdata.key_type = RTA_DATA_IMM;
 
-		cdb->sh_desc[0] = cipherdata.keylen;
+		p_authdata = &authdata;
+
 		cdb->sh_desc[1] = authdata.keylen;
-		err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-				       MIN_JOB_DESC_SIZE,
-				       (unsigned int *)cdb->sh_desc,
-				       &cdb->sh_desc[2], 2);
+	}
 
-		if (err < 0) {
-			DPAA_SEC_ERR("Crypto: Incorrect key lengths");
-			return err;
-		}
-		if (!(cdb->sh_desc[2] & 1) && cipherdata.keylen) {
-			cipherdata.key = (size_t)dpaa_mem_vtop(
-						(void *)(size_t)cipherdata.key);
-			cipherdata.key_type = RTA_DATA_PTR;
-		}
-		if (!(cdb->sh_desc[2] & (1<<1)) &&  authdata.keylen) {
-			authdata.key = (size_t)dpaa_mem_vtop(
-						(void *)(size_t)authdata.key);
-			authdata.key_type = RTA_DATA_PTR;
-		}
+	err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
+			       MIN_JOB_DESC_SIZE,
+			       (unsigned int *)cdb->sh_desc,
+			       &cdb->sh_desc[2], 2);
+	if (err < 0) {
+		DPAA_SEC_ERR("Crypto: Incorrect key lengths");
+		return err;
+	}
 
-		cdb->sh_desc[0] = 0;
-		cdb->sh_desc[1] = 0;
-		cdb->sh_desc[2] = 0;
+	if (!(cdb->sh_desc[2] & 1) && cipherdata.keylen) {
+		cipherdata.key =
+			(size_t)dpaa_mem_vtop((void *)(size_t)cipherdata.key);
+		cipherdata.key_type = RTA_DATA_PTR;
+	}
+	if (!(cdb->sh_desc[2] & (1 << 1)) &&  authdata.keylen) {
+		authdata.key =
+			(size_t)dpaa_mem_vtop((void *)(size_t)authdata.key);
+		authdata.key_type = RTA_DATA_PTR;
+	}
 
+	cdb->sh_desc[0] = 0;
+	cdb->sh_desc[1] = 0;
+	cdb->sh_desc[2] = 0;
+
+	if (ses->pdcp.domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
 		if (ses->dir == DIR_ENC)
 			shared_desc_len = cnstr_shdsc_pdcp_c_plane_encap(
 					cdb->sh_desc, 1, swap,
@@ -488,25 +497,6 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 					&cipherdata, &authdata,
 					0);
 	} else {
-		cdb->sh_desc[0] = cipherdata.keylen;
-		err = rta_inline_query(IPSEC_AUTH_VAR_AES_DEC_BASE_DESC_LEN,
-				       MIN_JOB_DESC_SIZE,
-				       (unsigned int *)cdb->sh_desc,
-				       &cdb->sh_desc[2], 1);
-
-		if (err < 0) {
-			DPAA_SEC_ERR("Crypto: Incorrect key lengths");
-			return err;
-		}
-		if (!(cdb->sh_desc[2] & 1) && cipherdata.keylen) {
-			cipherdata.key = (size_t)dpaa_mem_vtop(
-						(void *)(size_t)cipherdata.key);
-			cipherdata.key_type = RTA_DATA_PTR;
-		}
-		cdb->sh_desc[0] = 0;
-		cdb->sh_desc[1] = 0;
-		cdb->sh_desc[2] = 0;
-
 		if (ses->dir == DIR_ENC)
 			shared_desc_len = cnstr_shdsc_pdcp_u_plane_encap(
 					cdb->sh_desc, 1, swap,
@@ -515,7 +505,7 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 					ses->pdcp.bearer,
 					ses->pdcp.pkt_dir,
 					ses->pdcp.hfn_threshold,
-					&cipherdata, 0);
+					&cipherdata, p_authdata, 0);
 		else if (ses->dir == DIR_DEC)
 			shared_desc_len = cnstr_shdsc_pdcp_u_plane_decap(
 					cdb->sh_desc, 1, swap,
@@ -524,7 +514,7 @@  dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
 					ses->pdcp.bearer,
 					ses->pdcp.pkt_dir,
 					ses->pdcp.hfn_threshold,
-					&cipherdata, 0);
+					&cipherdata, p_authdata, 0);
 	}
 
 	return shared_desc_len;
@@ -2399,7 +2389,6 @@  dpaa_sec_set_pdcp_session(struct rte_cryptodev *dev,
 		session->dir = DIR_ENC;
 	}
 
-	/* Auth is only applicable for control mode operation. */
 	if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
 		if (pdcp_xform->sn_size != RTE_SECURITY_PDCP_SN_SIZE_5 &&
 		    pdcp_xform->sn_size != RTE_SECURITY_PDCP_SN_SIZE_12) {
@@ -2407,25 +2396,26 @@  dpaa_sec_set_pdcp_session(struct rte_cryptodev *dev,
 				"PDCP Seq Num size should be 5/12 bits for cmode");
 			goto out;
 		}
-		if (auth_xform) {
-			session->auth_key.data = rte_zmalloc(NULL,
-							auth_xform->key.length,
-							RTE_CACHE_LINE_SIZE);
-			if (session->auth_key.data == NULL &&
-					auth_xform->key.length > 0) {
-				DPAA_SEC_ERR("No Memory for auth key");
-				rte_free(session->cipher_key.data);
-				return -ENOMEM;
-			}
-			session->auth_key.length = auth_xform->key.length;
-			memcpy(session->auth_key.data, auth_xform->key.data,
-					auth_xform->key.length);
-			session->auth_alg = auth_xform->algo;
-		} else {
-			session->auth_key.data = NULL;
-			session->auth_key.length = 0;
-			session->auth_alg = RTE_CRYPTO_AUTH_NULL;
+	}
+
+	if (auth_xform) {
+		session->auth_key.data = rte_zmalloc(NULL,
+						     auth_xform->key.length,
+						     RTE_CACHE_LINE_SIZE);
+		if (!session->auth_key.data &&
+		    auth_xform->key.length > 0) {
+			DPAA_SEC_ERR("No Memory for auth key");
+			rte_free(session->cipher_key.data);
+			return -ENOMEM;
 		}
+		session->auth_key.length = auth_xform->key.length;
+		memcpy(session->auth_key.data, auth_xform->key.data,
+		       auth_xform->key.length);
+		session->auth_alg = auth_xform->algo;
+	} else {
+		session->auth_key.data = NULL;
+		session->auth_key.length = 0;
+		session->auth_alg = 0;
 	}
 	session->pdcp.domain = pdcp_xform->domain;
 	session->pdcp.bearer = pdcp_xform->bearer;