summaryrefslogtreecommitdiff
path: root/toxencryptsave
diff options
context:
space:
mode:
authordubslow <bunslow@gmail.com>2014-10-09 20:16:05 -0500
committerdubslow <bunslow@gmail.com>2014-10-09 20:18:29 -0500
commit54fdf3bdd653ebf6e55d2cb93fcae41e68436e11 (patch)
treed98c9b524ee0dfc507375e0a16051e19a77801b4 /toxencryptsave
parente6f30694d32a81f9171b2057d9c873cc16f6dca1 (diff)
re-refactor to separate pass->key and key->encryption
Diffstat (limited to 'toxencryptsave')
-rw-r--r--toxencryptsave/toxencryptsave.c102
-rw-r--r--toxencryptsave/toxencryptsave.h31
2 files changed, 108 insertions, 25 deletions
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
index b018bd48..953ee802 100644
--- a/toxencryptsave/toxencryptsave.c
+++ b/toxencryptsave/toxencryptsave.c
@@ -47,13 +47,19 @@ uint32_t tox_encrypted_size(const Tox *tox)
47 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + TOX_ENC_SAVE_MAGIC_LENGTH; 47 return tox_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH + TOX_ENC_SAVE_MAGIC_LENGTH;
48} 48}
49 49
50/* Encrypts the given data with the given passphrase. The output array must be 50/* Generates a secret symmetric key from the given passphrase. out_key must be at least
51 * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. 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.
52 * 58 *
53 * returns 0 on success 59 * returns 0 on success
54 * returns -1 on failure 60 * returns -1 on failure
55 */ 61 */
56int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint32_t pplength, uint8_t* out) 62int tox_derive_key_from_pass(uint8_t* passphrase, uint32_t pplength, uint8_t* out_key)
57{ 63{
58 if (pplength == 0) 64 if (pplength == 0)
59 return -1; 65 return -1;
@@ -77,7 +83,23 @@ int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint
77 } 83 }
78 84
79 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}
80 90
91/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output
92 * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
93 * key must be TOX_PASS_KEY_LENGTH bytes.
94 * If you already have a symmetric key from somewhere besides this module, simply
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{
81 /* the output data consists of, in order: 103 /* the output data consists of, in order:
82 * salt, nonce, mac, enc_data 104 * salt, nonce, mac, enc_data
83 * where the mac is automatically prepended by the encrypt() 105 * where the mac is automatically prepended by the encrypt()
@@ -88,9 +110,10 @@ int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint
88 110
89 /* first add the prefix */ 111 /* first add the prefix */
90 uint8_t nonce[crypto_box_NONCEBYTES]; 112 uint8_t nonce[crypto_box_NONCEBYTES];
91 random_nonce(nonce); 113 random_nonce(nonce);
92 114
93 memcpy(out, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); 115 memcpy(out, key, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
116 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
94 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 117 out += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
95 memcpy(out, nonce, crypto_box_NONCEBYTES); 118 memcpy(out, nonce, crypto_box_NONCEBYTES);
96 out += crypto_box_NONCEBYTES; 119 out += crypto_box_NONCEBYTES;
@@ -104,6 +127,22 @@ int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint
104 return 0; 127 return 0;
105} 128}
106 129
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.
133 *
134 * returns 0 on success
135 * returns -1 on failure
136 */
137int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint32_t pplength, uint8_t* out)
138{
139 uint8_t key[TOX_PASS_KEY_LENGTH];
140 if (tox_derive_key_from_pass(passphrase, pplength, key) == -1)
141 return -1;
142
143 return tox_pass_key_encrypt(data, data_len, key, out);
144}
145
107/* Save the messenger data encrypted with the given password. 146/* Save the messenger data encrypted with the given password.
108 * data must be at least tox_encrypted_size(). 147 * data must be at least tox_encrypted_size().
109 * 148 *
@@ -122,40 +161,61 @@ int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint3
122 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH); 161 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
123 data += TOX_ENC_SAVE_MAGIC_LENGTH; 162 data += TOX_ENC_SAVE_MAGIC_LENGTH;
124 163
125
126 /* now encrypt */ 164 /* now encrypt */
127 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); 165 return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data);
128} 166}
129 167
130 168/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
131/* Decrypts the given data with the given passphrase. The output array must be 169 * tox_derive_key_from_pass.
132 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
133 * 170 *
134 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success 171 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
135 * returns -1 on failure 172 * returns -1 on failure
136 */ 173 */
137int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase, uint32_t pplength, uint8_t* out) 174int tox_pass_key_decrypt(const uint8_t* data, uint32_t length, const uint8_t* key, uint8_t* out)
138{ 175{
139 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) 176 if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH)
140 return -1; 177 return -1;
141 178
142 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; 179 uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
143 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; 180 //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
144 uint8_t nonce[crypto_box_NONCEBYTES]; 181 uint8_t nonce[crypto_box_NONCEBYTES];
145 182
146 uint8_t passkey[crypto_hash_sha256_BYTES]; 183 //memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
147 crypto_hash_sha256(passkey, passphrase, pplength); 184 key += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; // ignore the salt, which is only needed for kdf
148
149 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
150 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES; 185 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
151 memcpy(nonce, data, crypto_box_NONCEBYTES); 186 memcpy(nonce, data, crypto_box_NONCEBYTES);
152 data += crypto_box_NONCEBYTES; 187 data += crypto_box_NONCEBYTES;
153 188
189 /* decrypt the data */
190 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
191 != decrypt_length) {
192 return -1;
193 }
194
195 return decrypt_length;
196}
197
198/* Decrypts the given data with the given passphrase. The output array must be
199 * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long.
200 *
201 * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success
202 * returns -1 on failure
203 */
204int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase, uint32_t pplength, uint8_t* out)
205{
206
207 uint8_t passkey[crypto_hash_sha256_BYTES];
208 crypto_hash_sha256(passkey, passphrase, pplength);
209
210 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
211 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
212
154 /* derive the key */ 213 /* derive the key */
155 uint8_t key[crypto_box_KEYBYTES]; 214 uint8_t key[crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
156 215
157 if (crypto_pwhash_scryptsalsa208sha256( 216 if (crypto_pwhash_scryptsalsa208sha256(
158 key, sizeof(key), passkey, sizeof(passkey), salt, 217 key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES,
218 crypto_box_KEYBYTES, passkey, sizeof(passkey), salt,
159 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ 219 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
160 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { 220 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
161 /* out of memory most likely */ 221 /* out of memory most likely */
@@ -164,13 +224,7 @@ int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase,
164 224
165 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ 225 sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */
166 226
167 /* decrypt the data */ 227 return tox_pass_key_decrypt(data, length, key, out);
168 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out)
169 != decrypt_length) {
170 return -1;
171 }
172
173 return decrypt_length;
174} 228}
175 229
176/* Load the messenger from encrypted data of size length. 230/* Load the messenger from encrypted data of size length.
diff --git a/toxencryptsave/toxencryptsave.h b/toxencryptsave/toxencryptsave.h
index e3f998af..b85d945c 100644
--- a/toxencryptsave/toxencryptsave.h
+++ b/toxencryptsave/toxencryptsave.h
@@ -38,6 +38,8 @@ typedef struct Tox Tox;
38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ 38#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \
39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES) 39 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES)
40 40
41#define TOX_PASS_KEY_LENGTH (crypto_box_KEYBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES)
42
41/* 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
42 * 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
43 * becomes corrupted, the data will be entirely unrecoverable. 45 * becomes corrupted, the data will be entirely unrecoverable.
@@ -47,8 +49,35 @@ typedef struct Tox Tox;
47/* return size of the messenger data (for encrypted saving). */ 49/* return size of the messenger data (for encrypted saving). */
48uint32_t tox_encrypted_size(const Tox *tox); 50uint32_t tox_encrypted_size(const Tox *tox);
49 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
50/* Encrypts the given data with the given passphrase. The output array must be 78/* 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. 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.
52 * 81 *
53 * tox_encrypted_save() is a good example of how to use this function. 82 * tox_encrypted_save() is a good example of how to use this function.
54 * 83 *