summaryrefslogtreecommitdiff
path: root/src/reclaim/pabc_helper.c
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2021-02-22 10:16:16 +0100
committerMartin Schanzenbach <mschanzenbach@posteo.de>2021-04-24 00:56:26 +0200
commit3cd24823660a0447e590ff352e9da7eb076b292b (patch)
tree7e6feb37058bd9885ef0447d38c2fb77f6f97c57 /src/reclaim/pabc_helper.c
parent8d48dbafe69193f8a23765154be1f7db851bfa1c (diff)
RECLAIM: Added libpabc credential support.dev/schanzen/pabc
Diffstat (limited to 'src/reclaim/pabc_helper.c')
-rw-r--r--src/reclaim/pabc_helper.c364
1 files changed, 364 insertions, 0 deletions
diff --git a/src/reclaim/pabc_helper.c b/src/reclaim/pabc_helper.c
new file mode 100644
index 000000000..1b1dbea0f
--- /dev/null
+++ b/src/reclaim/pabc_helper.c
@@ -0,0 +1,364 @@
+// maximilian.kaul@aisec.fraunhofer.de
+
+// WIP implementation of
+// https://github.com/ontio/ontology-crypto/wiki/Anonymous-Credential
+// using the relic library https://github.com/relic-toolkit/relic/
+
+#include "pabc_helper.h"
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static char pabc_dir[PATH_MAX + 1];
+
+static const char *
+get_homedir ()
+{
+ const char *homedir;
+ if ((homedir = getenv ("HOME")) == NULL)
+ {
+ homedir = getpwuid (getuid ())->pw_dir;
+ }
+ return homedir;
+}
+
+
+static enum GNUNET_GenericReturnValue
+write_file (char const *const filename, const char *buffer)
+{
+ struct GNUNET_DISK_FileHandle *fh;
+ fh = GNUNET_DISK_file_open (filename,
+ GNUNET_DISK_OPEN_WRITE
+ | GNUNET_DISK_OPEN_TRUNCATE
+ | GNUNET_DISK_OPEN_CREATE,
+ GNUNET_DISK_PERM_USER_WRITE
+ | GNUNET_DISK_PERM_USER_READ);
+ if (fh == NULL)
+ return GNUNET_SYSERR;
+ if (GNUNET_SYSERR == GNUNET_DISK_file_write (fh,
+ buffer, strlen (buffer) + 1))
+ goto fail;
+ GNUNET_DISK_file_close (fh);
+ return GNUNET_OK;
+
+fail:
+ GNUNET_DISK_file_close (fh);
+ return GNUNET_SYSERR;
+}
+
+
+static enum GNUNET_GenericReturnValue
+init_pabc_dir ()
+{
+ size_t filename_size = strlen (get_homedir ()) + 1 + strlen (".local") + 1
+ + strlen ("pabc-reclaim") + 1;
+ snprintf (pabc_dir, filename_size, "%s/%s/%s",
+ get_homedir (), ".local", "pabc-reclaim");
+ return GNUNET_DISK_directory_create (pabc_dir);
+}
+
+
+static const char *
+get_pabcdir ()
+{
+ init_pabc_dir ();
+ return pabc_dir;
+}
+
+
+enum GNUNET_GenericReturnValue
+read_file (char const *const filename, char **buffer)
+{
+ struct GNUNET_DISK_FileHandle *fh;
+ if (GNUNET_YES != GNUNET_DISK_file_test (filename))
+ return GNUNET_SYSERR;
+
+ fh = GNUNET_DISK_file_open (filename,
+ GNUNET_DISK_OPEN_READ,
+ GNUNET_DISK_PERM_USER_READ);
+ if (fh == NULL)
+ return GNUNET_SYSERR;
+ long lSize = GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_END);
+ if (lSize < 0)
+ goto fail;
+ GNUNET_DISK_file_seek (fh, 0, GNUNET_DISK_SEEK_SET);
+ *buffer = calloc ((size_t) lSize + 1, sizeof(char));
+ if (*buffer == NULL)
+ goto fail;
+
+ // copy the file into the buffer:
+ size_t r = GNUNET_DISK_file_read (fh, *buffer, (size_t) lSize);
+ if (r != (size_t) lSize)
+ goto fail;
+
+ GNUNET_DISK_file_close (fh);
+ return GNUNET_OK;
+
+fail:
+ GNUNET_DISK_file_close (fh);
+ return GNUNET_SYSERR;
+}
+
+
+struct pabc_public_parameters *
+PABC_read_issuer_ppfile (const char *f, struct pabc_context *const ctx)
+{
+ if (NULL == ctx)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No global context provided\n");
+ return NULL;
+ }
+ struct pabc_public_parameters *pp;
+ char *buffer;
+ int r;
+ r = read_file (f, &buffer);
+ if (GNUNET_OK != r)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading file\n");
+ return NULL;
+ }
+ if (PABC_OK != pabc_decode_and_new_public_parameters (ctx, &pp, buffer))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to decode public parameters\n");
+ PABC_FREE_NULL (buffer);
+ return NULL;
+ }
+ PABC_FREE_NULL (buffer);
+ return pp;
+}
+
+
+enum GNUNET_GenericReturnValue
+PABC_load_public_parameters (struct pabc_context *const ctx,
+ char const *const pp_name,
+ struct pabc_public_parameters **pp)
+{
+ char fname[PATH_MAX];
+ char *pp_filename;
+ const char *pdir = get_pabcdir ();
+
+ if (ctx == NULL)
+ return GNUNET_SYSERR;
+ if (pp_name == NULL)
+ return GNUNET_SYSERR;
+
+ GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
+ if (GNUNET_YES != GNUNET_DISK_directory_test (pdir, GNUNET_YES))
+ {
+ GNUNET_free (pp_filename);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error reading %s\n", pdir);
+ return GNUNET_SYSERR;
+ }
+ snprintf (fname, PATH_MAX, "%s/%s%s", pdir, pp_filename, PABC_PP_EXT);
+ if (GNUNET_YES != GNUNET_DISK_file_test (fname))
+ {
+ GNUNET_free (pp_filename);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error testing %s\n", fname);
+ return GNUNET_SYSERR;
+ }
+ *pp = PABC_read_issuer_ppfile (fname, ctx);
+ if (*pp)
+ return GNUNET_OK;
+ else
+ return GNUNET_SYSERR;
+}
+
+
+enum GNUNET_GenericReturnValue
+PABC_write_public_parameters (char const *const pp_name,
+ struct pabc_public_parameters *const pp)
+{
+ char *json;
+ char *filename;
+ char *pp_filename;
+ enum pabc_status status;
+ struct pabc_context *ctx = NULL;
+
+ GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
+ PABC_ASSERT (pabc_new_ctx (&ctx));
+ // store in json file
+ status = pabc_encode_public_parameters (ctx, pp, &json);
+ if (status != PABC_OK)
+ {
+ GNUNET_free (pp_filename);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to encode public parameters.\n");
+ pabc_free_ctx (&ctx);
+ return GNUNET_SYSERR;
+ }
+
+ size_t filename_size =
+ strlen (get_pabcdir ()) + 1 + strlen (pp_filename) + strlen (PABC_PP_EXT)
+ + 1;
+ filename = GNUNET_malloc (filename_size);
+ if (! filename)
+ {
+ GNUNET_free (pp_filename);
+ PABC_FREE_NULL (json);
+ pabc_free_ctx (&ctx);
+ return GNUNET_SYSERR;
+ }
+ snprintf (filename, filename_size, "%s/%s%s", get_pabcdir (), pp_filename,
+ PABC_PP_EXT);
+
+ GNUNET_free (pp_filename);
+ if (GNUNET_OK != write_file (filename, json))
+ {
+ PABC_FREE_NULL (filename);
+ PABC_FREE_NULL (json);
+ pabc_free_ctx (&ctx);
+ return GNUNET_SYSERR;
+ }
+ PABC_FREE_NULL (filename);
+ PABC_FREE_NULL (json);
+ pabc_free_ctx (&ctx);
+ return GNUNET_OK;
+}
+
+
+enum GNUNET_GenericReturnValue
+PABC_write_usr_ctx (char const *const usr_name,
+ char const *const pp_name,
+ struct pabc_context const *const ctx,
+ struct pabc_public_parameters const *const pp,
+ struct pabc_user_context *const usr_ctx)
+{
+
+ char *pp_filename;
+ char *json = NULL;
+ enum pabc_status status;
+ char *fname = NULL;
+
+ if (NULL == usr_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == pp_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == ctx)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == pp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == usr_ctx)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
+ return GNUNET_SYSERR;
+ }
+
+ GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
+ status = pabc_encode_user_ctx (ctx, pp, usr_ctx, &json);
+ if (PABC_OK != status)
+ {
+ GNUNET_free (pp_filename);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
+ return status;
+ }
+
+ size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
+ + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
+ fname = GNUNET_malloc (fname_size);
+
+ snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
+ pp_filename,
+ PABC_USR_EXT);
+
+ GNUNET_free (pp_filename);
+ if (GNUNET_OK == write_file (fname, json))
+ {
+ GNUNET_free (fname);
+ GNUNET_free (json);
+ return GNUNET_OK;
+ }
+ else
+ {
+ GNUNET_free (fname);
+ GNUNET_free (json);
+ return GNUNET_SYSERR;
+ }
+}
+
+
+enum GNUNET_GenericReturnValue
+PABC_read_usr_ctx (char const *const usr_name,
+ char const *const pp_name,
+ struct pabc_context const *const ctx,
+ struct pabc_public_parameters const *const pp,
+ struct pabc_user_context **usr_ctx)
+{
+ char *json = NULL;
+ char *pp_filename;
+ enum pabc_status status;
+
+ char *fname = NULL;
+
+ if (NULL == usr_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No issuer given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == pp_name)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == ctx)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No context given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == pp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No public parameters given.\n");
+ return GNUNET_SYSERR;
+ }
+ if (NULL == usr_ctx)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No user context given.\n");
+ return GNUNET_SYSERR;
+ }
+ GNUNET_STRINGS_urlencode (pp_name, strlen (pp_name), &pp_filename);
+
+ size_t fname_size = strlen (get_pabcdir ()) + 1 + strlen (usr_name) + 1
+ + strlen (pp_filename) + strlen (PABC_USR_EXT) + 1;
+ fname = GNUNET_malloc (fname_size);
+ snprintf (fname, fname_size, "%s/%s_%s%s", get_pabcdir (), usr_name,
+ pp_filename,
+ PABC_USR_EXT);
+ GNUNET_free (pp_filename);
+ if (GNUNET_OK != read_file (fname, &json))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to read `%s'\n", fname);
+ PABC_FREE_NULL (fname);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_free (fname);
+
+ status = pabc_new_user_context (ctx, pp, usr_ctx);
+ if (PABC_OK != status)
+ {
+ GNUNET_free (json);
+ return GNUNET_SYSERR;
+ }
+ status = pabc_decode_user_ctx (ctx, pp, *usr_ctx, json);
+ GNUNET_free (json);
+ if (PABC_OK != status)
+ {
+ pabc_free_user_context (ctx, pp, usr_ctx);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to encode user context.\n");
+ return GNUNET_SYSERR;
+ }
+
+ return GNUNET_OK;
+}