Use a hardcoded IV length in password encryption.
[claws.git] / src / password.c
index bda205f..826d316 100644 (file)
@@ -98,8 +98,9 @@ const gboolean master_passphrase_is_set()
 const gboolean master_passphrase_is_correct(const gchar *input)
 {
        gchar *hash;
+       gchar **tokens;
        gchar *stored_hash = prefs_common_get_prefs()->master_passphrase_hash;
-       const GChecksumType hashtype = G_CHECKSUM_SHA512;
+       const GChecksumType hashtype = G_CHECKSUM_SHA256;
        const gssize hashlen = g_checksum_type_get_length(hashtype);
        gssize stored_len;
 
@@ -108,7 +109,16 @@ const gboolean master_passphrase_is_correct(const gchar *input)
        if (stored_hash == NULL)
                return FALSE;
 
-       debug_print("|stored_hash|%s|\n", stored_hash);
+       tokens = g_strsplit_set(stored_hash, "{}", 3);
+       if (strlen(tokens[0]) != 0 ||
+                       strcmp(tokens[1], "SHA-256") ||
+                       strlen(tokens[2]) == 0) {
+               debug_print("Mangled master_passphrase_hash in config, can not use it.\n");
+               g_strfreev(tokens);
+               return FALSE;
+       }
+
+       stored_hash = tokens[2];
        stored_len = strlen(stored_hash);
        g_return_val_if_fail(stored_len == 2*hashlen, FALSE);
 
@@ -116,8 +126,10 @@ const gboolean master_passphrase_is_correct(const gchar *input)
 
        if (!strncasecmp(hash, stored_hash, stored_len)) {
                g_free(hash);
+               g_strfreev(tokens);
                return TRUE;
        }
+       g_strfreev(tokens);
        g_free(hash);
 
        return FALSE;
@@ -135,12 +147,15 @@ void master_passphrase_forget()
        if (_master_passphrase != NULL) {
                memset(_master_passphrase, 0, strlen(_master_passphrase));
                g_free(_master_passphrase);
+               _master_passphrase = NULL;
        }
-       _master_passphrase = NULL;
 }
 
 void master_passphrase_change(const gchar *oldp, const gchar *newp)
 {
+       const GChecksumType hashtype = G_CHECKSUM_SHA256;
+       gchar *hash;
+
        if (oldp == NULL) {
                /* If oldp is NULL, make sure the user has to enter the
                 * current master passphrase before being able to change it. */
@@ -155,8 +170,10 @@ void master_passphrase_change(const gchar *oldp, const gchar *newp)
 
        if (newp != NULL) {
                debug_print("Storing hash of new master passphrase\n");
+               hash = g_compute_checksum_for_string(hashtype, newp, -1);
                prefs_common_get_prefs()->master_passphrase_hash =
-                       g_compute_checksum_for_string(G_CHECKSUM_SHA512, newp, -1);
+                       g_strconcat("{SHA-256}", hash, NULL);
+               g_free(hash);
        } else {
                debug_print("Setting master_passphrase_hash to NULL\n");
                prefs_common_get_prefs()->master_passphrase_hash = NULL;
@@ -221,6 +238,10 @@ gchar *password_decrypt_old(const gchar *password)
 #ifdef PASSWORD_CRYPTO_GNUTLS
 #define BUFSIZE 128
 
+/* Since we can't count on having GnuTLS new enough to have
+ * gnutls_cipher_get_iv_size(), we hardcode the IV length for now. */
+#define IVLEN 16
+
 gchar *password_encrypt_gnutls(const gchar *password,
                const gchar *encryption_passphrase)
 {
@@ -231,7 +252,7 @@ gchar *password_encrypt_gnutls(const gchar *password,
        gnutls_digest_algorithm_t digest = GNUTLS_DIG_SHA512;
        gnutls_cipher_hd_t handle;
        gnutls_datum_t key, iv;
-       int ivlen, keylen, digestlen, blocklen, ret, i;
+       int keylen, digestlen, blocklen, ret, i;
        unsigned char hashbuf[BUFSIZE], *buf, *encbuf, *base, *output;
 #if defined G_OS_UNIX
        int rnd;
@@ -242,7 +263,7 @@ gchar *password_encrypt_gnutls(const gchar *password,
        g_return_val_if_fail(password != NULL, NULL);
        g_return_val_if_fail(encryption_passphrase != NULL, NULL);
 
-       ivlen = gnutls_cipher_get_iv_size(algo);
+/*     ivlen = gnutls_cipher_get_iv_size(algo);*/
        keylen = gnutls_cipher_get_key_size(algo);
        blocklen = gnutls_cipher_get_block_size(algo);
        digestlen = gnutls_hash_get_len(digest);
@@ -279,15 +300,15 @@ gchar *password_encrypt_gnutls(const gchar *password,
        }
 
        /* Prepare random IV for cipher */
-       iv.data = malloc(ivlen);
-       iv.size = ivlen;
+       iv.data = malloc(IVLEN);
+       iv.size = IVLEN;
 #if defined G_OS_UNIX
-       ret = read(rnd, iv.data, ivlen);
-       if (ret != ivlen) {
+       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)) {
+       if (!CryptGenRandom(rnd, IVLEN, iv.data)) {
                debug_print("Could not read random data for IV\n");
                CryptReleaseContext(rnd, 0);
 #endif
@@ -377,7 +398,7 @@ gchar *password_decrypt_gnutls(const gchar *password,
        gnutls_digest_algorithm_t digest = GNUTLS_DIG_UNKNOWN;
        gnutls_cipher_hd_t handle;
        gnutls_datum_t key, iv;
-       int ivlen, keylen, digestlen, blocklen, ret, i;
+       int keylen, digestlen, blocklen, ret, i;
        gsize len;
        unsigned char hashbuf[BUFSIZE], *buf;
 #if defined G_OS_UNIX
@@ -413,7 +434,7 @@ gchar *password_decrypt_gnutls(const gchar *password,
                return NULL;
        }
 
-       ivlen = gnutls_cipher_get_iv_size(algo);
+/*     ivlen = gnutls_cipher_get_iv_size(algo); */
        keylen = gnutls_cipher_get_key_size(algo);
        blocklen = gnutls_cipher_get_block_size(algo);
        digestlen = gnutls_hash_get_len(digest);
@@ -453,15 +474,15 @@ gchar *password_decrypt_gnutls(const gchar *password,
        }
 
        /* Prepare random IV for cipher */
-       iv.data = malloc(ivlen);
-       iv.size = ivlen;
+       iv.data = malloc(IVLEN);
+       iv.size = IVLEN;
 #if defined G_OS_UNIX
-       ret = read(rnd, iv.data, ivlen);
-       if (ret != ivlen) {
+       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)) {
+       if (!CryptGenRandom(rnd, IVLEN, iv.data)) {
                debug_print("Could not read random data for IV\n");
                CryptReleaseContext(rnd, 0);
 #endif