Add SHA384 support, more cleanup

This commit is contained in:
Adam Ierymenko 2019-08-07 16:41:58 -05:00
parent 5b1cf33b1b
commit d0746da5e2
No known key found for this signature in database
GPG Key ID: 1657198823E52A61
9 changed files with 364 additions and 331 deletions

View File

@ -2696,7 +2696,7 @@ void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char
for (i = 64;i < smlen;++i) playground[i] = sm[i];
//crypto_hash_sha512(hram,playground,smlen);
ZeroTier::SHA512::hash(hram,playground,(unsigned int)smlen);
ZeroTier::SHA512(hram,playground,(unsigned int)smlen);
}
//////////////////////////////////////////////////////////////////////////////
@ -2716,11 +2716,11 @@ void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void
unsigned char digest[64];
crypto_scalarmult(rawkey,mine.data,their.data);
SHA512::hash(digest,rawkey,32);
SHA512(digest,rawkey,32);
for(unsigned int i=0,k=0;i<keylen;) {
if (k == 64) {
k = 0;
SHA512::hash(digest,digest,64);
SHA512(digest,digest,64);
}
((unsigned char *)keybuf)[i++] = digest[k++];
}
@ -2729,7 +2729,7 @@ void C25519::agree(const C25519::Private &mine,const C25519::Public &their,void
void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPublic,const void *msg,unsigned int len,void *signature)
{
unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg)
SHA512::hash(digest,msg,len);
SHA512(digest,msg,len);
#ifdef ZT_USE_FAST_X64_ED25519
ed25519_amd64_asm_sign(myPrivate.data + 32,myPublic.data + 32,digest,(unsigned char *)signature);
@ -2743,7 +2743,7 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli
unsigned char hram[crypto_hash_sha512_BYTES];
unsigned char *sig = (unsigned char *)signature;
SHA512::hash(extsk,myPrivate.data + 32,32);
SHA512(extsk,myPrivate.data + 32,32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;
@ -2753,7 +2753,7 @@ void C25519::sign(const C25519::Private &myPrivate,const C25519::Public &myPubli
for(unsigned int i=0;i<32;i++)
sig[64 + i] = digest[i];
SHA512::hash(hmg,sig + 32,64);
SHA512(hmg,sig + 32,64);
/* Computation of R */
sc25519_from64bytes(&sck, hmg);
@ -2785,7 +2785,7 @@ bool C25519::verify(const C25519::Public &their,const void *msg,unsigned int len
const unsigned char *sig = (const unsigned char *)signature;
unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg)
unsigned char sigtmp[96];
SHA512::hash(digest,msg,len);
SHA512(digest,msg,len);
if ((siglen == 96)&&(!Utils::secureEq(sig+64,digest,32))) {
return false;
@ -2831,7 +2831,7 @@ void C25519::_calcPubED(C25519::Pair &kp)
// Second 32 bytes of pub and priv are the keys for ed25519
// signing and verification.
SHA512::hash(extsk,kp.priv.data + 32,32);
SHA512(extsk,kp.priv.data + 32,32);
extsk[0] &= 248;
extsk[31] &= 127;
extsk[31] |= 64;

View File

@ -49,7 +49,7 @@ namespace ZeroTier {
static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem)
{
// Digest publicKey[] to obtain initial digest
SHA512::hash(digest,publicKey,publicKeyBytes);
SHA512(digest,publicKey,publicKeyBytes);
// Initialize genmem[] using Salsa20 in a CBC-like configuration since
// ordinary Salsa20 is randomly seek-able. This is good for a cipher
@ -123,7 +123,7 @@ void Identity::generate(const Type t)
do {
ECC384GenerateKey(_k.t1.pub,_k.t1.priv);
// TODO
SHA512::hash(digest,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
SHA512(digest,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
_address.setTo(digest + 59,ZT_ADDRESS_LENGTH);
} while (_address.isReserved());
_type = P384;

View File

@ -75,6 +75,8 @@ public:
~Identity() { Utils::burn(reinterpret_cast<void *>(this),sizeof(Identity)); }
inline void zero() { memset(reinterpret_cast<void *>(this),0,sizeof(Identity)); }
inline Identity &operator=(const Identity &id)
{
memcpy(reinterpret_cast<void *>(this),&id,sizeof(Identity));
@ -118,10 +120,10 @@ public:
if (_hasPrivate) {
switch(_type) {
case C25519:
SHA512::hash(sha,_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
SHA512(sha,_k.t0.priv.data,ZT_C25519_PRIVATE_KEY_LEN);
return true;
case P384:
SHA512::hash(sha,_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE);
SHA512(sha,_k.t1.priv,ZT_ECC384_PRIVATE_KEY_SIZE);
return true;
}
}
@ -139,10 +141,10 @@ public:
if (_hasPrivate) {
switch(_type) {
case C25519:
SHA512::hash(sha,_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
SHA512(sha,_k.t0.pub.data,ZT_C25519_PUBLIC_KEY_LEN);
return true;
case P384:
SHA512::hash(sha,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
SHA512(sha,_k.t1.pub,ZT_ECC384_PUBLIC_KEY_SIZE);
return true;
}
}
@ -175,7 +177,7 @@ public:
case P384:
if (siglen < ZT_ECC384_SIGNATURE_SIZE)
return 0;
SHA512::hash(h,data,len);
SHA512(h,data,len);
ECC384ECDSASign(_k.t1.priv,h,(uint8_t *)sig);
return ZT_ECC384_SIGNATURE_SIZE;
}
@ -200,7 +202,7 @@ public:
case P384:
if (siglen != ZT_ECC384_SIGNATURE_SIZE)
return false;
SHA512::hash(h,data,len);
SHA512(h,data,len);
return ECC384ECDSAVerify(_k.t1.pub,h,(const uint8_t *)sig);
}
return false;
@ -227,12 +229,12 @@ public:
return true;
case P384:
ECC384ECDH(id._k.t1.pub,_k.t1.priv,ecc384RawSecret);
SHA512::hash(h,ecc384RawSecret,sizeof(ecc384RawSecret));
SHA512(h,ecc384RawSecret,sizeof(ecc384RawSecret));
unsigned int hi = 0;
for(unsigned int i=0;i<klen;++i) {
if (hi == 64) {
hi = 0;
SHA512::hash(h,h,64);
SHA512(h,h,64);
}
((uint8_t *)key)[i] = h[hi++];
}

View File

@ -31,10 +31,15 @@
#include "Identity.hpp"
#include "InetAddress.hpp"
#include "Utils.hpp"
#include "Buffer.hpp"
#include "SHA512.hpp"
#include <algorithm>
#include <vector>
#define ZT_LOCATOR_MAX_PHYSICAL_ADDRESSES 255
#define ZT_LOCATOR_MAX_VIRTUAL_ADDRESSES 255
namespace ZeroTier {
/**
@ -48,22 +53,139 @@ namespace ZeroTier {
class Locator
{
public:
Locator() :
_signatureLength(0) {}
Locator() : _signatureLength(0) {}
inline const std::vector<InetAddress> &phy() const { return _physical; }
inline const std::vector<Identity> &virt() const { return _virtual; }
inline void add(const InetAddress &ip)
{
if (_physical.size() < ZT_LOCATOR_MAX_PHYSICAL_ADDRESSES)
_physical.push_back(ip);
}
inline void add(const Identity &zt)
{
if (_virtual.size() < ZT_LOCATOR_MAX_VIRTUAL_ADDRESSES)
_virtual.push_back(zt);
}
inline void finish(const Identity &id,const int64_t ts)
{
_ts = ts;
_id = id;
std::sort(_physical.begin(),_physical.end());
_physical.erase(std::unique(_physical.begin(),_physical.end()),_physical.end());
std::sort(_virtual.begin(),_virtual.end());
_virtual.erase(std::unique(_virtual.begin(),_virtual.end()),_virtual.end());
}
inline bool sign(const Identity &signingId)
{
std::sort(_physical.begin(),_physical.end());
std::sort(_virtual.begin(),_virtual.end());
_id = signingId;
if (!signingId.hasPrivate())
return false;
if (signingId == _id) {
_signedBy.zero();
} else {
_signedBy = signingId;
}
Buffer<65536> *tmp = new Buffer<65536>();
try {
serialize(*tmp,true);
_signatureLength = signingId.sign(tmp->data(),tmp->size(),_signature,ZT_SIGNATURE_BUFFER_SIZE);
delete tmp;
return (_signatureLength > 0);
} catch ( ... ) {
delete tmp;
return false;
}
}
inline bool verify() const
{
if ((_signatureLength == 0)||(_signatureLength > sizeof(_signature)))
return false;
Buffer<16384> *tmp;
try {
tmp = new Buffer<16384>(); // 16384 would be huge
serialize(*tmp,true);
const bool ok = (_signedBy) ? _signedBy.verify(tmp->data(),tmp->size(),_signature,_signatureLength) : _id.verify(tmp->data(),tmp->size(),_signature,_signatureLength);
delete tmp;
return ok;
} catch ( ... ) {
delete tmp;
return false;
}
}
template<unsigned int C>
inline void serialize(Buffer<C> &b,const bool forSign = false) const
{
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
b.append((uint8_t)0; // version/flags, currently 0
b.append((uint64_t)_ts);
_id.serialise(b,false);
if (_signedBy) {
b.append((uint8_t)1); // number of signers
_signedBy.serialize(b,false);
} else {
b.append((uint8_t)0); // signer is _id
}
b.append((uint8_t)_physical.size());
for(std::vector<InetAddress>::const_iterator i(_physical.begin());i!=_physical.end();++i)
i->serialize(b);
b.append((uint8_t)_virtual.size());
for(std::vector<Identity>::const_iterator i(_virtual.begin());i!=_virtual.end();++i)
i->serialize(b,false);
if (!forSign) {
b.append((uint16_t)_signatureLength);
b.append(_signature,_signatureLength);
}
b.append((uint16_t)0); // length of additional fields, currently 0
if (forSign) b.append((uint64_t)0x7f7f7f7f7f7f7f7fULL);
}
template<unsigned int C>
inline unsigned int deserialize(const Buffer<C> &b,unsigned int startAt = 0)
{
unsigned int p = startAt;
if (b[p++] != 0)
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
_ts = (int64_t)b.template at<uint64_t>(p); p += 8;
p += _id.deserialize(b,p);
const unsigned int signerCount = b[p++];
if (signerCount > 1)
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
if (signerCount == 1) {
p += _signedBy.deserialize(b,p);
} else {
_signedBy.zero();
}
const unsigned int physicalCount = b[p++];
_physical.resize(physicalCount);
for(unsigned int i=0;i<physicalCount;++i)
p += _physical[i].deserialize(b,p);
const unsigned int virtualCount = b[p++];
_virtual.resize(virtualCount);
for(unsigned int i=0;i<virtualCount;++i)
p += _virtual[i].deserialize(b,p);
_signatureLen = b.template at<uint16_t>(p); p += 2;
if (_signatureLength > ZT_SIGNATURE_BUFFER_SIZE)
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
memcpy(_signature,b.field(p,_signatureLength),_signatureLength);
p += _signatureLength;
p += b.template at<uint16_t>(p); p += 2;
if (p > b.size())
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
return (p - startAt);
}
private:
int64_t _ts;
Identity _id;
Identity _signedBy; // signed by _id if nil/zero
std::vector<InetAddress> _physical;
std::vector<Identity> _virtual;
unsigned int _signatureLength;

View File

@ -14,17 +14,29 @@ Public domain.
#include "SHA512.hpp"
#include "Utils.hpp"
#if 0
#ifdef __APPLE__
#include <CommonCrypto/CommonDigest.h>
#define ZT_HAVE_NATIVE_SHA512
namespace ZeroTier {
void SHA512::hash(void *digest,const void *data,unsigned int len)
void SHA512(void *digest,const void *data,unsigned int len)
{
CC_SHA512_CTX ctx;
CC_SHA512_Init(&ctx);
CC_SHA512_Update(&ctx,data,len);
CC_SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
}
void SHA384(void *digest,const void *data,unsigned int len)
{
CC_SHA512_CTX ctx;
CC_SHA384_Init(&ctx);
CC_SHA384_Update(&ctx,data,len);
CC_SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
}
}
#endif
@ -32,327 +44,221 @@ void SHA512::hash(void *digest,const void *data,unsigned int len)
#include <openssl/sha.h>
#define ZT_HAVE_NATIVE_SHA512
namespace ZeroTier {
void SHA512::hash(void *digest,const void *data,unsigned int len)
void SHA512(void *digest,const void *data,unsigned int len)
{
SHA512_CTX ctx;
SHA512_Init(&ctx);
SHA512_Update(&ctx,data,len);
SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
}
void SHA384(void *digest,const void *data,unsigned int len)
{
SHA512_CTX ctx;
SHA384_Init(&ctx);
SHA384_Update(&ctx,data,len);
SHA384_Final(reinterpret_cast<unsigned char *>(digest),&ctx);
}
}
#endif
#endif
#ifndef ZT_HAVE_NATIVE_SHA512
namespace ZeroTier {
#define uint64 uint64_t
namespace {
#ifdef ZT_NO_TYPE_PUNNING
static uint64 load_bigendian(const unsigned char *x)
static inline void sha512_encode(uint64_t input, uint8_t *output, uint32_t idx)
{
return
(uint64) (x[7]) \
| (((uint64) (x[6])) << 8) \
| (((uint64) (x[5])) << 16) \
| (((uint64) (x[4])) << 24) \
| (((uint64) (x[3])) << 32) \
| (((uint64) (x[2])) << 40) \
| (((uint64) (x[1])) << 48) \
| (((uint64) (x[0])) << 56)
;
output[idx + 0] = (uint8_t)(input >> 56);
output[idx + 1] = (uint8_t)(input >> 48);
output[idx + 2] = (uint8_t)(input >> 40);
output[idx + 3] = (uint8_t)(input >> 32);
output[idx + 4] = (uint8_t)(input >> 24);
output[idx + 5] = (uint8_t)(input >> 16);
output[idx + 6] = (uint8_t)(input >> 8);
output[idx + 7] = (uint8_t)(input >> 0);
}
static inline void sha512_decode(uint64_t *output, uint8_t *input, uint32_t idx)
{
*output = ((uint64_t)input[idx + 0] << 56)
| ((uint64_t)input[idx + 1] << 48)
| ((uint64_t)input[idx + 2] << 40)
| ((uint64_t)input[idx + 3] << 32)
| ((uint64_t)input[idx + 4] << 24)
| ((uint64_t)input[idx + 5] << 16)
| ((uint64_t)input[idx + 6] << 8)
| ((uint64_t)input[idx + 7] << 0);
}
static void store_bigendian(unsigned char *x,uint64 u)
{
x[7] = u; u >>= 8;
x[6] = u; u >>= 8;
x[5] = u; u >>= 8;
x[4] = u; u >>= 8;
x[3] = u; u >>= 8;
x[2] = u; u >>= 8;
x[1] = u; u >>= 8;
x[0] = u;
}
typedef struct sha512_ctx_tag {
uint32_t is_sha384;
uint8_t block[128];
uint64_t len[2];
uint64_t val[8];
uint8_t *payload_addr;
uint64_t payload_len;
} sha512_ctx_t;
#else // !ZT_NO_TYPE_PUNNING
#define LSR(x,n) (x >> n)
#define ROR(x,n) (LSR(x,n) | (x << (64 - n)))
#define load_bigendian(x) Utils::ntoh(*((const uint64_t *)(x)))
#define store_bigendian(x,u) (*((uint64_t *)(x)) = Utils::hton((u)))
#define MA(x,y,z) ((x & y) | (z & (x | y)))
#define CH(x,y,z) (z ^ (x & (y ^ z)))
#define GAMMA0(x) (ROR(x, 1) ^ ROR(x, 8) ^ LSR(x, 7))
#define GAMMA1(x) (ROR(x,19) ^ ROR(x,61) ^ LSR(x, 6))
#define SIGMA0(x) (ROR(x,28) ^ ROR(x,34) ^ ROR(x,39))
#define SIGMA1(x) (ROR(x,14) ^ ROR(x,18) ^ ROR(x,41))
#endif // ZT_NO_TYPE_PUNNING
#define INIT_COMPRESSOR() uint64_t tmp0 = 0, tmp1 = 0
#define COMPRESS( a, b, c, d, e, f, g, h, x, k) \
tmp0 = h + SIGMA1(e) + CH(e,f,g) + k + x; \
tmp1 = SIGMA0(a) + MA(a,b,c); d += tmp0; h = tmp0 + tmp1;
#define SHR(x,c) ((x) >> (c))
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
static const uint8_t sha512_padding[128] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
#define EXPAND \
M(w0 ,w14,w9 ,w1 ) \
M(w1 ,w15,w10,w2 ) \
M(w2 ,w0 ,w11,w3 ) \
M(w3 ,w1 ,w12,w4 ) \
M(w4 ,w2 ,w13,w5 ) \
M(w5 ,w3 ,w14,w6 ) \
M(w6 ,w4 ,w15,w7 ) \
M(w7 ,w5 ,w0 ,w8 ) \
M(w8 ,w6 ,w1 ,w9 ) \
M(w9 ,w7 ,w2 ,w10) \
M(w10,w8 ,w3 ,w11) \
M(w11,w9 ,w4 ,w12) \
M(w12,w10,w5 ,w13) \
M(w13,w11,w6 ,w14) \
M(w14,w12,w7 ,w15) \
M(w15,w13,w8 ,w0 )
#define F(w,k) \
T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
T2 = Sigma0(a) + Maj(a,b,c); \
h = g; \
g = f; \
f = e; \
e = d + T1; \
d = c; \
c = b; \
b = a; \
a = T1 + T2;
static inline int crypto_hashblocks(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
{
uint64 state[8];
uint64 a;
uint64 b;
uint64 c;
uint64 d;
uint64 e;
uint64 f;
uint64 g;
uint64 h;
uint64 T1;
uint64 T2;
a = load_bigendian(statebytes + 0); state[0] = a;
b = load_bigendian(statebytes + 8); state[1] = b;
c = load_bigendian(statebytes + 16); state[2] = c;
d = load_bigendian(statebytes + 24); state[3] = d;
e = load_bigendian(statebytes + 32); state[4] = e;
f = load_bigendian(statebytes + 40); state[5] = f;
g = load_bigendian(statebytes + 48); state[6] = g;
h = load_bigendian(statebytes + 56); state[7] = h;
while (inlen >= 128) {
uint64 w0 = load_bigendian(in + 0);
uint64 w1 = load_bigendian(in + 8);
uint64 w2 = load_bigendian(in + 16);
uint64 w3 = load_bigendian(in + 24);
uint64 w4 = load_bigendian(in + 32);
uint64 w5 = load_bigendian(in + 40);
uint64 w6 = load_bigendian(in + 48);
uint64 w7 = load_bigendian(in + 56);
uint64 w8 = load_bigendian(in + 64);
uint64 w9 = load_bigendian(in + 72);
uint64 w10 = load_bigendian(in + 80);
uint64 w11 = load_bigendian(in + 88);
uint64 w12 = load_bigendian(in + 96);
uint64 w13 = load_bigendian(in + 104);
uint64 w14 = load_bigendian(in + 112);
uint64 w15 = load_bigendian(in + 120);
F(w0 ,0x428a2f98d728ae22ULL)
F(w1 ,0x7137449123ef65cdULL)
F(w2 ,0xb5c0fbcfec4d3b2fULL)
F(w3 ,0xe9b5dba58189dbbcULL)
F(w4 ,0x3956c25bf348b538ULL)
F(w5 ,0x59f111f1b605d019ULL)
F(w6 ,0x923f82a4af194f9bULL)
F(w7 ,0xab1c5ed5da6d8118ULL)
F(w8 ,0xd807aa98a3030242ULL)
F(w9 ,0x12835b0145706fbeULL)
F(w10,0x243185be4ee4b28cULL)
F(w11,0x550c7dc3d5ffb4e2ULL)
F(w12,0x72be5d74f27b896fULL)
F(w13,0x80deb1fe3b1696b1ULL)
F(w14,0x9bdc06a725c71235ULL)
F(w15,0xc19bf174cf692694ULL)
EXPAND
F(w0 ,0xe49b69c19ef14ad2ULL)
F(w1 ,0xefbe4786384f25e3ULL)
F(w2 ,0x0fc19dc68b8cd5b5ULL)
F(w3 ,0x240ca1cc77ac9c65ULL)
F(w4 ,0x2de92c6f592b0275ULL)
F(w5 ,0x4a7484aa6ea6e483ULL)
F(w6 ,0x5cb0a9dcbd41fbd4ULL)
F(w7 ,0x76f988da831153b5ULL)
F(w8 ,0x983e5152ee66dfabULL)
F(w9 ,0xa831c66d2db43210ULL)
F(w10,0xb00327c898fb213fULL)
F(w11,0xbf597fc7beef0ee4ULL)
F(w12,0xc6e00bf33da88fc2ULL)
F(w13,0xd5a79147930aa725ULL)
F(w14,0x06ca6351e003826fULL)
F(w15,0x142929670a0e6e70ULL)
EXPAND
F(w0 ,0x27b70a8546d22ffcULL)
F(w1 ,0x2e1b21385c26c926ULL)
F(w2 ,0x4d2c6dfc5ac42aedULL)
F(w3 ,0x53380d139d95b3dfULL)
F(w4 ,0x650a73548baf63deULL)
F(w5 ,0x766a0abb3c77b2a8ULL)
F(w6 ,0x81c2c92e47edaee6ULL)
F(w7 ,0x92722c851482353bULL)
F(w8 ,0xa2bfe8a14cf10364ULL)
F(w9 ,0xa81a664bbc423001ULL)
F(w10,0xc24b8b70d0f89791ULL)
F(w11,0xc76c51a30654be30ULL)
F(w12,0xd192e819d6ef5218ULL)
F(w13,0xd69906245565a910ULL)
F(w14,0xf40e35855771202aULL)
F(w15,0x106aa07032bbd1b8ULL)
EXPAND
F(w0 ,0x19a4c116b8d2d0c8ULL)
F(w1 ,0x1e376c085141ab53ULL)
F(w2 ,0x2748774cdf8eeb99ULL)
F(w3 ,0x34b0bcb5e19b48a8ULL)
F(w4 ,0x391c0cb3c5c95a63ULL)
F(w5 ,0x4ed8aa4ae3418acbULL)
F(w6 ,0x5b9cca4f7763e373ULL)
F(w7 ,0x682e6ff3d6b2b8a3ULL)
F(w8 ,0x748f82ee5defb2fcULL)
F(w9 ,0x78a5636f43172f60ULL)
F(w10,0x84c87814a1f0ab72ULL)
F(w11,0x8cc702081a6439ecULL)
F(w12,0x90befffa23631e28ULL)
F(w13,0xa4506cebde82bde9ULL)
F(w14,0xbef9a3f7b2c67915ULL)
F(w15,0xc67178f2e372532bULL)
EXPAND
F(w0 ,0xca273eceea26619cULL)
F(w1 ,0xd186b8c721c0c207ULL)
F(w2 ,0xeada7dd6cde0eb1eULL)
F(w3 ,0xf57d4f7fee6ed178ULL)
F(w4 ,0x06f067aa72176fbaULL)
F(w5 ,0x0a637dc5a2c898a6ULL)
F(w6 ,0x113f9804bef90daeULL)
F(w7 ,0x1b710b35131c471bULL)
F(w8 ,0x28db77f523047d84ULL)
F(w9 ,0x32caab7b40c72493ULL)
F(w10,0x3c9ebe0a15c9bebcULL)
F(w11,0x431d67c49c100d4cULL)
F(w12,0x4cc5d4becb3e42b6ULL)
F(w13,0x597f299cfc657e2aULL)
F(w14,0x5fcb6fab3ad6faecULL)
F(w15,0x6c44198c4a475817ULL)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
e += state[4];
f += state[5];
g += state[6];
h += state[7];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
state[4] = e;
state[5] = f;
state[6] = g;
state[7] = h;
in += 128;
inlen -= 128;
}
store_bigendian(statebytes + 0,state[0]);
store_bigendian(statebytes + 8,state[1]);
store_bigendian(statebytes + 16,state[2]);
store_bigendian(statebytes + 24,state[3]);
store_bigendian(statebytes + 32,state[4]);
store_bigendian(statebytes + 40,state[5]);
store_bigendian(statebytes + 48,state[6]);
store_bigendian(statebytes + 56,state[7]);
return 0;
}
#define blocks crypto_hashblocks
static const unsigned char iv[64] = {
0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
static const uint64_t K[80] = {
0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL, 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
0xD807AA98A3030242ULL, 0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL, 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL, 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL, 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
0xD192E819D6EF5218ULL, 0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL, 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL, 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL, 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
};
void SHA512::hash(void *digest,const void *data,unsigned int len)
static inline void sha512_memcpy(uint8_t *src, uint8_t *dst, uint32_t size)
{
unsigned char h[64];
unsigned char padded[256];
int i;
uint64_t bytes = len;
uint32_t i = 0;
for (;i < size;i++) { *dst++ = *src++; }
}
static inline void sha512_memclr(uint8_t *dst, uint32_t size)
{
uint32_t i = 0;
for (;i < size;i++) { *dst++ = 0; }
}
const unsigned char *in = (const unsigned char *)data;
unsigned int inlen = len;
static inline void sha512_init_512(sha512_ctx_t *sha512_ctx, uint8_t *payload_addr, uint64_t payload_len)
{
sha512_memclr((uint8_t *)sha512_ctx,sizeof(sha512_ctx_t));
sha512_ctx->val[0] = 0x6A09E667F3BCC908ULL;
sha512_ctx->val[1] = 0xBB67AE8584CAA73BULL;
sha512_ctx->val[2] = 0x3C6EF372FE94F82BULL;
sha512_ctx->val[3] = 0xA54FF53A5F1D36F1ULL;
sha512_ctx->val[4] = 0x510E527FADE682D1ULL;
sha512_ctx->val[5] = 0x9B05688C2B3E6C1FULL;
sha512_ctx->val[6] = 0x1F83D9ABFB41BD6BULL;
sha512_ctx->val[7] = 0x5BE0CD19137E2179ULL;
sha512_ctx->is_sha384 = 0;
sha512_ctx->payload_addr = payload_addr;
sha512_ctx->payload_len = (uint64_t)payload_len;
sha512_ctx->len[0] = payload_len << 3;
sha512_ctx->len[1] = payload_len >> 61;
}
for (i = 0;i < 64;++i) h[i] = iv[i];
static inline void sha512_init_384(sha512_ctx_t *sha512_ctx, uint8_t *payload_addr, uint64_t payload_len)
{
sha512_memclr((uint8_t *)sha512_ctx,sizeof(sha512_ctx_t));
sha512_ctx->val[0] = 0xCBBB9D5DC1059ED8ULL;
sha512_ctx->val[1] = 0x629A292A367CD507ULL;
sha512_ctx->val[2] = 0x9159015A3070DD17ULL;
sha512_ctx->val[3] = 0x152FECD8F70E5939ULL;
sha512_ctx->val[4] = 0x67332667FFC00B31ULL;
sha512_ctx->val[5] = 0x8EB44A8768581511ULL;
sha512_ctx->val[6] = 0xDB0C2E0D64F98FA7ULL;
sha512_ctx->val[7] = 0x47B5481DBEFA4FA4ULL;
sha512_ctx->is_sha384 = 1;
sha512_ctx->payload_addr = payload_addr;
sha512_ctx->payload_len = (uint64_t)payload_len;
sha512_ctx->len[0] = payload_len << 3;
sha512_ctx->len[1] = payload_len >> 61;
}
blocks(h,in,inlen);
in += inlen;
inlen &= 127;
in -= inlen;
for (i = 0;i < (int)inlen;++i) padded[i] = in[i];
padded[inlen] = 0x80;
if (inlen < 112) {
for (i = inlen + 1;i < 119;++i) padded[i] = 0;
padded[119] = (unsigned char)((bytes >> 61) & 0xff);
padded[120] = (unsigned char)((bytes >> 53) & 0xff);
padded[121] = (unsigned char)((bytes >> 45) & 0xff);
padded[122] = (unsigned char)((bytes >> 37) & 0xff);
padded[123] = (unsigned char)((bytes >> 29) & 0xff);
padded[124] = (unsigned char)((bytes >> 21) & 0xff);
padded[125] = (unsigned char)((bytes >> 13) & 0xff);
padded[126] = (unsigned char)((bytes >> 5) & 0xff);
padded[127] = (unsigned char)((bytes << 3) & 0xff);
blocks(h,padded,128);
} else {
for (i = inlen + 1;i < 247;++i) padded[i] = 0;
padded[247] = (unsigned char)((bytes >> 61) & 0xff);
padded[248] = (unsigned char)((bytes >> 53) & 0xff);
padded[249] = (unsigned char)((bytes >> 45) & 0xff);
padded[250] = (unsigned char)((bytes >> 37) & 0xff);
padded[251] = (unsigned char)((bytes >> 29) & 0xff);
padded[252] = (unsigned char)((bytes >> 21) & 0xff);
padded[253] = (unsigned char)((bytes >> 13) & 0xff);
padded[254] = (unsigned char)((bytes >> 5) & 0xff);
padded[255] = (unsigned char)((bytes << 3) & 0xff);
blocks(h,padded,256);
static inline void sha512_hash_factory(sha512_ctx_t *ctx, uint8_t data[128])
{
uint32_t i = 0;
uint64_t W[80];
uint64_t v[8];
INIT_COMPRESSOR();
for(i = 0; i < 16; i++) { sha512_decode(&W[i], data, i << 3 ); }
for(; i < 80; i++) { W[i] = GAMMA1(W[i - 2]) + W[i - 7] + GAMMA0(W[i - 15]) + W[i - 16]; }
for (i = 0;i < 8; i++) { v[i] = ctx->val[i]; }
for(i = 0; i < 80;) {
COMPRESS(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7], W[i], K[i] ); i++;
COMPRESS(v[7], v[0], v[1], v[2], v[3], v[4], v[5], v[6], W[i], K[i] ); i++;
COMPRESS(v[6], v[7], v[0], v[1], v[2], v[3], v[4], v[5], W[i], K[i] ); i++;
COMPRESS(v[5], v[6], v[7], v[0], v[1], v[2], v[3], v[4], W[i], K[i] ); i++;
COMPRESS(v[4], v[5], v[6], v[7], v[0], v[1], v[2], v[3], W[i], K[i] ); i++;
COMPRESS(v[3], v[4], v[5], v[6], v[7], v[0], v[1], v[2], W[i], K[i] ); i++;
COMPRESS(v[2], v[3], v[4], v[5], v[6], v[7], v[0], v[1], W[i], K[i] ); i++;
COMPRESS(v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[0], W[i], K[i] ); i++;
}
for (i = 0; i < 8; i++) { ctx->val[i] += v[i]; }
}
for (i = 0;i < 64;++i) ((unsigned char *)digest)[i] = h[i];
static inline void sha512_stage1(sha512_ctx_t *sha512_ctx)
{
while (sha512_ctx->payload_len >= 128) {
sha512_hash_factory(sha512_ctx, sha512_ctx->payload_addr);
sha512_ctx->payload_addr += 128;
sha512_ctx->payload_len -= 128;
}
}
static inline void sha512_stage2(sha512_ctx_t *sha512_ctx, uint8_t output[64])
{
uint32_t block_pos = sha512_ctx->payload_len;
uint32_t padding_bytes = 0;
uint8_t temp_data[128] = {0};
uint8_t *temp_data_p = (uint8_t *)&temp_data[0];
uint8_t len_be[16] = {0};
uint8_t i = 0;
sha512_memcpy(sha512_ctx->payload_addr, temp_data_p, sha512_ctx->payload_len);
padding_bytes = 112 - block_pos;
temp_data_p += block_pos;
sha512_memcpy((uint8_t *)sha512_padding, temp_data_p, padding_bytes);
temp_data_p += padding_bytes;
sha512_encode(sha512_ctx->len[1], len_be, 0);
sha512_encode(sha512_ctx->len[0], len_be, 8);
sha512_memcpy(len_be, temp_data_p, 16);
sha512_hash_factory(sha512_ctx, temp_data);
for (i = 0; i < 6; i++) { sha512_encode(sha512_ctx->val[i], output, i * 8); }
for ( ;(i < 8) && (sha512_ctx->is_sha384 == 0); i++) { sha512_encode(sha512_ctx->val[i], output, i * 8); }
}
} // anonymous namespace
void SHA512(void *digest,const void *data,unsigned int len)
{
sha512_ctx_t h;
sha512_init_512(&h,(uint8_t *)data,len);
sha512_stage1(&h);
sha512_stage2(&h,(uint8_t *)digest);
}
void SHA384(void *digest,const void *data,unsigned int len)
{
sha512_ctx_t h;
sha512_init_384(&h,(uint8_t *)data,len);
sha512_stage1(&h);
sha512_stage2(&h,(uint8_t *)digest);
}
} // namespace ZeroTier
@ -363,5 +269,5 @@ void SHA512::hash(void *digest,const void *data,unsigned int len)
// This eliminates the need to link against a third party SHA512() from this code
extern "C" void ZT_sha512internal(void *digest,const void *data,unsigned int len)
{
ZeroTier::SHA512::hash(digest,data,len);
ZeroTier::SHA512(digest,data,len);
}

View File

@ -31,14 +31,9 @@
namespace ZeroTier {
/**
* SHA-512 digest algorithm
*/
class SHA512
{
public:
static void hash(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);
} // namespace ZeroTier

View File

@ -242,8 +242,8 @@ public:
*/
static void getSecureRandom(void *buf,unsigned int bytes);
static int Utils::b32d(const char *encoded, uint8_t *result, int bufSize);
static int Utils::b32e(const uint8_t *data,int length,char *result,int bufSize);
static int b32d(const char *encoded, uint8_t *result, int bufSize);
static int b32e(const uint8_t *data,int length,char *result,int bufSize);
/**
* Tokenize a string (alias for strtok_r or strtok_s depending on platform)

View File

@ -105,6 +105,7 @@ static const unsigned char poly1305TV1Tag[16] = { 0xa6,0xf7,0x45,0x00,0x8f,0x81,
static const char *sha512TV0Input = "supercalifragilisticexpealidocious";
static const unsigned char sha512TV0Digest[64] = { 0x18,0x2a,0x85,0x59,0x69,0xe5,0xd3,0xe6,0xcb,0xf6,0x05,0x24,0xad,0xf2,0x88,0xd1,0xbb,0xf2,0x52,0x92,0x81,0x24,0x31,0xf6,0xd2,0x52,0xf1,0xdb,0xc1,0xcb,0x44,0xdf,0x21,0x57,0x3d,0xe1,0xb0,0x6b,0x68,0x75,0x95,0x9f,0x3b,0x6f,0x87,0xb1,0x13,0x81,0xd0,0xbc,0x79,0x2c,0x43,0x3a,0x13,0x55,0x3c,0xe0,0x84,0xc2,0x92,0x55,0x31,0x1c };
static const unsigned char sha384TV0Digest[48] = { 0x71,0xe7,0x71,0x79,0xae,0xc3,0xf3,0x5f,0x93,0xea,0xe2,0x1d,0xe3,0x3f,0x24,0x6d,0xed,0x2a,0x59,0xae,0x22,0x45,0x27,0x6c,0x12,0x57,0xf3,0xbe,0xe6,0xce,0xe2,0x73,0xd8,0xad,0xaa,0x9b,0x99,0xa4,0x8a,0x1b,0x7a,0xb9,0x5d,0xfb,0x9c,0x1a,0x1c,0xf6 };
struct C25519TestVector
{
@ -220,7 +221,7 @@ static int testCrypto()
bytes += 1234567.0;
}
uint64_t end = OSUtils::now();
SHA512::hash(buf1,bb,1234567);
SHA512(buf1,bb,1234567);
std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl;
::free((void *)bb);
}
@ -272,18 +273,25 @@ static int testCrypto()
bytes += 1234567.0;
}
uint64_t end = OSUtils::now();
SHA512::hash(buf1,bb,1234567);
SHA512(buf1,bb,1234567);
std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl;
::free((void *)bb);
}
std::cout << "[crypto] Testing SHA-512... "; std::cout.flush();
SHA512::hash(buf1,sha512TV0Input,(unsigned int)strlen(sha512TV0Input));
SHA512(buf1,sha512TV0Input,(unsigned int)strlen(sha512TV0Input));
if (memcmp(buf1,sha512TV0Digest,64)) {
std::cout << "FAIL" << std::endl;
return -1;
}
std::cout << "PASS" << std::endl;
std::cout << "[crypto] Testing SHA-384... "; std::cout.flush();
SHA384(buf1,sha512TV0Input,(unsigned int)strlen(sha512TV0Input));
if (memcmp(buf1,sha384TV0Digest,48)) {
std::cout << "FAIL" << std::endl;
return -1;
}
std::cout << "PASS" << std::endl;
std::cout << "[crypto] Testing Poly1305... "; std::cout.flush();
Poly1305::compute(buf1,poly1305TV0Input,sizeof(poly1305TV0Input),poly1305TV0Key);

View File

@ -127,7 +127,7 @@ void SoftwareUpdater::setUpdateDistribution(bool distribute)
const std::string metaHash(OSUtils::jsonBinFromHex(d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH]));
if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) {
std::array<uint8_t,ZT_SHA512_DIGEST_LEN> sha512;
SHA512::hash(sha512.data(),d.bin.data(),(unsigned int)d.bin.length());
SHA512(sha512.data(),d.bin.data(),(unsigned int)d.bin.length());
if (!memcmp(sha512.data(),metaHash.data(),ZT_SHA512_DIGEST_LEN)) { // double check that hash in JSON is correct
d.meta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_SIZE] = d.bin.length(); // override with correct value -- setting this in meta json is optional
std::array<uint8_t,16> shakey;
@ -347,7 +347,7 @@ bool SoftwareUpdater::check(const int64_t now)
try {
// (1) Check the hash itself to make sure the image is basically okay
uint8_t sha512[ZT_SHA512_DIGEST_LEN];
SHA512::hash(sha512,_download.data(),(unsigned int)_download.length());
SHA512(sha512,_download.data(),(unsigned int)_download.length());
char hexbuf[(ZT_SHA512_DIGEST_LEN * 2) + 2];
if (OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"") == Utils::hex(sha512,ZT_SHA512_DIGEST_LEN,hexbuf)) {
// (2) Check signature by signing authority