Browse Source

Cleanup, Linux build fix.

Adam Ierymenko 6 years ago
parent
commit
a0fd4ad23f
4 changed files with 75 additions and 45 deletions
  1. 51 15
      node/AES.hpp
  2. 19 25
      node/Identity.hpp
  3. 1 1
      node/SHA512.cpp
  4. 4 4
      node/SHA512.hpp

+ 51 - 15
node/AES.hpp

@@ -53,9 +53,11 @@ public:
 
 	inline AES() {}
 	inline AES(const uint8_t key[32]) { this->init(key); }
-
 	inline ~AES() { Utils::burn(&_k,sizeof(_k)); }
 
+	/**
+	 * Set (or re-set) this AES256 cipher's key
+	 */
 	inline void init(const uint8_t key[32])
 	{
 #ifdef ZT_AES_AESNI
@@ -68,6 +70,12 @@ public:
 		_initSW(key);
 	}
 
+	/**
+	 * Encrypt a single AES block (ECB mode)
+	 *
+	 * @param in Input block
+	 * @param out Output block (can be same as input)
+	 */
 	inline void encrypt(const uint8_t in[16],uint8_t out[16]) const
 	{
 #ifdef ZT_AES_AESNI
@@ -80,6 +88,14 @@ public:
 		_encryptSW(in,out);
 	}
 
+	/**
+	 * Compute GMAC-AES256 (GCM without ciphertext)
+	 *
+	 * @param iv 96-bit IV
+	 * @param in Input data
+	 * @param len Length of input
+	 * @param out 128-bit authorization tag from GMAC
+	 */
 	inline void gmac(const uint8_t iv[12],const void *in,const unsigned int len,uint8_t out[16]) const
 	{
 #ifdef ZT_AES_AESNI
@@ -90,6 +106,18 @@ public:
 #endif
 	}
 
+	/**
+	 * Encrypt or decrypt (they're the same) using AES256-CTR
+	 *
+	 * The counter here is a 128-bit big-endian that starts at the IV. The code only
+	 * increments the least significant 64 bits, making it only safe to use for a
+	 * maximum of 2^64-1 bytes (much larger than we ever do).
+	 *
+	 * @param iv 128-bit CTR IV
+	 * @param in Input plaintext or ciphertext
+	 * @param len Length of input
+	 * @param out Output plaintext or ciphertext
+	 */
 	inline void ctr(const uint8_t iv[16],const void *in,unsigned int len,void *out) const
 	{
 #ifdef ZT_AES_AESNI
@@ -133,11 +161,11 @@ public:
 	 * @param out Output buffer to receive ciphertext
 	 * @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])
+	inline void ztGmacCtrEncrypt(const uint8_t iv[8],const void *in,unsigned int len,void *out,uint8_t tag[8]) const
 	{
 		uint8_t ctrIv[16],gmacIv[12];
 
-		// (1) Compute AES256-GMAC(in) using a 96-bit IV constructed from
+		// Compute AES256-GMAC(in) using a 96-bit IV constructed from
 		// 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];
@@ -151,9 +179,13 @@ public:
 #endif
 		gmac(gmacIv,in,len,ctrIv);
 
-		// (2) The first 64 bits of GMAC output are the auth tag. Create
-		// a secret synthetic AES256-CTR IV by encrypting these and the
-		// original supplied IV.
+		// Encrypt GMAC output because GMAC alone is not a PRF.
+		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) ctrIv[i+8] = iv[i];
@@ -163,7 +195,7 @@ public:
 #endif
 		encrypt(ctrIv,ctrIv);
 
-		// (3) Encrypt input using AES256-CTR
+		// Encrypt input using AES256-CTR
 		ctr(ctrIv,in,len,out);
 	}
 
@@ -177,11 +209,11 @@ public:
 	 * @param tag Authentication tag supplied with message
 	 * @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])
+	inline bool ztGmacCtrDecrypt(const uint8_t iv[8],const void *in,unsigned int len,void *out,const uint8_t tag[8]) const
 	{
 		uint8_t ctrIv[16],gmacOut[16],gmacIv[12];
 
-		// (1) Re-create the original secret synthetic AES256-CTR IV.
+		// 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+8] = iv[i];
@@ -191,10 +223,10 @@ public:
 #endif
 		encrypt(ctrIv,ctrIv);
 
-		// (2) Decrypt input using AES256-CTR
+		// Decrypt input using AES256-CTR and this synthetic IV.
 		ctr(ctrIv,in,len,out);
 
-		// (3) Compute AES256-GMAC(out) using the re-created 96-bit
+		// Compute AES256-GMAC(out) using the re-created 96-bit
 		// 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];
@@ -208,7 +240,11 @@ public:
 #endif
 		gmac(gmacIv,out,len,gmacOut);
 
-		// (4) Compare first 64 bits of GMAC output with tag.
+		// Encrypt GMAC results to get the tag that would have
+		// resulted from this message plaintext.
+		encrypt(gmacOut,gmacOut);
+
+		// Compare authentication tags.
 #ifdef ZT_NO_TYPE_PUNNING
 		return Utils::secureEq(gmacOut,tag,8);
 #else
@@ -444,9 +480,9 @@ private:
 
 		while (len >= 64) {
 			__m128i c0 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton(ctr),iv0),k0);
