diff --git a/include/libsodium/sodium/core.h b/include/libsodium/sodium/core.h
new file mode 100644
index 0000000..fd8980b
--- /dev/null
+++ b/include/libsodium/sodium/core.h
@@ -0,0 +1,28 @@
+
+#ifndef sodium_core_H
+#define sodium_core_H
+
+#include "export.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SODIUM_EXPORT
+int sodium_init(void)
+ __attribute__ ((warn_unused_result));
+
+/* ---- */
+
+SODIUM_EXPORT
+int sodium_set_misuse_handler(void (*handler)(void));
+
+extern void _sodium_misuse(char const *file, int line);
+
+#define sodium_misuse(...) _sodium_misuse(__FILE__, __LINE__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/libsodium/sodium/version.h b/include/libsodium/sodium/version.h
new file mode 100644
index 0000000..f916e08
--- /dev/null
+++ b/include/libsodium/sodium/version.h
@@ -0,0 +1,6 @@
+/*
+ * \brief Dummy version header needed by libsodium
+ * \author Stefan Kalkowski
+ * \date 2016-02-11
+ */
+
diff --git a/lib/import/import-libsodium.mk b/lib/import/import-libsodium.mk
new file mode 100644
index 0000000..739c6a6
--- /dev/null
+++ b/lib/import/import-libsodium.mk
@@ -0,0 +1,7 @@
+LIBSODIUM_PORT_DIR = $(call select_from_ports,libsodium)
+LIBSODIUM_REP_INC = $(call select_from_repositories,include/libsodium)
+
+INC_DIR += $(LIBSODIUM_PORT_DIR)/include/libsodium
+INC_DIR += $(LIBSODIUM_PORT_DIR)/include/libsodium/sodium
+INC_DIR += $(LIBSODIUM_REP_INC)
+INC_DIR += $(LIBSODIUM_REP_INC)/sodium
diff --git a/lib/mk/libsodium.mk b/lib/mk/libsodium.mk
new file mode 100644
index 0000000..ae27fba
--- /dev/null
+++ b/lib/mk/libsodium.mk
@@ -0,0 +1,30 @@
+include $(REP_DIR)/lib/import/import-libsodium.mk
+
+LIBSODIUM_PORT_DIR = $(call select_from_ports,libsodium)
+LIBSODIUM_SRC_DIR = $(call select_from_ports,libsodium)/src/lib/libsodium/src/libsodium
+
+LIBS += jitterentropy libc
+
+CC_DEF += -DSODIUM_VERSION_STRING=\"\"
+CC_DEF += -DSODIUM_LIBRARY_VERSION_MAJOR=0
+CC_DEF += -DSODIUM_LIBRARY_VERSION_MINOR=0
+CC_DEF += -DHAVE_ATOMIC_OPS
+
+EXPERT_CRYPTO_MAGIC := $(wildcard \
+ $(LIBSODIUM_SRC_DIR)/*/*.c \
+ $(LIBSODIUM_SRC_DIR)/*/*/*.c \
+ $(LIBSODIUM_SRC_DIR)/*/*/*/*.c)
+
+TOO_MUCH_MAGIC = core.c randombytes_sysrandom.c argon
+
+SRC_C += $(filter-out $(TOO_MUCH_MAGIC),$(notdir $(EXPERT_CRYPTO_MAGIC)))
+SRC_C += onetimeauth_poly1305.c
+vpath %.c $(sort $(dir $(EXPERT_CRYPTO_MAGIC)))
+
+SRC_C += randombytes_salsa20_jitterentropy.c
+vpath randombytes_salsa20_jitterentropy.c $(REP_DIR)/src/lib/libsodium
+
+SRC_CC += genode_core.cc
+vpath %.cc $(REP_DIR)/src/lib/libsodium
+
+SHARED_LIB = 1
diff --git a/lib/symbols/libsodium b/lib/symbols/libsodium
new file mode 100644
index 0000000..6ad7872
--- /dev/null
+++ b/lib/symbols/libsodium
@@ -0,0 +1,404 @@
+PBKDF2_SHA256 T
+crypto_aead_aes256gcm_is_available T
+crypto_aead_chacha20poly1305_abytes T
+crypto_aead_chacha20poly1305_decrypt T
+crypto_aead_chacha20poly1305_encrypt T
+crypto_aead_chacha20poly1305_ietf_decrypt T
+crypto_aead_chacha20poly1305_ietf_encrypt T
+crypto_aead_chacha20poly1305_ietf_npubbytes T
+crypto_aead_chacha20poly1305_keybytes T
+crypto_aead_chacha20poly1305_npubbytes T
+crypto_aead_chacha20poly1305_nsecbytes T
+crypto_auth T
+crypto_auth_bytes T
+crypto_auth_hmacsha256 T
+crypto_auth_hmacsha256_bytes T
+crypto_auth_hmacsha256_final T
+crypto_auth_hmacsha256_init T
+crypto_auth_hmacsha256_keybytes T
+crypto_auth_hmacsha256_statebytes T
+crypto_auth_hmacsha256_update T
+crypto_auth_hmacsha256_verify T
+crypto_auth_hmacsha512 T
+crypto_auth_hmacsha512256 T
+crypto_auth_hmacsha512256_bytes T
+crypto_auth_hmacsha512256_final T
+crypto_auth_hmacsha512256_init T
+crypto_auth_hmacsha512256_keybytes T
+crypto_auth_hmacsha512256_statebytes T
+crypto_auth_hmacsha512256_update T
+crypto_auth_hmacsha512256_verify T
+crypto_auth_hmacsha512_bytes T
+crypto_auth_hmacsha512_final T
+crypto_auth_hmacsha512_init T
+crypto_auth_hmacsha512_keybytes T
+crypto_auth_hmacsha512_statebytes T
+crypto_auth_hmacsha512_update T
+crypto_auth_hmacsha512_verify T
+crypto_auth_keybytes T
+crypto_auth_primitive T
+crypto_auth_verify T
+crypto_box T
+crypto_box_afternm T
+crypto_box_beforenm T
+crypto_box_beforenmbytes T
+crypto_box_boxzerobytes T
+crypto_box_curve25519xsalsa20poly1305 T
+crypto_box_curve25519xsalsa20poly1305_afternm T
+crypto_box_curve25519xsalsa20poly1305_beforenm T
+crypto_box_curve25519xsalsa20poly1305_beforenmbytes T
+crypto_box_curve25519xsalsa20poly1305_boxzerobytes T
+crypto_box_curve25519xsalsa20poly1305_keypair T
+crypto_box_curve25519xsalsa20poly1305_macbytes T
+crypto_box_curve25519xsalsa20poly1305_noncebytes T
+crypto_box_curve25519xsalsa20poly1305_open T
+crypto_box_curve25519xsalsa20poly1305_open_afternm T
+crypto_box_curve25519xsalsa20poly1305_publickeybytes T
+crypto_box_curve25519xsalsa20poly1305_secretkeybytes T
+crypto_box_curve25519xsalsa20poly1305_seed_keypair T
+crypto_box_curve25519xsalsa20poly1305_seedbytes T
+crypto_box_curve25519xsalsa20poly1305_zerobytes T
+crypto_box_detached T
+crypto_box_detached_afternm T
+crypto_box_easy T
+crypto_box_easy_afternm T
+crypto_box_keypair T
+crypto_box_macbytes T
+crypto_box_noncebytes T
+crypto_box_open T
+crypto_box_open_afternm T
+crypto_box_open_detached T
+crypto_box_open_detached_afternm T
+crypto_box_open_easy T
+crypto_box_open_easy_afternm T
+crypto_box_primitive T
+crypto_box_publickeybytes T
+crypto_box_seal T
+crypto_box_seal_open T
+crypto_box_sealbytes T
+crypto_box_secretkeybytes T
+crypto_box_seed_keypair T
+crypto_box_seedbytes T
+crypto_box_zerobytes T
+crypto_core_curve25519_ref10_fe_0 T
+crypto_core_curve25519_ref10_fe_1 T
+crypto_core_curve25519_ref10_fe_add T
+crypto_core_curve25519_ref10_fe_cmov T
+crypto_core_curve25519_ref10_fe_copy T
+crypto_core_curve25519_ref10_fe_frombytes T
+crypto_core_curve25519_ref10_fe_invert T
+crypto_core_curve25519_ref10_fe_isnegative T
+crypto_core_curve25519_ref10_fe_isnonzero T
+crypto_core_curve25519_ref10_fe_mul T
+crypto_core_curve25519_ref10_fe_neg T
+crypto_core_curve25519_ref10_fe_pow22523 T
+crypto_core_curve25519_ref10_fe_sq T
+crypto_core_curve25519_ref10_fe_sq2 T
+crypto_core_curve25519_ref10_fe_sub T
+crypto_core_curve25519_ref10_fe_tobytes T
+crypto_core_curve25519_ref10_ge_add T
+crypto_core_curve25519_ref10_ge_double_scalarmult_vartime T
+crypto_core_curve25519_ref10_ge_frombytes_negate_vartime T
+crypto_core_curve25519_ref10_ge_madd T
+crypto_core_curve25519_ref10_ge_msub T
+crypto_core_curve25519_ref10_ge_p1p1_to_p2 T
+crypto_core_curve25519_ref10_ge_p1p1_to_p3 T
+crypto_core_curve25519_ref10_ge_p2_0 T
+crypto_core_curve25519_ref10_ge_p2_dbl T
+crypto_core_curve25519_ref10_ge_p3_0 T
+crypto_core_curve25519_ref10_ge_p3_dbl T
+crypto_core_curve25519_ref10_ge_p3_to_cached T
+crypto_core_curve25519_ref10_ge_p3_to_p2 T
+crypto_core_curve25519_ref10_ge_p3_tobytes T
+crypto_core_curve25519_ref10_ge_precomp_0 T
+crypto_core_curve25519_ref10_ge_scalarmult_base T
+crypto_core_curve25519_ref10_ge_scalarmult_vartime T
+crypto_core_curve25519_ref10_ge_sub T
+crypto_core_curve25519_ref10_ge_tobytes T
+crypto_core_curve25519_ref10_sc_muladd T
+crypto_core_curve25519_ref10_sc_reduce T
+crypto_core_hsalsa20 T
+crypto_core_hsalsa20_constbytes T
+crypto_core_hsalsa20_inputbytes T
+crypto_core_hsalsa20_keybytes T
+crypto_core_hsalsa20_outputbytes T
+crypto_core_salsa20 T
+crypto_core_salsa2012 T
+crypto_core_salsa2012_constbytes T
+crypto_core_salsa2012_inputbytes T
+crypto_core_salsa2012_keybytes T
+crypto_core_salsa2012_outputbytes T
+crypto_core_salsa208 T
+crypto_core_salsa208_constbytes T
+crypto_core_salsa208_inputbytes T
+crypto_core_salsa208_keybytes T
+crypto_core_salsa208_outputbytes T
+crypto_core_salsa20_constbytes T
+crypto_core_salsa20_inputbytes T
+crypto_core_salsa20_keybytes T
+crypto_core_salsa20_outputbytes T
+crypto_generichash T
+crypto_generichash_blake2b T
+crypto_generichash_blake2b__blake2b T
+crypto_generichash_blake2b__blake2b_salt_personal T
+crypto_generichash_blake2b__final T
+crypto_generichash_blake2b__init T
+crypto_generichash_blake2b__init_key T
+crypto_generichash_blake2b__init_key_salt_personal T
+crypto_generichash_blake2b__init_param T
+crypto_generichash_blake2b__init_salt_personal T
+crypto_generichash_blake2b__pick_best_implementation T
+crypto_generichash_blake2b__update T
+crypto_generichash_blake2b_bytes T
+crypto_generichash_blake2b_bytes_max T
+crypto_generichash_blake2b_bytes_min T
+crypto_generichash_blake2b_final T
+crypto_generichash_blake2b_init T
+crypto_generichash_blake2b_init_salt_personal T
+crypto_generichash_blake2b_keybytes T
+crypto_generichash_blake2b_keybytes_max T
+crypto_generichash_blake2b_keybytes_min T
+crypto_generichash_blake2b_personalbytes T
+crypto_generichash_blake2b_salt_personal T
+crypto_generichash_blake2b_saltbytes T
+crypto_generichash_blake2b_update T
+crypto_generichash_bytes T
+crypto_generichash_bytes_max T
+crypto_generichash_bytes_min T
+crypto_generichash_final T
+crypto_generichash_init T
+crypto_generichash_keybytes T
+crypto_generichash_keybytes_max T
+crypto_generichash_keybytes_min T
+crypto_generichash_primitive T
+crypto_generichash_statebytes T
+crypto_generichash_update T
+crypto_hash T
+crypto_hash_bytes T
+crypto_hash_primitive T
+crypto_hash_sha256 T
+crypto_hash_sha256_bytes T
+crypto_hash_sha256_final T
+crypto_hash_sha256_init T
+crypto_hash_sha256_statebytes T
+crypto_hash_sha256_update T
+crypto_hash_sha512 T
+crypto_hash_sha512_bytes T
+crypto_hash_sha512_final T
+crypto_hash_sha512_init T
+crypto_hash_sha512_statebytes T
+crypto_hash_sha512_update T
+crypto_onetimeauth T
+crypto_onetimeauth_bytes T
+crypto_onetimeauth_final T
+crypto_onetimeauth_init T
+crypto_onetimeauth_keybytes T
+crypto_onetimeauth_poly1305 T
+crypto_onetimeauth_poly1305_bytes T
+crypto_onetimeauth_poly1305_donna_implementation D 40
+crypto_onetimeauth_poly1305_final T
+crypto_onetimeauth_poly1305_init T
+crypto_onetimeauth_poly1305_keybytes T
+crypto_onetimeauth_poly1305_update T
+crypto_onetimeauth_poly1305_verify T
+crypto_onetimeauth_primitive T
+crypto_onetimeauth_statebytes T
+crypto_onetimeauth_update T
+crypto_onetimeauth_verify T
+crypto_pwhash_scryptsalsa208sha256 T
+crypto_pwhash_scryptsalsa208sha256_ll T
+crypto_pwhash_scryptsalsa208sha256_memlimit_interactive T
+crypto_pwhash_scryptsalsa208sha256_memlimit_sensitive T
+crypto_pwhash_scryptsalsa208sha256_opslimit_interactive T
+crypto_pwhash_scryptsalsa208sha256_opslimit_sensitive T
+crypto_pwhash_scryptsalsa208sha256_saltbytes T
+crypto_pwhash_scryptsalsa208sha256_str T
+crypto_pwhash_scryptsalsa208sha256_str_verify T
+crypto_pwhash_scryptsalsa208sha256_strbytes T
+crypto_pwhash_scryptsalsa208sha256_strprefix T
+crypto_scalarmult T
+crypto_scalarmult_base T
+crypto_scalarmult_bytes T
+crypto_scalarmult_curve25519 T
+crypto_scalarmult_curve25519_base T
+crypto_scalarmult_curve25519_bytes T
+crypto_scalarmult_curve25519_ref10_implementation D 16
+crypto_scalarmult_curve25519_scalarbytes T
+crypto_scalarmult_primitive T
+crypto_scalarmult_scalarbytes T
+crypto_secretbox T
+crypto_secretbox_boxzerobytes T
+crypto_secretbox_detached T
+crypto_secretbox_easy T
+crypto_secretbox_keybytes T
+crypto_secretbox_macbytes T
+crypto_secretbox_noncebytes T
+crypto_secretbox_open T
+crypto_secretbox_open_detached T
+crypto_secretbox_open_easy T
+crypto_secretbox_primitive T
+crypto_secretbox_xsalsa20poly1305 T
+crypto_secretbox_xsalsa20poly1305_boxzerobytes T
+crypto_secretbox_xsalsa20poly1305_keybytes T
+crypto_secretbox_xsalsa20poly1305_macbytes T
+crypto_secretbox_xsalsa20poly1305_noncebytes T
+crypto_secretbox_xsalsa20poly1305_open T
+crypto_secretbox_xsalsa20poly1305_zerobytes T
+crypto_secretbox_zerobytes T
+crypto_shorthash T
+crypto_shorthash_bytes T
+crypto_shorthash_keybytes T
+crypto_shorthash_primitive T
+crypto_shorthash_siphash24 T
+crypto_shorthash_siphash24_bytes T
+crypto_shorthash_siphash24_keybytes T
+crypto_sign T
+crypto_sign_bytes T
+crypto_sign_detached T
+crypto_sign_ed25519 T
+crypto_sign_ed25519_bytes T
+crypto_sign_ed25519_detached T
+crypto_sign_ed25519_keypair T
+crypto_sign_ed25519_open T
+crypto_sign_ed25519_pk_to_curve25519 T
+crypto_sign_ed25519_publickeybytes T
+crypto_sign_ed25519_secretkeybytes T
+crypto_sign_ed25519_seed_keypair T
+crypto_sign_ed25519_seedbytes T
+crypto_sign_ed25519_sk_to_curve25519 T
+crypto_sign_ed25519_sk_to_pk T
+crypto_sign_ed25519_sk_to_seed T
+crypto_sign_ed25519_verify_detached T
+crypto_sign_edwards25519sha512batch T
+crypto_sign_edwards25519sha512batch_keypair T
+crypto_sign_edwards25519sha512batch_open T
+crypto_sign_keypair T
+crypto_sign_open T
+crypto_sign_primitive T
+crypto_sign_publickeybytes T
+crypto_sign_secretkeybytes T
+crypto_sign_seed_keypair T
+crypto_sign_seedbytes T
+crypto_sign_verify_detached T
+crypto_stream T
+crypto_stream_aes128ctr T
+crypto_stream_aes128ctr_afternm T
+crypto_stream_aes128ctr_beforenm T
+crypto_stream_aes128ctr_beforenmbytes T
+crypto_stream_aes128ctr_keybytes T
+crypto_stream_aes128ctr_noncebytes T
+crypto_stream_aes128ctr_portable_BS0 R 16
+crypto_stream_aes128ctr_portable_BS1 R 16
+crypto_stream_aes128ctr_portable_BS2 R 16
+crypto_stream_aes128ctr_portable_EXPB0 R 16
+crypto_stream_aes128ctr_portable_M0 R 16
+crypto_stream_aes128ctr_portable_M0SWAP R 16
+crypto_stream_aes128ctr_portable_ROTB R 16
+crypto_stream_aes128ctr_portable_SR R 16
+crypto_stream_aes128ctr_portable_SRM0 R 16
+crypto_stream_aes128ctr_portable_SWAP32 R 16
+crypto_stream_aes128ctr_portable_add_uint32_big T
+crypto_stream_aes128ctr_portable_and2 T
+crypto_stream_aes128ctr_portable_copy2 T
+crypto_stream_aes128ctr_portable_load32_bigendian T
+crypto_stream_aes128ctr_portable_load32_littleendian T
+crypto_stream_aes128ctr_portable_load64_littleendian T
+crypto_stream_aes128ctr_portable_lshift64_littleendian T
+crypto_stream_aes128ctr_portable_or2 T
+crypto_stream_aes128ctr_portable_rshift32_littleendian T
+crypto_stream_aes128ctr_portable_rshift64_littleendian T
+crypto_stream_aes128ctr_portable_shufb T
+crypto_stream_aes128ctr_portable_shufd T
+crypto_stream_aes128ctr_portable_store32_bigendian T
+crypto_stream_aes128ctr_portable_store32_littleendian T
+crypto_stream_aes128ctr_portable_store64_littleendian T
+crypto_stream_aes128ctr_portable_toggle T
+crypto_stream_aes128ctr_portable_xor2 T
+crypto_stream_aes128ctr_portable_xor_rcon T
+crypto_stream_aes128ctr_xor T
+crypto_stream_aes128ctr_xor_afternm T
+crypto_stream_chacha20 T
+crypto_stream_chacha20_ietf T
+crypto_stream_chacha20_ietf_noncebytes T
+crypto_stream_chacha20_ietf_xor T
+crypto_stream_chacha20_ietf_xor_ic T
+crypto_stream_chacha20_keybytes T
+crypto_stream_chacha20_noncebytes T
+crypto_stream_chacha20_ref_implementation D 32
+crypto_stream_chacha20_xor T
+crypto_stream_chacha20_xor_ic T
+crypto_stream_keybytes T
+crypto_stream_noncebytes T
+crypto_stream_primitive T
+crypto_stream_salsa20 T
+crypto_stream_salsa2012 T
+crypto_stream_salsa2012_keybytes T
+crypto_stream_salsa2012_noncebytes T
+crypto_stream_salsa2012_xor T
+crypto_stream_salsa208 T
+crypto_stream_salsa208_keybytes T
+crypto_stream_salsa208_noncebytes T
+crypto_stream_salsa208_xor T
+crypto_stream_salsa20_keybytes T
+crypto_stream_salsa20_noncebytes T
+crypto_stream_salsa20_xor T
+crypto_stream_salsa20_xor_ic T
+crypto_stream_xor T
+crypto_stream_xsalsa20 T
+crypto_stream_xsalsa20_keybytes T
+crypto_stream_xsalsa20_noncebytes T
+crypto_stream_xsalsa20_xor T
+crypto_stream_xsalsa20_xor_ic T
+crypto_verify_16 T
+crypto_verify_16_bytes T
+crypto_verify_32 T
+crypto_verify_32_bytes T
+crypto_verify_64 T
+crypto_verify_64_bytes T
+escrypt_free_local T
+escrypt_gensalt_r T
+escrypt_init_local T
+escrypt_kdf_nosse T
+escrypt_r T
+randombytes T
+randombytes_buf T
+randombytes_close T
+randombytes_implementation_name T
+randombytes_random T
+randombytes_salsa20_implementation_name T
+randombytes_salsa20_random T
+randombytes_salsa20_random_buf T
+randombytes_salsa20_random_close T
+randombytes_salsa20_random_stir T
+randombytes_set_implementation T
+randombytes_stir T
+randombytes_sysrandom_implementation D 48
+randombytes_uniform T
+sodium_add T
+sodium_allocarray T
+sodium_bin2hex T
+sodium_compare T
+sodium_free T
+sodium_hex2bin T
+sodium_increment T
+sodium_init T
+sodium_is_zero T
+sodium_library_version_major T
+sodium_library_version_minor T
+sodium_malloc T
+sodium_memcmp T
+sodium_memzero T
+sodium_mlock T
+sodium_mprotect_noaccess T
+sodium_mprotect_readonly T
+sodium_mprotect_readwrite T
+sodium_munlock T
+sodium_runtime_has_aesni T
+sodium_runtime_has_avx T
+sodium_runtime_has_neon T
+sodium_runtime_has_pclmul T
+sodium_runtime_has_sse2 T
+sodium_runtime_has_sse3 T
+sodium_runtime_has_sse41 T
+sodium_runtime_has_ssse3 T
+sodium_version_string T
diff --git a/ports/libsodium.hash b/ports/libsodium.hash
new file mode 100644
index 0000000..4532475
--- /dev/null
+++ b/ports/libsodium.hash
@@ -0,0 +1 @@
+b2a724da8d82f3a839f3b54e819d3fd7078b8c48
diff --git a/ports/libsodium.port b/ports/libsodium.port
new file mode 100644
index 0000000..62435e9
--- /dev/null
+++ b/ports/libsodium.port
@@ -0,0 +1,14 @@
+LICENSE := ISC
+VERSION := 1.0.16
+DOWNLOADS := libsodium.archive
+URL(libsodium) := https://download.libsodium.org/libsodium/releases/libsodium-$(VERSION).tar.gz
+SHA(libsodium) := eeadc7e1e1bcef09680fb4837d448fbdf57224978f865ac1c16745868fbd0533
+DIR(libsodium) := src/lib/libsodium
+
+#PATCHES := src/lib/libsodium/patch
+#PATCH_OPT := -p1 -d src/lib/libsodium
+
+DIRS := include/libsodium
+DIR_CONTENT(include/libsodium) = \
+ src/lib/libsodium/src/libsodium/include/sodium.h \
+ src/lib/libsodium/src/libsodium/include/sodium \
diff --git a/src/lib/libsodium/genode_core.cc b/src/lib/libsodium/genode_core.cc
new file mode 100644
index 0000000..a4bb0c7
--- /dev/null
+++ b/src/lib/libsodium/genode_core.cc
@@ -0,0 +1,61 @@
+#include "core.h"
+#include "crypto_generichash.h"
+#include "crypto_onetimeauth.h"
+#include "crypto_scalarmult.h"
+#include "crypto_stream_chacha20.h"
+#include "crypto_stream_salsa20.h"
+#include "randombytes.h"
+#include "runtime.h"
+#include "utils.h"
+#include "private/implementations.h"
+#include "private/mutex.h"
+
+#include
+
+static int initialized;
+
+static Genode::Lock *_sodium_lock;
+
+extern "C"
+int sodium_init(void)
+{
+ _sodium_runtime_get_cpu_features();
+ randombytes_stir();
+ _sodium_alloc_init();
+ //_crypto_onetimeauth_poly1305_pick_best_implementation();
+ //_crypto_scalarmult_curve25519_pick_best_implementation();
+ //_crypto_stream_chacha20_pick_best_implementation();
+ //_crypto_stream_salsa20_pick_best_implementation();
+ initialized = 1;
+ return 0;
+}
+
+
+int
+sodium_crit_enter(void)
+{
+ _sodium_lock->lock();
+ return 0;
+}
+
+int
+sodium_crit_leave(void)
+{
+ _sodium_lock->unlock();
+ return 0;
+}
+
+
+extern "C"
+int sodium_set_misuse_handler(void (*handler)(void))
+{
+ (void)handler;
+ Genode::error(__func__, " not implemented");
+ return 0;
+}
+
+extern "C"
+void _sodium_misuse(char const *file, int line)
+{
+ Genode::error("libsodium breakage at ", file, ":", line);
+}
diff --git a/src/lib/libsodium/randombytes_salsa20_jitterentropy.c b/src/lib/libsodium/randombytes_salsa20_jitterentropy.c
new file mode 100644
index 0000000..5bc5ba0
--- /dev/null
+++ b/src/lib/libsodium/randombytes_salsa20_jitterentropy.c
@@ -0,0 +1,169 @@
+/*
+ * \brief Salsa20 RNG seeded with Jitterentropy
+ * \author Emery Hemingway
+ * \date 2015-09-13
+ */
+
+#include "crypto_core_salsa20.h"
+#include "crypto_auth_hmacsha512256.h"
+#include "crypto_stream_salsa20.h"
+#include "randombytes.h"
+#include "randombytes_salsa20_random.h"
+#include "utils.h"
+
+#define SALSA20_RANDOM_BLOCK_SIZE crypto_core_salsa20_OUTPUTBYTES
+#define SHA512_BLOCK_SIZE 128U
+#define SHA512_MIN_PAD_SIZE (1U + 16U)
+#define COMPILER_ASSERT(X) (void) sizeof(char[(X) ? 1 : -1])
+
+typedef struct Salsa20Random_ {
+ unsigned char key[crypto_stream_salsa20_KEYBYTES];
+ unsigned char rnd32[16U * SALSA20_RANDOM_BLOCK_SIZE];
+ uint64_t nonce;
+ size_t rnd32_outleft;
+ struct rand_data *jent_collector;
+ int initialized;
+ int getrandom_available;
+} Salsa20Random;
+
+static Salsa20Random stream = {
+ .rnd32_outleft = (size_t) 0U,
+ .initialized = 0,
+ .getrandom_available = 0
+};
+
+static void
+randombytes_salsa20_random_init(void)
+{
+ /* XXX: check error */
+ jent_entropy_init();
+
+ stream.jent_collector = jent_entropy_collector_alloc(0, 0);
+ jent_read_entropy(stream.jent_collector, (char*)&stream.nonce, sizeof(stream.nonce));
+ /* assert(stream.nonce != (uint64_t) 0U); */
+}
+
+static void
+randombytes_salsa20_random_rekey(const unsigned char * const mix)
+{
+ unsigned char *key = stream.key;
+ size_t i;
+
+ for (i = (size_t) 0U; i < sizeof stream.key; i++) {
+ key[i] ^= mix[i];
+ }
+}
+
+void
+randombytes_salsa20_random_stir(void)
+{
+ const unsigned char s[crypto_auth_hmacsha512256_KEYBYTES] = {
+ 'T', 'h', 'i', 's', 'I', 's', 'J', 'u', 's', 't', 'A', 'T',
+ 'h', 'i', 'r', 't', 'y', 'T', 'w', 'o', 'B', 'y', 't', 'e',
+ 's', 'S', 'e', 'e', 'd', '.', '.', '.'
+ };
+ unsigned char m0[crypto_auth_hmacsha512256_BYTES +
+ 2U * SHA512_BLOCK_SIZE - SHA512_MIN_PAD_SIZE];
+ unsigned char *k0 = m0 + crypto_auth_hmacsha512256_BYTES;
+ size_t sizeof_k0 = sizeof m0 - crypto_auth_hmacsha512256_BYTES;
+
+ memset(stream.rnd32, 0, sizeof stream.rnd32);
+ stream.rnd32_outleft = (size_t) 0U;
+ if (stream.initialized == 0) {
+ randombytes_salsa20_random_init();
+ stream.initialized = 1;
+ }
+
+ jent_read_entropy(stream.jent_collector, (char*)m0, sizeof m0);
+
+ COMPILER_ASSERT(sizeof stream.key == crypto_auth_hmacsha512256_BYTES);
+ crypto_auth_hmacsha512256(stream.key, k0, sizeof_k0, s);
+ COMPILER_ASSERT(sizeof stream.key <= sizeof m0);
+ randombytes_salsa20_random_rekey(m0);
+ sodium_memzero(m0, sizeof m0);
+}
+
+static void
+randombytes_salsa20_random_stir_if_needed(void)
+{
+ if (stream.initialized == 0) {
+ randombytes_salsa20_random_stir();
+ }
+}
+
+static uint32_t
+randombytes_salsa20_random_getword(void)
+{
+ uint32_t val;
+
+ COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val));
+ COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key))
+ % sizeof val == (size_t) 0U);
+ if (stream.rnd32_outleft <= (size_t) 0U) {
+ randombytes_salsa20_random_stir_if_needed();
+ COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
+ crypto_stream_salsa20((unsigned char *) stream.rnd32,
+ (unsigned long long) sizeof stream.rnd32,
+ (unsigned char *) &stream.nonce,
+ stream.key);
+ //assert(ret == 0);
+ stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key);
+ randombytes_salsa20_random_rekey(&stream.rnd32[stream.rnd32_outleft]);
+ stream.nonce++;
+ }
+ stream.rnd32_outleft -= sizeof val;
+ memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val);
+ memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val);
+
+ return val;
+}
+
+int
+randombytes_salsa20_random_close(void)
+{
+ stream.initialized = 0;
+ return 0;
+}
+
+uint32_t
+randombytes_salsa20_random(void)
+{
+ return randombytes_salsa20_random_getword();
+}
+
+void
+randombytes_salsa20_random_buf(void * const buf, const size_t size)
+{
+ size_t i;
+
+ randombytes_salsa20_random_stir_if_needed();
+ COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_salsa20_NONCEBYTES);
+#ifdef ULONG_LONG_MAX
+ /* coverity[result_independent_of_operands] */
+ /* assert(size <= ULONG_LONG_MAX); */
+#endif
+ crypto_stream_salsa20((unsigned char *) buf, (unsigned long long) size,
+ (unsigned char *) &stream.nonce, stream.key);
+ /* assert(ret == 0); */
+ for (i = 0U; i < sizeof size; i++) {
+ stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i];
+ }
+ stream.nonce++;
+ crypto_stream_salsa20_xor(stream.key, stream.key, sizeof stream.key,
+ (unsigned char *) &stream.nonce, stream.key);
+}
+
+const char *
+randombytes_salsa20_implementation_name(void)
+{
+ return "salsa20";
+}
+
+struct randombytes_implementation randombytes_sysrandom_implementation = {
+ SODIUM_C99(.implementation_name =) randombytes_salsa20_implementation_name,
+ SODIUM_C99(.random =) randombytes_salsa20_random,
+ SODIUM_C99(.stir =) randombytes_salsa20_random_stir,
+ SODIUM_C99(.uniform =) NULL,
+ SODIUM_C99(.buf =) randombytes_salsa20_random_buf,
+ SODIUM_C99(.close =) randombytes_salsa20_random_close
+};
diff --git a/src/test/libsodium/main.cc b/src/test/libsodium/main.cc
new file mode 100644
index 0000000..fe8cafe
--- /dev/null
+++ b/src/test/libsodium/main.cc
@@ -0,0 +1,3 @@
+#include
+
+int main() { return sodium_init(); }
diff --git a/src/test/libsodium/target.mk b/src/test/libsodium/target.mk
new file mode 100644
index 0000000..1d59af2
--- /dev/null
+++ b/src/test/libsodium/target.mk
@@ -0,0 +1,5 @@
+TARGET = test-libsodium
+LIBS = libsodium libc posix
+SRC_CC = main.cc
+
+vpath main.cc $(PRG_DIR)