kernel-wfp: Allocate SPIs pseudo-randomly using a 0xc prefix
This commit is contained in:
@@ -41,6 +41,11 @@ struct private_kernel_wfp_ipsec_t {
|
||||
*/
|
||||
refcount_t nextspi;
|
||||
|
||||
/**
|
||||
* Mix value to distribute SPI allocation randomly
|
||||
*/
|
||||
u_int32_t mixspi;
|
||||
|
||||
/**
|
||||
* Temporary SAD/SPD entries referenced reqid, as uintptr_t => entry_t
|
||||
*/
|
||||
@@ -1204,11 +1209,58 @@ METHOD(kernel_ipsec_t, get_features, kernel_feature_t,
|
||||
return KERNEL_ESP_V3_TFC | KERNEL_NO_POLICY_UPDATES;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize seeds for SPI generation
|
||||
*/
|
||||
static bool init_spi(private_kernel_wfp_ipsec_t *this)
|
||||
{
|
||||
bool ok = TRUE;
|
||||
rng_t *rng;
|
||||
|
||||
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
|
||||
if (!rng)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
ok = rng->get_bytes(rng, sizeof(this->nextspi), (u_int8_t*)&this->nextspi);
|
||||
if (ok)
|
||||
{
|
||||
ok = rng->get_bytes(rng, sizeof(this->mixspi), (u_int8_t*)&this->mixspi);
|
||||
}
|
||||
rng->destroy(rng);
|
||||
return ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map an integer x with a one-to-one function using quadratic residues.
|
||||
*/
|
||||
static u_int permute(u_int x, u_int p)
|
||||
{
|
||||
u_int qr;
|
||||
|
||||
x = x % p;
|
||||
qr = ((u_int64_t)x * x) % p;
|
||||
if (x <= p / 2)
|
||||
{
|
||||
return qr;
|
||||
}
|
||||
return p - qr;
|
||||
}
|
||||
|
||||
METHOD(kernel_ipsec_t, get_spi, status_t,
|
||||
private_kernel_wfp_ipsec_t *this, host_t *src, host_t *dst,
|
||||
u_int8_t protocol, u_int32_t reqid, u_int32_t *spi)
|
||||
{
|
||||
*spi = htonl(ref_get(&this->nextspi));
|
||||
/* To avoid sequencial SPIs, we use a one-to-one permuation function on
|
||||
* an incrementing counter, that is a full period PRNG for the range we
|
||||
* allocate SPIs in. We add some randomness using a fixed XOR and start
|
||||
* the counter at random position. This is not cryptographically safe,
|
||||
* but that is actually not required.
|
||||
* The selected prime should be smaller than the range we allocate SPIs
|
||||
* in, and it must satisfy p % 4 == 3 to map x > p/2 using p - qr. */
|
||||
static const u_int p = 268435399, offset = 0xc0000000;
|
||||
|
||||
*spi = htonl(offset + permute(ref_get(&this->nextspi) ^ this->mixspi, p));
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1646,7 +1698,6 @@ kernel_wfp_ipsec_t *kernel_wfp_ipsec_create()
|
||||
.providerKey = { 0x59cdae2e, 0xf6bb, 0x4c09,
|
||||
{ 0xa9,0x59,0x9d,0x91,0xac,0xaf,0xf9,0x19 }},
|
||||
},
|
||||
.nextspi = 0xc0000001,
|
||||
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
|
||||
.tsas = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
|
||||
.isas = hashtable_create((void*)hash_sa, (void*)equals_sa, 4),
|
||||
@@ -1654,6 +1705,12 @@ kernel_wfp_ipsec_t *kernel_wfp_ipsec_create()
|
||||
.routes = hashtable_create((void*)hash_route, (void*)equals_route, 4),
|
||||
);
|
||||
|
||||
if (!init_spi(this))
|
||||
{
|
||||
destroy(this);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session,
|
||||
&this->handle);
|
||||
if (res != ERROR_SUCCESS)
|
||||
|
||||
Reference in New Issue
Block a user