summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-09-13 15:10:19 +0200
committerSébastien Helleu <flashcode@flashtux.org>2023-09-13 15:10:19 +0200
commitef99d544fa8b968358724db6926b78bc8eed5341 (patch)
treebe0390e5b95d2a61dca91a3fbbdc4b2a9fcc7220 /src
parent684bfd64c6893d12b6a4f82fe61e33e7d14e0a4d (diff)
downloadweechat-ef99d544fa8b968358724db6926b78bc8eed5341.zip
core: add algorithms `sha512-224`, `sha512-256`, `sha3-*`, blake2b-*` and `blake2s-*` in option sec.crypt.hash_algo (closes #2008)
Diffstat (limited to 'src')
-rw-r--r--src/core/wee-command.c36
-rw-r--r--src/core/wee-crypto.c33
-rw-r--r--src/core/wee-crypto.h1
-rw-r--r--src/core/wee-secure-buffer.c23
-rw-r--r--src/core/wee-secure-config.c138
-rw-r--r--src/core/wee-secure.c36
-rw-r--r--src/core/wee-secure.h19
7 files changed, 226 insertions, 60 deletions
diff --git a/src/core/wee-command.c b/src/core/wee-command.c
index d98b36541..6269b945c 100644
--- a/src/core/wee-command.c
+++ b/src/core/wee-command.c
@@ -6109,7 +6109,7 @@ COMMAND_CALLBACK(save)
COMMAND_CALLBACK(secure)
{
- int passphrase_was_set, count_encrypted;
+ int passphrase_was_set, count_encrypted, rc;
/* make C compiler happy */
(void) pointer;
@@ -6140,19 +6140,39 @@ COMMAND_CALLBACK(secure)
gui_chat_printf (NULL, _("All encrypted data has been deleted"));
return WEECHAT_RC_OK;
}
- if (secure_decrypt_data_not_decrypted (argv_eol[2]) > 0)
+ rc = secure_decrypt_data_not_decrypted (argv_eol[2]);
+ if (rc == -2)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to decrypt data: hash algorithm \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ config_file_option_string (secure_config_crypt_hash_algo));
+ }
+ else if (rc == -3)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to decrypt data: cipher \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ config_file_option_string (secure_config_crypt_cipher));
+ }
+ else if ((rc == -1) || (rc == 0))
{
gui_chat_printf (NULL,
- _("Encrypted data has been successfully decrypted"));
- if (secure_passphrase)
- free (secure_passphrase);
- secure_passphrase = strdup (argv_eol[2]);
+ _("%sFailed to decrypt data: wrong passphrase?"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
+
}
else
{
gui_chat_printf (NULL,
- _("%sFailed to decrypt data (wrong passphrase?)"),
- gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
+ _("Encrypted data has been successfully decrypted"));
+ if (secure_passphrase)
+ free (secure_passphrase);
+ secure_passphrase = strdup (argv_eol[2]);
}
return WEECHAT_RC_OK;
}
diff --git a/src/core/wee-crypto.c b/src/core/wee-crypto.c
index 77d1629c9..e91233495 100644
--- a/src/core/wee-crypto.c
+++ b/src/core/wee-crypto.c
@@ -98,6 +98,18 @@ int weecrypto_hash_algo[] = {
#endif
};
+char *weecrypto_cipher_string[] = {
+ "aes128",
+ "aes192",
+ "aes256",
+ NULL,
+};
+int weecrypto_cipher[] = {
+ GCRY_CIPHER_AES128,
+ GCRY_CIPHER_AES192,
+ GCRY_CIPHER_AES256,
+};
+
/*
* Returns the hash algorithm with the name, or GCRY_MD_NONE if not found.
@@ -121,6 +133,27 @@ weecrypto_get_hash_algo (const char *hash_algo)
}
/*
+ * Returns the cipher with the name, or GCRY_CIPHER_NONE if not found.
+ */
+
+int
+weecrypto_get_cipher (const char *cipher)
+{
+ int i;
+
+ if (!cipher)
+ return GCRY_CIPHER_NONE;
+
+ for (i = 0; weecrypto_cipher_string[i]; i++)
+ {
+ if (strcmp (weecrypto_cipher_string[i], cipher) == 0)
+ return weecrypto_cipher[i];
+ }
+
+ return GCRY_CIPHER_NONE;
+}
+
+/*
* Computes hash of data using the given hash algorithm.
*
* The hash size depends on the algorithm, common ones are:
diff --git a/src/core/wee-crypto.h b/src/core/wee-crypto.h
index c06de3d8f..8fc99c37a 100644
--- a/src/core/wee-crypto.h
+++ b/src/core/wee-crypto.h
@@ -24,6 +24,7 @@
#define WEECRYPTO_TOTP_MAX_DIGITS 10
extern int weecrypto_get_hash_algo (const char *hash_algo);
+extern int weecrypto_get_cipher (const char *cipher);
extern int weecrypto_hash (const void *data, int data_size, int hash_algo,
void *hash, int *hash_size);
extern int weecrypto_hash_file (const char *filename, int hash_algo,
diff --git a/src/core/wee-secure-buffer.c b/src/core/wee-secure-buffer.c
index 6152fe66e..164e09596 100644
--- a/src/core/wee-secure-buffer.c
+++ b/src/core/wee-secure-buffer.c
@@ -26,9 +26,11 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <gcrypt.h>
#include "weechat.h"
#include "wee-config-file.h"
+#include "wee-crypto.h"
#include "wee-hashtable.h"
#include "wee-secure.h"
#include "wee-secure-buffer.h"
@@ -85,7 +87,8 @@ secure_buffer_display_data (void *data,
void
secure_buffer_display ()
{
- int line, count, count_encrypted;
+ int line, count, count_encrypted, hash_algo;
+ char str_supported[1024];
if (!secure_buffer)
return;
@@ -99,10 +102,22 @@ secure_buffer_display ()
line = 0;
+ str_supported[0] = '\0';
+ hash_algo = weecrypto_get_hash_algo (
+ config_file_option_string (secure_config_crypt_hash_algo));
+ if (hash_algo == GCRY_MD_NONE)
+ {
+ snprintf (str_supported, sizeof (str_supported),
+ " (%s)",
+ /* TRANSLATORS: "hash algorithm not supported" */
+ _("not supported"));
+ }
+
gui_chat_printf_y (secure_buffer, line++,
- "Hash algo: %s Cipher: %s Salt: %s",
- secure_hash_algo_string[CONFIG_ENUM(secure_config_crypt_hash_algo)],
- secure_cipher_string[CONFIG_ENUM(secure_config_crypt_cipher)],
+ "Hash algo: %s%s Cipher: %s Salt: %s",
+ config_file_option_string (secure_config_crypt_hash_algo),
+ str_supported,
+ config_file_option_string (secure_config_crypt_cipher),
(CONFIG_BOOLEAN(secure_config_crypt_salt)) ? _("on") : _("off"));
/* display passphrase */
diff --git a/src/core/wee-secure-config.c b/src/core/wee-secure-config.c
index 767cbe390..9cf94fcdd 100644
--- a/src/core/wee-secure-config.c
+++ b/src/core/wee-secure-config.c
@@ -26,9 +26,11 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <gcrypt.h>
#include "weechat.h"
#include "wee-config-file.h"
+#include "wee-crypto.h"
#include "wee-hashtable.h"
#include "wee-secure.h"
#include "wee-secure-config.h"
@@ -48,6 +50,8 @@ struct t_config_option *secure_config_crypt_hash_algo = NULL;
struct t_config_option *secure_config_crypt_passphrase_command = NULL;
struct t_config_option *secure_config_crypt_salt = NULL;
+int secure_config_loading = 0;
+
/*
* Gets passphrase from user and puts it in variable "secure_passphrase".
@@ -173,6 +177,39 @@ secure_config_reload_cb (const void *pointer, void *data,
}
/*
+ * Callback for changes on some options "weechat.crypt.*" (that can not be
+ * changed if there are encrypted data.
+ */
+
+int
+secure_config_check_crypt_option_cb (const void *pointer, void *data,
+ struct t_config_option *option,
+ const char *value)
+{
+ /* make C compiler happy */
+ (void) pointer;
+ (void) data;
+ (void) value;
+
+ /* any value allowed while reading config */
+ if (secure_config_loading)
+ return 1;
+
+ /* no encrypted data => changes allowed */
+ if (secure_hashtable_data_encrypted->items_count == 0)
+ return 1;
+
+ gui_chat_printf (NULL,
+ _("%sOption %s.%s.%s can not be changed because there "
+ "are still encrypted data"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option->config_file->name,
+ option->section->name,
+ option->name);
+ return 0;
+}
+
+/*
* Reads a data option in secured data configuration file.
*/
@@ -183,7 +220,7 @@ secure_config_data_read_cb (const void *pointer, void *data,
const char *option_name, const char *value)
{
char *buffer, *decrypted, str_error[1024];
- int length_buffer, length_decrypted, rc;
+ int length_buffer, length_decrypted, rc, hash_algo, cipher;
/* make C compiler happy */
(void) pointer;
@@ -237,6 +274,38 @@ secure_config_data_read_cb (const void *pointer, void *data,
return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
}
+ /* get hash algorithm */
+ hash_algo = weecrypto_get_hash_algo (
+ config_file_option_string (secure_config_crypt_hash_algo));
+ if (hash_algo == GCRY_MD_NONE)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to decrypt data \"%s\": hash algorithm \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option_name,
+ config_file_option_string (secure_config_crypt_hash_algo));
+ hashtable_set (secure_hashtable_data_encrypted, option_name, value);
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
+ /* get cipher */
+ cipher = weecrypto_get_cipher (
+ config_file_option_string (secure_config_crypt_cipher));
+ if (cipher == GCRY_CIPHER_NONE)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to decrypt data \"%s\": cipher \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ option_name,
+ config_file_option_string (secure_config_crypt_cipher));
+ hashtable_set (secure_hashtable_data_encrypted, option_name, value);
+ return WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE;
+ }
+
/* decrypt data */
buffer = malloc (strlen (value) + 1);
if (!buffer)
@@ -250,8 +319,8 @@ secure_config_data_read_cb (const void *pointer, void *data,
rc = secure_decrypt_data (
buffer,
length_buffer,
- secure_hash_algo[CONFIG_ENUM(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_ENUM(secure_config_crypt_cipher)],
+ hash_algo,
+ cipher,
secure_passphrase,
&decrypted,
&length_decrypted);
@@ -311,13 +380,41 @@ secure_config_data_write_map_cb (void *data,
{
struct t_config_file *config_file;
char *buffer, *buffer_base16;
- int length_buffer, rc;
+ int length_buffer, rc, hash_algo, cipher;
/* make C compiler happy */
(void) hashtable;
config_file = (struct t_config_file *)data;
+ hash_algo = weecrypto_get_hash_algo (
+ config_file_option_string (secure_config_crypt_hash_algo));
+ if (hash_algo == GCRY_MD_NONE)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to encrypt data \"%s\": hash algorithm \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ key,
+ config_file_option_string (secure_config_crypt_hash_algo));
+ return;
+ }
+
+ cipher = weecrypto_get_cipher (
+ config_file_option_string (secure_config_crypt_cipher));
+ if (cipher == GCRY_CIPHER_NONE)
+ {
+ gui_chat_printf (
+ NULL,
+ _("%sFailed to encrypt data \"%s\": cipher \"%s\" is not "
+ "available (ligbcrypt version is too old?)"),
+ gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
+ key,
+ config_file_option_string (secure_config_crypt_cipher));
+ return;
+ }
+
buffer = NULL;
length_buffer = 0;
@@ -326,8 +423,8 @@ secure_config_data_write_map_cb (void *data,
/* encrypt password using passphrase */
rc = secure_encrypt_data (
value, strlen (value) + 1,
- secure_hash_algo[CONFIG_ENUM(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_ENUM(secure_config_crypt_cipher)],
+ hash_algo,
+ cipher,
secure_passphrase,
&buffer,
&length_buffer);
@@ -352,7 +449,7 @@ secure_config_data_write_map_cb (void *data,
else
{
gui_chat_printf (NULL,
- _("%sError encrypting data \"%s\" (%d)"),
+ _("%sFailed to encrypt data \"%s\" (%d)"),
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
key, rc);
}
@@ -469,13 +566,26 @@ secure_config_init_options ()
N_("cipher used to crypt data (the number after algorithm is the "
"size of the key in bits)"),
"aes128|aes192|aes256", 0, 0, "aes256", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ &secure_config_check_crypt_option_cb, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
secure_config_crypt_hash_algo = config_file_new_option (
secure_config_file, secure_config_section_crypt,
"hash_algo", "enum",
- N_("hash algorithm used to check the decrypted data"),
- "sha224|sha256|sha384|sha512", 0, 0, "sha256", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ N_("hash algorithm used to check the decrypted data; "
+ "some of them require a specific libgcrypt version: "
+ "sha3-*: libgcrypt >= 1.7.0, "
+ "blake2*: libgcrypt >= 1.8.0, "
+ "sha512-*: libgcrypt >= 1.9.4"),
+ "sha224|sha256|sha384|sha512"
+ "|sha512-224|sha512-256"
+ "|sha3-224|sha3-256|sha3-384|sha3-512"
+ "|blake2b-160|blake2b-256|blake2b-384|blake2b-512"
+ "|blake2s-128|blake2s-160|blake2s-224|blake2s-256",
+ 0, 0, "sha256", NULL, 0,
+ &secure_config_check_crypt_option_cb, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
secure_config_crypt_passphrase_command = config_file_new_option (
secure_config_file, secure_config_section_crypt,
"passphrase_command", "string",
@@ -500,7 +610,9 @@ secure_config_init_options ()
"then you can turn off this option to have always same content "
"in file"),
NULL, 0, 0, "on", NULL, 0,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+ &secure_config_check_crypt_option_cb, NULL, NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL);
}
/* data */
@@ -532,7 +644,9 @@ secure_config_read ()
secure_data_encrypted = 0;
+ secure_config_loading = 1;
rc = config_file_read (secure_config_file);
+ secure_config_loading = 0;
return rc;
}
diff --git a/src/core/wee-secure.c b/src/core/wee-secure.c
index f2c68f16f..3d8e9dac6 100644
--- a/src/core/wee-secure.c
+++ b/src/core/wee-secure.c
@@ -46,17 +46,6 @@ struct t_hashtable *secure_hashtable_data = NULL;
/* data still encrypted (if passphrase not set) */
struct t_hashtable *secure_hashtable_data_encrypted = NULL;
-/* hash algorithms */
-char *secure_hash_algo_string[] = { "sha224", "sha256", "sha384", "sha512",
- NULL };
-int secure_hash_algo[] = { GCRY_MD_SHA224, GCRY_MD_SHA256, GCRY_MD_SHA384,
- GCRY_MD_SHA512 };
-
-/* ciphers */
-char *secure_cipher_string[] = { "aes128", "aes192", "aes256", NULL };
-int secure_cipher[] = { GCRY_CIPHER_AES128, GCRY_CIPHER_AES192,
- GCRY_CIPHER_AES256 };
-
char *secure_decrypt_error[] = { "memory", "buffer", "key", "cipher", "setkey",
"decrypt", "hash", "hash mismatch" };
@@ -427,8 +416,10 @@ decrypt_end:
* secured data configuration file (because no passphrase was given).
*
* Returns:
- * > 0: number of decrypted data
- * 0: error decrypting data
+ * >= 0: number of decrypted data
+ * -1: error decrypting data (bad passphrase)
+ * -2: unsupported hash algorithm
+ * -3: unsupported cipher
*/
int
@@ -436,11 +427,22 @@ secure_decrypt_data_not_decrypted (const char *passphrase)
{
char **keys, *buffer, *decrypted;
const char *value;
- int num_ok, num_keys, i, length_buffer, length_decrypted, rc;
+ int num_ok, num_keys, i, hash_algo, cipher, rc;
+ int length_buffer, length_decrypted;
/* we need a passphrase to decrypt data! */
if (!passphrase || !passphrase[0])
- return 0;
+ return -1;
+
+ hash_algo = weecrypto_get_hash_algo (
+ config_file_option_string (secure_config_crypt_hash_algo));
+ if (hash_algo == GCRY_MD_NONE)
+ return -2;
+
+ cipher = weecrypto_get_cipher (
+ config_file_option_string (secure_config_crypt_cipher));
+ if (cipher == GCRY_CIPHER_NONE)
+ return -3;
num_ok = 0;
@@ -469,8 +471,8 @@ secure_decrypt_data_not_decrypted (const char *passphrase)
rc = secure_decrypt_data (
buffer,
length_buffer,
- secure_hash_algo[CONFIG_ENUM(secure_config_crypt_hash_algo)],
- secure_cipher[CONFIG_ENUM(secure_config_crypt_cipher)],
+ hash_algo,
+ cipher,
passphrase,
&decrypted,
&length_decrypted);
diff --git a/src/core/wee-secure.h b/src/core/wee-secure.h
index df7a8f7d0..9ea759edf 100644
--- a/src/core/wee-secure.h
+++ b/src/core/wee-secure.h
@@ -28,28 +28,9 @@
#define SECURE_DATA_PASSPHRASE_FLAG "__passphrase__"
#define SECURE_SALT_SIZE 8
-enum t_secure_config_hash_algo
-{
- SECURE_CONFIG_HASH_SHA224 = 0,
- SECURE_CONFIG_HASH_SHA256,
- SECURE_CONFIG_HASH_SHA384,
- SECURE_CONFIG_HASH_SHA512,
-};
-
-enum t_secure_config_cipher
-{
- SECURE_CONFIG_CIPHER_AES128 = 0,
- SECURE_CONFIG_CIPHER_AES192,
- SECURE_CONFIG_CIPHER_AES256,
-};
-
extern char *secure_passphrase;
extern struct t_hashtable *secure_hashtable_data;
extern struct t_hashtable *secure_hashtable_data_encrypted;
-extern char *secure_hash_algo_string[];
-extern int secure_hash_algo[];
-extern char *secure_cipher_string[];
-extern int secure_cipher[];
extern int secure_data_encrypted;
extern char *secure_decrypt_error[];