/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 */ |