Moved getting random bytes into a separate get_random_bytes() function.
authorAndrej Kacian <ticho@claws-mail.org>
Fri, 20 May 2016 09:38:32 +0000 (11:38 +0200)
committerAndrej Kacian <ticho@claws-mail.org>
Fri, 20 May 2016 10:30:57 +0000 (12:30 +0200)
src/common/utils.c
src/common/utils.h
src/password.c

index 236a924a118daf330b8a0f03eccacd82b63478ef..eb41d5cf6c2b1959b547d44f2caad5524a18e203 100644 (file)
@@ -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;
+}
index 2942135093c10011dca85be8ecf038fa10f8b0c0..5f35f737720d952ff1ec807c7c758d1de98fb3e6 100644 (file)
@@ -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
index 6cef02128cff31f11c5072abe5cdbe5c0485c6d7..5a20a5bc831a5c4d9fa30e2bf2e9f2f7afd50e53 100644 (file)
@@ -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);