1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
#include <stddef.h>
#include "core.h"
#include "crypto_generichash.h"
#include "crypto_kx.h"
#include "crypto_scalarmult.h"
#include "private/common.h"
#include "randombytes.h"
#include "utils.h"
int
crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
unsigned char sk[crypto_kx_SECRETKEYBYTES],
const unsigned char seed[crypto_kx_SEEDBYTES])
{
crypto_generichash(sk, crypto_kx_SECRETKEYBYTES,
seed, crypto_kx_SEEDBYTES, NULL, 0);
return crypto_scalarmult_base(pk, sk);
}
int
crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],
unsigned char sk[crypto_kx_SECRETKEYBYTES])
{
COMPILER_ASSERT(crypto_kx_SECRETKEYBYTES == crypto_scalarmult_SCALARBYTES);
COMPILER_ASSERT(crypto_kx_PUBLICKEYBYTES == crypto_scalarmult_BYTES);
randombytes_buf(sk, crypto_kx_SECRETKEYBYTES);
return crypto_scalarmult_base(pk, sk);
}
int
crypto_kx_client_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
unsigned char tx[crypto_kx_SESSIONKEYBYTES],
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES],
const unsigned char client_sk[crypto_kx_SECRETKEYBYTES],
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES])
{
crypto_generichash_state h;
unsigned char q[crypto_scalarmult_BYTES];
unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES];
int i;
if (rx == NULL) {
rx = tx;
}
if (tx == NULL) {
tx = rx;
}
if (rx == NULL) {
sodium_misuse(); /* LCOV_EXCL_LINE */
}
if (crypto_scalarmult(q, client_sk, server_pk) != 0) {
return -1;
}
COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX);
crypto_generichash_init(&h, NULL, 0U, sizeof keys);
crypto_generichash_update(&h, q, crypto_scalarmult_BYTES);
sodium_memzero(q, sizeof q);
crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
crypto_generichash_final(&h, keys, sizeof keys);
sodium_memzero(&h, sizeof h);
for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) {
rx[i] = keys[i]; /* rx cannot be NULL */
tx[i] = keys[i + crypto_kx_SESSIONKEYBYTES]; /* tx cannot be NULL */
}
sodium_memzero(keys, sizeof keys);
return 0;
}
int
crypto_kx_server_session_keys(unsigned char rx[crypto_kx_SESSIONKEYBYTES],
unsigned char tx[crypto_kx_SESSIONKEYBYTES],
const unsigned char server_pk[crypto_kx_PUBLICKEYBYTES],
const unsigned char server_sk[crypto_kx_SECRETKEYBYTES],
const unsigned char client_pk[crypto_kx_PUBLICKEYBYTES])
{
crypto_generichash_state h;
unsigned char q[crypto_scalarmult_BYTES];
unsigned char keys[2 * crypto_kx_SESSIONKEYBYTES];
int i;
if (rx == NULL) {
rx = tx;
}
if (tx == NULL) {
tx = rx;
}
if (rx == NULL) {
sodium_misuse(); /* LCOV_EXCL_LINE */
}
if (crypto_scalarmult(q, server_sk, client_pk) != 0) {
return -1;
}
COMPILER_ASSERT(sizeof keys <= crypto_generichash_BYTES_MAX);
crypto_generichash_init(&h, NULL, 0U, sizeof keys);
crypto_generichash_update(&h, q, crypto_scalarmult_BYTES);
sodium_memzero(q, sizeof q);
crypto_generichash_update(&h, client_pk, crypto_kx_PUBLICKEYBYTES);
crypto_generichash_update(&h, server_pk, crypto_kx_PUBLICKEYBYTES);
crypto_generichash_final(&h, keys, sizeof keys);
sodium_memzero(&h, sizeof h);
for (i = 0; i < crypto_kx_SESSIONKEYBYTES; i++) {
tx[i] = keys[i];
rx[i] = keys[i + crypto_kx_SESSIONKEYBYTES];
}
sodium_memzero(keys, sizeof keys);
return 0;
}
size_t
crypto_kx_publickeybytes(void)
{
return crypto_kx_PUBLICKEYBYTES;
}
size_t
crypto_kx_secretkeybytes(void)
{
return crypto_kx_SECRETKEYBYTES;
}
size_t
crypto_kx_seedbytes(void)
{
return crypto_kx_SEEDBYTES;
}
size_t
crypto_kx_sessionkeybytes(void)
{
return crypto_kx_SESSIONKEYBYTES;
}
const char *
crypto_kx_primitive(void)
{
return crypto_kx_PRIMITIVE;
}
|