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

k256: Do not normalize the argument in FieldElementImpl::is_odd() #530

Merged
merged 3 commits into from
Mar 14, 2022

Conversation

fjarri
Copy link
Contributor

@fjarri fjarri commented Mar 14, 2022

Fixes #529

FieldElementImpl::is_odd() (which was only compiled in debug version) normalized its argument, wherein in release mode it was bypassed in favor of the specific 32- or 64-bit implementation. This caused an inconsistency between the release and debug versions, and lead to uncaught issues where an un-normalized field element could be checked for is_odd() (the exact situation FieldElementImpl was designed to detect).

In this PR:

  • FieldElementImpl::is_odd() now checks for normalization instead of performing it
  • AffinePoint::decompress() normalizes y coordinate (beta in the code) before checking if it is odd
  • Scalar::try_sign_prehashed normalizes R.y before checking if it is odd

I added a regression test for the first change; the other two are already tested by arithmetic::affine::tests::compressed_round_trip, arithmetic::affine::tests::compressed_to_uncompressed and ecdsa::recoverable::tests::public_key_recovery - those tests only passed because they were always run in debug mode where force normalization was on.

@fjarri fjarri requested a review from tarcieri March 14, 2022 19:14
@tarcieri
Copy link
Member

@fjarri that looks like a legitimate failure to me.

One thing that's special about the platform it's failing on is that it's 32-bit. Perhaps it's an issue with the 32-bit field backend?

@@ -542,6 +542,29 @@ mod tests {
assert_eq!(four.sqrt().unwrap().normalize(), two.normalize());
}

#[test]
#[should_panic(expected = "assertion failed: self.normalized")]
Copy link
Member

Choose a reason for hiding this comment

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

Another potential issue is that test will only succeed (i.e. is_odd will only panic) when debug_assertions are enabled.

Perhaps the test, or at least the should_panic, should be gated on that?

Suggested change
#[should_panic(expected = "assertion failed: self.normalized")]
#[cfg_attr(debug_assertions, should_panic(expected = "assertion failed: self.normalized"))]

Copy link
Member

@tarcieri tarcieri left a comment

Choose a reason for hiding this comment

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

CI passed. Going to go ahead and merge this.

Can cut a bugfix release after that.

@tarcieri
Copy link
Member

FYI: I opened #531 with a proposal to encapsulate concerns around normalizing field elements using type safety

@tarcieri tarcieri merged commit 855da3c into RustCrypto:master Mar 14, 2022
@fjarri fjarri deleted the is-odd-fix branch March 14, 2022 20:08
tarcieri added a commit that referenced this pull request Mar 14, 2022
This release backports #530.

Since `master` is already v0.11 prereleases, this commit just contains
the release notes.

The released code can be found via the `k256/v0.10.3` tag:

https://github.com/RustCrypto/elliptic-curves/tree/k256/v0.10.3
tarcieri added a commit that referenced this pull request Mar 14, 2022
This release backports #530.

Since `master` is already v0.11 prereleases, this commit just contains
the release notes.

The released code can be found via the `k256/v0.10.3` tag:

https://github.com/RustCrypto/elliptic-curves/tree/k256/v0.10.3
dfinity-bot pushed a commit to dfinity/ic that referenced this pull request Mar 15, 2022
CRP-1445: Upgrade k256 crate to v0.10.3 to fix point serialization bug

Upgrades the `k256` crate used in `ic-crypto-internal-threshold-sig-ecdsa` to v0.10.3. This version contains a [fix](RustCrypto/elliptic-curves#530) for the point (de)serialization bug that we reported in [k256#529](RustCrypto/elliptic-curves#529). This bug caused our tests to fail sporadically because elliptic curve points were different before and after a (de)serialization round trip. 

See merge request dfinity-lab/public/ic!3752
tarcieri pushed a commit that referenced this pull request Mar 15, 2022
…530)

- `FieldElementImpl::is_odd()` now checks for normalization instead of performing it
- `AffinePoint::decompress()` normalizes `y` coordinate (`beta` in the code) before checking if it is odd
- `Scalar::try_sign_prehashed` normalizes `R.y` before checking if it is odd
@tarcieri tarcieri mentioned this pull request Mar 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

k256 Point deserialization+serialization round trips incorrectly
3 participants