diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 752f906f..b335cbe1 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -25,6 +25,9 @@ unsigned char known_key[crypto_box_BEFORENMBYTES] = {0x29, 0x36, 0x1c, 0x9e, 0x6 char* pw = "hunter2"; unsigned int pwlen = 7; +unsigned char known_key2[crypto_box_BEFORENMBYTES] = {0x7a, 0xfa, 0x95, 0x45, 0x36, 0x8a, 0xa2, 0x5c, 0x40, 0xfd, 0xc0, 0xe2, 0x35, 0x8, 0x7, 0x88, 0xfa, 0xf9, 0x37, 0x86, 0xeb, 0xff, 0x50, 0x4f, 0x3, 0xe2, 0xf6, 0xd9, 0xef, 0x9, 0x17, 0x1}; +// same as above, except standard opslimit instead of extra ops limit for test_known_kdf, and hash pw before kdf for compat + /* cause I'm shameless */ void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, uint16_t length, void *userdata) { @@ -61,11 +64,13 @@ START_TEST(test_save_friend) tox_get_address(tox2, address); int test = tox_add_friend(tox1, address, (uint8_t *)"Gentoo", 7); ck_assert_msg(test == 0, "Failed to add friend error code: %i", test); + uint32_t size = tox_encrypted_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_new(0); test = tox_encrypted_load(tox3, data, size, "correcthorsebatterystaple", 25); ck_assert_msg(test == 0, "failed to encrypted load"); @@ -73,6 +78,41 @@ START_TEST(test_save_friend) test = tox_get_client_id(tox3, 0, address2); ck_assert_msg(test == 0, "no friends!"); ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match!"); + + size = tox_encrypted_size(tox3); + uint8_t data2[size]; + 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_load + Tox* tox4 = tox_new(0); + test = tox_encrypted_key_load(tox4, data2, size, key); + ck_assert_msg(test == 0, "failed to encrypted load the second"); + uint8_t address4[TOX_CLIENT_ID_SIZE]; + test = tox_get_client_id(tox4, 0, address4); + ck_assert_msg(test == 0, "no friends! the second"); + ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the second"); + + // now test compaitibilty with tox_encrypted_load, first manually... + uint8_t out1[size], out2[size]; + printf("Trying to decrypt from pw:\n"); + uint32_t sz1 = tox_pass_decrypt(data2+TOX_ENC_SAVE_MAGIC_LENGTH, size-TOX_ENC_SAVE_MAGIC_LENGTH, pw, pwlen, out1); + uint32_t sz2 = tox_pass_key_decrypt(data2+TOX_ENC_SAVE_MAGIC_LENGTH, size-TOX_ENC_SAVE_MAGIC_LENGTH, key, out2); + ck_assert_msg(sz1 == sz2, "differing output sizes"); + ck_assert_msg(memcmp(out1, out2, sz1) == 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_new(0); + test = tox_encrypted_load(tox5, data2, size, pw, pwlen); + ck_assert_msg(test == 0, "failed to encrypted load the third"); + uint8_t address5[TOX_CLIENT_ID_SIZE]; + test = tox_get_client_id(tox4, 0, address5); + ck_assert_msg(test == 0, "no friends! the third"); + ck_assert_msg(memcmp(address, address2, TOX_CLIENT_ID_SIZE) == 0, "addresses don't match! the third"); } END_TEST diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 7492f06b..0d63a0aa 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -175,6 +175,28 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 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_size(tox); + uint8_t temp_data[temp_size]; + tox_save(tox, temp_data); + + /* the output data consists of, in order: magic number, enc_data */ + /* first add the magic number */ + memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); + data += TOX_ENC_SAVE_MAGIC_LENGTH; + + /* encrypt */ + return tox_pass_key_encrypt(temp_data, temp_size, key, data); +} + /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by * tox_derive_key_from_pass. * @@ -260,6 +282,29 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t * return tox_load(tox, temp_data, decrypt_length); } +/* Load the messenger from encrypted data of size length, with key from tox_derive_key. + * + * returns 0 on success + * returns -1 on failure + */ +int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t* key) +{ + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) + return -1; + + data += TOX_ENC_SAVE_MAGIC_LENGTH; + length -= TOX_ENC_SAVE_MAGIC_LENGTH; + + 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; + printf("tox key load: decryption passed\n"); + return tox_load(tox, temp_data, decrypt_length); +} + /* Determines whether or not the given data is encrypted (by checking the magic number) * * returns 1 if it is encrypted diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index d805cf97..ddfce485 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h @@ -95,6 +95,14 @@ 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); +/* 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); + /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by * tox_derive_key_from_pass. * @@ -121,6 +129,13 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, */ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength); +/* Load the messenger from encrypted data of size length, with key from tox_derive_key. + * + * returns 0 on success + * returns -1 on failure + */ +int tox_encrypted_key_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t* key); + /* Determines whether or not the given data is encrypted (by checking the magic number) * * returns 1 if it is encrypted