From 21e28d6d049a948fe71817da7cb3e3b0f1639eb6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 19 Jan 2022 14:38:57 +0100 Subject: implement routine to download meta data and decrypt to libanastasis; improve API to include timestamp --- src/lib/Makefile.am | 1 + src/lib/anastasis_backup.c | 27 +++++-- src/lib/anastasis_meta.c | 180 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 src/lib/anastasis_meta.c (limited to 'src/lib') diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 07460d4..6f71418 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -14,6 +14,7 @@ libanastasis_la_LDFLAGS = \ -no-undefined libanastasis_la_SOURCES = \ anastasis_backup.c \ + anastasis_meta.c \ anastasis_recovery.c libanastasis_la_LIBADD = \ $(top_builddir)/src/util/libanastasisutil.la \ diff --git a/src/lib/anastasis_backup.c b/src/lib/anastasis_backup.c index 20c77e4..2e769ca 100644 --- a/src/lib/anastasis_backup.c +++ b/src/lib/anastasis_backup.c @@ -734,6 +734,8 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx, json_t *esc_methods; size_t recovery_document_size; char *recovery_document_str; + size_t meta_size; + void *meta; if (0 == pss_length) { @@ -889,6 +891,18 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx, recovery_document_str = (char *) cbuf; } + meta_size = sizeof (struct GNUNET_HashCode); + if (NULL != secret_name) + meta_size += strlen (secret_name) + 1; + meta = GNUNET_malloc (meta_size); + GNUNET_CRYPTO_hash (recovery_document_str, + recovery_document_size, + (struct GNUNET_HashCode *) meta); + if (NULL != secret_name) + memcpy (meta + sizeof (struct GNUNET_HashCode), + secret_name, + strlen (secret_name) + 1); + for (unsigned int l = 0; l < ss->pss_length; l++) { struct PolicyStoreState *pss = &ss->pss[l]; @@ -905,12 +919,11 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx, ANASTASIS_CRYPTO_user_identifier_derive (id_data, &pss->server_salt, &pss->id); - if (NULL != secret_name) - ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id, - secret_name, - strlen (secret_name), - &enc_meta, - &enc_meta_size); + ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id, + meta, + meta_size, + &enc_meta, + &enc_meta_size); ANASTASIS_CRYPTO_account_private_key_derive (&pss->id, &anastasis_priv); ANASTASIS_CRYPTO_recovery_document_encrypt (&pss->id, @@ -943,9 +956,11 @@ ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx, GNUNET_break (0); ANASTASIS_secret_share_cancel (ss); GNUNET_free (recovery_document_str); + GNUNET_free (meta); return NULL; } } + GNUNET_free (meta); GNUNET_free (recovery_document_str); return ss; } diff --git a/src/lib/anastasis_meta.c b/src/lib/anastasis_meta.c new file mode 100644 index 0000000..7812f6b --- /dev/null +++ b/src/lib/anastasis_meta.c @@ -0,0 +1,180 @@ +/* + This file is part of Anastasis + Copyright (C) 2022 Anastasis SARL + + 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.GPL. If not, see +*/ +/** + * @brief anastasis client api to get recovery document meta data + * @author Christian Grothoff + */ +#include "platform.h" +#include "anastasis.h" +#include +#include +#include + + +/** + * Handle for a version check operation. + */ +struct ANASTASIS_VersionCheck +{ + /** + * Function to call with results. + */ + ANASTASIS_MetaPolicyCallback mpc; + + /** + * Closure for @e mpc. + */ + void *mpc_cls; + + /** + * Handle for the actual REST operation. + */ + struct ANASTASIS_PolicyMetaLookupOperation *plm; + + /** + * User identifier (needed to decrypt). + */ + struct ANASTASIS_CRYPTO_UserIdentifierP id; +}; + + +/** + * Function called with results from a GET /policy/$POL/meta request + * + * @param cls closure with the `struct ANASTASIS_VersionCheck *` + * @param http_status HTTP status code for this request + * @param dd the response details + */ +static void +meta_cb ( + void *cls, + unsigned int http_status, + const struct ANASTASIS_MetaDownloadDetails *dd) +{ + struct ANASTASIS_VersionCheck *vc = cls; + + vc->plm = NULL; + if ( (MHD_HTTP_OK != http_status) || + (NULL == dd) ) + { + vc->mpc (vc->mpc_cls, + 0, + GNUNET_TIME_UNIT_ZERO_TS, + NULL, + NULL); + ANASTASIS_recovery_get_versions_cancel (vc); + return; + } + for (size_t i = 0; imetas_length; i++) + { + const struct ANASTASIS_MetaDataEntry *meta = &dd->metas[i]; + const char *secret_name = NULL; + const struct GNUNET_HashCode *eph; + void *dec; + size_t dec_len; + + if (GNUNET_OK != + ANASTASIS_CRYPTO_recovery_metadata_decrypt ( + &vc->id, + meta->meta_data, + meta->meta_data_size, + &dec, + &dec_len)) + { + GNUNET_break_op (0); + continue; + } + if (sizeof (*eph) > dec_len) + { + GNUNET_break_op (0); + GNUNET_free (dec); + continue; + } + eph = dec; + if (sizeof (*eph) < dec_len) + { + secret_name = (const char *) &eph[1]; + dec_len -= sizeof (*eph); + if ('\0' != secret_name[dec_len - 1]) + { + GNUNET_break_op (0); + GNUNET_free (dec); + continue; + } + } + vc->mpc (vc->mpc_cls, + meta->version, + meta->server_time, + eph, + secret_name); + GNUNET_free (dec); + } + vc->mpc (vc->mpc_cls, + 0, + GNUNET_TIME_UNIT_ZERO_TS, + NULL, + NULL); + ANASTASIS_recovery_get_versions_cancel (vc); +} + + +struct ANASTASIS_VersionCheck * +ANASTASIS_recovery_get_versions ( + struct GNUNET_CURL_Context *ctx, + const json_t *id_data, + unsigned int max_version, + const char *anastasis_provider_url, + const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt, + ANASTASIS_MetaPolicyCallback mpc, + void *mpc_cls) +{ + struct ANASTASIS_VersionCheck *vc; + struct ANASTASIS_CRYPTO_AccountPublicKeyP account_pub; + + vc = GNUNET_new (struct ANASTASIS_VersionCheck); + vc->mpc = mpc; + vc->mpc_cls = mpc_cls; + ANASTASIS_CRYPTO_user_identifier_derive (id_data, + provider_salt, + &vc->id); + ANASTASIS_CRYPTO_account_public_key_derive (&vc->id, + &account_pub); + vc->plm = ANASTASIS_policy_meta_lookup (ctx, + anastasis_provider_url, + &account_pub, + max_version, + &meta_cb, + vc); + if (NULL == vc->plm) + { + GNUNET_break (0); + GNUNET_free (vc); + return NULL; + } + return vc; +} + + +void +ANASTASIS_recovery_get_versions_cancel (struct ANASTASIS_VersionCheck *vc) +{ + if (NULL != vc->plm) + { + ANASTASIS_policy_meta_lookup_cancel (vc->plm); + vc->plm = NULL; + } + GNUNET_free (vc); +} -- cgit v1.2.3