mirror of
https://github.com/irungentoo/toxcore.git
synced 2024-03-22 13:30:51 +08:00
Merge branch 'master' of https://github.com/dubslow/toxcore
This commit is contained in:
commit
99e0fde297
|
@ -55,7 +55,6 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(test_save_friend)
|
START_TEST(test_save_friend)
|
||||||
{
|
{
|
||||||
TOX_ERR_ENCRYPTED_NEW err = TOX_ERR_ENCRYPTED_NEW_OK;
|
|
||||||
Tox *tox1 = tox_new(0, 0, 0, 0);
|
Tox *tox1 = tox_new(0, 0, 0, 0);
|
||||||
Tox *tox2 = 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");
|
ck_assert_msg(tox1 || tox2, "Failed to create 2 tox instances");
|
||||||
|
@ -63,99 +62,109 @@ START_TEST(test_save_friend)
|
||||||
tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
|
tox_callback_friend_request(tox2, accept_friend_request, &to_compare);
|
||||||
uint8_t address[TOX_ADDRESS_SIZE];
|
uint8_t address[TOX_ADDRESS_SIZE];
|
||||||
tox_self_get_address(tox2, address);
|
tox_self_get_address(tox2, address);
|
||||||
int test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0);
|
uint32_t test = tox_friend_add(tox1, address, (uint8_t *)"Gentoo", 7, 0);
|
||||||
ck_assert_msg(test == 0, "Failed to add friend error code: %i", test);
|
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];
|
uint8_t data[size];
|
||||||
test = tox_encrypted_save(tox1, data, "correcthorsebatterystaple", 25);
|
tox_get_savedata(tox1, data);
|
||||||
ck_assert_msg(test == 0, "failed to encrypted save");
|
size_t size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
||||||
//ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing");
|
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 *tox3 = tox_encrypted_new(0, data, size, "correcthorsebatterystaple", 25, &err);
|
TOX_ERR_NEW err2;
|
||||||
ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new");
|
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];
|
uint8_t address2[TOX_PUBLIC_KEY_SIZE];
|
||||||
test = tox_friend_get_public_key(tox3, 0, address2, 0);
|
ret = tox_friend_get_public_key(tox3, 0, address2, 0);
|
||||||
ck_assert_msg(test == 1, "no friends!");
|
ck_assert_msg(ret, "no friends!");
|
||||||
ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match!");
|
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];
|
uint8_t data2[size];
|
||||||
|
tox_get_savedata(tox3, data2);
|
||||||
uint8_t key[32 + crypto_box_BEFORENMBYTES];
|
uint8_t key[32 + crypto_box_BEFORENMBYTES];
|
||||||
memcpy(key, salt, 32);
|
memcpy(key, salt, 32);
|
||||||
memcpy(key + 32, known_key2, crypto_box_BEFORENMBYTES);
|
memcpy(key + 32, known_key2, crypto_box_BEFORENMBYTES);
|
||||||
test = tox_encrypted_key_save(tox3, data2, key);
|
size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
||||||
ck_assert_msg(test == 0, "failed to encrypted save the second");
|
uint8_t encdata2[size2];
|
||||||
//ck_assert_msg(tox_is_save_encrypted(data2) == 1, "magic number the second missing");
|
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");
|
||||||
|
|
||||||
// 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...
|
|
||||||
uint8_t out1[size], out2[size];
|
uint8_t out1[size], out2[size];
|
||||||
//printf("Trying to decrypt from pw:\n");
|
ret = tox_pass_decrypt(encdata2, size2, pw, pwlen, out1, &err3);
|
||||||
uint32_t sz1 = tox_pass_decrypt(data2, size, pw, pwlen, out1);
|
ck_assert_msg(ret, "failed to pw decrypt %u", err3);
|
||||||
uint32_t sz2 = tox_pass_key_decrypt(data2, size, key, out2);
|
ret = tox_pass_key_decrypt(encdata2, size2, key, out2, &err3);
|
||||||
ck_assert_msg(sz1 == sz2, "differing output sizes");
|
ck_assert_msg(ret, "failed to key decrypt %u", err3);
|
||||||
ck_assert_msg(memcmp(out1, out2, sz1) == 0, "differing output data");
|
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
|
// 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)
|
// to remove the manual check now that it's there)
|
||||||
Tox *tox5 = tox_encrypted_new(0, data2, size, pw, pwlen, &err);
|
Tox *tox4 = tox_new(0, out1, size, &err2);
|
||||||
ck_assert_msg(err == TOX_ERR_ENCRYPTED_NEW_OK, "failed to encrypted new the third");
|
ck_assert_msg(err2 == TOX_ERR_NEW_OK, "failed to new the third");
|
||||||
uint8_t address5[TOX_PUBLIC_KEY_SIZE];
|
uint8_t address5[TOX_PUBLIC_KEY_SIZE];
|
||||||
test = tox_friend_get_public_key(tox4, 0, address5, 0);
|
ret = tox_friend_get_public_key(tox4, 0, address5, 0);
|
||||||
ck_assert_msg(test == 1, "no friends! the third");
|
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");
|
ck_assert_msg(memcmp(address, address2, TOX_PUBLIC_KEY_SIZE) == 0, "addresses don't match! the third");
|
||||||
|
|
||||||
tox_kill(tox1);
|
tox_kill(tox1);
|
||||||
tox_kill(tox2);
|
tox_kill(tox2);
|
||||||
tox_kill(tox3);
|
tox_kill(tox3);
|
||||||
tox_kill(tox4);
|
tox_kill(tox4);
|
||||||
tox_kill(tox5);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_keys)
|
START_TEST(test_keys)
|
||||||
{
|
{
|
||||||
uint8_t key[tox_pass_key_length()];
|
TOX_ERR_ENCRYPTION encerr;
|
||||||
tox_derive_key_from_pass("123qweasdzxc", 12, key);
|
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 *string = "No Patrick, mayonnaise is not an instrument."; // 44
|
||||||
|
|
||||||
uint8_t encrypted[44 + tox_pass_encryption_extra_length()];
|
uint8_t encrypted[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
|
||||||
int sz = tox_pass_key_encrypt(string, 44, key, encrypted);
|
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()];
|
uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
|
||||||
int sz2 = tox_pass_encrypt(string, 44, "123qweasdzxc", 12, encrypted2);
|
ret = tox_pass_encrypt(string, 44, "123qweasdzxc", 12, encrypted2, &encerr);
|
||||||
|
ck_assert_msg(ret, "generic failure 3: %u", encerr);
|
||||||
|
|
||||||
ck_assert_msg(sz == sz2, "an encryption failed");
|
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()];
|
ret = tox_pass_key_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, key, out1, &decerr);
|
||||||
uint8_t out2[44 + tox_pass_encryption_extra_length()];
|
ck_assert_msg(ret, "generic failure 4: %u", decerr);
|
||||||
|
|
||||||
sz = tox_pass_key_decrypt(encrypted, 44 + tox_pass_encryption_extra_length(), key, out1);
|
|
||||||
ck_assert_msg(sz == 44, "sz isn't right");
|
|
||||||
ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 1 failed");
|
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);
|
ret = tox_pass_decrypt(encrypted2, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out2, &decerr);
|
||||||
ck_assert_msg(sz2 == 44, "sz2 isn't right");
|
ck_assert_msg(ret, "generic failure 5: %u", &decerr);
|
||||||
ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed");
|
ck_assert_msg(memcmp(out2, string, 44) == 0, "decryption 2 failed");
|
||||||
|
|
||||||
// test that pass_decrypt can decrypt things from pass_key_encrypt
|
// 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);
|
ret = tox_pass_decrypt(encrypted, 44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH, "123qweasdzxc", 12, out1, &decerr);
|
||||||
ck_assert_msg(sz == 44, "sz isn't right");
|
ck_assert_msg(ret, "generic failure 6: %u", decerr);
|
||||||
ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed");
|
ck_assert_msg(memcmp(out1, string, 44) == 0, "decryption 3 failed");
|
||||||
|
|
||||||
uint8_t salt[tox_pass_salt_length()];
|
uint8_t salt[TOX_PASS_SALT_LENGTH];
|
||||||
ck_assert_msg(0 == tox_get_salt(encrypted, salt), "couldn't get salt");
|
ck_assert_msg(tox_get_salt(encrypted, salt), "couldn't get salt");
|
||||||
uint8_t key2[tox_pass_key_length()];
|
uint8_t key2[TOX_PASS_KEY_LENGTH];
|
||||||
tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2);
|
ret = tox_derive_key_with_salt("123qweasdzxc", 12, salt, key2, &keyerr);
|
||||||
ck_assert_msg(0 == memcmp(key, key2, tox_pass_key_length()), "salt comparison failed");
|
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
|
END_TEST
|
||||||
|
|
||||||
|
@ -163,7 +172,7 @@ Suite *encryptsave_suite(void)
|
||||||
{
|
{
|
||||||
Suite *s = suite_create("encryptsave");
|
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(save_friend, 20);
|
||||||
DEFTESTCASE_SLOW(keys, 30);
|
DEFTESTCASE_SLOW(keys, 30);
|
||||||
|
|
||||||
|
|
|
@ -37,81 +37,69 @@
|
||||||
#include <crypto_hash_sha256.h>
|
#include <crypto_hash_sha256.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \
|
#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES
|
||||||
+ crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH)
|
#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES)
|
#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_encryption_extra_length()
|
#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)
|
||||||
return TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
int tox_pass_key_length()
|
/* Clients should consider alerting their users that, unlike plain data, if even one bit
|
||||||
{
|
|
||||||
return TOX_PASS_KEY_LENGTH;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tox_pass_salt_length()
|
|
||||||
{
|
|
||||||
return crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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
|
|
||||||
* becomes corrupted, the data will be entirely unrecoverable.
|
* becomes corrupted, the data will be entirely unrecoverable.
|
||||||
* Ditto if they forget their password, there is no way to recover the data.
|
* 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
|
/* 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
|
* derive_key_with_salt to produce the same key as was previously used. Any encrpyted
|
||||||
* data with this module can be used as input.
|
* data with this module can be used as input.
|
||||||
*
|
*
|
||||||
* returns -1 if the magic number is wrong
|
* returns true if magic number matches
|
||||||
* returns 0 otherwise (no guarantee about validity of data)
|
* 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)
|
if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
data += TOX_ENC_SAVE_MAGIC_LENGTH;
|
data += TOX_ENC_SAVE_MAGIC_LENGTH;
|
||||||
memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
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
|
/* 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.
|
* 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 password is zeroed after key derivation.
|
||||||
* The key should only be used with the other functions in this module, as it
|
* The key should only be used with the other functions in this module, as it
|
||||||
* includes a salt.
|
* 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 true on success
|
||||||
* returns -1 on failure
|
|
||||||
*/
|
*/
|
||||||
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];
|
uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
|
||||||
randombytes(salt, sizeof salt);
|
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.
|
/* 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_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)
|
if (pplength == 0 || !passphrase || !salt || !out_key) {
|
||||||
return -1;
|
SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t passkey[crypto_hash_sha256_BYTES];
|
uint8_t passkey[crypto_hash_sha256_BYTES];
|
||||||
crypto_hash_sha256(passkey, passphrase, pplength);
|
crypto_hash_sha256(passkey, passphrase, pplength);
|
||||||
|
@ -127,27 +115,33 @@ 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_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
|
||||||
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
|
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
|
||||||
/* out of memory most likely */
|
/* 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 */
|
sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
|
||||||
memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
|
||||||
memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES);
|
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.
|
* array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
|
||||||
* key must be TOX_PASS_KEY_LENGTH bytes.
|
* key must be TOX_PASS_KEY_LENGTH bytes.
|
||||||
* If you already have a symmetric key from somewhere besides this module, simply
|
* If you already have a symmetric key from somewhere besides this module, simply
|
||||||
* call encrypt_data_symmetric in toxcore/crypto_core directly.
|
* call encrypt_data_symmetric in toxcore/crypto_core directly.
|
||||||
*
|
*
|
||||||
*
|
* returns true on success
|
||||||
* 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)
|
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:
|
/* the output data consists of, in order:
|
||||||
* salt, nonce, mac, enc_data
|
* salt, nonce, mac, enc_data
|
||||||
* where the mac is automatically prepended by the encrypt()
|
* where the mac is automatically prepended by the encrypt()
|
||||||
|
@ -173,78 +167,62 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *
|
||||||
/* now encrypt */
|
/* now encrypt */
|
||||||
if (encrypt_data_symmetric(key, nonce, data, data_len, out)
|
if (encrypt_data_symmetric(key, nonce, data, data_len, out)
|
||||||
!= data_len + crypto_box_MACBYTES) {
|
!= 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
|
/* 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
|
* at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
|
||||||
* to tox_derive_key_from_pass and tox_pass_key_encrypt.
|
* to tox_derive_key_from_pass and tox_pass_key_encrypt.
|
||||||
*
|
*
|
||||||
* returns 0 on success
|
* returns true 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)
|
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];
|
uint8_t key[TOX_PASS_KEY_LENGTH];
|
||||||
|
TOX_ERR_KEY_DERIVATION _error;
|
||||||
|
|
||||||
if (tox_derive_key_from_pass(passphrase, pplength, key) == -1)
|
if (!tox_derive_key_from_pass(passphrase, pplength, key, &_error)) {
|
||||||
return -1;
|
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 tox_pass_key_encrypt(data, data_len, key, out);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save the messenger data encrypted with the given password.
|
return tox_pass_key_encrypt(data, data_len, key, out, error);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
|
/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
|
||||||
* tox_derive_key_from_pass.
|
* tox_derive_key_from_pass.
|
||||||
*
|
*
|
||||||
* returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
|
* the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
|
||||||
* returns -1 on failure
|
*
|
||||||
|
* 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
|
if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) {
|
||||||
|| 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH))
|
SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH);
|
||||||
return -1;
|
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 += 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 salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
|
||||||
uint8_t nonce[crypto_box_NONCEBYTES];
|
uint8_t nonce[crypto_box_NONCEBYTES];
|
||||||
|
|
||||||
|
@ -257,20 +235,30 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke
|
||||||
/* decrypt the data */
|
/* decrypt the data */
|
||||||
if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
|
if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
|
||||||
!= decrypt_length) {
|
!= 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
|
/* 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.
|
||||||
*
|
*
|
||||||
* returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
|
* the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
|
||||||
* 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];
|
uint8_t passkey[crypto_hash_sha256_BYTES];
|
||||||
crypto_hash_sha256(passkey, passphrase, pplength);
|
crypto_hash_sha256(passkey, passphrase, pplength);
|
||||||
|
|
||||||
|
@ -286,60 +274,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_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
|
||||||
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
|
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
|
||||||
/* out of memory most likely */
|
/* 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 */
|
sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
|
||||||
|
|
||||||
return tox_pass_key_decrypt(data, length, key, out);
|
return tox_pass_key_decrypt(data, length, key, out, error);
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determines whether or not the given data is encrypted (by checking the magic number)
|
/* 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)
|
if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifndef TOX_DEFINED
|
#ifndef TOX_DEFINED
|
||||||
#define TOX_DEFINED
|
#define TOX_DEFINED
|
||||||
|
@ -37,21 +38,11 @@ typedef struct Tox Tox;
|
||||||
struct Tox_Options;
|
struct Tox_Options;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// these functions provide access to these defines in toxencryptsave.c, which
|
#define TOX_PASS_SALT_LENGTH 32
|
||||||
// otherwise aren't actually available in clients...
|
#define TOX_PASS_KEY_LENGTH 64
|
||||||
int tox_pass_encryption_extra_length();
|
#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH 80
|
||||||
|
|
||||||
int tox_pass_key_length();
|
/* This module is conceptually organized into two parts. The first part are the functions
|
||||||
|
|
||||||
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
|
|
||||||
* with "key" in the name. To use these functions, first derive an encryption key
|
* 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
|
* 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,
|
* encrypt the data. The second part takes the password itself instead of the key,
|
||||||
|
@ -61,13 +52,74 @@ uint32_t tox_encrypted_size(const Tox *tox);
|
||||||
* favor using the first part intead of the second part.
|
* favor using the first part intead of the second part.
|
||||||
*
|
*
|
||||||
* The encrypted data is prepended with a magic number, to aid validity checking
|
* 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
|
* Clients should consider alerting their users that, unlike plain data, if even one bit
|
||||||
* becomes corrupted, the data will be entirely unrecoverable.
|
* becomes corrupted, the data will be entirely unrecoverable.
|
||||||
* Ditto if they forget their password, there is no way to recover the data.
|
* Ditto if they forget their password, there is no way to recover the data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
typedef enum TOX_ERR_KEY_DERIVATION {
|
||||||
|
TOX_ERR_KEY_DERIVATION_OK,
|
||||||
|
/**
|
||||||
|
* Some input data, or maybe the output pointer, was null.
|
||||||
|
*/
|
||||||
|
TOX_ERR_KEY_DERIVATION_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_KEY_DERIVATION_FAILED
|
||||||
|
} TOX_ERR_KEY_DERIVATION;
|
||||||
|
|
||||||
|
typedef enum TOX_ERR_ENCRYPTION {
|
||||||
|
TOX_ERR_ENCRYPTION_OK,
|
||||||
|
/**
|
||||||
|
* Some input data, or maybe the output pointer, was null.
|
||||||
|
*/
|
||||||
|
TOX_ERR_ENCRYPTION_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_ENCRYPTION_KEY_DERIVATION_FAILED,
|
||||||
|
/**
|
||||||
|
* The encryption itself failed.
|
||||||
|
*/
|
||||||
|
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 input data was shorter than TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes
|
||||||
|
*/
|
||||||
|
TOX_ERR_DECRYPTION_INVALID_LENGTH,
|
||||||
|
/**
|
||||||
|
* The input data is missing the magic number (i.e. wasn't created by this
|
||||||
|
* module, or is corrupted)
|
||||||
|
*/
|
||||||
|
TOX_ERR_DECRYPTION_BAD_FORMAT,
|
||||||
|
/**
|
||||||
|
* 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_DECRYPTION_KEY_DERIVATION_FAILED,
|
||||||
|
/**
|
||||||
|
* The encrypted byte array could not be decrypted. Either the data was
|
||||||
|
* corrupt or the password/key was incorrect.
|
||||||
|
*/
|
||||||
|
TOX_ERR_DECRYPTION_FAILED
|
||||||
|
} TOX_ERR_DECRYPTION;
|
||||||
|
|
||||||
|
|
||||||
/******************************* BEGIN PART 2 *******************************
|
/******************************* BEGIN PART 2 *******************************
|
||||||
* For simplicty, the second part of the module is presented first. The API for
|
* For simplicty, the second part of the module is presented first. The API for
|
||||||
|
@ -77,98 +129,25 @@ uint32_t tox_encrypted_size(const Tox *tox);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Encrypts the given data with the given passphrase. The output array must be
|
/* 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
|
* at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
|
||||||
* to tox_derive_key_from_pass and tox_pass_key_encrypt.
|
* 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 true on success
|
||||||
*
|
|
||||||
* 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);
|
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);
|
||||||
|
|
||||||
/* 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
|
/* 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
|
* at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
|
||||||
* to tox_pass_key_decrypt.
|
* to tox_pass_key_decrypt.
|
||||||
*
|
*
|
||||||
* tox_encrypted_load() is a good example of how to use this function.
|
* 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 true 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);
|
bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out,
|
||||||
|
TOX_ERR_DECRYPTION *error);
|
||||||
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_ENCRYPTED_NEW *error);
|
|
||||||
|
|
||||||
|
|
||||||
/******************************* BEGIN PART 1 *******************************
|
/******************************* BEGIN PART 1 *******************************
|
||||||
|
@ -177,7 +156,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
|
/* 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.
|
* 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 password is zeroed after key derivation.
|
||||||
* The key should only be used with the other functions in this module, as it
|
* The key should only be used with the other functions in this module, as it
|
||||||
|
@ -185,72 +164,52 @@ 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
|
* 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.
|
* password, you also must know the random salt that was used. See below.
|
||||||
*
|
*
|
||||||
* returns 0 on success
|
* returns true on success
|
||||||
* returns -1 on failure
|
|
||||||
*/
|
*/
|
||||||
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.
|
/* 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_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
|
/* 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
|
* derive_key_with_salt to produce the same key as was previously used. Any encrpyted
|
||||||
* data with this module can be used as input.
|
* data with this module can be used as input.
|
||||||
*
|
*
|
||||||
* returns -1 if the magic number is wrong
|
* returns true if magic number matches
|
||||||
* returns 0 otherwise (no guarantee about validity of data)
|
* 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. */
|
/* Now come the functions that are analogous to the part 2 functions. */
|
||||||
|
|
||||||
/* Encrypt arbitrary with a key produced by tox_derive_key_. 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.
|
* array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
|
||||||
* key must be tox_pass_key_length() bytes.
|
* key must be TOX_PASS_KEY_LENGTH bytes.
|
||||||
* If you already have a symmetric key from somewhere besides this module, simply
|
* If you already have a symmetric key from somewhere besides this module, simply
|
||||||
* call encrypt_data_symmetric in toxcore/crypto_core directly.
|
* call encrypt_data_symmetric in toxcore/crypto_core directly.
|
||||||
*
|
*
|
||||||
* returns 0 on success
|
* returns true 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);
|
bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out,
|
||||||
|
TOX_ERR_ENCRYPTION *error);
|
||||||
/* 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
|
|
||||||
*/
|
|
||||||
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
|
/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
|
||||||
* tox_derive_key_from_pass.
|
* tox_derive_key_from_pass.
|
||||||
*
|
*
|
||||||
* returns the length of the output data (== data_len - tox_pass_encryption_extra_length()) on success
|
* the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
|
||||||
* 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().
|
|
||||||
*
|
*
|
||||||
* 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,
|
bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out,
|
||||||
TOX_ERR_ENCRYPTED_NEW *error);
|
TOX_ERR_DECRYPTION *error);
|
||||||
|
|
||||||
|
|
||||||
/* Determines whether or not the given data is encrypted (by checking the magic number)
|
/* 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user