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