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.
@@ -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
+ }