2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 2, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
21 * @file fs/fs_pseudonym.c
22 * @brief pseudonym functions
23 * @author Christian Grothoff
26 * - all cryptographic operations are currently NOT implemented and
27 * provided by stubs that merely pretend to work!
30 #include "gnunet_util_lib.h"
31 #include "gnunet_fs_service.h"
35 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
37 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
39 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
42 * Log an error message at log-level 'level' that indicates
43 * a failure of the command 'cmd' with the message given
44 * by gcry_strerror(rc).
46 #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);
49 * Name of the directory which stores meta data for pseudonym
51 #define PS_METADATA_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "metadata" DIR_SEPARATOR_STR
54 * Name of the directory which stores names for pseudonyms
56 #define PS_NAMES_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "names" DIR_SEPARATOR_STR
60 * Configuration section we use.
62 #define GNUNET_CLIENT_SERVICE_NAME "fs"
65 /* ************************* Disk operations (pseudonym data mgmt) **************** */
68 * Registered callbacks for discovery of pseudonyms.
70 struct GNUNET_FS_pseudonym_DiscoveryHandle
73 * This is a doubly linked list.
75 struct GNUNET_FS_pseudonym_DiscoveryHandle *next;
78 * This is a doubly linked list.
80 struct GNUNET_FS_pseudonym_DiscoveryHandle *prev;
83 * Function to call each time a pseudonym is discovered.
85 GNUNET_FS_PseudonymIterator callback;
88 * Closure for callback.
95 * Head of the linked list of functions to call when
96 * new pseudonyms are added.
98 static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_head;
101 * Tail of the linked list of functions to call when
102 * new pseudonyms are added.
104 static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_tail;
107 * Pointer to indiate 'anonymous' pseudonym (global static, all
108 * zeros). We actually use pointer comparisson to detect the
109 * "anonymous" pseudonym handle.
111 static struct GNUNET_FS_PseudonymHandle anonymous;
114 * Internal notification about new tracked URI.
116 * @param pseudonym public key of the pseudonym
117 * @param md meta data to be written
118 * @param rating rating of pseudonym
121 internal_notify (const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
122 const struct GNUNET_CONTAINER_MetaData *md, int rating)
124 struct GNUNET_FS_pseudonym_DiscoveryHandle *pos;
126 for (pos = disco_head; NULL != pos; pos = pos->next)
127 pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating);
132 * Register callback to be invoked whenever we discover
134 * Will immediately call provided iterator callback for all
135 * already discovered pseudonyms.
137 * @param cfg configuration to use
138 * @param iterator iterator over pseudonym
139 * @param iterator_cls point to a closure
140 * @return registration handle
142 struct GNUNET_FS_pseudonym_DiscoveryHandle *
143 GNUNET_FS_pseudonym_discovery_callback_register (const struct
144 GNUNET_CONFIGURATION_Handle *cfg,
145 GNUNET_FS_PseudonymIterator iterator,
148 struct GNUNET_FS_pseudonym_DiscoveryHandle *dh;
150 dh = GNUNET_malloc (sizeof (struct GNUNET_FS_pseudonym_DiscoveryHandle));
151 dh->callback = iterator;
152 dh->callback_cls = iterator_cls;
153 GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh);
154 GNUNET_FS_pseudonym_list_all (cfg, iterator, iterator_cls);
160 * Unregister pseudonym discovery callback.
162 * @param dh registration to unregister
165 GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_DiscoveryHandle *dh)
167 GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh);
173 * Get the filename (or directory name) for the given
174 * pseudonym identifier and directory prefix.
176 * @param cfg configuration to use
177 * @param prefix path components to append to the private directory name
178 * @param pseudonym the pseudonym, can be NULL
179 * @return filename of the pseudonym (if pseudonym != NULL) or directory with the data (if pseudonym == NULL)
182 get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
184 const struct GNUNET_FS_PseudonymIdentifier *pseudonym)
186 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
187 struct GNUNET_HashCode psid;
189 if (NULL != pseudonym)
191 GNUNET_CRYPTO_hash (pseudonym,
192 sizeof (struct GNUNET_FS_PseudonymIdentifier),
194 GNUNET_CRYPTO_hash_to_enc (&psid, &enc);
196 return GNUNET_DISK_get_home_filename (cfg,
197 GNUNET_CLIENT_SERVICE_NAME, prefix,
200 : (const char *) &enc,
206 * Get the filename (or directory name) for the given
207 * hash code and directory prefix.
209 * @param cfg configuration to use
210 * @param prefix path components to append to the private directory name
211 * @param hc some hash code
212 * @return filename of the pseudonym (if hc != NULL) or directory with the data (if hc == NULL)
215 get_data_filename_hash (const struct GNUNET_CONFIGURATION_Handle *cfg,
217 const struct GNUNET_HashCode *hc)
219 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
222 GNUNET_CRYPTO_hash_to_enc (hc, &enc);
223 return GNUNET_DISK_get_home_filename (cfg,
224 GNUNET_CLIENT_SERVICE_NAME, prefix,
227 : (const char *) &enc,
233 * Set the pseudonym metadata, rank and name.
234 * Writes the pseudonym infomation into a file
236 * @param cfg overall configuration
237 * @param pseudonym id of the pseudonym
238 * @param name name to set. Must be the non-unique version of it.
239 * May be NULL, in which case it erases pseudonym's name!
240 * @param md metadata to set
241 * May be NULL, in which case it erases pseudonym's metadata!
242 * @param rank rank to assign
243 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
246 GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
247 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
249 const struct GNUNET_CONTAINER_MetaData *md,
253 struct GNUNET_BIO_WriteHandle *fileW;
255 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
256 if (NULL == (fileW = GNUNET_BIO_write_open (fn)))
259 return GNUNET_SYSERR;
261 if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym,
262 sizeof (struct GNUNET_FS_PseudonymIdentifier))) ||
263 (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) ||
264 (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) ||
265 (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md)))
267 (void) GNUNET_BIO_write_close (fileW);
268 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
270 return GNUNET_SYSERR;
272 if (GNUNET_OK != GNUNET_BIO_write_close (fileW))
274 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
276 return GNUNET_SYSERR;
279 /* create entry for pseudonym name in names */
281 GNUNET_free_non_null (GNUNET_FS_pseudonym_name_uniquify (cfg, pseudonym,
288 * Read pseudonym infomation from a file
290 * @param cfg configuration to use
291 * @param pseudonym hash code of a pseudonym
292 * @param meta meta data to be read from a file
293 * @param rank rank of a pseudonym
294 * @param ns_name name of a pseudonym
295 * @return GNUNET_OK on success, GNUNET_SYSERR on error
298 read_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
299 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
300 struct GNUNET_CONTAINER_MetaData **meta,
304 struct GNUNET_FS_PseudonymIdentifier pd;
307 struct GNUNET_BIO_ReadHandle *fileR;
309 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
311 GNUNET_DISK_file_test (fn))
314 return GNUNET_SYSERR;
316 if (NULL == (fileR = GNUNET_BIO_read_open (fn)))
319 return GNUNET_SYSERR;
323 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
324 (0 != memcmp (&pd, pseudonym, sizeof (pd))) ||
325 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, rank)) ||
327 GNUNET_BIO_read_string (fileR, "Read string error!", ns_name, 200)) ||
329 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", meta)) )
331 (void) GNUNET_BIO_read_close (fileR, &emsg);
332 GNUNET_free_non_null (emsg);
333 GNUNET_free_non_null (*ns_name);
335 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
337 return GNUNET_SYSERR;
339 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
341 LOG (GNUNET_ERROR_TYPE_WARNING,
342 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fn,
344 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
345 GNUNET_CONTAINER_meta_data_destroy (*meta);
347 GNUNET_free_non_null (*ns_name);
349 GNUNET_free_non_null (emsg);
351 return GNUNET_SYSERR;
359 * Return unique variant of the namespace name. Use it after
360 * GNUNET_FS_pseudonym_get_info() to make sure that name is unique.
362 * @param cfg configuration
363 * @param pseudonym public key of the pseudonym
364 * @param name name to uniquify
365 * @param suffix if not NULL, filled with the suffix value
366 * @return NULL on failure (should never happen), name on success.
367 * Free the name with GNUNET_free().
370 GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg,
371 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
373 unsigned int *suffix)
375 struct GNUNET_HashCode nh;
376 struct GNUNET_FS_PseudonymIdentifier pi;
379 struct GNUNET_DISK_FileHandle *fh;
385 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
386 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
388 if (0 == STAT (fn, &sbuf))
389 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES));
390 fh = GNUNET_DISK_file_open (fn,
391 GNUNET_DISK_OPEN_CREATE |
392 GNUNET_DISK_OPEN_READWRITE,
393 GNUNET_DISK_PERM_USER_READ |
394 GNUNET_DISK_PERM_USER_WRITE);
397 while ((len >= sizeof (struct GNUNET_FS_PseudonymIdentifier)) &&
398 (sizeof (struct GNUNET_FS_PseudonymIdentifier) ==
399 GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_FS_PseudonymIdentifier))))
401 if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier)))
407 len -= sizeof (struct GNUNET_HashCode);
412 if (sizeof (struct GNUNET_FS_PseudonymIdentifier) !=
413 GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier)))
414 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn);
416 GNUNET_DISK_file_close (fh);
417 ret = GNUNET_malloc (strlen (name) + 32);
418 GNUNET_snprintf (ret, strlen (name) + 32, "%s-%u", name, idx);
427 * Get namespace name, metadata and rank
428 * This is a wrapper around internal read_info() call, and ensures that
429 * returned data is not invalid (not NULL).
431 * @param cfg configuration
432 * @param pseudonym public key of the pseudonym
433 * @param ret_meta a location to store metadata pointer. NULL, if metadata
434 * is not needed. Destroy with GNUNET_CONTAINER_meta_data_destroy().
435 * @param ret_rank a location to store rank. NULL, if rank not needed.
436 * @param ret_name a location to store human-readable name. Name is not unique.
437 * NULL, if name is not needed. Free with GNUNET_free().
438 * @param name_is_a_dup is set to GNUNET_YES, if ret_name was filled with
439 * a duplicate of a "no-name" placeholder
440 * @return GNUNET_OK on success. GNUENT_SYSERR if the data was
441 * unobtainable (in that case ret_* are filled with placeholders -
442 * empty metadata container, rank -1 and a "no-name" name).
445 GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
446 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
447 struct GNUNET_CONTAINER_MetaData **ret_meta,
452 struct GNUNET_CONTAINER_MetaData *meta;
458 if (GNUNET_OK == read_info (cfg, pseudonym, &meta, &rank, &name))
460 if ((meta != NULL) && (name == NULL))
462 GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
463 EXTRACTOR_METATYPE_TITLE,
464 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
465 EXTRACTOR_METATYPE_FILENAME,
466 EXTRACTOR_METATYPE_DESCRIPTION,
467 EXTRACTOR_METATYPE_SUBJECT,
468 EXTRACTOR_METATYPE_PUBLISHER,
469 EXTRACTOR_METATYPE_AUTHOR_NAME,
470 EXTRACTOR_METATYPE_COMMENT,
471 EXTRACTOR_METATYPE_SUMMARY,
473 if (ret_name != NULL)
477 name = GNUNET_strdup (_("no-name"));
478 if (name_is_a_dup != NULL)
479 *name_is_a_dup = GNUNET_YES;
481 else if (name_is_a_dup != NULL)
482 *name_is_a_dup = GNUNET_NO;
485 else if (name != NULL)
488 if (ret_meta != NULL)
491 meta = GNUNET_CONTAINER_meta_data_create ();
494 else if (meta != NULL)
495 GNUNET_CONTAINER_meta_data_destroy (meta);
497 if (ret_rank != NULL)
502 if (ret_name != NULL)
503 *ret_name = GNUNET_strdup (_("no-name"));
504 if (ret_meta != NULL)
505 *ret_meta = GNUNET_CONTAINER_meta_data_create ();
506 if (ret_rank != NULL)
508 if (name_is_a_dup != NULL)
509 *name_is_a_dup = GNUNET_YES;
510 return GNUNET_SYSERR;
515 * Get the namespace ID belonging to the given namespace name.
517 * @param cfg configuration to use
518 * @param ns_uname unique (!) human-readable name for the namespace
519 * @param pseudonym set to public key of pseudonym based on 'ns_uname'
520 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
523 GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg,
524 const char *ns_uname,
525 struct GNUNET_FS_PseudonymIdentifier *pseudonym)
531 struct GNUNET_HashCode nh;
533 struct GNUNET_DISK_FileHandle *fh;
536 slen = strlen (ns_uname);
537 while ((slen > 0) && (1 != SSCANF (&ns_uname[slen - 1], "-%u", &idx)))
540 return GNUNET_SYSERR;
541 name = GNUNET_strdup (ns_uname);
542 name[slen - 1] = '\0';
544 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
546 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
548 if ((GNUNET_OK != GNUNET_DISK_file_test (fn) ||
549 (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) ||
550 ((idx + 1) * sizeof (struct GNUNET_FS_PseudonymIdentifier) > len))
553 return GNUNET_SYSERR;
555 fh = GNUNET_DISK_file_open (fn,
556 GNUNET_DISK_OPEN_CREATE |
557 GNUNET_DISK_OPEN_READWRITE,
558 GNUNET_DISK_PERM_USER_READ |
559 GNUNET_DISK_PERM_USER_WRITE);
562 GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_FS_PseudonymIdentifier),
563 GNUNET_DISK_SEEK_SET))
565 GNUNET_DISK_file_close (fh);
566 return GNUNET_SYSERR;
568 if (sizeof (struct GNUNET_FS_PseudonymIdentifier) !=
569 GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier)))
571 GNUNET_DISK_file_close (fh);
572 return GNUNET_SYSERR;
574 GNUNET_DISK_file_close (fh);
581 * struct used to list the pseudonym
583 struct ListPseudonymClosure
587 * iterator over pseudonym
589 GNUNET_FS_PseudonymIterator iterator;
592 * Closure for iterator.
597 * Configuration to use.
599 const struct GNUNET_CONFIGURATION_Handle *cfg;
605 * Helper function to list all available pseudonyms
607 * @param cls point to a struct ListPseudonymClosure
608 * @param fullname name of pseudonym
611 list_pseudonym_helper (void *cls, const char *fullname)
613 struct ListPseudonymClosure *lpc = cls;
614 struct GNUNET_FS_PseudonymIdentifier pd;
616 struct GNUNET_BIO_ReadHandle *fileR;
619 struct GNUNET_CONTAINER_MetaData *meta;
623 if (NULL == (fileR = GNUNET_BIO_read_open (fullname)))
624 return GNUNET_SYSERR;
627 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
628 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, &rank)) ||
630 GNUNET_BIO_read_string (fileR, "Read string error!", &ns_name, 200)) ||
632 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", &meta)) )
634 (void) GNUNET_BIO_read_close (fileR, &emsg);
635 GNUNET_free_non_null (emsg);
636 GNUNET_free_non_null (ns_name);
637 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
638 return GNUNET_SYSERR;
641 ns_name = GNUNET_strdup (_("no-name"));
642 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
644 LOG (GNUNET_ERROR_TYPE_WARNING,
645 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fullname,
647 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
648 GNUNET_CONTAINER_meta_data_destroy (meta);
649 GNUNET_free (ns_name);
650 GNUNET_free_non_null (emsg);
651 return GNUNET_SYSERR;
654 name_unique = GNUNET_FS_pseudonym_name_uniquify (lpc->cfg, &pd, ns_name, NULL);
655 if (NULL != lpc->iterator)
656 ret = lpc->iterator (lpc->iterator_cls, &pd, ns_name, name_unique, meta, rank);
657 GNUNET_free (ns_name);
658 GNUNET_free_non_null (name_unique);
659 GNUNET_CONTAINER_meta_data_destroy (meta);
665 * List all available pseudonyms.
667 * @param cfg overall configuration
668 * @param iterator function to call for each pseudonym
669 * @param iterator_cls closure for iterator
670 * @return number of pseudonyms found
673 GNUNET_FS_pseudonym_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg,
674 GNUNET_FS_PseudonymIterator iterator,
677 struct ListPseudonymClosure cls;
681 cls.iterator = iterator;
682 cls.iterator_cls = iterator_cls;
684 fn = get_data_filename (cfg, PS_METADATA_DIR, NULL);
685 GNUNET_assert (fn != NULL);
686 GNUNET_DISK_directory_create (fn);
687 ret = GNUNET_DISK_directory_scan (fn, &list_pseudonym_helper, &cls);
694 * Change the rank of a pseudonym.
696 * @param cfg overall configuration
697 * @param pseudonym the pseudonym
698 * @param delta by how much should the rating be changed?
699 * @return new rating of the pseudonym
702 GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg,
703 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
706 struct GNUNET_CONTAINER_MetaData *meta;
712 ret = read_info (cfg, pseudonym, &meta, &rank, &name);
713 if (ret == GNUNET_SYSERR)
716 meta = GNUNET_CONTAINER_meta_data_create ();
719 GNUNET_FS_pseudonym_set_info (cfg, pseudonym, name, meta, rank);
720 GNUNET_CONTAINER_meta_data_destroy (meta);
721 GNUNET_free_non_null (name);
727 * Add a pseudonym to the set of known pseudonyms.
728 * For all pseudonym advertisements that we discover
729 * FS should automatically call this function.
731 * @param cfg overall configuration
732 * @param pseudonym the pseudonym to add
733 * @param meta metadata for the pseudonym
734 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
737 GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg,
738 const struct GNUNET_FS_PseudonymIdentifier *pseudonym,
739 const struct GNUNET_CONTAINER_MetaData *meta)
743 struct GNUNET_CONTAINER_MetaData *old;
749 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
750 GNUNET_assert (fn != NULL);
752 if ((0 == STAT (fn, &sbuf)) &&
753 (GNUNET_OK == read_info (cfg, pseudonym, &old, &rank, &name)))
755 GNUNET_CONTAINER_meta_data_merge (old, meta);
756 ret = GNUNET_FS_pseudonym_set_info (cfg, pseudonym, name, old, rank);
757 GNUNET_CONTAINER_meta_data_destroy (old);
758 GNUNET_free_non_null (name);
762 ret = GNUNET_FS_pseudonym_set_info (cfg, pseudonym, NULL, meta, rank);
765 internal_notify (pseudonym, meta, rank);
770 /* ***************************** cryptographic operations ************************* */
773 * Handle for a pseudonym (private key).
775 struct GNUNET_FS_PseudonymHandle
778 * 256-bit 'd' secret value (mod 'n', where n is 256-bit for NIST P-256).
780 unsigned char d[256 / 8];
783 * Public key corresponding to the private key.
785 struct GNUNET_FS_PseudonymIdentifier public_key;
790 * If target != size, move target bytes to the end of the size-sized
791 * buffer and zero out the first target-size bytes.
793 * @param buf original buffer
794 * @param size number of bytes in the buffer
795 * @param target target size of the buffer
798 adjust (unsigned char *buf, size_t size, size_t target)
802 memmove (&buf[target - size], buf, size);
803 memset (buf, 0, target - size);
809 * Extract values from an S-expression.
811 * @param array where to store the result(s)
812 * @param sexp S-expression to parse
813 * @param topname top-level name in the S-expression that is of interest
814 * @param elems names of the elements to extract
815 * @return 0 on success
818 key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
827 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
829 l2 = gcry_sexp_cadr (list);
830 gcry_sexp_release (list);
835 for (s = elems; *s; s++, idx++)
837 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
839 for (i = 0; i < idx; i++)
841 gcry_free (array[i]);
844 gcry_sexp_release (list);
845 return 3; /* required parameter not found */
847 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
848 gcry_sexp_release (l2);
851 for (i = 0; i < idx; i++)
853 gcry_free (array[i]);
856 gcry_sexp_release (list);
857 return 4; /* required parameter is invalid */
860 gcry_sexp_release (list);
866 * Create a pseudonym.
868 * @param filename name of the file to use for storage, NULL for in-memory only
869 * @return handle to the private key of the pseudonym
871 struct GNUNET_FS_PseudonymHandle *
872 GNUNET_FS_pseudonym_create (const char *filename)
874 struct GNUNET_FS_PseudonymHandle *ph;
886 ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle));
887 if ( (NULL != filename) &&
888 (GNUNET_YES == GNUNET_DISK_file_test (filename)) )
890 ret = GNUNET_DISK_fn_read (filename, ph,
891 sizeof (struct GNUNET_FS_PseudonymHandle));
892 /* Note: we don't do any validation here, maybe we should? */
893 if (sizeof (struct GNUNET_FS_PseudonymHandle) == ret)
896 if (0 != (rc = gcry_sexp_build (¶ms, NULL,
897 "(genkey(ecdsa(curve \"NIST P-256\")))")))
899 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
902 if (0 != (rc = gcry_pk_genkey (&r_key, params)))
904 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
905 gcry_sexp_release (params);
906 gcry_sexp_release (r_key);
909 gcry_sexp_release (params);
910 /* extract "d" (secret key) from r_key */
911 rc = key_from_sexp (&d, r_key, "private-key", "d");
913 rc = key_from_sexp (&d, r_key, "private-key", "d");
915 rc = key_from_sexp (&d, r_key, "ecc", "d");
918 gcry_sexp_release (r_key);
919 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
922 size = sizeof (ph->d);
924 gcry_mpi_print (GCRYMPI_FMT_USG, ph->d, size, &size,
926 gcry_mpi_release (d);
927 adjust (ph->d, size, sizeof (ph->d));
929 /* extract 'q' (public key) from r_key */
930 if (0 != (rc = gcry_mpi_ec_new (&ctx, r_key, NULL)))
932 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
933 gcry_sexp_release (r_key);
936 gcry_sexp_release (r_key);
937 q = gcry_mpi_ec_get_point ("q", ctx, 0);
938 q_x = gcry_mpi_new (256);
939 q_y = gcry_mpi_new (256);
940 gcry_mpi_ec_get_affine (q_x, q_y, q, ctx);
941 gcry_mpi_point_release (q);
942 gcry_ctx_release (ctx);
944 /* store q_x/q_y in public key */
945 size = sizeof (ph->public_key.q_x);
947 gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_x, size, &size,
950 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
951 gcry_mpi_release (q_x);
952 gcry_mpi_release (q_y);
956 adjust (ph->public_key.q_x, size, sizeof (ph->public_key.q_x));
957 gcry_mpi_release (q_x);
959 size = sizeof (ph->public_key.q_y);
961 gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_y, size, &size,
964 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
965 gcry_mpi_release (q_y);
968 adjust (ph->public_key.q_y, size, sizeof (ph->public_key.q_y));
969 gcry_mpi_release (q_y);
972 if (NULL != filename)
974 ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_FS_PseudonymHandle),
975 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
976 if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret)
987 * Create a pseudonym, from a file that must already exist.
989 * @param filename name of the file to use for storage, NULL for in-memory only
990 * @return handle to the private key of the pseudonym
992 struct GNUNET_FS_PseudonymHandle *
993 GNUNET_FS_pseudonym_create_from_existing_file (const char *filename)
995 struct GNUNET_FS_PseudonymHandle *ph;
998 ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle));
999 ret = GNUNET_DISK_fn_read (filename, ph,
1000 sizeof (struct GNUNET_FS_PseudonymHandle));
1001 if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret)
1006 /* Note: we don't do any validation here; maybe we should? */
1012 * Get the handle for the 'anonymous' pseudonym shared by all users.
1013 * That pseudonym uses a fixed 'secret' for the private key; this
1014 * construction is useful to make anonymous and pseudonymous APIs
1015 * (and packets) indistinguishable on the network. See #2564.
1017 * @return handle to the (non-secret) private key of the 'anonymous' pseudonym
1019 struct GNUNET_FS_PseudonymHandle *
1020 GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle ()
1027 * Destroy a pseudonym handle. Does NOT remove the private key from
1030 * @param ph pseudonym handle to destroy
1033 GNUNET_FS_pseudonym_destroy (struct GNUNET_FS_PseudonymHandle *ph)
1035 if (&anonymous != ph)
1041 * Convert the data specified in the given purpose argument to an
1042 * S-expression suitable for signature operations.
1044 * @param purpose data to convert
1045 * @return converted s-expression
1048 data_to_pkcs1 (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose)
1050 struct GNUNET_CRYPTO_ShortHashCode hc;
1054 GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc);
1055 #define FORMATSTRING "(4:data(5:flags3:raw)(5:value32:01234567890123456789012345678901))"
1056 bufSize = strlen (FORMATSTRING) + 1;
1060 memcpy (buff, FORMATSTRING, bufSize);
1064 ("01234567890123456789012345678901))")
1065 - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
1066 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1074 * Cryptographically sign some data with the pseudonym.
1076 * @param ph private key 'd' used for signing (corresponds to 'x' in #2564)
1077 * @param purpose data to sign
1078 * @param seed hash of the plaintext of the data that we are signing,
1079 * used for deterministic PRNG for anonymous signing;
1080 * corresponds to 'k' in section 2.7 of #2564
1081 * @param signing_key modifier to apply to the private key for signing ('h');
1082 * see section 2.3 of #2564.
1083 * @param signature where to store the signature
1084 * @return GNUNET_SYSERR on failure
1087 GNUNET_FS_pseudonym_sign (struct GNUNET_FS_PseudonymHandle *ph,
1088 const struct GNUNET_FS_PseudonymSignaturePurpose *purpose,
1089 const struct GNUNET_HashCode *seed,
1090 const struct GNUNET_HashCode *signing_key,
1091 struct GNUNET_FS_PseudonymSignature *signature)
1099 gcry_mpi_t n; /* n from P-256 */
1106 /* get private key 'd' from pseudonym */
1107 if (&anonymous == ph)
1109 d = gcry_mpi_new (0);
1110 gcry_mpi_set_ui (d, 0);
1114 size = sizeof (ph->d);
1115 if (0 != (rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
1119 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1120 return GNUNET_SYSERR;
1123 /* get 'x' value from signing key */
1124 size = sizeof (struct GNUNET_HashCode);
1125 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1129 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1130 gcry_mpi_release (d);
1131 return GNUNET_SYSERR;
1134 /* initialize 'n' from P-256; hex copied from libgcrypt code */
1135 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX,
1136 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL)))
1138 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1139 gcry_mpi_release (d);
1140 gcry_mpi_release (h);
1141 return GNUNET_SYSERR;
1144 /* calculate dx = d + h mod n */
1145 dh = gcry_mpi_new (256);
1146 gcry_mpi_addm (dh, d, h, n);
1147 gcry_mpi_release (d);
1148 gcry_mpi_release (h);
1149 gcry_mpi_release (n);
1151 /* now build sexpression with the signing key */
1152 if (0 != (rc = gcry_sexp_build (&spriv, &erroff,
1153 "(private-key(ecdsa(curve \"NIST P-256\")(d %m)))",
1156 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1157 gcry_mpi_release (dh);
1158 return GNUNET_SYSERR;
1160 gcry_mpi_release (dh);
1161 /* prepare data for signing */
1162 data = data_to_pkcs1 (purpose);
1164 /* get 'k' value from seed, if available */
1167 size = sizeof (struct GNUNET_HashCode);
1168 if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG,
1172 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1173 return GNUNET_SYSERR;
1177 /* actually create signature */
1178 /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */
1179 if (0 != (rc = gcry_pk_sign (&result, data, spriv)))
1181 LOG (GNUNET_ERROR_TYPE_WARNING,
1182 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1183 __LINE__, gcry_strerror (rc));
1184 gcry_sexp_release (data);
1185 gcry_sexp_release (spriv);
1187 gcry_mpi_release (k);
1188 memset (signature, 0, sizeof (struct GNUNET_FS_PseudonymSignature));
1189 return GNUNET_SYSERR;
1192 gcry_mpi_release (k);
1193 gcry_sexp_release (data);
1194 gcry_sexp_release (spriv);
1197 /* extract 'r' and 's' values from sexpression 'result' and store in 'signature' */
1198 if (0 != (rc = key_from_sexp (rs, result, "sig-val", "rs")))
1201 gcry_sexp_release (result);
1202 return GNUNET_SYSERR;
1204 gcry_sexp_release (result);
1205 size = sizeof (signature->sig_r);
1206 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_r, size,
1209 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1210 gcry_mpi_release (rs[0]);
1211 gcry_mpi_release (rs[1]);
1212 return GNUNET_SYSERR;
1214 adjust (signature->sig_r, size, sizeof (signature->sig_r));
1215 gcry_mpi_release (rs[0]);
1217 size = sizeof (signature->sig_s);
1218 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_s, size,
1221 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1222 gcry_mpi_release (rs[1]);
1223 return GNUNET_SYSERR;
1225 adjust (signature->sig_s, size, sizeof (signature->sig_s));
1226 gcry_mpi_release (rs[1]);
1230 struct GNUNET_FS_PseudonymIdentifier vk;
1231 struct GNUNET_FS_PseudonymIdentifier pi;
1233 GNUNET_FS_pseudonym_get_identifier (ph, &pi);
1234 GNUNET_assert (GNUNET_OK ==
1235 GNUNET_FS_pseudonym_derive_verification_key (&pi, signing_key, &vk));
1236 GNUNET_assert (GNUNET_OK ==
1237 GNUNET_FS_pseudonym_verify (purpose,
1243 GNUNET_FS_pseudonym_get_identifier (ph, &signature->signer);
1249 * Get an ECC context (with Q set to the respective public key) from
1252 * @param pseudonym with information on 'q'
1253 * @return curve context
1256 get_context_from_pseudonym (struct GNUNET_FS_PseudonymIdentifier *pseudonym)
1258 static struct GNUNET_FS_PseudonymIdentifier zerop;
1267 /* extract 'q' from pseudonym */
1268 if (0 == memcmp (pseudonym, &zerop, sizeof (zerop)))
1270 /* create basic ECC context */
1271 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1273 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1276 /* initialize 'ctx' with 'q' = 0 */
1277 zero = gcry_mpi_new (0);
1278 gcry_mpi_set_ui (zero, 0);
1279 q = gcry_mpi_point_new (0);
1280 gcry_mpi_point_set (q, zero, zero, zero);
1281 gcry_mpi_ec_set_point ("q", q, ctx);
1282 gcry_mpi_release (zero);
1283 gcry_mpi_point_release (q);
1286 size = sizeof (pseudonym->q_x);
1287 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, pseudonym->q_x, size, &size)))
1289 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1292 size = sizeof (pseudonym->q_y);
1293 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, pseudonym->q_y, size, &size)))
1295 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1296 gcry_mpi_release (q_x);
1299 q = gcry_mpi_point_new (256);
1300 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1301 gcry_mpi_release (q_x);
1302 gcry_mpi_release (q_y);
1304 /* create basic ECC context */
1305 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1307 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1308 gcry_mpi_point_release (q);
1311 /* initialize 'ctx' with 'q' */
1312 gcry_mpi_ec_set_point ("q", q, ctx);
1313 gcry_mpi_point_release (q);
1319 * Given a pseudonym and a signing key, derive the corresponding public
1320 * key that would be used to verify the resulting signature.
1322 * @param pseudonym the public key (dQ in ECDSA)
1323 * @param signing_key input to derive 'h' (see section 2.4 of #2564)
1324 * @param verification_key resulting public key to verify the signature
1325 * created from the '(d+h)' of 'pseudonym' and the 'signing_key';
1326 * the value stored here can then be given to GNUNET_FS_pseudonym_verify.
1327 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1330 GNUNET_FS_pseudonym_derive_verification_key (struct GNUNET_FS_PseudonymIdentifier *pseudonym,
1331 const struct GNUNET_HashCode *signing_key,
1332 struct GNUNET_FS_PseudonymIdentifier *verification_key)
1340 gcry_mpi_point_t hg;
1345 /* get 'h' value from signing key */
1346 size = sizeof (struct GNUNET_HashCode);
1347 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1351 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1352 return GNUNET_SYSERR;
1354 /* create ECC context based on Q from pseudonym */
1355 if (NULL == (ctx = get_context_from_pseudonym (pseudonym)))
1357 gcry_mpi_release (h);
1358 return GNUNET_SYSERR;
1361 g = gcry_mpi_ec_get_point ("g", ctx, 0);
1363 /* then call the 'multiply' function, to compute the product hG */
1364 hg = gcry_mpi_point_new (0);
1365 gcry_mpi_ec_mul (hg, h, g, ctx);
1366 gcry_mpi_point_release (g);
1367 gcry_mpi_release (h);
1369 /* get Q = dG from 'pseudonym' */
1370 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1371 /* calculate V = Q + hG = dG + hG = (d + h)G*/
1372 v = gcry_mpi_point_new (0);
1373 gcry_mpi_ec_add (v, q, hg, ctx);
1374 gcry_mpi_point_release (hg);
1376 /* store 'v' point in "verification_key" */
1377 v_x = gcry_mpi_new (256);
1378 v_y = gcry_mpi_new (256);
1379 gcry_mpi_ec_get_affine (v_x, v_y, v, ctx);
1381 gcry_mpi_point_release (v);
1382 gcry_ctx_release (ctx);
1384 size = sizeof (verification_key->q_x);
1385 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_x, size,
1388 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1389 gcry_mpi_release (v_x);
1390 gcry_mpi_release (v_y);
1391 return GNUNET_SYSERR;
1393 gcry_mpi_release (v_x);
1394 size = sizeof (verification_key->q_y);
1395 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_y, size,
1398 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1399 gcry_mpi_release (v_y);
1400 return GNUNET_SYSERR;
1402 gcry_mpi_release (v_y);
1408 * Verify a signature made with a pseudonym.
1410 * @param purpose data that was signed
1411 * @param signature signature to verify
1412 * @param verification_key public key to use for checking the signature;
1413 * corresponds to 'g^(x+h)' in section 2.4 of #2564.
1414 * @return GNUNET_OK on success (signature valid, 'pseudonym' set),
1415 * GNUNET_SYSERR if the signature is invalid
1418 GNUNET_FS_pseudonym_verify (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose,
1419 const struct GNUNET_FS_PseudonymSignature *signature,
1420 const struct GNUNET_FS_PseudonymIdentifier *verification_key)
1423 gcry_sexp_t sig_sexpr;
1424 gcry_sexp_t pk_sexpr;
1435 /* build s-expression for signature */
1436 size = sizeof (signature->sig_r);
1437 if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG,
1438 signature->sig_r, size, &size)))
1440 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1441 return GNUNET_SYSERR;
1443 size = sizeof (signature->sig_s);
1444 if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG,
1445 signature->sig_s, size, &size)))
1447 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1448 gcry_mpi_release (r);
1449 return GNUNET_SYSERR;
1451 if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))",
1454 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1455 gcry_mpi_release (r);
1456 gcry_mpi_release (s);
1457 return GNUNET_SYSERR;
1459 gcry_mpi_release (r);
1460 gcry_mpi_release (s);
1463 /* build s-expression for data that was signed */
1464 data = data_to_pkcs1 (purpose);
1466 /* create context of public key and initialize Q */
1467 size = sizeof (verification_key->q_x);
1468 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG,
1469 verification_key->q_x, size, &size)))
1471 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1472 gcry_sexp_release (data);
1473 gcry_sexp_release (sig_sexpr);
1474 return GNUNET_SYSERR;
1476 size = sizeof (verification_key->q_y);
1477 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG,
1478 verification_key->q_y, size, &size)))
1480 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1481 gcry_sexp_release (data);
1482 gcry_sexp_release (sig_sexpr);
1483 gcry_mpi_release (q_x);
1484 return GNUNET_SYSERR;
1486 q = gcry_mpi_point_new (256);
1487 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1488 gcry_mpi_release (q_x);
1489 gcry_mpi_release (q_y);
1491 /* create basic ECC context */
1492 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1494 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1495 gcry_sexp_release (data);
1496 gcry_sexp_release (sig_sexpr);
1497 gcry_mpi_point_release (q);
1498 return GNUNET_SYSERR;
1500 /* initialize 'ctx' with 'q' */
1501 gcry_mpi_ec_set_point ("q", q, ctx);
1502 gcry_mpi_point_release (q);
1504 /* convert 'ctx' to 'sexp' */
1505 if (0 != (rc = gcry_pubkey_get_sexp (&pk_sexpr, GCRY_PK_GET_PUBKEY, ctx)))
1507 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc);
1508 gcry_ctx_release (ctx);
1509 gcry_sexp_release (data);
1510 gcry_sexp_release (sig_sexpr);
1511 return GNUNET_SYSERR;
1513 gcry_ctx_release (ctx);
1515 /* finally, verify the signature */
1516 rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr);
1517 gcry_sexp_release (sig_sexpr);
1518 gcry_sexp_release (data);
1519 gcry_sexp_release (pk_sexpr);
1522 LOG (GNUNET_ERROR_TYPE_WARNING,
1523 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1524 __LINE__, gcry_strerror (rc));
1525 return GNUNET_SYSERR;
1532 * Get the identifier (public key) of a pseudonym.
1534 * @param ph pseudonym handle with the private key
1535 * @param pseudonym pseudonym identifier (set based on 'ph')
1538 GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph,
1539 struct GNUNET_FS_PseudonymIdentifier *pseudonym)
1541 if (&anonymous == ph)
1542 memset (pseudonym, 0, sizeof (struct GNUNET_FS_PseudonymIdentifier));
1544 memcpy (pseudonym, &ph->public_key,
1545 sizeof (struct GNUNET_FS_PseudonymIdentifier));
1550 * Remove pseudonym from the set of known pseudonyms.
1552 * @param cfg overall configuration
1553 * @param id the pseudonym identifier
1554 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1557 GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg,
1558 const struct GNUNET_FS_PseudonymIdentifier *id)
1563 fn = get_data_filename (cfg, PS_METADATA_DIR, id);
1565 return GNUNET_SYSERR;
1566 result = UNLINK (fn);
1568 return (0 == result) ? GNUNET_OK : GNUNET_SYSERR;
1571 /* end of pseudonym.c */