diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/wee-crypto.c | 116 | ||||
-rw-r--r-- | src/core/wee-crypto.h | 4 | ||||
-rw-r--r-- | src/plugins/plugin-api.c | 33 | ||||
-rw-r--r-- | src/plugins/plugin-api.h | 4 | ||||
-rw-r--r-- | src/plugins/plugin.c | 1 | ||||
-rw-r--r-- | src/plugins/weechat-plugin.h | 13 |
6 files changed, 145 insertions, 26 deletions
diff --git a/src/core/wee-crypto.c b/src/core/wee-crypto.c index 89a348fab..119230996 100644 --- a/src/core/wee-crypto.c +++ b/src/core/wee-crypto.c @@ -80,7 +80,7 @@ weecrypto_get_hash_algo (const char *hash_algo) } /* - * Computes hash of data using the given algorithm. + * Computes hash of data using the given hash algorithm. * * The hash size depends on the algorithm, common ones are: * @@ -137,6 +137,7 @@ weecrypto_hash (const void *data, int data_size, int hash_algo, hd_md_opened = 1; gcry_md_write (*hd_md, data, data_size); + ptr_hash = gcry_md_read (*hd_md, hash_algo); if (!ptr_hash) goto hash_end; @@ -217,6 +218,91 @@ hash_pbkdf2_end: } /* + * Computes keyed-hash message authentication code (HMAC). + * + * The hash size depends on the algorithm, common ones are: + * + * GCRY_MD_CRC32 32 bits == 4 bytes + * GCRY_MD_MD5 128 bits == 16 bytes + * GCRY_MD_SHA1 160 bits == 20 bytes + * GCRY_MD_SHA224 224 bits == 28 bytes + * GCRY_MD_SHA256 256 bits == 32 bytes + * GCRY_MD_SHA384 384 bits == 48 bytes + * GCRY_MD_SHA512 512 bits == 64 bytes + * GCRY_MD_SHA3_224 224 bits == 28 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_256 256 bits == 32 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_384 384 bits == 48 bytes (libgcrypt ≥ 1.7.0) + * GCRY_MD_SHA3_512 512 bits == 64 bytes (libgcrypt ≥ 1.7.0) + * + * The result hash is stored in "hash" (the buffer must be large enough). + * + * If hash_size is not NULL, the length of hash is stored in *hash_size + * (in bytes). + * + * Returns: + * 1: OK + * 0: error + */ + +int +weecrypto_hmac (const void *key, int key_size, + const void *message, int message_size, + int hash_algo, + void *hash, int *hash_size) +{ + gcry_md_hd_t *hd_md; + int rc, hd_md_opened, algo_size; + unsigned char *ptr_hash; + + rc = 0; + hd_md = NULL; + hd_md_opened = 0; + + if (!hash) + goto hmac_end; + + if (hash_size) + *hash_size = 0; + + if (!key || (key_size < 1) || !message || (message_size < 1)) + goto hmac_end; + + hd_md = malloc (sizeof (gcry_md_hd_t)); + if (!hd_md) + goto hmac_end; + + if (gcry_md_open (hd_md, hash_algo, GCRY_MD_FLAG_HMAC) != 0) + goto hmac_end; + + hd_md_opened = 1; + + if (gcry_md_setkey (*hd_md, key, key_size) != 0) + goto hmac_end; + + gcry_md_write (*hd_md, message, message_size); + + ptr_hash = gcry_md_read (*hd_md, hash_algo); + if (!ptr_hash) + goto hmac_end; + + algo_size = gcry_md_get_algo_dlen (hash_algo); + memcpy (hash, ptr_hash, algo_size); + if (hash_size) + *hash_size = algo_size; + + rc = 1; + +hmac_end: + if (hd_md) + { + if (hd_md_opened) + gcry_md_close (*hd_md); + free (hd_md); + } + return rc; +} + +/* * Generates a Time-based One-Time Password (TOTP), as described * in the RFC 6238. * @@ -230,22 +316,11 @@ weecrypto_totp_generate_internal (const char *secret, int length_secret, uint64_t moving_factor, int digits, char *result) { - gcry_md_hd_t hd_md; uint64_t moving_factor_swapped; - unsigned char *ptr_hash; char hash[20]; int offset, length; unsigned long bin_code; - if (gcry_md_open (&hd_md, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC) != 0) - return 0; - - if (gcry_md_setkey (hd_md, secret, length_secret) != 0) - { - gcry_md_close (hd_md); - return 0; - } - moving_factor_swapped = (moving_factor >> 56) | ((moving_factor << 40) & 0x00FF000000000000) | ((moving_factor << 24) & 0x0000FF0000000000) @@ -255,19 +330,10 @@ weecrypto_totp_generate_internal (const char *secret, int length_secret, | ((moving_factor >> 40) & 0x000000000000FF00) | (moving_factor << 56); - gcry_md_write (hd_md, - &moving_factor_swapped, sizeof (moving_factor_swapped)); - - ptr_hash = gcry_md_read (hd_md, GCRY_MD_SHA1); - if (!ptr_hash) - { - gcry_md_close (hd_md); - return 0; - } - - memcpy (hash, ptr_hash, sizeof (hash)); - - gcry_md_close (hd_md); + weecrypto_hmac (secret, length_secret, + &moving_factor_swapped, sizeof (moving_factor_swapped), + GCRY_MD_SHA1, + hash, NULL); offset = hash[19] & 0xf; bin_code = (hash[offset] & 0x7f) << 24 diff --git a/src/core/wee-crypto.h b/src/core/wee-crypto.h index efea48b00..897759775 100644 --- a/src/core/wee-crypto.h +++ b/src/core/wee-crypto.h @@ -31,6 +31,10 @@ extern int weecrypto_hash_pbkdf2 (const void *data, int data_size, const void *salt, int salt_size, int iterations, void *hash, int *hash_size); +extern int weecrypto_hmac (const void *key, int key_size, + const void *message, int message_size, + int hash_algo, + void *hash, int *hash_size); extern char *weecrypto_totp_generate (const char *secret, time_t totp_time, int digits); extern int weecrypto_totp_validate (const char *secret, time_t totp_time, diff --git a/src/plugins/plugin-api.c b/src/plugins/plugin-api.c index 95d46bf4c..2201eb4db 100644 --- a/src/plugins/plugin-api.c +++ b/src/plugins/plugin-api.c @@ -163,6 +163,39 @@ plugin_api_crypto_hash_pbkdf2 (const void *data, int data_size, } /* + * Computes HMAC of key + message using the given algorithm. + * + * Returns: + * 1: OK + * 0: error + */ + +int +plugin_api_crypto_hmac (const void *key, int key_size, + const void *message, int message_size, + const char *hash_algo, + void *hash, int *hash_size) +{ + int algo; + + if (!hash) + return 0; + + if (hash_size) + *hash_size = 0; + + if (!key || (key_size < 1) || !message || (message_size < 1) || !hash_algo) + return 0; + + algo = weecrypto_get_hash_algo (hash_algo); + if (algo == GCRY_MD_NONE) + return 0; + + return weecrypto_hmac (key, key_size, message, message_size, + algo, hash, hash_size); +} + +/* * Frees an option. */ diff --git a/src/plugins/plugin-api.h b/src/plugins/plugin-api.h index b8d377017..e266b5c69 100644 --- a/src/plugins/plugin-api.h +++ b/src/plugins/plugin-api.h @@ -38,6 +38,10 @@ extern int plugin_api_crypto_hash_pbkdf2 (const void *data, int data_size, const void *salt, int salt_size, int iterations, void *hash, int *hash_size); +extern int plugin_api_crypto_hmac (const void *key, int key_size, + const void *message, int message_size, + const char *hash_algo, + void *hash, int *hash_size); /* config */ extern void plugin_api_config_file_option_free (struct t_config_option *option); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 26cbff783..6254b613b 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -665,6 +665,7 @@ plugin_load (const char *filename, int init_plugin, int argc, char **argv) new_plugin->crypto_hash = &plugin_api_crypto_hash; new_plugin->crypto_hash_pbkdf2 = &plugin_api_crypto_hash_pbkdf2; + new_plugin->crypto_hmac = &plugin_api_crypto_hmac; new_plugin->mkdir_home = &dir_mkdir_home; new_plugin->mkdir = &dir_mkdir; diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index a261d8f44..9eb42f7e9 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -68,7 +68,7 @@ struct timeval; * please change the date with current one; for a second change at same * date, increment the 01, otherwise please keep 01. */ -#define WEECHAT_PLUGIN_API_VERSION "20201004-01" +#define WEECHAT_PLUGIN_API_VERSION "20210601-01" /* macros for defining plugin infos */ #define WEECHAT_PLUGIN_NAME(__name) \ @@ -382,6 +382,9 @@ struct t_weechat_plugin const void *salt, int salt_size, int iterations, void *hash, int *hash_size); + int (*crypto_hmac) (const void *key, int key_size, + const void *message, int message_size, + const char *hash_algo, void *hash, int *hash_size); /* directories/files */ int (*mkdir_home) (const char *directory, int mode); @@ -1347,6 +1350,14 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); __salt, __salt_size, \ __iterations, \ __hash, __hash_size) +#define weechat_crypto_hmac(__key, __key_size, \ + __message, __message_size, \ + __hash_algo, \ + __hash, __hash_size) \ + (weechat_plugin->crypto_hmac)(__key, __key_size, \ + __message, __message_size, \ + __hash_algo, \ + __hash, __hash_size) /* directories */ #define weechat_mkdir_home(__directory, __mode) \ |