mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-21 12:06:11 +00:00
Implement extended armor throughout system but not turned on yet.
This commit is contained in:
parent
3de5cbd105
commit
6b078ee935
@ -854,7 +854,7 @@ void Bond::sendPATH_NEGOTIATION_REQUEST(void* tPtr, int pathIdx)
|
|||||||
outp.append<int16_t>(_localUtility);
|
outp.append<int16_t>(_localUtility);
|
||||||
if (_paths[pathIdx].p->address()) {
|
if (_paths[pathIdx].p->address()) {
|
||||||
Metrics::pkt_path_negotiation_request_out++;
|
Metrics::pkt_path_negotiation_request_out++;
|
||||||
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
outp.armor(_peer->key(), true, false, _peer->aesKeysIfSupported(), _peer->identity());
|
||||||
RR->node->putPacket(tPtr, _paths[pathIdx].p->localSocket(), _paths[pathIdx].p->address(), outp.data(), outp.size());
|
RR->node->putPacket(tPtr, _paths[pathIdx].p->localSocket(), _paths[pathIdx].p->address(), outp.data(), outp.size());
|
||||||
_overheadBytes += outp.size();
|
_overheadBytes += outp.size();
|
||||||
}
|
}
|
||||||
@ -895,7 +895,7 @@ void Bond::sendQOS_MEASUREMENT(void* tPtr, int pathIdx, int64_t localSocket, con
|
|||||||
// debug("sending QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
// debug("sending QOS via link %s (len=%d)", pathToStr(_paths[pathIdx].p).c_str(), len);
|
||||||
outp.append(qosData, len);
|
outp.append(qosData, len);
|
||||||
if (atAddress) {
|
if (atAddress) {
|
||||||
outp.armor(_peer->key(), false, _peer->aesKeysIfSupported());
|
outp.armor(_peer->key(), true, false, _peer->aesKeysIfSupported(), _peer->identity());
|
||||||
RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size());
|
RR->node->putPacket(tPtr, localSocket, atAddress, outp.data(), outp.size());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -933,7 +933,7 @@ void Bond::processBackgroundBondTasks(void* tPtr, int64_t now)
|
|||||||
if ((_monitorInterval > 0) && (((now - _paths[i].p->_lastIn) >= (_paths[i].alive ? _monitorInterval : _failoverInterval)))) {
|
if ((_monitorInterval > 0) && (((now - _paths[i].p->_lastIn) >= (_paths[i].alive ? _monitorInterval : _failoverInterval)))) {
|
||||||
if ((_peer->remoteVersionProtocol() >= 5) && (! ((_peer->remoteVersionMajor() == 1) && (_peer->remoteVersionMinor() == 1) && (_peer->remoteVersionRevision() == 0)))) {
|
if ((_peer->remoteVersionProtocol() >= 5) && (! ((_peer->remoteVersionMajor() == 1) && (_peer->remoteVersionMinor() == 1) && (_peer->remoteVersionRevision() == 0)))) {
|
||||||
Packet outp(_peer->address(), RR->identity.address(), Packet::VERB_ECHO); // ECHO (this is our bond's heartbeat)
|
Packet outp(_peer->address(), RR->identity.address(), Packet::VERB_ECHO); // ECHO (this is our bond's heartbeat)
|
||||||
outp.armor(_peer->key(), true, _peer->aesKeysIfSupported());
|
outp.armor(_peer->key(), true, false, _peer->aesKeysIfSupported(), _peer->identity());
|
||||||
RR->node->expectReplyTo(outp.packetId());
|
RR->node->expectReplyTo(outp.packetId());
|
||||||
RR->node->putPacket(tPtr, _paths[i].p->localSocket(), _paths[i].p->address(), outp.data(), outp.size());
|
RR->node->putPacket(tPtr, _paths[i].p->localSocket(), _paths[i].p->address(), outp.data(), outp.size());
|
||||||
_paths[i].p->_lastOut = now;
|
_paths[i].p->_lastOut = now;
|
||||||
|
@ -14,17 +14,6 @@
|
|||||||
#ifndef ZT_CREDENTIAL_HPP
|
#ifndef ZT_CREDENTIAL_HPP
|
||||||
#define ZT_CREDENTIAL_HPP
|
#define ZT_CREDENTIAL_HPP
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "Constants.hpp"
|
|
||||||
|
|
||||||
namespace ZeroTier {
|
namespace ZeroTier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
|
|||||||
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
|
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
|
||||||
if (peer) {
|
if (peer) {
|
||||||
if (!_authenticated) {
|
if (!_authenticated) {
|
||||||
if (!dearmor(peer->key(), peer->aesKeys())) {
|
if (!dearmor(peer->key(), peer->aesKeys(), RR->identity)) {
|
||||||
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
|
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
|
||||||
peer->recordIncomingInvalidPacket(_path);
|
peer->recordIncomingInvalidPacket(_path);
|
||||||
return true;
|
return true;
|
||||||
@ -398,13 +398,13 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
|||||||
|
|
||||||
uint8_t key[ZT_SYMMETRIC_KEY_SIZE];
|
uint8_t key[ZT_SYMMETRIC_KEY_SIZE];
|
||||||
if (RR->identity.agree(id,key)) {
|
if (RR->identity.agree(id,key)) {
|
||||||
if (dearmor(key, peer->aesKeysIfSupported())) { // ensure packet is authentic, otherwise drop
|
if (dearmor(key, peer->aesKeysIfSupported(), RR->identity)) { // ensure packet is authentic, otherwise drop
|
||||||
RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"address collision");
|
RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"address collision");
|
||||||
Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR);
|
Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR);
|
||||||
outp.append((uint8_t)Packet::VERB_HELLO);
|
outp.append((uint8_t)Packet::VERB_HELLO);
|
||||||
outp.append((uint64_t)pid);
|
outp.append((uint64_t)pid);
|
||||||
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
|
outp.append((uint8_t)Packet::ERROR_IDENTITY_COLLISION);
|
||||||
outp.armor(key,true,peer->aesKeysIfSupported());
|
outp.armor(key,true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
Metrics::pkt_error_out++;
|
Metrics::pkt_error_out++;
|
||||||
Metrics::pkt_error_identity_collision_out++;
|
Metrics::pkt_error_identity_collision_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -419,7 +419,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
|||||||
} else {
|
} else {
|
||||||
// Identity is the same as the one we already have -- check packet integrity
|
// Identity is the same as the one we already have -- check packet integrity
|
||||||
|
|
||||||
if (!dearmor(peer->key(), peer->aesKeysIfSupported())) {
|
if (!dearmor(peer->key(), peer->aesKeysIfSupported(), RR->identity)) {
|
||||||
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
|
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -444,7 +444,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
|||||||
|
|
||||||
// Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap)
|
// Check packet integrity and MAC (this is faster than locallyValidate() so do it first to filter out total crap)
|
||||||
SharedPtr<Peer> newPeer(new Peer(RR,RR->identity,id));
|
SharedPtr<Peer> newPeer(new Peer(RR,RR->identity,id));
|
||||||
if (!dearmor(newPeer->key(), newPeer->aesKeysIfSupported())) {
|
if (!dearmor(newPeer->key(), newPeer->aesKeysIfSupported(), RR->identity)) {
|
||||||
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
|
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -510,38 +510,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
|||||||
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
|
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MAJOR);
|
||||||
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
|
outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR);
|
||||||
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
|
outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION);
|
||||||
|
_path->address().serialize(outp);
|
||||||
if (protoVersion >= 5) {
|
|
||||||
_path->address().serialize(outp);
|
|
||||||
} else {
|
|
||||||
/* LEGACY COMPATIBILITY HACK:
|
|
||||||
*
|
|
||||||
* For a while now (since 1.0.3), ZeroTier has recognized changes in
|
|
||||||
* its network environment empirically by examining its external network
|
|
||||||
* address as reported by trusted peers. In versions prior to 1.1.0
|
|
||||||
* (protocol version < 5), they did this by saving a snapshot of this
|
|
||||||
* information (in SelfAwareness.hpp) keyed by reporting device ID and
|
|
||||||
* address type.
|
|
||||||
*
|
|
||||||
* This causes problems when clustering is combined with symmetric NAT.
|
|
||||||
* Symmetric NAT remaps ports, so different endpoints in a cluster will
|
|
||||||
* report back different exterior addresses. Since the old code keys
|
|
||||||
* this by device ID and not sending physical address and compares the
|
|
||||||
* entire address including port, it constantly thinks its external
|
|
||||||
* surface is changing and resets connections when talking to a cluster.
|
|
||||||
*
|
|
||||||
* In new code we key by sending physical address and device and we also
|
|
||||||
* take the more conservative position of only interpreting changes in
|
|
||||||
* IP address (neglecting port) as a change in network topology that
|
|
||||||
* necessitates a reset. But we can make older clients work here by
|
|
||||||
* nulling out the port field. Since this info is only used for empirical
|
|
||||||
* detection of link changes, it doesn't break anything else.
|
|
||||||
*/
|
|
||||||
InetAddress tmpa(_path->address());
|
|
||||||
tmpa.setPort(0);
|
|
||||||
tmpa.serialize(outp);
|
|
||||||
}
|
|
||||||
|
|
||||||
const unsigned int worldUpdateSizeAt = outp.size();
|
const unsigned int worldUpdateSizeAt = outp.size();
|
||||||
outp.addSize(2); // make room for 16-bit size field
|
outp.addSize(2); // make room for 16-bit size field
|
||||||
if ((planetWorldId)&&(RR->topology->planetWorldTimestamp() > planetWorldTimestamp)&&(planetWorldId == RR->topology->planetWorldId())) {
|
if ((planetWorldId)&&(RR->topology->planetWorldTimestamp() > planetWorldTimestamp)&&(planetWorldId == RR->topology->planetWorldId())) {
|
||||||
@ -562,7 +531,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
|
|||||||
}
|
}
|
||||||
outp.setAt<uint16_t>(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2)));
|
outp.setAt<uint16_t>(worldUpdateSizeAt,(uint16_t)(outp.size() - (worldUpdateSizeAt + 2)));
|
||||||
|
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),now);
|
_path->send(RR,tPtr,outp.data(),outp.size(),now);
|
||||||
@ -724,7 +693,7 @@ bool IncomingPacket::_doWHOIS(const RuntimeEnvironment *RR,void *tPtr,const Shar
|
|||||||
|
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),RR->identity);
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,7 +921,7 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
|
|||||||
outp.append((uint64_t)packetId());
|
outp.append((uint64_t)packetId());
|
||||||
outp.append((uint64_t)nwid);
|
outp.append((uint64_t)nwid);
|
||||||
const int64_t now = RR->node->now();
|
const int64_t now = RR->node->now();
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -981,7 +950,7 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share
|
|||||||
if (size() > ZT_PACKET_IDX_PAYLOAD) {
|
if (size() > ZT_PACKET_IDX_PAYLOAD) {
|
||||||
outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD);
|
outp.append(reinterpret_cast<const unsigned char *>(data()) + ZT_PACKET_IDX_PAYLOAD,size() - ZT_PACKET_IDX_PAYLOAD);
|
||||||
}
|
}
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -1177,7 +1146,7 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void
|
|||||||
outp.append(requestPacketId);
|
outp.append(requestPacketId);
|
||||||
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
|
outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
Metrics::pkt_error_out++;
|
Metrics::pkt_error_out++;
|
||||||
Metrics::pkt_error_unsupported_op_out++;
|
Metrics::pkt_error_unsupported_op_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -1201,7 +1170,7 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c
|
|||||||
outp.append((uint64_t)network->id());
|
outp.append((uint64_t)network->id());
|
||||||
outp.append((uint64_t)configUpdateId);
|
outp.append((uint64_t)configUpdateId);
|
||||||
const int64_t now = RR->node->now();
|
const int64_t now = RR->node->now();
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -1244,7 +1213,7 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
|
|||||||
outp.append((uint32_t)mg.adi());
|
outp.append((uint32_t)mg.adi());
|
||||||
const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
|
const unsigned int gatheredLocally = RR->mc->gather(peer->address(),nwid,mg,outp,gatherLimit);
|
||||||
if (gatheredLocally > 0) {
|
if (gatheredLocally > 0) {
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),now);
|
_path->send(RR,tPtr,outp.data(),outp.size(),now);
|
||||||
@ -1348,7 +1317,7 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
|
|||||||
outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
|
outp.append((unsigned char)0x02); // flag 0x02 = contains gather results
|
||||||
if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
|
if (RR->mc->gather(peer->address(),nwid,to,outp,gatherLimit)) {
|
||||||
const int64_t now = RR->node->now();
|
const int64_t now = RR->node->now();
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
|
||||||
Metrics::pkt_ok_out++;
|
Metrics::pkt_ok_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
@ -1490,7 +1459,7 @@ void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void
|
|||||||
outp.append(packetId());
|
outp.append(packetId());
|
||||||
outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
outp.append((uint8_t)Packet::ERROR_NEED_MEMBERSHIP_CERTIFICATE);
|
||||||
outp.append(nwid);
|
outp.append(nwid);
|
||||||
outp.armor(peer->key(),true,peer->aesKeysIfSupported());
|
outp.armor(peer->key(),true,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
Metrics::pkt_error_out++;
|
Metrics::pkt_error_out++;
|
||||||
Metrics::pkt_error_need_membership_cert_out++;
|
Metrics::pkt_error_need_membership_cert_out++;
|
||||||
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
|
||||||
|
@ -198,7 +198,7 @@ void Multicaster::send(
|
|||||||
if (!network->config().disableCompression()) {
|
if (!network->config().disableCompression()) {
|
||||||
outp.compress();
|
outp.compress();
|
||||||
}
|
}
|
||||||
outp.armor(bestMulticastReplicator->key(),true,bestMulticastReplicator->aesKeysIfSupported());
|
outp.armor(bestMulticastReplicator->key(),true,false,bestMulticastReplicator->aesKeysIfSupported(),bestMulticastReplicator->identity());
|
||||||
Metrics::pkt_multicast_frame_out++;
|
Metrics::pkt_multicast_frame_out++;
|
||||||
bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now);
|
bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now);
|
||||||
return;
|
return;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "Packet.hpp"
|
#include "Packet.hpp"
|
||||||
|
#include "ECC.hpp"
|
||||||
|
|
||||||
#if defined(ZT_USE_X64_ASM_SALSA2012) && defined(ZT_ARCH_X64)
|
#if defined(ZT_USE_X64_ASM_SALSA2012) && defined(ZT_ARCH_X64)
|
||||||
#include "../ext/x64-salsa2012-asm/salsa2012.h"
|
#include "../ext/x64-salsa2012-asm/salsa2012.h"
|
||||||
@ -1009,8 +1010,7 @@ void Packet::armor(const void *key,bool encryptPayload,bool extendedArmor,const
|
|||||||
{
|
{
|
||||||
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
|
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
|
||||||
|
|
||||||
if (extendedArmor) {
|
this->setExtendedArmor(extendedArmor);
|
||||||
}
|
|
||||||
|
|
||||||
if ((aesKeys) && (encryptPayload)) {
|
if ((aesKeys) && (encryptPayload)) {
|
||||||
setCipher(ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV);
|
setCipher(ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV);
|
||||||
@ -1042,19 +1042,22 @@ void Packet::armor(const void *key,bool encryptPayload,bool extendedArmor,const
|
|||||||
if (ZT_HAS_FAST_CRYPTO()) {
|
if (ZT_HAS_FAST_CRYPTO()) {
|
||||||
const unsigned int payloadLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0;
|
const unsigned int payloadLen = (encryptPayload) ? (size() - ZT_PACKET_IDX_VERB) : 0;
|
||||||
uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8];
|
uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8];
|
||||||
|
uint64_t mac[2];
|
||||||
|
|
||||||
ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,payloadLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey);
|
ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,payloadLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey);
|
||||||
Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast<const uint8_t *>(keyStream + 8),payloadLen);
|
Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast<const uint8_t *>(keyStream + 8),payloadLen);
|
||||||
uint64_t mac[2];
|
|
||||||
Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream);
|
Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream);
|
||||||
|
|
||||||
#ifdef ZT_NO_TYPE_PUNNING
|
#ifdef ZT_NO_TYPE_PUNNING
|
||||||
memcpy(data + ZT_PACKET_IDX_MAC,mac,8);
|
memcpy(data + ZT_PACKET_IDX_MAC,mac,8);
|
||||||
#else
|
#else
|
||||||
(*reinterpret_cast<uint64_t *>(data + ZT_PACKET_IDX_MAC)) = mac[0];
|
(*reinterpret_cast<uint64_t *>(data + ZT_PACKET_IDX_MAC)) = mac[0];
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV);
|
|
||||||
|
|
||||||
uint64_t macKey[4];
|
uint64_t macKey[4];
|
||||||
|
uint64_t mac[2];
|
||||||
|
|
||||||
|
Salsa20 s20(mangledKey,data + ZT_PACKET_IDX_IV);
|
||||||
s20.crypt12(ZERO_KEY,macKey,sizeof(macKey));
|
s20.crypt12(ZERO_KEY,macKey,sizeof(macKey));
|
||||||
|
|
||||||
uint8_t *const payload = data + ZT_PACKET_IDX_VERB;
|
uint8_t *const payload = data + ZT_PACKET_IDX_VERB;
|
||||||
@ -1062,17 +1065,51 @@ void Packet::armor(const void *key,bool encryptPayload,bool extendedArmor,const
|
|||||||
if (encryptPayload) {
|
if (encryptPayload) {
|
||||||
s20.crypt12(payload,payload,payloadLen);
|
s20.crypt12(payload,payload,payloadLen);
|
||||||
}
|
}
|
||||||
uint64_t mac[2];
|
|
||||||
|
|
||||||
Poly1305::compute(mac,payload,payloadLen,macKey);
|
Poly1305::compute(mac,payload,payloadLen,macKey);
|
||||||
memcpy(data + ZT_PACKET_IDX_MAC,mac,8);
|
memcpy(data + ZT_PACKET_IDX_MAC,mac,8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (extendedArmor) {
|
||||||
|
ECC::Pair ephemeralKeyPair = ECC::generate();
|
||||||
|
uint8_t ephemeralSymmetric[32];
|
||||||
|
ECC::agree(ephemeralKeyPair, identity.publicKey(), ephemeralSymmetric, 32);
|
||||||
|
|
||||||
|
AES cipher(ephemeralSymmetric);
|
||||||
|
AES::CTR aesCtr(cipher);
|
||||||
|
aesCtr.init(data, 0, data + ZT_PACKET_IDX_EXTENDED_ARMOR_START);
|
||||||
|
aesCtr.crypt(data + ZT_PACKET_IDX_EXTENDED_ARMOR_START, size() - ZT_PACKET_IDX_EXTENDED_ARMOR_START);
|
||||||
|
|
||||||
|
this->append(ephemeralKeyPair.pub.data, ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Packet::dearmor(const void *key,const AES aesKeys[2],const Identity &identity)
|
bool Packet::dearmor(const void *key,const AES aesKeys[2],const Identity &identity)
|
||||||
{
|
{
|
||||||
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
|
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
|
||||||
|
|
||||||
|
if (extendedArmor()) {
|
||||||
|
if (size() < ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t ephemeralSymmetric[32];
|
||||||
|
ECC::Public ephemeralKey;
|
||||||
|
memcpy(ephemeralKey.data, data + (size() - ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN), ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN);
|
||||||
|
ECC::agree(identity.privateKeyPair(), ephemeralKey, ephemeralSymmetric, 32);
|
||||||
|
|
||||||
|
AES cipher(ephemeralSymmetric);
|
||||||
|
AES::CTR aesCtr(cipher);
|
||||||
|
aesCtr.init(data, 0, data + ZT_PACKET_IDX_EXTENDED_ARMOR_START);
|
||||||
|
aesCtr.crypt(data + ZT_PACKET_IDX_EXTENDED_ARMOR_START, size() - ZT_PACKET_IDX_EXTENDED_ARMOR_START);
|
||||||
|
|
||||||
|
this->setSize(size() - ZT_ECC_EPHEMERAL_PUBLIC_KEY_LEN);
|
||||||
|
|
||||||
|
/* Note: both the MAC and the data were encrypted with the ephemeral key. We don't need
|
||||||
|
* a separate MAC for the ephemeral encryption because the MAC check below is obviously
|
||||||
|
* going to fail if the ephemeral key was incorrect. */
|
||||||
|
}
|
||||||
|
|
||||||
const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB;
|
const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB;
|
||||||
unsigned char *const payload = data + ZT_PACKET_IDX_VERB;
|
unsigned char *const payload = data + ZT_PACKET_IDX_VERB;
|
||||||
const unsigned int cs = cipher();
|
const unsigned int cs = cipher();
|
||||||
@ -1080,6 +1117,7 @@ bool Packet::dearmor(const void *key,const AES aesKeys[2],const Identity &identi
|
|||||||
if (cs == ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV) {
|
if (cs == ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV) {
|
||||||
if (aesKeys) {
|
if (aesKeys) {
|
||||||
uint64_t tag[2];
|
uint64_t tag[2];
|
||||||
|
|
||||||
#ifdef ZT_NO_UNALIGNED_ACCESS
|
#ifdef ZT_NO_UNALIGNED_ACCESS
|
||||||
Utils::copy<8>(tag, data);
|
Utils::copy<8>(tag, data);
|
||||||
Utils::copy<8>(tag + 1, data + ZT_PACKET_IDX_MAC);
|
Utils::copy<8>(tag + 1, data + ZT_PACKET_IDX_MAC);
|
||||||
|
@ -1182,6 +1182,25 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return True if packet is encrypted with an extra ephemeral key
|
||||||
|
*/
|
||||||
|
inline bool extendedArmor() const { return (((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & ZT_PROTO_FLAG_EXTENDED_ARMOR) != 0); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this packet's extended armor flag
|
||||||
|
*
|
||||||
|
* @param f Extended armor flag value
|
||||||
|
*/
|
||||||
|
inline void setExtendedArmor(bool f)
|
||||||
|
{
|
||||||
|
if (f) {
|
||||||
|
(*this)[ZT_PACKET_IDX_FLAGS] |= (char)ZT_PROTO_FLAG_EXTENDED_ARMOR;
|
||||||
|
} else {
|
||||||
|
(*this)[ZT_PACKET_IDX_FLAGS] &= (char)(~ZT_PROTO_FLAG_EXTENDED_ARMOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return True if compressed (result only valid if unencrypted)
|
* @return True if compressed (result only valid if unencrypted)
|
||||||
*/
|
*/
|
||||||
@ -1287,6 +1306,8 @@ public:
|
|||||||
*
|
*
|
||||||
* @param key 32-byte key
|
* @param key 32-byte key
|
||||||
* @param encryptPayload If true, encrypt packet payload, else just MAC
|
* @param encryptPayload If true, encrypt packet payload, else just MAC
|
||||||
|
* @param extendedArmor Use an ephemeral key to encrypt payload (for encrypted HELLO)
|
||||||
|
* @param identity Identity of packet recipient/destination
|
||||||
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
|
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
|
||||||
*/
|
*/
|
||||||
void armor(const void *key,bool encryptPayload,bool extendedArmor,const AES aesKeys[2],const Identity &identity);
|
void armor(const void *key,bool encryptPayload,bool extendedArmor,const AES aesKeys[2],const Identity &identity);
|
||||||
@ -1300,6 +1321,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @param key 32-byte key
|
* @param key 32-byte key
|
||||||
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
|
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
|
||||||
|
* @param identity Receiver's identity (must include secret)
|
||||||
* @return False if packet is invalid or failed MAC authenticity check
|
* @return False if packet is invalid or failed MAC authenticity check
|
||||||
*/
|
*/
|
||||||
bool dearmor(const void *key,const AES aesKeys[2],const Identity &identity);
|
bool dearmor(const void *key,const AES aesKeys[2],const Identity &identity);
|
||||||
|
1140
node/Peer.cpp
1140
node/Peer.cpp
File diff suppressed because it is too large
Load Diff
1132
node/Peer.hpp
1132
node/Peer.hpp
File diff suppressed because it is too large
Load Diff
@ -1119,7 +1119,7 @@ void Switch::_sendViaSpecificPath(void *tPtr,SharedPtr<Peer> peer,SharedPtr<Path
|
|||||||
packet.setTrusted(trustedPathId);
|
packet.setTrusted(trustedPathId);
|
||||||
} else {
|
} else {
|
||||||
if (!packet.isEncrypted()) {
|
if (!packet.isEncrypted()) {
|
||||||
packet.armor(peer->key(),encrypt,peer->aesKeysIfSupported());
|
packet.armor(peer->key(),encrypt,false,peer->aesKeysIfSupported(),peer->identity());
|
||||||
}
|
}
|
||||||
RR->node->expectReplyTo(packet.packetId());
|
RR->node->expectReplyTo(packet.packetId());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user