Skip to content

Commit ddda605

Browse files
committed
fix: Don't crash if RNG init failed.
`system_random()` can fail and return NULL, which should be handled by toxencryptsave functions. Also synced function comments between .h and .c file for toxencryptsave.
1 parent 4430515 commit ddda605

File tree

4 files changed

+106
-42
lines changed

4 files changed

+106
-42
lines changed

other/analysis/run-gcc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ run() {
1616
-Wall \
1717
-Wextra \
1818
-Werror \
19-
-Wno-error=null-dereference \
2019
-Wno-error=type-limits \
2120
-Wno-aggressive-loop-optimizations \
2221
-Wno-float-conversion \
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
e1464fd52269f481bd529805f0e81f717c8586b0df93a0767507a6b2b8f3678b /usr/local/bin/tox-bootstrapd
1+
ccc903803f118d6d069f65bb0a1ef95979ab8b374d207e8f13716771d6da9dd8 /usr/local/bin/tox-bootstrapd

toxencryptsave/toxencryptsave.c

Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,24 @@ void tox_pass_key_free(Tox_Pass_Key *key)
6060
* Ditto if they forget their password, there is no way to recover the data.
6161
*/
6262

63-
/* This retrieves the salt used to encrypt the given data, which can then be passed to
64-
* tox_pass_key_derive_with_salt to produce the same key as was previously used. Any encrpyted
65-
* data with this module can be used as input.
63+
/**
64+
* Retrieves the salt used to encrypt the given data.
65+
*
66+
* The retrieved salt can then be passed to tox_pass_key_derive_with_salt to
67+
* produce the same key as was previously used. Any data encrypted with this
68+
* module can be used as input.
69+
*
70+
* The cipher text must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
71+
* The salt must be TOX_PASS_SALT_LENGTH bytes in length.
72+
* If the passed byte arrays are smaller than required, the behaviour is
73+
* undefined.
74+
*
75+
* If the cipher text pointer or the salt is NULL, this function returns false.
76+
*
77+
* Success does not say anything about the validity of the data, only that
78+
* data of the appropriate size was copied.
6679
*
67-
* returns true if magic number matches
68-
* success does not say anything about the validity of the data, only that data of
69-
* the appropriate size was copied
80+
* @return true on success.
7081
*/
7182
bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *error)
7283
{
@@ -86,27 +97,44 @@ bool tox_get_salt(const uint8_t *ciphertext, uint8_t *salt, Tox_Err_Get_Salt *er
8697
return true;
8798
}
8899

89-
/* Generates a secret symmetric key from the given passphrase. out_key must be at least
90-
* TOX_PASS_KEY_LENGTH bytes long.
91-
* Be sure to not compromise the key! Only keep it in memory, do not write to disk.
92-
* The password is zeroed after key derivation.
93-
* The key should only be used with the other functions in this module, as it
94-
* includes a salt.
95-
* Note that this function is not deterministic; to derive the same key from a
96-
* password, you also must know the random salt that was used. See below.
100+
/**
101+
* Generates a secret symmetric key from the given passphrase.
102+
*
103+
* Be sure to not compromise the key! Only keep it in memory, do not write
104+
* it to disk.
105+
*
106+
* Note that this function is not deterministic; to derive the same key from
107+
* a password, you also must know the random salt that was used. A
108+
* deterministic version of this function is `tox_pass_key_derive_with_salt`.
109+
*
110+
* @param passphrase The user-provided password. Can be empty.
111+
* @param passphrase_len The length of the password.
97112
*
98-
* returns true on success
113+
* @return new symmetric key on success, NULL on failure.
99114
*/
100115
Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len,
101116
Tox_Err_Key_Derivation *error)
102117
{
118+
const Random *rng = system_random();
119+
120+
if (rng == nullptr) {
121+
SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED);
122+
return nullptr;
123+
}
124+
103125
uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES];
104-
random_bytes(system_random(), salt, sizeof(salt));
126+
random_bytes(rng, salt, sizeof(salt));
105127
return tox_pass_key_derive_with_salt(passphrase, passphrase_len, salt, error);
106128
}
107129

