summaryrefslogtreecommitdiff
path: root/toxencryptsave/toxencryptsave.c
diff options
context:
space:
mode:
authordubslow <bunslow@gmail.com>2014-10-23 04:19:18 -0500
committerdubslow <bunslow@gmail.com>2014-10-23 04:19:18 -0500
commitd90ee9d4e447f7520fee899b7b6211125095242b (patch)
treeebcee2825fa850e92b5547e512d556ba82010328 /toxencryptsave/toxencryptsave.c
parentcfac10fb82b27c80e2ba72f07a3ef0c10f16faa6 (diff)
fix #1124 by adding salt manip functions
Also, all data now has the magic number prepended. This is incompatible for all but the save/load functions, but I think nothing besides the one experimental qTox branch used any of those, which is why I feel confident about the change.
Diffstat (limited to 'toxencryptsave/toxencryptsave.c')
-rw-r--r--toxencryptsave/toxencryptsave.c92
1 files changed, 55 insertions, 37 deletions
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index 6567eb96..c037ae58 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -36,9 +36,9 @@
36#endif 36#endif
37 37
38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ 38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \
39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) 39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
40 40
41#define TOX_PASS_KEY_LENGTH (crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) 41#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES)
42 42
43int tox_pass_encryption_extra_length() 43int tox_pass_encryption_extra_length()
44{ 44{
@@ -50,6 +50,11 @@ int tox_pass_key_length()
50 return TOX_PASS_KEY_LENGTH; 50 return TOX_PASS_KEY_LENGTH;
51} 51}
52 52
53int tox_pass_salt_length()
54{
55 return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
56}
57
53/* This "module" provides functions analogous to tox_load and tox_save in toxcore 58/* This "module" provides functions analogous to tox_load and tox_save in toxcore
54 * 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
55 * becomes corrupted, the data will be entirely unrecoverable. 60 * becomes corrupted, the data will be entirely unrecoverable.
@@ -59,7 +64,23 @@ int tox_pass_key_length()
59/* return size of the messenger data (for encrypted saving). */ 64/* return size of the messenger data (for encrypted saving). */
60uint32_t tox_encrypted_size(const Tox *tox) 65uint32_t tox_encrypted_size(const Tox *tox)
61{ 66{
62 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + TOX_ENC_SAVE_MAGIC_LENGTH; 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
71 * 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.
73 *
74 * returns -1 if the magic number is wrong
75 * returns 0 otherwise (no guarantee about validity of data)
76 */
77int tox_get_salt(uint8_t *data, uint8_t *salt)
78{
79 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
80 return -1;
81 data += TOX_ENC_SAVE_MAGIC_LENGTH;
82 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
83 return 0;
63} 84}
64 85
65/* Generates a secret symmetric key from the given passphrase. out_key must be at least 86/* Generates a secret symmetric key from the given passphrase. out_key must be at least
@@ -76,19 +97,28 @@ uint32_t tox_encrypted_size(const Tox *tox)
76 */ 97 */
77int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) 98int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key)
78{ 99{
100 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
101 randombytes(salt, sizeof salt);
102 return tox_derive_key_with_salt(passphrase, pplength, salt, out_key);
103}
104
105/* Same as above, except with use the given salt for deterministic key derivation.
106 * The salt must be tox_salt_length() bytes in length.
107 */
108int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key)
109{
79 if (pplength == 0) 110 if (pplength == 0)
80 return -1; 111 return -1;
81 112
82 uint8_t passkey[crypto_hash_sha256_BYTES]; 113 uint8_t passkey[crypto_hash_sha256_BYTES];
83 crypto_hash_sha256(passkey, passphrase, pplength); 114 crypto_hash_sha256(passkey, passphrase, pplength);
84 /* First derive a key from the password */ 115
116 uint8_t key[crypto_box_KEYBYTES];
117
118 /* Derive a key from the password */
85 /* http://doc.libsodium.org/key_derivation/README.html */ 119 /* http://doc.libsodium.org/key_derivation/README.html */
86 /* note that, according to the documentation, a generic pwhash interface will be created 120 /* note that, according to the documentation, a generic pwhash interface will be created
87 * once the pwhash competition (https://password-hashing.net/) is over */ 121 * once the pwhash competition (https://password-hashing.net/) is over */
88 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
89 uint8_t key[crypto_box_KEYBYTES];
90 randombytes(salt, sizeof salt);
91
92 if (crypto_pwhash_scryptsalsa208sha256( 122 if (crypto_pwhash_scryptsalsa208sha256(
93 key, sizeof(key), passkey, sizeof(passkey), salt, 123 key, sizeof(key), passkey, sizeof(passkey), salt,
94 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 124 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
@@ -123,13 +153,17 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
123 * need them to decrypt the data 153 * need them to decrypt the data
124 */ 154 */
125 155
126 /* first add the prefix */ 156 /* first add the magic number */
127 uint8_t nonce[crypto_box_NONCEBYTES]; 157 memcpy(out, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
128 random_nonce(nonce); 158 out += TOX_ENC_SAVE_MAGIC_LENGTH;
129 159
160 /* then add the rest prefix */
130 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 161 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
131 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 162 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
132 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 163 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
164
165 uint8_t nonce[crypto_box_NONCEBYTES];
166 random_nonce(nonce);
133 memcpy(out, nonce, crypto_box_NONCEBYTES); 167 memcpy(out, nonce, crypto_box_NONCEBYTES);
134 out += crypto_box_NONCEBYTES; 168 out += crypto_box_NONCEBYTES;
135 169
@@ -172,11 +206,6 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
172 uint8_t temp_data[temp_size]; 206 uint8_t temp_data[temp_size];
173 tox_save(tox, temp_data); 207 tox_save(tox, temp_data);
174 208
175 /* the output data consists of, in order: magic number, enc_data */
176 /* first add the magic number */
177 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
178 data += TOX_ENC_SAVE_MAGIC_LENGTH;
179
180 /* now encrypt */ 209 /* now encrypt */
181 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); 210 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
182} 211}
@@ -194,11 +223,6 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
194 uint8_t temp_data[temp_size]; 223 uint8_t temp_data[temp_size];
195 tox_save(tox, temp_data); 224 tox_save(tox, temp_data);
196 225
197 /* the output data consists of, in order: magic number, enc_data */
198 /* first add the magic number */
199 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
200 data += TOX_ENC_SAVE_MAGIC_LENGTH;
201
202 /* encrypt */ 226 /* encrypt */
203 return tox_pass_key_encrypt(temp_data, temp_size, key, data); 227 return tox_pass_key_encrypt(temp_data, temp_size, key, data);
204} 228}
@@ -211,8 +235,10 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key)
211 */ 235 */
212int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) 236int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out)
213{ 237{
214 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) 238 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH
239 || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH))
215 return -1; 240 return -1;
241 data += TOX_ENC_SAVE_MAGIC_LENGTH;
216 242
217 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 243 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
218 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 244 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
@@ -241,12 +267,11 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke
241 */ 267 */
242int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) 268int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out)
243{ 269{
244
245 uint8_t passkey[crypto_hash_sha256_BYTES]; 270 uint8_t passkey[crypto_hash_sha256_BYTES];
246 crypto_hash_sha256(passkey, passphrase, pplength); 271 crypto_hash_sha256(passkey, passphrase, pplength);
247 272
248 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 273 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
249 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 274 memcpy(salt, data+TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
250 275
251 /* derive the key */ 276 /* derive the key */
252 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 277 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
@@ -272,12 +297,6 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase,
272 */ 297 */
273int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) 298int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
274{ 299{
275 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
276 return -1;
277
278 data += TOX_ENC_SAVE_MAGIC_LENGTH;
279 length -= TOX_ENC_SAVE_MAGIC_LENGTH;
280
281 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 300 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
282 uint8_t temp_data[decrypt_length]; 301 uint8_t temp_data[decrypt_length];
283 302
@@ -295,12 +314,6 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
295 */ 314 */
296int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) 315int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key)
297{ 316{
298 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
299 return -1;
300
301 data += TOX_ENC_SAVE_MAGIC_LENGTH;
302 length -= TOX_ENC_SAVE_MAGIC_LENGTH;
303
304 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 317 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
305 uint8_t temp_data[decrypt_length]; 318 uint8_t temp_data[decrypt_length];
306 319
@@ -316,10 +329,15 @@ int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8
316 * returns 1 if it is encrypted 329 * returns 1 if it is encrypted
317 * returns 0 otherwise 330 * returns 0 otherwise
318 */ 331 */
319int tox_is_save_encrypted(const uint8_t *data) 332int tox_is_data_encrypted(const uint8_t *data)
320{ 333{
321 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) 334 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
322 return 1; 335 return 1;
323 else 336 else
324 return 0; 337 return 0;
325} 338}
339
340int tox_is_save_encrypted(const uint8_t *data)
341{
342 return tox_is_data_encrypted(data);
343}