Coverage Report

Created: 2026-10-24 08:16

/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
}
crypto_sha512_eq
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
}
crypto_sha512_eq
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
}
encrypt_precompute
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
}
encrypt_precompute
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
}
encrypt_data_symmetric
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
}
encrypt_data_symmetric
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
}
decrypt_data_symmetric
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
}
decrypt_data_symmetric
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
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
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
}