1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00
Files
wolfssl/tests/api/test_ossl_ec.h
Tobias Frauenschläger 8c6aacceb6 ecc: bound X9.63 ordinates to the curve and range check SP points
_ecc_import_x963_ex2() took the ordinate width from the input length and
never compared it with the curve, so a SubjectPublicKeyInfo naming one
curve but carrying wider ordinates became a key on that curve holding
oversized ordinates. wc_ecc_set_curve() bounds the size only by
ECC_MAXSIZE and, when given a curve id, selects the curve by id without
comparing sizes. The untrusted-import validation did not catch it in SP
builds: sp_ecc_is_point_256/384/521() copy only the low limbs out of the
mp_int, so the truncated point is on the curve and the import succeeds,
where the generic wc_ecc_is_point() returns ECC_OUT_OF_RANGE_E. Every
caller of the importer is affected, including wc_EccPublicKeyDecode(),
the TLS 1.2 and TLS 1.3 key exchange, PKCS#7 KARI, HPKE and the compat
d2i_* functions; none of them compares the wire length with the curve
size first.

wolfSSL_EC_POINT_point2hex() then placed the x-ordinate at an offset
derived from the curve size minus the ordinate size, which goes negative
once an ordinate is wider than the curve. The compressed form and the y
ordinate degenerate the same way.

_ecc_import_x963_ex2() now requires the ordinate size to equal
key->dp->size, returning ECC_BAD_ARG_E otherwise. This is the check
wc_ecc_import_point_der_ex() already has, placed in the shared importer
so it covers every caller and every math back end.

wolfSSL_EC_POINT_point2hex() refuses ordinates larger than the curve
before computing any offset, mirroring wc_ecc_export_point_der(), whose
guard wolfSSL_EC_POINT_point2oct() already inherits, and picks up the
NULL ordinate check that its new bound would otherwise be the first to
dereference past.

sp_ecc_is_point_256/384/521/1024() in all eight SP back ends gain the
mp_count_bits() and modulus comparison that the neighbouring
sp_ecc_check_key_*() already carries, so SP builds no longer accept a
same-length non-canonical encoding that every other back end rejects.
Both functions also gain the mp_isneg() test the generic implementation
has: sp_<n>_from_mp() ignores the sign, so a negative ordinate was read
as its magnitude. sp_ecc_check_key_*() lacked that check before this
change as well. The sp_*.c files are generator output; the change was
made in wolfSSL/scripts sp/ecc.rb and the files regenerated, and the
result is byte for byte what the modified generator produces.

Behaviour change: X9.63 encodings shorter than the curve size are
rejected as well. They are non-canonical under SEC 1 section 2.3.4 and
RFC 5480 and OpenSSL rejects them too. With ECC_CURVE_DEF the size-based
curve lookup still resolves exact-size encodings as before.

Tests: test_wc_ecc_import_x963_oversized and
test_wc_ecc_import_x963_non_canonical cover the importer,
test_wolfSSL_EC_POINT_point2hex_oversized covers the sink, and all three
fail on the unfixed tree. The SP MC/DC drivers gain the new bit-length
and sign branches and an operand exactly the field's width but not below
the modulus, without which the new range compare was only ever reached
with the bit-length guard already true. Those rows now assert
ECC_OUT_OF_RANGE_E rather than discarding the result, and report a
failure separately from a skipped row; removing either guard from a back
end makes them fail.
2026-10-08 08:38:09 +02:00

77 lines
3.3 KiB
C

/* test_ossl_ec.h
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLFCRYPT_TEST_OSSL_EC_H
#define WOLFCRYPT_TEST_OSSL_EC_H
#include <tests/api/api_decl.h>
#if defined(HAVE_ECC) && !defined(OPENSSL_NO_PK)
int test_wolfSSL_EC_GROUP(void);
int test_wolfSSL_PEM_read_bio_ECPKParameters(void);
int test_wolfSSL_i2d_ECPKParameters(void);
int test_wolfSSL_EC_POINT(void);
int test_wolfSSL_SPAKE(void);
int test_wolfSSL_EC_KEY_generate(void);
int test_EC_i2d(void);
int test_wolfSSL_EC_curve(void);
int test_wolfSSL_EC_KEY_dup(void);
int test_wolfSSL_EC_KEY_set_group(void);
int test_wolfSSL_EC_KEY_set_conv_form(void);
int test_wolfSSL_EC_KEY_private_key(void);
int test_wolfSSL_EC_KEY_public_key(void);
int test_wolfSSL_EC_KEY_print_fp(void);
int test_wolfSSL_EC_get_builtin_curves(void);
int test_wolfSSL_ECDSA_SIG(void);
int test_ECDSA_size_sign(void);
int test_ECDH_compute_key(void);
int test_d2i_ECPrivateKey_no_pubkey(void);
int test_wolfSSL_EC_POINT_point2hex_oversized(void);
#define TEST_OSSL_EC_DECLS \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_GROUP), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_PEM_read_bio_ECPKParameters), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_i2d_ECPKParameters), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_POINT), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_SPAKE), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_generate), \
TEST_DECL_GROUP("ossl_ec", test_EC_i2d), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_curve), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_dup), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_set_group), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_set_conv_form), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_private_key), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_public_key), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_KEY_print_fp), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_get_builtin_curves), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_ECDSA_SIG), \
TEST_DECL_GROUP("ossl_ec", test_ECDSA_size_sign), \
TEST_DECL_GROUP("ossl_ec", test_ECDH_compute_key), \
TEST_DECL_GROUP("ossl_ec", test_d2i_ECPrivateKey_no_pubkey), \
TEST_DECL_GROUP("ossl_ec", test_wolfSSL_EC_POINT_point2hex_oversized)
#endif
#endif /* WOLFCRYPT_TEST_OSSL_EC_H */