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]; for (i = 64;i < smlen;++i) playground[i] = sm[i];
//crypto_hash_sha512(hram,playground,smlen); //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]; unsigned char digest[64];
crypto_scalarmult(rawkey,mine.data,their.data); 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;) { for(unsigned int i=0,k=0;i<keylen;) {
if (k == 64) { if (k == 64) {
k = 0; k = 0;
SHA512::hash(digest,digest,64); SHA512(digest,digest,64);
} }
((unsigned char *)keybuf)[i++] = digest[k++]; ((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) 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) 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 #ifdef ZT_USE_FAST_X64_ED25519
ed25519_amd64_asm_sign(myPrivate.data + 32,myPublic.data + 32,digest,(unsigned char *)signature); 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 hram[crypto_hash_sha512_BYTES];
unsigned char *sig = (unsigned char *)signature; unsigned char *sig = (unsigned char *)signature;
SHA512::hash(extsk,myPrivate.data + 32,32); SHA512(extsk,myPrivate.data + 32,32);
extsk[0] &= 248; extsk[0] &= 248;
extsk[31] &= 127; extsk[31] &= 127;
extsk[31] |= 64; 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++) for(unsigned int i=0;i<32;i++)
sig[64 + i] = digest[i]; sig[64 + i] = digest[i];
SHA512::hash(hmg,sig + 32,64); SHA512(hmg,sig + 32,64);
/* Computation of R */ /* Computation of R */
sc25519_from64bytes(&sck, hmg); 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; const unsigned char *sig = (const unsigned char *)signature;
unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg) unsigned char digest[64]; // we sign the first 32 bytes of SHA-512(msg)
unsigned char sigtmp[96]; unsigned char sigtmp[96];
SHA512::hash(digest,msg,len); SHA512(digest,msg,len);
if ((siglen == 96)&&(!Utils::secureEq(sig+64,digest,32))) { if ((siglen == 96)&&(!Utils::secureEq(sig+64,digest,32))) {
return false; return false;
@ -2831,7 +2831,7 @@ void C25519::_calcPubED(C25519::Pair &kp)
// Second 32 bytes of pub and priv are the keys for ed25519 // Second 32 bytes of pub and priv are the keys for ed25519
// signing and verification. // signing and verification.
SHA512::hash(extsk,kp.priv.data + 32,32); SHA512(extsk,kp.priv.data + 32,32);
extsk[0] &= 248; extsk[0] &= 248;
extsk[31] &= 127; extsk[31] &= 127;
extsk[31] |= 64; 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) static inline void _computeMemoryHardHash(const void *publicKey,unsigned int publicKeyBytes,void *digest,void *genmem)
{ {
// Digest publicKey[] to obtain initial digest // 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 // Initialize genmem[] using Salsa20 in a CBC-like configuration since
// ordinary Salsa20 is randomly seek-able. This is good for a cipher // ordinary Salsa20 is randomly seek-able. This is good for a cipher
@ -123,7 +123,7 @@ void Identity::generate(const Type t)
do { do {
ECC384GenerateKey(_k.t1.pub,_k.t1.priv); ECC384GenerateKey(_k.t1.pub,_k.t1.priv);
// TODO // 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); _address.setTo(digest + 59,ZT_ADDRESS_LENGTH);
} while (_address.isReserved()); } while (_address.isReserved());
_type = P384; _type = P384;

View file

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

View file

@ -31,10 +31,15 @@
#include "Identity.hpp" #include "Identity.hpp"
#include "InetAddress.hpp" #include "InetAddress.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include "Buffer.hpp"
#include "SHA512.hpp"
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#define ZT_LOCATOR_MAX_PHYSICAL_ADDRESSES 255
#define ZT_LOCATOR_MAX_VIRTUAL_ADDRESSES 255
namespace ZeroTier { namespace ZeroTier {
/** /**
@ -48,22 +53,139 @@ namespace ZeroTier {
class Locator class Locator
{ {
public: public:
Locator() : Locator() : _signatureLength(0) {}
_signatureLength(0) {}
inline const std::vector<InetAddress> &phy() const { return _physical; } inline const std::vector<InetAddress> &phy() const { return _physical; }
inline const std::vector<Identity> &virt() const { return _virtual; } 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) inline bool sign(const Identity &signingId)
{ {
std::sort(_physical.begin(),_physical.end()); if (!signingId.hasPrivate())
std::sort(_virtual.begin(),_virtual.end()); return false;
_id = signingId; 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: private:
int64_t _ts; int64_t _ts;
Identity _id; Identity _id;
Identity _signedBy; // signed by _id if nil/zero
std::vector<InetAddress> _physical; std::vector<InetAddress> _physical;
std::vector<Identity> _virtual; std::vector<Identity> _virtual;
unsigned int _signatureLength; unsigned int _signatureLength;

View file

@ -14,17 +14,29 @@ Public domain.
#include "SHA512.hpp" #include "SHA512.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#if 0
#ifdef __APPLE__ #ifdef __APPLE__
#include <CommonCrypto/CommonDigest.h> #include <CommonCrypto/CommonDigest.h>
#define ZT_HAVE_NATIVE_SHA512 #define ZT_HAVE_NATIVE_SHA512
namespace ZeroTier { 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_CTX ctx;
CC_SHA512_Init(&ctx); CC_SHA512_Init(&ctx);
CC_SHA512_Update(&ctx,data,len); CC_SHA512_Update(&ctx,data,len);
CC_SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx); 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 #endif
@ -32,327 +44,221 @@ void SHA512::hash(void *digest,const void *data,unsigned int len)
#include <openssl/sha.h> #include <openssl/sha.h>
#define ZT_HAVE_NATIVE_SHA512 #define ZT_HAVE_NATIVE_SHA512
namespace ZeroTier { 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_CTX ctx;
SHA512_Init(&ctx); SHA512_Init(&ctx);
SHA512_Update(&ctx,data,len); SHA512_Update(&ctx,data,len);
SHA512_Final(reinterpret_cast<unsigned char *>(digest),&ctx); 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 #endif
#ifndef ZT_HAVE_NATIVE_SHA512 #ifndef ZT_HAVE_NATIVE_SHA512
namespace ZeroTier { namespace ZeroTier {
#define uint64 uint64_t namespace {
#ifdef ZT_NO_TYPE_PUNNING static inline void sha512_encode(uint64_t input, uint8_t *output, uint32_t idx)
static uint64 load_bigendian(const unsigned char *x)
{ {
return output[idx + 0] = (uint8_t)(input >> 56);
(uint64) (x[7]) \ output[idx + 1] = (uint8_t)(input >> 48);
| (((uint64) (x[6])) << 8) \ output[idx + 2] = (uint8_t)(input >> 40);
| (((uint64) (x[5])) << 16) \ output[idx + 3] = (uint8_t)(input >> 32);
| (((uint64) (x[4])) << 24) \ output[idx + 4] = (uint8_t)(input >> 24);
| (((uint64) (x[3])) << 32) \ output[idx + 5] = (uint8_t)(input >> 16);
| (((uint64) (x[2])) << 40) \ output[idx + 6] = (uint8_t)(input >> 8);
| (((uint64) (x[1])) << 48) \ output[idx + 7] = (uint8_t)(input >> 0);
| (((uint64) (x[0])) << 56)
;
} }
static inline void sha512_decode(uint64_t *output, uint8_t *input, uint32_t idx)
static void store_bigendian(unsigned char *x,uint64 u)
{ {
x[7] = u; u >>= 8; *output = ((uint64_t)input[idx + 0] << 56)
x[6] = u; u >>= 8; | ((uint64_t)input[idx + 1] << 48)
x[5] = u; u >>= 8; | ((uint64_t)input[idx + 2] << 40)
x[4] = u; u >>= 8; | ((uint64_t)input[idx + 3] << 32)
x[3] = u; u >>= 8; | ((uint64_t)input[idx + 4] << 24)
x[2] = u; u >>= 8; | ((uint64_t)input[idx + 5] << 16)
x[1] = u; u >>= 8; | ((uint64_t)input[idx + 6] << 8)
x[0] = u; | ((uint64_t)input[idx + 7] << 0);
} }
#else // !ZT_NO_TYPE_PUNNING 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;
#define load_bigendian(x) Utils::ntoh(*((const uint64_t *)(x))) #define LSR(x,n) (x >> n)
#define store_bigendian(x,u) (*((uint64_t *)(x)) = Utils::hton((u))) #define ROR(x,n) (LSR(x,n) | (x << (64 - n)))
#endif // ZT_NO_TYPE_PUNNING #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))
#define SHR(x,c) ((x) >> (c)) #define INIT_COMPRESSOR() uint64_t tmp0 = 0, tmp1 = 0
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) #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 Ch(x,y,z) ((x & y) ^ (~x & z)) 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 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; static const uint64_t K[80] = {
0x428A2F98D728AE22ULL, 0x7137449123EF65CDULL, 0xB5C0FBCFEC4D3B2FULL, 0xE9B5DBA58189DBBCULL,
#define EXPAND \ 0x3956C25BF348B538ULL, 0x59F111F1B605D019ULL, 0x923F82A4AF194F9BULL, 0xAB1C5ED5DA6D8118ULL,
M(w0 ,w14,w9 ,w1 ) \ 0xD807AA98A3030242ULL, 0x12835B0145706FBEULL, 0x243185BE4EE4B28CULL, 0x550C7DC3D5FFB4E2ULL,
M(w1 ,w15,w10,w2 ) \ 0x72BE5D74F27B896FULL, 0x80DEB1FE3B1696B1ULL, 0x9BDC06A725C71235ULL, 0xC19BF174CF692694ULL,
M(w2 ,w0 ,w11,w3 ) \ 0xE49B69C19EF14AD2ULL, 0xEFBE4786384F25E3ULL, 0x0FC19DC68B8CD5B5ULL, 0x240CA1CC77AC9C65ULL,
M(w3 ,w1 ,w12,w4 ) \ 0x2DE92C6F592B0275ULL, 0x4A7484AA6EA6E483ULL, 0x5CB0A9DCBD41FBD4ULL, 0x76F988DA831153B5ULL,
M(w4 ,w2 ,w13,w5 ) \ 0x983E5152EE66DFABULL, 0xA831C66D2DB43210ULL, 0xB00327C898FB213FULL, 0xBF597FC7BEEF0EE4ULL,
M(w5 ,w3 ,w14,w6 ) \ 0xC6E00BF33DA88FC2ULL, 0xD5A79147930AA725ULL, 0x06CA6351E003826FULL, 0x142929670A0E6E70ULL,
M(w6 ,w4 ,w15,w7 ) \ 0x27B70A8546D22FFCULL, 0x2E1B21385C26C926ULL, 0x4D2C6DFC5AC42AEDULL, 0x53380D139D95B3DFULL,
M(w7 ,w5 ,w0 ,w8 ) \ 0x650A73548BAF63DEULL, 0x766A0ABB3C77B2A8ULL, 0x81C2C92E47EDAEE6ULL, 0x92722C851482353BULL,
M(w8 ,w6 ,w1 ,w9 ) \ 0xA2BFE8A14CF10364ULL, 0xA81A664BBC423001ULL, 0xC24B8B70D0F89791ULL, 0xC76C51A30654BE30ULL,
M(w9 ,w7 ,w2 ,w10) \ 0xD192E819D6EF5218ULL, 0xD69906245565A910ULL, 0xF40E35855771202AULL, 0x106AA07032BBD1B8ULL,
M(w10,w8 ,w3 ,w11) \ 0x19A4C116B8D2D0C8ULL, 0x1E376C085141AB53ULL, 0x2748774CDF8EEB99ULL, 0x34B0BCB5E19B48A8ULL,
M(w11,w9 ,w4 ,w12) \ 0x391C0CB3C5C95A63ULL, 0x4ED8AA4AE3418ACBULL, 0x5B9CCA4F7763E373ULL, 0x682E6FF3D6B2B8A3ULL,
M(w12,w10,w5 ,w13) \ 0x748F82EE5DEFB2FCULL, 0x78A5636F43172F60ULL, 0x84C87814A1F0AB72ULL, 0x8CC702081A6439ECULL,
M(w13,w11,w6 ,w14) \ 0x90BEFFFA23631E28ULL, 0xA4506CEBDE82BDE9ULL, 0xBEF9A3F7B2C67915ULL, 0xC67178F2E372532BULL,
M(w14,w12,w7 ,w15) \ 0xCA273ECEEA26619CULL, 0xD186B8C721C0C207ULL, 0xEADA7DD6CDE0EB1EULL, 0xF57D4F7FEE6ED178ULL,
M(w15,w13,w8 ,w0 ) 0x06F067AA72176FBAULL, 0x0A637DC5A2C898A6ULL, 0x113F9804BEF90DAEULL, 0x1B710B35131C471BULL,
0x28DB77F523047D84ULL, 0x32CAAB7B40C72493ULL, 0x3C9EBE0A15C9BEBCULL, 0x431D67C49C100D4CULL,
#define F(w,k) \ 0x4CC5D4BECB3E42B6ULL, 0x597F299CFC657E2AULL, 0x5FCB6FAB3AD6FAECULL, 0x6C44198C4A475817ULL
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
}; };
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]; uint32_t i = 0;
unsigned char padded[256]; for (;i < size;i++) { *dst++ = *src++; }
int i; }
uint64_t bytes = len; static inline void sha512_memclr(uint8_t *dst, uint32_t size)
{
const unsigned char *in = (const unsigned char *)data; uint32_t i = 0;
unsigned int inlen = len; for (;i < size;i++) { *dst++ = 0; }
for (i = 0;i < 64;++i) h[i] = iv[i];
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);
} }
for (i = 0;i < 64;++i) ((unsigned char *)digest)[i] = h[i]; 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;
}
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;
}
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]; }
}
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 } // 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 // 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) 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 { namespace ZeroTier {
/** void SHA512(void *digest,const void *data,unsigned int len);
* SHA-512 digest algorithm
*/ void SHA384(void *digest,const void *data,unsigned int len);
class SHA512
{
public:
static void hash(void *digest,const void *data,unsigned int len);
};
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -242,8 +242,8 @@ public:
*/ */
static void getSecureRandom(void *buf,unsigned int bytes); static void getSecureRandom(void *buf,unsigned int bytes);
static int Utils::b32d(const char *encoded, uint8_t *result, int bufSize); static int 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 b32e(const uint8_t *data,int length,char *result,int bufSize);
/** /**
* Tokenize a string (alias for strtok_r or strtok_s depending on platform) * 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 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 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 struct C25519TestVector
{ {
@ -220,7 +221,7 @@ static int testCrypto()
bytes += 1234567.0; bytes += 1234567.0;
} }
uint64_t end = OSUtils::now(); 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; std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl;
::free((void *)bb); ::free((void *)bb);
} }
@ -272,18 +273,25 @@ static int testCrypto()
bytes += 1234567.0; bytes += 1234567.0;
} }
uint64_t end = OSUtils::now(); 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; std::cout << ((bytes / 1048576.0) / ((long double)(end - start) / 1024.0)) << " MiB/second (" << Utils::hex(buf1,16,hexbuf) << ')' << std::endl;
::free((void *)bb); ::free((void *)bb);
} }
std::cout << "[crypto] Testing SHA-512... "; std::cout.flush(); 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)) { if (memcmp(buf1,sha512TV0Digest,64)) {
std::cout << "FAIL" << std::endl; std::cout << "FAIL" << std::endl;
return -1; return -1;
} }
std::cout << "PASS" << std::endl; 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(); std::cout << "[crypto] Testing Poly1305... "; std::cout.flush();
Poly1305::compute(buf1,poly1305TV0Input,sizeof(poly1305TV0Input),poly1305TV0Key); 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])); 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))) { if ((metaHash.length() == ZT_SHA512_DIGEST_LEN)&&(OSUtils::readFile(binPath.c_str(),d.bin))) {
std::array<uint8_t,ZT_SHA512_DIGEST_LEN> sha512; 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 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 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; std::array<uint8_t,16> shakey;
@ -347,7 +347,7 @@ bool SoftwareUpdater::check(const int64_t now)
try { try {
// (1) Check the hash itself to make sure the image is basically okay // (1) Check the hash itself to make sure the image is basically okay
uint8_t sha512[ZT_SHA512_DIGEST_LEN]; 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]; 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)) { if (OSUtils::jsonString(_latestMeta[ZT_SOFTWARE_UPDATE_JSON_UPDATE_HASH],"") == Utils::hex(sha512,ZT_SHA512_DIGEST_LEN,hexbuf)) {
// (2) Check signature by signing authority // (2) Check signature by signing authority