Support for anti replay is added in OCTEON TX2 security PMD. The functionality has been tested with ipsec-secgw application running in inline protocol offload mode. Ankur Dwivedi (2): net/octeontx2: add anti replay support in security session net/octeontx2: add replay check for inline inbound packets .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++ drivers/crypto/octeontx2/otx2_ipsec_fp.h | 29 ++- drivers/crypto/octeontx2/otx2_security.h | 3 + drivers/net/octeontx2/otx2_ethdev_sec.c | 42 ++++ drivers/net/octeontx2/otx2_rx.h | 7 + 5 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h -- 2.28.0
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(-) diff --git a/drivers/crypto/octeontx2/otx2_ipsec_fp.h b/drivers/crypto/octeontx2/otx2_ipsec_fp.h index 52b3b41e2..a33041d77 100644 --- a/drivers/crypto/octeontx2/otx2_ipsec_fp.h +++ b/drivers/crypto/octeontx2/otx2_ipsec_fp.h @@ -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 diff --git a/drivers/crypto/octeontx2/otx2_security.h b/drivers/crypto/octeontx2/otx2_security.h index 086b50604..33d3b1515 100644 --- a/drivers/crypto/octeontx2/otx2_security.h +++ b/drivers/crypto/octeontx2/otx2_security.h @@ -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 { diff --git a/drivers/net/octeontx2/otx2_ethdev_sec.c b/drivers/net/octeontx2/otx2_ethdev_sec.c index a155594e2..af91e30f4 100644 --- a/drivers/net/octeontx2/otx2_ethdev_sec.c +++ b/drivers/net/octeontx2/otx2_ethdev_sec.c @@ -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); -- 2.28.0
The function handling anti replay is added. If replay window is enabled the rx packets will be validated against the window. The rx offload fails in case of error. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++ drivers/net/octeontx2/otx2_rx.h | 7 + 2 files changed, 215 insertions(+) create mode 100644 drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h diff --git a/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h new file mode 100644 index 000000000..44a1be426 --- /dev/null +++ b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2020 Marvell International Ltd. + */ + +#ifndef __OTX2_IPSEC_ANTI_REPLAY_H__ +#define __OTX2_IPSEC_ANTI_REPLAY_H__ + +#include <rte_mbuf.h> + +#include "otx2_ipsec_fp.h" + +#define WORD_SHIFT 6 +#define WORD_SIZE (1 << WORD_SHIFT) +#define WORD_MASK (WORD_SIZE - 1) + +#define IPSEC_ANTI_REPLAY_FAILED (-1) + +static inline int +anti_replay_check(uint64_t seq, struct otx2_ipsec_fp_in_sa *sa) +{ + struct otx2_ipsec_replay *replay = sa->replay; + uint64_t *window = &replay->window[0]; + uint64_t winsz = sa->replay_win_sz; + uint64_t ex_winsz = winsz + WORD_SIZE; + uint64_t winwords = ex_winsz >> WORD_SHIFT; + uint64_t base = replay->base; + uint32_t winb = replay->winb; + uint32_t wint = replay->wint; + uint64_t seqword, shiftwords; + uint64_t shift = 0; + uint64_t bit_pos; + uint64_t tmp = 0; + uint64_t *wptr; + + if (winsz > 64) + goto slow_shift; + /* Check if the seq is the biggest one yet */ + if (likely(seq > base)) { + shift = seq - base; + if (shift < winsz) { /* In window */ + /* + * If more than 64-bit anti-replay window, + * use slow shift routine + */ + wptr = window + (shift >> WORD_SHIFT); + *wptr <<= shift; + *wptr |= 1ull; + } else { + /* No special handling of window size > 64 */ + wptr = window + ((winsz - 1) >> WORD_SHIFT); + /* + * Zero out the whole window (especially for + * bigger than 64b window) till the last 64b word + * as the incoming sequence number minus + * base sequence is more than the window size. + */ + while (window != wptr) + *window++ = 0ull; + /* + * Set the last bit (of the window) to 1 + * as that corresponds to the base sequence number. + * Now any incoming sequence number which is + * (base - window size - 1) will pass anti-replay check + */ + *wptr = 1ull; + } + /* + * Set the base to incoming sequence number as + * that is the biggest sequence number seen yet + */ + replay->base = seq; + return 0; + } + + bit_pos = base - seq; + + /* If seq falls behind the window, return failure */ + if (bit_pos >= winsz) + return IPSEC_ANTI_REPLAY_FAILED; + + /* seq is within anti-replay window */ + wptr = window + ((winsz - bit_pos - 1) >> WORD_SHIFT); + bit_pos &= WORD_MASK; + + /* Check if this is a replayed packet */ + if (*wptr & ((1ull) << bit_pos)) + return IPSEC_ANTI_REPLAY_FAILED; + + /* mark as seen */ + *wptr |= ((1ull) << bit_pos); + return 0; + +slow_shift: + if (likely(seq > base)) { + uint32_t i; + + shift = seq - base; + if (unlikely(shift >= winsz)) { + /* + * shift is bigger than the window, + * so just zero out everything + */ + for (i = 0; i < winwords; i++) + window[i] = 0; +winupdate: + /* Find out the word */ + seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; + + /* Find out the bit in the word */ + bit_pos = (seq - 1) & WORD_MASK; + + /* + * Set the bit corresponding to sequence number + * in window to mark it as received + */ + window[seqword] |= (1ull << (63 - bit_pos)); + + /* wint and winb range from 1 to ex_winsz */ + replay->wint = ((wint + shift - 1) % ex_winsz) + 1; + replay->winb = ((winb + shift - 1) % ex_winsz) + 1; + + replay->base = seq; + return 0; + } + + /* + * New sequence number is bigger than the base but + * it's not bigger than base + window size + */ + + shiftwords = ((wint + shift - 1) >> WORD_SHIFT) - + ((wint - 1) >> WORD_SHIFT); + if (unlikely(shiftwords)) { + tmp = (wint + WORD_SIZE - 1) / WORD_SIZE; + for (i = 0; i < shiftwords; i++) { + tmp %= winwords; + window[tmp++] = 0; + } + } + + goto winupdate; + } + + /* Sequence number is before the window */ + if (unlikely((seq + winsz) <= base)) + return IPSEC_ANTI_REPLAY_FAILED; + + /* Sequence number is within the window */ + + /* Find out the word */ + seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; + + /* Find out the bit in the word */ + bit_pos = (seq - 1) & WORD_MASK; + + /* Check if this is a replayed packet */ + if (window[seqword] & (1ull << (63 - bit_pos))) + return IPSEC_ANTI_REPLAY_FAILED; + + /* + * Set the bit corresponding to sequence number + * in window to mark it as received + */ + window[seqword] |= (1ull << (63 - bit_pos)); + + return 0; +} + +static int +cpt_ipsec_antireplay_check(struct otx2_ipsec_fp_in_sa *sa, char *data) +{ + uint64_t seq_in_sa = 0; + uint32_t seqh = 0; + uint32_t seql; + uint64_t seq; + uint8_t esn; + int ret; + + esn = sa->ctl.esn_en; + seql = rte_be_to_cpu_32(*((uint32_t *)(data + + OTX2_IPSEC_SEQNO_LO_INDEX))); + + if (!esn) + seq = (uint64_t)seql; + else { + seqh = rte_be_to_cpu_32(*((uint32_t *)(data + + OTX2_IPSEC_SEQNO_HI_INDEX))); + seq = ((uint64_t)seqh << 32) | seql; + } + + if (unlikely(seq == 0)) + return IPSEC_ANTI_REPLAY_FAILED; + + rte_spinlock_lock(&sa->replay->lock); + ret = anti_replay_check(seq, sa); + if (esn && (ret == 0)) { + seq_in_sa = ((uint64_t)rte_be_to_cpu_32(sa->esn_hi) << 32) | + rte_be_to_cpu_32(sa->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); + } + } + rte_spinlock_unlock(&sa->replay->lock); + + return ret; +} +#endif /* __OTX2_IPSEC_ANTI_REPLAY_H__ */ diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h index d8648b692..f29a0542f 100644 --- a/drivers/net/octeontx2/otx2_rx.h +++ b/drivers/net/octeontx2/otx2_rx.h @@ -9,6 +9,7 @@ #include "otx2_common.h" #include "otx2_ethdev_sec.h" +#include "otx2_ipsec_anti_replay.h" #include "otx2_ipsec_fp.h" /* Default mark value used when none is provided. */ @@ -243,6 +244,12 @@ nix_rx_sec_mbuf_update(const struct nix_cqe_hdr_s *cq, struct rte_mbuf *m, m->udata64 = (uint64_t)sa->userdata; data = rte_pktmbuf_mtod(m, char *); + + if (sa->replay_win_sz) { + if (cpt_ipsec_antireplay_check(sa, data) < 0) + return PKT_RX_SEC_OFFLOAD | PKT_RX_SEC_OFFLOAD_FAILED; + } + memcpy(data + INLINE_INB_RPTR_HDR, data, RTE_ETHER_HDR_LEN); m->data_off += INLINE_INB_RPTR_HDR; -- 2.28.0
>
> Support for anti replay is added in OCTEON TX2 security PMD.
> The functionality has been tested with ipsec-secgw application running in
> inline protocol offload mode.
>
> Ankur Dwivedi (2):
> net/octeontx2: add anti replay support in security session
> net/octeontx2: add replay check for inline inbound packets
>
Series Acked-by: Anoob Joseph <anoobj@marvell.com>
Support for anti replay is added in OCTEON TX2 security PMD. The functionality has been tested with ipsec-secgw application running in inline protocol offload mode. v2: * In the "net/octeontx2: add replay check for inline inbound packets" patch, few local variables are explicitly initialized to zero which is not required. So removing the initialization in v2. Ankur Dwivedi (2): net/octeontx2: add anti replay support in security session net/octeontx2: add replay check for inline inbound packets .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++ drivers/crypto/octeontx2/otx2_ipsec_fp.h | 29 ++- drivers/crypto/octeontx2/otx2_security.h | 3 + drivers/net/octeontx2/otx2_ethdev_sec.c | 42 ++++ drivers/net/octeontx2/otx2_rx.h | 7 + 5 files changed, 286 insertions(+), 3 deletions(-) create mode 100644 drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h -- 2.28.0
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(-) diff --git a/drivers/crypto/octeontx2/otx2_ipsec_fp.h b/drivers/crypto/octeontx2/otx2_ipsec_fp.h index 52b3b41e2..a33041d77 100644 --- a/drivers/crypto/octeontx2/otx2_ipsec_fp.h +++ b/drivers/crypto/octeontx2/otx2_ipsec_fp.h @@ -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 diff --git a/drivers/crypto/octeontx2/otx2_security.h b/drivers/crypto/octeontx2/otx2_security.h index 086b50604..33d3b1515 100644 --- a/drivers/crypto/octeontx2/otx2_security.h +++ b/drivers/crypto/octeontx2/otx2_security.h @@ -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 { diff --git a/drivers/net/octeontx2/otx2_ethdev_sec.c b/drivers/net/octeontx2/otx2_ethdev_sec.c index a155594e2..af91e30f4 100644 --- a/drivers/net/octeontx2/otx2_ethdev_sec.c +++ b/drivers/net/octeontx2/otx2_ethdev_sec.c @@ -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); -- 2.28.0
The function handling anti replay is added. If replay window is enabled the rx packets will be validated against the window. The rx offload fails in case of error. Signed-off-by: Ankur Dwivedi <adwivedi@marvell.com> --- .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++ drivers/net/octeontx2/otx2_rx.h | 7 + 2 files changed, 215 insertions(+) create mode 100644 drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h diff --git a/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h new file mode 100644 index 000000000..858ce5b15 --- /dev/null +++ b/drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h @@ -0,0 +1,208 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright (C) 2020 Marvell International Ltd. + */ + +#ifndef __OTX2_IPSEC_ANTI_REPLAY_H__ +#define __OTX2_IPSEC_ANTI_REPLAY_H__ + +#include <rte_mbuf.h> + +#include "otx2_ipsec_fp.h" + +#define WORD_SHIFT 6 +#define WORD_SIZE (1 << WORD_SHIFT) +#define WORD_MASK (WORD_SIZE - 1) + +#define IPSEC_ANTI_REPLAY_FAILED (-1) + +static inline int +anti_replay_check(uint64_t seq, struct otx2_ipsec_fp_in_sa *sa) +{ + struct otx2_ipsec_replay *replay = sa->replay; + uint64_t *window = &replay->window[0]; + uint64_t winsz = sa->replay_win_sz; + uint64_t ex_winsz = winsz + WORD_SIZE; + uint64_t winwords = ex_winsz >> WORD_SHIFT; + uint64_t base = replay->base; + uint32_t winb = replay->winb; + uint32_t wint = replay->wint; + uint64_t seqword, shiftwords; + uint64_t bit_pos; + uint64_t shift; + uint64_t *wptr; + uint64_t tmp; + + if (winsz > 64) + goto slow_shift; + /* Check if the seq is the biggest one yet */ + if (likely(seq > base)) { + shift = seq - base; + if (shift < winsz) { /* In window */ + /* + * If more than 64-bit anti-replay window, + * use slow shift routine + */ + wptr = window + (shift >> WORD_SHIFT); + *wptr <<= shift; + *wptr |= 1ull; + } else { + /* No special handling of window size > 64 */ + wptr = window + ((winsz - 1) >> WORD_SHIFT); + /* + * Zero out the whole window (especially for + * bigger than 64b window) till the last 64b word + * as the incoming sequence number minus + * base sequence is more than the window size. + */ + while (window != wptr) + *window++ = 0ull; + /* + * Set the last bit (of the window) to 1 + * as that corresponds to the base sequence number. + * Now any incoming sequence number which is + * (base - window size - 1) will pass anti-replay check + */ + *wptr = 1ull; + } + /* + * Set the base to incoming sequence number as + * that is the biggest sequence number seen yet + */ + replay->base = seq; + return 0; + } + + bit_pos = base - seq; + + /* If seq falls behind the window, return failure */ + if (bit_pos >= winsz) + return IPSEC_ANTI_REPLAY_FAILED; + + /* seq is within anti-replay window */ + wptr = window + ((winsz - bit_pos - 1) >> WORD_SHIFT); + bit_pos &= WORD_MASK; + + /* Check if this is a replayed packet */ + if (*wptr & ((1ull) << bit_pos)) + return IPSEC_ANTI_REPLAY_FAILED; + + /* mark as seen */ + *wptr |= ((1ull) << bit_pos); + return 0; + +slow_shift: + if (likely(seq > base)) { + uint32_t i; + + shift = seq - base; + if (unlikely(shift >= winsz)) { + /* + * shift is bigger than the window, + * so just zero out everything + */ + for (i = 0; i < winwords; i++) + window[i] = 0; +winupdate: + /* Find out the word */ + seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; + + /* Find out the bit in the word */ + bit_pos = (seq - 1) & WORD_MASK; + + /* + * Set the bit corresponding to sequence number + * in window to mark it as received + */ + window[seqword] |= (1ull << (63 - bit_pos)); + + /* wint and winb range from 1 to ex_winsz */ + replay->wint = ((wint + shift - 1) % ex_winsz) + 1; + replay->winb = ((winb + shift - 1) % ex_winsz) + 1; + + replay->base = seq; + return 0; + } + + /* + * New sequence number is bigger than the base but + * it's not bigger than base + window size + */ + + shiftwords = ((wint + shift - 1) >> WORD_SHIFT) - + ((wint - 1) >> WORD_SHIFT); + if (unlikely(shiftwords)) { + tmp = (wint + WORD_SIZE - 1) / WORD_SIZE; + for (i = 0; i < shiftwords; i++) { + tmp %= winwords; + window[tmp++] = 0; + } + } + + goto winupdate; + } + + /* Sequence number is before the window */ + if (unlikely((seq + winsz) <= base)) + return IPSEC_ANTI_REPLAY_FAILED; + + /* Sequence number is within the window */ + + /* Find out the word */ + seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; + + /* Find out the bit in the word */ + bit_pos = (seq - 1) & WORD_MASK; + + /* Check if this is a replayed packet */ + if (window[seqword] & (1ull << (63 - bit_pos))) + return IPSEC_ANTI_REPLAY_FAILED; + + /* + * Set the bit corresponding to sequence number + * in window to mark it as received + */ + window[seqword] |= (1ull << (63 - bit_pos)); + + return 0; +} + +static int +cpt_ipsec_antireplay_check(struct otx2_ipsec_fp_in_sa *sa, char *data) +{ + uint64_t seq_in_sa; + uint32_t seqh = 0; + uint32_t seql; + uint64_t seq; + uint8_t esn; + int ret; + + esn = sa->ctl.esn_en; + seql = rte_be_to_cpu_32(*((uint32_t *)(data + + OTX2_IPSEC_SEQNO_LO_INDEX))); + + if (!esn) + seq = (uint64_t)seql; + else { + seqh = rte_be_to_cpu_32(*((uint32_t *)(data + + OTX2_IPSEC_SEQNO_HI_INDEX))); + seq = ((uint64_t)seqh << 32) | seql; + } + + if (unlikely(seq == 0)) + return IPSEC_ANTI_REPLAY_FAILED; + + rte_spinlock_lock(&sa->replay->lock); + ret = anti_replay_check(seq, sa); + if (esn && (ret == 0)) { + seq_in_sa = ((uint64_t)rte_be_to_cpu_32(sa->esn_hi) << 32) | + rte_be_to_cpu_32(sa->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); + } + } + rte_spinlock_unlock(&sa->replay->lock); + + return ret; +} +#endif /* __OTX2_IPSEC_ANTI_REPLAY_H__ */ diff --git a/drivers/net/octeontx2/otx2_rx.h b/drivers/net/octeontx2/otx2_rx.h index d8648b692..f29a0542f 100644 --- a/drivers/net/octeontx2/otx2_rx.h +++ b/drivers/net/octeontx2/otx2_rx.h @@ -9,6 +9,7 @@ #include "otx2_common.h" #include "otx2_ethdev_sec.h" +#include "otx2_ipsec_anti_replay.h" #include "otx2_ipsec_fp.h" /* Default mark value used when none is provided. */ @@ -243,6 +244,12 @@ nix_rx_sec_mbuf_update(const struct nix_cqe_hdr_s *cq, struct rte_mbuf *m, m->udata64 = (uint64_t)sa->userdata; data = rte_pktmbuf_mtod(m, char *); + + if (sa->replay_win_sz) { + if (cpt_ipsec_antireplay_check(sa, data) < 0) + return PKT_RX_SEC_OFFLOAD | PKT_RX_SEC_OFFLOAD_FAILED; + } + memcpy(data + INLINE_INB_RPTR_HDR, data, RTE_ETHER_HDR_LEN); m->data_off += INLINE_INB_RPTR_HDR; -- 2.28.0
On Fri, Sep 18, 2020 at 10:01 AM Anoob Joseph <anoobj@marvell.com> wrote:
>
> >
> > Support for anti replay is added in OCTEON TX2 security PMD.
> > The functionality has been tested with ipsec-secgw application running in
> > inline protocol offload mode.
> >
> > Ankur Dwivedi (2):
> > net/octeontx2: add anti replay support in security session
> > net/octeontx2: add replay check for inline inbound packets
> >
>
> Series Acked-by: Anoob Joseph <anoobj@marvell.com>
Wrt ethdev driver changes,
Reviewed-by: Jerin Jacob <jerinj@marvell.com>
Changed the delegate to Akhil as needs to pull through crypto-next.
Hi Akhil,
Please let me know if you have any review comments on this patch series.
Thanks
Ankur
>-----Original Message-----
>From: Ankur Dwivedi <adwivedi@marvell.com>
>Sent: Friday, September 18, 2020 4:40 PM
>To: dev@dpdk.org
>Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; akhil.goyal@nxp.com;
>radu.nicolau@intel.com; Anoob Joseph <anoobj@marvell.com>; Ankur
>Dwivedi <adwivedi@marvell.com>
>Subject: [PATCH v2 0/2] add anti replay support in OCTEON TX2 security
>
>Support for anti replay is added in OCTEON TX2 security PMD.
>The functionality has been tested with ipsec-secgw application running in
>inline protocol offload mode.
>
>v2:
>* In the "net/octeontx2: add replay check for inline inbound packets"
> patch, few local variables are explicitly initialized to zero which
> is not required. So removing the initialization in v2.
>
>Ankur Dwivedi (2):
> net/octeontx2: add anti replay support in security session
> net/octeontx2: add replay check for inline inbound packets
>
> .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++
> drivers/crypto/octeontx2/otx2_ipsec_fp.h | 29 ++-
> drivers/crypto/octeontx2/otx2_security.h | 3 +
> drivers/net/octeontx2/otx2_ethdev_sec.c | 42 ++++
> drivers/net/octeontx2/otx2_rx.h | 7 +
> 5 files changed, 286 insertions(+), 3 deletions(-) create mode 100644
>drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h
>
>--
>2.28.0
Adding Akhil in the to list of the email.
>-----Original Message-----
>From: Ankur Dwivedi
>Sent: Friday, October 9, 2020 7:17 PM
>To: 'Ankur Dwivedi' <adwivedi@marvell.com>; dev@dpdk.org
>Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; akhil.goyal@nxp.com;
>radu.nicolau@intel.com; Anoob Joseph <anoobj@marvell.com>
>Subject: RE: [PATCH v2 0/2] add anti replay support in OCTEON TX2 security
>
>Hi Akhil,
>
>Please let me know if you have any review comments on this patch series.
>
>Thanks
>Ankur
>
>>-----Original Message-----
>>From: Ankur Dwivedi <adwivedi@marvell.com>
>>Sent: Friday, September 18, 2020 4:40 PM
>>To: dev@dpdk.org
>>Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>;
>>akhil.goyal@nxp.com; radu.nicolau@intel.com; Anoob Joseph
>><anoobj@marvell.com>; Ankur Dwivedi <adwivedi@marvell.com>
>>Subject: [PATCH v2 0/2] add anti replay support in OCTEON TX2 security
>>
>>Support for anti replay is added in OCTEON TX2 security PMD.
>>The functionality has been tested with ipsec-secgw application running
>>in inline protocol offload mode.
>>
>>v2:
>>* In the "net/octeontx2: add replay check for inline inbound packets"
>> patch, few local variables are explicitly initialized to zero which
>> is not required. So removing the initialization in v2.
>>
>>Ankur Dwivedi (2):
>> net/octeontx2: add anti replay support in security session
>> net/octeontx2: add replay check for inline inbound packets
>>
>> .../crypto/octeontx2/otx2_ipsec_anti_replay.h | 208 ++++++++++++++++++
>> drivers/crypto/octeontx2/otx2_ipsec_fp.h | 29 ++-
>> drivers/crypto/octeontx2/otx2_security.h | 3 +
>> drivers/net/octeontx2/otx2_ethdev_sec.c | 42 ++++
>> drivers/net/octeontx2/otx2_rx.h | 7 +
>> 5 files changed, 286 insertions(+), 3 deletions(-) create mode 100644
>>drivers/crypto/octeontx2/otx2_ipsec_anti_replay.h
>>
>>--
>>2.28.0
Hi Ankur,
> >Hi Akhil,
> >
> >Please let me know if you have any review comments on this patch series.
> >
I am working on the crypto tree. These patches are in my back log and
will let you know if I face some issues.
These patches are PMD patches and are 2nd on my priority list and can go in RC2.
However will try my best to accommodate most of the patches in RC1.
Regards,
Akhil
Hi Akhil, >-----Original Message----- >From: Akhil Goyal <akhil.goyal@nxp.com> >Sent: Friday, October 9, 2020 8:24 PM >To: Ankur Dwivedi <adwivedi@marvell.com>; dev@dpdk.org >Cc: Jerin Jacob Kollanukkaran <jerinj@marvell.com>; radu.nicolau@intel.com; >Anoob Joseph <anoobj@marvell.com> >Subject: [EXT] RE: [PATCH v2 0/2] add anti replay support in OCTEON TX2 >security > >External Email > >---------------------------------------------------------------------- >Hi Ankur, > > >> >Hi Akhil, >> > >> >Please let me know if you have any review comments on this patch series. >> > > >I am working on the crypto tree. These patches are in my back log and will let >you know if I face some issues. >These patches are PMD patches and are 2nd on my priority list and can go in >RC2. >However will try my best to accommodate most of the patches in RC1. > Thanks for the information. Regards Ankur >Regards, >Akhil
> >
> >> >Hi Akhil,
> >> >
> >> >Please let me know if you have any review comments on this patch series.
> >> >
> >
> >I am working on the crypto tree. These patches are in my back log and will let
> >you know if I face some issues.
> >These patches are PMD patches and are 2nd on my priority list and can go in
> >RC2.
> >However will try my best to accommodate most of the patches in RC1.
> >
> Thanks for the information.
>
Series Applied to dpdk-next-crypto
Thanks.