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