diff options
author | dimitri staessens <dimitri.staessens@ugent.be> | 2017-04-16 11:46:34 +0000 |
---|---|---|
committer | Sander Vrijders <sander.vrijders@ugent.be> | 2017-04-16 11:46:34 +0000 |
commit | 5cbeb1586b7a5a0d5975ee7dc0cd6a2d471b940a (patch) | |
tree | 70abff35ecf47035630d2d3af29600bd6146bd5b | |
parent | 9c6750d70b591af5429fcafbad19aede69e21675 (diff) | |
parent | 97ef24340da7d3f55a39ba16b400d13f9bbe9e60 (diff) | |
download | ouroboros-5cbeb1586b7a5a0d5975ee7dc0cd6a2d471b940a.tar.gz ouroboros-5cbeb1586b7a5a0d5975ee7dc0cd6a2d471b940a.zip |
Merged in dstaesse/ouroboros/be-hashing (pull request #484)
Be hashing
-rw-r--r-- | include/ouroboros/crc32.h | 2 | ||||
-rw-r--r-- | include/ouroboros/endian.h | 2 | ||||
-rw-r--r-- | include/ouroboros/hash.h | 22 | ||||
-rw-r--r-- | include/ouroboros/ipcp.h | 4 | ||||
-rw-r--r-- | include/ouroboros/md5.h | 72 | ||||
-rw-r--r-- | include/ouroboros/sha3.h | 6 | ||||
-rw-r--r-- | src/ipcpd/ipcp.c | 18 | ||||
-rw-r--r-- | src/ipcpd/ipcp.h | 7 | ||||
-rw-r--r-- | src/ipcpd/local/main.c | 4 | ||||
-rw-r--r-- | src/ipcpd/normal/dir.c | 6 | ||||
-rw-r--r-- | src/ipcpd/normal/fmgr.c | 6 | ||||
-rw-r--r-- | src/ipcpd/normal/main.c | 24 | ||||
-rw-r--r-- | src/ipcpd/shim-data.c | 6 | ||||
-rw-r--r-- | src/ipcpd/shim-eth-llc/main.c | 12 | ||||
-rw-r--r-- | src/ipcpd/shim-udp/main.c | 12 | ||||
-rw-r--r-- | src/irmd/ipcp.c | 1 | ||||
-rw-r--r-- | src/irmd/main.c | 43 | ||||
-rw-r--r-- | src/irmd/registry.c | 4 | ||||
-rw-r--r-- | src/irmd/registry.h | 2 | ||||
-rw-r--r-- | src/lib/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/lib/hash.c | 69 | ||||
-rw-r--r-- | src/lib/ipcp_config.proto | 2 | ||||
-rw-r--r-- | src/lib/irm.c | 3 | ||||
-rw-r--r-- | src/lib/md5.c | 255 | ||||
-rw-r--r-- | src/lib/sha3.c | 4 | ||||
-rw-r--r-- | src/lib/tests/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/lib/tests/md5_test.c | 152 | ||||
-rw-r--r-- | src/lib/tests/sha3_test.c | 37 | ||||
-rw-r--r-- | src/tools/irm/irm_ipcp_bootstrap.c | 113 |
29 files changed, 759 insertions, 131 deletions
diff --git a/include/ouroboros/crc32.h b/include/ouroboros/crc32.h index dccdf7cb..800d6c4f 100644 --- a/include/ouroboros/crc32.h +++ b/include/ouroboros/crc32.h @@ -27,6 +27,8 @@ #include <stdint.h> #include <stddef.h> +#define CRC32_HASH_LEN 4 + void crc32(uint32_t * crc, const void * buf, size_t len); diff --git a/include/ouroboros/endian.h b/include/ouroboros/endian.h index 691e3f8b..4738159e 100644 --- a/include/ouroboros/endian.h +++ b/include/ouroboros/endian.h @@ -83,7 +83,7 @@ #define hton64(x) htobe64(x) #define hton32(x) htobe32(x) #define ntoh64(x) betoh64(x) -#define noth32(x) betoh32(x) +#define ntoh32(x) betoh32(x) #define hton16(x) htobe16(x) #define ntoh16(x) betoh16(x) diff --git a/include/ouroboros/hash.h b/include/ouroboros/hash.h index 4779a9a6..60bfbe30 100644 --- a/include/ouroboros/hash.h +++ b/include/ouroboros/hash.h @@ -24,18 +24,30 @@ #ifndef OUROBOROS_LIB_HASH_H #define OUROBOROS_LIB_HASH_H -#include <ouroboros/sha3.h> #include <ouroboros/crc32.h> +#include <ouroboros/md5.h> +#include <ouroboros/sha3.h> + +enum hash_algo { + HASH_CRC32 = 0, + HASH_MD5, + HASH_SHA3_224, + HASH_SHA3_256, + HASH_SHA3_384, + HASH_SHA3_512 +}; #define HASH_FMT "%02x%02x%02x%02x" -#define HASH_VAL(hash) \ +#define HASH_VAL(hash) \ ((*(unsigned int *) hash) & 0xFF000000) >> 24, \ ((*(unsigned int *) hash) & 0x00FF0000) >> 16, \ ((*(unsigned int *) hash) & 0x0000FF00) >> 8, \ ((*(unsigned int *) hash) & 0x000000FF) -/* FIXME: Implement specifying algorithm */ -void get_hash(uint8_t buf[], - const char * name); +uint16_t hash_len(enum hash_algo algo); + +void str_hash(enum hash_algo algo, + void * buf, + const char * str); #endif /* OUROBOROS_LIB_HASH_H */ diff --git a/include/ouroboros/ipcp.h b/include/ouroboros/ipcp.h index f439f29b..4c815b83 100644 --- a/include/ouroboros/ipcp.h +++ b/include/ouroboros/ipcp.h @@ -24,6 +24,8 @@ #ifndef OUROBOROS_IPCP_H #define OUROBOROS_IPCP_H +#include <ouroboros/hash.h> + #include <stdint.h> #include <unistd.h> #include <stdbool.h> @@ -51,7 +53,7 @@ enum pol_gam { struct ipcp_config { char * dif_name; enum ipcp_type type; - uint16_t dir_hash_len; + enum hash_algo dir_hash_algo; /* Normal DIF */ uint8_t addr_size; diff --git a/include/ouroboros/md5.h b/include/ouroboros/md5.h new file mode 100644 index 00000000..a628e6cb --- /dev/null +++ b/include/ouroboros/md5.h @@ -0,0 +1,72 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * MD5 algorithm + * + * Dimitri Staessens <dimitri.staessens@ugent.be> + * Sander Vrijders <sander.vrijders@ugent.be> + * + * This implementation is adapted and redistributed from the RHASH + * project implementation of the MD5 algorithm + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * -- original license + * + * md5.c - an implementation of the MD5 algorithm, based on RFC 1321. + * + * Copyright: 2007-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#ifndef OUROBOROS_LIB_MD5_H +#define OUROBOROS_LIB_MD5_H + +#include "unistd.h" +#include <stdint.h> + +#define MD5_BLOCK_SIZE 64 +#define MD5_HASH_LEN 16 + +struct md5_ctx +{ + /* 512-bit buffer for leftovers */ + uint32_t message[MD5_BLOCK_SIZE / 4]; + /* number of processed bytes */ + uint64_t length; + /* 128-bit algorithm internal hashing state */ + uint32_t hash[4]; +}; + +void rhash_md5_init(struct md5_ctx *ctx); + +void rhash_md5_update(struct md5_ctx * ctx, + const void * msg, + size_t size); + +void rhash_md5_final(struct md5_ctx * ctx, + uint8_t * result); + +#endif /* OUROBOROS_LIB_MD5_H */ diff --git a/include/ouroboros/sha3.h b/include/ouroboros/sha3.h index 17888870..2357b4aa 100644 --- a/include/ouroboros/sha3.h +++ b/include/ouroboros/sha3.h @@ -44,8 +44,8 @@ * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! */ -#ifndef OUROBOROS_SHA3_H -#define OUROBOROS_SHA3_H +#ifndef OUROBOROS_LIB_SHA3_H +#define OUROBOROS_LIB_SHA3_H #include <unistd.h> #include <stdint.h> @@ -83,4 +83,4 @@ void rhash_sha3_update(struct sha3_ctx * ctx, void rhash_sha3_final(struct sha3_ctx * ctx, uint8_t * res); -#endif /* OUROBOROS_SHA3_H */ +#endif /* OUROBOROS_LIB_SHA3_H */ diff --git a/src/ipcpd/ipcp.c b/src/ipcpd/ipcp.c index 77fcb549..d682309d 100644 --- a/src/ipcpd/ipcp.c +++ b/src/ipcpd/ipcp.c @@ -63,23 +63,23 @@ void ipcp_sig_handler(int sig, uint8_t * ipcp_hash_dup(const uint8_t * hash) { - uint8_t * dup = malloc(ipcpi.dir_hash_len); + uint8_t * dup = malloc(hash_len(ipcpi.dir_hash_algo)); if (dup == NULL) return NULL; - memcpy(dup, hash, ipcpi.dir_hash_len); + memcpy(dup, hash, ipcp_dir_hash_len()); return dup; } -void ipcp_hash_str(char buf[DIR_HASH_STRLEN + 1], +void ipcp_hash_str(char * buf, const uint8_t * hash) { size_t i; char * HEX = "0123456789abcdef"; - for (i = 0; i < ipcpi.dir_hash_len; ++i) { + for (i = 0; i < ipcp_dir_hash_len(); ++i) { buf[i * 2] = HEX[(hash[i] & 0xF0) >> 4]; buf[i * 2 + 1] = HEX[hash[i] & 0x0F]; } @@ -212,7 +212,7 @@ static void * ipcp_main_loop(void * o) conf_msg = msg->conf; conf.type = conf_msg->ipcp_type; - conf.dir_hash_len = conf_msg->dir_hash_len; + conf.dir_hash_algo = conf_msg->dir_hash_algo; conf.dif_name = conf_msg->dif_name; if (conf.dif_name == NULL) { ret_msg.has_result = true; @@ -270,7 +270,7 @@ static void * ipcp_main_loop(void * o) break; } - assert(msg->hash.len == ipcpi.dir_hash_len); + assert(msg->hash.len == ipcp_dir_hash_len()); ret_msg.result = ipcpi.ops->ipcp_reg(msg->hash.data); @@ -284,7 +284,7 @@ static void * ipcp_main_loop(void * o) break; } - assert(msg->hash.len == ipcpi.dir_hash_len); + assert(msg->hash.len == ipcp_dir_hash_len()); ret_msg.result = ipcpi.ops->ipcp_unreg(msg->hash.data); @@ -298,7 +298,7 @@ static void * ipcp_main_loop(void * o) break; } - assert(msg->hash.len == ipcpi.dir_hash_len); + assert(msg->hash.len == ipcp_dir_hash_len()); if (ipcp_get_state() != IPCP_OPERATIONAL) { log_err("IPCP in wrong state."); @@ -318,7 +318,7 @@ static void * ipcp_main_loop(void * o) break; } - assert(msg->hash.len == ipcpi.dir_hash_len); + assert(msg->hash.len == ipcp_dir_hash_len()); if (ipcp_get_state() != IPCP_OPERATIONAL) { log_err("IPCP in wrong state."); diff --git a/src/ipcpd/ipcp.h b/src/ipcpd/ipcp.h index d6e2aa7c..c78aa5a6 100644 --- a/src/ipcpd/ipcp.h +++ b/src/ipcpd/ipcp.h @@ -24,6 +24,7 @@ #define IPCPD_IPCP_H #include <ouroboros/config.h> +#include <ouroboros/hash.h> #include <ouroboros/ipcp.h> #include "shim-data.h" @@ -60,7 +61,8 @@ struct ipcp_ops { int (* ipcp_flow_dealloc)(int fd); }; -#define DIR_HASH_STRLEN (ipcpi.dir_hash_len * 2) +#define ipcp_dir_hash_strlen() (hash_len(ipcpi.dir_hash_algo) * 2) +#define ipcp_dir_hash_len() (hash_len(ipcpi.dir_hash_algo)) struct ipcp { int irmd_api; @@ -70,7 +72,8 @@ struct ipcp { char * dif_name; uint64_t dt_addr; - uint16_t dir_hash_len; + + enum hash_algo dir_hash_algo; struct ipcp_ops * ops; int irmd_fd; diff --git a/src/ipcpd/local/main.c b/src/ipcpd/local/main.c index 21ca7400..162ce4d9 100644 --- a/src/ipcpd/local/main.c +++ b/src/ipcpd/local/main.c @@ -119,7 +119,7 @@ static int ipcp_local_bootstrap(const struct ipcp_config * conf) assert(conf); assert(conf->type == THIS_TYPE); - ipcpi.dir_hash_len = conf->dir_hash_len; + ipcpi.dir_hash_algo = conf->dir_hash_algo; ipcp_set_state(IPCP_OPERATIONAL); @@ -198,7 +198,7 @@ static int ipcp_local_flow_alloc(int fd, assert(ipcpi.alloc_id == -1); - out_fd = ipcp_flow_req_arr(getpid(), dst, ipcpi.dir_hash_len, cube); + out_fd = ipcp_flow_req_arr(getpid(), dst, ipcp_dir_hash_len(), cube); if (out_fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_dbg("Flow allocation failed: %d", out_fd); diff --git a/src/ipcpd/normal/dir.c b/src/ipcpd/normal/dir.c index 0249ba06..5ea8a300 100644 --- a/src/ipcpd/normal/dir.c +++ b/src/ipcpd/normal/dir.c @@ -62,7 +62,7 @@ int dir_fini(void) int dir_reg(const uint8_t * hash) { - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; int ret; assert(hash); @@ -91,7 +91,7 @@ int dir_reg(const uint8_t * hash) int dir_unreg(const uint8_t * hash) { - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; size_t len; assert(hash); @@ -121,7 +121,7 @@ int dir_unreg(const uint8_t * hash) int dir_query(const uint8_t * hash) { - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; size_t len; dir_path_reset(); diff --git a/src/ipcpd/normal/fmgr.c b/src/ipcpd/normal/fmgr.c index 5166cc5d..ba36812f 100644 --- a/src/ipcpd/normal/fmgr.c +++ b/src/ipcpd/normal/fmgr.c @@ -439,7 +439,7 @@ int fmgr_np1_alloc(int fd, ssize_t ch; ssize_t i; char ** children; - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; char * dst_ipcp = NULL; ipcp_hash_str(hashstr, dst); @@ -477,7 +477,7 @@ int fmgr_np1_alloc(int fd, msg.code = FLOW_ALLOC_CODE__FLOW_REQ; msg.has_hash = true; - msg.hash.len = ipcpi.dir_hash_len; + msg.hash.len = ipcp_dir_hash_len(); msg.hash.data = (uint8_t *) dst; msg.has_qoscube = true; msg.qoscube = cube; @@ -663,7 +663,7 @@ int fmgr_np1_post_buf(cep_id_t cep_id, fd = ipcp_flow_req_arr(getpid(), msg->hash.data, - ipcpi.dir_hash_len, + ipcp_dir_hash_len(), msg->qoscube); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); diff --git a/src/ipcpd/normal/main.c b/src/ipcpd/normal/main.c index e37a0fbc..67424914 100644 --- a/src/ipcpd/normal/main.c +++ b/src/ipcpd/normal/main.c @@ -69,16 +69,16 @@ static int boot_components(void) return -1; } - len = rib_read(BOOT_PATH "/general/dir_hash_len", - &ipcpi.dir_hash_len, sizeof(ipcpi.dir_hash_len)); + len = rib_read(BOOT_PATH "/general/dir_hash_algo", + &ipcpi.dir_hash_algo, sizeof(ipcpi.dir_hash_algo)); if (len < 0) { log_err("Failed to read hash length: %zd.", len); return -1; } - ipcpi.dir_hash_len = ntoh16(ipcpi.dir_hash_len); + ipcpi.dir_hash_algo = ntoh32(ipcpi.dir_hash_algo); - assert(ipcpi.dir_hash_len != 0); + assert(ipcp_dir_hash_len() != 0); if (rib_add(MEMBERS_PATH, ipcpi.name)) { log_err("Failed to add name to " MEMBERS_PATH); @@ -229,7 +229,7 @@ static int normal_ipcp_enroll(const char * dst) log_dbg("Enrolled with " HASH_FMT, HASH_VAL(dst)); - return 0; + return ipcpi.dir_hash_algo; } const struct ros { @@ -245,7 +245,7 @@ const struct ros { {BOOT_PATH, "general"}, {BOOT_PATH "/general", "dif_name"}, - {BOOT_PATH "/general", "dir_hash_len"}, + {BOOT_PATH "/general", "dir_hash_algo"}, /* DT COMPONENT */ {BOOT_PATH, "dt"}, @@ -293,14 +293,14 @@ int normal_rib_init(void) static int normal_ipcp_bootstrap(const struct ipcp_config * conf) { - uint16_t hash_len; + uint32_t hash_algo; assert(conf); assert(conf->type == THIS_TYPE); - hash_len = hton16((uint16_t) conf->dir_hash_len); + hash_algo = hton32((uint32_t) conf->dir_hash_algo); - assert(ntoh16(hash_len) != 0); + assert(ntoh32(hash_algo) != 0); if (normal_rib_init()) { log_err("Failed to write initial structure to the RIB."); @@ -310,9 +310,9 @@ static int normal_ipcp_bootstrap(const struct ipcp_config * conf) if (rib_write(BOOT_PATH "/general/dif_name", conf->dif_name, strlen(conf->dif_name) + 1) || - rib_write(BOOT_PATH "/general/dir_hash_len", - &hash_len, - sizeof(hash_len)) || + rib_write(BOOT_PATH "/general/dir_hash_algo", + &hash_algo, + sizeof(hash_algo)) || rib_write(BOOT_PATH "/dt/const/addr_size", &conf->addr_size, sizeof(conf->addr_size)) || diff --git a/src/ipcpd/shim-data.c b/src/ipcpd/shim-data.c index 4459837d..2ef48cb0 100644 --- a/src/ipcpd/shim-data.c +++ b/src/ipcpd/shim-data.c @@ -187,7 +187,7 @@ static struct reg_entry * find_reg_entry_by_hash(struct shim_data * data, list_for_each(h, &data->registry) { struct reg_entry * e = list_entry(h, struct reg_entry, list); - if (!memcmp(e->hash, hash, ipcpi.dir_hash_len)) + if (!memcmp(e->hash, hash, ipcp_dir_hash_len())) return e; } @@ -202,7 +202,7 @@ static struct dir_entry * find_dir_entry(struct shim_data * data, list_for_each(h, &data->directory) { struct dir_entry * e = list_entry(h, struct dir_entry, list); if (e->addr == addr && - !memcmp(e->hash, hash, ipcpi.dir_hash_len)) + !memcmp(e->hash, hash, ipcp_dir_hash_len())) return e; } @@ -215,7 +215,7 @@ static struct dir_entry * find_dir_entry_any(struct shim_data * data, struct list_head * h; list_for_each(h, &data->directory) { struct dir_entry * e = list_entry(h, struct dir_entry, list); - if (!memcmp(e->hash, hash, ipcpi.dir_hash_len)) + if (!memcmp(e->hash, hash, ipcp_dir_hash_len())) return e; } diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 5ac3bb6f..36cb12c4 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -350,7 +350,7 @@ static int eth_llc_ipcp_sap_alloc(const uint8_t * dst_addr, msg.has_ssap = true; msg.ssap = ssap; msg.has_hash = true; - msg.hash.len = ipcpi.dir_hash_len; + msg.hash.len = ipcp_dir_hash_len(); msg.hash.data = (uint8_t *) hash; msg.has_qoscube = true; msg.qoscube = cube; @@ -398,7 +398,7 @@ static int eth_llc_ipcp_sap_req(uint8_t r_sap, } /* reply to IRM, called under lock to prevent race */ - fd = ipcp_flow_req_arr(getpid(), dst, ipcpi.dir_hash_len, cube); + fd = ipcp_flow_req_arr(getpid(), dst, ipcp_dir_hash_len(), cube); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_err("Could not get new flow from IRMd."); @@ -464,7 +464,7 @@ static int eth_llc_ipcp_name_query_req(const uint8_t * hash, if (shim_data_reg_has(ipcpi.shim_data, hash)) { msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REPLY; msg.has_hash = true; - msg.hash.len = ipcpi.dir_hash_len; + msg.hash.len = ipcp_dir_hash_len(); msg.hash.data = (uint8_t *) hash; eth_llc_ipcp_send_mgmt_frame(&msg, r_addr); @@ -487,7 +487,7 @@ static int eth_llc_ipcp_name_query_reply(const uint8_t * hash, list_for_each(pos, &ipcpi.shim_data->dir_queries) { struct dir_query * e = list_entry(pos, struct dir_query, next); - if (memcmp(e->hash, hash, ipcpi.dir_hash_len) == 0) { + if (memcmp(e->hash, hash, ipcp_dir_hash_len()) == 0) { shim_data_dir_query_respond(e); } } @@ -758,7 +758,7 @@ static int eth_llc_ipcp_bootstrap(const struct ipcp_config * conf) assert(conf); assert(conf->type == THIS_TYPE); - ipcpi.dir_hash_len = conf->dir_hash_len; + ipcpi.dir_hash_algo = conf->dir_hash_algo; if (conf->if_name == NULL) { log_err("Interface name is NULL."); @@ -942,7 +942,7 @@ static int eth_llc_ipcp_query(const uint8_t * hash) msg.code = SHIM_ETH_LLC_MSG_CODE__NAME_QUERY_REQ; msg.has_hash = true; - msg.hash.len = ipcpi.dir_hash_len; + msg.hash.len = ipcp_dir_hash_len(); msg.hash.data = (uint8_t *) hash; memset(r_addr, 0xff, MAC_SIZE); diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index e1fe5c7c..20e9b272 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -206,7 +206,7 @@ static int ipcp_udp_port_alloc(uint32_t dst_ip_addr, msg.code = SHIM_UDP_MSG_CODE__FLOW_REQ; msg.src_udp_port = src_udp_port; msg.has_hash = true; - msg.hash.len = ipcpi.dir_hash_len; + msg.hash.len = ipcp_dir_hash_len(); msg.hash.data = (uint8_t *) dst; msg.has_qoscube = true; msg.qoscube = cube; @@ -286,7 +286,7 @@ static int ipcp_udp_port_req(struct sockaddr_in * c_saddr, } /* reply to IRM */ - fd = ipcp_flow_req_arr(getpid(), dst, ipcpi.dir_hash_len, cube); + fd = ipcp_flow_req_arr(getpid(), dst, ipcp_dir_hash_len(), cube); if (fd < 0) { pthread_mutex_unlock(&ipcpi.alloc_lock); log_err("Could not get new flow from IRMd."); @@ -534,7 +534,7 @@ static int ipcp_udp_bootstrap(const struct ipcp_config * conf) assert(conf); assert(conf->type == THIS_TYPE); - ipcpi.dir_hash_len = conf->dir_hash_len; + ipcpi.dir_hash_algo = conf->dir_hash_algo; if (inet_ntop(AF_INET, &conf->ip_addr, @@ -749,7 +749,7 @@ static int ipcp_udp_reg(const uint8_t * hash) uint32_t dns_addr; uint32_t ip_addr; #endif - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; uint8_t * hash_dup; assert(hash); @@ -809,7 +809,7 @@ static int ipcp_udp_unreg(const uint8_t * hash) char cmd[100]; uint32_t dns_addr; #endif - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; assert(hash); @@ -846,7 +846,7 @@ static int ipcp_udp_query(const uint8_t * hash) #ifdef CONFIG_OUROBOROS_ENABLE_DNS uint32_t dns_addr = 0; #endif - char hashstr[DIR_HASH_STRLEN + 1]; + char hashstr[ipcp_dir_hash_strlen() + 1]; assert(hash); diff --git a/src/irmd/ipcp.c b/src/irmd/ipcp.c index f0e57dc8..7a32dd88 100644 --- a/src/irmd/ipcp.c +++ b/src/irmd/ipcp.c @@ -212,6 +212,7 @@ int ipcp_bootstrap(pid_t api, return ret; } +/* return the hash algorithm */ int ipcp_enroll(pid_t api, const char * dst) { diff --git a/src/irmd/main.c b/src/irmd/main.c index d55fbbc3..45a348ae 100644 --- a/src/irmd/main.c +++ b/src/irmd/main.c @@ -37,7 +37,6 @@ #include <ouroboros/qos.h> #include <ouroboros/time_utils.h> #include <ouroboros/logs.h> -#include <ouroboros/sha3.h> #include "utils.h" #include "registry.h" @@ -57,6 +56,7 @@ #define IRMD_CLEANUP_TIMER ((IRMD_FLOW_TIMEOUT / 20) * MILLION) /* ns */ #define SHM_SAN_HOLDOFF 1000 /* ms */ +#define IPCP_HASH_LEN(e) (hash_len(e->dir_hash_algo)) struct ipcp_entry { struct list_head next; @@ -64,8 +64,7 @@ struct ipcp_entry { char * name; pid_t api; enum ipcp_type type; - uint16_t dir_hash_len; - /* FIXME: add an enum to specify hash algo */ + enum hash_algo dir_hash_algo; char * dif_name; pthread_cond_t init_cond; @@ -239,13 +238,15 @@ static struct ipcp_entry * get_ipcp_by_dst_name(const char * name) list_for_each(p, &irmd.ipcps) { struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); - hash = malloc(e->dir_hash_len); + if (e->dir_hash_algo < 0) + continue; + hash = malloc(IPCP_HASH_LEN(e)); if (hash == NULL) return NULL; - get_hash(hash, name); + str_hash(e->dir_hash_algo, hash, name); - if (ipcp_query(e->api, hash, e->dir_hash_len) == 0) { + if (ipcp_query(e->api, hash, hash_len(e->dir_hash_algo)) == 0) { free(hash); return e; } @@ -306,8 +307,7 @@ static pid_t create_ipcp(char * name, tmp->dif_name = NULL; tmp->type = ipcp_type; tmp->init = false; - /* FIXME: ipcp dir_hash_len should be configurable */ - tmp->dir_hash_len = SHA3_256_HASH_LEN; + tmp->dir_hash_algo = -1; list_for_each(p, &irmd.ipcps) { struct ipcp_entry * e = list_entry(p, struct ipcp_entry, next); @@ -434,6 +434,8 @@ static int bootstrap_ipcp(pid_t api, return -ENOMEM; } + entry->dir_hash_algo = conf->dir_hash_algo; + pthread_rwlock_unlock(&irmd.reg_lock); log_info("Bootstrapped IPCP %d in DIF %s.", @@ -471,7 +473,8 @@ static int enroll_ipcp(pid_t api, pthread_rwlock_unlock(&irmd.reg_lock); - if (ipcp_enroll(api, dif_name)) { + entry->dir_hash_algo = ipcp_enroll(api, dif_name); + if (entry->dir_hash_algo < 0) { pthread_rwlock_wrlock(&irmd.reg_lock); free(entry->dif_name); entry->dif_name = NULL; @@ -766,13 +769,13 @@ static int name_reg(const char * name, if (wildcard_match(difs[i], e->dif_name)) continue; - hash = malloc(e->dir_hash_len); + hash = malloc(IPCP_HASH_LEN(e)); if (hash == NULL) break; - get_hash(hash, name); + str_hash(e->dir_hash_algo, hash, name); - if (ipcp_reg(e->api, hash, e->dir_hash_len)) { + if (ipcp_reg(e->api, hash, IPCP_HASH_LEN(e))) { log_err("Could not register " HASH_FMT " in DIF %s.", HASH_VAL(hash), e->dif_name); @@ -826,13 +829,13 @@ static int name_unreg(const char * name, if (wildcard_match(difs[i], e->dif_name)) continue; - hash = malloc(e->dir_hash_len); + hash = malloc(IPCP_HASH_LEN(e)); if (hash == NULL) break; - get_hash(hash, name); + str_hash(e->dir_hash_algo, hash, name); - if (ipcp_unreg(e->api, hash, e->dir_hash_len)) { + if (ipcp_unreg(e->api, hash, IPCP_HASH_LEN(e))) { log_err("Could not unregister %s in DIF %s.", name, e->dif_name); } else { @@ -1097,16 +1100,16 @@ static int flow_alloc(pid_t api, assert(irm_flow_get_state(f) == FLOW_ALLOC_PENDING); - hash = malloc(ipcp->dir_hash_len); + hash = malloc(IPCP_HASH_LEN(ipcp)); if (hash == NULL) { /* sanitizer cleans this */ return -ENOMEM; } - get_hash(hash, dst); + str_hash(ipcp->dir_hash_algo, hash, dst); if (ipcp_flow_alloc(ipcp->api, port_id, api, hash, - ipcp->dir_hash_len, cube)) { + IPCP_HASH_LEN(ipcp), cube)) { /* sanitizer cleans this */ log_info("Flow_allocation failed."); free(hash); @@ -1248,8 +1251,8 @@ static struct irm_flow * flow_req_arr(pid_t api, return NULL; } - re = registry_get_entry_by_hash(&irmd.registry, hash, - ipcp->dir_hash_len); + re = registry_get_entry_by_hash(&irmd.registry, ipcp->dir_hash_algo, + hash, IPCP_HASH_LEN(ipcp)); if (re == NULL) { pthread_rwlock_unlock(&irmd.reg_lock); log_err("Unknown hash: " HASH_FMT ".", HASH_VAL(hash)); diff --git a/src/irmd/registry.c b/src/irmd/registry.c index 71e6ea8a..e6571564 100644 --- a/src/irmd/registry.c +++ b/src/irmd/registry.c @@ -27,7 +27,6 @@ #include <ouroboros/logs.h> #include <ouroboros/irm.h> #include <ouroboros/time_utils.h> -#include <ouroboros/hash.h> #include "registry.h" #include "utils.h" @@ -522,6 +521,7 @@ struct reg_entry * registry_get_entry(struct list_head * registry, } struct reg_entry * registry_get_entry_by_hash(struct list_head * registry, + enum hash_algo algo, const uint8_t * hash, size_t len) { @@ -536,7 +536,7 @@ struct reg_entry * registry_get_entry_by_hash(struct list_head * registry, list_for_each(p, registry) { struct reg_entry * e = list_entry(p, struct reg_entry, next); - get_hash(thash, e->name); + str_hash(algo, thash, e->name); if (memcmp(thash, hash, len) == 0) { free(thash); return e; diff --git a/src/irmd/registry.h b/src/irmd/registry.h index 771ca83c..29cefc02 100644 --- a/src/irmd/registry.h +++ b/src/irmd/registry.h @@ -24,6 +24,7 @@ #define OUROBOROS_IRMD_REGISTRY_H #include <ouroboros/config.h> +#include <ouroboros/hash.h> #include <ouroboros/ipcp.h> #include <ouroboros/list.h> #include <ouroboros/shared.h> @@ -115,6 +116,7 @@ struct reg_entry * registry_get_entry(struct list_head * registry, const char * name); struct reg_entry * registry_get_entry_by_hash(struct list_head * registry, + enum hash_algo algo, const uint8_t * hash, size_t len); diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index cb94ef53..263065dd 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -41,6 +41,7 @@ set(SOURCE_FILES list.c lockfile.c logs.c + md5.c nsm.c rib.c sha3.c diff --git a/src/lib/hash.c b/src/lib/hash.c index f4fd75ea..e7806d94 100644 --- a/src/lib/hash.c +++ b/src/lib/hash.c @@ -28,16 +28,69 @@ #include <ouroboros/hash.h> #include <string.h> +#include <assert.h> +#include <stdbool.h> -void get_hash(uint8_t buf[], - const char * name) +uint16_t hash_len(enum hash_algo algo) { - /* currently we only support 256 bit SHA-3 */ - struct sha3_ctx ctx; - - rhash_sha3_256_init(&ctx); + switch (algo) { + case HASH_CRC32: + return CRC32_HASH_LEN; + case HASH_MD5: + return MD5_HASH_LEN; + case HASH_SHA3_224: + return SHA3_224_HASH_LEN; + case HASH_SHA3_256: + return SHA3_256_HASH_LEN; + case HASH_SHA3_384: + return SHA3_384_HASH_LEN; + case HASH_SHA3_512: + return SHA3_512_HASH_LEN; + default: + assert(false); + break; + } +} - rhash_sha3_update(&ctx, name, strlen(name)); +void str_hash(enum hash_algo algo, + void * buf, + const char * str) +{ + struct sha3_ctx sha3_ctx; + struct md5_ctx md5_ctx; - rhash_sha3_final(&ctx, buf); + switch (algo) { + case HASH_CRC32: + memset(buf, 0, CRC32_HASH_LEN); + crc32((uint32_t *) buf, str, strlen(str)); + break; + case HASH_MD5: + rhash_md5_init(&md5_ctx); + rhash_md5_update(&md5_ctx, str, strlen(str)); + rhash_md5_final(&md5_ctx, (uint8_t *) buf); + break; + case HASH_SHA3_224: + rhash_sha3_224_init(&sha3_ctx); + rhash_sha3_update(&sha3_ctx, str, strlen(str)); + rhash_sha3_final(&sha3_ctx, (uint8_t *) buf); + break; + case HASH_SHA3_256: + rhash_sha3_256_init(&sha3_ctx); + rhash_sha3_update(&sha3_ctx, str, strlen(str)); + rhash_sha3_final(&sha3_ctx, (uint8_t *) buf); + break; + case HASH_SHA3_384: + rhash_sha3_384_init(&sha3_ctx); + rhash_sha3_update(&sha3_ctx, str, strlen(str)); + rhash_sha3_final(&sha3_ctx, (uint8_t *) buf); + break; + case HASH_SHA3_512: + rhash_sha3_512_init(&sha3_ctx); + rhash_sha3_update(&sha3_ctx, str, strlen(str)); + rhash_sha3_final(&sha3_ctx, (uint8_t *) buf); + break; + default: + assert(false); + break; + } } diff --git a/src/lib/ipcp_config.proto b/src/lib/ipcp_config.proto index a0c14c41..d5ff75d6 100644 --- a/src/lib/ipcp_config.proto +++ b/src/lib/ipcp_config.proto @@ -25,7 +25,7 @@ syntax = "proto2"; message ipcp_config_msg { required string dif_name = 1; - required uint32 dir_hash_len = 2; + required uint32 dir_hash_algo = 2; required int32 ipcp_type = 3; // Config for normal IPCP optional uint32 addr_size = 4; diff --git a/src/lib/irm.c b/src/lib/irm.c index a2fd5d0b..12d8e8f7 100644 --- a/src/lib/irm.c +++ b/src/lib/irm.c @@ -23,6 +23,7 @@ #include <ouroboros/config.h> #include <ouroboros/errno.h> +#include <ouroboros/hash.h> #include <ouroboros/irm.h> #include <ouroboros/utils.h> #include <ouroboros/sockets.h> @@ -105,7 +106,7 @@ int irm_bootstrap_ipcp(pid_t api, msg.conf = &config; config.dif_name = conf->dif_name; config.ipcp_type = conf->type; - config.dir_hash_len = (uint16_t) conf->dir_hash_len; + config.dir_hash_algo = (enum hash_algo) conf->dir_hash_algo; switch (conf->type) { case IPCP_NORMAL: diff --git a/src/lib/md5.c b/src/lib/md5.c new file mode 100644 index 00000000..4534b6a1 --- /dev/null +++ b/src/lib/md5.c @@ -0,0 +1,255 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * SHA3 algorithm + * + * Dimitri Staessens <dimitri.staessens@ugent.be> + * Sander Vrijders <sander.vrijders@ugent.be> + * + * This implementation is adapted and redistributed from the RHASH + * project + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301 USA + * + * -- original license + * + * md5.c - an implementation of the MD5 algorithm, based on RFC 1321. + * + * Copyright: 2007-2012 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#include <ouroboros/endian.h> +#include <ouroboros/md5.h> + +#include <assert.h> +#include <string.h> + +#define ROTL32(dword, n) ((dword) << (n) ^ ((dword) >> (32 - (n)))) + +void rhash_md5_init(struct md5_ctx *ctx) +{ + ctx->length = 0; + + /* initialize state */ + ctx->hash[0] = 0x67452301; + ctx->hash[1] = 0xefcdab89; + ctx->hash[2] = 0x98badcfe; + ctx->hash[3] = 0x10325476; +} + +#define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z)) +#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) +#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) + +/* transformations for rounds 1, 2, 3, and 4. */ +#define MD5_ROUND1(a, b, c, d, x, s, ac) { \ + (a) += MD5_F((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} + +#define MD5_ROUND2(a, b, c, d, x, s, ac) { \ + (a) += MD5_G((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} + +#define MD5_ROUND3(a, b, c, d, x, s, ac) { \ + (a) += MD5_H((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} + +#define MD5_ROUND4(a, b, c, d, x, s, ac) { \ + (a) += MD5_I((b), (c), (d)) + (x) + (ac); \ + (a) = ROTL32((a), (s)); \ + (a) += (b); \ +} + +static void le32_copy(void * to, + int index, + const void * from, + size_t length) +{ + const uint32_t * src = (const uint32_t *) from; + const uint32_t * end = (const uint32_t *) ((const uint8_t *) + src + length); + uint32_t * dst = (uint32_t *)((uint8_t *) to + index); + while (src < end) + *(dst++) = htole32(*(src++)); +} + +static void rhash_md5_process_block(uint32_t * state, + const unsigned * x) +{ + register uint32_t a = state[0]; + register uint32_t b = state[1]; + register uint32_t c = state[2]; + register uint32_t d = state[3]; + + MD5_ROUND1(a, b, c, d, x[ 0], 7, 0xd76aa478); + MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756); + MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db); + MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee); + MD5_ROUND1(a, b, c, d, x[ 4], 7, 0xf57c0faf); + MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a); + MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613); + MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501); + MD5_ROUND1(a, b, c, d, x[ 8], 7, 0x698098d8); + MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af); + MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1); + MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be); + MD5_ROUND1(a, b, c, d, x[12], 7, 0x6b901122); + MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193); + MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e); + MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821); + + MD5_ROUND2(a, b, c, d, x[ 1], 5, 0xf61e2562); + MD5_ROUND2(d, a, b, c, x[ 6], 9, 0xc040b340); + MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51); + MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); + MD5_ROUND2(a, b, c, d, x[ 5], 5, 0xd62f105d); + MD5_ROUND2(d, a, b, c, x[10], 9, 0x2441453); + MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681); + MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); + MD5_ROUND2(a, b, c, d, x[ 9], 5, 0x21e1cde6); + MD5_ROUND2(d, a, b, c, x[14], 9, 0xc33707d6); + MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87); + MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed); + MD5_ROUND2(a, b, c, d, x[13], 5, 0xa9e3e905); + MD5_ROUND2(d, a, b, c, x[ 2], 9, 0xfcefa3f8); + MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9); + MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a); + + MD5_ROUND3(a, b, c, d, x[ 5], 4, 0xfffa3942); + MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681); + MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122); + MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c); + MD5_ROUND3(a, b, c, d, x[ 1], 4, 0xa4beea44); + MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9); + MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60); + MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70); + MD5_ROUND3(a, b, c, d, x[13], 4, 0x289b7ec6); + MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa); + MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085); + MD5_ROUND3(b, c, d, a, x[ 6], 23, 0x4881d05); + MD5_ROUND3(a, b, c, d, x[ 9], 4, 0xd9d4d039); + MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5); + MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8); + MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665); + + MD5_ROUND4(a, b, c, d, x[ 0], 6, 0xf4292244); + MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97); + MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7); + MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039); + MD5_ROUND4(a, b, c, d, x[12], 6, 0x655b59c3); + MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92); + MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d); + MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1); + MD5_ROUND4(a, b, c, d, x[ 8], 6, 0x6fa87e4f); + MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0); + MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314); + MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1); + MD5_ROUND4(a, b, c, d, x[ 4], 6, 0xf7537e82); + MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235); + MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); + MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391); + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; +} + +void rhash_md5_update(struct md5_ctx * ctx, + const void * pmsg, + size_t size) +{ + uint8_t * msg = (uint8_t *) pmsg; + uint64_t index = ctx->length & 63; + + ctx->length += size; + + /* fill partial block */ + if (index) { + size_t left = MD5_BLOCK_SIZE - index; + + le32_copy((uint8_t *) ctx->message, index, msg, + (size < left ? size : left)); + + if (size < left) + return; + + /* process partial block */ + rhash_md5_process_block(ctx->hash, ctx->message); + msg += left; + size -= left; + } + + while (size >= MD5_BLOCK_SIZE) { + uint32_t * aligned_message_block; + + le32_copy(ctx->message, 0, msg, MD5_BLOCK_SIZE); + aligned_message_block = ctx->message; + + rhash_md5_process_block(ctx->hash, aligned_message_block); + msg += MD5_BLOCK_SIZE; + size -= MD5_BLOCK_SIZE; + } + + if (size) + /* save leftovers */ + le32_copy(ctx->message, 0, msg, size); +} + +void rhash_md5_final(struct md5_ctx * ctx, + uint8_t * result) +{ + uint64_t index = (ctx->length & 63) >> 2; + uint64_t shift = (ctx->length & 3) * 8; + + ctx->message[index] &= ~(0xFFFFFFFF << shift); + ctx->message[index++] ^= 0x80 << shift; + + if (index > 14) { + while (index < 16) + ctx->message[index++] = 0; + + rhash_md5_process_block(ctx->hash, ctx->message); + index = 0; + } + + while (index < 14) + ctx->message[index++] = 0; + + ctx->message[14] = (uint32_t) (ctx->length << 3); + ctx->message[15] = (uint32_t) (ctx->length >> 29); + rhash_md5_process_block(ctx->hash, ctx->message); + + if (result) + le32_copy(result, 0, &ctx->hash, 16); +} diff --git a/src/lib/sha3.c b/src/lib/sha3.c index f80cc4bd..2c8a4614 100644 --- a/src/lib/sha3.c +++ b/src/lib/sha3.c @@ -268,7 +268,9 @@ void rhash_sha3_update(struct sha3_ctx * ctx, size_t block_size = (size_t) ctx->block_size; uint8_t * msg = (uint8_t *) pmsg; - if (ctx->rest & SHA3_FINALIZED) return; + if (ctx->rest & SHA3_FINALIZED) + return; + ctx->rest = (unsigned) ((ctx->rest + size) % block_size); /* fill partial block */ diff --git a/src/lib/tests/CMakeLists.txt b/src/lib/tests/CMakeLists.txt index a9f38c6f..71131929 100644 --- a/src/lib/tests/CMakeLists.txt +++ b/src/lib/tests/CMakeLists.txt @@ -7,6 +7,7 @@ create_test_sourcelist(${PARENT_DIR}_tests test_suite.c btree_test.c crc32_test.c hashtable_test.c + md5_test.c rib_test.c sha3_test.c ) diff --git a/src/lib/tests/md5_test.c b/src/lib/tests/md5_test.c new file mode 100644 index 00000000..684ecb3f --- /dev/null +++ b/src/lib/tests/md5_test.c @@ -0,0 +1,152 @@ +/* + * Ouroboros - Copyright (C) 2016 - 2017 + * + * Test of the MD5 function + * + * Dimitri Staessens <dimitri.staessens@ugent.be> + * Sander Vrijders <sander.vrijders@ugent.be> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <ouroboros/md5.h> + +#include <stdlib.h> +#include <stdint.h> +#include <assert.h> +#include <string.h> +#include <stdio.h> + +static char * hash_to_str(uint8_t * hash, + size_t len) +{ + size_t i; + + char * HEX = "0123456789abcdef"; + char * str; + + str = malloc(len * 2 + 1); + if (str == NULL) + return NULL; + + for (i = 0; i < len; ++i) { + str[i * 2] = HEX[(hash[i] & 0xF0) >> 4]; + str[i * 2 + 1] = HEX[hash[i] & 0x0F]; + } + + str[2 * i] = '\0'; + + return str; +} + +static int check_hash(char * check, + uint8_t * hash, + size_t len) +{ + char * res; + int ret; + + assert(hash); + assert(check); + assert(strlen(check)); + + res = hash_to_str(hash, len); + if (res == NULL) { + printf("Out of memory.\n"); + return -1; + } + + ret = strcmp(res, check); + + printf("hash : %s\n", res); + printf("check : %s\n\n", check); + + free(res); + + return ret; + +} + +int md5_test(int argc, + char ** argv) +{ + struct md5_ctx ctx; + + /* Storage for result. */ + uint8_t res[MD5_HASH_LEN]; + + /* SHA3 test vectors */ + char * str1_inp = "abc"; + + char * str1_md5 = "900150983cd24fb0d6963f7d28e17f72"; + + char * str2_inp = "The quick brown fox jumps over the lazy dog"; + + char * str2_md5 = "9e107d9d372bb6826bd81d3542a419d6"; + + char * str3_inp = + "abcdbcdecdefdefgefghfghighijhijk" + "ijkljklmklmnlmnomnopnopq"; + + char * str3_inp2 = + " abcdbcdecdefdefgefghfghighijhijk" + "ijkljklmklmnlmnomnopnopq"; + + char * str3_md5 = "8215ef0796a20bcaaae116d3876c664a"; + + (void) argc; + (void) argv; + + /* 1st input string. */ + printf("test: %s.\n\n", str1_inp); + + rhash_md5_init(&ctx); + rhash_md5_update(&ctx, str1_inp, strlen(str1_inp)); + rhash_md5_final(&ctx, res); + + if (check_hash(str1_md5, res, MD5_HASH_LEN)) + return -1; + + /* 2nd input string. */ + printf("test: <empty string>.\n\n"); + + rhash_md5_init(&ctx); + rhash_md5_update(&ctx, str2_inp, strlen(str2_inp)); + rhash_md5_final(&ctx, res); + + if (check_hash(str2_md5, res, MD5_HASH_LEN)) + return -1; + + /* 3rd input string */ + printf("test: %s.\n\n", str3_inp); + + rhash_md5_init(&ctx); + rhash_md5_update(&ctx, str3_inp, strlen(str3_inp)); + rhash_md5_final(&ctx, res); + + if (check_hash(str3_md5, res, MD5_HASH_LEN)) + return -1; + + /* unaligned 3rd input string. */ + printf("test: %s.\n\n", str3_inp2 + 1); + + rhash_md5_init(&ctx); + rhash_md5_update(&ctx, str3_inp2 + 1, strlen(str3_inp2 + 1)); + rhash_md5_final(&ctx, res); + + if (check_hash(str3_md5, res, MD5_HASH_LEN)) + return -1; + + return 0; +} diff --git a/src/lib/tests/sha3_test.c b/src/lib/tests/sha3_test.c index 8f1bce05..0d0e8d0a 100644 --- a/src/lib/tests/sha3_test.c +++ b/src/lib/tests/sha3_test.c @@ -149,6 +149,12 @@ int sha3_test(int argc, "ijklmnopjklmnopqklmnopqrlmnopqrs" "mnopqrstnopqrstu"; + char * str4_inp2 = + " abcdefghbcdefghicdefghijdefghijk" + "efghijklfghijklmghijklmnhijklmno" + "ijklmnopjklmnopqklmnopqrlmnopqrs" + "mnopqrstnopqrstu"; + char * str4_224 = "543e6868e1666c1a643630df77367ae5" "a62a85070a51c14cbf665cbc"; @@ -292,5 +298,36 @@ int sha3_test(int argc, if (check_hash(str4_512, res, SHA3_512_HASH_LEN)) return -1; + /* unaligned 4th input string. */ + printf("test: %s.\n\n", str4_inp2 + 1); + + rhash_sha3_224_init(&ctx); + rhash_sha3_update(&ctx, str4_inp2 + 1, strlen(str4_inp2 + 1)); + rhash_sha3_final(&ctx, res); + + if (check_hash(str4_224, res, SHA3_224_HASH_LEN)) + return -1; + + rhash_sha3_256_init(&ctx); + rhash_sha3_update(&ctx, str4_inp2 + 1, strlen(str4_inp2 + 1)); + rhash_sha3_final(&ctx, res); + + if (check_hash(str4_256, res, SHA3_256_HASH_LEN)) + return -1; + + rhash_sha3_384_init(&ctx); + rhash_sha3_update(&ctx, str4_inp2 + 1, strlen(str4_inp2 + 1)); + rhash_sha3_final(&ctx, res); + + if (check_hash(str4_384, res, SHA3_384_HASH_LEN)) + return -1; + + rhash_sha3_512_init(&ctx); + rhash_sha3_update(&ctx, str4_inp2 + 1, strlen(str4_inp2 + 1)); + rhash_sha3_final(&ctx, res); + + if (check_hash(str4_512, res, SHA3_512_HASH_LEN)) + return -1; + return 0; } diff --git a/src/tools/irm/irm_ipcp_bootstrap.c b/src/tools/irm/irm_ipcp_bootstrap.c index 489f98b9..32c09b55 100644 --- a/src/tools/irm/irm_ipcp_bootstrap.c +++ b/src/tools/irm/irm_ipcp_bootstrap.c @@ -34,25 +34,34 @@ #include "irm_ops.h" #include "irm_utils.h" -#define NORMAL "normal" -#define SHIM_UDP "shim-udp" -#define SHIM_ETH_LLC "shim-eth-llc" -#define LOCAL "local" +#define NORMAL "normal" +#define SHIM_UDP "shim-udp" +#define SHIM_ETH_LLC "shim-eth-llc" +#define LOCAL "local" -#define DEFAULT_ADDR_SIZE 4 -#define DEFAULT_CEP_ID_SIZE 2 +#define CRC32 "CRC32" +#define MD5 "MD5" +#define SHA3_224 "SHA3_224" +#define SHA3_256 "SHA3_256" +#define SHA3_384 "SHA3_384" +#define SHA3_512 "SHA3_512" + +#define DEFAULT_HASH_ALGO HASH_SHA3_256 +#define DEFAULT_HASH_STR SHA3_256 +#define DEFAULT_ADDR_SIZE 4 +#define DEFAULT_CEP_ID_SIZE 2 #define DEFAULT_PDU_LEN_SIZE 2 -#define DEFAULT_SEQ_NO_SIZE 4 +#define DEFAULT_SEQ_NO_SIZE 4 #define DEFAULT_MIN_PDU_SIZE 0 #define DEFAULT_MAX_PDU_SIZE 9000 -#define DEFAULT_DDNS 0 -#define DEFAULT_ADDR_AUTH FLAT_RANDOM -#define DEFAULT_DT_GAM COMPLETE -#define DEFAULT_RM_GAM COMPLETE +#define DEFAULT_DDNS 0 +#define DEFAULT_ADDR_AUTH FLAT_RANDOM +#define DEFAULT_DT_GAM COMPLETE +#define DEFAULT_RM_GAM COMPLETE +#define ADDR_AUTH_FLAT "flat" -#define ADDR_AUTH_FLAT "flat" -#define DT_GAM_COMPLETE "complete" -#define RM_GAM_COMPLETE "complete" +#define DT_GAM_COMPLETE "complete" +#define RM_GAM_COMPLETE "complete" static void usage(void) { @@ -61,9 +70,11 @@ static void usage(void) " name <ipcp name>\n" " dif <DIF name>\n" " type [TYPE]\n" -/* FIXME: add option to set hash algorithm and length for directory */ + " [hash [ALGORITHM] (default: %s)]\n" "where TYPE = {" NORMAL " " LOCAL " " - SHIM_UDP " " SHIM_ETH_LLC"}\n\n" + SHIM_UDP " " SHIM_ETH_LLC"},\n" + " ALGORITHM = { " CRC32 " " MD5 " " + SHA3_224 " " SHA3_256 " " SHA3_384 " " SHA3_512 "}.\n\n" "if TYPE == " NORMAL "\n" " [addr <address size> (default: %d)]\n" " [cep_id <CEP-id size> (default: %d)]\n" @@ -75,16 +86,16 @@ static void usage(void) " [max_pdu <maximum PDU size> (default: %d)]\n" " [addr_auth <address policy> (default: %s)]\n" " [dt_gam <data transfer graph adjacency manager>" - "(default: %s)]\n" + " (default: %s)]\n" " [rm_gam <rib manager graph adjacency manager>" - "(default: %s)]\n" + " (default: %s)]\n" "if TYPE == " SHIM_UDP "\n" " ip <IP address in dotted notation>\n" " [dns <DDNS IP address in dotted notation>" " (default = none: %d)]\n" "if TYPE == " SHIM_ETH_LLC "\n" " if_name <interface name>\n", - DEFAULT_ADDR_SIZE, DEFAULT_CEP_ID_SIZE, + DEFAULT_HASH_STR, DEFAULT_ADDR_SIZE, DEFAULT_CEP_ID_SIZE, DEFAULT_PDU_LEN_SIZE, DEFAULT_SEQ_NO_SIZE, DEFAULT_MIN_PDU_SIZE, DEFAULT_MAX_PDU_SIZE, ADDR_AUTH_FLAT, DT_GAM_COMPLETE, RM_GAM_COMPLETE, DEFAULT_DDNS); @@ -92,29 +103,29 @@ static void usage(void) int do_bootstrap_ipcp(int argc, char ** argv) { - char * name = NULL; - pid_t api; + char * name = NULL; + char * hash = DEFAULT_HASH_STR; + pid_t api; struct ipcp_config conf; - uint8_t addr_size = DEFAULT_ADDR_SIZE; - uint8_t cep_id_size = DEFAULT_CEP_ID_SIZE; - uint8_t pdu_length_size = DEFAULT_PDU_LEN_SIZE; - uint8_t seqno_size = DEFAULT_SEQ_NO_SIZE; - bool has_ttl = false; - bool has_chk = false; - uint32_t min_pdu_size = DEFAULT_MIN_PDU_SIZE; - uint32_t max_pdu_size = DEFAULT_MAX_PDU_SIZE; - enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; - enum pol_gam dt_gam_type = DEFAULT_DT_GAM; - enum pol_gam rm_gam_type = DEFAULT_RM_GAM; - uint32_t ip_addr = 0; - uint32_t dns_addr = DEFAULT_DDNS; - char * ipcp_type = NULL; - char * dif_name = NULL; - char * if_name = NULL; - pid_t * apis = NULL; - ssize_t len = 0; - int i = 0; - uint16_t dir_hash_len = SHA3_256_HASH_LEN; + uint8_t addr_size = DEFAULT_ADDR_SIZE; + uint8_t cep_id_size = DEFAULT_CEP_ID_SIZE; + uint8_t pdu_length_size = DEFAULT_PDU_LEN_SIZE; + uint8_t seqno_size = DEFAULT_SEQ_NO_SIZE; + bool has_ttl = false; + bool has_chk = false; + uint32_t min_pdu_size = DEFAULT_MIN_PDU_SIZE; + uint32_t max_pdu_size = DEFAULT_MAX_PDU_SIZE; + enum pol_addr_auth addr_auth_type = DEFAULT_ADDR_AUTH; + enum pol_gam dt_gam_type = DEFAULT_DT_GAM; + enum pol_gam rm_gam_type = DEFAULT_RM_GAM; + uint32_t ip_addr = 0; + uint32_t dns_addr = DEFAULT_DDNS; + char * ipcp_type = NULL; + char * dif_name = NULL; + char * if_name = NULL; + pid_t * apis = NULL; + ssize_t len = 0; + int i = 0; while (argc > 0) { if (matches(*argv, "type") == 0) { @@ -123,6 +134,8 @@ int do_bootstrap_ipcp(int argc, char ** argv) dif_name = *(argv + 1); } else if (matches(*argv, "name") == 0) { name = *(argv + 1); + } else if (matches(*argv, "hash") == 0) { + hash = *(argv + 1); } else if (matches(*argv, "ip") == 0) { if (inet_pton (AF_INET, *(argv + 1), &ip_addr) != 1) { usage(); @@ -180,7 +193,23 @@ int do_bootstrap_ipcp(int argc, char ** argv) } conf.dif_name = dif_name; - conf.dir_hash_len = dir_hash_len; + + if (strcmp(hash, CRC32) == 0) { + conf.dir_hash_algo = HASH_CRC32; + } else if (strcmp(hash, MD5) == 0) { + conf.dir_hash_algo = HASH_MD5; + } else if (strcmp(hash, SHA3_224) == 0) { + conf.dir_hash_algo = HASH_SHA3_224; + } else if (strcmp(hash, SHA3_256) == 0) { + conf.dir_hash_algo = HASH_SHA3_256; + } else if (strcmp(hash, SHA3_384) == 0) { + conf.dir_hash_algo = HASH_SHA3_384; + } else if (strcmp(hash, SHA3_512) == 0) { + conf.dir_hash_algo = HASH_SHA3_512; + } else { + usage(); + return -1; + } if (strcmp(ipcp_type, NORMAL) == 0) { conf.type = IPCP_NORMAL; |