diff --git a/node/Address.hpp b/node/Address.hpp index 2a22e9efb..06e35a258 100644 --- a/node/Address.hpp +++ b/node/Address.hpp @@ -21,8 +21,6 @@ #define ZT_ADDRESS_STRING_SIZE_MAX (ZT_ADDRESS_LENGTH_HEX + 1) -static_assert(ZT_ADDRESS_LENGTH == 5,"parts of Address will need modification for any change in ZT_ADDRESS_LENGTH"); - namespace ZeroTier { /** diff --git a/node/Buf.hpp b/node/Buf.hpp index b06d853e7..f25121f6e 100644 --- a/node/Buf.hpp +++ b/node/Buf.hpp @@ -394,9 +394,12 @@ public: { const char *const s = (const char *)(unsafeData + ii); const int sii = ii; - while (likely(ii < ZT_BUF_MEM_SIZE)) { + while (ii < ZT_BUF_MEM_SIZE) { if (unsafeData[ii++] == 0) { - Utils::copy(buf,s,ii - sii); + const int l = ii - sii; + if (unlikely((unsigned int)l > bufSize)) + return nullptr; + Utils::copy(buf,s,l); return buf; } } diff --git a/node/CMakeLists.txt b/node/CMakeLists.txt index 82b92e8b8..edf5b427e 100644 --- a/node/CMakeLists.txt +++ b/node/CMakeLists.txt @@ -41,7 +41,6 @@ set(core_headers SelfAwareness.hpp SHA512.hpp SharedPtr.hpp - Speck128.hpp SymmetricKey.hpp Tag.hpp Topology.hpp diff --git a/node/Capability.cpp b/node/Capability.cpp index 4b3bb35bf..e70724bf0 100644 --- a/node/Capability.cpp +++ b/node/Capability.cpp @@ -18,44 +18,52 @@ namespace ZeroTier { -bool Capability::sign(const Identity &from,const Address &to) noexcept +bool Capability::sign(const Identity &from, const Address &to) noexcept { uint8_t buf[ZT_CAPABILITY_MARSHAL_SIZE_MAX + 16]; m_issuedTo = to; m_signedBy = from.address(); - m_signatureLength = from.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); + m_signatureLength = from.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature)); return m_signatureLength > 0; } -int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX],const bool forSign) const noexcept +int Capability::marshal(uint8_t data[ZT_CAPABILITY_MARSHAL_SIZE_MAX], const bool forSign) const noexcept { int p = 0; if (forSign) { - for(int k=0;k<8;++k) + for (int k = 0;k < 8;++k) data[p++] = 0x7f; } - Utils::storeBigEndian(data + p, m_nwid); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)m_ts); p += 8; - Utils::storeBigEndian(data + p, m_id); p += 4; + Utils::storeBigEndian(data + p, m_nwid); + p += 8; + Utils::storeBigEndian(data + p, (uint64_t) m_ts); + p += 8; + Utils::storeBigEndian(data + p, m_id); + p += 4; - Utils::storeBigEndian(data + p,(uint16_t)m_ruleCount); p += 2; + Utils::storeBigEndian(data + p, (uint16_t) m_ruleCount); + p += 2; p += Capability::marshalVirtualNetworkRules(data + p, m_rules, m_ruleCount); // LEGACY: older versions supported multiple records with this being a maximum custody // chain length. This is deprecated so set the max chain length to one. - data[p++] = (uint8_t)1; + data[p++] = (uint8_t) 1; if (!forSign) { - m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - m_signedBy.copyTo(data + 0); p += ZT_ADDRESS_LENGTH; + m_issuedTo.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + 0); + p += ZT_ADDRESS_LENGTH; data[p++] = 1; // LEGACY: old versions require a reserved byte here - Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; - Utils::copy(data + p, m_signature, m_signatureLength); p += (int)m_signatureLength; + Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength); + p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); + p += (int) m_signatureLength; // LEGACY: older versions supported more than one record terminated by a zero address. - for(int k=0;k(data); - m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_ts = (int64_t) Utils::loadBigEndian(data + 8); m_id = Utils::loadBigEndian(data + 16); const unsigned int rc = Utils::loadBigEndian(data + 20); if (rc > ZT_MAX_CAPABILITY_RULES) return -1; - const int rulesLen = unmarshalVirtualNetworkRules(data + 22,len - 22, m_rules, m_ruleCount, rc); + const int rulesLen = unmarshalVirtualNetworkRules(data + 22, len - 22, m_rules, m_ruleCount, rc); if (rulesLen < 0) return rulesLen; int p = 22 + rulesLen; @@ -95,10 +103,11 @@ int Capability::unmarshal(const uint8_t *data,int len) noexcept // this feature was never used, just set the signature and issued to and other related // fields each time and we should only ever see one. If there's more than one and the // last is not the controller, this credential will just fail validity check. - for(unsigned int i=0;;++i) { + for (unsigned int i = 0;;++i) { if ((p + ZT_ADDRESS_LENGTH) > len) return -1; - const Address to(data + p); p += ZT_ADDRESS_LENGTH; + const Address to(data + p); + p += ZT_ADDRESS_LENGTH; if (!to) break; @@ -106,14 +115,17 @@ int Capability::unmarshal(const uint8_t *data,int len) noexcept m_issuedTo = to; if ((p + ZT_ADDRESS_LENGTH) > len) return -1; - m_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; // LEGACY: +1 to skip reserved field + m_signedBy.setTo(data + p); + p += ZT_ADDRESS_LENGTH + 1; // LEGACY: +1 to skip reserved field if ((p + 2) > len) return -1; - m_signatureLength = Utils::loadBigEndian(data + p); p += 2; - if ((m_signatureLength > sizeof(m_signature)) || ((p + (int)m_signatureLength) > len)) + m_signatureLength = Utils::loadBigEndian(data + p); + p += 2; + if ((m_signatureLength > sizeof(m_signature)) || ((p + (int) m_signatureLength) > len)) return -1; - Utils::copy(m_signature, data + p, m_signatureLength); p += (int)m_signatureLength; + Utils::copy(m_signature, data + p, m_signatureLength); + p += (int) m_signatureLength; } if ((p + 2) > len) @@ -126,12 +138,12 @@ int Capability::unmarshal(const uint8_t *data,int len) noexcept return p; } -int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetworkRule *const rules,const unsigned int ruleCount) noexcept +int Capability::marshalVirtualNetworkRules(uint8_t *data, const ZT_VirtualNetworkRule *const rules, const unsigned int ruleCount) noexcept { int p = 0; - for(unsigned int i=0;i(data + p,rules[i].v.fwd.address); p += 8; - Utils::storeBigEndian(data + p,rules[i].v.fwd.flags); p += 4; - Utils::storeBigEndian(data + p,rules[i].v.fwd.length); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.fwd.address); + p += 8; + Utils::storeBigEndian(data + p, rules[i].v.fwd.flags); + p += 4; + Utils::storeBigEndian(data + p, rules[i].v.fwd.length); + p += 2; break; case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: data[p++] = 5; - Address(rules[i].v.zt).copyTo(data + p); p += ZT_ADDRESS_LENGTH; + Address(rules[i].v.zt).copyTo(data + p); + p += ZT_ADDRESS_LENGTH; break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: data[p++] = 2; - Utils::storeBigEndian(data + p,rules[i].v.vlanId); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.vlanId); + p += 2; break; case ZT_NETWORK_RULE_MATCH_VLAN_PCP: data[p++] = 1; @@ -163,7 +180,8 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: data[p++] = 6; - MAC(rules[i].v.mac).copyTo(data + p); p += 6; + MAC(rules[i].v.mac).copyTo(data + p); + p += 6; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: @@ -177,7 +195,8 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: data[p++] = 17; - Utils::copy<16>(data + p,rules[i].v.ipv6.ip); p += 16; + Utils::copy<16>(data + p, rules[i].v.ipv6.ip); + p += 16; data[p++] = rules[i].v.ipv6.mask; break; case ZT_NETWORK_RULE_MATCH_IP_TOS: @@ -192,7 +211,8 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork break; case ZT_NETWORK_RULE_MATCH_ETHERTYPE: data[p++] = 2; - Utils::storeBigEndian(data + p,rules[i].v.etherType); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.etherType); + p += 2; break; case ZT_NETWORK_RULE_MATCH_ICMP: data[p++] = 3; @@ -203,21 +223,27 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: data[p++] = 4; - Utils::storeBigEndian(data + p,rules[i].v.port[0]); p += 2; - Utils::storeBigEndian(data + p,rules[i].v.port[1]); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.port[0]); + p += 2; + Utils::storeBigEndian(data + p, rules[i].v.port[1]); + p += 2; break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: data[p++] = 8; - Utils::storeBigEndian(data + p,rules[i].v.characteristics); p += 8; + Utils::storeBigEndian(data + p, rules[i].v.characteristics); + p += 8; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: data[p++] = 4; - Utils::storeBigEndian(data + p,rules[i].v.frameSize[0]); p += 2; - Utils::storeBigEndian(data + p,rules[i].v.frameSize[1]); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.frameSize[0]); + p += 2; + Utils::storeBigEndian(data + p, rules[i].v.frameSize[1]); + p += 2; break; case ZT_NETWORK_RULE_MATCH_RANDOM: data[p++] = 4; - Utils::storeBigEndian(data + p,rules[i].v.randomProbability); p += 4; + Utils::storeBigEndian(data + p, rules[i].v.randomProbability); + p += 4; break; case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE: case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: @@ -227,14 +253,19 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork case ZT_NETWORK_RULE_MATCH_TAG_SENDER: case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: data[p++] = 8; - Utils::storeBigEndian(data + p,rules[i].v.tag.id); p += 4; - Utils::storeBigEndian(data + p,rules[i].v.tag.value); p += 4; + Utils::storeBigEndian(data + p, rules[i].v.tag.id); + p += 4; + Utils::storeBigEndian(data + p, rules[i].v.tag.value); + p += 4; break; case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: data[p++] = 19; - Utils::storeBigEndian(data + p,rules[i].v.intRange.start); p += 8; - Utils::storeBigEndian(data + p,rules[i].v.intRange.start + (uint64_t)rules[i].v.intRange.end); p += 8; - Utils::storeBigEndian(data + p,rules[i].v.intRange.idx); p += 2; + Utils::storeBigEndian(data + p, rules[i].v.intRange.start); + p += 8; + Utils::storeBigEndian(data + p, rules[i].v.intRange.start + (uint64_t) rules[i].v.intRange.end); + p += 8; + Utils::storeBigEndian(data + p, rules[i].v.intRange.idx); + p += 2; data[p++] = rules[i].v.intRange.format; break; } @@ -242,7 +273,7 @@ int Capability::marshalVirtualNetworkRules(uint8_t *data,const ZT_VirtualNetwork return p; } -int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int len,ZT_VirtualNetworkRule *const rules,unsigned int &ruleCount,const unsigned int maxRuleCount) noexcept +int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data, const int len, ZT_VirtualNetworkRule *const rules, unsigned int &ruleCount, const unsigned int maxRuleCount) noexcept { int p = 0; unsigned int rc = 0; @@ -250,28 +281,33 @@ int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int if (p >= len) return -1; rules[ruleCount].t = data[p++]; - const int fieldLen = (int)data[p++]; + const int fieldLen = (int) data[p++]; if ((p + fieldLen) > len) return -1; - switch((ZT_VirtualNetworkRuleType)(rules[ruleCount].t & 0x3fU)) { + switch ((ZT_VirtualNetworkRuleType) (rules[ruleCount].t & 0x3fU)) { default: break; case ZT_NETWORK_RULE_ACTION_TEE: case ZT_NETWORK_RULE_ACTION_WATCH: case ZT_NETWORK_RULE_ACTION_REDIRECT: if ((p + 14) > len) return -1; - rules[ruleCount].v.fwd.address = Utils::loadBigEndian(data + p); p += 8; - rules[ruleCount].v.fwd.flags = Utils::loadBigEndian(data + p); p += 4; - rules[ruleCount].v.fwd.length = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.fwd.address = Utils::loadBigEndian(data + p); + p += 8; + rules[ruleCount].v.fwd.flags = Utils::loadBigEndian(data + p); + p += 4; + rules[ruleCount].v.fwd.length = Utils::loadBigEndian(data + p); + p += 2; break; case ZT_NETWORK_RULE_MATCH_SOURCE_ZEROTIER_ADDRESS: case ZT_NETWORK_RULE_MATCH_DEST_ZEROTIER_ADDRESS: if ((p + ZT_ADDRESS_LENGTH) > len) return -1; - rules[ruleCount].v.zt = Address(data + p).toInt(); p += ZT_ADDRESS_LENGTH; + rules[ruleCount].v.zt = Address(data + p).toInt(); + p += ZT_ADDRESS_LENGTH; break; case ZT_NETWORK_RULE_MATCH_VLAN_ID: if ((p + 2) > len) return -1; - rules[ruleCount].v.vlanId = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.vlanId = Utils::loadBigEndian(data + p); + p += 2; break; case ZT_NETWORK_RULE_MATCH_VLAN_PCP: if ((p + 1) > len) return -1; @@ -284,18 +320,21 @@ int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int case ZT_NETWORK_RULE_MATCH_MAC_SOURCE: case ZT_NETWORK_RULE_MATCH_MAC_DEST: if ((p + 6) > len) return -1; - Utils::copy<6>(rules[ruleCount].v.mac,data + p); p += 6; + Utils::copy<6>(rules[ruleCount].v.mac, data + p); + p += 6; break; case ZT_NETWORK_RULE_MATCH_IPV4_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV4_DEST: if ((p + 5) > len) return -1; - Utils::copy<4>(&(rules[ruleCount].v.ipv4.ip),data + p); p += 4; + Utils::copy<4>(&(rules[ruleCount].v.ipv4.ip), data + p); + p += 4; rules[ruleCount].v.ipv4.mask = data[p++]; break; case ZT_NETWORK_RULE_MATCH_IPV6_SOURCE: case ZT_NETWORK_RULE_MATCH_IPV6_DEST: if ((p + 17) > len) return -1; - Utils::copy<16>(rules[ruleCount].v.ipv6.ip,data + p); p += 16; + Utils::copy<16>(rules[ruleCount].v.ipv6.ip, data + p); + p += 16; rules[ruleCount].v.ipv6.mask = data[p++]; break; case ZT_NETWORK_RULE_MATCH_IP_TOS: @@ -310,7 +349,8 @@ int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int break; case ZT_NETWORK_RULE_MATCH_ETHERTYPE: if ((p + 2) > len) return -1; - rules[ruleCount].v.etherType = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.etherType = Utils::loadBigEndian(data + p); + p += 2; break; case ZT_NETWORK_RULE_MATCH_ICMP: if ((p + 3) > len) return -1; @@ -321,21 +361,27 @@ int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int case ZT_NETWORK_RULE_MATCH_IP_SOURCE_PORT_RANGE: case ZT_NETWORK_RULE_MATCH_IP_DEST_PORT_RANGE: if ((p + 4) > len) return -1; - rules[ruleCount].v.port[0] = Utils::loadBigEndian(data + p); p += 2; - rules[ruleCount].v.port[1] = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.port[0] = Utils::loadBigEndian(data + p); + p += 2; + rules[ruleCount].v.port[1] = Utils::loadBigEndian(data + p); + p += 2; break; case ZT_NETWORK_RULE_MATCH_CHARACTERISTICS: if ((p + 8) > len) return -1; - rules[ruleCount].v.characteristics = Utils::loadBigEndian(data + p); p += 8; + rules[ruleCount].v.characteristics = Utils::loadBigEndian(data + p); + p += 8; break; case ZT_NETWORK_RULE_MATCH_FRAME_SIZE_RANGE: if ((p + 4) > len) return -1; - rules[ruleCount].v.frameSize[0] = Utils::loadBigEndian(data + p); p += 2; - rules[ruleCount].v.frameSize[1] = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.frameSize[0] = Utils::loadBigEndian(data + p); + p += 2; + rules[ruleCount].v.frameSize[1] = Utils::loadBigEndian(data + p); + p += 2; break; case ZT_NETWORK_RULE_MATCH_RANDOM: if ((p + 4) > len) return -1; - rules[ruleCount].v.randomProbability = Utils::loadBigEndian(data + p); p += 4; + rules[ruleCount].v.randomProbability = Utils::loadBigEndian(data + p); + p += 4; break; case ZT_NETWORK_RULE_MATCH_TAGS_DIFFERENCE: case ZT_NETWORK_RULE_MATCH_TAGS_BITWISE_AND: @@ -345,14 +391,19 @@ int Capability::unmarshalVirtualNetworkRules(const uint8_t *const data,const int case ZT_NETWORK_RULE_MATCH_TAG_SENDER: case ZT_NETWORK_RULE_MATCH_TAG_RECEIVER: if ((p + 4) > len) return -1; - rules[ruleCount].v.tag.id = Utils::loadBigEndian(data + p); p += 4; - rules[ruleCount].v.tag.value = Utils::loadBigEndian(data + p); p += 4; + rules[ruleCount].v.tag.id = Utils::loadBigEndian(data + p); + p += 4; + rules[ruleCount].v.tag.value = Utils::loadBigEndian(data + p); + p += 4; break; case ZT_NETWORK_RULE_MATCH_INTEGER_RANGE: if ((p + 19) > len) return -1; - rules[ruleCount].v.intRange.start = Utils::loadBigEndian(data + p); p += 8; - rules[ruleCount].v.intRange.end = (uint32_t)(Utils::loadBigEndian(data + p) - rules[ruleCount].v.intRange.start); p += 8; - rules[ruleCount].v.intRange.idx = Utils::loadBigEndian(data + p); p += 2; + rules[ruleCount].v.intRange.start = Utils::loadBigEndian(data + p); + p += 8; + rules[ruleCount].v.intRange.end = (uint32_t) (Utils::loadBigEndian(data + p) - rules[ruleCount].v.intRange.start); + p += 8; + rules[ruleCount].v.intRange.idx = Utils::loadBigEndian(data + p); + p += 2; rules[ruleCount].v.intRange.format = data[p++]; break; } diff --git a/node/CertificateOfMembership.cpp b/node/CertificateOfMembership.cpp index ff1acbe9e..f166086f4 100644 --- a/node/CertificateOfMembership.cpp +++ b/node/CertificateOfMembership.cpp @@ -15,12 +15,13 @@ namespace ZeroTier { -CertificateOfMembership::CertificateOfMembership(const int64_t timestamp,const int64_t timestampMaxDelta,const uint64_t nwid,const Identity &issuedTo) noexcept : // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) +CertificateOfMembership::CertificateOfMembership(const int64_t timestamp, const int64_t timestampMaxDelta, const uint64_t nwid, const Identity &issuedTo) noexcept: // NOLINT(cppcoreguidelines-pro-type-member-init,hicpp-member-init) m_timestamp(timestamp), m_timestampMaxDelta(timestampMaxDelta), m_networkId(nwid), m_issuedTo(issuedTo.fingerprint()), - m_signatureLength(0) {} + m_signatureLength(0) +{} bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) const noexcept { @@ -36,10 +37,10 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c } // us <> them - for(FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { + for (FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { if (i->delta != 0xffffffffffffffffULL) { const uint64_t *v2 = nullptr; - for(FCV::const_iterator j(other.m_additionalQualifiers.begin());j != other.m_additionalQualifiers.end();++i) { + for (FCV::const_iterator j(other.m_additionalQualifiers.begin());j != other.m_additionalQualifiers.end();++i) { if (j->id == i->id) { v2 = &(j->value); break; @@ -58,10 +59,10 @@ bool CertificateOfMembership::agreesWith(const CertificateOfMembership &other) c } // them <> us (we need a second pass in case they have qualifiers we don't or vice versa) - for(FCV::const_iterator i(other.m_additionalQualifiers.begin());i != other.m_additionalQualifiers.end();++i) { + for (FCV::const_iterator i(other.m_additionalQualifiers.begin());i != other.m_additionalQualifiers.end();++i) { if (i->delta != 0xffffffffffffffffULL) { const uint64_t *v2 = nullptr; - for(FCV::const_iterator j(m_additionalQualifiers.begin());j != m_additionalQualifiers.end();++i) { + for (FCV::const_iterator j(m_additionalQualifiers.begin());j != m_additionalQualifiers.end();++i) { if (j->id == i->id) { v2 = &(j->value); break; @@ -93,45 +94,59 @@ bool CertificateOfMembership::sign(const Identity &with) noexcept return m_signatureLength > 0; } -int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX],const bool v2) const noexcept +int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MARSHAL_SIZE_MAX], const bool v2) const noexcept { data[0] = v2 ? 2 : 1; // All formats start with the standard three qualifiers: timestamp with delta, network ID as a strict // equality compare, and the address of the issued-to node as an informational tuple. int p = 3; - Utils::storeBigEndian(data + p,0); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)m_timestamp); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)m_timestampMaxDelta); p += 8; - Utils::storeBigEndian(data + p,1); p += 8; - Utils::storeBigEndian(data + p, m_networkId); p += 8; - Utils::storeBigEndian(data + p,0); p += 8; - Utils::storeBigEndian(data + p,2); p += 8; - Utils::storeBigEndian(data + p, m_issuedTo.address().toInt()); p += 8; - Utils::storeAsIsEndian(data + p,0xffffffffffffffffULL); p += 8; + Utils::storeBigEndian(data + p, 0); + p += 8; + Utils::storeBigEndian(data + p, (uint64_t) m_timestamp); + p += 8; + Utils::storeBigEndian(data + p, (uint64_t) m_timestampMaxDelta); + p += 8; + Utils::storeBigEndian(data + p, 1); + p += 8; + Utils::storeBigEndian(data + p, m_networkId); + p += 8; + Utils::storeBigEndian(data + p, 0); + p += 8; + Utils::storeBigEndian(data + p, 2); + p += 8; + Utils::storeBigEndian(data + p, m_issuedTo.address().toInt()); + p += 8; + Utils::storeAsIsEndian(data + p, 0xffffffffffffffffULL); + p += 8; if (v2) { // V2 marshal format will have three tuples followed by the fingerprint hash. - Utils::storeBigEndian(data + 1,3); + Utils::storeBigEndian(data + 1, 3); Utils::copy<48>(data + p, m_issuedTo.hash()); p += 48; } else { // V1 marshal format must shove everything into tuples, resulting in nine. - Utils::storeBigEndian(data + 1,9); - for(int k=0;k<6;++k) { - Utils::storeBigEndian(data + p,(uint64_t)k + 3); p += 8; - Utils::storeAsIsEndian(data + p,Utils::loadAsIsEndian(m_issuedTo.hash() + (k * 8))); p += 8; - Utils::storeAsIsEndian(data + p,0xffffffffffffffffULL); p += 8; + Utils::storeBigEndian(data + 1, 9); + for (int k = 0;k < 6;++k) { + Utils::storeBigEndian(data + p, (uint64_t) k + 3); + p += 8; + Utils::storeAsIsEndian(data + p, Utils::loadAsIsEndian(m_issuedTo.hash() + (k * 8))); + p += 8; + Utils::storeAsIsEndian(data + p, 0xffffffffffffffffULL); + p += 8; } } - m_signedBy.copyTo(data + p); p += 5; + m_signedBy.copyTo(data + p); + p += 5; if (v2) { // V2 marshal format prefixes signatures with a 16-bit length to support future signature types. - Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength); + p += 2; Utils::copy(data + p, m_signature, m_signatureLength); - p += (int)m_signatureLength; + p += (int) m_signatureLength; } else { // V1 only supports 96-byte signature fields. Utils::copy<96>(data + p, m_signature); @@ -141,7 +156,7 @@ int CertificateOfMembership::marshal(uint8_t data[ZT_CERTIFICATEOFMEMBERSHIP_MAR return p; } -int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept +int CertificateOfMembership::unmarshal(const uint8_t *data, int len) noexcept { if (len < (1 + 2 + 72)) return -1; @@ -149,19 +164,22 @@ int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept TriviallyCopyable::memoryZero(this); const unsigned int numq = Utils::loadBigEndian(data + 1); - if ((numq < 3)||(numq > (ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS + 3))) + if ((numq < 3) || (numq > (ZT_CERTIFICATEOFMEMBERSHIP_MAX_ADDITIONAL_QUALIFIERS + 3))) return -1; int p = 3; - for(unsigned int q=0;q len) return -1; - const uint64_t id = Utils::loadBigEndian(data + p); p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint64_t value = Utils::loadBigEndian(data + p); p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) - const uint64_t delta = Utils::loadBigEndian(data + p); p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) - switch(id) { + const uint64_t id = Utils::loadBigEndian(data + p); + p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint64_t value = Utils::loadBigEndian(data + p); + p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) + const uint64_t delta = Utils::loadBigEndian(data + p); + p += 8; // NOLINT(hicpp-use-auto,modernize-use-auto) + switch (id) { case 0: - m_timestamp = (int64_t)value; - m_timestampMaxDelta = (int64_t)delta; + m_timestamp = (int64_t) value; + m_timestampMaxDelta = (int64_t) delta; break; case 1: m_networkId = value; @@ -214,10 +232,10 @@ int CertificateOfMembership::unmarshal(const uint8_t *data,int len) noexcept if ((p + 2) > len) return -1; m_signatureLength = Utils::loadBigEndian(data + p); - if ((m_signatureLength > (unsigned int)sizeof(m_signature)) || ((p + (int)m_signatureLength) > len)) + if ((m_signatureLength > (unsigned int) sizeof(m_signature)) || ((p + (int) m_signatureLength) > len)) return -1; Utils::copy(m_signature, data + p, m_signatureLength); - return p + (int)m_signatureLength; + return p + (int) m_signatureLength; } return -1; @@ -235,8 +253,8 @@ unsigned int CertificateOfMembership::m_fillSigningBuf(uint64_t *buf) const noex // The standard three tuples that must begin every COM. buf[0] = 0; - buf[1] = Utils::hton((uint64_t)m_timestamp); - buf[2] = Utils::hton((uint64_t)m_timestampMaxDelta); + buf[1] = Utils::hton((uint64_t) m_timestamp); + buf[2] = Utils::hton((uint64_t) m_timestampMaxDelta); buf[3] = ZT_CONST_TO_BE_UINT64(1); buf[4] = Utils::hton(m_networkId); buf[5] = 0; @@ -269,7 +287,7 @@ unsigned int CertificateOfMembership::m_fillSigningBuf(uint64_t *buf) const noex buf[p++] = informational; } - for(FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { // NOLINT(modernize-loop-convert) + for (FCV::const_iterator i(m_additionalQualifiers.begin());i != m_additionalQualifiers.end();++i) { // NOLINT(modernize-loop-convert) buf[p++] = Utils::hton(i->id); buf[p++] = Utils::hton(i->value); buf[p++] = Utils::hton(i->delta); diff --git a/node/CertificateOfOwnership.cpp b/node/CertificateOfOwnership.cpp index 4dacdc74f..71f7b94e7 100644 --- a/node/CertificateOfOwnership.cpp +++ b/node/CertificateOfOwnership.cpp @@ -44,53 +44,57 @@ bool CertificateOfOwnership::sign(const Identity &signer) uint8_t buf[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX + 16]; if (signer.hasPrivate()) { m_signedBy = signer.address(); - m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); + m_signatureLength = signer.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; } -int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX],bool forSign) const noexcept +int CertificateOfOwnership::marshal(uint8_t data[ZT_CERTIFICATEOFOWNERSHIP_MARSHAL_SIZE_MAX], bool forSign) const noexcept { int p = 0; if (forSign) { - for(int k=0;k<16;++k) + for (int k = 0;k < 16;++k) data[p++] = 0x7f; } Utils::storeBigEndian(data + p, m_networkId); - Utils::storeBigEndian(data + p + 8,(uint64_t)m_ts); + Utils::storeBigEndian(data + p + 8, (uint64_t) m_ts); Utils::storeBigEndian(data + p + 16, m_flags); Utils::storeBigEndian(data + p + 24, m_id); - Utils::storeBigEndian(data + p + 28,(uint16_t)m_thingCount); + Utils::storeBigEndian(data + p + 28, (uint16_t) m_thingCount); p += 30; - for(unsigned int i=0,j=m_thingCount;i < j;++i) { + for (unsigned int i = 0, j = m_thingCount;i < j;++i) { data[p++] = m_thingTypes[i]; Utils::copy(data + p, m_thingValues[i]); p += ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE; } - m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + m_issuedTo.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; - Utils::copy(data + p, m_signature, m_signatureLength); p += (int)m_signatureLength; + Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength); + p += 2; + Utils::copy(data + p, m_signature, m_signatureLength); + p += (int) m_signatureLength; } data[p++] = 0; data[p++] = 0; if (forSign) { - for(int k=0;k<16;++k) + for (int k = 0;k < 16;++k) data[p++] = 0x7f; } return p; } -int CertificateOfOwnership::unmarshal(const uint8_t *data,int len) noexcept +int CertificateOfOwnership::unmarshal(const uint8_t *data, int len) noexcept { if (len < 30) return -1; m_networkId = Utils::loadBigEndian(data); - m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_ts = (int64_t) Utils::loadBigEndian(data + 8); m_flags = Utils::loadBigEndian(data + 16); m_id = Utils::loadBigEndian(data + 24); m_thingCount = Utils::loadBigEndian(data + 28); @@ -98,7 +102,7 @@ int CertificateOfOwnership::unmarshal(const uint8_t *data,int len) noexcept return -1; int p = 30; - for(unsigned int i=0,j=m_thingCount;i < j;++i) { + for (unsigned int i = 0, j = m_thingCount;i < j;++i) { if ((p + 1 + ZT_CERTIFICATEOFOWNERSHIP_MAX_THING_VALUE_SIZE) > len) return -1; m_thingTypes[i] = data[p++]; @@ -108,8 +112,10 @@ int CertificateOfOwnership::unmarshal(const uint8_t *data,int len) noexcept if ((p + ZT_ADDRESS_LENGTH + ZT_ADDRESS_LENGTH + 1 + 2) > len) return -1; - m_issuedTo.setTo(data + p); p += ZT_ADDRESS_LENGTH; - m_signedBy.setTo(data + p); p += ZT_ADDRESS_LENGTH + 1; + m_issuedTo.setTo(data + p); + p += ZT_ADDRESS_LENGTH; + m_signedBy.setTo(data + p); + p += ZT_ADDRESS_LENGTH + 1; p += 2 + Utils::loadBigEndian(data + p); if (p > len) diff --git a/node/Identity.cpp b/node/Identity.cpp index dffbfc7da..d212ee9c5 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -16,10 +16,8 @@ #include "SHA512.hpp" #include "Salsa20.hpp" #include "Utils.hpp" -#include "Speck128.hpp" +#include "AES.hpp" -#include -#include #include namespace ZeroTier { @@ -78,74 +76,34 @@ struct identityV0ProofOfWorkCriteria // It's not quite as heavy as the V0 frankenhash, is a little more orderly in // its design, but remains relatively resistant to GPU acceleration due to memory // requirements for efficient computation. -#define ZT_IDENTITY_V1_POW_MEMORY_SIZE 98304 +#define ZT_IDENTITY_V1_POW_MEMORY_SIZE 1048576 +#define ZT_IDENTITY_V1_POW_MEMORY_SIZE_U64 131072 bool identityV1ProofOfWorkCriteria(const void *in,const unsigned int len,uint64_t *const b) { SHA512(b,in,len); - // This treats hash output as little-endian, so swap on BE machines. -#if __BYTE_ORDER == __BIG_ENDIAN - b[0] = Utils::swapBytes(b[0]); - b[1] = Utils::swapBytes(b[1]); - b[2] = Utils::swapBytes(b[2]); - b[3] = Utils::swapBytes(b[3]); - b[4] = Utils::swapBytes(b[4]); - b[5] = Utils::swapBytes(b[5]); - b[6] = Utils::swapBytes(b[6]); - b[7] = Utils::swapBytes(b[7]); -#endif - - // Memory-intensive work: fill 'b' with pseudo-random bits generated from - // a reduced-round instance of Speck128 using a CBC-like construction. - // Then sort the resulting integer array in ascending numerical order. - // The sort requires that we compute and cache the whole data set, or at - // least that this is the most efficient implementation. - Speck128<24> s16; - s16.initXY(b[4],b[5]); - for(unsigned long i=0;i<(ZT_IDENTITY_V1_POW_MEMORY_SIZE-8);) { - // Load four 128-bit blocks. - uint64_t x0 = b[i]; - uint64_t y0 = b[i + 1]; - uint64_t x1 = b[i + 2]; - uint64_t y1 = b[i + 3]; - uint64_t x2 = b[i + 4]; - uint64_t y2 = b[i + 5]; - uint64_t x3 = b[i + 6]; - uint64_t y3 = b[i + 7]; - - // Advance by 512 bits / 64 bytes (its a uint64_t array). - i += 8; - - // Ensure that mixing happens across blocks. - x0 += x1; - x1 += x2; - x2 += x3; - x3 += y0; - - // Encrypt 4X blocks. Speck is used for this PoW function because - // its performance is similar on all architectures while AES is much - // faster on some than others. - s16.encryptXYXYXYXY(x0,y0,x1,y1,x2,y2,x3,y3); - - // Store four 128-bit blocks at new position. - b[i] = x0; - b[i + 1] = y0; - b[i + 2] = x1; - b[i + 3] = y1; - b[i + 4] = x2; - b[i + 5] = y2; - b[i + 6] = x3; - b[i + 7] = y3; + AES c(b); + for(unsigned int i=8;i> 49U))) + c.encrypt(b + i,b + i); } - // Sort array, something that can't efficiently be done unless we have - // computed the whole array and have it in memory. This also involves - // branching which is less efficient on GPUs. - std::sort(b,b + ZT_IDENTITY_V1_POW_MEMORY_SIZE); - - // Swap byte order back on BE machines. #if __BYTE_ORDER == __BIG_ENDIAN - for(unsigned int i=0;i<98304;i+=8) { + for(unsigned int i=0;icom.marshal(tmp)); } - std::vector *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES]); + Vector *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_CAPABILITIES]); for (unsigned int i = 0; i < this->capabilityCount; ++i) { int l = this->capabilities[i].marshal(tmp); if (l < 0) @@ -121,7 +121,7 @@ bool NetworkConfig::fromDictionary(const Dictionary &d) this->credentialTimeMaxDelta = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_CREDENTIAL_TIME_MAX_DELTA,0); this->revision = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_REVISION,0); this->issuedTo = d.getUI(ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO,0); - const std::vector *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]); + const Vector *blob = &(d[ZT_NETWORKCONFIG_DICT_KEY_ISSUED_TO_IDENTITY_HASH]); if (blob->size() == ZT_FINGERPRINT_HASH_SIZE) { Utils::copy(this->issuedToFingerprintHash,blob->data()); } else { diff --git a/node/PeerList.hpp b/node/PeerList.hpp index ed60eb9ba..988f284bc 100644 --- a/node/PeerList.hpp +++ b/node/PeerList.hpp @@ -33,7 +33,7 @@ namespace ZeroTier { class PeerList { public: - ZT_INLINE PeerList() noexcept : + ZT_INLINE PeerList() noexcept: m_onePeer(), m_peers(&m_onePeer), m_peerCount(0) @@ -47,7 +47,7 @@ public: m_peers = &m_onePeer; } else { m_peers = new SharedPtr[pc]; - for (unsigned int i=0;i &operator[](const unsigned int i) noexcept { return m_peers[i]; } - ZT_INLINE const SharedPtr &operator[](const unsigned int i) const noexcept { return m_peers[i]; } - ZT_INLINE unsigned int size() const noexcept { return m_peerCount; } + ZT_INLINE SharedPtr &operator[](const unsigned int i) noexcept + { return m_peers[i]; } + + ZT_INLINE const SharedPtr &operator[](const unsigned int i) const noexcept + { return m_peers[i]; } + + ZT_INLINE unsigned int size() const noexcept + { return m_peerCount; } private: - SharedPtr m_onePeer; - SharedPtr *m_peers; + SharedPtr m_onePeer; + SharedPtr *m_peers; unsigned int m_peerCount; }; diff --git a/node/Revocation.cpp b/node/Revocation.cpp index a21111cc0..eb1d0e8b6 100644 --- a/node/Revocation.cpp +++ b/node/Revocation.cpp @@ -17,48 +17,57 @@ namespace ZeroTier { bool Revocation::sign(const Identity &signer) noexcept { - uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX+32]; + uint8_t buf[ZT_REVOCATION_MARSHAL_SIZE_MAX + 32]; if (signer.hasPrivate()) { m_signedBy = signer.address(); - m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); + m_signatureLength = signer.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; } -int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX],bool forSign) const noexcept +int Revocation::marshal(uint8_t data[ZT_REVOCATION_MARSHAL_SIZE_MAX], bool forSign) const noexcept { int p = 0; if (forSign) { - for(int k=0;k<8;++k) + for (int k = 0;k < 8;++k) data[p++] = 0x7f; } - Utils::storeBigEndian(data + p,0); p += 4; - Utils::storeBigEndian(data + p, m_id); p += 4; - Utils::storeBigEndian(data + p, m_networkId); p += 8; - Utils::storeBigEndian(data + p,0); p += 4; - Utils::storeBigEndian(data + p, m_credentialId); p += 4; - Utils::storeBigEndian(data + p,(uint64_t)m_threshold); p += 8; - Utils::storeBigEndian(data + p, m_flags); p += 8; - m_target.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - data[p++] = (uint8_t)m_type; + Utils::storeBigEndian(data + p, 0); + p += 4; + Utils::storeBigEndian(data + p, m_id); + p += 4; + Utils::storeBigEndian(data + p, m_networkId); + p += 8; + Utils::storeBigEndian(data + p, 0); + p += 4; + Utils::storeBigEndian(data + p, m_credentialId); + p += 4; + Utils::storeBigEndian(data + p, (uint64_t) m_threshold); + p += 8; + Utils::storeBigEndian(data + p, m_flags); + p += 8; + m_target.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; + data[p++] = (uint8_t) m_type; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); + Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength); Utils::copy(data + p, m_signature, m_signatureLength); - p += (int)m_signatureLength; + p += (int) m_signatureLength; } data[p++] = 0; data[p++] = 0; if (forSign) { - for(int k=0;k<8;++k) + for (int k = 0;k < 8;++k) data[p++] = 0x7f; } return p; } -int Revocation::unmarshal(const uint8_t *restrict data,const int len) noexcept +int Revocation::unmarshal(const uint8_t *restrict data, const int len) noexcept { if (len < 54) return -1; @@ -67,14 +76,14 @@ int Revocation::unmarshal(const uint8_t *restrict data,const int len) noexcept m_networkId = Utils::loadBigEndian(data + 8); // 4 bytes reserved m_credentialId = Utils::loadBigEndian(data + 20); - m_threshold = (int64_t)Utils::loadBigEndian(data + 24); + m_threshold = (int64_t) Utils::loadBigEndian(data + 24); m_flags = Utils::loadBigEndian(data + 32); m_target.setTo(data + 40); m_signedBy.setTo(data + 45); - m_type = (ZT_CredentialType)data[50]; + m_type = (ZT_CredentialType) data[50]; // 1 byte reserved m_signatureLength = Utils::loadBigEndian(data + 52); - int p = 54 + (int)m_signatureLength; + int p = 54 + (int) m_signatureLength; if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len)) return -1; Utils::copy(m_signature, data + 54, m_signatureLength); diff --git a/node/SHA512.cpp b/node/SHA512.cpp index 619511b70..0deaf2e69 100644 --- a/node/SHA512.cpp +++ b/node/SHA512.cpp @@ -3,10 +3,6 @@ #include "SHA512.hpp" #include "Utils.hpp" -#include -#include -#include - namespace ZeroTier { #ifndef ZT_HAVE_NATIVE_SHA512 diff --git a/node/Salsa20.hpp b/node/Salsa20.hpp index ea36e1be4..399572df4 100644 --- a/node/Salsa20.hpp +++ b/node/Salsa20.hpp @@ -14,18 +14,11 @@ #ifndef ZT_SALSA20_HPP #define ZT_SALSA20_HPP -#include -#include -#include - #include "Constants.hpp" #include "Utils.hpp" #include "TriviallyCopyable.hpp" #ifdef ZT_ARCH_X64 -#include -#include -#include #define ZT_SALSA20_SSE 1 #endif diff --git a/node/Speck128.hpp b/node/Speck128.hpp deleted file mode 100644 index ad728fa45..000000000 --- a/node/Speck128.hpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c)2013-2020 ZeroTier, Inc. - * - * Use of this software is governed by the Business Source License included - * in the LICENSE.TXT file in the project's root directory. - * - * Change Date: 2024-01-01 - * - * On the date above, in accordance with the Business Source License, use - * of this software will be governed by version 2.0 of the Apache License. - */ -/****/ - -#ifndef ZT_SPECK128_HPP -#define ZT_SPECK128_HPP - -#include "Constants.hpp" -#include "Utils.hpp" - -#define ZT_SPECK128_KEY_SIZE 16 - -namespace ZeroTier { - -/** - * Tiny and simple 128-bit ARX block cipher - * - * Speck does not specify a mandatory endian-ness. This implementation is - * little-endian for higher performance on the majority of platforms. - * - * Right now this is only used as part of the PoW function for V1 identity - * generation. It's used because it's faster than SHA for filling a buffer - * with randomness and unlike AES its relative performance advantage - * across CPU architectures is pretty much identical. - * - * @tparam R Number of rounds (default: 32) - */ -template -class Speck128 -{ -public: - /** - * Create an uninitialized instance, init() must be called to set up. - */ - ZT_INLINE Speck128() noexcept {} - - /** - * Initialize Speck from a 128-bit key - * - * @param k 128-bit / 16 byte key - */ - ZT_INLINE Speck128(const void *k) noexcept { this->init(k); } - - ZT_INLINE ~Speck128() { Utils::burn(m_expandedKey, sizeof(m_expandedKey)); } - - /** - * Initialize Speck from a 128-bit key - * - * @param k 128-bit / 16 byte key - */ - ZT_INLINE void init(const void *k) noexcept - { - initXY(Utils::loadLittleEndian(k),Utils::loadLittleEndian(reinterpret_cast(k) + 8)); - } - - /** - * Initialize Speck from a 128-bit key in two 64-bit words - * - * @param x Least significant 64 bits - * @param y Most significant 64 bits - */ - ZT_INLINE void initXY(uint64_t x,uint64_t y) noexcept - { - m_expandedKey[0] = x; - for(uint64_t i=0;i<(R-1);++i) { - x = x >> 8U | x << 56U; - x += y; - x ^= i; - y = y << 3U | y >> 61U; - y ^= x; - m_expandedKey[i + 1] = y; - } - } - - /** - * Encrypt a 128-bit block as two 64-bit words - * - * These should be in host byte order. If read or written to/from data - * they should be stored in little-endian byte order. - * - * @param x Least significant 64 bits - * @param y Most significant 64 bits - */ - ZT_INLINE void encryptXY(uint64_t &x,uint64_t &y) const noexcept - { - for (int i=0;i> 8U | x << 56U; - x += y; - x ^= kk; - y = y << 3U | y >> 61U; - y ^= x; - } - } - - /** - * Encrypt 512 bits in parallel with the same key. - * - * Parallel in this case assumes instruction level parallelism, but even without that - * it may be faster due to cache/memory effects. - */ - ZT_INLINE void encryptXYXYXYXY(uint64_t &x0,uint64_t &y0,uint64_t &x1,uint64_t &y1,uint64_t &x2,uint64_t &y2,uint64_t &x3,uint64_t &y3) const noexcept - { - for (int i=0;i> 8U | x0 << 56U; - x1 = x1 >> 8U | x1 << 56U; - x2 = x2 >> 8U | x2 << 56U; - x3 = x3 >> 8U | x3 << 56U; - x0 += y0; - x1 += y1; - x2 += y2; - x3 += y3; - x0 ^= kk; - x1 ^= kk; - x2 ^= kk; - x3 ^= kk; - y0 = y0 << 3U | y0 >> 61U; - y1 = y1 << 3U | y1 >> 61U; - y2 = y2 << 3U | y2 >> 61U; - y3 = y3 << 3U | y3 >> 61U; - y0 ^= x0; - y1 ^= x1; - y2 ^= x2; - y3 ^= x3; - } - } - - /** - * Decrypt a 128-bit block as two 64-bit words - * - * These should be in host byte order. If read or written to/from data - * they should be stored in little-endian byte order. - * - * @param x Least significant 64 bits - * @param y Most significant 64 bits - */ - ZT_INLINE void decryptXY(uint64_t &x,uint64_t &y) const noexcept - { - for (int i=(R-1);i>=0;--i) { - const uint64_t kk = m_expandedKey[i]; - y ^= x; - y = y >> 3U | y << 61U; - x ^= kk; - x -= y; - x = x << 8U | x >> 56U; - } - } - - /** - * Encrypt a block - * - * @param in 128-bit / 16 byte input - * @param out 128-bit / 16 byte output - */ - ZT_INLINE void encrypt(const void *const in,void *const out) const noexcept - { - uint64_t x = Utils::loadLittleEndian(in); - uint64_t y = Utils::loadLittleEndian(reinterpret_cast(in) + 8); - encryptXY(x,y); - Utils::storeLittleEndian(out,x); - Utils::storeLittleEndian(reinterpret_cast(out) + 8,y); - } - - /** - * Decrypt a block - * - * @param in 128-bit / 16 byte input - * @param out 128-bit / 16 byte output - */ - ZT_INLINE void decrypt(const void *const in,void *const out) const noexcept - { - uint64_t x = Utils::loadLittleEndian(in); - uint64_t y = Utils::loadLittleEndian(reinterpret_cast(in) + 8); - decryptXY(x,y); - Utils::storeLittleEndian(out,x); - Utils::storeLittleEndian(reinterpret_cast(out) + 8,y); - } - -private: - uint64_t m_expandedKey[R]; -}; - -} // namespace ZeroTier - -#endif diff --git a/node/Tag.cpp b/node/Tag.cpp index 5e1efe9ec..717136371 100644 --- a/node/Tag.cpp +++ b/node/Tag.cpp @@ -20,53 +20,60 @@ bool Tag::sign(const Identity &signer) noexcept uint8_t buf[ZT_TAG_MARSHAL_SIZE_MAX]; if (signer.hasPrivate()) { m_signedBy = signer.address(); - m_signatureLength = signer.sign(buf, (unsigned int)marshal(buf, true), m_signature, sizeof(m_signature)); + m_signatureLength = signer.sign(buf, (unsigned int) marshal(buf, true), m_signature, sizeof(m_signature)); return true; } return false; } -int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX],bool forSign) const noexcept +int Tag::marshal(uint8_t data[ZT_TAG_MARSHAL_SIZE_MAX], bool forSign) const noexcept { int p = 0; if (forSign) { - for(int k=0;k<8;++k) + for (int k = 0;k < 8;++k) data[p++] = 0x7f; } - Utils::storeBigEndian(data + p, m_networkId); p += 8; - Utils::storeBigEndian(data + p,(uint64_t)m_ts); p += 8; - Utils::storeBigEndian(data + p, m_id); p += 4; - Utils::storeBigEndian(data + p, m_value); p += 4; - m_issuedTo.copyTo(data + p); p += ZT_ADDRESS_LENGTH; - m_signedBy.copyTo(data + p); p += ZT_ADDRESS_LENGTH; + Utils::storeBigEndian(data + p, m_networkId); + p += 8; + Utils::storeBigEndian(data + p, (uint64_t) m_ts); + p += 8; + Utils::storeBigEndian(data + p, m_id); + p += 4; + Utils::storeBigEndian(data + p, m_value); + p += 4; + m_issuedTo.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; + m_signedBy.copyTo(data + p); + p += ZT_ADDRESS_LENGTH; if (!forSign) { data[p++] = 1; - Utils::storeBigEndian(data + p,(uint16_t)m_signatureLength); p += 2; + Utils::storeBigEndian(data + p, (uint16_t) m_signatureLength); + p += 2; Utils::copy(data + p, m_signature, m_signatureLength); - p += (int)m_signatureLength; + p += (int) m_signatureLength; } data[p++] = 0; data[p++] = 0; if (forSign) { - for(int k=0;k<8;++k) + for (int k = 0;k < 8;++k) data[p++] = 0x7f; } return p; } -int Tag::unmarshal(const uint8_t *data,int len) noexcept +int Tag::unmarshal(const uint8_t *data, int len) noexcept { if (len < 37) return -1; m_networkId = Utils::loadBigEndian(data); - m_ts = (int64_t)Utils::loadBigEndian(data + 8); + m_ts = (int64_t) Utils::loadBigEndian(data + 8); m_id = Utils::loadBigEndian(data + 16); m_value = Utils::loadBigEndian(data + 20); m_issuedTo.setTo(data + 24); m_signedBy.setTo(data + 29); // 1 byte reserved m_signatureLength = Utils::loadBigEndian(data + 35); - int p = 37 + (int)m_signatureLength; + int p = 37 + (int) m_signatureLength; if ((m_signatureLength > ZT_SIGNATURE_BUFFER_SIZE) || (p > len)) return -1; Utils::copy(m_signature, data + p, m_signatureLength); diff --git a/node/Tests.cpp b/node/Tests.cpp index e56872458..ae4dde8b7 100644 --- a/node/Tests.cpp +++ b/node/Tests.cpp @@ -403,29 +403,29 @@ extern "C" const char *ZTT_general() FCV test,test2; for(unsigned int i=0;i<512;++i) test.push_back(LifeCycleTracker(cnt)); - if (cnt != 512) { + if (cnt != (long)test.size()) { ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (1))" ZT_EOL_S,cnt); return "FCV object life cycle test failed (1)"; } test2 = test; - if (cnt != 1024) { + if (cnt != (long)(test.size() + test2.size())) { ZT_T_PRINTF("FAILED (expected 1024 objects, got %lu (2))" ZT_EOL_S,cnt); return "FCV object life cycle test failed (2)"; } test.clear(); - if (cnt != 512) { + if (cnt != (long)test.size()) { ZT_T_PRINTF("FAILED (expected 512 objects, got %lu (3))" ZT_EOL_S,cnt); return "FCV object life cycle test failed (3)"; } for(unsigned int i=0;i<512;++i) test.push_back(LifeCycleTracker(cnt)); - if (cnt != 1024) { + if (cnt != (long)(test.size() + test2.size())) { ZT_T_PRINTF("FAILED (expected 1024 objects, got %lu (4))" ZT_EOL_S,cnt); return "FCV object life cycle test failed (4)"; } test.clear(); test2.clear(); - if (cnt != 0) { + if (cnt != (long)test.size()) { ZT_T_PRINTF("FAILED (expected 0 objects, got %lu (5))" ZT_EOL_S,cnt); return "FCV object life cycle test failed (5)"; } diff --git a/node/Topology.cpp b/node/Topology.cpp index cc48166a5..6dc44d6a4 100644 --- a/node/Topology.cpp +++ b/node/Topology.cpp @@ -15,31 +15,33 @@ namespace ZeroTier { -Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : +Topology::Topology(const RuntimeEnvironment *renv, void *tPtr) : RR(renv), m_numConfiguredPhysicalPaths(0) { - uint64_t idtmp[2]; idtmp[0] = 0; idtmp[1] = 0; - Vector data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_ROOTS,idtmp)); + uint64_t idtmp[2]; + idtmp[0] = 0; + idtmp[1] = 0; + Vector data(RR->node->stateObjectGet(tPtr, ZT_STATE_OBJECT_ROOTS, idtmp)); if (!data.empty()) { uint8_t *dptr = data.data(); - int drem = (int)data.size(); + int drem = (int) data.size(); while (drem > 0) { Identity id; - int l = id.unmarshal(dptr,drem); + int l = id.unmarshal(dptr, drem); if (l > 0) { m_roots.insert(id); dptr += l; drem -= l; - ZT_SPEW("loaded root %s",id.address().toString().c_str()); + ZT_SPEW("loaded root %s", id.address().toString().c_str()); } } } - for(Set::const_iterator r(m_roots.begin());r != m_roots.end();++r) { + for (Set::const_iterator r(m_roots.begin());r != m_roots.end();++r) { SharedPtr p; - m_loadCached(tPtr,r->address(),p); - if ((!p)||(p->identity() != *r)) { + m_loadCached(tPtr, r->address(), p); + if ((!p) || (p->identity() != *r)) { p.set(new Peer(RR)); p->init(*r); } @@ -48,26 +50,26 @@ Topology::Topology(const RuntimeEnvironment *renv,void *tPtr) : } } -SharedPtr Topology::add(void *tPtr,const SharedPtr &peer) +SharedPtr Topology::add(void *tPtr, const SharedPtr &peer) { RWMutex::Lock _l(m_peers_l); SharedPtr &hp = m_peers[peer->address()]; if (hp) return hp; - m_loadCached(tPtr,peer->address(),hp); + m_loadCached(tPtr, peer->address(), hp); if (hp) return hp; hp = peer; return peer; } -void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork,const ZT_PhysicalPathConfiguration *pathConfig) +void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathNetwork, const ZT_PhysicalPathConfiguration *pathConfig) { if (!pathNetwork) { m_numConfiguredPhysicalPaths = 0; } else { - std::map cpaths; - for(unsigned int i=0,j=m_numConfiguredPhysicalPaths;i < j;++i) + std::map cpaths; + for (unsigned int i = 0, j = m_numConfiguredPhysicalPaths;i < j;++i) cpaths[m_physicalPathConfig[i].first] = m_physicalPathConfig[i].second; if (pathConfig) { @@ -86,7 +88,7 @@ void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathN } unsigned int cnt = 0; - for(std::map::const_iterator i(cpaths.begin());((i!=cpaths.end())&&(cnt::const_iterator i(cpaths.begin());((i != cpaths.end()) && (cnt < ZT_MAX_CONFIGURABLE_PATHS));++i) { m_physicalPathConfig[cnt].first = i->first; m_physicalPathConfig[cnt].second = i->second; ++cnt; @@ -97,7 +99,7 @@ void Topology::setPhysicalPathConfiguration(const struct sockaddr_storage *pathN struct p_RootSortComparisonOperator { - ZT_INLINE bool operator()(const SharedPtr &a,const SharedPtr &b) const noexcept + ZT_INLINE bool operator()(const SharedPtr &a, const SharedPtr &b) const noexcept { // Sort in inverse order of latency with lowest latency first (and -1 last). const int bb = b->latency(); @@ -107,13 +109,13 @@ struct p_RootSortComparisonOperator } }; -void Topology::addRoot(void *const tPtr,const Identity &id,const InetAddress &bootstrap) +void Topology::addRoot(void *const tPtr, const Identity &id, const InetAddress &bootstrap) { if (id == RR->identity) return; RWMutex::Lock l1(m_peers_l); - std::pair< Set::iterator,bool > ir(m_roots.insert(id)); + std::pair::iterator, bool> ir(m_roots.insert(id)); if (ir.second) { SharedPtr &p = m_peers[id.address()]; if (!p) { @@ -123,17 +125,17 @@ void Topology::addRoot(void *const tPtr,const Identity &id,const InetAddress &bo p->setBootstrap(Endpoint(bootstrap)); } m_rootPeers.push_back(p); - std::sort(m_rootPeers.begin(),m_rootPeers.end(),p_RootSortComparisonOperator()); + std::sort(m_rootPeers.begin(), m_rootPeers.end(), p_RootSortComparisonOperator()); m_writeRootList(tPtr); } } -bool Topology::removeRoot(void *const tPtr,const Identity &id) +bool Topology::removeRoot(void *const tPtr, const Identity &id) { RWMutex::Lock l1(m_peers_l); Set::iterator r(m_roots.find(id)); if (r != m_roots.end()) { - for(Vector< SharedPtr >::iterator p(m_rootPeers.begin());p != m_rootPeers.end();++p) { + for (Vector >::iterator p(m_rootPeers.begin());p != m_rootPeers.end();++p) { if ((*p)->identity() == id) { m_rootPeers.erase(p); break; @@ -149,16 +151,16 @@ bool Topology::removeRoot(void *const tPtr,const Identity &id) void Topology::rankRoots() { RWMutex::Lock l1(m_peers_l); - std::sort(m_rootPeers.begin(),m_rootPeers.end(),p_RootSortComparisonOperator()); + std::sort(m_rootPeers.begin(), m_rootPeers.end(), p_RootSortComparisonOperator()); } -void Topology::doPeriodicTasks(void *tPtr,const int64_t now) +void Topology::doPeriodicTasks(void *tPtr, const int64_t now) { // Delete peers that haven't said anything in ZT_PEER_ALIVE_TIMEOUT. { RWMutex::Lock l1(m_peers_l); - for(Map< Address,SharedPtr >::iterator i(m_peers.begin());i != m_peers.end();) { - if ( ((now - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (m_roots.count(i->second->identity()) == 0) ) { + for (Map >::iterator i(m_peers.begin());i != m_peers.end();) { + if (((now - i->second->lastReceive()) > ZT_PEER_ALIVE_TIMEOUT) && (m_roots.count(i->second->identity()) == 0)) { i->second->save(tPtr); m_peers.erase(i++); } else ++i; @@ -168,7 +170,7 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now) // Delete paths that are no longer held by anyone else ("weak reference" type behavior). { RWMutex::Lock l1(m_paths_l); - for(Map< uint64_t,SharedPtr >::iterator i(m_paths.begin());i != m_paths.end();) { + for (Map >::iterator i(m_paths.begin());i != m_paths.end();) { if (i->second.weakGC()) m_paths.erase(i++); else ++i; @@ -179,7 +181,7 @@ void Topology::doPeriodicTasks(void *tPtr,const int64_t now) void Topology::saveAll(void *tPtr) { RWMutex::RLock l(m_peers_l); - for(Map< Address,SharedPtr >::iterator i(m_peers.begin());i!=m_peers.end();++i) + for (Map >::iterator i(m_peers.begin());i != m_peers.end();++i) i->second->save(tPtr); } @@ -189,14 +191,14 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr &pee uint64_t id[2]; id[0] = zta.toInt(); id[1] = 0; - Vector data(RR->node->stateObjectGet(tPtr,ZT_STATE_OBJECT_PEER,id)); + Vector data(RR->node->stateObjectGet(tPtr, ZT_STATE_OBJECT_PEER, id)); if (data.size() > 8) { const uint8_t *d = data.data(); - int dl = (int)data.size(); + int dl = (int) data.size(); - const int64_t ts = (int64_t)Utils::loadBigEndian(d); + const int64_t ts = (int64_t) Utils::loadBigEndian(d); Peer *const p = new Peer(RR); - int n = p->unmarshal(d + 8,dl - 8); + int n = p->unmarshal(d + 8, dl - 8); if (n < 0) { delete p; return; @@ -207,7 +209,7 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr &pee return; } } - } catch ( ... ) { + } catch (...) { peer.zero(); } } @@ -215,18 +217,18 @@ void Topology::m_loadCached(void *tPtr, const Address &zta, SharedPtr &pee void Topology::m_writeRootList(void *tPtr) { // assumes m_peers_l is locked - uint8_t *const roots = (uint8_t *)malloc(ZT_IDENTITY_MARSHAL_SIZE_MAX * m_roots.size()); + uint8_t *const roots = (uint8_t *) malloc(ZT_IDENTITY_MARSHAL_SIZE_MAX * m_roots.size()); if (roots) { // sanity check int p = 0; - for(Set::const_iterator i(m_roots.begin());i != m_roots.end();++i) { - const int pp = i->marshal(roots + p,false); + for (Set::const_iterator i(m_roots.begin());i != m_roots.end();++i) { + const int pp = i->marshal(roots + p, false); if (pp > 0) p += pp; } uint64_t id[2]; id[0] = 0; id[1] = 0; - RR->node->stateObjectPut(tPtr,ZT_STATE_OBJECT_ROOTS,id,roots,(unsigned int)p); + RR->node->stateObjectPut(tPtr, ZT_STATE_OBJECT_ROOTS, id, roots, (unsigned int) p); free(roots); } } diff --git a/node/Topology.hpp b/node/Topology.hpp index 5b20c6ac8..f8008f966 100644 --- a/node/Topology.hpp +++ b/node/Topology.hpp @@ -63,7 +63,7 @@ public: { RWMutex::RLock l(m_peers_l); const SharedPtr *const ap = m_peers.get(zta); - if (ap) + if (likely(ap != nullptr)) return *ap; } { @@ -95,7 +95,7 @@ public: { RWMutex::RLock lck(m_paths_l); SharedPtr *const p = m_paths.get(k); - if (p) + if (likely(p != nullptr)) return *p; } { @@ -115,7 +115,7 @@ public: ZT_INLINE SharedPtr root() const { RWMutex::RLock l(m_peers_l); - if (m_rootPeers.empty()) + if (unlikely(m_rootPeers.empty())) return SharedPtr(); return m_rootPeers.front(); } @@ -167,10 +167,8 @@ public: rootPeerPtrs.push_back((uintptr_t)rp->ptr()); std::sort(rootPeerPtrs.begin(),rootPeerPtrs.end()); - try { - for(Map< Address,SharedPtr >::const_iterator i(m_peers.begin());i != m_peers.end();++i) - f(i->second,std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)i->second.ptr())); - } catch ( ... ) {} // should not throw + for(Map< Address,SharedPtr >::const_iterator i(m_peers.begin());i != m_peers.end();++i) + f(i->second,std::binary_search(rootPeerPtrs.begin(),rootPeerPtrs.end(),(uintptr_t)i->second.ptr())); } /** @@ -185,56 +183,6 @@ public: allPeers.push_back(i->second); } - /** - * Get info about a path - * - * The supplied result variables are not modified if no special config info is found. - * - * @param physicalAddress Physical endpoint address - * @param mtu Variable set to MTU - * @param trustedPathId Variable set to trusted path ID - */ - ZT_INLINE void getOutboundPathInfo(const InetAddress &physicalAddress,unsigned int &mtu,uint64_t &trustedPathId) - { - for(unsigned int i=0,j=m_numConfiguredPhysicalPaths;i < j;++i) { - if (m_physicalPathConfig[i].first.containsAddress(physicalAddress)) { - trustedPathId = m_physicalPathConfig[i].second.trustedPathId; - mtu = m_physicalPathConfig[i].second.mtu; - return; - } - } - } - - /** - * Get the outbound trusted path ID for a physical address, or 0 if none - * - * @param physicalAddress Physical address to which we are sending the packet - * @return Trusted path ID or 0 if none (0 is not a valid trusted path ID) - */ - ZT_INLINE uint64_t getOutboundPathTrust(const InetAddress &physicalAddress) - { - for(unsigned int i=0,j=m_numConfiguredPhysicalPaths;i < j;++i) { - if (m_physicalPathConfig[i].first.containsAddress(physicalAddress)) - return m_physicalPathConfig[i].second.trustedPathId; - } - return 0; - } - - /** - * Check whether in incoming trusted path marked packet is valid - * - * @param physicalAddress Originating physical address - * @param trustedPathId Trusted path ID from packet (from MAC field) - */ - ZT_INLINE bool shouldInboundPathBeTrusted(const InetAddress &physicalAddress,const uint64_t trustedPathId) - { - for(unsigned int i=0,j=m_numConfiguredPhysicalPaths;i < j;++i) { - if ((m_physicalPathConfig[i].second.trustedPathId == trustedPathId) && (m_physicalPathConfig[i].first.containsAddress(physicalAddress))) - return true; - } - return false; - } - /** * Set or clear physical path configuration (called via Node::setPhysicalPathConfiguration) */ @@ -259,7 +207,7 @@ public: bool removeRoot(void *tPtr,const Identity &id); /** - * Sort roots in asecnding order of apparent latency + * Sort roots in ascending order of apparent latency * * @param now Current time */ diff --git a/node/Trace.cpp b/node/Trace.cpp index 1eb6c8baa..91fa99128 100644 --- a/node/Trace.cpp +++ b/node/Trace.cpp @@ -15,7 +15,6 @@ #include "RuntimeEnvironment.hpp" #include "Node.hpp" #include "Peer.hpp" -#include "Path.hpp" #include "InetAddress.hpp" #include "FCV.hpp" diff --git a/node/Utils.cpp b/node/Utils.cpp index d8a1f1dae..087787c30 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -11,15 +11,10 @@ */ /****/ -#include -#include -#include - #include "Utils.hpp" #include "Mutex.hpp" #include "AES.hpp" #include "SHA512.hpp" -#include "Speck128.hpp" #ifdef __UNIX_LIKE__ #include @@ -27,6 +22,8 @@ #include #endif +#include + #ifdef __WINDOWS__ #include #endif @@ -189,41 +186,31 @@ unsigned int unhex(const char *h,unsigned int hlen,void *buf,unsigned int buflen } #define ZT_GETSECURERANDOM_STATE_SIZE 64 -#define ZT_GETSECURERANDOM_BUF_SIZE 4096 +#define ZT_GETSECURERANDOM_ITERATIONS_PER_GENERATOR 1048576 -void getSecureRandom(void *const buf,const unsigned int bytes) noexcept +void getSecureRandom(void *const buf,unsigned int bytes) noexcept { static Mutex globalLock; static bool initialized = false; - static uint64_t randomState[ZT_GETSECURERANDOM_STATE_SIZE]; // secret state - static uint64_t randomBuf[ZT_GETSECURERANDOM_BUF_SIZE]; // next batch of random bytes - static unsigned long randomPtr = sizeof(randomBuf); // refresh on first iteration + static uint64_t randomState[ZT_GETSECURERANDOM_STATE_SIZE]; + static unsigned int randomByteCounter = ZT_GETSECURERANDOM_ITERATIONS_PER_GENERATOR; // init on first run + static AES randomGen; Mutex::Lock gl(globalLock); - // This could be a lot faster if we're not going to need a new block. - if ((randomPtr + (unsigned long)bytes) <= sizeof(randomBuf)) { - Utils::copy(buf,reinterpret_cast(randomBuf) + randomPtr,bytes); - randomPtr += bytes; - return; - } + // Re-initialize the generator every ITERATIONS_PER_GENERATOR bytes. + if (unlikely((randomByteCounter += bytes) >= ZT_GETSECURERANDOM_ITERATIONS_PER_GENERATOR)) { + // On first run fill randomState with random bits from the system. + if (unlikely(!initialized)) { + initialized = true; - for(unsigned int i=0;i= (unsigned long)sizeof(randomBuf)) { - randomPtr = 0; + // Don't let randomState be swapped to disk (if supported by OS). + Utils::memoryLock(randomState,sizeof(randomState)); - if (!initialized) { - initialized = true; - - Utils::memoryLock(randomState,sizeof(randomState)); - Utils::memoryLock(randomBuf,sizeof(randomBuf)); - - // Fill randomState with entropy from the system. If this doesn't work this is a hard fail. - Utils::zero(randomState); + // Fill randomState with entropy from the system. Failure equals hard exit. + Utils::zero(randomState); #ifdef __WINDOWS__ - HCRYPTPROV cryptProvider = NULL; + HCRYPTPROV cryptProvider = NULL; if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n"); exit(1); @@ -234,66 +221,63 @@ void getSecureRandom(void *const buf,const unsigned int bytes) noexcept } CryptReleaseContext(cryptProvider,0); #else - int devURandomFd = ::open("/dev/urandom",O_RDONLY); - if (devURandomFd < 0) { - fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to open /dev/urandom\n"); - exit(1); - } - if ((long)::read(devURandomFd,randomState,sizeof(randomState)) != (long)sizeof(randomState)) { - ::close(devURandomFd); - fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to read from /dev/urandom\n"); - exit(1); - } - close(devURandomFd); + int devURandomFd = ::open("/dev/urandom",O_RDONLY); + if (devURandomFd < 0) { + fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to open /dev/urandom\n"); + exit(1); + } + if ((long)::read(devURandomFd,randomState,sizeof(randomState)) != (long)sizeof(randomState)) { + ::close(devURandomFd); + fprintf(stderr,"FATAL: Utils::getSecureRandom() unable to read from /dev/urandom\n"); + exit(1); + } + close(devURandomFd); #endif - // Mix in additional entropy from time, the address of 'buf', CPU RDRAND if present, etc. - randomState[0] += (uint64_t)time(nullptr); - randomState[1] += (uint64_t)((uintptr_t)buf); + // Mix in additional entropy from time, the address of 'buf', CPU RDRAND if present, etc. + randomState[0] += (uint64_t)time(nullptr); + randomState[1] += (uint64_t)((uintptr_t)buf); #ifdef __UNIX_LIKE__ - randomState[2] += (uint64_t)getpid(); - randomState[3] += (uint64_t)getppid(); + randomState[2] += (uint64_t)getpid(); + randomState[3] += (uint64_t)getppid(); #endif #ifdef ZT_ARCH_X64 - if (CPUID.rdrand) { - uint64_t tmp = 0; - for(int k=0;k speck(randomState); - uint64_t ctr[2]; - ctr[0] = randomState[4]; - ctr[1] = randomState[5]; - for (int k = 0;k < ZT_GETSECURERANDOM_BUF_SIZE;k += 2) { - ++ctr[0]; - speck.encrypt(ctr,randomBuf + k); - } - } } - reinterpret_cast(buf)[i] = reinterpret_cast(randomBuf)[randomPtr++]; + // Initialize or re-initialize generator by hashing the full state, + // replacing the first 64 bytes with this hash, and then re-initializing + // AES with the first 32 bytes. + randomByteCounter = 0; + SHA512(randomState,randomState,sizeof(randomState)); + randomGen.init(randomState); + } + + // Generate random bytes using AES and bytes 32-48 of randomState as an in-place + // AES-CTR counter. Counter can be machine endian; we don't care about portability + // for a random generator. + uint64_t *const ctr = randomState + 4; + uint8_t *out = reinterpret_cast(buf); + while (bytes >= 16) { + ++*ctr; + randomGen.encrypt(ctr,out); + out += 16; + bytes -= 16; + } + if (bytes > 0) { + uint8_t tmp[16]; + ++*ctr; + randomGen.encrypt(ctr,tmp); + for(unsigned int i=0;i hdrRemaining) ? hdrRemaining : len; - Utils::copy(dest,src,hdrBytes); + Utils::copy(dest, src, hdrBytes); hdrRemaining -= hdrBytes; dest = reinterpret_cast(dest) + hdrBytes; src = reinterpret_cast(src) + hdrBytes; len -= hdrBytes; } - poly1305.update(src,len); - s20.crypt12(src,dest,len); + poly1305.update(src, len); + s20.crypt12(src, dest, len); } }; @@ -68,26 +69,27 @@ struct p_PolyCopyFunction { Poly1305 poly1305; unsigned int hdrRemaining; - ZT_INLINE p_PolyCopyFunction(const void *salsaKey,const void *salsaIv) : + ZT_INLINE p_PolyCopyFunction(const void *salsaKey, const void *salsaIv) : poly1305(), hdrRemaining(ZT_PROTO_PACKET_ENCRYPTED_SECTION_START) { uint8_t macKey[ZT_POLY1305_KEY_SIZE]; - Salsa20(salsaKey,salsaIv).crypt12(Utils::ZERO256,macKey,ZT_POLY1305_KEY_SIZE); + Salsa20(salsaKey, salsaIv).crypt12(Utils::ZERO256, macKey, ZT_POLY1305_KEY_SIZE); poly1305.init(macKey); } - ZT_INLINE void operator()(void *dest,const void *src,unsigned int len) noexcept + + ZT_INLINE void operator()(void *dest, const void *src, unsigned int len) noexcept { if (hdrRemaining != 0) { unsigned int hdrBytes = (len > hdrRemaining) ? hdrRemaining : len; - Utils::copy(dest,src,hdrBytes); + Utils::copy(dest, src, hdrBytes); hdrRemaining -= hdrBytes; dest = reinterpret_cast(dest) + hdrBytes; src = reinterpret_cast(src) + hdrBytes; len -= hdrBytes; } - poly1305.update(src,len); - Utils::copy(dest,src,len); + poly1305.update(src, len); + Utils::copy(dest, src, len); } }; @@ -98,13 +100,13 @@ VL1::VL1(const RuntimeEnvironment *renv) : { } -void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAddress &fromAddr,SharedPtr &data,const unsigned int len) +void VL1::onRemotePacket(void *const tPtr, const int64_t localSocket, const InetAddress &fromAddr, SharedPtr &data, const unsigned int len) { - const SharedPtr path(RR->topology->path(localSocket,fromAddr)); + const SharedPtr path(RR->topology->path(localSocket, fromAddr)); const int64_t now = RR->node->now(); - ZT_SPEW("%u bytes from %s (local socket %lld)",len,fromAddr.toString().c_str(),localSocket); - path->received(now,len); + ZT_SPEW("%u bytes from %s (local socket %lld)", len, fromAddr.toString().c_str(), localSocket); + path->received(now, len); // NOTE: likely/unlikely are used here to highlight the most common code path // for valid data packets. This may allow the compiler to generate very slightly @@ -126,13 +128,13 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd if (unlikely(len < ZT_PROTO_MIN_FRAGMENT_LENGTH)) return; - static_assert((ZT_PROTO_PACKET_ID_INDEX + sizeof(uint64_t)) < ZT_PROTO_MIN_FRAGMENT_LENGTH,"overflow"); + static_assert((ZT_PROTO_PACKET_ID_INDEX + sizeof(uint64_t)) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); const uint64_t packetId = Utils::loadAsIsEndian(data->unsafeData + ZT_PROTO_PACKET_ID_INDEX); - static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH,"overflow"); + static_assert((ZT_PROTO_PACKET_DESTINATION_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); Address destination(data->unsafeData + ZT_PROTO_PACKET_DESTINATION_INDEX); if (destination != RR->identity.address()) { - m_relay(tPtr,path,destination,data,len); + m_relay(tPtr, path, destination, data, len); return; } @@ -142,10 +144,10 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd Buf::PacketVector pktv; - static_assert(ZT_PROTO_PACKET_FRAGMENT_INDICATOR_INDEX <= ZT_PROTO_MIN_FRAGMENT_LENGTH,"overflow"); + static_assert(ZT_PROTO_PACKET_FRAGMENT_INDICATOR_INDEX <= ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); if (data->unsafeData[ZT_PROTO_PACKET_FRAGMENT_INDICATOR_INDEX] == ZT_PROTO_PACKET_FRAGMENT_INDICATOR) { // This looks like a fragment (excluding the head) of a larger packet. - static_assert(ZT_PROTO_PACKET_FRAGMENT_COUNTS < ZT_PROTO_MIN_FRAGMENT_LENGTH,"overflow"); + static_assert(ZT_PROTO_PACKET_FRAGMENT_COUNTS < ZT_PROTO_MIN_FRAGMENT_LENGTH, "overflow"); const unsigned int totalFragments = (data->unsafeData[ZT_PROTO_PACKET_FRAGMENT_COUNTS] >> 4U) & 0x0fU; const unsigned int fragmentNo = data->unsafeData[ZT_PROTO_PACKET_FRAGMENT_COUNTS] & 0x0fU; switch (m_inputPacketAssembler.assemble( @@ -171,7 +173,7 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd } else { if (unlikely(len < ZT_PROTO_MIN_PACKET_LENGTH)) return; - static_assert(ZT_PROTO_PACKET_FLAGS_INDEX < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert(ZT_PROTO_PACKET_FLAGS_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); if ((data->unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] & ZT_PROTO_FLAG_FRAGMENTED) != 0) { // This is the head of a series of fragments that we may or may not already have. switch (m_inputPacketAssembler.assemble( @@ -208,26 +210,26 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd // ---------------------------------------------------------------------------------------------------------------- const uint8_t *const hdr = pktv[0].b->unsafeData + pktv[0].s; - static_assert((ZT_PROTO_PACKET_SOURCE_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert((ZT_PROTO_PACKET_SOURCE_INDEX + ZT_ADDRESS_LENGTH) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); const Address source(hdr + ZT_PROTO_PACKET_SOURCE_INDEX); - static_assert(ZT_PROTO_PACKET_FLAGS_INDEX < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert(ZT_PROTO_PACKET_FLAGS_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); const uint8_t hops = hdr[ZT_PROTO_PACKET_FLAGS_INDEX] & ZT_PROTO_FLAG_FIELD_HOPS_MASK; const uint8_t cipher = (hdr[ZT_PROTO_PACKET_FLAGS_INDEX] >> 3U) & 3U; SharedPtr pkt(new Buf()); int pktSize = 0; - static_assert(ZT_PROTO_PACKET_VERB_INDEX < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); - if (unlikely( ((cipher == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE)||(cipher == ZT_PROTO_CIPHER_SUITE__NONE)) && ((hdr[ZT_PROTO_PACKET_VERB_INDEX] & ZT_PROTO_VERB_MASK) == Protocol::VERB_HELLO) )) { + static_assert(ZT_PROTO_PACKET_VERB_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); + if (unlikely(((cipher == ZT_PROTO_CIPHER_SUITE__POLY1305_NONE) || (cipher == ZT_PROTO_CIPHER_SUITE__NONE)) && ((hdr[ZT_PROTO_PACKET_VERB_INDEX] & ZT_PROTO_VERB_MASK) == Protocol::VERB_HELLO))) { // Handle unencrypted HELLO packets. pktSize = pktv.mergeCopy(*pkt); if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) { - ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d",packetId,source.toString().c_str(),fromAddr.toString().c_str(),pktSize); + ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); return; } const SharedPtr peer(m_HELLO(tPtr, path, *pkt, pktSize)); - if (peer) - peer->received(tPtr,path,hops,packetId,pktSize - ZT_PROTO_PACKET_PAYLOAD_START,Protocol::VERB_HELLO,Protocol::VERB_NOP); + if (likely(peer)) + peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, Protocol::VERB_HELLO, Protocol::VERB_NOP); return; } @@ -236,55 +238,55 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd // secrecy status. unsigned int auth = 0; - SharedPtr peer(RR->topology->peer(tPtr,source)); - if (peer) { - switch(cipher) { + SharedPtr peer(RR->topology->peer(tPtr, source)); + if (likely(peer)) { + switch (cipher) { case ZT_PROTO_CIPHER_SUITE__POLY1305_NONE: { uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE]; - Protocol::salsa2012DeriveKey(peer->rawIdentityKey(),perPacketKey,*pktv[0].b,pktv.totalSize()); - p_PolyCopyFunction s20cf(perPacketKey,&packetId); + Protocol::salsa2012DeriveKey(peer->rawIdentityKey(), perPacketKey, *pktv[0].b, pktv.totalSize()); + p_PolyCopyFunction s20cf(perPacketKey, &packetId); - pktSize = pktv.mergeMap(*pkt,ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,s20cf); + pktSize = pktv.mergeMap(*pkt, ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, s20cf); if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) { - ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d",packetId,source.toString().c_str(),fromAddr.toString().c_str(),pktSize); + ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); return; } uint64_t mac[2]; s20cf.poly1305.finish(mac); - static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); if (unlikely(Utils::loadAsIsEndian(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { - ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)",packetId,source.toString().c_str(),fromAddr.toString().c_str()); - RR->t->incomingPacketDropped(tPtr,0xcc89c812,packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (none/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); + RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return; } auth = ZT_VL1_AUTH_RESULT_FLAG_AUTHENTICATED; - } break; + } break; case ZT_PROTO_CIPHER_SUITE__POLY1305_SALSA2012: { uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE]; - Protocol::salsa2012DeriveKey(peer->rawIdentityKey(),perPacketKey,*pktv[0].b,pktv.totalSize()); - p_SalsaPolyCopyFunction s20cf(perPacketKey,&packetId); + Protocol::salsa2012DeriveKey(peer->rawIdentityKey(), perPacketKey, *pktv[0].b, pktv.totalSize()); + p_SalsaPolyCopyFunction s20cf(perPacketKey, &packetId); - pktSize = pktv.mergeMap(*pkt,ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,s20cf); + pktSize = pktv.mergeMap(*pkt, ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, s20cf); if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) { - ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d",packetId,source.toString().c_str(),fromAddr.toString().c_str(),pktSize); + ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size: %d", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); return; } uint64_t mac[2]; s20cf.poly1305.finish(mac); - static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert((ZT_PROTO_PACKET_MAC_INDEX + 8) < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); if (unlikely(Utils::loadAsIsEndian(hdr + ZT_PROTO_PACKET_MAC_INDEX) != mac[0])) { - ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)",packetId,source.toString().c_str(),fromAddr.toString().c_str()); - RR->t->incomingPacketDropped(tPtr,0xcc89c812,packetId,0,peer->identity(),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + ZT_SPEW("discarding packet %.16llx from %s(%s): packet MAC failed (salsa/poly1305)", packetId, source.toString().c_str(), fromAddr.toString().c_str()); + RR->t->incomingPacketDropped(tPtr, 0xcc89c812, packetId, 0, peer->identity(), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return; } auth = ZT_VL1_AUTH_RESULT_FLAG_AUTHENTICATED | ZT_VL1_AUTH_RESULT_FLAG_ENCRYPTED; - } break; + } break; case ZT_PROTO_CIPHER_SUITE__NONE: { // TODO @@ -292,10 +294,10 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd case ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV: { // TODO - } break; + } break; default: - RR->t->incomingPacketDropped(tPtr,0x5b001099,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(tPtr, 0x5b001099, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return; } } @@ -304,99 +306,136 @@ void VL1::onRemotePacket(void *const tPtr,const int64_t localSocket,const InetAd // If authentication was successful go on and process the packet. if (unlikely(pktSize < ZT_PROTO_MIN_PACKET_LENGTH)) { - ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size %d is smaller than minimum packet length",packetId,source.toString().c_str(),fromAddr.toString().c_str(),pktSize); + ZT_SPEW("discarding packet %.16llx from %s(%s): assembled packet size %d is smaller than minimum packet length", packetId, source.toString().c_str(), fromAddr.toString().c_str(), pktSize); return; } // TODO: should take instance ID into account here once that is fully implemented. if (unlikely(peer->deduplicateIncomingPacket(packetId))) { - ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!",packetId,source.toString().c_str(),fromAddr.toString().c_str()); + ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!", packetId, source.toString().c_str(), fromAddr.toString().c_str()); return; } - static_assert(ZT_PROTO_PACKET_VERB_INDEX < ZT_PROTO_MIN_PACKET_LENGTH,"overflow"); + static_assert(ZT_PROTO_PACKET_VERB_INDEX < ZT_PROTO_MIN_PACKET_LENGTH, "overflow"); const uint8_t verbFlags = pkt->unsafeData[ZT_PROTO_PACKET_VERB_INDEX]; - const Protocol::Verb verb = (Protocol::Verb)(verbFlags & ZT_PROTO_VERB_MASK); + const Protocol::Verb verb = (Protocol::Verb) (verbFlags & ZT_PROTO_VERB_MASK); // Decompress packet payload if compressed. For additional safety decompression is // only performed on packets whose MACs have already been validated. (Only HELLO is // sent without this, and HELLO doesn't benefit from compression.) - if (((verbFlags & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0)&&(pktSize > ZT_PROTO_PACKET_PAYLOAD_START)) { + if (((verbFlags & ZT_PROTO_VERB_FLAG_COMPRESSED) != 0) && (pktSize > ZT_PROTO_PACKET_PAYLOAD_START)) { SharedPtr dec(new Buf()); - Utils::copy(dec->unsafeData,pkt->unsafeData); + Utils::copy(dec->unsafeData, pkt->unsafeData); const int uncompressedLen = LZ4_decompress_safe( reinterpret_cast(pkt->unsafeData + ZT_PROTO_PACKET_PAYLOAD_START), reinterpret_cast(dec->unsafeData + ZT_PROTO_PACKET_PAYLOAD_START), pktSize - ZT_PROTO_PACKET_PAYLOAD_START, ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START); - if (likely((uncompressedLen >= 0)&&(uncompressedLen <= (ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START)))) { + if (likely((uncompressedLen >= 0) && (uncompressedLen <= (ZT_BUF_MEM_SIZE - ZT_PROTO_PACKET_PAYLOAD_START)))) { pkt.swap(dec); - ZT_SPEW("decompressed packet: %d -> %d",pktSize,ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen); + ZT_SPEW("decompressed packet: %d -> %d", pktSize, ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen); pktSize = ZT_PROTO_PACKET_PAYLOAD_START + uncompressedLen; } else { - RR->t->incomingPacketDropped(tPtr,0xee9e4392,packetId,0,identityFromPeerPtr(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA); + RR->t->incomingPacketDropped(tPtr, 0xee9e4392, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_INVALID_COMPRESSED_DATA); return; } } - ZT_SPEW("%s from %s(%s) (%d bytes)",Protocol::verbName(verb),source.toString().c_str(),fromAddr.toString().c_str(),pktSize); + ZT_SPEW("%s from %s(%s) (%d bytes)", Protocol::verbName(verb), source.toString().c_str(), fromAddr.toString().c_str(), pktSize); // NOTE: HELLO is normally sent in the clear (in terms of our usual AEAD modes) and is handled // above. We will try to process it here, but if so it'll still get re-authenticated via HELLO's // own internal authentication logic as usual. It would be abnormal to make it here with HELLO // but not invalid. - bool ok = true; Protocol::Verb inReVerb = Protocol::VERB_NOP; - switch(verb) { - case Protocol::VERB_NOP: break; - case Protocol::VERB_HELLO: ok = (bool)(m_HELLO(tPtr, path, *pkt, pktSize)); break; - case Protocol::VERB_ERROR: ok = m_ERROR(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); break; - case Protocol::VERB_OK: ok = m_OK(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); break; - case Protocol::VERB_WHOIS: ok = m_WHOIS(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_RENDEZVOUS: ok = m_RENDEZVOUS(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_FRAME: ok = RR->vl2->m_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_EXT_FRAME: ok = RR->vl2->m_EXT_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_ECHO: ok = m_ECHO(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_MULTICAST_LIKE: ok = RR->vl2->m_MULTICAST_LIKE(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_NETWORK_CREDENTIALS: ok = RR->vl2->m_NETWORK_CREDENTIALS(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_NETWORK_CONFIG_REQUEST: ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_NETWORK_CONFIG: ok = RR->vl2->m_NETWORK_CONFIG(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_MULTICAST_GATHER: ok = RR->vl2->m_MULTICAST_GATHER(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_MULTICAST_FRAME_deprecated: ok = RR->vl2->m_MULTICAST_FRAME_deprecated(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_PUSH_DIRECT_PATHS: ok = m_PUSH_DIRECT_PATHS(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_USER_MESSAGE: ok = m_USER_MESSAGE(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_MULTICAST: ok = RR->vl2->m_MULTICAST(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; - case Protocol::VERB_ENCAP: ok = m_ENCAP(tPtr, packetId, auth, path, peer, *pkt, pktSize); break; + bool ok = true; + switch (verb) { + case Protocol::VERB_NOP: + break; + case Protocol::VERB_HELLO: + ok = (bool) (m_HELLO(tPtr, path, *pkt, pktSize)); + break; + case Protocol::VERB_ERROR: + ok = m_ERROR(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); + break; + case Protocol::VERB_OK: + ok = m_OK(tPtr, packetId, auth, path, peer, *pkt, pktSize, inReVerb); + break; + case Protocol::VERB_WHOIS: + ok = m_WHOIS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_RENDEZVOUS: + ok = m_RENDEZVOUS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_FRAME: + ok = RR->vl2->m_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_EXT_FRAME: + ok = RR->vl2->m_EXT_FRAME(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_ECHO: + ok = m_ECHO(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_MULTICAST_LIKE: + ok = RR->vl2->m_MULTICAST_LIKE(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_NETWORK_CREDENTIALS: + ok = RR->vl2->m_NETWORK_CREDENTIALS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_NETWORK_CONFIG_REQUEST: + ok = RR->vl2->m_NETWORK_CONFIG_REQUEST(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_NETWORK_CONFIG: + ok = RR->vl2->m_NETWORK_CONFIG(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_MULTICAST_GATHER: + ok = RR->vl2->m_MULTICAST_GATHER(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_MULTICAST_FRAME_deprecated: + ok = RR->vl2->m_MULTICAST_FRAME_deprecated(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_PUSH_DIRECT_PATHS: + ok = m_PUSH_DIRECT_PATHS(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_USER_MESSAGE: + ok = m_USER_MESSAGE(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_MULTICAST: + ok = RR->vl2->m_MULTICAST(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; + case Protocol::VERB_ENCAP: + ok = m_ENCAP(tPtr, packetId, auth, path, peer, *pkt, pktSize); + break; default: - RR->t->incomingPacketDropped(tPtr,0xeeeeeff0,packetId,0,identityFromPeerPtr(peer),path->address(),hops,verb,ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); + RR->t->incomingPacketDropped(tPtr, 0xeeeeeff0, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, verb, ZT_TRACE_PACKET_DROP_REASON_UNRECOGNIZED_VERB); break; } if (likely(ok)) - peer->received(tPtr,path,hops,packetId,pktSize - ZT_PROTO_PACKET_PAYLOAD_START,verb,inReVerb); + peer->received(tPtr, path, hops, packetId, pktSize - ZT_PROTO_PACKET_PAYLOAD_START, verb, inReVerb); } else { // If decryption and authentication were not successful, try to look up identities. // This is rate limited by virtue of the retry rate limit timer. if (pktSize <= 0) pktSize = pktv.mergeCopy(*pkt); if (pktSize >= ZT_PROTO_MIN_PACKET_LENGTH) { - ZT_SPEW("authentication failed or no peers match, queueing WHOIS for %s",source.toString().c_str()); + ZT_SPEW("authentication failed or no peers match, queueing WHOIS for %s", source.toString().c_str()); bool sendPending; { Mutex::Lock wl(m_whoisQueue_l); p_WhoisQueueItem &wq = m_whoisQueue[source]; const unsigned int wpidx = wq.waitingPacketCount++ % ZT_VL1_MAX_WHOIS_WAITING_PACKETS; - wq.waitingPacketSize[wpidx] = (unsigned int)pktSize; + wq.waitingPacketSize[wpidx] = (unsigned int) pktSize; wq.waitingPacket[wpidx] = pkt; sendPending = (now - wq.lastRetry) >= ZT_WHOIS_RETRY_DELAY; } if (sendPending) - m_sendPendingWhois(tPtr,now); + m_sendPendingWhois(tPtr, now); } } - } catch ( ... ) { - RR->t->unexpectedError(tPtr,0xea1b6dea,"unexpected exception in onRemotePacket() parsing packet from %s",path->address().toString().c_str()); + } catch (...) { + RR->t->unexpectedError(tPtr, 0xea1b6dea, "unexpected exception in onRemotePacket() parsing packet from %s", path->address().toString().c_str()); } } @@ -413,10 +452,10 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now) if (unlikely(!rootPath)) return; - std::vector
toSend; + Vector
toSend; { Mutex::Lock wl(m_whoisQueue_l); - for(Map::iterator wi(m_whoisQueue.begin());wi!=m_whoisQueue.end();++wi) { + for (Map::iterator wi(m_whoisQueue.begin());wi != m_whoisQueue.end();++wi) { if ((now - wi->second.lastRetry) >= ZT_WHOIS_RETRY_DELAY) { wi->second.lastRetry = now; ++wi->second.retries; @@ -430,18 +469,18 @@ void VL1::m_sendPendingWhois(void *tPtr, int64_t now) const SharedPtr key(root->key()); uint8_t outp[ZT_DEFAULT_UDP_MTU - ZT_PROTO_MIN_PACKET_LENGTH]; - std::vector
::iterator a(toSend.begin()); + Vector
::iterator a(toSend.begin()); while (a != toSend.end()) { - const uint64_t packetId = key->nextMessage(RR->identity.address(),root->address()); - int p = Protocol::newPacket(outp,packetId,root->address(),RR->identity.address(),Protocol::VERB_WHOIS); - while ((a != toSend.end())&&(p < (sizeof(outp) - ZT_ADDRESS_LENGTH))) { + const uint64_t packetId = key->nextMessage(RR->identity.address(), root->address()); + int p = Protocol::newPacket(outp, packetId, root->address(), RR->identity.address(), Protocol::VERB_WHOIS); + while ((a != toSend.end()) && (p < (sizeof(outp) - ZT_ADDRESS_LENGTH))) { a->copyTo(outp + p); ++a; p += ZT_ADDRESS_LENGTH; } - Protocol::armor(outp,p,key,root->cipher()); - RR->expect->sending(packetId,now); - root->send(tPtr,now,outp,p,rootPath); + Protocol::armor(outp, p, key, root->cipher()); + RR->expect->sending(packetId, now); + root->send(tPtr, now, outp, p, rootPath); } } @@ -453,7 +492,7 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, const uint8_t protoVersion = pkt.lI8(); if (unlikely(protoVersion < ZT_PROTO_VERSION_MIN)) { - RR->t->incomingPacketDropped(tPtr,0x907a9891,packetId,0,Identity::NIL,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); + RR->t->incomingPacketDropped(tPtr, 0x907a9891, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD); return SharedPtr(); } const unsigned int versionMajor = pkt.lI8(); @@ -465,37 +504,37 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, // Get identity and verify that it matches the sending address in the packet. Identity id; - if (unlikely(pkt.rO(ii,id) < 0)) { - RR->t->incomingPacketDropped(tPtr,0x707a9810,packetId,0,Identity::NIL,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + if (unlikely(pkt.rO(ii, id) < 0)) { + RR->t->incomingPacketDropped(tPtr, 0x707a9810, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr(); } if (unlikely(id.address() != Address(pkt.unsafeData + ZT_PROTO_PACKET_SOURCE_INDEX))) { - RR->t->incomingPacketDropped(tPtr,0x707a9010,packetId,0,Identity::NIL,path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(tPtr, 0x707a9010, packetId, 0, Identity::NIL, path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } // Get the peer that matches this identity, or learn a new one if we don't know it. - SharedPtr peer(RR->topology->peer(tPtr,id.address(),true)); + SharedPtr peer(RR->topology->peer(tPtr, id.address(), true)); if (peer) { - if (peer->identity() != id) { - RR->t->incomingPacketDropped(tPtr,0x707a9891,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + if (unlikely(peer->identity() != id)) { + RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } - if (peer->deduplicateIncomingPacket(packetId)) { - ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!",packetId,id.address().toString().c_str(),path->address().toString().c_str()); + if (unlikely(peer->deduplicateIncomingPacket(packetId))) { + ZT_SPEW("discarding packet %.16llx from %s(%s): duplicate!", packetId, id.address().toString().c_str(), path->address().toString().c_str()); return SharedPtr(); } } else { if (unlikely(!id.locallyValidate())) { - RR->t->incomingPacketDropped(tPtr,0x707a9892,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(tPtr, 0x707a9892, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr(); } peer.set(new Peer(RR)); if (unlikely(!peer->init(id))) { - RR->t->incomingPacketDropped(tPtr,0x707a9893,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED); + RR->t->incomingPacketDropped(tPtr, 0x707a9893, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED); return SharedPtr(); } - peer = RR->topology->add(tPtr,peer); + peer = RR->topology->add(tPtr, peer); } // ------------------------------------------------------------------------------------------------------------------ @@ -508,34 +547,34 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, // field is ignored, and eventually it'll be undefined. uint8_t hmac[ZT_HMACSHA384_LEN]; if (unlikely(packetSize < ZT_HMACSHA384_LEN)) { - RR->t->incomingPacketDropped(tPtr,0xab9c9891,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(tPtr, 0xab9c9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } packetSize -= ZT_HMACSHA384_LEN; pkt.unsafeData[ZT_PROTO_PACKET_FLAGS_INDEX] &= ~ZT_PROTO_FLAG_FIELD_HOPS_MASK; // mask hops to 0 - Utils::storeAsIsEndian(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX,0); // set MAC field to 0 - HMACSHA384(peer->identityHelloHmacKey(),pkt.unsafeData,packetSize,hmac); - if (unlikely(!Utils::secureEq(hmac,pkt.unsafeData + packetSize,ZT_HMACSHA384_LEN))) { - RR->t->incomingPacketDropped(tPtr,0x707a9891,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + Utils::storeAsIsEndian(pkt.unsafeData + ZT_PROTO_PACKET_MAC_INDEX, 0); // set MAC field to 0 + HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, packetSize, hmac); + if (unlikely(!Utils::secureEq(hmac, pkt.unsafeData + packetSize, ZT_HMACSHA384_LEN))) { + RR->t->incomingPacketDropped(tPtr, 0x707a9891, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } } else { // Older versions use Poly1305 MAC (but no whole packet encryption) for HELLO. if (likely(packetSize > ZT_PROTO_PACKET_ENCRYPTED_SECTION_START)) { uint8_t perPacketKey[ZT_SALSA20_KEY_SIZE]; - Protocol::salsa2012DeriveKey(peer->rawIdentityKey(),perPacketKey,pkt,packetSize); + Protocol::salsa2012DeriveKey(peer->rawIdentityKey(), perPacketKey, pkt, packetSize); uint8_t macKey[ZT_POLY1305_KEY_SIZE]; - Salsa20(perPacketKey,&packetId).crypt12(Utils::ZERO256,macKey,ZT_POLY1305_KEY_SIZE); + Salsa20(perPacketKey, &packetId).crypt12(Utils::ZERO256, macKey, ZT_POLY1305_KEY_SIZE); Poly1305 poly1305(macKey); - poly1305.update(pkt.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START,packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START); + poly1305.update(pkt.unsafeData + ZT_PROTO_PACKET_ENCRYPTED_SECTION_START, packetSize - ZT_PROTO_PACKET_ENCRYPTED_SECTION_START); uint64_t polyMac[2]; poly1305.finish(polyMac); if (unlikely(mac != polyMac[0])) { - RR->t->incomingPacketDropped(tPtr,0x11bfff82,packetId,0,id,path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(tPtr, 0x11bfff82, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } } else { - RR->t->incomingPacketDropped(tPtr,0x11bfff81,packetId,0,id,path->address(),hops,Protocol::VERB_NOP,ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); + RR->t->incomingPacketDropped(tPtr, 0x11bfff81, packetId, 0, id, path->address(), hops, Protocol::VERB_NOP, ZT_TRACE_PACKET_DROP_REASON_MAC_FAILED); return SharedPtr(); } } @@ -545,8 +584,8 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, // ------------------------------------------------------------------------------------------------------------------ InetAddress sentTo; - if (unlikely(pkt.rO(ii,sentTo) < 0)) { - RR->t->incomingPacketDropped(tPtr,0x707a9811,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + if (unlikely(pkt.rO(ii, sentTo) < 0)) { + RR->t->incomingPacketDropped(tPtr, 0x707a9811, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return SharedPtr(); } @@ -559,19 +598,19 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, AES::CTR ctr(peer->identityHelloDictionaryEncryptionCipher()); const uint8_t *const ctrNonce = pkt.unsafeData + ii; ii += 12; - ctr.init(ctrNonce,0,pkt.unsafeData + ii); - ctr.crypt(pkt.unsafeData + ii,packetSize - ii); + ctr.init(ctrNonce, 0, pkt.unsafeData + ii); + ctr.crypt(pkt.unsafeData + ii, packetSize - ii); ctr.finish(); ii += 2; // skip reserved field const unsigned int dictSize = pkt.rI16(ii); if (unlikely((ii + dictSize) > packetSize)) { - RR->t->incomingPacketDropped(tPtr,0x707a9815,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + RR->t->incomingPacketDropped(tPtr, 0x707a9815, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return peer; } Dictionary md; - if (!md.decode(pkt.unsafeData + ii,dictSize)) { - RR->t->incomingPacketDropped(tPtr,0x707a9816,packetId,0,identityFromPeerPtr(peer),path->address(),hops,Protocol::VERB_HELLO,ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); + if (!md.decode(pkt.unsafeData + ii, dictSize)) { + RR->t->incomingPacketDropped(tPtr, 0x707a9816, packetId, 0, identityFromPeerPtr(peer), path->address(), hops, Protocol::VERB_HELLO, ZT_TRACE_PACKET_DROP_REASON_INVALID_OBJECT); return peer; } @@ -581,36 +620,36 @@ SharedPtr VL1::m_HELLO(void *tPtr, const SharedPtr &path, Buf &pkt, } } - Protocol::newPacket(pkt,key->nextMessage(RR->identity.address(),peer->address()),peer->address(),RR->identity.address(),Protocol::VERB_OK); + Protocol::newPacket(pkt, key->nextMessage(RR->identity.address(), peer->address()), peer->address(), RR->identity.address(), Protocol::VERB_OK); ii = ZT_PROTO_PACKET_PAYLOAD_START; - pkt.wI8(ii,Protocol::VERB_HELLO); - pkt.wI64(ii,packetId); - pkt.wI64(ii,timestamp); - pkt.wI8(ii,ZT_PROTO_VERSION); - pkt.wI8(ii,ZEROTIER_VERSION_MAJOR); - pkt.wI8(ii,ZEROTIER_VERSION_MINOR); - pkt.wI16(ii,ZEROTIER_VERSION_REVISION); - pkt.wO(ii,path->address()); - pkt.wI16(ii,0); // reserved, specifies no "moons" for older versions + pkt.wI8(ii, Protocol::VERB_HELLO); + pkt.wI64(ii, packetId); + pkt.wI64(ii, timestamp); + pkt.wI8(ii, ZT_PROTO_VERSION); + pkt.wI8(ii, ZEROTIER_VERSION_MAJOR); + pkt.wI8(ii, ZEROTIER_VERSION_MINOR); + pkt.wI16(ii, ZEROTIER_VERSION_REVISION); + pkt.wO(ii, path->address()); + pkt.wI16(ii, 0); // reserved, specifies no "moons" for older versions if (protoVersion >= 11) { - FCV okmd; - pkt.wI16(ii,(uint16_t)okmd.size()); - pkt.wB(ii,okmd.data(),okmd.size()); + FCV okmd; + pkt.wI16(ii, (uint16_t) okmd.size()); + pkt.wB(ii, okmd.data(), okmd.size()); if (unlikely((ii + ZT_HMACSHA384_LEN) > ZT_BUF_MEM_SIZE)) // sanity check, should be impossible return SharedPtr(); - HMACSHA384(peer->identityHelloHmacKey(),pkt.unsafeData,ii,pkt.unsafeData + ii); + HMACSHA384(peer->identityHelloHmacKey(), pkt.unsafeData, ii, pkt.unsafeData + ii); ii += ZT_HMACSHA384_LEN; } - peer->setRemoteVersion(protoVersion,versionMajor,versionMinor,versionRev); - peer->send(tPtr,RR->node->now(),pkt.unsafeData,ii,path); + peer->setRemoteVersion(protoVersion, versionMajor, versionMinor, versionRev); + peer->send(tPtr, RR->node->now(), pkt.unsafeData, ii, path); return peer; } -bool VL1::m_ERROR(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) +bool VL1::m_ERROR(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { #if 0 if (packetSize < (int)sizeof(Protocol::ERROR::Header)) { @@ -657,26 +696,26 @@ bool VL1::m_ERROR(void *tPtr,const uint64_t packetId,const unsigned int auth, co #endif } -bool VL1::m_OK(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) +bool VL1::m_OK(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize, Protocol::Verb &inReVerb) { int ii = ZT_PROTO_PACKET_PAYLOAD_START + 13; - inReVerb = (Protocol::Verb)pkt.rI8(ii); + inReVerb = (Protocol::Verb) pkt.rI8(ii); const uint64_t inRePacketId = pkt.rI64(ii); - if (unlikely(Buf::readOverflow(ii,packetSize))) { - RR->t->incomingPacketDropped(tPtr,0x4c1f1ff7,packetId,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_OK,ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); + if (unlikely(Buf::readOverflow(ii, packetSize))) { + RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff7, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_MALFORMED_PACKET); return false; } const int64_t now = RR->node->now(); - if (!RR->expect->expecting(inRePacketId,now)) { - RR->t->incomingPacketDropped(tPtr,0x4c1f1ff8,packetId,0,identityFromPeerPtr(peer),path->address(),0,Protocol::VERB_OK,ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED); + if (!RR->expect->expecting(inRePacketId, now)) { + RR->t->incomingPacketDropped(tPtr, 0x4c1f1ff8, packetId, 0, identityFromPeerPtr(peer), path->address(), 0, Protocol::VERB_OK, ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED); return false; } - ZT_SPEW("got OK in-re %s (packet ID %.16llx) from %s(%s)",Protocol::verbName(inReVerb),inRePacketId,peer->address().toString().c_str(),path->address().toString().c_str()); + ZT_SPEW("got OK in-re %s (packet ID %.16llx) from %s(%s)", Protocol::verbName(inReVerb), inRePacketId, peer->address().toString().c_str(), path->address().toString().c_str()); - switch(inReVerb) { + switch (inReVerb) { case Protocol::VERB_HELLO: break; @@ -695,7 +734,7 @@ bool VL1::m_OK(void *tPtr,const uint64_t packetId,const unsigned int auth, const return true; } -bool VL1::m_WHOIS(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_WHOIS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { #if 0 if (packetSize < (int)sizeof(Protocol::OK::Header)) { @@ -749,7 +788,7 @@ bool VL1::m_WHOIS(void *tPtr,const uint64_t packetId,const unsigned int auth, co #endif } -bool VL1::m_RENDEZVOUS(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_RENDEZVOUS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { #if 0 if (RR->topology->isRoot(peer->identity())) { @@ -797,7 +836,7 @@ bool VL1::m_RENDEZVOUS(void *tPtr,const uint64_t packetId,const unsigned int aut #endif } -bool VL1::m_ECHO(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_ECHO(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { #if 0 const uint64_t packetId = Protocol::packetId(pkt,packetSize); @@ -835,7 +874,7 @@ bool VL1::m_ECHO(void *tPtr,const uint64_t packetId,const unsigned int auth, con #endif } -bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { #if 0 if (packetSize < (int)sizeof(Protocol::PUSH_DIRECT_PATHS)) { @@ -926,13 +965,13 @@ bool VL1::m_PUSH_DIRECT_PATHS(void *tPtr,const uint64_t packetId,const unsigned #endif } -bool VL1::m_USER_MESSAGE(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_USER_MESSAGE(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { // TODO return true; } -bool VL1::m_ENCAP(void *tPtr,const uint64_t packetId,const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) +bool VL1::m_ENCAP(void *tPtr, const uint64_t packetId, const unsigned int auth, const SharedPtr &path, const SharedPtr &peer, Buf &pkt, int packetSize) { // TODO: not implemented yet return true; diff --git a/node/VL2.cpp b/node/VL2.cpp index 72c69cfa9..ef2fa38b0 100644 --- a/node/VL2.cpp +++ b/node/VL2.cpp @@ -27,7 +27,7 @@ VL2::VL2(const RuntimeEnvironment *renv) { } -void VL2::onLocalEthernet(void *const tPtr,const uint64_t packetId,const unsigned int auth,const SharedPtr &network,const MAC &from,const MAC &to,const unsigned int etherType,unsigned int vlanId,SharedPtr &data,unsigned int len) +void VL2::onLocalEthernet(void *const tPtr,const SharedPtr &network,const MAC &from,const MAC &to,const unsigned int etherType,unsigned int vlanId,SharedPtr &data,unsigned int len) { }