crypto/octeontx2: support IPsec ESN and anti-replay
authorTejasree Kondoj <ktejasree@marvell.com>
Fri, 18 Dec 2020 14:14:10 +0000 (19:44 +0530)
committerAkhil Goyal <akhil.goyal@nxp.com>
Tue, 19 Jan 2021 17:05:17 +0000 (18:05 +0100)
Adding ESN and anti-replay support for lookaside IPsec.

Signed-off-by: Tejasree Kondoj <ktejasree@marvell.com>
Acked-by: Anoob Joseph <anoobj@marvell.com>
doc/guides/cryptodevs/octeontx2.rst
doc/guides/rel_notes/release_21_02.rst
drivers/crypto/octeontx2/otx2_cryptodev_ops.c
drivers/crypto/octeontx2/otx2_cryptodev_sec.c
drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h
drivers/crypto/octeontx2/otx2_ipsec_po.h
drivers/crypto/octeontx2/otx2_ipsec_po_ops.h

index 0a38b86..170f03d 100644 (file)
@@ -175,4 +175,6 @@ Features supported
 * IPv6
 * ESP
 * Tunnel mode
+* ESN
+* Anti-replay
 * AES-128/192/256-GCM
index be5ea43..81ace19 100644 (file)
@@ -76,6 +76,11 @@ New Features
 
   * Added inner UDP/IPv4 support for VXLAN IPv4 GSO.
 
+* **Updated the OCTEON TX2 crypto PMD.**
+
+  * Updated the OCTEON TX2 crypto PMD lookaside protocol offload for IPsec with
+    ESN and anti-replay support.
+
 
 Removed Items
 -------------
index 5f2ccc0..16aa7f4 100644 (file)
@@ -14,6 +14,7 @@
 #include "otx2_cryptodev_mbox.h"
 #include "otx2_cryptodev_ops.h"
 #include "otx2_cryptodev_ops_helper.h"
+#include "otx2_ipsec_anti_replay.h"
 #include "otx2_ipsec_po_ops.h"
 #include "otx2_mbox.h"
 #include "otx2_sec_idev.h"
