From 7e669bcf6b6336ec429da949bcb4aa456971dba2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 30 Jul 2021 10:38:27 +0200 Subject: folding history in preparation of GNU Anastasis v0.0.0 release --- src/util/Makefile.am | 57 ++++ src/util/anastasis-config.in | 12 + src/util/anastasis_crypto.c | 637 +++++++++++++++++++++++++++++++++++++++ src/util/os_installation.c | 71 +++++ src/util/paths.conf | 29 ++ src/util/test_anastasis_crypto.c | 346 +++++++++++++++++++++ 6 files changed, 1152 insertions(+) create mode 100644 src/util/Makefile.am create mode 100644 src/util/anastasis-config.in create mode 100644 src/util/anastasis_crypto.c create mode 100644 src/util/os_installation.c create mode 100644 src/util/paths.conf create mode 100644 src/util/test_anastasis_crypto.c (limited to 'src/util') diff --git a/src/util/Makefile.am b/src/util/Makefile.am new file mode 100644 index 0000000..657ec0c --- /dev/null +++ b/src/util/Makefile.am @@ -0,0 +1,57 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include $(LIBGCRYPT_CFLAGS) + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +pkgcfgdir = $(prefix)/share/anastasis/config.d/ + +pkgcfg_DATA = \ + paths.conf + +EXTRA_DIST = \ + anastasis-config.in \ + $(pkgcfg_DATA) + +edit_script = $(SED) -e 's,%libdir%,$(libdir),'g $(NULL) + +anastasis-config: anastasis-config.in + rm -f $@ $@.tmp && \ + $(edit_script) $< >$@.tmp && \ + chmod a-w+x $@.tmp && \ + mv $@.tmp $@ + +bin_SCRIPTS = \ + anastasis-config + +lib_LTLIBRARIES = \ + libanastasisutil.la + +libanastasisutil_la_SOURCES = \ + anastasis_crypto.c \ + os_installation.c +libanastasisutil_la_LIBADD = \ + -lgnunetutil \ + $(LIBGCRYPT_LIBS) \ + -ljansson \ + -ltalerutil \ + $(XLIB) +libanastasisutil_la_LDFLAGS = \ + -version-info 0:0:0 \ + -no-undefined + +check_PROGRAMS = \ + test_anastasis_crypto + +TESTS = \ + $(check_PROGRAMS) + +test_anastasis_crypto_SOURCES = \ + test_anastasis_crypto.c +test_anastasis_crypto_LDADD = \ + -lgnunetutil \ + -ltalerutil \ + libanastasisutil.la \ + $(XLIB) diff --git a/src/util/anastasis-config.in b/src/util/anastasis-config.in new file mode 100644 index 0000000..0e94921 --- /dev/null +++ b/src/util/anastasis-config.in @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -eu + +if ! type gnunet-config >/dev/null; then + echo "$0 needs gnunet-config to be installed" + exit 1 +fi + +GC=`which gnunet-config` +export LD_PRELOAD=${LD_PRELOAD:-}:%libdir%/libanastasisutil.so +exec gnunet-config "$@" diff --git a/src/util/anastasis_crypto.c b/src/util/anastasis_crypto.c new file mode 100644 index 0000000..ace0162 --- /dev/null +++ b/src/util/anastasis_crypto.c @@ -0,0 +1,637 @@ +/* + This file is part of Anastasis + Copyright (C) 2020 Taler Systems SA + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis 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 + Anastasis; see the file COPYING.GPL. If not, see +*/ +/** + * @file lib/anastasis_crypto.c + * @brief anastasis crypto api + * @author Christian Grothoff + * @author Dominik Meister + * @author Dennis Neufeld + */ + +#include "platform.h" +#include "anastasis_crypto_lib.h" +#include +#include +#include +#include + +#if defined(DEBUG) || defined(DEBUG2) +#define SCRYPT_ITERATION 1 + +#else +#define SCRYPT_ITERATION 1000 +#endif + + +void +ANASTASIS_hash_answer (uint64_t code, + struct GNUNET_HashCode *hashed_code) +{ + char cbuf[40]; + + GNUNET_snprintf (cbuf, + sizeof (cbuf), + "%llu", + (unsigned long long) code); + GNUNET_CRYPTO_hash (cbuf, + strlen (cbuf), + hashed_code); +} + + +void +ANASTASIS_CRYPTO_secure_answer_hash ( + const char *answer, + const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid, + const struct ANASTASIS_CRYPTO_QuestionSaltP *salt, + struct GNUNET_HashCode *result) +{ + struct GNUNET_HashCode pow; + + GNUNET_CRYPTO_pow_hash (&salt->pow_salt, + answer, + strlen (answer), + &pow); + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf ( + result, + sizeof (*result), + "Anastasis-secure-question-uuid-salting", + strlen ("Anastasis-secure-question-uuid-salting"), + &pow, + sizeof (pow), + uuid, + sizeof (*uuid), + NULL, + 0)); +} + + +/** + * Compute @a key and @a iv. + * + * @param key_material key for calculation + * @param key_m_len length of key + * @param nonce nonce for calculation + * @param salt salt value for calculation + * @param[out] key where to write the en-/description key + * @param[out] iv where to write the IV + */ +static void +get_iv_key (const void *key_material, + size_t key_m_len, + const struct ANASTASIS_CRYPTO_NonceP *nonce, + const char *salt, + const struct ANASTASIS_CRYPTO_SymKeyP *key, + struct ANASTASIS_CRYPTO_IvP *iv) +{ + char res[sizeof (struct ANASTASIS_CRYPTO_SymKeyP) + + sizeof (struct ANASTASIS_CRYPTO_IvP)]; + + if (GNUNET_YES != + GNUNET_CRYPTO_hkdf (res, + sizeof (res), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + key_material, + key_m_len, + nonce, + sizeof (struct ANASTASIS_CRYPTO_NonceP), + salt, + strlen (salt), + NULL, + 0)) + { + GNUNET_break (0); + return; + } + memcpy ((void *) key, + res, + sizeof (*key)); + memcpy (iv, + &res[sizeof (*key)], + sizeof (*iv)); +} + + +/** + * Encryption of data like recovery document etc. + * + * @param nonce value to use for the nonce + * @param key key which is used to derive a key/iv pair from + * @param key_len length of key + * @param data data to encrypt + * @param data_size size of the data + * @param salt salt value which is used for key derivation + * @param res[out] ciphertext output + * @param res_size[out] size of the ciphertext + */ +static void +anastasis_encrypt (const struct ANASTASIS_CRYPTO_NonceP *nonce, + const void *key, + size_t key_len, + const void *data, + size_t data_size, + const char *salt, + void **res, + size_t *res_size) +{ + struct ANASTASIS_CRYPTO_NonceP *nonceptr; + gcry_cipher_hd_t cipher; + struct ANASTASIS_CRYPTO_SymKeyP sym_key; + struct ANASTASIS_CRYPTO_IvP iv; + int rc; + struct ANASTASIS_CRYPTO_AesTagP *tag; + char *ciphertext; + + *res_size = data_size + + sizeof (struct ANASTASIS_CRYPTO_NonceP) + + sizeof (struct ANASTASIS_CRYPTO_AesTagP); + if (*res_size <= data_size) + { + GNUNET_break (0); + return; + } + *res = GNUNET_malloc (*res_size); + if (*res_size != data_size + + sizeof (struct ANASTASIS_CRYPTO_NonceP) + + sizeof (struct ANASTASIS_CRYPTO_AesTagP)) + { + GNUNET_break (0); + return; + } + nonceptr = (struct ANASTASIS_CRYPTO_NonceP *) *res; + tag = (struct ANASTASIS_CRYPTO_AesTagP *) &nonceptr[1]; + ciphertext = (char *) &tag[1]; + memcpy (nonceptr, + nonce, + sizeof (*nonce)); + get_iv_key (key, + key_len, + nonce, + salt, + &sym_key, + &iv); + GNUNET_assert (0 == + gcry_cipher_open (&cipher, + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + 0)); + rc = gcry_cipher_setkey (cipher, + &sym_key, + sizeof (sym_key)); + GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); + rc = gcry_cipher_setiv (cipher, + &iv, + sizeof (iv)); + GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); + + GNUNET_assert (0 == + gcry_cipher_encrypt (cipher, + ciphertext, + data_size, + data, + data_size)); + GNUNET_assert (0 == + gcry_cipher_gettag (cipher, + tag, + sizeof (struct ANASTASIS_CRYPTO_AesTagP))); + gcry_cipher_close (cipher); +} + + +/** + * Decryption of data like encrypted recovery document etc. + * + * @param key key which is used to derive a key/iv pair from + * @param key_len length of key + * @param data data to decrypt + * @param data_size size of the data + * @param salt salt value which is used for key derivation + * @param res[out] plaintext output + * @param res_size[out] size of the plaintext + */ +static void +anastasis_decrypt (const void *key, + size_t key_len, + const void *data, + size_t data_size, + const char *salt, + void **res, + size_t *res_size) +{ + const struct ANASTASIS_CRYPTO_NonceP *nonce; + gcry_cipher_hd_t cipher; + const struct ANASTASIS_CRYPTO_SymKeyP sym_key; + struct ANASTASIS_CRYPTO_IvP iv; + int rc; + const struct ANASTASIS_CRYPTO_AesTagP *tag; + const char *ciphertext; + + *res_size = data_size + - sizeof (struct ANASTASIS_CRYPTO_NonceP) + - sizeof (struct ANASTASIS_CRYPTO_AesTagP); + if (*res_size >= data_size) + { + GNUNET_break (0); + return; + } + *res = GNUNET_malloc (*res_size); + if (*res_size != data_size + - sizeof (struct ANASTASIS_CRYPTO_NonceP) + - sizeof (struct ANASTASIS_CRYPTO_AesTagP)) + { + GNUNET_break (0); + GNUNET_free (*res); + return; + } + + nonce = (const struct ANASTASIS_CRYPTO_NonceP *) data; + tag = (struct ANASTASIS_CRYPTO_AesTagP *) &nonce[1]; + ciphertext = (const char *) &tag[1]; + get_iv_key (key, + key_len, + nonce, + salt, + &sym_key, + &iv); + GNUNET_assert (0 == + gcry_cipher_open (&cipher, + GCRY_CIPHER_AES256, + GCRY_CIPHER_MODE_GCM, + 0)); + rc = gcry_cipher_setkey (cipher, + &sym_key, + sizeof (sym_key)); + GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); + + rc = gcry_cipher_setiv (cipher, + &iv, + sizeof (iv)); + GNUNET_assert ((0 == rc) || ((char) rc == GPG_ERR_WEAK_KEY)); + + GNUNET_assert (0 == gcry_cipher_decrypt (cipher, + *res, + *res_size, + ciphertext, + *res_size)); + if (0 != + gcry_cipher_checktag (cipher, + tag, + sizeof (struct ANASTASIS_CRYPTO_AesTagP))) + { + GNUNET_break (0); + GNUNET_free (*res); + return; + } + gcry_cipher_close (cipher); +} + + +void +ANASTASIS_CRYPTO_user_identifier_derive ( + const json_t *id_data, + const struct ANASTASIS_CRYPTO_ProviderSaltP *server_salt, + struct ANASTASIS_CRYPTO_UserIdentifierP *id) +{ + char *json_enc; + struct GNUNET_HashCode hash; + + json_enc = json_dumps (id_data, + JSON_COMPACT | JSON_SORT_KEYS); + GNUNET_assert (NULL != json_enc); + GNUNET_CRYPTO_pow_hash (&server_salt->salt, + json_enc, + strlen (json_enc), + &hash); + id->hash = hash; + free (json_enc); +} + + +void +ANASTASIS_CRYPTO_account_private_key_derive ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + struct ANASTASIS_CRYPTO_AccountPrivateKeyP *priv_key) +{ + /* priv_key = ver_secret */ + if (GNUNET_YES != + GNUNET_CRYPTO_hkdf (&priv_key->priv, + sizeof (priv_key->priv), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), + "ver", + strlen ("ver"), + NULL, + 0)) + { + GNUNET_break (0); + return; + } + /* go from ver_secret to proper private key (eddsa_d_to_a() in spec) */ + priv_key->priv.d[0] = (priv_key->priv.d[0] & 0x7f) | 0x40; + priv_key->priv.d[31] &= 0xf8; +} + + +void +ANASTASIS_CRYPTO_account_public_key_derive ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + struct ANASTASIS_CRYPTO_AccountPublicKeyP *pub_key) +{ + struct ANASTASIS_CRYPTO_AccountPrivateKeyP priv; + + ANASTASIS_CRYPTO_account_private_key_derive (id, + &priv); + GNUNET_CRYPTO_eddsa_key_get_public (&priv.priv, + &pub_key->pub); +} + + +void +ANASTASIS_CRYPTO_recovery_document_encrypt ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const void *rec_doc, + size_t rd_size, + void **enc_rec_doc, + size_t *erd_size) +{ + const char *salt = "erd"; + struct ANASTASIS_CRYPTO_NonceP nonce; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &nonce, + sizeof (nonce)); + anastasis_encrypt (&nonce, + id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), + rec_doc, + rd_size, + salt, + enc_rec_doc, + erd_size); +} + + +void +ANASTASIS_CRYPTO_recovery_document_decrypt ( + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const void *enc_rec_doc, + size_t erd_size, + void **rec_doc, + size_t *rd_size) +{ + const char *salt = "erd"; + + anastasis_decrypt (id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), + enc_rec_doc, + erd_size, + salt, + rec_doc, + rd_size); +} + + +void +ANASTASIS_CRYPTO_keyshare_encrypt ( + const struct ANASTASIS_CRYPTO_KeyShareP *key_share, + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const char *xsalt, + struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share) +{ + const char *salt = "eks"; + size_t eks_size = 0; + void *eks = NULL; + struct ANASTASIS_CRYPTO_NonceP nonce; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &nonce, + sizeof (nonce)); + anastasis_encrypt (&nonce, + id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), + key_share, + sizeof (struct ANASTASIS_CRYPTO_KeyShareP), + (NULL == xsalt) ? salt : xsalt, + &eks, + &eks_size); + GNUNET_assert (eks_size == + sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); + memcpy (enc_key_share, + eks, + sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP)); + GNUNET_free (eks); +} + + +void +ANASTASIS_CRYPTO_keyshare_decrypt ( + const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *enc_key_share, + const struct ANASTASIS_CRYPTO_UserIdentifierP *id, + const char *xsalt, + struct ANASTASIS_CRYPTO_KeyShareP *key_share) +{ + const char *salt = "eks"; + size_t ks_size = 0; + void *ks = NULL; + + anastasis_decrypt (id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP), + enc_key_share, + sizeof (struct ANASTASIS_CRYPTO_EncryptedKeyShareP), + (NULL == xsalt) ? salt : xsalt, + &ks, + &ks_size); + GNUNET_assert (ks_size == + sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); + memcpy (key_share, + ks, + sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); + GNUNET_free (ks); +} + + +void +ANASTASIS_CRYPTO_truth_encrypt ( + const struct ANASTASIS_CRYPTO_NonceP *nonce, + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, + const void *truth, + size_t truth_size, + void **enc_truth, + size_t *ect_size) +{ + const char *salt = "ect"; + + anastasis_encrypt (nonce, + truth_enc_key, + sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), + truth, + truth_size, + salt, + enc_truth, + ect_size); +} + + +void +ANASTASIS_CRYPTO_truth_decrypt ( + const struct ANASTASIS_CRYPTO_TruthKeyP *truth_enc_key, + const void *enc_truth, + size_t ect_size, + void **truth, + size_t *truth_size) +{ + const char *salt = "ect"; + + anastasis_decrypt (truth_enc_key, + sizeof (struct ANASTASIS_CRYPTO_TruthKeyP), + enc_truth, + ect_size, + salt, + truth, + truth_size); +} + + +void +ANASTASIS_CRYPTO_keyshare_create ( + struct ANASTASIS_CRYPTO_KeyShareP *key_share) +{ + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, + key_share, + sizeof (struct ANASTASIS_CRYPTO_KeyShareP)); +} + + +void +ANASTASIS_CRYPTO_policy_key_derive ( + const struct ANASTASIS_CRYPTO_KeyShareP *key_shares, + unsigned int keyshare_length, + const struct ANASTASIS_CRYPTO_MasterSaltP *salt, + struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key) +{ + GNUNET_CRYPTO_hkdf (policy_key, + sizeof (*policy_key), + GCRY_MD_SHA512, + GCRY_MD_SHA256, + key_shares, + keyshare_length * sizeof (*key_shares), + salt, + sizeof (*salt), + NULL, 0); +} + + +void +ANASTASIS_CRYPTO_core_secret_encrypt ( + const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_keys, + unsigned int policy_keys_length, + const void *core_secret, + size_t core_secret_size, + void **enc_core_secret, + struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_keys) +{ + struct GNUNET_CRYPTO_SymmetricSessionKey sk; + struct GNUNET_CRYPTO_SymmetricInitializationVector iv; + struct GNUNET_HashCode master_key; + + *enc_core_secret = GNUNET_malloc (core_secret_size); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, + &master_key, + sizeof (struct GNUNET_HashCode)); + GNUNET_CRYPTO_hash_to_aes_key (&master_key, + &sk, + &iv); + GNUNET_assert (GNUNET_SYSERR != + GNUNET_CRYPTO_symmetric_encrypt (core_secret, + core_secret_size, + &sk, + &iv, + *enc_core_secret)); + for (unsigned int i = 0; i < policy_keys_length; i++) + { + struct GNUNET_CRYPTO_SymmetricSessionKey i_sk; + struct GNUNET_CRYPTO_SymmetricInitializationVector i_iv; + struct GNUNET_HashCode key = policy_keys[i].key; + + GNUNET_CRYPTO_hash_to_aes_key (&key, + &i_sk, + &i_iv); + GNUNET_assert ( + GNUNET_SYSERR != + GNUNET_CRYPTO_symmetric_encrypt (&master_key, + sizeof (struct GNUNET_HashCode), + &i_sk, + &i_iv, + &encrypted_master_keys[i])); + } +} + + +void +ANASTASIS_CRYPTO_core_secret_recover ( + const struct ANASTASIS_CRYPTO_EncryptedMasterKeyP *encrypted_master_key, + const struct ANASTASIS_CRYPTO_PolicyKeyP *policy_key, + const void *encrypted_core_secret, + size_t encrypted_core_secret_size, + void **core_secret, + size_t *core_secret_size) +{ + struct GNUNET_CRYPTO_SymmetricSessionKey mk_sk; + struct GNUNET_CRYPTO_SymmetricInitializationVector mk_iv; + struct GNUNET_CRYPTO_SymmetricSessionKey core_sk; + struct GNUNET_CRYPTO_SymmetricInitializationVector core_iv; + struct GNUNET_HashCode master_key; + struct GNUNET_HashCode key = policy_key->key; + + *core_secret = GNUNET_malloc (encrypted_core_secret_size); + GNUNET_CRYPTO_hash_to_aes_key (&key, + &mk_sk, + &mk_iv); + GNUNET_assert ( + GNUNET_SYSERR != + GNUNET_CRYPTO_symmetric_decrypt ( + encrypted_master_key, + sizeof (struct ANASTASIS_CRYPTO_EncryptedMasterKeyP), + &mk_sk, + &mk_iv, + &master_key)); + GNUNET_CRYPTO_hash_to_aes_key (&master_key, + &core_sk, + &core_iv); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__, + __LINE__, + TALER_b2s (encrypted_core_secret, encrypted_core_secret_size), + (unsigned long long) encrypted_core_secret_size); + *core_secret_size = GNUNET_CRYPTO_symmetric_decrypt (encrypted_core_secret, + encrypted_core_secret_size, + &core_sk, + &core_iv, + *core_secret); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__, + __LINE__, + TALER_b2s (*core_secret, *core_secret_size), + (unsigned long long) *core_secret_size); + GNUNET_assert (GNUNET_SYSERR != *core_secret_size); +} + + +/* end of anastasis_crypto.c */ diff --git a/src/util/os_installation.c b/src/util/os_installation.c new file mode 100644 index 0000000..d9608d3 --- /dev/null +++ b/src/util/os_installation.c @@ -0,0 +1,71 @@ +/* + This file is part of GNU Anastasis. + Copyright (C) 2019 Taler Systems SA + + Anastasis is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + Anastasis 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 Anastasis; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * @file os_installation.c + * @brief initialize libgnunet OS subsystem for Anastasis. + * @author Christian Grothoff + */ +#include "platform.h" +#include + + +/** + * Default project data used for installation path detection + * for GNU Anastasis. + */ +static const struct GNUNET_OS_ProjectData anastasis_pd = { + .libname = "libanastasisutil", + .project_dirname = "anastasis", + .binary_name = "anastasis-httpd", + .env_varname = "ANASTASIS_PREFIX", + .base_config_varname = "ANASTASIS_BASE_CONFIG", + .bug_email = "contact@anastasis.lu", + .homepage = "https://anastasis.lu/", + .config_file = "anastasis.conf", + .user_config_file = "~/.config/anastasis.conf", + .version = PACKAGE_VERSION, + .is_gnu = 0, + .gettext_domain = "anastasis", + .gettext_path = NULL, +}; + + +/** + * Return default project data used by Anastasis. + */ +const struct GNUNET_OS_ProjectData * +ANASTASIS_project_data_default (void) +{ + return &anastasis_pd; +} + + +/** + * Initialize libanastasisutil. + */ +void __attribute__ ((constructor)) +ANASTASIS_OS_init () +{ + GNUNET_OS_init (&anastasis_pd); +} + + +/* end of os_installation.c */ diff --git a/src/util/paths.conf b/src/util/paths.conf new file mode 100644 index 0000000..c62a24a --- /dev/null +++ b/src/util/paths.conf @@ -0,0 +1,29 @@ +# This file is in the public domain. +# +[PATHS] +# The PATHS section is special, as filenames including $-expression are +# expanded using the values from PATHS or the system environment (PATHS +# is checked first). Anastasis also supports expanding $-expressions using +# defaults with the syntax "${VAR:-default}". Here, "default" can again +# be a $-expression. +# +# We usually want $HOME for $ANASTASIS_HOME, but we allow testcases to +# easily override this by setting $ANASTASIS_TEST_HOME. +# +ANASTASIS_HOME = ${ANASTASIS_TEST_HOME:-${HOME:-${USERPROFILE}}} + +# see XDG Base Directory Specification at +# http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +# for how these should be used. + +# Persistent data storage +ANASTASIS_DATA_HOME = ${XDG_DATA_HOME:-$ANASTASIS_HOME/.local/share}/anastasis/ + +# Configuration files +ANASTASIS_CONFIG_HOME = ${XDG_CONFIG_HOME:-$ANASTASIS_HOME/.config}/anastasis/ + +# Cached data, no big deal if lost +ANASTASIS_CACHE_HOME = ${XDG_CACHE_HOME:-$ANASTASIS_HOME/.cache}/anastasis/ + +# Runtime data (always lost on system boot) +ANASTASIS_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/anastasis-system-runtime/ diff --git a/src/util/test_anastasis_crypto.c b/src/util/test_anastasis_crypto.c new file mode 100644 index 0000000..9a6a98c --- /dev/null +++ b/src/util/test_anastasis_crypto.c @@ -0,0 +1,346 @@ +/* + This file is part of TALER + Copyright (C) 2014-2020 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 3, or + (at your option) any later version. + + TALER 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 TALER; see the file COPYING. If not, see + +*/ + +/** + * @file lib/test_anastasis_api.c + * @brief testcase to test anastasis' HTTP API interface + * @author Christian Grothoff + * @author Dennis Neufeld + * @author Dominik Meister + */ +#include "platform.h" +#include +#include +#include "anastasis_crypto_lib.h" + +/** + * Testing derivation of the user identifier + */ +static int +test_user_identifier_derive (void) +{ + json_t *id_data_1; + json_t *id_data_2; + json_t *id_data_3; + struct ANASTASIS_CRYPTO_UserIdentifierP id_1; + struct ANASTASIS_CRYPTO_UserIdentifierP id_2; + struct ANASTASIS_CRYPTO_UserIdentifierP id_3; + struct ANASTASIS_CRYPTO_ProviderSaltP server_salt; + + char *salt_str = "Server-Salt-Test"; + + GNUNET_memcpy (&server_salt, + salt_str, + strlen (salt_str)); + // sample data 1 + id_data_1 = json_object (); + json_object_set_new (id_data_1, "arg1", json_string ("Hallo")); + // sample data 2, equal to sample data 1 + id_data_2 = json_object (); + json_object_set_new (id_data_2, "arg1", json_string ("Hallo")); + // sample data 3, differs + id_data_3 = json_object (); + json_object_set_new (id_data_3, "arg1", json_string ("Hallo2")); + + ANASTASIS_CRYPTO_user_identifier_derive (id_data_1, + &server_salt, + &id_1); + ANASTASIS_CRYPTO_user_identifier_derive (id_data_2, + &server_salt, + &id_2); + ANASTASIS_CRYPTO_user_identifier_derive (id_data_3, + &server_salt, + &id_3); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "UserIdentifier_1: %s\n", + TALER_B2S (&id_1)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "UserIdentifier_2: %s\n", + TALER_B2S (&id_2)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "UserIdentifier_3: %s\n", + TALER_B2S (&id_3)); + GNUNET_assert (0 == GNUNET_memcmp (&id_1, &id_2)); + GNUNET_assert (0 != GNUNET_memcmp (&id_1, &id_3)); + json_decref (id_data_1); + json_decref (id_data_2); + json_decref (id_data_3); + return 0; +} + + +/** + * Testing the encryption of an recovery document and the + * decryption of the encrypted recovery document + */ +static int +test_recovery_document (void) +{ + void *ciphertext; + size_t size_ciphertext; + void *plaintext; + size_t size_plaintext; + struct ANASTASIS_CRYPTO_UserIdentifierP id; + struct ANASTASIS_CRYPTO_ProviderSaltP server_salt; + int ret; + + json_t *id_data = json_object (); + const char *test = "TEST_ERD"; + char *salt_str = "Server-Salt-Test"; + + GNUNET_memcpy (&server_salt, + salt_str, + strlen (salt_str)); + json_object_set_new (id_data, "arg1", json_string ("ID_DATA")); + ANASTASIS_CRYPTO_user_identifier_derive (id_data, + &server_salt, + &id); + ANASTASIS_CRYPTO_recovery_document_encrypt (&id, + test, + strlen (test), + &ciphertext, + &size_ciphertext); + + ANASTASIS_CRYPTO_recovery_document_decrypt (&id, + ciphertext, + size_ciphertext, + &plaintext, + &size_plaintext); + GNUNET_assert (strlen (test) == size_plaintext); + ret = strncmp (plaintext, test, strlen (test)); + json_decref (id_data); + GNUNET_free (ciphertext); + GNUNET_free (plaintext); + return ret; +} + + +static int +test_key_share (void) +{ + struct ANASTASIS_CRYPTO_EncryptedKeyShareP ciphertext; + struct ANASTASIS_CRYPTO_KeyShareP plaintext; + struct ANASTASIS_CRYPTO_UserIdentifierP id; + struct ANASTASIS_CRYPTO_KeyShareP key_share; + struct ANASTASIS_CRYPTO_KeyShareP key_share_1; + struct ANASTASIS_CRYPTO_KeyShareP key_share_2; + + // testing creation of keyshares + ANASTASIS_CRYPTO_keyshare_create (&key_share_1); + ANASTASIS_CRYPTO_keyshare_create (&key_share_2); + GNUNET_assert (0 != + GNUNET_memcmp (&key_share_1, + &key_share_2)); + + // testing of enc-/decryption of a keyshare + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &id, + sizeof (struct ANASTASIS_CRYPTO_UserIdentifierP)); + ANASTASIS_CRYPTO_keyshare_create (&key_share); + ANASTASIS_CRYPTO_keyshare_encrypt (&key_share, + &id, + NULL, + &ciphertext); + ANASTASIS_CRYPTO_keyshare_decrypt (&ciphertext, + &id, + NULL, + &plaintext); + return GNUNET_memcmp (&key_share, + &plaintext); +} + + +static int +test_truth (void) +{ + const char *test = "TEST_TRUTH"; + void *ciphertext; + size_t size_ciphertext; + void *plaintext; + size_t size_plaintext; + struct ANASTASIS_CRYPTO_TruthKeyP truth_enc_key; + int ret; + struct ANASTASIS_CRYPTO_NonceP nonce; + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "TRUTH_BEFORE: %s\n", + TALER_b2s (test, + strlen (test))); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &truth_enc_key, + sizeof (struct ANASTASIS_CRYPTO_TruthKeyP)); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, + &nonce, + sizeof (nonce)); + ANASTASIS_CRYPTO_truth_encrypt (&nonce, + &truth_enc_key, + test, + strlen (test), + &ciphertext, + &size_ciphertext); + + ANASTASIS_CRYPTO_truth_decrypt (&truth_enc_key, + ciphertext, + size_ciphertext, + &plaintext, + &size_plaintext); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "TRUTH_AFTER: %s\n", + TALER_b2s (plaintext, size_plaintext)); + GNUNET_assert (strlen (test) == size_plaintext); + ret = strncmp (plaintext, test, strlen (test)); + GNUNET_free (ciphertext); + GNUNET_free (plaintext); + return ret; +} + + +static int +test_core_secret (void) +{ + const char *test = "TEST_CORE_SECRET"; + const char *test_wrong = "TEST_CORE_WRONG"; + void *enc_core_secret; + unsigned int policy_keys_length = 5; + struct ANASTASIS_CRYPTO_MasterSaltP salt; + struct ANASTASIS_CRYPTO_EncryptedMasterKeyP + encrypted_master_keys[policy_keys_length]; + + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + &salt, + sizeof (salt)); + + // construction of PolicyKey-array + struct ANASTASIS_CRYPTO_PolicyKeyP policy_keys[policy_keys_length]; + for (unsigned int i = 0; i < policy_keys_length; i++) + { + // construction of KeyShare-array + unsigned int keyshare_length = 5; + struct ANASTASIS_CRYPTO_KeyShareP keyshares[keyshare_length]; + for (unsigned int j = 0; j < keyshare_length; j++) + { + ANASTASIS_CRYPTO_keyshare_create (&keyshares[j]); + if (j > 0) + GNUNET_assert (0 != + GNUNET_memcmp (&keyshares[j - 1], &keyshares[j])); + } + + // derive policy-keys + ANASTASIS_CRYPTO_policy_key_derive ((struct + ANASTASIS_CRYPTO_KeyShareP *) + keyshares, + keyshare_length, + &salt, + &policy_keys[i]); + if (i > 0) + GNUNET_assert (0 != + GNUNET_memcmp (&policy_keys[i - 1], &policy_keys[i])); + } + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CORE_SECRET_BEFORE: %s\n", + TALER_b2s (test, strlen (test))); + + // test encryption of core_secret + ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys, + policy_keys_length, + test, + strlen (test), + &enc_core_secret, + (struct + ANASTASIS_CRYPTO_EncryptedMasterKeyP *) + &encrypted_master_keys); + + // test recover of core secret + for (unsigned int k = 0; k < policy_keys_length; k++) + { + void *dec_core_secret; + size_t core_secret_size; + + ANASTASIS_CRYPTO_core_secret_recover (&encrypted_master_keys[k], + &policy_keys[k], + enc_core_secret, + strlen (test), + &dec_core_secret, + &core_secret_size); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "CORE_SECRET_AFTER_%i: %s\n", + k, + TALER_b2s (dec_core_secret, strlen (test))); + GNUNET_assert (strlen (test) == core_secret_size); + GNUNET_assert (0 == + strncmp (dec_core_secret, test, strlen (test))); + GNUNET_assert (0 != + strncmp (dec_core_secret, test_wrong, strlen ( + test))); + GNUNET_free (dec_core_secret); + } + GNUNET_free (enc_core_secret); + return 0; +} + + +static int +test_public_key_derive (void) +{ + struct ANASTASIS_CRYPTO_UserIdentifierP id; + struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key; + struct ANASTASIS_CRYPTO_ProviderSaltP server_salt; + json_t *id_data = json_object (); + const char *salt_str = "Server-Salt-Test"; + + GNUNET_memcpy (&server_salt, + salt_str, + strlen (salt_str)); + + json_object_set_new (id_data, "arg1", json_string ("ID_DATA")); + ANASTASIS_CRYPTO_user_identifier_derive (id_data, + &server_salt, + &id); + + ANASTASIS_CRYPTO_account_public_key_derive (&id, + &pub_key); + // FIXME: write a real test, e.g. signing and verification + json_decref (id_data); + return 0; +} + + +int +main (int argc, + const char *const argv[]) +{ + GNUNET_log_setup (argv[0], "DEBUG", NULL); + if (0 != test_recovery_document ()) + return 1; + if (0 != test_user_identifier_derive ()) + return 1; + if (0 != test_key_share ()) + return 1; + if (0 != test_truth ()) + return 1; + if (0 != test_core_secret ()) + return 1; + if (0 != test_public_key_derive ()) + return 1; + return 0; +} + + +/* end of test_anastasis_crypto.c */ -- cgit v1.2.3