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