Coverage Report

Created: 2026-10-24 08:16

/work/toxencryptsave/toxencryptsave.h
Line
Count
Source
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2026 The TokTok team.
3
 * Copyright © 2013-2016 Tox Developers.
4
 */
5
6
/**
7
 * Batch encryption functions.
8
 */
9
10
#ifndef C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H
11
#define C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H
12
13
#include <stdbool.h>
14
#include <stddef.h>
15
#include <stdint.h>
16
17
#ifdef __cplusplus
18
extern "C" {
19
#endif
20
21
/*******************************************************************************
22
 *
23
 * This module is organized into two parts.
24
 *
25
 * 1. A simple API operating on plain text/cipher text data and a password to
26
 *    encrypt or decrypt it.
27
 * 2. A more advanced API that splits key derivation and encryption into two
28
 *    separate function calls.
29
 *
30
 * The first part is implemented in terms of the second part and simply calls
31
 * the separate functions in sequence. Since key derivation is very expensive
32
 * compared to the actual encryption, clients that do a lot of crypto should
33
 * prefer the advanced API and reuse pass-key objects.
34
 *
35
 * To use the second part, first derive an encryption key from a password with
36
 * tox_pass_key_derive, then use the derived key to encrypt the data.
37
 *
38
 * The encrypted data is prepended with a magic number, to aid validity
39
 * checking (no guarantees are made of course). Any data to be decrypted must
40
 * start with the magic number.
41
 *
42
 * Clients should consider alerting their users that, unlike plain data, if
43
 * even one bit becomes corrupted, the data will be entirely unrecoverable.
44
 * Ditto if they forget their password, there is no way to recover the data.
45
 *
46
 ******************************************************************************/
47
48
/**
49
 * The size of the salt part of a pass-key.
50
 */
51
15
#define TOX_PASS_SALT_LENGTH           32
52
53
uint32_t tox_pass_salt_length(void);
54
55
typedef uint8_t Tox_Pass_Salt[TOX_PASS_SALT_LENGTH];
56
57
/**
58
 * The size of the key part of a pass-key.
59
 */
60
14
#define TOX_PASS_KEY_LENGTH            32
61
62
uint32_t tox_pass_key_length(void);
63
64
/**
65
 * The amount of additional data required to store any encrypted byte array.
66
 * Encrypting an array of N bytes requires N + TOX_PASS_ENCRYPTION_EXTRA_LENGTH
67
 * bytes in the encrypted byte array.
68
 */
69
32
#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80
70
71
uint32_t tox_pass_encryption_extra_length(void);
72
73
typedef enum Tox_Err_Key_Derivation {
74
75
    /**
76
     * The function returned successfully.
77
     */
78
    TOX_ERR_KEY_DERIVATION_OK,
79
80
    /**
81
     * One of the arguments to the function was NULL when it was not expected.
82
     */
83
    TOX_ERR_KEY_DERIVATION_NULL,
84
85
    /**
86
     * The crypto lib was unable to derive a key from the given passphrase,
87
     * which is usually a lack of memory issue.
88
     */
89
    TOX_ERR_KEY_DERIVATION_FAILED,
90
91
} Tox_Err_Key_Derivation;
92
93
const char *tox_err_key_derivation_to_string(Tox_Err_Key_Derivation error);
94
95
typedef enum Tox_Err_Encryption {
96
97
    /**
98
     * The function returned successfully.
99
     */
100
    TOX_ERR_ENCRYPTION_OK,
101
102
    /**
103
     * One of the arguments to the function was NULL when it was not expected.
104
     */
105
    TOX_ERR_ENCRYPTION_NULL,
106
107
    /**
108
     * The crypto lib was unable to derive a key from the given passphrase,
109
     * which is usually a lack of memory issue. The functions accepting keys
110
     * do not produce this error.
111
     */
112
    TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED,
113
114
    /**
115
     * The encryption itself failed.
116
     */
117
    TOX_ERR_ENCRYPTION_FAILED,
118
119
} Tox_Err_Encryption;
120
121
const char *tox_err_encryption_to_string(Tox_Err_Encryption error);
122
123
typedef enum Tox_Err_Decryption {
124
125
    /**
126
     * The function returned successfully.
127
     */
128
    TOX_ERR_DECRYPTION_OK,
129
130
    /**
131
     * One of the arguments to the function was NULL when it was not expected.
132
     */
133
    TOX_ERR_DECRYPTION_NULL,
134
135
    /**
136
     * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
137
     */
138
    TOX_ERR_DECRYPTION_INVALID_LENGTH,
139
140
    /**
141
     * The input data is missing the magic number (i.e. wasn't created by this
142
     * module, or is corrupted).
143
     */
144
    TOX_ERR_DECRYPTION_BAD_FORMAT,
145
146
    /**
147
     * The crypto lib was unable to derive a key from the given passphrase,
148
     * which is usually a lack of memory issue. The functions accepting keys
149
     * do not produce this error.
150
     */
151
    TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED,
152
153
    /**
154
     * The encrypted byte array could not be decrypted. Either the data was
155
     * corrupted or the password/key was incorrect.
156
     */
157
    TOX_ERR_DECRYPTION_FAILED,
158
159
} Tox_Err_Decryption;
160
161
const char *tox_err_decryption_to_string(Tox_Err_Decryption error);
162
163
/*******************************************************************************
164
 *
165
 *                                BEGIN PART 1
166
 *
167
 * The simple API is presented first. If your code spends too much time using
168
 * these functions, consider using the advanced functions instead and caching
169
 * the generated pass-key.
170
 *
171
 ******************************************************************************/
172
173
/**
174
 * Encrypts the given data with the given passphrase.
175
 *
176
 * The output array must be at least
177
 * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This delegates
178
 * to tox_pass_key_derive and tox_pass_key_encrypt.
179
 *
180
 * @param plaintext A byte array of length `plaintext_len`.
181
 * @param plaintext_len The length of the plain text array. Bigger than 0.
182
 * @param passphrase The user-provided password. Can be empty.
183
 * @param passphrase_len The length of the password.
184
 * @param ciphertext The cipher text array to write the encrypted data to.
185
 *
186
 * @return true on success.
187
 */
188
bool tox_pass_encrypt(const uint8_t plaintext[], size_t plaintext_len, const uint8_t passphrase[], size_t passphrase_len,
189
                      uint8_t ciphertext[/*! plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Encryption *error);
190
191
/**
192
 * Decrypts the given data with the given passphrase.
193
 *
194
 * The output array must be at least
195
 * `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long. This
196
 * delegates to tox_pass_key_decrypt.
197
 *
198
 * @param ciphertext A byte array of length `ciphertext_len`.
199
 * @param ciphertext_len The length of the cipher text array. At least
200
 *   TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
201
 * @param passphrase The user-provided password. Can be empty.
202
 * @param passphrase_len The length of the password.
203
 * @param plaintext The plain text array to write the decrypted data to.
204
 *
205
 * @return true on success.
206
 */
207
bool tox_pass_decrypt(const uint8_t ciphertext[], size_t ciphertext_len, const uint8_t passphrase[],
208
                      size_t passphrase_len, uint8_t plaintext[/*! ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Decryption *error);
209
210
/*******************************************************************************
211
 *
212
 *                                BEGIN PART 2
213
 *
214
 * And now part 2, which does the actual encryption, and can be used to write
215
 * less CPU intensive client code than part one.
216
 *
217
 ******************************************************************************/
218
219
/**
220
 * This type represents a pass-key.
221
 *
222
 * A pass-key and a password are two different concepts: a password is given
223
 * by the user in plain text. A pass-key is the generated symmetric key used
224
 * for encryption and decryption. It is derived from a salt and the
225
 * user-provided password.
226
 *
227
 * The Tox_Pass_Key structure is hidden in the implementation. It can be created
228
 * using tox_pass_key_derive or tox_pass_key_derive_with_salt and must be
229
 * deallocated using tox_pass_key_free.
230
 */
231
typedef struct Tox_Pass_Key Tox_Pass_Key;
232
233
/**
234
 * Deallocate a Tox_Pass_Key. This function behaves like `free()`, so NULL is an
235
 * acceptable argument value.
236
 */
237
void tox_pass_key_free(Tox_Pass_Key *key);
238
239
/**
240
 * Generates a secret symmetric key from the given passphrase.
241
 *
242
 * Be sure to not compromise the key! Only keep it in memory, do not write
243
 * it to disk.
244
 *
245
 * Note that this function is not deterministic; to derive the same key from
246
 * a password, you also must know the random salt that was used. A
247
 * deterministic version of this function is `tox_pass_key_derive_with_salt`.
248
 *
249
 * @param passphrase The user-provided password. Can be empty.
250
 * @param passphrase_len The length of the password.
251
 *
252
 * @return new symmetric key on success, NULL on failure.
253
 */
254
Tox_Pass_Key *tox_pass_key_derive(
255
    const uint8_t passphrase[], size_t passphrase_len,
256
    Tox_Err_Key_Derivation *error);
257
258
/**
259
 * Same as above, except use the given salt for deterministic key derivation.
260
 *
261
 * @param passphrase The user-provided password. Can be empty.
262
 * @param passphrase_len The length of the password.
263
 * @param salt An array of exactly TOX_PASS_SALT_LENGTH bytes.
264
 *
265
 * @return new symmetric key on success, NULL on failure.
266
 */
267
Tox_Pass_Key *tox_pass_key_derive_with_salt(
268
    const uint8_t passphrase[], size_t passphrase_len,
269
    const Tox_Pass_Salt salt, Tox_Err_Key_Derivation *error);
270
271
/**
272
 * Encrypt a plain text with a key produced by tox_pass_key_derive or
273
 * tox_pass_key_derive_with_salt.
274
 *
275
 * The output array must be at least
276
 * `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH` bytes long.
277
 *
278
 * @param plaintext A byte array of length `plaintext_len`.
279
 * @param plaintext_len The length of the plain text array. Bigger than 0.
280
 * @param ciphertext The cipher text array to write the encrypted data to.
281
 *
282
 * @return true on success.
283
 */
284
bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t plaintext[], size_t plaintext_len,
285
                          uint8_t ciphertext[/*! plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Encryption *error);
286
287
/**
288
 * This is the inverse of tox_pass_key_encrypt, also using only keys produced by
289
 * tox_pass_key_derive or tox_pass_key_derive_with_salt.
290
 *
291
 * @param ciphertext A byte array of length `ciphertext_len`.
292
 * @param ciphertext_len The length of the cipher text array. At least
293
 *   TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
294
 * @param plaintext The plain text array to write the decrypted data to.
295
 *
296
 * @return true on success.
297
 */
298
bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t ciphertext[], size_t ciphertext_len,
299
                          uint8_t plaintext[/*! ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH */], Tox_Err_Decryption *error);
300
301
typedef enum Tox_Err_Get_Salt {
302
303
    /**
304
     * The function returned successfully.
305
     */
306
    TOX_ERR_GET_SALT_OK,
307
308
    /**
309
     * One of the arguments to the function was NULL when it was not expected.
310
     */
311
    TOX_ERR_GET_SALT_NULL,
312
313
    /**
314
     * The input data is missing the magic number (i.e. wasn't created by this
315
     * module, or is corrupted).
316
     */
317
    TOX_ERR_GET_SALT_BAD_FORMAT,
318
319
} Tox_Err_Get_Salt;
320
321
const char *tox_err_get_salt_to_string(Tox_Err_Get_Salt error);
322
323
/**
324
 * Retrieves the salt used to encrypt the given data.
325
 *
326
 * The retrieved salt can then be passed to tox_pass_key_derive_with_salt to
327
 * produce the same key as was previously used. Any data encrypted with this
328
 * module can be used as input.
329
 *
330
 * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in
331
 * length.
332
 * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
333
 * If the passed byte arrays are smaller than required, the behaviour is
334
 * undefined.
335
 *
336
 * If the cipher text pointer or the salt is NULL, this function returns false.
337
 *
338
 * Success does not say anything about the validity of the data, only that
339
 * data of the appropriate size was copied.
340
 *
341
 * @param ciphertext The encrypted data; at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes are read.
342
 * @param salt An array of exactly TOX_PASS_SALT_LENGTH bytes to write the salt to.
343
 *
344
 * @return true on success.
345
 */
346
bool tox_get_salt(
347
    const uint8_t ciphertext[TOX_PASS_ENCRYPTION_EXTRA_LENGTH],
348
    Tox_Pass_Salt salt, Tox_Err_Get_Salt *error);
349
350
/**
351
 * Determines whether or not the given data is encrypted by this module.
352
 *
353
 * It does this check by verifying that the magic number is the one put in
354
 * place by the encryption functions.
355
 *
356
 * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
357
 * If the passed byte array is smaller than required, the behaviour is
358
 * undefined.
359
 *
360
 * If the data pointer is NULL, the behaviour is undefined
361
 *
362
 * @param data The data to check; at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes are read.
363
 *
364
 * @return true if the data is encrypted by this module.
365
 */
366
bool tox_is_data_encrypted(const uint8_t data[TOX_PASS_ENCRYPTION_EXTRA_LENGTH]);
367
368
#ifdef __cplusplus
369
} /* extern "C" */
370
#endif
371
372
//!TOKSTYLE-
373
374
typedef Tox_Err_Key_Derivation TOX_ERR_KEY_DERIVATION;
375
typedef Tox_Err_Encryption TOX_ERR_ENCRYPTION;
376
typedef Tox_Err_Decryption TOX_ERR_DECRYPTION;
377
typedef Tox_Err_Get_Salt TOX_ERR_GET_SALT;
378
379
//!TOKSTYLE+
380
381
#endif /* C_TOXCORE_TOXENCRYPTSAVE_TOXENCRYPTSAVE_H */