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,25 @@
|
|
1
|
+
#ifdef __SSE2__
|
2
|
+
#include "gimli-core/sse2.h"
|
3
|
+
#else
|
4
|
+
#include "gimli-core/portable.h"
|
5
|
+
#endif
|
6
|
+
|
7
|
+
static void
|
8
|
+
gimli_core_u8(uint8_t state_u8[gimli_BLOCKBYTES], uint8_t tag)
|
9
|
+
{
|
10
|
+
state_u8[gimli_BLOCKBYTES - 1] ^= tag;
|
11
|
+
#ifndef NATIVE_LITTLE_ENDIAN
|
12
|
+
uint32_t state_u32[12];
|
13
|
+
int i;
|
14
|
+
|
15
|
+
for (i = 0; i < 12; i++) {
|
16
|
+
state_u32[i] = LOAD32_LE(&state_u8[i * 4]);
|
17
|
+
}
|
18
|
+
gimli_core(state_u32);
|
19
|
+
for (i = 0; i < 12; i++) {
|
20
|
+
STORE32_LE(&state_u8[i * 4], state_u32[i]);
|
21
|
+
}
|
22
|
+
#else
|
23
|
+
gimli_core((uint32_t *) (void *) state_u8); /* state_u8 must be properly aligned */
|
24
|
+
#endif
|
25
|
+
}
|
@@ -0,0 +1,39 @@
|
|
1
|
+
static void
|
2
|
+
gimli_core(uint32_t state[gimli_BLOCKBYTES / 4])
|
3
|
+
{
|
4
|
+
unsigned int round;
|
5
|
+
unsigned int column;
|
6
|
+
uint32_t x;
|
7
|
+
uint32_t y;
|
8
|
+
uint32_t z;
|
9
|
+
|
10
|
+
for (round = 24; round > 0; round--) {
|
11
|
+
for (column = 0; column < 4; column++) {
|
12
|
+
x = ROTL32(state[column], 24);
|
13
|
+
y = ROTL32(state[4 + column], 9);
|
14
|
+
z = state[8 + column];
|
15
|
+
|
16
|
+
state[8 + column] = x ^ (z << 1) ^ ((y & z) << 2);
|
17
|
+
state[4 + column] = y ^ x ^ ((x | z) << 1);
|
18
|
+
state[column] = z ^ y ^ ((x & y) << 3);
|
19
|
+
}
|
20
|
+
switch (round & 3) {
|
21
|
+
case 0:
|
22
|
+
x = state[0];
|
23
|
+
state[0] = state[1];
|
24
|
+
state[1] = x;
|
25
|
+
x = state[2];
|
26
|
+
state[2] = state[3];
|
27
|
+
state[3] = x;
|
28
|
+
state[0] ^= ((uint32_t) 0x9e377900 | round);
|
29
|
+
break;
|
30
|
+
case 2:
|
31
|
+
x = state[0];
|
32
|
+
state[0] = state[2];
|
33
|
+
state[2] = x;
|
34
|
+
x = state[1];
|
35
|
+
state[1] = state[3];
|
36
|
+
state[3] = x;
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
@@ -0,0 +1,100 @@
|
|
1
|
+
#include <emmintrin.h>
|
2
|
+
#ifdef __SSSE3__
|
3
|
+
# include <tmmintrin.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#define S 9
|
7
|
+
|
8
|
+
static inline __m128i
|
9
|
+
shift(__m128i x, int bits)
|
10
|
+
{
|
11
|
+
return _mm_slli_epi32(x, bits);
|
12
|
+
}
|
13
|
+
|
14
|
+
static inline __m128i
|
15
|
+
rotate(__m128i x, int bits)
|
16
|
+
{
|
17
|
+
return _mm_slli_epi32(x, bits) | _mm_srli_epi32(x, 32 - bits);
|
18
|
+
}
|
19
|
+
|
20
|
+
#ifdef __SSSE3__
|
21
|
+
static inline __m128i
|
22
|
+
rotate24(__m128i x)
|
23
|
+
{
|
24
|
+
return _mm_shuffle_epi8(x, _mm_set_epi8(12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1));
|
25
|
+
}
|
26
|
+
#else
|
27
|
+
static inline __m128i
|
28
|
+
rotate24(__m128i x)
|
29
|
+
{
|
30
|
+
uint8_t _hydro_attr_aligned_(16) x8[16], y8[16];
|
31
|
+
|
32
|
+
_mm_storeu_si128((__m128i *) (void *) x8, x);
|
33
|
+
|
34
|
+
y8[ 0] = x8[ 1]; y8[ 1] = x8[ 2]; y8[ 2] = x8[ 3]; y8[ 3] = x8[ 0];
|
35
|
+
y8[ 4] = x8[ 5]; y8[ 5] = x8[ 6]; y8[ 6] = x8[ 7]; y8[ 7] = x8[ 4];
|
36
|
+
y8[ 8] = x8[ 9]; y8[ 9] = x8[10]; y8[10] = x8[11]; y8[11] = x8[ 8];
|
37
|
+
y8[12] = x8[13]; y8[13] = x8[14]; y8[14] = x8[15]; y8[15] = x8[12];
|
38
|
+
|
39
|
+
return _mm_loadu_si128((const __m128i *) (const void *) y8);
|
40
|
+
}
|
41
|
+
#endif
|
42
|
+
|
43
|
+
static const uint32_t coeffs[24] _hydro_attr_aligned_(16) = {
|
44
|
+
0x9e377904, 0, 0, 0, 0x9e377908, 0, 0, 0, 0x9e37790c, 0, 0, 0,
|
45
|
+
0x9e377910, 0, 0, 0, 0x9e377914, 0, 0, 0, 0x9e377918, 0, 0, 0,
|
46
|
+
};
|
47
|
+
|
48
|
+
static void
|
49
|
+
gimli_core(uint32_t state[gimli_BLOCKBYTES / 4])
|
50
|
+
{
|
51
|
+
__m128i x = _mm_loadu_si128((const __m128i *) (const void *) &state[0]);
|
52
|
+
__m128i y = _mm_loadu_si128((const __m128i *) (const void *) &state[4]);
|
53
|
+
__m128i z = _mm_loadu_si128((const __m128i *) (const void *) &state[8]);
|
54
|
+
__m128i newy;
|
55
|
+
__m128i newz;
|
56
|
+
int round;
|
57
|
+
|
58
|
+
for (round = 5; round >= 0; round--) {
|
59
|
+
x = rotate24(x);
|
60
|
+
y = rotate(y, S);
|
61
|
+
newz = x ^ shift(z, 1) ^ shift(y & z, 2);
|
62
|
+
newy = y ^ x ^ shift(x | z, 1);
|
63
|
+
x = z ^ y ^ shift(x & y, 3);
|
64
|
+
y = newy;
|
65
|
+
z = newz;
|
66
|
+
|
67
|
+
x = _mm_shuffle_epi32(x, _MM_SHUFFLE(2, 3, 0, 1));
|
68
|
+
x ^= ((const __m128i *) (const void *) coeffs)[round];
|
69
|
+
|
70
|
+
x = rotate24(x);
|
71
|
+
y = rotate(y, S);
|
72
|
+
newz = x ^ shift(z, 1) ^ shift(y & z, 2);
|
73
|
+
newy = y ^ x ^ shift(x | z, 1);
|
74
|
+
x = z ^ y ^ shift(x & y, 3);
|
75
|
+
y = newy;
|
76
|
+
z = newz;
|
77
|
+
|
78
|
+
x = rotate24(x);
|
79
|
+
y = rotate(y, S);
|
80
|
+
newz = x ^ shift(z, 1) ^ shift(y & z, 2);
|
81
|
+
newy = y ^ x ^ shift(x | z, 1);
|
82
|
+
x = z ^ y ^ shift(x & y, 3);
|
83
|
+
y = newy;
|
84
|
+
z = newz;
|
85
|
+
|
86
|
+
x = _mm_shuffle_epi32(x, _MM_SHUFFLE(1, 0, 3, 2));
|
87
|
+
|
88
|
+
x = rotate24(x);
|
89
|
+
y = rotate(y, S);
|
90
|
+
newz = x ^ shift(z, 1) ^ shift(y & z, 2);
|
91
|
+
newy = y ^ x ^ shift(x | z, 1);
|
92
|
+
x = z ^ y ^ shift(x & y, 3);
|
93
|
+
y = newy;
|
94
|
+
z = newz;
|
95
|
+
}
|
96
|
+
|
97
|
+
_mm_storeu_si128((__m128i *) (void *) &state[0], x);
|
98
|
+
_mm_storeu_si128((__m128i *) (void *) &state[4], y);
|
99
|
+
_mm_storeu_si128((__m128i *) (void *) &state[8], z);
|
100
|
+
}
|
@@ -0,0 +1,140 @@
|
|
1
|
+
int
|
2
|
+
hydro_hash_update(hydro_hash_state *state, const void *in_, size_t in_len)
|
3
|
+
{
|
4
|
+
const uint8_t *in = (const uint8_t *) in_;
|
5
|
+
uint8_t * buf = (uint8_t *) (void *) state->state;
|
6
|
+
size_t left;
|
7
|
+
size_t ps;
|
8
|
+
size_t i;
|
9
|
+
|
10
|
+
while (in_len > 0) {
|
11
|
+
left = gimli_RATE - state->buf_off;
|
12
|
+
if ((ps = in_len) > left) {
|
13
|
+
ps = left;
|
14
|
+
}
|
15
|
+
for (i = 0; i < ps; i++) {
|
16
|
+
buf[state->buf_off + i] ^= in[i];
|
17
|
+
}
|
18
|
+
in += ps;
|
19
|
+
in_len -= ps;
|
20
|
+
state->buf_off += (uint8_t) ps;
|
21
|
+
if (state->buf_off == gimli_RATE) {
|
22
|
+
gimli_core_u8(buf, 0);
|
23
|
+
state->buf_off = 0;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
return 0;
|
27
|
+
}
|
28
|
+
|
29
|
+
/* pad(str_enc("kmac") || str_enc(context)) || pad(str_enc(k)) ||
|
30
|
+
msg || right_enc(msg_len) || 0x00 */
|
31
|
+
|
32
|
+
int
|
33
|
+
hydro_hash_init(hydro_hash_state *state, const char ctx[hydro_hash_CONTEXTBYTES],
|
34
|
+
const uint8_t key[hydro_hash_KEYBYTES])
|
35
|
+
{
|
36
|
+
uint8_t block[64] = { 4, 'k', 'm', 'a', 'c', 8 };
|
37
|
+
size_t p;
|
38
|
+
|
39
|
+
COMPILER_ASSERT(hydro_hash_KEYBYTES <= sizeof block - gimli_RATE - 1);
|
40
|
+
COMPILER_ASSERT(hydro_hash_CONTEXTBYTES == 8);
|
41
|
+
mem_zero(block + 14, sizeof block - 14);
|
42
|
+
memcpy(block + 6, ctx, 8);
|
43
|
+
if (key != NULL) {
|
44
|
+
block[gimli_RATE] = (uint8_t) hydro_hash_KEYBYTES;
|
45
|
+
memcpy(block + gimli_RATE + 1, key, hydro_hash_KEYBYTES);
|
46
|
+
p = (gimli_RATE + 1 + hydro_hash_KEYBYTES + (gimli_RATE - 1)) & ~(size_t)(gimli_RATE - 1);
|
47
|
+
} else {
|
48
|
+
block[gimli_RATE] = (uint8_t) 0;
|
49
|
+
p = (gimli_RATE + 1 + 0 + (gimli_RATE - 1)) & ~(size_t)(gimli_RATE - 1);
|
50
|
+
}
|
51
|
+
mem_zero(state, sizeof *state);
|
52
|
+
hydro_hash_update(state, block, p);
|
53
|
+
|
54
|
+
return 0;
|
55
|
+
}
|
56
|
+
|
57
|
+
/* pad(str_enc("tmac") || str_enc(context)) || pad(str_enc(k)) ||
|
58
|
+
pad(right_enc(tweak)) || msg || right_enc(msg_len) || 0x00 */
|
59
|
+
|
60
|
+
static int
|
61
|
+
hydro_hash_init_with_tweak(hydro_hash_state *state, const char ctx[hydro_hash_CONTEXTBYTES],
|
62
|
+
uint64_t tweak, const uint8_t key[hydro_hash_KEYBYTES])
|
63
|
+
{
|
64
|
+
uint8_t block[80] = { 4, 't', 'm', 'a', 'c', 8 };
|
65
|
+
size_t p;
|
66
|
+
|
67
|
+
COMPILER_ASSERT(hydro_hash_KEYBYTES <= sizeof block - 2 * gimli_RATE - 1);
|
68
|
+
COMPILER_ASSERT(hydro_hash_CONTEXTBYTES == 8);
|
69
|
+
mem_zero(block + 14, sizeof block - 14);
|
70
|
+
memcpy(block + 6, ctx, 8);
|
71
|
+
if (key != NULL) {
|
72
|
+
block[gimli_RATE] = (uint8_t) hydro_hash_KEYBYTES;
|
73
|
+
memcpy(block + gimli_RATE + 1, key, hydro_hash_KEYBYTES);
|
74
|
+
p = (gimli_RATE + 1 + hydro_hash_KEYBYTES + (gimli_RATE - 1)) & ~(size_t)(gimli_RATE - 1);
|
75
|
+
} else {
|
76
|
+
block[gimli_RATE] = (uint8_t) 0;
|
77
|
+
p = (gimli_RATE + 1 + 0 + (gimli_RATE - 1)) & ~(size_t)(gimli_RATE - 1);
|
78
|
+
}
|
79
|
+
block[p] = (uint8_t) sizeof tweak;
|
80
|
+
STORE64_LE(&block[p + 1], tweak);
|
81
|
+
p += gimli_RATE;
|
82
|
+
mem_zero(state, sizeof *state);
|
83
|
+
hydro_hash_update(state, block, p);
|
84
|
+
|
85
|
+
return 0;
|
86
|
+
}
|
87
|
+
|
88
|
+
int
|
89
|
+
hydro_hash_final(hydro_hash_state *state, uint8_t *out, size_t out_len)
|
90
|
+
{
|
91
|
+
uint8_t lc[4];
|
92
|
+
uint8_t *buf = (uint8_t *) (void *) state->state;
|
93
|
+
size_t i;
|
94
|
+
size_t lc_len;
|
95
|
+
size_t leftover;
|
96
|
+
|
97
|
+
if (out_len < hydro_hash_BYTES_MIN || out_len > hydro_hash_BYTES_MAX) {
|
98
|
+
return -1;
|
99
|
+
}
|
100
|
+
COMPILER_ASSERT(hydro_hash_BYTES_MAX <= 0xffff);
|
101
|
+
lc[1] = (uint8_t) out_len;
|
102
|
+
lc[2] = (uint8_t)(out_len >> 8);
|
103
|
+
lc[3] = 0;
|
104
|
+
lc_len = (size_t)(1 + (lc[2] != 0));
|
105
|
+
lc[0] = (uint8_t) lc_len;
|
106
|
+
hydro_hash_update(state, lc, 1 + lc_len + 1);
|
107
|
+
gimli_pad_u8(buf, state->buf_off, gimli_DOMAIN_XOF);
|
108
|
+
for (i = 0; i < out_len / gimli_RATE; i++) {
|
109
|
+
gimli_core_u8(buf, 0);
|
110
|
+
memcpy(out + i * gimli_RATE, buf, gimli_RATE);
|
111
|
+
}
|
112
|
+
leftover = out_len % gimli_RATE;
|
113
|
+
if (leftover != 0) {
|
114
|
+
gimli_core_u8(buf, 0);
|
115
|
+
mem_cpy(out + i * gimli_RATE, buf, leftover);
|
116
|
+
}
|
117
|
+
state->buf_off = gimli_RATE;
|
118
|
+
|
119
|
+
return 0;
|
120
|
+
}
|
121
|
+
|
122
|
+
int
|
123
|
+
hydro_hash_hash(uint8_t *out, size_t out_len, const void *in_, size_t in_len,
|
124
|
+
const char ctx[hydro_hash_CONTEXTBYTES], const uint8_t key[hydro_hash_KEYBYTES])
|
125
|
+
{
|
126
|
+
hydro_hash_state st;
|
127
|
+
const uint8_t * in = (const uint8_t *) in_;
|
128
|
+
|
129
|
+
if (hydro_hash_init(&st, ctx, key) != 0 || hydro_hash_update(&st, in, in_len) != 0 ||
|
130
|
+
hydro_hash_final(&st, out, out_len) != 0) {
|
131
|
+
return -1;
|
132
|
+
}
|
133
|
+
return 0;
|
134
|
+
}
|
135
|
+
|
136
|
+
void
|
137
|
+
hydro_hash_keygen(uint8_t key[hydro_hash_KEYBYTES])
|
138
|
+
{
|
139
|
+
hydro_random_buf(key, hydro_hash_KEYBYTES);
|
140
|
+
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
static int hydro_random_init(void);
|
2
|
+
|
3
|
+
/* ---------------- */
|
4
|
+
|
5
|
+
#define gimli_BLOCKBYTES 48
|
6
|
+
#define gimli_CAPACITY 32
|
7
|
+
#define gimli_RATE 16
|
8
|
+
|
9
|
+
#define gimli_TAG_HEADER 0x01
|
10
|
+
#define gimli_TAG_PAYLOAD 0x02
|
11
|
+
#define gimli_TAG_FINAL 0x08
|
12
|
+
#define gimli_TAG_FINAL0 0xf8
|
13
|
+
#define gimli_TAG_KEY0 0xfe
|
14
|
+
#define gimli_TAG_KEY 0xff
|
15
|
+
|
16
|
+
#define gimli_DOMAIN_AEAD 0x0
|
17
|
+
#define gimli_DOMAIN_XOF 0xf
|
18
|
+
|
19
|
+
static void gimli_core_u8(uint8_t state_u8[gimli_BLOCKBYTES], uint8_t tag);
|
20
|
+
|
21
|
+
static inline void
|
22
|
+
gimli_pad_u8(uint8_t buf[gimli_BLOCKBYTES], size_t pos, uint8_t domain)
|
23
|
+
{
|
24
|
+
buf[pos] ^= (domain << 1) | 1;
|
25
|
+
buf[gimli_RATE - 1] ^= 0x80;
|
26
|
+
}
|
27
|
+
|
28
|
+
static inline void
|
29
|
+
hydro_mem_ct_zero_u32(uint32_t *dst_, size_t n)
|
30
|
+
{
|
31
|
+
volatile uint32_t *volatile dst = (volatile uint32_t * volatile)(void *) dst_;
|
32
|
+
size_t i;
|
33
|
+
|
34
|
+
for (i = 0; i < n; i++) {
|
35
|
+
dst[i] = 0;
|
36
|
+
}
|
37
|
+
}
|
38
|
+
|
39
|
+
static inline uint32_t hydro_mem_ct_cmp_u32(const uint32_t *b1_, const uint32_t *b2,
|
40
|
+
size_t n) _hydro_attr_warn_unused_result_;
|
41
|
+
|
42
|
+
static inline uint32_t
|
43
|
+
hydro_mem_ct_cmp_u32(const uint32_t *b1_, const uint32_t *b2, size_t n)
|
44
|
+
{
|
45
|
+
const volatile uint32_t *volatile b1 = (const volatile uint32_t *volatile)(const void *) b1_;
|
46
|
+
size_t i;
|
47
|
+
uint32_t cv = 0;
|
48
|
+
|
49
|
+
for (i = 0; i < n; i++) {
|
50
|
+
cv |= b1[i] ^ b2[i];
|
51
|
+
}
|
52
|
+
return cv;
|
53
|
+
}
|
54
|
+
|
55
|
+
/* ---------------- */
|
56
|
+
|
57
|
+
static int hydro_hash_init_with_tweak(hydro_hash_state *state,
|
58
|
+
const char ctx[hydro_hash_CONTEXTBYTES], uint64_t tweak,
|
59
|
+
const uint8_t key[hydro_hash_KEYBYTES]);
|
60
|
+
|
61
|
+
/* ---------------- */
|
62
|
+
|
63
|
+
#define hydro_secretbox_NONCEBYTES 20
|
64
|
+
#define hydro_secretbox_MACBYTES 16
|
65
|
+
|
66
|
+
/* ---------------- */
|
67
|
+
|
68
|
+
#define hydro_x25519_BYTES 32
|
69
|
+
#define hydro_x25519_PUBLICKEYBYTES 32
|
70
|
+
#define hydro_x25519_SECRETKEYBYTES 32
|
71
|
+
|
72
|
+
static int hydro_x25519_scalarmult(uint8_t out[hydro_x25519_BYTES],
|
73
|
+
const uint8_t scalar[hydro_x25519_SECRETKEYBYTES],
|
74
|
+
const uint8_t x1[hydro_x25519_PUBLICKEYBYTES],
|
75
|
+
bool clamp) _hydro_attr_warn_unused_result_;
|
76
|
+
|
77
|
+
static inline int hydro_x25519_scalarmult_base(uint8_t pk[hydro_x25519_PUBLICKEYBYTES],
|
78
|
+
const uint8_t sk[hydro_x25519_SECRETKEYBYTES])
|
79
|
+
_hydro_attr_warn_unused_result_;
|
80
|
+
|
81
|
+
static inline void
|
82
|
+
hydro_x25519_scalarmult_base_uniform(uint8_t pk[hydro_x25519_PUBLICKEYBYTES],
|
83
|
+
const uint8_t sk[hydro_x25519_SECRETKEYBYTES]);
|
@@ -0,0 +1,20 @@
|
|
1
|
+
int
|
2
|
+
hydro_kdf_derive_from_key(uint8_t *subkey, size_t subkey_len, uint64_t subkey_id,
|
3
|
+
const char ctx[hydro_kdf_CONTEXTBYTES],
|
4
|
+
const uint8_t key[hydro_kdf_KEYBYTES])
|
5
|
+
{
|
6
|
+
hydro_hash_state st;
|
7
|
+
|
8
|
+
COMPILER_ASSERT(hydro_kdf_CONTEXTBYTES >= hydro_hash_CONTEXTBYTES);
|
9
|
+
COMPILER_ASSERT(hydro_kdf_KEYBYTES >= hydro_hash_KEYBYTES);
|
10
|
+
if (hydro_hash_init_with_tweak(&st, ctx, subkey_id, key) != 0) {
|
11
|
+
return -1;
|
12
|
+
}
|
13
|
+
return hydro_hash_final(&st, subkey, subkey_len);
|
14
|
+
}
|
15
|
+
|
16
|
+
void
|
17
|
+
hydro_kdf_keygen(uint8_t key[hydro_kdf_KEYBYTES])
|
18
|
+
{
|
19
|
+
hydro_random_buf(key, hydro_kdf_KEYBYTES);
|
20
|
+
}
|
@@ -0,0 +1,535 @@
|
|
1
|
+
#define hydro_kx_AEAD_KEYBYTES hydro_hash_KEYBYTES
|
2
|
+
#define hydro_kx_AEAD_MACBYTES 16
|
3
|
+
|
4
|
+
#define hydro_kx_CONTEXT "hydro_kx"
|
5
|
+
|
6
|
+
static void
|
7
|
+
hydro_kx_aead_init(uint8_t aead_state[gimli_BLOCKBYTES], uint8_t k[hydro_kx_AEAD_KEYBYTES],
|
8
|
+
hydro_kx_state *state)
|
9
|
+
{
|
10
|
+
static const uint8_t prefix[] = { 6, 'k', 'x', 'x', '2', '5', '6', 0 };
|
11
|
+
|
12
|
+
hydro_hash_final(&state->h_st, k, hydro_kx_AEAD_KEYBYTES);
|
13
|
+
|
14
|
+
mem_zero(aead_state + sizeof prefix, gimli_BLOCKBYTES - sizeof prefix);
|
15
|
+
memcpy(aead_state, prefix, sizeof prefix);
|
16
|
+
gimli_core_u8(aead_state, gimli_TAG_HEADER);
|
17
|
+
|
18
|
+
COMPILER_ASSERT(hydro_kx_AEAD_KEYBYTES == 2 * gimli_RATE);
|
19
|
+
mem_xor(aead_state, k, gimli_RATE);
|
20
|
+
gimli_core_u8(aead_state, gimli_TAG_KEY);
|
21
|
+
mem_xor(aead_state, k + gimli_RATE, gimli_RATE);
|
22
|
+
gimli_core_u8(aead_state, gimli_TAG_KEY);
|
23
|
+
}
|
24
|
+
|
25
|
+
static void
|
26
|
+
hydro_kx_aead_final(uint8_t *aead_state, const uint8_t key[hydro_kx_AEAD_KEYBYTES])
|
27
|
+
{
|
28
|
+
COMPILER_ASSERT(hydro_kx_AEAD_KEYBYTES == gimli_CAPACITY);
|
29
|
+
mem_xor(aead_state + gimli_RATE, key, hydro_kx_AEAD_KEYBYTES);
|
30
|
+
gimli_core_u8(aead_state, gimli_TAG_FINAL);
|
31
|
+
mem_xor(aead_state + gimli_RATE, key, hydro_kx_AEAD_KEYBYTES);
|
32
|
+
gimli_core_u8(aead_state, gimli_TAG_FINAL);
|
33
|
+
}
|
34
|
+
|
35
|
+
static void
|
36
|
+
hydro_kx_aead_xor_enc(uint8_t aead_state[gimli_BLOCKBYTES], uint8_t *out, const uint8_t *in,
|
37
|
+
size_t inlen)
|
38
|
+
{
|
39
|
+
size_t i;
|
40
|
+
size_t leftover;
|
41
|
+
|
42
|
+
for (i = 0; i < inlen / gimli_RATE; i++) {
|
43
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], aead_state, gimli_RATE);
|
44
|
+
memcpy(aead_state, &out[i * gimli_RATE], gimli_RATE);
|
45
|
+
gimli_core_u8(aead_state, gimli_TAG_PAYLOAD);
|
46
|
+
}
|
47
|
+
leftover = inlen % gimli_RATE;
|
48
|
+
if (leftover != 0) {
|
49
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], aead_state, leftover);
|
50
|
+
mem_cpy(aead_state, &out[i * gimli_RATE], leftover);
|
51
|
+
}
|
52
|
+
gimli_pad_u8(aead_state, leftover, gimli_DOMAIN_AEAD);
|
53
|
+
gimli_core_u8(aead_state, gimli_TAG_PAYLOAD);
|
54
|
+
}
|
55
|
+
|
56
|
+
static void
|
57
|
+
hydro_kx_aead_xor_dec(uint8_t aead_state[gimli_BLOCKBYTES], uint8_t *out, const uint8_t *in,
|
58
|
+
size_t inlen)
|
59
|
+
{
|
60
|
+
size_t i;
|
61
|
+
size_t leftover;
|
62
|
+
|
63
|
+
for (i = 0; i < inlen / gimli_RATE; i++) {
|
64
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], aead_state, gimli_RATE);
|
65
|
+
memcpy(aead_state, &in[i * gimli_RATE], gimli_RATE);
|
66
|
+
gimli_core_u8(aead_state, gimli_TAG_PAYLOAD);
|
67
|
+
}
|
68
|
+
leftover = inlen % gimli_RATE;
|
69
|
+
if (leftover != 0) {
|
70
|
+
mem_xor2(&out[i * gimli_RATE], &in[i * gimli_RATE], aead_state, leftover);
|
71
|
+
mem_cpy(aead_state, &in[i * gimli_RATE], leftover);
|
72
|
+
}
|
73
|
+
gimli_pad_u8(aead_state, leftover, gimli_DOMAIN_AEAD);
|
74
|
+
gimli_core_u8(aead_state, gimli_TAG_PAYLOAD);
|
75
|
+
}
|
76
|
+
|
77
|
+
static void
|
78
|
+
hydro_kx_aead_encrypt(hydro_kx_state *state, uint8_t *c, const uint8_t *m, size_t mlen)
|
79
|
+
{
|
80
|
+
_hydro_attr_aligned_(16) uint8_t aead_state[gimli_BLOCKBYTES];
|
81
|
+
uint8_t k[hydro_kx_AEAD_KEYBYTES];
|
82
|
+
uint8_t * mac = &c[0];
|
83
|
+
uint8_t * ct = &c[hydro_kx_AEAD_MACBYTES];
|
84
|
+
|
85
|
+
hydro_kx_aead_init(aead_state, k, state);
|
86
|
+
hydro_kx_aead_xor_enc(aead_state, ct, m, mlen);
|
87
|
+
hydro_kx_aead_final(aead_state, k);
|
88
|
+
COMPILER_ASSERT(hydro_kx_AEAD_MACBYTES <= gimli_CAPACITY);
|
89
|
+
memcpy(mac, aead_state + gimli_RATE, hydro_kx_AEAD_MACBYTES);
|
90
|
+
hydro_hash_update(&state->h_st, c, mlen + hydro_kx_AEAD_MACBYTES);
|
91
|
+
}
|
92
|
+
|
93
|
+
static int hydro_kx_aead_decrypt(hydro_kx_state *state, uint8_t *m, const uint8_t *c,
|
94
|
+
size_t clen) _hydro_attr_warn_unused_result_;
|
95
|
+
|
96
|
+
static int
|
97
|
+
hydro_kx_aead_decrypt(hydro_kx_state *state, uint8_t *m, const uint8_t *c, size_t clen)
|
98
|
+
{
|
99
|
+
_hydro_attr_aligned_(16) uint32_t int_state[gimli_BLOCKBYTES / 4];
|
100
|
+
uint32_t pub_mac[hydro_kx_AEAD_MACBYTES / 4];
|
101
|
+
uint8_t k[hydro_kx_AEAD_KEYBYTES];
|
102
|
+
uint8_t * aead_state = (uint8_t *) (void *) int_state;
|
103
|
+
const uint8_t * mac;
|
104
|
+
const uint8_t * ct;
|
105
|
+
size_t mlen;
|
106
|
+
uint32_t cv;
|
107
|
+
|
108
|
+
if (clen < hydro_kx_AEAD_MACBYTES) {
|
109
|
+
return -1;
|
110
|
+
}
|
111
|
+
mac = &c[0];
|
112
|
+
ct = &c[hydro_kx_AEAD_MACBYTES];
|
113
|
+
mlen = clen - hydro_kx_AEAD_MACBYTES;
|
114
|
+
memcpy(pub_mac, mac, sizeof pub_mac);
|
115
|
+
hydro_kx_aead_init(aead_state, k, state);
|
116
|
+
hydro_hash_update(&state->h_st, c, clen);
|
117
|
+
hydro_kx_aead_xor_dec(aead_state, m, ct, mlen);
|
118
|
+
hydro_kx_aead_final(aead_state, k);
|
119
|
+
COMPILER_ASSERT(hydro_kx_AEAD_MACBYTES <= gimli_CAPACITY);
|
120
|
+
COMPILER_ASSERT(gimli_RATE % 4 == 0);
|
121
|
+
cv = hydro_mem_ct_cmp_u32(int_state + gimli_RATE / 4, pub_mac, hydro_kx_AEAD_MACBYTES / 4);
|
122
|
+
hydro_mem_ct_zero_u32(int_state, gimli_BLOCKBYTES / 4);
|
123
|
+
if (cv != 0) {
|
124
|
+
mem_zero(m, mlen);
|
125
|
+
return -1;
|
126
|
+
}
|
127
|
+
return 0;
|
128
|
+
}
|
129
|
+
|
130
|
+
/* -- */
|
131
|
+
|
132
|
+
void
|
133
|
+
hydro_kx_keygen(hydro_kx_keypair *static_kp)
|
134
|
+
{
|
135
|
+
hydro_random_buf(static_kp->sk, hydro_kx_SECRETKEYBYTES);
|
136
|
+
if (hydro_x25519_scalarmult_base(static_kp->pk, static_kp->sk) != 0) {
|
137
|
+
abort();
|
138
|
+
}
|
139
|
+
}
|
140
|
+
|
141
|
+
void
|
142
|
+
hydro_kx_keygen_deterministic(hydro_kx_keypair *static_kp, const uint8_t seed[hydro_kx_SEEDBYTES])
|
143
|
+
{
|
144
|
+
COMPILER_ASSERT(hydro_kx_SEEDBYTES >= hydro_random_SEEDBYTES);
|
145
|
+
hydro_random_buf_deterministic(static_kp->sk, hydro_kx_SECRETKEYBYTES, seed);
|
146
|
+
if (hydro_x25519_scalarmult_base(static_kp->pk, static_kp->sk) != 0) {
|
147
|
+
abort();
|
148
|
+
}
|
149
|
+
}
|
150
|
+
|
151
|
+
static void
|
152
|
+
hydro_kx_init_state(hydro_kx_state *state, const char *name)
|
153
|
+
{
|
154
|
+
mem_zero(state, sizeof *state);
|
155
|
+
hydro_hash_init(&state->h_st, hydro_kx_CONTEXT, NULL);
|
156
|
+
hydro_hash_update(&state->h_st, name, strlen(name));
|
157
|
+
hydro_hash_final(&state->h_st, NULL, 0);
|
158
|
+
}
|
159
|
+
|
160
|
+
static void
|
161
|
+
hydro_kx_final(hydro_kx_state *state, uint8_t session_k1[hydro_kx_SESSIONKEYBYTES],
|
162
|
+
uint8_t session_k2[hydro_kx_SESSIONKEYBYTES])
|
163
|
+
{
|
164
|
+
uint8_t kdf_key[hydro_kdf_KEYBYTES];
|
165
|
+
|
166
|
+
hydro_hash_final(&state->h_st, kdf_key, sizeof kdf_key);
|
167
|
+
hydro_kdf_derive_from_key(session_k1, hydro_kx_SESSIONKEYBYTES, 0, hydro_kx_CONTEXT, kdf_key);
|
168
|
+
hydro_kdf_derive_from_key(session_k2, hydro_kx_SESSIONKEYBYTES, 1, hydro_kx_CONTEXT, kdf_key);
|
169
|
+
}
|
170
|
+
|
171
|
+
static int
|
172
|
+
hydro_kx_dh(hydro_kx_state *state, const uint8_t sk[hydro_x25519_SECRETKEYBYTES],
|
173
|
+
const uint8_t pk[hydro_x25519_PUBLICKEYBYTES])
|
174
|
+
{
|
175
|
+
uint8_t dh_result[hydro_x25519_BYTES];
|
176
|
+
|
177
|
+
if (hydro_x25519_scalarmult(dh_result, sk, pk, 1) != 0) {
|
178
|
+
return -1;
|
179
|
+
}
|
180
|
+
hydro_hash_update(&state->h_st, dh_result, hydro_x25519_BYTES);
|
181
|
+
|
182
|
+
return 0;
|
183
|
+
}
|
184
|
+
|
185
|
+
static void
|
186
|
+
hydro_kx_eph_keygen(hydro_kx_state *state, hydro_kx_keypair *kp)
|
187
|
+
{
|
188
|
+
hydro_kx_keygen(kp);
|
189
|
+
hydro_hash_update(&state->h_st, kp->pk, sizeof kp->pk);
|
190
|
+
}
|
191
|
+
|
192
|
+
/* NOISE_N */
|
193
|
+
|
194
|
+
int
|
195
|
+
hydro_kx_n_1(hydro_kx_session_keypair *kp, uint8_t packet1[hydro_kx_N_PACKET1BYTES],
|
196
|
+
const uint8_t psk[hydro_kx_PSKBYTES],
|
197
|
+
const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES])
|
198
|
+
{
|
199
|
+
hydro_kx_state state;
|
200
|
+
uint8_t * packet1_eph_pk = &packet1[0];
|
201
|
+
uint8_t * packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
202
|
+
|
203
|
+
if (psk == NULL) {
|
204
|
+
psk = zero;
|
205
|
+
}
|
206
|
+
hydro_kx_init_state(&state, "Noise_Npsk0_hydro1");
|
207
|
+
hydro_hash_update(&state.h_st, peer_static_pk, hydro_x25519_PUBLICKEYBYTES);
|
208
|
+
|
209
|
+
hydro_hash_update(&state.h_st, psk, hydro_kx_PSKBYTES);
|
210
|
+
hydro_kx_eph_keygen(&state, &state.eph_kp);
|
211
|
+
if (hydro_kx_dh(&state, state.eph_kp.sk, peer_static_pk) != 0) {
|
212
|
+
return -1;
|
213
|
+
}
|
214
|
+
hydro_kx_aead_encrypt(&state, packet1_mac, NULL, 0);
|
215
|
+
memcpy(packet1_eph_pk, state.eph_kp.pk, sizeof state.eph_kp.pk);
|
216
|
+
|
217
|
+
hydro_kx_final(&state, kp->rx, kp->tx);
|
218
|
+
|
219
|
+
return 0;
|
220
|
+
}
|
221
|
+
|
222
|
+
int
|
223
|
+
hydro_kx_n_2(hydro_kx_session_keypair *kp, const uint8_t packet1[hydro_kx_N_PACKET1BYTES],
|
224
|
+
const uint8_t psk[hydro_kx_PSKBYTES], const hydro_kx_keypair *static_kp)
|
225
|
+
{
|
226
|
+
hydro_kx_state state;
|
227
|
+
const uint8_t *peer_eph_pk = &packet1[0];
|
228
|
+
const uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
229
|
+
|
230
|
+
if (psk == NULL) {
|
231
|
+
psk = zero;
|
232
|
+
}
|
233
|
+
hydro_kx_init_state(&state, "Noise_Npsk0_hydro1");
|
234
|
+
hydro_hash_update(&state.h_st, static_kp->pk, hydro_kx_PUBLICKEYBYTES);
|
235
|
+
|
236
|
+
hydro_hash_update(&state.h_st, psk, hydro_kx_PSKBYTES);
|
237
|
+
hydro_hash_update(&state.h_st, peer_eph_pk, hydro_x25519_PUBLICKEYBYTES);
|
238
|
+
if (hydro_kx_dh(&state, static_kp->sk, peer_eph_pk) != 0 ||
|
239
|
+
hydro_kx_aead_decrypt(&state, NULL, packet1_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
240
|
+
return -1;
|
241
|
+
}
|
242
|
+
hydro_kx_final(&state, kp->tx, kp->rx);
|
243
|
+
|
244
|
+
return 0;
|
245
|
+
}
|
246
|
+
|
247
|
+
/* NOISE_KK */
|
248
|
+
|
249
|
+
int
|
250
|
+
hydro_kx_kk_1(hydro_kx_state *state, uint8_t packet1[hydro_kx_KK_PACKET1BYTES],
|
251
|
+
const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES],
|
252
|
+
const hydro_kx_keypair *static_kp)
|
253
|
+
{
|
254
|
+
uint8_t *packet1_eph_pk = &packet1[0];
|
255
|
+
uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
256
|
+
|
257
|
+
hydro_kx_init_state(state, "Noise_KK_hydro1");
|
258
|
+
hydro_hash_update(&state->h_st, static_kp->pk, hydro_kx_PUBLICKEYBYTES);
|
259
|
+
hydro_hash_update(&state->h_st, peer_static_pk, hydro_kx_PUBLICKEYBYTES);
|
260
|
+
|
261
|
+
hydro_kx_eph_keygen(state, &state->eph_kp);
|
262
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_static_pk) != 0 ||
|
263
|
+
hydro_kx_dh(state, static_kp->sk, peer_static_pk) != 0) {
|
264
|
+
return -1;
|
265
|
+
}
|
266
|
+
hydro_kx_aead_encrypt(state, packet1_mac, NULL, 0);
|
267
|
+
memcpy(packet1_eph_pk, state->eph_kp.pk, sizeof state->eph_kp.pk);
|
268
|
+
|
269
|
+
return 0;
|
270
|
+
}
|
271
|
+
|
272
|
+
int
|
273
|
+
hydro_kx_kk_2(hydro_kx_session_keypair *kp, uint8_t packet2[hydro_kx_KK_PACKET2BYTES],
|
274
|
+
const uint8_t packet1[hydro_kx_KK_PACKET1BYTES],
|
275
|
+
const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES],
|
276
|
+
const hydro_kx_keypair *static_kp)
|
277
|
+
{
|
278
|
+
hydro_kx_state state;
|
279
|
+
const uint8_t *peer_eph_pk = &packet1[0];
|
280
|
+
const uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
281
|
+
uint8_t * packet2_eph_pk = &packet2[0];
|
282
|
+
uint8_t * packet2_mac = &packet2[hydro_kx_PUBLICKEYBYTES];
|
283
|
+
|
284
|
+
hydro_kx_init_state(&state, "Noise_KK_hydro1");
|
285
|
+
hydro_hash_update(&state.h_st, peer_static_pk, hydro_kx_PUBLICKEYBYTES);
|
286
|
+
hydro_hash_update(&state.h_st, static_kp->pk, hydro_kx_PUBLICKEYBYTES);
|
287
|
+
|
288
|
+
hydro_hash_update(&state.h_st, peer_eph_pk, hydro_kx_PUBLICKEYBYTES);
|
289
|
+
if (hydro_kx_dh(&state, static_kp->sk, peer_eph_pk) != 0 ||
|
290
|
+
hydro_kx_dh(&state, static_kp->sk, peer_static_pk) != 0 ||
|
291
|
+
hydro_kx_aead_decrypt(&state, NULL, packet1_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
292
|
+
return -1;
|
293
|
+
}
|
294
|
+
|
295
|
+
hydro_kx_eph_keygen(&state, &state.eph_kp);
|
296
|
+
if (hydro_kx_dh(&state, state.eph_kp.sk, peer_eph_pk) != 0 ||
|
297
|
+
hydro_kx_dh(&state, state.eph_kp.sk, peer_static_pk) != 0) {
|
298
|
+
return -1;
|
299
|
+
}
|
300
|
+
hydro_kx_aead_encrypt(&state, packet2_mac, NULL, 0);
|
301
|
+
hydro_kx_final(&state, kp->tx, kp->rx);
|
302
|
+
memcpy(packet2_eph_pk, state.eph_kp.pk, sizeof state.eph_kp.pk);
|
303
|
+
|
304
|
+
return 0;
|
305
|
+
}
|
306
|
+
|
307
|
+
int
|
308
|
+
hydro_kx_kk_3(hydro_kx_state *state, hydro_kx_session_keypair *kp,
|
309
|
+
const uint8_t packet2[hydro_kx_KK_PACKET2BYTES], const hydro_kx_keypair *static_kp)
|
310
|
+
{
|
311
|
+
const uint8_t *peer_eph_pk = packet2;
|
312
|
+
const uint8_t *packet2_mac = &packet2[hydro_kx_PUBLICKEYBYTES];
|
313
|
+
|
314
|
+
hydro_hash_update(&state->h_st, peer_eph_pk, hydro_kx_PUBLICKEYBYTES);
|
315
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_eph_pk) != 0 ||
|
316
|
+
hydro_kx_dh(state, static_kp->sk, peer_eph_pk) != 0) {
|
317
|
+
return -1;
|
318
|
+
}
|
319
|
+
|
320
|
+
if (hydro_kx_aead_decrypt(state, NULL, packet2_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
321
|
+
return -1;
|
322
|
+
}
|
323
|
+
hydro_kx_final(state, kp->rx, kp->tx);
|
324
|
+
|
325
|
+
return 0;
|
326
|
+
}
|
327
|
+
|
328
|
+
/* NOISE_XX */
|
329
|
+
|
330
|
+
int
|
331
|
+
hydro_kx_xx_1(hydro_kx_state *state, uint8_t packet1[hydro_kx_XX_PACKET1BYTES],
|
332
|
+
const uint8_t psk[hydro_kx_PSKBYTES])
|
333
|
+
{
|
334
|
+
uint8_t *packet1_eph_pk = &packet1[0];
|
335
|
+
uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
336
|
+
|
337
|
+
if (psk == NULL) {
|
338
|
+
psk = zero;
|
339
|
+
}
|
340
|
+
hydro_kx_init_state(state, "Noise_XXpsk0+psk3_hydro1");
|
341
|
+
|
342
|
+
hydro_kx_eph_keygen(state, &state->eph_kp);
|
343
|
+
hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
|
344
|
+
memcpy(packet1_eph_pk, state->eph_kp.pk, sizeof state->eph_kp.pk);
|
345
|
+
hydro_kx_aead_encrypt(state, packet1_mac, NULL, 0);
|
346
|
+
|
347
|
+
return 0;
|
348
|
+
}
|
349
|
+
|
350
|
+
int
|
351
|
+
hydro_kx_xx_2(hydro_kx_state *state, uint8_t packet2[hydro_kx_XX_PACKET2BYTES],
|
352
|
+
const uint8_t packet1[hydro_kx_XX_PACKET1BYTES], const uint8_t psk[hydro_kx_PSKBYTES],
|
353
|
+
const hydro_kx_keypair *static_kp)
|
354
|
+
{
|
355
|
+
const uint8_t *peer_eph_pk = &packet1[0];
|
356
|
+
const uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
357
|
+
uint8_t * packet2_eph_pk = &packet2[0];
|
358
|
+
uint8_t * packet2_enc_static_pk = &packet2[hydro_kx_PUBLICKEYBYTES];
|
359
|
+
uint8_t * packet2_mac =
|
360
|
+
&packet2[hydro_kx_PUBLICKEYBYTES + hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES];
|
361
|
+
|
362
|
+
if (psk == NULL) {
|
363
|
+
psk = zero;
|
364
|
+
}
|
365
|
+
hydro_kx_init_state(state, "Noise_XXpsk0+psk3_hydro1");
|
366
|
+
|
367
|
+
hydro_hash_update(&state->h_st, peer_eph_pk, hydro_kx_PUBLICKEYBYTES);
|
368
|
+
hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
|
369
|
+
if (hydro_kx_aead_decrypt(state, NULL, packet1_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
370
|
+
return -1;
|
371
|
+
}
|
372
|
+
|
373
|
+
hydro_kx_eph_keygen(state, &state->eph_kp);
|
374
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_eph_pk) != 0) {
|
375
|
+
return -1;
|
376
|
+
}
|
377
|
+
hydro_kx_aead_encrypt(state, packet2_enc_static_pk, static_kp->pk, sizeof static_kp->pk);
|
378
|
+
if (hydro_kx_dh(state, static_kp->sk, peer_eph_pk) != 0) {
|
379
|
+
return -1;
|
380
|
+
}
|
381
|
+
hydro_kx_aead_encrypt(state, packet2_mac, NULL, 0);
|
382
|
+
|
383
|
+
memcpy(packet2_eph_pk, state->eph_kp.pk, sizeof state->eph_kp.pk);
|
384
|
+
|
385
|
+
return 0;
|
386
|
+
}
|
387
|
+
|
388
|
+
int
|
389
|
+
hydro_kx_xx_3(hydro_kx_state *state, hydro_kx_session_keypair *kp,
|
390
|
+
uint8_t packet3[hydro_kx_XX_PACKET3BYTES],
|
391
|
+
uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES],
|
392
|
+
const uint8_t packet2[hydro_kx_XX_PACKET2BYTES], const uint8_t psk[hydro_kx_PSKBYTES],
|
393
|
+
const hydro_kx_keypair *static_kp)
|
394
|
+
{
|
395
|
+
uint8_t peer_static_pk_[hydro_kx_PUBLICKEYBYTES];
|
396
|
+
const uint8_t *peer_eph_pk = &packet2[0];
|
397
|
+
const uint8_t *peer_enc_static_pk = &packet2[hydro_kx_PUBLICKEYBYTES];
|
398
|
+
const uint8_t *packet2_mac =
|
399
|
+
&packet2[hydro_kx_PUBLICKEYBYTES + hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES];
|
400
|
+
uint8_t *packet3_enc_static_pk = &packet3[0];
|
401
|
+
uint8_t *packet3_mac = &packet3[hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES];
|
402
|
+
|
403
|
+
if (psk == NULL) {
|
404
|
+
psk = zero;
|
405
|
+
}
|
406
|
+
if (peer_static_pk == NULL) {
|
407
|
+
peer_static_pk = peer_static_pk_;
|
408
|
+
}
|
409
|
+
hydro_hash_update(&state->h_st, peer_eph_pk, hydro_kx_PUBLICKEYBYTES);
|
410
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_eph_pk) != 0 ||
|
411
|
+
hydro_kx_aead_decrypt(state, peer_static_pk, peer_enc_static_pk,
|
412
|
+
hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES) != 0 ||
|
413
|
+
hydro_kx_dh(state, state->eph_kp.sk, peer_static_pk) != 0 ||
|
414
|
+
hydro_kx_aead_decrypt(state, NULL, packet2_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
415
|
+
return -1;
|
416
|
+
}
|
417
|
+
|
418
|
+
hydro_kx_aead_encrypt(state, packet3_enc_static_pk, static_kp->pk, sizeof static_kp->pk);
|
419
|
+
if (hydro_kx_dh(state, static_kp->sk, peer_eph_pk) != 0) {
|
420
|
+
return -1;
|
421
|
+
}
|
422
|
+
hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
|
423
|
+
hydro_kx_aead_encrypt(state, packet3_mac, NULL, 0);
|
424
|
+
hydro_kx_final(state, kp->rx, kp->tx);
|
425
|
+
|
426
|
+
return 0;
|
427
|
+
}
|
428
|
+
|
429
|
+
int
|
430
|
+
hydro_kx_xx_4(hydro_kx_state *state, hydro_kx_session_keypair *kp,
|
431
|
+
uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES],
|
432
|
+
const uint8_t packet3[hydro_kx_XX_PACKET3BYTES], const uint8_t psk[hydro_kx_PSKBYTES])
|
433
|
+
{
|
434
|
+
uint8_t peer_static_pk_[hydro_kx_PUBLICKEYBYTES];
|
435
|
+
const uint8_t *peer_enc_static_pk = &packet3[0];
|
436
|
+
const uint8_t *packet3_mac = &packet3[hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES];
|
437
|
+
|
438
|
+
if (psk == NULL) {
|
439
|
+
psk = zero;
|
440
|
+
}
|
441
|
+
if (peer_static_pk == NULL) {
|
442
|
+
peer_static_pk = peer_static_pk_;
|
443
|
+
}
|
444
|
+
if (hydro_kx_aead_decrypt(state, peer_static_pk, peer_enc_static_pk,
|
445
|
+
hydro_kx_PUBLICKEYBYTES + hydro_kx_AEAD_MACBYTES) != 0 ||
|
446
|
+
hydro_kx_dh(state, state->eph_kp.sk, peer_static_pk) != 0) {
|
447
|
+
return -1;
|
448
|
+
}
|
449
|
+
hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
|
450
|
+
if (hydro_kx_aead_decrypt(state, NULL, packet3_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
451
|
+
return -1;
|
452
|
+
}
|
453
|
+
hydro_kx_final(state, kp->tx, kp->rx);
|
454
|
+
|
455
|
+
return 0;
|
456
|
+
}
|
457
|
+
|
458
|
+
/* NOISE_NK */
|
459
|
+
|
460
|
+
int
|
461
|
+
hydro_kx_nk_1(hydro_kx_state *state, uint8_t packet1[hydro_kx_NK_PACKET1BYTES],
|
462
|
+
const uint8_t psk[hydro_kx_PSKBYTES],
|
463
|
+
const uint8_t peer_static_pk[hydro_kx_PUBLICKEYBYTES])
|
464
|
+
{
|
465
|
+
uint8_t *packet1_eph_pk = &packet1[0];
|
466
|
+
uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
467
|
+
|
468
|
+
if (psk == NULL) {
|
469
|
+
psk = zero;
|
470
|
+
}
|
471
|
+
hydro_kx_init_state(state, "Noise_NKpsk0_hydro1");
|
472
|
+
hydro_hash_update(&state->h_st, peer_static_pk, hydro_x25519_PUBLICKEYBYTES);
|
473
|
+
|
474
|
+
hydro_hash_update(&state->h_st, psk, hydro_kx_PSKBYTES);
|
475
|
+
hydro_kx_eph_keygen(state, &state->eph_kp);
|
476
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_static_pk) != 0) {
|
477
|
+
return -1;
|
478
|
+
}
|
479
|
+
hydro_kx_aead_encrypt(state, packet1_mac, NULL, 0);
|
480
|
+
memcpy(packet1_eph_pk, state->eph_kp.pk, sizeof state->eph_kp.pk);
|
481
|
+
|
482
|
+
return 0;
|
483
|
+
}
|
484
|
+
|
485
|
+
int
|
486
|
+
hydro_kx_nk_2(hydro_kx_session_keypair *kp, uint8_t packet2[hydro_kx_NK_PACKET2BYTES],
|
487
|
+
const uint8_t packet1[hydro_kx_NK_PACKET1BYTES], const uint8_t psk[hydro_kx_PSKBYTES],
|
488
|
+
const hydro_kx_keypair *static_kp)
|
489
|
+
{
|
490
|
+
hydro_kx_state state;
|
491
|
+
const uint8_t *peer_eph_pk = &packet1[0];
|
492
|
+
const uint8_t *packet1_mac = &packet1[hydro_kx_PUBLICKEYBYTES];
|
493
|
+
uint8_t * packet2_eph_pk = &packet2[0];
|
494
|
+
uint8_t * packet2_mac = &packet2[hydro_kx_PUBLICKEYBYTES];
|
495
|
+
|
496
|
+
if (psk == NULL) {
|
497
|
+
psk = zero;
|
498
|
+
}
|
499
|
+
hydro_kx_init_state(&state, "Noise_NKpsk0_hydro1");
|
500
|
+
hydro_hash_update(&state.h_st, static_kp->pk, hydro_kx_PUBLICKEYBYTES);
|
501
|
+
|
502
|
+
hydro_hash_update(&state.h_st, psk, hydro_kx_PSKBYTES);
|
503
|
+
hydro_hash_update(&state.h_st, peer_eph_pk, hydro_x25519_PUBLICKEYBYTES);
|
504
|
+
if (hydro_kx_dh(&state, static_kp->sk, peer_eph_pk) != 0 ||
|
505
|
+
hydro_kx_aead_decrypt(&state, NULL, packet1_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
506
|
+
return -1;
|
507
|
+
}
|
508
|
+
|
509
|
+
hydro_kx_eph_keygen(&state, &state.eph_kp);
|
510
|
+
if (hydro_kx_dh(&state, state.eph_kp.sk, peer_eph_pk) != 0) {
|
511
|
+
return -1;
|
512
|
+
}
|
513
|
+
hydro_kx_aead_encrypt(&state, packet2_mac, NULL, 0);
|
514
|
+
hydro_kx_final(&state, kp->tx, kp->rx);
|
515
|
+
memcpy(packet2_eph_pk, state.eph_kp.pk, sizeof state.eph_kp.pk);
|
516
|
+
|
517
|
+
return 0;
|
518
|
+
}
|
519
|
+
|
520
|
+
int
|
521
|
+
hydro_kx_nk_3(hydro_kx_state *state, hydro_kx_session_keypair *kp,
|
522
|
+
const uint8_t packet2[hydro_kx_NK_PACKET2BYTES])
|
523
|
+
{
|
524
|
+
const uint8_t *peer_eph_pk = &packet2[0];
|
525
|
+
const uint8_t *packet2_mac = &packet2[hydro_kx_PUBLICKEYBYTES];
|
526
|
+
|
527
|
+
hydro_hash_update(&state->h_st, peer_eph_pk, hydro_x25519_PUBLICKEYBYTES);
|
528
|
+
if (hydro_kx_dh(state, state->eph_kp.sk, peer_eph_pk) != 0 ||
|
529
|
+
hydro_kx_aead_decrypt(state, NULL, packet2_mac, hydro_kx_AEAD_MACBYTES) != 0) {
|
530
|
+
return -1;
|
531
|
+
}
|
532
|
+
hydro_kx_final(state, kp->rx, kp->tx);
|
533
|
+
|
534
|
+
return 0;
|
535
|
+
}
|