mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 14:00:48 +02:00
Merge pull request #10445 from embhorn/zd21742
Fix in ECC point conversion
This commit is contained in:
+24
-4
@@ -1356,9 +1356,19 @@ WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group,
|
||||
}
|
||||
|
||||
key_sz = (wolfSSL_EC_GROUP_get_degree(group) + 7) / 8;
|
||||
if (key_sz <= 0 || (size_t)key_sz > MAX_ECC_BYTES)
|
||||
goto err;
|
||||
|
||||
if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */
|
||||
str_sz = (size_t)key_sz * 2;
|
||||
|
||||
/* The uncompressed encoding is exactly 2 + 4*key_sz hex chars
|
||||
* ("04" prefix plus X and Y as 2*key_sz hex chars each). Reject
|
||||
* any other length so XMEMCPY/BN_hex2bn cannot read past the end
|
||||
* of the input and trailing garbage is not silently absorbed. */
|
||||
if (XSTRLEN(hex + 2) != str_sz * 2)
|
||||
goto err;
|
||||
|
||||
XMEMSET(strGx, 0x0, str_sz + 1);
|
||||
XMEMCPY(strGx, hex + 2, str_sz);
|
||||
|
||||
@@ -1377,10 +1387,20 @@ WOLFSSL_EC_POINT* wolfSSL_EC_POINT_hex2point(const WOLFSSL_EC_GROUP *group,
|
||||
}
|
||||
}
|
||||
else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) {
|
||||
size_t sz = XSTRLEN(hex + 2) / 2;
|
||||
/* compressed mode */
|
||||
octGx[0] = ECC_POINT_COMP_ODD;
|
||||
if (hex_to_bytes(hex + 2, octGx + 1, sz) != sz) {
|
||||
/* The SEC 1 compressed encoding is exactly 1 + key_sz bytes, so
|
||||
* the hex payload after the "02"/"03" prefix must be exactly
|
||||
* 2*key_sz hex chars. Compare the input length directly (rather
|
||||
* than XSTRLEN/2) so that odd-length inputs cannot slip past via
|
||||
* integer truncation. The exact-match rejects oversized inputs
|
||||
* (preventing a hex_to_bytes() write past strGx) and undersized
|
||||
* inputs (preventing wolfSSL_ECPoint_d2i() from reading
|
||||
* uninitialized stack bytes as the X coordinate). */
|
||||
if (XSTRLEN(hex + 2) != (size_t)key_sz * 2)
|
||||
goto err;
|
||||
octGx[0] = (hex[1] == '2') ? ECC_POINT_COMP_EVEN
|
||||
: ECC_POINT_COMP_ODD;
|
||||
if (hex_to_bytes(hex + 2, octGx + 1, (size_t)key_sz)
|
||||
!= (size_t)key_sz) {
|
||||
goto err;
|
||||
}
|
||||
if (wolfSSL_ECPoint_d2i(octGx, (word32)key_sz + 1, group, p)
|
||||
|
||||
@@ -631,6 +631,79 @@ int test_wolfSSL_EC_POINT(void)
|
||||
#endif
|
||||
XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC);
|
||||
EC_POINT_free(get_point);
|
||||
get_point = NULL;
|
||||
|
||||
/* Regression: oversized compressed-point hex must not overflow the stack
|
||||
* buffer in wolfSSL_EC_POINT_hex2point(). The byte length decoded from
|
||||
* the hex string must be bounded by the curve's ordinate size. */
|
||||
{
|
||||
char tooLongHex[2 + 600 + 1];
|
||||
size_t i;
|
||||
|
||||
tooLongHex[0] = '0';
|
||||
tooLongHex[1] = '3';
|
||||
for (i = 2; i < sizeof(tooLongHex) - 1; i++)
|
||||
tooLongHex[i] = 'A';
|
||||
tooLongHex[sizeof(tooLongHex) - 1] = '\0';
|
||||
ExpectNull(EC_POINT_hex2point(group, tooLongHex, NULL, ctx));
|
||||
|
||||
/* Same with the "02" (even Y) prefix. */
|
||||
tooLongHex[1] = '2';
|
||||
ExpectNull(EC_POINT_hex2point(group, tooLongHex, NULL, ctx));
|
||||
|
||||
/* Truncated uncompressed input: prefix "04" with too few hex chars
|
||||
* to cover the curve's coordinates. Must return NULL without
|
||||
* reading past the end of the input string. */
|
||||
ExpectNull(EC_POINT_hex2point(group, "04AB", NULL, ctx));
|
||||
|
||||
/* Empty payload after a recognized prefix. */
|
||||
ExpectNull(EC_POINT_hex2point(group, "03", NULL, ctx));
|
||||
ExpectNull(EC_POINT_hex2point(group, "04", NULL, ctx));
|
||||
|
||||
/* Partially populated compressed input: must be rejected so that
|
||||
* wolfSSL_ECPoint_d2i() does not consume uninitialized stack
|
||||
* bytes as the X coordinate. */
|
||||
ExpectNull(EC_POINT_hex2point(group, "03AB", NULL, ctx));
|
||||
ExpectNull(EC_POINT_hex2point(group, "02ABCD", NULL, ctx));
|
||||
|
||||
/* Odd-length compressed payload: 2*key_sz + 1 hex chars after
|
||||
* the "03" prefix (P-256: 65 chars). A truncating-divide bound
|
||||
* (sz = XSTRLEN/2) would round down to key_sz and accept this;
|
||||
* an exact-length compare must reject it. */
|
||||
{
|
||||
char oddLenHex[2 + 65 + 1];
|
||||
for (i = 2; i < sizeof(oddLenHex) - 1; i++)
|
||||
oddLenHex[i] = 'A';
|
||||
oddLenHex[0] = '0';
|
||||
oddLenHex[1] = '3';
|
||||
oddLenHex[sizeof(oddLenHex) - 1] = '\0';
|
||||
ExpectNull(EC_POINT_hex2point(group, oddLenHex, NULL, ctx));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_COMP_KEY) && !defined(HAVE_SELFTEST)
|
||||
/* Round-trip a compressed point with even Y ("02" prefix) to verify
|
||||
* that the prefix-to-parity flag is honored in the compressed branch. */
|
||||
{
|
||||
EC_POINT* even_point = NULL;
|
||||
EC_POINT* round_trip = NULL;
|
||||
char* even_hex = NULL;
|
||||
|
||||
ExpectNotNull(even_point = EC_POINT_dup(Gxy, group));
|
||||
ExpectIntEQ(EC_POINT_invert(group, even_point, ctx), 1);
|
||||
ExpectNotNull(even_hex = EC_POINT_point2hex(group, even_point,
|
||||
POINT_CONVERSION_COMPRESSED, ctx));
|
||||
/* P-256 G has odd Y; inverting flips Y parity so prefix is "02". */
|
||||
ExpectIntEQ(even_hex[1], '2');
|
||||
ExpectNotNull(round_trip = EC_POINT_hex2point(group, even_hex, NULL,
|
||||
ctx));
|
||||
ExpectIntEQ(EC_POINT_cmp(group, even_point, round_trip, ctx), 0);
|
||||
|
||||
XFREE(even_hex, NULL, DYNAMIC_TYPE_ECC);
|
||||
EC_POINT_free(round_trip);
|
||||
EC_POINT_free(even_point);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SELFTEST
|
||||
/* Test point to oct */
|
||||
|
||||
Reference in New Issue
Block a user