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 
12 int
crypto_kx_seed_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],unsigned char sk[crypto_kx_SECRETKEYBYTES],const unsigned char seed[crypto_kx_SEEDBYTES])13 crypto_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 
22 int
crypto_kx_keypair(unsigned char pk[crypto_kx_PUBLICKEYBYTES],unsigned char sk[crypto_kx_SECRETKEYBYTES])23 crypto_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 
33 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])34 crypto_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 
74 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])75 crypto_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 
115 size_t
crypto_kx_publickeybytes(void)116 crypto_kx_publickeybytes(void)
117 {
118     return crypto_kx_PUBLICKEYBYTES;
119 }
120 
121 size_t
crypto_kx_secretkeybytes(void)122 crypto_kx_secretkeybytes(void)
123 {
124     return crypto_kx_SECRETKEYBYTES;
125 }
126 
127 size_t
crypto_kx_seedbytes(void)128 crypto_kx_seedbytes(void)
129 {
130     return crypto_kx_SEEDBYTES;
131 }
132 
133 size_t
crypto_kx_sessionkeybytes(void)134 crypto_kx_sessionkeybytes(void)
135 {
136     return crypto_kx_SESSIONKEYBYTES;
137 }
138 
139 const char *
crypto_kx_primitive(void)140 crypto_kx_primitive(void)
141 {
142     return crypto_kx_PRIMITIVE;
143 }
144