From 57642ca653f4ffafee34aecfc2e17e2d63df74b8 Mon Sep 17 00:00:00 2001 From: Ludvig Strigeus Date: Fri, 16 Nov 2018 14:36:15 +0100 Subject: [PATCH] Remove ipzip stubs --- TunSafe.vcxproj | 2 - TunSafe.vcxproj.filters | 6 --- ipzip2/ipzip2.cpp | 2 - ipzip2/ipzip2.h | 1 - tunsafe_amalgam.cpp | 2 +- wireguard.cpp | 90 ++++++++++++++--------------------------- wireguard.h | 3 +- wireguard_proto.cpp | 56 ++++++------------------- wireguard_proto.h | 47 +++++++++++---------- 9 files changed, 70 insertions(+), 139 deletions(-) delete mode 100644 ipzip2/ipzip2.cpp delete mode 100644 ipzip2/ipzip2.h diff --git a/TunSafe.vcxproj b/TunSafe.vcxproj index ea793d3..42a9fbb 100644 --- a/TunSafe.vcxproj +++ b/TunSafe.vcxproj @@ -197,7 +197,6 @@ - @@ -221,7 +220,6 @@ - diff --git a/TunSafe.vcxproj.filters b/TunSafe.vcxproj.filters index 77805db..3134cb4 100644 --- a/TunSafe.vcxproj.filters +++ b/TunSafe.vcxproj.filters @@ -56,9 +56,6 @@ Source Files - - Source Files - Source Files @@ -152,9 +149,6 @@ Source Files - - Source Files - crypto\aesgcm diff --git a/ipzip2/ipzip2.cpp b/ipzip2/ipzip2.cpp deleted file mode 100644 index 5ed17a3..0000000 --- a/ipzip2/ipzip2.cpp +++ /dev/null @@ -1,2 +0,0 @@ -#include "stdafx.h" -// this is a placeholder for a packet compression algorithm not yet released. diff --git a/ipzip2/ipzip2.h b/ipzip2/ipzip2.h deleted file mode 100644 index bfcd94b..0000000 --- a/ipzip2/ipzip2.h +++ /dev/null @@ -1 +0,0 @@ -// this is a placeholder for a packet compression algorithm not yet released. diff --git a/tunsafe_amalgam.cpp b/tunsafe_amalgam.cpp index 664e79a..9d0c94e 100644 --- a/tunsafe_amalgam.cpp +++ b/tunsafe_amalgam.cpp @@ -19,7 +19,7 @@ #include "crypto/blake2s/blake2s.cpp" #include "crypto/siphash/siphash.cpp" #include "crypto/aesgcm/aesgcm.cpp" -#include "ipzip2/ipzip2.cpp" +#include "network_common.cpp" #if defined(WITH_NETWORK_BSD) #include "network_bsd.cpp" diff --git a/wireguard.cpp b/wireguard.cpp index 4c64613..f638aba 100644 --- a/wireguard.cpp +++ b/wireguard.cpp @@ -12,7 +12,6 @@ #include #include #include -#include "ipzip2/ipzip2.h" #include "wireguard.h" #include "wireguard_config.h" #include "util.h" @@ -104,31 +103,6 @@ void WireguardProcessor::ResetStats() { memset(&stats_, 0, sizeof(stats_)); } -void WireguardProcessor::SetupCompressionHeader(WgPacketCompressionVer01 *c) { - memset(c, 0, sizeof(WgPacketCompressionVer01)); - // Windows uses a ttl of 128 while other platforms use 64 -#if defined(OS_WIN) - c->ttl = 128; -#else // defined(OS_WIN) - c->ttl = 64; -#endif // defined(OS_WIN) - WriteLE16(&c->version, EXT_PACKET_COMPRESSION_VER); - - for (auto it = addresses_.begin(); it != addresses_.end(); ++it) { - if (it->size == 32) { - memcpy(c->ipv4_addr, it->addr, 4); - c->flags = ((it->cidr >> 3) & 3); - break; - } - } - for (auto it = addresses_.begin(); it != addresses_.end(); ++it) { - if (it->size == 128) { - memcpy(c->ipv6_addr, it->addr, 16); - break; - } - } -} - static WgCidrAddr WgCidrAddrFromIpAddr(const IpAddr &addr) { WgCidrAddr r = {0}; if (addr.sin.sin_family == AF_INET) { @@ -208,8 +182,6 @@ bool WireguardProcessor::ConfigureTun() { if (!tun_->Configure(std::move(config), &config_out)) return false; - SetupCompressionHeader(dev_.compression_header()); - network_discovery_spoofing_ = config_out.enable_neighbor_discovery_spoofing; memcpy(network_discovery_mac_, config_out.neighbor_discovery_spoofing_mac, 6); @@ -438,22 +410,18 @@ void WireguardProcessor::WriteAndEncryptPacketToUdp_WillUnlock(WgPeer *peer, Pac } else { peer->OnDataSent(); -#if WITH_HANDSHAKE_EXT - // Attempt to compress the packet headers using ipzip. - if (keypair->enabled_features[WG_FEATURE_ID_IPZIP]) { - uint32 rv = IpzipCompress(data, (uint32)size, &keypair->ipzip_state_, 0); - if (rv == (uint32)-1) + // Attempt to compress the packet headers + if (WITH_HANDSHAKE_EXT && keypair->compress_handler_) { + WgCompressHandler::CompressState st = keypair->compress_handler_->Compress(packet); + if (st == WgCompressHandler::COMPRESS_FAIL) goto getout_discard; - if (rv == 0) + if (st == WgCompressHandler::COMPRESS_NO) goto add_padding; - stats_.compression_hdr_saved_out += (int32)(size - rv); - data += (int32)(size - rv); - size = rv; + stats_.compression_hdr_saved_out += (int32)(size - packet->size); + data = packet->data; + size = packet->size; } else { add_padding: -#else - { -#endif // WITH_HANDSHAKE_EXT // Pad packet to a multiple of 16 bytes, but no more than the mtu bytes. unsigned padding = std::min((0 - size) & 15, (unsigned)mtu_ - (unsigned)size); memset(data + size, 0, padding); @@ -461,8 +429,7 @@ add_padding: } } -#if WITH_SHORT_HEADERS - if (keypair->enabled_features[WG_FEATURE_ID_SHORT_HEADER]) { + if (WITH_SHORT_HEADERS && keypair->enabled_features[WG_FEATURE_ID_SHORT_HEADER]) { size_t header_size; byte *write = data; uint8 tag = WG_SHORT_HEADER_BIT, inner_tag; @@ -530,9 +497,6 @@ add_padding: ad_len = data - write_after_ack_header; } else { need_big_packet: -#else - { -#endif // #if WITH_SHORT_HEADERS packet->size = (int)(size + sizeof(MessageData) + keypair->auth_tag_length); peer->tx_bytes_ += packet->size; @@ -859,7 +823,9 @@ void WireguardProcessor::HandleShortHeaderFormatPacket(uint32 tag, Packet *packe if (tag & WG_SHORT_HEADER_ACK) keypair->can_use_short_key_for_outgoing = (ack_tag & WG_ACK_HEADER_KEY_MASK) * WG_SHORT_HEADER_KEY_ID; - HandleAuthenticatedDataPacket_WillUnlock(keypair, packet, data, bytes_left - keypair->auth_tag_length); + packet->data = data; + packet->size = bytes_left - keypair->auth_tag_length; + HandleAuthenticatedDataPacket_WillUnlock(keypair, packet); return; getout_unlock: WG_RELEASE_LOCK(keypair->peer->mutex_); @@ -881,7 +847,7 @@ void WireguardProcessor::NotifyHandshakeComplete() { procdel_->OnConnected(); } -void WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet, uint8 *data, size_t data_size) { +void WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet) { WgPeer *peer = keypair->peer; assert(peer->IsPeerLocked()); @@ -901,6 +867,7 @@ void WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *key peer->ScheduleNewHandshake(); } + uint32 data_size = packet->size; if (data_size == 0) { peer->OnKeepaliveReceived(); WG_RELEASE_LOCK(peer->mutex_); @@ -909,22 +876,22 @@ void WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *key peer->OnDataReceived(); WG_RELEASE_LOCK(peer->mutex_); -#if WITH_HANDSHAKE_EXT - // Unpack the packet headers using ipzip - if (keypair->enabled_features[WG_FEATURE_ID_IPZIP]) { - uint32 rv = IpzipDecompress(data, (uint32)data_size, &keypair->ipzip_state_, IPZIP_RECV_BY_CLIENT); - if (rv == (uint32)-1) + // Unpack the packet headers? + if (WITH_HANDSHAKE_EXT && keypair->compress_handler_) { + WgCompressHandler::CompressState st = keypair->compress_handler_->Decompress(packet); + if (st == WgCompressHandler::COMPRESS_FAIL) goto getout; - stats_.compression_hdr_saved_in += (int64)rv - data_size; - data -= (int64)rv - data_size, data_size = rv; + if (st == WgCompressHandler::COMPRESS_YES) + stats_.compression_hdr_saved_in += (int32)(packet->size - exch(data_size, packet->size)); } -#endif // WITH_HANDSHAKE_EXT // Verify that the packet is a valid ipv4 or ipv6 packet of proper length, // with a source address that belongs to the peer. WgPeer *peer_from_header; - unsigned int ip_version, size_from_header; + uint32 ip_version, size_from_header; + uint8 *data; + data = packet->data; ip_version = *data >> 4; if (ip_version == 4) { if (data_size < IPV4_HEADER_SIZE) @@ -951,10 +918,9 @@ void WireguardProcessor::HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *key if (peer_from_header != peer || size_from_header > data_size) goto getout_error_header; - packet->data = data; packet->size = size_from_header; - stats_.tun_bytes_out += packet->size; + stats_.tun_bytes_out += size_from_header; stats_.tun_packets_out++; tun_->WriteTunPacket(packet); @@ -970,7 +936,7 @@ void WireguardProcessor::HandleDataPacket(Packet *packet) { assert(dev_.IsMainOrDataThread()); uint8 *data = packet->data; - size_t data_size = packet->size; + uint32 data_size = packet->size; uint32 key_id = ((MessageData*)data)->receiver_id; uint64 counter = ToLE64((((MessageData*)data)->counter)); WgKeypair *keypair = dev_.LookupKeypairByKeyId(key_id); @@ -981,6 +947,9 @@ getout: return; } + packet->data = data + sizeof(MessageData); + packet->size = data_size - sizeof(MessageData) - keypair->auth_tag_length; + if (!WgKeypairDecryptPayload(data + sizeof(MessageData), data_size - sizeof(MessageData), NULL, 0, counter, keypair)) { stats_.error_mac++; @@ -1001,7 +970,8 @@ getout: assert(!keypair->peer->marked_for_delete_); WgPeer::CopyEndpointToPeer_Locked(keypair, &packet->addr); - HandleAuthenticatedDataPacket_WillUnlock(keypair, packet, data + sizeof(MessageData), data_size - sizeof(MessageData) - keypair->auth_tag_length); + + HandleAuthenticatedDataPacket_WillUnlock(keypair, packet); } } diff --git a/wireguard.h b/wireguard.h index 70ccddb..69278ed 100644 --- a/wireguard.h +++ b/wireguard.h @@ -115,11 +115,10 @@ private: void HandleHandshakeCookiePacket(Packet *packet); void HandleDataPacket(Packet *packet); - void HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet, uint8 *data, size_t data_size); + void HandleAuthenticatedDataPacket_WillUnlock(WgKeypair *keypair, Packet *packet); void HandleShortHeaderFormatPacket(uint32 tag, Packet *packet); bool CheckIncomingHandshakeRateLimit(Packet *packet, bool overload); bool HandleIcmpv6NeighborSolicitation(const byte *data, size_t data_size); - void SetupCompressionHeader(WgPacketCompressionVer01 *c); void NotifyHandshakeComplete(); ProcessorDelegate *procdel_; diff --git a/wireguard_proto.cpp b/wireguard_proto.cpp index 214ac4b..5ea0966 100644 --- a/wireguard_proto.cpp +++ b/wireguard_proto.cpp @@ -60,7 +60,6 @@ WgDevice::WgDevice() { next_rng_slot_ = 0; main_thread_scheduled_ = NULL; main_thread_scheduled_last_ = &main_thread_scheduled_; - memset(&compression_header_, 0, sizeof(compression_header_)); low_resolution_timestamp_ = cookie_secret_timestamp_ = OsGetMilliseconds(); OsGetRandomBytes(cookie_secret_, sizeof(cookie_secret_)); @@ -791,6 +790,7 @@ void WgPeer::ParseMessageHandshakeCookie(WgDevice *dev, const MessageHandshakeCo #if WITH_HANDSHAKE_EXT size_t WgPeer::WriteHandshakeExtension(uint8 *dst, WgKeypair *keypair) { + uint8 *dst_end = dst + MAX_SIZE_OF_HANDSHAKE_EXTENSION; uint8 *dst_org = dst, value = 0; // Include the supported features extension if (!IsOnlyZeros(features_, sizeof(features_))) { @@ -818,13 +818,10 @@ size_t WgPeer::WriteHandshakeExtension(uint8 *dst, WgKeypair *keypair) { dst += ciphers; } } - if (features_[WG_FEATURE_ID_IPZIP]) { - // Include the packet compression extension - *dst++ = EXT_PACKET_COMPRESSION; - *dst++ = sizeof(WgPacketCompressionVer01); - memcpy(dst, &dev_->compression_header_, sizeof(WgPacketCompressionVer01)); - dst += sizeof(WgPacketCompressionVer01); - } + // Packet compression extension? + if (features_[WG_FEATURE_ID_IPZIP] && dev_->delegate_) + dst += dev_->delegate_->WritePacketCompressionExtension(dst, dst_end - dst); + return dst - dst_org; } @@ -856,32 +853,7 @@ static uint32 ResolveCipherSuite(int tie, const uint8 *a, size_t a_size, const u (tie == 0 && cipher_strengths[found_a] > cipher_strengths[found_b])) ? found_a : found_b; } -void WgKeypairSetupCompressionExtension(WgKeypair *keypair, const WgPacketCompressionVer01 *remotec) { - const WgPacketCompressionVer01 *localc = keypair->peer->dev_->compression_header(); - IpzipState *state = &keypair->ipzip_state_; - - // Use is_initiator as tie-breaker on who's going to be the client side. - int flags_xor = 0; - if ((localc->flags & ~3) + 2 * keypair->is_initiator - 1 <= (remotec->flags & ~3)) - std::swap(localc, remotec), flags_xor = 1; - state->flags_xor = flags_xor; - - memcpy(state->client_addr_v4, localc->ipv4_addr, 4); - memcpy(state->client_addr_v6, localc->ipv6_addr, 16); - state->guess_ttl[0] = localc->ttl; - state->client_addr_v4_subnet_bytes = (localc->flags & 3); - WriteLE32(&state->client_addr_v4_netmask, 0xffffffff >> ((localc->flags & 3) * 8)); - - memcpy(state->server_addr_v4, remotec->ipv4_addr, 4); - memcpy(state->server_addr_v6, remotec->ipv6_addr, 16); - state->guess_ttl[1] = remotec->ttl; - state->server_addr_v4_subnet_bytes = (remotec->flags & 3); - WriteLE32(&state->server_addr_v4_netmask, 0xffffffff >> ((remotec->flags & 3) * 8)); -} - -bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size_t data_size) { - bool did_setup_compression = false; - +bool WgPeer::ParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size_t data_size) { while (data_size >= 2) { uint8 type = data[0], size = data[1]; data += 2, data_size -= 2; @@ -892,7 +864,7 @@ bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size case EXT_CIPHER_SUITES: keypair->cipher_suite = ResolveCipherSuite(keypair->peer->cipher_prio_ - (type - EXT_CIPHER_SUITES), keypair->peer->ciphers_, keypair->peer->num_ciphers_, - data, data_size); + data, size); break; case EXT_BOOLEAN_FEATURES: for (size_t i = 0, j = std::max(WG_FEATURES_COUNT, size * 4); i != j; i++) { @@ -903,13 +875,8 @@ bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size } break; case EXT_PACKET_COMPRESSION: - if (size == sizeof(WgPacketCompressionVer01)) { - WgPacketCompressionVer01 *c = (WgPacketCompressionVer01*)data; - if (ReadLE16(&c->version) == EXT_PACKET_COMPRESSION_VER) { - WgKeypairSetupCompressionExtension(keypair, c); - did_setup_compression = true; - } - } + if (keypair->enabled_features[WG_FEATURE_ID_IPZIP] && !keypair->compress_handler_ && keypair->peer->dev_->delegate_) + keypair->compress_handler_ = keypair->peer->dev_->delegate_->ParsePacketCompressionExtension(keypair, data, size); break; } data += size, data_size -= size; @@ -917,7 +884,8 @@ bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size if (data_size != 0) return false; - keypair->enabled_features[WG_FEATURE_ID_IPZIP] &= did_setup_compression; + if (!keypair->compress_handler_) + keypair->enabled_features[WG_FEATURE_ID_IPZIP] = false; keypair->auth_tag_length = (keypair->enabled_features[WG_FEATURE_ID_SHORT_MAC] ? 8 : CHACHA20POLY1305_AUTHTAGLEN); // RINFO("Cipher Suite = %d", keypair->cipher_suite); @@ -965,7 +933,7 @@ WgKeypair *WgPeer::CreateNewKeypair(bool is_initiator, const uint8 chaining_key[ kp->auth_tag_length = CHACHA20POLY1305_AUTHTAGLEN; #if WITH_HANDSHAKE_EXT - if (!WgKeypairParseExtendedHandshake(kp, extfield, extfield_size)) { + if (!ParseExtendedHandshake(kp, extfield, extfield_size)) { fail: delete kp; return NULL; diff --git a/wireguard_proto.h b/wireguard_proto.h index bd16142..b1166be 100644 --- a/wireguard_proto.h +++ b/wireguard_proto.h @@ -4,7 +4,6 @@ #include "tunsafe_types.h" #include "netapi.h" -#include "ipzip2/ipzip2.h" #include "tunsafe_config.h" #include "tunsafe_endian.h" #include "tunsafe_threading.h" @@ -201,15 +200,6 @@ enum { WG_BOOLEAN_FEATURE_ENFORCES = 0x3, }; -struct WgPacketCompressionVer01 { - uint16 version; // Packet compressor version - uint8 ttl; // Guessed TTL - uint8 flags; // Subnet length and packet direction - uint8 ipv4_addr[4]; // IPV4 address of endpoint - uint8 ipv6_addr[16]; // IPV6 address of endpoint -}; -STATIC_ASSERT(sizeof(WgPacketCompressionVer01) == 24, WgPacketCompressionVer01_wrong_size); - struct WgKeypair; class WgPeer; @@ -303,6 +293,23 @@ struct WgPublicKeyHasher { size_t operator()(const WgPublicKey&a) const; }; +class WgCompressHandler { +public: + virtual ~WgCompressHandler() {} + + enum CompressState { + COMPRESS_FAIL = -1, + COMPRESS_NO = 0, + COMPRESS_YES = 1, + }; + + // Compress a packet. + virtual CompressState Compress(Packet *packet); + + virtual CompressState Decompress(Packet *packet); + +}; + class WgDevice { friend class WgPeer; friend class WireguardProcessor; @@ -316,6 +323,12 @@ public: // return true to try again or false to fail. The packet can be copied and saved // to resume a handshake later on. virtual bool HandleUnknownPeerId(uint8 public_key[WG_PUBLIC_KEY_LEN], Packet *packet) = 0; + + // Write out the compression header + virtual size_t WritePacketCompressionExtension(uint8 *data, size_t data_size) = 0; + + // Parse the packet compression extension + virtual WgCompressHandler *ParsePacketCompressionExtension(WgKeypair *keypair, const uint8 *data, size_t data_size) = 0; }; WgDevice(); @@ -346,7 +359,6 @@ public: WgPeer *first_peer() { return peers_; } const uint8 *public_key() const { return s_pub_; } WgRateLimit *rate_limiter() { return &rate_limiter_; } - WgPacketCompressionVer01 *compression_header() { return &compression_header_; } bool is_private_key_initialized() { return is_private_key_initialized_; } bool IsMainThread() { return CurrentThreadIdEquals(main_thread_id_); } @@ -436,8 +448,6 @@ private: WgRateLimit rate_limiter_; - WgPacketCompressionVer01 compression_header_; - // For defering deletes until all worker threads are guaranteed not to use an object. MultithreadedDelayedDelete delayed_delete_; }; @@ -447,8 +457,6 @@ class WgPeer { friend class WgDevice; friend class WireguardProcessor; friend class WgConfig; - friend bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size_t data_size); - friend void WgKeypairSetupCompressionExtension(WgKeypair *keypair, const WgPacketCompressionVer01 *remotec); public: explicit WgPeer(WgDevice *dev); ~WgPeer(); @@ -496,6 +504,7 @@ public: WgPeer *next_peer() { return next_peer_; } private: + static bool ParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size_t data_size); static WgKeypair *CreateNewKeypair(bool is_initiator, const uint8 key[WG_HASH_LEN], uint32 send_key_id, const uint8 *extfield, size_t extfield_size); void WriteMacToPacket(const uint8 *data, MessageMacs *mac); void CheckAndUpdateTimeOfNextKeyEvent(uint64 now); @@ -719,14 +728,12 @@ struct WgKeypair { AesGcm128StaticContext *aes_gcm128_context_; + WgCompressHandler *compress_handler_; + // -- all up to this point is initialized to zero // For replay detection of incoming packets ReplayDetector replay_detector; -#if WITH_HANDSHAKE_EXT - // State for packet compressor - IpzipState ipzip_state_; -#endif // WITH_HANDSHAKE_EXT }; void WgKeypairEncryptPayload(uint8 *dst, const size_t src_len, @@ -737,5 +744,3 @@ bool WgKeypairDecryptPayload(uint8 *dst, const size_t src_len, const uint8 *ad, const size_t ad_len, const uint64 nonce, WgKeypair *keypair); -bool WgKeypairParseExtendedHandshake(WgKeypair *keypair, const uint8 *data, size_t data_size); -