From e998aca8f75e46cd360210ac588ee77af0106c6d Mon Sep 17 00:00:00 2001 From: Dubslow Date: Tue, 31 Mar 2015 18:15:59 -0500 Subject: Fix toxencryptsave to be consistent with new_api Upon my own decision, the two tox_encryped_new convenience functions were removed due to basically needing two different sets of error codes. At iphydf's suggestion the corresponding tox_get_encrypted_savedata convenience functions were removed as well. --- toxencryptsave/toxencryptsave.c | 235 +++++++++++++++------------------------- 1 file changed, 87 insertions(+), 148 deletions(-) (limited to 'toxencryptsave/toxencryptsave.c') diff --git a/toxencryptsave/toxencryptsave.c b/toxencryptsave/toxencryptsave.c index 874f0fd0..e7ec31f1 100644 --- a/toxencryptsave/toxencryptsave.c +++ b/toxencryptsave/toxencryptsave.c @@ -37,81 +37,68 @@ #include #endif -#define TOX_PASS_ENCRYPTION_EXTRA_LENGTH (crypto_box_MACBYTES + crypto_box_NONCEBYTES \ - + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) - -#define TOX_PASS_KEY_LENGTH (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) - -int tox_pass_encryption_extra_length() -{ - return TOX_PASS_ENCRYPTION_EXTRA_LENGTH; -} +#if TOX_PASS_SALT_LENGTH != crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#error TOX_PASS_SALT_LENGTH is assumed to be equal to crypto_pwhash_scryptsalsa208sha256_SALTBYTES +#endif -int tox_pass_key_length() -{ - return TOX_PASS_KEY_LENGTH; -} +#if TOX_PASS_KEY_LENGTH != (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) +#error TOX_PASS_KEY_LENGTH is assumed to be equal to (crypto_pwhash_scryptsalsa208sha256_SALTBYTES + crypto_box_KEYBYTES) +#endif -int tox_pass_salt_length() -{ - return crypto_pwhash_scryptsalsa208sha256_SALTBYTES; -} +#if TOX_PASS_ENCRYPTION_EXTRA_LENGTH != (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) +#error TOX_PASS_ENCRYPTION_EXTRA_LENGTH is assumed to be equal to (crypto_box_MACBYTES + crypto_box_NONCEBYTES + crypto_pwhash_scryptsalsa208sha256_SALTBYTES + TOX_ENC_SAVE_MAGIC_LENGTH) +#endif -/* This "module" provides functions analogous to tox_load and tox_save in toxcore - * Clients should consider alerting their users that, unlike plain data, if even one bit +/* Clients should consider alerting their users that, unlike plain data, if even one bit * becomes corrupted, the data will be entirely unrecoverable. * Ditto if they forget their password, there is no way to recover the data. */ -/* return size of the messenger data (for encrypted saving). */ -uint32_t tox_encrypted_size(const Tox *tox) -{ - return tox_get_savedata_size(tox) + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; -} - /* This retrieves the salt used to encrypt the given data, which can then be passed to * derive_key_with_salt to produce the same key as was previously used. Any encrpyted * data with this module can be used as input. * - * returns -1 if the magic number is wrong - * returns 0 otherwise (no guarantee about validity of data) + * returns true if magic number matches + * success does not say anything about the validity of the data, only that data of + * the appropriate size was copied */ -int tox_get_salt(uint8_t *data, uint8_t *salt) +bool tox_get_salt(const uint8_t *data, uint8_t *salt) { if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) - return -1; + return 0; data += TOX_ENC_SAVE_MAGIC_LENGTH; memcpy(salt, data, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); - return 0; + return 1; } /* Generates a secret symmetric key from the given passphrase. out_key must be at least * TOX_PASS_KEY_LENGTH bytes long. * Be sure to not compromise the key! Only keep it in memory, do not write to disk. - * This function is fairly cheap, but irungentoo insists that you be allowed to - * cache the result if you want, to minimize computation for repeated encryptions. * The password is zeroed after key derivation. * The key should only be used with the other functions in this module, as it * includes a salt. + * Note that this function is not deterministic; to derive the same key from a + * password, you also must know the random salt that was used. See below. * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_derive_key_from_pass(uint8_t *passphrase, uint32_t pplength, uint8_t *out_key) +bool tox_derive_key_from_pass(uint8_t *passphrase, size_t pplength, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) { uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; randombytes(salt, sizeof salt); - return tox_derive_key_with_salt(passphrase, pplength, salt, out_key); + return tox_derive_key_with_salt(passphrase, pplength, salt, out_key, error); } /* Same as above, except with use the given salt for deterministic key derivation. * The salt must be tox_salt_length() bytes in length. */ -int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *salt, uint8_t *out_key) +bool tox_derive_key_with_salt(uint8_t *passphrase, size_t pplength, uint8_t *salt, uint8_t *out_key, TOX_ERR_KEY_DERIVATION *error) { - if (pplength == 0) - return -1; + if (pplength == 0 || !passphrase || !salt || !out_key) { + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_NULL); + return 0; + } uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); @@ -127,27 +114,32 @@ int tox_derive_key_with_salt(uint8_t *passphrase, uint32_t pplength, uint8_t *sa crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_FAILED); + return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ memcpy(out_key, salt, crypto_pwhash_scryptsalsa208sha256_SALTBYTES); memcpy(out_key + crypto_pwhash_scryptsalsa208sha256_SALTBYTES, key, crypto_box_KEYBYTES); - return 0; + SET_ERROR_PARAMETER(error, TOX_ERR_KEY_DERIVATION_OK); + return 1; } -/* Encrypt arbitrary with a key produced by tox_derive_key_from_pass. The output +/* Encrypt arbitrary with a key produced by tox_derive_key_*. The output * array must be at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. * key must be TOX_PASS_KEY_LENGTH bytes. * If you already have a symmetric key from somewhere besides this module, simply * call encrypt_data_symmetric in toxcore/crypto_core directly. * - * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t *key, uint8_t *out) +bool tox_pass_key_encrypt(const uint8_t *data, size_t data_len, const uint8_t *key, uint8_t *out, TOX_ERR_ENCRYPTION *error) { + if (data_len == 0 || !data || !key || !out) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + return 0; + } + /* the output data consists of, in order: * salt, nonce, mac, enc_data * where the mac is automatically prepended by the encrypt() @@ -173,78 +165,58 @@ int tox_pass_key_encrypt(const uint8_t *data, uint32_t data_len, const uint8_t * /* now encrypt */ if (encrypt_data_symmetric(key, nonce, data, data_len, out) != data_len + crypto_box_MACBYTES) { - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_FAILED); + return 0; } - return 0; + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_OK); + return 1; } /* Encrypts the given data with the given passphrase. The output array must be * at least data_len + TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates * to tox_derive_key_from_pass and tox_pass_key_encrypt. * - * returns 0 on success - * returns -1 on failure + * returns true on success */ -int tox_pass_encrypt(const uint8_t *data, uint32_t data_len, uint8_t *passphrase, uint32_t pplength, uint8_t *out) +bool tox_pass_encrypt(const uint8_t *data, size_t data_len, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_ENCRYPTION *error) { uint8_t key[TOX_PASS_KEY_LENGTH]; + TOX_ERR_KEY_DERIVATION _error; + + if (!tox_derive_key_from_pass(passphrase, pplength, key, &_error)) { + if (_error == TOX_ERR_KEY_DERIVATION_NULL) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_NULL); + } else if (_error == TOX_ERR_KEY_DERIVATION_FAILED) { + SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTION_KEY_DERIVATION_FAILED); + } + return 0; + } - if (tox_derive_key_from_pass(passphrase, pplength, key) == -1) - return -1; - - return tox_pass_key_encrypt(data, data_len, key, out); -} - -/* Save the messenger data encrypted with the given password. - * data must be at least tox_encrypted_size(). - * - * returns 0 on success - * returns -1 on failure - */ -int tox_encrypted_save(const Tox *tox, uint8_t *data, uint8_t *passphrase, uint32_t pplength) -{ - /* first get plain save data */ - uint32_t temp_size = tox_get_savedata_size(tox); - uint8_t temp_data[temp_size]; - tox_get_savedata(tox, temp_data); - - /* now encrypt */ - return tox_pass_encrypt(temp_data, temp_size, passphrase, pplength, data); -} - -/* Save the messenger data encrypted with the given key from tox_derive_key. - * data must be at least tox_encrypted_size(). - * - * returns 0 on success - * returns -1 on failure - */ -int tox_encrypted_key_save(const Tox *tox, uint8_t *data, uint8_t *key) -{ - /* first get plain save data */ - uint32_t temp_size = tox_get_savedata_size(tox); - uint8_t temp_data[temp_size]; - tox_get_savedata(tox, temp_data); - - /* encrypt */ - return tox_pass_key_encrypt(temp_data, temp_size, key, data); + return tox_pass_key_encrypt(data, data_len, key, out, error); } /* This is the inverse of tox_pass_key_encrypt, also using only keys produced by * tox_derive_key_from_pass. * - * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success - * returns -1 on failure + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH + * + * returns true on success */ -int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *key, uint8_t *out) +bool tox_pass_key_decrypt(const uint8_t *data, size_t length, const uint8_t *key, uint8_t *out, TOX_ERR_DECRYPTION *error) { - if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH - || 0 != memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH)) - return -1; + if (length <= TOX_PASS_ENCRYPTION_EXTRA_LENGTH) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_INVALID_LENGTH); + return 0; + } + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } data += TOX_ENC_SAVE_MAGIC_LENGTH; - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; + size_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; //uint8_t salt[crypto_pwhash_scryptsalsa208sha256_SALTBYTES]; uint8_t nonce[crypto_box_NONCEBYTES]; @@ -257,20 +229,29 @@ int tox_pass_key_decrypt(const uint8_t *data, uint32_t length, const uint8_t *ke /* decrypt the data */ if (decrypt_data_symmetric(key, nonce, data, decrypt_length + crypto_box_MACBYTES, out) != decrypt_length) { - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_FAILED); + return 0; } - return decrypt_length; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_OK); + return 1; } /* Decrypts the given data with the given passphrase. The output array must be - * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. + * at least data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH bytes long. This delegates + * to tox_pass_key_decrypt. + * + * the output data has size data_length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH * - * returns the length of the output data (== data_len - TOX_PASS_ENCRYPTION_EXTRA_LENGTH) on success - * returns -1 on failure + * returns true on success */ -int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, uint32_t pplength, uint8_t *out) +bool tox_pass_decrypt(const uint8_t *data, size_t length, uint8_t *passphrase, size_t pplength, uint8_t *out, TOX_ERR_DECRYPTION *error) { + if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) != 0) { + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_BAD_FORMAT); + return 0; + } + uint8_t passkey[crypto_hash_sha256_BYTES]; crypto_hash_sha256(passkey, passphrase, pplength); @@ -286,60 +267,18 @@ int tox_pass_decrypt(const uint8_t *data, uint32_t length, uint8_t *passphrase, crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 2, /* slightly stronger */ crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE) != 0) { /* out of memory most likely */ - return -1; + SET_ERROR_PARAMETER(error, TOX_ERR_DECRYPTION_KEY_DERIVATION_FAILED); + return 0; } sodium_memzero(passkey, crypto_hash_sha256_BYTES); /* wipe plaintext pw */ - return tox_pass_key_decrypt(data, length, key, out); -} - -/* Load the new messenger from encrypted data of size length. - * All other arguments are like toxcore/tox_new(). - * - * returns NULL on failure; see the documentation in toxcore/tox.h. - */ -Tox *tox_encrypted_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *passphrase, - size_t pplength, TOX_ERR_ENCRYPTED_NEW *error) -{ - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; - uint8_t temp_data[decrypt_length]; - - if (tox_pass_decrypt(data, length, passphrase, pplength, temp_data) - != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); - return NULL; - } - - return tox_new(options, temp_data, decrypt_length, error); -} - -/* Load the messenger from encrypted data of size length, with key from tox_derive_key. - * All other arguments are like toxcore/tox_new(). - * - * returns NULL on failure; see the documentation in toxcore/tox.h. - */ -Tox *tox_encrypted_key_new(const struct Tox_Options *options, const uint8_t *data, size_t length, uint8_t *key, - TOX_ERR_ENCRYPTED_NEW *error) -{ - uint32_t decrypt_length = length - TOX_PASS_ENCRYPTION_EXTRA_LENGTH; - uint8_t temp_data[decrypt_length]; - - if (tox_pass_key_decrypt(data, length, key, temp_data) - != decrypt_length) { - SET_ERROR_PARAMETER(error, TOX_ERR_ENCRYPTED_NEW_LOAD_DECRYPTION_FAILED); - return NULL; - } - - return tox_new(options, temp_data, decrypt_length, error); + return tox_pass_key_decrypt(data, length, key, out, error); } /* Determines whether or not the given data is encrypted (by checking the magic number) - * - * returns 1 if it is encrypted - * returns 0 otherwise */ -int tox_is_data_encrypted(const uint8_t *data) +bool tox_is_data_encrypted(const uint8_t *data) { if (memcmp(data, TOX_ENC_SAVE_MAGIC_NUMBER, TOX_ENC_SAVE_MAGIC_LENGTH) == 0) return 1; -- cgit v1.2.3