1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include "tweetnacl.h"
#include "tweetpwhash.h"
#define FOR(i, n) for (i = 0; i < n; ++i)
#define MIN(a,b) (((a)<(b))?(a):(b))
#define sv static void
#define HB crypto_hash_BYTES
#define BB crypto_hashblocks_BLOCKBYTES
#define SB crypto_pwhash_SALTBYTES
typedef unsigned char u8;
typedef unsigned long long u64;
sv ts64(u8 *x, u64 u)
{
int i;
for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
}
static const u8 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
};
typedef struct {
u8 h[HB];
u8 m[BB];
u64 n;
u64 l;
} ctx;
sv chi(ctx *c)
{
u64 i;
FOR(i, HB) c->h[i] = iv[i];
c->n = c->l = 0;
}
sv chu(ctx *c, const u8 *m, u64 n)
{
u64 i, t;
c->l += n;
while (n) {
t = MIN(n, BB - c->n);
FOR(i, t) c->m[c->n + i] = m[i];
c->n += t;
crypto_hashblocks(c->h, c->m, c->n);
c->n &= (BB - 1);
m += t;
n -= t;
}
}
sv chf(u8 *out, ctx *c)
{
u8 x[256];
u64 i, n = c->n;
FOR(i, 256) x[i] = 0;
FOR(i, n) x[i] = c->m[i];
x[n] = 128;
n = 256 - 128 * (n < 112);
x[n - 9] = c->l >> 61;
ts64(x + n - 8, c->l << 3);
crypto_hashblocks(c->h, x, n);
FOR(i, HB) out[i] = c->h[i];
}
sv prf(u8 *out, const u8 *m, u64 mln, const u8 *k, u64 kln)
{
ctx c;
u64 j;
u8 hk[HB], ik[BB], ok[BB], ih[HB];
if (kln > BB) {
chi(&c); chu(&c, k, kln); chf(hk, &c);
k = hk;
kln = HB;
}
FOR(j, BB) ik[j] = ok[j] = 0;
FOR(j, kln) ik[j] = ok[j] = k[j];
FOR(j, BB) ik[j] ^= 0x36;
FOR(j, BB) ok[j] ^= 0x5c;
chi(&c); chu(&c, ik, BB); chu(&c, m, mln); chf(ih, &c);
chi(&c); chu(&c, ok, BB); chu(&c, ih, HB); chf(out, &c);
}
int crypto_pwhash(u8 *out, u64 outln, const u8 *p, u64 pln, const u8 *s, u64 c)
{
u64 i, j, b, nb, bl, o;
u8 u[HB], t[HB], bs[SB + 4];
FOR(i, SB) bs[i] = s[i];
nb = (outln + HB - 1) / HB;
for (b = 1, o = 0; b <= nb; b++) {
bs[SB + 0] = (b >> 24) & 0xff;
bs[SB + 1] = (b >> 16) & 0xff;
bs[SB + 2] = (b >> 8) & 0xff;
bs[SB + 3] = b & 0xff;
prf(u, bs, SB + 4, p, pln);
FOR(i, HB) t[i] = u[i];
FOR(i, c - 1) {
prf(u, u, HB, p, pln);
FOR(j, HB) t[j] ^= u[j];
}
bl = MIN(HB, outln - o);
FOR(i, bl) out[o + i] = t[i];
o += bl;
}
return 0;
}
|