diff options
Diffstat (limited to 'toxencryptsave/toxencryptsave.c')
-rw-r--r-- | toxencryptsave/toxencryptsave.c | 289 |
1 files changed, 120 insertions, 169 deletions
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 | |||
43 | int tox_pass_encryption_extra_length() | ||
44 | { | ||
45 | return TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
46 | } | ||
47 | 42 | ||
48 | int 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 | ||
53 | int 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). */ | ||
65 | uint32_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 | */ |
77 | int tox_get_salt(uint8_t *data, uint8_t *salt) | 64 | bool 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 | */ |
99 | int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) | 85 | bool 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 | */ |
109 | int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key) | 96 | bool 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 | */ |
147 | int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) | 137 | bool 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 | */ |
187 | int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 183 | bool 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 | */ | ||
203 | int 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 | */ | ||
220 | int 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 | */ |
237 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) | 209 | bool 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 | */ |
270 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 255 | bool 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 | */ | ||
300 | int 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 | */ | ||
317 | int 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 | */ |
334 | int tox_is_data_encrypted(const uint8_t *data) | 290 | bool 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 | |||
342 | int tox_is_save_encrypted(const uint8_t *data) | ||
343 | { | ||
344 | return tox_is_data_encrypted(data); | ||
345 | } | ||