summaryrefslogtreecommitdiff
path: root/toxencryptsave
diff options
context:
space:
mode:
authoriphydf <iphydf@users.noreply.github.com>2016-12-10 11:21:22 +0000
committeriphydf <iphydf@users.noreply.github.com>2016-12-13 14:24:40 +0000
commit4cf69996cc16282b13615843febd68ff6355eb7d (patch)
treea25eabe891617be148a2de433fe1fe08759bea02 /toxencryptsave
parent3cfe5544b1cb01771b5a1f722311502127265d0b (diff)
Add apidsl file for toxencryptsave.
This breaks the toxencryptsave API. It hides the Tox_Pass_Key struct definition.
Diffstat (limited to 'toxencryptsave')
-rw-r--r--toxencryptsave/toxencryptsave.api.h322
-rw-r--r--toxencryptsave/toxencryptsave.c80
-rw-r--r--toxencryptsave/toxencryptsave.h367
3 files changed, 633 insertions, 136 deletions
diff --git a/toxencryptsave/toxencryptsave.api.h b/toxencryptsave/toxencryptsave.api.h
new file mode 100644
index 00000000..20b8da06
--- /dev/null
+++ b/toxencryptsave/toxencryptsave.api.h
@@ -0,0 +1,322 @@
1%{
2/* toxencryptsave.h
3 *
4 * Batch encryption functions.
5 *
6 * Copyright (C) 2013-2016 Tox Developers. All Rights Reserved.
7 *
8 * This file is part of Tox.
9 *
10 * Tox is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * Tox is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#ifndef TOXENCRYPTSAVE_H
26#define TOXENCRYPTSAVE_H
27
28#ifdef __cplusplus
29extern "C" {
30#endif
31
32#include <stdbool.h>
33#include <stddef.h>
34#include <stdint.h>
35%}
36
37/*******************************************************************************
38 *
39 * This module is organized into two parts.
40 *
41 * 1. A simple API operating on plain text/cipher text data and a password to
42 * encrypt or decrypt it.
43 * 2. A more advanced API that splits key derivation and encryption into two
44 * separate function calls.
45 *
46 * The first part is implemented in terms of the second part and simply calls
47 * the separate functions in sequence. Since key derivation is very expensive
48 * compared to the actual encryption, clients that do a lot of crypto should
49 * prefer the advanced API and reuse pass-key objects.
50 *
51 * To use the second part, first derive an encryption key from a password with
52 * ${pass_Key.derive}, then use the derived key to encrypt the data.
53 *
54 * The encrypted data is prepended with a magic number, to aid validity
55 * checking (no guarantees are made of course). Any data to be decrypted must
56 * start with the magic number.
57 *
58 * Clients should consider alerting their users that, unlike plain data, if
59 * even one bit becomes corrupted, the data will be entirely unrecoverable.
60 * Ditto if they forget their password, there is no way to recover the data.
61 *
62 *******************************************************************************/
63
64class tox {
65
66/**
67 * The size of the salt part of a pass-key.
68 */
69const PASS_SALT_LENGTH = 32;
70/**
71 * The size of the key part of a pass-key.
72 */
73const PASS_KEY_LENGTH = 32;
74/**
75 * The amount of additional data required to store any encrypted byte array.
76 * Encrypting an array of N bytes requires N + $PASS_ENCRYPTION_EXTRA_LENGTH
77 * bytes in the encrypted byte array.
78 */
79const PASS_ENCRYPTION_EXTRA_LENGTH = 80;
80
81error for key_derivation {
82 NULL,
83 /**
84 * The crypto lib was unable to derive a key from the given passphrase,
85 * which is usually a lack of memory issue. The functions accepting keys
86 * do not produce this error.
87 */
88 FAILED,
89}
90
91error for encryption {
92 NULL,
93 /**
94 * The crypto lib was unable to derive a key from the given passphrase,
95 * which is usually a lack of memory issue. The functions accepting keys
96 * do not produce this error.
97 */
98 KEY_DERIVATION_FAILED,
99 /**
100 * The encryption itself failed.
101 */
102 FAILED,
103}
104
105error for decryption {
106 NULL,
107 /**
108 * The input data was shorter than $PASS_ENCRYPTION_EXTRA_LENGTH bytes
109 */
110 INVALID_LENGTH,
111 /**
112 * The input data is missing the magic number (i.e. wasn't created by this
113 * module, or is corrupted).
114 */
115 BAD_FORMAT,
116 /**
117 * The crypto lib was unable to derive a key from the given passphrase,
118 * which is usually a lack of memory issue. The functions accepting keys
119 * do not produce this error.
120 */
121 KEY_DERIVATION_FAILED,
122 /**
123 * The encrypted byte array could not be decrypted. Either the data was
124 * corrupted or the password/key was incorrect.
125 */
126 FAILED,
127}
128
129
130/*******************************************************************************
131 *
132 * BEGIN PART 1
133 *
134 * The simple API is presented first. If your code spends too much time using
135 * these functions, consider using the advanced functions instead and caching
136 * the generated pass-key.
137 *
138 *******************************************************************************/
139
140/**
141 * Encrypts the given data with the given passphrase.
142 *
143 * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
144 * bytes long. This delegates to ${pass_Key.derive} and
145 * ${pass_Key.encrypt}.
146 *
147 * @param plaintext A byte array of length `plaintext_len`.
148 * @param plaintext_len The length of the plain text array. May be 0.
149 * @param passphrase The user-provided password.
150 * @param passphrase_len The length of the password.
151 * @param ciphertext The cipher text array to write the encrypted data to.
152 *
153 * @return true on success.
154 */
155static bool pass_encrypt(const uint8_t[plaintext_len] plaintext, const uint8_t[passphrase_len] passphrase, uint8_t *ciphertext)
156 with error for encryption;
157
158
159/**
160 * Decrypts the given data with the given passphrase.
161 *
162 * The output array must be at least `ciphertext_len - $PASS_ENCRYPTION_EXTRA_LENGTH`
163 * bytes long. This delegates to ${pass_Key.decrypt}.
164 *
165 * @param ciphertext A byte array of length `ciphertext_len`.
166 * @param ciphertext_len The length of the cipher text array. May be 0.
167 * @param passphrase The user-provided password.
168 * @param passphrase_len The length of the password.
169 * @param plaintext The plain text array to write the decrypted data to.
170 *
171 * @return true on success.
172 */
173static bool pass_decrypt(const uint8_t[ciphertext_len] ciphertext, const uint8_t[passphrase_len] passphrase, uint8_t *plaintext)
174 with error for decryption;
175
176
177/*******************************************************************************
178 *
179 * BEGIN PART 2
180 *
181 * And now part 2, which does the actual encryption, and can be used to write
182 * less CPU intensive client code than part one.
183 *
184 *******************************************************************************/
185
186class pass_Key {
187 /**
188 * This type represents a pass-key.
189 *
190 * A pass-key and a password are two different concepts: a password is given
191 * by the user in plain text. A pass-key is the generated symmetric key used
192 * for encryption and decryption. It is derived from a salt and the user-
193 * provided password.
194 *
195 * The $this structure is hidden in the implementation. It can be allocated
196 * using $new and must be deallocated using $free.
197 */
198 struct this;
199
200 /**
201 * Create a new $this. The initial value of it is indeterminate. To
202 * initialise it, use one of the derive_* functions below.
203 */
204 static this new();
205
206 /**
207 * Deallocate a $this. This function behaves like free(), so NULL is an
208 * acceptable argument value.
209 */
210 void free();
211
212 /**
213 * Generates a secret symmetric key from the given passphrase.
214 *
215 * Be sure to not compromise the key! Only keep it in memory, do not write
216 * it to disk.
217 *
218 * Note that this function is not deterministic; to derive the same key from
219 * a password, you also must know the random salt that was used. A
220 * deterministic version of this function is $derive_with_salt.
221 *
222 * @param passphrase The user-provided password.
223 * @param passphrase_len The length of the password.
224 *
225 * @return true on success.
226 */
227 bool derive(const uint8_t[passphrase_len] passphrase)
228 with error for key_derivation;
229
230 /**
231 * Same as above, except use the given salt for deterministic key derivation.
232 *
233 * @param passphrase The user-provided password.
234 * @param passphrase_len The length of the password.
235 * @param salt An array of at least $PASS_SALT_LENGTH bytes.
236 *
237 * @return true on success.
238 */
239 bool derive_with_salt(const uint8_t[passphrase_len] passphrase, const uint8_t[PASS_SALT_LENGTH] salt)
240 with error for key_derivation;
241
242 /**
243 * Encrypt a plain text with a key produced by $derive or $derive_with_salt.
244 *
245 * The output array must be at least `plaintext_len + $PASS_ENCRYPTION_EXTRA_LENGTH`
246 * bytes long.
247 *
248 * @param plaintext A byte array of length `plaintext_len`.
249 * @param plaintext_len The length of the plain text array. May be 0.
250 * @param ciphertext The cipher text array to write the encrypted data to.
251 *
252 * @return true on success.
253 */
254 const bool encrypt(const uint8_t[plaintext_len] plaintext, uint8_t *ciphertext)
255 with error for encryption;
256
257 /**
258 * This is the inverse of $encrypt, also using only keys produced by
259 * $derive or $derive_with_salt.
260 *
261 * @param ciphertext A byte array of length `ciphertext_len`.
262 * @param ciphertext_len The length of the cipher text array. May be 0.
263 * @param plaintext The plain text array to write the decrypted data to.
264 *
265 * @return true on success.
266 */
267 const bool decrypt(const uint8_t[ciphertext_len] ciphertext, uint8_t *plaintext)
268 with error for decryption;
269}
270
271/**
272 * Retrieves the salt used to encrypt the given data.
273 *
274 * The retrieved salt can then be passed to ${pass_Key.derive_with_salt} to
275 * produce the same key as was previously used. Any data encrypted with this
276 * module can be used as input.
277 *
278 * The cipher text must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
279 * The salt must be $PASS_SALT_LENGTH bytes in length.
280 * If the passed byte arrays are smaller than required, the behaviour is
281 * undefined.
282 *
283 * Success does not say anything about the validity of the data, only that
284 * data of the appropriate size was copied.
285 *
286 * @return true on success.
287 */
288static bool get_salt(const uint8_t *ciphertext, uint8_t[PASS_SALT_LENGTH] salt) {
289 NULL,
290 /**
291 * The input data is missing the magic number (i.e. wasn't created by this
292 * module, or is corrupted).
293 */
294 BAD_FORMAT,
295}
296
297/**
298 * Determines whether or not the given data is encrypted by this module.
299 *
300 * It does this check by verifying that the magic number is the one put in
301 * place by the encryption functions.
302 *
303 * The data must be at least $PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
304 * If the passed byte array is smaller than required, the behaviour is
305 * undefined.
306 *
307 * If the cipher text pointer is NULL, this function returns false.
308 *
309 * @return true if the data is encrypted by this module.
310 */
311static bool is_data_encrypted(const uint8_t *data);
312
313}
314
315%{
316
317#ifdef __cplusplus
318}
319#endif
320
321#endif
322%}
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index a6a75b0d..19aa2a14 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -47,28 +47,70 @@
47#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) 47#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
48#endif 48#endif
49 49
50struct Tox_Pass_Key {
51 uint8_t salt[TOX_PASS_SALT_LENGTH];
52 uint8_t key[TOX_PASS_KEY_LENGTH];
53};
54
55Tox_Pass_Key *tox_pass_key_new(void)
56{
57 return (Tox_Pass_Key *)malloc(sizeof(Tox_Pass_Key));
58}
59
60void tox_pass_key_free(Tox_Pass_Key *pass_key)
61{
62 free(pass_key);
63}
64
65void tox_pass_key_get_salt(const Tox_Pass_Key *pass_key, uint8_t *salt)
66{
67 memcpy(salt, pass_key->salt, TOX_PASS_SALT_LENGTH);
68}
69
70void tox_pass_key_set_salt(Tox_Pass_Key *pass_key, const uint8_t *salt)
71{
72 memcpy(pass_key->salt, salt, TOX_PASS_SALT_LENGTH);
73}
74
75void tox_pass_key_get_key(const Tox_Pass_Key *pass_key, uint8_t *key)
76{
77 memcpy(key, pass_key->key, TOX_PASS_KEY_LENGTH);
78}
79
80void tox_pass_key_set_key(Tox_Pass_Key *pass_key, const uint8_t *key)
81{
82 memcpy(pass_key->key, key, TOX_PASS_KEY_LENGTH);
83}
84
50/* Clients should consider alerting their users that, unlike plain data, if even one bit 85/* Clients should consider alerting their users that, unlike plain data, if even one bit
51 * becomes corrupted, the data will be entirely unrecoverable. 86 * becomes corrupted, the data will be entirely unrecoverable.
52 * Ditto if they forget their password, there is no way to recover the data. 87 * Ditto if they forget their password, there is no way to recover the data.
53 */ 88 */
54 89
55/* This retrieves the salt used to encrypt the given data, which can then be passed to 90/* This retrieves the salt used to encrypt the given data, which can then be passed to
56 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted 91 * tox_pass_key_derive_with_salt to produce the same key as was previously used. Any encrpyted
57 * data with this module can be used as input. 92 * data with this module can be used as input.
58 * 93 *
59 * returns true if magic number matches 94 * returns true if magic number matches
60 * success does not say anything about the validity of the data, only that data of 95 * success does not say anything about the validity of the data, only that data of
61 * the appropriate size was copied 96 * the appropriate size was copied
62 */ 97 */
63bool tox_get_salt(const uint8_t *data, uint8_t *salt) 98bool tox_get_salt(const uint8_t *data, uint8_t *salt, TOX_ERR_GET_SALT *error)
64{ 99{
100 if (!data || !salt) {
101 SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_NULL);
102 return false;
103 }
104
65 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { 105 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
66 return 0; 106 SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_BAD_FORMAT);
107 return false;
67 } 108 }
68 109
69 data += TOX_ENC_SAVE_MAGIC_LENGTH; 110 data += TOX_ENC_SAVE_MAGIC_LENGTH;
70 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 111 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
71 return 1; 112 SET_ERROR_PARAMETER(error, TOX_ERR_GET_SALT_OK);
113 return true;
72} 114}
73 115
74/* Generates a secret symmetric key from the given passphrase. out_key must be at least 116/* Generates a secret symmetric key from the given passphrase. out_key must be at least
@@ -82,19 +124,19 @@ bool tox_get_salt(const uint8_t *data, uint8_t *salt)
82 * 124 *
83 * returns true on success 125 * returns true on success
84 */ 126 */
85bool tox_derive_key_from_pass(const uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, 127bool tox_pass_key_derive(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
86 TOX_ERR_KEY_DERIVATION *error) 128 TOX_ERR_KEY_DERIVATION *error)
87{ 129{
88 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 130 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
89 randombytes(salt, sizeof salt); 131 randombytes(salt, sizeof salt);
90 return tox_derive_key_with_salt(passphrase, pplength, salt, out_key, error); 132 return tox_pass_key_derive_with_salt(out_key, passphrase, pplength, salt, error);
91} 133}
92 134
93/* Same as above, except with use the given salt for deterministic key derivation. 135/* Same as above, except with use the given salt for deterministic key derivation.
94 * The salt must be TOX_PASS_SALT_LENGTH bytes in length. 136 * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
95 */ 137 */
96bool tox_derive_key_with_salt(const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_PASS_KEY *out_key, 138bool tox_pass_key_derive_with_salt(Tox_Pass_Key *out_key, const uint8_t *passphrase, size_t pplength,
97 TOX_ERR_KEY_DERIVATION *error) 139 const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error)
98{ 140{
99 if (!salt || !out_key || (!passphrase && pplength != 0)) { 141 if (!salt || !out_key || (!passphrase && pplength != 0)) {
100 SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); 142 SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
@@ -134,7 +176,7 @@ bool tox_derive_key_with_salt(const uint8_t *passphrase, size_t pplength, const
134 * 176 *
135 * returns true on success 177 * returns true on success
136 */ 178 */
137bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out, 179bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t data_len, uint8_t *out,
138 TOX_ERR_ENCRYPTION *error) 180 TOX_ERR_ENCRYPTION *error)
139{ 181{
140 if (data_len == 0 || !data || !key || !out) { 182 if (data_len == 0 || !data || !key || !out) {
@@ -176,17 +218,17 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_K
176 218
177/* Encrypts the given data with the given passphrase. The output array must be 219/* Encrypts the given data with the given passphrase. The output array must be
178 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates 220 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
179 * to tox_derive_key_from_pass and tox_pass_key_encrypt. 221 * to tox_derive_key and tox_pass_key_encrypt.
180 * 222 *
181 * returns true on success 223 * returns true on success
182 */ 224 */
183bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out, 225bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out,
184 TOX_ERR_ENCRYPTION *error) 226 TOX_ERR_ENCRYPTION *error)
185{ 227{
186 TOX_PASS_KEY key; 228 Tox_Pass_Key key;
187 TOX_ERR_KEY_DERIVATION _error; 229 TOX_ERR_KEY_DERIVATION _error;
188 230
189 if (!tox_derive_key_from_pass(passphrase, pplength, &key, &_error)) { 231 if (!tox_pass_key_derive(&key, passphrase, pplength, &_error)) {
190 if (_error == TOX_ERR_KEY_DERIVATION_NULL) { 232 if (_error == TOX_ERR_KEY_DERIVATION_NULL) {
191 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); 233 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
192 } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { 234 } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) {
@@ -196,17 +238,17 @@ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passp
196 return 0; 238 return 0;
197 } 239 }
198 240
199 return tox_pass_key_encrypt(data, data_len, &key, out, error); 241 return tox_pass_key_encrypt(&key, data, data_len, out, error);
200} 242}
201 243
202/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by 244/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
203 * tox_derive_key_from_pass. 245 * tox_derive_key.
204 * 246 *
205 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH 247 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
206 * 248 *
207 * returns true on success 249 * returns true on success
208 */ 250 */
209bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out, 251bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *data, size_t length, uint8_t *out,
210 TOX_ERR_DECRYPTION *error) 252 TOX_ERR_DECRYPTION *error)
211{ 253{
212 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { 254 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
@@ -274,15 +316,15 @@ bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphr
274 memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 316 memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
275 317
276 /* derive the key */ 318 /* derive the key */
277 TOX_PASS_KEY key; 319 Tox_Pass_Key key;
278 320
279 if (!tox_derive_key_with_salt(passphrase, pplength, salt, &key, NULL)) { 321 if (!tox_pass_key_derive_with_salt(&key, passphrase, pplength, salt, NULL)) {
280 /* out of memory most likely */ 322 /* out of memory most likely */
281 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); 323 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED);
282 return 0; 324 return 0;
283 } 325 }
284 326
285 return tox_pass_key_decrypt(data, length, &key, out, error); 327 return tox_pass_key_decrypt(&key, data, length, out, error);
286} 328}
287 329
288/* Determines whether or not the given data is encrypted (by checking the magic number) 330/* Determines whether or not the given data is encrypted (by checking the magic number)
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h
index 5b2eea75..584efaed 100644
--- a/toxencryptsave/toxencryptsave.h
+++ b/toxencryptsave/toxencryptsave.h
@@ -1,8 +1,8 @@
1/* toxencryptsave.h 1/* toxencryptsave.h
2 * 2 *
3 * The Tox encrypted save functions. 3 * Batch encryption functions.
4 * 4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved. 5 * Copyright (C) 2013-2016 Tox Developers. All Rights Reserved.
6 * 6 *
7 * This file is part of Tox. 7 * This file is part of Tox.
8 * 8 *
@@ -32,217 +32,350 @@ extern "C" {
32#include <stddef.h> 32#include <stddef.h>
33#include <stdint.h> 33#include <stdint.h>
34 34
35#ifndef TOX_DEFINED
36#define TOX_DEFINED
37typedef struct Tox Tox;
38struct Tox_Options;
39#endif
40 35
41#define TOX_PASS_SALT_LENGTH 32 36/*******************************************************************************
42#define TOX_PASS_KEY_LENGTH 32 37 *
43#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80 38 * This module is organized into two parts.
39 *
40 * 1. A simple API operating on plain text/cipher text data and a password to
41 * encrypt or decrypt it.
42 * 2. A more advanced API that splits key derivation and encryption into two
43 * separate function calls.
44 *
45 * The first part is implemented in terms of the second part and simply calls
46 * the separate functions in sequence. Since key derivation is very expensive
47 * compared to the actual encryption, clients that do a lot of crypto should
48 * prefer the advanced API and reuse pass-key objects.
49 *
50 * To use the second part, first derive an encryption key from a password with
51 * <unresolved>, then use the derived key to encrypt the data.
52 *
53 * The encrypted data is prepended with a magic number, to aid validity
54 * checking (no guarantees are made of course). Any data to be decrypted must
55 * start with the magic number.
56 *
57 * Clients should consider alerting their users that, unlike plain data, if
58 * even one bit becomes corrupted, the data will be entirely unrecoverable.
59 * Ditto if they forget their password, there is no way to recover the data.
60 *
61 ******************************************************************************/
62
63
44 64
45/** 65/**
46 * ToxEncryptSave. 66 * The size of the salt part of a pass-key.
47 */ 67 */
48#ifndef TOXES_DEFINED 68#define TOX_PASS_SALT_LENGTH 32
49#define TOXES_DEFINED 69
50#endif /* TOXES_DEFINED */ 70uint32_t tox_pass_salt_length(void);
51 71
52/* This module is conceptually organized into two parts. The first part are the functions 72/**
53 * with "key" in the name. To use these functions, first derive an encryption key 73 * The size of the key part of a pass-key.
54 * from a password with tox_derive_key_from_pass, and use the returned key to
55 * encrypt the data. The second part takes the password itself instead of the key,
56 * and then delegates to the first part to derive the key before de/encryption,
57 * which can simplify client code; however, key derivation is very expensive
58 * compared to the actual encryption, so clients that do a lot of encryption should
59 * favor using the first part intead of the second part.
60 *
61 * The encrypted data is prepended with a magic number, to aid validity checking
62 * (no guarantees are made of course). Any data to be decrypted must start with
63 * the magic number.
64 *
65 * Clients should consider alerting their users that, unlike plain data, if even one bit
66 * becomes corrupted, the data will be entirely unrecoverable.
67 * Ditto if they forget their password, there is no way to recover the data.
68 */ 74 */
75#define TOX_PASS_KEY_LENGTH 32
76
77uint32_t tox_pass_key_length(void);
69 78
70/* Since apparently no one actually bothered to learn about the module previously, 79/**
71 * the recently removed functions tox_encrypted_new and tox_get_encrypted_savedata 80 * The amount of additional data required to store any encrypted byte array.
72 * may be trivially replaced by calls to tox_pass_decrypt -> tox_new or 81 * Encrypting an array of N bytes requires N + TOX_PASS_ENCRYPTION_EXTRA_LENGTH
73 * tox_get_savedata -> tox_pass_encrypt as appropriate. The removed functions 82 * bytes in the encrypted byte array.
74 * were never more than 5 line wrappers of the other public API functions anyways.
75 * (As has always been, tox_pass_decrypt and tox_pass_encrypt are interchangeable
76 * with tox_pass_key_decrypt and tox_pass_key_encrypt, as the client program requires.)
77 */ 83 */
84#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80
85
86uint32_t tox_pass_encryption_extra_length(void);
78 87
79typedef enum TOX_ERR_KEY_DERIVATION { 88typedef enum TOX_ERR_KEY_DERIVATION {
89
90 /**
91 * The function returned successfully.
92 */
80 TOX_ERR_KEY_DERIVATION_OK, 93 TOX_ERR_KEY_DERIVATION_OK,
94
81 /** 95 /**
82 * Some input data, or maybe the output pointer, was null. 96 * One of the arguments to the function was NULL when it was not expected.
83 */ 97 */
84 TOX_ERR_KEY_DERIVATION_NULL, 98 TOX_ERR_KEY_DERIVATION_NULL,
99
85 /** 100 /**
86 * The crypto lib was unable to derive a key from the given passphrase, 101 * The crypto lib was unable to derive a key from the given passphrase,
87 * which is usually a lack of memory issue. The functions accepting keys 102 * which is usually a lack of memory issue. The functions accepting keys
88 * do not produce this error. 103 * do not produce this error.
89 */ 104 */
90 TOX_ERR_KEY_DERIVATION_FAILED 105 TOX_ERR_KEY_DERIVATION_FAILED,
106
91} TOX_ERR_KEY_DERIVATION; 107} TOX_ERR_KEY_DERIVATION;
92 108
109
93typedef enum TOX_ERR_ENCRYPTION { 110typedef enum TOX_ERR_ENCRYPTION {
111
112 /**
113 * The function returned successfully.
114 */
94 TOX_ERR_ENCRYPTION_OK, 115 TOX_ERR_ENCRYPTION_OK,
116
95 /** 117 /**
96 * Some input data, or maybe the output pointer, was null. 118 * One of the arguments to the function was NULL when it was not expected.
97 */ 119 */
98 TOX_ERR_ENCRYPTION_NULL, 120 TOX_ERR_ENCRYPTION_NULL,
121
99 /** 122 /**
100 * The crypto lib was unable to derive a key from the given passphrase, 123 * The crypto lib was unable to derive a key from the given passphrase,
101 * which is usually a lack of memory issue. The functions accepting keys 124 * which is usually a lack of memory issue. The functions accepting keys
102 * do not produce this error. 125 * do not produce this error.
103 */ 126 */
104 TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED, 127 TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED,
128
105 /** 129 /**
106 * The encryption itself failed. 130 * The encryption itself failed.
107 */ 131 */
108 TOX_ERR_ENCRYPTION_FAILED 132 TOX_ERR_ENCRYPTION_FAILED,
133
109} TOX_ERR_ENCRYPTION; 134} TOX_ERR_ENCRYPTION;
110 135
136
111typedef enum TOX_ERR_DECRYPTION { 137typedef enum TOX_ERR_DECRYPTION {
138
139 /**
140 * The function returned successfully.
141 */
112 TOX_ERR_DECRYPTION_OK, 142 TOX_ERR_DECRYPTION_OK,
143
113 /** 144 /**
114 * Some input data, or maybe the output pointer, was null. 145 * One of the arguments to the function was NULL when it was not expected.
115 */ 146 */
116 TOX_ERR_DECRYPTION_NULL, 147 TOX_ERR_DECRYPTION_NULL,
148
117 /** 149 /**
118 * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes 150 * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
119 */ 151 */
120 TOX_ERR_DECRYPTION_INVALID_LENGTH, 152 TOX_ERR_DECRYPTION_INVALID_LENGTH,
153
121 /** 154 /**
122 * The input data is missing the magic number (i.e. wasn't created by this 155 * The input data is missing the magic number (i.e. wasn't created by this
123 * module, or is corrupted) 156 * module, or is corrupted).
124 */ 157 */
125 TOX_ERR_DECRYPTION_BAD_FORMAT, 158 TOX_ERR_DECRYPTION_BAD_FORMAT,
159
126 /** 160 /**
127 * The crypto lib was unable to derive a key from the given passphrase, 161 * The crypto lib was unable to derive a key from the given passphrase,
128 * which is usually a lack of memory issue. The functions accepting keys 162 * which is usually a lack of memory issue. The functions accepting keys
129 * do not produce this error. 163 * do not produce this error.
130 */ 164 */
131 TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED, 165 TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED,
166
132 /** 167 /**
133 * The encrypted byte array could not be decrypted. Either the data was 168 * The encrypted byte array could not be decrypted. Either the data was
134 * corrupt or the password/key was incorrect. 169 * corrupted or the password/key was incorrect.
135 */ 170 */
136 TOX_ERR_DECRYPTION_FAILED 171 TOX_ERR_DECRYPTION_FAILED,
172
137} TOX_ERR_DECRYPTION; 173} TOX_ERR_DECRYPTION;
138 174
139 175
140/******************************* BEGIN PART 2 ******************************* 176
141 * For simplicty, the second part of the module is presented first. The API for 177/*******************************************************************************
142 * the first part is analgous, with some extra functions for key handling. If 178 *
143 * your code spends too much time using these functions, consider using the part 179 * BEGIN PART 1
144 * 1 functions instead. 180 *
181 * The simple API is presented first. If your code spends too much time using
182 * these functions, consider using the advanced functions instead and caching
183 * the generated pass-key.
184 *
185 ******************************************************************************/
186
187
188
189/**
190 * Encrypts the given data with the given passphrase.
191 *
192 * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
193 * bytes long. This delegates to tox_pass_key_derive and
194 * tox_pass_key_encrypt.
195 *
196 * @param plaintext A byte array of length `plaintext_len`.
197 * @param plaintext_len The length of the plain text array. May be 0.
198 * @param passphrase The user-provided password.
199 * @param passphrase_len The length of the password.
200 * @param ciphertext The cipher text array to write the encrypted data to.
201 *
202 * @return true on success.
145 */ 203 */
204bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len,
205 uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error);
146 206
147/* Encrypts the given data with the given passphrase. The output array must be 207/**
148 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates 208 * Decrypts the given data with the given passphrase.
149 * to tox_derive_key_from_pass and tox_pass_key_encrypt.
150 * 209 *
151 * returns true on success 210 * The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
211 * bytes long. This delegates to tox_pass_key_decrypt.
212 *
213 * @param ciphertext A byte array of length `ciphertext_len`.
214 * @param ciphertext_len The length of the cipher text array. May be 0.
215 * @param passphrase The user-provided password.
216 * @param passphrase_len The length of the password.
217 * @param plaintext The plain text array to write the decrypted data to.
218 *
219 * @return true on success.
152 */ 220 */
153bool tox_pass_encrypt(const uint8_t *data, size_t data_len, const uint8_t *passphrase, size_t pplength, uint8_t *out, 221bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase,
154 TOX_ERR_ENCRYPTION *error); 222 size_t passphrase_len, uint8_t *plaintext, TOX_ERR_DECRYPTION *error);
155 223
156 224
157/* Decrypts the given data with the given passphrase. The output array must be 225/*******************************************************************************
158 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
159 * to tox_pass_key_decrypt.
160 * 226 *
161 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH 227 * BEGIN PART 2
162 * 228 *
163 * returns true on success 229 * And now part 2, which does the actual encryption, and can be used to write
164 */ 230 * less CPU intensive client code than part one.
165bool tox_pass_decrypt(const uint8_t *data, size_t length, const uint8_t *passphrase, size_t pplength, uint8_t *out, 231 *
166 TOX_ERR_DECRYPTION *error); 232 ******************************************************************************/
233
167 234
168 235
169/******************************* BEGIN PART 1 ******************************* 236/**
170 * And now part "1", which does the actual encryption, and is rather less cpu 237 * This type represents a pass-key.
171 * intensive than part one. The first 3 functions are for key handling. 238 *
239 * A pass-key and a password are two different concepts: a password is given
240 * by the user in plain text. A pass-key is the generated symmetric key used
241 * for encryption and decryption. It is derived from a salt and the user-
242 * provided password.
243 *
244 * The Tox_Pass_Key structure is hidden in the implementation. It can be allocated
245 * using tox_pass_key_new and must be deallocated using tox_pass_key_free.
172 */ 246 */
247#ifndef TOX_PASS_KEY_DEFINED
248#define TOX_PASS_KEY_DEFINED
249typedef struct Tox_Pass_Key Tox_Pass_Key;
250#endif /* TOX_PASS_KEY_DEFINED */
173 251
174/* This key structure's internals should not be used by any client program, even 252/**
175 * if they are straightforward here. 253 * Create a new Tox_Pass_Key. The initial value of it is indeterminate. To
254 * initialise it, use one of the derive_* functions below.
176 */ 255 */
177typedef struct { 256struct Tox_Pass_Key *tox_pass_key_new(void);
178 uint8_t salt[TOX_PASS_SALT_LENGTH]; 257
179 uint8_t key[TOX_PASS_KEY_LENGTH]; 258/**
180} TOX_PASS_KEY; 259 * Deallocate a Tox_Pass_Key. This function behaves like free(), so NULL is an
181 260 * acceptable argument value.
182/* Generates a secret symmetric key from the given passphrase. out_key must be at least
183 * TOX_PASS_KEY_LENGTH bytes long.
184 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
185 * The password is zeroed after key derivation.
186 * The key should only be used with the other functions in this module, as it
187 * includes a salt.
188 * Note that this function is not deterministic; to derive the same key from a
189 * password, you also must know the random salt that was used. See below.
190 *
191 * returns true on success
192 */ 261 */
193bool tox_derive_key_from_pass(const uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, 262void tox_pass_key_free(struct Tox_Pass_Key *_key);
194 TOX_ERR_KEY_DERIVATION *error);
195 263
196/* Same as above, except use the given salt for deterministic key derivation. 264/**
197 * The salt must be TOX_PASS_SALT_LENGTH bytes in length. 265 * Generates a secret symmetric key from the given passphrase.
266 *
267 * Be sure to not compromise the key! Only keep it in memory, do not write
268 * it to disk.
269 *
270 * Note that this function is not deterministic; to derive the same key from
271 * a password, you also must know the random salt that was used. A
272 * deterministic version of this function is tox_pass_key_derive_with_salt.
273 *
274 * @param passphrase The user-provided password.
275 * @param passphrase_len The length of the password.
276 *
277 * @return true on success.
198 */ 278 */
199bool tox_derive_key_with_salt(const uint8_t *passphrase, size_t pplength, const uint8_t *salt, TOX_PASS_KEY *out_key, 279bool tox_pass_key_derive(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len,
200 TOX_ERR_KEY_DERIVATION *error); 280 TOX_ERR_KEY_DERIVATION *error);
201 281
202/* This retrieves the salt used to encrypt the given data, which can then be passed to 282/**
203 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted 283 * Same as above, except use the given salt for deterministic key derivation.
204 * data with this module can be used as input.
205 * 284 *
206 * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. 285 * @param passphrase The user-provided password.
207 * The salt must be TOX_PASS_SALT_LENGTH bytes in length. 286 * @param passphrase_len The length of the password.
287 * @param salt An array of at least TOX_PASS_SALT_LENGTH bytes.
208 * 288 *
209 * returns true if magic number matches 289 * @return true on success.
210 * success does not say anything about the validity of the data, only that data of
211 * the appropriate size was copied
212 */ 290 */
213bool tox_get_salt(const uint8_t *data, uint8_t *salt); 291bool tox_pass_key_derive_with_salt(struct Tox_Pass_Key *_key, const uint8_t *passphrase, size_t passphrase_len,
292 const uint8_t *salt, TOX_ERR_KEY_DERIVATION *error);
214 293
215/* Now come the functions that are analogous to the part 2 functions. */ 294/**
295 * Encrypt a plain text with a key produced by tox_pass_key_derive or tox_pass_key_derive_with_salt.
296 *
297 * The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
298 * bytes long.
299 *
300 * @param plaintext A byte array of length `plaintext_len`.
301 * @param plaintext_len The length of the plain text array. May be 0.
302 * @param ciphertext The cipher text array to write the encrypted data to.
303 *
304 * @return true on success.
305 */
306bool tox_pass_key_encrypt(const struct Tox_Pass_Key *_key, const uint8_t *plaintext, size_t plaintext_len,
307 uint8_t *ciphertext, TOX_ERR_ENCRYPTION *error);
216 308
217/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output 309/**
218 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. 310 * This is the inverse of tox_pass_key_encrypt, also using only keys produced by
219 * key must be TOX_PASS_KEY_LENGTH bytes. 311 * tox_pass_key_derive or tox_pass_key_derive_with_salt.
220 * If you already have a symmetric key from somewhere besides this module, simply
221 * call encrypt_data_symmetric in toxcore/crypto_core directly.
222 * 312 *
223 * returns true on success 313 * @param ciphertext A byte array of length `ciphertext_len`.
314 * @param ciphertext_len The length of the cipher text array. May be 0.
315 * @param plaintext The plain text array to write the decrypted data to.
316 *
317 * @return true on success.
224 */ 318 */
225bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out, 319bool tox_pass_key_decrypt(const struct Tox_Pass_Key *_key, const uint8_t *ciphertext, size_t ciphertext_len,
226 TOX_ERR_ENCRYPTION *error); 320 uint8_t *plaintext, TOX_ERR_DECRYPTION *error);
321
322typedef enum TOX_ERR_GET_SALT {
323
324 /**
325 * The function returned successfully.
326 */
327 TOX_ERR_GET_SALT_OK,
328
329 /**
330 * One of the arguments to the function was NULL when it was not expected.
331 */
332 TOX_ERR_GET_SALT_NULL,
333
334 /**
335 * The input data is missing the magic number (i.e. wasn't created by this
336 * module, or is corrupted).
337 */
338 TOX_ERR_GET_SALT_BAD_FORMAT,
339
340} TOX_ERR_GET_SALT;
227 341
228/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by 342
229 * tox_derive_key_from_pass. 343/**
344 * Retrieves the salt used to encrypt the given data.
230 * 345 *
231 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH 346 * The retrieved salt can then be passed to tox_pass_key_derive_with_salt to
347 * produce the same key as was previously used. Any data encrypted with this
348 * module can be used as input.
232 * 349 *
233 * returns true on success 350 * The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
351 * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
352 * If the passed byte arrays are smaller than required, the behaviour is
353 * undefined.
354 *
355 * Success does not say anything about the validity of the data, only that
356 * data of the appropriate size was copied.
357 *
358 * @return true on success.
234 */ 359 */
235bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out, 360bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, TOX_ERR_GET_SALT *error);
236 TOX_ERR_DECRYPTION *error);
237 361
238/* Determines whether or not the given data is encrypted (by checking the magic number). 362/**
363 * Determines whether or not the given data is encrypted by this module.
364 *
365 * It does this check by verifying that the magic number is the one put in
366 * place by the encryption functions.
239 * 367 *
240 * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length. 368 * The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
369 * If the passed byte array is smaller than required, the behaviour is
370 * undefined.
371 *
372 * If the cipher text pointer is NULL, this function returns false.
241 * 373 *
242 * returns true on success 374 * @return true if the data is encrypted by this module.
243 */ 375 */
244bool tox_is_data_encrypted(const uint8_t *data); 376bool tox_is_data_encrypted(const uint8_t *data);
245 377
378
246#ifdef __cplusplus 379#ifdef __cplusplus
247} 380}
248#endif 381#endif