7 changed files with 830 additions and 25 deletions
@ -0,0 +1,345 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet |
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "Utils.hpp" |
||||
#include "C25519.hpp" |
||||
#include "SHA512.hpp" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Code taken from NaCl by D. J. Bernstein and others
|
||||
|
||||
/*
|
||||
Matthew Dempsky |
||||
Public domain. |
||||
Derived from public domain code by D. J. Bernstein. |
||||
*/ |
||||
|
||||
static void add(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) |
||||
{ |
||||
unsigned int j; |
||||
unsigned int u; |
||||
u = 0; |
||||
for (j = 0;j < 31;++j) { u += a[j] + b[j]; out[j] = u & 255; u >>= 8; } |
||||
u += a[31] + b[31]; out[31] = u; |
||||
} |
||||
|
||||
static void sub(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) |
||||
{ |
||||
unsigned int j; |
||||
unsigned int u; |
||||
u = 218; |
||||
for (j = 0;j < 31;++j) { |
||||
u += a[j] + 65280 - b[j]; |
||||
out[j] = u & 255; |
||||
u >>= 8; |
||||
} |
||||
u += a[31] - b[31]; |
||||
out[31] = u; |
||||
} |
||||
|
||||
static void squeeze(unsigned int a[32]) |
||||
{ |
||||
unsigned int j; |
||||
unsigned int u; |
||||
u = 0; |
||||
for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } |
||||
u += a[31]; a[31] = u & 127; |
||||
u = 19 * (u >> 7); |
||||
for (j = 0;j < 31;++j) { u += a[j]; a[j] = u & 255; u >>= 8; } |
||||
u += a[31]; a[31] = u; |
||||
} |
||||
|
||||
static const unsigned int minusp[32] = { |
||||
19, 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, 128 |
||||
} ; |
||||
|
||||
static void freeze(unsigned int a[32]) |
||||
{ |
||||
unsigned int aorig[32]; |
||||
unsigned int j; |
||||
unsigned int negative; |
||||
|
||||
for (j = 0;j < 32;++j) aorig[j] = a[j]; |
||||
add(a,a,minusp); |
||||
negative = -((a[31] >> 7) & 1); |
||||
for (j = 0;j < 32;++j) a[j] ^= negative & (aorig[j] ^ a[j]); |
||||
} |
||||
|
||||
static void mult(unsigned int out[32],const unsigned int a[32],const unsigned int b[32]) |
||||
{ |
||||
unsigned int i; |
||||
unsigned int j; |
||||
unsigned int u; |
||||
|
||||
for (i = 0;i < 32;++i) { |
||||
u = 0; |
||||
for (j = 0;j <= i;++j) u += a[j] * b[i - j]; |
||||
for (j = i + 1;j < 32;++j) u += 38 * a[j] * b[i + 32 - j]; |
||||
out[i] = u; |
||||
} |
||||
squeeze(out); |
||||
} |
||||
|
||||
static void mult121665(unsigned int out[32],const unsigned int a[32]) |
||||
{ |
||||
unsigned int j; |
||||
unsigned int u; |
||||
|
||||
u = 0; |
||||
for (j = 0;j < 31;++j) { u += 121665 * a[j]; out[j] = u & 255; u >>= 8; } |
||||
u += 121665 * a[31]; out[31] = u & 127; |
||||
u = 19 * (u >> 7); |
||||
for (j = 0;j < 31;++j) { u += out[j]; out[j] = u & 255; u >>= 8; } |
||||
u += out[j]; out[j] = u; |
||||
} |
||||
|
||||
static void square(unsigned int out[32],const unsigned int a[32]) |
||||
{ |
||||
unsigned int i; |
||||
unsigned int j; |
||||
unsigned int u; |
||||
|
||||
for (i = 0;i < 32;++i) { |
||||
u = 0; |
||||
for (j = 0;j < i - j;++j) u += a[j] * a[i - j]; |
||||
for (j = i + 1;j < i + 32 - j;++j) u += 38 * a[j] * a[i + 32 - j]; |
||||
u *= 2; |
||||
if ((i & 1) == 0) { |
||||
u += a[i / 2] * a[i / 2]; |
||||
u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; |
||||
} |
||||
out[i] = u; |
||||
} |
||||
squeeze(out); |
||||
} |
||||
|
||||
static void select(unsigned int p[64],unsigned int q[64],const unsigned int r[64],const unsigned int s[64],unsigned int b) |
||||
{ |
||||
unsigned int j; |
||||
unsigned int t; |
||||
unsigned int bminus1; |
||||
|
||||
bminus1 = b - 1; |
||||
for (j = 0;j < 64;++j) { |
||||
t = bminus1 & (r[j] ^ s[j]); |
||||
p[j] = s[j] ^ t; |
||||
q[j] = r[j] ^ t; |
||||
} |
||||
} |
||||
|
||||
static void mainloop(unsigned int work[64],const unsigned char e[32]) |
||||
{ |
||||
unsigned int xzm1[64]; |
||||
unsigned int xzm[64]; |
||||
unsigned int xzmb[64]; |
||||
unsigned int xzm1b[64]; |
||||
unsigned int xznb[64]; |
||||
unsigned int xzn1b[64]; |
||||
unsigned int a0[64]; |
||||
unsigned int a1[64]; |
||||
unsigned int b0[64]; |
||||
unsigned int b1[64]; |
||||
unsigned int c1[64]; |
||||
unsigned int r[32]; |
||||
unsigned int s[32]; |
||||
unsigned int t[32]; |
||||
unsigned int u[32]; |
||||
//unsigned int i;
|
||||
unsigned int j; |
||||
unsigned int b; |
||||
int pos; |
||||
|
||||
for (j = 0;j < 32;++j) xzm1[j] = work[j]; |
||||
xzm1[32] = 1; |
||||
for (j = 33;j < 64;++j) xzm1[j] = 0; |
||||
|
||||
xzm[0] = 1; |
||||
for (j = 1;j < 64;++j) xzm[j] = 0; |
||||
|
||||
for (pos = 254;pos >= 0;--pos) { |
||||
b = e[pos / 8] >> (pos & 7); |
||||
b &= 1; |
||||
select(xzmb,xzm1b,xzm,xzm1,b); |
||||
add(a0,xzmb,xzmb + 32); |
||||
sub(a0 + 32,xzmb,xzmb + 32); |
||||
add(a1,xzm1b,xzm1b + 32); |
||||
sub(a1 + 32,xzm1b,xzm1b + 32); |
||||
square(b0,a0); |
||||
square(b0 + 32,a0 + 32); |
||||
mult(b1,a1,a0 + 32); |
||||
mult(b1 + 32,a1 + 32,a0); |
||||
add(c1,b1,b1 + 32); |
||||
sub(c1 + 32,b1,b1 + 32); |
||||
square(r,c1 + 32); |
||||
sub(s,b0,b0 + 32); |
||||
mult121665(t,s); |
||||
add(u,t,b0); |
||||
mult(xznb,b0,b0 + 32); |
||||
mult(xznb + 32,s,u); |
||||
square(xzn1b,c1); |
||||
mult(xzn1b + 32,r,work); |
||||
select(xzm,xzm1,xznb,xzn1b,b); |
||||
} |
||||
|
||||
for (j = 0;j < 64;++j) work[j] = xzm[j]; |
||||
} |
||||
|
||||
static void recip(unsigned int out[32],const unsigned int z[32]) |
||||
{ |
||||
unsigned int z2[32]; |
||||
unsigned int z9[32]; |
||||
unsigned int z11[32]; |
||||
unsigned int z2_5_0[32]; |
||||
unsigned int z2_10_0[32]; |
||||
unsigned int z2_20_0[32]; |
||||
unsigned int z2_50_0[32]; |
||||
unsigned int z2_100_0[32]; |
||||
unsigned int t0[32]; |
||||
unsigned int t1[32]; |
||||
int i; |
||||
|
||||
/* 2 */ square(z2,z); |
||||
/* 4 */ square(t1,z2); |
||||
/* 8 */ square(t0,t1); |
||||
/* 9 */ mult(z9,t0,z); |
||||
/* 11 */ mult(z11,z9,z2); |
||||
/* 22 */ square(t0,z11); |
||||
/* 2^5 - 2^0 = 31 */ mult(z2_5_0,t0,z9); |
||||
|
||||
/* 2^6 - 2^1 */ square(t0,z2_5_0); |
||||
/* 2^7 - 2^2 */ square(t1,t0); |
||||
/* 2^8 - 2^3 */ square(t0,t1); |
||||
/* 2^9 - 2^4 */ square(t1,t0); |
||||
/* 2^10 - 2^5 */ square(t0,t1); |
||||
/* 2^10 - 2^0 */ mult(z2_10_0,t0,z2_5_0); |
||||
|
||||
/* 2^11 - 2^1 */ square(t0,z2_10_0); |
||||
/* 2^12 - 2^2 */ square(t1,t0); |
||||
/* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t0,t1); square(t1,t0); } |
||||
/* 2^20 - 2^0 */ mult(z2_20_0,t1,z2_10_0); |
||||
|
||||
/* 2^21 - 2^1 */ square(t0,z2_20_0); |
||||
/* 2^22 - 2^2 */ square(t1,t0); |
||||
/* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { square(t0,t1); square(t1,t0); } |
||||
/* 2^40 - 2^0 */ mult(t0,t1,z2_20_0); |
||||
|
||||
/* 2^41 - 2^1 */ square(t1,t0); |
||||
/* 2^42 - 2^2 */ square(t0,t1); |
||||
/* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { square(t1,t0); square(t0,t1); } |
||||
/* 2^50 - 2^0 */ mult(z2_50_0,t0,z2_10_0); |
||||
|
||||
/* 2^51 - 2^1 */ square(t0,z2_50_0); |
||||
/* 2^52 - 2^2 */ square(t1,t0); |
||||
/* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } |
||||
/* 2^100 - 2^0 */ mult(z2_100_0,t1,z2_50_0); |
||||
|
||||
/* 2^101 - 2^1 */ square(t1,z2_100_0); |
||||
/* 2^102 - 2^2 */ square(t0,t1); |
||||
/* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { square(t1,t0); square(t0,t1); } |
||||
/* 2^200 - 2^0 */ mult(t1,t0,z2_100_0); |
||||
|
||||
/* 2^201 - 2^1 */ square(t0,t1); |
||||
/* 2^202 - 2^2 */ square(t1,t0); |
||||
/* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { square(t0,t1); square(t1,t0); } |
||||
/* 2^250 - 2^0 */ mult(t0,t1,z2_50_0); |
||||
|
||||
/* 2^251 - 2^1 */ square(t1,t0); |
||||
/* 2^252 - 2^2 */ square(t0,t1); |
||||
/* 2^253 - 2^3 */ square(t1,t0); |
||||
/* 2^254 - 2^4 */ square(t0,t1); |
||||
/* 2^255 - 2^5 */ square(t1,t0); |
||||
/* 2^255 - 21 */ mult(out,t1,z11); |
||||
} |
||||
|
||||
static int crypto_scalarmult(unsigned char *q, |
||||
const unsigned char *n, |
||||
const unsigned char *p) |
||||
{ |
||||
unsigned int work[96]; |
||||
unsigned char e[32]; |
||||
unsigned int i; |
||||
for (i = 0;i < 32;++i) e[i] = n[i]; |
||||
e[0] &= 248; |
||||
e[31] &= 127; |
||||
e[31] |= 64; |
||||
for (i = 0;i < 32;++i) work[i] = p[i]; |
||||
mainloop(work,e); |
||||
recip(work + 32,work + 32); |
||||
mult(work + 64,work,work + 32); |
||||
freeze(work + 64); |
||||
for (i = 0;i < 32;++i) q[i] = work[64 + i]; |
||||
return 0; |
||||
} |
||||
|
||||
static const unsigned char base[32] = {9}; |
||||
|
||||
static int crypto_scalarmult_base(unsigned char *q, |
||||
const unsigned char *n) |
||||
{ |
||||
return crypto_scalarmult(q,n,base); |
||||
} |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
C25519::Pair C25519::generate() |
||||
{ |
||||
Pair kp; |
||||
Utils::getSecureRandom(kp.priv.data,kp.priv.size()); |
||||
|
||||
// First 32 bytes of pub and priv are the keys for C25519 key
|
||||
// agreement. This generates the public portion from the private.
|
||||
crypto_scalarmult_base(kp.pub.data,kp.priv.data); |
||||
|
||||
return kp; |
||||
} |
||||
|
||||
void C25519::agree(const C25519::Pair &mine,const C25519::Public &their,void *keybuf,unsigned int keylen) |
||||
{ |
||||
unsigned char rawkey[32]; |
||||
unsigned char digest[64]; |
||||
|
||||
crypto_scalarmult(rawkey,mine.priv.data,their.data); |
||||
SHA512::hash(digest,rawkey,32); |
||||
for(unsigned int i=0,k=0;i<keylen;) { |
||||
if (k == 64) { |
||||
k = 0; |
||||
SHA512::hash(digest,digest,64); |
||||
} |
||||
((unsigned char *)keybuf)[i++] = digest[k++]; |
||||
} |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet |
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifndef _ZT_C25519_HPP |
||||
#define _ZT_C25519_HPP |
||||
|
||||
#include "Array.hpp" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
/**
|
||||
* C25519 elliptic curve key agreement and signing |
||||
*/ |
||||
class C25519 |
||||
{ |
||||
public: |
||||
typedef Array<unsigned char,64> Public; // crypto key, signing key
|
||||
typedef Array<unsigned char,96> Private; // crypto key, signing key (64 bytes)
|
||||
typedef struct { |
||||
Public pub; |
||||
Private priv; |
||||
} Pair; |
||||
|
||||
/**
|
||||
* Generate a C25519 elliptic curve key pair |
||||
*/ |
||||
static Pair generate(); |
||||
|
||||
/**
|
||||
* Perform C25519 ECC key agreement |
||||
* |
||||
* Actual key bytes are generated from one or more SHA-512 digests of |
||||
* the raw result of key agreement. |
||||
* |
||||
* @param mine My key pair including secret |
||||
* @param their Their public key |
||||
* @param keybuf Buffer to fill |
||||
* @param keylen Number of key bytes to generate |
||||
*/ |
||||
static void agree(const Pair &mine,const Public &their,void *keybuf,unsigned int keylen); |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif |
||||
@ -0,0 +1,351 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet |
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
#include "SHA512.hpp" |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Code taken from NaCl by D. J. Bernstein and others
|
||||
// Public domain
|
||||
|
||||
/*
|
||||
20080913 |
||||
D. J. Bernstein |
||||
Public domain. |
||||
*/ |
||||
|
||||
#define uint64 uint64_t |
||||
|
||||
static uint64 load_bigendian(const unsigned char *x) |
||||
{ |
||||
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) |
||||
; |
||||
} |
||||
|
||||
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; |
||||
} |
||||
|
||||
#define SHR(x,c) ((x) >> (c)) |
||||
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c)))) |
||||
|
||||
#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; |
||||
|
||||
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) |
||||
{ |
||||
unsigned char h[64]; |
||||
unsigned char padded[256]; |
||||
int i; |
||||
uint64_t bytes = len; |
||||
|
||||
const unsigned char *in = (const unsigned char *)data; |
||||
unsigned int inlen = len; |
||||
|
||||
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]; |
||||
} |
||||
|
||||
} // namespace ZeroTier
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* ZeroTier One - Global Peer to Peer Ethernet |
||||
* Copyright (C) 2012-2013 ZeroTier Networks LLC |
||||
* |
||||
* This program is free software: you can redistribute it and/or modify |
||||
* it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* This program is distributed in the hope that it will be useful, |
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* |
||||
* -- |
||||
* |
||||
* ZeroTier may be used and distributed under the terms of the GPLv3, which |
||||
* are available at: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
* |
||||
* If you would like to embed ZeroTier into a commercial application or |
||||
* redistribute it in a modified binary form, please contact ZeroTier Networks |
||||
* LLC. Start here: http://www.zerotier.com/
|
||||
*/ |
||||
|
||||
#ifndef _ZT_SHA512_HPP |
||||
#define _ZT_SHA512_HPP |
||||
|
||||
#define ZT_SHA512_DIGEST_LEN 64 |
||||
|
||||
namespace ZeroTier { |
||||
|
||||
/**
|
||||
* SHA-512 digest algorithm |
||||
*/ |
||||
class SHA512 |
||||
{ |
||||
public: |
||||
static void hash(void *digest,const void *data,unsigned int len); |
||||
}; |
||||
|
||||
} // namespace ZeroTier
|
||||
|
||||
#endif |
||||
Loading…
Reference in new issue