Use siphash on some non-critical hashtables just in case
This commit is contained in:
parent
22b24a81d9
commit
e65f05d29a
|
@ -33,7 +33,7 @@
|
||||||
v1 ^= key->key[1]; \
|
v1 ^= key->key[1]; \
|
||||||
v0 ^= key->key[0];
|
v0 ^= key->key[0];
|
||||||
|
|
||||||
#define POSTAMBLE \
|
#define POSTAMBLE24 \
|
||||||
v3 ^= b; \
|
v3 ^= b; \
|
||||||
SIPROUND; \
|
SIPROUND; \
|
||||||
SIPROUND; \
|
SIPROUND; \
|
||||||
|
@ -45,6 +45,17 @@
|
||||||
SIPROUND; \
|
SIPROUND; \
|
||||||
return (v0 ^ v1) ^ (v2 ^ v3);
|
return (v0 ^ v1) ^ (v2 ^ v3);
|
||||||
|
|
||||||
|
#define POSTAMBLE13 \
|
||||||
|
v3 ^= b; \
|
||||||
|
SIPROUND; \
|
||||||
|
v0 ^= b; \
|
||||||
|
v2 ^= 0xff; \
|
||||||
|
SIPROUND; \
|
||||||
|
SIPROUND; \
|
||||||
|
SIPROUND; \
|
||||||
|
return (v0 ^ v1) ^ (v2 ^ v3);
|
||||||
|
|
||||||
|
|
||||||
uint64 siphash(const void *data, size_t len, const siphash_key_t *key) {
|
uint64 siphash(const void *data, size_t len, const siphash_key_t *key) {
|
||||||
const uint8 *end = (uint8*)data + len - (len % sizeof(uint64));
|
const uint8 *end = (uint8*)data + len - (len % sizeof(uint64));
|
||||||
const uint8 left = len & (sizeof(uint64) - 1);
|
const uint8 left = len & (sizeof(uint64) - 1);
|
||||||
|
@ -66,7 +77,7 @@ uint64 siphash(const void *data, size_t len, const siphash_key_t *key) {
|
||||||
case 2: b |= ReadLE16(data); break;
|
case 2: b |= ReadLE16(data); break;
|
||||||
case 1: b |= end[0];
|
case 1: b |= end[0];
|
||||||
}
|
}
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -81,7 +92,7 @@ uint64 siphash_1u64(const uint64 first, const siphash_key_t *key)
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= first;
|
v0 ^= first;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,7 +112,7 @@ uint64 siphash_2u64(const uint64 first, const uint64 second, const siphash_key_t
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= second;
|
v0 ^= second;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,7 +138,58 @@ uint64 siphash_3u64(const uint64 first, const uint64 second, const uint64 third,
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= third;
|
v0 ^= third;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* siphash13_3u64 - compute 64-bit siphash13 PRF value of 3 uint64
|
||||||
|
* @first: first uint64
|
||||||
|
* @second: second uint64
|
||||||
|
* @third: third uint64
|
||||||
|
* @key: the siphash key
|
||||||
|
*/
|
||||||
|
uint64 siphash13_3u64(const uint64 first, const uint64 second, const uint64 third,
|
||||||
|
const siphash_key_t *key) {
|
||||||
|
PREAMBLE(24)
|
||||||
|
v3 ^= first;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= first;
|
||||||
|
v3 ^= second;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= second;
|
||||||
|
v3 ^= third;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= third;
|
||||||
|
POSTAMBLE13
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 siphash13_2u64(const uint64 first, const uint64 second, const siphash_key_t *key) {
|
||||||
|
PREAMBLE(24)
|
||||||
|
v3 ^= first;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= first;
|
||||||
|
v3 ^= second;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= second;
|
||||||
|
POSTAMBLE13
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 siphash13_4u64(const uint64 first, const uint64 second, const uint64 third, const uint64 fourth,
|
||||||
|
const siphash_key_t *key) {
|
||||||
|
PREAMBLE(24)
|
||||||
|
v3 ^= first;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= first;
|
||||||
|
v3 ^= second;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= second;
|
||||||
|
v3 ^= third;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= third;
|
||||||
|
v3 ^= fourth;
|
||||||
|
SIPROUND;
|
||||||
|
v0 ^= fourth;
|
||||||
|
POSTAMBLE13
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,14 +220,14 @@ uint64 siphash_4u64(const uint64 first, const uint64 second, const uint64 third,
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= forth;
|
v0 ^= forth;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 siphash_1u32(const uint32 first, const siphash_key_t *key)
|
uint64 siphash_1u32(const uint32 first, const siphash_key_t *key)
|
||||||
{
|
{
|
||||||
PREAMBLE(4)
|
PREAMBLE(4)
|
||||||
b |= first;
|
b |= first;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 siphash_3u32(const uint32 first, const uint32 second, const uint32 third,
|
uint64 siphash_3u32(const uint32 first, const uint32 second, const uint32 third,
|
||||||
|
@ -178,7 +240,7 @@ uint64 siphash_3u32(const uint32 first, const uint32 second, const uint32 third,
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= combined;
|
v0 ^= combined;
|
||||||
b |= third;
|
b |= third;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 siphash_u64_u32(const uint64 combined, const uint32 third, const siphash_key_t *key) {
|
uint64 siphash_u64_u32(const uint64 combined, const uint32 third, const siphash_key_t *key) {
|
||||||
|
@ -188,6 +250,6 @@ uint64 siphash_u64_u32(const uint64 combined, const uint32 third, const siphash_
|
||||||
SIPROUND;
|
SIPROUND;
|
||||||
v0 ^= combined;
|
v0 ^= combined;
|
||||||
b |= third;
|
b |= third;
|
||||||
POSTAMBLE
|
POSTAMBLE24
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,4 +50,11 @@ uint64 siphash_u64_u32(const uint64 combined, const uint32 third, const siphash_
|
||||||
*/
|
*/
|
||||||
uint64 siphash(const void *data, size_t len, const siphash_key_t *key);
|
uint64 siphash(const void *data, size_t len, const siphash_key_t *key);
|
||||||
|
|
||||||
|
uint64 siphash13_2u64(const uint64 first, const uint64 second, const siphash_key_t *key);
|
||||||
|
uint64 siphash13_3u64(const uint64 first, const uint64 second, const uint64 third,
|
||||||
|
const siphash_key_t *key);
|
||||||
|
|
||||||
|
uint64 siphash13_4u64(const uint64 first, const uint64 second, const uint64 third,
|
||||||
|
const uint64 fourth, const siphash_key_t *key);
|
||||||
|
|
||||||
#endif // TUNSAFE_CRYPTO_SIPHASH_H_
|
#endif // TUNSAFE_CRYPTO_SIPHASH_H_
|
||||||
|
|
1455
third_party/flat_hash_map/bytell_hash_map.hpp
vendored
Normal file
1455
third_party/flat_hash_map/bytell_hash_map.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -9,3 +9,6 @@
|
||||||
#define WITH_HEADER_OBFUSCATION 0
|
#define WITH_HEADER_OBFUSCATION 0
|
||||||
#define WITH_AVX512_OPTIMIZATIONS 0
|
#define WITH_AVX512_OPTIMIZATIONS 0
|
||||||
#define WITH_BENCHMARK 0
|
#define WITH_BENCHMARK 0
|
||||||
|
|
||||||
|
// Use bytell hashmap instead. Only works in 64-bit builds
|
||||||
|
#define WITH_BYTELL_HASHMAP 0
|
||||||
|
|
|
@ -766,9 +766,7 @@ void WireguardProcessor::HandleShortHeaderFormatPacket(uint32 tag, Packet *packe
|
||||||
data += 4, bytes_left -= 4;
|
data += 4, bytes_left -= 4;
|
||||||
keypair = dev_.LookupKeypairByKeyId(key_id);
|
keypair = dev_.LookupKeypairByKeyId(key_id);
|
||||||
} else {
|
} else {
|
||||||
// Lookup the packet source ip and port in the address mapping
|
keypair = dev_.LookupKeypairInAddrEntryMap(packet->addr, ((tag & WG_SHORT_HEADER_KEY_ID_MASK) / WG_SHORT_HEADER_KEY_ID) - 1);
|
||||||
uint64 addr_id = packet->addr.sin.sin_addr.s_addr | ((uint64)packet->addr.sin.sin_port << 32);
|
|
||||||
keypair = dev_.LookupKeypairInAddrEntryMap(addr_id, ((tag / WG_SHORT_HEADER_KEY_ID) & 3) - 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keypair || !keypair->enabled_features[WG_FEATURE_ID_SHORT_HEADER])
|
if (!keypair || !keypair->enabled_features[WG_FEATURE_ID_SHORT_HEADER])
|
||||||
|
@ -854,10 +852,8 @@ void WireguardProcessor::HandleShortHeaderFormatPacket(uint32 tag, Packet *packe
|
||||||
// Periodically broadcast out the short key
|
// Periodically broadcast out the short key
|
||||||
if ((tag & WG_SHORT_HEADER_KEY_ID_MASK) == 0x00 && !keypair->did_attempt_remember_ip_port) {
|
if ((tag & WG_SHORT_HEADER_KEY_ID_MASK) == 0x00 && !keypair->did_attempt_remember_ip_port) {
|
||||||
keypair->did_attempt_remember_ip_port = true;
|
keypair->did_attempt_remember_ip_port = true;
|
||||||
if (keypair->enabled_features[WG_FEATURE_ID_SKIP_KEYID_IN]) {
|
if (keypair->enabled_features[WG_FEATURE_ID_SKIP_KEYID_IN])
|
||||||
uint64 addr_id = packet->addr.sin.sin_addr.s_addr | ((uint64)packet->addr.sin.sin_port << 32);
|
dev_.UpdateKeypairAddrEntry_Locked(packet->addr, keypair);
|
||||||
dev_.UpdateKeypairAddrEntry_Locked(addr_id, keypair);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Ack header may also signal that we can omit the key id in packets from now on.
|
// Ack header may also signal that we can omit the key id in packets from now on.
|
||||||
if (tag & WG_SHORT_HEADER_ACK)
|
if (tag & WG_SHORT_HEADER_ACK)
|
||||||
|
|
|
@ -263,20 +263,36 @@ void WgDevice::EraseKeypairAddrEntry_Locked(WgKeypair *kp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WgKeypair *WgDevice::LookupKeypairInAddrEntryMap(uint64 addr, uint32 slot) {
|
static WgAddrEntry::IpPort ConvertIpAddrToAddrX(const IpAddr &src) {
|
||||||
|
WgAddrEntry::IpPort r;
|
||||||
|
if (src.sin.sin_family == AF_INET) {
|
||||||
|
Write64(r.bytes, src.sin.sin_addr.s_addr);
|
||||||
|
Write64(r.bytes + 8, 0);
|
||||||
|
Write32(r.bytes + 16, src.sin.sin_port);
|
||||||
|
} else {
|
||||||
|
memcpy(r.bytes, &src.sin6.sin6_addr, 16);
|
||||||
|
Write32(r.bytes + 16, (AF_INET6 << 16) + src.sin6.sin6_port);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
WgKeypair *WgDevice::LookupKeypairInAddrEntryMap(const IpAddr &addr, uint32 slot) {
|
||||||
|
// Convert IpAddr to WgAddrEntry::IpPort suitable for use in hash.
|
||||||
|
WgAddrEntry::IpPort addr_x = ConvertIpAddrToAddrX(addr);
|
||||||
WG_SCOPED_RWLOCK_SHARED(addr_entry_lookup_lock_);
|
WG_SCOPED_RWLOCK_SHARED(addr_entry_lookup_lock_);
|
||||||
auto it = addr_entry_lookup_.find(addr);
|
auto it = addr_entry_lookup_.find(addr_x);
|
||||||
if (it == addr_entry_lookup_.end())
|
if (it == addr_entry_lookup_.end())
|
||||||
return NULL;
|
return NULL;
|
||||||
WgAddrEntry *addr_entry = it->second;
|
WgAddrEntry *addr_entry = it->second;
|
||||||
return addr_entry->keys[slot];
|
return addr_entry->keys[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
void WgDevice::UpdateKeypairAddrEntry_Locked(uint64 addr_id, WgKeypair *keypair) {
|
void WgDevice::UpdateKeypairAddrEntry_Locked(const IpAddr &addr, WgKeypair *keypair) {
|
||||||
assert(keypair->peer->IsPeerLocked());
|
assert(keypair->peer->IsPeerLocked());
|
||||||
|
WgAddrEntry::IpPort addr_x = ConvertIpAddrToAddrX(addr);
|
||||||
{
|
{
|
||||||
WG_SCOPED_RWLOCK_SHARED(addr_entry_lookup_lock_);
|
WG_SCOPED_RWLOCK_SHARED(addr_entry_lookup_lock_);
|
||||||
if (keypair->addr_entry != NULL && keypair->addr_entry->addr_entry_id == addr_id) {
|
if (keypair->addr_entry != NULL && keypair->addr_entry->addr_entry_id == addr_x) {
|
||||||
keypair->broadcast_short_key = 1;
|
keypair->broadcast_short_key = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -286,10 +302,10 @@ void WgDevice::UpdateKeypairAddrEntry_Locked(uint64 addr_id, WgKeypair *keypair)
|
||||||
if (keypair->addr_entry != NULL)
|
if (keypair->addr_entry != NULL)
|
||||||
EraseKeypairAddrEntry_Locked(keypair);
|
EraseKeypairAddrEntry_Locked(keypair);
|
||||||
|
|
||||||
WgAddrEntry **aep = &addr_entry_lookup_[addr_id], *ae;
|
WgAddrEntry **aep = &addr_entry_lookup_[addr_x], *ae;
|
||||||
|
|
||||||
if ((ae = *aep) == NULL) {
|
if ((ae = *aep) == NULL) {
|
||||||
*aep = ae = new WgAddrEntry(addr_id);
|
*aep = ae = new WgAddrEntry(addr_x);
|
||||||
} else {
|
} else {
|
||||||
// Ensure we don't insert new things in this addr entry too often.
|
// Ensure we don't insert new things in this addr entry too often.
|
||||||
if (ae->time_of_last_insertion + 1000 * 60 > low_resolution_timestamp_)
|
if (ae->time_of_last_insertion + 1000 * 60 > low_resolution_timestamp_)
|
||||||
|
@ -1452,3 +1468,20 @@ bool WgKeypairDecryptPayload(uint8 *dst, size_t src_len,
|
||||||
return memcmp_crypto(mac, dst + src_len, keypair->auth_tag_length) == 0;
|
return memcmp_crypto(mac, dst + src_len, keypair->auth_tag_length) == 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A random siphash key that can be used for hashing so it gets harder to induce hash collisions.
|
||||||
|
struct RandomSiphashKey {
|
||||||
|
RandomSiphashKey() { OsGetRandomBytes((uint8*)&key, sizeof(key)); }
|
||||||
|
siphash_key_t key;
|
||||||
|
};
|
||||||
|
static RandomSiphashKey random_siphash_key;
|
||||||
|
|
||||||
|
size_t WgAddrEntry::IpPortHasher::operator()(const WgAddrEntry::IpPort &a) const {
|
||||||
|
uint32 xx = Read32(a.bytes + 16);
|
||||||
|
return siphash13_2u64(Read64(a.bytes) + xx, Read64(a.bytes + 8) + xx, &random_siphash_key.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t WgPublicKeyHasher::operator()(const WgPublicKey&a) const {
|
||||||
|
return siphash13_4u64(a.u64[0], a.u64[1], a.u64[2], a.u64[3], &random_siphash_key.key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,12 +6,18 @@
|
||||||
#include "netapi.h"
|
#include "netapi.h"
|
||||||
#include "ipzip2/ipzip2.h"
|
#include "ipzip2/ipzip2.h"
|
||||||
#include "tunsafe_config.h"
|
#include "tunsafe_config.h"
|
||||||
|
#include "tunsafe_endian.h"
|
||||||
#include "tunsafe_threading.h"
|
#include "tunsafe_threading.h"
|
||||||
#include "ip_to_peer_map.h"
|
#include "ip_to_peer_map.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if WITH_BYTELL_HASHMAP
|
||||||
|
#include "third_party/flat_hash_map/bytell_hash_map.hpp"
|
||||||
|
#endif // WITH_BYTELL_HASHMAP
|
||||||
|
|
||||||
// Threading macros that enable locks only in MT builds
|
// Threading macros that enable locks only in MT builds
|
||||||
#if WITH_WG_THREADING
|
#if WITH_WG_THREADING
|
||||||
#define WG_SCOPED_LOCK(name) ScopedLock scoped_lock(&name)
|
#define WG_SCOPED_LOCK(name) ScopedLock scoped_lock(&name)
|
||||||
|
@ -41,6 +47,13 @@
|
||||||
#define WG_IF_LOCKS_ENABLED_ELSE(expr, def) (def)
|
#define WG_IF_LOCKS_ENABLED_ELSE(expr, def) (def)
|
||||||
#endif // WITH_WG_THREADING
|
#endif // WITH_WG_THREADING
|
||||||
|
|
||||||
|
// bytell hash is faster but more untested
|
||||||
|
#if WITH_BYTELL_HASHMAP
|
||||||
|
#define WG_HASHTABLE_IMPL ska::bytell_hash_map
|
||||||
|
#else
|
||||||
|
#define WG_HASHTABLE_IMPL std::unordered_map
|
||||||
|
#endif
|
||||||
|
|
||||||
enum ProtocolTimeouts {
|
enum ProtocolTimeouts {
|
||||||
COOKIE_SECRET_MAX_AGE_MS = 120000,
|
COOKIE_SECRET_MAX_AGE_MS = 120000,
|
||||||
COOKIE_SECRET_LATENCY_MS = 5000,
|
COOKIE_SECRET_LATENCY_MS = 5000,
|
||||||
|
@ -235,13 +248,23 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WgAddrEntry {
|
struct WgAddrEntry {
|
||||||
// The id of the addr entry, so we can delete ourselves
|
struct IpPort {
|
||||||
uint64 addr_entry_id;
|
uint8 bytes[20];
|
||||||
|
|
||||||
// Ensure there's at least 1 minute between we allow registering
|
friend bool operator==(const IpPort &a, const IpPort &b) {
|
||||||
// a new key in this table. This means that each key will have
|
uint64 rv = Read64(a.bytes) ^ Read64(b.bytes);
|
||||||
// a life time of at least 3 minutes.
|
rv |= Read64(a.bytes + 8) ^ Read64(b.bytes + 8);
|
||||||
uint64 time_of_last_insertion;
|
rv |= Read32(a.bytes + 16) ^ Read32(b.bytes + 16);
|
||||||
|
return (rv == 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IpPortHasher {
|
||||||
|
size_t operator()(const IpPort &a) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The id of the addr entry, so we can delete ourselves
|
||||||
|
IpPort addr_entry_id;
|
||||||
|
|
||||||
// This entry gets erased when there's no longer any key pointing at it.
|
// This entry gets erased when there's no longer any key pointing at it.
|
||||||
uint8 ref_count;
|
uint8 ref_count;
|
||||||
|
@ -249,13 +272,19 @@ struct WgAddrEntry {
|
||||||
// Index of the next slot 0-2 where we'll insert the next key.
|
// Index of the next slot 0-2 where we'll insert the next key.
|
||||||
uint8 next_slot;
|
uint8 next_slot;
|
||||||
|
|
||||||
|
// Ensure there's at least 1 minute between we allow registering
|
||||||
|
// a new key in this table. This means that each key will have
|
||||||
|
// a life time of at least 3 minutes.
|
||||||
|
uint64 time_of_last_insertion;
|
||||||
|
|
||||||
// The three keys.
|
// The three keys.
|
||||||
WgKeypair *keys[3];
|
WgKeypair *keys[3];
|
||||||
|
|
||||||
WgAddrEntry(uint64 addr_entry_id) : addr_entry_id(addr_entry_id), ref_count(0), next_slot(0) {
|
WgAddrEntry(const IpPort &addr_entry_id)
|
||||||
|
: addr_entry_id(addr_entry_id), ref_count(0), next_slot(0), time_of_last_insertion(0) {
|
||||||
keys[0] = keys[1] = keys[2] = NULL;
|
keys[0] = keys[1] = keys[2] = NULL;
|
||||||
time_of_last_insertion = 0x123456789123456;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScramblerSiphashKeys {
|
struct ScramblerSiphashKeys {
|
||||||
|
@ -271,10 +300,7 @@ union WgPublicKey {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WgPublicKeyHasher {
|
struct WgPublicKeyHasher {
|
||||||
size_t operator()(const WgPublicKey&a) const {
|
size_t operator()(const WgPublicKey&a) const;
|
||||||
uint64 rv = a.u64[0] ^ a.u64[1] ^ a.u64[2] ^ a.u64[3];
|
|
||||||
return (size_t)(rv ^ (rv >> 32));
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class WgDevice {
|
class WgDevice {
|
||||||
|
@ -314,14 +340,12 @@ public:
|
||||||
bool CheckCookieMac2(Packet *packet);
|
bool CheckCookieMac2(Packet *packet);
|
||||||
|
|
||||||
void CreateCookieMessage(MessageHandshakeCookie *dst, Packet *packet, uint32 remote_key_id);
|
void CreateCookieMessage(MessageHandshakeCookie *dst, Packet *packet, uint32 remote_key_id);
|
||||||
void UpdateKeypairAddrEntry_Locked(uint64 addr_id, WgKeypair *keypair);
|
|
||||||
void SecondLoop(uint64 now);
|
void SecondLoop(uint64 now);
|
||||||
|
|
||||||
IpToPeerMap &ip_to_peer_map() { return ip_to_peer_map_; }
|
IpToPeerMap &ip_to_peer_map() { return ip_to_peer_map_; }
|
||||||
WgPeer *first_peer() { return peers_; }
|
WgPeer *first_peer() { return peers_; }
|
||||||
const uint8 *public_key() const { return s_pub_; }
|
const uint8 *public_key() const { return s_pub_; }
|
||||||
WgRateLimit *rate_limiter() { return &rate_limiter_; }
|
WgRateLimit *rate_limiter() { return &rate_limiter_; }
|
||||||
std::unordered_map<uint64, WgAddrEntry*> &addr_entry_map() { return addr_entry_lookup_; }
|
|
||||||
WgPacketCompressionVer01 *compression_header() { return &compression_header_; }
|
WgPacketCompressionVer01 *compression_header() { return &compression_header_; }
|
||||||
bool is_private_key_initialized() { return is_private_key_initialized_; }
|
bool is_private_key_initialized() { return is_private_key_initialized_; }
|
||||||
|
|
||||||
|
@ -333,7 +357,9 @@ public:
|
||||||
private:
|
private:
|
||||||
std::pair<WgPeer*, WgKeypair*> *LookupPeerInKeyIdLookup(uint32 key_id);
|
std::pair<WgPeer*, WgKeypair*> *LookupPeerInKeyIdLookup(uint32 key_id);
|
||||||
WgKeypair *LookupKeypairByKeyId(uint32 key_id);
|
WgKeypair *LookupKeypairByKeyId(uint32 key_id);
|
||||||
WgKeypair *LookupKeypairInAddrEntryMap(uint64 addr, uint32 slot);
|
|
||||||
|
void UpdateKeypairAddrEntry_Locked(const IpAddr &addr, WgKeypair *keypair);
|
||||||
|
WgKeypair *LookupKeypairInAddrEntryMap(const IpAddr &addr, uint32 slot);
|
||||||
// Return the peer matching the |public_key| or NULL
|
// Return the peer matching the |public_key| or NULL
|
||||||
WgPeer *GetPeerFromPublicKey(const WgPublicKey &pubkey);
|
WgPeer *GetPeerFromPublicKey(const WgPublicKey &pubkey);
|
||||||
// Create a cookie by inspecting the source address of the |packet|
|
// Create a cookie by inspecting the source address of the |packet|
|
||||||
|
@ -357,20 +383,26 @@ private:
|
||||||
// For hooking
|
// For hooking
|
||||||
Delegate *delegate_;
|
Delegate *delegate_;
|
||||||
|
|
||||||
|
|
||||||
|
// Keypair IDs are generated randomly by us so no point in wasting cycles on
|
||||||
|
// hashing the random value.
|
||||||
|
struct KeyIdHasher {
|
||||||
|
size_t operator()(uint32 v) const { return v; }
|
||||||
|
};
|
||||||
|
|
||||||
// Lock that protects key_id_lookup_
|
// Lock that protects key_id_lookup_
|
||||||
WG_DECLARE_RWLOCK(key_id_lookup_lock_);
|
WG_DECLARE_RWLOCK(key_id_lookup_lock_);
|
||||||
// Mapping from key-id to either an active keypair (if keypair is non-NULL),
|
// Mapping from key-id to either an active keypair (if keypair is non-NULL),
|
||||||
// or to a handshake.
|
// or to a handshake.
|
||||||
std::unordered_map<uint32, std::pair<WgPeer*, WgKeypair*> > key_id_lookup_;
|
WG_HASHTABLE_IMPL<uint32, std::pair<WgPeer*, WgKeypair*>, KeyIdHasher> key_id_lookup_;
|
||||||
|
|
||||||
// Mapping from IPV4 IP/PORT to WgPeer*, so we can find the peer when a key id is
|
// Mapping from IPV4 IP/PORT to WgPeer*, so we can find the peer when a key id is
|
||||||
// not explicitly included.
|
// not explicitly included.
|
||||||
std::unordered_map<uint64, WgAddrEntry*> addr_entry_lookup_;
|
WG_HASHTABLE_IMPL<WgAddrEntry::IpPort, WgAddrEntry*, WgAddrEntry::IpPortHasher> addr_entry_lookup_;
|
||||||
WG_DECLARE_RWLOCK(addr_entry_lookup_lock_);
|
WG_DECLARE_RWLOCK(addr_entry_lookup_lock_);
|
||||||
|
|
||||||
// Mapping from peer id to peer. This may be accessed only from MT.
|
// Mapping from peer id to peer. This may be accessed only from MT.
|
||||||
std::unordered_map<WgPublicKey, WgPeer*, WgPublicKeyHasher> peer_id_lookup_;
|
WG_HASHTABLE_IMPL<WgPublicKey, WgPeer*, WgPublicKeyHasher> peer_id_lookup_;
|
||||||
|
|
||||||
// Queue of things scheduled to run on the main thread.
|
// Queue of things scheduled to run on the main thread.
|
||||||
WG_DECLARE_LOCK(main_thread_scheduled_lock_);
|
WG_DECLARE_LOCK(main_thread_scheduled_lock_);
|
||||||
WgPeer *main_thread_scheduled_, **main_thread_scheduled_last_;
|
WgPeer *main_thread_scheduled_, **main_thread_scheduled_last_;
|
||||||
|
|
Loading…
Reference in a new issue