From c3f6e8f19fd647c73b414322e287ba23cf8a0c7c Mon Sep 17 00:00:00 2001 From: Andrew Kozlik Date: Thu, 14 Jul 2022 12:20:46 +0200 Subject: [PATCH] feat(crypto): Support is_canonical parameter in zkp_ecdsa_sign_digest(). --- crypto/ecdsa.c | 2 +- crypto/zkp_ecdsa.c | 77 +++++++++++++++++---------- tests/device_tests/eos/test_signtx.py | 20 +++---- 3 files changed, 60 insertions(+), 39 deletions(-) diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c index 33ab45d6f..023194d92 100644 --- a/crypto/ecdsa.c +++ b/crypto/ecdsa.c @@ -1277,7 +1277,7 @@ int ecdsa_sign_digest(const ecdsa_curve *curve, const uint8_t *priv_key, const uint8_t *digest, uint8_t *sig, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t sig[64])) { #ifdef USE_SECP256K1_ZKP_ECDSA - if (curve == &secp256k1 && is_canonical == NULL) { + if (curve == &secp256k1) { return zkp_ecdsa_sign_digest(curve, priv_key, digest, sig, pby, is_canonical); } diff --git a/crypto/zkp_ecdsa.c b/crypto/zkp_ecdsa.c index 7d0733c9e..7ae018773 100644 --- a/crypto/zkp_ecdsa.c +++ b/crypto/zkp_ecdsa.c @@ -160,15 +160,13 @@ int zkp_ecdsa_get_public_key65(const ecdsa_curve *curve, // digest has 32 bytes // signature_bytes has 64 bytes // pby is one byte -// is_canonical has to be NULL // returns 0 on success int zkp_ecdsa_sign_digest( const ecdsa_curve *curve, const uint8_t *private_key_bytes, const uint8_t *digest, uint8_t *signature_bytes, uint8_t *pby, int (*is_canonical)(uint8_t by, uint8_t signature_bytes[64])) { assert(curve == &secp256k1); - assert(is_canonical == NULL); - if (curve != &secp256k1 || is_canonical != NULL) { + if (curve != &secp256k1) { return 1; } @@ -191,41 +189,64 @@ int zkp_ecdsa_sign_digest( result = 1; } } - if (result == 0) { - if (secp256k1_context_writable_randomize(context_writable) != 0) { + + uint16_t retry_count = 0; + int recid = 0; + do { + if (retry_count >= 10000) { result = 1; } - } - secp256k1_ecdsa_recoverable_signature recoverable_signature = {0}; - if (result == 0) { - if (secp256k1_ecdsa_sign_recoverable(context_writable, - &recoverable_signature, digest, - private_key_bytes, NULL, NULL) != 1) { - result = 1; + if (result == 0) { + if (secp256k1_context_writable_randomize(context_writable) != 0) { + result = 1; + } } - } + + secp256k1_ecdsa_recoverable_signature recoverable_signature = {0}; + if (result == 0) { + uint8_t rfc6979_nonce_data[32] = {0}; + void *rfc6979_nonce = NULL; + if (retry_count != 0) { + // If this is a retry attempt, then randomize rfc6979 with the counter. + rfc6979_nonce_data[0] = retry_count & 0xff; + rfc6979_nonce_data[1] = (retry_count >> 8) & 0xff; + rfc6979_nonce = rfc6979_nonce_data; + } + + if (secp256k1_ecdsa_sign_recoverable( + context_writable, &recoverable_signature, digest, + private_key_bytes, secp256k1_nonce_function_rfc6979, + rfc6979_nonce) != 1) { + result = 1; + } + } + + if (result == 0) { + const secp256k1_context *context_read_only = zkp_context_get_read_only(); + if (secp256k1_ecdsa_recoverable_signature_serialize_compact( + context_read_only, signature_bytes, &recid, + &recoverable_signature) != 1) { + result = 1; + } + + if (pby != NULL) { + *pby = (uint8_t)recid; + } + } + memzero(&recoverable_signature, sizeof(recoverable_signature)); + + retry_count += 1; + + // If the signature is not acceptable then retry. + } while (result == 0 && is_canonical != NULL && + !is_canonical(recid, signature_bytes)); if (context_writable) { zkp_context_release_writable(); context_writable = NULL; } - if (result == 0) { - int recid = 0; - const secp256k1_context *context_read_only = zkp_context_get_read_only(); - if (secp256k1_ecdsa_recoverable_signature_serialize_compact( - context_read_only, signature_bytes, &recid, - &recoverable_signature) != 1) { - result = 1; - } - if (pby != NULL) { - *pby = (uint8_t)recid; - } - } - - memzero(&recoverable_signature, sizeof(recoverable_signature)); - return result; } diff --git a/tests/device_tests/eos/test_signtx.py b/tests/device_tests/eos/test_signtx.py index e2b0355d3..b05c4ad68 100644 --- a/tests/device_tests/eos/test_signtx.py +++ b/tests/device_tests/eos/test_signtx.py @@ -64,7 +64,7 @@ def test_eos_signtx_transfer_token(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_JveDuew7oyKjgLmApra3NmKArx3QH6HVmatgkLYeUYWv7aGaoQPFyjBwAdcxuo2Skq9wRgsizos92h9iq9i5JbeHh7zNuo" + == "SIG_K1_JyuCzvv5DUT6bWo2cQ5yjtsbVD3fLbzAbSRhH4wRRfWrivbasrU17VpfK8JqiqiWrw1aqcwYghuqSpwhexRmbHgwx5xib3" ) @@ -97,7 +97,7 @@ def test_eos_signtx_buyram(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_K4gU5S9g7rS6MojaPwWppEBCBbPrJm1pyJtVR9mts1sBq5xyN7nJv3FGnrBR7ByjanboCtK4ogY35sNPFX1F5qoZW7BkF9" + == "SIG_K1_K86DReCevfV5sfwfM1AYzsT98ZVSYrymsnYz47rXyBBpUSWA8QdkFnQhJQdwJJqJT4vcqYUcoWM2ECUAGJLdKXUn55RymR" ) @@ -130,7 +130,7 @@ def test_eos_signtx_buyrambytes(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_K618wK9f27YxHoPG9hoUCsazZXzxumBj3V9MqcTUh9yCocvP1uFZQAmGmZLhsAtuC2TRR4gtqbeQj57FniYd5i4faQCb6t" + == "SIG_K1_Kh4JmjHFQ4HkUP4wMwjoUYuUj3dQYc41P6HXT1YkLD8MSQQjqeCZJXXXAYFeu4xzTyqvowyPpW1N8VsfVw16jt3o1j57pG" ) @@ -159,7 +159,7 @@ def test_eos_signtx_sellram(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_JusrCS7H5DR53qke7edoWvJuLiQS2VQ84CsN5NWmWYVa7wmJVjh3Hcg5hH42zF8KjAmmvHtaJZ3wkortTW9eds1eoiKsrj" + == "SIG_K1_Jxcs3V5FNDf7oR8yGCJekVPGR2Bf7LVk3kpr4RFbAg76Y3tSR8DJnDXQRE3j49VjXJSokXBHmGytdtK7V2ycJ64DPZ6LgR" ) @@ -194,7 +194,7 @@ def test_eos_signtx_delegate(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_Juju8Wjzyn38nuvgS1KT3koKQLHxMMfqVHrp5jMjv4QLU2pUG6EbiJD7D1EHE6xP8DRuwFLVUNR38nTyUKC1Eiz33WocUE" + == "SIG_K1_KdwCsth6XmRG39LxgswkFhJShWdTkTSeg8UDUzJn6qhEES92iGy3P1aJs3HKXNrrUkYU8tJbiXczb2NUJwe4tTnry5CNNH" ) @@ -228,7 +228,7 @@ def test_eos_signtx_undelegate(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_K3XXUzCUkT2HEdrJTz1CdDDKZbLMShmyEjknQozGhy4F21yUetr1nEe2vUgmGebk2nyYe49R5nkA155J5yFBBaLsTcSdBL" + == "SIG_K1_KakW1eEPediabKj8YmJq4SqDvtLsKuV1cbuwWj1iAPrG4jt2F2he7xFzgYjgzRHchh2q8Hb9LJoHPevPUWZ5U2HQZWhLXt" ) @@ -291,7 +291,7 @@ def test_eos_signtx_linkauth(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_Kgs3JdLNqTyGz7uyNiuYLK8sy5qhVQWozrBY7bJWKsjrWAxNyDQUKqHsHmTom5rGY21vYdXmCpi4msU6XeMgWvi4bsBxTx" + == "SIG_K1_KVSS3vmu3quh63t2PADN9Fa7tAgEpC8Cg5y1JVQ8MbYUuh5EX4qdCNzgZpjHMBENjbyUiyTNwRDfvA6gM6vWfivTdQHXUd" ) @@ -409,7 +409,7 @@ def test_eos_signtx_deleteauth(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_KjPTp8jCtgBKQWqsndhrH4pdCGiks76Q1qBt9e8MtexW6FQg3FzfVFKDU4SvyVDyFs3worn6RyW6WYavw76ACNqcqkCYjf" + == "SIG_K1_JyDbrnQhvBKx6ZHvrya57ajWtMzWWjy1F2U9NL7cUPer6NJjNFZ6E98qGoyBkQ67VBWKQVW2fWwuG3AeGz7vZ1KkSqRnZb" ) @@ -606,7 +606,7 @@ def test_eos_signtx_newaccount(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_KhjdS1gKUHR4jKbN3YSdNbPbEqnUVM1Nt6ybdzEAwsUtfbCRJDwpQwPRuEau48CyvhYC5fKo5BiWMPQJbQPrg5ErHThieU" + == "SIG_K1_JxgTbQsTKAfrJG2LnSAmfUG57MrLshJEeF3BZTPo7FrA1KARGA5gGX4kYctSvpxgb669JC3WfuNQzT8Gm4FkKznTE3sYjb" ) @@ -642,5 +642,5 @@ def test_eos_signtx_setcontract(client: Client): assert isinstance(resp, EosSignedTx) assert ( resp.signature - == "SIG_K1_KiG8c8t2SQkSfrEbD9BwJoYT133BPFLx3gu8sAzJadXyFk1EXKYAsgx4tkjt79G6ofuaQzJPAfDqy1FSpgLRbhbeFH9omd" + == "SIG_K1_KkRowmmQgKvUxaCWFLUqwP16hPrh7vULMpsFvz5e7ufaGgArKyAWtueWBpdGmy9Ji761UTSA8KfSEJUnccwzh2orPukbgE" )