| 1245 | */ |
| 1246 | |
| 1247 | int |
| 1248 | ipsec_chkreplay(uint32_t seq, uint32_t *seqhigh, struct secasvar *sav) |
| 1249 | { |
| 1250 | char buf[128]; |
| 1251 | struct secreplay *replay; |
| 1252 | uint32_t window; |
| 1253 | uint32_t tl, th, bl; |
| 1254 | uint32_t seqh; |
| 1255 | |
| 1256 | IPSEC_ASSERT(sav != NULL, ("Null SA")); |
| 1257 | IPSEC_ASSERT(sav->replay != NULL, ("Null replay state")); |
| 1258 | |
| 1259 | replay = sav->replay; |
| 1260 | |
| 1261 | /* No need to check replay if disabled. */ |
| 1262 | if (replay->wsize == 0) |
| 1263 | return (1); |
| 1264 | |
| 1265 | /* Zero sequence number is not allowed. */ |
| 1266 | if (seq == 0 && replay->last == 0) |
| 1267 | return (0); |
| 1268 | |
| 1269 | window = replay->wsize << 3; /* Size of window */ |
| 1270 | tl = (uint32_t)replay->last; /* Top of window, lower part */ |
| 1271 | th = (uint32_t)(replay->last >> 32); /* Top of window, high part */ |
| 1272 | bl = tl - window + 1; /* Bottom of window, lower part */ |
| 1273 | |
| 1274 | /* |
| 1275 | * We keep the high part intact when: |
| 1276 | * 1) the seq is within [bl, 0xffffffff] and the whole window is |
| 1277 | * within one subspace; |
| 1278 | * 2) the seq is within [0, bl) and window spans two subspaces. |
| 1279 | */ |
| 1280 | if ((tl >= window - 1 && seq >= bl) || |
| 1281 | (tl < window - 1 && seq < bl)) { |
| 1282 | *seqhigh = th; |
| 1283 | if (seq <= tl) { |
| 1284 | /* Sequence number inside window - check against replay */ |
| 1285 | if (check_window(replay, seq)) |
| 1286 | return (0); |
| 1287 | } |
| 1288 | |
| 1289 | /* Sequence number above top of window or not found in bitmap */ |
| 1290 | return (1); |
| 1291 | } |
| 1292 | |
| 1293 | /* |
| 1294 | * If ESN is not enabled and packet with highest sequence number |
| 1295 | * was received we should report overflow |
| 1296 | */ |
| 1297 | if (tl == 0xffffffff && !(sav->flags & SADB_X_SAFLAGS_ESN)) { |
| 1298 | /* Set overflow flag. */ |
| 1299 | replay->overflow++; |
| 1300 | |
| 1301 | if ((sav->flags & SADB_X_EXT_CYCSEQ) == 0) { |
| 1302 | if (sav->sah->saidx.proto == IPPROTO_ESP) |
| 1303 | ESPSTAT_INC(esps_wrap); |
| 1304 | else if (sav->sah->saidx.proto == IPPROTO_AH) |
no test coverage detected