summaryrefslogtreecommitdiff
path: root/toxencryptsave
diff options
context:
space:
mode:
authormannol <eniz_vukovic@hotmail.com>2015-04-17 19:19:58 +0200
committermannol <eniz_vukovic@hotmail.com>2015-04-17 19:19:58 +0200
commitd1fd3e36a6b58d4cd6b3e2a7ccbed7e1e5d2e2a3 (patch)
tree6ae0aacc5fba56fc356be615b6f459c95647d597 /toxencryptsave
parent969367b72aebaa2ecfc168cf2e86b20501298c20 (diff)
parentf8087887feaf77577a345ae1be68776459613c03 (diff)
Updated with upstream
Diffstat (limited to 'toxencryptsave')
-rw-r--r--toxencryptsave/defines.h2
-rw-r--r--toxencryptsave/toxencryptsave.c289
-rw-r--r--toxencryptsave/toxencryptsave.h200
3 files changed, 242 insertions, 249 deletions
diff --git a/toxencryptsave/defines.h b/toxencryptsave/defines.h
new file mode 100644
index 00000000..e3fca073
--- /dev/null
+++ b/toxencryptsave/defines.h
@@ -0,0 +1,2 @@
1#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave"
2#define TOX_ENC_SAVE_MAGIC_LENGTH 8
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index 9172f512..e2f28a58 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -26,8 +26,9 @@
26#endif 26#endif
27 27
28#include "toxencryptsave.h" 28#include "toxencryptsave.h"
29#include "defines.h"
29#include "../toxcore/crypto_core.h" 30#include "../toxcore/crypto_core.h"
30#include "../toxcore/tox.h" 31#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}}
31 32
32#ifdef VANILLA_NACL 33#ifdef VANILLA_NACL
33#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h" 34#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
@@ -35,81 +36,70 @@
35#include <crypto_hash_sha256.h> 36#include <crypto_hash_sha256.h>
36#endif 37#endif
37 38
38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ 39#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES
39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) 40#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES
40 41#endif
41#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES)
42
43int tox_pass_encryption_extra_length()
44{
45 return TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
46}
47 42
48int tox_pass_key_length() 43#if TOX_PASS_KEY_LENGTH != crypto_box_KEYBYTES
49{ 44#error TOX_PASS_KEY_LENGTH is assumed to be equal to crypto_box_KEYBYTES
50 return TOX_PASS_KEY_LENGTH; 45#endif
51}
52 46
53int tox_pass_salt_length() 47#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
54{ 48#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)
55 return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 49#endif
56}
57 50
58/* This "module" provides functions analogous to tox_load and tox_save in toxcore 51/* Clients should consider alerting their users that, unlike plain data, if even one bit
59 * Clients should consider alerting their users that, unlike plain data, if even one bit
60 * becomes corrupted, the data will be entirely unrecoverable. 52 * becomes corrupted, the data will be entirely unrecoverable.
61 * Ditto if they forget their password, there is no way to recover the data. 53 * Ditto if they forget their password, there is no way to recover the data.
62 */ 54 */
63 55
64/* return size of the messenger data (for encrypted saving). */
65uint32_t tox_encrypted_size(const Tox *tox)
66{
67 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
68}
69
70/* This retrieves the salt used to encrypt the given data, which can then be passed to 56/* This retrieves the salt used to encrypt the given data, which can then be passed to
71 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted 57 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted
72 * data with this module can be used as input. 58 * data with this module can be used as input.
73 * 59 *
74 * returns -1 if the magic number is wrong 60 * returns true if magic number matches
75 * returns 0 otherwise (no guarantee about validity of data) 61 * success does not say anything about the validity of the data, only that data of
62 * the appropriate size was copied
76 */ 63 */
77int tox_get_salt(uint8_t *data, uint8_t *salt) 64bool tox_get_salt(const uint8_t *data, uint8_t *salt)
78{ 65{
79 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) 66 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
80 return -1; 67 return 0;
81 68
82 data += TOX_ENC_SAVE_MAGIC_LENGTH; 69 data += TOX_ENC_SAVE_MAGIC_LENGTH;
83 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 70 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
84 return 0; 71 return 1;
85} 72}
86 73
87/* Generates a secret symmetric key from the given passphrase. out_key must be at least 74/* Generates a secret symmetric key from the given passphrase. out_key must be at least
88 * TOX_PASS_KEY_LENGTH bytes long. 75 * TOX_PASS_KEY_LENGTH bytes long.
89 * Be sure to not compromise the key! Only keep it in memory, do not write to disk. 76 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
90 * This function is fairly cheap, but irungentoo insists that you be allowed to
91 * cache the result if you want, to minimize computation for repeated encryptions.
92 * The password is zeroed after key derivation. 77 * The password is zeroed after key derivation.
93 * The key should only be used with the other functions in this module, as it 78 * The key should only be used with the other functions in this module, as it
94 * includes a salt. 79 * includes a salt.
80 * Note that this function is not deterministic; to derive the same key from a
81 * password, you also must know the random salt that was used. See below.
95 * 82 *
96 * returns 0 on success 83 * returns true on success
97 * returns -1 on failure
98 */ 84 */
99int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) 85bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key,
86 TOX_ERR_KEY_DERIVATION *error)
100{ 87{
101 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 88 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
102 randombytes(salt, sizeof salt); 89 randombytes(salt, sizeof salt);
103 return tox_derive_key_with_salt(passphrase, pplength, salt, out_key); 90 return tox_derive_key_with_salt(passphrase, pplength, salt, out_key, error);
104} 91}
105 92
106/* Same as above, except with use the given salt for deterministic key derivation. 93/* Same as above, except with use the given salt for deterministic key derivation.
107 * The salt must be tox_salt_length() bytes in length. 94 * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
108 */ 95 */
109int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key) 96bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key,
97 TOX_ERR_KEY_DERIVATION *error)
110{ 98{
111 if (pplength == 0) 99 if (pplength == 0 || !passphrase || !salt || !out_key) {
112 return -1; 100 SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
101 return 0;
102 }
113 103
114 uint8_t passkey[crypto_hash_sha256_BYTES]; 104 uint8_t passkey[crypto_hash_sha256_BYTES];
115 crypto_hash_sha256(passkey, passphrase, pplength); 105 crypto_hash_sha256(passkey, passphrase, pplength);
@@ -125,27 +115,33 @@ int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *sa
125 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 115 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
126 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { 116 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
127 /* out of memory most likely */ 117 /* out of memory most likely */
128 return -1; 118 SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED);
119 return 0;
129 } 120 }
130 121
131 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ 122 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
132 memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 123 memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
133 memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); 124 memcpy(out_key->key, key, crypto_box_KEYBYTES);
134 return 0; 125 SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK);
126 return 1;
135} 127}
136 128
137/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output 129/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output
138 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. 130 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
139 * key must be TOX_PASS_KEY_LENGTH bytes. 131 * key must be TOX_PASS_KEY_LENGTH bytes.
140 * If you already have a symmetric key from somewhere besides this module, simply 132 * If you already have a symmetric key from somewhere besides this module, simply
141 * call encrypt_data_symmetric in toxcore/crypto_core directly. 133 * call encrypt_data_symmetric in toxcore/crypto_core directly.
142 * 134 *
143 * 135 * returns true on success
144 * returns 0 on success
145 * returns -1 on failure
146 */ 136 */
147int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) 137bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out,
138 TOX_ERR_ENCRYPTION *error)
148{ 139{
140 if (data_len == 0 || !data || !key || !out) {
141 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
142 return 0;
143 }
144
149 /* the output data consists of, in order: 145 /* the output data consists of, in order:
150 * salt, nonce, mac, enc_data 146 * salt, nonce, mac, enc_data
151 * where the mac is automatically prepended by the encrypt() 147 * where the mac is automatically prepended by the encrypt()
@@ -159,8 +155,7 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
159 out += TOX_ENC_SAVE_MAGIC_LENGTH; 155 out += TOX_ENC_SAVE_MAGIC_LENGTH;
160 156
161 /* then add the rest prefix */ 157 /* then add the rest prefix */
162 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 158 memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
163 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
164 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 159 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
165 160
166 uint8_t nonce[crypto_box_NONCEBYTES]; 161 uint8_t nonce[crypto_box_NONCEBYTES];
@@ -169,177 +164,133 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
169 out += crypto_box_NONCEBYTES; 164 out += crypto_box_NONCEBYTES;
170 165
171 /* now encrypt */ 166 /* now encrypt */
172 if (encrypt_data_symmetric(key, nonce, data, data_len, out) 167 if (encrypt_data_symmetric(key->key, nonce, data, data_len, out)
173 != data_len + crypto_box_MACBYTES) { 168 != data_len + crypto_box_MACBYTES) {
174 return -1; 169 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
170 return 0;
175 } 171 }
176 172
177 return 0; 173 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK);
174 return 1;
178} 175}
179 176
180/* Encrypts the given data with the given passphrase. The output array must be 177/* Encrypts the given data with the given passphrase. The output array must be
181 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates 178 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
182 * to tox_derive_key_from_pass and tox_pass_key_encrypt. 179 * to tox_derive_key_from_pass and tox_pass_key_encrypt.
183 * 180 *
184 * returns 0 on success 181 * returns true on success
185 * returns -1 on failure
186 */ 182 */
187int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) 183bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out,
184 TOX_ERR_ENCRYPTION *error)
188{ 185{
189 uint8_t key[TOX_PASS_KEY_LENGTH]; 186 TOX_PASS_KEY key;
190 187 TOX_ERR_KEY_DERIVATION _error;
191 if (tox_derive_key_from_pass(passphrase, pplength, key) == -1)
192 return -1;
193 188
194 return tox_pass_key_encrypt(data, data_len, key, out); 189 if (!tox_derive_key_from_pass(passphrase, pplength, &key, &_error)) {
195} 190 if (_error == TOX_ERR_KEY_DERIVATION_NULL) {
196 191 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
197/* Save the messenger data encrypted with the given password. 192 } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) {
198 * data must be at least tox_encrypted_size(). 193 SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED);
199 * 194 }
200 * returns 0 on success
201 * returns -1 on failure
202 */
203int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength)
204{
205 /* first get plain save data */
206 uint32_t temp_size = tox_size(tox);
207 uint8_t temp_data[temp_size];
208 tox_save(tox, temp_data);
209
210 /* now encrypt */
211 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
212}
213 195
214/* Save the messenger data encrypted with the given key from tox_derive_key. 196 return 0;
215 * data must be at least tox_encrypted_size(). 197 }
216 *
217 * returns 0 on success
218 * returns -1 on failure
219 */
220int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
221{
222 /* first get plain save data */
223 uint32_t temp_size = tox_size(tox);
224 uint8_t temp_data[temp_size];
225 tox_save(tox, temp_data);
226 198
227 /* encrypt */ 199 return tox_pass_key_encrypt(data, data_len, &key, out, error);
228 return tox_pass_key_encrypt(temp_data, temp_size, key, data);
229} 200}
230 201
231/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by 202/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
232 * tox_derive_key_from_pass. 203 * tox_derive_key_from_pass.
233 * 204 *
234 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success 205 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
235 * returns -1 on failure 206 *
207 * returns true on success
236 */ 208 */
237int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) 209bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out,
210 TOX_ERR_DECRYPTION *error)
238{ 211{
239 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH 212 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
240 || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH)) 213 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
241 return -1; 214 return 0;
215 }
216
217 if (!data || !key || !out) {
218 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
219 return 0;
220 }
221
222 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
223 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
224 return 0;
225 }
242 226
243 data += TOX_ENC_SAVE_MAGIC_LENGTH; 227 data += TOX_ENC_SAVE_MAGIC_LENGTH;
228 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation
244 229
245 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 230 size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
246 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
247 uint8_t nonce[crypto_box_NONCEBYTES];
248 231
249 //memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 232 uint8_t nonce[crypto_box_NONCEBYTES];
250 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // ignore the salt, which is only needed for kdf
251 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
252 memcpy(nonce, data, crypto_box_NONCEBYTES); 233 memcpy(nonce, data, crypto_box_NONCEBYTES);
253 data += crypto_box_NONCEBYTES; 234 data += crypto_box_NONCEBYTES;
254 235
255 /* decrypt the data */ 236 /* decrypt the data */
256 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) 237 if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
257 != decrypt_length) { 238 != decrypt_length) {
258 return -1; 239 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED);
240 return 0;
259 } 241 }
260 242
261 return decrypt_length; 243 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK);
244 return 1;
262} 245}
263 246
264/* Decrypts the given data with the given passphrase. The output array must be 247/* Decrypts the given data with the given passphrase. The output array must be
265 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. 248 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
249 * to tox_pass_key_decrypt.
250 *
251 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
266 * 252 *
267 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success 253 * returns true on success
268 * returns -1 on failure
269 */ 254 */
270int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) 255bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out,
256 TOX_ERR_DECRYPTION *error)
271{ 257{
272 uint8_t passkey[crypto_hash_sha256_BYTES]; 258 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH || pplength == 0) {
273 crypto_hash_sha256(passkey, passphrase, pplength); 259 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
260 return 0;
261 }
262
263 if (!data || !passphrase || !out) {
264 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL);
265 return 0;
266 }
267
268 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) {
269 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT);
270 return 0;
271 }
274 272
275 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 273 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
276 memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 274 memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
277 275
278 /* derive the key */ 276 /* derive the key */
279 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 277 TOX_PASS_KEY key;
280 278
281 if (crypto_pwhash_scryptsalsa208sha256( 279 if (!tox_derive_key_with_salt(passphrase, pplength, salt, &key, NULL)) {
282 key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
283 crypto_box_KEYBYTES, (char *)passkey, sizeof(passkey), salt,
284 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
285 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
286 /* out of memory most likely */ 280 /* out of memory most likely */
287 return -1; 281 SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED);
282 return 0;
288 } 283 }
289 284
290 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ 285 return tox_pass_key_decrypt(data, length, &key, out, error);
291
292 return tox_pass_key_decrypt(data, length, key, out);
293}
294
295/* Load the messenger from encrypted data of size length.
296 *
297 * returns 0 on success
298 * returns -1 on failure
299 */
300int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
301{
302 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
303 uint8_t temp_data[decrypt_length];
304
305 if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data)
306 != decrypt_length)
307 return -1;
308
309 return tox_load(tox, temp_data, decrypt_length);
310}
311
312/* Load the messenger from encrypted data of size length, with key from tox_derive_key.
313 *
314 * returns 0 on success
315 * returns -1 on failure
316 */
317int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key)
318{
319 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
320 uint8_t temp_data[decrypt_length];
321
322 if (tox_pass_key_decrypt(data, length, key, temp_data)
323 != decrypt_length)
324 return -1;
325
326 return tox_load(tox, temp_data, decrypt_length);
327} 286}
328 287
329/* Determines whether or not the given data is encrypted (by checking the magic number) 288/* Determines whether or not the given data is encrypted (by checking the magic number)
330 *
331 * returns 1 if it is encrypted
332 * returns 0 otherwise
333 */ 289 */
334int tox_is_data_encrypted(const uint8_t *data) 290bool tox_is_data_encrypted(const uint8_t *data)
335{ 291{
336 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) 292 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
337 return 1; 293 return 1;
338 else 294 else
339 return 0; 295 return 0;
340} 296}
341
342int tox_is_save_encrypted(const uint8_t *data)
343{
344 return tox_is_data_encrypted(data);
345}
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h
index 169f736c..c077d899 100644
--- a/toxencryptsave/toxencryptsave.h
+++ b/toxencryptsave/toxencryptsave.h
@@ -29,27 +29,20 @@ extern "C" {
29#endif 29#endif
30 30
31#include <stdint.h> 31#include <stdint.h>
32#include <stddef.h>
33#include <stdbool.h>
32 34
33#ifndef __TOX_DEFINED__ 35#ifndef TOX_DEFINED
34#define __TOX_DEFINED__ 36#define TOX_DEFINED
35typedef struct Tox Tox; 37typedef struct Tox Tox;
38struct Tox_Options;
36#endif 39#endif
37 40
38// these functions provide access to these defines in toxencryptsave.c, which 41#define TOX_PASS_SALT_LENGTH 32
39// otherwise aren't actually available in clients... 42#define TOX_PASS_KEY_LENGTH 32
40int tox_pass_encryption_extra_length(); 43#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80
41 44
42int tox_pass_key_length(); 45/* This module is conceptually organized into two parts. The first part are the functions
43
44int tox_pass_salt_length();
45
46/* return size of the messenger data (for encrypted Messenger saving). */
47uint32_t tox_encrypted_size(const Tox *tox);
48
49/* This "module" provides functions analogous to tox_load and tox_save in toxcore,
50 * as well as functions for encryption of arbitrary client data (e.g. chat logs).
51 *
52 * It is conceptually organized into two parts. The first part are the functions
53 * with "key" in the name. To use these functions, first derive an encryption key 46 * with "key" in the name. To use these functions, first derive an encryption key
54 * from a password with tox_derive_key_from_pass, and use the returned key to 47 * 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, 48 * encrypt the data. The second part takes the password itself instead of the key,
@@ -59,13 +52,83 @@ uint32_t tox_encrypted_size(const Tox *tox);
59 * favor using the first part intead of the second part. 52 * favor using the first part intead of the second part.
60 * 53 *
61 * The encrypted data is prepended with a magic number, to aid validity checking 54 * The encrypted data is prepended with a magic number, to aid validity checking
62 * (no guarantees are made of course). 55 * (no guarantees are made of course). Any data to be decrypted must start with
56 * the magic number.
63 * 57 *
64 * Clients should consider alerting their users that, unlike plain data, if even one bit 58 * Clients should consider alerting their users that, unlike plain data, if even one bit
65 * becomes corrupted, the data will be entirely unrecoverable. 59 * becomes corrupted, the data will be entirely unrecoverable.
66 * Ditto if they forget their password, there is no way to recover the data. 60 * Ditto if they forget their password, there is no way to recover the data.
67 */ 61 */
68 62
63/* Since apparently no one actually bothered to learn about the module previously,
64 * the recently removed functions tox_encrypted_new and tox_get_encrypted_savedata
65 * may be trivially replaced by calls to tox_pass_decrypt -> tox_new or
66 * tox_get_savedata -> tox_pass_encrypt as appropriate. The removed functions
67 * were never more than 5 line wrappers of the other public API functions anyways.
68 * (As has always been, tox_pass_decrypt and tox_pass_encrypt are interchangeable
69 * with tox_pass_key_decrypt and tox_pass_key_encrypt, as the client program requires.)
70 */
71
72typedef enum TOX_ERR_KEY_DERIVATION {
73 TOX_ERR_KEY_DERIVATION_OK,
74 /**
75 * Some input data, or maybe the output pointer, was null.
76 */
77 TOX_ERR_KEY_DERIVATION_NULL,
78 /**
79 * The crypto lib was unable to derive a key from the given passphrase,
80 * which is usually a lack of memory issue. The functions accepting keys
81 * do not produce this error.
82 */
83 TOX_ERR_KEY_DERIVATION_FAILED
84} TOX_ERR_KEY_DERIVATION;
85
86typedef enum TOX_ERR_ENCRYPTION {
87 TOX_ERR_ENCRYPTION_OK,
88 /**
89 * Some input data, or maybe the output pointer, was null.
90 */
91 TOX_ERR_ENCRYPTION_NULL,
92 /**
93 * The crypto lib was unable to derive a key from the given passphrase,
94 * which is usually a lack of memory issue. The functions accepting keys
95 * do not produce this error.
96 */
97 TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED,
98 /**
99 * The encryption itself failed.
100 */
101 TOX_ERR_ENCRYPTION_FAILED
102} TOX_ERR_ENCRYPTION;
103
104typedef enum TOX_ERR_DECRYPTION {
105 TOX_ERR_DECRYPTION_OK,
106 /**
107 * Some input data, or maybe the output pointer, was null.
108 */
109 TOX_ERR_DECRYPTION_NULL,
110 /**
111 * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
112 */
113 TOX_ERR_DECRYPTION_INVALID_LENGTH,
114 /**
115 * The input data is missing the magic number (i.e. wasn't created by this
116 * module, or is corrupted)
117 */
118 TOX_ERR_DECRYPTION_BAD_FORMAT,
119 /**
120 * The crypto lib was unable to derive a key from the given passphrase,
121 * which is usually a lack of memory issue. The functions accepting keys
122 * do not produce this error.
123 */
124 TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED,
125 /**
126 * The encrypted byte array could not be decrypted. Either the data was
127 * corrupt or the password/key was incorrect.
128 */
129 TOX_ERR_DECRYPTION_FAILED
130} TOX_ERR_DECRYPTION;
131
69 132
70/******************************* BEGIN PART 2 ******************************* 133/******************************* BEGIN PART 2 *******************************
71 * For simplicty, the second part of the module is presented first. The API for 134 * For simplicty, the second part of the module is presented first. The API for
@@ -75,41 +138,25 @@ uint32_t tox_encrypted_size(const Tox *tox);
75 */ 138 */
76 139
77/* Encrypts the given data with the given passphrase. The output array must be 140/* Encrypts the given data with the given passphrase. The output array must be
78 * at least data_len + tox_pass_encryption_extra_length() bytes long. This delegates 141 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
79 * to tox_derive_key_from_pass and tox_pass_key_encrypt. 142 * to tox_derive_key_from_pass and tox_pass_key_encrypt.
80 * 143 *
81 * tox_encrypted_save() is a good example of how to use this function. 144 * returns true on success
82 *
83 * returns 0 on success
84 * returns -1 on failure
85 */ 145 */
86int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out); 146bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out,
147 TOX_ERR_ENCRYPTION *error);
87 148
88/* Save the messenger data encrypted with the given password.
89 * data must be at least tox_encrypted_size().
90 *
91 * returns 0 on success
92 * returns -1 on failure
93 */
94int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength);
95 149
96/* Decrypts the given data with the given passphrase. The output array must be 150/* Decrypts the given data with the given passphrase. The output array must be
97 * at least data_len - tox_pass_encryption_extra_length() bytes long. This delegates 151 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
98 * to tox_pass_key_decrypt. 152 * to tox_pass_key_decrypt.
99 * 153 *
100 * tox_encrypted_load() is a good example of how to use this function. 154 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
101 * 155 *
102 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success 156 * returns true on success
103 * returns -1 on failure
104 */ 157 */
105int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); 158bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out,
106 159 TOX_ERR_DECRYPTION *error);
107/* Load the messenger from encrypted data of size length.
108 *
109 * returns 0 on success
110 * returns -1 on failure
111 */
112int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength);
113 160
114 161
115/******************************* BEGIN PART 1 ******************************* 162/******************************* BEGIN PART 1 *******************************
@@ -117,8 +164,16 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
117 * intensive than part one. The first 3 functions are for key handling. 164 * intensive than part one. The first 3 functions are for key handling.
118 */ 165 */
119 166
167/* This key structure's internals should not be used by any client program, even
168 * if they are straightforward here.
169 */
170typedef struct {
171 uint8_t salt[TOX_PASS_SALT_LENGTH];
172 uint8_t key[TOX_PASS_KEY_LENGTH];
173} TOX_PASS_KEY;
174
120/* Generates a secret symmetric key from the given passphrase. out_key must be at least 175/* Generates a secret symmetric key from the given passphrase. out_key must be at least
121 * tox_pass_key_length() bytes long. 176 * TOX_PASS_KEY_LENGTH bytes long.
122 * Be sure to not compromise the key! Only keep it in memory, do not write to disk. 177 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
123 * The password is zeroed after key derivation. 178 * The password is zeroed after key derivation.
124 * The key should only be used with the other functions in this module, as it 179 * The key should only be used with the other functions in this module, as it
@@ -126,68 +181,53 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
126 * Note that this function is not deterministic; to derive the same key from a 181 * Note that this function is not deterministic; to derive the same key from a
127 * password, you also must know the random salt that was used. See below. 182 * password, you also must know the random salt that was used. See below.
128 * 183 *
129 * returns 0 on success 184 * returns true on success
130 * returns -1 on failure
131 */ 185 */
132int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key); 186bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key,
187 TOX_ERR_KEY_DERIVATION *error);
133 188
134/* Same as above, except with use the given salt for deterministic key derivation. 189/* Same as above, except use the given salt for deterministic key derivation.
135 * The salt must be tox_salt_length() bytes in length. 190 * The salt must be TOX_PASS_SALT_LENGTH bytes in length.
136 */ 191 */
137int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key); 192bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key,
193 TOX_ERR_KEY_DERIVATION *error);
138 194
139/* This retrieves the salt used to encrypt the given data, which can then be passed to 195/* This retrieves the salt used to encrypt the given data, which can then be passed to
140 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted 196 * derive_key_with_salt to produce the same key as was previously used. Any encrpyted
141 * data with this module can be used as input. 197 * data with this module can be used as input.
142 * 198 *
143 * returns -1 if the magic number is wrong 199 * returns true if magic number matches
144 * returns 0 otherwise (no guarantee about validity of data) 200 * success does not say anything about the validity of the data, only that data of
201 * the appropriate size was copied
145 */ 202 */
146int tox_get_salt(uint8_t *data, uint8_t *salt); 203bool tox_get_salt(const uint8_t *data, uint8_t *salt);
147 204
148/* Now come the functions that are analogous to the part 2 functions. */ 205/* Now come the functions that are analogous to the part 2 functions. */
149 206
150/* Encrypt arbitrary with a key produced by tox_derive_key_. The output 207/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output
151 * array must be at least data_len + tox_pass_encryption_extra_length() bytes long. 208 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
152 * key must be tox_pass_key_length() bytes. 209 * key must be TOX_PASS_KEY_LENGTH bytes.
153 * If you already have a symmetric key from somewhere besides this module, simply 210 * If you already have a symmetric key from somewhere besides this module, simply
154 * call encrypt_data_symmetric in toxcore/crypto_core directly. 211 * call encrypt_data_symmetric in toxcore/crypto_core directly.
155 * 212 *
156 * returns 0 on success 213 * returns true on success
157 * returns -1 on failure
158 */ 214 */
159int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out); 215bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out,
160 216 TOX_ERR_ENCRYPTION *error);
161/* Save the messenger data encrypted with the given key from tox_derive_key.
162 * data must be at least tox_encrypted_size().
163 *
164 * returns 0 on success
165 * returns -1 on failure
166 */
167int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key);
168 217
169/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by 218/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
170 * tox_derive_key_from_pass. 219 * tox_derive_key_from_pass.
171 * 220 *
172 * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success 221 * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
173 * returns -1 on failure
174 */
175int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out);
176
177/* Load the messenger from encrypted data of size length, with key from tox_derive_key.
178 * 222 *
179 * returns 0 on success 223 * returns true on success
180 * returns -1 on failure
181 */ 224 */
182int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key); 225bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out,
226 TOX_ERR_DECRYPTION *error);
183 227
184/* Determines whether or not the given data is encrypted (by checking the magic number) 228/* Determines whether or not the given data is encrypted (by checking the magic number)
185 *
186 * returns 1 if it is encrypted
187 * returns 0 otherwise
188 */ 229 */
189int tox_is_data_encrypted(const uint8_t *data); 230bool tox_is_data_encrypted(const uint8_t *data);
190int tox_is_save_encrypted(const uint8_t *data); // poorly-named alias for backwards compat (oh irony...)
191 231
192#ifdef __cplusplus 232#ifdef __cplusplus
193} 233}