108-
/* Same as above, except with use the given salt for deterministic key derivation.
109-
* The salt must be TOX_PASS_SALT_LENGTH bytes in length.
130+
/**
131+
* Same as above, except use the given salt for deterministic key derivation.
132+
*
133+
* @param passphrase The user-provided password. Can be empty.
134+
* @param passphrase_len The length of the password.
135+
* @param salt An array of at least TOX_PASS_SALT_LENGTH bytes.
136+
*
137+
* @return new symmetric key on success, NULL on failure.
110138
*/
111139
Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len,
112140
const uint8_t *salt, Tox_Err_Key_Derivation *error)
@@ -164,6 +192,13 @@ Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t pa
164192
bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len,
165193
uint8_t *ciphertext, Tox_Err_Encryption *error)
166194
{
195+
const Random *rng = system_random();
196+
197+
if (rng == nullptr) {
198+
SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED);
199+
return false;
200+
}
201+
167202
if (plaintext_len == 0 || plaintext == nullptr || key == nullptr || ciphertext == nullptr) {
168203
SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL);
169204
return false;
@@ -185,7 +220,7 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, siz
185220
ciphertext += crypto_pwhash_scryptsalsa208sha256_SALTBYTES;
186221

187222
uint8_t nonce[crypto_box_NONCEBYTES];
188-
random_nonce(system_random(), nonce);
223+
random_nonce(rng, nonce);
189224
memcpy(ciphertext, nonce, crypto_box_NONCEBYTES);
190225
ciphertext += crypto_box_NONCEBYTES;
191226

@@ -200,11 +235,20 @@ bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, siz
200235
return true;
201236
}
202237

203-
/* Encrypts the given data with the given passphrase. The output array must be
204-
* at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
205-
* to tox_derive_key and tox_pass_key_encrypt.
238+
/**
239+
* Encrypts the given data with the given passphrase.
240+
*
241+
* The output array must be at least `plaintext_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
242+
* bytes long. This delegates to tox_pass_key_derive and
243+
* tox_pass_key_encrypt.
206244
*
207-
* returns true on success
245+
* @param plaintext A byte array of length `plaintext_len`.
246+
* @param plaintext_len The length of the plain text array. Bigger than 0.
247+
* @param passphrase The user-provided password. Can be empty.
248+
* @param passphrase_len The length of the password.
249+
* @param ciphertext The cipher text array to write the encrypted data to.
250+
*
251+
* @return true on success.
208252
*/
209253
bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint8_t *passphrase, size_t passphrase_len,
210254
uint8_t *ciphertext, Tox_Err_Encryption *error)
@@ -227,12 +271,15 @@ bool tox_pass_encrypt(const uint8_t *plaintext, size_t plaintext_len, const uint
227271
return result;
228272
}
229273

230-
/* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
231-
* tox_derive_key.
274+
/**
275+
* This is the inverse of tox_pass_key_encrypt, also using only keys produced by
276+
* tox_pass_key_derive or tox_pass_key_derive_with_salt.
232277
*
233-
* the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
278+
* @param ciphertext A byte array of length `ciphertext_len`.
279+
* @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
280+
* @param plaintext The plain text array to write the decrypted data to.
234281
*
235-
* returns true on success
282+
* @return true on success.
236283
*/
237284
bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len,
238285
uint8_t *plaintext, Tox_Err_Decryption *error)
@@ -272,13 +319,19 @@ bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, si
272319
return true;
273320
}
274321

