From 3c7888d7523f876740084c7315e31f973920212b Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 14 Feb 2015 23:00:12 -0500 Subject: A bit of new api work done. --- toxencryptsave/defines.h | 2 ++ toxencryptsave/toxencryptsave.c | 7 ++++--- toxencryptsave/toxencryptsave.h | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 toxencryptsave/defines.h (limited to 'toxencryptsave') 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 @@ +#define TOX_ENC_SAVE_MAGIC_NUMBER "toxEsave" +#define TOX_ENC_SAVE_MAGIC_LENGTH 8 diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 9172f512..13a34dea 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -26,6 +26,7 @@ #endif #include "toxencryptsave.h" +#include "defines.h" #include "../toxcore/crypto_core.h" #include "../toxcore/tox.h" @@ -64,7 +65,7 @@ int tox_pass_salt_length() /* return size of the messenger data (for encrypted saving). */ uint32_t tox_encrypted_size(const Tox *tox) { - return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + return tox_save_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } /* This retrieves the salt used to encrypt the given data, which can then be passed to @@ -203,7 +204,7 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) { /* first get plain save data */ - uint32_t temp_size = tox_size(tox); + uint32_t temp_size = tox_save_size(tox); uint8_t temp_data[temp_size]; tox_save(tox, temp_data); @@ -220,7 +221,7 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) { /* first get plain save data */ - uint32_t temp_size = tox_size(tox); + uint32_t temp_size = tox_save_size(tox); uint8_t temp_data[temp_size]; tox_save(tox, temp_data); diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 169f736c..da13f312 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -30,8 +30,8 @@ extern "C" { #include -#ifndef __TOX_DEFINED__ -#define __TOX_DEFINED__ +#ifndef TOX_DEFINED +#define TOX_DEFINED typedef struct Tox Tox; #endif -- cgit v1.2.3 From e632ef8a478ebb964b855c641e2ba14b279c78e1 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Fri, 27 Feb 2015 17:42:36 -0600 Subject: Realign toxencryptsave with new API --- toxcore/tox.h | 8 ++++++++ toxencryptsave/toxencryptsave.c | 36 ++++++++++++++++++------------------ toxencryptsave/toxencryptsave.h | 25 +++++++++++++++++-------- 3 files changed, 43 insertions(+), 26 deletions(-) (limited to 'toxencryptsave') diff --git a/toxcore/tox.h b/toxcore/tox.h index 2acc70ea..abae26e6 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -443,6 +443,14 @@ enum TOX_ERR_NEW { * The byte array to be loaded contained an encrypted save. */ TOX_ERR_NEW_LOAD_ENCRYPTED, + /** + * The encrypted byte array could not be decrypted. Either the data was + * corrupt or the password/key was incorrect. + * + * NOTE: This error code is only set by tox_encrypted_new() and + * tox_encrypted_key_new(), in the toxencryptsave module. + */ + TOX_ERR_NEW_LOAD_DECRYPTION_FAILED, /** * The data format was invalid. This can happen when loading data that was * saved by an older version of Tox, or when the data has been corrupted. diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 13a34dea..b801e1ba 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -29,6 +29,7 @@ #include "defines.h" #include "../toxcore/crypto_core.h" #include "../toxcore/tox.h" +#define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} #ifdef VANILLA_NACL #include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h" @@ -293,38 +294,42 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, return tox_pass_key_decrypt(data, length, key, out); } -/* Load the messenger from encrypted data of size length. +/* Load the new messenger from encrypted data of size length. + * All other arguments are like toxcore/tox_new(). * - * returns 0 on success - * returns -1 on failure + * returns NULL on failure; see the documentation in toxcore/tox.h. */ -int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) +Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, TOX_ERR_NEW *error) { uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t temp_data[decrypt_length]; if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) - != decrypt_length) - return -1; + != decrypt_length) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED); + return NULL; + } - return tox_load(tox, temp_data, decrypt_length); + return tox_new(options, temp_data, decrypt_length, error); } /* Load the messenger from encrypted data of size length, with key from tox_derive_key. + * All other arguments are like toxcore/tox_new(). * - * returns 0 on success - * returns -1 on failure + * returns NULL on failure; see the documentation in toxcore/tox.h. */ -int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key) +Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, TOX_ERR_NEW *error) { uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t temp_data[decrypt_length]; if (tox_pass_key_decrypt(data, length, key, temp_data) - != decrypt_length) - return -1; + != decrypt_length) { + SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED); + return NULL; + } - return tox_load(tox, temp_data, decrypt_length); + return tox_new(options, temp_data, decrypt_length, error); } /* Determines whether or not the given data is encrypted (by checking the magic number) @@ -339,8 +344,3 @@ int tox_is_data_encrypted(const uint8_t *data) else return 0; } - -int tox_is_save_encrypted(const uint8_t *data) -{ - return tox_is_data_encrypted(data); -} diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index da13f312..ea5f4eab 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -29,10 +29,13 @@ extern "C" { #endif #include +#include #ifndef TOX_DEFINED #define TOX_DEFINED typedef struct Tox Tox; +struct Tox_Options; +typedef uint8_t TOX_ERR_NEW; #endif // these functions provide access to these defines in toxencryptsave.c, which @@ -88,6 +91,9 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase /* Save the messenger data encrypted with the given password. * data must be at least tox_encrypted_size(). * + * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return + * value. + * * returns 0 on success * returns -1 on failure */ @@ -104,12 +110,12 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 */ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); -/* Load the messenger from encrypted data of size length. +/* Load the new messenger from encrypted data of size length. + * All other arguments are like toxcore/tox_new(). * - * returns 0 on success - * returns -1 on failure + * returns NULL on failure; see the documentation in toxcore/tox.h. */ -int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength); +Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, TOX_ERR_NEW *error); /******************************* BEGIN PART 1 ******************************* @@ -161,6 +167,9 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t * /* Save the messenger data encrypted with the given key from tox_derive_key. * data must be at least tox_encrypted_size(). * + * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return + * value. + * * returns 0 on success * returns -1 on failure */ @@ -175,11 +184,12 @@ int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key); int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out); /* Load the messenger from encrypted data of size length, with key from tox_derive_key. + * All other arguments are like toxcore/tox_new(). * - * returns 0 on success - * returns -1 on failure + * returns NULL on failure; see the documentation in toxcore/tox.h. */ -int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *key); +Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, TOX_ERR_NEW *error); + /* Determines whether or not the given data is encrypted (by checking the magic number) * @@ -187,7 +197,6 @@ int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8 * returns 0 otherwise */ int tox_is_data_encrypted(const uint8_t *data); -int tox_is_save_encrypted(const uint8_t *data); // poorly-named alias for backwards compat (oh irony...) #ifdef __cplusplus } -- cgit v1.2.3 From 20090ea661be7e3cd5eccc47084d220aff0d4607 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Fri, 6 Mar 2015 21:37:00 -0500 Subject: Fixed typedef. --- toxencryptsave/toxencryptsave.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'toxencryptsave') diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 5ceeefdd..9b613cac 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -35,7 +35,7 @@ extern "C" { #define TOX_DEFINED typedef struct Tox Tox; struct Tox_Options; -typedef uint8_t TOX_ERR_NEW; +typedef enum TOX_ERR_NEW TOX_ERR_NEW; #endif // these functions provide access to these defines in toxencryptsave.c, which -- cgit v1.2.3 From 8286c2c22fc110dcc58c981eb39dd7bf46ae8aa9 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Tue, 17 Mar 2015 16:20:38 -0400 Subject: Save function renamed to tox_get_savedata() --- auto_tests/tox_test.c | 4 ++-- testing/nTox.c | 4 ++-- toxcore/tox.c | 4 ++-- toxcore/tox.h | 13 +++++++------ toxencryptsave/toxencryptsave.c | 10 +++++----- 5 files changed, 18 insertions(+), 17 deletions(-) (limited to 'toxencryptsave') diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c index 31f65505..42ba65c7 100644 --- a/auto_tests/tox_test.c +++ b/auto_tests/tox_test.c @@ -305,9 +305,9 @@ START_TEST(test_one) tox_self_set_name(tox1, name, sizeof(name), 0); ck_assert_msg(tox_self_get_name_size(tox1) == sizeof(name), "Can't set name of TOX_MAX_NAME_LENGTH"); - size_t save_size = tox_save_size(tox1); + size_t save_size = tox_get_savedata_size(tox1); uint8_t data[save_size]; - tox_save(tox1, data); + tox_get_savedata(tox1, data); tox_kill(tox2); TOX_ERR_NEW err_n; diff --git a/testing/nTox.c b/testing/nTox.c index a0101b6b..9e114ba5 100644 --- a/testing/nTox.c +++ b/testing/nTox.c @@ -965,9 +965,9 @@ static int save_data(Tox *m) } int res = 1; - size_t size = tox_save_size(m); + size_t size = tox_get_savedata_size(m); uint8_t data[size]; - tox_save(m, data); + tox_get_savedata(m, data); if (fwrite(data, sizeof(uint8_t), size, data_file) != size) { fputs("[!] could not write data file (1)!", stderr); diff --git a/toxcore/tox.c b/toxcore/tox.c index 47f4f6a3..297e7796 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -224,13 +224,13 @@ void tox_kill(Tox *tox) logger_kill_global(); } -size_t tox_save_size(const Tox *tox) +size_t tox_get_savedata_size(const Tox *tox) { const Messenger *m = tox; return messenger_size(m); } -void tox_save(const Tox *tox, uint8_t *data) +void tox_get_savedata(const Tox *tox, uint8_t *data) { if (data) { const Messenger *m = tox; diff --git a/toxcore/tox.h b/toxcore/tox.h index 0b9a63ba..2625040f 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -497,14 +497,14 @@ typedef enum TOX_ERR_NEW { * loop with a new instance will operate correctly. * * If the data parameter is not NULL, this function will load the Tox instance - * from a byte array previously filled by tox_save. + * from a byte array previously filled by tox_get_savedata. * * If loading failed or succeeded only partially, the new or partially loaded * instance is returned and an error code is set. * * @param options An options object as described above. If this parameter is * NULL, the default options are used. - * @param data A byte array containing data previously stored by tox_save. + * @param data A byte array containing data previously stored by tox_get_savedata. * @param length The length of the byte array data. If this parameter is 0, the * data parameter is ignored. * @@ -525,20 +525,21 @@ void tox_kill(Tox *tox); /** * Calculates the number of bytes required to store the tox instance with - * tox_save. This function cannot fail. The result is always greater than 0. + * tox_get_savedata. This function cannot fail. The result is always greater + * than 0. * * @see threading for concurrency implications. */ -size_t tox_save_size(const Tox *tox); +size_t tox_get_savedata_size(const Tox *tox); /** * Store all information associated with the tox instance to a byte array. * * @param data A memory region large enough to store the tox instance data. - * Call tox_save_size to find the number of bytes required. If this parameter + * Call tox_get_savedata_size to find the number of bytes required. If this parameter * is NULL, this function has no effect. */ -void tox_save(const Tox *tox, uint8_t *data); +void tox_get_savedata(const Tox *tox, uint8_t *data); /******************************************************************************* diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index f9846ac9..587c7048 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -66,7 +66,7 @@ int tox_pass_salt_length() /* return size of the messenger data (for encrypted saving). */ uint32_t tox_encrypted_size(const Tox *tox) { - return tox_save_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + return tox_get_savedata_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; } /* This retrieves the salt used to encrypt the given data, which can then be passed to @@ -205,9 +205,9 @@ int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) { /* first get plain save data */ - uint32_t temp_size = tox_save_size(tox); + uint32_t temp_size = tox_get_savedata_size(tox); uint8_t temp_data[temp_size]; - tox_save(tox, temp_data); + tox_get_savedata(tox, temp_data); /* now encrypt */ return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); @@ -222,9 +222,9 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) { /* first get plain save data */ - uint32_t temp_size = tox_save_size(tox); + uint32_t temp_size = tox_get_savedata_size(tox); uint8_t temp_data[temp_size]; - tox_save(tox, temp_data); + tox_get_savedata(tox, temp_data); /* encrypt */ return tox_pass_key_encrypt(temp_data, temp_size, key, data); -- cgit v1.2.3 From 06b389ea5e4e0ffb1f8e6627d4909c53c23099e1 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Thu, 26 Mar 2015 12:39:09 -0400 Subject: Making tox_encrypted_new() use the same error codes as tox_new was a bad idea. They now have their own error codes. --- auto_tests/encryptsave_test.c | 8 +++--- toxcore/tox.h | 8 ------ toxencryptsave/toxencryptsave.c | 8 +++--- toxencryptsave/toxencryptsave.h | 58 ++++++++++++++++++++++++++++++++++++++--- 4 files changed, 63 insertions(+), 19 deletions(-) (limited to 'toxencryptsave') diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index de78a0c2..e2f41f43 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -55,7 +55,7 @@ END_TEST START_TEST(test_save_friend) { - TOX_ERR_NEW err = TOX_ERR_NEW_OK; + TOX_ERR_ENCRYPTED_NEW err = TOX_ERR_ENCRYPTED_NEW_OK; Tox *tox1 = tox_new(0, 0, 0, 0); Tox *tox2 = tox_new(0, 0, 0, 0); ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances"); @@ -73,7 +73,7 @@ START_TEST(test_save_friend) //ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing"); Tox *tox3 = tox_encrypted_new(0, data, size, "correcthorsebatterystaple", 25, &err); - ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new"); + ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new"); uint8_t address2[TOX_PUBLIC_KEY_SIZE]; test = tox_friend_get_public_key(tox3, 0, address2, 0); ck_assert_msg(test == 1, "no friends!"); @@ -90,7 +90,7 @@ START_TEST(test_save_friend) // first test tox_encrypted_key_new Tox *tox4 = tox_encrypted_key_new(0, data2, size, key, &err); - ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new the second"); + ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new the second"); uint8_t address4[TOX_PUBLIC_KEY_SIZE]; test = tox_friend_get_public_key(tox4, 0, address4, 0); ck_assert_msg(test == 1, "no friends! the second"); @@ -107,7 +107,7 @@ START_TEST(test_save_friend) // and now with the code in use (I only bothered with manually to debug this, and it seems a waste // to remove the manual check now that it's there) Tox *tox5 = tox_encrypted_new(0, data2, size, pw, pwlen, &err); - ck_assert_msg(err == TOX_ERR_NEW_OK, "failed to encrypted new the third"); + ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new the third"); uint8_t address5[TOX_PUBLIC_KEY_SIZE]; test = tox_friend_get_public_key(tox4, 0, address5, 0); ck_assert_msg(test == 1, "no friends! the third"); diff --git a/toxcore/tox.h b/toxcore/tox.h index f645282e..e9d007db 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -487,14 +487,6 @@ typedef enum TOX_ERR_NEW { * The byte array to be loaded contained an encrypted save. */ TOX_ERR_NEW_LOAD_ENCRYPTED, - /** - * The encrypted byte array could not be decrypted. Either the data was - * corrupt or the password/key was incorrect. - * - * NOTE: This error code is only set by tox_encrypted_new() and - * tox_encrypted_key_new(), in the toxencryptsave module. - */ - TOX_ERR_NEW_LOAD_DECRYPTION_FAILED, /** * The data format was invalid. This can happen when loading data that was * saved by an older version of Tox, or when the data has been corrupted. diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 587c7048..874f0fd0 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -300,14 +300,14 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, * returns NULL on failure; see the documentation in toxcore/tox.h. */ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, - size_t pplength, TOX_ERR_NEW *error) + size_t pplength, TOX_ERR_ENCRYPTED_NEW *error) { uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t temp_data[decrypt_length]; if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED); + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); return NULL; } @@ -320,14 +320,14 @@ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, s * returns NULL on failure; see the documentation in toxcore/tox.h. */ Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, - TOX_ERR_NEW *error) + TOX_ERR_ENCRYPTED_NEW *error) { uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t temp_data[decrypt_length]; if (tox_pass_key_decrypt(data, length, key, temp_data) != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_NEW_LOAD_DECRYPTION_FAILED); + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); return NULL; } diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 9b613cac..db272592 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -35,7 +35,6 @@ extern "C" { #define TOX_DEFINED typedef struct Tox Tox; struct Tox_Options; -typedef enum TOX_ERR_NEW TOX_ERR_NEW; #endif // these functions provide access to these defines in toxencryptsave.c, which @@ -110,13 +109,66 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 */ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); +typedef enum TOX_ERR_ENCRYPTED_NEW { + TOX_ERR_ENCRYPTED_NEW_OK, + TOX_ERR_ENCRYPTED_NEW_NULL, + /** + * The function was unable to allocate enough memory to store the internal + * structures for the Tox object. + */ + TOX_ERR_ENCRYPTED_NEW_MALLOC, + /** + * The function was unable to bind to a port. This may mean that all ports + * have already been bound, e.g. by other Tox instances, or it may mean + * a permission error. You may be able to gather more information from errno. + */ + TOX_ERR_ENCRYPTED_NEW_PORT_ALLOC, + /** + * proxy_type was invalid. + */ + TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_TYPE, + /** + * proxy_type was valid but the proxy_host passed had an invalid format + * or was NULL. + */ + TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_HOST, + /** + * proxy_type was valid, but the proxy_port was invalid. + */ + TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_PORT, + /** + * The proxy host passed could not be resolved. + */ + TOX_ERR_ENCRYPTED_NEW_PROXY_NOT_FOUND, + /** + * The byte array to be loaded contained an encrypted save. + */ + TOX_ERR_ENCRYPTED_NEW_LOAD_ENCRYPTED, + /** + * The data format was invalid. This can happen when loading data that was + * saved by an older version of Tox, or when the data has been corrupted. + * When loading from badly formatted data, some data may have been loaded, + * and the rest is discarded. Passing an invalid length parameter also + * causes this error. + */ + TOX_ERR_ENCRYPTED_NEW_LOAD_BAD_FORMAT, + /** + * The encrypted byte array could not be decrypted. Either the data was + * corrupt or the password/key was incorrect. + * + * NOTE: This error code is only set by tox_encrypted_new() and + * tox_encrypted_key_new(), in the toxencryptsave module. + */ + TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED +} TOX_ERR_ENCRYPTED_NEW; + /* Load the new messenger from encrypted data of size length. * All other arguments are like toxcore/tox_new(). * * returns NULL on failure; see the documentation in toxcore/tox.h. */ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, - size_t pplength, TOX_ERR_NEW *error); + size_t pplength, TOX_ERR_ENCRYPTED_NEW *error); /******************************* BEGIN PART 1 ******************************* @@ -190,7 +242,7 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke * returns NULL on failure; see the documentation in toxcore/tox.h. */ Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, - TOX_ERR_NEW *error); + TOX_ERR_ENCRYPTED_NEW *error); /* Determines whether or not the given data is encrypted (by checking the magic number) -- cgit v1.2.3 From e998aca8f75e46cd360210ac588ee77af0106c6d Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 31 Mar 2015 18:15:59 -0500 Subject: 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. --- auto_tests/encryptsave_test.c | 124 +++++++++++---------- toxencryptsave/toxencryptsave.c | 235 +++++++++++++++------------------------- toxencryptsave/toxencryptsave.h | 220 +++++++++++++++---------------------- 3 files changed, 240 insertions(+), 339 deletions(-) (limited to 'toxencryptsave') diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index e2f41f43..9ab29a27 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -55,7 +55,6 @@ END_TEST START_TEST(test_save_friend) { - TOX_ERR_ENCRYPTED_NEW err = TOX_ERR_ENCRYPTED_NEW_OK; Tox *tox1 = tox_new(0, 0, 0, 0); Tox *tox2 = tox_new(0, 0, 0, 0); ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances"); @@ -63,99 +62,108 @@ START_TEST(test_save_friend) tox_callback_friend_request(tox2, accept_friend_request, &to_compare); uint8_t address[TOX_ADDRESS_SIZE]; tox_self_get_address(tox2, address); - int test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0); - ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); + uint32_t test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0); + ck_assert_msg(test != UINT32_MAX, "Failed to add friend"); - uint32_t size = tox_encrypted_size(tox1); + size_t size = tox_get_savedata_size(tox1); uint8_t data[size]; - test = tox_encrypted_save(tox1, data, "correcthorsebatterystaple", 25); - ck_assert_msg(test == 0, "failed to encrypted save"); - //ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing"); - - Tox *tox3 = tox_encrypted_new(0, data, size, "correcthorsebatterystaple", 25, &err); - ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new"); + tox_get_savedata(tox1, data); + size_t size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + uint8_t enc_data[size2]; + TOX_ERR_ENCRYPTION error1; + bool ret = tox_pass_encrypt(data, size, "correcthorsebatterystaple", 25, enc_data, &error1); + ck_assert_msg(ret, "failed to encrypted save: %u", error1); + ck_assert_msg(tox_is_data_encrypted(enc_data), "magic number missing"); + + TOX_ERR_NEW err2; + Tox *tox3 = tox_new(0, enc_data, size2, &err2); + ck_assert_msg(err2 == TOX_ERR_NEW_LOAD_ENCRYPTED, "wrong error! %u. should fail with %u", err2, TOX_ERR_NEW_LOAD_ENCRYPTED); + uint8_t dec_data[size]; + TOX_ERR_DECRYPTION err3; + ret = tox_pass_decrypt(enc_data, size2, "correcthorsebatterystaple", 25, dec_data, &err3); + ck_assert_msg(ret, "failed to decrypt save: %u", err3); + tox3 = tox_new(0, dec_data, size, &err2); + ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to load from decrypted data: %u", err2); uint8_t address2[TOX_PUBLIC_KEY_SIZE]; - test = tox_friend_get_public_key(tox3, 0, address2, 0); - ck_assert_msg(test == 1, "no friends!"); + ret = tox_friend_get_public_key(tox3, 0, address2, 0); + ck_assert_msg(ret, "no friends!"); ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match!"); - size = tox_encrypted_size(tox3); + size = tox_get_savedata_size(tox3); uint8_t data2[size]; + tox_get_savedata(tox3, data2); uint8_t key[32 + crypto_box_BEFORENMBYTES]; memcpy(key, salt, 32); memcpy(key + 32, known_key2, crypto_box_BEFORENMBYTES); - test = tox_encrypted_key_save(tox3, data2, key); - ck_assert_msg(test == 0, "failed to encrypted save the second"); - //ck_assert_msg(tox_is_save_encrypted(data2) == 1, "magic number the second missing"); - - // first test tox_encrypted_key_new - Tox *tox4 = tox_encrypted_key_new(0, data2, size, key, &err); - ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new the second"); - uint8_t address4[TOX_PUBLIC_KEY_SIZE]; - test = tox_friend_get_public_key(tox4, 0, address4, 0); - ck_assert_msg(test == 1, "no friends! the second"); - ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the second"); - - // now test compaitibilty with tox_encrypted_new, first manually... + size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + uint8_t encdata2[size2]; + ret = tox_pass_key_encrypt(data2, size, key, encdata2, &error1); + ck_assert_msg(ret, "failed to key encrypt %u", error1); + ck_assert_msg(tox_is_data_encrypted(encdata2), "magic number the second missing"); + uint8_t out1[size], out2[size]; - //printf("Trying to decrypt from pw:\n"); - uint32_t sz1 = tox_pass_decrypt(data2, size, pw, pwlen, out1); - uint32_t sz2 = tox_pass_key_decrypt(data2, size, key, out2); - ck_assert_msg(sz1 == sz2, "differing output sizes"); - ck_assert_msg(memcmp(out1, out2, sz1) == 0, "differing output data"); + ret = tox_pass_decrypt(encdata2, size2, pw, pwlen, out1, &err3); + ck_assert_msg(ret, "failed to pw decrypt %u", err3); + ret = tox_pass_key_decrypt(encdata2, size2, key, out2, &err3); + ck_assert_msg(ret, "failed to key decrypt %u", err3); + ck_assert_msg(memcmp(out1, out2, size) == 0, "differing output data"); // and now with the code in use (I only bothered with manually to debug this, and it seems a waste // to remove the manual check now that it's there) - Tox *tox5 = tox_encrypted_new(0, data2, size, pw, pwlen, &err); - ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new the third"); + Tox *tox4 = tox_new(0, out1, size, &err2); + ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third"); uint8_t address5[TOX_PUBLIC_KEY_SIZE]; - test = tox_friend_get_public_key(tox4, 0, address5, 0); - ck_assert_msg(test == 1, "no friends! the third"); + ret = tox_friend_get_public_key(tox4, 0, address5, 0); + ck_assert_msg(ret, "no friends! the third"); ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the third"); tox_kill(tox1); tox_kill(tox2); tox_kill(tox3); tox_kill(tox4); - tox_kill(tox5); } END_TEST START_TEST(test_keys) { - uint8_t key[tox_pass_key_length()]; - tox_derive_key_from_pass("123qweasdzxc", 12, key); + TOX_ERR_ENCRYPTION encerr; + TOX_ERR_DECRYPTION decerr; + TOX_ERR_KEY_DERIVATION keyerr; + uint8_t key[TOX_PASS_KEY_LENGTH]; + bool ret = tox_derive_key_from_pass("123qweasdzxc", 12, key, &keyerr); + ck_assert_msg(ret, "generic failure 1: %u", keyerr); uint8_t *string = "No Patrick, mayonnaise is not an instrument."; // 44 - uint8_t encrypted[44 + tox_pass_encryption_extra_length()]; - int sz = tox_pass_key_encrypt(string, 44, key, encrypted); - - uint8_t encrypted2[44 + tox_pass_encryption_extra_length()]; - int sz2 = tox_pass_encrypt(string, 44, "123qweasdzxc", 12, encrypted2); + uint8_t encrypted[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + ret = tox_pass_key_encrypt(string, 44, key, encrypted, &encerr); + ck_assert_msg(ret, "generic failure 2: %u", encerr); - ck_assert_msg(sz == sz2, "an encryption failed"); + uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + ret = tox_pass_encrypt(string, 44, "123qweasdzxc", 12, encrypted2, &encerr); + ck_assert_msg(ret, "generic failure 3: %u", encerr); - uint8_t out1[44 + tox_pass_encryption_extra_length()]; - uint8_t out2[44 + tox_pass_encryption_extra_length()]; + uint8_t out1[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; + uint8_t out2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; - sz = tox_pass_key_decrypt(encrypted, 44 + tox_pass_encryption_extra_length(), key, out1); - ck_assert_msg(sz == 44, "sz isn't right"); + ret = tox_pass_key_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, key, out1, &decerr); + ck_assert_msg(ret, "generic failure 4: %u", decerr); ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 1 failed"); - sz2 = tox_pass_decrypt(encrypted2, 44 + tox_pass_encryption_extra_length(), "123qweasdzxc", 12, out2); - ck_assert_msg(sz2 == 44, "sz2 isn't right"); + ret = tox_pass_decrypt(encrypted2, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out2, &decerr); + ck_assert_msg(ret, "generic failure 5: %u", &decerr); ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed"); // test that pass_decrypt can decrypt things from pass_key_encrypt - sz = tox_pass_decrypt(encrypted, 44 + tox_pass_encryption_extra_length(), "123qweasdzxc", 12, out1); - ck_assert_msg(sz == 44, "sz isn't right"); + ret = tox_pass_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out1, &decerr); + ck_assert_msg(ret, "generic failure 6: %u", decerr); ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed"); - uint8_t salt[tox_pass_salt_length()]; - ck_assert_msg(0 == tox_get_salt(encrypted, salt), "couldn't get salt"); - uint8_t key2[tox_pass_key_length()]; - tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2); - ck_assert_msg(0 == memcmp(key, key2, tox_pass_key_length()), "salt comparison failed"); + uint8_t salt[TOX_PASS_SALT_LENGTH]; + ck_assert_msg(tox_get_salt(encrypted, salt), "couldn't get salt"); + uint8_t key2[TOX_PASS_KEY_LENGTH]; + ret = tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2, &keyerr); + ck_assert_msg(ret, "generic failure 7: %u", keyerr); + ck_assert_msg(0 == memcmp(key, key2, TOX_PASS_KEY_LENGTH), "salt comparison failed"); } END_TEST @@ -163,7 +171,7 @@ Suite *encryptsave_suite(void) { Suite *s = suite_create("encryptsave"); - DEFTESTCASE_SLOW(known_kdf, 60); /* is 5-10 seconds on my computer, but is directly dependent on CPU */ + DEFTESTCASE_SLOW(known_kdf, 60); DEFTESTCASE_SLOW(save_friend, 20); DEFTESTCASE_SLOW(keys, 30); 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 @@ #include #endif -#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ - + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) - -#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) - -int tox_pass_encryption_extra_length() -{ - return TOX_PASS_ENCRYPTION_EXTRA_LENGTH; -} +#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#endif -int tox_pass_key_length() -{ - return TOX_PASS_KEY_LENGTH; -} +#if TOX_PASS_KEY_LENGTH != (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) +#error TOX_PASS_KEY_LENGTH is assumed to be equal to (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) +#endif -int tox_pass_salt_length() -{ - return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; -} +#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) +#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) +#endif -/* This "module" provides functions analogous to tox_load and tox_save in toxcore - * Clients should consider alerting their users that, unlike plain data, if even one bit +/* Clients should consider alerting their users that, unlike plain data, if even one bit * becomes corrupted, the data will be entirely unrecoverable. * Ditto if they forget their password, there is no way to recover the data. */ -/* return size of the messenger data (for encrypted saving). */ -uint32_t tox_encrypted_size(const Tox *tox) -{ - return tox_get_savedata_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; -} - /* This retrieves the salt used to encrypt the given data, which can then be passed to * derive_key_with_salt to produce the same key as was previously used. Any encrpyted * data with this module can be used as input. * - * returns -1 if the magic number is wrong - * returns 0 otherwise (no guarantee about validity of data) + * returns true if magic number matches + * success does not say anything about the validity of the data, only that data of + * the appropriate size was copied */ -int tox_get_salt(uint8_t *data, uint8_t *salt) +bool tox_get_salt(const uint8_t *data, uint8_t *salt) { if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) - return -1; + return 0; data += TOX_ENC_SAVE_MAGIC_LENGTH; memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); - return 0; + return 1; } /* Generates a secret symmetric key from the given passphrase. out_key must be at least * TOX_PASS_KEY_LENGTH bytes long. * Be sure to not compromise the key! Only keep it in memory, do not write to disk. - * This function is fairly cheap, but irungentoo insists that you be allowed to - * cache the result if you want, to minimize computation for repeated encryptions. * The password is zeroed after key derivation. * The key should only be used with the other functions in this module, as it * includes a salt. + * Note that this function is not deterministic; to derive the same key from a + * password, you also must know the random salt that was used. See below. * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) +bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) { uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; randombytes(salt, sizeof salt); - return tox_derive_key_with_salt(passphrase, pplength, salt, out_key); + return tox_derive_key_with_salt(passphrase, pplength, salt, out_key, error); } /* Same as above, except with use the given salt for deterministic key derivation. * The salt must be tox_salt_length() bytes in length. */ -int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key) +bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) { - if (pplength == 0) - return -1; + if (pplength == 0 || !passphrase || !salt || !out_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); + return 0; + } uint8_t passkey[crypto_hash_sha256_BYTES]; 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 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); + return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); - return 0; + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); + return 1; } -/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output +/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. * key must be TOX_PASS_KEY_LENGTH bytes. * If you already have a symmetric key from somewhere besides this module, simply * call encrypt_data_symmetric in toxcore/crypto_core directly. * - * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) +bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, TOX_ERR_ENCRYPTION *error) { + if (data_len == 0 || !data || !key || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + return 0; + } + /* the output data consists of, in order: * salt, nonce, mac, enc_data * 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 * /* now encrypt */ if (encrypt_data_symmetric(key, nonce, data, data_len, out) != data_len + crypto_box_MACBYTES) { - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); + return 0; } - return 0; + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK); + return 1; } /* Encrypts the given data with the given passphrase. The output array must be * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates * to tox_derive_key_from_pass and tox_pass_key_encrypt. * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) +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) { uint8_t key[TOX_PASS_KEY_LENGTH]; + TOX_ERR_KEY_DERIVATION _error; + + if (!tox_derive_key_from_pass(passphrase, pplength, key, &_error)) { + if (_error == TOX_ERR_KEY_DERIVATION_NULL) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED); + } + return 0; + } - if (tox_derive_key_from_pass(passphrase, pplength, key) == -1) - return -1; - - return tox_pass_key_encrypt(data, data_len, key, out); -} - -/* Save the messenger data encrypted with the given password. - * data must be at least tox_encrypted_size(). - * - * returns 0 on success - * returns -1 on failure - */ -int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) -{ - /* first get plain save data */ - uint32_t temp_size = tox_get_savedata_size(tox); - uint8_t temp_data[temp_size]; - tox_get_savedata(tox, temp_data); - - /* now encrypt */ - return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); -} - -/* Save the messenger data encrypted with the given key from tox_derive_key. - * data must be at least tox_encrypted_size(). - * - * returns 0 on success - * returns -1 on failure - */ -int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) -{ - /* first get plain save data */ - uint32_t temp_size = tox_get_savedata_size(tox); - uint8_t temp_data[temp_size]; - tox_get_savedata(tox, temp_data); - - /* encrypt */ - return tox_pass_key_encrypt(temp_data, temp_size, key, data); + return tox_pass_key_encrypt(data, data_len, key, out, error); } /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by * tox_derive_key_from_pass. * - * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success - * returns -1 on failure + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH + * + * returns true on success */ -int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) +bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, TOX_ERR_DECRYPTION *error) { - if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH - || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH)) - return -1; + if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); + return 0; + } + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } data += TOX_ENC_SAVE_MAGIC_LENGTH; - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; uint8_t nonce[crypto_box_NONCEBYTES]; @@ -257,20 +229,29 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke /* decrypt the data */ if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) != decrypt_length) { - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); + return 0; } - return decrypt_length; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK); + return 1; } /* Decrypts the given data with the given passphrase. The output array must be - * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. + * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_pass_key_decrypt. + * + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH * - * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success - * returns -1 on failure + * returns true on success */ -int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) +bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error) { + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } + uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); @@ -286,60 +267,18 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); + return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ - return tox_pass_key_decrypt(data, length, key, out); -} - -/* Load the new messenger from encrypted data of size length. - * All other arguments are like toxcore/tox_new(). - * - * returns NULL on failure; see the documentation in toxcore/tox.h. - */ -Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, - size_t pplength, TOX_ERR_ENCRYPTED_NEW *error) -{ - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; - uint8_t temp_data[decrypt_length]; - - if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) - != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); - return NULL; - } - - return tox_new(options, temp_data, decrypt_length, error); -} - -/* Load the messenger from encrypted data of size length, with key from tox_derive_key. - * All other arguments are like toxcore/tox_new(). - * - * returns NULL on failure; see the documentation in toxcore/tox.h. - */ -Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, - TOX_ERR_ENCRYPTED_NEW *error) -{ - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; - uint8_t temp_data[decrypt_length]; - - if (tox_pass_key_decrypt(data, length, key, temp_data) - != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); - return NULL; - } - - return tox_new(options, temp_data, decrypt_length, error); + return tox_pass_key_decrypt(data, length, key, out, error); } /* Determines whether or not the given data is encrypted (by checking the magic number) - * - * returns 1 if it is encrypted - * returns 0 otherwise */ -int tox_is_data_encrypted(const uint8_t *data) +bool tox_is_data_encrypted(const uint8_t *data) { if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) 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" { #include #include +#include #ifndef TOX_DEFINED #define TOX_DEFINED @@ -37,21 +38,11 @@ typedef struct Tox Tox; struct Tox_Options; #endif -// these functions provide access to these defines in toxencryptsave.c, which -// otherwise aren't actually available in clients... -int tox_pass_encryption_extra_length(); +#define TOX_PASS_SALT_LENGTH 32 +#define TOX_PASS_KEY_LENGTH 64 +#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80 -int tox_pass_key_length(); - -int tox_pass_salt_length(); - -/* return size of the messenger data (for encrypted Messenger saving). */ -uint32_t tox_encrypted_size(const Tox *tox); - -/* This "module" provides functions analogous to tox_load and tox_save in toxcore, - * as well as functions for encryption of arbitrary client data (e.g. chat logs). - * - * It is conceptually organized into two parts. The first part are the functions +/* This module is conceptually organized into two parts. The first part are the functions * with "key" in the name. To use these functions, first derive an encryption key * from a password with tox_derive_key_from_pass, and use the returned key to * 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); * favor using the first part intead of the second part. * * The encrypted data is prepended with a magic number, to aid validity checking - * (no guarantees are made of course). + * (no guarantees are made of course). Any data to be decrypted must start with + * the magic number. * * Clients should consider alerting their users that, unlike plain data, if even one bit * becomes corrupted, the data will be entirely unrecoverable. * Ditto if they forget their password, there is no way to recover the data. */ - -/******************************* BEGIN PART 2 ******************************* - * For simplicty, the second part of the module is presented first. The API for - * the first part is analgous, with some extra functions for key handling. If - * your code spends too much time using these functions, consider using the part - * 1 functions instead. - */ - -/* Encrypts the given data with the given passphrase. The output array must be - * at least data_len + tox_pass_encryption_extra_length() bytes long. This delegates - * to tox_derive_key_from_pass and tox_pass_key_encrypt. - * - * tox_encrypted_save() is a good example of how to use this function. - * - * returns 0 on success - * returns -1 on failure - */ -int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out); - -/* Save the messenger data encrypted with the given password. - * data must be at least tox_encrypted_size(). - * - * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return - * value. - * - * returns 0 on success - * returns -1 on failure - */ -int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); - -/* Decrypts the given data with the given passphrase. The output array must be - * at least data_len - tox_pass_encryption_extra_length() bytes long. This delegates - * to tox_pass_key_decrypt. - * - * tox_encrypted_load() is a good example of how to use this function. - * - * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success - * returns -1 on failure - */ -int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out); - -typedef enum TOX_ERR_ENCRYPTED_NEW { - TOX_ERR_ENCRYPTED_NEW_OK, - TOX_ERR_ENCRYPTED_NEW_NULL, +typedef enum TOX_ERR_KEY_DERIVATION { + TOX_ERR_KEY_DERIVATION_OK, /** - * The function was unable to allocate enough memory to store the internal - * structures for the Tox object. + * Some input data, or maybe the output pointer, was null. */ - TOX_ERR_ENCRYPTED_NEW_MALLOC, + TOX_ERR_KEY_DERIVATION_NULL, /** - * The function was unable to bind to a port. This may mean that all ports - * have already been bound, e.g. by other Tox instances, or it may mean - * a permission error. You may be able to gather more information from errno. + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. */ - TOX_ERR_ENCRYPTED_NEW_PORT_ALLOC, + TOX_ERR_KEY_DERIVATION_FAILED +} TOX_ERR_KEY_DERIVATION; + +typedef enum TOX_ERR_ENCRYPTION { + TOX_ERR_ENCRYPTION_OK, /** - * proxy_type was invalid. + * Some input data, or maybe the output pointer, was null. */ - TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_TYPE, + TOX_ERR_ENCRYPTION_NULL, /** - * proxy_type was valid but the proxy_host passed had an invalid format - * or was NULL. + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. */ - TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_HOST, + TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED, /** - * proxy_type was valid, but the proxy_port was invalid. + * The encryption itself failed. */ - TOX_ERR_ENCRYPTED_NEW_PROXY_BAD_PORT, + TOX_ERR_ENCRYPTION_FAILED +} TOX_ERR_ENCRYPTION; + +typedef enum TOX_ERR_DECRYPTION { + TOX_ERR_DECRYPTION_OK, + /** + * Some input data, or maybe the output pointer, was null. + */ + TOX_ERR_DECRYPTION_NULL, /** - * The proxy host passed could not be resolved. + * The input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes */ - TOX_ERR_ENCRYPTED_NEW_PROXY_NOT_FOUND, + TOX_ERR_DECRYPTION_INVALID_LENGTH, /** - * The byte array to be loaded contained an encrypted save. + * The input data is missing the magic number (i.e. wasn't created by this + * module, or is corrupted) */ - TOX_ERR_ENCRYPTED_NEW_LOAD_ENCRYPTED, + TOX_ERR_DECRYPTION_BAD_FORMAT, /** - * The data format was invalid. This can happen when loading data that was - * saved by an older version of Tox, or when the data has been corrupted. - * When loading from badly formatted data, some data may have been loaded, - * and the rest is discarded. Passing an invalid length parameter also - * causes this error. + * The crypto lib was unable to derive a key from the given passphrase, + * which is usually a lack of memory issue. The functions accepting keys + * do not produce this error. */ - TOX_ERR_ENCRYPTED_NEW_LOAD_BAD_FORMAT, + TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED, /** * The encrypted byte array could not be decrypted. Either the data was * corrupt or the password/key was incorrect. - * - * NOTE: This error code is only set by tox_encrypted_new() and - * tox_encrypted_key_new(), in the toxencryptsave module. */ - TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED -} TOX_ERR_ENCRYPTED_NEW; + TOX_ERR_DECRYPTION_FAILED +} TOX_ERR_DECRYPTION; + + +/******************************* BEGIN PART 2 ******************************* + * For simplicty, the second part of the module is presented first. The API for + * the first part is analgous, with some extra functions for key handling. If + * your code spends too much time using these functions, consider using the part + * 1 functions instead. + */ + +/* Encrypts the given data with the given passphrase. The output array must be + * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_derive_key_from_pass and tox_pass_key_encrypt. + * + * returns true on success + */ +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); -/* Load the new messenger from encrypted data of size length. - * All other arguments are like toxcore/tox_new(). + +/* Decrypts the given data with the given passphrase. The output array must be + * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_pass_key_decrypt. + * + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH * - * returns NULL on failure; see the documentation in toxcore/tox.h. + * returns true on success */ -Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, - size_t pplength, TOX_ERR_ENCRYPTED_NEW *error); +bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error); /******************************* BEGIN PART 1 ******************************* @@ -177,7 +154,7 @@ Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, s */ /* Generates a secret symmetric key from the given passphrase. out_key must be at least - * tox_pass_key_length() bytes long. + * TOX_PASS_KEY_LENGTH bytes long. * Be sure to not compromise the key! Only keep it in memory, do not write to disk. * The password is zeroed after key derivation. * 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 * Note that this function is not deterministic; to derive the same key from a * password, you also must know the random salt that was used. See below. * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key); +bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); /* Same as above, except with use the given salt for deterministic key derivation. * The salt must be tox_salt_length() bytes in length. */ -int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key); +bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); /* This retrieves the salt used to encrypt the given data, which can then be passed to * derive_key_with_salt to produce the same key as was previously used. Any encrpyted * data with this module can be used as input. * - * returns -1 if the magic number is wrong - * returns 0 otherwise (no guarantee about validity of data) + * returns true if magic number matches + * success does not say anything about the validity of the data, only that data of + * the appropriate size was copied */ -int tox_get_salt(uint8_t *data, uint8_t *salt); +bool tox_get_salt(const uint8_t *data, uint8_t *salt); /* Now come the functions that are analogous to the part 2 functions. */ -/* Encrypt arbitrary with a key produced by tox_derive_key_. The output - * array must be at least data_len + tox_pass_encryption_extra_length() bytes long. - * key must be tox_pass_key_length() bytes. +/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output + * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. + * key must be TOX_PASS_KEY_LENGTH bytes. * If you already have a symmetric key from somewhere besides this module, simply * call encrypt_data_symmetric in toxcore/crypto_core directly. * - * returns 0 on success - * returns -1 on failure - */ -int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out); - -/* Save the messenger data encrypted with the given key from tox_derive_key. - * data must be at least tox_encrypted_size(). - * - * NOTE: Unlike tox_save(), this function may fail. Be sure to check its return - * value. - * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key); +bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, TOX_ERR_ENCRYPTION *error); /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by * tox_derive_key_from_pass. * - * returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success - * returns -1 on failure - */ -int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out); - -/* Load the messenger from encrypted data of size length, with key from tox_derive_key. - * All other arguments are like toxcore/tox_new(). + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH * - * returns NULL on failure; see the documentation in toxcore/tox.h. + * returns true on success */ -Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, - TOX_ERR_ENCRYPTED_NEW *error); - +bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, TOX_ERR_DECRYPTION *error); /* Determines whether or not the given data is encrypted (by checking the magic number) - * - * returns 1 if it is encrypted - * returns 0 otherwise */ -int tox_is_data_encrypted(const uint8_t *data); +bool tox_is_data_encrypted(const uint8_t *data); #ifdef __cplusplus } -- cgit v1.2.3 From 9b66c57bd0ec8d7e89b7fa751d83ffabd1ce2e75 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 31 Mar 2015 19:30:09 -0500 Subject: Fix minor code duplication --- auto_tests/encryptsave_test.c | 2 +- toxencryptsave/toxencryptsave.c | 22 ++++++++++------------ toxencryptsave/toxencryptsave.h | 4 ++-- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'toxencryptsave') diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 13e06db4..07b0c4d4 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -151,7 +151,7 @@ START_TEST(test_keys) ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 1 failed"); ret = tox_pass_decrypt(encrypted2, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out2, &decerr); - ck_assert_msg(ret, "generic failure 5: %u", &decerr); + ck_assert_msg(ret, "generic failure 5: %u", decerr); ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed"); // test that pass_decrypt can decrypt things from pass_key_encrypt diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 9b202f49..c086ddb7 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -28,7 +28,6 @@ #include "toxencryptsave.h" #include "defines.h" #include "../toxcore/crypto_core.h" -#include "../toxcore/tox.h" #define SET_ERROR_PARAMETER(param, x) {if(param) {*param = x;}} #ifdef VANILLA_NACL @@ -91,7 +90,7 @@ bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out } /* Same as above, except with use the given salt for deterministic key derivation. - * The salt must be tox_salt_length() bytes in length. + * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) @@ -254,32 +253,31 @@ bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error) { + if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH || pplength == 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); + return 0; + } + if (!data || !passphrase || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL); + return 0; + } if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); return 0; } - uint8_t passkey[crypto_hash_sha256_BYTES]; - crypto_hash_sha256(passkey, passphrase, pplength); - uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); /* derive the key */ uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; - if (crypto_pwhash_scryptsalsa208sha256( - key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, - crypto_box_KEYBYTES, (char *)passkey, sizeof(passkey), salt, - crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ - crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { + if (!tox_derive_key_with_salt(passphrase, pplength, salt, key, NULL)) { /* out of memory most likely */ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); return 0; } - sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ - return tox_pass_key_decrypt(data, length, key, out, error); } diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 2ee4af46..51f75c66 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -168,8 +168,8 @@ bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, s */ bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); -/* Same as above, except with use the given salt for deterministic key derivation. - * The salt must be tox_salt_length() bytes in length. +/* Same as above, except use the given salt for deterministic key derivation. + * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); -- cgit v1.2.3 From f7beee495e9c3199ecbae91fde2e92f1698f48b2 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 31 Mar 2015 21:16:04 -0500 Subject: Make keys into a struct for more programmer safety --- auto_tests/encryptsave_test.c | 24 ++++++++++----------- toxencryptsave/toxencryptsave.c | 47 ++++++++++++++++++++--------------------- toxencryptsave/toxencryptsave.h | 18 +++++++++++----- 3 files changed, 48 insertions(+), 41 deletions(-) (limited to 'toxencryptsave') diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 07b0c4d4..a239bcee 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -93,19 +93,19 @@ START_TEST(test_save_friend) size = tox_get_savedata_size(tox3); uint8_t data2[size]; tox_get_savedata(tox3, data2); - uint8_t key[32 + crypto_box_BEFORENMBYTES]; - memcpy(key, salt, 32); - memcpy(key + 32, known_key2, crypto_box_BEFORENMBYTES); + TOX_PASS_KEY key; + memcpy(key.salt, salt, 32); + memcpy(key.key, known_key2, crypto_box_BEFORENMBYTES); size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; uint8_t encdata2[size2]; - ret = tox_pass_key_encrypt(data2, size, key, encdata2, &error1); + ret = tox_pass_key_encrypt(data2, size, &key, encdata2, &error1); ck_assert_msg(ret, "failed to key encrypt %u", error1); ck_assert_msg(tox_is_data_encrypted(encdata2), "magic number the second missing"); uint8_t out1[size], out2[size]; ret = tox_pass_decrypt(encdata2, size2, pw, pwlen, out1, &err3); ck_assert_msg(ret, "failed to pw decrypt %u", err3); - ret = tox_pass_key_decrypt(encdata2, size2, key, out2, &err3); + ret = tox_pass_key_decrypt(encdata2, size2, &key, out2, &err3); ck_assert_msg(ret, "failed to key decrypt %u", err3); ck_assert_msg(memcmp(out1, out2, size) == 0, "differing output data"); @@ -130,13 +130,13 @@ START_TEST(test_keys) TOX_ERR_ENCRYPTION encerr; TOX_ERR_DECRYPTION decerr; TOX_ERR_KEY_DERIVATION keyerr; - uint8_t key[TOX_PASS_KEY_LENGTH]; - bool ret = tox_derive_key_from_pass("123qweasdzxc", 12, key, &keyerr); + TOX_PASS_KEY key; + bool ret = tox_derive_key_from_pass("123qweasdzxc", 12, &key, &keyerr); ck_assert_msg(ret, "generic failure 1: %u", keyerr); uint8_t *string = "No Patrick, mayonnaise is not an instrument."; // 44 uint8_t encrypted[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; - ret = tox_pass_key_encrypt(string, 44, key, encrypted, &encerr); + ret = tox_pass_key_encrypt(string, 44, &key, encrypted, &encerr); ck_assert_msg(ret, "generic failure 2: %u", encerr); uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; @@ -146,7 +146,7 @@ START_TEST(test_keys) uint8_t out1[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; uint8_t out2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; - ret = tox_pass_key_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, key, out1, &decerr); + ret = tox_pass_key_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, &key, out1, &decerr); ck_assert_msg(ret, "generic failure 4: %u", decerr); ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 1 failed"); @@ -161,10 +161,10 @@ START_TEST(test_keys) uint8_t salt[TOX_PASS_SALT_LENGTH]; ck_assert_msg(tox_get_salt(encrypted, salt), "couldn't get salt"); - uint8_t key2[TOX_PASS_KEY_LENGTH]; - ret = tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2, &keyerr); + TOX_PASS_KEY key2; + ret = tox_derive_key_with_salt("123qweasdzxc", 12, salt, &key2, &keyerr); ck_assert_msg(ret, "generic failure 7: %u", keyerr); - ck_assert_msg(0 == memcmp(key, key2, TOX_PASS_KEY_LENGTH), "salt comparison failed"); + ck_assert_msg(0 == memcmp(&key, &key2, sizeof(TOX_PASS_KEY)), "salt comparison failed"); } END_TEST diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index c086ddb7..b38209a4 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -40,8 +40,8 @@ #error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES #endif -#if TOX_PASS_KEY_LENGTH != (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) -#error TOX_PASS_KEY_LENGTH is assumed to be equal to (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) +#if TOX_PASS_KEY_LENGTH != crypto_box_KEYBYTES +#error TOX_PASS_KEY_LENGTH is assumed to be equal to crypto_box_KEYBYTES #endif #if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) @@ -82,7 +82,7 @@ bool tox_get_salt(const uint8_t *data, uint8_t *salt) * * returns true on success */ -bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) +bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, TOX_ERR_KEY_DERIVATION *error) { uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; randombytes(salt, sizeof salt); @@ -92,7 +92,7 @@ bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out /* Same as above, except with use the given salt for deterministic key derivation. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ -bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, +bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key, TOX_ERR_KEY_DERIVATION *error) { if (pplength == 0 || !passphrase || !salt || !out_key) { @@ -119,8 +119,8 @@ bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *sal } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ - memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); - memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); + memcpy(out_key->salt, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); + memcpy(out_key->key, key, crypto_box_KEYBYTES); SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); return 1; } @@ -133,7 +133,7 @@ bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *sal * * returns true on success */ -bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, +bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out, TOX_ERR_ENCRYPTION *error) { if (data_len == 0 || !data || !key || !out) { @@ -154,8 +154,7 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *k out += TOX_ENC_SAVE_MAGIC_LENGTH; /* then add the rest prefix */ - memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); - key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; + memcpy(out, key->salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; uint8_t nonce[crypto_box_NONCEBYTES]; @@ -164,7 +163,7 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *k out += crypto_box_NONCEBYTES; /* now encrypt */ - if (encrypt_data_symmetric(key, nonce, data, data_len, out) + if (encrypt_data_symmetric(key->key, nonce, data, data_len, out) != data_len + crypto_box_MACBYTES) { SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); return 0; @@ -183,10 +182,10 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *k 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) { - uint8_t key[TOX_PASS_KEY_LENGTH]; + TOX_PASS_KEY key; TOX_ERR_KEY_DERIVATION _error; - if (!tox_derive_key_from_pass(passphrase, pplength, key, &_error)) { + if (!tox_derive_key_from_pass(passphrase, pplength, &key, &_error)) { if (_error == TOX_ERR_KEY_DERIVATION_NULL) { SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { @@ -196,7 +195,7 @@ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, return 0; } - return tox_pass_key_encrypt(data, data_len, key, out, error); + return tox_pass_key_encrypt(data, data_len, &key, out, error); } /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by @@ -206,33 +205,33 @@ bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, * * returns true on success */ -bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, +bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out, TOX_ERR_DECRYPTION *error) { if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); return 0; } - + if (!data || !key || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_NULL); + return 0; + } if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); return 0; } data += TOX_ENC_SAVE_MAGIC_LENGTH; + data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // salt only affects key derivation size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; - //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; - uint8_t nonce[crypto_box_NONCEBYTES]; - //memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); - key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // ignore the salt, which is only needed for kdf - data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; + uint8_t nonce[crypto_box_NONCEBYTES]; memcpy(nonce, data, crypto_box_NONCEBYTES); data += crypto_box_NONCEBYTES; /* decrypt the data */ - if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) + if (decrypt_data_symmetric(key->key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) != decrypt_length) { SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); return 0; @@ -270,15 +269,15 @@ bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, s memcpy(salt, data + TOX_ENC_SAVE_MAGIC_LENGTH, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); /* derive the key */ - uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; + TOX_PASS_KEY key; - if (!tox_derive_key_with_salt(passphrase, pplength, salt, key, NULL)) { + if (!tox_derive_key_with_salt(passphrase, pplength, salt, &key, NULL)) { /* out of memory most likely */ SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); return 0; } - return tox_pass_key_decrypt(data, length, key, out, error); + return tox_pass_key_decrypt(data, length, &key, out, error); } /* Determines whether or not the given data is encrypted (by checking the magic number) diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 51f75c66..103cf874 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -39,7 +39,7 @@ struct Tox_Options; #endif #define TOX_PASS_SALT_LENGTH 32 -#define TOX_PASS_KEY_LENGTH 64 +#define TOX_PASS_KEY_LENGTH 32 #define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80 /* This module is conceptually organized into two parts. The first part are the functions @@ -155,6 +155,14 @@ bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, s * intensive than part one. The first 3 functions are for key handling. */ +/* This key structure's internals should not be used by any client program, even + * if they are straightforward here. + */ +typedef struct { + uint8_t salt[TOX_PASS_SALT_LENGTH]; + uint8_t key[TOX_PASS_KEY_LENGTH]; +} TOX_PASS_KEY; + /* Generates a secret symmetric key from the given passphrase. out_key must be at least * TOX_PASS_KEY_LENGTH bytes long. * Be sure to not compromise the key! Only keep it in memory, do not write to disk. @@ -166,12 +174,12 @@ bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, s * * returns true on success */ -bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error); +bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, TOX_PASS_KEY *out_key, TOX_ERR_KEY_DERIVATION *error); /* Same as above, except use the given salt for deterministic key derivation. * The salt must be TOX_PASS_SALT_LENGTH bytes in length. */ -bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, +bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, TOX_PASS_KEY *out_key, TOX_ERR_KEY_DERIVATION *error); /* This retrieves the salt used to encrypt the given data, which can then be passed to @@ -194,7 +202,7 @@ bool tox_get_salt(const uint8_t *data, uint8_t *salt); * * returns true on success */ -bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, +bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const TOX_PASS_KEY *key, uint8_t *out, TOX_ERR_ENCRYPTION *error); /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by @@ -204,7 +212,7 @@ bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *k * * returns true on success */ -bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, +bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const TOX_PASS_KEY *key, uint8_t *out, TOX_ERR_DECRYPTION *error); /* Determines whether or not the given data is encrypted (by checking the magic number) -- cgit v1.2.3 From 36ed4956fdeacd73243d9348dcb7ef279f22c726 Mon Sep 17 00:00:00 2001 From: Dubslow Date: Wed, 1 Apr 2015 15:26:09 -0500 Subject: Enough pestering me please --- toxencryptsave/toxencryptsave.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'toxencryptsave') diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 103cf874..078bd879 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -60,6 +60,15 @@ struct Tox_Options; * Ditto if they forget their password, there is no way to recover the data. */ +/* Since apparently no one actually bothered to learn about the module previously, + * the recently removed functions tox_encrypted_new and tox_get_encrypted_savedata + * may be trivially replaced by calls to tox_pass_decrypt -> tox_new or + * tox_get_savedata -> tox_pass_encrypt as appropriate. The removed functions + * were never more than 5 line wrappers of the other public API functions anyways. + * (As has always been, tox_pass_decrypt and tox_pass_encrypt are interchangeable + * with tox_pass_key_decrypt and tox_pass_key_encrypt, as the client program requires.) + */ + typedef enum TOX_ERR_KEY_DERIVATION { TOX_ERR_KEY_DERIVATION_OK, /** -- cgit v1.2.3