Cleanup, Linux build fix.

This commit is contained in:
Adam Ierymenko 2019-08-26 12:17:23 -07:00
parent b6d7a95028
commit a0fd4ad23f
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
4 changed files with 75 additions and 45 deletions

View file

@ -53,9 +53,11 @@ public:
inline AES() {} inline AES() {}
inline AES(const uint8_t key[32]) { this->init(key); } inline AES(const uint8_t key[32]) { this->init(key); }
inline ~AES() { Utils::burn(&_k,sizeof(_k)); } inline ~AES() { Utils::burn(&_k,sizeof(_k)); }
/**
* Set (or re-set) this AES256 cipher's key
*/
inline void init(const uint8_t key[32]) inline void init(const uint8_t key[32])
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
@ -68,6 +70,12 @@ public:
_initSW(key); _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 inline void encrypt(const uint8_t in[16],uint8_t out[16]) const
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
@ -80,6 +88,14 @@ public:
_encryptSW(in,out); _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 inline void gmac(const uint8_t iv[12],const void *in,const unsigned int len,uint8_t out[16]) const
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
@ -90,6 +106,18 @@ public:
#endif #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 inline void ctr(const uint8_t iv[16],const void *in,unsigned int len,void *out) const
{ {
#ifdef ZT_AES_AESNI #ifdef ZT_AES_AESNI
@ -133,11 +161,11 @@ public:
* @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]) 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]; 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. // the 64-bit supplied IV and the message size.
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i]; for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i];
@ -151,9 +179,13 @@ public:
#endif #endif
gmac(gmacIv,in,len,ctrIv); gmac(gmacIv,in,len,ctrIv);
// (2) The first 64 bits of GMAC output are the auth tag. Create // Encrypt GMAC output because GMAC alone is not a PRF.
// a secret synthetic AES256-CTR IV by encrypting these and the encrypt(ctrIv,ctrIv);
// original supplied IV.
// 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 #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]; for(unsigned int i=0;i<8;++i) ctrIv[i+8] = iv[i];
@ -163,7 +195,7 @@ public:
#endif #endif
encrypt(ctrIv,ctrIv); encrypt(ctrIv,ctrIv);
// (3) Encrypt input using AES256-CTR // Encrypt input using AES256-CTR
ctr(ctrIv,in,len,out); ctr(ctrIv,in,len,out);
} }
@ -177,11 +209,11 @@ public:
* @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]) 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]; 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 #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]; for(unsigned int i=0;i<8;++i) ctrIv[i+8] = iv[i];
@ -191,10 +223,10 @@ public:
#endif #endif
encrypt(ctrIv,ctrIv); encrypt(ctrIv,ctrIv);
// (2) Decrypt input using AES256-CTR // Decrypt input using AES256-CTR and this synthetic IV.
ctr(ctrIv,in,len,out); 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. // GMAC IV built from the message IV and the message size.
#ifdef ZT_NO_TYPE_PUNNING #ifdef ZT_NO_TYPE_PUNNING
for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i]; for(unsigned int i=0;i<8;++i) gmacIv[i] = iv[i];
@ -208,7 +240,11 @@ public:
#endif #endif
gmac(gmacIv,out,len,gmacOut); 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 #ifdef ZT_NO_TYPE_PUNNING
return Utils::secureEq(gmacOut,tag,8); return Utils::secureEq(gmacOut,tag,8);
#else #else
@ -444,9 +480,9 @@ private:
while (len >= 64) { while (len >= 64) {
__m128i c0 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton(ctr),iv0),k0); __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 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(ctr+2ULL),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(ctr+3ULL),iv0),k0); __m128i c3 = _mm_xor_si128(_mm_set_epi64((__m64)Utils::hton((uint64_t)(ctr+3ULL)),iv0),k0);
ctr += 4; ctr += 4;
c0 = _mm_aesenc_si128(c0,k1); c0 = _mm_aesenc_si128(c0,k1);
c1 = _mm_aesenc_si128(c1,k1); c1 = _mm_aesenc_si128(c1,k1);

View file

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

View file

@ -228,7 +228,7 @@ void SHA384(void *digest,const void *data,unsigned int len)
memcpy(digest,tmp,48); 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]; uint8_t tmp[64];
sha512_state state; sha512_state state;

View file

@ -50,7 +50,7 @@ static inline void SHA384(void *digest,const void *data,unsigned int len)
CC_SHA384_Update(&ctx,data,len); CC_SHA384_Update(&ctx,data,len);
CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx); 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_SHA512_CTX ctx;
CC_SHA384_Init(&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_Update(&ctx,data,len);
SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx); 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; SHA512_CTX ctx;
SHA384_Init(&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 #ifndef ZT_HAVE_NATIVE_SHA512
void SHA512(void *digest,const void *data,unsigned int len); void SHA512(void *digest,const void *data,unsigned int len);
void SHA384(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 #endif
static inline void HMACSHA384(const uint8_t key[32],const void *msg,const unsigned int msglen,uint8_t mac[48]) 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 #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)) SHA384(mac,outer,176); // H(output padded key | H(input padded key | msg))
} }