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 CVE-2024-9143 for 8.4-stable #696

Open
wants to merge 2 commits into
base: 8.4-stable
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

Changes between 8.4.0 and 8.4.1 [xx XXX xxxx]

*) 修复CVE-2024-9143

*) 修复CVE-2024-5535

*) 修复CVE-2024-4741
Expand Down
28 changes: 20 additions & 8 deletions crypto/bn/bn_gf2m.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "bn_local.h"

#ifndef OPENSSL_NO_EC2M
# include <openssl/ec.h>

/*
* Maximum number of iterations before BN_GF2m_mod_solve_quad_arr should
Expand Down Expand Up @@ -1134,16 +1135,26 @@ int BN_GF2m_mod_solve_quad(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
/*
* Convert the bit-string representation of a polynomial ( \sum_{i=0}^n a_i *
* x^i) into an array of integers corresponding to the bits with non-zero
* coefficient. Array is terminated with -1. Up to max elements of the array
* will be filled. Return value is total number of array elements that would
* be filled if array was large enough.
* coefficient. The array is intended to be suitable for use with
* `BN_GF2m_mod_arr()`, and so the constant term of the polynomial must not be
* zero. This translates to a requirement that the input BIGNUM `a` is odd.
*
* Given sufficient room, the array is terminated with -1. Up to max elements
* of the array will be filled.
*
* The return value is total number of array elements that would be filled if
* array was large enough, including the terminating `-1`. It is `0` when `a`
* is not odd or the constant term is zero contrary to requirement.
*
* The return value is also `0` when the leading exponent exceeds
* `OPENSSL_ECC_MAX_FIELD_BITS`, this guards against CPU exhaustion attacks,
*/
int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
{
int i, j, k = 0;
BN_ULONG mask;

if (BN_is_zero(a))
if (!BN_is_odd(a))
return 0;

for (i = a->top - 1; i >= 0; i--) {
Expand All @@ -1161,12 +1172,13 @@ int BN_GF2m_poly2arr(const BIGNUM *a, int p[], int max)
}
}

if (k < max) {
if (k > 0 && p[0] > OPENSSL_ECC_MAX_FIELD_BITS)
return 0;

if (k < max)
p[k] = -1;
k++;
}

return k;
return k + 1;
}

/*
Expand Down
51 changes: 51 additions & 0 deletions test/ec_internal_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,56 @@ static int field_tests_ecp_mont(void)
}

#ifndef OPENSSL_NO_EC2M
/* Test that decoding of invalid GF2m field parameters fails. */
static int ec2m_field_sanity(void)
{
int ret = 0;
BN_CTX *ctx = BN_CTX_new();
BIGNUM *p, *a, *b;
EC_GROUP *group1 = NULL, *group2 = NULL, *group3 = NULL;

TEST_info("Testing GF2m hardening\n");

BN_CTX_start(ctx);
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
if (!TEST_ptr(b = BN_CTX_get(ctx))
|| !TEST_true(BN_one(a))
|| !TEST_true(BN_one(b)))
goto out;

/* Even pentanomial value should be rejected */
if (!TEST_true(BN_set_word(p, 0xf2)))
goto out;
if (!TEST_ptr_null(group1 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
TEST_error("Zero constant term accepted in GF2m polynomial");

/* Odd hexanomial should also be rejected */
if (!TEST_true(BN_set_word(p, 0xf3)))
goto out;
if (!TEST_ptr_null(group2 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
TEST_error("Hexanomial accepted as GF2m polynomial");

/* Excessive polynomial degree should also be rejected */
if (!TEST_true(BN_set_word(p, 0x71))
|| !TEST_true(BN_set_bit(p, OPENSSL_ECC_MAX_FIELD_BITS + 1)))
goto out;
if (!TEST_ptr_null(group3 = EC_GROUP_new_curve_GF2m(p, a, b, ctx)))
TEST_error("GF2m polynomial degree > %d accepted",
OPENSSL_ECC_MAX_FIELD_BITS);

ret = group1 == NULL && group2 == NULL && group3 == NULL;

out:
EC_GROUP_free(group1);
EC_GROUP_free(group2);
EC_GROUP_free(group3);
BN_CTX_end(ctx);
BN_CTX_free(ctx);

return ret;
}

/* test EC_GF2m_simple_method directly */
static int field_tests_ec2_simple(void)
{
Expand Down Expand Up @@ -410,6 +460,7 @@ int setup_tests(void)
ADD_TEST(field_tests_ecp_simple);
ADD_TEST(field_tests_ecp_mont);
#ifndef OPENSSL_NO_EC2M
ADD_TEST(ec2m_field_sanity);
ADD_TEST(field_tests_ec2_simple);
#endif
ADD_ALL_TESTS(field_tests_default, crv_len);
Expand Down
Loading