talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit f7b5405defb3f1a4b124253a10c8cfe0e6aabeba
parent a451a77a45d751008a663d3b5f08381a38654917
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Fri, 20 May 2016 11:38:32 +0200

Moved getting random bytes into a separate get_random_bytes() function.

Diffstat:
Msrc/common/utils.c | 54++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/common/utils.h | 2++
Msrc/password.c | 128++++---------------------------------------------------------------------------
3 files changed, 61 insertions(+), 123 deletions(-)

diff --git a/src/common/utils.c b/src/common/utils.c @@ -5408,3 +5408,57 @@ g_utf8_substring (const gchar *str, return out; } #endif + +/* Attempts to read count bytes from a PRNG into memory area starting at buf. + * It is up to the caller to make sure there is at least count bytes + * available at buf. */ +gboolean +get_random_bytes(void *buf, size_t count) +{ + /* Open our prng source. */ +#if defined G_OS_WIN32 + HCRYPTPROV rnd; + + if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) && + !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { + debug_print("Could not acquire a CSP handle.\n"); + return FALSE; + } +#else + int rnd; + ssize_t ret; + + rnd = open("/dev/urandom", O_RDONLY); + if (rnd == -1) { + perror("open on /dev/urandom"); + debug_print("Could not open /dev/urandom.\n"); + return FALSE; + } +#endif + + /* Read data from the source into buf. */ +#if defined G_OS_WIN32 + if (!CryptGenRandom(rnd, count, buf)) { + debug_print("Could not read %d random bytes.\n", count); + CryptReleaseContext(rnd, 0); + return FALSE; + } +#else + ret = read(rnd, buf, count); + if (ret != count) { + perror("read from /dev/urandom"); + debug_print("Could not read enough data from /dev/urandom, read only %ld of %lu bytes.\n", ret, count); + close(rnd); + return FALSE; + } +#endif + + /* Close the prng source. */ +#if defined G_OS_WIN32 + CryptReleaseContext(rnd, 0); +#else + close(rnd); +#endif + + return TRUE; +} diff --git a/src/common/utils.h b/src/common/utils.h @@ -606,6 +606,8 @@ gchar *g_utf8_substring (const gchar *p, glong end_pos) G_GNUC_MALLOC; #endif +gboolean get_random_bytes(void *buf, size_t count); + #ifdef __cplusplus } #endif diff --git a/src/password.c b/src/password.c @@ -62,50 +62,17 @@ static gchar *_master_passphrase = NULL; static void _generate_salt() { -#if defined G_OS_UNIX - int rnd; -#elif defined G_OS_WIN32 - HCRYPTPROV rnd; -#endif - gint ret; guchar salt[KD_SALT_LENGTH]; if (prefs_common_get_prefs()->master_passphrase_salt != NULL) { g_free(prefs_common_get_prefs()->master_passphrase_salt); } - /* Prepare our source of random data. */ -#if defined G_OS_UNIX - rnd = open("/dev/urandom", O_RDONLY); - if (rnd == -1) { - perror("fopen on /dev/urandom"); -#elif defined G_OS_WIN32 - if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) && - !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { - debug_print("Could not acquire a CSP handle.\n"); -#endif + if (!get_random_bytes(salt, KD_SALT_LENGTH)) { + debug_print("Could not get random bytes for kd salt.\n"); return; } -#if defined G_OS_UNIX - ret = read(rnd, salt, KD_SALT_LENGTH); - if (ret != KD_SALT_LENGTH) { - perror("read into salt"); - close(rnd); -#elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, KD_SALT_LENGTH, salt)) { - debug_print("Could not read random data for salt\n"); - CryptReleaseContext(rnd, 0); -#endif - return; - } - -#if defined G_OS_UNIX - close(rnd); -#elif defined G_OS_WIN32 - CryptReleaseContext(rnd, 0); -#endif - prefs_common_get_prefs()->master_passphrase_salt = g_base64_encode(salt, KD_SALT_LENGTH); } @@ -362,11 +329,6 @@ gchar *password_encrypt_gnutls(const gchar *password, gnutls_datum_t key, iv; int keylen, digestlen, blocklen, ret, i; unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output; -#if defined G_OS_UNIX - int rnd; -#elif defined G_OS_WIN32 - HCRYPTPROV rnd; -#endif g_return_val_if_fail(password != NULL, NULL); g_return_val_if_fail(encryption_passphrase != NULL, NULL); @@ -392,33 +354,10 @@ gchar *password_encrypt_gnutls(const gchar *password, memcpy(key.data, &hashbuf, keylen); key.size = keylen; - /* Prepare our source of random data. */ -#if defined G_OS_UNIX - rnd = open("/dev/urandom", O_RDONLY); - if (rnd == -1) { - perror("fopen on /dev/urandom"); -#elif defined G_OS_WIN32 - if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) && - !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { - debug_print("Could not acquire a CSP handle.\n"); -#endif - g_free(key.data); - return NULL; - } - /* Prepare random IV for cipher */ iv.data = malloc(IVLEN); iv.size = IVLEN; -#if defined G_OS_UNIX - ret = read(rnd, iv.data, IVLEN); - if (ret != IVLEN) { - perror("read into iv"); - close(rnd); -#elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, IVLEN, iv.data)) { - debug_print("Could not read random data for IV\n"); - CryptReleaseContext(rnd, 0); -#endif + if (!get_random_bytes(iv.data, IVLEN)) { g_free(key.data); g_free(iv.data); return NULL; @@ -429,11 +368,6 @@ gchar *password_encrypt_gnutls(const gchar *password, if (ret < 0) { g_free(key.data); g_free(iv.data); -#if defined G_OS_UNIX - close(rnd); -#elif defined G_OS_WIN32 - CryptReleaseContext(rnd, 0); -#endif return NULL; } @@ -441,16 +375,7 @@ gchar *password_encrypt_gnutls(const gchar *password, * rest with zero bytes. */ buf = malloc(BUFSIZE + blocklen); memset(buf, 0, BUFSIZE); -#if defined G_OS_UNIX - ret = read(rnd, buf, blocklen); - if (ret != blocklen) { - perror("read into buffer"); - close(rnd); -#elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, blocklen, buf)) { - debug_print("Could not read random data for IV\n"); - CryptReleaseContext(rnd, 0); -#endif + if (!get_random_bytes(buf, blocklen)) { g_free(buf); g_free(key.data); g_free(iv.data); @@ -458,13 +383,6 @@ gchar *password_encrypt_gnutls(const gchar *password, return NULL; } - /* We don't need any more random data. */ -#if defined G_OS_UNIX - close(rnd); -#elif defined G_OS_WIN32 - CryptReleaseContext(rnd, 0); -#endif - memcpy(buf + blocklen, password, strlen(password)); /* Encrypt into encbuf */ @@ -508,11 +426,6 @@ gchar *password_decrypt_gnutls(const gchar *password, int keylen, digestlen, blocklen, ret, i; gsize len; unsigned char hashbuf[BUFSIZE], *buf; -#if defined G_OS_UNIX - int rnd; -#elif defined G_OS_WIN32 - HCRYPTPROV rnd; -#endif g_return_val_if_fail(password != NULL, NULL); g_return_val_if_fail(decryption_passphrase != NULL, NULL); @@ -564,47 +477,16 @@ gchar *password_decrypt_gnutls(const gchar *password, memcpy(key.data, &hashbuf, keylen); key.size = keylen; - /* Prepare our source of random data. */ -#if defined G_OS_UNIX - rnd = open("/dev/urandom", O_RDONLY); - if (rnd == -1) { - perror("fopen on /dev/urandom"); -#elif defined G_OS_WIN32 - if (!CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, 0) && - !CryptAcquireContext(&rnd, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) { - debug_print("Could not acquire a CSP handle.\n"); -#endif - g_free(key.data); - g_strfreev(tokens); - return NULL; - } - /* Prepare random IV for cipher */ iv.data = malloc(IVLEN); iv.size = IVLEN; -#if defined G_OS_UNIX - ret = read(rnd, iv.data, IVLEN); - if (ret != IVLEN) { - perror("read into iv"); - close(rnd); -#elif defined G_OS_WIN32 - if (!CryptGenRandom(rnd, IVLEN, iv.data)) { - debug_print("Could not read random data for IV\n"); - CryptReleaseContext(rnd, 0); -#endif + if (!get_random_bytes(iv.data, IVLEN)) { g_free(key.data); g_free(iv.data); g_strfreev(tokens); return NULL; } - /* We don't need any more random data. */ -#if defined G_OS_UNIX - close(rnd); -#elif defined G_OS_WIN32 - CryptReleaseContext(rnd, 0); -#endif - /* Prepare encrypted password string for decryption. */ tmp = g_base64_decode(tokens[2], &len); g_strfreev(tokens);