@@ -650,21 +651,55 @@ static __rte_always_inline int __rte_hot
 otx2_cpt_enqueue_sec(struct otx2_cpt_qp *qp, struct rte_crypto_op *op,
                     struct pending_queue *pend_q)
 {
+       uint32_t winsz, esn_low = 0, esn_hi = 0, seql = 0, seqh = 0;
+       struct rte_mbuf *m_src = op->sym->m_src;
        struct otx2_sec_session_ipsec_lp *sess;
        struct otx2_ipsec_po_sa_ctl *ctl_wrd;
+       struct otx2_ipsec_po_in_sa *sa;
        struct otx2_sec_session *priv;
        struct cpt_request_info *req;
+       uint64_t seq_in_sa, seq = 0;
+       uint8_t esn;
        int ret;
 
        priv = get_sec_session_private_data(op->sym->sec_session);
        sess = &priv->ipsec.lp;
+       sa = &sess->in_sa;
 
-       ctl_wrd = &sess->in_sa.ctl;
+       ctl_wrd = &sa->ctl;
+       esn = ctl_wrd->esn_en;
+       winsz = sa->replay_win_sz;
 
        if (ctl_wrd->direction == OTX2_IPSEC_PO_SA_DIRECTION_OUTBOUND)
                ret = process_outb_sa(op, sess, &qp->meta_info, (void **)&req);
-       else
+       else {
+               if (winsz) {
+                       esn_low = rte_be_to_cpu_32(sa->esn_low);
+                       esn_hi = rte_be_to_cpu_32(sa->esn_hi);
+                       seql = *rte_pktmbuf_mtod_offset(m_src, uint32_t *,
+                               sizeof(struct rte_ipv4_hdr) + 4);
+                       seql = rte_be_to_cpu_32(seql);
+
+                       if (!esn)
+                               seq = (uint64_t)seql;
+                       else {
+                               seqh = anti_replay_get_seqh(winsz, seql, esn_hi,
+                                               esn_low);
+                               seq = ((uint64_t)seqh << 32) | seql;
+                       }
+
+                       if (unlikely(seq == 0))
+                               return IPSEC_ANTI_REPLAY_FAILED;
+
+                       ret = anti_replay_check(sa->replay, seq, winsz);
+                       if (unlikely(ret)) {
+                               otx2_err("Anti replay check failed");
+                               return IPSEC_ANTI_REPLAY_FAILED;
+                       }
+               }
+
                ret = process_inb_sa(op, sess, &qp->meta_info, (void **)&req);
+       }
 
        if (unlikely(ret)) {
                otx2_err("Crypto req : op %p, ret 0x%x", op, ret);
@@ -673,6 +708,14 @@ otx2_cpt_enqueue_sec(struct otx2_cpt_qp *qp, struct rte_crypto_op *op,
 
        ret = otx2_cpt_enqueue_req(qp, pend_q, req, sess->cpt_inst_w7);
 
+       if (winsz && esn) {
+               seq_in_sa = ((uint64_t)esn_hi << 32) | esn_low;
+               if (seq > seq_in_sa) {
+                       sa->esn_low = rte_cpu_to_be_32(seql);
+                       sa->esn_hi = rte_cpu_to_be_32(seqh);
+               }
+       }
+
        return ret;
 }
 
index bad9c5c..1f5645f 100644 (file)
@@ -213,6 +213,7 @@ crypto_sec_ipsec_outb_session_create(struct rte_cryptodev *crypto_dev,
        int ret;
 
        sess = get_sec_session_private_data(sec_sess);
+       sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
        lp = &sess->ipsec.lp;
 
        sa = &lp->out_sa;
@@ -351,6 +352,7 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev,
        int ret;
 
        sess = get_sec_session_private_data(sec_sess);
+       sess->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
        lp = &sess->ipsec.lp;
 
        sa = &lp->in_sa;
@@ -362,6 +364,7 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev,
        }
 
        memset(sa, 0, sizeof(struct otx2_ipsec_po_in_sa));
+       sa->replay_win_sz = ipsec->replay_win_sz;
 
        ret = ipsec_po_sa_ctl_set(ipsec, crypto_xform, ctl);
        if (ret)
@@ -414,6 +417,24 @@ crypto_sec_ipsec_inb_session_create(struct rte_cryptodev *crypto_dev,
        set_session_misc_attributes(lp, crypto_xform,
                                    auth_xform, cipher_xform);
 
+       if (sa->replay_win_sz) {
+               if (sa->replay_win_sz > OTX2_IPSEC_MAX_REPLAY_WIN_SZ) {
+                       otx2_err("Replay window size is not supported");
+                       return -ENOTSUP;
+               }
+               sa->replay = rte_zmalloc(NULL, sizeof(struct otx2_ipsec_replay),
+                               0);
+               if (sa->replay == NULL)
+                       return -ENOMEM;
+
+               /* Set window bottom to 1, base and top to size of window */
+               sa->replay->winb = 1;
+               sa->replay->wint = sa->replay_win_sz;
+               sa->replay->base = sa->replay_win_sz;
+               sa->esn_low = 0;
+               sa->esn_hi = 0;
+       }
+
        return otx2_cpt_enq_sa_write(lp, crypto_dev->data->queue_pairs[0],
                                     OTX2_IPSEC_PO_WRITE_IPSEC_INB);
 }
index d599692..b2b1f77 100644 (file)
@@ -204,4 +204,25 @@ cpt_ipsec_ip_antireplay_check(struct otx2_ipsec_fp_in_sa *sa, char *data)
 
        return ret;
 }
+
+static inline uint32_t
+anti_replay_get_seqh(uint32_t winsz, uint32_t seql,
+                       uint32_t esn_hi, uint32_t esn_low)
+{
+       uint32_t win_low = esn_low - winsz + 1;
+
+       if (esn_low > winsz - 1) {
+               /* Window is in one sequence number subspace */
+               if (seql > win_low)
+                       return esn_hi;
+               else
+                       return esn_hi + 1;
+       } else {
+               /* Window is split across two sequence number subspaces */
+               if (seql > win_low)
+                       return esn_hi - 1;
+               else
+                       return esn_hi;
+       }
+}
 #endif /* __OTX2_IPSEC_ANTI_REPLAY_H__ */
index da24f6a..6d25e29 100644 (file)
@@ -161,6 +161,11 @@ struct otx2_ipsec_po_in_sa {
                uint8_t hmac_key[48];
                struct otx2_ipsec_po_traffic_selector selector;
        } aes_gcm;
+       union {
+               struct otx2_ipsec_replay *replay;
+               uint64_t replay64;
+       };
+       uint32_t replay_win_sz;
 };
 
 struct otx2_ipsec_po_ip_template {
index bc702d5..c0c9361 100644 (file)
@@ -124,6 +124,8 @@ process_outb_sa(struct rte_crypto_op *cop,
        req->ist.ei1 = rte_pktmbuf_iova(m_src);
        req->ist.ei2 = req->ist.ei1;
 
+       sa->esn_hi = sess->seq_hi;
+
        hdr->seq = rte_cpu_to_be_32(sess->seq_lo);
        hdr->ip_id = rte_cpu_to_be_32(sess->ip_id);