[Commits] [SCM] claws branch, master, updated. 3.16.0-193-ga7f0d04
ticho at claws-mail.org
ticho at claws-mail.org
Sun Jun 10 00:53:54 CEST 2018
The branch, master has been updated
via a7f0d049b6a7f1df5fe4e6487ddbb140c22370e0 (commit)
from 0bb007721f5a1fb10b9491fb6c1a7921fc3cec22 (commit)
Summary of changes:
doc/src/password_encryption.txt | 15 ++++++++++++---
src/password.c | 26 +++++++++++++++++---------
2 files changed, 29 insertions(+), 12 deletions(-)
- Log -----------------------------------------------------------------
commit a7f0d049b6a7f1df5fe4e6487ddbb140c22370e0
Author: Andrej Kacian <ticho at claws-mail.org>
Date: Sun Jun 10 00:38:42 2018 +0200
Fix a buffer overflow in password encryption, and allow arbitrary password length.
Fixes bug #4033 - Claws Mail crashes [malloc(): memory
corruption] while trying to save account password greater
than 136 chars
diff --git a/doc/src/password_encryption.txt b/doc/src/password_encryption.txt
index 7746499..f618378 100644
--- a/doc/src/password_encryption.txt
+++ b/doc/src/password_encryption.txt
@@ -12,9 +12,18 @@ IV (initialization vector) for the cipher is filled with random bytes.
Encryption
----------
-We prepare a buffer 128+blocksize bytes long, with one block of random
-data at the beginning, followed by the password we want to encrypt (in
-UTF-8), rest is padded with zero bytes.
+We prepare a buffer long enough to fit the NULL-terminated password string
+plus one cipher block in it, with one block of random data at the beginning,
+followed by the password we want to encrypt (in UTF-8), rest is padded
+with zero bytes.
+
+The minimal buffer size is 128+blocksize, and if the password (including
+the trailing NULL byte) is longer than 128 bytes, the size is increased by
+another 128 bytes until it is long enough to fit the password plus one
+cipher block. This is to make it harder to guess the password length from
+length of the encrypted string. So for example, if the password (again,
+including the trailing NULL byte) is 129 characters long, our buffer will
+be 256+blocksize bytes long.
We encrypt the buffer using the encryption key and IV mentioned above,
resulting in ciphertext of the same length as the buffer.
diff --git a/src/password.c b/src/password.c
index 9e66a92..8f764e3 100644
--- a/src/password.c
+++ b/src/password.c
@@ -319,7 +319,7 @@ gchar *password_encrypt_gnutls(const gchar *password,
gnutls_cipher_algorithm_t algo = GNUTLS_CIPHER_AES_256_CBC;
gnutls_cipher_hd_t handle;
gnutls_datum_t key, iv;
- int keylen, blocklen, ret;
+ int keylen, blocklen, ret, len, i;
unsigned char *buf, *encbuf, *base, *output;
guint rounds = prefs_common_get_prefs()->master_passphrase_pbkdf2_rounds;
@@ -353,10 +353,18 @@ gchar *password_encrypt_gnutls(const gchar *password,
return NULL;
}
+ /* Find out how big buffer (in multiples of BUFSIZE)
+ * we need to store the password. */
+ i = 1;
+ len = strlen(password);
+ while(len >= i * BUFSIZE)
+ i++;
+ len = i * BUFSIZE;
+
/* Fill buf with one block of random data, our password, pad the
* rest with zero bytes. */
- buf = malloc(BUFSIZE + blocklen);
- memset(buf, 0, BUFSIZE + blocklen);
+ buf = malloc(len + blocklen);
+ memset(buf, 0, len + blocklen);
if (!get_random_bytes(buf, blocklen)) {
g_free(buf);
g_free(key.data);
@@ -368,10 +376,10 @@ gchar *password_encrypt_gnutls(const gchar *password,
memcpy(buf + blocklen, password, strlen(password));
/* Encrypt into encbuf */
- encbuf = malloc(BUFSIZE + blocklen);
- memset(encbuf, 0, BUFSIZE + blocklen);
- ret = gnutls_cipher_encrypt2(handle, buf, BUFSIZE + blocklen,
- encbuf, BUFSIZE + blocklen);
+ encbuf = malloc(len + blocklen);
+ memset(encbuf, 0, len + blocklen);
+ ret = gnutls_cipher_encrypt2(handle, buf, len + blocklen,
+ encbuf, len + blocklen);
if (ret < 0) {
g_free(key.data);
g_free(iv.data);
@@ -389,7 +397,7 @@ gchar *password_encrypt_gnutls(const gchar *password,
/* And finally prepare the resulting string:
* "{algorithm,rounds}base64encodedciphertext" */
- base = g_base64_encode(encbuf, BUFSIZE + blocklen);
+ base = g_base64_encode(encbuf, len + blocklen);
g_free(encbuf);
output = g_strdup_printf("{%s,%d}%s",
gnutls_cipher_get_name(algo), rounds, base);
@@ -515,7 +523,7 @@ gchar *password_decrypt_gnutls(const gchar *password,
/* 'buf+blocklen' should now be pointing to the plaintext
* password string. The first block contains random data from the IV. */
- tmp = g_strndup(buf + blocklen, MIN(strlen(buf + blocklen), BUFSIZE));
+ tmp = g_strndup(buf + blocklen, strlen(buf + blocklen));
memset(buf, 0, len);
g_free(buf);
-----------------------------------------------------------------------
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list