diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-10-26 22:13:01 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-10-26 22:13:01 +0000 |
commit | 64d3e46cfb99a711e500fa1f114e7c44bdf10040 (patch) | |
tree | 83093d92761d5c1b8b2fded713adaa19af29274c /src/util/crypto_ecc.c | |
parent | ef6f05f63769263a5201636c4b7f71eaa455cdf3 (diff) | |
download | gnunet-64d3e46cfb99a711e500fa1f114e7c44bdf10040.tar.gz gnunet-64d3e46cfb99a711e500fa1f114e7c44bdf10040.zip |
-bugfixes, code cleanup
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r-- | src/util/crypto_ecc.c | 98 |
1 files changed, 47 insertions, 51 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index 60f70e083..56cb3c709 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c | |||
@@ -25,7 +25,9 @@ | |||
25 | * | 25 | * |
26 | * This is just a first, completely untested, draft hack for future ECC support. | 26 | * This is just a first, completely untested, draft hack for future ECC support. |
27 | * TODO: | 27 | * TODO: |
28 | * - adjust encoding length and other parameters | 28 | * - fix public key generation; somehow the result is currently considered invalid by libgcrypt |
29 | * => suspect that libgcrypt does NOT take pabgn from "CURVE" for public key if not | ||
30 | * explicitly given! | ||
29 | * - actually test it! | 31 | * - actually test it! |
30 | */ | 32 | */ |
31 | #include "platform.h" | 33 | #include "platform.h" |
@@ -65,26 +67,6 @@ struct GNUNET_CRYPTO_EccPrivateKey | |||
65 | 67 | ||
66 | 68 | ||
67 | /** | 69 | /** |
68 | * If target != size, move target bytes to the | ||
69 | * end of the size-sized buffer and zero out the | ||
70 | * first target-size bytes. | ||
71 | * | ||
72 | * @param buf original buffer | ||
73 | * @param size number of bytes in the buffer | ||
74 | * @param target target size of the buffer | ||
75 | */ | ||
76 | static void | ||
77 | adjust (unsigned char *buf, size_t size, size_t target) | ||
78 | { | ||
79 | if (size < target) | ||
80 | { | ||
81 | memmove (&buf[target - size], buf, size); | ||
82 | memset (buf, 0, target - size); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | |||
87 | /** | ||
88 | * Free memory occupied by ECC key | 70 | * Free memory occupied by ECC key |
89 | * | 71 | * |
90 | * @param privatekey pointer to the memory to free | 72 | * @param privatekey pointer to the memory to free |
@@ -171,6 +153,7 @@ GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv | |||
171 | size_t size; | 153 | size_t size; |
172 | int rc; | 154 | int rc; |
173 | 155 | ||
156 | memset (pub, 0, sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); | ||
174 | rc = key_from_sexp (&skey, priv->sexp, "public-key", "q"); | 157 | rc = key_from_sexp (&skey, priv->sexp, "public-key", "q"); |
175 | if (rc) | 158 | if (rc) |
176 | rc = key_from_sexp (&skey, priv->sexp, "private-key", "q"); | 159 | rc = key_from_sexp (&skey, priv->sexp, "private-key", "q"); |
@@ -183,7 +166,6 @@ GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv | |||
183 | gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size, | 166 | gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size, |
184 | skey)); | 167 | skey)); |
185 | pub->len = htons (size); | 168 | pub->len = htons (size); |
186 | adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH); | ||
187 | gcry_mpi_release (skey); | 169 | gcry_mpi_release (skey); |
188 | } | 170 | } |
189 | 171 | ||
@@ -245,7 +227,7 @@ GNUNET_CRYPTO_ecc_public_key_from_string (const char *enc, | |||
245 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded))) | 227 | sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded))) |
246 | return GNUNET_SYSERR; | 228 | return GNUNET_SYSERR; |
247 | if ( (ntohs (pub->size) != sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) || | 229 | if ( (ntohs (pub->size) != sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)) || |
248 | (ntohs (pub->len) > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH) ) | 230 | (ntohs (pub->len) > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH) ) |
249 | return GNUNET_SYSERR; | 231 | return GNUNET_SYSERR; |
250 | return GNUNET_OK; | 232 | return GNUNET_OK; |
251 | } | 233 | } |
@@ -267,24 +249,38 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicK | |||
267 | size_t erroff; | 249 | size_t erroff; |
268 | int rc; | 250 | int rc; |
269 | 251 | ||
270 | if (ntohs (publicKey->len) > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH) | 252 | if (ntohs (publicKey->len) > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH) |
271 | { | 253 | { |
272 | GNUNET_break (0); | 254 | GNUNET_break (0); |
273 | return NULL; | 255 | return NULL; |
274 | } | 256 | } |
275 | size = ntohs (publicKey->size); | 257 | size = ntohs (publicKey->len); |
276 | if (0 != (rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG, publicKey->key, size, &size))) | 258 | if (0 != (rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG, publicKey->key, size, &size))) |
277 | { | 259 | { |
278 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); | 260 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); |
279 | return NULL; | 261 | return NULL; |
280 | } | 262 | } |
281 | rc = gcry_sexp_build (&result, &erroff, "(public-key(ecc((curve \"" CURVE "\")(q %m)))", q); | 263 | |
264 | rc = gcry_sexp_build (&result, &erroff, | ||
265 | "(public-key(ecdsa(curve \"" CURVE "\")(q %m)))", | ||
266 | q); | ||
282 | gcry_mpi_release (q); | 267 | gcry_mpi_release (q); |
283 | if (0 != rc) | 268 | if (0 != rc) |
284 | { | 269 | { |
285 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ | 270 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ |
286 | return NULL; | 271 | return NULL; |
287 | } | 272 | } |
273 | // FIXME: is this key expected to pass pk_testkey? | ||
274 | #if 0 | ||
275 | #if EXTRA_CHECKS | ||
276 | if (0 != (rc = gcry_pk_testkey (result))) | ||
277 | { | ||
278 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); | ||
279 | gcry_sexp_release (result); | ||
280 | return NULL; | ||
281 | } | ||
282 | #endif | ||
283 | #endif | ||
288 | return result; | 284 | return result; |
289 | } | 285 | } |
290 | 286 | ||
@@ -386,7 +382,7 @@ ecc_key_create () | |||
386 | int rc; | 382 | int rc; |
387 | 383 | ||
388 | if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, | 384 | if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL, |
389 | "(genkey(ecdsa(curve 10:NIST P-521)))"))) | 385 | "(genkey(ecdsa(curve \"" CURVE "\")))"))) |
390 | { | 386 | { |
391 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); | 387 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); |
392 | return NULL; | 388 | return NULL; |
@@ -428,7 +424,7 @@ try_read_key (const char *filename) | |||
428 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) | 424 | if (GNUNET_YES != GNUNET_DISK_file_test (filename)) |
429 | return NULL; | 425 | return NULL; |
430 | 426 | ||
431 | /* hostkey file exists already, read it! */ | 427 | /* key file exists already, read it! */ |
432 | if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, | 428 | if (NULL == (fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, |
433 | GNUNET_DISK_PERM_NONE))) | 429 | GNUNET_DISK_PERM_NONE))) |
434 | { | 430 | { |
@@ -582,12 +578,9 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
582 | GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); | 578 | GNUNET_assert (GNUNET_YES == GNUNET_DISK_file_close (fd)); |
583 | GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); | 579 | GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); |
584 | GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); | 580 | GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); |
585 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
586 | _("I am host `%s'. Stored new private key in `%s'.\n"), | ||
587 | GNUNET_i2s (&pid), filename); | ||
588 | return ret; | 581 | return ret; |
589 | } | 582 | } |
590 | /* hostkey file exists already, read it! */ | 583 | /* key file exists already, read it! */ |
591 | fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, | 584 | fd = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, |
592 | GNUNET_DISK_PERM_NONE); | 585 | GNUNET_DISK_PERM_NONE); |
593 | if (NULL == fd) | 586 | if (NULL == fd) |
@@ -611,7 +604,7 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
611 | STRERROR (ec)); | 604 | STRERROR (ec)); |
612 | LOG (GNUNET_ERROR_TYPE_ERROR, | 605 | LOG (GNUNET_ERROR_TYPE_ERROR, |
613 | _ | 606 | _ |
614 | ("This may be ok if someone is currently generating a hostkey.\n")); | 607 | ("This may be ok if someone is currently generating a private key.\n")); |
615 | } | 608 | } |
616 | short_wait (); | 609 | short_wait (); |
617 | continue; | 610 | continue; |
@@ -632,7 +625,7 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
632 | fs = 0; | 625 | fs = 0; |
633 | if (fs < sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)) | 626 | if (fs < sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)) |
634 | { | 627 | { |
635 | /* maybe we got the read lock before the hostkey generating | 628 | /* maybe we got the read lock before the key generating |
636 | * process had a chance to get the write lock; give it up! */ | 629 | * process had a chance to get the write lock; give it up! */ |
637 | if (GNUNET_YES != | 630 | if (GNUNET_YES != |
638 | GNUNET_DISK_file_unlock (fd, 0, | 631 | GNUNET_DISK_file_unlock (fd, 0, |
@@ -642,12 +635,12 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
642 | { | 635 | { |
643 | LOG (GNUNET_ERROR_TYPE_ERROR, | 636 | LOG (GNUNET_ERROR_TYPE_ERROR, |
644 | _ | 637 | _ |
645 | ("When trying to read hostkey file `%s' I found %u bytes but I need at least %u.\n"), | 638 | ("When trying to read key file `%s' I found %u bytes but I need at least %u.\n"), |
646 | filename, (unsigned int) fs, | 639 | filename, (unsigned int) fs, |
647 | (unsigned int) sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)); | 640 | (unsigned int) sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded)); |
648 | LOG (GNUNET_ERROR_TYPE_ERROR, | 641 | LOG (GNUNET_ERROR_TYPE_ERROR, |
649 | _ | 642 | _ |
650 | ("This may be ok if someone is currently generating a hostkey.\n")); | 643 | ("This may be ok if someone is currently generating a key.\n")); |
651 | } | 644 | } |
652 | short_wait (); /* wait a bit longer! */ | 645 | short_wait (); /* wait a bit longer! */ |
653 | continue; | 646 | continue; |
@@ -679,9 +672,6 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename) | |||
679 | { | 672 | { |
680 | GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); | 673 | GNUNET_CRYPTO_ecc_key_get_public (ret, &pub); |
681 | GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); | 674 | GNUNET_CRYPTO_hash (&pub, sizeof (pub), &pid.hashPubKey); |
682 | LOG (GNUNET_ERROR_TYPE_INFO, | ||
683 | _("I am host `%s'. Read private key from `%s'.\n"), GNUNET_i2s (&pid), | ||
684 | filename); | ||
685 | } | 675 | } |
686 | return ret; | 676 | return ret; |
687 | } | 677 | } |
@@ -909,15 +899,15 @@ GNUNET_CRYPTO_ecc_key_create_start (const char *filename, | |||
909 | 899 | ||
910 | 900 | ||
911 | /** | 901 | /** |
912 | * Setup a hostkey file for a peer given the name of the | 902 | * Setup a key file for a peer given the name of the |
913 | * configuration file (!). This function is used so that | 903 | * configuration file (!). This function is used so that |
914 | * at a later point code can be certain that reading a | 904 | * at a later point code can be certain that reading a |
915 | * hostkey is fast (for example in time-dependent testcases). | 905 | * key is fast (for example in time-dependent testcases). |
916 | * | 906 | * |
917 | * @param cfg_name name of the configuration file to use | 907 | * @param cfg_name name of the configuration file to use |
918 | */ | 908 | */ |
919 | void | 909 | void |
920 | GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name) | 910 | GNUNET_CRYPTO_ecc_setup_key (const char *cfg_name) |
921 | { | 911 | { |
922 | struct GNUNET_CONFIGURATION_Handle *cfg; | 912 | struct GNUNET_CONFIGURATION_Handle *cfg; |
923 | struct GNUNET_CRYPTO_EccPrivateKey *pk; | 913 | struct GNUNET_CRYPTO_EccPrivateKey *pk; |
@@ -947,12 +937,12 @@ GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name) | |||
947 | static gcry_sexp_t | 937 | static gcry_sexp_t |
948 | data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) | 938 | data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) |
949 | { | 939 | { |
950 | struct GNUNET_HashCode hc; | 940 | struct GNUNET_CRYPTO_ShortHashCode hc; |
951 | size_t bufSize; | 941 | size_t bufSize; |
952 | gcry_sexp_t data; | 942 | gcry_sexp_t data; |
953 | 943 | ||
954 | GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); | 944 | GNUNET_CRYPTO_short_hash (purpose, ntohl (purpose->size), &hc); |
955 | #define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))" | 945 | #define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha25632:01234567890123456789012345678901))" |
956 | bufSize = strlen (FORMATSTRING) + 1; | 946 | bufSize = strlen (FORMATSTRING) + 1; |
957 | { | 947 | { |
958 | char buff[bufSize]; | 948 | char buff[bufSize]; |
@@ -961,8 +951,8 @@ data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) | |||
961 | memcpy (&buff | 951 | memcpy (&buff |
962 | [bufSize - | 952 | [bufSize - |
963 | strlen | 953 | strlen |
964 | ("0123456789012345678901234567890123456789012345678901234567890123))") | 954 | ("01234567890123456789012345678901))") |
965 | - 1], &hc, sizeof (struct GNUNET_HashCode)); | 955 | - 1], &hc, sizeof (struct GNUNET_CRYPTO_ShortHashCode)); |
966 | GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); | 956 | GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0)); |
967 | } | 957 | } |
968 | #undef FORMATSTRING | 958 | #undef FORMATSTRING |
@@ -986,14 +976,20 @@ GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key, | |||
986 | gcry_sexp_t result; | 976 | gcry_sexp_t result; |
987 | gcry_sexp_t data; | 977 | gcry_sexp_t data; |
988 | size_t ssize; | 978 | size_t ssize; |
979 | int rc; | ||
989 | 980 | ||
990 | data = data_to_pkcs1 (purpose); | 981 | data = data_to_pkcs1 (purpose); |
991 | GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp)); | 982 | if (0 != (rc = gcry_pk_sign (&result, data, key->sexp))) |
983 | { | ||
984 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
985 | _("ECC signing failed at %s:%d: %s\n"), __FILE__, | ||
986 | __LINE__, gcry_strerror (rc)); | ||
987 | } | ||
992 | gcry_sexp_release (data); | 988 | gcry_sexp_release (data); |
993 | ssize = gcry_sexp_sprint (result, | 989 | ssize = gcry_sexp_sprint (result, |
994 | GCRYSEXP_FMT_DEFAULT, | 990 | GCRYSEXP_FMT_DEFAULT, |
995 | sig->sexpr, | 991 | sig->sexpr, |
996 | GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH); | 992 | GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH); |
997 | if (0 == ssize) | 993 | if (0 == ssize) |
998 | { | 994 | { |
999 | GNUNET_break (0); | 995 | GNUNET_break (0); |
@@ -1001,7 +997,7 @@ GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key, | |||
1001 | } | 997 | } |
1002 | sig->size = htons ((uint16_t) (ssize + sizeof (uint16_t))); | 998 | sig->size = htons ((uint16_t) (ssize + sizeof (uint16_t))); |
1003 | /* padd with zeros */ | 999 | /* padd with zeros */ |
1004 | memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - ssize); | 1000 | memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH - ssize); |
1005 | gcry_sexp_release (result); | 1001 | gcry_sexp_release (result); |
1006 | return GNUNET_OK; | 1002 | return GNUNET_OK; |
1007 | } | 1003 | } |
@@ -1035,7 +1031,7 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose, | |||
1035 | return GNUNET_SYSERR; /* purpose mismatch */ | 1031 | return GNUNET_SYSERR; /* purpose mismatch */ |
1036 | size = ntohs (sig->size); | 1032 | size = ntohs (sig->size); |
1037 | if ( (size < sizeof (uint16_t)) || | 1033 | if ( (size < sizeof (uint16_t)) || |
1038 | (size > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - sizeof (uint16_t)) ) | 1034 | (size > GNUNET_CRYPTO_ECC_SIGNATURE_DATA_ENCODING_LENGTH - sizeof (uint16_t)) ) |
1039 | return GNUNET_SYSERR; /* size out of range */ | 1035 | return GNUNET_SYSERR; /* size out of range */ |
1040 | data = data_to_pkcs1 (validate); | 1036 | data = data_to_pkcs1 (validate); |
1041 | GNUNET_assert (0 == | 1037 | GNUNET_assert (0 == |