summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ouroboros/crc32.h2
-rw-r--r--include/ouroboros/endian.h2
-rw-r--r--include/ouroboros/hash.h22
-rw-r--r--include/ouroboros/ipcp.h4
-rw-r--r--include/ouroboros/md5.h72
-rw-r--r--include/ouroboros/sha3.h6
-rw-r--r--src/ipcpd/ipcp.c18
-rw-r--r--src/ipcpd/ipcp.h7
-rw-r--r--src/ipcpd/local/main.c4
-rw-r--r--src/ipcpd/normal/dir.c6
-rw-r--r--src/ipcpd/normal/fmgr.c6
-rw-r--r--src/ipcpd/normal/main.c24
-rw-r--r--src/ipcpd/shim-data.c6
-rw-r--r--src/ipcpd/shim-eth-llc/main.c12
-rw-r--r--src/ipcpd/shim-udp/main.c12
-rw-r--r--src/irmd/ipcp.c1
-rw-r--r--src/irmd/main.c43
-rw-r--r--src/irmd/registry.c4
-rw-r--r--src/irmd/registry.h2
-rw-r--r--src/lib/CMakeLists.txt1
-rw-r--r--src/lib/hash.c69
-rw-r--r--src/lib/ipcp_config.proto2
-rw-r--r--src/lib/irm.c3
-rw-r--r--src/lib/md5.c255
-rw-r--r--src/lib/sha3.c4
-rw-r--r--src/lib/tests/CMakeLists.txt1
-rw-r--r--src/lib/tests/md5_test.c152
-rw-r--r--src/lib/tests/sha3_test.c37
-rw-r--r--src/tools/irm/irm_ipcp_bootstrap.c113
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 <[email protected]>
+ * Sander Vrijders <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ * Sander Vrijders <[email protected]>
+ *
+ * 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 <[email protected]>
+ *
+ * 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 <[email protected]>
+ * Sander Vrijders <[email protected]>
+ *
+ * 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;