diff options
author | Dubslow <bunslow@gmail.com> | 2015-03-31 18:15:59 -0500 |
---|---|---|
committer | Dubslow <bunslow@gmail.com> | 2015-03-31 18:31:23 -0500 |
commit | e998aca8f75e46cd360210ac588ee77af0106c6d (patch) | |
tree | 1b475ea960261fec87e963cf06243b956bc73b9b /toxencryptsave | |
parent | 1d583fa1118edeff48b5461a855b9d32c6aa0cb0 (diff) |
Fix toxencryptsave to be consistent with new_api
Upon my own decision, the two tox_encryped_new convenience functions were removed due to basically needing two different sets of error codes.
At iphydf's suggestion the corresponding tox_get_encrypted_savedata convenience functions were removed as well.
Diffstat (limited to 'toxencryptsave')
-rw-r--r-- | toxencryptsave/toxencryptsave.c | 235 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.h | 220 |
2 files changed, 174 insertions, 281 deletions
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 874f0fd0..e7ec31f1 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c | |||
@@ -37,81 +37,68 @@ | |||
37 | #include <crypto_hash_sha256.h> | 37 | #include <crypto_hash_sha256.h> |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ | 40 | #if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES |
41 | + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) | 41 | #error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES |
42 | 42 | #endif | |
43 | #define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) | ||
44 | |||
45 | int tox_pass_encryption_extra_length() | ||
46 | { | ||
47 | return TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
48 | } | ||
49 | 43 | ||
50 | int tox_pass_key_length() | 44 | #if TOX_PASS_KEY_LENGTH != (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) |
51 | { | 45 | #error TOX_PASS_KEY_LENGTH is assumed to be equal to (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) |
52 | return TOX_PASS_KEY_LENGTH; | 46 | #endif |
53 | } | ||
54 | 47 | ||
55 | int tox_pass_salt_length() | 48 | #if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) |
56 | { | 49 | #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) |
57 | return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; | 50 | #endif |
58 | } | ||
59 | 51 | ||
60 | /* This "module" provides functions analogous to tox_load and tox_save in toxcore | 52 | /* Clients should consider alerting their users that, unlike plain data, if even one bit |
61 | * Clients should consider alerting their users that, unlike plain data, if even one bit | ||
62 | * becomes corrupted, the data will be entirely unrecoverable. | 53 | * becomes corrupted, the data will be entirely unrecoverable. |
63 | * Ditto if they forget their password, there is no way to recover the data. | 54 | * Ditto if they forget their password, there is no way to recover the data. |
64 | */ | 55 | */ |
65 | 56 | ||
66 | /* return size of the messenger data (for encrypted saving). */ | ||
67 | uint32_t tox_encrypted_size(const Tox *tox) | ||
68 | { | ||
69 | return tox_get_savedata_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
70 | } | ||
71 | |||
72 | /* This retrieves the salt used to encrypt the given data, which can then be passed to | 57 | /* This retrieves the salt used to encrypt the given data, which can then be passed to |
73 | * derive_key_with_salt to produce the same key as was previously used. Any encrpyted | 58 | * derive_key_with_salt to produce the same key as was previously used. Any encrpyted |
74 | * data with this module can be used as input. | 59 | * data with this module can be used as input. |
75 | * | 60 | * |
76 | * returns -1 if the magic number is wrong | 61 | * returns true if magic number matches |
77 | * returns 0 otherwise (no guarantee about validity of data) | 62 | * success does not say anything about the validity of the data, only that data of |
63 | * the appropriate size was copied | ||
78 | */ | 64 | */ |
79 | int tox_get_salt(uint8_t *data, uint8_t *salt) | 65 | bool tox_get_salt(const uint8_t *data, uint8_t *salt) |
80 | { | 66 | { |
81 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) | 67 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) |
82 | return -1; | 68 | return 0; |
83 | 69 | ||
84 | data += TOX_ENC_SAVE_MAGIC_LENGTH; | 70 | data += TOX_ENC_SAVE_MAGIC_LENGTH; |
85 | memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); | 71 | memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); |
86 | return 0; | 72 | return 1; |
87 | } | 73 | } |
88 | 74 | ||
89 | /* Generates a secret symmetric key from the given passphrase. out_key must be at least | 75 | /* Generates a secret symmetric key from the given passphrase. out_key must be at least |
90 | * TOX_PASS_KEY_LENGTH bytes long. | 76 | * TOX_PASS_KEY_LENGTH bytes long. |
91 | * Be sure to not compromise the key! Only keep it in memory, do not write to disk. | 77 | * Be sure to not compromise the key! Only keep it in memory, do not write to disk. |
92 | * This function is fairly cheap, but irungentoo insists that you be allowed to | ||
93 | * cache the result if you want, to minimize computation for repeated encryptions. | ||
94 | * The password is zeroed after key derivation. | 78 | * The password is zeroed after key derivation. |
95 | * The key should only be used with the other functions in this module, as it | 79 | * The key should only be used with the other functions in this module, as it |
96 | * includes a salt. | 80 | * includes a salt. |
81 | * Note that this function is not deterministic; to derive the same key from a | ||
82 | * password, you also must know the random salt that was used. See below. | ||
97 | * | 83 | * |
98 | * returns 0 on success | 84 | * returns true on success |
99 | * returns -1 on failure | ||
100 | */ | 85 | */ |
101 | int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) | 86 | bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) |
102 | { | 87 | { |
103 | uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; | 88 | uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; |
104 | randombytes(salt, sizeof salt); | 89 | randombytes(salt, sizeof salt); |
105 | return tox_derive_key_with_salt(passphrase, pplength, salt, out_key); | 90 | return tox_derive_key_with_salt(passphrase, pplength, salt, out_key, error); |
106 | } | 91 | } |
107 | 92 | ||
108 | /* 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. |
109 | * The salt must be tox_salt_length() bytes in length. | 94 | * The salt must be tox_salt_length() bytes in length. |
110 | */ | 95 | */ |
111 | 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, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) |
112 | { | 97 | { |
113 | if (pplength == 0) | 98 | if (pplength == 0 || !passphrase || !salt || !out_key) { |
114 | return -1; | 99 | SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); |
100 | return 0; | ||
101 | } | ||
115 | 102 | ||
116 | uint8_t passkey[crypto_hash_sha256_BYTES]; | 103 | uint8_t passkey[crypto_hash_sha256_BYTES]; |
117 | crypto_hash_sha256(passkey, passphrase, pplength); | 104 | crypto_hash_sha256(passkey, passphrase, pplength); |
@@ -127,27 +114,32 @@ int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *sa | |||
127 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ | 114 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ |
128 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { | 115 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { |
129 | /* out of memory most likely */ | 116 | /* out of memory most likely */ |
130 | return -1; | 117 | SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); |
118 | return 0; | ||
131 | } | 119 | } |
132 | 120 | ||
133 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ | 121 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ |
134 | memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); | 122 | memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); |
135 | memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); | 123 | memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); |
136 | return 0; | 124 | SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); |
125 | return 1; | ||
137 | } | 126 | } |
138 | 127 | ||
139 | /* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output | 128 | /* Encrypt arbitrary with a key produced by tox_derive_key_*. The output |
140 | * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. | 129 | * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. |
141 | * key must be TOX_PASS_KEY_LENGTH bytes. | 130 | * key must be TOX_PASS_KEY_LENGTH bytes. |
142 | * If you already have a symmetric key from somewhere besides this module, simply | 131 | * If you already have a symmetric key from somewhere besides this module, simply |
143 | * call encrypt_data_symmetric in toxcore/crypto_core directly. | 132 | * call encrypt_data_symmetric in toxcore/crypto_core directly. |
144 | * | 133 | * |
145 | * | 134 | * returns true on success |
146 | * returns 0 on success | ||
147 | * returns -1 on failure | ||
148 | */ | 135 | */ |
149 | int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) | 136 | bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, TOX_ERR_ENCRYPTION *error) |
150 | { | 137 | { |
138 | if (data_len == 0 || !data || !key || !out) { | ||
139 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); | ||
140 | return 0; | ||
141 | } | ||
142 | |||
151 | /* the output data consists of, in order: | 143 | /* the output data consists of, in order: |
152 | * salt, nonce, mac, enc_data | 144 | * salt, nonce, mac, enc_data |
153 | * where the mac is automatically prepended by the encrypt() | 145 | * where the mac is automatically prepended by the encrypt() |
@@ -173,78 +165,58 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t * | |||
173 | /* now encrypt */ | 165 | /* now encrypt */ |
174 | if (encrypt_data_symmetric(key, nonce, data, data_len, out) | 166 | if (encrypt_data_symmetric(key, nonce, data, data_len, out) |
175 | != data_len + crypto_box_MACBYTES) { | 167 | != data_len + crypto_box_MACBYTES) { |
176 | return -1; | 168 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); |
169 | return 0; | ||
177 | } | 170 | } |
178 | 171 | ||
179 | return 0; | 172 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK); |
173 | return 1; | ||
180 | } | 174 | } |
181 | 175 | ||
182 | /* Encrypts the given data with the given passphrase. The output array must be | 176 | /* Encrypts the given data with the given passphrase. The output array must be |
183 | * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates | 177 | * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates |
184 | * to tox_derive_key_from_pass and tox_pass_key_encrypt. | 178 | * to tox_derive_key_from_pass and tox_pass_key_encrypt. |
185 | * | 179 | * |
186 | * returns 0 on success | 180 | * returns true on success |
187 | * returns -1 on failure | ||
188 | */ | 181 | */ |
189 | int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 182 | bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_ENCRYPTION *error) |
190 | { | 183 | { |
191 | uint8_t key[TOX_PASS_KEY_LENGTH]; | 184 | uint8_t key[TOX_PASS_KEY_LENGTH]; |
185 | TOX_ERR_KEY_DERIVATION _error; | ||
186 | |||
187 | if (!tox_derive_key_from_pass(passphrase, pplength, key, &_error)) { | ||
188 | if (_error == TOX_ERR_KEY_DERIVATION_NULL) { | ||
189 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); | ||
190 | } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { | ||
191 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED); | ||
192 | } | ||
193 | return 0; | ||
194 | } | ||
192 | 195 | ||
193 | if (tox_derive_key_from_pass(passphrase, pplength, key) == -1) | 196 | return tox_pass_key_encrypt(data, data_len, key, out, error); |
194 | return -1; | ||
195 | |||
196 | return tox_pass_key_encrypt(data, data_len, key, out); | ||
197 | } | ||
198 | |||
199 | /* Save the messenger data encrypted with the given password. | ||
200 | * data must be at least tox_encrypted_size(). | ||
201 | * | ||
202 | * returns 0 on success | ||
203 | * returns -1 on failure | ||
204 | */ | ||
205 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) | ||
206 | { | ||
207 | /* first get plain save data */ | ||
208 | uint32_t temp_size = tox_get_savedata_size(tox); | ||
209 | uint8_t temp_data[temp_size]; | ||
210 | tox_get_savedata(tox, temp_data); | ||
211 | |||
212 | /* now encrypt */ | ||
213 | return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); | ||
214 | } | ||
215 | |||
216 | /* Save the messenger data encrypted with the given key from tox_derive_key. | ||
217 | * data must be at least tox_encrypted_size(). | ||
218 | * | ||
219 | * returns 0 on success | ||
220 | * returns -1 on failure | ||
221 | */ | ||
222 | int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) | ||
223 | { | ||
224 | /* first get plain save data */ | ||
225 | uint32_t temp_size = tox_get_savedata_size(tox); | ||
226 | uint8_t temp_data[temp_size]; | ||
227 | tox_get_savedata(tox, temp_data); | ||
228 | |||
229 | /* encrypt */ | ||
230 | return tox_pass_key_encrypt(temp_data, temp_size, key, data); | ||
231 | } | 197 | } |
232 | 198 | ||
233 | /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by | 199 | /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by |
234 | * tox_derive_key_from_pass. | 200 | * tox_derive_key_from_pass. |
235 | * | 201 | * |
236 | * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success | 202 | * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH |
237 | * returns -1 on failure | 203 | * |
204 | * returns true on success | ||
238 | */ | 205 | */ |
239 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) | 206 | bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, TOX_ERR_DECRYPTION *error) |
240 | { | 207 | { |
241 | if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH | 208 | if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { |
242 | || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH)) | 209 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); |
243 | return -1; | 210 | return 0; |
211 | } | ||
212 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { | ||
213 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); | ||
214 | return 0; | ||
215 | } | ||
244 | 216 | ||
245 | data += TOX_ENC_SAVE_MAGIC_LENGTH; | 217 | data += TOX_ENC_SAVE_MAGIC_LENGTH; |
246 | 218 | ||
247 | uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | 219 | size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; |
248 | //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; | 220 | //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; |
249 | uint8_t nonce[crypto_box_NONCEBYTES]; | 221 | uint8_t nonce[crypto_box_NONCEBYTES]; |
250 | 222 | ||
@@ -257,20 +229,29 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke | |||
257 | /* decrypt the data */ | 229 | /* decrypt the data */ |
258 | if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) | 230 | if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) |
259 | != decrypt_length) { | 231 | != decrypt_length) { |
260 | return -1; | 232 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); |
233 | return 0; | ||
261 | } | 234 | } |
262 | 235 | ||
263 | return decrypt_length; | 236 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK); |
237 | return 1; | ||
264 | } | 238 | } |
265 | 239 | ||
266 | /* Decrypts the given data with the given passphrase. The output array must be | 240 | /* Decrypts the given data with the given passphrase. The output array must be |
267 | * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. | 241 | * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates |
242 | * to tox_pass_key_decrypt. | ||
243 | * | ||
244 | * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH | ||
268 | * | 245 | * |
269 | * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success | 246 | * returns true on success |
270 | * returns -1 on failure | ||
271 | */ | 247 | */ |
272 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) | 248 | bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error) |
273 | { | 249 | { |
250 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { | ||
251 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
274 | uint8_t passkey[crypto_hash_sha256_BYTES]; | 255 | uint8_t passkey[crypto_hash_sha256_BYTES]; |
275 | crypto_hash_sha256(passkey, passphrase, pplength); | 256 | crypto_hash_sha256(passkey, passphrase, pplength); |
276 | 257 | ||
@@ -286,60 +267,18 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, | |||
286 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ | 267 | crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ |
287 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { | 268 | crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { |
288 | /* out of memory most likely */ | 269 | /* out of memory most likely */ |
289 | return -1; | 270 | SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); |
271 | return 0; | ||
290 | } | 272 | } |
291 | 273 | ||
292 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ | 274 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ |
293 | 275 | ||
294 | return tox_pass_key_decrypt(data, length, key, out); | 276 | return tox_pass_key_decrypt(data, length, key, out, error); |
295 | } | ||
296 | |||
297 | /* Load the new messenger from encrypted data of size length. | ||
298 | * All other arguments are like toxcore/tox_new(). | ||
299 | * | ||
300 | * returns NULL on failure; see the documentation in toxcore/tox.h. | ||
301 | */ | ||
302 | Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, | ||
303 | size_t pplength, TOX_ERR_ENCRYPTED_NEW *error) | ||
304 | { | ||
305 | uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
306 | uint8_t temp_data[decrypt_length]; | ||
307 | |||
308 | if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) | ||
309 | != decrypt_length) { | ||
310 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); | ||
311 | return NULL; | ||
312 | } | ||
313 | |||
314 | return tox_new(options, temp_data, decrypt_length, error); | ||
315 | } | ||
316 | |||
317 | /* Load the messenger from encrypted data of size length, with key from tox_derive_key. | ||
318 | * All other arguments are like toxcore/tox_new(). | ||
319 | * | ||
320 | * returns NULL on failure; see the documentation in toxcore/tox.h. | ||
321 | */ | ||
322 | Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, | ||
323 | TOX_ERR_ENCRYPTED_NEW *error) | ||
324 | { | ||
325 | uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
326 | uint8_t temp_data[decrypt_length]; | ||
327 | |||
328 | if (tox_pass_key_decrypt(data, length, key, temp_data) | ||
329 | != decrypt_length) { | ||
330 | SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); | ||
331 | return NULL; | ||
332 | } | ||
333 | |||
334 | return tox_new(options, temp_data, decrypt_length, error); | ||
335 | } | 277 | } |
336 | 278 | ||
337 | /* Determines whether or not the given data is encrypted (by checking the magic number) | 279 | /* Determines whether or not the given data is encrypted (by checking the magic number) |
338 | * | ||
339 | * returns 1 if it is encrypted | ||
340 | * returns 0 otherwise | ||
341 | */ | 280 | */ |
342 | int tox_is_data_encrypted(const uint8_t *data) | 281 | bool tox_is_data_encrypted(const uint8_t *data) |
343 | { | 282 | { |
344 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) | 283 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) |
345 | return 1; | 284 | return 1; |
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index db272592..ef1dfb5e 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h | |||
@@ -30,6 +30,7 @@ extern "C" { | |||
30 | 30 | ||
31 | #include <stdint.h> | 31 | #include <stdint.h> |
32 | #include <stddef.h> | 32 | #include <stddef.h> |
33 | #include <stdbool.h> | ||
33 | 34 | ||
34 | #ifndef TOX_DEFINED | 35 | #ifndef TOX_DEFINED |
35 | #define TOX_DEFINED | 36 | #define TOX_DEFINED |
@@ -37,21 +38,11 @@ typedef struct Tox Tox; | |||
37 | struct Tox_Options; | 38 | struct Tox_Options; |
38 | #endif | 39 | #endif |
39 | 40 | ||
40 | // these functions provide access to these defines in toxencryptsave.c, which | 41 | #define TOX_PASS_SALT_LENGTH 32 |
41 | // otherwise aren't actually available in clients... | 42 | #define TOX_PASS_KEY_LENGTH 64 |
42 | int tox_pass_encryption_extra_length(); | 43 | #define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80 |
43 | 44 | ||
44 | int tox_pass_key_length(); | 45 | /* This module is conceptually organized into two parts. The first part are the functions |
45 | |||
46 | int tox_pass_salt_length(); | ||
47 | |||
48 | /* return size of the messenger data (for encrypted Messenger saving). */ | ||
49 | uint32_t tox_encrypted_size(const Tox *tox); | ||
50 | |||
51 | /* This "module" provides functions analogous to tox_load and tox_save in toxcore, | ||
52 | * as well as functions for encryption of arbitrary client data (e.g. chat logs). | ||
53 | * | ||
54 | * It is conceptually organized into two parts. The first part are the functions | ||
55 | * 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 |
56 | * 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 |
57 | * 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, |
@@ -61,114 +52,100 @@ uint32_t tox_encrypted_size(const Tox *tox); | |||
61 | * favor using the first part intead of the second part. | 52 | * favor using the first part intead of the second part. |
62 | * | 53 | * |
63 | * 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 |
64 | * (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. | ||
65 | * | 57 | * |
66 | * 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 |
67 | * becomes corrupted, the data will be entirely unrecoverable. | 59 | * becomes corrupted, the data will be entirely unrecoverable. |
68 | * 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. |
69 | */ | 61 | */ |
70 | 62 | ||
71 | 63 | typedef enum TOX_ERR_KEY_DERIVATION { | |
72 | /******************************* BEGIN PART 2 ******************************* | 64 | TOX_ERR_KEY_DERIVATION_OK, |
73 | * For simplicty, the second part of the module is presented first. The API for | ||
74 | * the first part is analgous, with some extra functions for key handling. If | ||
75 | * your code spends too much time using these functions, consider using the part | ||
76 | * 1 functions instead. | ||
77 | */ | ||
78 | |||
79 | /* Encrypts the given data with the given passphrase. The output array must be | ||
80 | * at least data_len + tox_pass_encryption_extra_length() bytes long. This delegates | ||
81 | * to tox_derive_key_from_pass and tox_pass_key_encrypt. | ||
82 | * | ||
83 | * tox_encrypted_save() is a good example of how to use this function. | ||
84 | * | ||
85 | * returns 0 on success | ||
86 | * returns -1 on failure | ||
87 | */ | ||
88 | int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out); | ||
89 | |||
90 | /* Save the messenger data encrypted with the given password. | ||
91 | * data must be at least tox_encrypted_size(). | ||
92 | * | ||
93 | * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return | ||
94 | * value. | ||
95 | * | ||
96 | * returns 0 on success | ||
97 | * returns -1 on failure | ||
98 | */ | ||
99 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); | ||
100 | |||
101 | /* Decrypts the given data with the given passphrase. The output array must be | ||
102 | * at least data_len - tox_pass_encryption_extra_length() bytes long. This delegates | ||
103 | * to tox_pass_key_decrypt. | ||
104 | * | ||
105 | * tox_encrypted_load() is a good example of how to use this function. | ||
106 | * | ||
107 | * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success | ||
108 | * returns -1 on failure | ||
109 | */ | ||
110 | int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); | ||
111 | |||
112 | typedef enum TOX_ERR_ENCRYPTED_NEW { | ||
113 | TOX_ERR_ENCRYPTED_NEW_OK, | ||
114 | TOX_ERR_ENCRYPTED_NEW_NULL, | ||
115 | /** | 65 | /** |
116 | * The function was unable to allocate enough memory to store the internal | 66 | * Some input data, or maybe the output pointer, was null. |
117 | * structures for the Tox object. | ||
118 | */ | 67 | */ |
119 | TOX_ERR_ENCRYPTED_NEW_MALLOC, | 68 | TOX_ERR_KEY_DERIVATION_NULL, |
120 | /** | 69 | /** |
121 | * The function was unable to bind to a port. This may mean that all ports | 70 | * The crypto lib was unable to derive a key from the given passphrase, |
122 | * have already been bound, e.g. by other Tox instances, or it may mean | 71 | * which is usually a lack of memory issue. The functions accepting keys |
123 | * a permission error. You may be able to gather more information from errno. | 72 | * do not produce this error. |
124 | */ | 73 | */ |
125 | TOX_ERR_ENCRYPTED_NEW_PORT_ALLOC, | 74 | TOX_ERR_KEY_DERIVATION_FAILED |
75 | } TOX_ERR_KEY_DERIVATION; | ||
76 | |||
77 | typedef enum TOX_ERR_ENCRYPTION { | ||
78 | TOX_ERR_ENCRYPTION_OK, | ||
126 | /** | 79 | /** |
127 | * proxy_type was invalid. | 80 | * Some input data, or maybe the output pointer, was null. |
128 | */ | 81 | */ |
129 | TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_TYPE, | 82 | TOX_ERR_ENCRYPTION_NULL, |
130 | /** | 83 | /** |
131 | * proxy_type was valid but the proxy_host passed had an invalid format | 84 | * The crypto lib was unable to derive a key from the given passphrase, |
132 | * or was NULL. | 85 | * which is usually a lack of memory issue. The functions accepting keys |
86 | * do not produce this error. | ||
133 | */ | 87 | */ |
134 | TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_HOST, | 88 | TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED, |
135 | /** | 89 | /** |
136 | * proxy_type was valid, but the proxy_port was invalid. | 90 | * The encryption itself failed. |
137 | */ | 91 | */ |
138 | TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_PORT, | 92 | TOX_ERR_ENCRYPTION_FAILED |
93 | } TOX_ERR_ENCRYPTION; | ||
94 | |||
95 | typedef enum TOX_ERR_DECRYPTION { | ||
96 | TOX_ERR_DECRYPTION_OK, | ||
97 | /** | ||
98 | * Some input data, or maybe the output pointer, was null. | ||
99 | */ | ||
100 | TOX_ERR_DECRYPTION_NULL, | ||
139 | /** | 101 | /** |
140 | * The proxy host passed could not be resolved. | 102 | * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes |
141 | */ | 103 | */ |
142 | TOX_ERR_ENCRYPTED_NEW_PROXY_NOT_FOUND, | 104 | TOX_ERR_DECRYPTION_INVALID_LENGTH, |
143 | /** | 105 | /** |
144 | * The byte array to be loaded contained an encrypted save. | 106 | * The input data is missing the magic number (i.e. wasn't created by this |
107 | * module, or is corrupted) | ||
145 | */ | 108 | */ |
146 | TOX_ERR_ENCRYPTED_NEW_LOAD_ENCRYPTED, | 109 | TOX_ERR_DECRYPTION_BAD_FORMAT, |
147 | /** | 110 | /** |
148 | * The data format was invalid. This can happen when loading data that was | 111 | * The crypto lib was unable to derive a key from the given passphrase, |
149 | * saved by an older version of Tox, or when the data has been corrupted. | 112 | * which is usually a lack of memory issue. The functions accepting keys |
150 | * When loading from badly formatted data, some data may have been loaded, | 113 | * do not produce this error. |
151 | * and the rest is discarded. Passing an invalid length parameter also | ||
152 | * causes this error. | ||
153 | */ | 114 | */ |
154 | TOX_ERR_ENCRYPTED_NEW_LOAD_BAD_FORMAT, | 115 | TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED, |
155 | /** | 116 | /** |
156 | * The encrypted byte array could not be decrypted. Either the data was | 117 | * The encrypted byte array could not be decrypted. Either the data was |
157 | * corrupt or the password/key was incorrect. | 118 | * corrupt or the password/key was incorrect. |
158 | * | ||
159 | * NOTE: This error code is only set by tox_encrypted_new() and | ||
160 | * tox_encrypted_key_new(), in the toxencryptsave module. | ||
161 | */ | 119 | */ |
162 | TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED | 120 | TOX_ERR_DECRYPTION_FAILED |
163 | } TOX_ERR_ENCRYPTED_NEW; | 121 | } TOX_ERR_DECRYPTION; |
122 | |||
123 | |||
124 | /******************************* BEGIN PART 2 ******************************* | ||
125 | * For simplicty, the second part of the module is presented first. The API for | ||
126 | * the first part is analgous, with some extra functions for key handling. If | ||
127 | * your code spends too much time using these functions, consider using the part | ||
128 | * 1 functions instead. | ||
129 | */ | ||
130 | |||
131 | /* Encrypts the given data with the given passphrase. The output array must be | ||
132 | * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates | ||
133 | * to tox_derive_key_from_pass and tox_pass_key_encrypt. | ||
134 | * | ||
135 | * returns true on success | ||
136 | */ | ||
137 | bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_ENCRYPTION *error); | ||
164 | 138 | ||
165 | /* Load the new messenger from encrypted data of size length. | 139 | |
166 | * All other arguments are like toxcore/tox_new(). | 140 | /* Decrypts the given data with the given passphrase. The output array must be |
141 | * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates | ||
142 | * to tox_pass_key_decrypt. | ||
143 | * | ||
144 | * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH | ||
167 | * | 145 | * |
168 | * returns NULL on failure; see the documentation in toxcore/tox.h. | 146 | * returns true on success |
169 | */ | 147 | */ |
170 | Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, | 148 | bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error); |
171 | size_t pplength, TOX_ERR_ENCRYPTED_NEW *error); | ||
172 | 149 | ||
173 | 150 | ||
174 | /******************************* BEGIN PART 1 ******************************* | 151 | /******************************* BEGIN PART 1 ******************************* |
@@ -177,7 +154,7 @@ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, s | |||
177 | */ | 154 | */ |
178 | 155 | ||
179 | /* Generates a secret symmetric key from the given passphrase. out_key must be at least | 156 | /* Generates a secret symmetric key from the given passphrase. out_key must be at least |
180 | * tox_pass_key_length() bytes long. | 157 | * TOX_PASS_KEY_LENGTH bytes long. |
181 | * Be sure to not compromise the key! Only keep it in memory, do not write to disk. | 158 | * Be sure to not compromise the key! Only keep it in memory, do not write to disk. |
182 | * The password is zeroed after key derivation. | 159 | * The password is zeroed after key derivation. |
183 | * The key should only be used with the other functions in this module, as it | 160 | * The key should only be used with the other functions in this module, as it |
@@ -185,72 +162,49 @@ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, s | |||
185 | * Note that this function is not deterministic; to derive the same key from a | 162 | * Note that this function is not deterministic; to derive the same key from a |
186 | * password, you also must know the random salt that was used. See below. | 163 | * password, you also must know the random salt that was used. See below. |
187 | * | 164 | * |
188 | * returns 0 on success | 165 | * returns true on success |
189 | * returns -1 on failure | ||
190 | */ | 166 | */ |
191 | int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key); | 167 | bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); |
192 | 168 | ||
193 | /* Same as above, except with use the given salt for deterministic key derivation. | 169 | /* Same as above, except with use the given salt for deterministic key derivation. |
194 | * The salt must be tox_salt_length() bytes in length. | 170 | * The salt must be tox_salt_length() bytes in length. |
195 | */ | 171 | */ |
196 | int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key); | 172 | bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); |
197 | 173 | ||
198 | /* This retrieves the salt used to encrypt the given data, which can then be passed to | 174 | /* This retrieves the salt used to encrypt the given data, which can then be passed to |
199 | * derive_key_with_salt to produce the same key as was previously used. Any encrpyted | 175 | * derive_key_with_salt to produce the same key as was previously used. Any encrpyted |
200 | * data with this module can be used as input. | 176 | * data with this module can be used as input. |
201 | * | 177 | * |
202 | * returns -1 if the magic number is wrong | 178 | * returns true if magic number matches |
203 | * returns 0 otherwise (no guarantee about validity of data) | 179 | * success does not say anything about the validity of the data, only that data of |
180 | * the appropriate size was copied | ||
204 | */ | 181 | */ |
205 | int tox_get_salt(uint8_t *data, uint8_t *salt); | 182 | bool tox_get_salt(const uint8_t *data, uint8_t *salt); |
206 | 183 | ||
207 | /* Now come the functions that are analogous to the part 2 functions. */ | 184 | /* Now come the functions that are analogous to the part 2 functions. */ |
208 | 185 | ||
209 | /* Encrypt arbitrary with a key produced by tox_derive_key_. The output | 186 | /* Encrypt arbitrary with a key produced by tox_derive_key_*. The output |
210 | * array must be at least data_len + tox_pass_encryption_extra_length() bytes long. | 187 | * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. |
211 | * key must be tox_pass_key_length() bytes. | 188 | * key must be TOX_PASS_KEY_LENGTH bytes. |
212 | * If you already have a symmetric key from somewhere besides this module, simply | 189 | * If you already have a symmetric key from somewhere besides this module, simply |
213 | * call encrypt_data_symmetric in toxcore/crypto_core directly. | 190 | * call encrypt_data_symmetric in toxcore/crypto_core directly. |
214 | * | 191 | * |
215 | * returns 0 on success | 192 | * returns true on success |
216 | * returns -1 on failure | ||
217 | */ | ||
218 | int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out); | ||
219 | |||
220 | /* Save the messenger data encrypted with the given key from tox_derive_key. | ||
221 | * data must be at least tox_encrypted_size(). | ||
222 | * | ||
223 | * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return | ||
224 | * value. | ||
225 | * | ||
226 | * returns 0 on success | ||
227 | * returns -1 on failure | ||
228 | */ | 193 | */ |
229 | int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key); | 194 | bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, TOX_ERR_ENCRYPTION *error); |
230 | 195 | ||
231 | /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by | 196 | /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by |
232 | * tox_derive_key_from_pass. | 197 | * tox_derive_key_from_pass. |
233 | * | 198 | * |
234 | * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success | 199 | * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH |
235 | * returns -1 on failure | ||
236 | */ | ||
237 | int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out); | ||
238 | |||
239 | /* Load the messenger from encrypted data of size length, with key from tox_derive_key. | ||
240 | * All other arguments are like toxcore/tox_new(). | ||
241 | * | 200 | * |
242 | * returns NULL on failure; see the documentation in toxcore/tox.h. | 201 | * returns true on success |
243 | */ | 202 | */ |
244 | Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, | 203 | bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, TOX_ERR_DECRYPTION *error); |
245 | TOX_ERR_ENCRYPTED_NEW *error); | ||
246 | |||
247 | 204 | ||
248 | /* Determines whether or not the given data is encrypted (by checking the magic number) | 205 | /* Determines whether or not the given data is encrypted (by checking the magic number) |
249 | * | ||
250 | * returns 1 if it is encrypted | ||
251 | * returns 0 otherwise | ||
252 | */ | 206 | */ |
253 | int tox_is_data_encrypted(const uint8_t *data); | 207 | bool tox_is_data_encrypted(const uint8_t *data); |
254 | 208 | ||
255 | #ifdef __cplusplus | 209 | #ifdef __cplusplus |
256 | } | 210 | } |