diff options
Diffstat (limited to 'src/fs/fs_pseudonym.c')
-rw-r--r-- | src/fs/fs_pseudonym.c | 977 |
1 files changed, 39 insertions, 938 deletions
diff --git a/src/fs/fs_pseudonym.c b/src/fs/fs_pseudonym.c index 36eaab6fa..f5493ca16 100644 --- a/src/fs/fs_pseudonym.c +++ b/src/fs/fs_pseudonym.c | |||
@@ -21,15 +21,10 @@ | |||
21 | * @file fs/fs_pseudonym.c | 21 | * @file fs/fs_pseudonym.c |
22 | * @brief pseudonym functions | 22 | * @brief pseudonym functions |
23 | * @author Christian Grothoff | 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 | */ | 24 | */ |
29 | #include "platform.h" | 25 | #include "platform.h" |
30 | #include "gnunet_util_lib.h" | 26 | #include "gnunet_util_lib.h" |
31 | #include "gnunet_fs_service.h" | 27 | #include "gnunet_fs_service.h" |
32 | #include <gcrypt.h> | ||
33 | 28 | ||
34 | 29 | ||
35 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) | 30 | #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) |
@@ -38,12 +33,6 @@ | |||
38 | 33 | ||
39 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) | 34 | #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) |
40 | 35 | ||
41 | /** | ||
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). | ||
45 | */ | ||
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); | ||
47 | 36 | ||
48 | /** | 37 | /** |
49 | * Name of the directory which stores meta data for pseudonym | 38 | * Name of the directory which stores meta data for pseudonym |
@@ -67,17 +56,17 @@ | |||
67 | /** | 56 | /** |
68 | * Registered callbacks for discovery of pseudonyms. | 57 | * Registered callbacks for discovery of pseudonyms. |
69 | */ | 58 | */ |
70 | struct GNUNET_FS_pseudonym_DiscoveryHandle | 59 | struct GNUNET_FS_Pseudonym_DiscoveryHandle |
71 | { | 60 | { |
72 | /** | 61 | /** |
73 | * This is a doubly linked list. | 62 | * This is a doubly linked list. |
74 | */ | 63 | */ |
75 | struct GNUNET_FS_pseudonym_DiscoveryHandle *next; | 64 | struct GNUNET_FS_Pseudonym_DiscoveryHandle *next; |
76 | 65 | ||
77 | /** | 66 | /** |
78 | * This is a doubly linked list. | 67 | * This is a doubly linked list. |
79 | */ | 68 | */ |
80 | struct GNUNET_FS_pseudonym_DiscoveryHandle *prev; | 69 | struct GNUNET_FS_Pseudonym_DiscoveryHandle *prev; |
81 | 70 | ||
82 | /** | 71 | /** |
83 | * Function to call each time a pseudonym is discovered. | 72 | * Function to call each time a pseudonym is discovered. |
@@ -95,19 +84,14 @@ struct GNUNET_FS_pseudonym_DiscoveryHandle | |||
95 | * Head of the linked list of functions to call when | 84 | * Head of the linked list of functions to call when |
96 | * new pseudonyms are added. | 85 | * new pseudonyms are added. |
97 | */ | 86 | */ |
98 | static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_head; | 87 | static struct GNUNET_FS_Pseudonym_DiscoveryHandle *disco_head; |
99 | 88 | ||
100 | /** | 89 | /** |
101 | * Tail of the linked list of functions to call when | 90 | * Tail of the linked list of functions to call when |
102 | * new pseudonyms are added. | 91 | * new pseudonyms are added. |
103 | */ | 92 | */ |
104 | static struct GNUNET_FS_pseudonym_DiscoveryHandle *disco_tail; | 93 | static struct GNUNET_FS_Pseudonym_DiscoveryHandle *disco_tail; |
105 | 94 | ||
106 | /** | ||
107 | * Pointer to indiate 'anonymous' pseudonym (global static, | ||
108 | * d=1, public key = G (generator). | ||
109 | */ | ||
110 | static struct GNUNET_FS_PseudonymHandle anonymous; | ||
111 | 95 | ||
112 | /** | 96 | /** |
113 | * Internal notification about new tracked URI. | 97 | * Internal notification about new tracked URI. |
@@ -117,10 +101,10 @@ static struct GNUNET_FS_PseudonymHandle anonymous; | |||
117 | * @param rating rating of pseudonym | 101 | * @param rating rating of pseudonym |
118 | */ | 102 | */ |
119 | static void | 103 | static void |
120 | internal_notify (const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 104 | internal_notify (const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
121 | const struct GNUNET_CONTAINER_MetaData *md, int rating) | 105 | const struct GNUNET_CONTAINER_MetaData *md, int rating) |
122 | { | 106 | { |
123 | struct GNUNET_FS_pseudonym_DiscoveryHandle *pos; | 107 | struct GNUNET_FS_Pseudonym_DiscoveryHandle *pos; |
124 | 108 | ||
125 | for (pos = disco_head; NULL != pos; pos = pos->next) | 109 | for (pos = disco_head; NULL != pos; pos = pos->next) |
126 | pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating); | 110 | pos->callback (pos->callback_cls, pseudonym, NULL, NULL, md, rating); |
@@ -138,15 +122,15 @@ internal_notify (const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | |||
138 | * @param iterator_cls point to a closure | 122 | * @param iterator_cls point to a closure |
139 | * @return registration handle | 123 | * @return registration handle |
140 | */ | 124 | */ |
141 | struct GNUNET_FS_pseudonym_DiscoveryHandle * | 125 | struct GNUNET_FS_Pseudonym_DiscoveryHandle * |
142 | GNUNET_FS_pseudonym_discovery_callback_register (const struct | 126 | GNUNET_FS_pseudonym_discovery_callback_register (const struct |
143 | GNUNET_CONFIGURATION_Handle *cfg, | 127 | GNUNET_CONFIGURATION_Handle *cfg, |
144 | GNUNET_FS_PseudonymIterator iterator, | 128 | GNUNET_FS_PseudonymIterator iterator, |
145 | void *iterator_cls) | 129 | void *iterator_cls) |
146 | { | 130 | { |
147 | struct GNUNET_FS_pseudonym_DiscoveryHandle *dh; | 131 | struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh; |
148 | 132 | ||
149 | dh = GNUNET_malloc (sizeof (struct GNUNET_FS_pseudonym_DiscoveryHandle)); | 133 | dh = GNUNET_new (struct GNUNET_FS_Pseudonym_DiscoveryHandle); |
150 | dh->callback = iterator; | 134 | dh->callback = iterator; |
151 | dh->callback_cls = iterator_cls; | 135 | dh->callback_cls = iterator_cls; |
152 | GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh); | 136 | GNUNET_CONTAINER_DLL_insert (disco_head, disco_tail, dh); |
@@ -161,7 +145,7 @@ GNUNET_FS_pseudonym_discovery_callback_register (const struct | |||
161 | * @param dh registration to unregister | 145 | * @param dh registration to unregister |
162 | */ | 146 | */ |
163 | void | 147 | void |
164 | GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_DiscoveryHandle *dh) | 148 | GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_Pseudonym_DiscoveryHandle *dh) |
165 | { | 149 | { |
166 | GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh); | 150 | GNUNET_CONTAINER_DLL_remove (disco_head, disco_tail, dh); |
167 | GNUNET_free (dh); | 151 | GNUNET_free (dh); |
@@ -180,7 +164,7 @@ GNUNET_FS_pseudonym_discovery_callback_unregister (struct GNUNET_FS_pseudonym_Di | |||
180 | static char * | 164 | static char * |
181 | get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, | 165 | get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, |
182 | const char *prefix, | 166 | const char *prefix, |
183 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym) | 167 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym) |
184 | { | 168 | { |
185 | struct GNUNET_CRYPTO_HashAsciiEncoded enc; | 169 | struct GNUNET_CRYPTO_HashAsciiEncoded enc; |
186 | struct GNUNET_HashCode psid; | 170 | struct GNUNET_HashCode psid; |
@@ -188,7 +172,7 @@ get_data_filename (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
188 | if (NULL != pseudonym) | 172 | if (NULL != pseudonym) |
189 | { | 173 | { |
190 | GNUNET_CRYPTO_hash (pseudonym, | 174 | GNUNET_CRYPTO_hash (pseudonym, |
191 | sizeof (struct GNUNET_FS_PseudonymIdentifier), | 175 | sizeof (struct GNUNET_CRYPTO_EccPublicKey), |
192 | &psid); | 176 | &psid); |
193 | GNUNET_CRYPTO_hash_to_enc (&psid, &enc); | 177 | GNUNET_CRYPTO_hash_to_enc (&psid, &enc); |
194 | } | 178 | } |
@@ -243,7 +227,7 @@ get_data_filename_hash (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
243 | */ | 227 | */ |
244 | int | 228 | int |
245 | GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | 229 | GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, |
246 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 230 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
247 | const char *name, | 231 | const char *name, |
248 | const struct GNUNET_CONTAINER_MetaData *md, | 232 | const struct GNUNET_CONTAINER_MetaData *md, |
249 | int32_t rank) | 233 | int32_t rank) |
@@ -258,7 +242,7 @@ GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
258 | return GNUNET_SYSERR; | 242 | return GNUNET_SYSERR; |
259 | } | 243 | } |
260 | if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym, | 244 | if ((GNUNET_OK != GNUNET_BIO_write (fileW, pseudonym, |
261 | sizeof (struct GNUNET_FS_PseudonymIdentifier))) || | 245 | sizeof (struct GNUNET_CRYPTO_EccPublicKey))) || |
262 | (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) || | 246 | (GNUNET_OK != GNUNET_BIO_write_int32 (fileW, rank)) || |
263 | (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) || | 247 | (GNUNET_OK != GNUNET_BIO_write_string (fileW, name)) || |
264 | (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md))) | 248 | (GNUNET_OK != GNUNET_BIO_write_meta_data (fileW, md))) |
@@ -295,12 +279,12 @@ GNUNET_FS_pseudonym_set_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
295 | */ | 279 | */ |
296 | static int | 280 | static int |
297 | read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | 281 | read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, |
298 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 282 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
299 | struct GNUNET_CONTAINER_MetaData **meta, | 283 | struct GNUNET_CONTAINER_MetaData **meta, |
300 | int32_t *rank, | 284 | int32_t *rank, |
301 | char **ns_name) | 285 | char **ns_name) |
302 | { | 286 | { |
303 | struct GNUNET_FS_PseudonymIdentifier pd; | 287 | struct GNUNET_CRYPTO_EccPublicKey pd; |
304 | char *fn; | 288 | char *fn; |
305 | char *emsg; | 289 | char *emsg; |
306 | struct GNUNET_BIO_ReadHandle *fileR; | 290 | struct GNUNET_BIO_ReadHandle *fileR; |
@@ -367,12 +351,12 @@ read_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
367 | */ | 351 | */ |
368 | char * | 352 | char * |
369 | GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, | 353 | GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg, |
370 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 354 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
371 | const char *name, | 355 | const char *name, |
372 | unsigned int *suffix) | 356 | unsigned int *suffix) |
373 | { | 357 | { |
374 | struct GNUNET_HashCode nh; | 358 | struct GNUNET_HashCode nh; |
375 | struct GNUNET_FS_PseudonymIdentifier pi; | 359 | struct GNUNET_CRYPTO_EccPublicKey pi; |
376 | uint64_t len; | 360 | uint64_t len; |
377 | char *fn; | 361 | char *fn; |
378 | struct GNUNET_DISK_FileHandle *fh; | 362 | struct GNUNET_DISK_FileHandle *fh; |
@@ -393,11 +377,11 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg | |||
393 | GNUNET_DISK_PERM_USER_WRITE); | 377 | GNUNET_DISK_PERM_USER_WRITE); |
394 | i = 0; | 378 | i = 0; |
395 | idx = -1; | 379 | idx = -1; |
396 | while ((len >= sizeof (struct GNUNET_FS_PseudonymIdentifier)) && | 380 | while ((len >= sizeof (struct GNUNET_CRYPTO_EccPublicKey)) && |
397 | (sizeof (struct GNUNET_FS_PseudonymIdentifier) == | 381 | (sizeof (struct GNUNET_CRYPTO_EccPublicKey) == |
398 | GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_FS_PseudonymIdentifier)))) | 382 | GNUNET_DISK_file_read (fh, &pi, sizeof (struct GNUNET_CRYPTO_EccPublicKey)))) |
399 | { | 383 | { |
400 | if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) | 384 | if (0 == memcmp (&pi, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) |
401 | { | 385 | { |
402 | idx = i; | 386 | idx = i; |
403 | break; | 387 | break; |
@@ -408,8 +392,8 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg | |||
408 | if (-1 == idx) | 392 | if (-1 == idx) |
409 | { | 393 | { |
410 | idx = i; | 394 | idx = i; |
411 | if (sizeof (struct GNUNET_FS_PseudonymIdentifier) != | 395 | if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) != |
412 | GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) | 396 | GNUNET_DISK_file_write (fh, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) |
413 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn); | 397 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "write", fn); |
414 | } | 398 | } |
415 | GNUNET_DISK_file_close (fh); | 399 | GNUNET_DISK_file_close (fh); |
@@ -442,11 +426,11 @@ GNUNET_FS_pseudonym_name_uniquify (const struct GNUNET_CONFIGURATION_Handle *cfg | |||
442 | */ | 426 | */ |
443 | int | 427 | int |
444 | GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | 428 | GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, |
445 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 429 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
446 | struct GNUNET_CONTAINER_MetaData **ret_meta, | 430 | struct GNUNET_CONTAINER_MetaData **ret_meta, |
447 | int32_t *ret_rank, | 431 | int32_t *ret_rank, |
448 | char **ret_name, | 432 | char **ret_name, |
449 | int *name_is_a_dup) | 433 | int *name_is_a_dup) |
450 | { | 434 | { |
451 | struct GNUNET_CONTAINER_MetaData *meta; | 435 | struct GNUNET_CONTAINER_MetaData *meta; |
452 | char *name; | 436 | char *name; |
@@ -521,7 +505,7 @@ GNUNET_FS_pseudonym_get_info (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
521 | int | 505 | int |
522 | GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, | 506 | GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, |
523 | const char *ns_uname, | 507 | const char *ns_uname, |
524 | struct GNUNET_FS_PseudonymIdentifier *pseudonym) | 508 | struct GNUNET_CRYPTO_EccPublicKey *pseudonym) |
525 | { | 509 | { |
526 | size_t slen; | 510 | size_t slen; |
527 | uint64_t len; | 511 | uint64_t len; |
@@ -546,7 +530,7 @@ GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
546 | 530 | ||
547 | if ((GNUNET_OK != GNUNET_DISK_file_test (fn) || | 531 | if ((GNUNET_OK != GNUNET_DISK_file_test (fn) || |
548 | (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) || | 532 | (GNUNET_OK != GNUNET_DISK_file_size (fn, &len, GNUNET_YES, GNUNET_YES))) || |
549 | ((idx + 1) * sizeof (struct GNUNET_FS_PseudonymIdentifier) > len)) | 533 | ((idx + 1) * sizeof (struct GNUNET_CRYPTO_EccPublicKey) > len)) |
550 | { | 534 | { |
551 | GNUNET_free (fn); | 535 | GNUNET_free (fn); |
552 | return GNUNET_SYSERR; | 536 | return GNUNET_SYSERR; |
@@ -558,14 +542,14 @@ GNUNET_FS_pseudonym_name_to_id (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
558 | GNUNET_DISK_PERM_USER_WRITE); | 542 | GNUNET_DISK_PERM_USER_WRITE); |
559 | GNUNET_free (fn); | 543 | GNUNET_free (fn); |
560 | if (GNUNET_SYSERR == | 544 | if (GNUNET_SYSERR == |
561 | GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_FS_PseudonymIdentifier), | 545 | GNUNET_DISK_file_seek (fh, idx * sizeof (struct GNUNET_CRYPTO_EccPublicKey), |
562 | GNUNET_DISK_SEEK_SET)) | 546 | GNUNET_DISK_SEEK_SET)) |
563 | { | 547 | { |
564 | GNUNET_DISK_file_close (fh); | 548 | GNUNET_DISK_file_close (fh); |
565 | return GNUNET_SYSERR; | 549 | return GNUNET_SYSERR; |
566 | } | 550 | } |
567 | if (sizeof (struct GNUNET_FS_PseudonymIdentifier) != | 551 | if (sizeof (struct GNUNET_CRYPTO_EccPublicKey) != |
568 | GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_FS_PseudonymIdentifier))) | 552 | GNUNET_DISK_file_read (fh, pseudonym, sizeof (struct GNUNET_CRYPTO_EccPublicKey))) |
569 | { | 553 | { |
570 | GNUNET_DISK_file_close (fh); | 554 | GNUNET_DISK_file_close (fh); |
571 | return GNUNET_SYSERR; | 555 | return GNUNET_SYSERR; |
@@ -610,7 +594,7 @@ static int | |||
610 | list_pseudonym_helper (void *cls, const char *fullname) | 594 | list_pseudonym_helper (void *cls, const char *fullname) |
611 | { | 595 | { |
612 | struct ListPseudonymClosure *lpc = cls; | 596 | struct ListPseudonymClosure *lpc = cls; |
613 | struct GNUNET_FS_PseudonymIdentifier pd; | 597 | struct GNUNET_CRYPTO_EccPublicKey pd; |
614 | char *emsg; | 598 | char *emsg; |
615 | struct GNUNET_BIO_ReadHandle *fileR; | 599 | struct GNUNET_BIO_ReadHandle *fileR; |
616 | int32_t rank; | 600 | int32_t rank; |
@@ -699,7 +683,7 @@ GNUNET_FS_pseudonym_list_all (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
699 | */ | 683 | */ |
700 | int | 684 | int |
701 | GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, | 685 | GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, |
702 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 686 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
703 | int32_t delta) | 687 | int32_t delta) |
704 | { | 688 | { |
705 | struct GNUNET_CONTAINER_MetaData *meta; | 689 | struct GNUNET_CONTAINER_MetaData *meta; |
@@ -734,8 +718,8 @@ GNUNET_FS_pseudonym_rank (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
734 | */ | 718 | */ |
735 | int | 719 | int |
736 | GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, | 720 | GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, |
737 | const struct GNUNET_FS_PseudonymIdentifier *pseudonym, | 721 | const struct GNUNET_CRYPTO_EccPublicKey *pseudonym, |
738 | const struct GNUNET_CONTAINER_MetaData *meta) | 722 | const struct GNUNET_CONTAINER_MetaData *meta) |
739 | { | 723 | { |
740 | char *name; | 724 | char *name; |
741 | int32_t rank; | 725 | int32_t rank; |
@@ -766,888 +750,5 @@ GNUNET_FS_pseudonym_add (const struct GNUNET_CONFIGURATION_Handle *cfg, | |||
766 | } | 750 | } |
767 | 751 | ||
768 | 752 | ||
769 | /* ***************************** cryptographic operations ************************* */ | ||
770 | |||
771 | /** | ||
772 | * Handle for a pseudonym (private key). | ||
773 | */ | ||
774 | struct GNUNET_FS_PseudonymHandle | ||
775 | { | ||
776 | /** | ||
777 | * 256-bit 'd' secret value (mod 'n', where n is 256-bit for NIST P-256). | ||
778 | */ | ||
779 | unsigned char d[256 / 8]; | ||
780 | |||
781 | /** | ||
782 | * Public key corresponding to the private key. | ||
783 | */ | ||
784 | struct GNUNET_FS_PseudonymIdentifier public_key; | ||
785 | }; | ||
786 | |||
787 | |||
788 | /** | ||
789 | * If target != size, move target bytes to the end of the size-sized | ||
790 | * buffer and zero out the first target-size bytes. | ||
791 | * | ||
792 | * @param buf original buffer | ||
793 | * @param size number of bytes in the buffer | ||
794 | * @param target target size of the buffer | ||
795 | */ | ||
796 | static void | ||
797 | adjust (unsigned char *buf, size_t size, size_t target) | ||
798 | { | ||
799 | if (size < target) | ||
800 | { | ||
801 | memmove (&buf[target - size], buf, size); | ||
802 | memset (buf, 0, target - size); | ||
803 | } | ||
804 | } | ||
805 | |||
806 | |||
807 | /** | ||
808 | * Extract values from an S-expression. | ||
809 | * | ||
810 | * @param array where to store the result(s) | ||
811 | * @param sexp S-expression to parse | ||
812 | * @param topname top-level name in the S-expression that is of interest | ||
813 | * @param elems names of the elements to extract | ||
814 | * @return 0 on success | ||
815 | */ | ||
816 | static int | ||
817 | key_from_sexp (gcry_mpi_t * array, gcry_sexp_t sexp, const char *topname, | ||
818 | const char *elems) | ||
819 | { | ||
820 | gcry_sexp_t list; | ||
821 | gcry_sexp_t l2; | ||
822 | const char *s; | ||
823 | unsigned int i; | ||
824 | unsigned int idx; | ||
825 | |||
826 | if (! (list = gcry_sexp_find_token (sexp, topname, 0))) | ||
827 | return 1; | ||
828 | l2 = gcry_sexp_cadr (list); | ||
829 | gcry_sexp_release (list); | ||
830 | list = l2; | ||
831 | if (! list) | ||
832 | return 2; | ||
833 | idx = 0; | ||
834 | for (s = elems; *s; s++, idx++) | ||
835 | { | ||
836 | if (! (l2 = gcry_sexp_find_token (list, s, 1))) | ||
837 | { | ||
838 | for (i = 0; i < idx; i++) | ||
839 | { | ||
840 | gcry_free (array[i]); | ||
841 | array[i] = NULL; | ||
842 | } | ||
843 | gcry_sexp_release (list); | ||
844 | return 3; /* required parameter not found */ | ||
845 | } | ||
846 | array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG); | ||
847 | gcry_sexp_release (l2); | ||
848 | if (! array[idx]) | ||
849 | { | ||
850 | for (i = 0; i < idx; i++) | ||
851 | { | ||
852 | gcry_free (array[i]); | ||
853 | array[i] = NULL; | ||
854 | } | ||
855 | gcry_sexp_release (list); | ||
856 | return 4; /* required parameter is invalid */ | ||
857 | } | ||
858 | } | ||
859 | gcry_sexp_release (list); | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | |||
864 | /** | ||
865 | * Create a pseudonym. | ||
866 | * | ||
867 | * @param filename name of the file to use for storage, NULL for in-memory only | ||
868 | * @return handle to the private key of the pseudonym | ||
869 | */ | ||
870 | struct GNUNET_FS_PseudonymHandle * | ||
871 | GNUNET_FS_pseudonym_create (const char *filename) | ||
872 | { | ||
873 | struct GNUNET_FS_PseudonymHandle *ph; | ||
874 | ssize_t ret; | ||
875 | gcry_sexp_t r_key; | ||
876 | gcry_sexp_t params; | ||
877 | gcry_ctx_t ctx; | ||
878 | gcry_mpi_point_t q; | ||
879 | gcry_mpi_t q_x; | ||
880 | gcry_mpi_t q_y; | ||
881 | gcry_error_t rc; | ||
882 | gcry_mpi_t d; | ||
883 | size_t size; | ||
884 | |||
885 | ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle)); | ||
886 | if ( (NULL != filename) && | ||
887 | (GNUNET_YES == GNUNET_DISK_file_test (filename)) ) | ||
888 | { | ||
889 | ret = GNUNET_DISK_fn_read (filename, ph, | ||
890 | sizeof (struct GNUNET_FS_PseudonymHandle)); | ||
891 | /* Note: we don't do any validation here, maybe we should? */ | ||
892 | if (sizeof (struct GNUNET_FS_PseudonymHandle) == ret) | ||
893 | return ph; | ||
894 | } | ||
895 | if (0 != (rc = gcry_sexp_build (¶ms, NULL, | ||
896 | "(genkey(ecdsa(curve \"NIST P-256\")))"))) | ||
897 | { | ||
898 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
899 | return NULL; | ||
900 | } | ||
901 | if (0 != (rc = gcry_pk_genkey (&r_key, params))) | ||
902 | { | ||
903 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc); | ||
904 | gcry_sexp_release (params); | ||
905 | gcry_sexp_release (r_key); | ||
906 | return NULL; | ||
907 | } | ||
908 | gcry_sexp_release (params); | ||
909 | /* extract "d" (secret key) from r_key */ | ||
910 | rc = key_from_sexp (&d, r_key, "private-key", "d"); | ||
911 | if (0 != rc) | ||
912 | rc = key_from_sexp (&d, r_key, "private-key", "d"); | ||
913 | if (0 != rc) | ||
914 | rc = key_from_sexp (&d, r_key, "ecc", "d"); | ||
915 | if (0 != rc) | ||
916 | { | ||
917 | gcry_sexp_release (r_key); | ||
918 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc); | ||
919 | return NULL; | ||
920 | } | ||
921 | size = sizeof (ph->d); | ||
922 | GNUNET_assert (0 == | ||
923 | gcry_mpi_print (GCRYMPI_FMT_USG, ph->d, size, &size, | ||
924 | d)); | ||
925 | gcry_mpi_release (d); | ||
926 | adjust (ph->d, size, sizeof (ph->d)); | ||
927 | |||
928 | /* extract 'q' (public key) from r_key */ | ||
929 | if (0 != (rc = gcry_mpi_ec_new (&ctx, r_key, NULL))) | ||
930 | { | ||
931 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ | ||
932 | gcry_sexp_release (r_key); | ||
933 | return NULL; | ||
934 | } | ||
935 | gcry_sexp_release (r_key); | ||
936 | q = gcry_mpi_ec_get_point ("q", ctx, 0); | ||
937 | q_x = gcry_mpi_new (256); | ||
938 | q_y = gcry_mpi_new (256); | ||
939 | gcry_mpi_ec_get_affine (q_x, q_y, q, ctx); | ||
940 | gcry_mpi_point_release (q); | ||
941 | gcry_ctx_release (ctx); | ||
942 | |||
943 | /* store q_x/q_y in public key */ | ||
944 | size = sizeof (ph->public_key.q_x); | ||
945 | if (0 != | ||
946 | gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_x, size, &size, | ||
947 | q_x)) | ||
948 | { | ||
949 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
950 | gcry_mpi_release (q_x); | ||
951 | gcry_mpi_release (q_y); | ||
952 | return NULL; | ||
953 | |||
954 | } | ||
955 | adjust (ph->public_key.q_x, size, sizeof (ph->public_key.q_x)); | ||
956 | gcry_mpi_release (q_x); | ||
957 | |||
958 | size = sizeof (ph->public_key.q_y); | ||
959 | if (0 != | ||
960 | gcry_mpi_print (GCRYMPI_FMT_USG, ph->public_key.q_y, size, &size, | ||
961 | q_y)) | ||
962 | { | ||
963 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
964 | gcry_mpi_release (q_y); | ||
965 | return NULL; | ||
966 | } | ||
967 | adjust (ph->public_key.q_y, size, sizeof (ph->public_key.q_y)); | ||
968 | gcry_mpi_release (q_y); | ||
969 | |||
970 | /* write to disk */ | ||
971 | if (NULL != filename) | ||
972 | { | ||
973 | ret = GNUNET_DISK_fn_write (filename, ph, sizeof (struct GNUNET_FS_PseudonymHandle), | ||
974 | GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); | ||
975 | if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret) | ||
976 | { | ||
977 | GNUNET_free (ph); | ||
978 | return NULL; | ||
979 | } | ||
980 | } | ||
981 | return ph; | ||
982 | } | ||
983 | |||
984 | |||
985 | /** | ||
986 | * Create a pseudonym, from a file that must already exist. | ||
987 | * | ||
988 | * @param filename name of the file to use for storage, NULL for in-memory only | ||
989 | * @return handle to the private key of the pseudonym | ||
990 | */ | ||
991 | struct GNUNET_FS_PseudonymHandle * | ||
992 | GNUNET_FS_pseudonym_create_from_existing_file (const char *filename) | ||
993 | { | ||
994 | struct GNUNET_FS_PseudonymHandle *ph; | ||
995 | ssize_t ret; | ||
996 | |||
997 | ph = GNUNET_malloc (sizeof (struct GNUNET_FS_PseudonymHandle)); | ||
998 | ret = GNUNET_DISK_fn_read (filename, ph, | ||
999 | sizeof (struct GNUNET_FS_PseudonymHandle)); | ||
1000 | if (sizeof (struct GNUNET_FS_PseudonymHandle) != ret) | ||
1001 | { | ||
1002 | GNUNET_free (ph); | ||
1003 | return NULL; | ||
1004 | } | ||
1005 | /* Note: we don't do any validation here; maybe we should? */ | ||
1006 | return ph; | ||
1007 | } | ||
1008 | |||
1009 | |||
1010 | /** | ||
1011 | * Get the handle for the 'anonymous' pseudonym shared by all users. | ||
1012 | * That pseudonym uses a fixed 'secret' for the private key; this | ||
1013 | * construction is useful to make anonymous and pseudonymous APIs | ||
1014 | * (and packets) indistinguishable on the network. See #2564. | ||
1015 | * | ||
1016 | * @return handle to the (non-secret) private key of the 'anonymous' pseudonym | ||
1017 | */ | ||
1018 | struct GNUNET_FS_PseudonymHandle * | ||
1019 | GNUNET_FS_pseudonym_get_anonymous_pseudonym_handle () | ||
1020 | { | ||
1021 | static int once; | ||
1022 | gcry_mpi_t d; | ||
1023 | size_t size; | ||
1024 | gcry_ctx_t ctx; | ||
1025 | int rc; | ||
1026 | gcry_mpi_t g_x; | ||
1027 | gcry_mpi_t g_y; | ||
1028 | gcry_mpi_point_t g; | ||
1029 | |||
1030 | if (once) | ||
1031 | return &anonymous; | ||
1032 | d = gcry_mpi_new (1); | ||
1033 | gcry_mpi_set_ui (d, 1); | ||
1034 | size = sizeof (anonymous.d); | ||
1035 | GNUNET_assert (0 == | ||
1036 | gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.d, size, &size, | ||
1037 | d)); | ||
1038 | gcry_mpi_release (d); | ||
1039 | adjust (anonymous.d, size, sizeof (anonymous.d)); | ||
1040 | |||
1041 | /* create basic ECC context */ | ||
1042 | if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) | ||
1043 | { | ||
1044 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, | ||
1045 | "gcry_mpi_ec_new", rc); | ||
1046 | return NULL; | ||
1047 | } | ||
1048 | |||
1049 | g = gcry_mpi_ec_get_point ("g", ctx, 0); | ||
1050 | g_x = gcry_mpi_new (256); | ||
1051 | g_y = gcry_mpi_new (256); | ||
1052 | gcry_mpi_ec_get_affine (g_x, g_y, g, ctx); | ||
1053 | gcry_mpi_point_release (g); | ||
1054 | gcry_ctx_release (ctx); | ||
1055 | |||
1056 | /* store g_x/g_y in public key */ | ||
1057 | size = sizeof (anonymous.public_key.q_x); | ||
1058 | if (0 != | ||
1059 | gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.public_key.q_x, size, &size, | ||
1060 | g_x)) | ||
1061 | { | ||
1062 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1063 | gcry_mpi_release (g_x); | ||
1064 | gcry_mpi_release (g_y); | ||
1065 | return NULL; | ||
1066 | } | ||
1067 | adjust (anonymous.public_key.q_x, size, sizeof (anonymous.public_key.q_x)); | ||
1068 | gcry_mpi_release (g_x); | ||
1069 | |||
1070 | size = sizeof (anonymous.public_key.q_y); | ||
1071 | if (0 != | ||
1072 | gcry_mpi_print (GCRYMPI_FMT_USG, anonymous.public_key.q_y, size, &size, | ||
1073 | g_y)) | ||
1074 | { | ||
1075 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1076 | gcry_mpi_release (g_y); | ||
1077 | return NULL; | ||
1078 | } | ||
1079 | adjust (anonymous.public_key.q_y, size, sizeof (anonymous.public_key.q_y)); | ||
1080 | gcry_mpi_release (g_y); | ||
1081 | |||
1082 | once = 1; | ||
1083 | return &anonymous; | ||
1084 | } | ||
1085 | |||
1086 | |||
1087 | /** | ||
1088 | * Destroy a pseudonym handle. Does NOT remove the private key from | ||
1089 | * the disk. | ||
1090 | * | ||
1091 | * @param ph pseudonym handle to destroy | ||
1092 | */ | ||
1093 | void | ||
1094 | GNUNET_FS_pseudonym_destroy (struct GNUNET_FS_PseudonymHandle *ph) | ||
1095 | { | ||
1096 | if (&anonymous != ph) | ||
1097 | GNUNET_free (ph); | ||
1098 | } | ||
1099 | |||
1100 | |||
1101 | /** | ||
1102 | * Convert the data specified in the given purpose argument to an | ||
1103 | * S-expression suitable for signature operations. | ||
1104 | * | ||
1105 | * @param purpose data to convert | ||
1106 | * @param rfc6979 GNUNET_YES if we are to use deterministic ECDSA | ||
1107 | * @return converted s-expression | ||
1108 | */ | ||
1109 | static gcry_sexp_t | ||
1110 | data_to_pkcs1 (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, | ||
1111 | int rfc6979) | ||
1112 | { | ||
1113 | struct GNUNET_CRYPTO_ShortHashCode hc; | ||
1114 | size_t bufSize; | ||
1115 | gcry_sexp_t data; | ||
1116 | const char *fmt; | ||
1117 | int rc; | ||
1118 | |||
1119 | GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc); | ||
1120 | if (rfc6979) | ||
1121 | { | ||
1122 | if (0 != (rc = gcry_sexp_build (&data, NULL, | ||
1123 | "(data(flags rfc6979)(hash %s %b))", | ||
1124 | "sha256", | ||
1125 | sizeof (hc), | ||
1126 | &hc))) | ||
1127 | { | ||
1128 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1129 | return NULL; | ||
1130 | } | ||
1131 | } | ||
1132 | else | ||
1133 | { | ||
1134 | fmt = "(data(flags raw)(5:value32:01234567890123456789012345678901))"; | ||
1135 | bufSize = strlen (fmt) + 1; | ||
1136 | { | ||
1137 | char buff[bufSize]; | ||
1138 | |||
1139 | memcpy (buff, fmt, bufSize); | ||
1140 | memcpy (&buff | ||
1141 | [bufSize - | ||
1142 | strlen | ||
1143 | ("01234567890123456789012345678901))") | ||
1144 | - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); | ||
1145 | GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); | ||
1146 | } | ||
1147 | } | ||
1148 | return data; | ||
1149 | } | ||
1150 | |||
1151 | |||
1152 | /** | ||
1153 | * Cryptographically sign some data with the pseudonym. | ||
1154 | * | ||
1155 | * @param ph private key 'd' used for signing (corresponds to 'x' in #2564) | ||
1156 | * @param purpose data to sign | ||
1157 | * @param seed hash of the plaintext of the data that we are signing, | ||
1158 | * used for deterministic PRNG for anonymous signing; | ||
1159 | * corresponds to 'k' in section 2.7 of #2564 | ||
1160 | * @param signing_key modifier to apply to the private key for signing ('h'); | ||
1161 | * see section 2.3 of #2564. | ||
1162 | * @param signature where to store the signature | ||
1163 | * @return GNUNET_SYSERR on failure | ||
1164 | */ | ||
1165 | int | ||
1166 | GNUNET_FS_pseudonym_sign (struct GNUNET_FS_PseudonymHandle *ph, | ||
1167 | const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, | ||
1168 | const struct GNUNET_HashCode *seed, | ||
1169 | const struct GNUNET_HashCode *signing_key, | ||
1170 | struct GNUNET_FS_PseudonymSignature *signature) | ||
1171 | { | ||
1172 | size_t size; | ||
1173 | size_t erroff; | ||
1174 | gcry_mpi_t d; | ||
1175 | gcry_mpi_t k; | ||
1176 | gcry_mpi_t h; | ||
1177 | gcry_mpi_t dh; | ||
1178 | gcry_mpi_t n; /* n from P-256 */ | ||
1179 | gcry_sexp_t spriv; | ||
1180 | gcry_sexp_t data; | ||
1181 | gcry_sexp_t result; | ||
1182 | gcry_mpi_t rs[2]; | ||
1183 | int rc; | ||
1184 | |||
1185 | /* get private key 'd' from pseudonym */ | ||
1186 | size = sizeof (ph->d); | ||
1187 | if (0 != (rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG, | ||
1188 | &ph->d, | ||
1189 | size, &size))) | ||
1190 | { | ||
1191 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1192 | return GNUNET_SYSERR; | ||
1193 | } | ||
1194 | /* get 'x' value from signing key */ | ||
1195 | size = sizeof (struct GNUNET_HashCode); | ||
1196 | if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, | ||
1197 | signing_key, | ||
1198 | size, &size))) | ||
1199 | { | ||
1200 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1201 | gcry_mpi_release (d); | ||
1202 | return GNUNET_SYSERR; | ||
1203 | } | ||
1204 | |||
1205 | /* initialize 'n' from P-256; hex copied from libgcrypt code */ | ||
1206 | if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, | ||
1207 | "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL))) | ||
1208 | { | ||
1209 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1210 | gcry_mpi_release (d); | ||
1211 | gcry_mpi_release (h); | ||
1212 | return GNUNET_SYSERR; | ||
1213 | } | ||
1214 | |||
1215 | /* calculate dh = d * h mod n */ | ||
1216 | dh = gcry_mpi_new (256); | ||
1217 | gcry_mpi_mulm (dh, d, h, n); | ||
1218 | gcry_mpi_release (d); | ||
1219 | gcry_mpi_release (h); | ||
1220 | gcry_mpi_release (n); | ||
1221 | |||
1222 | /* now build sexpression with the signing key */ | ||
1223 | if (0 != (rc = gcry_sexp_build (&spriv, &erroff, | ||
1224 | "(private-key(ecdsa(curve \"NIST P-256\")(d %m)))", | ||
1225 | dh))) | ||
1226 | { | ||
1227 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1228 | gcry_mpi_release (dh); | ||
1229 | return GNUNET_SYSERR; | ||
1230 | } | ||
1231 | gcry_mpi_release (dh); | ||
1232 | /* prepare data for signing */ | ||
1233 | data = data_to_pkcs1 (purpose, NULL != seed); | ||
1234 | if (NULL == data) | ||
1235 | { | ||
1236 | gcry_sexp_release (spriv); | ||
1237 | return GNUNET_SYSERR; | ||
1238 | } | ||
1239 | /* get 'k' value from seed, if available */ | ||
1240 | if (NULL != seed) | ||
1241 | { | ||
1242 | size = sizeof (struct GNUNET_HashCode); | ||
1243 | if (0 != (rc = gcry_mpi_scan (&k, GCRYMPI_FMT_USG, | ||
1244 | seed, | ||
1245 | size, &size))) | ||
1246 | { | ||
1247 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1248 | gcry_sexp_release (spriv); | ||
1249 | gcry_sexp_release (data); | ||
1250 | return GNUNET_SYSERR; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | /* actually create signature */ | ||
1255 | /* FIXME: need API to pass 'k' if 'seed' was non-NULL! */ | ||
1256 | if (0 != (rc = gcry_pk_sign (&result, data, spriv))) | ||
1257 | { | ||
1258 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1259 | _("ECC signing failed at %s:%d: %s\n"), __FILE__, | ||
1260 | __LINE__, gcry_strerror (rc)); | ||
1261 | gcry_sexp_release (data); | ||
1262 | gcry_sexp_release (spriv); | ||
1263 | if (NULL != seed) | ||
1264 | gcry_mpi_release (k); | ||
1265 | memset (signature, 0, sizeof (struct GNUNET_FS_PseudonymSignature)); | ||
1266 | return GNUNET_SYSERR; | ||
1267 | } | ||
1268 | if (NULL != seed) | ||
1269 | gcry_mpi_release (k); | ||
1270 | gcry_sexp_release (data); | ||
1271 | gcry_sexp_release (spriv); | ||
1272 | |||
1273 | |||
1274 | /* extract 'r' and 's' values from sexpression 'result' and store in 'signature' */ | ||
1275 | if (0 != (rc = key_from_sexp (rs, result, "sig-val", "rs"))) | ||
1276 | { | ||
1277 | GNUNET_break (0); | ||
1278 | gcry_sexp_release (result); | ||
1279 | return GNUNET_SYSERR; | ||
1280 | } | ||
1281 | gcry_sexp_release (result); | ||
1282 | size = sizeof (signature->sig_r); | ||
1283 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_r, size, | ||
1284 | &size, rs[0]))) | ||
1285 | { | ||
1286 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1287 | gcry_mpi_release (rs[0]); | ||
1288 | gcry_mpi_release (rs[1]); | ||
1289 | return GNUNET_SYSERR; | ||
1290 | } | ||
1291 | adjust (signature->sig_r, size, sizeof (signature->sig_r)); | ||
1292 | gcry_mpi_release (rs[0]); | ||
1293 | |||
1294 | size = sizeof (signature->sig_s); | ||
1295 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, signature->sig_s, size, | ||
1296 | &size, rs[1]))) | ||
1297 | { | ||
1298 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1299 | gcry_mpi_release (rs[1]); | ||
1300 | return GNUNET_SYSERR; | ||
1301 | } | ||
1302 | adjust (signature->sig_s, size, sizeof (signature->sig_s)); | ||
1303 | gcry_mpi_release (rs[1]); | ||
1304 | |||
1305 | #if EXTRA_CHECKS | ||
1306 | { | ||
1307 | struct GNUNET_FS_PseudonymIdentifier vk; | ||
1308 | struct GNUNET_FS_PseudonymIdentifier pi; | ||
1309 | |||
1310 | GNUNET_FS_pseudonym_get_identifier (ph, &pi); | ||
1311 | GNUNET_assert (GNUNET_OK == | ||
1312 | GNUNET_FS_pseudonym_derive_verification_key (&pi, signing_key, &vk)); | ||
1313 | GNUNET_assert (GNUNET_OK == | ||
1314 | GNUNET_FS_pseudonym_verify (purpose, | ||
1315 | signature, | ||
1316 | &vk)); | ||
1317 | } | ||
1318 | #endif | ||
1319 | |||
1320 | GNUNET_FS_pseudonym_get_identifier (ph, &signature->signer); | ||
1321 | return GNUNET_OK; | ||
1322 | } | ||
1323 | |||
1324 | |||
1325 | /** | ||
1326 | * Get an ECC context (with Q set to the respective public key) from | ||
1327 | * a pseudonym. | ||
1328 | * | ||
1329 | * @param pseudonym with information on 'q' | ||
1330 | * @return curve context | ||
1331 | */ | ||
1332 | static gcry_ctx_t | ||
1333 | get_context_from_pseudonym (struct GNUNET_FS_PseudonymIdentifier *pseudonym) | ||
1334 | { | ||
1335 | static struct GNUNET_FS_PseudonymIdentifier zerop; | ||
1336 | gcry_ctx_t ctx; | ||
1337 | gcry_mpi_t q_x; | ||
1338 | gcry_mpi_t q_y; | ||
1339 | gcry_mpi_t zero; | ||
1340 | gcry_mpi_point_t q; | ||
1341 | size_t size; | ||
1342 | int rc; | ||
1343 | |||
1344 | /* extract 'q' from pseudonym */ | ||
1345 | if (0 == memcmp (pseudonym, &zerop, sizeof (zerop))) | ||
1346 | { | ||
1347 | /* create basic ECC context */ | ||
1348 | if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) | ||
1349 | { | ||
1350 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ | ||
1351 | return NULL; | ||
1352 | } | ||
1353 | /* FIXME: initialize 'ctx' with 'q' = G */ | ||
1354 | zero = gcry_mpi_new (0); | ||
1355 | gcry_mpi_set_ui (zero, 0); | ||
1356 | q = gcry_mpi_point_new (0); | ||
1357 | gcry_mpi_point_set (q, zero, zero, zero); | ||
1358 | gcry_mpi_ec_set_point ("q", q, ctx); | ||
1359 | gcry_mpi_release (zero); | ||
1360 | gcry_mpi_point_release (q); | ||
1361 | return ctx; | ||
1362 | } | ||
1363 | size = sizeof (pseudonym->q_x); | ||
1364 | if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, pseudonym->q_x, size, &size))) | ||
1365 | { | ||
1366 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1367 | return NULL; | ||
1368 | } | ||
1369 | size = sizeof (pseudonym->q_y); | ||
1370 | if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, pseudonym->q_y, size, &size))) | ||
1371 | { | ||
1372 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1373 | gcry_mpi_release (q_x); | ||
1374 | return NULL; | ||
1375 | } | ||
1376 | q = gcry_mpi_point_new (256); | ||
1377 | gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE); | ||
1378 | gcry_mpi_release (q_x); | ||
1379 | gcry_mpi_release (q_y); | ||
1380 | |||
1381 | /* create basic ECC context */ | ||
1382 | if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) | ||
1383 | { | ||
1384 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ | ||
1385 | gcry_mpi_point_release (q); | ||
1386 | return NULL; | ||
1387 | } | ||
1388 | /* initialize 'ctx' with 'q' */ | ||
1389 | gcry_mpi_ec_set_point ("q", q, ctx); | ||
1390 | gcry_mpi_point_release (q); | ||
1391 | return ctx; | ||
1392 | } | ||
1393 | |||
1394 | |||
1395 | /** | ||
1396 | * Given a pseudonym and a signing key, derive the corresponding public | ||
1397 | * key that would be used to verify the resulting signature. | ||
1398 | * | ||
1399 | * @param pseudonym the public key (dQ in ECDSA) | ||
1400 | * @param signing_key input to derive 'h' (see section 2.4 of #2564) | ||
1401 | * @param verification_key resulting public key to verify the signature | ||
1402 | * created from the '(d*h)' of 'pseudonym' and the 'signing_key'; | ||
1403 | * the value stored here can then be given to GNUNET_FS_pseudonym_verify. | ||
1404 | * @return GNUNET_OK on success, GNUNET_SYSERR on error | ||
1405 | */ | ||
1406 | int | ||
1407 | GNUNET_FS_pseudonym_derive_verification_key (struct GNUNET_FS_PseudonymIdentifier *pseudonym, | ||
1408 | const struct GNUNET_HashCode *signing_key, | ||
1409 | struct GNUNET_FS_PseudonymIdentifier *verification_key) | ||
1410 | { | ||
1411 | gcry_mpi_t h; | ||
1412 | size_t size; | ||
1413 | int rc; | ||
1414 | gcry_ctx_t ctx; | ||
1415 | gcry_mpi_point_t q; | ||
1416 | gcry_mpi_point_t v; | ||
1417 | gcry_mpi_t v_x; | ||
1418 | gcry_mpi_t v_y; | ||
1419 | gcry_mpi_t h_mod_n; | ||
1420 | gcry_mpi_t n; /* n from P-256 */ | ||
1421 | |||
1422 | /* get 'h' value from signing key */ | ||
1423 | size = sizeof (struct GNUNET_HashCode); | ||
1424 | if (0 != (rc = gcry_mpi_scan (&h, GCRYMPI_FMT_USG, | ||
1425 | signing_key, | ||
1426 | size, &size))) | ||
1427 | { | ||
1428 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1429 | return GNUNET_SYSERR; | ||
1430 | } | ||
1431 | /* create ECC context based on Q from pseudonym */ | ||
1432 | if (NULL == (ctx = get_context_from_pseudonym (pseudonym))) | ||
1433 | { | ||
1434 | gcry_mpi_release (h); | ||
1435 | return GNUNET_SYSERR; | ||
1436 | } | ||
1437 | /* initialize 'n' from P-256; hex copied from libgcrypt code */ | ||
1438 | if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX, | ||
1439 | "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL))) | ||
1440 | { | ||
1441 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1442 | gcry_mpi_release (h); | ||
1443 | return GNUNET_SYSERR; | ||
1444 | } | ||
1445 | h_mod_n = gcry_mpi_new (0); | ||
1446 | gcry_mpi_mod (h_mod_n, h, n); | ||
1447 | gcry_mpi_release (h); | ||
1448 | |||
1449 | /* get Q = dG from 'pseudonym' */ | ||
1450 | q = gcry_mpi_ec_get_point ("q", ctx, 0); | ||
1451 | /* calculate V = hQ = hdG */ | ||
1452 | v = gcry_mpi_point_new (0); | ||
1453 | |||
1454 | gcry_mpi_ec_mul (v, h_mod_n, q, ctx); | ||
1455 | gcry_mpi_release (h_mod_n); | ||
1456 | |||
1457 | /* store 'v' point in "verification_key" */ | ||
1458 | v_x = gcry_mpi_new (256); | ||
1459 | v_y = gcry_mpi_new (256); | ||
1460 | gcry_mpi_ec_get_affine (v_x, v_y, v, ctx); | ||
1461 | |||
1462 | gcry_mpi_point_release (v); | ||
1463 | gcry_ctx_release (ctx); | ||
1464 | |||
1465 | size = sizeof (verification_key->q_x); | ||
1466 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_x, size, | ||
1467 | &size, v_x))) | ||
1468 | { | ||
1469 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1470 | gcry_mpi_release (v_x); | ||
1471 | gcry_mpi_release (v_y); | ||
1472 | return GNUNET_SYSERR; | ||
1473 | } | ||
1474 | gcry_mpi_release (v_x); | ||
1475 | size = sizeof (verification_key->q_y); | ||
1476 | if (0 != (rc = gcry_mpi_print (GCRYMPI_FMT_USG, verification_key->q_y, size, | ||
1477 | &size, v_y))) | ||
1478 | { | ||
1479 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_print", rc); | ||
1480 | gcry_mpi_release (v_y); | ||
1481 | return GNUNET_SYSERR; | ||
1482 | } | ||
1483 | gcry_mpi_release (v_y); | ||
1484 | return GNUNET_OK; | ||
1485 | } | ||
1486 | |||
1487 | |||
1488 | /** | ||
1489 | * Verify a signature made with a pseudonym. | ||
1490 | * | ||
1491 | * @param purpose data that was signed | ||
1492 | * @param signature signature to verify | ||
1493 | * @param verification_key public key to use for checking the signature; | ||
1494 | * corresponds to 'g^(x+h)' in section 2.4 of #2564. | ||
1495 | * @return GNUNET_OK on success (signature valid, 'pseudonym' set), | ||
1496 | * GNUNET_SYSERR if the signature is invalid | ||
1497 | */ | ||
1498 | int | ||
1499 | GNUNET_FS_pseudonym_verify (const struct GNUNET_FS_PseudonymSignaturePurpose *purpose, | ||
1500 | const struct GNUNET_FS_PseudonymSignature *signature, | ||
1501 | const struct GNUNET_FS_PseudonymIdentifier *verification_key) | ||
1502 | { | ||
1503 | gcry_sexp_t data; | ||
1504 | gcry_sexp_t sig_sexpr; | ||
1505 | gcry_sexp_t pk_sexpr; | ||
1506 | size_t size; | ||
1507 | gcry_ctx_t ctx; | ||
1508 | gcry_mpi_t r; | ||
1509 | gcry_mpi_t s; | ||
1510 | gcry_mpi_point_t q; | ||
1511 | gcry_mpi_t q_x; | ||
1512 | gcry_mpi_t q_y; | ||
1513 | size_t erroff; | ||
1514 | int rc; | ||
1515 | |||
1516 | /* build s-expression for signature */ | ||
1517 | size = sizeof (signature->sig_r); | ||
1518 | if (0 != (rc = gcry_mpi_scan (&r, GCRYMPI_FMT_USG, | ||
1519 | signature->sig_r, size, &size))) | ||
1520 | { | ||
1521 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1522 | return GNUNET_SYSERR; | ||
1523 | } | ||
1524 | size = sizeof (signature->sig_s); | ||
1525 | if (0 != (rc = gcry_mpi_scan (&s, GCRYMPI_FMT_USG, | ||
1526 | signature->sig_s, size, &size))) | ||
1527 | { | ||
1528 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1529 | gcry_mpi_release (r); | ||
1530 | return GNUNET_SYSERR; | ||
1531 | } | ||
1532 | if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))", | ||
1533 | r, s))) | ||
1534 | { | ||
1535 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | ||
1536 | gcry_mpi_release (r); | ||
1537 | gcry_mpi_release (s); | ||
1538 | return GNUNET_SYSERR; | ||
1539 | } | ||
1540 | gcry_mpi_release (r); | ||
1541 | gcry_mpi_release (s); | ||
1542 | |||
1543 | |||
1544 | /* build s-expression for data that was signed */ | ||
1545 | data = data_to_pkcs1 (purpose, GNUNET_NO); | ||
1546 | if (NULL == data) | ||
1547 | { | ||
1548 | gcry_sexp_release (sig_sexpr); | ||
1549 | return GNUNET_SYSERR; | ||
1550 | } | ||
1551 | /* create context of public key and initialize Q */ | ||
1552 | size = sizeof (verification_key->q_x); | ||
1553 | if (0 != (rc = gcry_mpi_scan (&q_x, GCRYMPI_FMT_USG, | ||
1554 | verification_key->q_x, size, &size))) | ||
1555 | { | ||
1556 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1557 | gcry_sexp_release (data); | ||
1558 | gcry_sexp_release (sig_sexpr); | ||
1559 | return GNUNET_SYSERR; | ||
1560 | } | ||
1561 | size = sizeof (verification_key->q_y); | ||
1562 | if (0 != (rc = gcry_mpi_scan (&q_y, GCRYMPI_FMT_USG, | ||
1563 | verification_key->q_y, size, &size))) | ||
1564 | { | ||
1565 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | ||
1566 | gcry_sexp_release (data); | ||
1567 | gcry_sexp_release (sig_sexpr); | ||
1568 | gcry_mpi_release (q_x); | ||
1569 | return GNUNET_SYSERR; | ||
1570 | } | ||
1571 | q = gcry_mpi_point_new (256); | ||
1572 | gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE); | ||
1573 | gcry_mpi_release (q_x); | ||
1574 | gcry_mpi_release (q_y); | ||
1575 | |||
1576 | /* create basic ECC context */ | ||
1577 | if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, "NIST P-256"))) | ||
1578 | { | ||
1579 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */ | ||
1580 | gcry_sexp_release (data); | ||
1581 | gcry_sexp_release (sig_sexpr); | ||
1582 | gcry_mpi_point_release (q); | ||
1583 | return GNUNET_SYSERR; | ||
1584 | } | ||
1585 | /* initialize 'ctx' with 'q' */ | ||
1586 | gcry_mpi_ec_set_point ("q", q, ctx); | ||
1587 | gcry_mpi_point_release (q); | ||
1588 | |||
1589 | /* convert 'ctx' to 'sexp' */ | ||
1590 | if (0 != (rc = gcry_pubkey_get_sexp (&pk_sexpr, GCRY_PK_GET_PUBKEY, ctx))) | ||
1591 | { | ||
1592 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc); | ||
1593 | gcry_ctx_release (ctx); | ||
1594 | gcry_sexp_release (data); | ||
1595 | gcry_sexp_release (sig_sexpr); | ||
1596 | return GNUNET_SYSERR; | ||
1597 | } | ||
1598 | gcry_ctx_release (ctx); | ||
1599 | |||
1600 | /* finally, verify the signature */ | ||
1601 | rc = gcry_pk_verify (sig_sexpr, data, pk_sexpr); | ||
1602 | gcry_sexp_release (sig_sexpr); | ||
1603 | gcry_sexp_release (data); | ||
1604 | gcry_sexp_release (pk_sexpr); | ||
1605 | if (rc) | ||
1606 | { | ||
1607 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1608 | _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__, | ||
1609 | __LINE__, gcry_strerror (rc)); | ||
1610 | return GNUNET_SYSERR; | ||
1611 | } | ||
1612 | return GNUNET_OK; | ||
1613 | } | ||
1614 | |||
1615 | |||
1616 | /** | ||
1617 | * Get the identifier (public key) of a pseudonym. | ||
1618 | * | ||
1619 | * @param ph pseudonym handle with the private key | ||
1620 | * @param pseudonym pseudonym identifier (set based on 'ph') | ||
1621 | */ | ||
1622 | void | ||
1623 | GNUNET_FS_pseudonym_get_identifier (struct GNUNET_FS_PseudonymHandle *ph, | ||
1624 | struct GNUNET_FS_PseudonymIdentifier *pseudonym) | ||
1625 | { | ||
1626 | memcpy (pseudonym, &ph->public_key, | ||
1627 | sizeof (struct GNUNET_FS_PseudonymIdentifier)); | ||
1628 | } | ||
1629 | |||
1630 | |||
1631 | /** | ||
1632 | * Remove pseudonym from the set of known pseudonyms. | ||
1633 | * | ||
1634 | * @param cfg overall configuration | ||
1635 | * @param id the pseudonym identifier | ||
1636 | * @return GNUNET_OK on success, GNUNET_SYSERR on failure | ||
1637 | */ | ||
1638 | int | ||
1639 | GNUNET_FS_pseudonym_remove (const struct GNUNET_CONFIGURATION_Handle *cfg, | ||
1640 | const struct GNUNET_FS_PseudonymIdentifier *id) | ||
1641 | { | ||
1642 | char *fn; | ||
1643 | int result; | ||
1644 | |||
1645 | fn = get_data_filename (cfg, PS_METADATA_DIR, id); | ||
1646 | if (NULL == fn) | ||
1647 | return GNUNET_SYSERR; | ||
1648 | result = UNLINK (fn); | ||
1649 | GNUNET_free (fn); | ||
1650 | return (0 == result) ? GNUNET_OK : GNUNET_SYSERR; | ||
1651 | } | ||
1652 | 753 | ||
1653 | /* end of pseudonym.c */ | 754 | /* end of pseudonym.c */ |