Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify secp256k1_zkp usage #2385

Merged
merged 2 commits into from
Jun 21, 2023
Merged

Unify secp256k1_zkp usage #2385

merged 2 commits into from
Jun 21, 2023

Conversation

andrewkozlik
Copy link
Contributor

@andrewkozlik andrewkozlik commented Jul 14, 2022

Resolves #1864.

  • Moves the dispatching of zkp_ecdsa_*() vs. ecdsa_*() functions to ecdsa.c to simplify usage (no more #ifdefs for this in core and legacy code).
    • As a side-result the above change automatically causes crypto/bip32.c to use the secp256k1_zkp functions for public key derivation and signing without any code changes in bip32.c.
    • I renamed the trezor-crypto native implementations of the relevant ecdsa_* functions to tc_ecdsa_* so that they can be tested independently in the crypto tests.
    • It seems that the usage of secp256k1_zkp in bip32.c causes a different amount of data to be taken from the PRNG, which in turn causes the PIN matrix layouts to change, hence the changes to UI tests.
  • Implements Ethereum and EOS canonical ECDSA signing using the secp256k1_zkp library.
    • Some of the EOS signatures (10/16) had to be changed, because the signing retry works differently than in the trezor-crypto native implementation.
    • Signing of EOS operations will need to be tested extensively by QA!

@andrewkozlik andrewkozlik added crypto Stand-alone cryptography library used by both Trezor Core and the Trezor Legacy firmware code Code improvements labels Jul 14, 2022
@prusnak prusnak added the flash reduction Decrease required size of flash label Aug 30, 2022
crypto/ecdsa_internal.h Outdated Show resolved Hide resolved
crypto/zkp_ecdsa.c Outdated Show resolved Hide resolved
int recid) {
#ifdef USE_SECP256K1_ZKP_ECDSA
if (curve == &secp256k1) {
return zkp_ecdsa_recover_pub_from_sig(curve, pub_key, sig, digest, recid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about moving these wrappers into a separate file?

I'm thinking about something like

  • renaming ecdsa.c to native_ecdsa.c,
  • renaming ecdsa_internal.h to native_ecdsa.h and
  • moving the wrappers back to ecdsa.c.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So let me get this straight. Based on the described scheme all the other ecdsa functions such as scalar_multiply() would be implemented in native_ecdsa.c, but their declaration would remain in ecdsa.h while there exists a file called native_ecdsa.h? That seems confusing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the described scheme all the other ecdsa functions such as scalar_multiply() would be implemented in native_ecdsa.c, but their declaration would remain in ecdsa.h while there exists a file called native_ecdsa.h?

A would move the declaration of scalar_multiply() to native_ecdsa.h.

The thing I don't like about the architecture is ecdsa.c contains both the ecdsa wrappers and the native implementation of ecdsa. These functions should be in separate files, in my opinion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[I] would move the declaration of scalar_multiply() to native_ecdsa.h.

Then any code that uses functions that were originally declared in ecdsa.h but do not have a counterpart in the secp256k1 library, i.e. are not wrapped, would have to include native_ecdsa.h instead of ecdsa.h (or both). Again seems confusing and technically breaks the API although only a little.

The thing I don't like about the architecture is ecdsa.c contains both the ecdsa wrappers and the native implementation of ecdsa.

I don't see a problem with that other than unit testing, which is an internal matter.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then any code that uses functions that were originally declared in ecdsa.h but do not have a counterpart in the secp256k1 library, i.e. are not wrapped, would have to include native_ecdsa.h instead of ecdsa.h (or both).

Exactly.

Again seems confusing and technically breaks the API although only a little.

What is confusing about it? Which API does it breaks and how?

I think it's the most natural approach. I see it as ecdsa.c being an interface and zkp_ecdsa.c and native_ecdsa.c being two implementations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is confusing about it? Which API does it breaks and how?

It moves certain functions to different header files, such as scalar_multiply() and others.

I think it's the most natural approach. I see it as ecdsa.c being an interface and zkp_ecdsa.c and native_ecdsa.c being two implementations.

If it's meant to be an "interface", then we would also have to add dummy wrappers to ecdsa.c for the functions that are in native_ecdsa.c only. The caller shouldn't have to deal with the question of whether the implementation is native or non-native.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It moves certain functions to different header files, such as scalar_multiply() and others.

What is wrong about it? What is confusing about it?

If it's meant to be an "interface", then we would also have to add dummy wrappers to ecdsa.c for the functions that are in native_ecdsa.c only. The caller shouldn't have to deal with the question of whether the implementation is native or non-native.

This may surprise you but I'm all for it. Nevertheless, I don't think it's necessary because I see nothing wrong with using an "implementation" directly instead of an "interface".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is wrong about it? What is confusing about it?

As I stated, the caller shouldn't have to deal with the question of whether the implementation is native or non-native. The whole point of this PR is to simplify the usage of the ecdsa calls.

I am not a fan of creating dummy code where it serves no purpose. So I don't like that option either. This is purely a matter of style. It makes no difference in terms of functionality, usability, maintainability or in any other respect. Feel free to create a separate issue.

crypto/zkp_ecdsa.c Outdated Show resolved Hide resolved
@Hannsek
Copy link
Contributor

Hannsek commented Apr 14, 2023

@andrewkozlik What is the state of this pr?

@andrewkozlik
Copy link
Contributor Author

@andrewkozlik What is the state of this pr?

Awaiting review from @onvej-sl. Probably needs manual rebase afterwards.

@onvej-sl
Copy link
Contributor

I announce in advance I'm not going to approve this pull request. The pull request is ok in terms of functionality and security (this is the last comment that has to be resolved in this sense) but I don't agree with one of the architectural decisions made. To be specific, I don't like that ecdsa.c contains both

  • the native implementation of the elliptic curve cryptography and
  • the wrappers that call either the native implementation or the zkp-secp256k1 implementation.

See this thread. In my opinion, ecdsa.c already contains functions that should be split between multiple files and this pull request makes it worse.

I and Andrew have a different perspective on this. Let someone else review this part of the pull request.

@andrewkozlik
Copy link
Contributor Author

@matejcik please review this discussion. @onvej-sl already reviewed this PR from the functional and security perspectives, but disagrees about the code style.

@matejcik
Copy link
Contributor

I did a very brief review of the ecdsa.h interface, and ISTM as of now it can't be considered a good interface. I would basically agree that there's too many functions already, but splitting off the wrappers and tc_ prefixed internal implementations doesn't help anything besides raw line count which is not interesting.

A larger refactor, with possible header API breakage, would be nice -- but this PR is not it and doesn't need to be it.

(that said, my view into trezor-crypto architecture is limited and i might be missing something)

As such I'm approving the PR as it is now. Please resolve the conflicts and let's get this merged.

@andrewkozlik andrewkozlik dismissed onvej-sl’s stale review June 21, 2023 06:36

The last unresolved requested change is unrelated to this PR.

@andrewkozlik andrewkozlik merged commit c3f6e8f into master Jun 21, 2023
@andrewkozlik andrewkozlik deleted the andrewkozlik/1864 branch June 21, 2023 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code Code improvements crypto Stand-alone cryptography library used by both Trezor Core and the Trezor Legacy firmware flash reduction Decrease required size of flash
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

Deeper integration of secp256k1_zkp
5 participants