diff options
author | dubslow <bunslow@gmail.com> | 2014-10-23 04:19:18 -0500 |
---|---|---|
committer | dubslow <bunslow@gmail.com> | 2014-10-23 04:19:18 -0500 |
commit | d90ee9d4e447f7520fee899b7b6211125095242b (patch) | |
tree | ebcee2825fa850e92b5547e512d556ba82010328 /toxencryptsave/toxencryptsave.c | |
parent | cfac10fb82b27c80e2ba72f07a3ef0c10f16faa6 (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.c | 92 |
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 | ||
43 | int tox_pass_encryption_extra_length() | 43 | int 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 | ||
53 | int 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). */ |
60 | uint32_t tox_encrypted_size(const Tox *tox) | 65 | uint32_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 | */ | ||
77 | int 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 | */ |
77 | int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) | 98 | int 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 | */ | ||
108 | int 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 | */ |
212 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) | 236 | int 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 | */ |
242 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 268 | int 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 | */ |
273 | int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) | 298 | int 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 | */ |
296 | int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) | 315 | int 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 | */ |
319 | int tox_is_save_encrypted(const uint8_t *data) | 332 | int 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 | |||
340 | int tox_is_save_encrypted(const uint8_t *data) | ||
341 | { | ||
342 | return tox_is_data_encrypted(data); | ||
343 | } | ||