/*
This file is part of GNUnet
Copyright (C) 2020 GNUnet e.V.
GNUnet is free software: you can redistribute it and/or modify it
under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License,
or (at your option) any later version.
GNUnet 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
Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
SPDX-License-Identifier: AGPL3.0-or-later
*/
/**
* @file escrow/plugin_escrow_gns.c
* @brief escrow-plugin-gns escrow plugin for the escrow of the key
* using GNS and escrow identities
*
* @author Johannes Späth
*/
#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_escrow_plugin.h"
#include "escrow_plugin_helper.h"
#include
#include
struct ESCROW_GnsPluginOperation
{
/**
* Handle for the escrow component
*/
struct GNUNET_ESCROW_Handle *h;
/**
* Scheduler task the SCHEDULE operation returns (needed for cancellation)
*/
struct GNUNET_SCHEDULER_Task *sched_task;
};
/**
* Identity handle
*/
static struct GNUNET_IDENTITY_Handle *identity_handle;
/**
* Handle for the plugin instance
*/
struct ESCROW_PluginHandle ph;
/**
* Start the GNS escrow of the key
*
* @param h the handle for the escrow component
* @param ego the identity ego containing the private key
* @param cb the function called upon completion
* @param op_id unique ID of the respective ESCROW_Operation
*
* @return plugin operation wrapper
*/
struct ESCROW_PluginOperationWrapper *
start_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
const struct GNUNET_IDENTITY_Ego *ego,
GNUNET_SCHEDULER_TaskCallback cb,
uint32_t op_id)
{
const struct GNUNET_CRYPTO_EcdsaPrivateKey *pk;
sss_Keyshare keyshares;
struct GNUNET_ESCROW_Anchor *anchor;
int anchorDataSize;
struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
struct ESCROW_GnsPluginOperation *p_op;
struct ESCROW_Plugin_AnchorContinuationWrapper *w;
unsigned long long shares, share_threshold;
// create a new GNS plugin operation (in a wrapper) and insert it into the DLL
plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
ph.plugin_op_tail,
plugin_op_wrap);
p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
p_op->h = h;
w = GNUNET_new (struct ESCROW_Plugin_AnchorContinuationWrapper);
w->h = h;
w->op_id = op_id;
if (NULL == ego)
{
w->escrowAnchor = NULL;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
pk = GNUNET_IDENTITY_ego_get_private_key (ego);
// split the private key (SSS)
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (h->cfg,
"escrow",
"gns_shares",
&shares))
{
fprintf (stderr, "Number of shares not specified in config!");
w->escrowAnchor = NULL;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (h->cfg,
"escrow",
"gns_share_threshold",
&share_threshold))
{
fprintf (stderr, "Share threshold not specified in config");
w->escrowAnchor = NULL;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
sss_create_keyshares (&keyshares,
pk->d,
(uint8_t)shares,
(uint8_t)share_threshold);
// create the escrow identities
// distribute the shares to the identities
// TODO: implement
anchorDataSize = 0; // TODO!
anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + anchorDataSize);
w->escrowAnchor = anchor;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
/**
* Verify the GNS escrow of the key
*
* @param h the handle for the escrow component
* @param ego the identity ego containing the private key
* @param escrowAnchor the escrow anchor needed to restore the key
* @param cb the function called upon completion
* @param op_id unique ID of the respective ESCROW_Operation
*
* @return plugin operation wrapper
*/
struct ESCROW_PluginOperationWrapper *
verify_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
const struct GNUNET_IDENTITY_Ego *ego,
struct GNUNET_ESCROW_Anchor *escrowAnchor,
GNUNET_SCHEDULER_TaskCallback cb,
uint32_t op_id)
{
struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
struct ESCROW_GnsPluginOperation *p_op;
struct ESCROW_Plugin_VerifyContinuationWrapper *w;
// create a new GNS plugin operation (in a wrapper) and insert it into the DLL
plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
ph.plugin_op_tail,
plugin_op_wrap);
p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
p_op->h = h;
w = GNUNET_new (struct ESCROW_Plugin_VerifyContinuationWrapper);
w->h = h;
w->op_id = op_id;
// TODO: implement
w->verificationResult = GNUNET_ESCROW_INVALID;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
/**
* Restore the key from GNS escrow
*
* @param h the handle for the escrow component
* @param escrowAnchor the escrow anchor needed to restore the key
* @param egoName the name of the ego to restore
* @param cb the function called upon completion
* @param op_id unique ID of the respective ESCROW_Operation
*
* @return plugin operation wrapper
*/
struct ESCROW_PluginOperationWrapper *
restore_gns_key_escrow (struct GNUNET_ESCROW_Handle *h,
struct GNUNET_ESCROW_Anchor *escrowAnchor,
char *egoName,
GNUNET_SCHEDULER_TaskCallback cb,
uint32_t op_id)
{
struct ESCROW_PluginOperationWrapper *plugin_op_wrap;
struct ESCROW_GnsPluginOperation *p_op;
struct ESCROW_Plugin_EgoContinuationWrapper *w;
// create a new GNS plugin operation (in a wrapper) and insert it into the DLL
plugin_op_wrap = GNUNET_new (struct ESCROW_PluginOperationWrapper);
plugin_op_wrap->plugin_op = GNUNET_new (struct ESCROW_GnsPluginOperation);
GNUNET_CONTAINER_DLL_insert_tail (ph.plugin_op_head,
ph.plugin_op_tail,
plugin_op_wrap);
p_op = (struct ESCROW_GnsPluginOperation *)plugin_op_wrap->plugin_op;
p_op->h = h;
w = GNUNET_new (struct ESCROW_Plugin_EgoContinuationWrapper);
w->h = h;
w->op_id = op_id;
// TODO: implement
w->ego = NULL;
p_op->sched_task = GNUNET_SCHEDULER_add_now (cb, w);
return plugin_op_wrap;
}
/**
* Get the status of a GNS escrow
*
* @param h the handle for the escrow component
* @param ego the identity ego of which the status has to be obtained
* @param escrowAnchor the escrow anchor needed to restore the key
*
* @return the status of the escrow packed into a GNUNET_ESCROW_Status struct
*/
struct GNUNET_ESCROW_Status *
gns_get_status (struct GNUNET_ESCROW_Handle *h,
const struct GNUNET_IDENTITY_Ego *ego,
struct GNUNET_ESCROW_Anchor *escrowAnchor)
{
struct GNUNET_ESCROW_Status *status;
status = GNUNET_new (struct GNUNET_ESCROW_Status);
// TODO: get the correct time values
status->last_escrow_time = GNUNET_TIME_absolute_get ();
status->next_recommended_escrow_time = GNUNET_TIME_absolute_get ();
// END TODO
return status;
}
/**
* Deserialize an escrow anchor string into a GNUNET_ESCROW_Anchor struct
*
* @param anchorString the encoded escrow anchor string
*
* @return the deserialized data packed into a GNUNET_ESCROW_Anchor struct
*/
struct GNUNET_ESCROW_Anchor *
gns_anchor_string_to_data (struct GNUNET_ESCROW_Handle *h,
char *anchorString)
{
struct GNUNET_ESCROW_Anchor *anchor;
uint32_t data_size;
data_size = strlen (anchorString) + 1;
anchor = GNUNET_malloc (sizeof (struct GNUNET_ESCROW_Anchor) + data_size);
anchor->size = data_size;
// TODO: deserialize?
GNUNET_memcpy (&anchor[1], anchorString, data_size);
return anchor;
}
/**
* Serialize an escrow anchor struct into a string
*
* @param h the handle for the escrow component
* @param escrowAnchor the escrow anchor struct
*
* @return the encoded escrow anchor string
*/
char *
gns_anchor_data_to_string (struct GNUNET_ESCROW_Handle *h,
struct GNUNET_ESCROW_Anchor *escrowAnchor)
{
// TODO: implement
return NULL;
}
/**
* Cancel a GNS plugin operation.
*
* @param plugin_op_wrap the plugin operation wrapper containing the operation
*/
void
cancel_gns_operation (struct ESCROW_PluginOperationWrapper *plugin_op_wrap)
{
// TODO: implement
return;
}
/**
* IdentityInitContinuation for the GNS plugin
*/
void
gns_cont_init ()
{
return;
}
/**
* Entry point for the plugin.
*
* @param cls Config info
*
* @return the exported block API
*/
void *
libgnunet_plugin_escrow_gns_init (void *cls)
{
struct GNUNET_ESCROW_KeyPluginFunctions *api;
struct GNUNET_CONFIGURATION_Handle *cfg = cls;
api = GNUNET_new (struct GNUNET_ESCROW_KeyPluginFunctions);
api->start_key_escrow = &start_gns_key_escrow;
api->verify_key_escrow = &verify_gns_key_escrow;
api->restore_key = &restore_gns_key_escrow;
api->get_status = &gns_get_status;
api->anchor_string_to_data = &gns_anchor_string_to_data;
api->cancel_plugin_operation = &cancel_gns_operation;
ph.id_init_cont = &gns_cont_init;
identity_handle = GNUNET_IDENTITY_connect (cfg,
&ESCROW_list_ego,
&ph);
return api;
}
/**
* Exit point from the plugin.
*
* @param cls the return value from #libgnunet_plugin_block_test_init()
*
* @return NULL
*/
void *
libgnunet_plugin_escrow_gns_done (void *cls)
{
struct GNUNET_RECLAIM_EscrowKeyPluginFunctions *api = cls;
GNUNET_free (api);
GNUNET_IDENTITY_disconnect (identity_handle);
ESCROW_cleanup_ego_list (&ph);
return NULL;
}
/* end of plugin_escrow_gns.c */