aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/util/gnunet-crypto-tvg.c607
1 files changed, 595 insertions, 12 deletions
diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c
index b9dbba065..5915b4b44 100644
--- a/src/util/gnunet-crypto-tvg.c
+++ b/src/util/gnunet-crypto-tvg.c
@@ -23,6 +23,9 @@
23 * @brief Generate test vectors for cryptographic operations. 23 * @brief Generate test vectors for cryptographic operations.
24 * @author Florian Dold 24 * @author Florian Dold
25 * 25 *
26 * Note that this program shouldn't depend on code in src/json/,
27 * so we're using raw jansson and no GNUnet JSON helpers.
28 *
26 * Test vectors have the following format (TypeScript pseudo code): 29 * Test vectors have the following format (TypeScript pseudo code):
27 * 30 *
28 * interface TestVectorFile { 31 * interface TestVectorFile {
@@ -68,6 +71,18 @@ GNUNET_NETWORK_STRUCT_END
68 71
69 72
70/** 73/**
74 * Should we verify or output test vectors?
75 */
76static int verify_flag = GNUNET_NO;
77
78
79/**
80 * Global exit code.
81 */
82static int global_ret = 0;
83
84
85/**
71 * Create a fresh test vector for a given operation label. 86 * Create a fresh test vector for a given operation label.
72 * 87 *
73 * @param vecs array of vectors to append the new vector to 88 * @param vecs array of vectors to append the new vector to
@@ -131,19 +146,552 @@ uint2j (json_t *vec,
131 json_object_set_new (vec, label, json); 146 json_object_set_new (vec, label, json);
132} 147}
133 148
149
150static int
151expect_data_fixed (json_t *vec,
152 const char *name,
153 void *data,
154 size_t expect_len)
155{
156 const char *s = json_string_value (json_object_get (vec, name));
157
158 if (NULL == s)
159 return GNUNET_NO;
160
161 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s,
162 strlen (s),
163 data,
164 expect_len))
165 return GNUNET_NO;
166 return GNUNET_OK;
167}
168
169static int
170expect_data_dynamic (json_t *vec,
171 const char *name,
172 void **data,
173 size_t *ret_len)
174{
175 const char *s = json_string_value (json_object_get (vec, name));
176 size_t len;
177
178 if (NULL == s)
179 return GNUNET_NO;
180
181 len = (strlen (s) * 5) / 8;
182 if (NULL != ret_len)
183 *ret_len = len;
184 *data = GNUNET_malloc (len);
185
186 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s, strlen (s), *data, len))
187 return GNUNET_NO;
188 return GNUNET_OK;
189}
190
191#define RETONERR(x) do { int v = x; if (GNUNET_OK != v) return v; } while (0)
192
193static int
194checkvec (const char *operation,
195 json_t *vec)
196{
197 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
198 "checking %s\n", operation);
199
200 if (0 == strcmp (operation, "hash"))
201 {
202 void *data;
203 size_t data_len;
204 struct GNUNET_HashCode hash_out;
205 struct GNUNET_HashCode hc;
206
207 if (GNUNET_OK != expect_data_dynamic (vec,
208 "input",
209 &data,
210 &data_len))
211 {
212 GNUNET_break (0);
213 return GNUNET_SYSERR;
214 }
215 if (GNUNET_OK != expect_data_fixed (vec,
216 "output",
217 &hash_out,
218 sizeof (hash_out)))
219 {
220 GNUNET_break (0);
221 return GNUNET_NO;
222 }
223
224 GNUNET_CRYPTO_hash (data, data_len, &hc);
225
226 if (0 != GNUNET_memcmp (&hc, &hash_out))
227 {
228 GNUNET_break (0);
229 return GNUNET_NO;
230 }
231 }
232 else if (0 == strcmp (operation, "ecc_ecdh"))
233 {
234 struct GNUNET_CRYPTO_EcdhePrivateKey priv1;
235 struct GNUNET_CRYPTO_EcdhePublicKey pub1;
236 struct GNUNET_CRYPTO_EcdhePrivateKey priv2;
237 struct GNUNET_HashCode skm;
238 struct GNUNET_HashCode skm_comp;
239
240 if (GNUNET_OK != expect_data_fixed (vec,
241 "priv1",
242 &priv1,
243 sizeof (priv1)))
244 {
245 GNUNET_break (0);
246 return GNUNET_NO;
247 }
248 if (GNUNET_OK != expect_data_fixed (vec,
249 "priv2",
250 &priv2,
251 sizeof (priv2)))
252 {
253 GNUNET_break (0);
254 return GNUNET_NO;
255 }
256 if (GNUNET_OK != expect_data_fixed (vec,
257 "pub1",
258 &pub1,
259 sizeof (pub1)))
260 {
261 GNUNET_break (0);
262 return GNUNET_NO;
263 }
264 if (GNUNET_OK != expect_data_fixed (vec,
265 "skm",
266 &skm,
267 sizeof (skm)))
268 {
269 GNUNET_break (0);
270 return GNUNET_NO;
271 }
272 GNUNET_assert (GNUNET_OK ==
273 GNUNET_CRYPTO_ecc_ecdh (&priv2,
274 &pub1,
275 &skm_comp));
276 if (0 != GNUNET_memcmp (&skm, &skm_comp))
277 {
278 GNUNET_break (0);
279 return GNUNET_NO;
280 }
281 }
282 else if (0 == strcmp (operation, "eddsa_key_derivation"))
283 {
284 struct GNUNET_CRYPTO_EddsaPrivateKey priv;
285 struct GNUNET_CRYPTO_EddsaPublicKey pub;
286 struct GNUNET_CRYPTO_EddsaPublicKey pub_comp;
287
288 if (GNUNET_OK != expect_data_fixed (vec,
289 "priv",
290 &priv,
291 sizeof (priv)))
292 {
293 GNUNET_break (0);
294 return GNUNET_NO;
295 }
296
297 if (GNUNET_OK != expect_data_fixed (vec,
298 "pub",
299 &pub,
300 sizeof (pub)))
301 {
302 GNUNET_break (0);
303 return GNUNET_NO;
304 }
305
306 GNUNET_CRYPTO_eddsa_key_get_public (&priv,
307 &pub_comp);
308 if (0 != GNUNET_memcmp (&pub, &pub_comp))
309 {
310 GNUNET_break (0);
311 return GNUNET_NO;
312 }
313
314 }
315 else if (0 == strcmp (operation, "eddsa_signing"))
316 {
317 struct GNUNET_CRYPTO_EddsaPrivateKey priv;
318 struct GNUNET_CRYPTO_EddsaPublicKey pub;
319 struct TestSignatureDataPS data = { 0 };
320 struct GNUNET_CRYPTO_EddsaSignature sig;
321 struct GNUNET_CRYPTO_EddsaSignature sig_comp;
322
323 if (GNUNET_OK != expect_data_fixed (vec,
324 "priv",
325 &priv,
326 sizeof (priv)))
327 {
328 GNUNET_break (0);
329 return GNUNET_NO;
330 }
331
332 if (GNUNET_OK != expect_data_fixed (vec,
333 "pub",
334 &pub,
335 sizeof (pub)))
336 {
337 GNUNET_break (0);
338 return GNUNET_NO;
339 }
340
341 if (GNUNET_OK != expect_data_fixed (vec,
342 "data",
343 &data,
344 sizeof (data)))
345 {
346 GNUNET_break (0);
347 return GNUNET_NO;
348 }
349
350 if (GNUNET_OK != expect_data_fixed (vec,
351 "sig",
352 &sig,
353 sizeof (sig)))
354 {
355 GNUNET_break (0);
356 return GNUNET_NO;
357 }
358
359 GNUNET_CRYPTO_eddsa_sign (&priv,
360 &data,
361 &sig_comp);
362 GNUNET_assert (GNUNET_OK ==
363 GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST,
364 &data,
365 &sig,
366 &pub));
367 if (0 != GNUNET_memcmp (&sig, &sig_comp))
368 {
369 GNUNET_break (0);
370 return GNUNET_NO;
371 }
372 }
373 else if (0 == strcmp (operation, "kdf"))
374 {
375 size_t out_len;
376 void *out;
377 size_t out_len_comp;
378 void *out_comp;
379 void *ikm;
380 size_t ikm_len;
381 void *salt;
382 size_t salt_len;
383 void *ctx;
384 size_t ctx_len;
385
386 if (GNUNET_OK != expect_data_dynamic (vec,
387 "out",
388 &out,
389 &out_len))
390 {
391 GNUNET_break (0);
392 return GNUNET_SYSERR;
393 }
394
395 out_len_comp = out_len;
396 out_comp = GNUNET_malloc (out_len_comp);
397
398 if (GNUNET_OK != expect_data_dynamic (vec,
399 "ikm",
400 &ikm,
401 &ikm_len))
402 {
403 GNUNET_break (0);
404 return GNUNET_SYSERR;
405 }
406
407 if (GNUNET_OK != expect_data_dynamic (vec,
408 "salt",
409 &salt,
410 &salt_len))
411 {
412 GNUNET_break (0);
413 return GNUNET_SYSERR;
414 }
415
416 if (GNUNET_OK != expect_data_dynamic (vec,
417 "ctx",
418 &ctx,
419 &ctx_len))
420 {
421 GNUNET_break (0);
422 return GNUNET_SYSERR;
423 }
424
425 GNUNET_assert (GNUNET_OK ==
426 GNUNET_CRYPTO_kdf (out_comp,
427 out_len_comp,
428 salt,
429 salt_len,
430 ikm,
431 ikm_len,
432 ctx,
433 ctx_len,
434 NULL));
435
436 if (0 != memcmp (out, out_comp, out_len))
437 {
438 GNUNET_break (0);
439 return GNUNET_NO;
440 }
441
442 }
443 else if (0 == strcmp (operation, "eddsa_ecdh"))
444 {
445 struct GNUNET_CRYPTO_EcdhePrivateKey priv_ecdhe;
446 struct GNUNET_CRYPTO_EcdhePublicKey pub_ecdhe;
447 struct GNUNET_CRYPTO_EddsaPrivateKey priv_eddsa;
448 struct GNUNET_CRYPTO_EddsaPublicKey pub_eddsa;
449 struct GNUNET_HashCode key_material;
450 struct GNUNET_HashCode key_material_comp;
451
452 if (GNUNET_OK != expect_data_fixed (vec,
453 "priv_ecdhe",
454 &priv_ecdhe,
455 sizeof (priv_ecdhe)))
456 {
457 GNUNET_break (0);
458 return GNUNET_NO;
459 }
460
461 if (GNUNET_OK != expect_data_fixed (vec,
462 "pub_ecdhe",
463 &pub_ecdhe,
464 sizeof (pub_ecdhe)))
465 {
466 GNUNET_break (0);
467 return GNUNET_NO;
468 }
469
470 if (GNUNET_OK != expect_data_fixed (vec,
471 "priv_eddsa",
472 &priv_eddsa,
473 sizeof (priv_eddsa)))
474 {
475 GNUNET_break (0);
476 return GNUNET_NO;
477 }
478
479 if (GNUNET_OK != expect_data_fixed (vec,
480 "pub_eddsa",
481 &pub_eddsa,
482 sizeof (pub_eddsa)))
483 {
484 GNUNET_break (0);
485 return GNUNET_NO;
486 }
487
488 if (GNUNET_OK != expect_data_fixed (vec,
489 "key_material",
490 &key_material,
491 sizeof (key_material)))
492 {
493 GNUNET_break (0);
494 return GNUNET_NO;
495 }
496
497 GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdhe, &pub_eddsa, &key_material_comp);
498
499 if (0 != GNUNET_memcmp (&key_material, &key_material_comp))
500 {
501 GNUNET_break (0);
502 return GNUNET_NO;
503 }
504 }
505 else if (0 == strcmp (operation, "rsa_blind_signing"))
506 {
507 struct GNUNET_CRYPTO_RsaPrivateKey *skey;
508 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
509 struct GNUNET_HashCode message_hash;
510 struct GNUNET_CRYPTO_RsaBlindingKeySecret bks;
511 struct GNUNET_CRYPTO_RsaSignature *blinded_sig;
512 struct GNUNET_CRYPTO_RsaSignature *sig;
513 void *blinded_data;
514 size_t blinded_len;
515 void *blinded_data_comp;
516 size_t blinded_len_comp;
517 void *public_enc_data;
518 size_t public_enc_len;
519 void *secret_enc_data;
520 size_t secret_enc_len;
521 void *sig_enc_data;
522 size_t sig_enc_length;
523 void *sig_enc_data_comp;
524 size_t sig_enc_length_comp;
525
526 if (GNUNET_OK != expect_data_fixed (vec,
527 "message_hash",
528 &message_hash,
529 sizeof (message_hash)))
530 {
531 GNUNET_break (0);
532 return GNUNET_SYSERR;
533 }
534
535 if (GNUNET_OK != expect_data_fixed (vec,
536 "blinding_key_secret",
537 &bks,
538 sizeof (bks)))
539 {
540 GNUNET_break (0);
541 return GNUNET_SYSERR;
542 }
543
544 if (GNUNET_OK != expect_data_dynamic (vec,
545 "blinded_message",
546 &blinded_data,
547 &blinded_len))
548 {
549 GNUNET_break (0);
550 return GNUNET_SYSERR;
551 }
552
553 if (GNUNET_OK != expect_data_dynamic (vec,
554 "rsa_public_key",
555 &public_enc_data,
556 &public_enc_len))
557 {
558 GNUNET_break (0);
559 return GNUNET_SYSERR;
560 }
561
562 if (GNUNET_OK != expect_data_dynamic (vec,
563 "rsa_private_key",
564 &secret_enc_data,
565 &secret_enc_len))
566 {
567 GNUNET_break (0);
568 return GNUNET_SYSERR;
569 }
570
571 if (GNUNET_OK != expect_data_dynamic (vec,
572 "sig",
573 &sig_enc_data,
574 &sig_enc_length))
575 {
576 GNUNET_break (0);
577 return GNUNET_SYSERR;
578 }
579
580 pkey = GNUNET_CRYPTO_rsa_public_key_decode (public_enc_data,
581 public_enc_len);
582 GNUNET_assert (NULL != pkey);
583 skey = GNUNET_CRYPTO_rsa_private_key_decode (secret_enc_data,
584 secret_enc_len);
585 GNUNET_assert (NULL != skey);
586
587 GNUNET_assert (GNUNET_YES ==
588 GNUNET_CRYPTO_rsa_blind (&message_hash,
589 &bks,
590 pkey,
591 &blinded_data_comp,
592 &blinded_len_comp));
593 if ( (blinded_len != blinded_len_comp) || (0 != memcmp (blinded_data,
594 blinded_data_comp,
595 blinded_len)) )
596 {
597 GNUNET_break (0);
598 return GNUNET_NO;
599 }
600 blinded_sig = GNUNET_CRYPTO_rsa_sign_blinded (skey, blinded_data,
601 blinded_len);
602 sig = GNUNET_CRYPTO_rsa_unblind (blinded_sig, &bks, pkey);
603 GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_verify (&message_hash, sig,
604 pkey));
605 public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey,
606 &public_enc_data);
607 sig_enc_length_comp = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data_comp);
608
609 if ( (sig_enc_length != sig_enc_length_comp) ||
610 (0 != memcmp (sig_enc_data, sig_enc_data_comp, sig_enc_length) ))
611 {
612 GNUNET_break (0);
613 return GNUNET_NO;
614 }
615 }
616 else
617 {
618 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
619 "unsupported operation '%s'\n", operation);
620 }
621
622 return GNUNET_OK;
623}
624
134/** 625/**
135 * Main function that will be run. 626 * Check test vectors from stdin.
136 * 627 *
137 * @param cls closure 628 * @returns global exit code
138 * @param args remaining command-line arguments
139 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
140 * @param cfg configuration
141 */ 629 */
142static void 630static int
143run (void *cls, 631check_vectors ()
144 char *const *args, 632{
145 const char *cfgfile, 633 json_error_t err;
146 const struct GNUNET_CONFIGURATION_Handle *cfg) 634 json_t *vecfile = json_loadf (stdin, 0, &err);
635 const char *encoding;
636 json_t *vectors;
637
638 if (NULL == vecfile)
639 {
640 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "unable to parse JSON\n");
641 return 1;
642 }
643 encoding = json_string_value (json_object_get (vecfile,
644 "encoding"));
645 if ( (NULL == encoding) || (0 != strcmp (encoding, "base32crockford")) )
646 {
647 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "unsupported or missing encoding\n");
648 json_decref (vecfile);
649 return 1;
650 }
651 vectors = json_object_get (vecfile, "vectors");
652 if (!json_is_array (vectors))
653 {
654 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bad vectors\n");
655 json_decref (vecfile);
656 return 1;
657 }
658 {
659 /* array is a JSON array */
660 size_t index;
661 json_t *value;
662 int ret;
663
664 json_array_foreach (vectors, index, value) {
665 const char *op = json_string_value (json_object_get (value,
666 "operation"));
667
668 if (NULL == op)
669 {
670 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
671 "missing operation\n");
672 ret = GNUNET_SYSERR;
673 break;
674 }
675 ret = checkvec (op, value);
676 if (GNUNET_OK != ret)
677 {
678 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
679 "bad vector %u\n",
680 (unsigned int) index);
681 break;
682 }
683 }
684 return (ret == GNUNET_OK) ? 0 : 1;
685 }
686}
687
688/**
689 * Output test vectors.
690 *
691 * @returns global exit code
692 */
693static int
694output_vectors ()
147{ 695{
148 json_t *vecfile = json_object (); 696 json_t *vecfile = json_object ();
149 json_t *vecs = json_array (); 697 json_t *vecs = json_array ();
@@ -169,7 +717,7 @@ run (void *cls,
169 d2j (vec, "output", &hc, sizeof (struct GNUNET_HashCode)); 717 d2j (vec, "output", &hc, sizeof (struct GNUNET_HashCode));
170 } 718 }
171 { 719 {
172 json_t *vec = vec_for (vecs, "ecdhe_key_derivation"); 720 json_t *vec = vec_for (vecs, "ecc_ecdh");
173 struct GNUNET_CRYPTO_EcdhePrivateKey priv1; 721 struct GNUNET_CRYPTO_EcdhePrivateKey priv1;
174 struct GNUNET_CRYPTO_EcdhePublicKey pub1; 722 struct GNUNET_CRYPTO_EcdhePublicKey pub1;
175 struct GNUNET_CRYPTO_EcdhePrivateKey priv2; 723 struct GNUNET_CRYPTO_EcdhePrivateKey priv2;
@@ -342,6 +890,8 @@ run (void *cls,
342 size_t blinded_len; 890 size_t blinded_len;
343 void *public_enc_data; 891 void *public_enc_data;
344 size_t public_enc_len; 892 size_t public_enc_len;
893 void *secret_enc_data;
894 size_t secret_enc_len;
345 void *blinded_sig_enc_data; 895 void *blinded_sig_enc_data;
346 size_t blinded_sig_enc_length; 896 size_t blinded_sig_enc_length;
347 void *sig_enc_data; 897 void *sig_enc_data;
@@ -369,6 +919,8 @@ run (void *cls,
369 pkey)); 919 pkey));
370 public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, 920 public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey,
371 &public_enc_data); 921 &public_enc_data);
922 secret_enc_len = GNUNET_CRYPTO_rsa_private_key_encode (skey,
923 &secret_enc_data);
372 blinded_sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (blinded_sig, 924 blinded_sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (blinded_sig,
373 & 925 &
374 blinded_sig_enc_data); 926 blinded_sig_enc_data);
@@ -382,6 +934,10 @@ run (void *cls,
382 public_enc_data, 934 public_enc_data,
383 public_enc_len); 935 public_enc_len);
384 d2j (vec, 936 d2j (vec,
937 "rsa_private_key",
938 secret_enc_data,
939 secret_enc_len);
940 d2j (vec,
385 "blinding_key_secret", 941 "blinding_key_secret",
386 &bks, 942 &bks,
387 sizeof (struct GNUNET_CRYPTO_RsaBlindingKeySecret)); 943 sizeof (struct GNUNET_CRYPTO_RsaBlindingKeySecret));
@@ -410,6 +966,28 @@ run (void *cls,
410 json_dumpf (vecfile, stdout, JSON_INDENT (2)); 966 json_dumpf (vecfile, stdout, JSON_INDENT (2));
411 json_decref (vecfile); 967 json_decref (vecfile);
412 printf ("\n"); 968 printf ("\n");
969
970 return 0;
971}
972
973/**
974 * Main function that will be run.
975 *
976 * @param cls closure
977 * @param args remaining command-line arguments
978 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
979 * @param cfg configuration
980 */
981static void
982run (void *cls,
983 char *const *args,
984 const char *cfgfile,
985 const struct GNUNET_CONFIGURATION_Handle *cfg)
986{
987 if (GNUNET_YES == verify_flag)
988 global_ret = check_vectors ();
989 else
990 global_ret = output_vectors ();
413} 991}
414 992
415 993
@@ -425,6 +1003,11 @@ main (int argc,
425 char *const *argv) 1003 char *const *argv)
426{ 1004{
427 const struct GNUNET_GETOPT_CommandLineOption options[] = { 1005 const struct GNUNET_GETOPT_CommandLineOption options[] = {
1006 GNUNET_GETOPT_option_flag ('V',
1007 "verify",
1008 gettext_noop (
1009 "verify a test vector from stdin"),
1010 &verify_flag),
428 GNUNET_GETOPT_OPTION_END 1011 GNUNET_GETOPT_OPTION_END
429 }; 1012 };
430 1013
@@ -439,7 +1022,7 @@ main (int argc,
439 options, 1022 options,
440 &run, NULL)) 1023 &run, NULL))
441 return 1; 1024 return 1;
442 return 0; 1025 return global_ret;
443} 1026}
444 1027
445 1028