dualcone 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }