summaryrefslogtreecommitdiff
path: root/toxencryptsave/toxencryptsave.c
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-09-13 21:29:33 -0400
committerirungentoo <irungentoo@gmail.com>2014-09-13 21:29:33 -0400
commitcbb526e83fcb0a1dd73228c8765ef29491caff2a (patch)
tree768dc51ba8057ccf806130fc5cdab1d6548a73a6 /toxencryptsave/toxencryptsave.c
parented7bed6b59134b074db1586866cb1ef57ce1ba54 (diff)
parenteb58cdc9645e2209d2e6597732aa238953f7df9b (diff)
Merge branch 'encrypted_data' of https://github.com/dubslow/toxcore
Diffstat (limited to 'toxencryptsave/toxencryptsave.c')
-rw-r--r--toxencryptsave/toxencryptsave.c174
1 files changed, 174 insertions, 0 deletions
diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c
new file mode 100644
index 00000000..89c47a03
--- /dev/null
+++ b/toxencryptsave/toxencryptsave.c
@@ -0,0 +1,174 @@
1/* toxencryptsave.c
2 *
3 * The Tox encrypted save functions.
4 *
5 * Copyright (C) 2013 Tox project All Rights Reserved.
6 *
7 * This file is part of Tox.
8 *
9 * Tox is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * Tox is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include "toxencryptsave.h"
29#include "../toxcore/crypto_core.h"
30
31#ifdef VANILLA_NACL
32#include "crypto_pwhash_scryptsalsa208sha256/crypto_pwhash_scryptsalsa208sha256.h"
33#include "crypto_pwhash_scryptsalsa208sha256/utils.h" /* sodium_memzero */
34#endif
35
36/* This "module" provides functions analogous to tox_load and tox_save in toxcore
37 * Clients should consider alerting their users that, unlike plain data, if even one bit
38 * becomes corrupted, the data will be entirely unrecoverable.
39 * Ditto if they forget their password, there is no way to recover the data.
40 */
41
42/* return size of the messenger data (for encrypted saving). */
43uint32_t tox_encrypted_size(const Tox *tox)
44{
45 return tox_size(tox) + crypto_box_MACBYTES + crypto_box_NONCEBYTES
46 + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH;
47}
48
49/* Save the messenger data encrypted with the given password.
50 * data must be at least tox_encrypted_size().
51 *
52 * returns 0 on success
53 * returns -1 on failure
54 */
55int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength)
56{
57 if (pplength == 0)
58 return -1;
59
60 /* First derive a key from the password */
61 /* http://doc.libsodium.org/key_derivation/README.html */
62 /* note that, according to the documentation, a generic pwhash interface will be created
63 * once the pwhash competition (https://password-hashing.net/) is over */
64 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
65 uint8_t key[crypto_box_KEYBYTES];
66 randombytes(salt, sizeof salt);
67
68 if (crypto_pwhash_scryptsalsa208sha256(
69 key, sizeof(key), passphrase, pplength, salt,
70 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
71 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
72 /* out of memory most likely */
73 return -1;
74 }
75
76 /* calling sodium_memzero segfaults, but printing passphrase works, so... libsodium bug?
77 * ...eh, it's not segfaulting anywhere else, so I'll assume pebkac...
78 sodium_memzero(passphrase, pplength); /* wipe plaintext pw */
79
80 /* next get plain save data */
81 uint32_t temp_size = tox_size(tox);
82 uint8_t temp_data[temp_size];
83 tox_save(tox, temp_data);
84
85 /* the output data consists of, in order:
86 * magic number, salt, nonce, mac, enc_data
87 * where the mac is automatically prepended by the encrypt()
88 * the magic+salt+nonce is called the prefix
89 * I'm not sure what else I'm supposed to do with the salt and nonce, since we
90 * need them to decrypt the data
91 */
92
93 /* first add the prefix */
94 uint8_t nonce[crypto_box_NONCEBYTES];
95 random_nonce(nonce);
96
97 memcpy(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH);
98 data += TOX_ENC_SAVE_MAGIC_LENGTH;
99 memcpy(data, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
100 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
101 memcpy(data, nonce, crypto_box_NONCEBYTES);
102 data += crypto_box_NONCEBYTES;
103
104 /* now encrypt */
105 if (encrypt_data_symmetric(key, nonce, temp_data, temp_size, data)
106 != temp_size + crypto_box_MACBYTES) {
107 return -1;
108 }
109
110 return 0;
111}
112
113/* Load the messenger from encrypted data of size length.
114 *
115 * returns 0 on success
116 * returns -1 on failure
117 */
118int tox_encrypted_load(Tox *tox, const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength)
119{
120 if (length <= crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES +
121 TOX_ENC_SAVE_MAGIC_LENGTH)
122 return -1;
123
124 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0)
125 return -1;
126
127 data += TOX_ENC_SAVE_MAGIC_LENGTH;
128
129 uint32_t decrypt_length = length - crypto_box_MACBYTES - crypto_box_NONCEBYTES
130 - crypto_pwhash_scryptsalsa208sha256_SALTBYTES - TOX_ENC_SAVE_MAGIC_LENGTH;
131 uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
132 uint8_t nonce[crypto_box_NONCEBYTES];
133
134 memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES);
135 data += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
136 memcpy(nonce, data, crypto_box_NONCEBYTES);
137 data += crypto_box_NONCEBYTES;
138
139 /* derive the key */
140 uint8_t key[crypto_box_KEYBYTES];
141
142 if (crypto_pwhash_scryptsalsa208sha256(
143 key, sizeof(key), passphrase, pplength, salt,
144 crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */
145 crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) {
146 /* out of memory most likely */
147 return -1;
148 }
149
150 /* sodium_memzero(passphrase, pplength); /* wipe plaintext pw */
151
152 /* decrypt the data */
153 uint8_t temp_data[decrypt_length];
154
155 if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, temp_data)
156 != decrypt_length) {
157 return -1;
158 }
159
160 return tox_load(tox, temp_data, decrypt_length);
161}
162
163/* Determines whether or not the given data is encrypted (by checking the magic number)
164 *
165 * returns 1 if it is encrypted
166 * returns 0 otherwise
167 */
168int tox_is_data_encrypted(const uint8_t *data)
169{
170 if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0)
171 return 1;
172 else
173 return 0;
174}