From 1a3070b15b944b2c7406d123947a15af3fd7aa64 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 4 Dec 2020 14:52:45 +0100 Subject: gnunet-crypto-tvg: output JSON, fix memleaks This commit also bumps the version of libgnunetutil, due to the spell checking fix to xts in rsa (un)blinding. --- src/util/Makefile.am | 4 +- src/util/gnunet-crypto-tvg.c | 262 ++++++++++++++++++++++++++++++++----------- 2 files changed, 199 insertions(+), 67 deletions(-) diff --git a/src/util/Makefile.am b/src/util/Makefile.am index c5059bbb1..1949dceb0 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -138,7 +138,7 @@ libgnunetutil_la_LIBADD = \ libgnunetutil_la_LDFLAGS = \ $(GN_LIB_LDFLAGS) \ - -version-info 13:2:0 + -version-info 13:2:1 if HAVE_TESTING GNUNET_ECC = gnunet-ecc @@ -195,7 +195,7 @@ gnunet_crypto_tvg_SOURCES = \ gnunet-crypto-tvg.c gnunet_crypto_tvg_LDADD = \ libgnunetutil.la \ - $(GN_LIBINTL) -lgcrypt + $(GN_LIBINTL) -lgcrypt -ljansson gnunet_ecc_SOURCES = \ gnunet-ecc.c diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c index c3fead62e..b9dbba065 100644 --- a/src/util/gnunet-crypto-tvg.c +++ b/src/util/gnunet-crypto-tvg.c @@ -22,11 +22,33 @@ * @file util/gnunet-crypto-tgv.c * @brief Generate test vectors for cryptographic operations. * @author Florian Dold + * + * Test vectors have the following format (TypeScript pseudo code): + * + * interface TestVectorFile { + * encoding: "base32crockford"; + * producer?: string; + * vectors: TestVector[]; + * } + * + * enum Operation { + * Hash("hash"), + * ... + * } + * + * interface TestVector { + * operation: Operation; + * // Inputs for the operation + * [ k: string]: string | number; + * }; + * + * */ #include "platform.h" #include "gnunet_util_lib.h" #include "gnunet_signatures.h" #include "gnunet_testing_lib.h" +#include #include GNUNET_NETWORK_STRUCT_BEGIN @@ -46,20 +68,68 @@ GNUNET_NETWORK_STRUCT_END /** - * Print data base32-crockford with a preceding label. + * Create a fresh test vector for a given operation label. + * + * @param vecs array of vectors to append the new vector to + * @param vecname label for the operation of the vector + * @returns the fresh test vector + */ +static json_t * +vec_for (json_t *vecs, const char *vecname) +{ + json_t *t = json_object (); + + json_object_set_new (t, + "operation", + json_string (vecname)); + json_array_append_new (vecs, t); + return t; +} + + +/** + * Add a base32crockford encoded value + * to a test vector. * - * @param label label to print - * @param data data to print + * @param vec test vector to add to + * @param label label for the value + * @param data data to add * @param size size of data */ static void -display_data (char *label, void *data, size_t size) +d2j (json_t *vec, + const char *label, + const void *data, + size_t size) { - char *enc = GNUNET_STRINGS_data_to_string_alloc (data, size); - printf ("%s %s\n", label, enc); - GNUNET_free (enc); + char *buf; + json_t *json; + + buf = GNUNET_STRINGS_data_to_string_alloc (data, size); + json = json_string (buf); + GNUNET_free (buf); + GNUNET_break (NULL != json); + + json_object_set_new (vec, label, json); } +/** + * Add a number to a test vector. + * + * @param vec test vector to add to + * @param label label for the value + * @param data data to add + * @param size size of data + */ +static void +uint2j (json_t *vec, + const char *label, + unsigned int num) +{ + json_t *json = json_integer (num); + + json_object_set_new (vec, label, json); +} /** * Main function that will be run. @@ -75,17 +145,31 @@ run (void *cls, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg) { + json_t *vecfile = json_object (); + json_t *vecs = json_array (); + + json_object_set_new (vecfile, + "encoding", + json_string ("base32crockford")); + json_object_set_new (vecfile, + "producer", + json_string ("GNUnet " PACKAGE_VERSION " " VCS_VERSION)); + json_object_set_new (vecfile, + "vectors", + vecs); + { + json_t *vec = vec_for (vecs, "hash"); struct GNUNET_HashCode hc; char *str = "Hello, GNUnet"; GNUNET_CRYPTO_hash (str, strlen (str), &hc); - printf ("hash code:\n"); - display_data (" input", str, strlen (str)); - display_data (" output", &hc, sizeof (struct GNUNET_HashCode)); + d2j (vec, "input", str, strlen (str)); + d2j (vec, "output", &hc, sizeof (struct GNUNET_HashCode)); } { + json_t *vec = vec_for (vecs, "ecdhe_key_derivation"); struct GNUNET_CRYPTO_EcdhePrivateKey priv1; struct GNUNET_CRYPTO_EcdhePublicKey pub1; struct GNUNET_CRYPTO_EcdhePrivateKey priv2; @@ -100,22 +184,26 @@ run (void *cls, &pub1, &skm)); - printf ("ecdhe key:\n"); - display_data (" priv1", - &priv1, - sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); - display_data (" pub1", - &pub1, - sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); - display_data (" priv2", - &priv2, - sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); - display_data (" skm", - &skm, - sizeof (struct GNUNET_HashCode)); + d2j (vec, + "priv1", + &priv1, + sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); + d2j (vec, + "pub1", + &pub1, + sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); + d2j (vec, + "priv2", + &priv2, + sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); + d2j (vec, + "skm", + &skm, + sizeof (struct GNUNET_HashCode)); } { + json_t *vec = vec_for (vecs, "eddsa_key_derivation"); struct GNUNET_CRYPTO_EddsaPrivateKey priv; struct GNUNET_CRYPTO_EddsaPublicKey pub; @@ -123,15 +211,17 @@ run (void *cls, GNUNET_CRYPTO_eddsa_key_get_public (&priv, &pub); - printf ("eddsa key:\n"); - display_data (" priv", - &priv, - sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); - display_data (" pub", - &pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + d2j (vec, + "priv", + &priv, + sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); + d2j (vec, + "pub", + &pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); } { + json_t *vec = vec_for (vecs, "eddsa_signing"); struct GNUNET_CRYPTO_EddsaPrivateKey priv; struct GNUNET_CRYPTO_EddsaPublicKey pub; struct GNUNET_CRYPTO_EddsaSignature sig; @@ -151,22 +241,26 @@ run (void *cls, &sig, &pub)); - printf ("eddsa sig:\n"); - display_data (" priv", - &priv, - sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); - display_data (" pub", - &pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); - display_data (" data", - &data, - sizeof (struct TestSignatureDataPS)); - display_data (" sig", - &sig, - sizeof (struct GNUNET_CRYPTO_EddsaSignature)); + d2j (vec, + "priv", + &priv, + sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); + d2j (vec, + "pub", + &pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + d2j (vec, + "data", + &data, + sizeof (struct TestSignatureDataPS)); + d2j (vec, + "sig", + &sig, + sizeof (struct GNUNET_CRYPTO_EddsaSignature)); } { + json_t *vec = vec_for (vecs, "kdf"); size_t out_len = 64; char out[out_len]; char *ikm = "I'm the secret input key material"; @@ -184,14 +278,28 @@ run (void *cls, strlen (ctx), NULL)); - printf ("kdf:\n"); - display_data (" salt", salt, strlen (salt)); - display_data (" ikm", ikm, strlen (ikm)); - display_data (" ctx", ctx, strlen (ctx)); - printf (" out_len %u\n", (unsigned int) out_len); - display_data (" out", out, out_len); + d2j (vec, + "salt", + salt, + strlen (salt)); + d2j (vec, + "ikm", + ikm, + strlen (ikm)); + d2j (vec, + "ctx", + ctx, + strlen (ctx)); + uint2j (vec, + "out_len %u\n", + (unsigned int) out_len); + d2j (vec, + "out", + out, + out_len); } { + json_t *vec = vec_for (vecs, "eddsa_ecdh"); struct GNUNET_CRYPTO_EcdhePrivateKey priv_ecdhe; struct GNUNET_CRYPTO_EcdhePublicKey pub_ecdhe; struct GNUNET_CRYPTO_EddsaPrivateKey priv_eddsa; @@ -204,25 +312,26 @@ run (void *cls, GNUNET_CRYPTO_eddsa_key_get_public (&priv_eddsa, &pub_eddsa); GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdhe, &pub_eddsa, &key_material); - printf ("eddsa_ecdh:\n"); - display_data (" priv_ecdhe", + d2j (vec, "priv_ecdhe", &priv_ecdhe, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey)); - display_data (" pub_ecdhe", + d2j (vec, "pub_ecdhe", &pub_ecdhe, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); - display_data (" priv_eddsa", + d2j (vec, "priv_eddsa", &priv_eddsa, sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)); - display_data (" pub_eddsa", + d2j (vec, "pub_eddsa", &pub_eddsa, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); - display_data (" key_material", + d2j (vec, "key_material", &key_material, sizeof (struct GNUNET_HashCode)); } { + json_t *vec = vec_for (vecs, "rsa_blind_signing"); + struct GNUNET_CRYPTO_RsaPrivateKey *skey; struct GNUNET_CRYPTO_RsaPublicKey *pkey; struct GNUNET_HashCode message_hash; @@ -237,6 +346,7 @@ run (void *cls, size_t blinded_sig_enc_length; void *sig_enc_data; size_t sig_enc_length; + skey = GNUNET_CRYPTO_rsa_private_key_create (2048); pkey = GNUNET_CRYPTO_rsa_private_key_get_public (skey); GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, @@ -263,21 +373,43 @@ run (void *cls, & blinded_sig_enc_data); sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data); - printf ("blind signing:\n"); - display_data (" message_hash", &message_hash, sizeof (struct - GNUNET_HashCode)); - display_data (" rsa_public_key", public_enc_data, public_enc_len); - display_data (" blinding_key_secret", &bks, sizeof (struct - GNUNET_CRYPTO_RsaBlindingKeySecret)); - display_data (" blinded_message", blinded_data, blinded_len); - display_data (" blinded_sig", blinded_sig_enc_data, - blinded_sig_enc_length); - display_data (" sig", sig_enc_data, sig_enc_length); + d2j (vec, + "message_hash", + &message_hash, + sizeof (struct GNUNET_HashCode)); + d2j (vec, + "rsa_public_key", + public_enc_data, + public_enc_len); + d2j (vec, + "blinding_key_secret", + &bks, + sizeof (struct GNUNET_CRYPTO_RsaBlindingKeySecret)); + d2j (vec, + "blinded_message", + blinded_data, + blinded_len); + d2j (vec, + "blinded_sig", + blinded_sig_enc_data, + blinded_sig_enc_length); + d2j (vec, + "sig", + sig_enc_data, + sig_enc_length); GNUNET_CRYPTO_rsa_private_key_free (skey); GNUNET_CRYPTO_rsa_public_key_free (pkey); GNUNET_CRYPTO_rsa_signature_free (sig); GNUNET_CRYPTO_rsa_signature_free (blinded_sig); + GNUNET_free (public_enc_data); + GNUNET_free (blinded_data); + GNUNET_free (sig_enc_data); + GNUNET_free (blinded_sig_enc_data); } + + json_dumpf (vecfile, stdout, JSON_INDENT (2)); + json_decref (vecfile); + printf ("\n"); } -- cgit v1.2.3 From 4c10ff3b40f6409548e38b763fd96866b69c0a38 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 4 Dec 2020 17:22:38 +0100 Subject: gnunet-crypto-tvg: add verification mode --- src/util/gnunet-crypto-tvg.c | 607 ++++++++++++++++++++++++++++++++++++++++++- 1 file 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 @@ * @brief Generate test vectors for cryptographic operations. * @author Florian Dold * + * Note that this program shouldn't depend on code in src/json/, + * so we're using raw jansson and no GNUnet JSON helpers. + * * Test vectors have the following format (TypeScript pseudo code): * * interface TestVectorFile { @@ -67,6 +70,18 @@ struct TestSignatureDataPS GNUNET_NETWORK_STRUCT_END +/** + * Should we verify or output test vectors? + */ +static int verify_flag = GNUNET_NO; + + +/** + * Global exit code. + */ +static int global_ret = 0; + + /** * Create a fresh test vector for a given operation label. * @@ -131,19 +146,552 @@ uint2j (json_t *vec, json_object_set_new (vec, label, json); } + +static int +expect_data_fixed (json_t *vec, + const char *name, + void *data, + size_t expect_len) +{ + const char *s = json_string_value (json_object_get (vec, name)); + + if (NULL == s) + return GNUNET_NO; + + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s, + strlen (s), + data, + expect_len)) + return GNUNET_NO; + return GNUNET_OK; +} + +static int +expect_data_dynamic (json_t *vec, + const char *name, + void **data, + size_t *ret_len) +{ + const char *s = json_string_value (json_object_get (vec, name)); + size_t len; + + if (NULL == s) + return GNUNET_NO; + + len = (strlen (s) * 5) / 8; + if (NULL != ret_len) + *ret_len = len; + *data = GNUNET_malloc (len); + + if (GNUNET_OK != GNUNET_STRINGS_string_to_data (s, strlen (s), *data, len)) + return GNUNET_NO; + return GNUNET_OK; +} + +#define RETONERR(x) do { int v = x; if (GNUNET_OK != v) return v; } while (0) + +static int +checkvec (const char *operation, + json_t *vec) +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "checking %s\n", operation); + + if (0 == strcmp (operation, "hash")) + { + void *data; + size_t data_len; + struct GNUNET_HashCode hash_out; + struct GNUNET_HashCode hc; + + if (GNUNET_OK != expect_data_dynamic (vec, + "input", + &data, + &data_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != expect_data_fixed (vec, + "output", + &hash_out, + sizeof (hash_out))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + GNUNET_CRYPTO_hash (data, data_len, &hc); + + if (0 != GNUNET_memcmp (&hc, &hash_out)) + { + GNUNET_break (0); + return GNUNET_NO; + } + } + else if (0 == strcmp (operation, "ecc_ecdh")) + { + struct GNUNET_CRYPTO_EcdhePrivateKey priv1; + struct GNUNET_CRYPTO_EcdhePublicKey pub1; + struct GNUNET_CRYPTO_EcdhePrivateKey priv2; + struct GNUNET_HashCode skm; + struct GNUNET_HashCode skm_comp; + + if (GNUNET_OK != expect_data_fixed (vec, + "priv1", + &priv1, + sizeof (priv1))) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_OK != expect_data_fixed (vec, + "priv2", + &priv2, + sizeof (priv2))) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_OK != expect_data_fixed (vec, + "pub1", + &pub1, + sizeof (pub1))) + { + GNUNET_break (0); + return GNUNET_NO; + } + if (GNUNET_OK != expect_data_fixed (vec, + "skm", + &skm, + sizeof (skm))) + { + GNUNET_break (0); + return GNUNET_NO; + } + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecc_ecdh (&priv2, + &pub1, + &skm_comp)); + if (0 != GNUNET_memcmp (&skm, &skm_comp)) + { + GNUNET_break (0); + return GNUNET_NO; + } + } + else if (0 == strcmp (operation, "eddsa_key_derivation")) + { + struct GNUNET_CRYPTO_EddsaPrivateKey priv; + struct GNUNET_CRYPTO_EddsaPublicKey pub; + struct GNUNET_CRYPTO_EddsaPublicKey pub_comp; + + if (GNUNET_OK != expect_data_fixed (vec, + "priv", + &priv, + sizeof (priv))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "pub", + &pub, + sizeof (pub))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + GNUNET_CRYPTO_eddsa_key_get_public (&priv, + &pub_comp); + if (0 != GNUNET_memcmp (&pub, &pub_comp)) + { + GNUNET_break (0); + return GNUNET_NO; + } + + } + else if (0 == strcmp (operation, "eddsa_signing")) + { + struct GNUNET_CRYPTO_EddsaPrivateKey priv; + struct GNUNET_CRYPTO_EddsaPublicKey pub; + struct TestSignatureDataPS data = { 0 }; + struct GNUNET_CRYPTO_EddsaSignature sig; + struct GNUNET_CRYPTO_EddsaSignature sig_comp; + + if (GNUNET_OK != expect_data_fixed (vec, + "priv", + &priv, + sizeof (priv))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "pub", + &pub, + sizeof (pub))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "data", + &data, + sizeof (data))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "sig", + &sig, + sizeof (sig))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + GNUNET_CRYPTO_eddsa_sign (&priv, + &data, + &sig_comp); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_verify (GNUNET_SIGNATURE_PURPOSE_TEST, + &data, + &sig, + &pub)); + if (0 != GNUNET_memcmp (&sig, &sig_comp)) + { + GNUNET_break (0); + return GNUNET_NO; + } + } + else if (0 == strcmp (operation, "kdf")) + { + size_t out_len; + void *out; + size_t out_len_comp; + void *out_comp; + void *ikm; + size_t ikm_len; + void *salt; + size_t salt_len; + void *ctx; + size_t ctx_len; + + if (GNUNET_OK != expect_data_dynamic (vec, + "out", + &out, + &out_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + out_len_comp = out_len; + out_comp = GNUNET_malloc (out_len_comp); + + if (GNUNET_OK != expect_data_dynamic (vec, + "ikm", + &ikm, + &ikm_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "salt", + &salt, + &salt_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "ctx", + &ctx, + &ctx_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_kdf (out_comp, + out_len_comp, + salt, + salt_len, + ikm, + ikm_len, + ctx, + ctx_len, + NULL)); + + if (0 != memcmp (out, out_comp, out_len)) + { + GNUNET_break (0); + return GNUNET_NO; + } + + } + else if (0 == strcmp (operation, "eddsa_ecdh")) + { + struct GNUNET_CRYPTO_EcdhePrivateKey priv_ecdhe; + struct GNUNET_CRYPTO_EcdhePublicKey pub_ecdhe; + struct GNUNET_CRYPTO_EddsaPrivateKey priv_eddsa; + struct GNUNET_CRYPTO_EddsaPublicKey pub_eddsa; + struct GNUNET_HashCode key_material; + struct GNUNET_HashCode key_material_comp; + + if (GNUNET_OK != expect_data_fixed (vec, + "priv_ecdhe", + &priv_ecdhe, + sizeof (priv_ecdhe))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "pub_ecdhe", + &pub_ecdhe, + sizeof (pub_ecdhe))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "priv_eddsa", + &priv_eddsa, + sizeof (priv_eddsa))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "pub_eddsa", + &pub_eddsa, + sizeof (pub_eddsa))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "key_material", + &key_material, + sizeof (key_material))) + { + GNUNET_break (0); + return GNUNET_NO; + } + + GNUNET_CRYPTO_ecdh_eddsa (&priv_ecdhe, &pub_eddsa, &key_material_comp); + + if (0 != GNUNET_memcmp (&key_material, &key_material_comp)) + { + GNUNET_break (0); + return GNUNET_NO; + } + } + else if (0 == strcmp (operation, "rsa_blind_signing")) + { + struct GNUNET_CRYPTO_RsaPrivateKey *skey; + struct GNUNET_CRYPTO_RsaPublicKey *pkey; + struct GNUNET_HashCode message_hash; + struct GNUNET_CRYPTO_RsaBlindingKeySecret bks; + struct GNUNET_CRYPTO_RsaSignature *blinded_sig; + struct GNUNET_CRYPTO_RsaSignature *sig; + void *blinded_data; + size_t blinded_len; + void *blinded_data_comp; + size_t blinded_len_comp; + void *public_enc_data; + size_t public_enc_len; + void *secret_enc_data; + size_t secret_enc_len; + void *sig_enc_data; + size_t sig_enc_length; + void *sig_enc_data_comp; + size_t sig_enc_length_comp; + + if (GNUNET_OK != expect_data_fixed (vec, + "message_hash", + &message_hash, + sizeof (message_hash))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_fixed (vec, + "blinding_key_secret", + &bks, + sizeof (bks))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "blinded_message", + &blinded_data, + &blinded_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "rsa_public_key", + &public_enc_data, + &public_enc_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "rsa_private_key", + &secret_enc_data, + &secret_enc_len)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + if (GNUNET_OK != expect_data_dynamic (vec, + "sig", + &sig_enc_data, + &sig_enc_length)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + pkey = GNUNET_CRYPTO_rsa_public_key_decode (public_enc_data, + public_enc_len); + GNUNET_assert (NULL != pkey); + skey = GNUNET_CRYPTO_rsa_private_key_decode (secret_enc_data, + secret_enc_len); + GNUNET_assert (NULL != skey); + + GNUNET_assert (GNUNET_YES == + GNUNET_CRYPTO_rsa_blind (&message_hash, + &bks, + pkey, + &blinded_data_comp, + &blinded_len_comp)); + if ( (blinded_len != blinded_len_comp) || (0 != memcmp (blinded_data, + blinded_data_comp, + blinded_len)) ) + { + GNUNET_break (0); + return GNUNET_NO; + } + blinded_sig = GNUNET_CRYPTO_rsa_sign_blinded (skey, blinded_data, + blinded_len); + sig = GNUNET_CRYPTO_rsa_unblind (blinded_sig, &bks, pkey); + GNUNET_assert (GNUNET_YES == GNUNET_CRYPTO_rsa_verify (&message_hash, sig, + pkey)); + public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, + &public_enc_data); + sig_enc_length_comp = GNUNET_CRYPTO_rsa_signature_encode (sig, &sig_enc_data_comp); + + if ( (sig_enc_length != sig_enc_length_comp) || + (0 != memcmp (sig_enc_data, sig_enc_data_comp, sig_enc_length) )) + { + GNUNET_break (0); + return GNUNET_NO; + } + } + else + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "unsupported operation '%s'\n", operation); + } + + return GNUNET_OK; +} + /** - * Main function that will be run. + * Check test vectors from stdin. * - * @param cls closure - * @param args remaining command-line arguments - * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param cfg configuration + * @returns global exit code */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) +static int +check_vectors () +{ + json_error_t err; + json_t *vecfile = json_loadf (stdin, 0, &err); + const char *encoding; + json_t *vectors; + + if (NULL == vecfile) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "unable to parse JSON\n"); + return 1; + } + encoding = json_string_value (json_object_get (vecfile, + "encoding")); + if ( (NULL == encoding) || (0 != strcmp (encoding, "base32crockford")) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "unsupported or missing encoding\n"); + json_decref (vecfile); + return 1; + } + vectors = json_object_get (vecfile, "vectors"); + if (!json_is_array (vectors)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "bad vectors\n"); + json_decref (vecfile); + return 1; + } + { + /* array is a JSON array */ + size_t index; + json_t *value; + int ret; + + json_array_foreach (vectors, index, value) { + const char *op = json_string_value (json_object_get (value, + "operation")); + + if (NULL == op) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "missing operation\n"); + ret = GNUNET_SYSERR; + break; + } + ret = checkvec (op, value); + if (GNUNET_OK != ret) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "bad vector %u\n", + (unsigned int) index); + break; + } + } + return (ret == GNUNET_OK) ? 0 : 1; + } +} + +/** + * Output test vectors. + * + * @returns global exit code + */ +static int +output_vectors () { json_t *vecfile = json_object (); json_t *vecs = json_array (); @@ -169,7 +717,7 @@ run (void *cls, d2j (vec, "output", &hc, sizeof (struct GNUNET_HashCode)); } { - json_t *vec = vec_for (vecs, "ecdhe_key_derivation"); + json_t *vec = vec_for (vecs, "ecc_ecdh"); struct GNUNET_CRYPTO_EcdhePrivateKey priv1; struct GNUNET_CRYPTO_EcdhePublicKey pub1; struct GNUNET_CRYPTO_EcdhePrivateKey priv2; @@ -342,6 +890,8 @@ run (void *cls, size_t blinded_len; void *public_enc_data; size_t public_enc_len; + void *secret_enc_data; + size_t secret_enc_len; void *blinded_sig_enc_data; size_t blinded_sig_enc_length; void *sig_enc_data; @@ -369,6 +919,8 @@ run (void *cls, pkey)); public_enc_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &public_enc_data); + secret_enc_len = GNUNET_CRYPTO_rsa_private_key_encode (skey, + &secret_enc_data); blinded_sig_enc_length = GNUNET_CRYPTO_rsa_signature_encode (blinded_sig, & blinded_sig_enc_data); @@ -381,6 +933,10 @@ run (void *cls, "rsa_public_key", public_enc_data, public_enc_len); + d2j (vec, + "rsa_private_key", + secret_enc_data, + secret_enc_len); d2j (vec, "blinding_key_secret", &bks, @@ -410,6 +966,28 @@ run (void *cls, json_dumpf (vecfile, stdout, JSON_INDENT (2)); json_decref (vecfile); printf ("\n"); + + return 0; +} + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + if (GNUNET_YES == verify_flag) + global_ret = check_vectors (); + else + global_ret = output_vectors (); } @@ -425,6 +1003,11 @@ main (int argc, char *const *argv) { const struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_flag ('V', + "verify", + gettext_noop ( + "verify a test vector from stdin"), + &verify_flag), GNUNET_GETOPT_OPTION_END }; @@ -439,7 +1022,7 @@ main (int argc, options, &run, NULL)) return 1; - return 0; + return global_ret; } -- cgit v1.2.3 From 2f03e8b0c3599cb720f0ca36f5fae06523967c72 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 4 Dec 2020 17:33:27 +0100 Subject: add test vector unit test --- src/util/Makefile.am | 5 +++- src/util/crypto-test-vectors.json | 56 +++++++++++++++++++++++++++++++++++++++ src/util/test_crypto_vectors.sh | 3 +++ 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/util/crypto-test-vectors.json create mode 100755 src/util/test_crypto_vectors.sh diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 1949dceb0..d2e4b4d1a 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -169,7 +169,7 @@ noinst_PROGRAMS = \ if ENABLE_TEST_RUN AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; -TESTS = $(check_PROGRAMS) +TESTS = $(check_PROGRAMS) $(check_SCRIPTS) endif gnunet_timeout_SOURCES = \ @@ -255,6 +255,9 @@ if HAVE_SSH_KEY # SSH_USING_TESTS = test_socks.nc endif +check_SCRIPTS = \ + test_crypto_vectors.sh + check_PROGRAMS = \ test_bio \ test_client.nc \ diff --git a/src/util/crypto-test-vectors.json b/src/util/crypto-test-vectors.json new file mode 100644 index 000000000..972b62c3e --- /dev/null +++ b/src/util/crypto-test-vectors.json @@ -0,0 +1,56 @@ +{ + "encoding": "base32crockford", + "producer": "GNUnet 0.14.0 git-64ad3b0a1", + "vectors": [ + { + "operation": "hash", + "input": "91JPRV3F5GG4EKJNDSJQ8", + "output": "D0R24RZ1TPASVQ2NY56CT8AJDYZE9ZGDB0GVZ05E9D4YGZQW2RC5YFPQ0Q86EPW836DY7VYQTNFFJT3ZR2K508F4JVS5JNJKYN2MMFR" + }, + { + "operation": "ecc_ecdh", + "priv1": "TFA439C75RT2JK9V6GTRRXH3QR3QC4SVJ1KBQ4MNY3S338GT6T50", + "pub1": "E19WJDA83485BC8EC8RV7FTAK86BESJG1YNYRENEC0JV7XEZ7M80", + "priv2": "2DT3B0TMY6VVP56YZKG5ASRSQAEV0GB4QMT9N6CTPDARNJ905APG", + "skm": "GY63DCHR6BGV2AKDM44V7A4H4DA0WJC7D5C2R7DXTWC9D83H7XM0PEQKKZ1K2HWMWBSBNPDWXDN7PA1R1WJKVQ2RDTNF1PBXCFHM9QR" + }, + { + "operation": "eddsa_key_derivation", + "priv": "8QC2VNF8443S5KPNKMB4XMV58BTHWAKZ7SVW5WG3KRB37567XS90", + "pub": "3M9KK1WSNM1RTY5P72HKFA264V4B7MVHVJ08Y90CV06DYHV8XPP0" + }, + { + "operation": "eddsa_signing", + "priv": "5077XJR9AMH4T97ACKFBVBJD0KFENHPV66B2Y1JBSKXBJKNZJ4E0", + "pub": "6E2F03JJ8AEDANTTZZ4SBZDFEEZSF8A9DVGTS6VFBCVZQYQ46RRG", + "data": "00000300000000000000", + "sig": "XCNJGJ96WPDH60YVMH6C74NGQSGJE3BC1TYMGX6BHY5DMZZZKTB373QTXJ507K5EBSG9YS2EYKHCX3ATRQ6P5MY9MXC4ZB1XSZ2X23G" + }, + { + "operation": "kdf", + "salt": "94KPT83PCNS7J83KC5P78Y8", + "ikm": "94KPT83MD1JJ0WV5CDS6AX10D5Q70XBM41NPAY90DNGQ8SBJD5GPR", + "ctx": "94KPT83141HPYVKMCNW78833D1TPWTSC41GPRWVF41NPWVVQDRG62WS04XMPWSKF4WG6JVH0EHM6A82J8S1G", + "out_len %u\n": 64, + "out": "GTMR4QT05Z9WF5HKVG0WK9RPXGHSMHJNW377G9GJXCA8B0FEKPF4D27RJMSJZYWSQNTBJ5EYVV7ZW18B48Z0JVJJ80RHB706Y96Q358" + }, + { + "operation": "eddsa_ecdh", + "priv_ecdhe": "5FBRFZY942H2PD96NFNYWZKYXCRFY11JWQ59V7G9B4M8EX1KE100", + "pub_ecdhe": "GDX7FC01AZYMG0BY0AMHR6E7KCGX9F6SWES16WZ1QWZ2VSYXKH00", + "priv_eddsa": "3HYHM9DZQ3D61APDQNBCSKJE452YEP6JK01DWR1J3VZAASFEA570", + "pub_eddsa": "87N7PFAHBX97HRE8XYW8KYN64YZDF4FCBR2BZ5SZN3QE3D2BF0R0", + "key_material": "QH0RAXXC9RYDEAXKNTAWM0WXJS25RS67H5T252EGA22RA6JTYRFDAEK8CJY85QSYWGYHQXK5Y1SWSRB3P0NXNXYP237EXMXQ3P2WE00" + }, + { + "operation": "rsa_blind_signing", + "message_hash": "XKQMJ4CNTXBFE1V2WR6JS063J7PZQE4XMB5JH3RS5X0THQ1JQSQ69Y7KDBC9TYRJEZH48MEPY2SF4QHQ4VHXC0YQX5935MQEGP0AX6R", + "rsa_public_key": "040000YRN1NVJ68RS6RJF52PGRCQG19ZKWQPSTJX2G7ZDCKSZFE2VW3HHA81YF5C639JHJF5TX8YTEE2FW2WQCG1PTKNBSPPJEJGA032CN3E8QZ27VWY0K6JFT8ZSYWRH2SKDMXW56A4QKY46JJBWJ6T0ZRVBW6S1HTHXVE2RW8MXRW5T801077MDY13N5F8Z1JZVKBJ06TK3S0YPEDBXK0VEHRHEQJ5X5XYKR4KQTFAZNBMKXY8836VCHBXTK4YNX6AJ1CK29SMJH3Z3QRM16A2TNQGFR0HSMV446BF7FMT2E379ZAT5ST4G3BM2NWZYW545S2SW5MG5S6M88XZZ7SKFD48YVXNZ205GGSEYJPVBMR76WG4ZG30WBCPC1N54XE12RMAG81D8C09WG22PKGGDHYXX68N04002", + "rsa_private_key": "50W3MTV5F4PP8RBMC4520A1H60X70XB2DHMP6BBBCNWGM81050SKMWKKC452081050RKMVHJ6MVKM06RN1NVJ68RS6RJF52PGRCQG19ZKWQPSTJX2G7ZDCKSZFE2VW3HHA81YF5C639JHJF5TX8YTEE2FW2WQCG1PTKNBSPPJEJGA032CN3E8QZ27VWY0K6JFT8ZSYWRH2SKDMXW56A4QKY46JJBWJ6T0ZRVBW6S1HTHXVE2RW8MXRW5T801077MDY13N5F8Z1JZVKBJ06TK3S0YPEDBXK0VEHRHEQJ5X5XYKR4KQTFAZNBMKXY8836VCHBXTK4YNX6AJ1CK29SMJH3Z3QRM16A2TNQGFR0HSMV446BF7FMT2E379ZAT5ST4G3BM2NWZYW545S2SW5MG5S6M88XZZ7SKFD48YVXNZ205GGSEYJPVBMR76WG4ZG30WBCPC1N54XE12RMAG81D8C09WG22PKGGDHYXX68N5452081050RKMS9K780G009918G2081918G20A8A40M32C9TE1S6JXK1EHJJTTV5F45208186CX74WV118G2081864X6WCHN6WX01P58DEWHJ669P4KS8NM635W0AFWZ5XPEMQ8M1ZVB4YFVVGPZ0WCAJ0FKSB1GTCMCKSEQA7PKKGKZ0Q5V40DPMXAYDNMKMM2G0RK58VJ5ZRHYZ7G4SMKYJ7YFQ648PCVD7F19JH5WZH1MMJZ4HPG7Y6TZ1P8CEMFEVGP7257E71EJ0081SX3FG8X9BT7RCQYWTWG1PMRY87NKKAZCR6VME4BNWHF9FFMY14XYKTQXAX4ZFJ20SPV4AZEMS7NF9JMGB4RJED4M8ZRXY509JGPNDW3Y04ED6S11JVSVX6GKGSTFTPHEEH40TX0NF7ZQ191E8PF1D41E9N227FZSYCVV927PZDFRG1C46BQMNPTX61SQ417W0R72V5K0D997BG8P52M20BA302F40GNMW43CFQF9J59918G2081864X6ACST04002A8A40G20A1H79J34D9P78SBPDS45EQZVX2D6R1GZ6FHKHDG4ABYZ6FCPSMMGZ29ZY5NS8B304D0QBD800A5SM3D8S92WKS3KFWFXE8X597TNJBR94BGNCFHY8TV63KQZ0RFMRTPHFA2XNFX2V4KECZNTHGKZNJTWH8051XP6FJJ6700A5KWMH24CK1KF9XVH2ATQJ4F1ZJZQM00A00ESTVKM5N58K5FN5TW34B1H1Q1CWRZXJ9QMBG0QKHXHZMFYZSN9ERV59935716NGSX9GBB3R9BY32TBTAJ7K0N391ATSE5263X5NKVDH7XCF1PF0WRTTJYBAJBQWVGJ8P7RGVWB27Q3S4AJJ55FS2T9K341EHATHJZQQTR0JWP5E4NQHR4GN60QMK2SY0VJM56N0NHJXRGAGJW3S9ABJ7M4TAV6YRJJ2H040G2GC9TE0RK4E9T03CET00DAJDXJ1NF511J69JMDDSVARPSFSS6AJTRMVXD10NVA4Z162ER74WNH0J6H2RTA9C9MZM4TEBP8P7AF0NANBH4XZJCNDZV7BEAMJ6R363GHZKGBR0HH1SATGWNJWGW2961MRFPX7S0RJK7CWYE7EX1XQ2683TENRPDKV29D1F1RNDD6P04MZTKSH5YMEZPKGEDRJZXXM9918G2081864X72C9J74X01ZXF256C681JDWRRG7T4AC9JRHP54YM65X9AT17YGC3G4569ZKBQEZ219Y7JG4V10F4AW7Q1XKGPTW3Y3X0WCTB06HM249Q094VHEYD4BTEQ2DF334W8G3VEB7N1CHCMPZEVVTR0XWQSNV6MBJRF5MBY6Z148YA36YA61EXA28PHE3KSN1M4HVF7B06JD736TSK9GC9CAG8F0MMGM81040M32EKN64S3JEG0YCC3PHPNBZAGQ2WE8HJHM28B049N2MQ94G8VPXNHG43C6ADB44DE1DK8ASMYTSXZWMAYKN1SS2GVFTVH8Q4N3TTJ3BKA61Y93QE17XNRF3S0CSSQTY3SVVAFHDA9APFFSMRYD67N4DXQ1X42NA270VF6H0MCRQ87JKVBQAB0CH2WH7RHYMCQ4KN50M2NEFE1YA6F2N2DG7Z9JA8A40G20A8A40G2J2H054500", + "blinding_key_secret": "3SWF49XZPHQMENTSBZQR7Z0B8ZSZ2JRARE79Q4VXZMQ7W6QABXMG", + "blinded_message": "3KHKZJZ30ABB4E56MA2V0EQWGCWH0QQG9P2ZHYHR186C5HZXJMM4N9WXAQTKS94QSV9Y17GGNXN5MB1PZZFG7Q0FY88QPKKRG4MYCPSMTZK5W59R0MJVNJ4P4AQM96TDG5W7RV8GSNR1QQZ1GNHW3CX6D6ZRTMXB2NKB5SSYTDJS79F5ZFBRZ4HVED9JBBPWSR79KVV5QQ4APBGHBCKGMF9NJJS53A1BVYHDEVYAGFYF2SNEP827ZP50FKJ5GKGV8NQ15ESEZ69AT7GJG0T3TZVENY2YN9CVR98W3BKEZ53J7VTANARG8SJS8AMJQ7S23P5HRJ7XE9KTNRNXKH49MXV9JHHYE5535N7AGWEKR47SBCGNF44Z7XJ9RV5BQV12ZRJKN4HBZQHDNCMH3QKX9Z6G64", + "blinded_sig": "ND1V807BK0G73SDXN582BP3Q21MWF4A76EGWD0KA3XGJAWPSVHNHKA44931ZRB9M76SYAFD8ZPTG3A7FH5G2CWGX76VXTCDX5XNRW7EEBNMPDAQ0ZEKF6AHP872SKCGRH89SK4NGC57M8BRA3ZRPDDT9XCBG3XY02VQH4Z0F39DPBS48K0EBMK7B9S3X6QDNR5ND5MV0G7G7T3VPKZRW94MQBKPY1T6K53MQGG4PV81D9YEWNRM3WE04NNQREYDA5ETVDWQ5ZCYV9HF4ZCMWVVGWDBDH732JA3NKZ2B8QK0E6XS0Y4GGGQJS6HFQ4PATGK3TS5GHJEPDF3A6XAFNJQV99CSJW7V1NC504NTQ5NJ8KAVC1758MBBV3SS2BND4YHF0Y4NWJNVH3STV166YWFKR8W", + "sig": "EC5MVSPGQMM96N2VT4R2G5104E61V8RY4PR6AK9F614TVVEN7D152T0DP97CDTRDDSQGBV4GZWXQPM90SW30R2RAKKHNDCXHQFAMRSW1XCBEKVKBGC6FP0AQY9S37NVR01VJ2WVX8PN29H2ZFFQBQ9JK96GTJZ3B7DD583S8Y93GH5KWEM41CZJ73QCRT1A2AGVXX5ACFR0T448MC81QB4EGCKP5Z96VCX6RPDD5S9A4295M0E9PPQJCN5G5JKWKG17HWEDF4A26ZMD8YW27EQBZ69GSEZX4PWEV7AXFGG5X0RPKCQEPCX7XDY6NXJ1E2FZBX259RDRCFNDAZS80T0DHD9NVE73QDDESZYEZTM1TM669GHPN8AF4QV8DNW7SFZZKJ67FWR8CZC0PWTEN4ZPTRM" + } + ] +} diff --git a/src/util/test_crypto_vectors.sh b/src/util/test_crypto_vectors.sh new file mode 100755 index 000000000..40700a324 --- /dev/null +++ b/src/util/test_crypto_vectors.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +cat ./crypto-test-vectors.json | ./gnunet-crypto-tvg --verify -- cgit v1.2.3 From 1346641a163ed02540b6931fd4ad31ba6af4d64d Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 4 Dec 2020 17:36:35 +0100 Subject: gnunet-crypto-tvg: fix bogus label --- src/util/gnunet-crypto-tvg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c index 5915b4b44..1e9cc3174 100644 --- a/src/util/gnunet-crypto-tvg.c +++ b/src/util/gnunet-crypto-tvg.c @@ -839,7 +839,7 @@ output_vectors () ctx, strlen (ctx)); uint2j (vec, - "out_len %u\n", + "out_len", (unsigned int) out_len); d2j (vec, "out", -- cgit v1.2.3 From 2c5857012467c1420270545472be72d8fa9a5563 Mon Sep 17 00:00:00 2001 From: Florian Dold Date: Fri, 4 Dec 2020 17:51:15 +0100 Subject: -remove unused macro / add comment --- src/util/gnunet-crypto-tvg.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/util/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c index 1e9cc3174..8949f427c 100644 --- a/src/util/gnunet-crypto-tvg.c +++ b/src/util/gnunet-crypto-tvg.c @@ -188,8 +188,15 @@ expect_data_dynamic (json_t *vec, return GNUNET_OK; } -#define RETONERR(x) do { int v = x; if (GNUNET_OK != v) return v; } while (0) +/** + * Check a single vector. + * + * @param operation operator of the vector + * @param vec the vector, a JSON object. + * + * @returns GNUNET_OK if the vector is okay + */ static int checkvec (const char *operation, json_t *vec) -- cgit v1.2.3