aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-10-26 22:13:01 +0000
committerChristian Grothoff <christian@grothoff.org>2012-10-26 22:13:01 +0000
commit64d3e46cfb99a711e500fa1f114e7c44bdf10040 (patch)
tree83093d92761d5c1b8b2fded713adaa19af29274c /src/util/crypto_ecc.c
parentef6f05f63769263a5201636c4b7f71eaa455cdf3 (diff)
downloadgnunet-64d3e46cfb99a711e500fa1f114e7c44bdf10040.tar.gz
gnunet-64d3e46cfb99a711e500fa1f114e7c44bdf10040.zip
-bugfixes, code cleanup
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r--src/util/crypto_ecc.c98
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 */
76static void
77adjust (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 */
919void 909void
920GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name) 910GNUNET_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)
947static gcry_sexp_t 937static gcry_sexp_t
948data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose) 938data_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 ==