[v2,1/2] net/octeontx2: add anti replay support in security session
Checks
Commit Message
Initialize the inbound session for anti replay. The replay
window is allocated during session create and freed in session destroy.
Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com>
---
drivers/crypto/octeontx2/otx2_ipsec_fp.h | 29 ++++++++++++++--
drivers/crypto/octeontx2/otx2_security.h | 3 ++
drivers/net/octeontx2/otx2_ethdev_sec.c | 42 ++++++++++++++++++++++++
3 files changed, 71 insertions(+), 3 deletions(-)
@@ -8,6 +8,17 @@
#include <rte_crypto_sym.h>
#include <rte_security.h>
+/* Macros for anti replay and ESN */
+#define OTX2_IPSEC_MAX_REPLAY_WIN_SZ 1024
+#define OTX2_IPSEC_SAINDEX_SZ 4
+#define OTX2_IPSEC_SEQNO_LO 4
+
+#define OTX2_IPSEC_SEQNO_LO_INDEX (RTE_ETHER_HDR_LEN + \
+ OTX2_IPSEC_SAINDEX_SZ)
+
+#define OTX2_IPSEC_SEQNO_HI_INDEX (OTX2_IPSEC_SEQNO_LO_INDEX + \
+ OTX2_IPSEC_SEQNO_LO)
+
enum {
OTX2_IPSEC_FP_SA_DIRECTION_INBOUND = 0,
OTX2_IPSEC_FP_SA_DIRECTION_OUTBOUND = 1,
@@ -105,6 +116,14 @@ struct otx2_ipsec_fp_out_sa {
uint8_t hmac_key[48];
};
+struct otx2_ipsec_replay {
+ rte_spinlock_t lock;
+ uint32_t winb;
+ uint32_t wint;
+ uint64_t base; /**< base of the anti-replay window */
+ uint64_t window[17]; /**< anti-replay window */
+};
+
struct otx2_ipsec_fp_in_sa {
/* w0 */
struct otx2_ipsec_fp_sa_ctl ctl;
@@ -114,8 +133,8 @@ struct otx2_ipsec_fp_in_sa {
uint32_t unused;
/* w2 */
- uint32_t esn_low;
uint32_t esn_hi;
+ uint32_t esn_low;
/* w3-w6 */
uint8_t cipher_key[32];
@@ -128,9 +147,13 @@ struct otx2_ipsec_fp_in_sa {
void *userdata;
uint64_t udata64;
};
+ union {
+ struct otx2_ipsec_replay *replay;
+ uint64_t replay64;
+ };
+ uint32_t replay_win_sz;
- uint64_t reserved1;
- uint64_t reserved2;
+ uint32_t reserved1;
};
static inline int
@@ -5,6 +5,8 @@
#ifndef __OTX2_SECURITY_H__
#define __OTX2_SECURITY_H__
+#include <rte_security.h>
+
#include "otx2_cryptodev_sec.h"
#include "otx2_ethdev_sec.h"
@@ -20,6 +22,7 @@
union otx2_sec_session_ipsec {
struct otx2_sec_session_ipsec_ip ip;
struct otx2_sec_session_ipsec_lp lp;
+ enum rte_security_ipsec_sa_direction dir;
};
struct otx2_sec_session {
@@ -360,6 +360,7 @@ eth_sec_ipsec_out_sess_create(struct rte_eth_dev *eth_dev,
struct otx2_cpt_qp *qp;
priv = get_sec_session_private_data(sec_sess);
+ priv->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_EGRESS;
sess = &priv->ipsec.ip;
sa = &sess->out_sa;
@@ -482,6 +483,7 @@ eth_sec_ipsec_in_sess_create(struct rte_eth_dev *eth_dev,
ctl = &sa->ctl;
priv = get_sec_session_private_data(sec_sess);
+ priv->ipsec.dir = RTE_SECURITY_IPSEC_SA_DIR_INGRESS;
sess = &priv->ipsec.ip;
if (ctl->valid) {
@@ -519,6 +521,8 @@ eth_sec_ipsec_in_sess_create(struct rte_eth_dev *eth_dev,
sa->userdata = priv->userdata;
+ sa->replay_win_sz = ipsec->replay_win_sz;
+
if (lookup_mem_sa_index_update(eth_dev, ipsec->spi, sa))
return -EINVAL;
@@ -533,7 +537,32 @@ eth_sec_ipsec_in_sess_create(struct rte_eth_dev *eth_dev,
return ret;
ret = hmac_init(ctl, qp, auth_key, auth_key_len, sa->hmac_key);
otx2_sec_idev_tx_cpt_qp_put(qp);
+ if (ret)
+ return ret;
}
+
+ 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;
+
+ rte_spinlock_init(&sa->replay->lock);
+ /*
+ * 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 ret;
}
@@ -600,6 +629,15 @@ otx2_eth_sec_session_create(void *device,
return ret;
}
+static void
+otx2_eth_sec_free_anti_replay(struct otx2_ipsec_fp_in_sa *sa)
+{
+ if (sa != NULL) {
+ if (sa->replay_win_sz && sa->replay)
+ rte_free(sa->replay);
+ }
+}
+
static int
otx2_eth_sec_session_destroy(void *device __rte_unused,
struct rte_security_session *sess)
@@ -615,6 +653,10 @@ otx2_eth_sec_session_destroy(void *device __rte_unused,
sess_ip = &priv->ipsec.ip;
+ /* Release the anti replay window */
+ if (priv->ipsec.dir == RTE_SECURITY_IPSEC_SA_DIR_INGRESS)
+ otx2_eth_sec_free_anti_replay(sess_ip->in_sa);
+
/* Release CPT LF used for this session */
if (sess_ip->qp != NULL) {
ret = otx2_sec_idev_tx_cpt_qp_put(sess_ip->qp);