From 1e86edd3212fc6ffa93bd99a21f529c9116c04e5 Mon Sep 17 00:00:00 2001 From: Jon Titor Date: Tue, 3 Oct 2017 15:14:46 -0400 Subject: [PATCH] more --- Makefile | 22 +++-- daemon/main.c | 6 +- include/sarp/buffer.h | 18 ++++ include/sarp/config.h | 19 ++++ include/sarp/crypto.h | 44 +++++++++ include/sarp/mem.h | 26 +++++ include/sarp/router.h | 19 ++++ libsarp/config.cpp | 57 +++++++++++ libsarp/crypto_libsodium.cpp | 52 ++++++++++ libsarp/ini.hpp | 186 +++++++++++++++++++++++++++++++++++ libsarp/mem_jemalloc.cpp | 35 +++++++ libsarp/mem_std.cpp | 41 ++++++++ libsarp/sarp.c | 2 - readme.md | 10 ++ 14 files changed, 524 insertions(+), 13 deletions(-) create mode 100644 include/sarp/buffer.h create mode 100644 include/sarp/config.h create mode 100644 include/sarp/crypto.h create mode 100644 include/sarp/mem.h create mode 100644 libsarp/config.cpp create mode 100644 libsarp/crypto_libsodium.cpp create mode 100644 libsarp/ini.hpp create mode 100644 libsarp/mem_jemalloc.cpp create mode 100644 libsarp/mem_std.cpp delete mode 100644 libsarp/sarp.c diff --git a/Makefile b/Makefile index 012292ae6..4bcbe56bd 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,10 @@ REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) EXE = $(REPO)/sarpd -LIB = sarp -STATIC_LIB = $(REPO)/lib$(LIB).a +STATIC_LIB = $(REPO)/libsarp.a -STATIC_SRC = $(wildcard $(REPO)/libsarp/*.c) -STATIC_OBJ = $(STATIC_SRC:.c=.o) +STATIC_SRC = $(wildcard $(REPO)/libsarp/*.cpp) +STATIC_OBJ = $(STATIC_SRC:.cpp=.cpp.o) DAEMON_SRC = $(wildcard $(REPO)/daemon/*.c) DAEMON_OBJ = $(DAEMON_SRC:.c=.o) @@ -14,21 +13,24 @@ PKG = pkg-config PKGS = libsodium -REQUIRED_CFLAGS = $(CFLAGS) $(shell $(PKG) --cflags $(PKGS)) -I $(REPO)/include -std=c99 -REQUIRED_LDFLAGS = $(LDFLAGS) $(shell $(PKG) --libs $(PKGS)) +REQUIRED_CFLAGS = $(shell $(PKG) --cflags $(PKGS)) -I$(REPO)/include -std=c99 +REQUIRED_CXXFLAGS = $(shell $(PKG) --cflags $(PKGS)) -I$(REPO)/include -std=c++17 +REQUIRED_LDFLAGS = $(LDFLAGS) $(shell $(PKG) --libs $(PKGS)) -ljemalloc +CXXFLAGS := $(REQUIRED_CXXFLAGS) +CFLAGS := $(REQUIRED_CFLAGS) all: build build: $(EXE) $(EXE): $(DAEMON_OBJ) $(STATIC_LIB) - $(CC) $(REQUIRED_CFLAGS) $(REQUIRED_LDFLAGS) -o $(EXE) $(DAEMON_OBJ) $(STATIC_LIB) + $(CXX) $(DAEMON_OBJ) $(STATIC_LIB) $(REQUIRED_LDFLAGS) -o $(EXE) + +%.cpp.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $<.o $(STATIC_LIB): $(STATIC_OBJ) $(AR) -r $(STATIC_LIB) $(STATIC_OBJ) -%.o: %.c - $(CC) $(REQUIRED_CFLAGS) -c $^ -o $@ - clean: $(RM) $(DAEMON_OBJ) $(EXE) $(STATIC_OBJ) $(STATIC_LIB) diff --git a/daemon/main.c b/daemon/main.c index 70b510c6e..b492c7ed6 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -1,6 +1,10 @@ - +#include int main(int argc, char * argv[]) { + struct sarp_router * router = NULL; + struct sarp_alloc mem; + sarp_mem_jemalloc(&mem); + return 0; } diff --git a/include/sarp/buffer.h b/include/sarp/buffer.h new file mode 100644 index 000000000..8e0599aad --- /dev/null +++ b/include/sarp/buffer.h @@ -0,0 +1,18 @@ +#ifndef SARP_BUFFER_H_ +#define SARP_BUFFER_H_ +#ifdef __cplusplus +extern "C" { +#endif +#include +#include + +typedef struct { + uint8_t * ptr; + size_t sz; +} sarp_buffer_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sarp/config.h b/include/sarp/config.h new file mode 100644 index 000000000..a79f73519 --- /dev/null +++ b/include/sarp/config.h @@ -0,0 +1,19 @@ +#ifndef SARP_CONFIG_H_ +#define SARP_CONFIG_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct sarp_config; + +void sarp_new_config(struct sarp_config ** conf, struct sarp_alloc * mem); +void sarp_free_config(struct sarp_config ** conf); + +int sarp_load_config(struct sarp_config * conf, const char * fname); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include/sarp/crypto.h b/include/sarp/crypto.h new file mode 100644 index 000000000..e26bac3a0 --- /dev/null +++ b/include/sarp/crypto.h @@ -0,0 +1,44 @@ +#ifndef SARP_CRYPTO_H_ +#define SARP_CRYPTO_H_ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PUBKEYSIZE 32 +#define SECKEYSIZE 32 +#define SYMKEYSIZE 32 +#define NOUNCESIZE 24 +#define SHAREDKEYSIZE 64 +#define HASHSIZE 64 +#define HMACSECSIZE 32 +#define SIGSIZE 64 + +typedef uint8_t sarp_pubkey_t[PUBKEYSIZE]; +typedef uint8_t sarp_seckey_t[SECKEYSIZE]; +typedef uint8_t sarp_symkey_t[SYMKEYSIZE]; +typedef uint8_t sarp_nounce_t[NOUNCESIZE]; +typedef uint8_t sarp_sharedkey_t[SHAREDKEYSIZE]; +typedef uint8_t sarp_hash_t[HASHSIZE]; +typedef uint8_t sarp_hmacsec_t[HMACSECSIZE]; +typedef uint8_t sarp_sig_t[SIGSIZE]; + +struct sarp_crypto +{ + int (*xchacha20)(sarp_buffer_t, sarp_symkey_t, sarp_nounce_t); + int (*dh_client)(sarp_sharedkey_t *, sarp_pubkey_t, sarp_seckey_t); + int (*dh_server)(sarp_sharedkey_t *, sarp_pubkey_t, sarp_seckey_t); + int (*hash)(sarp_hash_t *, sarp_buffer_t); + int (*mhac)(sarp_hash_t *, sarp_buffer_t, sarp_hmacsec_t); + int (*sign)(sarp_sig_t *, sarp_seckey_t, sarp_buffer_t); + int (*verify)(sarp_pubkey_t, sarp_buffer_t, sarp_sig_t); +}; + +void sarp_crypto_libsodium_init(struct sarp_crypto * c); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/sarp/mem.h b/include/sarp/mem.h new file mode 100644 index 000000000..f45356506 --- /dev/null +++ b/include/sarp/mem.h @@ -0,0 +1,26 @@ +#ifndef SARP_MEM_H_ +#define SARP_MEM_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct sarp_alloc +{ + void * (*malloc)(size_t sz); + void * (*realloc)(void * ptr, size_t sz); + void * (*calloc)(size_t n, size_t sz); + void (*free)(void * ptr); +}; +void sarp_mem_jemalloc(struct sarp_alloc * mem); +void sarp_mem_libc(struct sarp_alloc * mem); +void sarp_mem_dmalloc(struct sarp_alloc * mem); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/sarp/router.h b/include/sarp/router.h index cfb577d89..81313e210 100644 --- a/include/sarp/router.h +++ b/include/sarp/router.h @@ -1,5 +1,24 @@ #ifndef SARP_ROUTER_H_ #define SARP_ROUTER_H_ +#include +#include +#ifdef __cplusplus +extern "C" { +#endif + +struct sarp_router; + +void sarp_init_router(struct sarp_router ** router, struct sarp_alloc * mem); +void sarp_free_router(struct sarp_router ** router); + +int sarp_configure_router(struct sarp_router * router, struct sarp_config * conf); + +void sarp_run_router(struct sarp_router * router); +void sarp_stop_router(struct sarp_router * router); + +#ifdef __cplusplus +} +#endif #endif diff --git a/libsarp/config.cpp b/libsarp/config.cpp new file mode 100644 index 000000000..4c407105f --- /dev/null +++ b/libsarp/config.cpp @@ -0,0 +1,57 @@ +#include +#include "ini.hpp" + +namespace sarp +{ + struct config + { + typedef std::map section_t; + section_t router; + section_t network; + section_t netdb; + + bool Load(const char * fname) + { + std::ifstream f; + f.open(fname); + if(f.is_open()) + { + ini::Parser parser(f); + auto & top = parser.top(); + + return true; + } + return false; + }; + + }; +} + + +extern "C" { + struct sarp_config + { + sarp::config impl; + sarp_alloc * mem; + }; + + void sarp_new_config(struct sarp_config ** conf, struct sarp_alloc * mem) + { + sarp_config * c = static_cast(mem->malloc(sizeof(struct sarp_config))); + c->mem = mem; + *conf = c; + } + + void sarp_free_config(struct sarp_config ** conf) + { + sarp_alloc * mem = (*conf)->mem; + mem->free(*conf); + *conf = nullptr; + } + + int sarp_load_config(struct sarp_config * conf, const char * fname) + { + if(!conf->impl.Load(fname)) return -1; + return 0; + } +} diff --git a/libsarp/crypto_libsodium.cpp b/libsarp/crypto_libsodium.cpp new file mode 100644 index 000000000..dad707b43 --- /dev/null +++ b/libsarp/crypto_libsodium.cpp @@ -0,0 +1,52 @@ +#include +#include +#include +#include + +namespace sarp +{ + namespace sodium + { + int xchacha20(sarp_buffer_t buff, sarp_symkey_t k, sarp_nounce_t n) + { + return crypto_stream_xchacha20_xor(buff.ptr, buff.ptr, buff.sz, n, k); + } + + int dh(sarp_sharedkey_t * shared, uint8_t * client_pk, uint8_t * server_pk, uint8_t * remote_key, uint8_t * local_key) + { + uint8_t * out = *shared; + const size_t outsz = sizeof(sarp_sharedkey_t); + crypto_generichash_state h; + if(crypto_scalarmult(out, local_key, remote_key) == -1) return -1; + crypto_generichash_init(&h, NULL, 0U, outsz); + crypto_generichash_update(&h, client_pk, sizeof(sarp_pubkey_t)); + crypto_generichash_update(&h, server_pk, sizeof(sarp_pubkey_t)); + crypto_generichash_update(&h, out, crypto_scalarmult_BYTES); + crypto_generichash_final(&h, out, outsz); + return 0; + } + + int dh_client(sarp_sharedkey_t * shared, sarp_pubkey_t pk, sarp_seckey_t sk) + { + sarp_pubkey_t local_pk; + crypto_scalarmult_base(local_pk, sk); + return dh(shared, local_pk, pk, pk, sk); + } + + int dh_server(sarp_sharedkey_t * shared, sarp_pubkey_t pk, sarp_seckey_t sk) + { + sarp_pubkey_t local_pk; + crypto_scalarmult_base(local_pk, sk); + return dh(shared, pk, local_pk, pk, sk); + } + } +} + +extern "C" { + void sarp_crypto_libsodium_init(struct sarp_crypto * c) + { + c->xchacha20 = sarp::sodium::xchacha20; + c->dh_client = sarp::sodium::dh_client; + c->dh_server = sarp::sodium::dh_server; + } +} diff --git a/libsarp/ini.hpp b/libsarp/ini.hpp new file mode 100644 index 000000000..534d2b116 --- /dev/null +++ b/libsarp/ini.hpp @@ -0,0 +1,186 @@ +/** + * The MIT License (MIT) + * Copyright (c) <2015> + * + * 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, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#ifndef INI_HPP +#define INI_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace ini { + +struct Level +{ + Level() : parent(NULL), depth(0) {} + Level(Level* p) : parent(p), depth(0) {} + + typedef std::map value_map_t; + typedef std::map section_map_t; + typedef std::list values_t; + typedef std::list sections_t; + value_map_t values; + section_map_t sections; + values_t ordered_values; // original order in the ini file + sections_t ordered_sections; + Level* parent; + size_t depth; + + const std::string& operator[](const std::string& name) { return values[name]; } + Level& operator()(const std::string& name) { return sections[name]; } +}; + +class Parser +{ +public: + Parser(const std::string & fname) : Parser(fname.c_str()) {} + Parser(const char* fn); + Parser(std::istream& f) : f_(&f), ln_(0) { parse(top_); } + Level& top() { return top_; } + void dump(std::ostream& s) { dump(s, top(), ""); } + +private: + void dump(std::ostream& s, const Level& l, const std::string& sname); + void parse(Level& l); + void parseSLine(std::string& sname, size_t& depth); + void err(const char* s); + +private: + Level top_; + std::ifstream f0_; + std::istream* f_; + std::string line_; + size_t ln_; +}; + +inline void +Parser::err(const char* s) +{ + char buf[256]; + sprintf(buf, "%s on line #%ld", s, ln_); + throw std::runtime_error(buf); +} + +inline std::string trim(const std::string& s) +{ + char p[] = " \t\r\n"; + long sp = 0; + long ep = s.length() - 1; + for (; sp <= ep; ++sp) + if (!strchr(p, s[sp])) break; + for (; ep >= 0; --ep) + if (!strchr(p, s[ep])) break; + return s.substr(sp, ep-sp+1); +} + +inline +Parser::Parser(const char* fn) : f0_(fn), f_(&f0_), ln_(0) +{ + if (!f0_) + throw std::runtime_error(std::string("failed to open file: ") + fn); + + parse(top_); +} + +inline void +Parser::parseSLine(std::string& sname, size_t& depth) +{ + depth = 0; + for (; depth < line_.length(); ++depth) + if (line_[depth] != '[') break; + + sname = line_.substr(depth, line_.length() - 2*depth); +} + +inline void +Parser::parse(Level& l) +{ + while (std::getline(*f_, line_)) { + ++ln_; + if (line_[0] == '#' || line_[0] == ';') continue; + line_ = trim(line_); + if (line_.empty()) continue; + if (line_[0] == '[') { + size_t depth; + std::string sname; + parseSLine(sname, depth); + Level* lp = NULL; + Level* parent = &l; + if (depth > l.depth + 1) + err("section with wrong depth"); + if (l.depth == depth-1) + lp = &l.sections[sname]; + else { + lp = l.parent; + size_t n = l.depth - depth; + for (size_t i = 0; i < n; ++i) lp = lp->parent; + parent = lp; + lp = &lp->sections[sname]; + } + if (lp->depth != 0) + err("duplicate section name on the same level"); + if (!lp->parent) { + lp->depth = depth; + lp->parent = parent; + } + parent->ordered_sections.push_back(parent->sections.find(sname)); + parse(*lp); + } else { + size_t n = line_.find('='); + if (n == std::string::npos) + err("no '=' found"); + std::pair res = + l.values.insert(std::make_pair(trim(line_.substr(0, n)), + trim(line_.substr(n+1, line_.length()-n-1)))); + if (!res.second) + err("duplicated key found"); + l.ordered_values.push_back(res.first); + } + } +} + +inline void +Parser::dump(std::ostream& s, const Level& l, const std::string& sname) +{ + if (!sname.empty()) s << '\n'; + for (size_t i = 0; i < l.depth; ++i) s << '['; + if (!sname.empty()) s << sname; + for (size_t i = 0; i < l.depth; ++i) s << ']'; + if (!sname.empty()) s << std::endl; + for (Level::values_t::const_iterator it = l.ordered_values.begin(); it != l.ordered_values.end(); ++it) + s << (*it)->first << '=' << (*it)->second << std::endl; + for (Level::sections_t::const_iterator it = l.ordered_sections.begin(); it != l.ordered_sections.end(); ++it) { + assert((*it)->second.depth == l.depth+1); + dump(s, (*it)->second, (*it)->first); + } +} + +} + +#endif // INI_HPP diff --git a/libsarp/mem_jemalloc.cpp b/libsarp/mem_jemalloc.cpp new file mode 100644 index 000000000..d72f3b0ec --- /dev/null +++ b/libsarp/mem_jemalloc.cpp @@ -0,0 +1,35 @@ +#include +#include + +namespace sarp +{ + static void * jem_malloc(size_t sz) + { + return mallocx(sz, MALLOCX_ZERO); + } + + static void jem_free(void * ptr) + { + if(ptr) free(ptr); + } + + static void * jem_calloc(size_t n, size_t sz) + { + return mallocx(n * sz, MALLOCX_ZERO); + } + + static void * jem_realloc(void * ptr, size_t sz) + { + return rallocx(ptr, sz, MALLOCX_ZERO); + } +} + +extern "C" { + void sarp_mem_jemalloc(struct sarp_alloc * mem) + { + mem->malloc = sarp::jem_malloc; + mem->free = sarp::jem_free; + mem->calloc = sarp::jem_calloc; + mem->realloc = sarp::jem_realloc; + } +} diff --git a/libsarp/mem_std.cpp b/libsarp/mem_std.cpp new file mode 100644 index 000000000..c4c50c2ae --- /dev/null +++ b/libsarp/mem_std.cpp @@ -0,0 +1,41 @@ +#include + +namespace sarp +{ + void * std_malloc(size_t sz) + { + void * ptr = malloc(sz); + if(ptr) return ptr; + abort(); + } + + void std_free(void * ptr) + { + if(ptr) free(ptr); + } + + void * std_calloc(size_t n, size_t sz) + { + void * ptr = calloc(n, sz); + if (ptr) return ptr; + abort(); + } + + void * std_realloc(void * ptr, size_t sz) + { + ptr = realloc(ptr, sz); + if (ptr) return ptr; + abort(); + } + +} + +extern "C" { + void sarp_mem_std(struct sarp_alloc * mem) + { + mem->malloc = sarp::std_malloc; + mem->free = sarp::std_free; + mem->calloc = sarp::std_calloc; + mem->realloc = sarp::std_realloc; + } +} diff --git a/libsarp/sarp.c b/libsarp/sarp.c deleted file mode 100644 index 139597f9c..000000000 --- a/libsarp/sarp.c +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/readme.md b/readme.md index a7bf7f8ab..9e975bec8 100644 --- a/readme.md +++ b/readme.md @@ -3,3 +3,13 @@ Simple Anon Routing Protocol [rfc](doc/proto_v0.txt) + +## ref impl + +Build requirements: + +* GNU Make +* pkg-config +* libsodium >= 1.0.14 +* c++ 17 capable C++ compiler +* c99 compliant C compiler