2 This file is part of GNUnet
3 (C) 2003-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 3, 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 * @param rfc6979 GNUNET_YES if we are to use deterministic ECDSA
1046 * @return converted s-expression
1049 data_to_pkcs1 (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose,
1052 struct GNUNET_CRYPTO_ShortHashCode hc;
1058 GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc);
1061 if (0 != (rc = gcry_sexp_build (&data, NULL,
1062 "(data(flags rfc6979)(hash %s %b))",
1067 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1073 fmt = "(data(flags raw)(5:value32:01234567890123456789012345678901))";
1074 bufSize = strlen (fmt) + 1;
1078 memcpy (buff, fmt, bufSize);
1082 ("01234567890123456789012345678901))")
1083 - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
1084 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1092 * Cryptographically sign some data with the pseudonym.
1094 * @param ph private key 'd' used for signing (corresponds to 'x' in #2564)
1095 * @param purpose data to sign
1096 * @param seed hash of the plaintext of the data that we are signing,
1097 * used for deterministic PRNG for anonymous signing;
1098 * corresponds to 'k' in section 2.7 of #2564
1099 * @param signing_key modifier to apply to the private key for signing ('h');
1100 * see section 2.3 of #2564.
1101 * @param signature where to store the signature
1102 * @return GNUNET_SYSERR on failure
1105 GNUNET_FS_pseudonym_sign (struct GNUNET_FS_PseudonymHandle *ph,
1106 const struct GNUNET_FS_PseudonymSignaturePurpose *purpose,
1107 const struct GNUNET_HashCode *seed,
1108 const struct GNUNET_HashCode *signing_key,
1109 struct GNUNET_FS_PseudonymSignature *signature)
1117 gcry_mpi_t n; /* n from P-256 */
1124 /* get private key 'd' from pseudonym */
1125 if (&anonymous == ph)
1127 d = gcry_mpi_new (0);
1128 gcry_mpi_set_ui (d, 0);
1132 size = sizeof (ph->d);
1133 if (0 != (rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG,
1137 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1138 return GNUNET_SYSERR;
1141 /* get 'x' value from signing key */
1142 size = sizeof (struct GNUNET_HashCode);
1143 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1147 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1148 gcry_mpi_release (d);
1149 return GNUNET_SYSERR;
1152 /* initialize 'n' from P-256; hex copied from libgcrypt code */
1153 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX,
1154 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL)))
1156 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1157 gcry_mpi_release (d);
1158 gcry_mpi_release (h);
1159 return GNUNET_SYSERR;
1162 /* calculate dx = d + h mod n */
1163 dh = gcry_mpi_new (256);
1164 gcry_mpi_addm (dh, d, h, n);
1165 gcry_mpi_release (d);
1166 gcry_mpi_release (h);
1167 gcry_mpi_release (n);
1169 /* now build sexpression with the signing key */
1170 if (0 != (rc = gcry_sexp_build (&spriv, &erroff,
1171 "(private-key(ecdsa(curve \"NIST P-256\")(d %m)))",
1174 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1175 gcry_mpi_release (dh);
1176 return GNUNET_SYSERR;
1178 gcry_mpi_release (dh);
1179 /* prepare data for signing */
1180 data = data_to_pkcs1 (purpose, NULL != seed);
1183 gcry_sexp_release (spriv);
1184 return GNUNET_SYSERR;
1186 /* get 'k' value from seed, if available */
1189 size = sizeof (struct GNUNET_HashCode);
1190 if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG,
1194 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1195 gcry_sexp_release (spriv);
1196 gcry_sexp_release (data);
1197 return GNUNET_SYSERR;
1201 /* actually create signature */
1202 /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */
1203 if (0 != (rc = gcry_pk_sign (&result, data, spriv)))
1205 LOG (GNUNET_ERROR_TYPE_WARNING,
1206 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1207 __LINE__, gcry_strerror (rc));
1208 gcry_sexp_release (data);
1209 gcry_sexp_release (spriv);
1211 gcry_mpi_release (k);
1212 memset (signature, 0, sizeof (struct GNUNET_FS_PseudonymSignature));
1213 return GNUNET_SYSERR;
1216 gcry_mpi_release (k);
1217 gcry_sexp_release (data);
1218 gcry_sexp_release (spriv);
1221 /* extract 'r' and 's' values from sexpression 'result' and store in 'signature' */
1222 if (0 != (rc = key_from_sexp (rs, result, "sig-val", "rs")))
1225 gcry_sexp_release (result);
1226 return GNUNET_SYSERR;
1228 gcry_sexp_release (result);
1229 size = sizeof (signature->sig_r);
1230 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_r, size,
1233 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1234 gcry_mpi_release (rs[0]);
1235 gcry_mpi_release (rs[1]);
1236 return GNUNET_SYSERR;
1238 adjust (signature->sig_r, size, sizeof (signature->sig_r));
1239 gcry_mpi_release (rs[0]);
1241 size = sizeof (signature->sig_s);
1242 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_s, size,
1245 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1246 gcry_mpi_release (rs[1]);
1247 return GNUNET_SYSERR;
1249 adjust (signature->sig_s, size, sizeof (signature->sig_s));
1250 gcry_mpi_release (rs[1]);
1254 struct GNUNET_FS_PseudonymIdentifier vk;
1255 struct GNUNET_FS_PseudonymIdentifier pi;
1257 GNUNET_FS_pseudonym_get_identifier (ph, &pi);
1258 GNUNET_assert (GNUNET_OK ==
1259 GNUNET_FS_pseudonym_derive_verification_key (&pi, signing_key, &vk));
1260 GNUNET_assert (GNUNET_OK ==
1261 GNUNET_FS_pseudonym_verify (purpose,
1267 GNUNET_FS_pseudonym_get_identifier (ph, &signature->signer);
1273 * Get an ECC context (with Q set to the respective public key) from
1276 * @param pseudonym with information on 'q'
1277 * @return curve context
1280 get_context_from_pseudonym (struct GNUNET_FS_PseudonymIdentifier *pseudonym)
1282 static struct GNUNET_FS_PseudonymIdentifier zerop;
1291 /* extract 'q' from pseudonym */
1292 if (0 == memcmp (pseudonym, &zerop, sizeof (zerop)))
1294 /* create basic ECC context */
1295 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1297 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1300 /* initialize 'ctx' with 'q' = 0 */
1301 zero = gcry_mpi_new (0);
1302 gcry_mpi_set_ui (zero, 0);
1303 q = gcry_mpi_point_new (0);
1304 gcry_mpi_point_set (q, zero, zero, zero);
1305 gcry_mpi_ec_set_point ("q", q, ctx);
1306 gcry_mpi_release (zero);
1307 gcry_mpi_point_release (q);
1310 size = sizeof (pseudonym->q_x);
1311 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, pseudonym->q_x, size, &size)))
1313 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1316 size = sizeof (pseudonym->q_y);
1317 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, pseudonym->q_y, size, &size)))
1319 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1320 gcry_mpi_release (q_x);
1323 q = gcry_mpi_point_new (256);
1324 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1325 gcry_mpi_release (q_x);
1326 gcry_mpi_release (q_y);
1328 /* create basic ECC context */
1329 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1331 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1332 gcry_mpi_point_release (q);
1335 /* initialize 'ctx' with 'q' */
1336 gcry_mpi_ec_set_point ("q", q, ctx);
1337 gcry_mpi_point_release (q);
1343 * Given a pseudonym and a signing key, derive the corresponding public
1344 * key that would be used to verify the resulting signature.
1346 * @param pseudonym the public key (dQ in ECDSA)
1347 * @param signing_key input to derive 'h' (see section 2.4 of #2564)
1348 * @param verification_key resulting public key to verify the signature
1349 * created from the '(d+h)' of 'pseudonym' and the 'signing_key';
1350 * the value stored here can then be given to GNUNET_FS_pseudonym_verify.
1351 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1354 GNUNET_FS_pseudonym_derive_verification_key (struct GNUNET_FS_PseudonymIdentifier *pseudonym,
1355 const struct GNUNET_HashCode *signing_key,
1356 struct GNUNET_FS_PseudonymIdentifier *verification_key)
1364 gcry_mpi_point_t hg;
1369 /* get 'h' value from signing key */
1370 size = sizeof (struct GNUNET_HashCode);
1371 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1375 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1376 return GNUNET_SYSERR;
1378 /* create ECC context based on Q from pseudonym */
1379 if (NULL == (ctx = get_context_from_pseudonym (pseudonym)))
1381 gcry_mpi_release (h);
1382 return GNUNET_SYSERR;
1385 g = gcry_mpi_ec_get_point ("g", ctx, 0);
1387 /* then call the 'multiply' function, to compute the product hG */
1388 hg = gcry_mpi_point_new (0);
1389 gcry_mpi_ec_mul (hg, h, g, ctx);
1390 gcry_mpi_point_release (g);
1391 gcry_mpi_release (h);
1393 /* get Q = dG from 'pseudonym' */
1394 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1395 /* calculate V = Q + hG = dG + hG = (d + h)G*/
1396 v = gcry_mpi_point_new (0);
1397 gcry_mpi_ec_add (v, q, hg, ctx);
1398 gcry_mpi_point_release (hg);
1400 /* store 'v' point in "verification_key" */
1401 v_x = gcry_mpi_new (256);
1402 v_y = gcry_mpi_new (256);
1403 gcry_mpi_ec_get_affine (v_x, v_y, v, ctx);
1405 gcry_mpi_point_release (v);
1406 gcry_ctx_release (ctx);
1408 size = sizeof (verification_key->q_x);
1409 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_x, size,
1412 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1413 gcry_mpi_release (v_x);
1414 gcry_mpi_release (v_y);
1415 return GNUNET_SYSERR;
1417 gcry_mpi_release (v_x);
1418 size = sizeof (verification_key->q_y);
1419 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_y, size,
1422 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1423 gcry_mpi_release (v_y);
1424 return GNUNET_SYSERR;
1426 gcry_mpi_release (v_y);
1432 * Verify a signature made with a pseudonym.
1434 * @param purpose data that was signed
1435 * @param signature signature to verify
1436 * @param verification_key public key to use for checking the signature;
1437 * corresponds to 'g^(x+h)' in section 2.4 of #2564.
1438 * @return GNUNET_OK on success (signature valid, 'pseudonym' set),
1439 * GNUNET_SYSERR if the signature is invalid
1442 GNUNET_FS_pseudonym_verify (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose,
1443 const struct GNUNET_FS_PseudonymSignature *signature,
1444 const struct GNUNET_FS_PseudonymIdentifier *verification_key)
1447 gcry_sexp_t sig_sexpr;
1448 gcry_sexp_t pk_sexpr;
1459 /* build s-expression for signature */
1460 size = sizeof (signature->sig_r);
1461 if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG,
1462 signature->sig_r, size, &size)))
1464 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1465 return GNUNET_SYSERR;
1467 size = sizeof (signature->sig_s);
1468 if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG,
1469 signature->sig_s, size, &size)))
1471 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1472 gcry_mpi_release (r);
1473 return GNUNET_SYSERR;
1475 if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))",
1478 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1479 gcry_mpi_release (r);
1480 gcry_mpi_release (s);
1481 return GNUNET_SYSERR;
1483 gcry_mpi_release (r);
1484 gcry_mpi_release (s);
1487 /* build s-expression for data that was signed */
1488 data = data_to_pkcs1 (purpose, GNUNET_NO);
1491 gcry_sexp_release (sig_sexpr);
1492 return GNUNET_SYSERR;
1494 /* create context of public key and initialize Q */
1495 size = sizeof (verification_key->q_x);
1496 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG,
1497 verification_key->q_x, size, &size)))
1499 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1500 gcry_sexp_release (data);
1501 gcry_sexp_release (sig_sexpr);
1502 return GNUNET_SYSERR;
1504 size = sizeof (verification_key->q_y);
1505 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG,
1506 verification_key->q_y, size, &size)))
1508 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1509 gcry_sexp_release (data);
1510 gcry_sexp_release (sig_sexpr);
1511 gcry_mpi_release (q_x);
1512 return GNUNET_SYSERR;
1514 q = gcry_mpi_point_new (256);
1515 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1516 gcry_mpi_release (q_x);
1517 gcry_mpi_release (q_y);
1519 /* create basic ECC context */
1520 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1522 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1523 gcry_sexp_release (data);
1524 gcry_sexp_release (sig_sexpr);
1525 gcry_mpi_point_release (q);
1526 return GNUNET_SYSERR;
1528 /* initialize 'ctx' with 'q' */
1529 gcry_mpi_ec_set_point ("q", q, ctx);
1530 gcry_mpi_point_release (q);
1532 /* convert 'ctx' to 'sexp' */
1533 if (0 != (rc = gcry_pubkey_get_sexp (&pk_sexpr, GCRY_PK_GET_PUBKEY, ctx)))
1535 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc);
1536 gcry_ctx_release (ctx);
1537 gcry_sexp_release (data);
1538 gcry_sexp_release (sig_sexpr);
1539 return GNUNET_SYSERR;
1541 gcry_ctx_release (ctx);
1543 /* finally, verify the signature */
1544 rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr);
1545 gcry_sexp_release (sig_sexpr);
1546 gcry_sexp_release (data);
1547 gcry_sexp_release (pk_sexpr);
1550 LOG (GNUNET_ERROR_TYPE_WARNING,
1551 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1552 __LINE__, gcry_strerror (rc));
1553 return GNUNET_SYSERR;
1560 * Get the identifier (public key) of a pseudonym.
1562 * @param ph pseudonym handle with the private key
1563 * @param pseudonym pseudonym identifier (set based on 'ph')
1566 GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph,
1567 struct GNUNET_FS_PseudonymIdentifier *pseudonym)
1569 if (&anonymous == ph)
1570 memset (pseudonym, 0, sizeof (struct GNUNET_FS_PseudonymIdentifier));
1572 memcpy (pseudonym, &ph->public_key,
1573 sizeof (struct GNUNET_FS_PseudonymIdentifier));
1578 * Remove pseudonym from the set of known pseudonyms.
1580 * @param cfg overall configuration
1581 * @param id the pseudonym identifier
1582 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1585 GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg,
1586 const struct GNUNET_FS_PseudonymIdentifier *id)
1591 fn = get_data_filename (cfg, PS_METADATA_DIR, id);
1593 return GNUNET_SYSERR;
1594 result = UNLINK (fn);
1596 return (0 == result) ? GNUNET_OK : GNUNET_SYSERR;
1599 /* end of pseudonym.c */