crypto/dpaax_sec: fix 18-bit PDCP cases with HFN override
authorAkhil Goyal <akhil.goyal@nxp.com>
Mon, 1 Jun 2020 17:17:45 +0000 (22:47 +0530)
committerThomas Monjalon <thomas@monjalon.net>
Wed, 8 Jul 2020 16:16:17 +0000 (18:16 +0200)
In case of RTA_SEC_ERA = 8, where the length of shared desc
is large for some of PDCP cases, the descriptor buffer cannot
hold 2 extra words when HFN override is enabled. As a result,
the descriptor fails.

This patch converts one of the keys from immediate key to
reference key hence reducing the length of the descriptor.

Fixes: 2e4cbdb4b2c2 ("crypto/dpaax_sec: support PDCP U-Plane with integrity")
Cc: stable@dpdk.org
Signed-off-by: Akhil Goyal <akhil.goyal@nxp.com>
Acked-by: Hemant Agrawal <hemant.agrawal@nxp.com>
drivers/common/dpaax/caamflib/desc/pdcp.h
drivers/crypto/dpaa2_sec/dpaa2_sec_dpseci.c
drivers/crypto/dpaa_sec/dpaa_sec.c

index b5e2d24..99eb0f7 100644 (file)
@@ -262,6 +262,50 @@ enum pdb_type_e {
        PDCP_PDB_TYPE_INVALID
 };
 
+/**
+ * rta_inline_pdcp_query() - Provide indications if a key can be passed as
+ *                           immediate data or shall be referenced in a
+ *                           shared descriptor.
+ * Return: 0 if data can be inlined or 1 if referenced.
+ */
+static inline int
+rta_inline_pdcp_query(enum auth_type_pdcp auth_alg,
+                     enum cipher_type_pdcp cipher_alg,
+                     enum pdcp_sn_size sn_size,
+                     int8_t hfn_ovd)
+{
+       /**
+        * Shared Descriptors for some of the cases does not fit in the
+        * MAX_DESC_SIZE of the descriptor especially when non-protocol
+        * descriptors are formed as in 18bit cases and when HFN override
+        * is enabled as 2 extra words are added in the job descriptor.
+        * The cases which exceed are for RTA_SEC_ERA=8 and HFN override
+        * enabled and 18bit uplane and either of following Algo combinations.
+        * - SNOW-AES
+        * - AES-SNOW
+        * - SNOW-SNOW
+        * - ZUC-SNOW
+        *
+        * We cannot make inline for all cases, as this will impact performance
+        * due to extra memory accesses for the keys.
+        */
+       if ((rta_sec_era == RTA_SEC_ERA_8) && hfn_ovd &&
+                       (sn_size == PDCP_SN_SIZE_18) &&
+                       ((cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
+                               auth_alg == PDCP_AUTH_TYPE_AES) ||
+                       (cipher_alg == PDCP_CIPHER_TYPE_AES &&
+                               auth_alg == PDCP_AUTH_TYPE_SNOW) ||
+                       (cipher_alg == PDCP_CIPHER_TYPE_SNOW &&
+                               auth_alg == PDCP_AUTH_TYPE_SNOW) ||
+                       (cipher_alg == PDCP_CIPHER_TYPE_ZUC &&
+                               auth_alg == PDCP_AUTH_TYPE_SNOW))) {
+
+               return 1;
+       }
+
+       return 0;
+}
+
 /*
  * Function for appending the portion of a PDCP Control Plane shared descriptor
  * which performs NULL encryption and integrity (i.e. copies the input frame
index 12f8331..60fdced 100644 (file)
@@ -3154,6 +3154,14 @@ dpaa2_sec_set_pdcp_session(struct rte_cryptodev *dev,
                goto out;
        }
 
+       if (rta_inline_pdcp_query(authdata.algtype,
+                               cipherdata.algtype,
+                               session->pdcp.sn_size,
+                               session->pdcp.hfn_ovd)) {
+               cipherdata.key = DPAA2_VADDR_TO_IOVA(cipherdata.key);
+               cipherdata.key_type = RTA_DATA_PTR;
+       }
+
        if (pdcp_xform->domain == RTE_SECURITY_PDCP_MODE_CONTROL) {
                if (session->dir == DIR_ENC)
                        bufsize = cnstr_shdsc_pdcp_c_plane_encap(
index d9fa8bb..01e79c8 100644 (file)
@@ -240,7 +240,6 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
        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
        int swap = false;
 #else
@@ -254,10 +253,6 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
        cipherdata.algtype = ses->cipher_key.alg;
        cipherdata.algmode = ses->cipher_key.algmode;
 
-       cdb->sh_desc[0] = cipherdata.keylen;
-       cdb->sh_desc[1] = 0;
-       cdb->sh_desc[2] = 0;
-
        if (ses->auth_alg) {
                authdata.key = (size_t)ses->auth_key.data;
                authdata.keylen = ses->auth_key.length;
@@ -267,33 +262,17 @@ dpaa_sec_prep_pdcp_cdb(dpaa_sec_session *ses)
                authdata.algmode = ses->auth_key.algmode;
 
                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) {
+       if (rta_inline_pdcp_query(authdata.algtype,
+                               cipherdata.algtype,
+                               ses->pdcp.sn_size,
+                               ses->pdcp.hfn_ovd)) {
                cipherdata.key =
-                       (size_t)rte_dpaa_mem_vtop((void *)(size_t)cipherdata.key);
+                       (size_t)rte_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)rte_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)