/work/toxcore/crypto_core.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* SPDX-License-Identifier: GPL-3.0-or-later |
2 | | * Copyright © 2016-2025 The TokTok team. |
3 | | * Copyright © 2013 Tox project. |
4 | | */ |
5 | | |
6 | | #include "crypto_core.h" |
7 | | |
8 | | #include <assert.h> |
9 | | #include <string.h> |
10 | | |
11 | | #include <sodium.h> |
12 | | |
13 | | #include "attributes.h" |
14 | | #include "ccompat.h" |
15 | | #include "mem.h" |
16 | | #include "tox_random.h" |
17 | | #include "util.h" |
18 | | |
19 | | static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES, |
20 | | "CRYPTO_PUBLIC_KEY_SIZE should be equal to crypto_box_PUBLICKEYBYTES"); |
21 | | static_assert(CRYPTO_SECRET_KEY_SIZE == crypto_box_SECRETKEYBYTES, |
22 | | "CRYPTO_SECRET_KEY_SIZE should be equal to crypto_box_SECRETKEYBYTES"); |
23 | | static_assert(CRYPTO_SHARED_KEY_SIZE == crypto_box_BEFORENMBYTES, |
24 | | "CRYPTO_SHARED_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES"); |
25 | | static_assert(CRYPTO_SYMMETRIC_KEY_SIZE == crypto_box_BEFORENMBYTES, |
26 | | "CRYPTO_SYMMETRIC_KEY_SIZE should be equal to crypto_box_BEFORENMBYTES"); |
27 | | static_assert(CRYPTO_MAC_SIZE == crypto_box_MACBYTES, |
28 | | "CRYPTO_MAC_SIZE should be equal to crypto_box_MACBYTES"); |
29 | | static_assert(CRYPTO_NONCE_SIZE == crypto_box_NONCEBYTES, |
30 | | "CRYPTO_NONCE_SIZE should be equal to crypto_box_NONCEBYTES"); |
31 | | static_assert(CRYPTO_HMAC_SIZE == crypto_auth_BYTES, |
32 | | "CRYPTO_HMAC_SIZE should be equal to crypto_auth_BYTES"); |
33 | | static_assert(CRYPTO_HMAC_KEY_SIZE == crypto_auth_KEYBYTES, |
34 | | "CRYPTO_HMAC_KEY_SIZE should be equal to crypto_auth_KEYBYTES"); |
35 | | static_assert(CRYPTO_SHA256_SIZE == crypto_hash_sha256_BYTES, |
36 | | "CRYPTO_SHA256_SIZE should be equal to crypto_hash_sha256_BYTES"); |
37 | | static_assert(CRYPTO_SHA512_SIZE == crypto_hash_sha512_BYTES, |
38 | | "CRYPTO_SHA512_SIZE should be equal to crypto_hash_sha512_BYTES"); |
39 | | static_assert(CRYPTO_PUBLIC_KEY_SIZE == 32, |
40 | | "CRYPTO_PUBLIC_KEY_SIZE is required to be 32 bytes for pk_equal to work"); |
41 | | |
42 | | static_assert(CRYPTO_SIGNATURE_SIZE == crypto_sign_BYTES, |
43 | | "CRYPTO_SIGNATURE_SIZE should be equal to crypto_sign_BYTES"); |
44 | | static_assert(CRYPTO_SIGN_PUBLIC_KEY_SIZE == crypto_sign_PUBLICKEYBYTES, |
45 | | "CRYPTO_SIGN_PUBLIC_KEY_SIZE should be equal to crypto_sign_PUBLICKEYBYTES"); |
46 | | static_assert(CRYPTO_SIGN_SECRET_KEY_SIZE == crypto_sign_SECRETKEYBYTES, |
47 | | "CRYPTO_SIGN_SECRET_KEY_SIZE should be equal to crypto_sign_SECRETKEYBYTES"); |
48 | | |
49 | | bool create_extended_keypair(Extended_Public_Key *pk, Extended_Secret_Key *sk, const Random *rng) |
50 | 345 | { |
51 | | /* create signature key pair */ |
52 | 345 | uint8_t seed[crypto_sign_SEEDBYTES]; |
53 | 345 | random_bytes(rng, seed, crypto_sign_SEEDBYTES); |
54 | 345 | crypto_sign_seed_keypair(pk->sig, sk->sig, seed); |
55 | 345 | crypto_memzero(seed, crypto_sign_SEEDBYTES); |
56 | | |
57 | | /* convert public signature key to public encryption key */ |
58 | 345 | const int res1 = crypto_sign_ed25519_pk_to_curve25519(pk->enc, pk->sig); |
59 | | |
60 | | /* convert secret signature key to secret encryption key */ |
61 | 345 | const int res2 = crypto_sign_ed25519_sk_to_curve25519(sk->enc, sk->sig); |
62 | | |
63 | 345 | return res1 == 0 && res2 == 0; |
64 | 345 | } |
65 | | |
66 | | const uint8_t *get_enc_key(const Extended_Public_Key *key) |
67 | 4.04k | { |
68 | 4.04k | return key->enc; |
69 | 4.04k | } |
70 | | |
71 | | const uint8_t *get_sig_pk(const Extended_Public_Key *key) |
72 | 7.89k | { |
73 | 7.89k | return key->sig; |
74 | 7.89k | } |
75 | | |
76 | | void set_sig_pk(Extended_Public_Key *key, const uint8_t *sig_pk) |
77 | 368 | { |
78 | 368 | memcpy(key->sig, sig_pk, SIG_PUBLIC_KEY_SIZE); |
79 | 368 | } |
80 | | |
81 | | const uint8_t *get_sig_sk(const Extended_Secret_Key *key) |
82 | 1.38k | { |
83 | 1.38k | return key->sig; |
84 | 1.38k | } |
85 | | |
86 | | const uint8_t *get_chat_id(const Extended_Public_Key *key) |
87 | 13.2k | { |
88 | 13.2k | return key->sig; |
89 | 13.2k | } |
90 | | |
91 | | #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
92 | | static uint8_t *crypto_malloc(const Memory *_Nonnull mem, size_t bytes) |
93 | 4.18M | { |
94 | 4.18M | uint8_t *ptr = (uint8_t *)mem_balloc(mem, bytes); |
95 | | |
96 | 4.18M | if (ptr != nullptr) { |
97 | 4.17M | crypto_memlock(ptr, bytes); |
98 | 4.17M | } |
99 | | |
100 | 4.18M | return ptr; |
101 | 4.18M | } |
102 | | |
103 | | static void crypto_free(const Memory *_Nonnull mem, uint8_t *_Nullable ptr, size_t bytes) |
104 | 4.18M | { |
105 | 4.18M | if (ptr != nullptr) { |
106 | 4.17M | crypto_memzero(ptr, bytes); |
107 | 4.17M | crypto_memunlock(ptr, bytes); |
108 | 4.17M | } |
109 | | |
110 | 4.18M | mem_delete(mem, ptr); |
111 | 4.18M | } |
112 | | #endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */ |
113 | | |
114 | | void crypto_memzero(void *data, size_t length) |
115 | 4.39M | { |
116 | 4.39M | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
117 | 4.39M | memzero((uint8_t *)data, length); |
118 | | #else |
119 | | sodium_memzero(data, length); |
120 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
121 | 4.39M | } |
122 | | |
123 | | bool crypto_memlock(void *data, size_t length) |
124 | 9.81k | { |
125 | 9.81k | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
126 | 9.81k | return false; |
127 | | #else |
128 | | |
129 | | return sodium_mlock(data, length) == 0; |
130 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
131 | 9.81k | } |
132 | | |
133 | | bool crypto_memunlock(void *data, size_t length) |
134 | 23.0k | { |
135 | 23.0k | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
136 | 23.0k | return false; |
137 | | #else |
138 | | |
139 | | return sodium_munlock(data, length) == 0; |
140 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
141 | 23.0k | } |
142 | | |
143 | | bool pk_equal(const uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE]) |
144 | 1.13G | { |
145 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
146 | | // Hope that this is better for the fuzzer |
147 | 569M | return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0; |
148 | | #else |
149 | | return crypto_verify_32(pk1, pk2) == 0; |
150 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
151 | 1.13G | } Line | Count | Source | 144 | 569M | { | 145 | 569M | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 146 | | // Hope that this is better for the fuzzer | 147 | 569M | return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0; | 148 | | #else | 149 | | return crypto_verify_32(pk1, pk2) == 0; | 150 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 151 | 569M | } |
Line | Count | Source | 144 | 569M | { | 145 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 146 | | // Hope that this is better for the fuzzer | 147 | | return memcmp(pk1, pk2, CRYPTO_PUBLIC_KEY_SIZE) == 0; | 148 | | #else | 149 | 569M | return crypto_verify_32(pk1, pk2) == 0; | 150 | 569M | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 151 | 569M | } |
|
152 | | |
153 | | void pk_copy(uint8_t dest[CRYPTO_PUBLIC_KEY_SIZE], const uint8_t src[CRYPTO_PUBLIC_KEY_SIZE]) |
154 | 56.0k | { |
155 | 56.0k | memcpy(dest, src, CRYPTO_PUBLIC_KEY_SIZE); |
156 | 56.0k | } |
157 | | |
158 | | bool crypto_sha512_eq(const uint8_t cksum1[CRYPTO_SHA512_SIZE], const uint8_t cksum2[CRYPTO_SHA512_SIZE]) |
159 | 3.22k | { |
160 | | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
161 | | // Hope that this is better for the fuzzer |
162 | 1.61k | return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0; |
163 | | #else |
164 | | return crypto_verify_64(cksum1, cksum2) == 0; |
165 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
166 | 3.22k | } Line | Count | Source | 159 | 1.61k | { | 160 | 1.61k | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) | 161 | | // Hope that this is better for the fuzzer | 162 | 1.61k | return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0; | 163 | | #else | 164 | | return crypto_verify_64(cksum1, cksum2) == 0; | 165 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 166 | 1.61k | } |
Line | Count | Source | 159 | 1.61k | { | 160 | | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) | 161 | | // Hope that this is better for the fuzzer | 162 | | return memcmp(cksum1, cksum2, CRYPTO_SHA512_SIZE) == 0; | 163 | | #else | 164 | 1.61k | return crypto_verify_64(cksum1, cksum2) == 0; | 165 | 1.61k | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 166 | 1.61k | } |
|
167 | | |
168 | | bool crypto_sha256_eq(const uint8_t cksum1[CRYPTO_SHA256_SIZE], const uint8_t cksum2[CRYPTO_SHA256_SIZE]) |
169 | 0 | { |
170 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
171 | | // Hope that this is better for the fuzzer |
172 | 0 | return memcmp(cksum1, cksum2, CRYPTO_SHA256_SIZE) == 0; |
173 | | #else |
174 | | return crypto_verify_32(cksum1, cksum2) == 0; |
175 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
176 | 0 | } Unexecuted instantiation: crypto_sha256_eq Unexecuted instantiation: crypto_sha256_eq |
177 | | |
178 | | uint8_t random_u08(const Random *rng) |
179 | 17.0k | { |
180 | 17.0k | uint8_t randnum; |
181 | 17.0k | random_bytes(rng, &randnum, 1); |
182 | 17.0k | return randnum; |
183 | 17.0k | } |
184 | | |
185 | | uint16_t random_u16(const Random *rng) |
186 | 428 | { |
187 | 428 | uint16_t randnum; |
188 | 428 | random_bytes(rng, (uint8_t *)&randnum, sizeof(randnum)); |
189 | 428 | return randnum; |
190 | 428 | } |
191 | | |
192 | | uint32_t random_u32(const Random *rng) |
193 | 517k | { |
194 | 517k | uint32_t randnum; |
195 | 517k | random_bytes(rng, (uint8_t *)&randnum, sizeof(randnum)); |
196 | 517k | return randnum; |
197 | 517k | } |
198 | | |
199 | | uint64_t random_u64(const Random *rng) |
200 | 179k | { |
201 | 179k | uint64_t randnum; |
202 | 179k | random_bytes(rng, (uint8_t *)&randnum, sizeof(randnum)); |
203 | 179k | return randnum; |
204 | 179k | } |
205 | | |
206 | | uint32_t random_range_u32(const Random *rng, uint32_t upper_bound) |
207 | 247k | { |
208 | 247k | return tox_random_uniform(rng, upper_bound); |
209 | 247k | } |
210 | | |
211 | | bool crypto_signature_create(uint8_t signature[CRYPTO_SIGNATURE_SIZE], |
212 | | const uint8_t *message, uint64_t message_length, |
213 | | const uint8_t secret_key[SIG_SECRET_KEY_SIZE]) |
214 | 240 | { |
215 | 240 | return crypto_sign_detached(signature, nullptr, message, message_length, secret_key) == 0; |
216 | 240 | } |
217 | | |
218 | | bool crypto_signature_verify(const uint8_t signature[CRYPTO_SIGNATURE_SIZE], |
219 | | const uint8_t *message, uint64_t message_length, |
220 | | const uint8_t public_key[SIG_PUBLIC_KEY_SIZE]) |
221 | 360 | { |
222 | 360 | return crypto_sign_verify_detached(signature, message, message_length, public_key) == 0; |
223 | 360 | } |
224 | | |
225 | | bool public_key_valid(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]) |
226 | 1.79k | { |
227 | | /* Last bit of key is always zero. */ |
228 | 1.79k | return public_key[31] < 128; |
229 | 1.79k | } |
230 | | |
231 | | int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], |
232 | | const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], |
233 | | uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]) |
234 | 450k | { |
235 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
236 | 225k | memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE); |
237 | | return 0; |
238 | | #else |
239 | | return crypto_box_beforenm(shared_key, public_key, secret_key); |
240 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
241 | 450k | } Line | Count | Source | 234 | 225k | { | 235 | 225k | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 236 | 225k | memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE); | 237 | 225k | return 0; | 238 | | #else | 239 | | return crypto_box_beforenm(shared_key, public_key, secret_key); | 240 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 241 | 225k | } |
Line | Count | Source | 234 | 225k | { | 235 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 236 | | memcpy(shared_key, public_key, CRYPTO_SHARED_KEY_SIZE); | 237 | | return 0; | 238 | | #else | 239 | 225k | return crypto_box_beforenm(shared_key, public_key, secret_key); | 240 | 225k | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 241 | 225k | } |
|
242 | | |
243 | | int32_t encrypt_data_symmetric(const Memory *mem, |
244 | | const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], |
245 | | const uint8_t nonce[CRYPTO_NONCE_SIZE], |
246 | | const uint8_t *plain, size_t length, uint8_t *encrypted) |
247 | 1.13M | { |
248 | 1.13M | if (length == 0 || shared_key == nullptr || nonce == nullptr || plain == nullptr || encrypted == nullptr) { |
249 | 0 | return -1; |
250 | 0 | } |
251 | | |
252 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
253 | | // Don't encrypt anything. |
254 | 0 | memcpy(encrypted, plain, length); |
255 | | // Zero MAC to avoid uninitialized memory reads. |
256 | 0 | memzero(encrypted + length, crypto_box_MACBYTES); |
257 | | #else |
258 | | |
259 | 1.13M | const size_t size_temp_plain = length + crypto_box_ZEROBYTES; |
260 | 1.13M | const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; |
261 | | |
262 | 1.13M | uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); |
263 | 1.13M | uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); |
264 | | |
265 | 1.13M | if (temp_plain == nullptr || temp_encrypted == nullptr) { |
266 | 502 | crypto_free(mem, temp_plain, size_temp_plain); |
267 | 502 | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
268 | 502 | return -1; |
269 | 502 | } |
270 | | |
271 | | // crypto_box_afternm requires the entire range of the output array be |
272 | | // initialised with something. It doesn't matter what it's initialised with, |
273 | | // so we'll pick 0x00. |
274 | 1.13M | memzero(temp_encrypted, size_temp_encrypted); |
275 | | |
276 | 1.13M | memzero(temp_plain, crypto_box_ZEROBYTES); |
277 | | // Pad the message with 32 0 bytes. |
278 | 1.13M | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); |
279 | | |
280 | 1.13M | if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, |
281 | 1.13M | shared_key) != 0) { |
282 | 0 | crypto_free(mem, temp_plain, size_temp_plain); |
283 | 0 | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
284 | 0 | return -1; |
285 | 0 | } |
286 | | |
287 | | // Unpad the encrypted message. |
288 | 1.13M | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); |
289 | | |
290 | 1.13M | crypto_free(mem, temp_plain, size_temp_plain); |
291 | 1.13M | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
292 | 1.13M | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
293 | 1.13M | assert(length < INT32_MAX - crypto_box_MACBYTES); |
294 | 1.13M | return (int32_t)(length + crypto_box_MACBYTES); |
295 | 1.13M | } Unexecuted instantiation: encrypt_data_symmetric Line | Count | Source | 247 | 1.13M | { | 248 | 1.13M | if (length == 0 || shared_key == nullptr || nonce == nullptr || plain == nullptr || encrypted == nullptr) { | 249 | 0 | return -1; | 250 | 0 | } | 251 | | | 252 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 253 | | // Don't encrypt anything. | 254 | | memcpy(encrypted, plain, length); | 255 | | // Zero MAC to avoid uninitialized memory reads. | 256 | | memzero(encrypted + length, crypto_box_MACBYTES); | 257 | | #else | 258 | | | 259 | 1.13M | const size_t size_temp_plain = length + crypto_box_ZEROBYTES; | 260 | 1.13M | const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; | 261 | | | 262 | 1.13M | uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); | 263 | 1.13M | uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); | 264 | | | 265 | 1.13M | if (temp_plain == nullptr || temp_encrypted == nullptr) { | 266 | 502 | crypto_free(mem, temp_plain, size_temp_plain); | 267 | 502 | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 268 | 502 | return -1; | 269 | 502 | } | 270 | | | 271 | | // crypto_box_afternm requires the entire range of the output array be | 272 | | // initialised with something. It doesn't matter what it's initialised with, | 273 | | // so we'll pick 0x00. | 274 | 1.13M | memzero(temp_encrypted, size_temp_encrypted); | 275 | | | 276 | 1.13M | memzero(temp_plain, crypto_box_ZEROBYTES); | 277 | | // Pad the message with 32 0 bytes. | 278 | 1.13M | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); | 279 | | | 280 | 1.13M | if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, | 281 | 1.13M | shared_key) != 0) { | 282 | 0 | crypto_free(mem, temp_plain, size_temp_plain); | 283 | 0 | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 284 | 0 | return -1; | 285 | 0 | } | 286 | | | 287 | | // Unpad the encrypted message. | 288 | 1.13M | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); | 289 | | | 290 | 1.13M | crypto_free(mem, temp_plain, size_temp_plain); | 291 | 1.13M | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 292 | 1.13M | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 293 | 1.13M | assert(length < INT32_MAX - crypto_box_MACBYTES); | 294 | 1.13M | return (int32_t)(length + crypto_box_MACBYTES); | 295 | 1.13M | } |
|
296 | | |
297 | | int32_t decrypt_data_symmetric(const Memory *mem, |
298 | | const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], |
299 | | const uint8_t nonce[CRYPTO_NONCE_SIZE], |
300 | | const uint8_t *encrypted, size_t length, uint8_t *plain) |
301 | 957k | { |
302 | 957k | if (length <= crypto_box_BOXZEROBYTES || shared_key == nullptr || nonce == nullptr || encrypted == nullptr |
303 | 957k | || plain == nullptr) { |
304 | 0 | return -1; |
305 | 0 | } |
306 | | |
307 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
308 | 1 | assert(length >= crypto_box_MACBYTES); |
309 | 1 | memcpy(plain, encrypted, length - crypto_box_MACBYTES); // Don't encrypt anything |
310 | | #else |
311 | | |
312 | 957k | const size_t size_temp_plain = length + crypto_box_ZEROBYTES; |
313 | 957k | const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; |
314 | | |
315 | 957k | uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); |
316 | 957k | uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); |
317 | | |
318 | 957k | if (temp_plain == nullptr || temp_encrypted == nullptr) { |
319 | 207 | crypto_free(mem, temp_plain, size_temp_plain); |
320 | 207 | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
321 | 207 | return -1; |
322 | 207 | } |
323 | | |
324 | | // crypto_box_open_afternm requires the entire range of the output array be |
325 | | // initialised with something. It doesn't matter what it's initialised with, |
326 | | // so we'll pick 0x00. |
327 | 957k | memzero(temp_plain, size_temp_plain); |
328 | | |
329 | 957k | memzero(temp_encrypted, crypto_box_BOXZEROBYTES); |
330 | | // Pad the message with 16 0 bytes. |
331 | 957k | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); |
332 | | |
333 | 957k | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, |
334 | 957k | shared_key) != 0) { |
335 | 4.52k | crypto_free(mem, temp_plain, size_temp_plain); |
336 | 4.52k | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
337 | 4.52k | return -1; |
338 | 4.52k | } |
339 | | |
340 | 952k | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); |
341 | | |
342 | 952k | crypto_free(mem, temp_plain, size_temp_plain); |
343 | 952k | crypto_free(mem, temp_encrypted, size_temp_encrypted); |
344 | 952k | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
345 | 952k | assert(length > crypto_box_MACBYTES); |
346 | 952k | assert(length < INT32_MAX); |
347 | 952k | return (int32_t)(length - crypto_box_MACBYTES); |
348 | 952k | } Line | Count | Source | 301 | 1 | { | 302 | 1 | if (length <= crypto_box_BOXZEROBYTES || shared_key == nullptr || nonce == nullptr || encrypted == nullptr | 303 | 1 | || plain == nullptr) { | 304 | 0 | return -1; | 305 | 0 | } | 306 | | | 307 | 1 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 308 | 1 | assert(length >= crypto_box_MACBYTES); | 309 | 1 | memcpy(plain, encrypted, length - crypto_box_MACBYTES); // Don't encrypt anything | 310 | | #else | 311 | | | 312 | | const size_t size_temp_plain = length + crypto_box_ZEROBYTES; | 313 | | const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; | 314 | | | 315 | | uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); | 316 | | uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); | 317 | | | 318 | | if (temp_plain == nullptr || temp_encrypted == nullptr) { | 319 | | crypto_free(mem, temp_plain, size_temp_plain); | 320 | | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 321 | | return -1; | 322 | | } | 323 | | | 324 | | // crypto_box_open_afternm requires the entire range of the output array be | 325 | | // initialised with something. It doesn't matter what it's initialised with, | 326 | | // so we'll pick 0x00. | 327 | | memzero(temp_plain, size_temp_plain); | 328 | | | 329 | | memzero(temp_encrypted, crypto_box_BOXZEROBYTES); | 330 | | // Pad the message with 16 0 bytes. | 331 | | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); | 332 | | | 333 | | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, | 334 | | shared_key) != 0) { | 335 | | crypto_free(mem, temp_plain, size_temp_plain); | 336 | | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 337 | | return -1; | 338 | | } | 339 | | | 340 | | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); | 341 | | | 342 | | crypto_free(mem, temp_plain, size_temp_plain); | 343 | | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 344 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 345 | 1 | assert(length > crypto_box_MACBYTES); | 346 | 1 | assert(length < INT32_MAX); | 347 | 1 | return (int32_t)(length - crypto_box_MACBYTES); | 348 | 1 | } |
Line | Count | Source | 301 | 957k | { | 302 | 957k | if (length <= crypto_box_BOXZEROBYTES || shared_key == nullptr || nonce == nullptr || encrypted == nullptr | 303 | 957k | || plain == nullptr) { | 304 | 0 | return -1; | 305 | 0 | } | 306 | | | 307 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 308 | | assert(length >= crypto_box_MACBYTES); | 309 | | memcpy(plain, encrypted, length - crypto_box_MACBYTES); // Don't encrypt anything | 310 | | #else | 311 | | | 312 | 957k | const size_t size_temp_plain = length + crypto_box_ZEROBYTES; | 313 | 957k | const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; | 314 | | | 315 | 957k | uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain); | 316 | 957k | uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted); | 317 | | | 318 | 957k | if (temp_plain == nullptr || temp_encrypted == nullptr) { | 319 | 207 | crypto_free(mem, temp_plain, size_temp_plain); | 320 | 207 | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 321 | 207 | return -1; | 322 | 207 | } | 323 | | | 324 | | // crypto_box_open_afternm requires the entire range of the output array be | 325 | | // initialised with something. It doesn't matter what it's initialised with, | 326 | | // so we'll pick 0x00. | 327 | 957k | memzero(temp_plain, size_temp_plain); | 328 | | | 329 | 957k | memzero(temp_encrypted, crypto_box_BOXZEROBYTES); | 330 | | // Pad the message with 16 0 bytes. | 331 | 957k | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); | 332 | | | 333 | 957k | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, | 334 | 957k | shared_key) != 0) { | 335 | 4.52k | crypto_free(mem, temp_plain, size_temp_plain); | 336 | 4.52k | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 337 | 4.52k | return -1; | 338 | 4.52k | } | 339 | | | 340 | 952k | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); | 341 | | | 342 | 952k | crypto_free(mem, temp_plain, size_temp_plain); | 343 | 952k | crypto_free(mem, temp_encrypted, size_temp_encrypted); | 344 | 952k | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 345 | 952k | assert(length > crypto_box_MACBYTES); | 346 | 952k | assert(length < INT32_MAX); | 347 | 952k | return (int32_t)(length - crypto_box_MACBYTES); | 348 | 952k | } |
|
349 | | |
350 | | int32_t encrypt_data(const Memory *mem, |
351 | | const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], |
352 | | const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], |
353 | | const uint8_t nonce[CRYPTO_NONCE_SIZE], |
354 | | const uint8_t *plain, size_t length, uint8_t *encrypted) |
355 | 85.9k | { |
356 | 85.9k | if (public_key == nullptr || secret_key == nullptr) { |
357 | 0 | return -1; |
358 | 0 | } |
359 | | |
360 | 85.9k | uint8_t k[crypto_box_BEFORENMBYTES]; |
361 | 85.9k | encrypt_precompute(public_key, secret_key, k); |
362 | 85.9k | const int ret = encrypt_data_symmetric(mem, k, nonce, plain, length, encrypted); |
363 | 85.9k | crypto_memzero(k, sizeof(k)); |
364 | 85.9k | return ret; |
365 | 85.9k | } |
366 | | |
367 | | int32_t decrypt_data(const Memory *mem, |
368 | | const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], |
369 | | const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], |
370 | | const uint8_t nonce[CRYPTO_NONCE_SIZE], |
371 | | const uint8_t *encrypted, size_t length, uint8_t *plain) |
372 | 70.3k | { |
373 | 70.3k | if (public_key == nullptr || secret_key == nullptr) { |
374 | 0 | return -1; |
375 | 0 | } |
376 | | |
377 | 70.3k | uint8_t k[crypto_box_BEFORENMBYTES]; |
378 | 70.3k | encrypt_precompute(public_key, secret_key, k); |
379 | 70.3k | const int ret = decrypt_data_symmetric(mem, k, nonce, encrypted, length, plain); |
380 | 70.3k | crypto_memzero(k, sizeof(k)); |
381 | 70.3k | return ret; |
382 | 70.3k | } |
383 | | |
384 | | void increment_nonce(uint8_t nonce[CRYPTO_NONCE_SIZE]) |
385 | 613k | { |
386 | | /* TODO(irungentoo): use `increment_nonce_number(nonce, 1)` or |
387 | | * sodium_increment (change to little endian). |
388 | | * |
389 | | * NOTE don't use breaks inside this loop. |
390 | | * In particular, make sure, as far as possible, |
391 | | * that loop bounds and their potential underflow or overflow |
392 | | * are independent of user-controlled input (you may have heard of the Heartbleed bug). |
393 | | */ |
394 | 613k | uint_fast16_t carry = 1U; |
395 | | |
396 | 15.3M | for (uint32_t i = crypto_box_NONCEBYTES; i != 0; --i) { |
397 | 14.7M | carry += (uint_fast16_t)nonce[i - 1]; |
398 | 14.7M | nonce[i - 1] = (uint8_t)carry; |
399 | 14.7M | carry >>= 8; |
400 | 14.7M | } |
401 | 613k | } |
402 | | |
403 | | void increment_nonce_number(uint8_t nonce[CRYPTO_NONCE_SIZE], uint32_t increment) |
404 | 500k | { |
405 | | /* NOTE don't use breaks inside this loop |
406 | | * In particular, make sure, as far as possible, |
407 | | * that loop bounds and their potential underflow or overflow |
408 | | * are independent of user-controlled input (you may have heard of the Heartbleed bug). |
409 | | */ |
410 | 500k | uint8_t num_as_nonce[crypto_box_NONCEBYTES] = {0}; |
411 | 500k | num_as_nonce[crypto_box_NONCEBYTES - 4] = increment >> 24; |
412 | 500k | num_as_nonce[crypto_box_NONCEBYTES - 3] = increment >> 16; |
413 | 500k | num_as_nonce[crypto_box_NONCEBYTES - 2] = increment >> 8; |
414 | 500k | num_as_nonce[crypto_box_NONCEBYTES - 1] = increment; |
415 | | |
416 | 500k | uint_fast16_t carry = 0U; |
417 | | |
418 | 12.5M | for (uint32_t i = crypto_box_NONCEBYTES; i != 0; --i) { |
419 | 12.0M | carry += (uint_fast16_t)nonce[i - 1] + (uint_fast16_t)num_as_nonce[i - 1]; |
420 | 12.0M | nonce[i - 1] = (uint8_t)carry; |
421 | 12.0M | carry >>= 8; |
422 | 12.0M | } |
423 | 500k | } |
424 | | |
425 | | void random_nonce(const Random *rng, uint8_t nonce[CRYPTO_NONCE_SIZE]) |
426 | 639k | { |
427 | 639k | random_bytes(rng, nonce, crypto_box_NONCEBYTES); |
428 | 639k | } |
429 | | |
430 | | void new_symmetric_key(const Random *rng, uint8_t key[CRYPTO_SYMMETRIC_KEY_SIZE]) |
431 | 8.70k | { |
432 | 8.70k | random_bytes(rng, key, CRYPTO_SYMMETRIC_KEY_SIZE); |
433 | 8.70k | } |
434 | | |
435 | | int32_t crypto_new_keypair(const Random *rng, |
436 | | uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], |
437 | | uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE]) |
438 | 44.1k | { |
439 | 44.1k | random_bytes(rng, secret_key, CRYPTO_SECRET_KEY_SIZE); |
440 | 44.1k | memzero(public_key, CRYPTO_PUBLIC_KEY_SIZE); // Make MSAN happy |
441 | 44.1k | crypto_derive_public_key(public_key, secret_key); |
442 | 44.1k | return 0; |
443 | 44.1k | } |
444 | | |
445 | | void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], |
446 | | const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE]) |
447 | 47.9k | { |
448 | 47.9k | crypto_scalarmult_curve25519_base(public_key, secret_key); |
449 | 47.9k | } |
450 | | |
451 | | void new_hmac_key(const Random *rng, uint8_t key[CRYPTO_HMAC_KEY_SIZE]) |
452 | 8.56k | { |
453 | 8.56k | random_bytes(rng, key, CRYPTO_HMAC_KEY_SIZE); |
454 | 8.56k | } |
455 | | |
456 | | void crypto_hmac(uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE], |
457 | | const uint8_t *data, size_t length) |
458 | 0 | { |
459 | 0 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
460 | 0 | memcpy(auth, key, 16); |
461 | 0 | memcpy(auth + 16, data, length < 16 ? length : 16); |
462 | | #else |
463 | | crypto_auth(auth, data, length, key); |
464 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
465 | 0 | } |
466 | | |
467 | | bool crypto_hmac_verify(const uint8_t auth[CRYPTO_HMAC_SIZE], const uint8_t key[CRYPTO_HMAC_KEY_SIZE], |
468 | | const uint8_t *data, size_t length) |
469 | 0 | { |
470 | 0 | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
471 | 0 | return memcmp(auth, key, 16) == 0 && memcmp(auth + 16, data, length < 16 ? length : 16) == 0; |
472 | | #else |
473 | | return crypto_auth_verify(auth, data, length, key) == 0; |
474 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
475 | 0 | } |
476 | | |
477 | | void crypto_sha256(uint8_t hash[CRYPTO_SHA256_SIZE], const uint8_t *data, size_t length) |
478 | 57 | { |
479 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
480 | 0 | memzero(hash, CRYPTO_SHA256_SIZE); |
481 | 0 | memcpy(hash, data, length < CRYPTO_SHA256_SIZE ? length : CRYPTO_SHA256_SIZE); |
482 | | #else |
483 | | crypto_hash_sha256(hash, data, length); |
484 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
485 | 57 | } Unexecuted instantiation: crypto_sha256 Line | Count | Source | 478 | 57 | { | 479 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 480 | | memzero(hash, CRYPTO_SHA256_SIZE); | 481 | | memcpy(hash, data, length < CRYPTO_SHA256_SIZE ? length : CRYPTO_SHA256_SIZE); | 482 | | #else | 483 | 57 | crypto_hash_sha256(hash, data, length); | 484 | 57 | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 485 | 57 | } |
|
486 | | |
487 | | void crypto_sha512(uint8_t hash[CRYPTO_SHA512_SIZE], const uint8_t *data, size_t length) |
488 | 3.16k | { |
489 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
490 | 0 | memzero(hash, CRYPTO_SHA512_SIZE); |
491 | 0 | memcpy(hash, data, length < CRYPTO_SHA512_SIZE ? length : CRYPTO_SHA512_SIZE); |
492 | | #else |
493 | | crypto_hash_sha512(hash, data, length); |
494 | | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ |
495 | 3.16k | } Unexecuted instantiation: crypto_sha512 Line | Count | Source | 488 | 3.16k | { | 489 | | #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION | 490 | | memzero(hash, CRYPTO_SHA512_SIZE); | 491 | | memcpy(hash, data, length < CRYPTO_SHA512_SIZE ? length : CRYPTO_SHA512_SIZE); | 492 | | #else | 493 | 3.16k | crypto_hash_sha512(hash, data, length); | 494 | 3.16k | #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ | 495 | 3.16k | } |
|
496 | | |
497 | | void random_bytes(const Random *rng, uint8_t *bytes, size_t length) |
498 | 1.41M | { |
499 | 1.41M | tox_random_bytes(rng, bytes, length); |
500 | 1.41M | } |