From 303ab4dafbc680b1b362f95df5b12dae831b1593 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 6 Aug 2013 20:46:22 +0000 Subject: -fixing main FS build, updating man page of gnunet-pseudonym --- doc/man/gnunet-pseudonym.1 | 31 +- src/Makefile.am | 1 + src/fs/Makefile.am | 3 + src/fs/fs_api.c | 35 +- src/fs/fs_api.h | 128 +--- src/fs/fs_namespace.c | 772 ++++++++--------------- src/fs/fs_pseudonym.c | 977 ++--------------------------- src/fs/fs_publish.c | 30 +- src/fs/fs_publish_ksk.c | 179 ++---- src/fs/fs_publish_ublock.c | 262 ++++++++ src/fs/fs_publish_ublock.h | 108 ++++ src/fs/fs_search.c | 114 ++-- src/fs/fs_unindex.c | 25 +- src/fs/fs_uri.c | 109 ++-- src/fs/gnunet-pseudonym.c | 260 ++++---- src/fs/gnunet-publish.c | 211 ++++--- src/fs/plugin_block_fs.c | 9 +- src/fs/test_fs_namespace.c | 53 +- src/fs/test_fs_namespace_list_updateable.c | 14 +- src/fs/test_fs_uri.c | 9 +- src/fs/test_pseudonym.c | 148 +---- src/identity/identity_api.c | 25 +- src/include/block_fs.h | 9 +- src/include/gnunet_crypto_lib.h | 12 +- src/include/gnunet_fs_service.h | 375 +---------- src/include/gnunet_identity_service.h | 13 +- src/util/crypto_ecc.c | 25 + 27 files changed, 1270 insertions(+), 2667 deletions(-) create mode 100644 src/fs/fs_publish_ublock.c create mode 100644 src/fs/fs_publish_ublock.h diff --git a/doc/man/gnunet-pseudonym.1 b/doc/man/gnunet-pseudonym.1 index 1e6de87af..6254283ad 100644 --- a/doc/man/gnunet-pseudonym.1 +++ b/doc/man/gnunet-pseudonym.1 @@ -1,18 +1,18 @@ -.TH GNUNET-PSEUDONYM "1" "25 Feb 2012" "GNUnet" +.TH GNUNET-PSEUDONYM "1" "6 Aug 2013" "GNUnet" .SH NAME -gnunet\-pseudonym \- create, delete or list pseudonyms +gnunet\-pseudonym \- advertise or list pseudonyms .SH SYNOPSIS .B gnunet\-pseudonym [options] .SH DESCRIPTION .PP -gnunet\-pseudonym is a tool for managing pseudonyms and namespaces. A pseudonym is the persona that controls a namespace. As such, it is identical to a public\-private RSA key pair. A namespace is a collection of files that have been signed by the corresponding private RSA key. A namespace is typically associated with a nickname and other metadata. +gnunet\-pseudonym is a tool for advertising pseudonyms. A pseudonym is the persona that controls a namespace. As such, it is identical to a public\-private ECC key pair. A namespace is a collection of files that have been signed by the corresponding private ECC key. A namespace is typically associated with a nickname and other metadata. Namespaces are an important tool for providing assurances about content integrity and authenticity in GNUnet. Since all of the content in the namespace must have been provided by the same entity, users can form an opinion about that entity and learn to search (or avoid) certain namespaces. -gnunet\-pseudonym can be used to list all of the pseudonyms that were created locally, to create new pseudonyms, to delete existing pseudonyms (the namespace will continue to exist, but it will be impossible to add additional data to it) and to list all of the namespaces (with their meta-data) known to the local user. By default, gnunet\-pseudonym lists all pseudonyms that were discovered so far. +gnunet\-pseudonym can be used to list all of the pseudonyms that were created locally, to advertise namespaces to other users, and to list all of the namespaces (with their meta\-data) known to the local user. By default, gnunet\-pseudonym lists all pseudonyms that were discovered so far. -Creating a new pseudonym requires using the \-C option together with a nickname that is to be used for the namespace. Nicknames must be unique for each user, global uniqueness is desirable but not necessary. If two namespaces in GNUnet use the same nickname all GNUnet tools will display the nickname together with a number which ensures that the name becomes locally unique to avoid ambiguity. Additional options can be passed together with the \-C option to provide additional meta\-data that describes the namespace. Possible meta\-data includes the 'realname' of the person controlling the namespace, a description, the mime\-type for content in the namespace (useful if the namespace is dedicated to some specific type of content) and contact information. One important piece of meta\-data that can be specified is the identifier of a document root, that is the name of a file in the namespace that is a portal to the rest of the content. This is useful to help users find this root in the absence of conventions. Note that all of this meta\-data is optional and should never be trusted blindly. +Advertising a pseudonym requires using the \-A option together with the name of the pseudonym. Names for pseudonyms controlled by the user must be unique. However, names for namespaces of other users may not be globally unique. If two foreign namespaces in GNUnet use the same nickname, all GNUnet tools will display the nickname together with a number which ensures that the name becomes locally unique to avoid ambiguity. Additional options can be passed together with the \-A option to provide additional meta\-data that describes the namespace. Possible meta\-data includes the 'realname' of the person controlling the namespace, a description, the mime\-type for content in the namespace (useful if the namespace is dedicated to some specific type of content) and contact information. One important piece of meta\-data that can be specified is the identifier of a document root, that is the name of a file in the namespace that is a portal to the rest of the content. This is useful to help users find this root in the absence of conventions. Note that all of this meta\-data is optional and should never be trusted blindly. As mentioned before, by default, gnunet\-pseudonym simply lists the meta\-data available for other namespaces. Namespaces can be discovered whenever the peer obtains the namespace advertisement. Namespace advertisements can be found using ordinary keyword\-based searches (by default gnunet\-pseudonym publishes the namespace advertisement under the keyword 'namespace', but the \-k option can be used to specify other keywords) and under the 'empty' identifier of the respective namespace (using a namespace\-search if the namespace ID is already known). @@ -23,12 +23,8 @@ For more details about GNUnet namespaces and content encoding please read the 'E set desired level of sender anonymity. Default is 1. .TP -\fB\-C NAME\fR, \fB\-\-create=NAME\fR -Creates a new pseudonym with the given NAME or creates a new advertisement for the pseudonym with the given NAME (if the pseudonym already exists). - -.TP -\fB\-D NAME\fR, \fB\-\-delete=NAME\fR -Delete the pseudonym with the given NAME. +\fB\-A NAME\fR, \fB\-\-advertise=NAME\fR +Advertise namespace of the pseudonym with the given NAME. .TP \fB\-h\fR, \fB\-\-help\fR @@ -42,10 +38,6 @@ Publish a namespace advertisement under the keyword 'KEYWORD'. Default is 'name \fB\-m \fITYPE:VALUE\fR, \fB\-\-meta=\fITYPE:VALUE\fR For the main file (or directory), set the metadata of the given TYPE to the given VALUE. Note that this will not add the respective VALUE to the set of keywords under which the file can be found. -.TP -\fB\-o\fR, \fB\-\-only\-local\fR -display names of local namespaces (those that we can extend with content because we created them) - .TP \fB\-p \fIPRIORITY\fR, \fB\-\-prio=\fIPRIORITY\fR Set the priority of the namespace advertisement (default: 365). If the local database is full, GNUnet will discard the content with the lowest ranking. Note that ranks change over time depending on popularity. The default should be high enough to preserve the locally inserted content in favor of content that migrates from other peers. @@ -68,10 +60,13 @@ Change the rating for the namespace identified by ID by VALUE. For example, "\- .SH FILES .TP -~/.gnunet/data/pseudonyms/ -Directory where the pseudonyms are stored +~/.gnunet/data/pseudonym/ +Directory where information about non-local pseudonyms is stored +.TP +~/.gnunet/fs/updates/ +Directory where information about possible updates to local pseudonyms is stored .SH "REPORTING BUGS" Report bugs by using Mantis or by sending electronic mail to .SH "SEE ALSO" -\fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1) +\fBgnunet\-identity\fP(1), \fBgnunet\-publish\fP(1), \fBgnunet\-search\fP(1) diff --git a/src/Makefile.am b/src/Makefile.am index 9126815f4..00c4d6f93 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -64,6 +64,7 @@ SUBDIRS = \ dns \ identity \ set \ + fs \ $(LINUX_DIR) \ $(MINGW_DIR) \ gns \ diff --git a/src/fs/Makefile.am b/src/fs/Makefile.am index e8928f770..ce70ff751 100644 --- a/src/fs/Makefile.am +++ b/src/fs/Makefile.am @@ -39,6 +39,7 @@ libgnunetfs_la_SOURCES = \ fs_pseudonym.c \ fs_publish.c \ fs_publish_ksk.c \ + fs_publish_ublock.c fs_publish_ublock.h \ fs_misc.c \ fs_namespace.c \ fs_search.c \ @@ -126,6 +127,7 @@ gnunet_download_DEPENDENCIES = \ gnunet_publish_SOURCES = \ gnunet-publish.c gnunet_publish_LDADD = \ + $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ @@ -154,6 +156,7 @@ gnunet_helper_fs_publish_DEPENDENCIES = \ gnunet_pseudonym_SOURCES = \ gnunet-pseudonym.c gnunet_pseudonym_LDADD = \ + $(top_builddir)/src/identity/libgnunetidentity.la \ $(top_builddir)/src/fs/libgnunetfs.la \ $(top_builddir)/src/util/libgnunetutil.la \ -lextractor \ diff --git a/src/fs/fs_api.c b/src/fs/fs_api.c index ab49139b9..9676f2e3c 100644 --- a/src/fs/fs_api.c +++ b/src/fs/fs_api.c @@ -1467,17 +1467,17 @@ deserialize_publish_file (void *cls, const char *filename) struct GNUNET_FS_PublishContext *pc; int32_t options; int32_t all_done; + int32_t have_ns; char *fi_root; - char *ns; + struct GNUNET_CRYPTO_EccPrivateKey ns; char *fi_pos; char *emsg; - pc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); + pc = GNUNET_new (struct GNUNET_FS_PublishContext); pc->h = h; pc->serialization = get_serialization_short_name (filename); fi_root = NULL; fi_pos = NULL; - ns = NULL; rh = GNUNET_BIO_read_open (filename); if (NULL == rh) { @@ -1489,10 +1489,12 @@ deserialize_publish_file (void *cls, const char *filename) GNUNET_BIO_read_string (rh, "publish-nuid", &pc->nuid, 1024)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &options)) || (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &all_done)) || + (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &have_ns)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-firoot", &fi_root, 128)) || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-fipos", &fi_pos, 128)) - || (GNUNET_OK != GNUNET_BIO_read_string (rh, "publish-ns", &ns, 1024))) + || ( (GNUNET_YES == have_ns) && + (GNUNET_OK != GNUNET_BIO_read (rh, "publish-ns", &ns, sizeof (ns)))) ) { GNUNET_break (0); goto cleanup; @@ -1510,17 +1512,10 @@ deserialize_publish_file (void *cls, const char *filename) GNUNET_break (0); goto cleanup; } - if (NULL != ns) + if (GNUNET_YES == have_ns) { - pc->ns = GNUNET_FS_namespace_create (h, ns); - if (NULL == pc->ns) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _ - ("Failed to recover namespace `%s', cannot resume publishing operation.\n"), - ns); - goto cleanup; - } + pc->ns = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); + *pc->ns = ns; } if ((0 == (pc->options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) && (GNUNET_YES != pc->all_done)) @@ -1563,7 +1558,6 @@ deserialize_publish_file (void *cls, const char *filename) filename, emsg); GNUNET_free (emsg); } - GNUNET_free_non_null (ns); pc->top = GNUNET_FS_make_top (h, &GNUNET_FS_publish_signal_suspend_, pc); return GNUNET_OK; cleanup: @@ -1571,7 +1565,6 @@ cleanup: GNUNET_free_non_null (pc->nuid); GNUNET_free_non_null (fi_root); GNUNET_free_non_null (fi_pos); - GNUNET_free_non_null (ns); if ((NULL != rh) && (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -1601,6 +1594,7 @@ void GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc) { struct GNUNET_BIO_WriteHandle *wh; + int32_t have_ns; if (NULL == pc->serialization) pc->serialization = @@ -1622,17 +1616,20 @@ GNUNET_FS_publish_sync_ (struct GNUNET_FS_PublishContext *pc) GNUNET_break (0); goto cleanup; } + have_ns = (NULL != pc->ns) ? GNUNET_YES : GNUNET_NO; if ((GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nid)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->nuid)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->options)) || (GNUNET_OK != GNUNET_BIO_write_int32 (wh, pc->all_done)) || + (GNUNET_OK != GNUNET_BIO_write_int32 (wh, have_ns)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, pc->fi->serialization)) || (GNUNET_OK != GNUNET_BIO_write_string (wh, (NULL == pc->fi_pos) ? NULL : pc->fi_pos->serialization)) || - (GNUNET_OK != - GNUNET_BIO_write_string (wh, - (NULL == pc->ns) ? NULL : pc->ns->name))) + ( (NULL != pc->ns) && + GNUNET_BIO_write (wh, + pc->ns, + sizeof (struct GNUNET_CRYPTO_EccPrivateKey)) ) ) { GNUNET_break (0); goto cleanup; diff --git a/src/fs/fs_api.h b/src/fs/fs_api.h index 2fe38f604..83e8c3801 100644 --- a/src/fs/fs_api.h +++ b/src/fs/fs_api.h @@ -182,16 +182,13 @@ struct GNUNET_FS_Uri struct { /** - * Keywords start with a '+' if they are - * mandatory (in which case the '+' is NOT - * part of the keyword) and with a - * simple space if they are optional - * (in which case the space is ALSO not - * part of the actual keyword). + * Keywords start with a '+' if they are mandatory (in which + * case the '+' is NOT part of the keyword) and with a simple + * space if they are optional (in which case the space is ALSO + * not part of the actual keyword). * - * Double-quotes to protect spaces and - * %-encoding are NOT used internally - * (only in URI-strings). + * Double-quotes to protect spaces and %-encoding are NOT used + * internally (only in URI-strings). */ char **keywords; @@ -206,7 +203,7 @@ struct GNUNET_FS_Uri /** * Identifier of the namespace. */ - struct GNUNET_FS_PseudonymIdentifier ns; + struct GNUNET_CRYPTO_EccPublicKey ns; /** * Human-readable identifier chosen for this @@ -1178,7 +1175,7 @@ struct GNUNET_FS_PublishContext /** * Namespace that we are publishing in, NULL if we have no namespace. */ - struct GNUNET_FS_Namespace *ns; + struct GNUNET_CRYPTO_EccPrivateKey *ns; /** * ID of the content in the namespace, NULL if we have no namespace. @@ -1459,17 +1456,23 @@ struct GNUNET_FS_UnindexContext */ struct SearchRequestEntry { - /** - * Hash of the original keyword, used to derive the - * key (for decrypting the KBlock). - */ - struct GNUNET_HashCode ukey; /** * Hash of the public key, also known as the query. */ struct GNUNET_HashCode uquery; + /** + * Derived public key, hashes to 'uquery'. + */ + struct GNUNET_CRYPTO_EccPublicKey dpub; + + /** + * The original keyword, used to derive the + * key (for decrypting the UBlock). + */ + char *keyword; + /** * Map that contains a "struct GNUNET_FS_SearchResult" for each result that * was found under this keyword. Note that the entries will point @@ -1963,99 +1966,6 @@ struct GNUNET_FS_DownloadContext }; -/** - * Information about an (updateable) node in the - * namespace. - */ -struct NamespaceUpdateNode -{ - /** - * Identifier for this node. - */ - char *id; - - /** - * Identifier of children of this node. - */ - char *update; - - /** - * Metadata for this entry. - */ - struct GNUNET_CONTAINER_MetaData *md; - - /** - * URI of this entry in the namespace. - */ - struct GNUNET_FS_Uri *uri; - - /** - * Namespace update generation ID. Used to ensure - * freshness of the tree_id. - */ - unsigned int nug; - - /** - * TREE this entry belongs to (if nug is current). - */ - unsigned int tree_id; - -}; - - -/** - * Handle to one of our namespaces. - */ -struct GNUNET_FS_Namespace -{ - - /** - * Handle to the FS service context. - */ - struct GNUNET_FS_Handle *h; - - /** - * Array with information about nodes in the namespace. - */ - struct NamespaceUpdateNode **update_nodes; - - /** - * Private key for the namespace. - */ - struct GNUNET_FS_PseudonymHandle *key; - - /** - * Hash map mapping identifiers of update nodes - * to the update nodes (initialized on-demand). - */ - struct GNUNET_CONTAINER_MultiHashMap *update_map; - - /** - * Name of the file with the private key. - */ - char *filename; - - /** - * Name of the namespace. - */ - char *name; - - /** - * Size of the update nodes array. - */ - unsigned int update_node_count; - - /** - * Reference counter. - */ - unsigned int rc; - - /** - * Generator for unique nug numbers. - */ - unsigned int nug_gen; -}; - #endif /* end of fs_api.h */ diff --git a/src/fs/fs_namespace.c b/src/fs/fs_namespace.c index d456dc34b..8537ba0e6 100644 --- a/src/fs/fs_namespace.c +++ b/src/fs/fs_namespace.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet - (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2003-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -20,7 +20,7 @@ /** * @file fs/fs_namespace.c - * @brief create and destroy namespaces + * @brief publishing to namespaces, and tracking updateable entries * @author Christian Grothoff */ #include "platform.h" @@ -29,30 +29,91 @@ #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" #include "fs_api.h" +#include "fs_publish_ublock.h" /** - * Return the name of the directory in which we store - * our local namespaces (or rather, their public keys). - * - * @param h global fs handle - * @return NULL on error, otherwise the name of the directory + * Information about an (updateable) node in the + * namespace. */ -static char * -get_namespace_directory (struct GNUNET_FS_Handle *h) +struct NamespaceUpdateNode { - char *dn; + /** + * Identifier for this node. + */ + char *id; - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "IDENTITY_DIR", - &dn)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "fs", "IDENTITY_DIR"); - return NULL; - } - return dn; -} + /** + * Identifier of children of this node. + */ + char *update; + + /** + * Metadata for this entry. + */ + struct GNUNET_CONTAINER_MetaData *md; + + /** + * URI of this entry in the namespace. + */ + struct GNUNET_FS_Uri *uri; + + /** + * Namespace update generation ID. Used to ensure + * freshness of the tree_id. + */ + unsigned int nug; + + /** + * TREE this entry belongs to (if nug is current). + */ + unsigned int tree_id; + +}; + + +/** + * Handle to update information for a namespace. + */ +struct GNUNET_FS_UpdateInformationGraph +{ + + /** + * Handle to the FS service context. + */ + struct GNUNET_FS_Handle *h; + + /** + * Array with information about nodes in the namespace. + */ + struct NamespaceUpdateNode **update_nodes; + + /** + * Private key for the namespace. + */ + struct GNUNET_CRYPTO_EccPrivateKey ns; + + /** + * Hash map mapping identifiers of update nodes + * to the update nodes (initialized on-demand). + */ + struct GNUNET_CONTAINER_MultiHashMap *update_map; + + /** + * Size of the update nodes array. + */ + unsigned int update_node_count; + + /** + * Reference counter. + */ + unsigned int rc; + + /** + * Generator for unique nug numbers. + */ + unsigned int nug_gen; +}; /** @@ -63,32 +124,71 @@ get_namespace_directory (struct GNUNET_FS_Handle *h) * @return NULL on error, otherwise the name of the directory */ static char * -get_update_information_directory (struct GNUNET_FS_Namespace *ns) +get_update_information_directory (struct GNUNET_FS_Handle *h, + const struct GNUNET_CRYPTO_EccPrivateKey *ns) { char *dn; char *ret; + struct GNUNET_CRYPTO_EccPublicKey pub; + struct GNUNET_CRYPTO_ShortHashCode hc; + struct GNUNET_CRYPTO_ShortHashAsciiEncoded enc; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (ns->h->cfg, "FS", "UPDATE_DIR", + GNUNET_CONFIGURATION_get_value_filename (h->cfg, "FS", "UPDATE_DIR", &dn)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "fs", "UPDATE_DIR"); return NULL; } - GNUNET_asprintf (&ret, "%s%s%s", dn, DIR_SEPARATOR_STR, ns->name); + GNUNET_CRYPTO_ecc_key_get_public (ns, &pub); + GNUNET_CRYPTO_short_hash (&pub, sizeof (pub), &hc); + GNUNET_CRYPTO_short_hash_to_enc (&hc, + &enc); + GNUNET_asprintf (&ret, "%s%s%s", + dn, + DIR_SEPARATOR_STR, + (const char *) enc.short_encoding); GNUNET_free (dn); return ret; } +/** + * Release memory occupied by UIG datastructure. + * + * @param uig data structure to free + */ +static void +free_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) +{ + unsigned int i; + struct NamespaceUpdateNode *nsn; + + for (i = 0; i < uig->update_node_count; i++) + { + nsn = uig->update_nodes[i]; + GNUNET_CONTAINER_meta_data_destroy (nsn->md); + GNUNET_FS_uri_destroy (nsn->uri); + GNUNET_free (nsn->id); + GNUNET_free (nsn->update); + GNUNET_free (nsn); + } + GNUNET_array_grow (uig->update_nodes, uig->update_node_count, + 0); + if (NULL != uig->update_map) + GNUNET_CONTAINER_multihashmap_destroy (uig->update_map); + GNUNET_free (uig); +} + + /** * Write the namespace update node graph to a file. * * @param ns namespace to dump */ static void -write_update_information_graph (struct GNUNET_FS_Namespace *ns) +write_update_information_graph (struct GNUNET_FS_UpdateInformationGraph *uig) { char *fn; struct GNUNET_BIO_WriteHandle *wh; @@ -96,7 +196,8 @@ write_update_information_graph (struct GNUNET_FS_Namespace *ns) struct NamespaceUpdateNode *n; char *uris; - fn = get_update_information_directory (ns); + fn = get_update_information_directory (uig->h, + &uig->ns); wh = GNUNET_BIO_write_open (fn); if (NULL == wh) { @@ -105,11 +206,11 @@ write_update_information_graph (struct GNUNET_FS_Namespace *ns) GNUNET_free (fn); return; } - if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, ns->update_node_count)) + if (GNUNET_OK != GNUNET_BIO_write_int32 (wh, uig->update_node_count)) goto END; - for (i = 0; i < ns->update_node_count; i++) + for (i = 0; i < uig->update_node_count; i++) { - n = ns->update_nodes[i]; + n = uig->update_nodes[i]; uris = GNUNET_FS_uri_to_string (n->uri); if ((GNUNET_OK != GNUNET_BIO_write_string (wh, n->id)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (wh, n->md)) || @@ -132,11 +233,15 @@ END: /** * Read the namespace update node graph from a file. * + * @param h FS handle to use * @param ns namespace to read + * @return update graph, never NULL */ -static void -read_update_information_graph (struct GNUNET_FS_Namespace *ns) +static struct GNUNET_FS_UpdateInformationGraph * +read_update_information_graph (struct GNUNET_FS_Handle *h, + const struct GNUNET_CRYPTO_EccPrivateKey *ns) { + struct GNUNET_FS_UpdateInformationGraph *uig; char *fn; struct GNUNET_BIO_ReadHandle *rh; unsigned int i; @@ -145,40 +250,43 @@ read_update_information_graph (struct GNUNET_FS_Namespace *ns) uint32_t count; char *emsg; - fn = get_update_information_directory (ns); + uig = GNUNET_new (struct GNUNET_FS_UpdateInformationGraph); + uig->h = h; + uig->ns = *ns; + fn = get_update_information_directory (h, ns); if (GNUNET_YES != GNUNET_DISK_file_test (fn)) { GNUNET_free (fn); - return; + return uig; } rh = GNUNET_BIO_read_open (fn); if (NULL == rh) { GNUNET_free (fn); - return; + return uig; } if (GNUNET_OK != GNUNET_BIO_read_int32 (rh, &count)) { GNUNET_break (0); - goto END; + goto ERROR; } if (count > 1024 * 1024) { GNUNET_break (0); - goto END; + goto ERROR; } if (0 == count) { GNUNET_break (GNUNET_OK == GNUNET_BIO_read_close (rh, NULL)); GNUNET_free (fn); - return; + return uig; } - ns->update_nodes = - GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *)); + uig->update_nodes = + GNUNET_malloc (count * sizeof (struct NamespaceUpdateNode *)); for (i = 0; i < count; i++) { - n = GNUNET_malloc (sizeof (struct NamespaceUpdateNode)); + n = GNUNET_new (struct NamespaceUpdateNode); if ((GNUNET_OK != GNUNET_BIO_read_string (rh, "identifier", &n->id, 1024)) || (GNUNET_OK != GNUNET_BIO_read_meta_data (rh, "meta", &n->md)) || (GNUNET_OK != @@ -205,304 +313,25 @@ read_update_information_graph (struct GNUNET_FS_Namespace *ns) GNUNET_free (n); break; } - ns->update_nodes[i] = n; + uig->update_nodes[i] = n; } - ns->update_node_count = i; -END: + uig->update_node_count = i; if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to write `%s': %s\n"), emsg); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read `%s': %s\n"), + fn, emsg); GNUNET_free (emsg); } - GNUNET_free (fn); -} - - -/** - * Create a namespace with the given name; if one already - * exists, return a handle to the existing namespace. - * - * @param h handle to the file sharing subsystem - * @param name name to use for the namespace - * @return handle to the namespace, NULL on error (i.e. invalid filename) - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h, const char *name) -{ - char *dn; - char *fn; - struct GNUNET_FS_Namespace *ret; - - dn = get_namespace_directory (h); - if (NULL == dn) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Can't determine where namespace directory is\n")); - return NULL; - } - GNUNET_asprintf (&fn, "%s%s%s", dn, DIR_SEPARATOR_STR, name); - GNUNET_free (dn); - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); - ret->h = h; - ret->rc = 1; - ret->key = GNUNET_FS_pseudonym_create (fn); - if (NULL == ret->key) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to create or read private key for namespace `%s'\n"), - name); - GNUNET_free (ret); - GNUNET_free (fn); - return NULL; - } - ret->name = GNUNET_strdup (name); - ret->filename = fn; - return ret; -} - - -/** - * Open the namespace with the given name; if it does not exist, - * or the key file is corrupted, the function fails. - * - * @param h handle to the file sharing subsystem - * @param name name of the namespace - * @return handle to the namespace, - * NULL on error (i.e. invalid filename, non-existent filename) - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_open_existing (struct GNUNET_FS_Handle *h, const char *name) -{ - char *dn; - char *fn; - struct GNUNET_FS_Namespace *ret; - - dn = get_namespace_directory (h); - if (NULL == dn) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Can't determine where namespace directory is\n")); - return NULL; - } - GNUNET_asprintf (&fn, "%s%s%s", dn, DIR_SEPARATOR_STR, name); - GNUNET_free (dn); - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Namespace)); - ret->h = h; - ret->rc = 1; - ret->key = GNUNET_FS_pseudonym_create_from_existing_file (fn); - if (NULL == ret->key) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Failed to read private key for namespace `%s'\n"), name); - GNUNET_free (ret); - GNUNET_free (fn); - return NULL; - } - ret->name = GNUNET_strdup (name); - ret->filename = fn; - return ret; -} - - -/** - * Rename a local namespace. - * - * @param h handle to the file sharing subsystem - * @param old_name old name of the namespace - * @param new_name new name of the namespace - * @return GNUNET_OK on success, GNUNET_SYSERR on error (see errno for details) - */ -int -GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, - const char *old_name, - const char *new_name) -{ - char *dn; - char *fn_old; - char *fn_new; - int result; - int save_errno; - - dn = get_namespace_directory (h); - if (NULL == dn) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Can't determine where namespace directory is\n")); - return GNUNET_SYSERR; - } - GNUNET_asprintf (&fn_old, "%s%s%s", dn, DIR_SEPARATOR_STR, old_name); - GNUNET_asprintf (&fn_new, "%s%s%s", dn, DIR_SEPARATOR_STR, new_name); - GNUNET_free (dn); - result = RENAME (fn_old, fn_new); - save_errno = errno; - GNUNET_free (fn_old); - GNUNET_free (fn_new); - errno = save_errno; - if (result == 0) - return GNUNET_OK; - return GNUNET_SYSERR; -} - - -/** - * Duplicate a namespace handle. - * - * @param ns namespace handle - * @return duplicated handle to the namespace - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_dup (struct GNUNET_FS_Namespace *ns) -{ - ns->rc++; - return ns; -} - - -/** - * Delete a namespace handle. Can be used for a clean shutdown (free - * memory) or also to freeze the namespace to prevent further - * insertions by anyone. - * - * @param ns handle to the namespace that should be deleted / freed - * @param freeze prevents future insertions; creating a namespace - * with the same name again will create a fresh namespace instead - * - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *ns, int freeze) -{ - unsigned int i; - struct NamespaceUpdateNode *nsn; - - ns->rc--; - if (freeze) - { - if (0 != UNLINK (ns->filename)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "unlink", - ns->filename); - } - if (0 != ns->rc) - return GNUNET_OK; - GNUNET_FS_pseudonym_destroy (ns->key); - GNUNET_free (ns->filename); - GNUNET_free (ns->name); - for (i = 0; i < ns->update_node_count; i++) - { - nsn = ns->update_nodes[i]; - GNUNET_CONTAINER_meta_data_destroy (nsn->md); - GNUNET_FS_uri_destroy (nsn->uri); - GNUNET_free (nsn->id); - GNUNET_free (nsn->update); - GNUNET_free (nsn); - } - GNUNET_array_grow (ns->update_nodes, ns->update_node_count, - 0); - if (ns->update_map != NULL) - GNUNET_CONTAINER_multihashmap_destroy (ns->update_map); - GNUNET_free (ns); - return GNUNET_OK; -} - - -/** - * Context for the 'process_namespace' callback. - * Specifies a function to call on each namespace. - */ -struct ProcessNamespaceContext -{ - /** - * Function to call. - */ - GNUNET_FS_NamespaceInfoProcessor cb; - - /** - * Closure for 'cb'. - */ - void *cb_cls; -}; - - -/** - * Get hash of the public key of a namespace. - * - * @param ns namespace - * @param id buffer to store the key in - * @return GNUNET_OK on success - * GNUNET_SYSERR on failure (contents of id remain intact) - */ -int -GNUNET_FS_namespace_get_public_identifier (struct GNUNET_FS_Namespace *ns, - struct GNUNET_FS_PseudonymIdentifier *id) -{ - if ((NULL == ns) || (NULL == id)) - return GNUNET_SYSERR; - GNUNET_FS_pseudonym_get_identifier (ns->key, id); - return GNUNET_OK; -} - - -/** - * Function called with a filename of a namespace. Reads the key and - * calls the callback. - * - * @param cls closure (struct ProcessNamespaceContext) - * @param filename complete filename (absolute path) - * @return GNUNET_OK to continue to iterate, - * GNUNET_SYSERR to abort iteration with error! - */ -static int -process_namespace (void *cls, const char *filename) -{ - struct ProcessNamespaceContext *pnc = cls; - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier id; - const char *name; - const char *t; - - if (NULL == (ph = GNUNET_FS_pseudonym_create (filename))) + return uig; +ERROR: + if (GNUNET_OK != GNUNET_BIO_read_close (rh, &emsg)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _ - ("Failed to read namespace private key file `%s', deleting it!\n"), - filename); - if (0 != UNLINK (filename)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); - return GNUNET_OK; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to read `%s': %s\n"), + fn, emsg); + GNUNET_free (emsg); } - GNUNET_FS_pseudonym_get_identifier (ph, &id); - GNUNET_FS_pseudonym_destroy (ph); - name = filename; - while (NULL != (t = strstr (name, DIR_SEPARATOR_STR))) - name = t + 1; - pnc->cb (pnc->cb_cls, name, &id); - return GNUNET_OK; -} - - -/** - * Build a list of all available local (!) namespaces The returned - * names are only the nicknames since we only iterate over the local - * namespaces. - * - * @param h handle to the file sharing subsystem - * @param cb function to call on each known namespace - * @param cb_cls closure for cb - */ -void -GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h, - GNUNET_FS_NamespaceInfoProcessor cb, void *cb_cls) -{ - char *dn; - struct ProcessNamespaceContext ctx; - - dn = get_namespace_directory (h); - if (NULL == dn) - return; - ctx.cb = cb; - ctx.cb_cls = cb_cls; - GNUNET_DISK_directory_scan (dn, &process_namespace, &ctx); - GNUNET_free (dn); + GNUNET_free (fn); + return uig; } @@ -526,13 +355,18 @@ struct GNUNET_FS_PublishSksContext /** * Namespace we're publishing to. */ - struct GNUNET_FS_Namespace *ns; + struct GNUNET_CRYPTO_EccPrivateKey ns; /** * Handle to the datastore. */ struct GNUNET_DATASTORE_Handle *dsh; + /** + * Handle to FS. + */ + struct GNUNET_FS_Handle *h; + /** * Function to call once we're done. */ @@ -544,31 +378,28 @@ struct GNUNET_FS_PublishSksContext void *cont_cls; /** - * Handle for our datastore request. + * Handle for our UBlock operation request. */ - struct GNUNET_DATASTORE_QueueEntry *dqe; + struct GNUNET_FS_PublishUblockContext *uc; }; /** - * Function called by the datastore API with + * Function called by the UBlock construction with * the result from the PUT (UBlock) request. * * @param cls closure of type "struct GNUNET_FS_PublishSksContext*" - * @param success GNUNET_OK on success - * @param min_expiration minimum expiration time required for content to be stored * @param msg error message (or NULL) */ static void -sb_put_cont (void *cls, int success, - struct GNUNET_TIME_Absolute min_expiration, - const char *msg) +sks_publish_cont (void *cls, + const char *msg) { struct GNUNET_FS_PublishSksContext *psc = cls; - struct GNUNET_HashCode hc; + struct GNUNET_FS_UpdateInformationGraph *uig; - psc->dqe = NULL; - if (GNUNET_OK != success) + psc->uc = NULL; + if (NULL != msg) { if (NULL != psc->cont) psc->cont (psc->cont_cls, NULL, msg); @@ -580,19 +411,14 @@ sb_put_cont (void *cls, int success, /* FIXME: this can be done much more * efficiently by simply appending to the * file and overwriting the 4-byte header */ - if (psc->ns->update_nodes == NULL) - read_update_information_graph (psc->ns); - GNUNET_array_append (psc->ns->update_nodes, - psc->ns->update_node_count, psc->nsn); - if (NULL != psc->ns->update_map) - { - GNUNET_CRYPTO_hash (psc->nsn->id, strlen (psc->nsn->id), &hc); - GNUNET_CONTAINER_multihashmap_put (psc->ns->update_map, &hc, - psc->nsn, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - } + uig = read_update_information_graph (psc->h, + &psc->ns); + GNUNET_array_append (uig->update_nodes, + uig->update_node_count, + psc->nsn); psc->nsn = NULL; - write_update_information_graph (psc->ns); + write_update_information_graph (uig); + free_update_information_graph (uig); } if (NULL != psc->cont) psc->cont (psc->cont_cls, psc->uri, NULL); @@ -617,7 +443,7 @@ sb_put_cont (void *cls, int success, */ struct GNUNET_FS_PublishSksContext * GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, - struct GNUNET_FS_Namespace *ns, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, const char *identifier, const char *update, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, @@ -626,144 +452,49 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, GNUNET_FS_PublishContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishSksContext *psc; - struct GNUNET_CRYPTO_AesSessionKey sk; - struct GNUNET_CRYPTO_AesInitializationVector iv; struct GNUNET_FS_Uri *sks_uri; - char *uris; - size_t size; - size_t slen; - size_t nidlen; - size_t idlen; - ssize_t mdsize; - struct UBlock *ub; - struct UBlock *ub_enc; - char *dest; - struct GNUNET_CONTAINER_MetaData *mmeta; - struct GNUNET_HashCode id_hash; /* hash of thisId */ - struct GNUNET_HashCode ns_hash; /* hash of namespace public key */ - struct GNUNET_HashCode key; /* id_hash ^ ns_hash, for AES key */ - struct GNUNET_HashCode signing_key; /* H(key) = input for public key */ - struct GNUNET_HashCode query; /* H(verification_key) = query */ - - idlen = strlen (identifier); - if (NULL != update) - nidlen = strlen (update) + 1; - else - nidlen = 1; - uris = GNUNET_FS_uri_to_string (uri); - slen = strlen (uris) + 1; - if ( (slen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock)) || - (nidlen >= MAX_UBLOCK_SIZE - sizeof (struct UBlock) - slen) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - _("Identifiers or URI too long to create UBlock")); - GNUNET_free (uris); - return NULL; - } - if (NULL == meta) - mmeta = GNUNET_CONTAINER_meta_data_create (); - else - mmeta = GNUNET_CONTAINER_meta_data_duplicate (meta); - mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (mmeta); - size = sizeof (struct UBlock) + slen + nidlen + mdsize; - if ( (size > MAX_UBLOCK_SIZE) || - (size < sizeof (struct UBlock) + slen + nidlen) ) - { - size = MAX_UBLOCK_SIZE; - mdsize = MAX_UBLOCK_SIZE - (sizeof (struct UBlock) + slen + nidlen); - } - ub = GNUNET_malloc (sizeof (struct UBlock) + size); - dest = (char *) &ub[1]; - if (NULL != update) - memcpy (dest, update, nidlen); - else - memset (dest, 0, 1); - dest += nidlen; - memcpy (dest, uris, slen); - GNUNET_free (uris); - dest += slen; - mdsize = - GNUNET_CONTAINER_meta_data_serialize (mmeta, &dest, mdsize, - GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); - GNUNET_CONTAINER_meta_data_destroy (mmeta); - if (-1 == mdsize) - { - GNUNET_break (0); - GNUNET_free (ub); - if (NULL != cont) - cont (cont_cls, NULL, _("Internal error.")); - return NULL; - } - sks_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + + sks_uri = GNUNET_new (struct GNUNET_FS_Uri); sks_uri->type = GNUNET_FS_URI_SKS; sks_uri->data.sks.identifier = GNUNET_strdup (identifier); - GNUNET_FS_namespace_get_public_identifier (ns, - &sks_uri->data.sks.ns); - - size = sizeof (struct UBlock) + mdsize + slen + nidlen; - ub_enc = GNUNET_malloc (size); - GNUNET_CRYPTO_hash (identifier, idlen, &id_hash); - GNUNET_CRYPTO_hash (&sks_uri->data.sks.ns, - sizeof (sks_uri->data.sks.ns), &ns_hash); - GNUNET_CRYPTO_hash_xor (&id_hash, &ns_hash, &key); - GNUNET_CRYPTO_hash_to_aes_key (&key, &sk, &iv); - GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &signing_key); - - GNUNET_CRYPTO_aes_encrypt (&ub[1], - size - sizeof (struct UBlock), - &sk, &iv, - &ub_enc[1]); - ub_enc->purpose.size = htonl (nidlen + slen + mdsize + sizeof (struct UBlock) - - sizeof (struct GNUNET_FS_PseudonymSignature)); - ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); - GNUNET_FS_pseudonym_derive_verification_key (&sks_uri->data.sks.ns, - &signing_key, - &ub_enc->verification_key); - GNUNET_CRYPTO_hash (&ub_enc->verification_key, - sizeof (ub_enc->verification_key), - &query); - GNUNET_FS_pseudonym_sign (ns->key, - &ub_enc->purpose, - NULL, - &signing_key, - &ub_enc->signature); - psc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishSksContext)); + GNUNET_CRYPTO_ecc_key_get_public (ns, + &sks_uri->data.sks.ns); + + psc = GNUNET_new (struct GNUNET_FS_PublishSksContext); + psc->h = h; psc->uri = sks_uri; psc->cont = cont; - psc->ns = GNUNET_FS_namespace_dup (ns); psc->cont_cls = cont_cls; - if (0 != (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) - { - GNUNET_free (ub_enc); - GNUNET_free (ub); - sb_put_cont (psc, GNUNET_OK, GNUNET_TIME_UNIT_ZERO_ABS, NULL); - return NULL; - } - psc->dsh = GNUNET_DATASTORE_connect (h->cfg); - if (NULL == psc->dsh) + psc->ns = *ns; + if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { - GNUNET_free (ub_enc); - GNUNET_free (ub); - sb_put_cont (psc, GNUNET_NO, GNUNET_TIME_UNIT_ZERO_ABS, _("Failed to connect to datastore.")); - return NULL; + psc->dsh = GNUNET_DATASTORE_connect (h->cfg); + if (NULL == psc->dsh) + { + sks_publish_cont (psc, + _("Failed to connect to datastore.")); + return NULL; + } } - if (NULL != update) { - psc->nsn = GNUNET_malloc (sizeof (struct NamespaceUpdateNode)); + psc->nsn = GNUNET_new (struct NamespaceUpdateNode); psc->nsn->id = GNUNET_strdup (identifier); psc->nsn->update = GNUNET_strdup (update); psc->nsn->md = GNUNET_CONTAINER_meta_data_duplicate (meta); psc->nsn->uri = GNUNET_FS_uri_dup (uri); } - - psc->dqe = GNUNET_DATASTORE_put (psc->dsh, 0, &query, size, ub_enc, - GNUNET_BLOCK_TYPE_FS_UBLOCK, bo->content_priority, - bo->anonymity_level, bo->replication_level, - bo->expiration_time, -2, 1, - GNUNET_CONSTANTS_SERVICE_TIMEOUT, &sb_put_cont, psc); - GNUNET_free (ub); - GNUNET_free (ub_enc); + psc->uc = GNUNET_FS_publish_ublock_ (h, + psc->dsh, + identifier, + update, + ns, + meta, + uri, + bo, + options, + &sks_publish_cont, + psc); return psc; } @@ -776,17 +507,16 @@ GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, void GNUNET_FS_publish_sks_cancel (struct GNUNET_FS_PublishSksContext *psc) { - if (NULL != psc->dqe) + if (NULL != psc->uc) { - GNUNET_DATASTORE_cancel (psc->dqe); - psc->dqe = NULL; + GNUNET_FS_publish_ublock_cancel_ (psc->uc); + psc->uc = NULL; } if (NULL != psc->dsh) { GNUNET_DATASTORE_disconnect (psc->dsh, GNUNET_NO); psc->dsh = NULL; } - GNUNET_FS_namespace_delete (psc->ns, GNUNET_NO); GNUNET_FS_uri_destroy (psc->uri); if (NULL != psc->nsn) { @@ -828,12 +558,18 @@ struct ProcessUpdateClosure * GNUNET_NO if not. */ static int -process_update_node (void *cls, const struct GNUNET_HashCode * key, void *value) +process_update_node (void *cls, + const struct GNUNET_HashCode *key, + void *value) { struct ProcessUpdateClosure *pc = cls; struct NamespaceUpdateNode *nsn = value; - pc->ip (pc->ip_cls, nsn->id, nsn->uri, nsn->md, nsn->update); + pc->ip (pc->ip_cls, + nsn->id, + nsn->uri, + nsn->md, + nsn->update); return GNUNET_YES; } @@ -844,9 +580,9 @@ process_update_node (void *cls, const struct GNUNET_HashCode * key, void *value) struct FindTreeClosure { /** - * Namespace we are operating on. + * UIG we are operating on. */ - struct GNUNET_FS_Namespace *ns; + struct GNUNET_FS_UpdateInformationGraph *uig; /** * Array with 'head's of TREEs. @@ -891,7 +627,9 @@ struct FindTreeClosure * GNUNET_NO if not. */ static int -find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) +find_trees (void *cls, + const struct GNUNET_HashCode *key, + void *value) { struct FindTreeClosure *fc = cls; struct NamespaceUpdateNode *nsn = value; @@ -918,7 +656,7 @@ find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) nsn->tree_id = UINT_MAX; /* mark as undef */ /* trace */ GNUNET_CRYPTO_hash (nsn->update, strlen (nsn->update), &hc); - GNUNET_CONTAINER_multihashmap_get_multiple (fc->ns->update_map, &hc, + GNUNET_CONTAINER_multihashmap_get_multiple (fc->uig->update_map, &hc, &find_trees, fc); } return GNUNET_YES; @@ -942,13 +680,15 @@ find_trees (void *cls, const struct GNUNET_HashCode * key, void *value) * I know, odd definition of a tree, but the GUI will display an actual * tree (GtkTreeView), so that's what counts for the term here. * + * @param h fs handle to use * @param ns namespace to inspect for updateable content * @param next_id ID to look for; use NULL to look for tree roots * @param ip function to call on each updateable identifier * @param ip_cls closure for ip */ void -GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, +GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Handle *h, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, const char *next_id, GNUNET_FS_IdentifierProcessor ip, void *ip_cls) @@ -959,50 +699,48 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, struct NamespaceUpdateNode *nsn; struct ProcessUpdateClosure pc; struct FindTreeClosure fc; + struct GNUNET_FS_UpdateInformationGraph *uig; - if (NULL == ns->update_nodes) - read_update_information_graph (ns); - if (NULL == ns->update_nodes) + uig = read_update_information_graph (h, ns); + if (NULL == uig->update_nodes) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "No updateable nodes found for ID `%s'\n", next_id); + free_update_information_graph (uig); return; /* no nodes */ } - if (NULL == ns->update_map) + uig->update_map = + GNUNET_CONTAINER_multihashmap_create (2 + + 3 * uig->update_node_count / + 4, + GNUNET_NO); + for (i = 0; i < uig->update_node_count; i++) { - /* need to construct */ - ns->update_map = - GNUNET_CONTAINER_multihashmap_create (2 + - 3 * ns->update_node_count / - 4, - GNUNET_NO); - for (i = 0; i < ns->update_node_count; i++) - { - nsn = ns->update_nodes[i]; - GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); - GNUNET_CONTAINER_multihashmap_put (ns->update_map, &hc, nsn, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); - } + nsn = uig->update_nodes[i]; + GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); + GNUNET_CONTAINER_multihashmap_put (uig->update_map, &hc, nsn, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); } if (NULL != next_id) { GNUNET_CRYPTO_hash (next_id, strlen (next_id), &hc); pc.ip = ip; pc.ip_cls = ip_cls; - GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, + GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &process_update_node, &pc); + free_update_information_graph (uig); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calculating TREEs to find roots of update trees\n"); /* Find heads of TREEs in update graph */ - nug = ++ns->nug_gen; + nug = ++uig->nug_gen; fc.tree_array = NULL; fc.tree_array_size = 0; - for (i = 0; i < ns->update_node_count; i++) + for (i = 0; i < uig->update_node_count; i++) { - nsn = ns->update_nodes[i]; + nsn = uig->update_nodes[i]; if (nsn->nug == nug) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, @@ -1014,15 +752,15 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, nsn->tree_id = UINT_MAX; fc.id = UINT_MAX; fc.nug = nug; - fc.ns = ns; - GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, + fc.uig = uig; + GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &find_trees, &fc); if (UINT_MAX == fc.id) { /* start new TREE */ for (fc.id = 0; fc.id < fc.tree_array_size; fc.id++) { - if (fc.tree_array[fc.id] == NULL) + if (NULL == fc.tree_array[fc.id]) { fc.tree_array[fc.id] = nsn; nsn->tree_id = fc.id; @@ -1041,8 +779,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, GNUNET_CRYPTO_hash (nsn->id, strlen (nsn->id), &hc); fc.id = nsn->tree_id; fc.nug = nug; - fc.ns = ns; - GNUNET_CONTAINER_multihashmap_get_multiple (ns->update_map, &hc, + fc.uig = uig; + GNUNET_CONTAINER_multihashmap_get_multiple (uig->update_map, &hc, &find_trees, &fc); } else @@ -1051,7 +789,8 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, fc.tree_array[fc.id] = nsn; nsn->tree_id = fc.id; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TREE of node `%s' is %u\n", nsn->id, + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "TREE of node `%s' is %u\n", nsn->id, fc.id); } for (i = 0; i < fc.tree_array_size; i++) @@ -1066,6 +805,7 @@ GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, } GNUNET_array_grow (fc.tree_array, fc.tree_array_size, 0); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Done processing TREEs\n"); + free_update_information_graph (uig); } diff --git a/src/fs/fs_pseudonym.c b/src/fs/fs_pseudonym.c index 36eaab6fa..f5493ca16 100644 --- a/src/fs/fs_pseudonym.c +++ b/src/fs/fs_pseudonym.c @@ -21,15 +21,10 @@ * @file fs/fs_pseudonym.c * @brief pseudonym functions * @author Christian Grothoff - * - * TODO: - * - all cryptographic operations are currently NOT implemented and - * provided by stubs that merely pretend to work! */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_fs_service.h" -#include #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) @@ -38,12 +33,6 @@ #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) -/** - * Log an error message at log-level 'level' that indicates - * a failure of the command 'cmd' with the message given - * by gcry_strerror(rc). - */ -#define LOG_GCRY(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gcry_strerror(rc)); } while(0); /** * Name of the directory which stores meta data for pseudonym @@ -67,17 +56,17 @@ /** * Registered callbacks for discovery of pseudonyms. */ -struct GNUNET_FS_pseudonym_DiscoveryHandle +struct GNUNET_FS_Pseudonym_DiscoveryHandle { /** * This is a doubly linked list. */ - struct GNUNET_FS_pseudonym_DiscoveryHandle *next; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *next; /** * This is a doubly linked list. */ - struct GNUNET_FS_pseudonym_DiscoveryHandle *prev; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *prev; /** * Function to call each time a pseudonym is discovered. @@ -95,19 +84,14 @@ struct GNUNET_FS_pseudonym_DiscoveryHandle * Head of the linked list of functions to call when * new pseudonyms are added. */ -static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_head; +static struct GNUNET_FS_Pseudonym_DiscoveryHandle *disco_head; /** * Tail of the linked list of functions to call when * new pseudonyms are added. */ -static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_tail; +static struct GNUNET_FS_Pseudonym_DiscoveryHandle *disco_tail; -/** - * Pointer to indiate 'anonymous' pseudonym (global static, - * d=1, public key = G (generator). - */ -static struct GNUNET_FS_PseudonymHandle anonymous; /** * Internal notification about new tracked URI. @@ -117,10 +101,10 @@ static struct GNUNET_FS_PseudonymHandle anonymous; * @param rating rating of pseudonym */ static void -internal_notify (const struct GNUNET_FS_PseudonymIdentifier *pseudonym, +internal_notify (const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const struct GNUNET_CONTAINER_MetaData *md, int rating) { - struct GNUNET_FS_pseudonym_DiscoveryHandle *pos; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *pos; for (pos = disco_head; NULL != pos; pos = pos->next) pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating); @@ -138,15 +122,15 @@ internal_notify (const struct GNUNET_FS_PseudonymIdentifier *pseudonym, * @param iterator_cls point to a closure * @return registration handle */ -struct GNUNET_FS_pseudonym_DiscoveryHandle * +struct GNUNET_FS_Pseudonym_DiscoveryHandle * GNUNET_FS_pseudonym_discovery_callback_register (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_FS_PseudonymIterator iterator, void *iterator_cls) { - struct GNUNET_FS_pseudonym_DiscoveryHandle *dh; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh; - dh = GNUNET_malloc (sizeof (struct GNUNET_FS_pseudonym_DiscoveryHandle)); + dh = GNUNET_new (struct GNUNET_FS_Pseudonym_DiscoveryHandle); dh->callback = iterator; dh->callback_cls = iterator_cls; GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh); @@ -161,7 +145,7 @@ GNUNET_FS_pseudonym_discovery_callback_register (const struct * @param dh registration to unregister */ void -GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_DiscoveryHandle *dh) +GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh) { GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh); GNUNET_free (dh); @@ -180,7 +164,7 @@ GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_Di static char * get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *prefix, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym) + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym) { struct GNUNET_CRYPTO_HashAsciiEncoded enc; struct GNUNET_HashCode psid; @@ -188,7 +172,7 @@ get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, if (NULL != pseudonym) { GNUNET_CRYPTO_hash (pseudonym, - sizeof (struct GNUNET_FS_PseudonymIdentifier), + sizeof (struct GNUNET_CRYPTO_EccPublicKey), &psid); GNUNET_CRYPTO_hash_to_enc (&psid, &enc); } @@ -243,7 +227,7 @@ get_data_filename_hash (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const struct GNUNET_CONTAINER_MetaData *md, int32_t rank) @@ -258,7 +242,7 @@ GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, return GNUNET_SYSERR; } if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym, - sizeof (struct GNUNET_FS_PseudonymIdentifier))) || + sizeof (struct GNUNET_CRYPTO_EccPublicKey))) || (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) || (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) || (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md))) @@ -295,12 +279,12 @@ GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ static int read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, struct GNUNET_CONTAINER_MetaData **meta, int32_t *rank, char **ns_name) { - struct GNUNET_FS_PseudonymIdentifier pd; + struct GNUNET_CRYPTO_EccPublicKey pd; char *fn; char *emsg; struct GNUNET_BIO_ReadHandle *fileR; @@ -367,12 +351,12 @@ read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, */ char * GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, unsigned int *suffix) { struct GNUNET_HashCode nh; - struct GNUNET_FS_PseudonymIdentifier pi; + struct GNUNET_CRYPTO_EccPublicKey pi; uint64_t len; char *fn; struct GNUNET_DISK_FileHandle *fh; @@ -393,11 +377,11 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg GNUNET_DISK_PERM_USER_WRITE); i = 0; idx = -1; - while ((len >= sizeof (struct GNUNET_FS_PseudonymIdentifier)) && - (sizeof (struct GNUNET_FS_PseudonymIdentifier) == - GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_FS_PseudonymIdentifier)))) + while ((len >= sizeof (struct GNUNET_CRYPTO_EccPublicKey)) && + (sizeof (struct GNUNET_CRYPTO_EccPublicKey) == + GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_CRYPTO_EccPublicKey)))) { - if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) + if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) { idx = i; break; @@ -408,8 +392,8 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg if (-1 == idx) { idx = i; - if (sizeof (struct GNUNET_FS_PseudonymIdentifier) != - GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) + if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) != + GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn); } GNUNET_DISK_file_close (fh); @@ -442,11 +426,11 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg */ int GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, - struct GNUNET_CONTAINER_MetaData **ret_meta, - int32_t *ret_rank, - char **ret_name, - int *name_is_a_dup) + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, + struct GNUNET_CONTAINER_MetaData **ret_meta, + int32_t *ret_rank, + char **ret_name, + int *name_is_a_dup) { struct GNUNET_CONTAINER_MetaData *meta; char *name; @@ -521,7 +505,7 @@ GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, int GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *ns_uname, - struct GNUNET_FS_PseudonymIdentifier *pseudonym) + struct GNUNET_CRYPTO_EccPublicKey *pseudonym) { size_t slen; uint64_t len; @@ -546,7 +530,7 @@ GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, if ((GNUNET_OK != GNUNET_DISK_file_test (fn) || (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) || - ((idx + 1) * sizeof (struct GNUNET_FS_PseudonymIdentifier) > len)) + ((idx + 1) * sizeof (struct GNUNET_CRYPTO_EccPublicKey) > len)) { GNUNET_free (fn); return GNUNET_SYSERR; @@ -558,14 +542,14 @@ GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_DISK_PERM_USER_WRITE); GNUNET_free (fn); if (GNUNET_SYSERR == - GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_FS_PseudonymIdentifier), + GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_CRYPTO_EccPublicKey), GNUNET_DISK_SEEK_SET)) { GNUNET_DISK_file_close (fh); return GNUNET_SYSERR; } - if (sizeof (struct GNUNET_FS_PseudonymIdentifier) != - GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) + if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) != + GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) { GNUNET_DISK_file_close (fh); return GNUNET_SYSERR; @@ -610,7 +594,7 @@ static int list_pseudonym_helper (void *cls, const char *fullname) { struct ListPseudonymClosure *lpc = cls; - struct GNUNET_FS_PseudonymIdentifier pd; + struct GNUNET_CRYPTO_EccPublicKey pd; char *emsg; struct GNUNET_BIO_ReadHandle *fileR; int32_t rank; @@ -699,7 +683,7 @@ GNUNET_FS_pseudonym_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, int32_t delta) { struct GNUNET_CONTAINER_MetaData *meta; @@ -734,8 +718,8 @@ GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, - const struct GNUNET_CONTAINER_MetaData *meta) + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, + const struct GNUNET_CONTAINER_MetaData *meta) { char *name; int32_t rank; @@ -766,888 +750,5 @@ GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, } -/* ***************************** cryptographic operations ************************* */ - -/** - * Handle for a pseudonym (private key). - */ -struct GNUNET_FS_PseudonymHandle -{ - /** - * 256-bit 'd' secret value (mod 'n', where n is 256-bit for NIST P-256). - */ - unsigned char d[256 / 8]; - - /** - * Public key corresponding to the private key. - */ - struct GNUNET_FS_PseudonymIdentifier public_key; -}; - - -/** - * If target != size, move target bytes to the end of the size-sized - * buffer and zero out the first target-size bytes. - * - * @param buf original buffer - * @param size number of bytes in the buffer - * @param target target size of the buffer - */ -static void -adjust (unsigned char *buf, size_t size, size_t target) -{ - if (size < target) - { - memmove (&buf[target - size], buf, size); - memset (buf, 0, target - size); - } -} - - -/** - * Extract values from an S-expression. - * - * @param array where to store the result(s) - * @param sexp S-expression to parse - * @param topname top-level name in the S-expression that is of interest - * @param elems names of the elements to extract - * @return 0 on success - */ -static int -key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, - const char *elems) -{ - gcry_sexp_t list; - gcry_sexp_t l2; - const char *s; - unsigned int i; - unsigned int idx; - - if (! (list = gcry_sexp_find_token (sexp, topname, 0))) - return 1; - l2 = gcry_sexp_cadr (list); - gcry_sexp_release (list); - list = l2; - if (! list) - return 2; - idx = 0; - for (s = elems; *s; s++, idx++) - { - if (! (l2 = gcry_sexp_find_token (list, s, 1))) - { - for (i = 0; i < idx; i++) - { - gcry_free (array[i]); - array[i] = NULL; - } - gcry_sexp_release (list); - return 3; /* required parameter not found */ - } - array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); - gcry_sexp_release (l2); - if (! array[idx]) - { - for (i = 0; i < idx; i++) - { - gcry_free (array[i]); - array[i] = NULL; - } - gcry_sexp_release (list); - return 4; /* required parameter is invalid */ - } - } - gcry_sexp_release (list); - return 0; -} - - -/** - * Create a pseudonym. - * - * @param filename name of the file to use for storage, NULL for in-memory only - * @return handle to the private key of the pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_create (const char *filename) -{ - struct GNUNET_FS_PseudonymHandle *ph; - ssize_t ret; - gcry_sexp_t r_key; - gcry_sexp_t params; - gcry_ctx_t ctx; - gcry_mpi_point_t q; - gcry_mpi_t q_x; - gcry_mpi_t q_y; - gcry_error_t rc; - gcry_mpi_t d; - size_t size; - - ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle)); - if ( (NULL != filename) && - (GNUNET_YES == GNUNET_DISK_file_test (filename)) ) - { - ret = GNUNET_DISK_fn_read (filename, ph, - sizeof (struct GNUNET_FS_PseudonymHandle)); - /* Note: we don't do any validation here, maybe we should? */ - if (sizeof (struct GNUNET_FS_PseudonymHandle) == ret) - return ph; - } - if (0 != (rc = gcry_sexp_build (¶ms, NULL, - "(genkey(ecdsa(curve \"NIST P-256\")))"))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); - return NULL; - } - if (0 != (rc = gcry_pk_genkey (&r_key, params))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); - gcry_sexp_release (params); - gcry_sexp_release (r_key); - return NULL; - } - gcry_sexp_release (params); - /* extract "d" (secret key) from r_key */ - rc = key_from_sexp (&d, r_key, "private-key", "d"); - if (0 != rc) - rc = key_from_sexp (&d, r_key, "private-key", "d"); - if (0 != rc) - rc = key_from_sexp (&d, r_key, "ecc", "d"); - if (0 != rc) - { - gcry_sexp_release (r_key); - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc); - return NULL; - } - size = sizeof (ph->d); - GNUNET_assert (0 == - gcry_mpi_print (GCRYMPI_FMT_USG, ph->d, size, &size, - d)); - gcry_mpi_release (d); - adjust (ph->d, size, sizeof (ph->d)); - - /* extract 'q' (public key) from r_key */ - if (0 != (rc = gcry_mpi_ec_new (&ctx, r_key, NULL))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ - gcry_sexp_release (r_key); - return NULL; - } - gcry_sexp_release (r_key); - q = gcry_mpi_ec_get_point ("q", ctx, 0); - q_x = gcry_mpi_new (256); - q_y = gcry_mpi_new (256); - gcry_mpi_ec_get_affine (q_x, q_y, q, ctx); - gcry_mpi_point_release (q); - gcry_ctx_release (ctx); - - /* store q_x/q_y in public key */ - size = sizeof (ph->public_key.q_x); - if (0 != - gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_x, size, &size, - q_x)) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (q_x); - gcry_mpi_release (q_y); - return NULL; - - } - adjust (ph->public_key.q_x, size, sizeof (ph->public_key.q_x)); - gcry_mpi_release (q_x); - - size = sizeof (ph->public_key.q_y); - if (0 != - gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_y, size, &size, - q_y)) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (q_y); - return NULL; - } - adjust (ph->public_key.q_y, size, sizeof (ph->public_key.q_y)); - gcry_mpi_release (q_y); - - /* write to disk */ - if (NULL != filename) - { - ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_FS_PseudonymHandle), - GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); - if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret) - { - GNUNET_free (ph); - return NULL; - } - } - return ph; -} - - -/** - * Create a pseudonym, from a file that must already exist. - * - * @param filename name of the file to use for storage, NULL for in-memory only - * @return handle to the private key of the pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_create_from_existing_file (const char *filename) -{ - struct GNUNET_FS_PseudonymHandle *ph; - ssize_t ret; - - ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle)); - ret = GNUNET_DISK_fn_read (filename, ph, - sizeof (struct GNUNET_FS_PseudonymHandle)); - if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret) - { - GNUNET_free (ph); - return NULL; - } - /* Note: we don't do any validation here; maybe we should? */ - return ph; -} - - -/** - * Get the handle for the 'anonymous' pseudonym shared by all users. - * That pseudonym uses a fixed 'secret' for the private key; this - * construction is useful to make anonymous and pseudonymous APIs - * (and packets) indistinguishable on the network. See #2564. - * - * @return handle to the (non-secret) private key of the 'anonymous' pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle () -{ - static int once; - gcry_mpi_t d; - size_t size; - gcry_ctx_t ctx; - int rc; - gcry_mpi_t g_x; - gcry_mpi_t g_y; - gcry_mpi_point_t g; - - if (once) - return &anonymous; - d = gcry_mpi_new (1); - gcry_mpi_set_ui (d, 1); - size = sizeof (anonymous.d); - GNUNET_assert (0 == - gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.d, size, &size, - d)); - gcry_mpi_release (d); - adjust (anonymous.d, size, sizeof (anonymous.d)); - - /* create basic ECC context */ - if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, - "gcry_mpi_ec_new", rc); - return NULL; - } - - g = gcry_mpi_ec_get_point ("g", ctx, 0); - g_x = gcry_mpi_new (256); - g_y = gcry_mpi_new (256); - gcry_mpi_ec_get_affine (g_x, g_y, g, ctx); - gcry_mpi_point_release (g); - gcry_ctx_release (ctx); - - /* store g_x/g_y in public key */ - size = sizeof (anonymous.public_key.q_x); - if (0 != - gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.public_key.q_x, size, &size, - g_x)) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (g_x); - gcry_mpi_release (g_y); - return NULL; - } - adjust (anonymous.public_key.q_x, size, sizeof (anonymous.public_key.q_x)); - gcry_mpi_release (g_x); - - size = sizeof (anonymous.public_key.q_y); - if (0 != - gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.public_key.q_y, size, &size, - g_y)) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (g_y); - return NULL; - } - adjust (anonymous.public_key.q_y, size, sizeof (anonymous.public_key.q_y)); - gcry_mpi_release (g_y); - - once = 1; - return &anonymous; -} - - -/** - * Destroy a pseudonym handle. Does NOT remove the private key from - * the disk. - * - * @param ph pseudonym handle to destroy - */ -void -GNUNET_FS_pseudonym_destroy (struct GNUNET_FS_PseudonymHandle *ph) -{ - if (&anonymous != ph) - GNUNET_free (ph); -} - - -/** - * Convert the data specified in the given purpose argument to an - * S-expression suitable for signature operations. - * - * @param purpose data to convert - * @param rfc6979 GNUNET_YES if we are to use deterministic ECDSA - * @return converted s-expression - */ -static gcry_sexp_t -data_to_pkcs1 (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - int rfc6979) -{ - struct GNUNET_CRYPTO_ShortHashCode hc; - size_t bufSize; - gcry_sexp_t data; - const char *fmt; - int rc; - - GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc); - if (rfc6979) - { - if (0 != (rc = gcry_sexp_build (&data, NULL, - "(data(flags rfc6979)(hash %s %b))", - "sha256", - sizeof (hc), - &hc))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); - return NULL; - } - } - else - { - fmt = "(data(flags raw)(5:value32:01234567890123456789012345678901))"; - bufSize = strlen (fmt) + 1; - { - char buff[bufSize]; - - memcpy (buff, fmt, bufSize); - memcpy (&buff - [bufSize - - strlen - ("01234567890123456789012345678901))") - - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); - GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); - } - } - return data; -} - - -/** - * Cryptographically sign some data with the pseudonym. - * - * @param ph private key 'd' used for signing (corresponds to 'x' in #2564) - * @param purpose data to sign - * @param seed hash of the plaintext of the data that we are signing, - * used for deterministic PRNG for anonymous signing; - * corresponds to 'k' in section 2.7 of #2564 - * @param signing_key modifier to apply to the private key for signing ('h'); - * see section 2.3 of #2564. - * @param signature where to store the signature - * @return GNUNET_SYSERR on failure - */ -int -GNUNET_FS_pseudonym_sign (struct GNUNET_FS_PseudonymHandle *ph, - const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - const struct GNUNET_HashCode *seed, - const struct GNUNET_HashCode *signing_key, - struct GNUNET_FS_PseudonymSignature *signature) -{ - size_t size; - size_t erroff; - gcry_mpi_t d; - gcry_mpi_t k; - gcry_mpi_t h; - gcry_mpi_t dh; - gcry_mpi_t n; /* n from P-256 */ - gcry_sexp_t spriv; - gcry_sexp_t data; - gcry_sexp_t result; - gcry_mpi_t rs[2]; - int rc; - - /* get private key 'd' from pseudonym */ - size = sizeof (ph->d); - if (0 != (rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG, - &ph->d, - size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return GNUNET_SYSERR; - } - /* get 'x' value from signing key */ - size = sizeof (struct GNUNET_HashCode); - if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, - signing_key, - size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (d); - return GNUNET_SYSERR; - } - - /* initialize 'n' from P-256; hex copied from libgcrypt code */ - if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, - "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (d); - gcry_mpi_release (h); - return GNUNET_SYSERR; - } - - /* calculate dh = d * h mod n */ - dh = gcry_mpi_new (256); - gcry_mpi_mulm (dh, d, h, n); - gcry_mpi_release (d); - gcry_mpi_release (h); - gcry_mpi_release (n); - - /* now build sexpression with the signing key */ - if (0 != (rc = gcry_sexp_build (&spriv, &erroff, - "(private-key(ecdsa(curve \"NIST P-256\")(d %m)))", - dh))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); - gcry_mpi_release (dh); - return GNUNET_SYSERR; - } - gcry_mpi_release (dh); - /* prepare data for signing */ - data = data_to_pkcs1 (purpose, NULL != seed); - if (NULL == data) - { - gcry_sexp_release (spriv); - return GNUNET_SYSERR; - } - /* get 'k' value from seed, if available */ - if (NULL != seed) - { - size = sizeof (struct GNUNET_HashCode); - if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG, - seed, - size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_sexp_release (spriv); - gcry_sexp_release (data); - return GNUNET_SYSERR; - } - } - - /* actually create signature */ - /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */ - if (0 != (rc = gcry_pk_sign (&result, data, spriv))) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("ECC signing failed at %s:%d: %s\n"), __FILE__, - __LINE__, gcry_strerror (rc)); - gcry_sexp_release (data); - gcry_sexp_release (spriv); - if (NULL != seed) - gcry_mpi_release (k); - memset (signature, 0, sizeof (struct GNUNET_FS_PseudonymSignature)); - return GNUNET_SYSERR; - } - if (NULL != seed) - gcry_mpi_release (k); - gcry_sexp_release (data); - gcry_sexp_release (spriv); - - - /* extract 'r' and 's' values from sexpression 'result' and store in 'signature' */ - if (0 != (rc = key_from_sexp (rs, result, "sig-val", "rs"))) - { - GNUNET_break (0); - gcry_sexp_release (result); - return GNUNET_SYSERR; - } - gcry_sexp_release (result); - size = sizeof (signature->sig_r); - if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_r, size, - &size, rs[0]))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (rs[0]); - gcry_mpi_release (rs[1]); - return GNUNET_SYSERR; - } - adjust (signature->sig_r, size, sizeof (signature->sig_r)); - gcry_mpi_release (rs[0]); - - size = sizeof (signature->sig_s); - if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_s, size, - &size, rs[1]))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (rs[1]); - return GNUNET_SYSERR; - } - adjust (signature->sig_s, size, sizeof (signature->sig_s)); - gcry_mpi_release (rs[1]); - -#if EXTRA_CHECKS - { - struct GNUNET_FS_PseudonymIdentifier vk; - struct GNUNET_FS_PseudonymIdentifier pi; - - GNUNET_FS_pseudonym_get_identifier (ph, &pi); - GNUNET_assert (GNUNET_OK == - GNUNET_FS_pseudonym_derive_verification_key (&pi, signing_key, &vk)); - GNUNET_assert (GNUNET_OK == - GNUNET_FS_pseudonym_verify (purpose, - signature, - &vk)); - } -#endif - - GNUNET_FS_pseudonym_get_identifier (ph, &signature->signer); - return GNUNET_OK; -} - - -/** - * Get an ECC context (with Q set to the respective public key) from - * a pseudonym. - * - * @param pseudonym with information on 'q' - * @return curve context - */ -static gcry_ctx_t -get_context_from_pseudonym (struct GNUNET_FS_PseudonymIdentifier *pseudonym) -{ - static struct GNUNET_FS_PseudonymIdentifier zerop; - gcry_ctx_t ctx; - gcry_mpi_t q_x; - gcry_mpi_t q_y; - gcry_mpi_t zero; - gcry_mpi_point_t q; - size_t size; - int rc; - - /* extract 'q' from pseudonym */ - if (0 == memcmp (pseudonym, &zerop, sizeof (zerop))) - { - /* create basic ECC context */ - if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ - return NULL; - } - /* FIXME: initialize 'ctx' with 'q' = G */ - zero = gcry_mpi_new (0); - gcry_mpi_set_ui (zero, 0); - q = gcry_mpi_point_new (0); - gcry_mpi_point_set (q, zero, zero, zero); - gcry_mpi_ec_set_point ("q", q, ctx); - gcry_mpi_release (zero); - gcry_mpi_point_release (q); - return ctx; - } - size = sizeof (pseudonym->q_x); - if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, pseudonym->q_x, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return NULL; - } - size = sizeof (pseudonym->q_y); - if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, pseudonym->q_y, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (q_x); - return NULL; - } - q = gcry_mpi_point_new (256); - gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE); - gcry_mpi_release (q_x); - gcry_mpi_release (q_y); - - /* create basic ECC context */ - if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ - gcry_mpi_point_release (q); - return NULL; - } - /* initialize 'ctx' with 'q' */ - gcry_mpi_ec_set_point ("q", q, ctx); - gcry_mpi_point_release (q); - return ctx; -} - - -/** - * Given a pseudonym and a signing key, derive the corresponding public - * key that would be used to verify the resulting signature. - * - * @param pseudonym the public key (dQ in ECDSA) - * @param signing_key input to derive 'h' (see section 2.4 of #2564) - * @param verification_key resulting public key to verify the signature - * created from the '(d*h)' of 'pseudonym' and the 'signing_key'; - * the value stored here can then be given to GNUNET_FS_pseudonym_verify. - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_FS_pseudonym_derive_verification_key (struct GNUNET_FS_PseudonymIdentifier *pseudonym, - const struct GNUNET_HashCode *signing_key, - struct GNUNET_FS_PseudonymIdentifier *verification_key) -{ - gcry_mpi_t h; - size_t size; - int rc; - gcry_ctx_t ctx; - gcry_mpi_point_t q; - gcry_mpi_point_t v; - gcry_mpi_t v_x; - gcry_mpi_t v_y; - gcry_mpi_t h_mod_n; - gcry_mpi_t n; /* n from P-256 */ - - /* get 'h' value from signing key */ - size = sizeof (struct GNUNET_HashCode); - if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, - signing_key, - size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return GNUNET_SYSERR; - } - /* create ECC context based on Q from pseudonym */ - if (NULL == (ctx = get_context_from_pseudonym (pseudonym))) - { - gcry_mpi_release (h); - return GNUNET_SYSERR; - } - /* initialize 'n' from P-256; hex copied from libgcrypt code */ - if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, - "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (h); - return GNUNET_SYSERR; - } - h_mod_n = gcry_mpi_new (0); - gcry_mpi_mod (h_mod_n, h, n); - gcry_mpi_release (h); - - /* get Q = dG from 'pseudonym' */ - q = gcry_mpi_ec_get_point ("q", ctx, 0); - /* calculate V = hQ = hdG */ - v = gcry_mpi_point_new (0); - - gcry_mpi_ec_mul (v, h_mod_n, q, ctx); - gcry_mpi_release (h_mod_n); - - /* store 'v' point in "verification_key" */ - v_x = gcry_mpi_new (256); - v_y = gcry_mpi_new (256); - gcry_mpi_ec_get_affine (v_x, v_y, v, ctx); - - gcry_mpi_point_release (v); - gcry_ctx_release (ctx); - - size = sizeof (verification_key->q_x); - if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_x, size, - &size, v_x))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (v_x); - gcry_mpi_release (v_y); - return GNUNET_SYSERR; - } - gcry_mpi_release (v_x); - size = sizeof (verification_key->q_y); - if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_y, size, - &size, v_y))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); - gcry_mpi_release (v_y); - return GNUNET_SYSERR; - } - gcry_mpi_release (v_y); - return GNUNET_OK; -} - - -/** - * Verify a signature made with a pseudonym. - * - * @param purpose data that was signed - * @param signature signature to verify - * @param verification_key public key to use for checking the signature; - * corresponds to 'g^(x+h)' in section 2.4 of #2564. - * @return GNUNET_OK on success (signature valid, 'pseudonym' set), - * GNUNET_SYSERR if the signature is invalid - */ -int -GNUNET_FS_pseudonym_verify (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - const struct GNUNET_FS_PseudonymSignature *signature, - const struct GNUNET_FS_PseudonymIdentifier *verification_key) -{ - gcry_sexp_t data; - gcry_sexp_t sig_sexpr; - gcry_sexp_t pk_sexpr; - size_t size; - gcry_ctx_t ctx; - gcry_mpi_t r; - gcry_mpi_t s; - gcry_mpi_point_t q; - gcry_mpi_t q_x; - gcry_mpi_t q_y; - size_t erroff; - int rc; - - /* build s-expression for signature */ - size = sizeof (signature->sig_r); - if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG, - signature->sig_r, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - return GNUNET_SYSERR; - } - size = sizeof (signature->sig_s); - if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG, - signature->sig_s, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_mpi_release (r); - return GNUNET_SYSERR; - } - if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))", - r, s))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); - gcry_mpi_release (r); - gcry_mpi_release (s); - return GNUNET_SYSERR; - } - gcry_mpi_release (r); - gcry_mpi_release (s); - - - /* build s-expression for data that was signed */ - data = data_to_pkcs1 (purpose, GNUNET_NO); - if (NULL == data) - { - gcry_sexp_release (sig_sexpr); - return GNUNET_SYSERR; - } - /* create context of public key and initialize Q */ - size = sizeof (verification_key->q_x); - if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, - verification_key->q_x, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_sexp_release (data); - gcry_sexp_release (sig_sexpr); - return GNUNET_SYSERR; - } - size = sizeof (verification_key->q_y); - if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, - verification_key->q_y, size, &size))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); - gcry_sexp_release (data); - gcry_sexp_release (sig_sexpr); - gcry_mpi_release (q_x); - return GNUNET_SYSERR; - } - q = gcry_mpi_point_new (256); - gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE); - gcry_mpi_release (q_x); - gcry_mpi_release (q_y); - - /* create basic ECC context */ - if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ - gcry_sexp_release (data); - gcry_sexp_release (sig_sexpr); - gcry_mpi_point_release (q); - return GNUNET_SYSERR; - } - /* initialize 'ctx' with 'q' */ - gcry_mpi_ec_set_point ("q", q, ctx); - gcry_mpi_point_release (q); - - /* convert 'ctx' to 'sexp' */ - if (0 != (rc = gcry_pubkey_get_sexp (&pk_sexpr, GCRY_PK_GET_PUBKEY, ctx))) - { - LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc); - gcry_ctx_release (ctx); - gcry_sexp_release (data); - gcry_sexp_release (sig_sexpr); - return GNUNET_SYSERR; - } - gcry_ctx_release (ctx); - - /* finally, verify the signature */ - rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr); - gcry_sexp_release (sig_sexpr); - gcry_sexp_release (data); - gcry_sexp_release (pk_sexpr); - if (rc) - { - LOG (GNUNET_ERROR_TYPE_WARNING, - _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__, - __LINE__, gcry_strerror (rc)); - return GNUNET_SYSERR; - } - return GNUNET_OK; -} - - -/** - * Get the identifier (public key) of a pseudonym. - * - * @param ph pseudonym handle with the private key - * @param pseudonym pseudonym identifier (set based on 'ph') - */ -void -GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph, - struct GNUNET_FS_PseudonymIdentifier *pseudonym) -{ - memcpy (pseudonym, &ph->public_key, - sizeof (struct GNUNET_FS_PseudonymIdentifier)); -} - - -/** - * Remove pseudonym from the set of known pseudonyms. - * - * @param cfg overall configuration - * @param id the pseudonym identifier - * @return GNUNET_OK on success, GNUNET_SYSERR on failure - */ -int -GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *id) -{ - char *fn; - int result; - - fn = get_data_filename (cfg, PS_METADATA_DIR, id); - if (NULL == fn) - return GNUNET_SYSERR; - result = UNLINK (fn); - GNUNET_free (fn); - return (0 == result) ? GNUNET_OK : GNUNET_SYSERR; -} /* end of pseudonym.c */ diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c index 041d4213c..1ed37d7e4 100644 --- a/src/fs/fs_publish.c +++ b/src/fs/fs_publish.c @@ -84,11 +84,6 @@ publish_cleanup (struct GNUNET_FS_PublishContext *pc) pc->fhc = NULL; } GNUNET_FS_file_information_destroy (pc->fi, NULL, NULL); - if (pc->ns != NULL) - { - GNUNET_FS_namespace_delete (pc->ns, GNUNET_NO); - pc->ns = NULL; - } GNUNET_free_non_null (pc->nid); GNUNET_free_non_null (pc->nuid); GNUNET_free_non_null (pc->serialization); @@ -271,9 +266,15 @@ static void publish_sblock (struct GNUNET_FS_PublishContext *pc) { if (NULL != pc->ns) - pc->sks_pc = GNUNET_FS_publish_sks (pc->h, pc->ns, pc->nid, pc->nuid, - pc->fi->meta, pc->fi->chk_uri, &pc->fi->bo, - pc->options, &publish_sblocks_cont, pc); + pc->sks_pc = GNUNET_FS_publish_sks (pc->h, + pc->ns, + pc->nid, + pc->nuid, + pc->fi->meta, + pc->fi->chk_uri, + &pc->fi->bo, + pc->options, + &publish_sblocks_cont, pc); else publish_sblocks_cont (pc, NULL, NULL); } @@ -1117,7 +1118,8 @@ finish_reserve (void *cls, int success, struct GNUNET_FS_PublishContext * GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_FileInformation *fi, - struct GNUNET_FS_Namespace *ns, const char *nid, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, + const char *nid, const char *nuid, enum GNUNET_FS_PublishOptions options) { @@ -1135,20 +1137,20 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, { dsh = NULL; } - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishContext)); + ret = GNUNET_new (struct GNUNET_FS_PublishContext); ret->dsh = dsh; ret->h = h; ret->fi = fi; - ret->ns = ns; - ret->options = options; - if (ns != NULL) + if (NULL != ns) { - ns->rc++; + ret->ns = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); + *ret->ns = *ns; GNUNET_assert (NULL != nid); ret->nid = GNUNET_strdup (nid); if (NULL != nuid) ret->nuid = GNUNET_strdup (nuid); } + ret->options = options; /* signal start */ GNUNET_FS_file_information_inspect (ret->fi, &fip_signal_start, ret); ret->fi_pos = ret->fi; diff --git a/src/fs/fs_publish_ksk.c b/src/fs/fs_publish_ksk.c index 10512af5f..7cbc880a2 100644 --- a/src/fs/fs_publish_ksk.c +++ b/src/fs/fs_publish_ksk.c @@ -33,7 +33,7 @@ #include "gnunet_fs_service.h" #include "fs_api.h" #include "fs_tree.h" - +#include "fs_publish_ublock.h" /** * Context for the KSK publication. @@ -47,33 +47,29 @@ struct GNUNET_FS_PublishKskContext struct GNUNET_FS_Uri *ksk_uri; /** - * Global FS context. + * URI to publish. */ - struct GNUNET_FS_Handle *h; + struct GNUNET_FS_Uri *uri; /** - * The master block that we are sending - * (in plaintext), has "mdsize+slen" more - * bytes than the struct would suggest. + * Metadata to use. */ - struct UBlock *ub; + struct GNUNET_CONTAINER_MetaData *meta; /** - * Buffer of the same size as "kb" for - * the encrypted version. + * Global FS context. */ - struct UBlock *cpy; + struct GNUNET_FS_Handle *h; /** - * Handle to the datastore, NULL if we are just - * simulating. + * UBlock publishing operation that is active. */ - struct GNUNET_DATASTORE_Handle *dsh; + struct GNUNET_FS_PublishUblockContext *uc; /** - * Handle to datastore PUT request. + * Handle to the datastore, NULL if we are just simulating. */ - struct GNUNET_DATASTORE_QueueEntry *qre; + struct GNUNET_DATASTORE_Handle *dsh; /** * Current task. @@ -96,14 +92,9 @@ struct GNUNET_FS_PublishKskContext struct GNUNET_FS_BlockOptions bo; /** - * Size of the serialized metadata. - */ - ssize_t mdsize; - - /** - * Size of the (CHK) URI as a string. - */ - size_t slen; + * Options to use. + */ + enum GNUNET_FS_PublishOptions options; /** * Keyword that we are currently processing. @@ -122,7 +113,8 @@ struct GNUNET_FS_PublishKskContext * @param tc unused */ static void -publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +publish_ksk_cont (void *cls, + const struct GNUNET_SCHEDULER_TaskContext *tc); /** @@ -130,19 +122,16 @@ publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); * the result from the PUT request. * * @param cls closure of type "struct GNUNET_FS_PublishKskContext*" - * @param success GNUNET_OK on success - * @param min_expiration minimum expiration time required for content to be stored * @param msg error message (or NULL) */ static void -kb_put_cont (void *cls, int success, - struct GNUNET_TIME_Absolute min_expiration, +kb_put_cont (void *cls, const char *msg) { struct GNUNET_FS_PublishKskContext *pkc = cls; - pkc->qre = NULL; - if (GNUNET_OK != success) + pkc->uc = NULL; + if (NULL != msg) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "KBlock PUT operation failed: %s\n", msg); @@ -166,15 +155,6 @@ publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { struct GNUNET_FS_PublishKskContext *pkc = cls; const char *keyword; - struct GNUNET_HashCode key; - struct GNUNET_HashCode seed; - struct GNUNET_HashCode signing_key; - struct GNUNET_HashCode query; - struct GNUNET_CRYPTO_AesSessionKey skey; - struct GNUNET_CRYPTO_AesInitializationVector iv; - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier pseudonym; - struct UBlock *ub_dst; pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK; if ( (pkc->i == pkc->ksk_uri->data.ksk.keywordCount) || @@ -186,61 +166,15 @@ publish_ksk_cont (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) return; } keyword = pkc->ksk_uri->data.ksk.keywords[pkc->i++]; - pkc->sks_task = GNUNET_FS_publish_sks (pkc->h, - anonymous, - keyword, NULL, - pkc->meta, - pkc->uri, - &pkc->bo, - pkc->options, - &publish_ksk_cont, pkc); - - - /* derive signing seed from plaintext */ - GNUNET_CRYPTO_hash (&pkc->ub[1], - 1 + pkc->slen + pkc->mdsize, - &seed); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Publishing under keyword `%s'\n", - &keyword[1]); - /* first character of keyword indicates if it is - * mandatory or not -- ignore for hashing */ - GNUNET_CRYPTO_hash (&keyword[1], strlen (&keyword[1]), &key); - - GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); - ub_dst = pkc->cpy; - GNUNET_CRYPTO_aes_encrypt (&pkc->ub[1], - 1 + pkc->slen + pkc->mdsize, - &skey, &iv, - &ub_dst[1]); - ph = GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle (); - GNUNET_CRYPTO_hash (&key, sizeof (key), &signing_key); - ub_dst->purpose.size = htonl (1 + pkc->slen + pkc->mdsize + - sizeof (struct UBlock) - - sizeof (struct GNUNET_FS_PseudonymSignature)); - ub_dst->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); - - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym); - GNUNET_FS_pseudonym_derive_verification_key (&pseudonym, - &signing_key, - &ub_dst->verification_key); - GNUNET_FS_pseudonym_sign (ph, - &ub_dst->purpose, - &seed, - &signing_key, - &ub_dst->signature); - - GNUNET_CRYPTO_hash (&ub_dst->verification_key, - sizeof (ub_dst->verification_key), - &query); - GNUNET_FS_pseudonym_destroy (ph); - pkc->qre = - GNUNET_DATASTORE_put (pkc->dsh, 0, &query, - 1 + pkc->slen + pkc->mdsize + sizeof (struct UBlock), - ub_dst, GNUNET_BLOCK_TYPE_FS_UBLOCK, - pkc->bo.content_priority, pkc->bo.anonymity_level, - pkc->bo.replication_level, pkc->bo.expiration_time, - -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, - &kb_put_cont, pkc); + pkc->uc = GNUNET_FS_publish_ublock_ (pkc->h, + pkc->dsh, + keyword, NULL, + GNUNET_CRYPTO_ecc_key_get_anonymous (), + pkc->meta, + pkc->uri, + &pkc->bo, + pkc->options, + &kb_put_cont, pkc); } @@ -267,17 +201,15 @@ GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, GNUNET_FS_PublishContinuation cont, void *cont_cls) { struct GNUNET_FS_PublishKskContext *pkc; - char *uris; - size_t size; - char *kbe; - char *sptr; GNUNET_assert (NULL != uri); - pkc = GNUNET_malloc (sizeof (struct GNUNET_FS_PublishKskContext)); + pkc = GNUNET_new (struct GNUNET_FS_PublishKskContext); pkc->h = h; pkc->bo = *bo; + pkc->options = options; pkc->cont = cont; pkc->cont_cls = cont_cls; + pkc->meta = GNUNET_CONTAINER_meta_data_duplicate (meta); if (0 == (options & GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY)) { pkc->dsh = GNUNET_DATASTORE_connect (h->cfg); @@ -288,44 +220,7 @@ GNUNET_FS_publish_ksk (struct GNUNET_FS_Handle *h, return NULL; } } - if (meta == NULL) - pkc->mdsize = 0; - else - pkc->mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); - GNUNET_assert (pkc->mdsize >= 0); - uris = GNUNET_FS_uri_to_string (uri); - pkc->slen = strlen (uris) + 1; - size = pkc->mdsize + sizeof (struct UBlock) + pkc->slen + 1; - if (size > MAX_UBLOCK_SIZE) - { - size = MAX_UBLOCK_SIZE; - pkc->mdsize = size - sizeof (struct UBlock) - pkc->slen + 1; - } - pkc->ub = GNUNET_malloc (size); - kbe = (char *) &pkc->ub[1]; - kbe++; /* leave one '\0' for the update identifier */ - memcpy (kbe, uris, pkc->slen); - GNUNET_free (uris); - sptr = &kbe[pkc->slen]; - if (meta != NULL) - pkc->mdsize = - GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, pkc->mdsize, - GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); - if (-1 == pkc->mdsize) - { - GNUNET_break (0); - GNUNET_free (pkc->ub); - if (NULL != pkc->dsh) - { - GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); - pkc->dsh = NULL; - } - GNUNET_free (pkc); - cont (cont_cls, NULL, _("Internal error.")); - return NULL; - } - size = sizeof (struct UBlock) + pkc->slen + pkc->mdsize + 1; - pkc->cpy = GNUNET_malloc (size); + pkc->uri = GNUNET_FS_uri_dup (uri); pkc->ksk_uri = GNUNET_FS_uri_dup (ksk_uri); pkc->ksk_task = GNUNET_SCHEDULER_add_now (&publish_ksk_cont, pkc); return pkc; @@ -345,19 +240,19 @@ GNUNET_FS_publish_ksk_cancel (struct GNUNET_FS_PublishKskContext *pkc) GNUNET_SCHEDULER_cancel (pkc->ksk_task); pkc->ksk_task = GNUNET_SCHEDULER_NO_TASK; } - if (NULL != pkc->qre) + if (NULL != pkc->uc) { - GNUNET_DATASTORE_cancel (pkc->qre); - pkc->qre = NULL; + GNUNET_FS_publish_ublock_cancel_ (pkc->uc); + pkc->uc = NULL; } if (NULL != pkc->dsh) { GNUNET_DATASTORE_disconnect (pkc->dsh, GNUNET_NO); pkc->dsh = NULL; } - GNUNET_free (pkc->cpy); - GNUNET_free (pkc->ub); + GNUNET_CONTAINER_meta_data_destroy (pkc->meta); GNUNET_FS_uri_destroy (pkc->ksk_uri); + GNUNET_FS_uri_destroy (pkc->uri); GNUNET_free (pkc); } diff --git a/src/fs/fs_publish_ublock.c b/src/fs/fs_publish_ublock.c new file mode 100644 index 000000000..9ddff0655 --- /dev/null +++ b/src/fs/fs_publish_ublock.c @@ -0,0 +1,262 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file fs/fs_publish_ublock.c + * @brief publish a UBLOCK in GNUnet + * @see https://gnunet.org/encoding and #2564 + * @author Krista Bennett + * @author Christian Grothoff + */ +#include "platform.h" +#include "gnunet_constants.h" +#include "gnunet_signatures.h" +#include "fs_publish_ublock.h" +#include "fs_api.h" +#include "fs_tree.h" + + +/** + * Decrypt the given UBlock, storing the result in output. + * + * @param input input data + * @param input_len number of bytes in input + * @param ns public key under which the UBlock was stored + * @param label label under which the UBlock was stored + * @param output where to write the result, has input_len bytes + */ +void +GNUNET_FS_ublock_decrypt_ (const void *input, + size_t input_len, + const struct GNUNET_CRYPTO_EccPublicKey *ns, + const char *label, + void *output) +{ + GNUNET_break (0); +} + + +/** + * Context for 'ublock_put_cont'. + */ +struct GNUNET_FS_PublishUblockContext +{ + + /** + * Function to call when done. + */ + GNUNET_FS_UBlockContinuation cont; + + /** + * Closure of 'cont'. + */ + void *cont_cls; + + /** + * Handle for active datastore operation. + */ + struct GNUNET_DATASTORE_QueueEntry *qre; +}; + + +/** + * Continuation of "GNUNET_FS_publish_ublock_". + * + * @param cls closure of type "struct GNUNET_FS_PublishUblockContext*" + * @param success GNUNET_SYSERR on failure (including timeout/queue drop) + * GNUNET_NO if content was already there + * GNUNET_YES (or other positive value) on success + * @param min_expiration minimum expiration time required for 0-priority content to be stored + * by the datacache at this time, zero for unknown, forever if we have no + * space for 0-priority content + * @param msg NULL on success, otherwise an error message + */ +static void +ublock_put_cont (void *cls, + int32_t success, + struct GNUNET_TIME_Absolute min_expiration, + const char *msg) +{ + struct GNUNET_FS_PublishUblockContext *uc = cls; + + uc->qre = NULL; + uc->cont (uc->cont_cls, msg); + GNUNET_free (uc); +} + + +/** + * Publish a UBlock. + * + * @param h handle to the file sharing subsystem + * @param dsh datastore handle to use for storage operation + * @param label identifier to use + * @param ulabel update label to use, may be an empty string for none + * @param ns namespace to publish in + * @param meta metadata to use + * @param uri URI to refer to in the UBlock + * @param bo per-block options + * @param options publication options + * @param cont continuation + * @param cont_cls closure for cont + * @return NULL on error ('cont' will still be called) + */ +struct GNUNET_FS_PublishUblockContext * +GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h, + struct GNUNET_DATASTORE_Handle *dsh, + const char *label, + const char *ulabel, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, + const struct GNUNET_CONTAINER_MetaData *meta, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_FS_BlockOptions *bo, + enum GNUNET_FS_PublishOptions options, + GNUNET_FS_UBlockContinuation cont, void *cont_cls) +{ + struct GNUNET_FS_PublishUblockContext *uc; + struct GNUNET_HashCode key; + struct GNUNET_HashCode seed; + struct GNUNET_HashCode signing_key; + struct GNUNET_HashCode query; + struct GNUNET_CRYPTO_AesSessionKey skey; + struct GNUNET_CRYPTO_AesInitializationVector iv; + struct GNUNET_CRYPTO_EccPrivateKey *nsd; + struct GNUNET_CRYPTO_EccPublicKey pub; + char *uris; + size_t size; + char *kbe; + char *sptr; + ssize_t mdsize; + size_t slen; + size_t ulen; + struct UBlock *ub_plain; + struct UBlock *ub_enc; + + /* compute ublock to publish */ + if (NULL == meta) + mdsize = 0; + else + mdsize = GNUNET_CONTAINER_meta_data_get_serialized_size (meta); + GNUNET_assert (mdsize >= 0); + uris = GNUNET_FS_uri_to_string (uri); + slen = strlen (uris) + 1; + ulen = strlen (ulabel) + 1; + size = mdsize + sizeof (struct UBlock) + slen + ulen; + if (size > MAX_UBLOCK_SIZE) + { + size = MAX_UBLOCK_SIZE; + mdsize = size - sizeof (struct UBlock) - (slen + ulen); + } + ub_plain = GNUNET_malloc (size); + kbe = (char *) &ub_plain[1]; + memcpy (kbe, ulabel, ulen); + kbe += ulen; + memcpy (kbe, uris, slen); + kbe += slen; + GNUNET_free (uris); + sptr = kbe; + if (NULL != meta) + mdsize = + GNUNET_CONTAINER_meta_data_serialize (meta, &sptr, mdsize, + GNUNET_CONTAINER_META_DATA_SERIALIZE_PART); + if (-1 == mdsize) + { + GNUNET_break (0); + GNUNET_free (ub_plain); + cont (cont_cls, _("Internal error.")); + return NULL; + } + size = sizeof (struct UBlock) + slen + mdsize + ulen; + + /* derive signing seed from plaintext */ + GNUNET_CRYPTO_hash (&ub_plain[1], + ulen + slen + mdsize, + &seed); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Publishing under identifier `%s'\n", + label); + /* get public key of the namespace */ + GNUNET_CRYPTO_ecc_key_get_public (ns, + &pub); + /* derive key from 'label' and public key of the namespace */ + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&key, sizeof (key), + "UBLOCK-ENC", strlen ("UBLOCK-ENC"), + label, strlen (label), + &pub, sizeof (pub), + NULL, 0)); + GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); + + /* encrypt ublock */ + ub_enc = GNUNET_malloc (size); + GNUNET_CRYPTO_aes_encrypt (&ub_plain[1], + ulen + slen + mdsize, + &skey, &iv, + &ub_enc[1]); + ub_enc->purpose.size = htonl (ulen + slen + mdsize + + sizeof (struct UBlock) + - sizeof (struct GNUNET_CRYPTO_EccSignature)); + ub_enc->purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK); + + /* derive signing-key from 'label' and public key of the namespace */ + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_kdf (&signing_key, sizeof (signing_key), + "UBLOCK-SIGN", strlen ("UBLOCK-SIGN"), + label, strlen (label), + &pub, sizeof (pub), + NULL, 0)); + nsd = GNUNET_CRYPTO_ecc_key_derive (ns, label); + GNUNET_CRYPTO_ecc_key_get_public (nsd, + &ub_enc->verification_key); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_sign (nsd, + &ub_enc->purpose, + &ub_enc->signature)); + GNUNET_CRYPTO_hash (&ub_enc->verification_key, + sizeof (ub_enc->verification_key), + &query); + GNUNET_CRYPTO_ecc_key_free (nsd); + + uc = GNUNET_new (struct GNUNET_FS_PublishUblockContext); + uc->cont = cont; + uc->cont_cls = cont_cls; + uc->qre = + GNUNET_DATASTORE_put (dsh, 0, &query, + ulen + slen + mdsize + sizeof (struct UBlock), + ub_enc, GNUNET_BLOCK_TYPE_FS_UBLOCK, + bo->content_priority, bo->anonymity_level, + bo->replication_level, bo->expiration_time, + -2, 1, GNUNET_CONSTANTS_SERVICE_TIMEOUT, + &ublock_put_cont, uc); + return uc; +} + + +/** + * Abort UBlock publishing operation. + * + * @param uc operation to abort. + */ +void +GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc) +{ + GNUNET_DATASTORE_cancel (uc->qre); + GNUNET_free (uc); +} diff --git a/src/fs/fs_publish_ublock.h b/src/fs/fs_publish_ublock.h new file mode 100644 index 000000000..9a2db54ac --- /dev/null +++ b/src/fs/fs_publish_ublock.h @@ -0,0 +1,108 @@ +/* + This file is part of GNUnet. + (C) 2009, 2010, 2012, 2013 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file fs/fs_publish_ublock.h + * @brief publish a UBLOCK in GNUnet + * @see https://gnunet.org/encoding and #2564 + * @author Krista Bennett + * @author Christian Grothoff + */ +#ifndef FS_PUBLISH_UBLOCK_H +#define FS_PUBLISH_UBLOCK_H + +#include "gnunet_util_lib.h" +#include "gnunet_datastore_service.h" +#include "gnunet_fs_service.h" +#include "gnunet_identity_service.h" + + +/** + * Decrypt the given UBlock, storing the result in output. + * + * @param input input data + * @param input_len number of bytes in input + * @param ns public key under which the UBlock was stored + * @param label label under which the UBlock was stored + * @param output where to write the result, has input_len bytes + */ +void +GNUNET_FS_ublock_decrypt_ (const void *input, + size_t input_len, + const struct GNUNET_CRYPTO_EccPublicKey *ns, + const char *label, + void *output); + + +/** + * Context for 'ublock_put_cont'. + */ +struct GNUNET_FS_PublishUblockContext; + + +/** + * Signature of a function called as the continuation of a UBlock + * publication. + * + * @param cls closure + * @param emsg error message, NULL on success + */ +typedef void (*GNUNET_FS_UBlockContinuation) (void *cls, + const char *emsg); + + +/** + * Publish a UBlock. + * + * @param h handle to the file sharing subsystem + * @param dsh datastore handle to use for storage operation + * @param label identifier to use + * @param ulabel update label to use, may be an empty string for none + * @param ns namespace to publish in + * @param meta metadata to use + * @param uri URI to refer to in the UBlock + * @param bo per-block options + * @param options publication options + * @param cont continuation + * @param cont_cls closure for cont + * @return NULL on error ('cont' will still be called) + */ +struct GNUNET_FS_PublishUblockContext * +GNUNET_FS_publish_ublock_ (struct GNUNET_FS_Handle *h, + struct GNUNET_DATASTORE_Handle *dsh, + const char *label, + const char *ulabel, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, + const struct GNUNET_CONTAINER_MetaData *meta, + const struct GNUNET_FS_Uri *uri, + const struct GNUNET_FS_BlockOptions *bo, + enum GNUNET_FS_PublishOptions options, + GNUNET_FS_UBlockContinuation cont, void *cont_cls); + + +/** + * Abort UBlock publishing operation. + * + * @param uc operation to abort. + */ +void +GNUNET_FS_publish_ublock_cancel_ (struct GNUNET_FS_PublishUblockContext *uc); + +#endif diff --git a/src/fs/fs_search.c b/src/fs/fs_search.c index 10627753a..3b0db0429 100644 --- a/src/fs/fs_search.c +++ b/src/fs/fs_search.c @@ -27,6 +27,7 @@ #include "gnunet_fs_service.h" #include "gnunet_protocols.h" #include "fs_api.h" +#include "fs_publish_ublock.h" /** @@ -669,7 +670,7 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, const char *id_update, * given ciphertext block. * * @param sc search context with the keywords - * @param verification_key public key to use to lookup the keyword + * @param dpub derived public key used for the search * @param edata encrypted data * @param edata_size number of bytes in 'edata' (and 'data') * @param data where to store the plaintext @@ -678,22 +679,20 @@ process_sks_result (struct GNUNET_FS_SearchContext *sc, const char *id_update, */ static int decrypt_block_with_keyword (const struct GNUNET_FS_SearchContext *sc, - const struct GNUNET_FS_PseudonymIdentifier *verification_key, + const struct GNUNET_CRYPTO_EccPublicKey *dpub, const void *edata, size_t edata_size, char *data) { - struct GNUNET_HashCode q; - struct GNUNET_CRYPTO_AesSessionKey skey; - struct GNUNET_CRYPTO_AesInitializationVector iv; - int i; + const struct GNUNET_CRYPTO_EccPrivateKey *anon; + struct GNUNET_CRYPTO_EccPublicKey anon_pub; + unsigned int i; - GNUNET_CRYPTO_hash (verification_key, - sizeof (struct GNUNET_FS_PseudonymIdentifier), - &q); /* find key */ for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) - if (0 == memcmp (&q, &sc->requests[i].uquery, sizeof (struct GNUNET_HashCode))) + if (0 == memcmp (dpub, + &sc->requests[i].dpub, + sizeof (struct GNUNET_CRYPTO_EccPublicKey))) break; if (i == sc->uri->data.ksk.keywordCount) { @@ -702,14 +701,12 @@ decrypt_block_with_keyword (const struct GNUNET_FS_SearchContext *sc, return GNUNET_SYSERR; } /* decrypt */ - GNUNET_CRYPTO_hash_to_aes_key (&sc->requests[i].ukey, &skey, &iv); - if (-1 == - GNUNET_CRYPTO_aes_decrypt (edata, edata_size, &skey, - &iv, data)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } + anon = GNUNET_CRYPTO_ecc_key_get_anonymous (); + GNUNET_CRYPTO_ecc_key_get_public (anon, &anon_pub); + GNUNET_FS_ublock_decrypt_ (edata, edata_size, + &anon_pub, + sc->requests[i].keyword, + data); return i; } @@ -789,31 +786,18 @@ process_sblock (struct GNUNET_FS_SearchContext *sc, { size_t len = size - sizeof (struct UBlock); char pt[len]; - struct GNUNET_CRYPTO_AesSessionKey skey; - struct GNUNET_CRYPTO_AesInitializationVector iv; struct GNUNET_FS_Uri *uri; struct GNUNET_CONTAINER_MetaData *meta; const char *id; const char *uris; size_t off; char *emsg; - struct GNUNET_HashCode key; - struct GNUNET_HashCode id_hash; - struct GNUNET_HashCode ns_hash; - char *identifier; /* decrypt */ - identifier = sc->uri->data.sks.identifier; - GNUNET_CRYPTO_hash (identifier, strlen (identifier), &id_hash); - GNUNET_CRYPTO_hash (&sc->uri->data.sks.ns, - sizeof (sc->uri->data.sks.ns), &ns_hash); - GNUNET_CRYPTO_hash_xor (&id_hash, &ns_hash, &key); - GNUNET_CRYPTO_hash_to_aes_key (&key, &skey, &iv); - if (-1 == GNUNET_CRYPTO_aes_decrypt (&ub[1], len, &skey, &iv, pt)) - { - GNUNET_break (0); - return; - } + GNUNET_FS_ublock_decrypt_ (&ub[1], len, + &sc->uri->data.sks.ns, + sc->uri->data.sks.identifier, + pt); /* parse */ if (0 == (off = GNUNET_STRINGS_buffer_tokenize (pt, len, 2, &id, &uris))) { @@ -1050,12 +1034,7 @@ transmit_search_request (void *cls, size_t size, void *buf) struct MessageBuilderContext mbc; size_t msize; struct SearchMessage *sm; - const char *identifier; - struct GNUNET_HashCode key; - struct GNUNET_HashCode signing_key; - struct GNUNET_HashCode ns_hash; - struct GNUNET_HashCode id_hash; - struct GNUNET_FS_PseudonymIdentifier verification_key; + struct GNUNET_CRYPTO_EccPublicKey dpub; unsigned int sqms; uint32_t options; @@ -1122,18 +1101,11 @@ transmit_search_request (void *cls, size_t size, void *buf) sm->type = htonl (GNUNET_BLOCK_TYPE_FS_UBLOCK); sm->anonymity_level = htonl (sc->anonymity); memset (&sm->target, 0, sizeof (struct GNUNET_HashCode)); - - identifier = sc->uri->data.sks.identifier; - GNUNET_CRYPTO_hash (identifier, strlen (identifier), &id_hash); - GNUNET_CRYPTO_hash (&sc->uri->data.sks.ns, - sizeof (sc->uri->data.sks.ns), &ns_hash); - GNUNET_CRYPTO_hash_xor (&id_hash, &ns_hash, &key); - GNUNET_CRYPTO_hash (&key, sizeof (struct GNUNET_HashCode), &signing_key); - GNUNET_FS_pseudonym_derive_verification_key (&sc->uri->data.sks.ns, - &signing_key, - &verification_key); - GNUNET_CRYPTO_hash (&verification_key, - sizeof (verification_key), + GNUNET_CRYPTO_ecc_public_key_derive (&sc->uri->data.sks.ns, + sc->uri->data.sks.identifier, + &dpub); + GNUNET_CRYPTO_hash (&dpub, + sizeof (dpub), &sm->query); mbc.put_cnt = (size - msize) / sizeof (struct GNUNET_HashCode); sqms = GNUNET_CONTAINER_multihashmap_size (sc->master_result_map); @@ -1297,35 +1269,34 @@ GNUNET_FS_search_start_searching_ (struct GNUNET_FS_SearchContext *sc) { unsigned int i; const char *keyword; - struct GNUNET_HashCode signing_key; - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier anon; - struct GNUNET_FS_PseudonymIdentifier verification_key; + const struct GNUNET_CRYPTO_EccPrivateKey *anon; + struct GNUNET_CRYPTO_EccPublicKey anon_pub; + struct SearchRequestEntry *sre; GNUNET_assert (NULL == sc->client); if (GNUNET_FS_uri_test_ksk (sc->uri)) { GNUNET_assert (0 != sc->uri->data.ksk.keywordCount); - ph = GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle (); - GNUNET_FS_pseudonym_get_identifier (ph, &anon); - GNUNET_FS_pseudonym_destroy (ph); + anon = GNUNET_CRYPTO_ecc_key_get_anonymous (); + GNUNET_CRYPTO_ecc_key_get_public (anon, &anon_pub); sc->requests = GNUNET_malloc (sizeof (struct SearchRequestEntry) * sc->uri->data.ksk.keywordCount); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) { keyword = &sc->uri->data.ksk.keywords[i][1]; - GNUNET_CRYPTO_hash (keyword, strlen (keyword), &sc->requests[i].ukey); - GNUNET_CRYPTO_hash (&sc->requests[i].ukey, sizeof (struct GNUNET_HashCode), &signing_key); - GNUNET_FS_pseudonym_derive_verification_key (&anon, - &signing_key, - &verification_key); - GNUNET_CRYPTO_hash (&verification_key, sizeof (struct GNUNET_FS_PseudonymIdentifier), - &sc->requests[i].uquery); - sc->requests[i].mandatory = (sc->uri->data.ksk.keywords[i][0] == '+'); - if (sc->requests[i].mandatory) + sre = &sc->requests[i]; + sre->keyword = GNUNET_strdup (keyword); + GNUNET_CRYPTO_ecc_public_key_derive (&anon_pub, + keyword, + &sre->dpub); + GNUNET_CRYPTO_hash (&sre->dpub, + sizeof (struct GNUNET_CRYPTO_EccPublicKey), + &sre->uquery); + sre->mandatory = (sc->uri->data.ksk.keywords[i][0] == '+'); + if (sre->mandatory) sc->mandatory_count++; - sc->requests[i].results = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); + sre->results = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO); } } sc->client = GNUNET_CLIENT_connect ("fs", sc->h->cfg); @@ -1475,7 +1446,10 @@ GNUNET_FS_search_signal_suspend_ (void *cls) { GNUNET_assert (GNUNET_FS_uri_test_ksk (sc->uri)); for (i = 0; i < sc->uri->data.ksk.keywordCount; i++) + { GNUNET_CONTAINER_multihashmap_destroy (sc->requests[i].results); + GNUNET_free (sc->requests[i].keyword); + } } GNUNET_free_non_null (sc->requests); GNUNET_free_non_null (sc->emsg); diff --git a/src/fs/fs_unindex.c b/src/fs/fs_unindex.c index 132109c59..cfe73d617 100644 --- a/src/fs/fs_unindex.c +++ b/src/fs/fs_unindex.c @@ -553,10 +553,9 @@ void GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc) { const char *keyword; - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier anon; - struct GNUNET_FS_PseudonymIdentifier verification_key; - struct GNUNET_HashCode signing_key; + const struct GNUNET_CRYPTO_EccPrivateKey *anon; + struct GNUNET_CRYPTO_EccPublicKey anon_pub; + struct GNUNET_CRYPTO_EccPublicKey dpub; if (NULL == uc->dsh) uc->dsh = GNUNET_DATASTORE_connect (uc->h->cfg); @@ -574,18 +573,14 @@ GNUNET_FS_unindex_do_remove_kblocks_ (struct GNUNET_FS_UnindexContext *uc) unindex_finish (uc); return; } - /* FIXME: code duplication with fs_search.c here... */ - ph = GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle (); - GNUNET_FS_pseudonym_get_identifier (ph, &anon); - GNUNET_FS_pseudonym_destroy (ph); + anon = GNUNET_CRYPTO_ecc_key_get_anonymous (); + GNUNET_CRYPTO_ecc_key_get_public (anon, &anon_pub); keyword = &uc->ksk_uri->data.ksk.keywords[uc->ksk_offset][1]; - GNUNET_CRYPTO_hash (keyword, strlen (keyword), &uc->ukey); - GNUNET_CRYPTO_hash (&uc->ukey, sizeof (struct GNUNET_HashCode), &signing_key); - GNUNET_FS_pseudonym_derive_verification_key (&anon, - &signing_key, - &verification_key); - GNUNET_CRYPTO_hash (&verification_key, - sizeof (struct GNUNET_FS_PseudonymIdentifier), + GNUNET_CRYPTO_ecc_public_key_derive (&anon_pub, + keyword, + &dpub); + GNUNET_CRYPTO_hash (&dpub, + sizeof (dpub), &uc->uquery); uc->first_uid = 0; uc->dqe = GNUNET_DATASTORE_get_key (uc->dsh, diff --git a/src/fs/fs_uri.c b/src/fs/fs_uri.c index 78b5459fd..e0bdc7ed6 100644 --- a/src/fs/fs_uri.c +++ b/src/fs/fs_uri.c @@ -95,10 +95,11 @@ * into HashMaps. The key may change between FS implementations. * * @param uri uri to convert to a unique key - * @param key wherer to store the unique key + * @param key where to store the unique key */ void -GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode * key) +GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, + struct GNUNET_HashCode *key) { switch (uri->type) { @@ -144,7 +145,7 @@ GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri) char **keywords; unsigned int keywordCount; - if ((uri == NULL) || (uri->type != GNUNET_FS_URI_KSK)) + if ((NULL == uri) || (GNUNET_FS_URI_KSK != uri->type)) { GNUNET_break (0); return NULL; @@ -269,7 +270,7 @@ uri_ksk_parse (const char *s, char **emsg) char *dup; int saw_quote; - GNUNET_assert (s != NULL); + GNUNET_assert (NULL != s); slen = strlen (s); pos = strlen (GNUNET_FS_URI_KSK_PREFIX); if ((slen <= pos) || (0 != strncmp (s, GNUNET_FS_URI_KSK_PREFIX, pos))) @@ -329,7 +330,7 @@ uri_ksk_parse (const char *s, char **emsg) goto CLEANUP; GNUNET_assert (max == 0); GNUNET_free (dup); - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ret->data.ksk.keywordCount = iret; ret->data.ksk.keywords = keywords; @@ -356,7 +357,7 @@ static struct GNUNET_FS_Uri * uri_sks_parse (const char *s, char **emsg) { struct GNUNET_FS_Uri *ret; - struct GNUNET_FS_PseudonymIdentifier id; + struct GNUNET_CRYPTO_EccPublicKey ns; size_t pos; char *end; @@ -369,16 +370,16 @@ uri_sks_parse (const char *s, char **emsg) (GNUNET_OK != GNUNET_STRINGS_string_to_data (&s[pos], end - &s[pos], - &id, - sizeof (id))) ) + &ns, + sizeof (ns))) ) { *emsg = GNUNET_strdup (_("Malformed SKS URI")); return NULL; /* malformed */ } end++; /* skip over '/' */ - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_SKS; - ret->data.sks.ns = id; + ret->data.sks.ns = ns; ret->data.sks.identifier = GNUNET_strdup (end); return ret; } @@ -434,7 +435,7 @@ uri_chk_parse (const char *s, char **emsg) return NULL; } fi.file_length = GNUNET_htonll (flen); - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_CHK; ret->data.chk = fi; return ret; @@ -505,24 +506,36 @@ enc2bin (const char *input, void *data, size_t size) } +GNUNET_NETWORK_STRUCT_BEGIN /** - * Structure that defines how the - * contents of a location URI must be - * assembled in memory to create or - * verify the signature of a location + * Structure that defines how the contents of a location URI must be + * assembled in memory to create or verify the signature of a location * URI. */ struct LocUriAssembly { + /** + * What is being signed (rest of this struct). + */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + /** + * Expiration time of the offer. + */ struct GNUNET_TIME_AbsoluteNBO exptime; + /** + * File being offered. + */ struct FileIdentifier fi; + /** + * Peer offering the file. + */ struct GNUNET_CRYPTO_EccPublicKey peer; }; +GNUNET_NETWORK_STRUCT_END #define GNUNET_FS_URI_LOC_PREFIX GNUNET_FS_URI_PREFIX GNUNET_FS_URI_LOC_INFIX @@ -635,7 +648,7 @@ uri_loc_parse (const char *s, char **emsg) GNUNET_strdup (_("SKS URI malformed (signature failed validation)")); goto ERR; } - uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_LOC; uri->data.loc.fi = ass.fi; uri->data.loc.peer = ass.peer; @@ -862,7 +875,7 @@ GNUNET_FS_uri_loc_get_uri (const struct GNUNET_FS_Uri *uri) if (uri->type != GNUNET_FS_URI_LOC) return NULL; - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_CHK; ret->data.chk = uri->data.loc.fi; return ret; @@ -912,7 +925,7 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, ass.exptime = GNUNET_TIME_absolute_hton (expiration_time); ass.fi = baseUri->data.chk; ass.peer = my_public_key; - uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_LOC; uri->data.loc.fi = baseUri->data.chk; uri->data.loc.expirationTime = expiration_time; @@ -925,58 +938,22 @@ GNUNET_FS_uri_loc_create (const struct GNUNET_FS_Uri *baseUri, } -/** - * Create an SKS URI from a namespace and an identifier. - * - * @param ns namespace - * @param id identifier - * @param emsg where to store an error message - * @return an FS URI for the given namespace and identifier - */ -struct GNUNET_FS_Uri * -GNUNET_FS_uri_sks_create (struct GNUNET_FS_Namespace *ns, const char *id, - char **emsg) -{ - struct GNUNET_FS_Uri *ns_uri; - - if (NULL == id) - { - if (NULL != emsg) - *emsg = GNUNET_strdup (_("identifier is NULL!")); - return NULL; - } - else if ('\0' == id[0]) - { - if (NULL != emsg) - *emsg = GNUNET_strdup (_("identifier has zero length!")); - return NULL; - } - if (NULL != emsg) - *emsg = NULL; - ns_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); - ns_uri->type = GNUNET_FS_URI_SKS; - GNUNET_FS_namespace_get_public_identifier (ns, &ns_uri->data.sks.ns); - ns_uri->data.sks.identifier = GNUNET_strdup (id); - return ns_uri; -} - - /** * Create an SKS URI from a namespace ID and an identifier. * - * @param pseudonym namespace ID + * @param ns namespace ID * @param id identifier * @return an FS URI for the given namespace and identifier */ struct GNUNET_FS_Uri * -GNUNET_FS_uri_sks_create_from_nsid (struct GNUNET_FS_PseudonymIdentifier *pseudonym, - const char *id) +GNUNET_FS_uri_sks_create (const struct GNUNET_CRYPTO_EccPublicKey *ns, + const char *id) { struct GNUNET_FS_Uri *ns_uri; - ns_uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ns_uri = GNUNET_new (struct GNUNET_FS_Uri); ns_uri->type = GNUNET_FS_URI_SKS; - ns_uri->data.sks.ns = *pseudonym; + ns_uri->data.sks.ns = *ns; ns_uri->data.sks.identifier = GNUNET_strdup (id); return ns_uri; } @@ -1033,7 +1010,7 @@ GNUNET_FS_uri_ksk_merge (const struct GNUNET_FS_Uri *u1, if (0 == found) kl[kc++] = GNUNET_strdup (kp); } - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ret->data.ksk.keywordCount = kc; ret->data.ksk.keywords = kl; @@ -1055,7 +1032,7 @@ GNUNET_FS_uri_dup (const struct GNUNET_FS_Uri *uri) if (uri == NULL) return NULL; - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); memcpy (ret, uri, sizeof (struct GNUNET_FS_Uri)); switch (ret->type) { @@ -1224,7 +1201,7 @@ GNUNET_FS_uri_ksk_create_from_args (unsigned int argc, const char **argv) && (NULL != (uri = GNUNET_FS_uri_parse (argv[0], &emsg)))) return uri; GNUNET_free_non_null (emsg); - uri = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + uri = GNUNET_new (struct GNUNET_FS_Uri); uri->type = GNUNET_FS_URI_KSK; uri->data.ksk.keywordCount = argc; uri->data.ksk.keywords = GNUNET_malloc (argc * sizeof (char *)); @@ -1280,7 +1257,7 @@ GNUNET_FS_uri_test_equal (const struct GNUNET_FS_Uri *u1, case GNUNET_FS_URI_SKS: if ((0 == memcmp (&u1->data.sks.ns, &u2->data.sks.ns, - sizeof (struct GNUNET_FS_PseudonymIdentifier))) && + sizeof (struct GNUNET_CRYPTO_EccPublicKey))) && (0 == strcmp (u1->data.sks.identifier, u2->data.sks.identifier))) return GNUNET_YES; @@ -1341,7 +1318,7 @@ GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri) */ int GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri, - struct GNUNET_FS_PseudonymIdentifier *pseudonym) + struct GNUNET_CRYPTO_EccPublicKey *pseudonym) { if (!GNUNET_FS_uri_test_sks (uri)) { @@ -1812,7 +1789,7 @@ GNUNET_FS_uri_ksk_create_from_meta_data (const struct GNUNET_CONTAINER_MetaData if (md == NULL) return NULL; - ret = GNUNET_malloc (sizeof (struct GNUNET_FS_Uri)); + ret = GNUNET_new (struct GNUNET_FS_Uri); ret->type = GNUNET_FS_URI_KSK; ent = GNUNET_CONTAINER_meta_data_iterate (md, NULL, NULL); if (ent > 0) @@ -1944,7 +1921,7 @@ uri_sks_to_string (const struct GNUNET_FS_Uri *uri) if (GNUNET_FS_URI_SKS != uri->type) return NULL; ret = GNUNET_STRINGS_data_to_string (&uri->data.sks.ns, - sizeof (struct GNUNET_FS_PseudonymIdentifier), + sizeof (struct GNUNET_CRYPTO_EccPublicKey), buf, sizeof (buf)); GNUNET_assert (NULL != ret); diff --git a/src/fs/gnunet-pseudonym.c b/src/fs/gnunet-pseudonym.c index 61975e463..c87679641 100644 --- a/src/fs/gnunet-pseudonym.c +++ b/src/fs/gnunet-pseudonym.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009, 2010 Christian Grothoff (and other contributing authors) + (C) 2001-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -24,27 +24,19 @@ */ #include "platform.h" #include "gnunet_fs_service.h" +#include "gnunet_identity_service.h" -/** - * -C option - */ -static char *create_ns; /** - * -D option + * -A option */ -static char *delete_ns; +static char *advertise_ns; /** * -k option */ static struct GNUNET_FS_Uri *ksk_uri; -/** - * -l option. - */ -static int print_local_only; - /** * -m option. */ @@ -76,17 +68,37 @@ static char *rating_change; static struct GNUNET_FS_Handle *h; /** - * Namespace we are looking at. + * Our configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + +/** + * Handle to identity service. */ -static struct GNUNET_FS_Namespace *ns; +static struct GNUNET_IDENTITY_Handle *identity; /** - * Our configuration. + * Target namespace. */ -static const struct GNUNET_CONFIGURATION_Handle *cfg; +static struct GNUNET_IDENTITY_Ego *namespace; +/** + * URI to advertise. + */ +static struct GNUNET_FS_Uri *sks_uri; + +/** + * Global return value. + */ static int ret; + +/** + * Progress callback given to FS. + * + * @param cls unused + * @param info progress information, unused + */ static void * progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) { @@ -94,20 +106,6 @@ progress_cb (void *cls, const struct GNUNET_FS_ProgressInfo *info) } -static void -ns_printer (void *cls, const char *name, const struct GNUNET_FS_PseudonymIdentifier *pseudonym) -{ - struct GNUNET_CRYPTO_HashAsciiEncoded enc; - struct GNUNET_HashCode hc; - - GNUNET_CRYPTO_hash (pseudonym, - sizeof (struct GNUNET_FS_PseudonymIdentifier), - &hc); - GNUNET_CRYPTO_hash_to_enc (&hc, &enc); - FPRINTF (stdout, "%s (%s)\n", name, (const char *) &enc); -} - - /** * Output information about a pseudonym. * @@ -121,7 +119,7 @@ ns_printer (void *cls, const char *name, const struct GNUNET_FS_PseudonymIdentif */ static int pseudo_printer (void *cls, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, @@ -135,77 +133,105 @@ pseudo_printer (void *cls, * GNUNET_FS_pseudonym_get_info () never returns NULL. */ getinfo_result = GNUNET_FS_pseudonym_get_info (cfg, pseudonym, - NULL, NULL, &id, NULL); - if (getinfo_result != GNUNET_OK) + NULL, NULL, &id, NULL); + if (GNUNET_OK != getinfo_result) { GNUNET_break (0); return GNUNET_OK; } unique_id = GNUNET_FS_pseudonym_name_uniquify (cfg, pseudonym, id, NULL); GNUNET_free (id); - FPRINTF (stdout, "%s (%d):\n", unique_id, rating); + FPRINTF (stdout, + "%s (%d):\n", + unique_id, rating); GNUNET_CONTAINER_meta_data_iterate (md, &EXTRACTOR_meta_data_print, stdout); - FPRINTF (stdout, "%s", "\n"); + FPRINTF (stdout, + "%s", + "\n"); GNUNET_free (unique_id); return GNUNET_OK; } +/** + * Function called once advertising is finished. + * + * @param cls closure (NULL) + * @param uri the advertised URI + * @param emsg error message, NULL on success + */ static void -post_advertising (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) +post_advertising (void *cls, + const struct GNUNET_FS_Uri *uri, + const char *emsg) { - struct GNUNET_FS_PseudonymIdentifier nsid; - char *set; - int delta; - if (emsg != NULL) { FPRINTF (stderr, "%s", emsg); ret = 1; } - if (ns != NULL) - { - if (GNUNET_OK != GNUNET_FS_namespace_delete (ns, GNUNET_NO)) - ret = 1; - } - if (NULL != rating_change) + GNUNET_FS_stop (h); + GNUNET_IDENTITY_disconnect (identity); +} + + +/** + * Function called by identity service with known pseudonyms. + * + * @param cls closure, NULL + * @param ego ego handle + * @param ego_ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param name name assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used + */ +static void +identity_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + char *emsg; + struct GNUNET_CRYPTO_EccPublicKey pub; + + if (NULL == ego) { - set = rating_change; - while ((*set != '\0') && (*set != ':')) - set++; - if (*set != ':') + if (NULL == namespace) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Invalid argument `%s'\n"), - rating_change); + ret = 1; + return; } - else + if (NULL != root_identifier) { - *set = '\0'; - delta = strtol (&set[1], NULL, /* no error handling yet */ - 10); - if (GNUNET_OK == GNUNET_FS_pseudonym_name_to_id (cfg, rating_change, &nsid)) + if (NULL == ksk_uri) { - (void) GNUNET_FS_pseudonym_rank (cfg, &nsid, delta); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - ("Namespace `%s' unknown. Make sure you specify its numeric suffix, if any.\n"), - rating_change); + emsg = NULL; + ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/namespace", &emsg); + GNUNET_assert (NULL == emsg); } + GNUNET_IDENTITY_ego_get_public_key (namespace, + &pub); + sks_uri = GNUNET_FS_uri_sks_create (&pub, + root_identifier); + GNUNET_FS_publish_ksk (h, ksk_uri, adv_metadata, sks_uri, + &bo, + GNUNET_FS_PUBLISH_OPTION_NONE, + &post_advertising, NULL); + GNUNET_FS_uri_destroy (sks_uri); + return; } - GNUNET_free (rating_change); - rating_change = NULL; - } - if (0 != print_local_only) - { - GNUNET_FS_namespace_list (h, &ns_printer, NULL); - } - else if (0 == no_remote_printing) - { - GNUNET_FS_pseudonym_list_all (cfg, &pseudo_printer, NULL); + else + { + if (NULL != ksk_uri) + FPRINTF (stderr, _("Option `%s' ignored\n"), "-k"); + if (NULL != advertise_ns) + FPRINTF (stderr, _("Option `%s' ignored\n"), "-A"); + } + return; } - GNUNET_FS_stop (h); + if (0 == strcmp (name, advertise_ns)) + namespace = ego; } @@ -221,68 +247,50 @@ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { - struct GNUNET_FS_Uri *sks_uri; - char *emsg; + struct GNUNET_CRYPTO_EccPublicKey nsid; + char *set; + int delta; cfg = c; h = GNUNET_FS_start (cfg, "gnunet-pseudonym", &progress_cb, NULL, GNUNET_FS_FLAGS_NONE, GNUNET_FS_OPTIONS_END); - if (NULL != delete_ns) - { - ns = GNUNET_FS_namespace_create (h, delete_ns); - if (ns == NULL) - { - ret = 1; - } - else - { - if (GNUNET_OK != GNUNET_FS_namespace_delete (ns, GNUNET_YES)) - ret = 1; - ns = NULL; - } - } - if (NULL != create_ns) + if (NULL != rating_change) { - ns = GNUNET_FS_namespace_create (h, create_ns); - if (ns == NULL) + set = rating_change; + while ((*set != '\0') && (*set != ':')) + set++; + if (*set != ':') { - ret = 1; + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + _("Invalid argument `%s'\n"), + rating_change); } else { - if (NULL != root_identifier) + *set = '\0'; + delta = strtol (&set[1], NULL, /* no error handling yet */ + 10); + if (GNUNET_OK == GNUNET_FS_pseudonym_name_to_id (cfg, rating_change, &nsid)) { - if (ksk_uri == NULL) - { - emsg = NULL; - ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/namespace", &emsg); - GNUNET_assert (NULL == emsg); - } - sks_uri = GNUNET_FS_uri_sks_create (ns, root_identifier, &emsg); - GNUNET_assert (NULL == emsg); - GNUNET_FS_publish_ksk (h, ksk_uri, adv_metadata, sks_uri, - &bo, - GNUNET_FS_PUBLISH_OPTION_NONE, - &post_advertising, NULL); - GNUNET_FS_uri_destroy (sks_uri); - return; + (void) GNUNET_FS_pseudonym_rank (cfg, &nsid, delta); } else { - if (ksk_uri != NULL) - FPRINTF (stderr, _("Option `%s' ignored\n"), "-k"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + ("Namespace `%s' unknown. Make sure you specify its numeric suffix, if any.\n"), + rating_change); } } + GNUNET_free (rating_change); + rating_change = NULL; } - else - { - if (root_identifier != NULL) - FPRINTF (stderr, _("Option `%s' ignored\n"), "-r"); - if (ksk_uri != NULL) - FPRINTF (stderr, _("Option `%s' ignored\n"), "-k"); - } + if (0 == no_remote_printing) + GNUNET_FS_pseudonym_list_all (cfg, &pseudo_printer, NULL); - post_advertising (NULL, NULL, NULL); + if (NULL != advertise_ns) + identity = GNUNET_IDENTITY_connect (cfg, + &identity_cb, + NULL); } @@ -301,12 +309,9 @@ main (int argc, char *const *argv) {'a', "anonymity", "LEVEL", gettext_noop ("set the desired LEVEL of sender-anonymity"), 1, &GNUNET_GETOPT_set_uint, &bo.anonymity_level}, - {'C', "create", "NAME", - gettext_noop ("create or advertise namespace NAME"), - 1, &GNUNET_GETOPT_set_string, &create_ns}, - {'D', "delete", "NAME", - gettext_noop ("delete namespace NAME "), - 1, &GNUNET_GETOPT_set_string, &delete_ns}, + {'A', "advertise", "NAME", + gettext_noop ("advertise namespace NAME"), + 1, &GNUNET_GETOPT_set_string, &advertise_ns}, {'k', "keyword", "VALUE", gettext_noop ("add an additional keyword for the advertisment" " (this option can be specified multiple times)"), @@ -314,9 +319,6 @@ main (int argc, char *const *argv) {'m', "meta", "TYPE:VALUE", gettext_noop ("set the meta-data for the given TYPE to the given VALUE"), 1, &GNUNET_FS_getopt_set_metadata, &adv_metadata}, - {'o', "only-local", NULL, - gettext_noop ("print names of local namespaces"), - 0, &GNUNET_GETOPT_set_one, &print_local_only}, {'p', "priority", "PRIORITY", gettext_noop ("use the given PRIORITY for the advertisments"), 1, &GNUNET_GETOPT_set_uint, &bo.content_priority}, diff --git a/src/fs/gnunet-publish.c b/src/fs/gnunet-publish.c index 59b40a5e4..39235683c 100644 --- a/src/fs/gnunet-publish.c +++ b/src/fs/gnunet-publish.c @@ -27,6 +27,7 @@ */ #include "platform.h" #include "gnunet_fs_service.h" +#include "gnunet_identity_service.h" /** * Global return value from 'main'. @@ -137,7 +138,12 @@ static struct GNUNET_FS_DirScanner *ds; * Which namespace do we publish to? NULL if we do not publish to * a namespace. */ -static struct GNUNET_FS_Namespace *namespace; +static struct GNUNET_IDENTITY_Ego *namespace; + +/** + * Handle to identity service. + */ +static struct GNUNET_IDENTITY_Handle *identity; /** @@ -153,7 +159,7 @@ do_stop_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) struct GNUNET_FS_PublishContext *p; kill_task = GNUNET_SCHEDULER_NO_TASK; - if (pc != NULL) + if (NULL != pc) { p = pc; pc = NULL; @@ -182,10 +188,10 @@ stop_scanner_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) GNUNET_FS_directory_scan_abort (ds); ds = NULL; } - if (NULL != namespace) + if (NULL != identity) { - GNUNET_FS_namespace_delete (namespace, GNUNET_NO); - namespace = NULL; + GNUNET_IDENTITY_disconnect (identity); + identity = NULL; } GNUNET_FS_stop (ctx); ctx = NULL; @@ -432,29 +438,20 @@ static void uri_ksk_continuation (void *cls, const struct GNUNET_FS_Uri *ksk_uri, const char *emsg) { - struct GNUNET_FS_Namespace *ns; + const struct GNUNET_CRYPTO_EccPrivateKey *priv; if (NULL != emsg) { FPRINTF (stderr, "%s\n", emsg); ret = 1; } - if (NULL != pseudonym) + if (NULL != namespace) { - ns = GNUNET_FS_namespace_create (ctx, pseudonym); - if (NULL == ns) - { - FPRINTF (stderr, _("Failed to create namespace `%s' (illegal filename?)\n"), pseudonym); - ret = 1; - } - else - { - GNUNET_FS_publish_sks (ctx, ns, this_id, next_id, meta, uri, &bo, - GNUNET_FS_PUBLISH_OPTION_NONE, - &uri_sks_continuation, NULL); - GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_NO)); - return; - } + priv = GNUNET_IDENTITY_ego_get_private_key (namespace); + GNUNET_FS_publish_sks (ctx, priv, this_id, next_id, meta, uri, &bo, + GNUNET_FS_PUBLISH_OPTION_NONE, + &uri_sks_continuation, NULL); + return; } GNUNET_FS_uri_destroy (uri); uri = NULL; @@ -523,40 +520,37 @@ static void directory_trim_complete (struct GNUNET_FS_ShareTreeItem *directory_scan_result) { struct GNUNET_FS_FileInformation *fi; + const struct GNUNET_CRYPTO_EccPrivateKey *priv; fi = get_file_information (directory_scan_result); GNUNET_FS_share_tree_free (directory_scan_result); if (NULL == fi) { FPRINTF (stderr, "%s", _("Could not publish\n")); - if (NULL != namespace) - GNUNET_FS_namespace_delete (namespace, GNUNET_NO); - GNUNET_FS_stop (ctx); + GNUNET_SCHEDULER_shutdown (); ret = 1; return; } GNUNET_FS_file_information_inspect (fi, &publish_inspector, NULL); if (extract_only) { - if (NULL != namespace) - GNUNET_FS_namespace_delete (namespace, GNUNET_NO); GNUNET_FS_file_information_destroy (fi, NULL, NULL); - GNUNET_FS_stop (ctx); - if (GNUNET_SCHEDULER_NO_TASK != kill_task) - { - GNUNET_SCHEDULER_cancel (kill_task); - kill_task = GNUNET_SCHEDULER_NO_TASK; - } + GNUNET_SCHEDULER_shutdown (); return; } - pc = GNUNET_FS_publish_start (ctx, fi, namespace, this_id, next_id, + if (NULL == namespace) + priv = NULL; + else + priv = GNUNET_IDENTITY_ego_get_private_key (namespace); + pc = GNUNET_FS_publish_start (ctx, fi, + priv, this_id, next_id, (do_simulate) ? GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY : GNUNET_FS_PUBLISH_OPTION_NONE); if (NULL == pc) { FPRINTF (stderr, "%s", _("Could not start publishing.\n")); - GNUNET_FS_stop (ctx); + GNUNET_SCHEDULER_shutdown (); ret = 1; return; } @@ -631,6 +625,94 @@ directory_scan_cb (void *cls, } +/** + * Continuation proceeding with initialization after identity subsystem + * has been initialized. + * + * @param args0 filename to publish + */ +static void +identity_continuation (const char *args0) +{ + char *ex; + char *emsg; + + if ( (NULL != pseudonym) && + (NULL == namespace) ) + { + FPRINTF (stderr, _("Selected pseudonym `%s' unknown\n"), pseudonym); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (NULL != uri_string) + { + emsg = NULL; + if (NULL == (uri = GNUNET_FS_uri_parse (uri_string, &emsg))) + { + FPRINTF (stderr, _("Failed to parse URI: %s\n"), emsg); + GNUNET_free (emsg); + GNUNET_SCHEDULER_shutdown (); + ret = 1; + return; + } + GNUNET_FS_publish_ksk (ctx, topKeywords, meta, uri, &bo, + GNUNET_FS_PUBLISH_OPTION_NONE, &uri_ksk_continuation, + NULL); + return; + } + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, "FS", "EXTRACTORS", &ex)) + ex = NULL; + if (0 != ACCESS (args0, R_OK)) + { + FPRINTF (stderr, + _("Failed to access `%s': %s\n"), + args0, + STRERROR (errno)); + return; + } + ds = GNUNET_FS_directory_scan_start (args0, + disable_extractor, + ex, + &directory_scan_cb, NULL); + if (NULL == ds) + { + FPRINTF (stderr, + "%s", _("Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed?\n")); + return; + } +} + + +/** + * Function called by identity service with known pseudonyms. + * + * @param cls closure with 'const char *' of filename to publish + * @param ego ego handle + * @param ego_ctx context for application to store data for this ego + * (during the lifetime of this process, initially NULL) + * @param name name assigned by the user for this ego, + * NULL if the user just deleted the ego and it + * must thus no longer be used + */ +static void +identity_cb (void *cls, + struct GNUNET_IDENTITY_Ego *ego, + void **ctx, + const char *name) +{ + const char *args0 = cls; + + if (NULL == ego) + { + identity_continuation (args0); + return; + } + if (0 == strcmp (name, pseudonym)) + namespace = ego; +} + + /** * Main function that will be run by the scheduler. * @@ -643,9 +725,6 @@ static void run (void *cls, char *const *args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c) { - char *ex; - char *emsg; - /* check arguments */ if ((NULL != uri_string) && (extract_only)) { @@ -703,62 +782,14 @@ run (void *cls, char *const *args, const char *cfgfile, ret = 1; return; } - namespace = NULL; - if (NULL != pseudonym) - { - namespace = GNUNET_FS_namespace_create (ctx, pseudonym); - if (NULL == namespace) - { - FPRINTF (stderr, _("Failed to create namespace `%s' (illegal filename?)\n"), pseudonym); - GNUNET_FS_stop (ctx); - ret = 1; - return; - } - } - if (NULL != uri_string) - { - emsg = NULL; - if (NULL == (uri = GNUNET_FS_uri_parse (uri_string, &emsg))) - { - FPRINTF (stderr, _("Failed to parse URI: %s\n"), emsg); - GNUNET_free (emsg); - if (namespace != NULL) - GNUNET_FS_namespace_delete (namespace, GNUNET_NO); - GNUNET_FS_stop (ctx); - ret = 1; - return; - } - GNUNET_FS_publish_ksk (ctx, topKeywords, meta, uri, &bo, - GNUNET_FS_PUBLISH_OPTION_NONE, &uri_ksk_continuation, - NULL); - if (NULL != namespace) - GNUNET_FS_namespace_delete (namespace, GNUNET_NO); - return; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, "FS", "EXTRACTORS", &ex)) - ex = NULL; - if (0 != ACCESS (args[0], R_OK)) - { - FPRINTF (stderr, - _("Failed to access `%s': %s\n"), - args[0], - STRERROR (errno)); - return; - } - ds = GNUNET_FS_directory_scan_start (args[0], - disable_extractor, - ex, - &directory_scan_cb, NULL); - if (NULL == ds) - { - FPRINTF (stderr, - "%s", _("Failed to start meta directory scanner. Is gnunet-helper-publish-fs installed?\n")); - return; - } kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &do_stop_task, NULL); + if (NULL != pseudonym) + identity = GNUNET_IDENTITY_connect (cfg, + &identity_cb, args[0]); + else + identity_continuation (args[0]); } diff --git a/src/fs/plugin_block_fs.c b/src/fs/plugin_block_fs.c index 453338614..e493319be 100644 --- a/src/fs/plugin_block_fs.c +++ b/src/fs/plugin_block_fs.c @@ -105,15 +105,16 @@ block_plugin_fs_evaluate (void *cls, enum GNUNET_BLOCK_Type type, GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } - if (reply_block_size != ntohl (ub->purpose.size) + sizeof (struct GNUNET_FS_PseudonymSignature)) + if (reply_block_size != ntohl (ub->purpose.size) + sizeof (struct GNUNET_CRYPTO_EccSignature)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; } if (GNUNET_OK != - GNUNET_FS_pseudonym_verify (&ub->purpose, - &ub->signature, - &ub->verification_key)) + GNUNET_CRYPTO_ecc_verify (GNUNET_SIGNATURE_PURPOSE_FS_UBLOCK, + &ub->purpose, + &ub->signature, + &ub->verification_key)) { GNUNET_break_op (0); return GNUNET_BLOCK_EVALUATION_RESULT_INVALID; diff --git a/src/fs/test_fs_namespace.c b/src/fs/test_fs_namespace.c index c720cb919..c8371f0b5 100644 --- a/src/fs/test_fs_namespace.c +++ b/src/fs/test_fs_namespace.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors) + (C) 2005-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -29,7 +29,7 @@ #include "gnunet_fs_service.h" -static struct GNUNET_FS_PseudonymIdentifier nsid; +static struct GNUNET_CRYPTO_EccPublicKey nsid; static struct GNUNET_FS_Uri *sks_expect_uri; @@ -68,15 +68,10 @@ abort_ksk_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) static void abort_sks_search_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { - struct GNUNET_FS_Namespace *ns; - if (sks_search == NULL) return; GNUNET_FS_search_stop (sks_search); sks_search = NULL; - ns = GNUNET_FS_namespace_create (fs, "testNamespace"); - GNUNET_assert (NULL != ns); - GNUNET_assert (GNUNET_OK == GNUNET_FS_namespace_delete (ns, GNUNET_YES)); if (ksk_search == NULL) { GNUNET_FS_stop (fs); @@ -242,7 +237,7 @@ static void adv_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { struct GNUNET_CONTAINER_MetaData *meta; - struct GNUNET_FS_Namespace *ns; + struct GNUNET_CRYPTO_EccPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; if (NULL != emsg) @@ -252,57 +247,32 @@ adv_cont (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) GNUNET_FS_stop (fs); return; } - ns = GNUNET_FS_namespace_create (fs, "testNamespace"); - GNUNET_assert (NULL != ns); + ns = GNUNET_CRYPTO_ecc_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); - GNUNET_assert (NULL == emsg); sks_expect_uri = GNUNET_FS_uri_dup (uri); bo.content_priority = 1; bo.anonymity_level = 1; bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); + GNUNET_CRYPTO_ecc_key_get_public (ns, &nsid); GNUNET_FS_publish_sks (fs, ns, "this", "next", meta, uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &sks_cont, NULL); GNUNET_CONTAINER_meta_data_destroy (meta); - GNUNET_FS_namespace_delete (ns, GNUNET_NO); -} - - -static void -ns_iterator (void *cls, const char *name, const struct GNUNET_FS_PseudonymIdentifier *id) -{ - int *ok = cls; - - if (0 != strcmp (name, "testNamespace")) - return; - *ok = GNUNET_YES; - nsid = *id; + GNUNET_CRYPTO_ecc_key_free (ns); } static void testNamespace () { - struct GNUNET_FS_Namespace *ns; + struct GNUNET_CRYPTO_EccPrivateKey *ns; struct GNUNET_FS_BlockOptions bo; struct GNUNET_CONTAINER_MetaData *meta; struct GNUNET_FS_Uri *ksk_uri; struct GNUNET_FS_Uri *sks_uri; - int ok; - ns = GNUNET_FS_namespace_create (fs, "testNamespace"); - GNUNET_assert (NULL != ns); - ok = GNUNET_NO; - GNUNET_FS_namespace_list (fs, &ns_iterator, &ok); - if (GNUNET_NO == ok) - { - FPRINTF (stderr, "%s", "namespace_list failed to find namespace!\n"); - GNUNET_FS_namespace_delete (ns, GNUNET_YES); - GNUNET_FS_stop (fs); - err = 1; - return; - } + ns = GNUNET_CRYPTO_ecc_key_create (); meta = GNUNET_CONTAINER_meta_data_create (); ksk_uri = GNUNET_FS_uri_parse ("gnunet://fs/ksk/testnsa", NULL); bo.content_priority = 1; @@ -310,17 +280,18 @@ testNamespace () bo.replication_level = 0; bo.expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES); - sks_uri = GNUNET_FS_uri_sks_create (ns, "root", NULL); + sks_uri = GNUNET_FS_uri_sks_create (&nsid, "root"); GNUNET_FS_publish_ksk (fs, - ksk_uri, meta, sks_uri, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, + ksk_uri, meta, sks_uri, + &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &adv_cont, NULL); GNUNET_FS_uri_destroy (sks_uri); kill_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES, &do_timeout, NULL); GNUNET_FS_uri_destroy (ksk_uri); - GNUNET_FS_namespace_delete (ns, GNUNET_NO); GNUNET_CONTAINER_meta_data_destroy (meta); + GNUNET_CRYPTO_ecc_key_free (ns); } diff --git a/src/fs/test_fs_namespace_list_updateable.c b/src/fs/test_fs_namespace_list_updateable.c index dc17ce458..ff662c9e6 100644 --- a/src/fs/test_fs_namespace_list_updateable.c +++ b/src/fs/test_fs_namespace_list_updateable.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - (C) 2005, 2006, 2008, 2009 Christian Grothoff (and other contributing authors) + (C) 2005-2013 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published @@ -33,7 +33,7 @@ static struct GNUNET_FS_Handle *fs; static int err; -static struct GNUNET_FS_Namespace *ns; +static struct GNUNET_CRYPTO_EccPrivateKey *ns; static struct GNUNET_CONTAINER_MetaData *meta; @@ -59,7 +59,7 @@ do_shutdown () if (uri_next != NULL) GNUNET_FS_uri_destroy (uri_next); if (ns != NULL) - GNUNET_FS_namespace_delete (ns, GNUNET_NO); + GNUNET_CRYPTO_ecc_key_free (ns); if (meta != NULL) GNUNET_CONTAINER_meta_data_destroy (meta); } @@ -87,7 +87,7 @@ check_this_next (void *cls, const char *last_id, GNUNET_break (0 == strcmp (next_id, "next")); err -= 2; err += 4; - GNUNET_FS_namespace_list_updateable (ns, next_id, &check_next, NULL); + GNUNET_FS_namespace_list_updateable (fs, ns, next_id, &check_next, NULL); } @@ -96,7 +96,7 @@ sks_cont_next (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { GNUNET_assert (NULL == emsg); err += 2; - GNUNET_FS_namespace_list_updateable (ns, NULL, &check_this_next, NULL); + GNUNET_FS_namespace_list_updateable (fs, ns, NULL, &check_this_next, NULL); } @@ -117,7 +117,7 @@ sks_cont_this (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) { GNUNET_assert (NULL == emsg); err = 1; - GNUNET_FS_namespace_list_updateable (ns, NULL, &check_this, NULL); + GNUNET_FS_namespace_list_updateable (fs, ns, NULL, &check_this, NULL); GNUNET_FS_publish_sks (fs, ns, "next", "future", meta, uri_next, &bo, GNUNET_FS_PUBLISH_OPTION_NONE, &sks_cont_next, NULL); @@ -127,7 +127,7 @@ sks_cont_this (void *cls, const struct GNUNET_FS_Uri *uri, const char *emsg) static void testNamespace () { - ns = GNUNET_FS_namespace_create (fs, "testNamespace"); + ns = GNUNET_CRYPTO_ecc_key_create (); GNUNET_assert (NULL != ns); bo.content_priority = 1; bo.anonymity_level = 1; diff --git a/src/fs/test_fs_uri.c b/src/fs/test_fs_uri.c index d0aa26b79..ca89a7652 100644 --- a/src/fs/test_fs_uri.c +++ b/src/fs/test_fs_uri.c @@ -162,8 +162,8 @@ testNamespace (int i) char *uri; struct GNUNET_FS_Uri *ret; char *emsg; - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier id; + struct GNUNET_CRYPTO_EccPrivateKey *ph; + struct GNUNET_CRYPTO_EccPublicKey id; char buf[1024]; char ubuf[1024]; char *sret; @@ -192,8 +192,8 @@ testNamespace (int i) GNUNET_assert (0); } GNUNET_free (emsg); - ph = GNUNET_FS_pseudonym_create (NULL); - GNUNET_FS_pseudonym_get_identifier (ph, &id); + ph = GNUNET_CRYPTO_ecc_key_create (); + GNUNET_CRYPTO_ecc_key_get_public (ph, &id); sret = GNUNET_STRINGS_data_to_string (&id, sizeof (id), ubuf, sizeof (ubuf) - 1); GNUNET_assert (NULL != sret); @@ -232,6 +232,7 @@ testNamespace (int i) return 0; } + static int testFile (int i) { diff --git a/src/fs/test_pseudonym.c b/src/fs/test_pseudonym.c index a6e258038..c3b459420 100644 --- a/src/fs/test_pseudonym.c +++ b/src/fs/test_pseudonym.c @@ -33,17 +33,18 @@ static struct GNUNET_CONTAINER_MetaData *meta; -static struct GNUNET_FS_PseudonymIdentifier id1; +static struct GNUNET_CRYPTO_EccPublicKey id1; static int -iter (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseudonym, +iter (void *cls, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int32_t rating) { int *ok = cls; - if ((0 == memcmp (pseudonym, &id1, sizeof (struct GNUNET_FS_PseudonymIdentifier))) && + if ((0 == memcmp (pseudonym, &id1, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) && (!GNUNET_CONTAINER_meta_data_test_equal (md, meta))) { *ok = GNUNET_NO; @@ -54,7 +55,7 @@ iter (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseudonym, static int -noti_callback (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseudonym, +noti_callback (void *cls, const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int32_t rating) { @@ -66,7 +67,8 @@ noti_callback (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseudonym static int -fake_noti_callback (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseudonym, +fake_noti_callback (void *cls, + const struct GNUNET_CRYPTO_EccPublicKey * pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, int32_t rating) { @@ -78,13 +80,13 @@ fake_noti_callback (void *cls, const struct GNUNET_FS_PseudonymIdentifier * pseu static void -create_pseu (struct GNUNET_FS_PseudonymIdentifier *pseu) +create_pseu (struct GNUNET_CRYPTO_EccPublicKey *pseu) { - struct GNUNET_FS_PseudonymHandle *ph; + struct GNUNET_CRYPTO_EccPrivateKey *ph; - ph = GNUNET_FS_pseudonym_create (NULL); - GNUNET_FS_pseudonym_get_identifier (ph, pseu); - GNUNET_FS_pseudonym_destroy (ph); + ph = GNUNET_CRYPTO_ecc_key_create (); + GNUNET_CRYPTO_ecc_key_get_public (ph, pseu); + GNUNET_CRYPTO_ecc_key_free (ph); } @@ -95,11 +97,11 @@ static int test_io () { int ok; - struct GNUNET_FS_PseudonymIdentifier rid1; - struct GNUNET_FS_PseudonymIdentifier id2; - struct GNUNET_FS_PseudonymIdentifier rid2; - struct GNUNET_FS_PseudonymIdentifier fid; - struct GNUNET_FS_PseudonymIdentifier id3; + struct GNUNET_CRYPTO_EccPublicKey rid1; + struct GNUNET_CRYPTO_EccPublicKey id2; + struct GNUNET_CRYPTO_EccPublicKey rid2; + struct GNUNET_CRYPTO_EccPublicKey fid; + struct GNUNET_CRYPTO_EccPublicKey id3; int old; int newVal; struct GNUNET_CONFIGURATION_Handle *cfg; @@ -112,12 +114,11 @@ test_io () int noname_is_a_dup; int notiCount, fakenotiCount; static char m[1024 * 1024 * 10]; - struct GNUNET_FS_pseudonym_DiscoveryHandle *dh1; - struct GNUNET_FS_pseudonym_DiscoveryHandle *dh2; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh1; + struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh2; memset (m, 'b', sizeof (m)); m[sizeof (m) - 1] = '\0'; - GNUNET_log_setup ("test-pseudonym", "WARNING", NULL); ok = GNUNET_YES; (void) GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test"); @@ -178,8 +179,8 @@ test_io () CHECK (GNUNET_SYSERR == GNUNET_FS_pseudonym_name_to_id (cfg, name1, &rid1)); CHECK (GNUNET_OK == GNUNET_FS_pseudonym_name_to_id (cfg, name2_unique, &rid2)); CHECK (GNUNET_OK == GNUNET_FS_pseudonym_name_to_id (cfg, name1_unique, &rid1)); - CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_FS_PseudonymIdentifier))); - CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_FS_PseudonymIdentifier))); + CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_CRYPTO_EccPublicKey))); + CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_CRYPTO_EccPublicKey))); create_pseu (&fid); GNUNET_log_skip (1, GNUNET_NO); @@ -207,119 +208,12 @@ FAILURE: } -/** - * Use the given input to sign and check the resulting signature. - */ -static void -test_signature (struct GNUNET_FS_PseudonymHandle *ph, - struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - struct GNUNET_HashCode *seed, - struct GNUNET_HashCode *signing_key, - char *bit) -{ - struct GNUNET_FS_PseudonymSignature signature; - struct GNUNET_FS_PseudonymSignature signature2; - struct GNUNET_FS_PseudonymIdentifier pseudonym; - struct GNUNET_FS_PseudonymIdentifier verification_key; - - GNUNET_FS_pseudonym_sign (ph, purpose, seed, signing_key, &signature); - GNUNET_FS_pseudonym_sign (ph, purpose, seed, signing_key, &signature2); - /* with seed, two sigs must be identical, without, they must be different! */ - if (NULL != seed) - GNUNET_break (0 == memcmp (&signature, &signature2, sizeof (signature))); - else /* crypto not implemented, thus for now 'break' */ - GNUNET_break (0 != memcmp (&signature, &signature2, sizeof (signature))); - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym); - GNUNET_FS_pseudonym_derive_verification_key (&pseudonym, - signing_key, - &verification_key); - GNUNET_break (GNUNET_OK == - GNUNET_FS_pseudonym_verify (purpose, &signature, &verification_key)); - /* also check that if the data is changed, the signature no longer matches */ - (*bit)++; - GNUNET_log_skip (1, GNUNET_NO); - /* crypto not implemented, thus for now 'break' */ - GNUNET_break (GNUNET_OK != - GNUNET_FS_pseudonym_verify (purpose, &signature, &verification_key)); - (*bit)--; -} - - -/** - * Test cryptographic operations for a given private key. - * - * @param ph private key to test - */ -static void -test_crypto_ops (struct GNUNET_FS_PseudonymHandle *ph) -{ - char data[16]; - struct GNUNET_FS_PseudonymSignaturePurpose *purpose; - struct GNUNET_HashCode seed; - struct GNUNET_HashCode signing_key; - - memset (data, 42, sizeof (data)); - purpose = (struct GNUNET_FS_PseudonymSignaturePurpose *) data; - purpose->size = htonl (sizeof (data)); - purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST); - memset (&seed, 41, sizeof (seed)); - memset (&signing_key, 40, sizeof (signing_key)); - test_signature (ph, purpose, &seed, - &signing_key, &data[sizeof (struct GNUNET_FS_PseudonymSignaturePurpose)]); - test_signature (ph, purpose, NULL, - &signing_key, &data[sizeof (struct GNUNET_FS_PseudonymSignaturePurpose)]); -} - - -/** - * Test cryptographic operations. - */ -static int -test_crypto () -{ - struct GNUNET_FS_PseudonymHandle *ph; - struct GNUNET_FS_PseudonymIdentifier pseudonym; - struct GNUNET_FS_PseudonymIdentifier pseudonym2; - - /* check writing to and reading from disk */ - ph = GNUNET_FS_pseudonym_create ("/tmp/gnunet-pseudonym-test/pseu.dsa"); - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym); - GNUNET_FS_pseudonym_destroy (ph); - ph = GNUNET_FS_pseudonym_create ("/tmp/gnunet-pseudonym-test/pseu.dsa"); - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym2); - test_crypto_ops (ph); - GNUNET_FS_pseudonym_destroy (ph); - if (0 != memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym))) - return 1; - - /* check in-memory generation */ - ph = GNUNET_FS_pseudonym_create (NULL); - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym2); - if (0 == memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym))) - return 1; - test_crypto_ops (ph); - GNUNET_FS_pseudonym_destroy (ph); - - /* check anonymous pseudonym operations generation */ - fprintf (stderr, "Checking anonymous ops\n"); - ph = GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle (); - GNUNET_FS_pseudonym_get_identifier (ph, &pseudonym2); - if (0 == memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym))) - return 1; - test_crypto_ops (ph); - GNUNET_FS_pseudonym_destroy (ph); - return 0; -} - - int main (int argc, char *argv[]) { GNUNET_log_setup ("test-pseudonym", "WARNING", NULL); if (0 != test_io ()) return 1; - if (0 != test_crypto ()) - return 1; GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test")); return 0; diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c index 2062ddc63..84ecb8765 100644 --- a/src/identity/identity_api.c +++ b/src/identity/identity_api.c @@ -175,6 +175,24 @@ struct GNUNET_IDENTITY_Handle }; +/** + * Obtain the ego representing 'anonymous' users. + */ +const struct GNUNET_IDENTITY_Ego * +GNUNET_IDENTITY_ego_get_anonymous () +{ + static struct GNUNET_IDENTITY_Ego anon; + struct GNUNET_CRYPTO_EccPublicKey pub; + + if (NULL != anon.pk) + return &anon; + anon.pk = GNUNET_CRYPTO_ecc_key_get_anonymous (); + GNUNET_CRYPTO_ecc_key_get_public (anon.pk, + &pub); + GNUNET_CRYPTO_hash (&pub, sizeof (pub), &anon.id); + return &anon; +} + /** * Try again to connect to network size estimation service. @@ -566,7 +584,7 @@ GNUNET_IDENTITY_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_IDENTITY_ego_get_private_key (struct GNUNET_IDENTITY_Ego *ego) +GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego) { return ego->pk; } @@ -579,10 +597,11 @@ GNUNET_IDENTITY_ego_get_private_key (struct GNUNET_IDENTITY_Ego *ego) * @param pk set to ego's public key */ void -GNUNET_IDENTITY_ego_get_public_key (struct GNUNET_IDENTITY_Ego *ego, +GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EccPublicKey *pk) { - GNUNET_assert (0); + GNUNET_CRYPTO_ecc_key_get_public (ego->pk, + pk); } diff --git a/src/include/block_fs.h b/src/include/block_fs.h index a2063270e..772180fc8 100644 --- a/src/include/block_fs.h +++ b/src/include/block_fs.h @@ -48,18 +48,17 @@ struct UBlock /** * Signature using pseudonym and search keyword / identifier. */ - struct GNUNET_FS_PseudonymSignature signature; + struct GNUNET_CRYPTO_EccSignature signature; /** * What is being signed and why? */ - struct GNUNET_FS_PseudonymSignaturePurpose purpose GNUNET_PACKED; + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * Public key used to sign this block. Hash of this value - * is the query. + * Public key used to sign this block. */ - struct GNUNET_FS_PseudonymIdentifier verification_key; + struct GNUNET_CRYPTO_EccPublicKey verification_key; /* rest of the data is encrypted */ diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 5f209efea..52bb983b0 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h @@ -884,8 +884,7 @@ GNUNET_CRYPTO_ecc_key_create_from_configuration (const struct GNUNET_CONFIGURATI /** - * Create a new private key. Caller must free return value. Blocking version - * (blocks to gather entropy). + * Create a new private key. Caller must free return value. * * @return fresh private key */ @@ -893,6 +892,15 @@ struct GNUNET_CRYPTO_EccPrivateKey * GNUNET_CRYPTO_ecc_key_create (void); +/** + * Get the shared private key we use for anonymous users. + * + * @return "anonymous" private key + */ +const struct GNUNET_CRYPTO_EccPrivateKey * +GNUNET_CRYPTO_ecc_key_get_anonymous (void); + + /** * Setup a hostkey file for a peer given the name of the * configuration file (!). This function is used so that diff --git a/src/include/gnunet_fs_service.h b/src/include/gnunet_fs_service.h index afe53b0e0..5dcee17cd 100644 --- a/src/include/gnunet_fs_service.h +++ b/src/include/gnunet_fs_service.h @@ -26,7 +26,6 @@ #define GNUNET_FS_LIB_H #include "gnunet_util_lib.h" -#include "gnunet_scheduler_lib.h" #ifdef __cplusplus extern "C" @@ -80,78 +79,6 @@ extern "C" struct GNUNET_FS_Uri; -/** - * Identifier for a GNUnet pseudonym (the public key). Q-point, Q=dP. - * Note that we (ab)use an identifier of 'Q=G=1P' to mean the - * 'anonymous' pseudonym. - */ -struct GNUNET_FS_PseudonymIdentifier -{ - /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. - */ - unsigned char q_x[256 / 8]; - - /** - * Q consists of an x- and a y-value, each mod p (256 bits), - * given here in affine coordinates. - */ - unsigned char q_y[256 / 8]; - -}; - - -/** - * Handle for a pseudonym (private key). - */ -struct GNUNET_FS_PseudonymHandle; - - -/** - * Signature made with a pseudonym (includes the full public key). - * The ECDSA signature is a pair (r,s) with r = x1 mod n where - * (x1,y1) = kG for "random" k and s = k^{-1}(z + rd) mod n, - * where z is derived from the hash of the message that is being - * signed. - */ -struct GNUNET_FS_PseudonymSignature -{ - - /** - * Who created the signature? (public key of the signer), 'd' value in NIST P-256. - */ - struct GNUNET_FS_PseudonymIdentifier signer; - - /** - * Binary ECDSA signature data, r-value. Value is mod n, and n is 256 bits. - */ - unsigned char sig_r[256 / 8]; - - /** - * Binary ECDSA signature data, s-value. Value is mod n, and n is 256 bits. - */ - unsigned char sig_s[256 / 8]; -}; - - -/** - * Purpose for signature made with a pseudonym. - */ -struct GNUNET_FS_PseudonymSignaturePurpose -{ - /** - * How many bytes are being signed (including this header)? - */ - uint32_t size; - - /** - * What is the context/purpose of the signature? - */ - uint32_t purpose; -}; - - /** * Iterator over keywords * @@ -165,120 +92,11 @@ typedef int (*GNUNET_FS_KeywordIterator) (void *cls, const char *keyword, - -/** - * Create a pseudonym. - * - * @param filename name of the file to use for storage, NULL for in-memory only - * @return handle to the private key of the pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_create (const char *filename); - - -/** - * Create a pseudonym, from a file that must already exist. - * - * @param filename name of the file to use for storage, NULL for in-memory only - * @return handle to the private key of the pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_create_from_existing_file (const char *filename); - - -/** - * Get the handle for the 'anonymous' pseudonym shared by all users. - * That pseudonym uses a fixed 'secret' for the private key; this - * construction is useful to make anonymous and pseudonymous APIs - * (and packets) indistinguishable on the network. See #2564. - * - * @return handle to the (non-secret) private key of the 'anonymous' pseudonym - */ -struct GNUNET_FS_PseudonymHandle * -GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle (void); - - -/** - * Destroy a pseudonym handle. Does NOT remove the private key from - * the disk. - * - * @param ph pseudonym handle to destroy - */ -void -GNUNET_FS_pseudonym_destroy (struct GNUNET_FS_PseudonymHandle *ph); - - -/** - * Cryptographically sign some data with the pseudonym. - * - * @param ph private key used for signing (corresponds to 'x' in #2564) - * @param purpose data to sign - * @param seed hash of the plaintext of the data that we are signing, - * used for deterministic PRNG for anonymous signing; - * corresponds to 'k' in section 2.7 of #2564 - * @param signing_key modifier to apply to the private key for signing; - * corresponds to 'h' in section 2.3 of #2564. - * @param signature where to store the signature - * @return GNUNET_SYSERR on failure - */ -int -GNUNET_FS_pseudonym_sign (struct GNUNET_FS_PseudonymHandle *ph, - const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - const struct GNUNET_HashCode *seed, - const struct GNUNET_HashCode *signing_key, - struct GNUNET_FS_PseudonymSignature *signature); - - -/** - * Given a pseudonym and a signing key, derive the corresponding public - * key that would be used to verify the resulting signature. - * - * @param pseudonym the public key (g^x in DSA, dQ in ECDSA) - * @param signing_key input to derive 'h' (see section 2.4 of #2564) - * @param verification_key resulting public key to verify the signature - * created from the 'ph' of 'pseudonym' and the 'signing_key'; - * the value stored here can then be given to GNUNET_FS_pseudonym_verify. - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_FS_pseudonym_derive_verification_key (struct GNUNET_FS_PseudonymIdentifier *pseudonym, - const struct GNUNET_HashCode *signing_key, - struct GNUNET_FS_PseudonymIdentifier *verification_key); - - -/** - * Verify a signature made with a pseudonym. - * - * @param purpose data that was signed - * @param signature signature to verify - * @param verification_key public key to use for checking the signature; - * corresponds to 'g^(x+h)' in section 2.4 of #2564. - * @return GNUNET_OK on success (signature valid, 'pseudonym' set), - * GNUNET_SYSERR if the signature is invalid - */ -int -GNUNET_FS_pseudonym_verify (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, - const struct GNUNET_FS_PseudonymSignature *signature, - const struct GNUNET_FS_PseudonymIdentifier *verification_key); - - -/** - * Get the identifier (public key) of a pseudonym. - * - * @param ph pseudonym handle with the private key - * @param pseudonym pseudonym identifier (set based on 'ph') - */ -void -GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph, - struct GNUNET_FS_PseudonymIdentifier *pseudonym); - - - /** * Iterator over all known pseudonyms. * * @param cls closure - * @param pseudonym hash code of public key of pseudonym + * @param pseudonym public key of pseudonym * @param name name of the pseudonym (might be NULL) * @param unique_name unique name of the pseudonym (might be NULL) * @param md meta data known about the pseudonym @@ -286,11 +104,11 @@ GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph, * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort */ typedef int (*GNUNET_FS_PseudonymIterator) (void *cls, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const char *unique_name, const struct GNUNET_CONTAINER_MetaData *md, - int32_t rating); + int32_t rating); /** @@ -303,7 +121,7 @@ typedef int (*GNUNET_FS_PseudonymIterator) (void *cls, */ int GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, int32_t delta); @@ -319,7 +137,7 @@ GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const struct GNUNET_CONTAINER_MetaData *meta); @@ -340,7 +158,7 @@ GNUNET_FS_pseudonym_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg, /** * Handle for a discovery callback registration. */ -struct GNUNET_FS_pseudonym_DiscoveryHandle; +struct GNUNET_FS_Pseudonym_DiscoveryHandle; /** @@ -352,7 +170,7 @@ struct GNUNET_FS_pseudonym_DiscoveryHandle; * @param iterator_cls closure for iterator * @return registration handle */ -struct GNUNET_FS_pseudonym_DiscoveryHandle * +struct GNUNET_FS_Pseudonym_DiscoveryHandle * GNUNET_FS_pseudonym_discovery_callback_register (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_FS_PseudonymIterator iterator, void *iterator_cls); @@ -364,7 +182,7 @@ GNUNET_FS_pseudonym_discovery_callback_register (const struct GNUNET_CONFIGURATI * @param dh registration to unregister */ void -GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_DiscoveryHandle *dh); +GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh); /** @@ -380,7 +198,7 @@ GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_Di */ char * GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, unsigned int *suffix); @@ -407,7 +225,7 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg */ int GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, struct GNUNET_CONTAINER_MetaData **ret_meta, int32_t *ret_rank, char **ret_name, @@ -425,7 +243,7 @@ GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, int GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *ns_uname, - struct GNUNET_FS_PseudonymIdentifier *pseudonym); + struct GNUNET_CRYPTO_EccPublicKey *pseudonym); /** @@ -442,24 +260,12 @@ GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, */ int GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *pseudonym, + const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, const char *name, const struct GNUNET_CONTAINER_MetaData *md, int32_t rank); -/** - * Remove pseudonym from the set of known pseudonyms. - * - * @param cfg overall configuration - * @param id the pseudonym identifier - * @return GNUNET_OK on success, GNUNET_SYSERR on failure - */ -int -GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, - const struct GNUNET_FS_PseudonymIdentifier *id); - - /** * Get a unique key from a URI. This is for putting URIs * into HashMaps. The key may change between FS implementations. @@ -468,7 +274,8 @@ GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param key wherer to store the unique key */ void -GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, struct GNUNET_HashCode * key); +GNUNET_FS_uri_to_key (const struct GNUNET_FS_Uri *uri, + struct GNUNET_HashCode *key); /** @@ -501,7 +308,8 @@ GNUNET_FS_uri_ksk_to_string_fancy (const struct GNUNET_FS_Uri *uri); * @param is_mandatory is this keyword mandatory? */ void -GNUNET_FS_uri_ksk_add_keyword (struct GNUNET_FS_Uri *uri, const char *keyword, +GNUNET_FS_uri_ksk_add_keyword (struct GNUNET_FS_Uri *uri, + const char *keyword, int is_mandatory); @@ -694,35 +502,16 @@ int GNUNET_FS_uri_test_sks (const struct GNUNET_FS_Uri *uri); -/** - * Handle to one of our namespaces. - */ -struct GNUNET_FS_Namespace; - - -/** - * Create an SKS URI from a namespace and an identifier. - * - * @param ns namespace - * @param id identifier - * @param emsg where to store an error message - * @return an FS URI for the given namespace and identifier - */ -struct GNUNET_FS_Uri * -GNUNET_FS_uri_sks_create (struct GNUNET_FS_Namespace *ns, const char *id, - char **emsg); - - /** * Create an SKS URI from a namespace ID and an identifier. * - * @param pseudonym pseudonym to use + * @param ns pseudonym to use * @param id identifier * @return an FS URI for the given namespace and identifier */ struct GNUNET_FS_Uri * -GNUNET_FS_uri_sks_create_from_nsid (struct GNUNET_FS_PseudonymIdentifier *pseudonym, - const char *id); +GNUNET_FS_uri_sks_create (const struct GNUNET_CRYPTO_EccPublicKey *ns, + const char *id); /** @@ -735,7 +524,7 @@ GNUNET_FS_uri_sks_create_from_nsid (struct GNUNET_FS_PseudonymIdentifier *pseudo */ int GNUNET_FS_uri_sks_get_namespace (const struct GNUNET_FS_Uri *uri, - struct GNUNET_FS_PseudonymIdentifier *pseudonym); + struct GNUNET_CRYPTO_EccPublicKey *pseudonym); /** @@ -1756,12 +1545,6 @@ struct GNUNET_FS_ProgressInfo struct { - /** - * Handle to the namespace (NULL if it is not a local - * namespace). - */ - struct GNUNET_FS_Namespace *ns; - /** * Short, human-readable name of the namespace. */ @@ -1780,7 +1563,7 @@ struct GNUNET_FS_ProgressInfo /** * Public key of the namespace. */ - struct GNUNET_FS_PseudonymIdentifier pseudonym; + struct GNUNET_CRYPTO_EccPublicKey pseudonym; } ns; @@ -2379,6 +2162,7 @@ enum GNUNET_FS_PublishOptions GNUNET_FS_PUBLISH_OPTION_SIMULATE_ONLY = 1 }; + /** * Publish a file or directory. * @@ -2395,7 +2179,8 @@ enum GNUNET_FS_PublishOptions struct GNUNET_FS_PublishContext * GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h, struct GNUNET_FS_FileInformation *fi, - struct GNUNET_FS_Namespace *ns, const char *nid, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, + const char *nid, const char *nuid, enum GNUNET_FS_PublishOptions options); @@ -2421,7 +2206,7 @@ GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc); * @param emsg error message, NULL on success */ typedef void (*GNUNET_FS_PublishContinuation) (void *cls, - const struct GNUNET_FS_Uri * uri, + const struct GNUNET_FS_Uri *uri, const char *emsg); @@ -2486,7 +2271,7 @@ struct GNUNET_FS_PublishSksContext; */ struct GNUNET_FS_PublishSksContext * GNUNET_FS_publish_sks (struct GNUNET_FS_Handle *h, - struct GNUNET_FS_Namespace *ns, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, const char *identifier, const char *update, const struct GNUNET_CONTAINER_MetaData *meta, const struct GNUNET_FS_Uri *uri, @@ -2567,110 +2352,6 @@ void GNUNET_FS_unindex_stop (struct GNUNET_FS_UnindexContext *uc); -/** - * Create a namespace with the given name; if one already - * exists, return a handle to the existing namespace. - * - * @param h handle to the file sharing subsystem - * @param name name to use for the namespace - * @return handle to the namespace, NULL on error (i.e. invalid filename) - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_create (struct GNUNET_FS_Handle *h, const char *name); - - -/** - * Open the namespace with the given name; if it does not exist, - * or the key file is corrupted, the function fails. - * - * @param h handle to the file sharing subsystem - * @param name name of the namespace - * @return handle to the namespace, - * NULL on error (i.e. invalid filename, non-existent filename) - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_open_existing (struct GNUNET_FS_Handle *h, const char *name); - - -/** - * Rename a local namespace. - * - * @param h handle to the file sharing subsystem - * @param old_name old name of the namespace - * @param new_name new name of the namespace - * @return GNUNET_OK on success, GNUNET_SYSERR on error (see errno for details) - */ -int -GNUNET_FS_namespace_rename (struct GNUNET_FS_Handle *h, - const char *old_name, - const char *new_name); - - -/** - * Duplicate a namespace handle. - * - * @param ns namespace handle - * @return duplicated handle to the namespace - */ -struct GNUNET_FS_Namespace * -GNUNET_FS_namespace_dup (struct GNUNET_FS_Namespace *ns); - - -/** - * Get hash of the public key of a namespace. - * - * @param ns namespace - * @param id buffer to store the key in - * @return GNUNET_OK on success - * GNUNET_SYSERR on failure (contents of id remain intact) - */ -int -GNUNET_FS_namespace_get_public_identifier (struct GNUNET_FS_Namespace *ns, - struct GNUNET_FS_PseudonymIdentifier *id); - - -/** - * Delete a namespace handle. Can be used for a clean shutdown (free - * memory) or also to freeze the namespace to prevent further - * insertions by anyone. - * - * @param ns handle to the namespace that should be deleted / freed - * @param freeze prevents future insertions; creating a namespace - * with the same name again will create a fresh namespace instead - * - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_FS_namespace_delete (struct GNUNET_FS_Namespace *ns, int freeze); - - -/** - * Callback with information about local (!) namespaces. - * Contains the names of the local namespace and the global - * ID. - * - * @param cls closure - * @param name human-readable identifier of the namespace - * @param id identifier for the namespace - */ -typedef void (*GNUNET_FS_NamespaceInfoProcessor) (void *cls, const char *name, - const struct GNUNET_FS_PseudonymIdentifier *id); - - -/** - * Build a list of all available local (!) namespaces The returned - * names are only the nicknames since we only iterate over the local - * namespaces. - * - * @param h handle to the file sharing subsystem - * @param cb function to call on each known namespace - * @param cb_cls closure for cb - */ -void -GNUNET_FS_namespace_list (struct GNUNET_FS_Handle *h, - GNUNET_FS_NamespaceInfoProcessor cb, void *cb_cls); - - /** * Function called on updateable identifiers. * @@ -2703,13 +2384,15 @@ typedef void (*GNUNET_FS_IdentifierProcessor) (void *cls, const char *last_id, * cause the library to call "ip" with all children of the node. Note * that cycles within an SCC are possible (including self-loops). * +* @param h fs handle to use * @param ns namespace to inspect for updateable content * @param next_id ID to look for; use NULL to look for SCC roots * @param ip function to call on each updateable identifier * @param ip_cls closure for ip */ void -GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Namespace *ns, +GNUNET_FS_namespace_list_updateable (struct GNUNET_FS_Handle *h, + const struct GNUNET_CRYPTO_EccPrivateKey *ns, const char *next_id, GNUNET_FS_IdentifierProcessor ip, void *ip_cls); diff --git a/src/include/gnunet_identity_service.h b/src/include/gnunet_identity_service.h index dfc643d22..23dee600f 100644 --- a/src/include/gnunet_identity_service.h +++ b/src/include/gnunet_identity_service.h @@ -74,7 +74,16 @@ struct GNUNET_IDENTITY_Operation; * @return associated ECC key, valid as long as the ego is valid */ const struct GNUNET_CRYPTO_EccPrivateKey * -GNUNET_IDENTITY_ego_get_private_key (struct GNUNET_IDENTITY_Ego *ego); +GNUNET_IDENTITY_ego_get_private_key (const struct GNUNET_IDENTITY_Ego *ego); + + +/** + * Obtain the ego representing 'anonymous' users. + * + * @returns handle for the anonymous user, must not be freed + */ +const struct GNUNET_IDENTITY_Ego * +GNUNET_IDENTITY_ego_get_anonymous (void); /** @@ -84,7 +93,7 @@ GNUNET_IDENTITY_ego_get_private_key (struct GNUNET_IDENTITY_Ego *ego); * @param pk set to ego's public key */ void -GNUNET_IDENTITY_ego_get_public_key (struct GNUNET_IDENTITY_Ego *ego, +GNUNET_IDENTITY_ego_get_public_key (const struct GNUNET_IDENTITY_Ego *ego, struct GNUNET_CRYPTO_EccPublicKey *pk); diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index a93512e38..122c1857d 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c @@ -445,6 +445,31 @@ GNUNET_CRYPTO_ecc_key_create () } +/** + * Get the shared private key we use for anonymous users. + * + * @return "anonymous" private key + */ +const struct GNUNET_CRYPTO_EccPrivateKey * +GNUNET_CRYPTO_ecc_key_get_anonymous () +{ + /** + * 'anonymous' pseudonym (global static, d=1, public key = G + * (generator). + */ + static struct GNUNET_CRYPTO_EccPrivateKey anonymous; + static int once; + + if (once) + return &anonymous; + mpi_print (anonymous.d, + sizeof (anonymous.d), + GCRYMPI_CONST_ONE); + once = 1; + return &anonymous; +} + + /** * Wait for a short time (we're trying to lock a file or want * to give another process a shot at finishing a disk write, etc.). -- cgit v1.2.3