mirror of
https://github.com/weechat/weechat.git
synced 2026-07-10 11:43:13 +02:00
api: add function crypto_hmac (issue #1628)
This commit is contained in:
+91
-25
@@ -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;
|
||||
@@ -216,6 +217,91 @@ hash_pbkdf2_end:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -162,6 +162,39 @@ plugin_api_crypto_hash_pbkdf2 (const void *data, int data_size,
|
||||
iterations, hash, hash_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.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
Reference in New Issue
Block a user