-			__m128i c1 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton(ctr+1ULL),iv0),k0);
-			__m128i c2 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton(ctr+2ULL),iv0),k0);
-			__m128i c3 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton(ctr+3ULL),iv0),k0);
+			__m128i c1 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton((uint64_t)(ctr+1ULL)),iv0),k0);
+			__m128i c2 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton((uint64_t)(ctr+2ULL)),iv0),k0);
+			__m128i c3 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton((uint64_t)(ctr+3ULL)),iv0),k0);
 			ctr += 4;
 			c0 = _mm_aesenc_si128(c0,k1);
 			c1 = _mm_aesenc_si128(c1,k1);

+ 19 - 25
node/Identity.hpp

@@ -160,30 +160,26 @@ public:
 	 */
 	inline unsigned int sign(const void *data,unsigned int len,void *sig,unsigned int siglen) const
 	{
-		uint8_t h[48 + ZT_C25519_PUBLIC_KEY_LEN];
-		if (!_hasPrivate)
-			return 0;
-		switch(_type) {
+		if (_hasPrivate) {
+			switch(_type) {
 
-			case C25519:
-				if (siglen < ZT_C25519_SIGNATURE_LEN)
-					return 0;
-				C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
-				return ZT_C25519_SIGNATURE_LEN;
+				case C25519:
+					if (siglen >= ZT_C25519_SIGNATURE_LEN) {
+						C25519::sign(_priv.c25519,_pub.c25519,data,len,sig);
+						return ZT_C25519_SIGNATURE_LEN;
+					}
 
-			case P384:
-				if (siglen < ZT_ECC384_SIGNATURE_SIZE)
-					return 0;
-				// Include C25519 public key in input for P-384 signature so the two keys are "bound
-				// together" and cannot be decoupled in the same identity. An identity can have the
-				// same C25519 key but a different P-384 key and have the same address, but this
-				// means its signatures and key agreements will be different.
-				SHA384(h,data,len);
-				memcpy(h + 48,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
-				SHA384(h,h,48 + ZT_C25519_PUBLIC_KEY_LEN);
-				ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
-				return ZT_ECC384_SIGNATURE_SIZE;
+				case P384:
+					if (siglen >= ZT_ECC384_SIGNATURE_SIZE) {
+						// Signature is a hash of the message followed by the c25519/ed25519 type 0
+						// identity public keys to ensure that the two public keys are not separable.
+						uint8_t h[48];
+						SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
+						ECC384ECDSASign(_priv.p384,h,(uint8_t *)sig);
+						return ZT_ECC384_SIGNATURE_SIZE;
+					}
 
+			}
 		}
 		return 0;
 	}
@@ -204,10 +200,8 @@ public:
 				return C25519::verify(_pub.c25519,data,len,sig,siglen);
 			case P384:
 				if (siglen == ZT_ECC384_SIGNATURE_SIZE) {
-					uint8_t h[48 + ZT_C25519_PUBLIC_KEY_LEN];
-					SHA384(h,data,len);
-					memcpy(h + 48,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
-					SHA384(h,h,48 + ZT_C25519_PUBLIC_KEY_LEN);
+					uint8_t h[48];
+					SHA384(h,data,len,_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN);
 					return ECC384ECDSAVerify(_pub.p384,h,(const uint8_t *)sig);
 				}
 				break;

+ 1 - 1
node/SHA512.cpp

@@ -228,7 +228,7 @@ void SHA384(void *digest,const void *data,unsigned int len)
 	memcpy(digest,tmp,48);
 }
 
-void SHA384ab(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
+void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
 {
 	uint8_t tmp[64];
 	sha512_state state;

+ 4 - 4
node/SHA512.hpp

@@ -50,7 +50,7 @@ static inline void SHA384(void *digest,const void *data,unsigned int len)
 	CC_SHA384_Update(&ctx,data,len);
 	CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
 }
-static inline void SHA384ab(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
+static inline void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
 {
 	CC_SHA512_CTX ctx;
 	CC_SHA384_Init(&ctx);
@@ -76,7 +76,7 @@ static inline void SHA384(void *digest,const void *data,unsigned int len)
 	SHA384_Update(&ctx,data,len);
 	SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
 }
-static inline void SHA384ab(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
+static inline void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1)
 {
 	SHA512_CTX ctx;
 	SHA384_Init(&ctx);
@@ -89,7 +89,7 @@ static inline void SHA384ab(void *digest,const void *data0,unsigned int len0,con
 #ifndef ZT_HAVE_NATIVE_SHA512
 void SHA512(void *digest,const void *data,unsigned int len);
 void SHA384(void *digest,const void *data,unsigned int len);
-void SHA384ab(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1);
+void SHA384(void *digest,const void *data0,unsigned int len0,const void *data1,unsigned int len1);
 #endif
 
 static inline void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,uint8_t mac[48])
@@ -121,7 +121,7 @@ static inline void HMACSHA384(const uint8_t key[32],const void *msg,const unsign
 	}
 #endif
 
-	SHA384ab(((uint8_t *)outer) + 128,kInPadded,128,msg,msglen); // H(input padded key | msg)
+	SHA384(((uint8_t *)outer) + 128,kInPadded,128,msg,msglen); // H(input padded key | msg)
 	SHA384(mac,outer,176); // H(output padded key | H(input padded key | msg))
 }