From c51b8a9eba2b7f50f34796f9606c4cb7322993fa Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 21 Dec 2013 22:35:27 -0500 Subject: [PATCH] Added function to save an encrypted version of the messenger. Also added some tests. --- auto_tests/crypto_test.c | 31 +++++++++++++++++ auto_tests/messenger_test.c | 22 ++++++++++++ toxcore/Messenger.c | 69 +++++++++++++++++++++++++++++++++++++ toxcore/Messenger.h | 18 ++++++++++ toxcore/network.h | 1 + toxcore/tox.c | 29 ++++++++++++++++ toxcore/tox.h | 31 ++++++++++++++++- 7 files changed, 200 insertions(+), 1 deletion(-) diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c index 806ea7b8..95cdefcd 100644 --- a/auto_tests/crypto_test.c +++ b/auto_tests/crypto_test.c @@ -246,6 +246,36 @@ START_TEST(test_large_data) } END_TEST +START_TEST(test_large_data_symmetric) +{ + unsigned char k[crypto_secretbox_KEYBYTES]; + + unsigned char n[crypto_secretbox_NONCEBYTES]; + + unsigned char m1[16 * 16 * 16]; + unsigned char c1[sizeof(m1) + crypto_box_MACBYTES]; + unsigned char m1prime[sizeof(m1)]; + + int c1len; + int m1plen; + + //Generate random messages + rand_bytes(m1, sizeof(m1)); + rand_bytes(n, crypto_box_NONCEBYTES); + + //Generate key + new_symmetric_key(k); + + c1len = encrypt_data_symmetric(k, n, m1, sizeof(m1), c1); + ck_assert_msg(c1len == sizeof(m1) + crypto_box_MACBYTES, "could not encrypt data"); + + m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); + + ck_assert_msg(m1plen == sizeof(m1), "decrypted text lengths differ"); + ck_assert_msg(memcmp(m1prime, m1, sizeof(m1)) == 0, "decrypted texts differ"); +} +END_TEST + #define DEFTESTCASE(NAME) \ TCase *NAME = tcase_create(#NAME); \ tcase_add_test(NAME, test_##NAME); \ @@ -263,6 +293,7 @@ Suite *crypto_suite(void) DEFTESTCASE(fast_known); DEFTESTCASE_SLOW(endtoend, 15); /* waiting up to 15 seconds */ DEFTESTCASE(large_data); + DEFTESTCASE(large_data_symmetric); return s; } diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c index cfbc4967..5c8e242e 100644 --- a/auto_tests/messenger_test.c +++ b/auto_tests/messenger_test.c @@ -310,6 +310,27 @@ START_TEST(test_messenger_state_saveloadsave) } END_TEST +START_TEST(test_messenger_state_saveload_encrypted) +{ + uint8_t addr[FRIEND_ADDRESS_SIZE]; + getaddress(m, addr); + Messenger *m_temp = new_messenger(TOX_ENABLE_IPV6_DEFAULT); + + size_t size = messenger_size_encrypted(m); + uint8_t buffer[size]; + messenger_save_encrypted(m, buffer, "Gentoo", sizeof("Gentoo")); + + ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Ubuntu", sizeof("Ubuntu")) == -1, + "Bad password didn't make the function fail."); + ck_assert_msg(messenger_load_encrypted(m_temp, buffer, size, "Gentoo", sizeof("Gentoo")) == 0, + "Good password didn't make the function succeed."); + uint8_t addr1[FRIEND_ADDRESS_SIZE]; + getaddress(m_temp, addr1); + ck_assert_msg(memcmp(addr1, addr, FRIEND_ADDRESS_SIZE) == 0, "Didn't load messenger successfully"); + kill_messenger(m_temp); +} +END_TEST + #define DEFTESTCASE(NAME) \ TCase *tc_##NAME = tcase_create(#NAME); \ tcase_add_test(tc_##NAME, test_##NAME); \ @@ -321,6 +342,7 @@ Suite *messenger_suite(void) DEFTESTCASE(dht_state_saveloadsave); DEFTESTCASE(messenger_state_saveloadsave); + DEFTESTCASE(messenger_state_saveload_encrypted); DEFTESTCASE(getself_name); DEFTESTCASE(m_get_userstatus_size); diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index b3c8fb40..78c83519 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -2264,6 +2264,75 @@ int messenger_load(Messenger *m, uint8_t *data, uint32_t length) return -1; } +/* return the size of data to pass to messenger_save_encrypted(...) + * + */ +uint32_t messenger_size_encrypted(Messenger *m) +{ + return messenger_size(m) + crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES; +} + +/* Save the messenger, encrypting the data with key of length key_length + * + * return 0 on success. + * return -1 on failure. + */ +int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length) +{ + uint32_t m_size = messenger_size(m); + uint8_t *plain_messenger = malloc(m_size); + + if (plain_messenger == NULL) + return -1; + + messenger_save(m, plain_messenger); + + /* Hash the key with SHA256 to get a 32byte key. */ + uint8_t hash[crypto_hash_sha256_BYTES]; + crypto_hash_sha256(hash, key, key_length); + random_nonce(data); + encrypt_data_symmetric(hash, data, plain_messenger, m_size, data + crypto_secretbox_NONCEBYTES); + + memset(plain_messenger, 0, m_size); + free(plain_messenger); + memset(hash, 0, crypto_hash_sha256_BYTES); + return 0; +} + +/* Load the messenger from data of size length encrypted with key of key_length. + * + * return 0 on success. + * return -1 on failure. + */ +int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) +{ + if (length <= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES) + return -1; + + uint8_t *plain_messenger = malloc(length); + + if (plain_messenger == NULL) + return -1; + + /* Hash the key with SHA256 to get a 32byte key. */ + uint8_t hash[crypto_hash_sha256_BYTES]; + crypto_hash_sha256(hash, key, key_length); + int len = decrypt_data_symmetric(hash, data, data + crypto_secretbox_NONCEBYTES, length - crypto_secretbox_NONCEBYTES, + plain_messenger); + int ret; + + if ((uint32_t)len == length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES) { + ret = messenger_load(m, plain_messenger, length - crypto_secretbox_NONCEBYTES - crypto_secretbox_MACBYTES); + } else { + ret = -1; + } + + memset(plain_messenger, 0, length); + free(plain_messenger); + memset(hash, 0, crypto_hash_sha256_BYTES); + return ret; +} + /* Return the number of friends in the instance m. * You should use this to determine how much memory to allocate * for copy_friendlist. */ diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 61d7f86c..3cfd5065 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -652,6 +652,24 @@ void messenger_save(Messenger *m, uint8_t *data); /* Load the messenger from data of size length. */ int messenger_load(Messenger *m, uint8_t *data, uint32_t length); +/* return the size of data to pass to messenger_save_encrypted(...) + */ +uint32_t messenger_size_encrypted(Messenger *m); + +/* Save the messenger, encrypting the data with key of length key_length + * + * return 0 on success. + * return -1 on failure. + */ +int messenger_save_encrypted(Messenger *m, uint8_t *data, uint8_t *key, uint16_t key_length); + +/* Load the messenger from data of size length encrypted with key of key_length. + * + * return 0 on success. + * return -1 on failure. + */ +int messenger_load_encrypted(Messenger *m, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); + /* Return the number of friends in the instance m. * You should use this to determine how much memory to allocate * for copy_friendlist. */ diff --git a/toxcore/network.h b/toxcore/network.h index 24c7ed04..02c43e57 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -82,6 +82,7 @@ typedef int sock_t; #include #include #include +#include #define crypto_box_MACBYTES (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) #endif diff --git a/toxcore/tox.c b/toxcore/tox.c index 87fbdf35..04e412be 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -749,3 +749,32 @@ int tox_load(Tox *tox, uint8_t *data, uint32_t length) return messenger_load(m, data, length); } +/* return the size of data to pass to messenger_save_encrypted(...) + */ +uint32_t tox_size_encrypted(Tox *tox) +{ + Messenger *m = tox; + return messenger_size_encrypted(m); +} + +/* Save the messenger, encrypting the data with key of length key_length + * + * return 0 on success. + * return -1 on failure. + */ +int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length) +{ + Messenger *m = tox; + return messenger_save_encrypted(m, data, key, key_length); +} + +/* Load the messenger from data of size length encrypted with key of key_length. + * + * return 0 on success. + * return -1 on failure. + */ +int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length) +{ + Messenger *m = tox; + return messenger_load_encrypted(m, data, length, key, key_length); +} diff --git a/toxcore/tox.h b/toxcore/tox.h index 8d551c69..0ffeba62 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -657,9 +657,38 @@ uint32_t tox_size(Tox *tox); /* Save the messenger in data (must be allocated memory of size Messenger_size()). */ void tox_save(Tox *tox, uint8_t *data); -/* Load the messenger from data of size length. */ +/* Load the messenger from data of size length. + * + * returns 0 on success + * returns -1 on failure + */ int tox_load(Tox *tox, uint8_t *data, uint32_t length); +/**/ + +/* return the size of data to pass to messenger_save_encrypted(...) + */ +uint32_t tox_size_encrypted(Tox *tox); + +/* Save the messenger, encrypting the data with key of length key_length + * + * This functions simply calls and then encrypt the output of tox_save(..) + * with crypto_secretbox(...) from NaCl/libsodium with the key + * given to crypto_secretbox(...) being the SHA256 sum of the key + * passed to this function. + * + * return 0 on success. + * return -1 on failure. + */ +int tox_save_encrypted(Tox *tox, uint8_t *data, uint8_t *key, uint16_t key_length); + +/* Load the messenger from data of size length encrypted with key of key_length. + * + * return 0 on success. + * return -1 on failure. + */ +int tox_load_encrypted(Tox *tox, uint8_t *data, uint32_t length, uint8_t *key, uint16_t key_length); + #ifdef __cplusplus }