dualcone 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|