crypto/dpaax_sec: support PDCP U-Plane with integrity
authorVakul Garg <vakul.garg@nxp.com>
Mon, 30 Sep 2019 14:40:42 +0000 (20:10 +0530)
committerAkhil Goyal <akhil.goyal@nxp.com>
Wed, 9 Oct 2019 09:50:12 +0000 (11:50 +0200)
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
drivers/crypto/dpaa2_sec/hw/desc/pdcp.h
drivers/crypto/dpaa_sec/dpaa_sec.c

index fae2168..75a4fe0 100644 (file)
@@ -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) {
index 607c587..a636640 100644 (file)
@@ -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;
index d29e563..059d440 100644 (file)
@@ -386,6 +386,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
@@ -418,7 +419,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;
@@ -443,32 +448,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,
@@ -490,25 +499,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,
@@ -517,7 +507,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,
@@ -526,7 +516,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;
@@ -2389,7 +2379,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) {
@@ -2397,25 +2386,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;