From ceb024ab03a114c8dadbbd393032231069981c45 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Mon, 16 Sep 2013 13:02:10 -0400 Subject: Integrating new crypto, work still in progress... --- node/Identity.cpp | 52 ++++++++++++++++++++++++- node/Node.cpp | 1 - node/NodeConfig.cpp | 46 ++++++++++++----------- node/Packet.hpp | 67 +++++++++++++++------------------ node/PacketDecoder.cpp | 24 ++++++------ node/Switch.cpp | 10 ++--- node/Utils.cpp | 100 ------------------------------------------------- node/Utils.hpp | 29 ++------------ 8 files changed, 126 insertions(+), 203 deletions(-) (limited to 'node') diff --git a/node/Identity.cpp b/node/Identity.cpp index 18f59cce..5a752e85 100644 --- a/node/Identity.cpp +++ b/node/Identity.cpp @@ -71,14 +71,64 @@ std::string Identity::toString(bool includePrivate) const r.append(_address.toString()); r.append(":2:"); // 2 == IDENTITY_TYPE_C25519 + r.append(Utils::hex(_publicKey.data,_publicKey.size())); + r.push_back(':'); + r.append(Utils::hex(_signature.data,_signature.size())); + if ((_privateKey)&&(includePrivate)) { + r.push_back(':'); + r.append(Utils::hex(_privateKey.data,_privateKey.size())); + } return r; } bool Identity::fromString(const char *str) { + char *saveptr = (char *)0; + char tmp[4096]; + if (!Utils::scopy(tmp,sizeof(tmp),str)) + return false; + + delete _privateKey; + _privateKey = (C25519::Private *)0; + + int fno = 0; + for(char *f=Utils::stok(tmp,":",&saveptr);(f);f=Utils::stok((char *)0,":",&saveptr)) { + switch(fno++) { + case 0: + _address = Address(f); + if (_address.isReserved()) + return false; + break; + case 1: + if (strcmp(f,"2")) + return false; + break; + case 2: + if (Utils::unhex(f,_publicKey.data,_publicKey.size()) != _publicKey.size()) + return false; + break; + case 3: + if (Utils::unhex(f,_signature.data,_signature.size()) != _signature.size()) + return false; + break; + case 4: + _privateKey = new C25519::Private(); + if (Utils::unhex(f,_privateKey->data,_privateKey->size()) != _privateKey->size()) + return false; + break; + default: + return false; + } + } + if (fno < 4) + return false; + + return true; } +// These are fixed parameters and can't be changed without a new +// identity type. #define ZT_IDENTITY_DERIVEADDRESS_DIGESTS 540672 #define ZT_IDENTITY_DERIVEADDRESS_ROUNDS 4 @@ -91,7 +141,7 @@ Address Identity::deriveAddress(const void *keyBytes,unsigned int keyLen) * unfortunately cannot be used here. If that were used, it would be * equivalently costly to simply increment/vary the public key and find * a collision as it would be to find the address. We need something - * that creates a costly 1:~1 mapping from key to address, hence this odd + * that creates a costly 1:~1 mapping from key to address, hence this * algorithm. * * Search for "sequential memory hard algorithm" for academic references diff --git a/node/Node.cpp b/node/Node.cpp index 07b5805e..590b9662 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -57,7 +57,6 @@ #include "Logger.hpp" #include "InetAddress.hpp" #include "Salsa20.hpp" -#include "HMAC.hpp" #include "RuntimeEnvironment.hpp" #include "NodeConfig.hpp" #include "Defaults.hpp" diff --git a/node/NodeConfig.cpp b/node/NodeConfig.cpp index bc7c35f4..4567d410 100644 --- a/node/NodeConfig.cpp +++ b/node/NodeConfig.cpp @@ -35,8 +35,6 @@ #include #include -#include - #include "Constants.hpp" #ifdef __WINDOWS__ @@ -54,7 +52,8 @@ #include "InetAddress.hpp" #include "Peer.hpp" #include "Salsa20.hpp" -#include "HMAC.hpp" +#include "Poly1305.hpp" +#include "SHA512.hpp" #include "Node.hpp" #ifdef __WINDOWS__ @@ -68,10 +67,11 @@ NodeConfig::NodeConfig(const RuntimeEnvironment *renv,const char *authToken) _r(renv), _controlSocket(true,ZT_CONTROL_UDP_PORT,false,&_CBcontrolPacketHandler,this) { - SHA256_CTX sha; - SHA256_Init(&sha); - SHA256_Update(&sha,authToken,strlen(authToken)); - SHA256_Final(_controlSocketKey,&sha); + { + unsigned int csk[64]; + SHA512::hash(authToken,strlen(authToken)); + memcpy(_controlSocketKey,csk,32); + } std::map networksDotD(Utils::listDirectory((_r->homePath + ZT_PATH_SEPARATOR_S + "networks.d").c_str())); std::set nwids; @@ -249,12 +249,13 @@ std::vector NodeConfig::execute(const char *command) std::vector< Buffer > NodeConfig::encodeControlMessage(const void *key,unsigned long conversationId,const std::vector &payload) throw(std::out_of_range) { - char hmac[32]; + char poly1305tag[ZT_POLY1305_MAC_LEN]; + char iv[8]; char keytmp[32]; std::vector< Buffer > packets; Buffer packet; - packet.setSize(16); // room for HMAC and IV + packet.setSize(16); // room for poly1305 auth tag and IV packet.append((uint32_t)(conversationId & 0xffffffff)); for(unsigned int i=0;i > NodeConfig::encodeControlMe packet.append((unsigned char)0); if (((i + 1) >= payload.size())||((packet.size() + payload[i + 1].length() + 1) >= packet.capacity())) { - Utils::getSecureRandom(packet.field(8,8),8); + Utils::getSecureRandom(iv,8); + memcpy(packet.field(8,8),iv,8); - Salsa20 s20(key,256,packet.field(8,8)); + Salsa20 s20(key,256,iv); s20.encrypt(packet.field(16,packet.size() - 16),packet.field(16,packet.size() - 16),packet.size() - 16); memcpy(keytmp,key,32); - for(unsigned int i=0;i<32;++i) - keytmp[i] ^= 0x77; // use a different permutation of key for HMAC than for Salsa20 - HMAC::sha256(keytmp,32,packet.field(16,packet.size() - 16),packet.size() - 16,hmac); - memcpy(packet.field(0,8),hmac,8); + for(unsigned int i=0;i<8;++i) + keytmp[i] ^= iv[i]; // can't reuse poly1305 keys, so mangle key with IV each time + Poly1305::compute(poly1305tag,packet.field(16,packet.size() - 16),packet.size() - 16,keytmp); + memcpy(packet.field(0,8),poly1305tag,8); packets.push_back(packet); - packet.setSize(16); // room for HMAC and IV + packet.setSize(16); // room for poly1305 auth tag and IV packet.append((uint32_t)(conversationId & 0xffffffff)); } } @@ -285,8 +287,9 @@ std::vector< Buffer > NodeConfig::encodeControlMe bool NodeConfig::decodeControlMessagePacket(const void *key,const void *data,unsigned int len,unsigned long &conversationId,std::vector &payload) { - char hmac[32]; + char poly1305tag[ZT_POLY1305_MAC_LEN]; char keytmp[32]; + char iv[8]; try { if (len < 20) @@ -295,10 +298,11 @@ bool NodeConfig::decodeControlMessagePacket(const void *key,const void *data,uns Buffer packet(data,len); memcpy(keytmp,key,32); - for(unsigned int i=0;i<32;++i) - keytmp[i] ^= 0x77; // use a different permutation of key for HMAC than for Salsa20 - HMAC::sha256(keytmp,32,packet.field(16,packet.size() - 16),packet.size() - 16,hmac); - if (memcmp(packet.field(0,8),hmac,8)) + memcpy(iv,packet.field(8,8),8); + for(unsigned int i=0;i<8;++i) + keytmp[i] ^= iv[i]; + Poly1305::compute(poly1305tag,packet.field(16,packet.size() - 16),packet.size() - 16,keytmp); + if (!Utils::secureEq(packet.field(0,8),poly1305tag,8)) return false; Salsa20 s20(key,256,packet.field(8,8)); diff --git a/node/Packet.hpp b/node/Packet.hpp index 509ef1a4..f42198e1 100644 --- a/node/Packet.hpp +++ b/node/Packet.hpp @@ -35,7 +35,7 @@ #include #include "Address.hpp" -#include "HMAC.hpp" +#include "Poly1305.hpp" #include "Salsa20.hpp" #include "Utils.hpp" #include "Constants.hpp" @@ -65,7 +65,7 @@ * Header flag indicating that a packet is encrypted with Salsa20 * * If this is not set, then the packet's payload is in the clear and the - * HMAC is over this (since there is no ciphertext). Otherwise the HMAC is + * MAC is over this (since there is no ciphertext). Otherwise the MAC is * of the ciphertext after encryption. */ #define ZT_PROTO_FLAG_ENCRYPTED 0x80 @@ -89,7 +89,7 @@ #define ZT_PACKET_IDX_DEST 8 #define ZT_PACKET_IDX_SOURCE 13 #define ZT_PACKET_IDX_FLAGS 18 -#define ZT_PACKET_IDX_HMAC 19 +#define ZT_PACKET_IDX_MAC 19 #define ZT_PACKET_IDX_VERB 27 #define ZT_PACKET_IDX_PAYLOAD 28 @@ -201,7 +201,7 @@ namespace ZeroTier { * <[5] destination ZT address> * <[5] source ZT address> * <[1] flags (LS 5 bits) and ZT hop count (MS 3 bits)> - * <[8] first 8 bytes of 32-byte HMAC-SHA-256 MAC> + * <[8] 8-bit MAC (currently first 8 bytes of poly1305 tag)> * [... -- begin encryption envelope -- ...] * <[1] encrypted flags (MS 3 bits) and verb (LS 5 bits)> * [... verb-specific payload ...] @@ -770,39 +770,39 @@ public: } /** - * Compute the HMAC of this packet's payload and set HMAC field + * Generate a message authenticationc code and set MAC field of packet * * For encrypted packets, this must be called after encryption. * * @param key 256-bit (32 byte) key */ - inline void hmacSet(const void *key) + inline void macSet(const void *key) { - unsigned char mac[32]; + unsigned char mac[16]; unsigned char key2[32]; _mangleKey((const unsigned char *)key,key2); - unsigned int hmacLen = (size() >= ZT_PACKET_IDX_VERB) ? (size() - ZT_PACKET_IDX_VERB) : 0; - HMAC::sha256(key2,sizeof(key2),field(ZT_PACKET_IDX_VERB,hmacLen),hmacLen,mac); - memcpy(field(ZT_PACKET_IDX_HMAC,8),mac,8); + unsigned int macLen = (size() >= ZT_PACKET_IDX_VERB) ? (size() - ZT_PACKET_IDX_VERB) : 0; + Poly1305::compute(mac,field(ZT_PACKET_IDX_VERB,macLen),macLen,key2); + memcpy(field(ZT_PACKET_IDX_MAC,8),mac,8); } /** - * Check the HMAC of this packet's payload + * Check the MAC of this packet's payload * * For encrypted packets, this must be checked before decryption. * * @param key 256-bit (32 byte) key */ - inline bool hmacVerify(const void *key) const + inline bool macVerify(const void *key) const { - unsigned char mac[32]; + unsigned char mac[16]; unsigned char key2[32]; if (size() < ZT_PACKET_IDX_VERB) return false; // incomplete packets fail _mangleKey((const unsigned char *)key,key2); - unsigned int hmacLen = size() - ZT_PACKET_IDX_VERB; - HMAC::sha256(key2,sizeof(key2),field(ZT_PACKET_IDX_VERB,hmacLen),hmacLen,mac); - return (!memcmp(field(ZT_PACKET_IDX_HMAC,8),mac,8)); + unsigned int macLen = size() - ZT_PACKET_IDX_VERB; + Poly1305::compute(mac,field(ZT_PACKET_IDX_VERB,macLen),macLen,key2); + return Utils::secureEq(mac,field(ZT_PACKET_IDX_MAC,8),8); } /** @@ -895,38 +895,31 @@ public: private: /** - * Deterministically mangle a 256-bit crypto key based on packet characteristics - * - * This takes the static agreed-upon input key and mangles it using - * info from the packet. This serves two purposes: - * - * (1) It reduces the (already minute) probability of a duplicate key / - * IV combo, which is good since keys are extremely long-lived. Another - * way of saying this is that it increases the effective IV size by - * using other parts of the packet as IV material. - * (2) It causes HMAC to fail should any of the following change: ordering - * of source and dest addresses, flags, IV, or packet size. HMAC has - * no explicit scheme for AAD (additional authenticated data). - * - * NOTE: this function will have to be changed if the order of any packet - * fields or their sizes/padding changes in the spec. + * Deterministically mangle a 256-bit crypto key based on packet * * @param in Input key (32 bytes) * @param out Output buffer (32 bytes) */ inline void _mangleKey(const unsigned char *in,unsigned char *out) const { - // Random IV (Salsa20 also uses the IV natively, but HMAC doesn't), and - // destination and source addresses. Using dest and source addresses - // gives us a (likely) different key space for a->b vs b->a. + // IV and source/destination addresses. Salsa uses the IV natively + // so this is redundant there, but not harmful. But Poly1305 depends + // on the key being mangled with the IV. Using the source and + // destination addresses bifurcates the key space into a different + // key space for each direction of the conversation. for(unsigned int i=0;i<18;++i) // 8 + (ZT_ADDRESS_LENGTH * 2) == 18 out[i] = in[i] ^ (unsigned char)(*this)[i]; - // Flags, but masking off hop count which is altered by forwarding nodes + + // Flags, but with hop count masked off. Hop count is altered by forwarding + // nodes. It's one of the only parts of a packet modifiable by people + // without the key. out[18] = in[18] ^ ((unsigned char)(*this)[ZT_PACKET_IDX_FLAGS] & 0xf8); - // Raw packet size in bytes -- each raw packet size defines a possibly - // different space of keys. + + // Raw packet size in bytes -- thus each packet size defines a new + // key space. out[19] = in[19] ^ (unsigned char)(size() & 0xff); out[20] = in[20] ^ (unsigned char)((size() >> 8) & 0xff); // little endian + // Rest of raw key is used unchanged for(unsigned int i=21;i<32;++i) out[i] = in[i]; diff --git a/node/PacketDecoder.cpp b/node/PacketDecoder.cpp index 533fb161..b9eb5684 100644 --- a/node/PacketDecoder.cpp +++ b/node/PacketDecoder.cpp @@ -75,8 +75,8 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) } // No saved state? Verify MAC before we proceed. - if (!hmacVerify(peer->macKey())) { - TRACE("dropped packet from %s(%s), HMAC authentication failed (size: %u)",source().toString().c_str(),_remoteAddress.toString().c_str(),size()); + if (!macVerify(peer->macKey())) { + TRACE("dropped packet from %s(%s), authentication failed (size: %u)",source().toString().c_str(),_remoteAddress.toString().c_str(),size()); return true; } @@ -85,7 +85,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) decrypt(peer->cryptKey()); } else { // Unencrypted is tolerated in case we want to run this on - // devices where squeezing out cycles matters. HMAC is + // devices where squeezing out cycles matters. MAC is // what's really important. But log it in debug to catch any // packets being mistakenly sent in the clear. TRACE("ODD: %s from %s(%s) wasn't encrypted",Packet::verbString(verb()),source().toString().c_str(),_remoteAddress.toString().c_str()); @@ -130,7 +130,7 @@ bool PacketDecoder::tryDecode(const RuntimeEnvironment *_r) return _doNETWORK_CONFIG_REFRESH(_r,peer); default: // This might be something from a new or old version of the protocol. - // Technically it passed HMAC so the packet is still valid, but we + // Technically it passed MAC so the packet is still valid, but we // ignore it. TRACE("ignored unrecognized verb %.2x from %s(%s)",(unsigned int)v,source().toString().c_str(),_remoteAddress.toString().c_str()); return true; @@ -162,7 +162,7 @@ void PacketDecoder::_CBaddPeerFromHello(void *arg,const SharedPtr &p,Topol outp.append((unsigned char)ZEROTIER_ONE_VERSION_MINOR); outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); outp.encrypt(p->cryptKey()); - outp.hmacSet(p->macKey()); + outp.macSet(p->macKey()); _r->demarc->send(req->localPort,req->remoteAddress,outp.data(),outp.size(),-1); } break; @@ -172,7 +172,7 @@ void PacketDecoder::_CBaddPeerFromHello(void *arg,const SharedPtr &p,Topol outp.append(req->helloPacketId); outp.append((unsigned char)Packet::ERROR_IDENTITY_INVALID); outp.encrypt(p->cryptKey()); - outp.hmacSet(p->macKey()); + outp.macSet(p->macKey()); _r->demarc->send(req->localPort,req->remoteAddress,outp.data(),outp.size(),-1); } break; @@ -183,7 +183,7 @@ void PacketDecoder::_CBaddPeerFromHello(void *arg,const SharedPtr &p,Topol outp.append(req->helloPacketId); outp.append((unsigned char)Packet::ERROR_IDENTITY_COLLISION); outp.encrypt(p->cryptKey()); - outp.hmacSet(p->macKey()); + outp.macSet(p->macKey()); _r->demarc->send(req->localPort,req->remoteAddress,outp.data(),outp.size(),-1); } break; } @@ -268,7 +268,7 @@ bool PacketDecoder::_doHELLO(const RuntimeEnvironment *_r) outp.append(packetId()); outp.append(timestamp); outp.encrypt(existingPeer->cryptKey()); - outp.hmacSet(existingPeer->macKey()); + outp.macSet(existingPeer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); return true; } @@ -353,7 +353,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.append(packetId()); p->identity().serialize(outp,false); outp.encrypt(peer->cryptKey()); - outp.hmacSet(peer->macKey()); + outp.macSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); TRACE("sent WHOIS response to %s for %s",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } else { @@ -363,7 +363,7 @@ bool PacketDecoder::_doWHOIS(const RuntimeEnvironment *_r,const SharedPtr outp.append((unsigned char)Packet::ERROR_OBJ_NOT_FOUND); outp.append(payload(),ZT_ADDRESS_LENGTH); outp.encrypt(peer->cryptKey()); - outp.hmacSet(peer->macKey()); + outp.macSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); TRACE("sent WHOIS ERROR to %s for %s (not found)",source().toString().c_str(),Address(payload(),ZT_ADDRESS_LENGTH).toString().c_str()); } @@ -467,7 +467,7 @@ bool PacketDecoder::_doMULTICAST_LIKE(const RuntimeEnvironment *_r,const SharedP outp.append(packetId()); outp.append((uint16_t)numAccepted); outp.encrypt(peer->cryptKey()); - outp.hmacSet(peer->macKey()); + outp.macSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); } catch (std::exception &ex) { TRACE("dropped MULTICAST_LIKE from %s(%s): unexpected exception: %s",source().toString().c_str(),_remoteAddress.toString().c_str(),ex.what()); @@ -654,7 +654,7 @@ bool PacketDecoder::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *_r,const outp.append((unsigned char)Packet::ERROR_UNSUPPORTED_OPERATION); outp.append(nwid); outp.encrypt(peer->cryptKey()); - outp.hmacSet(peer->macKey()); + outp.macSet(peer->macKey()); _r->demarc->send(_localPort,_remoteAddress,outp.data(),outp.size(),-1); #ifndef __WINDOWS__ } diff --git a/node/Switch.cpp b/node/Switch.cpp index e0ffba0b..e17f2196 100644 --- a/node/Switch.cpp +++ b/node/Switch.cpp @@ -218,7 +218,7 @@ bool Switch::sendHELLO(const SharedPtr &dest,Demarc::Port localPort,const outp.append((uint16_t)ZEROTIER_ONE_VERSION_REVISION); outp.append(now); _r->identity.serialize(outp,false); - outp.hmacSet(dest->macKey()); + outp.macSet(dest->macKey()); if (_r->demarc->send(localPort,remoteAddr,outp.data(),outp.size(),-1)) { dest->onSent(_r,false,Packet::VERB_HELLO,now); @@ -277,7 +277,7 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) outp.append(cg.first.rawIpData(),4); } outp.encrypt(p1p->cryptKey()); - outp.hmacSet(p1p->macKey()); + outp.macSet(p1p->macKey()); if (p1p->send(_r,outp.data(),outp.size(),now)) p1p->onSent(_r,false,Packet::VERB_RENDEZVOUS,now); } @@ -293,7 +293,7 @@ bool Switch::unite(const Address &p1,const Address &p2,bool force) outp.append(cg.second.rawIpData(),4); } outp.encrypt(p2p->cryptKey()); - outp.hmacSet(p2p->macKey()); + outp.macSet(p2p->macKey()); if (p2p->send(_r,outp.data(),outp.size(),now)) p2p->onSent(_r,false,Packet::VERB_RENDEZVOUS,now); } @@ -617,7 +617,7 @@ Address Switch::_sendWhoisRequest(const Address &addr,const Address *peersAlread Packet outp(supernode->address(),_r->identity.address(),Packet::VERB_WHOIS); addr.appendTo(outp); outp.encrypt(supernode->cryptKey()); - outp.hmacSet(supernode->macKey()); + outp.macSet(supernode->macKey()); uint64_t now = Utils::now(); if (supernode->send(_r,outp.data(),outp.size(),now)) { @@ -654,7 +654,7 @@ bool Switch::_trySend(const Packet &packet,bool encrypt) if (encrypt) tmp.encrypt(peer->cryptKey()); - tmp.hmacSet(peer->macKey()); + tmp.macSet(peer->macKey()); if (via->send(_r,tmp.data(),chunkSize,now)) { if (chunkSize < tmp.size()) { diff --git a/node/Utils.cpp b/node/Utils.cpp index 0b5afcbd..31174ecc 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -181,36 +181,6 @@ const uint64_t Utils::crc64Table[256] = { 0x536fa08fdfd90e51ULL,0x29b7d047efec8728ULL }; -const char Utils::base64EncMap[64] = { - 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48, - 0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50, - 0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58, - 0x59,0x5A,0x61,0x62,0x63,0x64,0x65,0x66, - 0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E, - 0x6F,0x70,0x71,0x72,0x73,0x74,0x75,0x76, - 0x77,0x78,0x79,0x7A,0x30,0x31,0x32,0x33, - 0x34,0x35,0x36,0x37,0x38,0x39,0x2B,0x2F -}; - -const char Utils::base64DecMap[128] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x3F, - 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, - 0x3C,0x3D,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06, - 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, - 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, - 0x17,0x18,0x19,0x00,0x00,0x00,0x00,0x00, - 0x00,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, - 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, - 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30, - 0x31,0x32,0x33,0x00,0x00,0x00,0x00,0x00 -}; - static const char *DAY_NAMES[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; static const char *MONTH_NAMES[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; @@ -249,76 +219,6 @@ std::map Utils::listDirectory(const char *path) return r; } -std::string Utils::base64Encode(const void *data,unsigned int len) -{ - if (!len) - return std::string(); - - std::string out; - unsigned int sidx = 0; - - if (len > 1) { - while (sidx < (len - 2)) { - out.push_back(base64EncMap[(((const unsigned char *)data)[sidx] >> 2) & 077]); - out.push_back(base64EncMap[((((const unsigned char *)data)[sidx + 1] >> 4) & 017) | ((((const unsigned char *)data)[sidx] << 4) & 077)]); - out.push_back(base64EncMap[((((const unsigned char *)data)[sidx + 2] >> 6) & 003) | ((((const unsigned char *)data)[sidx + 1] << 2) & 077)]); - out.push_back(base64EncMap[((const unsigned char *)data)[sidx + 2] & 077]); - sidx += 3; - } - } - if (sidx < len) { - out.push_back(base64EncMap[(((const unsigned char *)data)[sidx] >> 2) & 077]); - if (sidx < len - 1) { - out.push_back(base64EncMap[((((const unsigned char *)data)[sidx + 1] >> 4) & 017) | ((((const unsigned char *)data)[sidx] << 4) & 077)]); - out.push_back(base64EncMap[(((const unsigned char *)data)[sidx + 1] << 2) & 077]); - } else out.push_back(base64EncMap[(((const unsigned char *)data)[sidx] << 4) & 077]); - } - while (out.length() < (((len + 2) / 3) * 4)) - out.push_back('='); - - return out; -} - -std::string Utils::base64Decode(const char *data,unsigned int len) -{ - if (!len) - return std::string(); - std::string out; - - while ((len)&&(((const unsigned char *)data)[len-1] == '=')) - --len; - - for (unsigned idx=0;idx 47 && ch < 58) || (ch > 64 && ch < 91) || (ch > 96 && ch < 123) || ch == '+' || ch == '/' || ch == '=') - out.push_back(base64DecMap[ch]); - else return std::string(); - } - - unsigned outLen = len - ((len + 3) / 4); - if ((!outLen)||((((outLen + 2) / 3) * 4) < len)) - return std::string(); - - unsigned sidx = 0; - unsigned didx = 0; - if (outLen > 1) { - while (didx < outLen - 2) { - out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003)); - out[didx + 1] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017)); - out[didx + 2] = (((out[sidx + 2] << 6) & 255) | (out[sidx + 3] & 077)); - sidx += 4; - didx += 3; - } - } - - if (didx < outLen) - out[didx] = (((out[sidx] << 2) & 255) | ((out[sidx + 1] >> 4) & 003)); - if (++didx < outLen) - out[didx] = (((out[sidx + 1] << 4) & 255) | ((out[sidx + 2] >> 2) & 017)); - - return out.substr(0,outLen); -} - std::string Utils::hex(const void *data,unsigned int len) { std::string r; diff --git a/node/Utils.hpp b/node/Utils.hpp index 627a6628..b214c78c 100644 --- a/node/Utils.hpp +++ b/node/Utils.hpp @@ -87,13 +87,8 @@ public: p2 += 8; len -= 8; } - - while (len) { - diff |= (uint64_t)(*p1 ^ *p2); - ++p1; - ++p2; - --len; - } + while (len--) + diff |= (uint64_t)(*p1++ ^ *p2++); return (diff == 0ULL); } @@ -449,22 +444,6 @@ public: return writeFile(path,s.data(),(unsigned int)s.length()); } - /** - * @param data Binary data to encode - * @param len Length of data - * @return Base64-encoded string - */ - static std::string base64Encode(const void *data,unsigned int len); - inline static std::string base64Encode(const std::string &data) { return base64Encode(data.data(),(unsigned int)data.length()); } - - /** - * @param data Base64-encoded string - * @param len Length of encoded string - * @return Decoded binary date - */ - static std::string base64Decode(const char *data,unsigned int len); - inline static std::string base64Decode(const std::string &data) { return base64Decode(data.data(),(unsigned int)data.length()); } - /** * Split a string by delimiter, with optional escape and quote characters * @@ -477,7 +456,7 @@ public: static std::vector split(const char *s,const char *const sep,const char *esc,const char *quot); /** - * Tokenize a string + * Tokenize a string (alias for strtok_r or strtok_s depending on platform) * * @param str String to split * @param delim Delimiters @@ -772,8 +751,6 @@ public: private: static const uint64_t crc64Table[256]; - static const char base64EncMap[64]; - static const char base64DecMap[128]; }; } // namespace ZeroTier -- cgit v1.2.3