aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-04-14 18:45:55 +0000
committerChristian Grothoff <christian@grothoff.org>2013-04-14 18:45:55 +0000
commit7d9d8f793ebc261192fe33a87905133e1bf36512 (patch)
treed9dd0eaa5863a36878cd65190aeff96a41f25ca4 /src/util
parentd03a033c429a993d0d0511600fef0c15ada5d950 (diff)
downloadgnunet-7d9d8f793ebc261192fe33a87905133e1bf36512.tar.gz
gnunet-7d9d8f793ebc261192fe33a87905133e1bf36512.zip
-move pseudonym code to fs, mark fs as experimental for now
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/pseudonym.c1526
-rw-r--r--src/util/test_pseudonym.c323
3 files changed, 0 insertions, 1856 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index ef9ec7281..42d91c0ba 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -96,7 +96,6 @@ libgnunetutil_la_SOURCES = \
96 peer.c \ 96 peer.c \
97 plugin.c \ 97 plugin.c \
98 program.c \ 98 program.c \
99 pseudonym.c \
100 resolver_api.c resolver.h \ 99 resolver_api.c resolver.h \
101 scheduler.c \ 100 scheduler.c \
102 server.c \ 101 server.c \
@@ -234,7 +233,6 @@ check_PROGRAMS = \
234 test_peer \ 233 test_peer \
235 test_plugin \ 234 test_plugin \
236 test_program \ 235 test_program \
237 test_pseudonym \
238 test_resolver_api \ 236 test_resolver_api \
239 test_scheduler \ 237 test_scheduler \
240 test_scheduler_delay \ 238 test_scheduler_delay \
@@ -436,11 +434,6 @@ test_program_SOURCES = \
436test_program_LDADD = \ 434test_program_LDADD = \
437 $(top_builddir)/src/util/libgnunetutil.la 435 $(top_builddir)/src/util/libgnunetutil.la
438 436
439test_pseudonym_SOURCES = \
440 test_pseudonym.c
441test_pseudonym_LDADD = \
442 $(top_builddir)/src/util/libgnunetutil.la
443
444test_resolver_api_SOURCES = \ 437test_resolver_api_SOURCES = \
445 test_resolver_api.c 438 test_resolver_api.c
446test_resolver_api_LDADD = \ 439test_resolver_api_LDADD = \
diff --git a/src/util/pseudonym.c b/src/util/pseudonym.c
deleted file mode 100644
index 497f6ad6f..000000000
--- a/src/util/pseudonym.c
+++ /dev/null
@@ -1,1526 +0,0 @@
1/*
2 This file is part of GNUnet
3 (C) 2003, 2004, 2005, 2006, 2007, 2008, 2013 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19*/
20/**
21 * @file util/pseudonym.c
22 * @brief helper functions
23 * @author Christian Grothoff
24 *
25 * TODO:
26 * - all cryptographic operations are currently NOT implemented and
27 * provided by stubs that merely pretend to work!
28 */
29#include "platform.h"
30#include "gnunet_common.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_disk_lib.h"
33#include "gnunet_pseudonym_lib.h"
34#include "gnunet_bio_lib.h"
35#include <gcrypt.h>
36
37#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
38
39#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
40
41#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
42
43/**
44 * Log an error message at log-level 'level' that indicates
45 * a failure of the command 'cmd' with the message given
46 * by gcry_strerror(rc).
47 */
48#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
50/**
51 * Name of the directory which stores meta data for pseudonym
52 */
53#define PS_METADATA_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "metadata" DIR_SEPARATOR_STR
54
55/**
56 * Name of the directory which stores names for pseudonyms
57 */
58#define PS_NAMES_DIR DIR_SEPARATOR_STR "data" DIR_SEPARATOR_STR "pseudonym" DIR_SEPARATOR_STR "names" DIR_SEPARATOR_STR
59
60
61/**
62 * Configuration section we use.
63 */
64#define GNUNET_CLIENT_SERVICE_NAME "client"
65
66
67/* ************************* Disk operations (pseudonym data mgmt) **************** */
68
69/**
70 * Registered callbacks for discovery of pseudonyms.
71 */
72struct GNUNET_PSEUDONYM_DiscoveryHandle
73{
74 /**
75 * This is a doubly linked list.
76 */
77 struct GNUNET_PSEUDONYM_DiscoveryHandle *next;
78
79 /**
80 * This is a doubly linked list.
81 */
82 struct GNUNET_PSEUDONYM_DiscoveryHandle *prev;
83
84 /**
85 * Function to call each time a pseudonym is discovered.
86 */
87 GNUNET_PSEUDONYM_Iterator callback;
88
89 /**
90 * Closure for callback.
91 */
92 void *callback_cls;
93};
94
95
96/**
97 * Head of the linked list of functions to call when
98 * new pseudonyms are added.
99 */
100static struct GNUNET_PSEUDONYM_DiscoveryHandle *disco_head;
101
102/**
103 * Tail of the linked list of functions to call when
104 * new pseudonyms are added.
105 */
106static struct GNUNET_PSEUDONYM_DiscoveryHandle *disco_tail;
107
108
109/**
110 * Internal notification about new tracked URI.
111 *
112 * @param pseudonym public key of the pseudonym
113 * @param md meta data to be written
114 * @param rating rating of pseudonym
115 */
116static void
117internal_notify (const struct GNUNET_PseudonymIdentifier *pseudonym,
118 const struct GNUNET_CONTAINER_MetaData *md, int rating)
119{
120 struct GNUNET_PSEUDONYM_DiscoveryHandle *pos;
121
122 for (pos = disco_head; NULL != pos; pos = pos->next)
123 pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating);
124}
125
126
127/**
128 * Register callback to be invoked whenever we discover
129 * a new pseudonym.
130 * Will immediately call provided iterator callback for all
131 * already discovered pseudonyms.
132 *
133 * @param cfg configuration to use
134 * @param iterator iterator over pseudonym
135 * @param iterator_cls point to a closure
136 * @return registration handle
137 */
138struct GNUNET_PSEUDONYM_DiscoveryHandle *
139GNUNET_PSEUDONYM_discovery_callback_register (const struct
140 GNUNET_CONFIGURATION_Handle *cfg,
141 GNUNET_PSEUDONYM_Iterator iterator,
142 void *iterator_cls)
143{
144 struct GNUNET_PSEUDONYM_DiscoveryHandle *dh;
145
146 dh = GNUNET_malloc (sizeof (struct GNUNET_PSEUDONYM_DiscoveryHandle));
147 dh->callback = iterator;
148 dh->callback_cls = iterator_cls;
149 GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh);
150 GNUNET_PSEUDONYM_list_all (cfg, iterator, iterator_cls);
151 return dh;
152}
153
154
155/**
156 * Unregister pseudonym discovery callback.
157 *
158 * @param dh registration to unregister
159 */
160void
161GNUNET_PSEUDONYM_discovery_callback_unregister (struct GNUNET_PSEUDONYM_DiscoveryHandle *dh)
162{
163 GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh);
164 GNUNET_free (dh);
165}
166
167
168/**
169 * Get the filename (or directory name) for the given
170 * pseudonym identifier and directory prefix.
171 *
172 * @param cfg configuration to use
173 * @param prefix path components to append to the private directory name
174 * @param pseudonym the pseudonym, can be NULL
175 * @return filename of the pseudonym (if pseudonym != NULL) or directory with the data (if pseudonym == NULL)
176 */
177static char *
178get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg,
179 const char *prefix,
180 const struct GNUNET_PseudonymIdentifier *pseudonym)
181{
182 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
183 struct GNUNET_HashCode psid;
184
185 if (NULL != pseudonym)
186 {
187 GNUNET_CRYPTO_hash (pseudonym,
188 sizeof (struct GNUNET_PseudonymIdentifier),
189 &psid);
190 GNUNET_CRYPTO_hash_to_enc (&psid, &enc);
191 }
192 return GNUNET_DISK_get_home_filename (cfg,
193 GNUNET_CLIENT_SERVICE_NAME, prefix,
194 (NULL == pseudonym)
195 ? NULL
196 : (const char *) &enc,
197 NULL);
198}
199
200
201/**
202 * Get the filename (or directory name) for the given
203 * hash code and directory prefix.
204 *
205 * @param cfg configuration to use
206 * @param prefix path components to append to the private directory name
207 * @param hc some hash code
208 * @return filename of the pseudonym (if hc != NULL) or directory with the data (if hc == NULL)
209 */
210static char *
211get_data_filename_hash (const struct GNUNET_CONFIGURATION_Handle *cfg,
212 const char *prefix,
213 const struct GNUNET_HashCode *hc)
214{
215 struct GNUNET_CRYPTO_HashAsciiEncoded enc;
216
217 if (NULL != hc)
218 GNUNET_CRYPTO_hash_to_enc (hc, &enc);
219 return GNUNET_DISK_get_home_filename (cfg,
220 GNUNET_CLIENT_SERVICE_NAME, prefix,
221 (NULL == hc)
222 ? NULL
223 : (const char *) &enc,
224 NULL);
225}
226
227
228/**
229 * Set the pseudonym metadata, rank and name.
230 * Writes the pseudonym infomation into a file
231 *
232 * @param cfg overall configuration
233 * @param pseudonym id of the pseudonym
234 * @param name name to set. Must be the non-unique version of it.
235 * May be NULL, in which case it erases pseudonym's name!
236 * @param md metadata to set
237 * May be NULL, in which case it erases pseudonym's metadata!
238 * @param rank rank to assign
239 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
240 */
241int
242GNUNET_PSEUDONYM_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
243 const struct GNUNET_PseudonymIdentifier *pseudonym,
244 const char *name,
245 const struct GNUNET_CONTAINER_MetaData *md,
246 int32_t rank)
247{
248 char *fn;
249 struct GNUNET_BIO_WriteHandle *fileW;
250
251 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
252 if (NULL == (fileW = GNUNET_BIO_write_open (fn)))
253 {
254 GNUNET_free (fn);
255 return GNUNET_SYSERR;
256 }
257 if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym,
258 sizeof (struct GNUNET_PseudonymIdentifier))) ||
259 (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) ||
260 (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) ||
261 (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md)))
262 {
263 (void) GNUNET_BIO_write_close (fileW);
264 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
265 GNUNET_free (fn);
266 return GNUNET_SYSERR;
267 }
268 if (GNUNET_OK != GNUNET_BIO_write_close (fileW))
269 {
270 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
271 GNUNET_free (fn);
272 return GNUNET_SYSERR;
273 }
274 GNUNET_free (fn);
275 /* create entry for pseudonym name in names */
276 if (NULL != name)
277 GNUNET_free_non_null (GNUNET_PSEUDONYM_name_uniquify (cfg, pseudonym,
278 name, NULL));
279 return GNUNET_OK;
280}
281
282
283/**
284 * Read pseudonym infomation from a file
285 *
286 * @param cfg configuration to use
287 * @param pseudonym hash code of a pseudonym
288 * @param meta meta data to be read from a file
289 * @param rank rank of a pseudonym
290 * @param ns_name name of a pseudonym
291 * @return GNUNET_OK on success, GNUNET_SYSERR on error
292 */
293static int
294read_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
295 const struct GNUNET_PseudonymIdentifier *pseudonym,
296 struct GNUNET_CONTAINER_MetaData **meta,
297 int32_t *rank,
298 char **ns_name)
299{
300 struct GNUNET_PseudonymIdentifier pd;
301 char *fn;
302 char *emsg;
303 struct GNUNET_BIO_ReadHandle *fileR;
304
305 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
306 if (GNUNET_YES !=
307 GNUNET_DISK_file_test (fn))
308 {
309 GNUNET_free (fn);
310 return GNUNET_SYSERR;
311 }
312 if (NULL == (fileR = GNUNET_BIO_read_open (fn)))
313 {
314 GNUNET_free (fn);
315 return GNUNET_SYSERR;
316 }
317 emsg = NULL;
318 *ns_name = NULL;
319 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
320 (0 != memcmp (&pd, pseudonym, sizeof (pd))) ||
321 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, rank)) ||
322 (GNUNET_OK !=
323 GNUNET_BIO_read_string (fileR, "Read string error!", ns_name, 200)) ||
324 (GNUNET_OK !=
325 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", meta)) )
326 {
327 (void) GNUNET_BIO_read_close (fileR, &emsg);
328 GNUNET_free_non_null (emsg);
329 GNUNET_free_non_null (*ns_name);
330 *ns_name = NULL;
331 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
332 GNUNET_free (fn);
333 return GNUNET_SYSERR;
334 }
335 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
336 {
337 LOG (GNUNET_ERROR_TYPE_WARNING,
338 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fn,
339 emsg);
340 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fn));
341 GNUNET_CONTAINER_meta_data_destroy (*meta);
342 *meta = NULL;
343 GNUNET_free_non_null (*ns_name);
344 *ns_name = NULL;
345 GNUNET_free_non_null (emsg);
346 GNUNET_free (fn);
347 return GNUNET_SYSERR;
348 }
349 GNUNET_free (fn);
350 return GNUNET_OK;
351}
352
353
354/**
355 * Return unique variant of the namespace name. Use it after
356 * GNUNET_PSEUDONYM_get_info() to make sure that name is unique.
357 *
358 * @param cfg configuration
359 * @param pseudonym public key of the pseudonym
360 * @param name name to uniquify
361 * @param suffix if not NULL, filled with the suffix value
362 * @return NULL on failure (should never happen), name on success.
363 * Free the name with GNUNET_free().
364 */
365char *
366GNUNET_PSEUDONYM_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg,
367 const struct GNUNET_PseudonymIdentifier *pseudonym,
368 const char *name,
369 unsigned int *suffix)
370{
371 struct GNUNET_HashCode nh;
372 struct GNUNET_PseudonymIdentifier pi;
373 uint64_t len;
374 char *fn;
375 struct GNUNET_DISK_FileHandle *fh;
376 unsigned int i;
377 unsigned int idx;
378 char *ret;
379 struct stat sbuf;
380
381 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
382 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
383 len = 0;
384 if (0 == STAT (fn, &sbuf))
385 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES));
386 fh = GNUNET_DISK_file_open (fn,
387 GNUNET_DISK_OPEN_CREATE |
388 GNUNET_DISK_OPEN_READWRITE,
389 GNUNET_DISK_PERM_USER_READ |
390 GNUNET_DISK_PERM_USER_WRITE);
391 i = 0;
392 idx = -1;
393 while ((len >= sizeof (struct GNUNET_PseudonymIdentifier)) &&
394 (sizeof (struct GNUNET_PseudonymIdentifier) ==
395 GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_PseudonymIdentifier))))
396 {
397 if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
398 {
399 idx = i;
400 break;
401 }
402 i++;
403 len -= sizeof (struct GNUNET_HashCode);
404 }
405 if (-1 == idx)
406 {
407 idx = i;
408 if (sizeof (struct GNUNET_PseudonymIdentifier) !=
409 GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
410 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn);
411 }
412 GNUNET_DISK_file_close (fh);
413 ret = GNUNET_malloc (strlen (name) + 32);
414 GNUNET_snprintf (ret, strlen (name) + 32, "%s-%u", name, idx);
415 if (suffix != NULL)
416 *suffix = idx;
417 GNUNET_free (fn);
418 return ret;
419}
420
421
422/**
423 * Get namespace name, metadata and rank
424 * This is a wrapper around internal read_info() call, and ensures that
425 * returned data is not invalid (not NULL).
426 *
427 * @param cfg configuration
428 * @param pseudonym public key of the pseudonym
429 * @param ret_meta a location to store metadata pointer. NULL, if metadata
430 * is not needed. Destroy with GNUNET_CONTAINER_meta_data_destroy().
431 * @param ret_rank a location to store rank. NULL, if rank not needed.
432 * @param ret_name a location to store human-readable name. Name is not unique.
433 * NULL, if name is not needed. Free with GNUNET_free().
434 * @param name_is_a_dup is set to GNUNET_YES, if ret_name was filled with
435 * a duplicate of a "no-name" placeholder
436 * @return GNUNET_OK on success. GNUENT_SYSERR if the data was
437 * unobtainable (in that case ret_* are filled with placeholders -
438 * empty metadata container, rank -1 and a "no-name" name).
439 */
440int
441GNUNET_PSEUDONYM_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg,
442 const struct GNUNET_PseudonymIdentifier *pseudonym,
443 struct GNUNET_CONTAINER_MetaData **ret_meta,
444 int32_t *ret_rank,
445 char **ret_name,
446 int *name_is_a_dup)
447{
448 struct GNUNET_CONTAINER_MetaData *meta;
449 char *name;
450 int32_t rank = -1;
451
452 meta = NULL;
453 name = NULL;
454 if (GNUNET_OK == read_info (cfg, pseudonym, &meta, &rank, &name))
455 {
456 if ((meta != NULL) && (name == NULL))
457 name =
458 GNUNET_CONTAINER_meta_data_get_first_by_types (meta,
459 EXTRACTOR_METATYPE_TITLE,
460 EXTRACTOR_METATYPE_GNUNET_ORIGINAL_FILENAME,
461 EXTRACTOR_METATYPE_FILENAME,
462 EXTRACTOR_METATYPE_DESCRIPTION,
463 EXTRACTOR_METATYPE_SUBJECT,
464 EXTRACTOR_METATYPE_PUBLISHER,
465 EXTRACTOR_METATYPE_AUTHOR_NAME,
466 EXTRACTOR_METATYPE_COMMENT,
467 EXTRACTOR_METATYPE_SUMMARY,
468 -1);
469 if (ret_name != NULL)
470 {
471 if (name == NULL)
472 {
473 name = GNUNET_strdup (_("no-name"));
474 if (name_is_a_dup != NULL)
475 *name_is_a_dup = GNUNET_YES;
476 }
477 else if (name_is_a_dup != NULL)
478 *name_is_a_dup = GNUNET_NO;
479 *ret_name = name;
480 }
481 else if (name != NULL)
482 GNUNET_free (name);
483
484 if (ret_meta != NULL)
485 {
486 if (meta == NULL)
487 meta = GNUNET_CONTAINER_meta_data_create ();
488 *ret_meta = meta;
489 }
490 else if (meta != NULL)
491 GNUNET_CONTAINER_meta_data_destroy (meta);
492
493 if (ret_rank != NULL)
494 *ret_rank = rank;
495
496 return GNUNET_OK;
497 }
498 if (ret_name != NULL)
499 *ret_name = GNUNET_strdup (_("no-name"));
500 if (ret_meta != NULL)
501 *ret_meta = GNUNET_CONTAINER_meta_data_create ();
502 if (ret_rank != NULL)
503 *ret_rank = -1;
504 if (name_is_a_dup != NULL)
505 *name_is_a_dup = GNUNET_YES;
506 return GNUNET_SYSERR;
507}
508
509
510/**
511 * Get the namespace ID belonging to the given namespace name.
512 *
513 * @param cfg configuration to use
514 * @param ns_uname unique (!) human-readable name for the namespace
515 * @param pseudonym set to public key of pseudonym based on 'ns_uname'
516 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
517 */
518int
519GNUNET_PSEUDONYM_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg,
520 const char *ns_uname,
521 struct GNUNET_PseudonymIdentifier *pseudonym)
522{
523 size_t slen;
524 uint64_t len;
525 unsigned int idx;
526 char *name;
527 struct GNUNET_HashCode nh;
528 char *fn;
529 struct GNUNET_DISK_FileHandle *fh;
530
531 idx = -1;
532 slen = strlen (ns_uname);
533 while ((slen > 0) && (1 != SSCANF (&ns_uname[slen - 1], "-%u", &idx)))
534 slen--;
535 if (0 == slen)
536 return GNUNET_SYSERR;
537 name = GNUNET_strdup (ns_uname);
538 name[slen - 1] = '\0';
539
540 GNUNET_CRYPTO_hash (name, strlen (name), &nh);
541 GNUNET_free (name);
542 fn = get_data_filename_hash (cfg, PS_NAMES_DIR, &nh);
543
544 if ((GNUNET_OK != GNUNET_DISK_file_test (fn) ||
545 (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) ||
546 ((idx + 1) * sizeof (struct GNUNET_PseudonymIdentifier) > len))
547 {
548 GNUNET_free (fn);
549 return GNUNET_SYSERR;
550 }
551 fh = GNUNET_DISK_file_open (fn,
552 GNUNET_DISK_OPEN_CREATE |
553 GNUNET_DISK_OPEN_READWRITE,
554 GNUNET_DISK_PERM_USER_READ |
555 GNUNET_DISK_PERM_USER_WRITE);
556 GNUNET_free (fn);
557 if (GNUNET_SYSERR ==
558 GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_PseudonymIdentifier),
559 GNUNET_DISK_SEEK_SET))
560 {
561 GNUNET_DISK_file_close (fh);
562 return GNUNET_SYSERR;
563 }
564 if (sizeof (struct GNUNET_PseudonymIdentifier) !=
565 GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_PseudonymIdentifier)))
566 {
567 GNUNET_DISK_file_close (fh);
568 return GNUNET_SYSERR;
569 }
570 GNUNET_DISK_file_close (fh);
571 return GNUNET_OK;
572}
573
574
575
576/**
577 * struct used to list the pseudonym
578 */
579struct ListPseudonymClosure
580{
581
582 /**
583 * iterator over pseudonym
584 */
585 GNUNET_PSEUDONYM_Iterator iterator;
586
587 /**
588 * Closure for iterator.
589 */
590 void *iterator_cls;
591
592 /**
593 * Configuration to use.
594 */
595 const struct GNUNET_CONFIGURATION_Handle *cfg;
596};
597
598
599
600/**
601 * Helper function to list all available pseudonyms
602 *
603 * @param cls point to a struct ListPseudonymClosure
604 * @param fullname name of pseudonym
605 */
606static int
607list_pseudonym_helper (void *cls, const char *fullname)
608{
609 struct ListPseudonymClosure *lpc = cls;
610 struct GNUNET_PseudonymIdentifier pd;
611 char *emsg;
612 struct GNUNET_BIO_ReadHandle *fileR;
613 int32_t rank;
614 char *ns_name;
615 struct GNUNET_CONTAINER_MetaData *meta;
616 int ret;
617 char *name_unique;
618
619 if (NULL == (fileR = GNUNET_BIO_read_open (fullname)))
620 return GNUNET_SYSERR;
621 emsg = NULL;
622 ns_name = NULL;
623 if ( (GNUNET_OK != GNUNET_BIO_read (fileR, "pseudonym", &pd, sizeof (pd))) ||
624 (GNUNET_OK != GNUNET_BIO_read_int32 (fileR, &rank)) ||
625 (GNUNET_OK !=
626 GNUNET_BIO_read_string (fileR, "Read string error!", &ns_name, 200)) ||
627 (GNUNET_OK !=
628 GNUNET_BIO_read_meta_data (fileR, "Read meta data error!", &meta)) )
629 {
630 (void) GNUNET_BIO_read_close (fileR, &emsg);
631 GNUNET_free_non_null (emsg);
632 GNUNET_free_non_null (ns_name);
633 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
634 return GNUNET_SYSERR;
635 }
636 if (NULL == ns_name)
637 ns_name = GNUNET_strdup (_("no-name"));
638 if (GNUNET_OK != GNUNET_BIO_read_close (fileR, &emsg))
639 {
640 LOG (GNUNET_ERROR_TYPE_WARNING,
641 _("Failed to parse metadata about pseudonym from file `%s': %s\n"), fullname,
642 emsg);
643 GNUNET_break (GNUNET_OK == GNUNET_DISK_directory_remove (fullname));
644 GNUNET_CONTAINER_meta_data_destroy (meta);
645 GNUNET_free (ns_name);
646 GNUNET_free_non_null (emsg);
647 return GNUNET_SYSERR;
648 }
649 ret = GNUNET_OK;
650 name_unique = GNUNET_PSEUDONYM_name_uniquify (lpc->cfg, &pd, ns_name, NULL);
651 if (NULL != lpc->iterator)
652 ret = lpc->iterator (lpc->iterator_cls, &pd, ns_name, name_unique, meta, rank);
653 GNUNET_free (ns_name);
654 GNUNET_free_non_null (name_unique);
655 GNUNET_CONTAINER_meta_data_destroy (meta);
656 return ret;
657}
658
659
660/**
661 * List all available pseudonyms.
662 *
663 * @param cfg overall configuration
664 * @param iterator function to call for each pseudonym
665 * @param iterator_cls closure for iterator
666 * @return number of pseudonyms found
667 */
668int
669GNUNET_PSEUDONYM_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg,
670 GNUNET_PSEUDONYM_Iterator iterator,
671 void *iterator_cls)
672{
673 struct ListPseudonymClosure cls;
674 char *fn;
675 int ret;
676
677 cls.iterator = iterator;
678 cls.iterator_cls = iterator_cls;
679 cls.cfg = cfg;
680 fn = get_data_filename (cfg, PS_METADATA_DIR, NULL);
681 GNUNET_assert (fn != NULL);
682 GNUNET_DISK_directory_create (fn);
683 ret = GNUNET_DISK_directory_scan (fn, &list_pseudonym_helper, &cls);
684 GNUNET_free (fn);
685 return ret;
686}
687
688
689/**
690 * Change the rank of a pseudonym.
691 *
692 * @param cfg overall configuration
693 * @param pseudonym the pseudonym
694 * @param delta by how much should the rating be changed?
695 * @return new rating of the pseudonym
696 */
697int
698GNUNET_PSEUDONYM_rank (const struct GNUNET_CONFIGURATION_Handle *cfg,
699 const struct GNUNET_PseudonymIdentifier *pseudonym,
700 int32_t delta)
701{
702 struct GNUNET_CONTAINER_MetaData *meta;
703 int ret;
704 int32_t rank;
705 char *name;
706
707 name = NULL;
708 ret = read_info (cfg, pseudonym, &meta, &rank, &name);
709 if (ret == GNUNET_SYSERR)
710 {
711 rank = 0;
712 meta = GNUNET_CONTAINER_meta_data_create ();
713 }
714 rank += delta;
715 GNUNET_PSEUDONYM_set_info (cfg, pseudonym, name, meta, rank);
716 GNUNET_CONTAINER_meta_data_destroy (meta);
717 GNUNET_free_non_null (name);
718 return rank;
719}
720
721
722/**
723 * Add a pseudonym to the set of known pseudonyms.
724 * For all pseudonym advertisements that we discover
725 * FS should automatically call this function.
726 *
727 * @param cfg overall configuration
728 * @param pseudonym the pseudonym to add
729 * @param meta metadata for the pseudonym
730 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
731 */
732int
733GNUNET_PSEUDONYM_add (const struct GNUNET_CONFIGURATION_Handle *cfg,
734 const struct GNUNET_PseudonymIdentifier *pseudonym,
735 const struct GNUNET_CONTAINER_MetaData *meta)
736{
737 char *name;
738 int32_t rank;
739 struct GNUNET_CONTAINER_MetaData *old;
740 char *fn;
741 struct stat sbuf;
742 int ret;
743
744 rank = 0;
745 fn = get_data_filename (cfg, PS_METADATA_DIR, pseudonym);
746 GNUNET_assert (fn != NULL);
747
748 if ((0 == STAT (fn, &sbuf)) &&
749 (GNUNET_OK == read_info (cfg, pseudonym, &old, &rank, &name)))
750 {
751 GNUNET_CONTAINER_meta_data_merge (old, meta);
752 ret = GNUNET_PSEUDONYM_set_info (cfg, pseudonym, name, old, rank);
753 GNUNET_CONTAINER_meta_data_destroy (old);
754 GNUNET_free_non_null (name);
755 }
756 else
757 {
758 ret = GNUNET_PSEUDONYM_set_info (cfg, pseudonym, NULL, meta, rank);
759 }
760 GNUNET_free (fn);
761 internal_notify (pseudonym, meta, rank);
762 return ret;
763}
764
765
766/* ***************************** cryptographic operations ************************* */
767
768/**
769 * Handle for a pseudonym (private key).
770 */
771struct GNUNET_PseudonymHandle
772{
773 /**
774 * 256-bit 'd' secret value (mod 'n', where n is 256-bit for NIST P-256).
775 */
776 unsigned char d[256 / 8];
777
778 /**
779 * Public key corresponding to the private key.
780 */
781 struct GNUNET_PseudonymIdentifier public_key;
782};
783
784
785/**
786 * If target != size, move target bytes to the end of the size-sized
787 * buffer and zero out the first target-size bytes.
788 *
789 * @param buf original buffer
790 * @param size number of bytes in the buffer
791 * @param target target size of the buffer
792 */
793static void
794adjust (unsigned char *buf, size_t size, size_t target)
795{
796 if (size < target)
797 {
798 memmove (&buf[target - size], buf, size);
799 memset (buf, 0, target - size);
800 }
801}
802
803
804/**
805 * Extract values from an S-expression.
806 *
807 * @param array where to store the result(s)
808 * @param sexp S-expression to parse
809 * @param topname top-level name in the S-expression that is of interest
810 * @param elems names of the elements to extract
811 * @return 0 on success
812 */
813static int
814key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname,
815 const char *elems)
816{
817 gcry_sexp_t list;
818 gcry_sexp_t l2;
819 const char *s;
820 unsigned int i;
821 unsigned int idx;
822
823 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
824 return 1;
825 l2 = gcry_sexp_cadr (list);
826 gcry_sexp_release (list);
827 list = l2;
828 if (! list)
829 return 2;
830 idx = 0;
831 for (s = elems; *s; s++, idx++)
832 {
833 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
834 {
835 for (i = 0; i < idx; i++)
836 {
837 gcry_free (array[i]);
838 array[i] = NULL;
839 }
840 gcry_sexp_release (list);
841 return 3; /* required parameter not found */
842 }
843 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
844 gcry_sexp_release (l2);
845 if (! array[idx])
846 {
847 for (i = 0; i < idx; i++)
848 {
849 gcry_free (array[i]);
850 array[i] = NULL;
851 }
852 gcry_sexp_release (list);
853 return 4; /* required parameter is invalid */
854 }
855 }
856 gcry_sexp_release (list);
857 return 0;
858}
859
860
861/**
862 * Create a pseudonym.
863 *
864 * @param filename name of the file to use for storage, NULL for in-memory only
865 * @return handle to the private key of the pseudonym
866 */
867struct GNUNET_PseudonymHandle *
868GNUNET_PSEUDONYM_create (const char *filename)
869{
870 struct GNUNET_PseudonymHandle *ph;
871 ssize_t ret;
872 gcry_sexp_t r_key;
873 gcry_sexp_t params;
874 gcry_ctx_t ctx;
875 gcry_mpi_point_t q;
876 gcry_mpi_t q_x;
877 gcry_mpi_t q_y;
878 gcry_error_t rc;
879 gcry_mpi_t d;
880 size_t size;
881
882 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
883 if ( (NULL != filename) &&
884 (GNUNET_YES == GNUNET_DISK_file_test (filename)) )
885 {
886 ret = GNUNET_DISK_fn_read (filename, ph,
887 sizeof (struct GNUNET_PseudonymHandle));
888 /* Note: we don't do any validation here, maybe we should? */
889 if (sizeof (struct GNUNET_PseudonymHandle) == ret)
890 return ph;
891 }
892 if (0 != (rc = gcry_sexp_build (&params, NULL,
893 "(genkey(ecdsa(curve \"NIST P-256\")))")))
894 {
895 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
896 return NULL;
897 }
898 if (0 != (rc = gcry_pk_genkey (&r_key, params)))
899 {
900 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
901 gcry_sexp_release (r_key);
902 return NULL;
903 }
904 /* extract "d" (secret key) from r_key */
905 rc = key_from_sexp (&d, r_key, "private-key", "d");
906 if (0 != rc)
907 rc = key_from_sexp (&d, r_key, "private-key", "d");
908 if (0 != rc)
909 rc = key_from_sexp (&d, r_key, "ecc", "d");
910 if (0 != rc)
911 {
912 gcry_sexp_release (r_key);
913 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
914 return NULL;
915 }
916 size = sizeof (ph->d);
917 GNUNET_assert (0 ==
918 gcry_mpi_print (GCRYMPI_FMT_USG, ph->d, size, &size,
919 d));
920 gcry_mpi_release (d);
921 adjust (ph->d, size, sizeof (ph->d));
922
923 /* extract 'q' (public key) from r_key */
924 if (0 != (rc = gcry_mpi_ec_new (&ctx, r_key, NULL)))
925 {
926 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
927 gcry_sexp_release (r_key);
928 return NULL;
929 }
930 gcry_sexp_release (r_key);
931 q = gcry_mpi_ec_get_point ("q", ctx, 0);
932 q_x = gcry_mpi_new (256);
933 q_y = gcry_mpi_new (256);
934 gcry_mpi_ec_get_affine (q_x, q_y, q, ctx);
935 gcry_mpi_point_release (q);
936
937 /* store q_x/q_y in public key */
938 size = sizeof (ph->public_key.q_x);
939 if (0 !=
940 gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_x, size, &size,
941 q_x))
942 {
943 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
944 gcry_mpi_release (q_x);
945 gcry_mpi_release (q_y);
946 return NULL;
947
948 }
949 adjust (ph->public_key.q_x, size, sizeof (ph->public_key.q_x));
950 gcry_mpi_release (q_x);
951
952 size = sizeof (ph->public_key.q_y);
953 if (0 !=
954 gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_y, size, &size,
955 q_y))
956 {
957 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
958 gcry_mpi_release (q_y);
959 return NULL;
960 }
961 adjust (ph->public_key.q_y, size, sizeof (ph->public_key.q_y));
962 gcry_mpi_release (q_y);
963
964 /* write to disk */
965 if (NULL != filename)
966 {
967 ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_PseudonymHandle),
968 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
969 if (sizeof (struct GNUNET_PseudonymHandle) != ret)
970 {
971 GNUNET_free (ph);
972 return NULL;
973 }
974 }
975 return ph;
976}
977
978
979/**
980 * Create a pseudonym, from a file that must already exist.
981 *
982 * @param filename name of the file to use for storage, NULL for in-memory only
983 * @return handle to the private key of the pseudonym
984 */
985struct GNUNET_PseudonymHandle *
986GNUNET_PSEUDONYM_create_from_existing_file (const char *filename)
987{
988 struct GNUNET_PseudonymHandle *ph;
989 ssize_t ret;
990
991 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
992 ret = GNUNET_DISK_fn_read (filename, ph,
993 sizeof (struct GNUNET_PseudonymHandle));
994 if (sizeof (struct GNUNET_PseudonymHandle) != ret)
995 {
996 GNUNET_free (ph);
997 return NULL;
998 }
999 /* Note: we don't do any validation here; maybe we should? */
1000 return ph;
1001}
1002
1003
1004/**
1005 * Get the handle for the 'anonymous' pseudonym shared by all users.
1006 * That pseudonym uses a fixed 'secret' for the private key; this
1007 * construction is useful to make anonymous and pseudonymous APIs
1008 * (and packets) indistinguishable on the network. See #2564.
1009 *
1010 * @return handle to the (non-secret) private key of the 'anonymous' pseudonym
1011 */
1012struct GNUNET_PseudonymHandle *
1013GNUNET_PSEUDONYM_get_anonymous_pseudonym_handle ()
1014{
1015 struct GNUNET_PseudonymHandle *ph;
1016
1017 ph = GNUNET_malloc (sizeof (struct GNUNET_PseudonymHandle));
1018 /* Note if we use 'd=0' for the anonymous handle (as per#2564),
1019 then I believe the public key should be also zero, as Q=0P=0;
1020 so setting everything to all-zeros (as per GNUNET_malloc)
1021 should be all that is needed here).
1022 */
1023 return ph;
1024}
1025
1026
1027/**
1028 * Destroy a pseudonym handle. Does NOT remove the private key from
1029 * the disk.
1030 *
1031 * @param ph pseudonym handle to destroy
1032 */
1033void
1034GNUNET_PSEUDONYM_destroy (struct GNUNET_PseudonymHandle *ph)
1035{
1036 GNUNET_free (ph);
1037}
1038
1039
1040/**
1041 * Convert the data specified in the given purpose argument to an
1042 * S-expression suitable for signature operations.
1043 *
1044 * @param purpose data to convert
1045 * @return converted s-expression
1046 */
1047static gcry_sexp_t
1048data_to_pkcs1 (const struct GNUNET_PseudonymSignaturePurpose *purpose)
1049{
1050 struct GNUNET_CRYPTO_ShortHashCode hc;
1051 size_t bufSize;
1052 gcry_sexp_t data;
1053
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;
1057 {
1058 char buff[bufSize];
1059
1060 memcpy (buff, FORMATSTRING, bufSize);
1061 memcpy (&buff
1062 [bufSize -
1063 strlen
1064 ("01234567890123456789012345678901))")
1065 - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode));
1066 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1067 }
1068#undef FORMATSTRING
1069 return data;
1070}
1071
1072
1073/**
1074 * Cryptographically sign some data with the pseudonym.
1075 *
1076 * @param ph private key 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;
1082 * corresponds to 'h' in section 2.3 of #2564.
1083 * @param signature where to store the signature
1084 * @return GNUNET_SYSERR on failure
1085 */
1086int
1087GNUNET_PSEUDONYM_sign (struct GNUNET_PseudonymHandle *ph,
1088 const struct GNUNET_PseudonymSignaturePurpose *purpose,
1089 const struct GNUNET_HashCode *seed,
1090 const struct GNUNET_HashCode *signing_key,
1091 struct GNUNET_PseudonymSignature *signature)
1092{
1093 size_t size;
1094 size_t erroff;
1095 gcry_mpi_t x;
1096 gcry_mpi_t k;
1097 gcry_mpi_t h;
1098 gcry_mpi_t d;
1099 gcry_mpi_t n; /* n from P-256 */
1100 gcry_sexp_t spriv;
1101 gcry_sexp_t data;
1102 gcry_sexp_t result;
1103 gcry_mpi_t rs[2];
1104 int rc;
1105
1106 /* get private key 'x' from pseudonym */
1107 size = sizeof (ph->d);
1108 if (0 != (rc = gcry_mpi_scan (&x, GCRYMPI_FMT_USG,
1109 &ph->d,
1110 size, &size)))
1111 {
1112 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1113 return GNUNET_SYSERR;
1114 }
1115 /* get 'h' value from signing key */
1116 size = sizeof (struct GNUNET_HashCode);
1117 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1118 signing_key,
1119 size, &size)))
1120 {
1121 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1122 gcry_mpi_release (x);
1123 return GNUNET_SYSERR;
1124 }
1125
1126 /* initialize 'n' from P-256; hex copied from libgcrypt code */
1127 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX,
1128 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL)))
1129 {
1130 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1131 gcry_mpi_release (x);
1132 gcry_mpi_release (h);
1133 return GNUNET_SYSERR;
1134 }
1135
1136 /* calculate d = x + h mod n */
1137 d = gcry_mpi_new (256);
1138 gcry_mpi_addm (d, x, h, n);
1139 gcry_mpi_release (x);
1140 gcry_mpi_release (h);
1141 gcry_mpi_release (n);
1142
1143 /* now build sexpression with the signing key */
1144 if (0 != (rc = gcry_sexp_build (&spriv, &erroff,
1145 "(private-key(ecdsa(curve \"NIST P-256\")(d %m)))",
1146 d)))
1147 {
1148 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1149 gcry_mpi_release (d);
1150 return GNUNET_SYSERR;
1151 }
1152 gcry_mpi_release (d);
1153 /* prepare data for signing */
1154 data = data_to_pkcs1 (purpose);
1155
1156 /* get 'k' value from seed, if available */
1157 if (NULL != seed)
1158 {
1159 size = sizeof (struct GNUNET_HashCode);
1160 if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG,
1161 seed,
1162 size, &size)))
1163 {
1164 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1165 gcry_mpi_release (x);
1166 return GNUNET_SYSERR;
1167 }
1168 }
1169
1170 /* actually create signature */
1171 /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */
1172 if (0 != (rc = gcry_pk_sign (&result, data, spriv)))
1173 {
1174 LOG (GNUNET_ERROR_TYPE_WARNING,
1175 _("ECC signing failed at %s:%d: %s\n"), __FILE__,
1176 __LINE__, gcry_strerror (rc));
1177 gcry_sexp_release (data);
1178 gcry_sexp_release (spriv);
1179 if (NULL != seed)
1180 gcry_mpi_release (k);
1181 memset (signature, 0, sizeof (struct GNUNET_PseudonymSignature));
1182 return GNUNET_SYSERR;
1183 }
1184 if (NULL != seed)
1185 gcry_mpi_release (k);
1186 gcry_sexp_release (data);
1187 gcry_sexp_release (spriv);
1188
1189
1190 /* extract 'r' and 's' values from sexpression 'result' and store in 'signature' */
1191 if (0 != (rc = key_from_sexp (rs, result, "sig-val", "rs")))
1192 {
1193 GNUNET_break (0);
1194 gcry_sexp_release (result);
1195 return GNUNET_SYSERR;
1196 }
1197 gcry_sexp_release (result);
1198 size = sizeof (signature->sig_r);
1199 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_r, size,
1200 &size, rs[0])))
1201 {
1202 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1203 gcry_mpi_release (rs[0]);
1204 gcry_mpi_release (rs[1]);
1205 return GNUNET_SYSERR;
1206 }
1207 gcry_mpi_release (rs[0]);
1208 size = sizeof (signature->sig_s);
1209 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_s, size,
1210 &size, rs[1])))
1211 {
1212 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1213 gcry_mpi_release (rs[1]);
1214 return GNUNET_SYSERR;
1215 }
1216 gcry_mpi_release (rs[1]);
1217 return GNUNET_OK;
1218}
1219
1220
1221/**
1222 * Get an ECC context (with Q set to the respective public key) from
1223 * a pseudonym.
1224 *
1225 * @param pseudonym with information on 'q'
1226 * @return curve context
1227 */
1228static gcry_ctx_t
1229get_context_from_pseudonym (struct GNUNET_PseudonymIdentifier *pseudonym)
1230{
1231 gcry_ctx_t ctx;
1232 gcry_mpi_t ONE;
1233 gcry_mpi_t q_x;
1234 gcry_mpi_t q_y;
1235 gcry_mpi_point_t q;
1236 size_t size;
1237 int rc;
1238
1239 /* extract 'q' from pseudonym */
1240 size = sizeof (pseudonym->q_x);
1241 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, pseudonym->q_x, size, &size)))
1242 {
1243 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1244 return NULL;
1245 }
1246 size = sizeof (pseudonym->q_y);
1247 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, pseudonym->q_y, size, &size)))
1248 {
1249 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1250 gcry_mpi_release (q_x);
1251 return NULL;
1252 }
1253 q = gcry_mpi_point_new (256);
1254 ONE = gcry_mpi_new (1);
1255 gcry_mpi_set_ui (ONE, 1);
1256 gcry_mpi_point_set (q, q_x, q_y, ONE); /* FIXME: convenience function 'set_affine'? */
1257 gcry_mpi_release (ONE);
1258 gcry_mpi_release (q_x);
1259 gcry_mpi_release (q_y);
1260
1261 /* create basic ECC context */
1262 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1263 {
1264 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1265 gcry_mpi_point_release (q);
1266 return NULL;
1267 }
1268 /* initialize 'ctx' with 'q' */
1269 gcry_mpi_ec_set_point ("q", q, ctx);
1270 gcry_mpi_point_release (q);
1271 return ctx;
1272}
1273
1274
1275/**
1276 * Given a pseudonym and a signing key, derive the corresponding public
1277 * key that would be used to verify the resulting signature.
1278 *
1279 * @param pseudonym the public key (g^x in DSA, dQ in ECDSA)
1280 * @param signing_key input to derive 'h' (see section 2.4 of #2564)
1281 * @param verification_key resulting public key to verify the signature
1282 * created from the 'ph' of 'pseudonym' and the 'signing_key';
1283 * the value stored here can then be given to GNUNET_PSEUDONYM_verify.
1284 * @return GNUNET_OK on success, GNUNET_SYSERR on error
1285 */
1286int
1287GNUNET_PSEUDONYM_derive_verification_key (struct GNUNET_PseudonymIdentifier *pseudonym,
1288 const struct GNUNET_HashCode *signing_key,
1289 struct GNUNET_PseudonymIdentifier *verification_key)
1290{
1291 gcry_mpi_t h;
1292 size_t size;
1293 int rc;
1294 gcry_ctx_t ctx;
1295 gcry_mpi_point_t g;
1296 gcry_mpi_point_t q;
1297 gcry_mpi_point_t hg;
1298 gcry_mpi_point_t v;
1299 gcry_mpi_t v_x;
1300 gcry_mpi_t v_y;
1301
1302 /* get 'h' value from signing key */
1303 size = sizeof (struct GNUNET_HashCode);
1304 if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG,
1305 signing_key,
1306 size, &size)))
1307 {
1308 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1309 return GNUNET_SYSERR;
1310 }
1311 /* create ECC context based on Q from pseudonym */
1312 if (NULL == (ctx = get_context_from_pseudonym (pseudonym)))
1313 {
1314 gcry_mpi_release (h);
1315 return GNUNET_SYSERR;
1316 }
1317 /* get G */
1318 g = gcry_mpi_ec_get_point ("g", ctx, 0);
1319
1320 /* then call the 'multiply' function, to compute the product hG */
1321 hg = gcry_mpi_point_new (0);
1322 gcry_mpi_ec_mul (hg, h, g, ctx);
1323 gcry_mpi_release (h);
1324
1325 /* get Q = dG from 'pseudonym' */
1326 q = gcry_mpi_ec_get_point ("q", ctx, 0);
1327
1328 /* calculate V = q + hG = dG + hG */
1329 v = gcry_mpi_point_new (0);
1330 gcry_mpi_ec_add (v, q, hg, ctx);
1331
1332 /* store 'v' point in "verification_key" */
1333 v_x = gcry_mpi_new (256);
1334 v_y = gcry_mpi_new (256);
1335 gcry_mpi_ec_get_affine (v_x, v_y, v, ctx);
1336 gcry_mpi_point_release (v);
1337 gcry_ctx_release (ctx);
1338
1339 size = sizeof (verification_key->q_x);
1340 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_x, size,
1341 &size, v_x)))
1342 {
1343 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1344 gcry_mpi_release (v_x);
1345 gcry_mpi_release (v_y);
1346 return GNUNET_SYSERR;
1347 }
1348 gcry_mpi_release (v_x);
1349 size = sizeof (verification_key->q_y);
1350 if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_y, size,
1351 &size, v_y)))
1352 {
1353 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc);
1354 gcry_mpi_release (v_y);
1355 return GNUNET_SYSERR;
1356 }
1357 gcry_mpi_release (v_y);
1358 return GNUNET_OK;
1359}
1360
1361
1362/**
1363 * Verify a signature made with a pseudonym.
1364 *
1365 * @param purpose data that was signed
1366 * @param signature signature to verify
1367 * @param verification_key public key to use for checking the signature;
1368 * corresponds to 'g^(x+h)' in section 2.4 of #2564.
1369 * @return GNUNET_OK on success (signature valid, 'pseudonym' set),
1370 * GNUNET_SYSERR if the signature is invalid
1371 */
1372int
1373GNUNET_PSEUDONYM_verify (const struct GNUNET_PseudonymSignaturePurpose *purpose,
1374 const struct GNUNET_PseudonymSignature *signature,
1375 const struct GNUNET_PseudonymIdentifier *verification_key)
1376{
1377 gcry_sexp_t data;
1378 gcry_sexp_t sig_sexpr;
1379 gcry_sexp_t pk_sexpr;
1380 size_t size;
1381 gcry_ctx_t ctx;
1382 gcry_mpi_t ONE;
1383 gcry_mpi_t r;
1384 gcry_mpi_t s;
1385 gcry_mpi_point_t q;
1386 gcry_mpi_t q_x;
1387 gcry_mpi_t q_y;
1388 size_t erroff;
1389 int rc;
1390
1391 /* build s-expression for signature */
1392 size = sizeof (signature->sig_r);
1393 if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG,
1394 signature->sig_r, size, &size)))
1395 {
1396 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1397 return GNUNET_SYSERR;
1398 }
1399 size = sizeof (signature->sig_s);
1400 if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG,
1401 signature->sig_s, size, &size)))
1402 {
1403 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1404 gcry_mpi_release (r);
1405 return GNUNET_SYSERR;
1406 }
1407 if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))",
1408 r, s)))
1409 {
1410 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
1411 gcry_mpi_release (r);
1412 gcry_mpi_release (s);
1413 return GNUNET_SYSERR;
1414 }
1415 gcry_mpi_release (r);
1416 gcry_mpi_release (s);
1417
1418 /* build s-expression for data that was signed */
1419 data = data_to_pkcs1 (purpose);
1420
1421 /* create context of public key and initialize Q */
1422 size = sizeof (verification_key->q_x);
1423 if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG,
1424 verification_key->q_x, size, &size)))
1425 {
1426 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1427 gcry_sexp_release (data);
1428 gcry_sexp_release (sig_sexpr);
1429 return GNUNET_SYSERR;
1430 }
1431 size = sizeof (verification_key->q_y);
1432 if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG,
1433 verification_key->q_y, size, &size)))
1434 {
1435 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1436 gcry_sexp_release (data);
1437 gcry_sexp_release (sig_sexpr);
1438 gcry_mpi_release (q_x);
1439 return GNUNET_SYSERR;
1440 }
1441 q = gcry_mpi_point_new (256);
1442 ONE = gcry_mpi_new (1);
1443 gcry_mpi_set_ui (ONE, 1);
1444 gcry_mpi_point_set (q, q_x, q_y, ONE); /* FIXME: convenience function 'set_affine'? */
1445 gcry_mpi_release (ONE);
1446 gcry_mpi_release (q_x);
1447 gcry_mpi_release (q_y);
1448
1449 /* create basic ECC context */
1450 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256")))
1451 {
1452 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
1453 gcry_sexp_release (data);
1454 gcry_sexp_release (sig_sexpr);
1455 gcry_mpi_point_release (q);
1456 return GNUNET_SYSERR;
1457 }
1458 /* initialize 'ctx' with 'q' */
1459 gcry_mpi_ec_set_point ("q", q, ctx);
1460 gcry_mpi_point_release (q);
1461
1462 /* convert 'ctx' to 'sexp' */
1463 if (0 != (rc = gcry_pubkey_get_sexp (&pk_sexpr, GCRY_PK_GET_PUBKEY, ctx)))
1464 {
1465 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc);
1466 gcry_ctx_release (ctx);
1467 gcry_sexp_release (data);
1468 gcry_sexp_release (sig_sexpr);
1469 return GNUNET_SYSERR;
1470 }
1471 gcry_ctx_release (ctx);
1472
1473 /* finally, verify the signature */
1474 rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr);
1475 gcry_sexp_release (sig_sexpr);
1476 gcry_sexp_release (data);
1477 gcry_sexp_release (pk_sexpr);
1478 if (rc)
1479 {
1480 LOG (GNUNET_ERROR_TYPE_WARNING,
1481 _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
1482 __LINE__, gcry_strerror (rc));
1483 return GNUNET_SYSERR;
1484 }
1485 return GNUNET_OK;
1486}
1487
1488
1489/**
1490 * Get the identifier (public key) of a pseudonym.
1491 *
1492 * @param ph pseudonym handle with the private key
1493 * @param pseudonym pseudonym identifier (set based on 'ph')
1494 */
1495void
1496GNUNET_PSEUDONYM_get_identifier (struct GNUNET_PseudonymHandle *ph,
1497 struct GNUNET_PseudonymIdentifier *pseudonym)
1498{
1499 memcpy (pseudonym, &ph->public_key,
1500 sizeof (struct GNUNET_PseudonymIdentifier));
1501}
1502
1503
1504/**
1505 * Remove pseudonym from the set of known pseudonyms.
1506 *
1507 * @param cfg overall configuration
1508 * @param id the pseudonym identifier
1509 * @return GNUNET_OK on success, GNUNET_SYSERR on failure
1510 */
1511int
1512GNUNET_PSEUDONYM_remove (const struct GNUNET_CONFIGURATION_Handle *cfg,
1513 const struct GNUNET_PseudonymIdentifier *id)
1514{
1515 char *fn;
1516 int result;
1517
1518 fn = get_data_filename (cfg, PS_METADATA_DIR, id);
1519 if (NULL == fn)
1520 return GNUNET_SYSERR;
1521 result = UNLINK (fn);
1522 GNUNET_free (fn);
1523 return (0 == result) ? GNUNET_OK : GNUNET_SYSERR;
1524}
1525
1526/* end of pseudonym.c */
diff --git a/src/util/test_pseudonym.c b/src/util/test_pseudonym.c
deleted file mode 100644
index a3b3f3fdb..000000000
--- a/src/util/test_pseudonym.c
+++ /dev/null
@@ -1,323 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2005--2013 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19*/
20
21/**
22 * @file util/test_pseudonym.c
23 * @brief testcase for pseudonym.c
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_common.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_signatures.h"
30
31#define CHECK(a) do { if (!(a)) { ok = GNUNET_NO; GNUNET_break(0); goto FAILURE; } } while (0)
32
33static struct GNUNET_CONTAINER_MetaData *meta;
34
35static struct GNUNET_PseudonymIdentifier id1;
36
37
38static int
39iter (void *cls, const struct GNUNET_PseudonymIdentifier * pseudonym,
40 const char *name, const char *unique_name,
41 const struct GNUNET_CONTAINER_MetaData *md, int32_t rating)
42{
43 int *ok = cls;
44
45 if ((0 == memcmp (pseudonym, &id1, sizeof (struct GNUNET_PseudonymIdentifier))) &&
46 (!GNUNET_CONTAINER_meta_data_test_equal (md, meta)))
47 {
48 *ok = GNUNET_NO;
49 GNUNET_break (0);
50 }
51 return GNUNET_OK;
52}
53
54
55static int
56noti_callback (void *cls, const struct GNUNET_PseudonymIdentifier * pseudonym,
57 const char *name, const char *unique_name,
58 const struct GNUNET_CONTAINER_MetaData *md, int32_t rating)
59{
60 int *ret = cls;
61
62 (*ret)++;
63 return GNUNET_OK;
64}
65
66
67static int
68fake_noti_callback (void *cls, const struct GNUNET_PseudonymIdentifier * pseudonym,
69 const char *name, const char *unique_name,
70 const struct GNUNET_CONTAINER_MetaData *md, int32_t rating)
71{
72 int *ret = cls;
73
74 (*ret)++;
75 return GNUNET_OK;
76}
77
78
79static void
80create_pseu (struct GNUNET_PseudonymIdentifier *pseu)
81{
82 struct GNUNET_PseudonymHandle *ph;
83
84 ph = GNUNET_PSEUDONYM_create (NULL);
85 GNUNET_PSEUDONYM_get_identifier (ph, pseu);
86 GNUNET_PSEUDONYM_destroy (ph);
87}
88
89
90/**
91 * Testcase for meta data / ranking IO routines.
92 */
93static int
94test_io ()
95{
96 int ok;
97 struct GNUNET_PseudonymIdentifier rid1;
98 struct GNUNET_PseudonymIdentifier id2;
99 struct GNUNET_PseudonymIdentifier rid2;
100 struct GNUNET_PseudonymIdentifier fid;
101 struct GNUNET_PseudonymIdentifier id3;
102 int old;
103 int newVal;
104 struct GNUNET_CONFIGURATION_Handle *cfg;
105 char *name1;
106 char *name2;
107 char *name3;
108 char *name1_unique;
109 char *name2_unique;
110 char *noname;
111 int noname_is_a_dup;
112 int notiCount, fakenotiCount;
113 static char m[1024 * 1024 * 10];
114 struct GNUNET_PSEUDONYM_DiscoveryHandle *dh1;
115 struct GNUNET_PSEUDONYM_DiscoveryHandle *dh2;
116
117 memset (m, 'b', sizeof (m));
118 m[sizeof (m) - 1] = '\0';
119
120 GNUNET_log_setup ("test-pseudonym", "WARNING", NULL);
121 ok = GNUNET_YES;
122 (void) GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test");
123 cfg = GNUNET_CONFIGURATION_create ();
124 if (-1 == GNUNET_CONFIGURATION_parse (cfg, "test_pseudonym_data.conf"))
125 {
126 GNUNET_CONFIGURATION_destroy (cfg);
127 GNUNET_break (0);
128 return -1;
129 }
130 notiCount = 0;
131 fakenotiCount = 0;
132 dh1 = GNUNET_PSEUDONYM_discovery_callback_register (cfg, &fake_noti_callback,
133 &fakenotiCount);
134 dh2 = GNUNET_PSEUDONYM_discovery_callback_register (cfg, &noti_callback,
135 &notiCount);
136 GNUNET_PSEUDONYM_discovery_callback_unregister (dh1);
137
138 /* ACTUAL TEST CODE */
139 old = GNUNET_PSEUDONYM_list_all (cfg, NULL, NULL);
140 meta = GNUNET_CONTAINER_meta_data_create ();
141 GNUNET_CONTAINER_meta_data_insert (meta, "<test>", EXTRACTOR_METATYPE_TITLE,
142 EXTRACTOR_METAFORMAT_UTF8, "text/plain",
143 "test", strlen ("test") + 1);
144 create_pseu (&id1);
145 GNUNET_PSEUDONYM_add (cfg, &id1, meta);
146 CHECK (notiCount == 1);
147 GNUNET_PSEUDONYM_add (cfg, &id1, meta);
148 CHECK (notiCount == 2);
149 newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
150 CHECK (old < newVal);
151 old = newVal;
152 create_pseu (&id2);
153 GNUNET_PSEUDONYM_add (cfg, &id2, meta);
154 CHECK (notiCount == 3);
155 newVal = GNUNET_PSEUDONYM_list_all (cfg, &iter, &ok);
156 CHECK (old < newVal);
157 GNUNET_assert (GNUNET_OK ==
158 GNUNET_CONTAINER_meta_data_insert (meta, "<test>",
159 EXTRACTOR_METATYPE_COMMENT,
160 EXTRACTOR_METAFORMAT_UTF8,
161 "text/plain", m,
162 strlen (m) + 1));
163 create_pseu (&id3);
164 GNUNET_PSEUDONYM_add (cfg, &id3, meta);
165 GNUNET_PSEUDONYM_get_info (cfg, &id3, NULL, NULL, &name3, NULL);
166 CHECK (name3 != NULL);
167 GNUNET_PSEUDONYM_get_info (cfg, &id2, NULL, NULL, &name2, NULL);
168 CHECK (name2 != NULL);
169 GNUNET_PSEUDONYM_get_info (cfg, &id1, NULL, NULL, &name1, NULL);
170 CHECK (name1 != NULL);
171 CHECK (0 == strcmp (name1, name2));
172 name1_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id1, name1, NULL);
173 name2_unique = GNUNET_PSEUDONYM_name_uniquify (cfg, &id2, name2, NULL);
174 CHECK (0 != strcmp (name1_unique, name2_unique));
175 CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, "fake", &rid2));
176 CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name2, &rid2));
177 CHECK (GNUNET_SYSERR == GNUNET_PSEUDONYM_name_to_id (cfg, name1, &rid1));
178 CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name2_unique, &rid2));
179 CHECK (GNUNET_OK == GNUNET_PSEUDONYM_name_to_id (cfg, name1_unique, &rid1));
180 CHECK (0 == memcmp (&id1, &rid1, sizeof (struct GNUNET_PseudonymIdentifier)));
181 CHECK (0 == memcmp (&id2, &rid2, sizeof (struct GNUNET_PseudonymIdentifier)));
182
183 create_pseu (&fid);
184 GNUNET_log_skip (1, GNUNET_NO);
185 CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &fid, 0));
186 GNUNET_log_skip (0, GNUNET_NO);
187 CHECK (GNUNET_OK == GNUNET_PSEUDONYM_get_info (cfg, &fid, NULL, NULL, &noname, &noname_is_a_dup));
188 CHECK (noname != NULL);
189 CHECK (noname_is_a_dup == GNUNET_YES);
190 CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 0));
191 CHECK (5 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
192 CHECK (-5 == GNUNET_PSEUDONYM_rank (cfg, &id1, -10));
193 CHECK (0 == GNUNET_PSEUDONYM_rank (cfg, &id1, 5));
194 GNUNET_free (name1);
195 GNUNET_free (name2);
196 GNUNET_free (name1_unique);
197 GNUNET_free (name2_unique);
198 GNUNET_free (name3);
199 GNUNET_free (noname);
200 /* END OF TEST CODE */
201FAILURE:
202 GNUNET_PSEUDONYM_discovery_callback_unregister (dh2);
203 GNUNET_CONTAINER_meta_data_destroy (meta);
204 GNUNET_CONFIGURATION_destroy (cfg);
205 return (ok == GNUNET_YES) ? 0 : 1;
206}
207
208
209/**
210 * Use the given input to sign and check the resulting signature.
211 */
212static void
213test_signature (struct GNUNET_PseudonymHandle *ph,
214 struct GNUNET_PseudonymSignaturePurpose *purpose,
215 struct GNUNET_HashCode *seed,
216 struct GNUNET_HashCode *signing_key,
217 char *bit)
218{
219 struct GNUNET_PseudonymSignature signature;
220 struct GNUNET_PseudonymSignature signature2;
221 struct GNUNET_PseudonymIdentifier pseudonym;
222 struct GNUNET_PseudonymIdentifier verification_key;
223
224 GNUNET_PSEUDONYM_sign (ph, purpose, seed, signing_key, &signature);
225 GNUNET_PSEUDONYM_sign (ph, purpose, seed, signing_key, &signature2);
226 /* with seed, two sigs must be identical, without, they must be different! */
227 if (NULL != seed)
228 GNUNET_break (0 == memcmp (&signature, &signature2, sizeof (signature)));
229 else /* crypto not implemented, thus for now 'break' */
230 GNUNET_break (0 != memcmp (&signature, &signature2, sizeof (signature)));
231 GNUNET_PSEUDONYM_get_identifier (ph, &pseudonym);
232 GNUNET_PSEUDONYM_derive_verification_key (&pseudonym,
233 signing_key,
234 &verification_key);
235 GNUNET_break (GNUNET_OK ==
236 GNUNET_PSEUDONYM_verify (purpose, &signature, &verification_key));
237 /* also check that if the data is changed, the signature no longer matches */
238 (*bit)++;
239 /* crypto not implemented, thus for now 'break' */
240 GNUNET_break (GNUNET_OK !=
241 GNUNET_PSEUDONYM_verify (purpose, &signature, &verification_key));
242 (*bit)--;
243}
244
245
246/**
247 * Test cryptographic operations for a given private key.
248 *
249 * @param ph private key to test
250 */
251static void
252test_crypto_ops (struct GNUNET_PseudonymHandle *ph)
253{
254 char data[16];
255 struct GNUNET_PseudonymSignaturePurpose *purpose;
256 struct GNUNET_HashCode seed;
257 struct GNUNET_HashCode signing_key;
258
259 memset (data, 42, sizeof (data));
260 purpose = (struct GNUNET_PseudonymSignaturePurpose *) data;
261 purpose->size = htonl (sizeof (data));
262 purpose->purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST);
263 memset (&seed, 41, sizeof (seed));
264 memset (&signing_key, 40, sizeof (signing_key));
265 test_signature (ph, purpose, &seed, &signing_key, &data[sizeof (struct GNUNET_PseudonymSignaturePurpose)]);
266 test_signature (ph, purpose, NULL, &signing_key, &data[sizeof (struct GNUNET_PseudonymSignaturePurpose)]);
267}
268
269
270/**
271 * Test cryptographic operations.
272 */
273static int
274test_crypto ()
275{
276 struct GNUNET_PseudonymHandle *ph;
277 struct GNUNET_PseudonymIdentifier pseudonym;
278 struct GNUNET_PseudonymIdentifier pseudonym2;
279
280 /* check writing to and reading from disk */
281 ph = GNUNET_PSEUDONYM_create ("/tmp/gnunet-pseudonym-test/pseu.dsa");
282 GNUNET_PSEUDONYM_get_identifier (ph, &pseudonym);
283 GNUNET_PSEUDONYM_destroy (ph);
284 ph = GNUNET_PSEUDONYM_create ("/tmp/gnunet-pseudonym-test/pseu.dsa");
285 GNUNET_PSEUDONYM_get_identifier (ph, &pseudonym2);
286 test_crypto_ops (ph);
287 GNUNET_PSEUDONYM_destroy (ph);
288 if (0 != memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym)))
289 return 1;
290
291 /* check in-memory generation */
292 ph = GNUNET_PSEUDONYM_create (NULL);
293 GNUNET_PSEUDONYM_get_identifier (ph, &pseudonym2);
294 if (0 == memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym)))
295 return 1;
296 test_crypto_ops (ph);
297 GNUNET_PSEUDONYM_destroy (ph);
298
299 /* check anonymous pseudonym operations generation */
300 ph = GNUNET_PSEUDONYM_get_anonymous_pseudonym_handle ();
301 GNUNET_PSEUDONYM_get_identifier (ph, &pseudonym2);
302 if (0 == memcmp (&pseudonym, &pseudonym2, sizeof (pseudonym)))
303 return 1;
304 test_crypto_ops (ph);
305 GNUNET_PSEUDONYM_destroy (ph);
306 return 0;
307}
308
309
310int
311main (int argc, char *argv[])
312{
313 if (0 != test_io ())
314 return 1;
315 if (0 != test_crypto ())
316 return 1;
317 GNUNET_break (GNUNET_OK ==
318 GNUNET_DISK_directory_remove ("/tmp/gnunet-pseudonym-test"));
319 return 0;
320}
321
322
323/* end of test_pseudoynm.c */