summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-12-05 10:46:47 +0100
committerChristian Grothoff <christian@grothoff.org>2020-12-05 10:46:47 +0100
commit813d74fafbd7d6556edeb94d8654838682624c27 (patch)
tree85a26aec056311613f0c04fdf15bb5d41d7aa10e
parent4dce2caf4a001bdc03d117474b45fe8712e33a96 (diff)
parent2c5857012467c1420270545472be72d8fa9a5563 (diff)
Merge branch 'master' of git+ssh://gnunet.org/gnunet
-rw-r--r--src/util/Makefile.am9
-rw-r--r--src/util/crypto-test-vectors.json56
-rw-r--r--src/util/gnunet-crypto-tvg.c874
-rwxr-xr-xsrc/util/test_crypto_vectors.sh3
4 files changed, 863 insertions, 79 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index c5059bbb1..d2e4b4d1a 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
@@ -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 = \
@@ -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
@@ -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/gnunet-crypto-tvg.c b/src/util/gnunet-crypto-tvg.c
index c3fead62e..8949f427c 100644
--- a/src/util/gnunet-crypto-tvg.c
+++ b/src/util/gnunet-crypto-tvg.c
@@ -22,11 +22,36 @@
* @file util/gnunet-crypto-tgv.c
* @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 {
+ * 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 <jansson.h>
#include <gcrypt.h>
GNUNET_NETWORK_STRUCT_BEGIN
@@ -46,46 +71,660 @@ GNUNET_NETWORK_STRUCT_END
/**
- * Print data base32-crockford with a preceding label.
+ * 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.
+ *
+ * @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);
+}
/**
- * Main function that will be run.
+ * Add a number to a test vector.
*
- * @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
+ * @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
-run (void *cls,
- char *const *args,
- const char *cfgfile,
- const struct GNUNET_CONFIGURATION_Handle *cfg)
+uint2j (json_t *vec,
+ const char *label,
+ unsigned int num)
+{
+ json_t *json = json_integer (num);
+
+ 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;
+}
+
+
+/**
+ * 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)
+{
+ 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;
+}
+
+/**
+ * Check test vectors from stdin.
+ *
+ * @returns global exit code
+ */
+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 ();
+
+ 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, "ecc_ecdh");
struct GNUNET_CRYPTO_EcdhePrivateKey priv1;
struct GNUNET_CRYPTO_EcdhePublicKey pub1;
struct GNUNET_CRYPTO_EcdhePrivateKey priv2;
@@ -100,22 +739,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 +766,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 +796,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 +833,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",
+ (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 +867,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;
@@ -233,10 +897,13 @@ 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;
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,
@@ -259,25 +926,75 @@ 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);
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,
+ "rsa_private_key",
+ secret_enc_data,
+ secret_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");
+
+ 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 ();
}
@@ -293,6 +1010,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
};
@@ -307,7 +1029,7 @@ main (int argc,
options,
&run, NULL))
return 1;
- return 0;
+ return global_ret;
}
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