diff options
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 31 | ||||
-rw-r--r-- | src/util/crypto_ecc.c | 282 | ||||
-rw-r--r-- | src/util/test_crypto_ecc.c | 35 |
3 files changed, 0 insertions, 348 deletions
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 8592f0da5..3df6c4a30 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h | |||
@@ -1288,12 +1288,6 @@ GNUNET_CRYPTO_ecc_key_create_from_configuration (const struct GNUNET_CONFIGURATI | |||
1288 | 1288 | ||
1289 | 1289 | ||
1290 | /** | 1290 | /** |
1291 | * Handle to cancel private key generation and state for the | ||
1292 | * key generation operation. | ||
1293 | */ | ||
1294 | struct GNUNET_CRYPTO_EccKeyGenerationContext; | ||
1295 | |||
1296 | /** | ||
1297 | * Create a new private key. Caller must free return value. Blocking version | 1291 | * Create a new private key. Caller must free return value. Blocking version |
1298 | * (blocks to gather entropy). | 1292 | * (blocks to gather entropy). |
1299 | * | 1293 | * |
@@ -1304,31 +1298,6 @@ GNUNET_CRYPTO_ecc_key_create (void); | |||
1304 | 1298 | ||
1305 | 1299 | ||
1306 | /** | 1300 | /** |
1307 | * Create a new private key by reading it from a file. If the files | ||
1308 | * does not exist, create a new key and write it to the file. If the | ||
1309 | * contents of the file are invalid the old file is deleted and a | ||
1310 | * fresh key is created. | ||
1311 | * | ||
1312 | * @param filename name of file to use for storage | ||
1313 | * @param cont function to call when done (or on errors) | ||
1314 | * @param cont_cls closure for 'cont' | ||
1315 | * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned) | ||
1316 | */ | ||
1317 | struct GNUNET_CRYPTO_EccKeyGenerationContext * | ||
1318 | GNUNET_CRYPTO_ecc_key_create_start (const char *filename, | ||
1319 | GNUNET_CRYPTO_EccKeyCallback cont, | ||
1320 | void *cont_cls); | ||
1321 | |||
1322 | |||
1323 | /** | ||
1324 | * Abort ECC key generation. | ||
1325 | * | ||
1326 | * @param gc key generation context to abort | ||
1327 | */ | ||
1328 | void | ||
1329 | GNUNET_CRYPTO_ecc_key_create_stop (struct GNUNET_CRYPTO_EccKeyGenerationContext *gc); | ||
1330 | |||
1331 | /** | ||
1332 | * Setup a hostkey file for a peer given the name of the | 1301 | * Setup a hostkey file for a peer given the name of the |
1333 | * configuration file (!). This function is used so that | 1302 | * configuration file (!). This function is used so that |
1334 | * at a later point code can be certain that reading a | 1303 | * at a later point code can be certain that reading a |
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index 498de59df..3cec12868 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c | |||
@@ -405,72 +405,6 @@ GNUNET_CRYPTO_ecc_key_create () | |||
405 | 405 | ||
406 | 406 | ||
407 | /** | 407 | /** |
408 | * Try to read the private key from the given file. | ||
409 | * | ||
410 | * @param filename file to read the key from | ||
411 | * @return NULL on error | ||
412 | */ | ||
413 | static struct GNUNET_CRYPTO_EccPrivateKey * | ||
414 | try_read_key (const char *filename) | ||
415 | { | ||
416 | struct GNUNET_CRYPTO_EccPrivateKey *ret; | ||
417 | struct GNUNET_DISK_FileHandle *fd; | ||
418 | OFF_T fs; | ||
419 | |||
420 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | ||
421 | return NULL; | ||
422 | |||
423 | /* key file exists already, read it! */ | ||
424 | if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, | ||
425 | GNUNET_DISK_PERM_NONE))) | ||
426 | { | ||
427 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "open", filename); | ||
428 | return NULL; | ||
429 | } | ||
430 | if (GNUNET_OK != (GNUNET_DISK_file_handle_size (fd, &fs))) | ||
431 | { | ||
432 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "stat", filename); | ||
433 | (void) GNUNET_DISK_file_close (fd); | ||
434 | return NULL; | ||
435 | } | ||
436 | if (0 == fs) | ||
437 | { | ||
438 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); | ||
439 | return NULL; | ||
440 | } | ||
441 | if (fs > UINT16_MAX) | ||
442 | { | ||
443 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
444 | _("File `%s' does not contain a valid private key (too long, %llu bytes). Deleting it.\n"), | ||
445 | filename, | ||
446 | (unsigned long long) fs); | ||
447 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); | ||
448 | if (0 != UNLINK (filename)) | ||
449 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); | ||
450 | return NULL; | ||
451 | } | ||
452 | { | ||
453 | char enc[fs]; | ||
454 | |||
455 | GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs)); | ||
456 | if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs, GNUNET_YES))) | ||
457 | { | ||
458 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
459 | _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"), | ||
460 | filename, | ||
461 | (unsigned long long) fs); | ||
462 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); | ||
463 | if (0 != UNLINK (filename)) | ||
464 | LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); | ||
465 | return NULL; | ||
466 | } | ||
467 | } | ||
468 | GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); | ||
469 | return ret; | ||
470 | } | ||
471 | |||
472 | |||
473 | /** | ||
474 | * Wait for a short time (we're trying to lock a file or want | 408 | * Wait for a short time (we're trying to lock a file or want |
475 | * to give another process a shot at finishing a disk write, etc.). | 409 | * to give another process a shot at finishing a disk write, etc.). |
476 | * Sleeps for 100ms (as that should be long enough for virtually all | 410 | * Sleeps for 100ms (as that should be long enough for virtually all |
@@ -674,222 +608,6 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
674 | 608 | ||
675 | 609 | ||
676 | /** | 610 | /** |
677 | * Handle to cancel private key generation and state for the | ||
678 | * key generation operation. | ||
679 | */ | ||
680 | struct GNUNET_CRYPTO_EccKeyGenerationContext | ||
681 | { | ||
682 | |||
683 | /** | ||
684 | * Continuation to call upon completion. | ||
685 | */ | ||
686 | GNUNET_CRYPTO_EccKeyCallback cont; | ||
687 | |||
688 | /** | ||
689 | * Closure for 'cont'. | ||
690 | */ | ||
691 | void *cont_cls; | ||
692 | |||
693 | /** | ||
694 | * Name of the file. | ||
695 | */ | ||
696 | char *filename; | ||
697 | |||
698 | /** | ||
699 | * Handle to the helper process which does the key generation. | ||
700 | */ | ||
701 | struct GNUNET_OS_Process *gnunet_ecc; | ||
702 | |||
703 | /** | ||
704 | * Handle to 'stdout' of gnunet-ecc. We 'read' on stdout to detect | ||
705 | * process termination (instead of messing with SIGCHLD). | ||
706 | */ | ||
707 | struct GNUNET_DISK_PipeHandle *gnunet_ecc_out; | ||
708 | |||
709 | /** | ||
710 | * Location where we store the private key if it already existed. | ||
711 | * (if this is used, 'filename', 'gnunet_ecc' and 'gnunet_ecc_out' will | ||
712 | * not be used). | ||
713 | */ | ||
714 | struct GNUNET_CRYPTO_EccPrivateKey *pk; | ||
715 | |||
716 | /** | ||
717 | * Task reading from 'gnunet_ecc_out' to wait for process termination. | ||
718 | */ | ||
719 | GNUNET_SCHEDULER_TaskIdentifier read_task; | ||
720 | |||
721 | }; | ||
722 | |||
723 | |||
724 | /** | ||
725 | * Abort ECC key generation. | ||
726 | * | ||
727 | * @param gc key generation context to abort | ||
728 | */ | ||
729 | void | ||
730 | GNUNET_CRYPTO_ecc_key_create_stop (struct GNUNET_CRYPTO_EccKeyGenerationContext *gc) | ||
731 | { | ||
732 | if (GNUNET_SCHEDULER_NO_TASK != gc->read_task) | ||
733 | { | ||
734 | GNUNET_SCHEDULER_cancel (gc->read_task); | ||
735 | gc->read_task = GNUNET_SCHEDULER_NO_TASK; | ||
736 | } | ||
737 | if (NULL != gc->gnunet_ecc) | ||
738 | { | ||
739 | (void) GNUNET_OS_process_kill (gc->gnunet_ecc, SIGKILL); | ||
740 | GNUNET_break (GNUNET_OK == | ||
741 | GNUNET_OS_process_wait (gc->gnunet_ecc)); | ||
742 | GNUNET_OS_process_destroy (gc->gnunet_ecc); | ||
743 | GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); | ||
744 | } | ||
745 | |||
746 | if (NULL != gc->filename) | ||
747 | { | ||
748 | if ( (0 != UNLINK (gc->filename)) && | ||
749 | (ENOENT != errno) ) | ||
750 | GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", gc->filename); | ||
751 | GNUNET_free (gc->filename); | ||
752 | } | ||
753 | if (NULL != gc->pk) | ||
754 | GNUNET_CRYPTO_ecc_key_free (gc->pk); | ||
755 | GNUNET_free (gc); | ||
756 | } | ||
757 | |||
758 | |||
759 | /** | ||
760 | * Task called upon shutdown or process termination of 'gnunet-ecc' during | ||
761 | * ECC key generation. Check where we are and perform the appropriate | ||
762 | * action. | ||
763 | * | ||
764 | * @param cls the 'struct GNUNET_CRYPTO_EccKeyGenerationContext' | ||
765 | * @param tc scheduler context | ||
766 | */ | ||
767 | static void | ||
768 | check_key_generation_completion (void *cls, | ||
769 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
770 | { | ||
771 | struct GNUNET_CRYPTO_EccKeyGenerationContext *gc = cls; | ||
772 | struct GNUNET_CRYPTO_EccPrivateKey *pk; | ||
773 | |||
774 | gc->read_task = GNUNET_SCHEDULER_NO_TASK; | ||
775 | if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN)) | ||
776 | { | ||
777 | gc->cont (gc->cont_cls, NULL, _("interrupted by shutdown")); | ||
778 | GNUNET_CRYPTO_ecc_key_create_stop (gc); | ||
779 | return; | ||
780 | } | ||
781 | GNUNET_assert (GNUNET_OK == | ||
782 | GNUNET_OS_process_wait (gc->gnunet_ecc)); | ||
783 | GNUNET_OS_process_destroy (gc->gnunet_ecc); | ||
784 | gc->gnunet_ecc = NULL; | ||
785 | if (NULL == (pk = try_read_key (gc->filename))) | ||
786 | { | ||
787 | GNUNET_break (0); | ||
788 | gc->cont (gc->cont_cls, NULL, _("gnunet-ecc failed")); | ||
789 | GNUNET_CRYPTO_ecc_key_create_stop (gc); | ||
790 | return; | ||
791 | } | ||
792 | gc->cont (gc->cont_cls, pk, NULL); | ||
793 | GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); | ||
794 | GNUNET_free (gc->filename); | ||
795 | GNUNET_free (gc); | ||
796 | } | ||
797 | |||
798 | |||
799 | /** | ||
800 | * Return the private ECC key which already existed on disk | ||
801 | * (asynchronously) to the caller. | ||
802 | * | ||
803 | * @param cls the 'struct GNUNET_CRYPTO_EccKeyGenerationContext' | ||
804 | * @param tc scheduler context (unused) | ||
805 | */ | ||
806 | static void | ||
807 | async_return_key (void *cls, | ||
808 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
809 | { | ||
810 | struct GNUNET_CRYPTO_EccKeyGenerationContext *gc = cls; | ||
811 | |||
812 | gc->cont (gc->cont_cls, | ||
813 | gc->pk, | ||
814 | NULL); | ||
815 | GNUNET_free (gc); | ||
816 | } | ||
817 | |||
818 | |||
819 | /** | ||
820 | * Create a new private key by reading it from a file. If the files | ||
821 | * does not exist, create a new key and write it to the file. If the | ||
822 | * contents of the file are invalid the old file is deleted and a | ||
823 | * fresh key is created. | ||
824 | * | ||
825 | * @param filename name of file to use for storage | ||
826 | * @param cont function to call when done (or on errors) | ||
827 | * @param cont_cls closure for 'cont' | ||
828 | * @return handle to abort operation, NULL on fatal errors (cont will not be called if NULL is returned) | ||
829 | */ | ||
830 | struct GNUNET_CRYPTO_EccKeyGenerationContext * | ||
831 | GNUNET_CRYPTO_ecc_key_create_start (const char *filename, | ||
832 | GNUNET_CRYPTO_EccKeyCallback cont, | ||
833 | void *cont_cls) | ||
834 | { | ||
835 | struct GNUNET_CRYPTO_EccKeyGenerationContext *gc; | ||
836 | struct GNUNET_CRYPTO_EccPrivateKey *pk; | ||
837 | |||
838 | if (NULL != (pk = try_read_key (filename))) | ||
839 | { | ||
840 | /* quick happy ending: key already exists! */ | ||
841 | gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccKeyGenerationContext)); | ||
842 | gc->pk = pk; | ||
843 | gc->cont = cont; | ||
844 | gc->cont_cls = cont_cls; | ||
845 | gc->read_task = GNUNET_SCHEDULER_add_now (&async_return_key, | ||
846 | gc); | ||
847 | return gc; | ||
848 | } | ||
849 | gc = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccKeyGenerationContext)); | ||
850 | gc->filename = GNUNET_strdup (filename); | ||
851 | gc->cont = cont; | ||
852 | gc->cont_cls = cont_cls; | ||
853 | gc->gnunet_ecc_out = GNUNET_DISK_pipe (GNUNET_NO, | ||
854 | GNUNET_NO, | ||
855 | GNUNET_NO, | ||
856 | GNUNET_YES); | ||
857 | if (NULL == gc->gnunet_ecc_out) | ||
858 | { | ||
859 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "pipe"); | ||
860 | GNUNET_free (gc->filename); | ||
861 | GNUNET_free (gc); | ||
862 | return NULL; | ||
863 | } | ||
864 | gc->gnunet_ecc = GNUNET_OS_start_process (GNUNET_NO, | ||
865 | GNUNET_OS_INHERIT_STD_ERR, | ||
866 | NULL, | ||
867 | gc->gnunet_ecc_out, | ||
868 | "gnunet-ecc", | ||
869 | "gnunet-ecc", | ||
870 | gc->filename, | ||
871 | NULL); | ||
872 | if (NULL == gc->gnunet_ecc) | ||
873 | { | ||
874 | GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fork"); | ||
875 | GNUNET_DISK_pipe_close (gc->gnunet_ecc_out); | ||
876 | GNUNET_free (gc->filename); | ||
877 | GNUNET_free (gc); | ||
878 | return NULL; | ||
879 | } | ||
880 | GNUNET_assert (GNUNET_OK == | ||
881 | GNUNET_DISK_pipe_close_end (gc->gnunet_ecc_out, | ||
882 | GNUNET_DISK_PIPE_END_WRITE)); | ||
883 | gc->read_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, | ||
884 | GNUNET_DISK_pipe_handle (gc->gnunet_ecc_out, | ||
885 | GNUNET_DISK_PIPE_END_READ), | ||
886 | &check_key_generation_completion, | ||
887 | gc); | ||
888 | return gc; | ||
889 | } | ||
890 | |||
891 | |||
892 | /** | ||
893 | * Create a new private key by reading our peer's key from | 611 | * Create a new private key by reading our peer's key from |
894 | * the file specified in the configuration. | 612 | * the file specified in the configuration. |
895 | * | 613 | * |
diff --git a/src/util/test_crypto_ecc.c b/src/util/test_crypto_ecc.c index 8aa58971f..1d58e9607 100644 --- a/src/util/test_crypto_ecc.c +++ b/src/util/test_crypto_ecc.c | |||
@@ -146,40 +146,6 @@ testCreateFromFile () | |||
146 | 146 | ||
147 | 147 | ||
148 | static void | 148 | static void |
149 | key_cont (void *cls, | ||
150 | struct GNUNET_CRYPTO_EccPrivateKey *pk, | ||
151 | const char *emsg) | ||
152 | { | ||
153 | const char *txt = cls; | ||
154 | struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub1; | ||
155 | struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pub2; | ||
156 | |||
157 | GNUNET_assert (0 == strcmp ("ok", txt)); | ||
158 | GNUNET_CRYPTO_ecc_key_get_public (pk, &pub1); | ||
159 | GNUNET_CRYPTO_ecc_key_get_public (key, &pub2); | ||
160 | GNUNET_assert (0 == memcmp (&pub1, &pub2, | ||
161 | sizeof (pub1))); | ||
162 | GNUNET_CRYPTO_ecc_key_free (pk); | ||
163 | } | ||
164 | |||
165 | |||
166 | static void | ||
167 | test_async_creation (void *cls, | ||
168 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
169 | { | ||
170 | struct GNUNET_CRYPTO_EccKeyGenerationContext *gc; | ||
171 | |||
172 | gc = GNUNET_CRYPTO_ecc_key_create_start (KEYFILE, | ||
173 | &key_cont, | ||
174 | (void*) "bug"); | ||
175 | GNUNET_CRYPTO_ecc_key_create_stop (gc); | ||
176 | gc = GNUNET_CRYPTO_ecc_key_create_start (KEYFILE, | ||
177 | &key_cont, | ||
178 | (void*) "ok"); | ||
179 | } | ||
180 | |||
181 | |||
182 | static void | ||
183 | test_ecdh () | 149 | test_ecdh () |
184 | { | 150 | { |
185 | struct GNUNET_CRYPTO_EccPrivateKey *priv1; | 151 | struct GNUNET_CRYPTO_EccPrivateKey *priv1; |
@@ -238,7 +204,6 @@ main (int argc, char *argv[]) | |||
238 | GNUNET_log_setup ("test-crypto-ecc", "WARNING", NULL); | 204 | GNUNET_log_setup ("test-crypto-ecc", "WARNING", NULL); |
239 | if (GNUNET_OK != testCreateFromFile ()) | 205 | if (GNUNET_OK != testCreateFromFile ()) |
240 | failureCount++; | 206 | failureCount++; |
241 | GNUNET_SCHEDULER_run (&test_async_creation, NULL); | ||
242 | #if PERF | 207 | #if PERF |
243 | if (GNUNET_OK != testSignPerformance ()) | 208 | if (GNUNET_OK != testSignPerformance ()) |
244 | failureCount++; | 209 | failureCount++; |