dualcone 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +116 -0
- data/ext/dualcone/dualcone.c +288 -0
- data/ext/dualcone/dualcone.h +49 -0
- data/ext/dualcone/extconf.rb +36 -0
- data/lib/dualcone.rb +4 -0
- data/lib/dualcone/version.rb +5 -0
- data/vendor/libhydrogen/LICENSE +18 -0
- data/vendor/libhydrogen/Makefile +61 -0
- data/vendor/libhydrogen/README.md +36 -0
- data/vendor/libhydrogen/hydrogen.c +18 -0
- data/vendor/libhydrogen/hydrogen.h +331 -0
- data/vendor/libhydrogen/impl/common.h +321 -0
- data/vendor/libhydrogen/impl/core.h +223 -0
- data/vendor/libhydrogen/impl/gimli-core.h +25 -0
- data/vendor/libhydrogen/impl/gimli-core/portable.h +39 -0
- data/vendor/libhydrogen/impl/gimli-core/sse2.h +100 -0
- data/vendor/libhydrogen/impl/hash.h +140 -0
- data/vendor/libhydrogen/impl/hydrogen_p.h +83 -0
- data/vendor/libhydrogen/impl/kdf.h +20 -0
- data/vendor/libhydrogen/impl/kx.h +535 -0
- data/vendor/libhydrogen/impl/pwhash.h +281 -0
- data/vendor/libhydrogen/impl/random.h +465 -0
- data/vendor/libhydrogen/impl/secretbox.h +236 -0
- data/vendor/libhydrogen/impl/sign.h +207 -0
- data/vendor/libhydrogen/impl/x25519.h +384 -0
- metadata +186 -0
@@ -0,0 +1,236 @@
|
|
1
|
+
#define hydro_secretbox_IVBYTES 20
|
2
|
+
#define hydro_secretbox_SIVBYTES 20
|
3
|
+
#define hydro_secretbox_MACBYTES 16
|
4
|
+
|
5
|
+
void
|
6
|
+
hydro_secretbox_keygen(uint8_t key[hydro_secretbox_KEYBYTES])
|
7
|
+
{
|
8
|
+
hydro_random_buf(key, hydro_secretbox_KEYBYTES);
|
9
|
+
}
|
10
|
+
|
11
|
+
static void
|
12
|
+
hydro_secretbox_xor_enc(uint8_t buf[gimli_BLOCKBYTES], uint8_t *out, const uint8_t *in,
|
13
|
+
size_t inlen)
|
14
|
+
{
|
15
|
+
size_t i;
|
16
|
+
size_t leftover;
|
17
|
+
|
18
|
+
for (i = 0; i < inlen / gimli_RATE; i++) {
|
19
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], buf, gimli_RATE);
|
20
|
+
memcpy(buf, &out[i * gimli_RATE], gimli_RATE);
|
21
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
22
|
+
}
|
23
|
+
leftover = inlen % gimli_RATE;
|
24
|
+
if (leftover != 0) {
|
25
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], buf, leftover);
|
26
|
+
mem_cpy(buf, &out[i * gimli_RATE], leftover);
|
27
|
+
}
|
28
|
+
gimli_pad_u8(buf, leftover, gimli_DOMAIN_AEAD);
|
29
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
30
|
+
}
|
31
|
+
|
32
|
+
static void
|
33
|
+
hydro_secretbox_xor_dec(uint8_t buf[gimli_BLOCKBYTES], uint8_t *out, const uint8_t *in,
|
34
|
+
size_t inlen)
|
35
|
+
{
|
36
|
+
size_t i;
|
37
|
+
size_t leftover;
|
38
|
+
|
39
|
+
for (i = 0; i < inlen / gimli_RATE; i++) {
|
40
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], buf, gimli_RATE);
|
41
|
+
memcpy(buf, &in[i * gimli_RATE], gimli_RATE);
|
42
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
43
|
+
}
|
44
|
+
leftover = inlen % gimli_RATE;
|
45
|
+
if (leftover != 0) {
|
46
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], buf, leftover);
|
47
|
+
mem_cpy(buf, &in[i * gimli_RATE], leftover);
|
48
|
+
}
|
49
|
+
gimli_pad_u8(buf, leftover, gimli_DOMAIN_AEAD);
|
50
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
51
|
+
}
|
52
|
+
|
53
|
+
static void
|
54
|
+
hydro_secretbox_setup(uint8_t buf[gimli_BLOCKBYTES], uint64_t msg_id,
|
55
|
+
const char ctx[hydro_secretbox_CONTEXTBYTES],
|
56
|
+
const uint8_t key[hydro_secretbox_KEYBYTES],
|
57
|
+
const uint8_t iv[hydro_secretbox_IVBYTES], uint8_t key_tag)
|
58
|
+
{
|
59
|
+
static const uint8_t prefix[] = { 6, 's', 'b', 'x', '2', '5', '6', 8 };
|
60
|
+
uint8_t msg_id_le[8];
|
61
|
+
|
62
|
+
mem_zero(buf, gimli_BLOCKBYTES);
|
63
|
+
COMPILER_ASSERT(hydro_secretbox_CONTEXTBYTES == 8);
|
64
|
+
COMPILER_ASSERT(sizeof prefix + hydro_secretbox_CONTEXTBYTES <= gimli_RATE);
|
65
|
+
memcpy(buf, prefix, sizeof prefix);
|
66
|
+
memcpy(buf + sizeof prefix, ctx, hydro_secretbox_CONTEXTBYTES);
|
67
|
+
COMPILER_ASSERT(sizeof prefix + hydro_secretbox_CONTEXTBYTES == gimli_RATE);
|
68
|
+
gimli_core_u8(buf, gimli_TAG_HEADER);
|
69
|
+
|
70
|
+
COMPILER_ASSERT(hydro_secretbox_KEYBYTES == 2 * gimli_RATE);
|
71
|
+
mem_xor(buf, key, gimli_RATE);
|
72
|
+
gimli_core_u8(buf, key_tag);
|
73
|
+
mem_xor(buf, key + gimli_RATE, gimli_RATE);
|
74
|
+
gimli_core_u8(buf, key_tag);
|
75
|
+
|
76
|
+
COMPILER_ASSERT(hydro_secretbox_IVBYTES < gimli_RATE * 2);
|
77
|
+
buf[0] ^= hydro_secretbox_IVBYTES;
|
78
|
+
mem_xor(&buf[1], iv, gimli_RATE - 1);
|
79
|
+
gimli_core_u8(buf, gimli_TAG_HEADER);
|
80
|
+
mem_xor(buf, iv + gimli_RATE - 1, hydro_secretbox_IVBYTES - (gimli_RATE - 1));
|
81
|
+
STORE64_LE(msg_id_le, msg_id);
|
82
|
+
COMPILER_ASSERT(hydro_secretbox_IVBYTES - gimli_RATE + 8 <= gimli_RATE);
|
83
|
+
mem_xor(buf + hydro_secretbox_IVBYTES - gimli_RATE, msg_id_le, 8);
|
84
|
+
gimli_core_u8(buf, gimli_TAG_HEADER);
|
85
|
+
}
|
86
|
+
|
87
|
+
static void
|
88
|
+
hydro_secretbox_final(uint8_t *buf, const uint8_t key[hydro_secretbox_KEYBYTES], uint8_t tag)
|
89
|
+
{
|
90
|
+
COMPILER_ASSERT(hydro_secretbox_KEYBYTES == gimli_CAPACITY);
|
91
|
+
mem_xor(buf + gimli_RATE, key, hydro_secretbox_KEYBYTES);
|
92
|
+
gimli_core_u8(buf, tag);
|
93
|
+
mem_xor(buf + gimli_RATE, key, hydro_secretbox_KEYBYTES);
|
94
|
+
gimli_core_u8(buf, tag);
|
95
|
+
}
|
96
|
+
|
97
|
+
static int
|
98
|
+
hydro_secretbox_encrypt_iv(uint8_t *c, const void *m_, size_t mlen, uint64_t msg_id,
|
99
|
+
const char ctx[hydro_secretbox_CONTEXTBYTES],
|
100
|
+
const uint8_t key[hydro_secretbox_KEYBYTES],
|
101
|
+
const uint8_t iv[hydro_secretbox_IVBYTES])
|
102
|
+
{
|
103
|
+
_hydro_attr_aligned_(16) uint32_t state[gimli_BLOCKBYTES / 4];
|
104
|
+
uint8_t * buf = (uint8_t *) (void *) state;
|
105
|
+
const uint8_t * m = (const uint8_t *) m_;
|
106
|
+
uint8_t * siv = &c[0];
|
107
|
+
uint8_t * mac = &c[hydro_secretbox_SIVBYTES];
|
108
|
+
uint8_t * ct = &c[hydro_secretbox_SIVBYTES + hydro_secretbox_MACBYTES];
|
109
|
+
size_t i;
|
110
|
+
size_t leftover;
|
111
|
+
|
112
|
+
if (c == m) {
|
113
|
+
memmove(c + hydro_secretbox_HEADERBYTES, m, mlen);
|
114
|
+
m = c + hydro_secretbox_HEADERBYTES;
|
115
|
+
}
|
116
|
+
|
117
|
+
/* first pass: compute the SIV */
|
118
|
+
|
119
|
+
hydro_secretbox_setup(buf, msg_id, ctx, key, iv, gimli_TAG_KEY0);
|
120
|
+
for (i = 0; i < mlen / gimli_RATE; i++) {
|
121
|
+
mem_xor(buf, &m[i * gimli_RATE], gimli_RATE);
|
122
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
123
|
+
}
|
124
|
+
leftover = mlen % gimli_RATE;
|
125
|
+
if (leftover != 0) {
|
126
|
+
mem_xor(buf, &m[i * gimli_RATE], leftover);
|
127
|
+
}
|
128
|
+
gimli_pad_u8(buf, leftover, gimli_DOMAIN_XOF);
|
129
|
+
gimli_core_u8(buf, gimli_TAG_PAYLOAD);
|
130
|
+
|
131
|
+
hydro_secretbox_final(buf, key, gimli_TAG_FINAL0);
|
132
|
+
COMPILER_ASSERT(hydro_secretbox_SIVBYTES <= gimli_CAPACITY);
|
133
|
+
memcpy(siv, buf + gimli_RATE, hydro_secretbox_SIVBYTES);
|
134
|
+
|
135
|
+
/* second pass: encrypt the message, mix the key, squeeze an extra block for
|
136
|
+
* the MAC */
|
137
|
+
|
138
|
+
COMPILER_ASSERT(hydro_secretbox_SIVBYTES == hydro_secretbox_IVBYTES);
|
139
|
+
hydro_secretbox_setup(buf, msg_id, ctx, key, siv, gimli_TAG_KEY);
|
140
|
+
hydro_secretbox_xor_enc(buf, ct, m, mlen);
|
141
|
+
|
142
|
+
hydro_secretbox_final(buf, key, gimli_TAG_FINAL);
|
143
|
+
COMPILER_ASSERT(hydro_secretbox_MACBYTES <= gimli_CAPACITY);
|
144
|
+
memcpy(mac, buf + gimli_RATE, hydro_secretbox_MACBYTES);
|
145
|
+
|
146
|
+
return 0;
|
147
|
+
}
|
148
|
+
|
149
|
+
void
|
150
|
+
hydro_secretbox_probe_create(uint8_t probe[hydro_secretbox_PROBEBYTES], const uint8_t *c,
|
151
|
+
size_t c_len, const char ctx[hydro_secretbox_CONTEXTBYTES],
|
152
|
+
const uint8_t key[hydro_secretbox_KEYBYTES])
|
153
|
+
{
|
154
|
+
const uint8_t *mac;
|
155
|
+
|
156
|
+
if (c_len < hydro_secretbox_HEADERBYTES) {
|
157
|
+
abort();
|
158
|
+
}
|
159
|
+
mac = &c[hydro_secretbox_SIVBYTES];
|
160
|
+
COMPILER_ASSERT(hydro_secretbox_CONTEXTBYTES >= hydro_hash_CONTEXTBYTES);
|
161
|
+
COMPILER_ASSERT(hydro_secretbox_KEYBYTES >= hydro_hash_KEYBYTES);
|
162
|
+
hydro_hash_hash(probe, hydro_secretbox_PROBEBYTES, mac, hydro_secretbox_MACBYTES, ctx, key);
|
163
|
+
}
|
164
|
+
|
165
|
+
int
|
166
|
+
hydro_secretbox_probe_verify(const uint8_t probe[hydro_secretbox_PROBEBYTES], const uint8_t *c,
|
167
|
+
size_t c_len, const char ctx[hydro_secretbox_CONTEXTBYTES],
|
168
|
+
const uint8_t key[hydro_secretbox_KEYBYTES])
|
169
|
+
{
|
170
|
+
uint8_t computed_probe[hydro_secretbox_PROBEBYTES];
|
171
|
+
const uint8_t *mac;
|
172
|
+
|
173
|
+
if (c_len < hydro_secretbox_HEADERBYTES) {
|
174
|
+
return -1;
|
175
|
+
}
|
176
|
+
mac = &c[hydro_secretbox_SIVBYTES];
|
177
|
+
hydro_hash_hash(computed_probe, hydro_secretbox_PROBEBYTES, mac, hydro_secretbox_MACBYTES, ctx,
|
178
|
+
key);
|
179
|
+
if (hydro_equal(computed_probe, probe, hydro_secretbox_PROBEBYTES) == 1) {
|
180
|
+
return 0;
|
181
|
+
}
|
182
|
+
hydro_memzero(computed_probe, hydro_secretbox_PROBEBYTES);
|
183
|
+
return -1;
|
184
|
+
}
|
185
|
+
|
186
|
+
int
|
187
|
+
hydro_secretbox_encrypt(uint8_t *c, const void *m_, size_t mlen, uint64_t msg_id,
|
188
|
+
const char ctx[hydro_secretbox_CONTEXTBYTES],
|
189
|
+
const uint8_t key[hydro_secretbox_KEYBYTES])
|
190
|
+
{
|
191
|
+
uint8_t iv[hydro_secretbox_IVBYTES];
|
192
|
+
|
193
|
+
hydro_random_buf(iv, sizeof iv);
|
194
|
+
|
195
|
+
return hydro_secretbox_encrypt_iv(c, m_, mlen, msg_id, ctx, key, iv);
|
196
|
+
}
|
197
|
+
|
198
|
+
int
|
199
|
+
hydro_secretbox_decrypt(void *m_, const uint8_t *c, size_t clen, uint64_t msg_id,
|
200
|
+
const char ctx[hydro_secretbox_CONTEXTBYTES],
|
201
|
+
const uint8_t key[hydro_secretbox_KEYBYTES])
|
202
|
+
{
|
203
|
+
_hydro_attr_aligned_(16) uint32_t state[gimli_BLOCKBYTES / 4];
|
204
|
+
uint32_t pub_mac[hydro_secretbox_MACBYTES / 4];
|
205
|
+
uint8_t * buf = (uint8_t *) (void *) state;
|
206
|
+
const uint8_t * siv;
|
207
|
+
const uint8_t * mac;
|
208
|
+
const uint8_t * ct;
|
209
|
+
uint8_t * m = (uint8_t *) m_;
|
210
|
+
size_t mlen;
|
211
|
+
uint32_t cv;
|
212
|
+
|
213
|
+
if (clen < hydro_secretbox_HEADERBYTES) {
|
214
|
+
return -1;
|
215
|
+
}
|
216
|
+
siv = &c[0];
|
217
|
+
mac = &c[hydro_secretbox_SIVBYTES];
|
218
|
+
ct = &c[hydro_secretbox_SIVBYTES + hydro_secretbox_MACBYTES];
|
219
|
+
|
220
|
+
mlen = clen - hydro_secretbox_HEADERBYTES;
|
221
|
+
memcpy(pub_mac, mac, sizeof pub_mac);
|
222
|
+
COMPILER_ASSERT(hydro_secretbox_SIVBYTES == hydro_secretbox_IVBYTES);
|
223
|
+
hydro_secretbox_setup(buf, msg_id, ctx, key, siv, gimli_TAG_KEY);
|
224
|
+
hydro_secretbox_xor_dec(buf, m, ct, mlen);
|
225
|
+
|
226
|
+
hydro_secretbox_final(buf, key, gimli_TAG_FINAL);
|
227
|
+
COMPILER_ASSERT(hydro_secretbox_MACBYTES <= gimli_CAPACITY);
|
228
|
+
COMPILER_ASSERT(gimli_RATE % 4 == 0);
|
229
|
+
cv = hydro_mem_ct_cmp_u32(state + gimli_RATE / 4, pub_mac, hydro_secretbox_MACBYTES / 4);
|
230
|
+
hydro_mem_ct_zero_u32(state, gimli_BLOCKBYTES / 4);
|
231
|
+
if (cv != 0) {
|
232
|
+
mem_zero(m, mlen);
|
233
|
+
return -1;
|
234
|
+
}
|
235
|
+
return 0;
|
236
|
+
}
|
@@ -0,0 +1,207 @@
|
|
1
|
+
#define hydro_sign_CHALLENGEBYTES 32
|
2
|
+
#define hydro_sign_NONCEBYTES 32
|
3
|
+
#define hydro_sign_PREHASHBYTES 64
|
4
|
+
|
5
|
+
static void
|
6
|
+
hydro_sign_p2(uint8_t sig[hydro_x25519_BYTES], const uint8_t challenge[hydro_sign_CHALLENGEBYTES],
|
7
|
+
const uint8_t eph_sk[hydro_x25519_BYTES], const uint8_t sk[hydro_x25519_BYTES])
|
8
|
+
{
|
9
|
+
hydro_x25519_scalar_t scalar1, scalar2, scalar3;
|
10
|
+
|
11
|
+
COMPILER_ASSERT(hydro_sign_CHALLENGEBYTES == hydro_x25519_BYTES);
|
12
|
+
hydro_x25519_swapin(scalar1, eph_sk);
|
13
|
+
hydro_x25519_swapin(scalar2, sk);
|
14
|
+
hydro_x25519_swapin(scalar3, challenge);
|
15
|
+
hydro_x25519_sc_montmul(scalar1, scalar2, scalar3);
|
16
|
+
mem_zero(scalar2, sizeof scalar2);
|
17
|
+
hydro_x25519_sc_montmul(scalar2, scalar1, hydro_x25519_sc_r2);
|
18
|
+
hydro_x25519_swapout(sig, scalar2);
|
19
|
+
}
|
20
|
+
|
21
|
+
static void
|
22
|
+
hydro_sign_challenge(uint8_t challenge[hydro_sign_CHALLENGEBYTES],
|
23
|
+
const uint8_t nonce[hydro_sign_NONCEBYTES],
|
24
|
+
const uint8_t pk[hydro_sign_PUBLICKEYBYTES],
|
25
|
+
const uint8_t prehash[hydro_sign_PREHASHBYTES])
|
26
|
+
{
|
27
|
+
hydro_hash_state st;
|
28
|
+
|
29
|
+
hydro_hash_init(&st, (const char *) zero, NULL);
|
30
|
+
hydro_hash_update(&st, nonce, hydro_sign_NONCEBYTES);
|
31
|
+
hydro_hash_update(&st, pk, hydro_sign_PUBLICKEYBYTES);
|
32
|
+
hydro_hash_update(&st, prehash, hydro_sign_PREHASHBYTES);
|
33
|
+
hydro_hash_final(&st, challenge, hydro_sign_CHALLENGEBYTES);
|
34
|
+
}
|
35
|
+
|
36
|
+
static int
|
37
|
+
hydro_sign_prehash(uint8_t csig[hydro_sign_BYTES], const uint8_t prehash[hydro_sign_PREHASHBYTES],
|
38
|
+
const uint8_t sk[hydro_sign_SECRETKEYBYTES])
|
39
|
+
{
|
40
|
+
hydro_hash_state st;
|
41
|
+
uint8_t challenge[hydro_sign_CHALLENGEBYTES];
|
42
|
+
const uint8_t * pk = &sk[hydro_x25519_SECRETKEYBYTES];
|
43
|
+
uint8_t * nonce = &csig[0];
|
44
|
+
uint8_t * sig = &csig[hydro_sign_NONCEBYTES];
|
45
|
+
uint8_t * eph_sk = sig;
|
46
|
+
|
47
|
+
hydro_random_buf(eph_sk, hydro_x25519_SECRETKEYBYTES);
|
48
|
+
COMPILER_ASSERT(hydro_x25519_SECRETKEYBYTES == hydro_hash_KEYBYTES);
|
49
|
+
hydro_hash_init(&st, (const char *) zero, sk);
|
50
|
+
hydro_hash_update(&st, eph_sk, hydro_x25519_SECRETKEYBYTES);
|
51
|
+
hydro_hash_update(&st, prehash, hydro_sign_PREHASHBYTES);
|
52
|
+
hydro_hash_final(&st, eph_sk, hydro_x25519_SECRETKEYBYTES);
|
53
|
+
|
54
|
+
hydro_x25519_scalarmult_base_uniform(nonce, eph_sk);
|
55
|
+
hydro_sign_challenge(challenge, nonce, pk, prehash);
|
56
|
+
|
57
|
+
COMPILER_ASSERT(hydro_sign_BYTES == hydro_sign_NONCEBYTES + hydro_x25519_SECRETKEYBYTES);
|
58
|
+
COMPILER_ASSERT(hydro_x25519_SECRETKEYBYTES <= hydro_sign_CHALLENGEBYTES);
|
59
|
+
hydro_sign_p2(sig, challenge, eph_sk, sk);
|
60
|
+
|
61
|
+
return 0;
|
62
|
+
}
|
63
|
+
|
64
|
+
static int
|
65
|
+
hydro_sign_verify_core(hydro_x25519_fe xs[5], const hydro_x25519_limb_t *other1,
|
66
|
+
const uint8_t other2[hydro_x25519_BYTES])
|
67
|
+
{
|
68
|
+
hydro_x25519_limb_t * z2 = xs[1], *x3 = xs[2], *z3 = xs[3];
|
69
|
+
hydro_x25519_fe xo2;
|
70
|
+
const hydro_x25519_limb_t sixteen = 16;
|
71
|
+
|
72
|
+
hydro_x25519_swapin(xo2, other2);
|
73
|
+
memcpy(x3, other1, 2 * sizeof(hydro_x25519_fe));
|
74
|
+
hydro_x25519_ladder_part1(xs);
|
75
|
+
|
76
|
+
/* Here z2 = t2^2 */
|
77
|
+
hydro_x25519_mul1(z2, other1);
|
78
|
+
hydro_x25519_mul1(z2, other1 + hydro_x25519_NLIMBS);
|
79
|
+
hydro_x25519_mul1(z2, xo2);
|
80
|
+
|
81
|
+
hydro_x25519_mul(z2, z2, &sixteen, 1);
|
82
|
+
|
83
|
+
hydro_x25519_mul1(z3, xo2);
|
84
|
+
hydro_x25519_sub(z3, z3, x3);
|
85
|
+
hydro_x25519_sqr1(z3);
|
86
|
+
|
87
|
+
/* check equality */
|
88
|
+
hydro_x25519_sub(z3, z3, z2);
|
89
|
+
|
90
|
+
/* canon(z2): both sides are zero. canon(z3): the two sides are equal. */
|
91
|
+
/* Reject sigs where both sides are zero. */
|
92
|
+
return hydro_x25519_canon(z2) | ~hydro_x25519_canon(z3);
|
93
|
+
}
|
94
|
+
|
95
|
+
static int
|
96
|
+
hydro_sign_verify_p2(const uint8_t sig[hydro_x25519_BYTES],
|
97
|
+
const uint8_t challenge[hydro_sign_CHALLENGEBYTES],
|
98
|
+
const uint8_t nonce[hydro_sign_NONCEBYTES],
|
99
|
+
const uint8_t pk[hydro_x25519_BYTES])
|
100
|
+
{
|
101
|
+
hydro_x25519_fe xs[7];
|
102
|
+
|
103
|
+
hydro_x25519_core(&xs[0], challenge, pk, 0);
|
104
|
+
hydro_x25519_core(&xs[2], sig, hydro_x25519_BASE_POINT, 0);
|
105
|
+
|
106
|
+
return hydro_sign_verify_core(&xs[2], xs[0], nonce);
|
107
|
+
}
|
108
|
+
|
109
|
+
static int
|
110
|
+
hydro_sign_verify_challenge(const uint8_t csig[hydro_sign_BYTES],
|
111
|
+
const uint8_t challenge[hydro_sign_CHALLENGEBYTES],
|
112
|
+
const uint8_t pk[hydro_sign_PUBLICKEYBYTES])
|
113
|
+
{
|
114
|
+
const uint8_t *nonce = &csig[0];
|
115
|
+
const uint8_t *sig = &csig[hydro_sign_NONCEBYTES];
|
116
|
+
|
117
|
+
return hydro_sign_verify_p2(sig, challenge, nonce, pk);
|
118
|
+
}
|
119
|
+
|
120
|
+
void
|
121
|
+
hydro_sign_keygen(hydro_sign_keypair *kp)
|
122
|
+
{
|
123
|
+
uint8_t *pk_copy = &kp->sk[hydro_x25519_SECRETKEYBYTES];
|
124
|
+
|
125
|
+
COMPILER_ASSERT(hydro_sign_SECRETKEYBYTES ==
|
126
|
+
hydro_x25519_SECRETKEYBYTES + hydro_x25519_PUBLICKEYBYTES);
|
127
|
+
COMPILER_ASSERT(hydro_sign_PUBLICKEYBYTES == hydro_x25519_PUBLICKEYBYTES);
|
128
|
+
hydro_random_buf(kp->sk, hydro_x25519_SECRETKEYBYTES);
|
129
|
+
hydro_x25519_scalarmult_base_uniform(kp->pk, kp->sk);
|
130
|
+
memcpy(pk_copy, kp->pk, hydro_x25519_PUBLICKEYBYTES);
|
131
|
+
}
|
132
|
+
|
133
|
+
void
|
134
|
+
hydro_sign_keygen_deterministic(hydro_sign_keypair *kp, const uint8_t seed[hydro_sign_SEEDBYTES])
|
135
|
+
{
|
136
|
+
uint8_t *pk_copy = &kp->sk[hydro_x25519_SECRETKEYBYTES];
|
137
|
+
|
138
|
+
COMPILER_ASSERT(hydro_sign_SEEDBYTES >= hydro_random_SEEDBYTES);
|
139
|
+
hydro_random_buf_deterministic(kp->sk, hydro_x25519_SECRETKEYBYTES, seed);
|
140
|
+
hydro_x25519_scalarmult_base_uniform(kp->pk, kp->sk);
|
141
|
+
memcpy(pk_copy, kp->pk, hydro_x25519_PUBLICKEYBYTES);
|
142
|
+
}
|
143
|
+
|
144
|
+
int
|
145
|
+
hydro_sign_init(hydro_sign_state *state, const char ctx[hydro_sign_CONTEXTBYTES])
|
146
|
+
{
|
147
|
+
return hydro_hash_init(&state->hash_st, ctx, NULL);
|
148
|
+
}
|
149
|
+
|
150
|
+
int
|
151
|
+
hydro_sign_update(hydro_sign_state *state, const void *m_, size_t mlen)
|
152
|
+
{
|
153
|
+
return hydro_hash_update(&state->hash_st, m_, mlen);
|
154
|
+
}
|
155
|
+
|
156
|
+
int
|
157
|
+
hydro_sign_final_create(hydro_sign_state *state, uint8_t csig[hydro_sign_BYTES],
|
158
|
+
const uint8_t sk[hydro_sign_SECRETKEYBYTES])
|
159
|
+
{
|
160
|
+
uint8_t prehash[hydro_sign_PREHASHBYTES];
|
161
|
+
|
162
|
+
hydro_hash_final(&state->hash_st, prehash, sizeof prehash);
|
163
|
+
|
164
|
+
return hydro_sign_prehash(csig, prehash, sk);
|
165
|
+
}
|
166
|
+
|
167
|
+
int
|
168
|
+
hydro_sign_final_verify(hydro_sign_state *state, const uint8_t csig[hydro_sign_BYTES],
|
169
|
+
const uint8_t pk[hydro_sign_PUBLICKEYBYTES])
|
170
|
+
{
|
171
|
+
uint8_t challenge[hydro_sign_CHALLENGEBYTES];
|
172
|
+
uint8_t prehash[hydro_sign_PREHASHBYTES];
|
173
|
+
const uint8_t *nonce = &csig[0];
|
174
|
+
|
175
|
+
hydro_hash_final(&state->hash_st, prehash, sizeof prehash);
|
176
|
+
hydro_sign_challenge(challenge, nonce, pk, prehash);
|
177
|
+
|
178
|
+
return hydro_sign_verify_challenge(csig, challenge, pk);
|
179
|
+
}
|
180
|
+
|
181
|
+
int
|
182
|
+
hydro_sign_create(uint8_t csig[hydro_sign_BYTES], const void *m_, size_t mlen,
|
183
|
+
const char ctx[hydro_sign_CONTEXTBYTES],
|
184
|
+
const uint8_t sk[hydro_sign_SECRETKEYBYTES])
|
185
|
+
{
|
186
|
+
hydro_sign_state st;
|
187
|
+
|
188
|
+
if (hydro_sign_init(&st, ctx) != 0 || hydro_sign_update(&st, m_, mlen) != 0 ||
|
189
|
+
hydro_sign_final_create(&st, csig, sk) != 0) {
|
190
|
+
return -1;
|
191
|
+
}
|
192
|
+
return 0;
|
193
|
+
}
|
194
|
+
|
195
|
+
int
|
196
|
+
hydro_sign_verify(const uint8_t csig[hydro_sign_BYTES], const void *m_, size_t mlen,
|
197
|
+
const char ctx[hydro_sign_CONTEXTBYTES],
|
198
|
+
const uint8_t pk[hydro_sign_PUBLICKEYBYTES])
|
199
|
+
{
|
200
|
+
hydro_sign_state st;
|
201
|
+
|
202
|
+
if (hydro_sign_init(&st, ctx) != 0 || hydro_sign_update(&st, m_, mlen) != 0 ||
|
203
|
+
hydro_sign_final_verify(&st, csig, pk) != 0) {
|
204
|
+
return -1;
|
205
|
+
}
|
206
|
+
return 0;
|
207
|
+
}
|
@@ -0,0 +1,384 @@
|
|
1
|
+
/*
|
2
|
+
* Based on Michael Hamburg's STROBE reference implementation.
|
3
|
+
* Copyright (c) 2015-2016 Cryptography Research, Inc.
|
4
|
+
* MIT License (MIT)
|
5
|
+
*/
|
6
|
+
|
7
|
+
#if defined(__GNUC__) && defined(__SIZEOF_INT128__)
|
8
|
+
#define hydro_x25519_WBITS 64
|
9
|
+
#else
|
10
|
+
#define hydro_x25519_WBITS 32
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#if hydro_x25519_WBITS == 64
|
14
|
+
typedef uint64_t hydro_x25519_limb_t;
|
15
|
+
typedef __uint128_t hydro_x25519_dlimb_t;
|
16
|
+
typedef __int128_t hydro_x25519_sdlimb_t;
|
17
|
+
#define hydro_x25519_eswap_limb(X) LOAD64_LE((const uint8_t *) &(X))
|
18
|
+
#define hydro_x25519_LIMB(x) x##ull
|
19
|
+
#elif hydro_x25519_WBITS == 32
|
20
|
+
typedef uint32_t hydro_x25519_limb_t;
|
21
|
+
typedef uint64_t hydro_x25519_dlimb_t;
|
22
|
+
typedef int64_t hydro_x25519_sdlimb_t;
|
23
|
+
#define hydro_x25519_eswap_limb(X) LOAD32_LE((const uint8_t *) &(X))
|
24
|
+
#define hydro_x25519_LIMB(x) (uint32_t)(x##ull), (uint32_t)((x##ull) >> 32)
|
25
|
+
#else
|
26
|
+
#error "Need to know hydro_x25519_WBITS"
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#define hydro_x25519_NLIMBS (256 / hydro_x25519_WBITS)
|
30
|
+
typedef hydro_x25519_limb_t hydro_x25519_fe[hydro_x25519_NLIMBS];
|
31
|
+
|
32
|
+
typedef hydro_x25519_limb_t hydro_x25519_scalar_t[hydro_x25519_NLIMBS];
|
33
|
+
|
34
|
+
static const hydro_x25519_limb_t hydro_x25519_MONTGOMERY_FACTOR =
|
35
|
+
(hydro_x25519_limb_t) 0xd2b51da312547e1bull;
|
36
|
+
|
37
|
+
static const hydro_x25519_scalar_t hydro_x25519_sc_p = { hydro_x25519_LIMB(0x5812631a5cf5d3ed),
|
38
|
+
hydro_x25519_LIMB(0x14def9dea2f79cd6),
|
39
|
+
hydro_x25519_LIMB(0x0000000000000000),
|
40
|
+
hydro_x25519_LIMB(0x1000000000000000) };
|
41
|
+
|
42
|
+
static const hydro_x25519_scalar_t hydro_x25519_sc_r2 = { hydro_x25519_LIMB(0xa40611e3449c0f01),
|
43
|
+
hydro_x25519_LIMB(0xd00e1ba768859347),
|
44
|
+
hydro_x25519_LIMB(0xceec73d217f5be65),
|
45
|
+
hydro_x25519_LIMB(0x0399411b7c309a3d) };
|
46
|
+
|
47
|
+
static const uint8_t hydro_x25519_BASE_POINT[hydro_x25519_BYTES] = { 9 };
|
48
|
+
|
49
|
+
static const hydro_x25519_limb_t hydro_x25519_a24[1] = { 121665 };
|
50
|
+
|
51
|
+
static inline hydro_x25519_limb_t
|
52
|
+
hydro_x25519_umaal(hydro_x25519_limb_t *carry, hydro_x25519_limb_t acc, hydro_x25519_limb_t mand,
|
53
|
+
hydro_x25519_limb_t mier)
|
54
|
+
{
|
55
|
+
hydro_x25519_dlimb_t tmp = (hydro_x25519_dlimb_t) mand * mier + acc + *carry;
|
56
|
+
|
57
|
+
*carry = tmp >> hydro_x25519_WBITS;
|
58
|
+
return (hydro_x25519_limb_t) tmp;
|
59
|
+
}
|
60
|
+
|
61
|
+
static inline hydro_x25519_limb_t
|
62
|
+
hydro_x25519_adc(hydro_x25519_limb_t *carry, hydro_x25519_limb_t acc, hydro_x25519_limb_t mand)
|
63
|
+
{
|
64
|
+
hydro_x25519_dlimb_t total = (hydro_x25519_dlimb_t) *carry + acc + mand;
|
65
|
+
|
66
|
+
*carry = total >> hydro_x25519_WBITS;
|
67
|
+
return (hydro_x25519_limb_t) total;
|
68
|
+
}
|
69
|
+
|
70
|
+
static inline hydro_x25519_limb_t
|
71
|
+
hydro_x25519_adc0(hydro_x25519_limb_t *carry, hydro_x25519_limb_t acc)
|
72
|
+
{
|
73
|
+
hydro_x25519_dlimb_t total = (hydro_x25519_dlimb_t) *carry + acc;
|
74
|
+
|
75
|
+
*carry = total >> hydro_x25519_WBITS;
|
76
|
+
return (hydro_x25519_limb_t) total;
|
77
|
+
}
|
78
|
+
|
79
|
+
static void
|
80
|
+
hydro_x25519_propagate(hydro_x25519_fe x, hydro_x25519_limb_t over)
|
81
|
+
{
|
82
|
+
hydro_x25519_limb_t carry;
|
83
|
+
int i;
|
84
|
+
|
85
|
+
over = x[hydro_x25519_NLIMBS - 1] >> (hydro_x25519_WBITS - 1) | over << 1;
|
86
|
+
x[hydro_x25519_NLIMBS - 1] &= ~((hydro_x25519_limb_t) 1 << (hydro_x25519_WBITS - 1));
|
87
|
+
carry = over * 19;
|
88
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
89
|
+
x[i] = hydro_x25519_adc0(&carry, x[i]);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
|
93
|
+
static void
|
94
|
+
hydro_x25519_add(hydro_x25519_fe out, const hydro_x25519_fe a, const hydro_x25519_fe b)
|
95
|
+
{
|
96
|
+
hydro_x25519_limb_t carry = 0;
|
97
|
+
int i;
|
98
|
+
|
99
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
100
|
+
out[i] = hydro_x25519_adc(&carry, a[i], b[i]);
|
101
|
+
}
|
102
|
+
hydro_x25519_propagate(out, carry);
|
103
|
+
}
|
104
|
+
|
105
|
+
static void
|
106
|
+
hydro_x25519_sub(hydro_x25519_fe out, const hydro_x25519_fe a, const hydro_x25519_fe b)
|
107
|
+
{
|
108
|
+
hydro_x25519_sdlimb_t carry = -38;
|
109
|
+
int i;
|
110
|
+
|
111
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
112
|
+
out[i] = (hydro_x25519_limb_t)(carry = carry + a[i] - b[i]);
|
113
|
+
carry >>= hydro_x25519_WBITS;
|
114
|
+
}
|
115
|
+
hydro_x25519_propagate(out, (hydro_x25519_limb_t)(1 + carry));
|
116
|
+
}
|
117
|
+
|
118
|
+
static void
|
119
|
+
hydro_x25519_swapin(hydro_x25519_limb_t *x, const uint8_t *in)
|
120
|
+
{
|
121
|
+
int i;
|
122
|
+
|
123
|
+
memcpy(x, in, sizeof(hydro_x25519_fe));
|
124
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
125
|
+
x[i] = hydro_x25519_eswap_limb(x[i]);
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
static void
|
130
|
+
hydro_x25519_swapout(uint8_t *out, hydro_x25519_limb_t *x)
|
131
|
+
{
|
132
|
+
int i;
|
133
|
+
|
134
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
135
|
+
x[i] = hydro_x25519_eswap_limb(x[i]);
|
136
|
+
}
|
137
|
+
memcpy(out, x, sizeof(hydro_x25519_fe));
|
138
|
+
}
|
139
|
+
|
140
|
+
static void
|
141
|
+
hydro_x25519_mul(hydro_x25519_fe out, const hydro_x25519_fe a, const hydro_x25519_fe b, int nb)
|
142
|
+
{
|
143
|
+
hydro_x25519_limb_t accum[2 * hydro_x25519_NLIMBS] = { 0 };
|
144
|
+
hydro_x25519_limb_t carry2;
|
145
|
+
int i, j;
|
146
|
+
|
147
|
+
for (i = 0; i < nb; i++) {
|
148
|
+
carry2 = 0;
|
149
|
+
hydro_x25519_limb_t mand = b[i];
|
150
|
+
for (j = 0; j < hydro_x25519_NLIMBS; j++) {
|
151
|
+
accum[i + j] = hydro_x25519_umaal(&carry2, accum[i + j], mand, a[j]);
|
152
|
+
}
|
153
|
+
accum[i + j] = carry2;
|
154
|
+
}
|
155
|
+
carry2 = 0;
|
156
|
+
for (j = 0; j < hydro_x25519_NLIMBS; j++) {
|
157
|
+
const hydro_x25519_limb_t mand = 38;
|
158
|
+
|
159
|
+
out[j] = hydro_x25519_umaal(&carry2, accum[j], mand, accum[j + hydro_x25519_NLIMBS]);
|
160
|
+
}
|
161
|
+
hydro_x25519_propagate(out, carry2);
|
162
|
+
}
|
163
|
+
|
164
|
+
static void
|
165
|
+
hydro_x25519_sqr(hydro_x25519_fe out, const hydro_x25519_fe a)
|
166
|
+
{
|
167
|
+
hydro_x25519_mul(out, a, a, hydro_x25519_NLIMBS);
|
168
|
+
}
|
169
|
+
|
170
|
+
static void
|
171
|
+
hydro_x25519_mul1(hydro_x25519_fe out, const hydro_x25519_fe a)
|
172
|
+
{
|
173
|
+
hydro_x25519_mul(out, a, out, hydro_x25519_NLIMBS);
|
174
|
+
}
|
175
|
+
|
176
|
+
static void
|
177
|
+
hydro_x25519_sqr1(hydro_x25519_fe a)
|
178
|
+
{
|
179
|
+
hydro_x25519_mul1(a, a);
|
180
|
+
}
|
181
|
+
|
182
|
+
static void
|
183
|
+
hydro_x25519_condswap(hydro_x25519_limb_t a[2 * hydro_x25519_NLIMBS],
|
184
|
+
hydro_x25519_limb_t b[2 * hydro_x25519_NLIMBS], hydro_x25519_limb_t doswap)
|
185
|
+
{
|
186
|
+
int i;
|
187
|
+
|
188
|
+
for (i = 0; i < 2 * hydro_x25519_NLIMBS; i++) {
|
189
|
+
hydro_x25519_limb_t xorv = (a[i] ^ b[i]) & doswap;
|
190
|
+
a[i] ^= xorv;
|
191
|
+
b[i] ^= xorv;
|
192
|
+
}
|
193
|
+
}
|
194
|
+
|
195
|
+
static int
|
196
|
+
hydro_x25519_canon(hydro_x25519_fe x)
|
197
|
+
{
|
198
|
+
hydro_x25519_sdlimb_t carry;
|
199
|
+
hydro_x25519_limb_t carry0 = 19;
|
200
|
+
hydro_x25519_limb_t res;
|
201
|
+
int i;
|
202
|
+
|
203
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
204
|
+
x[i] = hydro_x25519_adc0(&carry0, x[i]);
|
205
|
+
}
|
206
|
+
hydro_x25519_propagate(x, carry0);
|
207
|
+
carry = -19;
|
208
|
+
res = 0;
|
209
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
210
|
+
res |= x[i] = (hydro_x25519_limb_t)(carry += x[i]);
|
211
|
+
carry >>= hydro_x25519_WBITS;
|
212
|
+
}
|
213
|
+
return ((hydro_x25519_dlimb_t) res - 1) >> hydro_x25519_WBITS;
|
214
|
+
}
|
215
|
+
|
216
|
+
static void
|
217
|
+
hydro_x25519_ladder_part1(hydro_x25519_fe xs[5])
|
218
|
+
{
|
219
|
+
hydro_x25519_limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
|
220
|
+
|
221
|
+
hydro_x25519_add(t1, x2, z2); // t1 = A
|
222
|
+
hydro_x25519_sub(z2, x2, z2); // z2 = B
|
223
|
+
hydro_x25519_add(x2, x3, z3); // x2 = C
|
224
|
+
hydro_x25519_sub(z3, x3, z3); // z3 = D
|
225
|
+
hydro_x25519_mul1(z3, t1); // z3 = DA
|
226
|
+
hydro_x25519_mul1(x2, z2); // x3 = BC
|
227
|
+
hydro_x25519_add(x3, z3, x2); // x3 = DA+CB
|
228
|
+
hydro_x25519_sub(z3, z3, x2); // z3 = DA-CB
|
229
|
+
hydro_x25519_sqr1(t1); // t1 = AA
|
230
|
+
hydro_x25519_sqr1(z2); // z2 = BB
|
231
|
+
hydro_x25519_sub(x2, t1, z2); // x2 = E = AA-BB
|
232
|
+
hydro_x25519_mul(z2, x2, hydro_x25519_a24, // z2 = E*a24
|
233
|
+
sizeof(hydro_x25519_a24) / sizeof(hydro_x25519_a24[0]));
|
234
|
+
hydro_x25519_add(z2, z2, t1); // z2 = E*a24 + AA
|
235
|
+
}
|
236
|
+
|
237
|
+
static void
|
238
|
+
hydro_x25519_ladder_part2(hydro_x25519_fe xs[5], const hydro_x25519_fe x1)
|
239
|
+
{
|
240
|
+
hydro_x25519_limb_t *x2 = xs[0], *z2 = xs[1], *x3 = xs[2], *z3 = xs[3], *t1 = xs[4];
|
241
|
+
|
242
|
+
hydro_x25519_sqr1(z3); // z3 = (DA-CB)^2
|
243
|
+
hydro_x25519_mul1(z3, x1); // z3 = x1 * (DA-CB)^2
|
244
|
+
hydro_x25519_sqr1(x3); // x3 = (DA+CB)^2
|
245
|
+
hydro_x25519_mul1(z2, x2); // z2 = AA*(E*a24+AA)
|
246
|
+
hydro_x25519_sub(x2, t1, x2); // x2 = BB again
|
247
|
+
hydro_x25519_mul1(x2, t1); // x2 = AA*BB
|
248
|
+
}
|
249
|
+
|
250
|
+
static void
|
251
|
+
hydro_x25519_core(hydro_x25519_fe xs[5], const uint8_t scalar[hydro_x25519_BYTES],
|
252
|
+
const uint8_t *x1, bool clamp)
|
253
|
+
{
|
254
|
+
hydro_x25519_limb_t swap;
|
255
|
+
hydro_x25519_limb_t *x2 = xs[0], *x3 = xs[2], *z3 = xs[3];
|
256
|
+
hydro_x25519_fe x1i;
|
257
|
+
int i;
|
258
|
+
|
259
|
+
hydro_x25519_swapin(x1i, x1);
|
260
|
+
x1 = (const uint8_t *) x1i;
|
261
|
+
swap = 0;
|
262
|
+
mem_zero(xs, 4 * sizeof(hydro_x25519_fe));
|
263
|
+
x2[0] = z3[0] = 1;
|
264
|
+
memcpy(x3, x1, sizeof(hydro_x25519_fe));
|
265
|
+
for (i = 255; i >= 0; i--) {
|
266
|
+
uint8_t bytei = scalar[i / 8];
|
267
|
+
hydro_x25519_limb_t doswap;
|
268
|
+
hydro_x25519_fe x1_dup;
|
269
|
+
|
270
|
+
if (clamp) {
|
271
|
+
if (i / 8 == 0) {
|
272
|
+
bytei &= ~7;
|
273
|
+
} else if (i / 8 == hydro_x25519_BYTES - 1) {
|
274
|
+
bytei &= 0x7F;
|
275
|
+
bytei |= 0x40;
|
276
|
+
}
|
277
|
+
}
|
278
|
+
doswap = 1U + ~(hydro_x25519_limb_t)((bytei >> (i % 8)) & 1);
|
279
|
+
hydro_x25519_condswap(x2, x3, swap ^ doswap);
|
280
|
+
swap = doswap;
|
281
|
+
hydro_x25519_ladder_part1(xs);
|
282
|
+
memcpy(x1_dup, x1, sizeof x1_dup);
|
283
|
+
hydro_x25519_ladder_part2(xs, x1_dup);
|
284
|
+
}
|
285
|
+
hydro_x25519_condswap(x2, x3, swap);
|
286
|
+
}
|
287
|
+
|
288
|
+
static int
|
289
|
+
hydro_x25519_scalarmult(uint8_t out[hydro_x25519_BYTES],
|
290
|
+
const uint8_t scalar[hydro_x25519_SECRETKEYBYTES],
|
291
|
+
const uint8_t x1[hydro_x25519_PUBLICKEYBYTES], bool clamp)
|
292
|
+
{
|
293
|
+
hydro_x25519_fe xs[5];
|
294
|
+
hydro_x25519_limb_t *x2, *z2, *z3;
|
295
|
+
hydro_x25519_limb_t *prev;
|
296
|
+
int i;
|
297
|
+
int ret;
|
298
|
+
|
299
|
+
hydro_x25519_core(xs, scalar, x1, clamp);
|
300
|
+
|
301
|
+
/* Precomputed inversion chain */
|
302
|
+
x2 = xs[0];
|
303
|
+
z2 = xs[1];
|
304
|
+
z3 = xs[3];
|
305
|
+
prev = z2;
|
306
|
+
|
307
|
+
/* Raise to the p-2 = 0x7f..ffeb */
|
308
|
+
for (i = 253; i >= 0; i--) {
|
309
|
+
hydro_x25519_sqr(z3, prev);
|
310
|
+
prev = z3;
|
311
|
+
if (i >= 8 || (0xeb >> i & 1)) {
|
312
|
+
hydro_x25519_mul1(z3, z2);
|
313
|
+
}
|
314
|
+
}
|
315
|
+
|
316
|
+
/* Here prev = z3 */
|
317
|
+
/* x2 /= z2 */
|
318
|
+
hydro_x25519_mul1(x2, z3);
|
319
|
+
ret = hydro_x25519_canon(x2);
|
320
|
+
hydro_x25519_swapout(out, x2);
|
321
|
+
|
322
|
+
if (clamp == 0) {
|
323
|
+
return 0;
|
324
|
+
}
|
325
|
+
return ret;
|
326
|
+
}
|
327
|
+
|
328
|
+
static inline int
|
329
|
+
hydro_x25519_scalarmult_base(uint8_t pk[hydro_x25519_PUBLICKEYBYTES],
|
330
|
+
const uint8_t sk[hydro_x25519_SECRETKEYBYTES])
|
331
|
+
{
|
332
|
+
return hydro_x25519_scalarmult(pk, sk, hydro_x25519_BASE_POINT, 1);
|
333
|
+
}
|
334
|
+
|
335
|
+
static inline void
|
336
|
+
hydro_x25519_scalarmult_base_uniform(uint8_t pk[hydro_x25519_PUBLICKEYBYTES],
|
337
|
+
const uint8_t sk[hydro_x25519_SECRETKEYBYTES])
|
338
|
+
{
|
339
|
+
if (hydro_x25519_scalarmult(pk, sk, hydro_x25519_BASE_POINT, 0) != 0) {
|
340
|
+
abort();
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
static void
|
345
|
+
hydro_x25519_sc_montmul(hydro_x25519_scalar_t out, const hydro_x25519_scalar_t a,
|
346
|
+
const hydro_x25519_scalar_t b)
|
347
|
+
{
|
348
|
+
hydro_x25519_limb_t hic = 0;
|
349
|
+
int i, j;
|
350
|
+
|
351
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
352
|
+
hydro_x25519_limb_t carry = 0, carry2 = 0, mand = a[i],
|
353
|
+
mand2 = hydro_x25519_MONTGOMERY_FACTOR;
|
354
|
+
|
355
|
+
for (j = 0; j < hydro_x25519_NLIMBS; j++) {
|
356
|
+
hydro_x25519_limb_t acc = out[j];
|
357
|
+
|
358
|
+
acc = hydro_x25519_umaal(&carry, acc, mand, b[j]);
|
359
|
+
if (j == 0) {
|
360
|
+
mand2 *= acc;
|
361
|
+
}
|
362
|
+
acc = hydro_x25519_umaal(&carry2, acc, mand2, hydro_x25519_sc_p[j]);
|
363
|
+
if (j > 0) {
|
364
|
+
out[j - 1] = acc;
|
365
|
+
}
|
366
|
+
}
|
367
|
+
|
368
|
+
/* Add two carry registers and high carry */
|
369
|
+
out[hydro_x25519_NLIMBS - 1] = hydro_x25519_adc(&hic, carry, carry2);
|
370
|
+
}
|
371
|
+
|
372
|
+
/* Reduce */
|
373
|
+
hydro_x25519_sdlimb_t scarry = 0;
|
374
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
375
|
+
out[i] = (hydro_x25519_limb_t)(scarry = scarry + out[i] - hydro_x25519_sc_p[i]);
|
376
|
+
scarry >>= hydro_x25519_WBITS;
|
377
|
+
}
|
378
|
+
hydro_x25519_limb_t need_add = (hydro_x25519_limb_t) - (scarry + hic);
|
379
|
+
|
380
|
+
hydro_x25519_limb_t carry = 0;
|
381
|
+
for (i = 0; i < hydro_x25519_NLIMBS; i++) {
|
382
|
+
out[i] = hydro_x25519_umaal(&carry, out[i], need_add, hydro_x25519_sc_p[i]);
|
383
|
+
}
|
384
|
+
}
|