From e8cdda318fe2a09ff7302c54cdd7900040a8ba5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Tue, 15 Jun 2021 21:49:45 +0200 Subject: irc: drop support of DH-BLOWFISH and DH-AES SASL mechanisms (closes #175) --- src/plugins/irc/irc-config.c | 8 +- src/plugins/irc/irc-protocol.c | 8 - src/plugins/irc/irc-sasl.c | 384 +---------------------------------------- src/plugins/irc/irc-sasl.h | 10 -- 4 files changed, 3 insertions(+), 407 deletions(-) (limited to 'src') diff --git a/src/plugins/irc/irc-config.c b/src/plugins/irc/irc-config.c index 3ad0ed8a6..2eb0b8635 100644 --- a/src/plugins/irc/irc-config.c +++ b/src/plugins/irc/irc-config.c @@ -1868,13 +1868,9 @@ irc_config_server_new_option (struct t_config_file *config_file, "\"ecdsa-nist256p-challenge\" for key-based " "challenge authentication, " "\"external\" for authentication using client side SSL " - "cert, " - "\"dh-blowfish\" for blowfish crypted password " - "(insecure, not recommended), " - "\"dh-aes\" for AES crypted password " - "(insecure, not recommended)"), + "certificate"), "plain|scram-sha-1|scram-sha-256|scram-sha-512|" - "ecdsa-nist256p-challenge|external|dh-blowfish|dh-aes", + "ecdsa-nist256p-challenge|external", 0, 0, default_value, value, null_value_allowed, diff --git a/src/plugins/irc/irc-protocol.c b/src/plugins/irc/irc-protocol.c index 642f7a8e2..e75ed9224 100644 --- a/src/plugins/irc/irc-protocol.c +++ b/src/plugins/irc/irc-protocol.c @@ -502,14 +502,6 @@ IRC_PROTOCOL_CALLBACK(authenticate) case IRC_SASL_MECHANISM_EXTERNAL: answer = strdup ("+"); break; - case IRC_SASL_MECHANISM_DH_BLOWFISH: - answer = irc_sasl_mechanism_dh_blowfish ( - argv[1], sasl_username, sasl_password, &sasl_error); - break; - case IRC_SASL_MECHANISM_DH_AES: - answer = irc_sasl_mechanism_dh_aes ( - argv[1], sasl_username, sasl_password, &sasl_error); - break; } if (answer) { diff --git a/src/plugins/irc/irc-sasl.c b/src/plugins/irc/irc-sasl.c index bfd7824ef..512b315c6 100644 --- a/src/plugins/irc/irc-sasl.c +++ b/src/plugins/irc/irc-sasl.c @@ -43,7 +43,7 @@ */ char *irc_sasl_mechanism_string[IRC_NUM_SASL_MECHANISMS] = { "plain", "scram-sha-1", "scram-sha-256", "scram-sha-512", - "ecdsa-nist256p-challenge", "external", "dh-blowfish", "dh-aes" }; + "ecdsa-nist256p-challenge", "external" }; /* @@ -711,385 +711,3 @@ irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *server, return NULL; #endif /* LIBGNUTLS_VERSION_NUMBER >= 0x030015 */ } - -/* - * Reads key sent by server (Diffie-Hellman key exchange). - * - * If an error occurs and if sasl_error is not NULL, *sasl_error is set to the - * error and must be freed after use. - * - * Returns: - * 1: OK - * 0: error - */ - -int -irc_sasl_dh (const char *data_base64, - unsigned char **public_bin, unsigned char **secret_bin, - int *length_key, char **sasl_error) -{ - char *data; - unsigned char *ptr_data; - int length_data, size, num_bits_prime_number, rc; - size_t num_written; - gcry_mpi_t data_prime_number, data_generator_number, data_server_pub_key; - gcry_mpi_t pub_key, priv_key, secret_mpi; - - rc = 0; - - data = NULL; - data_prime_number = NULL; - data_generator_number = NULL; - data_server_pub_key = NULL; - pub_key = NULL; - priv_key = NULL; - secret_mpi = NULL; - - /* decode data */ - data = malloc (strlen (data_base64) + 1); - if (!data) - goto memory_error; - length_data = weechat_string_base_decode (64, data_base64, data); - ptr_data = (unsigned char *)data; - - /* extract prime number */ - size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); - ptr_data += 2; - length_data -= 2; - if (size > length_data) - goto crypto_error; - data_prime_number = gcry_mpi_new (size * 8); - gcry_mpi_scan (&data_prime_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); - num_bits_prime_number = gcry_mpi_get_nbits (data_prime_number); - if (num_bits_prime_number == 0 || INT_MAX - 7 < num_bits_prime_number) - goto crypto_error; - ptr_data += size; - length_data -= size; - - /* extract generator number */ - size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); - ptr_data += 2; - length_data -= 2; - if (size > length_data) - goto crypto_error; - data_generator_number = gcry_mpi_new (size * 8); - gcry_mpi_scan (&data_generator_number, GCRYMPI_FMT_USG, ptr_data, size, NULL); - ptr_data += size; - length_data -= size; - - /* extract server-generated public key */ - size = ntohs ((((unsigned int)ptr_data[1]) << 8) | ptr_data[0]); - ptr_data += 2; - length_data -= 2; - if (size > length_data) - goto crypto_error; - data_server_pub_key = gcry_mpi_new (size * 8); - gcry_mpi_scan (&data_server_pub_key, GCRYMPI_FMT_USG, ptr_data, size, NULL); - - /* generate keys */ - pub_key = gcry_mpi_new (num_bits_prime_number); - priv_key = gcry_mpi_new (num_bits_prime_number); - gcry_mpi_randomize (priv_key, num_bits_prime_number, GCRY_STRONG_RANDOM); - /* pub_key = (g ^ priv_key) % p */ - gcry_mpi_powm (pub_key, data_generator_number, priv_key, data_prime_number); - - /* compute secret_bin */ - *length_key = (num_bits_prime_number + 7) / 8; - *secret_bin = malloc (*length_key); - secret_mpi = gcry_mpi_new (num_bits_prime_number); - /* secret_mpi = (y ^ priv_key) % p */ - gcry_mpi_powm (secret_mpi, data_server_pub_key, priv_key, data_prime_number); - gcry_mpi_print (GCRYMPI_FMT_USG, *secret_bin, *length_key, - &num_written, secret_mpi); - - /* create public_bin */ - *public_bin = malloc (*length_key); - gcry_mpi_print (GCRYMPI_FMT_USG, *public_bin, *length_key, - &num_written, pub_key); - rc = 1; - - goto end; - -memory_error: - if (sasl_error) - *sasl_error = strdup (_("memory error")); - goto end; - -crypto_error: - if (sasl_error) - *sasl_error = strdup (_("cryptography error")); - goto end; - -end: - if (data) - free (data); - if (data_prime_number) - gcry_mpi_release (data_prime_number); - if (data_generator_number) - gcry_mpi_release (data_generator_number); - if (data_server_pub_key) - gcry_mpi_release (data_server_pub_key); - if (pub_key) - gcry_mpi_release (pub_key); - if (priv_key) - gcry_mpi_release (priv_key); - if (secret_mpi) - gcry_mpi_release (secret_mpi); - - return rc; -} - -/* - * Builds answer for SASL authentication, using mechanism "DH-BLOWFISH". - * - * Argument data_base64 is a concatenation of 3 strings, each string is composed - * of 2 bytes (length of string), followed by content of string: - * 1. a prime number - * 2. a generator number - * 3. server-generated public key - * - * If an error occurs and if sasl_error is not NULL, *sasl_error is set to the - * error and must be freed after use. - * - * Note: result must be freed after use. - */ - -char * -irc_sasl_mechanism_dh_blowfish (const char *data_base64, - const char *sasl_username, - const char *sasl_password, - char **sasl_error) -{ - char *answer, *ptr_answer, *answer_base64; - unsigned char *password_clear, *password_crypted; - int length_key, length_username, length_password, length_answer; - unsigned char *public_bin, *secret_bin; - gcry_cipher_hd_t gcrypt_handle; - - password_clear = NULL; - password_crypted = NULL; - answer = NULL; - answer_base64 = NULL; - secret_bin = NULL; - public_bin = NULL; - - if (!irc_sasl_dh (data_base64, &public_bin, &secret_bin, &length_key, - sasl_error)) - { - goto end; - } - - /* create password buffers (clear and crypted) */ - length_password = strlen (sasl_password) + - ((8 - (strlen (sasl_password) % 8)) % 8); - password_clear = calloc (1, length_password); - password_crypted = calloc (1, length_password); - memcpy (password_clear, sasl_password, strlen (sasl_password)); - - /* crypt password using blowfish */ - if (gcry_cipher_open (&gcrypt_handle, GCRY_CIPHER_BLOWFISH, - GCRY_CIPHER_MODE_ECB, 0) != 0) - goto crypto_error; - if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0) - goto crypto_error; - if (gcry_cipher_encrypt (gcrypt_handle, - password_crypted, length_password, - password_clear, length_password) != 0) - goto crypto_error; - - gcry_cipher_close (gcrypt_handle); - - /* - * build answer for server, it is concatenation of: - * 1. key length (2 bytes) - * 2. public key ('length_key' bytes) - * 3. sasl_username ('length_username'+1 bytes) - * 4. encrypted password ('length_password' bytes) - */ - length_username = strlen (sasl_username) + 1; - length_answer = 2 + length_key + length_username + length_password; - answer = malloc (length_answer); - ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons (length_key); - ptr_answer += 2; - memcpy (ptr_answer, public_bin, length_key); - ptr_answer += length_key; - memcpy (ptr_answer, sasl_username, length_username); - ptr_answer += length_username; - memcpy (ptr_answer, password_crypted, length_password); - - /* encode answer to base64 */ - answer_base64 = malloc ((length_answer + 1) * 4); - if (answer_base64) - { - if (weechat_string_base_encode (64, answer, length_answer, - answer_base64) < 0) - { - free (answer_base64); - answer_base64 = NULL; - } - } - - goto end; - -crypto_error: - if (sasl_error) - *sasl_error = strdup (_("cryptography error")); - goto end; - -end: - if (secret_bin) - free (secret_bin); - if (public_bin) - free (public_bin); - if (password_clear) - free (password_clear); - if (password_crypted) - free (password_crypted); - if (answer) - free (answer); - - return answer_base64; -} - -/* - * Builds answer for SASL authentication, using mechanism "DH-AES". - * - * Argument data_base64 is a concatenation of 3 strings, each string is composed - * of 2 bytes (length of string), followed by content of string: - * 1. a prime number - * 2. a generator number - * 3. server-generated public key - * - * If an error occurs and if sasl_error is not NULL, *sasl_error is set to the - * error and must be freed after use. - * - * Note: result must be freed after use. - */ - -char * -irc_sasl_mechanism_dh_aes (const char *data_base64, - const char *sasl_username, - const char *sasl_password, - char **sasl_error) -{ - char *answer, *ptr_answer, *answer_base64; - unsigned char *ptr_userpass, *userpass_clear, *userpass_crypted; - int length_key, length_answer; - int length_username, length_password, length_userpass; - unsigned char *public_bin, *secret_bin; - char iv[16]; - int cipher_algo; - gcry_cipher_hd_t gcrypt_handle; - - userpass_clear = NULL; - userpass_crypted = NULL; - answer = NULL; - answer_base64 = NULL; - secret_bin = NULL; - public_bin = NULL; - - if (!irc_sasl_dh (data_base64, &public_bin, &secret_bin, &length_key, - sasl_error)) - { - goto end; - } - - /* Select cipher algorithm: key length * 8 = cipher bit size */ - switch (length_key) - { - case 32: - cipher_algo = GCRY_CIPHER_AES256; - break; - case 24: - cipher_algo = GCRY_CIPHER_AES192; - break; - case 16: - cipher_algo = GCRY_CIPHER_AES128; - break; - default: - /* Invalid bit length */ - goto end; - } - - /* Generate the IV */ - gcry_randomize (iv, sizeof (iv), GCRY_STRONG_RANDOM); - - /* create user/pass buffers (clear and crypted) */ - length_username = strlen (sasl_username) + 1; - length_password = strlen (sasl_password) + 1; - length_userpass = length_username + length_password + - ((16 - ((length_username + length_password) % 16)) % 16); - userpass_clear = calloc (1, length_userpass); - ptr_userpass = userpass_clear; - userpass_crypted = calloc (1, length_userpass); - memcpy (ptr_userpass, sasl_username, length_username); - ptr_userpass += length_username; - memcpy (ptr_userpass, sasl_password, length_password); - - /* crypt password using AES in CBC mode */ - if (gcry_cipher_open (&gcrypt_handle, cipher_algo, - GCRY_CIPHER_MODE_CBC, 0) != 0) - goto crypto_error; - if (gcry_cipher_setkey (gcrypt_handle, secret_bin, length_key) != 0) - goto crypto_error; - if (gcry_cipher_setiv (gcrypt_handle, iv, sizeof (iv)) != 0) - goto crypto_error; - if (gcry_cipher_encrypt (gcrypt_handle, - userpass_crypted, length_userpass, - userpass_clear, length_userpass) != 0) - goto crypto_error; - - gcry_cipher_close (gcrypt_handle); - - /* - * build answer for server, it is concatenation of: - * 1. key length (2 bytes) - * 2. public key ('length_key' bytes) - * 3. IV (sizeof (iv) bytes) - * 4. encrypted password ('length_userpass' bytes) - */ - length_answer = 2 + length_key + sizeof (iv) + length_userpass; - answer = malloc (length_answer); - ptr_answer = answer; - *((unsigned int *)ptr_answer) = htons (length_key); - ptr_answer += 2; - memcpy (ptr_answer, public_bin, length_key); - ptr_answer += length_key; - memcpy (ptr_answer, iv, sizeof (iv)); - ptr_answer += sizeof (iv); - memcpy (ptr_answer, userpass_crypted, length_userpass); - - /* encode answer to base64 */ - answer_base64 = malloc ((length_answer + 1) * 4); - if (answer_base64) - { - if (weechat_string_base_encode (64, answer, length_answer, - answer_base64) < 0) - { - free (answer_base64); - answer_base64 = NULL; - } - } - - goto end; - -crypto_error: - if (sasl_error) - *sasl_error = strdup (_("cryptography error")); - goto end; - -end: - if (secret_bin) - free (secret_bin); - if (public_bin) - free (public_bin); - if (userpass_clear) - free (userpass_clear); - if (userpass_crypted) - free (userpass_crypted); - if (answer) - free (answer); - - return answer_base64; -} diff --git a/src/plugins/irc/irc-sasl.h b/src/plugins/irc/irc-sasl.h index 841d0dbdf..3e4163b9b 100644 --- a/src/plugins/irc/irc-sasl.h +++ b/src/plugins/irc/irc-sasl.h @@ -35,8 +35,6 @@ enum t_irc_sasl_mechanism IRC_SASL_MECHANISM_SCRAM_SHA_512, IRC_SASL_MECHANISM_ECDSA_NIST256P_CHALLENGE, IRC_SASL_MECHANISM_EXTERNAL, - IRC_SASL_MECHANISM_DH_BLOWFISH, - IRC_SASL_MECHANISM_DH_AES, /* number of SASL mechanisms */ IRC_NUM_SASL_MECHANISMS, }; @@ -56,13 +54,5 @@ extern char *irc_sasl_mechanism_ecdsa_nist256p_challenge (struct t_irc_server *s const char *sasl_username, const char *sasl_key, char **sasl_error); -extern char *irc_sasl_mechanism_dh_blowfish (const char *data_base64, - const char *sasl_username, - const char *sasl_password, - char **sasl_error); -extern char *irc_sasl_mechanism_dh_aes (const char *data_base64, - const char *sasl_username, - const char *sasl_password, - char **sasl_error); #endif /* WEECHAT_PLUGIN_IRC_SASL_H */ -- cgit v1.2.3