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

Fix ECDSA failing when the hash is all-bits-zero #4199

Merged
merged 7 commits into from
Apr 19, 2021

Conversation

TRodziewicz
Copy link
Contributor

@TRodziewicz TRodziewicz commented Mar 4, 2021

Description

Fix function mbedtls_ecp_mul_shortcuts() to skip multiplication when m
is 0 and simply assignt 0 to R. Additionally fix ecjpake_zkp_read() to
return MBEDTLS_ERR_BAD_INPUT_DATA when r length is 0 and ecjpake
test to expect that.

Fix #1792

Status

READY

Requires Backporting

Yes

Migrations

NO

Todos

  • Tests
  • Documentation
  • Backported

Steps to test or reproduce

Please check: #1792

Fix function mbedtls_ecp_mul_shortcuts() to skip multiplication when m
is 0 and simply assignt 0 to R. Additionally fix ecjpake_zkp_read() to
return MBEDTLS_ERR_ECP_INVALID_KEY when the above condintion is met.

Fix Mbed-TLS#1792

Signed-off-by: TRodziewicz <[email protected]>
Copy link
Contributor

@stevew817 stevew817 left a comment

Choose a reason for hiding this comment

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

If the ZKP is indeed strictly non-zero, then this change would be correct.

However, I read through RFC's 8235 and 8236, and couldn't find anywhere that a ZKP is guaranteed to be non-zero. Sure, it's a corner case, but consider this (according to the ecjpake draft, paragraph 7.4.2):

  • v is a random integer [1,n-1] (i.e. ephemeral private key)
  • V is the public point of private key v
  • h is a SHA-256 hash mod n, which has a theoretical range of [0,2^256-1] mod n, ergo [0,n-1]
  • x is a private key, meaning it has a range of [1,n-1] just like v

The ZKP signature is calculated as r = v - x*h mod n. Given the range of v and h, it's theoretically possible that they collide in such a way that makes r evaluate to zero, meaning that a signature of all-bits zero could theoretically be correct.

library/ecjpake.c Outdated Show resolved Hide resolved
@stevew817 stevew817 added bug Community needs-review Every commit must be reviewed by at least two team members, needs-reviewer This PR needs someone to pick it up for review labels Mar 5, 2021
ChangeLog.d/issue1792.txt Outdated Show resolved Hide resolved
ChangeLog.d/issue1792.txt Outdated Show resolved Hide resolved
@mpg
Copy link
Contributor

mpg commented Mar 9, 2021

@stevew817 Excellent point, thanks for noticing! It was my mistake, when I saw this test failing I assumed r == 0 was forbidden (probably reasoning by analogy with ECDSA which does forbid it), but actually I should have read the description of the test better: what's forbidden is for the length of the encoded version of r to be zero. The Thread spec, as cited in the comments defines the encoding as opaque r<1..2^8-1>; so even if r was 0, it would be illegal to encode it as a zero-length string.

Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

As Steven pointed out, the fix I initially suggested for the EC J-PAKE part was misguided, so it should be changed.

Also, the ChangeLog entry needs to be updated.

Finally, I left a note about the ideal commit structures, but that's just things to keep in mind for future PRs. For this one you can just add new commits to fix things, no worries.

library/ecjpake.c Outdated Show resolved Hide resolved
@TRodziewicz
Copy link
Contributor Author

Thanks Manuel, works like a charm.

@TRodziewicz TRodziewicz requested a review from mpg March 22, 2021 10:46
@mpg mpg changed the title Fix EC J-PAKE failing when the payload is all-bits-zero Fix ECDSA failing when the hash is all-bits-zero Mar 29, 2021
Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

This looks mostly good to me, except for two things:

  1. We should have a regression test for 1792. As Ronald mentioned in CMake: usage of CMAKE_SOURCE_DIR in CMakeLists.txt files. #4268, an easy way to do that would be to modify the existing test functions ecdsa_prim_random and ecdsa_write_read_random: currently they generate a verify a signature with a random hash. We could turn the body into a loop that runs twice: once with a random hash, once with an all-zero hash.
  2. In the ChangeLog entry I think we should say "hash" instead of "payload".

Signed-off-by: TRodziewicz <[email protected]>
@mpg mpg self-requested a review April 7, 2021 09:33
mpg
mpg previously approved these changes Apr 7, 2021
Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

Thanks for adding a non-regresssion test and fixing the ChangeLog entry as requested. Looks all good to me now!

@mpg mpg requested a review from stevew817 April 7, 2021 11:18
@mpg mpg removed the needs-reviewer This PR needs someone to pick it up for review label Apr 7, 2021
Copy link
Contributor

@gilles-peskine-arm gilles-peskine-arm left a comment

Choose a reason for hiding this comment

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

The code changes and test data changes are correct, but the way the regression test is implemented is confusing.

tests/suites/test_suite_ecdsa.function Outdated Show resolved Hide resolved
ChangeLog.d/issue1792.txt Outdated Show resolved Hide resolved
tests/suites/test_suite_ecdsa.function Outdated Show resolved Hide resolved
tests/suites/test_suite_ecdsa.function Outdated Show resolved Hide resolved
@gilles-peskine-arm gilles-peskine-arm added needs-work and removed needs-review Every commit must be reviewed by at least two team members, labels Apr 7, 2021
@gilles-peskine-arm
Copy link
Contributor

I think this should be backported to 2.16 since it's a bug, but given how much of a corner case it is, I'd be ok with not doing the backport.

@TRodziewicz TRodziewicz added needs-review Every commit must be reviewed by at least two team members, and removed needs-work labels Apr 7, 2021
@stevew817
Copy link
Contributor

It was my mistake, when I saw this test failing I assumed r == 0 was forbidden (probably reasoning by analogy with ECDSA which does forbid it), but actually I should have read the description of the test better: what's forbidden is for the length of the encoded version of r to be zero.

@mpg Wouldn't it make sense to add an explicit test for ECJPAKE with r == 0, since it's apparently easy to run afoul of this corner case?

Copy link
Contributor

@mpg mpg left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@mpg
Copy link
Contributor

mpg commented Apr 19, 2021

Wouldn't it make sense to add an explicit test for ECJPAKE with r == 0, since it's apparently easy to run afoul of this corner case?

I think that would be a nice addition if it can be done* but I don't think it's important enough to block this PR. This case if very unlikely to happen at random, and if an attacker forced it, the worst that could happen is that we reject the message for the wrong reason.

*I didn't check for NIZP, but for ECDSA r == 0 is forbidden (the signature generation function should re-try with a fresh ephemeral key when it happens) but that's one part of your signature generation routine that you just can't test without solving a discrete log on the curve, which in practice means you need to have a weak curve available in your library if you want to test this... One of the many things that are annoying with ECDSA. Again I didn't check how it is with NIZP, so perhaps there it's possible to generate a valid ZKP with r == 0 for testing. I you feel like checking, I'm curious to know what you find, but unfortunately I don't have time to investigate myself now.

@mpg mpg added approved Design and code approved - may be waiting for CI or backports and removed needs-review Every commit must be reviewed by at least two team members, labels Apr 19, 2021
@mpg mpg merged commit 0bbb38c into Mbed-TLS:development Apr 19, 2021
@TRodziewicz TRodziewicz deleted the mul_shortcut_fix branch April 21, 2021 14:22
daverodgman pushed a commit that referenced this pull request Apr 23, 2021
Fix ECDSA failing when the hash is all-bits-zero
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Design and code approved - may be waiting for CI or backports bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ECDSA verification fails when the payload is all-bits-zero
5 participants