Wire up dearmor() path.

This commit is contained in:
Adam Ierymenko 2020-08-25 14:13:20 -07:00
parent 93d6b41898
commit b7b01da742
4 changed files with 40 additions and 20 deletions

View file

@ -67,7 +67,7 @@ bool IncomingPacket::tryDecode(const RuntimeEnvironment *RR,void *tPtr,int32_t f
const SharedPtr<Peer> peer(RR->topology->getPeer(tPtr,sourceAddress));
if (peer) {
if (!trusted) {
if (!dearmor(peer->key())) {
if (!dearmor(peer->key(), peer->aesKeysIfSupported())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,packetId(),sourceAddress,hops(),"invalid MAC");
peer->recordIncomingInvalidPacket(_path);
return true;
@ -288,7 +288,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
uint8_t key[ZT_PEER_SECRET_KEY_LENGTH];
if (RR->identity.agree(id,key,ZT_PEER_SECRET_KEY_LENGTH)) {
if (dearmor(key)) { // ensure packet is authentic, otherwise drop
if (dearmor(key, peer->aesKeysIfSupported())) { // ensure packet is authentic, otherwise drop
RR->t->incomingPacketDroppedHELLO(tPtr,_path,pid,fromAddress,"address collision");
Packet outp(id.address(),RR->identity.address(),Packet::VERB_ERROR);
outp.append((uint8_t)Packet::VERB_HELLO);
@ -307,7 +307,7 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
} else {
// Identity is the same as the one we already have -- check packet integrity
if (!dearmor(peer->key())) {
if (!dearmor(peer->key(), peer->aesKeysIfSupported())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
return true;
}
@ -332,7 +332,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)
SharedPtr<Peer> newPeer(new Peer(RR,RR->identity,id));
if (!dearmor(newPeer->key())) {
if (!dearmor(newPeer->key(), newPeer->aesKeysIfSupported())) {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
return true;
}

View file

@ -901,14 +901,16 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2])
*reinterpret_cast<uint64_t *>(data + ZT_PACKET_IDX_MAC) = tag[1];
#endif
} else {
uint8_t mangledKey[32];
setCipher(encryptPayload ? ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012 : ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE);
uint8_t mangledKey[32];
_salsa20MangleKey((const unsigned char *)key,mangledKey);
if (ZT_HAS_FAST_CRYPTO()) {
const unsigned int encryptLen = (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];
ZT_FAST_SINGLE_PASS_SALSA2012(keyStream,encryptLen + 64,(data + ZT_PACKET_IDX_IV),mangledKey);
Salsa20::memxor(data + ZT_PACKET_IDX_VERB,reinterpret_cast<const uint8_t *>(keyStream + 8),encryptLen);
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);
uint64_t mac[2];
Poly1305::compute(mac,data + ZT_PACKET_IDX_VERB,size() - ZT_PACKET_IDX_VERB,keyStream);
#ifdef ZT_NO_TYPE_PUNNING
@ -934,15 +936,33 @@ void Packet::armor(const void *key,bool encryptPayload,const AES aesKeys[2])
}
}
bool Packet::dearmor(const void *key)
bool Packet::dearmor(const void *key,const AES aesKeys[2])
{
uint8_t mangledKey[32];
uint8_t *const data = reinterpret_cast<uint8_t *>(unsafeData());
const unsigned int payloadLen = size() - ZT_PACKET_IDX_VERB;
unsigned char *const payload = data + ZT_PACKET_IDX_VERB;
const unsigned int cs = cipher();
if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) {
if (cs == ZT_PROTO_CIPHER_SUITE__AES_GMAC_SIV) {
if (aesKeys) {
AES::GMACSIVDecryptor dec(aesKeys[0],aesKeys[1]);
uint64_t tag[2];
#ifdef ZT_NO_UNALIGNED_ACCESS
Utils::copy<8>(tag, data);
Utils::copy<8>(tag + 1, data + ZT_PACKET_IDX_MAC);
#else
tag[0] = *reinterpret_cast<uint64_t *>(data);
tag[1] = *reinterpret_cast<uint64_t *>(data + ZT_PACKET_IDX_MAC);
#endif
dec.init(tag, payload);
dec.aad(data + ZT_PACKET_IDX_DEST,11);
dec.update(payload, payloadLen);
return dec.finish();
}
} else if ((cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_NONE)||(cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)) {
uint8_t mangledKey[32];
_salsa20MangleKey((const unsigned char *)key,mangledKey);
if (ZT_HAS_FAST_CRYPTO()) {
uint64_t keyStream[(ZT_PROTO_MAX_PACKET_LENGTH + 64 + 8) / 8];
@ -974,11 +994,10 @@ bool Packet::dearmor(const void *key)
if (cs == ZT_PROTO_CIPHER_SUITE__C25519_POLY1305_SALSA2012)
s20.crypt12(payload,payload,payloadLen);
}
return true;
} else {
return false; // unrecognized cipher suite
}
return false;
}
void Packet::cryptField(const void *key,unsigned int start,unsigned int len)

View file

@ -1313,7 +1313,7 @@ public:
*
* @param key 32-byte key
* @param encryptPayload If true, encrypt packet payload, else just MAC
* @param aes Use new AES-GMAC-SIV constrution
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
*/
void armor(const void *key,bool encryptPayload,const AES aesKeys[2]);
@ -1325,9 +1325,10 @@ public:
* address and MAC field match a trusted path.
*
* @param key 32-byte key
* @param aesKeys If non-NULL these are the two keys for AES-GMAC-SIV
* @return False if packet is invalid or failed MAC authenticity check
*/
bool dearmor(const void *key);
bool dearmor(const void *key,const AES aesKeys[2]);
/**
* Encrypt/decrypt a separately armored portion of a packet

View file

@ -533,11 +533,11 @@ public:
*/
inline int8_t bondingPolicy() { return _bondingPolicy; }
const AES *aesKeysIfSupported() const
{ return (const AES *)0; }
//const AES *aesKeysIfSupported() const
//{ return (_vProto >= 10) ? _aesKeys : (const AES *)0; }
//{ return (const AES *)0; }
const AES *aesKeysIfSupported() const
{ return (_vProto >= 10) ? _aesKeys : (const AES *)0; }
private:
struct _PeerPath