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