1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
/* compute rekey time for libreswan
*
* Copyright (C) 2022 Antony Antony <antony@phenome.org>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <https://www.gnu.org/licenses/lgpl-2.1.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*
*/
#include "constants.h" /* for enum sa_role */
#include "lswlog.h"
#include "rnd.h"
#include "rnd.h" /* for fips get_rnd() */
#include "constants.h" /* for enum sa_role */
#include "lswlog.h" /* for bad_case() */
#include "rekeyfuzz.h"
#include "sa_role.h"
/*
* Important policy lies buried here.
*
* The initiator is made to rekey earlier, either with a smaller limit
* or bigger margin before a replace.
*/
deltatime_t fuzz_rekey_margin(enum sa_role role, deltatime_t marg, unsigned fuzz_percent)
{
switch (role) {
case SA_INITIATOR:
{
/*
* Give the initiator a larger margin so that its
* rekey event is scheduled earlier (relative to the
* replace event).
*/
uintmax_t fuzz = get_rnd_uintmax() % (fuzz_percent + 1);
return deltatime_scale(marg, 100 + fuzz, 100);
}
case SA_RESPONDER:
/*
* Give the responder a smaller margin so that its
* rekey event is scheduled later (relative to the
* replace event).
*/
return deltatime_scale(marg, 1, 2);
default:
bad_case(role);
}
}
uintmax_t fuzz_soft_limit(const char *what, enum sa_role role,
uintmax_t hard_limit, unsigned soft_limit_percentage,
struct logger *logger)
{
/*
* Can't use c->sa_rekey_fuzz as configuration allows values
* >100%. For a limit calculation that would be a disaster.
*/
if (!pexpect(hard_limit > 1)) {
return hard_limit;
}
passert(soft_limit_percentage >= 1);
passert(soft_limit_percentage <= 100);
/*
* Convert the HARD_LIMIT into a soft limit; being careful of
* underflow and overflow:
*
* - when HARD_LIMIT is small use H*P/100 as H/100 in H/100*P
* will underflow
*
* - when HARD_LIMIT is large compute H/100*P as HP*P in
* H*P/100 will overflow
*/
uintmax_t soft_limit;
if (hard_limit < 1000*100) {
soft_limit = hard_limit * soft_limit_percentage / 100;
} else {
soft_limit = (hard_limit / 100) * soft_limit_percentage;
}
/*
* Give the SOFT_LIMIT a little fuzz in the range
* [SOFT_LIMIT..SOFT_LIMIT/8], however don't fuzz small values
* (i.e., make the value deterministic, presumably it is for
* testing).
*
* SOFT_LIMIT/8 is somewhat arbitrary, it ensures that
* SOFT_LIMIT/2+FUZZ < SOFT_LIMIT-FUZZ.
*
* +1 is not arbitrary, without it get_rnd_uintmax()
* would barf when soft_limit/8==0.
*/
uintmax_t fuzz;
if (hard_limit < 16384/*magic*/) {
fuzz = 0;
} else {
fuzz = get_rnd_uintmax() % (soft_limit / 8 + 1);
}
const char *role_name;
uintmax_t softer_limit;
uintmax_t actual_limit;
switch (role) {
case SA_INITIATOR:
/*
* Make the initiator rekey first by further dividing
* the soft limit.
*/
role_name = "initiator";
softer_limit = soft_limit/2;
actual_limit = softer_limit + fuzz;
break;
case SA_RESPONDER:
/*
* Make the responder rekey last by giving it
* the larger ~SOFT_LIMIT.
*/
role_name = "responder";
softer_limit = soft_limit;
actual_limit = softer_limit - fuzz;
break;
default:
bad_case(role);
}
/* just don't reduce a hard-limit to 0 */
if (actual_limit == 0) {
actual_limit = 1;
}
if (DBGP(DBG_BASE)) {
ldbg(logger, "%s %s: hard-limit=%ju soft-limit=%ju softer-limit=%ju fuzz=%ju actual-limit=%ju",
role_name, what, hard_limit, soft_limit, softer_limit, fuzz, actual_limit);
}
return actual_limit;
}
|