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