This commit is contained in:
Adam Ierymenko 2019-08-27 14:25:11 -07:00
parent 6f22570648
commit 40803a4dc1
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
2 changed files with 16 additions and 74 deletions

View file

@ -24,17 +24,6 @@
#define ZT_AES_AESNI 1 #define ZT_AES_AESNI 1
#endif #endif
#if defined(_M_ARM64) || defined(__aarch64__) || defined(__aarch64) || defined(__AARCH64__)
#include <arm64intr.h>
#include <arm64_neon.h>
#ifndef ZT_AES_ARMNEON
#define ZT_AES_ARMNEON 1
#endif
#if defined(__GNUC__) && !defined(__apple_build_version__) && (defined(__ARM_ACLE) || defined(__ARM_FEATURE_CRYPTO))
#include <arm_acle.h>
#endif
#endif
#define ZT_AES_KEY_SIZE 32 #define ZT_AES_KEY_SIZE 32
#define ZT_AES_BLOCK_SIZE 16 #define ZT_AES_BLOCK_SIZE 16
@ -165,98 +154,56 @@ public:
* *
* This mode combines the two standard modes AES256-GMAC and AES256-CTR to * This mode combines the two standard modes AES256-GMAC and AES256-CTR to
* yield a mode similar to AES256-GCM-SIV that is resistant to accidental * yield a mode similar to AES256-GCM-SIV that is resistant to accidental
* message IV duplication. * message IV duplication. This is good because ZeroTier is stateless and
* uses a small (64-bit) IV to reduce bandwidth overhead.
* *
* @param iv 64-bit message IV * @param iv 96-bit message IV
* @param in Message plaintext * @param in Message plaintext
* @param len Length of plaintext * @param len Length of plaintext
* @param out Output buffer to receive ciphertext * @param out Output buffer to receive ciphertext
* @param tag Output buffer to receive 64-bit authentication tag * @param tag Output buffer to receive 64-bit authentication tag
*/ */
inline void ztGmacCtrEncrypt(const uint8_t iv[8],const void *in,unsigned int len,void *out,uint8_t tag[8]) const inline void ztGmacCtrEncrypt(const uint8_t iv[12],const void *in,unsigned int len,void *out,uint8_t tag[8]) const
{ {
uint8_t ctrIv[16],gmacIv[12]; uint8_t ctrIv[16];
// Compute AES256-GMAC(in) using a 96-bit IV constructed from gmac(iv,in,len,ctrIv);
// the 64-bit supplied IV and the message size.
#ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i];
gmacIv[8] = (uint8_t)(len >> 24);
gmacIv[9] = (uint8_t)(len >> 16);
gmacIv[10] = (uint8_t)(len >> 8);
gmacIv[11] = (uint8_t)len;
#else
*((uint64_t *)gmacIv) = *((const uint64_t *)iv);
*((uint32_t *)(gmacIv + 8)) = Utils::hton((uint32_t)len);
#endif
gmac(gmacIv,in,len,ctrIv);
// Encrypt GMAC output because GMAC alone is not a PRF.
encrypt(ctrIv,ctrIv); encrypt(ctrIv,ctrIv);
// Auth tag is the first 64 bits of AES(GMAC tag). CTR IV is this
// followed by the original 64-bit IV and then encrypted. This
// produces a secret, random, and one-time-use synthetic IV for
// CTR that is dependent on message content (via GMAC).
#ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) tag[i] = ctrIv[i]; for(unsigned int i=0;i<8;++i) tag[i] = ctrIv[i];
for(unsigned int i=0;i<8;++i) ctrIv[i+8] = iv[i];
#else for(unsigned int i=4;i<8;++i) ctrIv[i] ^= iv[i - 4];
*((uint64_t *)tag) = *((const uint64_t *)ctrIv); for(unsigned int i=8;i<16;++i) ctrIv[i] = iv[i - 4];
*((uint64_t *)(ctrIv + 8)) = *((const uint64_t *)iv);
#endif
encrypt(ctrIv,ctrIv); encrypt(ctrIv,ctrIv);
// Encrypt input using AES256-CTR
ctr(ctrIv,in,len,out); ctr(ctrIv,in,len,out);
} }
/** /**
* Decrypt a message encrypted with AES-256-GMAC-CTR and check its authenticity * Decrypt a message encrypted with AES-256-GMAC-CTR and check its authenticity
* *
* @param iv 64-bit message IV * @param iv 96-bit message IV
* @param in Message ciphertext * @param in Message ciphertext
* @param len Length of ciphertext * @param len Length of ciphertext
* @param out Output buffer to receive plaintext * @param out Output buffer to receive plaintext
* @param tag Authentication tag supplied with message * @param tag Authentication tag supplied with message
* @return True if authentication tags match and message appears authentic * @return True if authentication tags match and message appears authentic
*/ */
inline bool ztGmacCtrDecrypt(const uint8_t iv[8],const void *in,unsigned int len,void *out,const uint8_t tag[8]) const inline bool ztGmacCtrDecrypt(const uint8_t iv[12],const void *in,unsigned int len,void *out,const uint8_t tag[8]) const
{ {
uint8_t ctrIv[16],gmacOut[16],gmacIv[12]; uint8_t ctrIv[16],gmacOut[16];
// Re-create the original secret synthetic AES256-CTR IV.
#ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) ctrIv[i] = tag[i]; for(unsigned int i=0;i<8;++i) ctrIv[i] = tag[i];
for(unsigned int i=0;i<8;++i) ctrIv[i+8] = iv[i];
#else for(unsigned int i=4;i<8;++i) ctrIv[i] ^= iv[i - 4];
*((uint64_t *)ctrIv) = *((const uint8_t *)tag); for(unsigned int i=8;i<16;++i) ctrIv[i] = iv[i - 4];
*((uint64_t *)(ctrIv + 8)) = *((const uint64_t *)iv);
#endif
encrypt(ctrIv,ctrIv); encrypt(ctrIv,ctrIv);
// Decrypt input using AES256-CTR and this synthetic IV.
ctr(ctrIv,in,len,out); ctr(ctrIv,in,len,out);
// Compute AES256-GMAC(out) using the re-created 96-bit gmac(iv,out,len,gmacOut);
// GMAC IV built from the message IV and the message size.
#ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i];
gmacIv[8] = (uint8_t)(len >> 24);
gmacIv[9] = (uint8_t)(len >> 16);
gmacIv[10] = (uint8_t)(len >> 8);
gmacIv[11] = (uint8_t)len;
#else
*((uint64_t *)gmacIv) = *((const uint64_t *)iv);
*((uint32_t *)(gmacIv + 8)) = Utils::hton((uint32_t)len);
#endif
gmac(gmacIv,out,len,gmacOut);
// Encrypt GMAC results to get the tag that would have
// resulted from this message plaintext.
encrypt(gmacOut,gmacOut); encrypt(gmacOut,gmacOut);
// Compare authentication tags.
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
return Utils::secureEq(gmacOut,tag,8); return Utils::secureEq(gmacOut,tag,8);
#else #else

View file

@ -584,11 +584,6 @@ public:
* <[4] multicast additional distinguishing information (ADI)> * <[4] multicast additional distinguishing information (ADI)>
* [... additional tuples of network/address/adi ...] * [... additional tuples of network/address/adi ...]
* *
* LIKEs may be sent to any peer, though a good implementation should
* restrict them to peers on the same network they're for and to network
* controllers and root servers. In the current network, root servers
* will provide the service of final multicast cache.
*
* OK/ERROR are not generated. * OK/ERROR are not generated.
*/ */
VERB_MULTICAST_LIKE = 0x09, VERB_MULTICAST_LIKE = 0x09,