summaryrefslogtreecommitdiff
path: root/toxencryptsave
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-10-10 22:07:43 -0400
committerirungentoo <irungentoo@gmail.com>2014-10-10 22:07:43 -0400
commit3f855b2445970fb32f06f4e8f5d07c89d617024f (patch)
tree33fb187e809166ee24853573631daa70f3c9b323 /toxencryptsave
parentd80ee91ae77d0b852c685604b71774b6ee88cc2d (diff)
parent54fdf3bdd653ebf6e55d2cb93fcae41e68436e11 (diff)
Merge branch 'master' of https://github.com/dubslow/toxcore
Diffstat (limited to 'toxencryptsave')
-rw-r--r--toxencryptsave/toxencryptsave.c164
-rw-r--r--toxencryptsave/toxencryptsave.h53
2 files changed, 177 insertions, 40 deletions
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index 070f0184..7efba089 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -44,17 +44,22 @@
44/* return size of the messenger data (for encrypted saving). */ 44/* return size of the messenger data (for encrypted saving). */
45uint32_t tox_encrypted_size(const Tox *tox) 45uint32_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/* Generates a secret symmetric key from the given passphrase. out_key must be at least
52 * data must be at least tox_encrypted_size(). 51 * TOX_PASS_KEY_LENGTH bytes long.
52 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
53 * This function is fairly cheap, but irungentoo insists that you be allowed to
54 * cache the result if you want, to minimize computation for repeated encryptions.
55 * The password is zeroed after key derivation.
56 * The key should only be used with the other functions in this module, as it
57 * includes a salt.
53 * 58 *
54 * returns 0 on success 59 * returns 0 on success
55 * returns -1 on failure 60 * returns -1 on failure
56 */ 61 */
57int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) 62int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key)
58{ 63{
59 if (pplength == 0) 64 if (pplength == 0)
60 return -1; 65 return -1;
@@ -78,16 +83,27 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
78 } 83 }
79 84
80 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ 85 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
86 memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
87 memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES);
88 return 0;
89}
81 90
82 /* next get plain save data */ 91/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output
83 uint32_t temp_size = tox_size(tox); 92 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
84 uint8_t temp_data[temp_size]; 93 * key must be TOX_PASS_KEY_LENGTH bytes.
85 tox_save(tox, temp_data); 94 * If you already have a symmetric key from somewhere besides this module, simply
86 95 * call encrypt_data_symmetric in toxcore/crypto_core directly.
96 *
97 *
98 * returns 0 on success
99 * returns -1 on failure
100 */
101int tox_pass_key_encrypt(uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out)
102{
87 /* the output data consists of, in order: 103 /* the output data consists of, in order:
88 * magic number, salt, nonce, mac, enc_data 104 * salt, nonce, mac, enc_data
89 * where the mac is automatically prepended by the encrypt() 105 * where the mac is automatically prepended by the encrypt()
90 * the magic+salt+nonce is called the prefix 106 * 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 107 * 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 108 * need them to decrypt the data
93 */ 109 */
@@ -96,56 +112,111 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
96 uint8_t nonce[crypto_box_NONCEBYTES]; 112 uint8_t nonce[crypto_box_NONCEBYTES];
97 random_nonce(nonce); 113 random_nonce(nonce);
98 114
99 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); 115 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
100 data += TOX_ENC_SAVE_MAGIC_LENGTH; 116 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
101 memcpy(data, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 117 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
102 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 118 memcpy(out, nonce, crypto_box_NONCEBYTES);
103 memcpy(data, nonce, crypto_box_NONCEBYTES); 119 out += crypto_box_NONCEBYTES;
104 data += crypto_box_NONCEBYTES;
105 120
106 /* now encrypt */ 121 /* now encrypt */
107 if (encrypt_data_symmetric(key, nonce, temp_data, temp_size, data) 122 if (encrypt_data_symmetric(key, nonce, data, data_len, out)
108 != temp_size + crypto_box_MACBYTES) { 123 != data_len + crypto_box_MACBYTES) {
109 return -1; 124 return -1;
110 } 125 }
111 126
112 return 0; 127 return 0;
113} 128}
114 129
115/* Load the messenger from encrypted data of size length. 130/* Encrypts the given data with the given passphrase. The output array must be
131 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
132 * to tox_derive_key_from_pass and tox_pass_key_encrypt.
116 * 133 *
117 * returns 0 on success 134 * returns 0 on success
118 * returns -1 on failure 135 * returns -1 on failure
119 */ 136 */
120int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength) 137int tox_pass_encrypt(uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out)
121{ 138{
122 if (length <= crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + 139 uint8_t key[TOX_PASS_KEY_LENGTH];
123 TOX_ENC_SAVE_MAGIC_LENGTH)
124 return -1;
125 140
126 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) 141 if (tox_derive_key_from_pass(passphrase, pplength, key) == -1)
127 return -1; 142 return -1;
128 143
144 return tox_pass_key_encrypt(data, data_len, key, out);
145}
146
147/* Save the messenger data encrypted with the given password.
148 * data must be at least tox_encrypted_size().
149 *
150 * returns 0 on success
151 * returns -1 on failure
152 */
153int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength)
154{
155 /* first get plain save data */
156 uint32_t temp_size = tox_size(tox);
157 uint8_t temp_data[temp_size];
158 tox_save(tox, temp_data);
159
160 /* the output data consists of, in order: magic number, enc_data */
161 /* first add the magic number */
162 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
129 data += TOX_ENC_SAVE_MAGIC_LENGTH; 163 data += TOX_ENC_SAVE_MAGIC_LENGTH;
130 164
131 uint32_t decrypt_length = length - crypto_box_MACBYTES - crypto_box_NONCEBYTES 165 /* now encrypt */
132 - crypto_pwhash_scryptsalsa208sha256_SALTBYTES - TOX_ENC_SAVE_MAGIC_LENGTH; 166 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
133 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 167}
168
169/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
170 * tox_derive_key_from_pass.
171 *
172 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
173 * returns -1 on failure
174 */
175int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out)
176{
177 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
178 return -1;
179
180 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
181 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
134 uint8_t nonce[crypto_box_NONCEBYTES]; 182 uint8_t nonce[crypto_box_NONCEBYTES];
135 183
184 //memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
185 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // ignore the salt, which is only needed for kdf
186 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
187 memcpy(nonce, data, crypto_box_NONCEBYTES);
188 data += crypto_box_NONCEBYTES;
189
190 /* decrypt the data */
191 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
192 != decrypt_length) {
193 return -1;
194 }
195
196 return decrypt_length;
197}
198
199/* Decrypts the given data with the given passphrase. The output array must be
200 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
201 *
202 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
203 * returns -1 on failure
204 */
205int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out)
206{
207
136 uint8_t passkey[crypto_hash_sha256_BYTES]; 208 uint8_t passkey[crypto_hash_sha256_BYTES];
137 crypto_hash_sha256(passkey, passphrase, pplength); 209 crypto_hash_sha256(passkey, passphrase, pplength);
138 210
211 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
139 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 212 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
140 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
141 memcpy(nonce, data, crypto_box_NONCEBYTES);
142 data += crypto_box_NONCEBYTES;
143 213
144 /* derive the key */ 214 /* derive the key */
145 uint8_t key[crypto_box_KEYBYTES]; 215 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
146 216
147 if (crypto_pwhash_scryptsalsa208sha256( 217 if (crypto_pwhash_scryptsalsa208sha256(
148 key, sizeof(key), passkey, sizeof(passkey), salt, 218 key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
219 crypto_box_KEYBYTES, passkey, sizeof(passkey), salt,
149 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 220 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
150 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { 221 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
151 /* out of memory most likely */ 222 /* out of memory most likely */
@@ -154,13 +225,28 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
154 225
155 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ 226 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
156 227
157 /* decrypt the data */ 228 return tox_pass_key_decrypt(data, length, key, out);
229}
230
231/* Load the messenger from encrypted data of size length.
232 *
233 * returns 0 on success
234 * returns -1 on failure
235 */
236int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
237{
238 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
239 return -1;
240
241 data += TOX_ENC_SAVE_MAGIC_LENGTH;
242 length -= TOX_ENC_SAVE_MAGIC_LENGTH;
243
244 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
158 uint8_t temp_data[decrypt_length]; 245 uint8_t temp_data[decrypt_length];
159 246
160 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, temp_data) 247 if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data)
161 != decrypt_length) { 248 != decrypt_length)
162 return -1; 249 return -1;
163 }
164 250
165 return tox_load(tox, temp_data, decrypt_length); 251 return tox_load(tox, temp_data, decrypt_length);
166} 252}
@@ -170,7 +256,7 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
170 * returns 1 if it is encrypted 256 * returns 1 if it is encrypted
171 * returns 0 otherwise 257 * returns 0 otherwise
172 */ 258 */
173int tox_is_data_encrypted(const uint8_t *data) 259int tox_is_save_encrypted(const uint8_t *data)
174{ 260{
175 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) 261 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
176 return 1; 262 return 1;
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h
index 75094a2b..527578a5 100644
--- a/toxencryptsave/toxencryptsave.h
+++ b/toxencryptsave/toxencryptsave.h
@@ -35,6 +35,10 @@ extern "C" {
35typedef struct Tox Tox; 35typedef 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)
40
41#define TOX_PASS_KEY_LENGTH (crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES)
38 42
39/* This "module" provides functions analogous to tox_load and tox_save in toxcore 43/* 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 44 * Clients should consider alerting their users that, unlike plain data, if even one bit
@@ -45,6 +49,43 @@ typedef struct Tox Tox;
45/* return size of the messenger data (for encrypted saving). */ 49/* return size of the messenger data (for encrypted saving). */
46uint32_t tox_encrypted_size(const Tox *tox); 50uint32_t tox_encrypted_size(const Tox *tox);
47 51
52/* Generates a secret symmetric key from the given passphrase. out_key must be at least
53 * TOX_PASS_KEY_LENGTH bytes long.
54 * Be sure to not compromise the key! Only keep it in memory, do not write to disk.
55 * This function is fairly cheap, but irungentoo insists that you be allowed to
56 * cache the result if you want, to minimize computation for repeated encryptions.
57 * The password is zeroed after key derivation.
58 * The key should only be used with the other functions in this module, as it
59 * includes a salt.
60 *
61 * returns 0 on success
62 * returns -1 on failure
63 */
64int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key);
65
66/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output
67 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
68 * key must be TOX_PASS_KEY_LENGTH bytes.
69 * If you already have a symmetric key from somewhere besides this module, simply
70 * call encrypt_data_symmetric in toxcore/crypto_core directly.
71 *
72 *
73 * returns 0 on success
74 * returns -1 on failure
75 */
76int tox_pass_key_encrypt(uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out);
77
78/* Encrypts the given data with the given passphrase. The output array must be
79 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
80 * to tox_derive_key_from_pass and tox_pass_key_encrypt.
81 *
82 * tox_encrypted_save() is a good example of how to use this function.
83 *
84 * returns 0 on success
85 * returns -1 on failure
86 */
87int tox_pass_encrypt(uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out);
88
48/* Save the messenger data encrypted with the given password. 89/* Save the messenger data encrypted with the given password.
49 * data must be at least tox_encrypted_size(). 90 * data must be at least tox_encrypted_size().
50 * 91 *
@@ -53,6 +94,16 @@ uint32_t tox_encrypted_size(const Tox *tox);
53 */ 94 */
54int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength); 95int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength);
55 96
97/* Decrypts the given data with the given passphrase. The output array must be
98 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
99 *
100 * tox_encrypted_load() is a good example of how to use this function.
101 *
102 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
103 * returns -1 on failure
104 */
105int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out);
106
56/* Load the messenger from encrypted data of size length. 107/* Load the messenger from encrypted data of size length.
57 * 108 *
58 * returns 0 on success 109 * returns 0 on success
@@ -65,7 +116,7 @@ int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *
65 * returns 1 if it is encrypted 116 * returns 1 if it is encrypted
66 * returns 0 otherwise 117 * returns 0 otherwise
67 */ 118 */
68int tox_is_data_encrypted(const uint8_t *data); 119int tox_is_save_encrypted(const uint8_t *data);
69 120
70#ifdef __cplusplus 121#ifdef __cplusplus
71} 122}