diff options
author | dubslow <bunslow@gmail.com> | 2014-10-09 20:16:05 -0500 |
---|---|---|
committer | dubslow <bunslow@gmail.com> | 2014-10-09 20:18:29 -0500 |
commit | 54fdf3bdd653ebf6e55d2cb93fcae41e68436e11 (patch) | |
tree | d98c9b524ee0dfc507375e0a16051e19a77801b4 /toxencryptsave | |
parent | e6f30694d32a81f9171b2057d9c873cc16f6dca1 (diff) |
re-refactor to separate pass->key and key->encryption
Diffstat (limited to 'toxencryptsave')
-rw-r--r-- | toxencryptsave/toxencryptsave.c | 102 | ||||
-rw-r--r-- | toxencryptsave/toxencryptsave.h | 31 |
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 | */ |
56 | int tox_pass_encrypt(uint8_t* data, uint32_t data_len, uint8_t* passphrase, uint32_t pplength, uint8_t* out) | 62 | int 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 | */ | ||
101 | int 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 | */ | ||
137 | int 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 | */ |
137 | int tox_pass_decrypt(const uint8_t* data, uint32_t length, uint8_t* passphrase, uint32_t pplength, uint8_t* out) | 174 | int 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 | */ | ||
204 | int 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). */ |
48 | uint32_t tox_encrypted_size(const Tox *tox); | 50 | uint32_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 | */ | ||
64 | int 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 | */ | ||
76 | int 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 | * |