diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-10-17 19:35:13 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-10-17 19:35:13 +0000 |
commit | 69c3f226a7e62844b7dc08da92affeed8a062f4b (patch) | |
tree | 0a725aa1e16458a78a1dd0de6dc2f99b8dcbf1d7 /src/util/crypto_ecc.c | |
parent | 5ad33cbc7aa715b7c154196aab7b4e1db76487b3 (diff) | |
download | gnunet-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.c | 430 |
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 | */ | ||
65 | struct GNUNET_CRYPTO_EccSignature | ||
66 | { | ||
67 | unsigned char sig[GNUNET_CRYPTO_ECC_DATA_ENCODING_LENGTH]; | ||
68 | }; | ||
69 | |||
70 | |||
71 | GNUNET_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 | */ | ||
78 | struct 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). |
102 | struct 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 | |||
121 | struct 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 | */ |
139 | struct 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 | |||
144 | GNUNET_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 | */ | ||
168 | typedef 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 | */ |
206 | void | 95 | void |
@@ -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 | */ |
413 | struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * | 303 | struct GNUNET_CRYPTO_EccPrivateKeyBinaryEncoded * |
414 | GNUNET_CRYPTO_ecc_encode_key (const struct GNUNET_CRYPTO_EccPrivateKey *hostkey) | 304 | GNUNET_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 | */ |
481 | struct GNUNET_CRYPTO_EccPrivateKey * | 344 | struct GNUNET_CRYPTO_EccPrivateKey * |
482 | GNUNET_CRYPTO_ecc_decode_key (const char *buf, uint16_t len) | 345 | GNUNET_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 * | |||
574 | try_read_key (const char *filename) | 411 | try_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 | */ |
1159 | ssize_t | 991 | ssize_t |
1160 | GNUNET_CRYPTO_ecc_decrypt (const struct GNUNET_CRYPTO_EccPrivateKey * key, | 992 | GNUNET_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 | */ | ||
1039 | static gcry_sexp_t | ||
1040 | data_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__, |