Skip to content

Fix BN_mod_exp_consttime so it does not produce unreduced result - #18510

Closed
t8m wants to merge 4 commits into
openssl:masterfrom
t8m:fix-modexp
Closed

t8m wants to merge 4 commits into
openssl:masterfrom
t8m:fix-modexp

Conversation

@t8m

@t8m t8m commented Jun 9, 2022

Copy link
Copy Markdown
Member

The BN_mod_exp_consttime can produce result == modulus instead of 0. This was reported by @guidovranken.

Original fix was developed by @davidben for BoringSSL.

t8m added 2 commits June 9, 2022 12:34
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>
Inspired by BoringSSL fix by David Benjamin.
@t8m t8m added branch: master Applies to master branch approval: review pending This pull request needs review by a committer branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) approval: otc review pending triaged: bug The issue/pr is/fixes a bug branch: 3.0 Applies to openssl-3.0 branch (EOL) labels Jun 9, 2022
@t8m

t8m commented Jun 9, 2022

Copy link
Copy Markdown
Member Author

@github-actions github-actions Bot added the severity: fips change The pull request changes FIPS provider sources label Jun 9, 2022
@t8m t8m removed the branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) label Jun 9, 2022
Comment thread crypto/bn/bn_exp.c
}

ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
tmp.top = top;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You probably want to keep this line (tmp.top = top). That was a mistake in my original patch. The line isn't actually necessary in BoringSSL, due to how we solved #6640, but dropping it was a little sloppy on my part. I'm not sure if, for you all, it's a matter of sloppiness or actual necessity, since you haven't solved #6640 but have some partial "fixed top" bits. (Would need to dig into that.)

This was the follow-up that I did in BoringSSL, but that bn_resize_words in that CL is part of some infrastructure we did for #6640. Probably easiest for you all to put tmp.top back in. (It's because the most of this code just uses tmp as a random array, with implicit bounds, and so nothing actually ensures tmp.top matches the array bounds.
https://boringssl.googlesource.com/boringssl/+/77dc23983f004056dbcd95ae96922be107365190%5E%21/#F0

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

OK, done.

Comment thread crypto/bn/rsaz_exp.h Outdated
Comment thread crypto/bn/rsaz_exp.h
}

static ossl_inline BN_ULONG bn_reduce_once_in_place(BN_ULONG *r,
BN_ULONG carry,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

carry is always zero in the places you all call this one. (We have a carry argument because we actually use this function all over the place. It's because 2*m might have one bit more than m and not fit in num. It shows up in Montgomery reduction, modular addition, and setting up the ECDSA digest. Dunno if you were intending to do the same.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Well, not any time soon, but at some point we might want to if we decide to fix the BN const time handling.

Comment thread crypto/bn/rsaz_exp_x2.c
from_words52(res2, factor_size, rr2_red);

bn_reduce_once_in_place(res1, /*carry=*/0, m1, storage, factor_size);
bn_reduce_once_in_place(res2, /*carry=*/0, m2, storage, factor_size);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

NB: BoringSSL doesn't have this code, so I don't actually know whether this is the correct fix for it or what it's doing. The reference to both "AMM" and "RSAZ" (which uses NRMM, not AMM) is a little odd. This may warrant extra review make sure this fix is necessary/sufficient.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yeah, someone who fully understands the math should verify if this is needed. @amatyuko-intc perhaps?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These two lines is causing #18625.

Comment thread crypto/bn/rsaz_exp.c Outdated
/* from Montgomery */
rsaz_512_mul_by_one(result, temp, m, k0);

bn_reduce_once_in_place(result, /*carry=*/0, m, storage, 8);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

BoringSSL doesn't have this code---we don't consider RSA-1024 worth optimizing for these days---so I don't know off-hand whether it is correct. But supposing it's the same algorithm as rsaz_1024 (RSA-2048), the fix looks right.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The 512 bit testcase was actually failing without it and passing with it. So IMO this is right.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah, question is whether it is sufficient. This fix assumes the result is bounded by 2m, which depends on what the code is doing. (I read through papers and asm to develop the fix for the bits we cared about.) But, yeah, this fix is almost certainly right since I'm pretty sure they're doing the same thing at different sizes. Less sure about ossl_rsaz_mod_exp_avx512_x2, but I haven't looked at what it's doing.

@t8m

t8m commented Jun 9, 2022

Copy link
Copy Markdown
Member Author

Thanks @davidben for the review

@paulidale paulidale added approval: done This pull request has the required number of approvals and removed approval: review pending This pull request needs review by a committer labels Jun 15, 2022
@openssl-machine openssl-machine added approval: ready to merge The 24 hour grace period has passed, ready to merge and removed approval: done This pull request has the required number of approvals labels Jun 16, 2022
@openssl-machine

Copy link
Copy Markdown
Collaborator

This pull request is ready to merge

openssl-machine pushed a commit that referenced this pull request Jun 16, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from #18510)
openssl-machine pushed a commit that referenced this pull request Jun 16, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from #18510)
openssl-machine pushed a commit that referenced this pull request Jun 16, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from #18510)

(cherry picked from commit 0ae365e)
openssl-machine pushed a commit that referenced this pull request Jun 16, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from #18510)

(cherry picked from commit 6d702ce)
@t8m

t8m commented Jun 16, 2022

Copy link
Copy Markdown
Member Author

Merged to master and 3.0 branches. Thank you for the reviews.

@t8m t8m closed this Jun 16, 2022
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 18, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 18, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 19, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 19, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 19, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
jquepi pushed a commit to jquepi/openssl7555 that referenced this pull request Jun 19, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl/openssl#18510)
sftcd pushed a commit to sftcd/openssl that referenced this pull request Sep 24, 2022
This partially fixes a bug where, on x86_64, BN_mod_exp_mont_consttime
would sometimes return m, the modulus, when it should have returned
zero. Thanks to Guido Vranken for reporting it. It is only a partial fix
because the same bug also exists in the "rsaz" codepath.

The bug only affects zero outputs (with non-zero inputs), so we believe
it has no security impact on our cryptographic functions.

The fx is to delete lowercase bn_from_montgomery altogether, and have the
mont5 path use the same BN_from_montgomery ending as the non-mont5 path.
This only impacts the final step of the whole exponentiation and has no
measurable perf impact.

See the original BoringSSL commit
https://boringssl.googlesource.com/boringssl/+/13c9d5c69d04485a7a8840c12185c832026c8315
for further analysis.

Original-author: David Benjamin <[email protected]>

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl#18510)
sftcd pushed a commit to sftcd/openssl that referenced this pull request Sep 24, 2022
Inspired by BoringSSL fix by David Benjamin.

Reviewed-by: Matt Caswell <[email protected]>
Reviewed-by: Paul Dale <[email protected]>
(Merged from openssl#18510)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: ready to merge The 24 hour grace period has passed, ready to merge branch: master Applies to master branch branch: 3.0 Applies to openssl-3.0 branch (EOL) severity: fips change The pull request changes FIPS provider sources triaged: bug The issue/pr is/fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants