talons

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

commit 5805ff8180e298a04a4c99ab57374cf87e273c11
parent dc1debf5645c552a1cd9c6be5313e0ed8b797d28
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Thu, 14 Dec 2017 23:18:50 +0100

Fix buffer length handling in GnuTLS password encryption and decryption.

Also zero out one forgotten copy of plaintext password
before freeing it. Oops!

Diffstat:
Msrc/password.c | 18+++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/src/password.c b/src/password.c @@ -356,7 +356,7 @@ gchar *password_encrypt_gnutls(const gchar *password, /* Fill buf with one block of random data, our password, pad the * rest with zero bytes. */ buf = malloc(BUFSIZE + blocklen); - memset(buf, 0, BUFSIZE); + memset(buf, 0, BUFSIZE + blocklen); if (!get_random_bytes(buf, blocklen)) { g_free(buf); g_free(key.data); @@ -389,7 +389,7 @@ gchar *password_encrypt_gnutls(const gchar *password, /* And finally prepare the resulting string: * "{algorithm,rounds}base64encodedciphertext" */ - base = g_base64_encode(encbuf, BUFSIZE); + base = g_base64_encode(encbuf, BUFSIZE + blocklen); g_free(encbuf); output = g_strdup_printf("{%s,%d}%s", gnutls_cipher_get_name(algo), rounds, base); @@ -479,6 +479,7 @@ gchar *password_decrypt_gnutls(const gchar *password, g_free(tmp); return NULL; } + debug_print("Encrypted password string length: %lu\n", len); /* Initialize the decryption */ ret = gnutls_cipher_init(&handle, algo, &key, &iv); @@ -490,10 +491,13 @@ gchar *password_decrypt_gnutls(const gchar *password, return NULL; } - buf = malloc(len + blocklen); - memset(buf, 0, len + blocklen); + /* Allocate the buffer to store decrypted plaintext in. */ + buf = malloc(len); + memset(buf, 0, len); + + /* Decrypt! */ ret = gnutls_cipher_decrypt2(handle, tmp, len, - buf, len + blocklen); + buf, len); g_free(tmp); if (ret < 0) { debug_print("Decryption failed: %s\n", gnutls_strerror(ret)); @@ -509,8 +513,12 @@ gchar *password_decrypt_gnutls(const gchar *password, g_free(key.data); g_free(iv.data); + /* '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)); + memset(buf, 0, len); g_free(buf); + return tmp; }