Skip to content

Comments

Limit size of modulus for BN_mod_exp_mont_consttime() [1.1.1]#19647

Closed
t8m wants to merge 1 commit intoopenssl:OpenSSL_1_1_1-stablefrom
t8m:bn-modexp-limit-111
Closed

Limit size of modulus for BN_mod_exp_mont_consttime() [1.1.1]#19647
t8m wants to merge 1 commit intoopenssl:OpenSSL_1_1_1-stablefrom
t8m:bn-modexp-limit-111

Conversation

@t8m
Copy link
Member

@t8m t8m commented Nov 10, 2022

Otherwise the powerbufLen can overflow.

Issue reported by Jiayi Lin.

Checklist
  • tests are added or updated

Same as #19632 but for 1.1.1 - as this is security related although not an exploitable security issue we might want this on 1.1.1.

Otherwise the powerbufLen can overflow.

Issue reported by Jiayi Lin.
@t8m t8m added 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 tests: present The PR has suitable tests present labels Nov 10, 2022
@t8m t8m requested review from beldmit and mattcaswell November 10, 2022 16:51
return 0;
}
if ((unsigned int)top > INT_MAX / sizeof(m->d[0]) / (1 << 8)) {
/* Prevent overflowing the powerbufLen computation below */
Copy link
Member

Choose a reason for hiding this comment

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

have you seen the np = alloca(top * sizeof(BN_ULONG)); down below ?

Copy link
Member Author

Choose a reason for hiding this comment

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

heh, no. Now that is SPARC only code. Not sure what to do with that. Change it to OPENSSL_malloc() for some value of top? Can be a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

Could we solve this differently, like when the modulus size is larger than RSA_MAX_MODULUS then ignore the constant time flag, since that large numbers are usually just used for denial of service attacks?

Copy link
Member

Choose a reason for hiding this comment

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

I mean the non-constant time code will be orders of magnitude faster than this, and will not have these alloca problem.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, that is a good idea.

Copy link
Contributor

Choose a reason for hiding this comment

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

If you're concerned about the alloca, note that bn_mul_mont itself, used also by BN_mod_exp_mont, internally does a similar alloca, hidden away in assembly. It may be worth just cutting down the largest BIGNUM a little. (I'll probably go that route in BoringSSL.)

If we do that, this actually won't be able to overflow. The largest BIGNUM is capped here. It's INT_MAX / (4 * BN_BITS2) words, or INT_MAX / 4 bits, or INT_MAX / 32 bytes, or 64MiB.

if (words > (INT_MAX / (4 * BN_BITS2))) {

Scrolling down, powerbufLen increases from two places, a top * sizeof(mont->N.d[0]) term (which, if it happens, forces window to 5), and the more complex term:

    powerbufLen += sizeof(m->d[0]) * (top * numPowers +
                                      ((2 * top) >
                                       numPowers ? (2 * top) : numPowers));

(Incidentally, I believe the (2 * top) > numPowers ? (2 * top) : numPowers bit is a remnant of older versions of mont5 which used to overread the table by one row. Unreasonably clever scheduling. It no longer does this and probably can be replaced with 2 * top now, though I haven't carefully analyzed all the files in OpenSSL, just the subset we have.)

numPowers is at most 64, so we're looking at 64 BIGNUMs, plus change, or a bit over 4GiB. That won't fit in int, but it's close enough that we don't need to bring it down too much further to make it always fit.

Copy link
Contributor

Choose a reason for hiding this comment

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

It may be worth just cutting down the largest BIGNUM a little. (I'll probably go that route in BoringSSL.)

Update: this almost works, except we found one project that relies on making 8MiB bignums, and some others that needed 32-64KiB. 32-64KiB is plausible to alloca, but 8MiB is too much. So we're probably going to apply the cap Montgomery moduli instead.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, isn't a kernel task stack just 64 K large?

Copy link
Contributor

@davidben davidben Nov 22, 2022

Choose a reason for hiding this comment

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

Hmm yeah that's possibly also a bit large. Regardless, the 8MiB one means solving it with a bn-wide limit doesn't seem viable for us. My plan was to do a 8KiB limit in BN_MONT_CTX, which is enough for the maximum of all our cryptographic primitives, with a little additional leeway. (The callers that needed 32-64KiB also don't use Montgomery reduction.)

Copy link
Member

@bernd-edlinger bernd-edlinger Nov 22, 2022

Choose a reason for hiding this comment

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

Take a look at #19735 is that acceptable, or did I miss something?

BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME, ERR_R_PASSED_INVALID_ARGUMENT);
return 0;
}
if ((unsigned int)top > INT_MAX / sizeof(m->d[0]) / (1 << 8)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Given this depends on BN_window_bits_for_ctime_exponent_size, perhaps this should be based on BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE.

return 0;
}
if ((unsigned int)top > INT_MAX / sizeof(m->d[0]) / (1 << 8)) {
/* Prevent overflowing the powerbufLen computation below */
Copy link
Contributor

Choose a reason for hiding this comment

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

If you're concerned about the alloca, note that bn_mul_mont itself, used also by BN_mod_exp_mont, internally does a similar alloca, hidden away in assembly. It may be worth just cutting down the largest BIGNUM a little. (I'll probably go that route in BoringSSL.)

If we do that, this actually won't be able to overflow. The largest BIGNUM is capped here. It's INT_MAX / (4 * BN_BITS2) words, or INT_MAX / 4 bits, or INT_MAX / 32 bytes, or 64MiB.

if (words > (INT_MAX / (4 * BN_BITS2))) {

Scrolling down, powerbufLen increases from two places, a top * sizeof(mont->N.d[0]) term (which, if it happens, forces window to 5), and the more complex term:

    powerbufLen += sizeof(m->d[0]) * (top * numPowers +
                                      ((2 * top) >
                                       numPowers ? (2 * top) : numPowers));

(Incidentally, I believe the (2 * top) > numPowers ? (2 * top) : numPowers bit is a remnant of older versions of mont5 which used to overread the table by one row. Unreasonably clever scheduling. It no longer does this and probably can be replaced with 2 * top now, though I haven't carefully analyzed all the files in OpenSSL, just the subset we have.)

numPowers is at most 64, so we're looking at 64 BIGNUMs, plus change, or a bit over 4GiB. That won't fit in int, but it's close enough that we don't need to bring it down too much further to make it always fit.

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/otc but the last update was 30 days ago

@openssl-machine
Copy link
Collaborator

This PR is in a state where it requires action by @openssl/otc but the last update was 61 days ago

@t8m
Copy link
Member Author

t8m commented Jan 17, 2023

Now that #19735 is merged. Closing.

@t8m t8m closed this Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: review pending This pull request needs review by a committer branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) tests: present The PR has suitable tests present triaged: bug The issue/pr is/fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants