diff options
-rw-r--r-- | auto_tests/encryptsave_test.c | 2 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.c | 97 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.h | 24 |
3 files changed, 87 insertions, 36 deletions
diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index 7661cbc7..752f906f 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c | |||
@@ -65,7 +65,7 @@ START_TEST(test_save_friend) | |||
65 | uint8_t data[size]; | 65 | uint8_t data[size]; |
66 | test = tox_encrypted_save(tox1, data, "correcthorsebatterystaple", 25); | 66 | test = tox_encrypted_save(tox1, data, "correcthorsebatterystaple", 25); |
67 | ck_assert_msg(test == 0, "failed to encrypted save"); | 67 | ck_assert_msg(test == 0, "failed to encrypted save"); |
68 | ck_assert_msg(tox_is_data_encrypted(data) == 1, "magic number missing"); | 68 | ck_assert_msg(tox_is_save_encrypted(data) == 1, "magic number missing"); |
69 | Tox *tox3 = tox_new(0); | 69 | Tox *tox3 = tox_new(0); |
70 | test = tox_encrypted_load(tox3, data, size, "correcthorsebatterystaple", 25); | 70 | test = tox_encrypted_load(tox3, data, size, "correcthorsebatterystaple", 25); |
71 | ck_assert_msg(test == 0, "failed to encrypted load"); | 71 | ck_assert_msg(test == 0, "failed to encrypted load"); |
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 070f0184..b018bd48 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c | |||
@@ -44,17 +44,16 @@ | |||
44 | /* return size of the messenger data (for encrypted saving). */ | 44 | /* return size of the messenger data (for encrypted saving). */ |
45 | uint32_t tox_encrypted_size(const Tox *tox) | 45 | uint32_t tox_encrypted_size(const Tox *tox) |
46 | { | 46 | { |
47 | return tox_size(tox) + crypto_box_MACBYTES + crypto_box_NONCEBYTES | 47 | return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + TOX_ENC_SAVE_MAGIC_LENGTH; |
48 | + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH; | ||
49 | } | 48 | } |
50 | 49 | ||
51 | /* Save the messenger data encrypted with the given password. | 50 | /* Encrypts the given data with the given passphrase. The output array must be |
52 | * data must be at least tox_encrypted_size(). | 51 | * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. |
53 | * | 52 | * |
54 | * returns 0 on success | 53 | * returns 0 on success |
55 | * returns -1 on failure | 54 | * returns -1 on failure |
56 | */ | 55 | */ |
57 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) | 56 | int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint32_t pplength, uint8_t* out) |
58 | { | 57 | { |
59 | if (pplength == 0) | 58 | if (pplength == 0) |
60 | return -1; | 59 | return -1; |
@@ -79,15 +78,10 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 | |||
79 | 78 | ||
80 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ | 79 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ |
81 | 80 | ||
82 | /* next get plain save data */ | ||
83 | uint32_t temp_size = tox_size(tox); | ||
84 | uint8_t temp_data[temp_size]; | ||
85 | tox_save(tox, temp_data); | ||
86 | |||
87 | /* the output data consists of, in order: | 81 | /* the output data consists of, in order: |
88 | * magic number, salt, nonce, mac, enc_data | 82 | * salt, nonce, mac, enc_data |
89 | * where the mac is automatically prepended by the encrypt() | 83 | * where the mac is automatically prepended by the encrypt() |
90 | * the magic+salt+nonce is called the prefix | 84 | * the salt+nonce is called the prefix |
91 | * I'm not sure what else I'm supposed to do with the salt and nonce, since we | 85 | * I'm not sure what else I'm supposed to do with the salt and nonce, since we |
92 | * need them to decrypt the data | 86 | * need them to decrypt the data |
93 | */ | 87 | */ |
@@ -96,40 +90,56 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3 | |||
96 | uint8_t nonce[crypto_box_NONCEBYTES]; | 90 | uint8_t nonce[crypto_box_NONCEBYTES]; |
97 | random_nonce(nonce); | 91 | random_nonce(nonce); |
98 | 92 | ||
99 | memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); | 93 | memcpy(out, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); |
100 | data += TOX_ENC_SAVE_MAGIC_LENGTH; | 94 | out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; |
101 | memcpy(data, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); | 95 | memcpy(out, nonce, crypto_box_NONCEBYTES); |
102 | data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; | 96 | out += crypto_box_NONCEBYTES; |
103 | memcpy(data, nonce, crypto_box_NONCEBYTES); | ||
104 | data += crypto_box_NONCEBYTES; | ||
105 | 97 | ||
106 | /* now encrypt */ | 98 | /* now encrypt */ |
107 | if (encrypt_data_symmetric(key, nonce, temp_data, temp_size, data) | 99 | if (encrypt_data_symmetric(key, nonce, data, data_len, out) |
108 | != temp_size + crypto_box_MACBYTES) { | 100 | != data_len + crypto_box_MACBYTES) { |
109 | return -1; | 101 | return -1; |
110 | } | 102 | } |
111 | 103 | ||
112 | return 0; | 104 | return 0; |
113 | } | 105 | } |
114 | 106 | ||
115 | /* Load the messenger from encrypted data of size length. | 107 | /* Save the messenger data encrypted with the given password. |
108 | * data must be at least tox_encrypted_size(). | ||
116 | * | 109 | * |
117 | * returns 0 on success | 110 | * returns 0 on success |
118 | * returns -1 on failure | 111 | * returns -1 on failure |
119 | */ | 112 | */ |
120 | int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) | 113 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) |
121 | { | 114 | { |
122 | if (length <= crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + | 115 | /* first get plain save data */ |
123 | TOX_ENC_SAVE_MAGIC_LENGTH) | 116 | uint32_t temp_size = tox_size(tox); |
124 | return -1; | 117 | uint8_t temp_data[temp_size]; |
125 | 118 | tox_save(tox, temp_data); | |
126 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) | ||
127 | return -1; | ||
128 | 119 | ||
120 | /* the output data consists of, in order: magic number, enc_data */ | ||
121 | /* first add the magic number */ | ||
122 | memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); | ||
129 | data += TOX_ENC_SAVE_MAGIC_LENGTH; | 123 | data += TOX_ENC_SAVE_MAGIC_LENGTH; |
130 | 124 | ||
131 | uint32_t decrypt_length = length - crypto_box_MACBYTES - crypto_box_NONCEBYTES | 125 | |
132 | - crypto_pwhash_scryptsalsa208sha256_SALTBYTES - TOX_ENC_SAVE_MAGIC_LENGTH; | 126 | /* now encrypt */ |
127 | return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); | ||
128 | } | ||
129 | |||
130 | |||
131 | /* Decrypts the given data with the given passphrase. The output array must be | ||
132 | * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. | ||
133 | * | ||
134 | * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success | ||
135 | * returns -1 on failure | ||
136 | */ | ||
137 | int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase, uint32_t pplength, uint8_t* out) | ||
138 | { | ||
139 | if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) | ||
140 | return -1; | ||
141 | |||
142 | uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
133 | uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; | 143 | uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; |
134 | uint8_t nonce[crypto_box_NONCEBYTES]; | 144 | uint8_t nonce[crypto_box_NONCEBYTES]; |
135 | 145 | ||
@@ -155,13 +165,32 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t * | |||
155 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ | 165 | sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ |
156 | 166 | ||
157 | /* decrypt the data */ | 167 | /* decrypt the data */ |
158 | uint8_t temp_data[decrypt_length]; | 168 | if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) |
159 | |||
160 | if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, temp_data) | ||
161 | != decrypt_length) { | 169 | != decrypt_length) { |
162 | return -1; | 170 | return -1; |
163 | } | 171 | } |
164 | 172 | ||
173 | return decrypt_length; | ||
174 | } | ||
175 | |||
176 | /* Load the messenger from encrypted data of size length. | ||
177 | * | ||
178 | * returns 0 on success | ||
179 | * returns -1 on failure | ||
180 | */ | ||
181 | int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) | ||
182 | { | ||
183 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) | ||
184 | return -1; | ||
185 | data += TOX_ENC_SAVE_MAGIC_LENGTH; length -= TOX_ENC_SAVE_MAGIC_LENGTH; | ||
186 | |||
187 | uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; | ||
188 | uint8_t temp_data[decrypt_length]; | ||
189 | |||
190 | if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) | ||
191 | != decrypt_length) | ||
192 | return -1; | ||
193 | |||
165 | return tox_load(tox, temp_data, decrypt_length); | 194 | return tox_load(tox, temp_data, decrypt_length); |
166 | } | 195 | } |
167 | 196 | ||
@@ -170,7 +199,7 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t * | |||
170 | * returns 1 if it is encrypted | 199 | * returns 1 if it is encrypted |
171 | * returns 0 otherwise | 200 | * returns 0 otherwise |
172 | */ | 201 | */ |
173 | int tox_is_data_encrypted(const uint8_t *data) | 202 | int tox_is_save_encrypted(const uint8_t *data) |
174 | { | 203 | { |
175 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) | 204 | if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) |
176 | return 1; | 205 | return 1; |
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h index 75094a2b..e3f998af 100644 --- a/toxencryptsave/toxencryptsave.h +++ b/toxencryptsave/toxencryptsave.h | |||
@@ -35,6 +35,8 @@ extern "C" { | |||
35 | typedef struct Tox Tox; | 35 | typedef struct Tox Tox; |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ | ||
39 | + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) | ||
38 | 40 | ||
39 | /* This "module" provides functions analogous to tox_load and tox_save in toxcore | 41 | /* This "module" provides functions analogous to tox_load and tox_save in toxcore |
40 | * Clients should consider alerting their users that, unlike plain data, if even one bit | 42 | * Clients should consider alerting their users that, unlike plain data, if even one bit |
@@ -45,6 +47,16 @@ typedef struct Tox Tox; | |||
45 | /* return size of the messenger data (for encrypted saving). */ | 47 | /* return size of the messenger data (for encrypted saving). */ |
46 | uint32_t tox_encrypted_size(const Tox *tox); | 48 | uint32_t tox_encrypted_size(const Tox *tox); |
47 | 49 | ||
50 | /* Encrypts the given data with the given passphrase. The output array must be | ||
51 | * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. | ||
52 | * | ||
53 | * tox_encrypted_save() is a good example of how to use this function. | ||
54 | * | ||
55 | * returns 0 on success | ||
56 | * returns -1 on failure | ||
57 | */ | ||
58 | int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint32_t pplength, uint8_t* out); | ||
59 | |||
48 | /* Save the messenger data encrypted with the given password. | 60 | /* Save the messenger data encrypted with the given password. |
49 | * data must be at least tox_encrypted_size(). | 61 | * data must be at least tox_encrypted_size(). |
50 | * | 62 | * |
@@ -53,6 +65,16 @@ uint32_t tox_encrypted_size(const Tox *tox); | |||
53 | */ | 65 | */ |
54 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); | 66 | int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); |
55 | 67 | ||
68 | /* Decrypts the given data with the given passphrase. The output array must be | ||
69 | * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. | ||
70 | * | ||
71 | * tox_encrypted_load() is a good example of how to use this function. | ||
72 | * | ||
73 | * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success | ||
74 | * returns -1 on failure | ||
75 | */ | ||
76 | int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase, uint32_t pplength, uint8_t* out); | ||
77 | |||
56 | /* Load the messenger from encrypted data of size length. | 78 | /* Load the messenger from encrypted data of size length. |
57 | * | 79 | * |
58 | * returns 0 on success | 80 | * returns 0 on success |
@@ -65,7 +87,7 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t * | |||
65 | * returns 1 if it is encrypted | 87 | * returns 1 if it is encrypted |
66 | * returns 0 otherwise | 88 | * returns 0 otherwise |
67 | */ | 89 | */ |
68 | int tox_is_data_encrypted(const uint8_t *data); | 90 | int tox_is_save_encrypted(const uint8_t *data); |
69 | 91 | ||
70 | #ifdef __cplusplus | 92 | #ifdef __cplusplus |
71 | } | 93 | } |