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

mbedtls_mpi_cmp_int undefined behavior if parameter is LLONG_MIN #6597

Closed
guidovranken opened this issue Nov 13, 2022 · 4 comments
Closed

mbedtls_mpi_cmp_int undefined behavior if parameter is LLONG_MIN #6597

guidovranken opened this issue Nov 13, 2022 · 4 comments
Labels
bug component-crypto Crypto primitives and low-level interfaces

Comments

@guidovranken
Copy link
Contributor

Summary

mbedtls_mpi_cmp_int negates the input value. If the input value if the lowest possible value for mbedtls_mpi_sint, then negating that value is undefined behavior, because the negation LLONG_MIN (which is -9223372036854775808) is 9223372036854775808, but that value cannot be expressed in an mbedtls_mpi_sint.

System information

Mbed TLS version (number or commit id):
Operating system and version: Linux x64
Configuration (if not default, please attach mbedtls_config.h):
Compiler and options (if you used a pre-built binary, please indicate how you obtained it): git clone --depth 1 -b development https://github.com/ARMmbed/mbedtls.git
Additional environment information:

Expected behavior

No undefined behavior

Actual behavior

Undefined behavior:

/home/jhg/oss-fuzz-53367/mbedtls/library/bignum.c:856:23: runtime error: negation of -9223372036854775808 cannot be represented in type 'mbedtls_mpi_sint' (aka 'long'); cast to an unsigned type to negate this value to itself
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /home/jhg/oss-fuzz-53367/mbedtls/library/bignum.c:856:23 in 

Steps to reproduce

#include <mbedtls/bignum.h>

#define CF_CHECK_EQ(expr, res) if ( (expr) != (res) ) { goto end; }

int main(void)
{
    mbedtls_mpi a;
    mbedtls_mpi_init(&a);
    const mbedtls_mpi_sint b = -9223372036854775808ULL;
    CF_CHECK_EQ(mbedtls_mpi_read_string(&a, 10, "0"), 0);
    mbedtls_mpi_cmp_int(&a, b);
end:
    mbedtls_mpi_free(&a);
    return 0;
}

Additional information

OSS-Fuzz #53367 https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=53367

@guidovranken guidovranken changed the title mbedtls_mpi_cmp_intundefined behavior if parameter is LLONG_MIN mbedtls_mpi_cmp_int undefined behavior if parameter is LLONG_MIN Nov 13, 2022
@gilles-peskine-arm
Copy link
Contributor

I thought this had been raised in the past, but it might have been a private discussion only.

Several other mbedtls_mpi_xxx_int functions have a similar issue.

The mpi_xxx_int functions were mostly intended for constants appearing in code. Since they don't allow the full range of a bignum limb, they're of limited use with variables. It's unfortunate that this was not documented.

Expecting a cryptographic library to cope with negative integers is dubious in the first place; Mbed TLS currently uses them internally, but we're currently rewriting the bignum module to separate out these uses of negative integers, and it's likely that the next major version of Mbed TLS (if not, the one after that) will not support negative bignums anymore.

So we're likely to keep this as a documented bug, and add a note to the documentation that -2^(biL-1) is not an acceptable input to these functions.

@gilles-peskine-arm gilles-peskine-arm added bug component-crypto Crypto primitives and low-level interfaces labels Nov 13, 2022
guidovranken added a commit to guidovranken/cryptofuzz that referenced this issue Nov 13, 2022
@guidovranken
Copy link
Contributor Author

OK, I've worked around the issue in my fuzzer, so it won't be detected on OSS-Fuzz anymore.

gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this issue Nov 15, 2022
Some bignum functions take a value of type mbedtls_mpi_sint as an argument.
This was mostly intended for constants in the source code. There isn't much
use for supporting the whole _signed_ range correctly (supporting the whole
unsigned range would be another matter). Supporting the most negative value
V of a two's complement signed type is hard: -V is an integer overflow.
Since it's both hard and not useful, don't bother. Just document that it
is not supported. This does not affect the use of these functions inside
the library and is unlikely to affect real applications.

Resolves Mbed-TLS#6597.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
gilles-peskine-arm added a commit to gilles-peskine-arm/mbedtls that referenced this issue Nov 15, 2022
Some bignum functions take a value of type mbedtls_mpi_sint as an argument.
This was mostly intended for constants in the source code. There isn't much
use for supporting the whole _signed_ range correctly (supporting the whole
unsigned range would be another matter). Supporting the most negative value
V of a two's complement signed type is hard: -V is an integer overflow.
Since it's both hard and not useful, don't bother. Just document that it
has undefined behavior. This does not affect the use of these functions
inside the library and is unlikely to affect real applications.

Resolves Mbed-TLS#6597.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
@gilles-peskine-arm
Copy link
Contributor

Actually, looking closely, a cast is enough to make the behavior well-defined. So here's a proper fix.

@gilles-peskine-arm
Copy link
Contributor

Fixed by #6609 and backport.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug component-crypto Crypto primitives and low-level interfaces
Projects
None yet
Development

No branches or pull requests

2 participants