From 79153135b7669de6dba7f8a92c0d43f5edaf2ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Vejpustek?= Date: Wed, 16 Jun 2021 14:34:34 +0200 Subject: [PATCH] test(crypto): add ecdsa tests for secp256k1_zkp --- crypto/Makefile | 4 ++-- crypto/tests/test_check.c | 15 +++++++++++++++ crypto/tests/test_curves.py | 34 ++++++++++++++++++++++++++++++--- crypto/tests/test_wycheproof.py | 24 +++++++++++++++++++++++ crypto/zkp_context.c | 2 ++ 5 files changed, 74 insertions(+), 5 deletions(-) diff --git a/crypto/Makefile b/crypto/Makefile index b0573776b..27b61619a 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -125,8 +125,8 @@ tests/test_speed: tests/test_speed.o $(OBJS) tests/test_openssl: tests/test_openssl.o $(OBJS) $(CC) tests/test_openssl.o $(OBJS) $(TESTSSLLIBS) -o tests/test_openssl -tests/libtrezor-crypto.so: $(SRCS) - $(CC) $(CFLAGS) -DAES_128 -DAES_192 -fPIC -shared $(SRCS) -o tests/libtrezor-crypto.so +tests/libtrezor-crypto.so: $(SRCS) secp256k1-zkp.o + $(CC) $(CFLAGS) -DAES_128 -DAES_192 -fPIC -shared $(SRCS) secp256k1-zkp.o -o tests/libtrezor-crypto.so tools: tools/xpubaddrgen tools/mktable tools/bip39bruteforce diff --git a/crypto/tests/test_check.c b/crypto/tests/test_check.c index 5568253b6..b0acc765d 100644 --- a/crypto/tests/test_check.c +++ b/crypto/tests/test_check.c @@ -71,6 +71,8 @@ #include "shamir.h" #include "slip39.h" #include "slip39_wordlist.h" +#include "zkp_context.h" +#include "zkp_ecdsa.h" #if VALGRIND /* @@ -3621,6 +3623,11 @@ START_TEST(test_ecdsa_recover_pub_from_sig) { } END_TEST +START_TEST(test_zkp_ecdsa_recover_pub_from_sig) { + test_ecdsa_recover_pub_from_sig_helper(zkp_ecdsa_recover_pub_from_sig); +} +END_TEST + static void test_ecdsa_verify_digest_helper(int (*ecdsa_verify_digest_fn)( const ecdsa_curve *, const uint8_t *, const uint8_t *, const uint8_t *)) { int res; @@ -3656,6 +3663,11 @@ START_TEST(test_ecdsa_verify_digest) { } END_TEST +START_TEST(test_zkp_ecdsa_verify_digest) { + test_ecdsa_verify_digest_helper(zkp_ecdsa_verify_digest); +} +END_TEST + #define test_deterministic(KEY, MSG, K) \ do { \ sha256_Raw((uint8_t *)MSG, strlen(MSG), buf); \ @@ -9178,6 +9190,8 @@ Suite *test_suite(void) { tc = tcase_create("ecdsa"); tcase_add_test(tc, test_ecdsa_recover_pub_from_sig); tcase_add_test(tc, test_ecdsa_verify_digest); + tcase_add_test(tc, test_zkp_ecdsa_recover_pub_from_sig); + tcase_add_test(tc, test_zkp_ecdsa_verify_digest); suite_add_tcase(s, tc); tc = tcase_create("rfc6979"); @@ -9436,6 +9450,7 @@ Suite *test_suite(void) { // run suite int main(void) { + zkp_context_init(); int number_failed; Suite *s = test_suite(); SRunner *sr = srunner_create(s); diff --git a/crypto/tests/test_curves.py b/crypto/tests/test_curves.py index 6897cea87..de8bdc009 100755 --- a/crypto/tests/test_curves.py +++ b/crypto/tests/test_curves.py @@ -79,6 +79,8 @@ random_iters = int(os.environ.get("ITERS", 1)) DIR = os.path.abspath(os.path.dirname(__file__)) lib = c.cdll.LoadLibrary(os.path.join(DIR, "libtrezor-crypto.so")) +if not lib.zkp_context_is_initialized(): + lib.zkp_context_init() BIGNUM = c.c_uint32 * 9 @@ -139,9 +141,7 @@ def r(request): return Random(seed + int(os.environ.get("SEED", 0))) -@pytest.fixture(params=list(sorted(curves))) -def curve(request): - name = request.param +def get_curve_obj(name): curve_ptr = lib.get_curve_by_name(bytes(name, "ascii")).contents.params assert curve_ptr, "curve {} not found".format(name) curve_obj = curves[name] @@ -150,6 +150,11 @@ def curve(request): return curve_obj +@pytest.fixture(params=list(sorted(curves))) +def curve(request): + return get_curve_obj(request.param) + + @pytest.fixture(params=points) def point(request): name = request.param.curve @@ -304,6 +309,29 @@ def test_sign(curve, r): assert vk.verify_digest(sig, digest, sigdecode) +def test_sign_zkp(r): + curve = get_curve_obj("secp256k1") + + priv = r.randbytes(32) + digest = r.randbytes(32) + sig = r.randbytes(64) + + lib.zkp_ecdsa_sign_digest( + curve.ptr, priv, digest, sig, c.c_void_p(0), c.c_void_p(0) + ) + + exp = bytes2num(priv) + sk = ecdsa.SigningKey.from_secret_exponent(exp, curve, hashfunc=hashlib.sha256) + vk = sk.get_verifying_key() + + sig_ref = sk.sign_digest_deterministic( + digest, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_string_canonize + ) + assert binascii.hexlify(sig) == binascii.hexlify(sig_ref) + + assert vk.verify_digest(sig, digest, sigdecode) + + def test_validate_pubkey(curve, r): p = r.randpoint(curve) assert lib.ecdsa_validate_pubkey(curve.ptr, to_POINT(p)) diff --git a/crypto/tests/test_wycheproof.py b/crypto/tests/test_wycheproof.py index c449b29c8..8791ac04c 100755 --- a/crypto/tests/test_wycheproof.py +++ b/crypto/tests/test_wycheproof.py @@ -599,6 +599,8 @@ def generate_eddsa(filename): dir = os.path.abspath(os.path.dirname(__file__)) lib = ctypes.cdll.LoadLibrary(os.path.join(dir, "libtrezor-crypto.so")) +if not lib.zkp_context_is_initialized(): + lib.zkp_context_init() testvectors_directory = os.path.join(dir, "wycheproof/testvectors") context_structure_length = 1024 @@ -650,6 +652,28 @@ def test_ecdsa(curve_name, public_key, hasher, message, signature, result): assert result == computed_result +@pytest.mark.parametrize( + "curve_name, public_key, hasher, message, signature, result", + filter(lambda v: v[0] == "secp256k1", ecdsa_vectors), +) +def test_ecdsa_zkp(curve_name, public_key, hasher, message, signature, result): + curve = get_curve_by_name(curve_name) + if curve is None: + raise NotSupported("Curve not supported: {}".format(curve_name)) + + public_key = unhexlify(public_key) + signature = unhexlify(signature) + message = unhexlify(message) + + computed_result = ( + lib.zkp_ecdsa_verify( + curve, hasher, public_key, signature, message, len(message) + ) + == 0 + ) + assert result == computed_result + + @pytest.mark.parametrize( "public_key, private_key, shared, result", curve25519_dh_vectors ) diff --git a/crypto/zkp_context.c b/crypto/zkp_context.c index 008d9f68f..0208817ae 100644 --- a/crypto/zkp_context.c +++ b/crypto/zkp_context.c @@ -43,6 +43,8 @@ void secp256k1_context_writable_randomize(secp256k1_context *context_writable) { assert(returned == 1); } +bool zkp_context_is_initialized(void) { return initialized; } + void zkp_context_init() { assert(initialized == false);