From 72000880b02706f2375095e5ecad9f939840d62b Mon Sep 17 00:00:00 2001 From: Abhinay Ramesh Date: Tue, 11 May 2021 10:00:38 +0000 Subject: [PATCH] lib: Changes to support hash algo in keychain. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Problem Statement: ================== Currently there is no support for configuring hash algorithm in keychain.    RCA: ==== Not implemented yet.   Fix: ==== Changes are done to configure hash algorithm as part of keychain. which will easy the configuration from modules using keychain.   Risk: ===== Low risk   Tests Executed: =============== Have tested the configuration and unconfiguration flow for newly implemented CLI. ! key chain abcd key 100 key-string password cryptographic-algorithm sha1 exit key 200 key-string password cryptographic-algorithm sha256 exit ! Signed-off-by: Abhinay Ramesh --- lib/keychain.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/keychain.h | 45 +++++++++++++++- 2 files changed, 180 insertions(+), 2 deletions(-) diff --git a/lib/keychain.c b/lib/keychain.c index 1d678b949..6b03fbd56 100644 --- a/lib/keychain.c +++ b/lib/keychain.c @@ -18,6 +18,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" #include #include "command.h" @@ -207,6 +208,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index) key = key_new(); key->index = index; + key->hash_algo = KEYCHAIN_ALGO_NULL; listnode_add_sort(keychain->key, key); return key; @@ -336,6 +338,133 @@ DEFUN (no_key_string, return CMD_SUCCESS; } +const struct keychain_algo_info algo_info[] = { + {KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"}, + {KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE, + KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE, "MD5"}, + {KEYCHAIN_ALGO_HMAC_SHA1, "hmac-sha-1", KEYCHAIN_HMAC_SHA1_HASH_SIZE, + KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE, "HMAC-SHA-1"}, + {KEYCHAIN_ALGO_HMAC_SHA256, "hmac-sha-256", + KEYCHAIN_HMAC_SHA256_HASH_SIZE, KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE, + "HMAC-SHA-256"}, + {KEYCHAIN_ALGO_HMAC_SHA384, "hmac-sha-384", + KEYCHAIN_HMAC_SHA384_HASH_SIZE, KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE, + "HMAC-SHA-384"}, + {KEYCHAIN_ALGO_HMAC_SHA512, "hmac-sha-512", + KEYCHAIN_HMAC_SHA512_HASH_SIZE, KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE, + "HMAC-SHA-512"}, + {KEYCHAIN_ALGO_MAX, "max", KEYCHAIN_MAX_HASH_SIZE, + KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE, "Not defined"} +}; + +uint32_t keychain_get_block_size(enum keychain_hash_algo key) +{ + return algo_info[key].block; +} + +uint32_t keychain_get_hash_len(enum keychain_hash_algo key) +{ + return algo_info[key].length; +} + +const char *keychain_get_description(enum keychain_hash_algo key) +{ + return algo_info[key].desc; +} + +struct keychain_algo_info +keychain_get_hash_algo_info(enum keychain_hash_algo key) +{ + return algo_info[key]; +} + +enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name) +{ +#ifdef CRYPTO_INTERNAL + if (!strncmp(name, "hmac-sha-2", 10)) + return KEYCHAIN_ALGO_HMAC_SHA256; + else if (!strncmp(name, "m", 1)) + return KEYCHAIN_ALGO_MD5; + else + return KEYCHAIN_ALGO_NULL; +#else + if (!strncmp(name, "m", 1)) + return KEYCHAIN_ALGO_MD5; + else if (!strncmp(name, "hmac-sha-1", 10)) + return KEYCHAIN_ALGO_HMAC_SHA1; + else if (!strncmp(name, "hmac-sha-2", 10)) + return KEYCHAIN_ALGO_HMAC_SHA256; + else if (!strncmp(name, "hmac-sha-3", 10)) + return KEYCHAIN_ALGO_HMAC_SHA384; + else if (!strncmp(name, "hmac-sha-5", 10)) + return KEYCHAIN_ALGO_HMAC_SHA512; + else + return KEYCHAIN_ALGO_NULL; +#endif +} + +const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key) +{ + return algo_info[key].name; +} + +DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd, + "cryptographic-algorithm " + "", + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n") +{ + int algo_idx = 1; + uint8_t hash_algo = KEYCHAIN_ALGO_NULL; + + VTY_DECLVAR_CONTEXT_SUB(key, key); + hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); +#ifndef CRYPTO_OPENSSL + if (hash_algo == KEYCHAIN_ALGO_NULL) { + vty_out(vty, + "Hash algorithm not supported, compile with --with-crypto=openssl\n"); + return CMD_WARNING_CONFIG_FAILED; + } +#endif /* CRYPTO_OPENSSL */ + key->hash_algo = hash_algo; + return CMD_SUCCESS; +} + +DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd, + "no cryptographic-algorithm " + "[]", + NO_STR + "Cryptographic-algorithm\n" + "Use MD5 algorithm\n" + "Use HMAC-SHA-1 algorithm\n" + "Use HMAC-SHA-256 algorithm\n" + "Use HMAC-SHA-384 algorithm\n" + "Use HMAC-SHA-512 algorithm\n") +{ + int algo_idx = 2; + uint8_t hash_algo = KEYCHAIN_ALGO_NULL; + + VTY_DECLVAR_CONTEXT_SUB(key, key); + if (argc > algo_idx) { + hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg); + if (hash_algo == KEYCHAIN_ALGO_NULL) { + vty_out(vty, + "Hash algorithm not supported, try compiling with --with-crypto=openssl\n"); + return CMD_WARNING_CONFIG_FAILED; + } + } + + if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo)) + return CMD_SUCCESS; + + key->hash_algo = KEYCHAIN_ALGO_NULL; + return CMD_SUCCESS; +} + /* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when given string is malformed. */ static time_t key_str2time(const char *time_str, const char *day_str, @@ -1004,6 +1133,11 @@ static int keychain_config_write(struct vty *vty) if (key->string) vty_out(vty, " key-string %s\n", key->string); + if (key->hash_algo != KEYCHAIN_ALGO_NULL) + vty_out(vty, " cryptographic-algorithm %s\n", + keychain_get_algo_name_by_id( + key->hash_algo)); + if (key->accept.start) { keychain_strftime(buf, BUFSIZ, &key->accept.start); @@ -1051,6 +1185,7 @@ static int keychain_config_write(struct vty *vty) return 0; } + static void keychain_active_config(vector comps, struct cmd_token *token) { struct keychain *keychain; @@ -1131,4 +1266,6 @@ void keychain_init(void) install_element(KEYCHAIN_KEY_NODE, &send_lifetime_duration_month_day_cmd); install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd); + install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd); + install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd); } diff --git a/lib/keychain.h b/lib/keychain.h index eb6d2f175..c47bb7a79 100644 --- a/lib/keychain.h +++ b/lib/keychain.h @@ -27,6 +27,47 @@ extern "C" { #endif +enum keychain_hash_algo { + KEYCHAIN_ALGO_NULL, + KEYCHAIN_ALGO_MD5, + KEYCHAIN_ALGO_HMAC_SHA1, + KEYCHAIN_ALGO_HMAC_SHA256, + KEYCHAIN_ALGO_HMAC_SHA384, + KEYCHAIN_ALGO_HMAC_SHA512, + KEYCHAIN_ALGO_MAX +}; + +#define KEYCHAIN_MD5_HASH_SIZE 16 +#define KEYCHAIN_HMAC_SHA1_HASH_SIZE 20 +#define KEYCHAIN_HMAC_SHA256_HASH_SIZE 32 +#define KEYCHAIN_HMAC_SHA384_HASH_SIZE 48 +#define KEYCHAIN_HMAC_SHA512_HASH_SIZE 64 +#define KEYCHAIN_MAX_HASH_SIZE 64 + +#define KEYCHAIN_ALGO_MD5_INTERNAL_BLK_SIZE 16 +#define KEYCHAIN_ALGO_SHA1_INTERNAL_BLK_SIZE 64 +#define KEYCHAIN_ALGO_SHA256_INTERNAL_BLK_SIZE 64 +#define KEYCHAIN_ALGO_SHA384_INTERNAL_BLK_SIZE 128 +#define KEYCHAIN_ALGO_SHA512_INTERNAL_BLK_SIZE 128 +#define KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE 128 + +struct keychain_algo_info { + enum keychain_hash_algo key; + const char *name; + uint32_t length; + uint32_t block; + const char *desc; +}; + +extern const struct keychain_algo_info algo_info[]; +uint32_t keychain_get_block_size(enum keychain_hash_algo key); +uint32_t keychain_get_hash_len(enum keychain_hash_algo key); +const char *keychain_get_description(enum keychain_hash_algo key); +struct keychain_algo_info +keychain_get_hash_algo_info(enum keychain_hash_algo key); +enum keychain_hash_algo keychain_get_algo_id_by_name(const char *name); +const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key); + struct keychain { char *name; @@ -47,7 +88,7 @@ struct key { uint32_t index; char *string; - + enum keychain_hash_algo hash_algo; struct key_range send; struct key_range accept; @@ -60,7 +101,7 @@ extern struct keychain *keychain_lookup(const char *); extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t); extern struct key *key_match_for_accept(const struct keychain *, const char *); extern struct key *key_lookup_for_send(const struct keychain *); - +const char *keychain_algo_str(enum keychain_hash_algo hash_algo); #ifdef __cplusplus } #endif -- 2.39.5