275-
/* Decrypts the given data with the given passphrase. The output array must be
276-
* at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates
277-
* to tox_pass_key_decrypt.
322+
/**
323+
* Decrypts the given data with the given passphrase.
278324
*
279-
* the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH
325+
* The output array must be at least `ciphertext_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH`
326+
* bytes long. This delegates to tox_pass_key_decrypt.
280327
*
281-
* returns true on success
328+
* @param ciphertext A byte array of length `ciphertext_len`.
329+
* @param ciphertext_len The length of the cipher text array. At least TOX_PASS_ENCRYPTION_EXTRA_LENGTH.
330+
* @param passphrase The user-provided password. Can be empty.
331+
* @param passphrase_len The length of the password.
332+
* @param plaintext The plain text array to write the decrypted data to.
333+
*
334+
* @return true on success.
282335
*/
283336
bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const uint8_t *passphrase,
284337
size_t passphrase_len, uint8_t *plaintext, Tox_Err_Decryption *error)
@@ -315,7 +368,19 @@ bool tox_pass_decrypt(const uint8_t *ciphertext, size_t ciphertext_len, const ui
315368
return result;
316369
}
317370

318-
/* Determines whether or not the given data is encrypted (by checking the magic number)
371+
/**
372+
* Determines whether or not the given data is encrypted by this module.
373+
*
374+
* It does this check by verifying that the magic number is the one put in
375+
* place by the encryption functions.
376+
*
377+
* The data must be at least TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes in length.
378+
* If the passed byte array is smaller than required, the behaviour is
379+
* undefined.
380+
*
381+
* If the data pointer is NULL, the behaviour is undefined
382+
*
383+
* @return true if the data is encrypted by this module.
319384
*/
320385
bool tox_is_data_encrypted(const uint8_t *data)
321386
{

toxencryptsave/toxencryptsave.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ typedef struct Tox_Pass_Key Tox_Pass_Key;
238238
* Deallocate a Tox_Pass_Key. This function behaves like `free()`, so NULL is an
239239
* acceptable argument value.
240240
*/
241-
void tox_pass_key_free(struct Tox_Pass_Key *key);
241+
void tox_pass_key_free(Tox_Pass_Key *key);
242242

243243
/**
244244
* Generates a secret symmetric key from the given passphrase.
@@ -253,9 +253,9 @@ void tox_pass_key_free(struct Tox_Pass_Key *key);
253253
* @param passphrase The user-provided password. Can be empty.
254254
* @param passphrase_len The length of the password.
255255
*
256-
* @return true on success.
256+
* @return new symmetric key on success, NULL on failure.
257257
*/
258-
struct Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len,
258+
Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passphrase_len,
259259
Tox_Err_Key_Derivation *error);
260260

261261
/**
@@ -265,9 +265,9 @@ struct Tox_Pass_Key *tox_pass_key_derive(const uint8_t *passphrase, size_t passp
265265
* @param passphrase_len The length of the password.
266266
* @param salt An array of at least TOX_PASS_SALT_LENGTH bytes.
267267
*
268-
* @return true on success.
268+
* @return new symmetric key on success, NULL on failure.
269269
*/
270-
struct Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len,
270+
Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, size_t passphrase_len,
271271
const uint8_t *salt, Tox_Err_Key_Derivation *error);
272272

273273
/**
@@ -282,7 +282,7 @@ struct Tox_Pass_Key *tox_pass_key_derive_with_salt(const uint8_t *passphrase, si
282282
*
283283
* @return true on success.
284284
*/
285-
bool tox_pass_key_encrypt(const struct Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len,
285+
bool tox_pass_key_encrypt(const Tox_Pass_Key *key, const uint8_t *plaintext, size_t plaintext_len,
286286
uint8_t *ciphertext, Tox_Err_Encryption *error);
287287

288288
/**
@@ -295,7 +295,7 @@ bool tox_pass_key_encrypt(const struct Tox_Pass_Key *key, const uint8_t *plainte
295295
*
296296
* @return true on success.
297297
*/
298-
bool tox_pass_key_decrypt(const struct Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len,
298+
bool tox_pass_key_decrypt(const Tox_Pass_Key *key, const uint8_t *ciphertext, size_t ciphertext_len,
299299
uint8_t *plaintext, Tox_Err_Decryption *error);
300300

301301
typedef enum Tox_Err_Get_Salt {

0 commit comments

Comments
 (0)