diff options
author | Sébastien Helleu <flashcode@flashtux.org> | 2023-09-13 15:10:19 +0200 |
---|---|---|
committer | Sébastien Helleu <flashcode@flashtux.org> | 2023-09-13 15:10:19 +0200 |
commit | ef99d544fa8b968358724db6926b78bc8eed5341 (patch) | |
tree | be0390e5b95d2a61dca91a3fbbdc4b2a9fcc7220 /src | |
parent | 684bfd64c6893d12b6a4f82fe61e33e7d14e0a4d (diff) | |
download | weechat-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.c | 36 | ||||
-rw-r--r-- | src/core/wee-crypto.c | 33 | ||||
-rw-r--r-- | src/core/wee-crypto.h | 1 | ||||
-rw-r--r-- | src/core/wee-secure-buffer.c | 23 | ||||
-rw-r--r-- | src/core/wee-secure-config.c | 138 | ||||
-rw-r--r-- | src/core/wee-secure.c | 36 | ||||
-rw-r--r-- | src/core/wee-secure.h | 19 |
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[]; |