Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright(C) 2021 Marvell. 3 : : */ 4 : : 5 : : #ifndef __CNXK_SECURITY_AR_H__ 6 : : #define __CNXK_SECURITY_AR_H__ 7 : : 8 : : #include <rte_mbuf.h> 9 : : 10 : : #include "cnxk_security.h" 11 : : 12 : : #define CNXK_ON_AR_WIN_SIZE_MAX 1024 13 : : 14 : : /* u64 array size to fit anti replay window bits */ 15 : : #define AR_WIN_ARR_SZ \ 16 : : (PLT_ALIGN_CEIL(CNXK_ON_AR_WIN_SIZE_MAX + 1, BITS_PER_LONG_LONG) / \ 17 : : BITS_PER_LONG_LONG) 18 : : 19 : : #define WORD_SHIFT 6 20 : : #define WORD_SIZE (1ULL << WORD_SHIFT) 21 : : #define WORD_MASK (WORD_SIZE - 1) 22 : : 23 : : #define IPSEC_ANTI_REPLAY_FAILED (-1) 24 : : 25 : : struct cnxk_on_ipsec_ar { 26 : : rte_spinlock_t lock; 27 : : uint32_t winb; 28 : : uint32_t wint; 29 : : uint64_t base; /**< base of the anti-replay window */ 30 : : uint64_t window[AR_WIN_ARR_SZ]; /**< anti-replay window */ 31 : : }; 32 : : 33 : : static inline uint32_t 34 : : cnxk_on_anti_replay_get_seqh(uint32_t winsz, uint32_t seql, uint32_t esn_hi, 35 : : uint32_t esn_low) 36 : : { 37 : : uint32_t win_low = esn_low - winsz + 1; 38 : : 39 : : if (esn_low > winsz - 1) { 40 : : /* Window is in one sequence number subspace */ 41 : : if (seql > win_low) 42 : : return esn_hi; 43 : : else 44 : : return esn_hi + 1; 45 : : } else { 46 : : /* Window is split across two sequence number subspaces */ 47 : : if (seql > win_low) 48 : : return esn_hi - 1; 49 : : else 50 : : return esn_hi; 51 : : } 52 : : } 53 : : 54 : : static inline int 55 : 0 : cnxk_on_anti_replay_check(uint64_t seq, struct cnxk_on_ipsec_ar *ar, 56 : : uint32_t winsz) 57 : : { 58 : 0 : uint64_t ex_winsz = winsz + WORD_SIZE; 59 : 0 : uint64_t *window = &ar->window[0]; 60 : : uint64_t seqword, shiftwords; 61 : 0 : uint64_t base = ar->base; 62 : 0 : uint32_t winb = ar->winb; 63 : 0 : uint32_t wint = ar->wint; 64 : : uint64_t winwords; 65 : : uint64_t bit_pos; 66 : : uint64_t shift; 67 : : uint64_t *wptr; 68 : : uint64_t tmp; 69 : : 70 : 0 : winwords = ex_winsz >> WORD_SHIFT; 71 [ # # ]: 0 : if (winsz > 64) 72 : 0 : goto slow_shift; 73 : : /* Check if the seq is the biggest one yet */ 74 [ # # ]: 0 : if (likely(seq > base)) { 75 : 0 : shift = seq - base; 76 [ # # ]: 0 : if (shift < winsz) { /* In window */ 77 : : /* 78 : : * If more than 64-bit anti-replay window, 79 : : * use slow shift routine 80 : : */ 81 : 0 : wptr = window + (shift >> WORD_SHIFT); 82 : 0 : *wptr <<= shift; 83 : 0 : *wptr |= 1ull; 84 : : } else { 85 : : /* No special handling of window size > 64 */ 86 : 0 : wptr = window + ((winsz - 1) >> WORD_SHIFT); 87 : : /* 88 : : * Zero out the whole window (especially for 89 : : * bigger than 64b window) till the last 64b word 90 : : * as the incoming sequence number minus 91 : : * base sequence is more than the window size. 92 : : */ 93 [ # # ]: 0 : while (window != wptr) 94 : 0 : *window++ = 0ull; 95 : : /* 96 : : * Set the last bit (of the window) to 1 97 : : * as that corresponds to the base sequence number. 98 : : * Now any incoming sequence number which is 99 : : * (base - window size - 1) will pass anti-replay check 100 : : */ 101 : 0 : *wptr = 1ull; 102 : : } 103 : : /* 104 : : * Set the base to incoming sequence number as 105 : : * that is the biggest sequence number seen yet 106 : : */ 107 : 0 : ar->base = seq; 108 : 0 : return 0; 109 : : } 110 : : 111 : 0 : bit_pos = base - seq; 112 : : 113 : : /* If seq falls behind the window, return failure */ 114 [ # # ]: 0 : if (bit_pos >= winsz) 115 : : return IPSEC_ANTI_REPLAY_FAILED; 116 : : 117 : : /* seq is within anti-replay window */ 118 : 0 : wptr = window + ((winsz - bit_pos - 1) >> WORD_SHIFT); 119 : 0 : bit_pos &= WORD_MASK; 120 : : 121 : : /* Check if this is a replayed packet */ 122 [ # # ]: 0 : if (*wptr & ((1ull) << bit_pos)) 123 : : return IPSEC_ANTI_REPLAY_FAILED; 124 : : 125 : : /* mark as seen */ 126 : 0 : *wptr |= ((1ull) << bit_pos); 127 : 0 : return 0; 128 : : 129 : : slow_shift: 130 [ # # ]: 0 : if (likely(seq > base)) { 131 : : uint32_t i; 132 : : 133 : 0 : shift = seq - base; 134 [ # # ]: 0 : if (unlikely(shift >= winsz)) { 135 : : /* 136 : : * shift is bigger than the window, 137 : : * so just zero out everything 138 : : */ 139 [ # # ]: 0 : for (i = 0; i < winwords; i++) 140 : 0 : window[i] = 0; 141 : 0 : winupdate: 142 : : /* Find out the word */ 143 : 0 : seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; 144 : : 145 : : /* Find out the bit in the word */ 146 : 0 : bit_pos = (seq - 1) & WORD_MASK; 147 : : 148 : : /* 149 : : * Set the bit corresponding to sequence number 150 : : * in window to mark it as received 151 : : */ 152 : 0 : window[seqword] |= (1ull << (63 - bit_pos)); 153 : : 154 : : /* wint and winb range from 1 to ex_winsz */ 155 : 0 : ar->wint = ((wint + shift - 1) % ex_winsz) + 1; 156 : 0 : ar->winb = ((winb + shift - 1) % ex_winsz) + 1; 157 : : 158 : 0 : ar->base = seq; 159 : 0 : return 0; 160 : : } 161 : : 162 : : /* 163 : : * New sequence number is bigger than the base but 164 : : * it's not bigger than base + window size 165 : : */ 166 : : 167 : 0 : shiftwords = ((wint + shift - 1) >> WORD_SHIFT) - 168 : 0 : ((wint - 1) >> WORD_SHIFT); 169 [ # # ]: 0 : if (unlikely(shiftwords)) { 170 : 0 : tmp = (wint + WORD_SIZE - 1) / WORD_SIZE; 171 [ # # ]: 0 : for (i = 0; i < shiftwords; i++) { 172 : 0 : tmp %= winwords; 173 : 0 : window[tmp++] = 0; 174 : : } 175 : : } 176 : : 177 : 0 : goto winupdate; 178 : : } 179 : : 180 : : /* Sequence number is before the window */ 181 [ # # ]: 0 : if (unlikely((seq + winsz) <= base)) 182 : : return IPSEC_ANTI_REPLAY_FAILED; 183 : : 184 : : /* Sequence number is within the window */ 185 : : 186 : : /* Find out the word */ 187 : 0 : seqword = ((seq - 1) % ex_winsz) >> WORD_SHIFT; 188 : : 189 : : /* Find out the bit in the word */ 190 : 0 : bit_pos = (seq - 1) & WORD_MASK; 191 : : 192 : : /* Check if this is a replayed packet */ 193 [ # # ]: 0 : if (window[seqword] & (1ull << (63 - bit_pos))) 194 : : return IPSEC_ANTI_REPLAY_FAILED; 195 : : 196 : : /* 197 : : * Set the bit corresponding to sequence number 198 : : * in window to mark it as received 199 : : */ 200 : 0 : window[seqword] |= (1ull << (63 - bit_pos)); 201 : : 202 : 0 : return 0; 203 : : } 204 : : 205 : : #endif /* __CNXK_SECURITY_AR_H__ */