aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-10-17 19:35:13 +0000
committerChristian Grothoff <christian@grothoff.org>2012-10-17 19:35:13 +0000
commit69c3f226a7e62844b7dc08da92affeed8a062f4b (patch)
tree0a725aa1e16458a78a1dd0de6dc2f99b8dcbf1d7 /src/util/crypto_ecc.c
parent5ad33cbc7aa715b7c154196aab7b4e1db76487b3 (diff)
downloadgnunet-69c3f226a7e62844b7dc08da92affeed8a062f4b.tar.gz
gnunet-69c3f226a7e62844b7dc08da92affeed8a062f4b.zip
-fixing obvious ecc issues, adding gnunet-ecc based on gnunet-rsa
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r--src/util/crypto_ecc.c430
1 files changed, 133 insertions, 297 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 1ef1ec7b5..af3fe3359 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -46,103 +46,12 @@
46 46
47#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) 47#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
48 48
49
50/**
51 * FIXME: what is an acceptable value here?
52 */
53#define GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH 64
54
55/**
56 * Length of the q-point (Q = dP) in the public key.
57 * FIXME: double-check that this is right.
58 */
59#define GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH 64
60
61
62/**
63 * @brief an ECC signature
64 */
65struct GNUNET_CRYPTO_EccSignature
66{
67 unsigned char sig[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
68};
69
70
71GNUNET_NETWORK_STRUCT_BEGIN
72
73/**
74 * @brief header of what an ECC signature signs
75 * this must be followed by "size - 8" bytes of
76 * the actual signed data
77 */
78struct GNUNET_CRYPTO_EccSignaturePurpose
79{
80 /**
81 * How many bytes does this signature sign?
82 * (including this purpose header); in network
83 * byte order (!).
84 */
85 uint32_t size GNUNET_PACKED;
86
87 /**
88 * What does this signature vouch for? This
89 * must contain a GNUNET_SIGNATURE_PURPOSE_XXX
90 * constant (from gnunet_signatures.h). In
91 * network byte order!
92 */
93 uint32_t purpose GNUNET_PACKED;
94
95};
96
97
98/** 49/**
99 * Public ECC key (always for NIST P-521) encoded in a format suitable 50 * Log an error message at log-level 'level' that indicates
100 * for network transmission. 51 * a failure of the command 'cmd' with the message given
101 */ 52 * by gcry_strerror(rc).
102struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded
103{
104 /**
105 * Size of the encoding, in network byte order.
106 */
107 uint16_t size;
108
109 /**
110 * Actual length of the q-point binary encoding.
111 */
112 uint16_t len;
113
114 /**
115 * 0-padded q-point in binary encoding (GCRYPT_MPI_FMT_USG).
116 */
117 unsigned char key[GNUNET_CRYPTO_ECC_PUBLIC_KEY_LENGTH];
118};
119
120
121struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded
122{
123 /**
124 * Overall size of the private key.
125 */
126 uint16_t size;
127
128 /**
129 * Size of the q and d components of the private key.
130 * Note that the other parameters are from NIST P-521.
131 */
132 uint16_t sizes[2];
133};
134
135
136/**
137 * ECC Encrypted data.
138 */ 53 */
139struct GNUNET_CRYPTO_EccEncryptedData 54#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);
140{
141 unsigned char encoding[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH];
142};
143
144GNUNET_NETWORK_STRUCT_END
145
146 55
147 56
148/** 57/**
@@ -159,27 +68,6 @@ struct GNUNET_CRYPTO_EccPrivateKey
159 68
160 69
161/** 70/**
162 * Function called upon completion of 'GNUNET_CRYPTO_ecc_key_create_async'.
163 *
164 * @param cls closure
165 * @param pk NULL on error, otherwise the private key (which must be free'd by the callee)
166 * @param emsg NULL on success, otherwise an error message
167 */
168typedef void (*GNUNET_CRYPTO_EccKeyCallback)(void *cls,
169 struct GNUNET_CRYPTO_EccPrivateKey *pk,
170 const char *emsg);
171
172
173
174/**
175 * Log an error message at log-level 'level' that indicates
176 * a failure of the command 'cmd' with the message given
177 * by gcry_strerror(rc).
178 */
179#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);
180
181
182/**
183 * If target != size, move target bytes to the 71 * If target != size, move target bytes to the
184 * end of the size-sized buffer and zero out the 72 * end of the size-sized buffer and zero out the
185 * first target-size bytes. 73 * first target-size bytes.
@@ -200,7 +88,8 @@ adjust (unsigned char *buf, size_t size, size_t target)
200 88
201 89
202/** 90/**
203 * Free memory occupied by hostkey 91 * Free memory occupied by ECC key
92 *
204 * @param privatekey pointer to the memory to free 93 * @param privatekey pointer to the memory to free
205 */ 94 */
206void 95void
@@ -292,12 +181,12 @@ GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv
292 rc = key_from_sexp (&skey, priv->sexp, "ecc", "q"); 181 rc = key_from_sexp (&skey, priv->sexp, "ecc", "q");
293 GNUNET_assert (0 == rc); 182 GNUNET_assert (0 == rc);
294 pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded)); 183 pub->size = htons (sizeof (struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded));
295 size = GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH; 184 size = GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH;
296 GNUNET_assert (0 == 185 GNUNET_assert (0 ==
297 gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size, 186 gcry_mpi_print (GCRYMPI_FMT_USG, pub->key, size, &size,
298 skey)); 187 skey));
299 pub->len = htons (size); 188 pub->len = htons (size);
300 adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH); 189 adjust (&pub->key[0], size, GNUNET_CRYPTO_ECC_MAX_PUBLIC_KEY_LENGTH);
301 gcry_mpi_release (skey); 190 gcry_mpi_release (skey);
302} 191}
303 192
@@ -407,19 +296,16 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded *publicK
407 * Encode the private key in a format suitable for 296 * Encode the private key in a format suitable for
408 * storing it into a file. 297 * storing it into a file.
409 * 298 *
410 * @returns encoding of the private key. 299 * @param key key to encode
300 * @return encoding of the private key.
411 * The first 4 bytes give the size of the array, as usual. 301 * The first 4 bytes give the size of the array, as usual.
412 */ 302 */
413struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * 303struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *
414GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey) 304GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *key)
415{ 305{
416 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval; 306 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *retval;
417 gcry_mpi_t pkv[2]; 307 char buf[65536];
418 void *pbu[2]; 308 uint16_t be;
419 size_t sizes[2];
420 size_t off;
421 int rc;
422 unsigned int i;
423 size_t size; 309 size_t size;
424 310
425#if EXTRA_CHECKS 311#if EXTRA_CHECKS
@@ -429,43 +315,20 @@ GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey)
429 return NULL; 315 return NULL;
430 } 316 }
431#endif 317#endif
432 318 size = gcry_sexp_sprint (key->sexp,
433 memset (pkv, 0, sizeof (gcry_mpi_t) * 2); 319 GCRYSEXP_FMT_DEFAULT,
434 rc = key_from_sexp (pkv, hostkey->sexp, "private-key", "qd"); 320 &buf[2], sizeof (buf) - sizeof (uint16_t));
435 if (rc) 321 if (0 == size)
436 rc = key_from_sexp (pkv, hostkey->sexp, "ecc", "qd");
437 GNUNET_assert (0 == rc);
438 size = sizeof (struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded);
439 for (i=0;i<2;i++)
440 { 322 {
441 if (NULL != pkv[i]) 323 GNUNET_break (0);
442 { 324 return NULL;
443 GNUNET_assert (0 ==
444 gcry_mpi_aprint (GCRYMPI_FMT_USG,
445 (unsigned char **) &pbu[i], &sizes[i],
446 pkv[i]));
447 size += sizes[i];
448 }
449 else
450 {
451 pbu[i] = NULL;
452 sizes[i] = 0;
453 }
454 } 325 }
455 GNUNET_assert (size < 65536); 326 GNUNET_assert (size < 65536 - sizeof (uint16_t));
327 be = htons ((uint16_t) size);
328 memcpy (buf, &be, sizeof (be));
329 size += sizeof (be);
456 retval = GNUNET_malloc (size); 330 retval = GNUNET_malloc (size);
457 retval->size = htons (size); 331 memcpy (retval, buf, size);
458 off = 0;
459 for (i=0;i<2;i++)
460 {
461 retval->sizes[i] = htons (sizes[0]);
462 memcpy (&((char *) (&retval[1]))[off], pbu[i], sizes[i]);
463 off += sizes[i];
464 if (NULL != pkv[i])
465 gcry_mpi_release (pkv[i]);
466 if (NULL != pbu[i])
467 free (pbu[i]);
468 }
469 return retval; 332 return retval;
470} 333}
471 334
@@ -479,61 +342,35 @@ GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey)
479 * @return NULL on error 342 * @return NULL on error
480 */ 343 */
481struct GNUNET_CRYPTO_EccPrivateKey * 344struct GNUNET_CRYPTO_EccPrivateKey *
482GNUNET_CRYPTO_ecc_decode_key (const char *buf, uint16_t len) 345GNUNET_CRYPTO_ecc_decode_key (const char *buf,
346 size_t len)
483{ 347{
484 struct GNUNET_CRYPTO_EccPrivateKey *ret; 348 struct GNUNET_CRYPTO_EccPrivateKey *ret;
485 const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *encoding = 349 uint16_t be;
486 (const struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *) buf; 350 gcry_sexp_t sexp;
487 gcry_sexp_t res;
488 gcry_mpi_t q;
489 gcry_mpi_t d;
490 int rc; 351 int rc;
491 size_t size;
492 size_t pos;
493 uint16_t enc_len;
494 size_t erroff; 352 size_t erroff;
495 353
496 enc_len = ntohs (encoding->size); 354 if (len < sizeof (uint16_t))
497 if (len != enc_len)
498 return NULL; 355 return NULL;
499 pos = 0; 356 memcpy (&be, buf, sizeof (be));
500 size = ntohs (encoding->sizes[0]); 357 if (len != ntohs (be))
501 rc = gcry_mpi_scan (&q, GCRYMPI_FMT_USG,
502 &((const unsigned char *) (&encoding[1]))[pos], size,
503 &size);
504 pos += ntohs (encoding->sizes[0]);
505 if (0 != rc)
506 {
507 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
508 return NULL; 358 return NULL;
509 } 359 if (0 != (rc = gcry_sexp_sscan (&sexp,
510 size = ntohs (encoding->sizes[1]); 360 &erroff,
511 rc = gcry_mpi_scan (&d, GCRYMPI_FMT_USG, 361 &buf[2],
512 &((const unsigned char *) (&encoding[1]))[pos], size, 362 len - sizeof (uint16_t))))
513 &size);
514 pos += ntohs (encoding->sizes[1]);
515 if (0 != rc)
516 { 363 {
517 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc); 364 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_scan", rc);
518 gcry_mpi_release (d);
519 return NULL; 365 return NULL;
520 } 366 }
521 rc = gcry_sexp_build (&res, &erroff, 367 if (0 != (rc = gcry_pk_testkey (sexp)))
522 "(private-key(ecc(q %m)(d %m)(curve \"" CURVE "\")))",
523 q, d);
524 gcry_mpi_release (q);
525 gcry_mpi_release (d);
526 if (0 != rc)
527 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
528#if EXTRA_CHECKS
529 if (0 != (rc = gcry_pk_testkey (res)))
530 { 368 {
531 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc); 369 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
532 return NULL; 370 return NULL;
533 } 371 }
534#endif
535 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); 372 ret = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey));
536 ret->sexp = res; 373 ret->sexp = sexp;
537 return ret; 374 return ret;
538} 375}
539 376
@@ -574,10 +411,8 @@ static struct GNUNET_CRYPTO_EccPrivateKey *
574try_read_key (const char *filename) 411try_read_key (const char *filename)
575{ 412{
576 struct GNUNET_CRYPTO_EccPrivateKey *ret; 413 struct GNUNET_CRYPTO_EccPrivateKey *ret;
577 struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded *enc;
578 struct GNUNET_DISK_FileHandle *fd; 414 struct GNUNET_DISK_FileHandle *fd;
579 OFF_T fs; 415 OFF_T fs;
580 uint16_t len;
581 416
582 if (GNUNET_YES != GNUNET_DISK_file_test (filename)) 417 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
583 return NULL; 418 return NULL;
@@ -611,26 +446,22 @@ try_read_key (const char *filename)
611 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename); 446 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
612 return NULL; 447 return NULL;
613 } 448 }
614
615 enc = GNUNET_malloc (fs);
616 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
617 len = ntohs (enc->size);
618 ret = NULL;
619 if ((len != fs) ||
620 (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, len))))
621 { 449 {
622 LOG (GNUNET_ERROR_TYPE_ERROR, 450 char enc[fs];
623 _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
624 filename,
625 (unsigned long long) fs);
626 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
627 if (0 != UNLINK (filename))
628 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
629 GNUNET_free (enc);
630 return NULL;
631 }
632 GNUNET_free (enc);
633 451
452 GNUNET_break (fs == GNUNET_DISK_file_read (fd, enc, fs));
453 if (NULL == (ret = GNUNET_CRYPTO_ecc_decode_key ((char *) enc, fs)))
454 {
455 LOG (GNUNET_ERROR_TYPE_ERROR,
456 _("File `%s' does not contain a valid private key (failed decode, %llu bytes). Deleting it.\n"),
457 filename,
458 (unsigned long long) fs);
459 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
460 if (0 != UNLINK (filename))
461 LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", filename);
462 return NULL;
463 }
464 }
634 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd)); 465 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_close (fd));
635 return ret; 466 return ret;
636} 467}
@@ -1084,7 +915,7 @@ GNUNET_CRYPTO_ecc_setup_hostkey (const char *cfg_name)
1084 cfg = GNUNET_CONFIGURATION_create (); 915 cfg = GNUNET_CONFIGURATION_create ();
1085 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name); 916 (void) GNUNET_CONFIGURATION_load (cfg, cfg_name);
1086 if (GNUNET_OK == 917 if (GNUNET_OK ==
1087 GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY", &fn)) 918 GNUNET_CONFIGURATION_get_value_filename (cfg, "PEER", "PRIVATE_KEY", &fn))
1088 { 919 {
1089 pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn); 920 pk = GNUNET_CRYPTO_ecc_key_create_from_file (fn);
1090 if (NULL != pk) 921 if (NULL != pk)
@@ -1115,7 +946,6 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1115 gcry_sexp_t data; 946 gcry_sexp_t data;
1116 gcry_sexp_t psexp; 947 gcry_sexp_t psexp;
1117 gcry_mpi_t val; 948 gcry_mpi_t val;
1118 gcry_mpi_t rval;
1119 size_t isize; 949 size_t isize;
1120 size_t erroff; 950 size_t erroff;
1121 951
@@ -1132,16 +962,18 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1132 GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp)); 962 GNUNET_assert (0 == gcry_pk_encrypt (&result, data, psexp));
1133 gcry_sexp_release (data); 963 gcry_sexp_release (data);
1134 gcry_sexp_release (psexp); 964 gcry_sexp_release (psexp);
1135 965 isize = gcry_sexp_sprint (result,
1136 GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "a")); 966 GCRYSEXP_FMT_DEFAULT,
1137 gcry_sexp_release (result); 967 target->encoding,
1138 isize = sizeof (struct GNUNET_CRYPTO_EccEncryptedData); 968 GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
1139 GNUNET_assert (0 == 969 if (0 == isize)
1140 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) target, 970 {
1141 isize, &isize, rval)); 971 GNUNET_break (0);
1142 gcry_mpi_release (rval); 972 return GNUNET_SYSERR;
1143 adjust (&target->encoding[0], isize, 973 }
1144 sizeof (struct GNUNET_CRYPTO_EccEncryptedData)); 974 target->size = htons ((uint16_t) isize);
975 /* padd with zeros */
976 memset (&target->encoding[isize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - isize);
1145 return GNUNET_OK; 977 return GNUNET_OK;
1146} 978}
1147 979
@@ -1157,8 +989,8 @@ GNUNET_CRYPTO_ecc_encrypt (const void *block, size_t size,
1157 * @return the size of the decrypted block, -1 on error 989 * @return the size of the decrypted block, -1 on error
1158 */ 990 */
1159ssize_t 991ssize_t
1160GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key, 992GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1161 const struct GNUNET_CRYPTO_EccEncryptedData * block, 993 const struct GNUNET_CRYPTO_EccEncryptedData *block,
1162 void *result, size_t max) 994 void *result, size_t max)
1163{ 995{
1164 gcry_sexp_t resultsexp; 996 gcry_sexp_t resultsexp;
@@ -1167,19 +999,15 @@ GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key,
1167 size_t size; 999 size_t size;
1168 gcry_mpi_t val; 1000 gcry_mpi_t val;
1169 unsigned char *endp; 1001 unsigned char *endp;
1170 unsigned char *tmp;
1171 1002
1172#if EXTRA_CHECKS 1003#if EXTRA_CHECKS
1173 GNUNET_assert (0 == gcry_pk_testkey (key->sexp)); 1004 GNUNET_assert (0 == gcry_pk_testkey (key->sexp));
1174#endif 1005#endif
1175 size = sizeof (struct GNUNET_CRYPTO_EccEncryptedData); 1006 size = ntohs (block->size);
1176 GNUNET_assert (0 ==
1177 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, &block->encoding[0],
1178 size, &size));
1179 GNUNET_assert (0 == 1007 GNUNET_assert (0 ==
1180 gcry_sexp_build (&data, &erroff, "(enc-val(flags)(ecc(a %m)))", 1008 gcry_sexp_sscan (&data,
1181 val)); 1009 &erroff,
1182 gcry_mpi_release (val); 1010 block->encoding, size));
1183 GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp)); 1011 GNUNET_assert (0 == gcry_pk_decrypt (&resultsexp, data, key->sexp));
1184 gcry_sexp_release (data); 1012 gcry_sexp_release (data);
1185 /* resultsexp has format "(value %m)" */ 1013 /* resultsexp has format "(value %m)" */
@@ -1187,19 +1015,54 @@ GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key,
1187 (val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG))); 1015 (val = gcry_sexp_nth_mpi (resultsexp, 1, GCRYMPI_FMT_USG)));
1188 gcry_sexp_release (resultsexp); 1016 gcry_sexp_release (resultsexp);
1189 size = max + GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH * 2; 1017 size = max + GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH * 2;
1190 tmp = GNUNET_malloc (size); 1018 {
1191 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val)); 1019 unsigned char tmp[size];
1192 gcry_mpi_release (val); 1020
1193 endp = tmp; 1021 GNUNET_assert (0 == gcry_mpi_print (GCRYMPI_FMT_USG, tmp, size, &size, val));
1194 endp += (size - max); 1022 gcry_mpi_release (val);
1195 size = max; 1023 endp = tmp;
1196 memcpy (result, endp, size); 1024 endp += (size - max);
1197 GNUNET_free (tmp); 1025 size = max;
1026 memcpy (result, endp, size);
1027 }
1198 return size; 1028 return size;
1199} 1029}
1200 1030
1201 1031
1202/** 1032/**
1033 * Convert the data specified in the given purpose argument to an
1034 * S-expression suitable for signature operations.
1035 *
1036 * @param purpose data to convert
1037 * @return converted s-expression
1038 */
1039static gcry_sexp_t
1040data_to_pkcs1 (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
1041{
1042 struct GNUNET_HashCode hc;
1043 size_t bufSize;
1044 gcry_sexp_t data;
1045
1046 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
1047#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
1048 bufSize = strlen (FORMATSTRING) + 1;
1049 {
1050 char buff[bufSize];
1051
1052 memcpy (buff, FORMATSTRING, bufSize);
1053 memcpy (&buff
1054 [bufSize -
1055 strlen
1056 ("0123456789012345678901234567890123456789012345678901234567890123))")
1057 - 1], &hc, sizeof (struct GNUNET_HashCode));
1058 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1059 }
1060#undef FORMATSTRING
1061 return data;
1062}
1063
1064
1065/**
1203 * Sign a given block. 1066 * Sign a given block.
1204 * 1067 *
1205 * @param key private key to use for the signing 1068 * @param key private key to use for the signing
@@ -1215,33 +1078,23 @@ GNUNET_CRYPTO_ecc_sign (const struct GNUNET_CRYPTO_EccPrivateKey *key,
1215 gcry_sexp_t result; 1078 gcry_sexp_t result;
1216 gcry_sexp_t data; 1079 gcry_sexp_t data;
1217 size_t ssize; 1080 size_t ssize;
1218 gcry_mpi_t rval;
1219 struct GNUNET_HashCode hc;
1220 char *buff;
1221 int bufSize;
1222 1081
1223 GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc); 1082 data = data_to_pkcs1 (purpose);
1224#define FORMATSTRING "(4:data(5:flags5:pkcs1)(4:hash6:sha51264:0123456789012345678901234567890123456789012345678901234567890123))"
1225 bufSize = strlen (FORMATSTRING) + 1;
1226 buff = GNUNET_malloc (bufSize);
1227 memcpy (buff, FORMATSTRING, bufSize);
1228 memcpy (&buff
1229 [bufSize -
1230 strlen
1231 ("0123456789012345678901234567890123456789012345678901234567890123))")
1232 - 1], &hc, sizeof (struct GNUNET_HashCode));
1233 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1234 GNUNET_free (buff);
1235 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp)); 1083 GNUNET_assert (0 == gcry_pk_sign (&result, data, key->sexp));
1236 gcry_sexp_release (data); 1084 gcry_sexp_release (data);
1237 GNUNET_assert (0 == key_from_sexp (&rval, result, "ecc", "s")); 1085 ssize = gcry_sexp_sprint (result,
1086 GCRYSEXP_FMT_DEFAULT,
1087 sig->sexpr,
1088 GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH);
1089 if (0 == ssize)
1090 {
1091 GNUNET_break (0);
1092 return GNUNET_SYSERR;
1093 }
1094 sig->size = htons ((uint16_t) ssize);
1095 /* padd with zeros */
1096 memset (&sig->sexpr[ssize], 0, GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - ssize);
1238 gcry_sexp_release (result); 1097 gcry_sexp_release (result);
1239 ssize = sizeof (struct GNUNET_CRYPTO_EccSignature);
1240 GNUNET_assert (0 ==
1241 gcry_mpi_print (GCRYMPI_FMT_USG, (unsigned char *) sig, ssize,
1242 &ssize, rval));
1243 gcry_mpi_release (rval);
1244 adjust (sig->sig, ssize, sizeof (struct GNUNET_CRYPTO_EccSignature));
1245 return GNUNET_OK; 1098 return GNUNET_OK;
1246} 1099}
1247 1100
@@ -1266,35 +1119,18 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
1266 gcry_sexp_t data; 1119 gcry_sexp_t data;
1267 gcry_sexp_t sigdata; 1120 gcry_sexp_t sigdata;
1268 size_t size; 1121 size_t size;
1269 gcry_mpi_t val;
1270 gcry_sexp_t psexp; 1122 gcry_sexp_t psexp;
1271 struct GNUNET_HashCode hc;
1272 char *buff;
1273 int bufSize;
1274 size_t erroff; 1123 size_t erroff;
1275 int rc; 1124 int rc;
1276 1125
1277 if (purpose != ntohl (validate->purpose)) 1126 if (purpose != ntohl (validate->purpose))
1278 return GNUNET_SYSERR; /* purpose mismatch */ 1127 return GNUNET_SYSERR; /* purpose mismatch */
1279 GNUNET_CRYPTO_hash (validate, ntohl (validate->size), &hc); 1128 size = ntohs (sig->size);
1280 size = sizeof (struct GNUNET_CRYPTO_EccSignature); 1129 if (size > GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH - sizeof (uint16_t))
1130 return GNUNET_SYSERR; /* size out of range */
1131 data = data_to_pkcs1 (validate);
1281 GNUNET_assert (0 == 1132 GNUNET_assert (0 ==
1282 gcry_mpi_scan (&val, GCRYMPI_FMT_USG, 1133 gcry_sexp_sscan (&sigdata, &erroff, sig->sexpr, size));
1283 (const unsigned char *) sig, size, &size));
1284 GNUNET_assert (0 ==
1285 gcry_sexp_build (&sigdata, &erroff, "(sig-val(ecc(s %m)))",
1286 val));
1287 gcry_mpi_release (val);
1288 bufSize = strlen (FORMATSTRING) + 1;
1289 buff = GNUNET_malloc (bufSize);
1290 memcpy (buff, FORMATSTRING, bufSize);
1291 memcpy (&buff
1292 [strlen (FORMATSTRING) -
1293 strlen
1294 ("0123456789012345678901234567890123456789012345678901234567890123))")],
1295 &hc, sizeof (struct GNUNET_HashCode));
1296 GNUNET_assert (0 == gcry_sexp_new (&data, buff, bufSize, 0));
1297 GNUNET_free (buff);
1298 if (! (psexp = decode_public_key (publicKey))) 1134 if (! (psexp = decode_public_key (publicKey)))
1299 { 1135 {
1300 gcry_sexp_release (data); 1136 gcry_sexp_release (data);
@@ -1305,7 +1141,7 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
1305 gcry_sexp_release (psexp); 1141 gcry_sexp_release (psexp);
1306 gcry_sexp_release (data); 1142 gcry_sexp_release (data);
1307 gcry_sexp_release (sigdata); 1143 gcry_sexp_release (sigdata);
1308 if (rc) 1144 if (0 != rc)
1309 { 1145 {
1310 LOG (GNUNET_ERROR_TYPE_WARNING, 1146 LOG (GNUNET_ERROR_TYPE_WARNING,
1311 _("ECC signature verification failed at %s:%d: %s\n"), __FILE__, 1147 _("ECC signature verification failed at %s:%d: %s\n"), __FILE__,