Merge pull request #9324 from douzzer/20251020-coverity-WC_SAFE_foo

20251020-coverity-WC_SAFE_foo
This commit is contained in:
David Garske
2025-10-21 09:41:25 -07:00
committed by GitHub
4 changed files with 483 additions and 43 deletions

View File

@@ -11192,7 +11192,7 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size)
#else
const byte align = WOLFSSL_GENERAL_ALIGNMENT;
#endif
word32 newSz;
word32 newSz = 0;
#if WOLFSSL_GENERAL_ALIGNMENT > 0
/* the encrypted data will be offset from the front of the buffer by

View File

@@ -568,6 +568,7 @@ typedef struct testVector {
#define WOLFSSL_TEST_SUBROUTINE
#endif
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t macro_test(void);
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void);
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base64_test(void);
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t base16_test(void);
@@ -2010,6 +2011,11 @@ options: [-s max_relative_stack_bytes] [-m max_relative_heap_memory_bytes]\n\
TEST_PASS("CAVP selftest passed!\n");
#endif
if ( (ret = macro_test()) != 0)
TEST_FAIL("macro test failed!\n", ret);
else
TEST_PASS("macro test passed!\n");
if ( (ret = error_test()) != 0)
TEST_FAIL("error test failed!\n", ret);
else
@@ -3203,6 +3209,364 @@ static wc_test_ret_t _SaveDerAndPem(const byte* der, int derSz,
}
#endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */
static wc_test_ret_t safe_sum_word32_test(void) {
word32 out;
int ret;
int i;
static const struct {
word32 a;
word32 b;
word32 e;
int t;
} cases[] = {
#define u_max 4294967295U
#define half (4294967295U / 2U)
{ 0, 0, 0, 1 },
{ 1, 1, 2, 1 },
{ u_max, 0, u_max, 1 },
{ u_max - 1, 1, u_max, 1 },
{ u_max, 1, u_max, 0 },
{ 0, u_max, u_max, 1 },
{ half, half, half * 2U, 1 },
{ u_max - 1, 2, u_max, 0 }
#undef half
#undef u_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUM_UNSIGNED_CLIP(word32, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUM_UNSIGNED(word32, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sub_word32_test(void) {
word32 out;
int ret;
int i;
static const struct {
word32 a;
word32 b;
word32 e;
int t;
} cases[] = {
#define u_max 4294967295U
{ 5, 3, 2, 1 },
{ 0, 0, 0, 1 },
{ 1, 0, 1, 1 },
{ 0, 1, 0, 0 },
{ u_max, u_max, 0, 1 },
{ u_max, 0, u_max, 1 },
{ u_max, 1, u_max - 1, 1 },
{ 1, 2, 0, 0 },
#undef u_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUB_UNSIGNED_CLIP(word32, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUB_UNSIGNED(word32, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sum_sword32_test(void) {
sword32 out;
int ret;
int i;
static const struct {
sword32 a;
sword32 b;
sword32 e;
int t;
} cases[] = {
#define i_max 2147483647
#define i_min (-i_max - 1)
#define half (i_max / 2)
{ 0, 0, 0, 1 },
{ 1, 1, 2, 1 },
{ i_max, 0, i_max, 1 },
{ i_max - 1, 1, i_max, 1 },
{ i_max, 1, i_max, 0 },
{ 0, i_max, i_max, 1 },
{ -1, -1, -2, 1 },
{ i_min, 0, i_min, 1 },
{ i_min + 1, -1, i_min, 1 },
{ i_min, -1, i_min, 0 },
{ 1, -1, 0, 1 },
{ -1, 1, 0, 1 },
{ half, half + 1, i_max, 1 },
{ half + 1, half + 1, i_max, 0 }
#undef half
#undef i_min
#undef i_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUM_SIGNED_CLIP(sword32, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUM_SIGNED(sword32, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sub_sword32_test(void) {
sword32 out;
int ret;
int i;
static const struct {
sword32 a;
sword32 b;
sword32 e;
int t;
} cases[] = {
#define i_max 2147483647
#define i_min (-i_max - 1)
{ 0, 0, 0, 1 },
{ 5, 3, 2, 1 },
{ 1, -1, 2, 1 },
{ i_max, 0, i_max, 1 },
{ i_max, -1, i_max, 0 },
{ -5, -3, -2, 1 },
{ 0, 1, -1, 1 },
{ i_min, 0, i_min, 1 },
{ i_min + 1, 1, i_min, 1 },
{ i_min, 1, i_min, 0 },
{ 1, 2, -1, 1 },
{ -1, -2, 1, 1 },
{ -1, i_min, i_max, 1 },
{ i_min, -1, i_min + 1, 1 },
{ 2, -3, 5, 1 }
#undef i_min
#undef i_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUB_SIGNED_CLIP(sword32, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUB_SIGNED(sword32, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
#ifdef WORD64_AVAILABLE
static wc_test_ret_t safe_sum_word64_test(void) {
word64 out;
int ret;
int i;
static const struct {
word64 a;
word64 b;
word64 e;
int t;
} cases[] = {
#define u_max W64LIT(18446744073709551615)
#define half (u_max / 2)
{ 0, 0, 0, 1 },
{ 1, 1, 2, 1 },
{ u_max, 0, u_max, 1 },
{ u_max - 1, 1, u_max, 1 },
{ u_max, 1, u_max, 0 },
{ 0, u_max, u_max, 1 },
{ half, half, half * 2ULL, 1 },
{ u_max - 1, 2, u_max, 0 }
#undef half
#undef u_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUM_UNSIGNED_CLIP(word64, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUM_UNSIGNED(word64, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sub_word64_test(void) {
word64 out;
int ret;
int i;
static const struct {
word64 a;
word64 b;
word64 e;
int t;
} cases[] = {
#define u_max W64LIT(18446744073709551615)
{ 5, 3, 2, 1 },
{ 0, 0, 0, 1 },
{ 1, 0, 1, 1 },
{ 0, 1, 0, 0 },
{ u_max, u_max, 0, 1 },
{ u_max, 0, u_max, 1 },
{ u_max, 1, u_max - 1, 1 },
{ 1, 2, 0, 0 }
#undef u_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUB_UNSIGNED_CLIP(word64, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUB_UNSIGNED(word64, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sum_sword64_test(void) {
sword64 out;
int ret;
int i;
static const struct {
sword64 a;
sword64 b;
sword64 e;
int t;
} cases[] = {
#define i_max SW64LIT(9223372036854775807)
#define i_min (-i_max-1)
#define half (i_max / 2)
{ 0, 0, 0, 1 },
{ 1, 1, 2, 1 },
{ i_max, 0, i_max, 1 },
{ i_max - 1, 1, i_max, 1 },
{ i_max, 1, i_max, 0 },
{ 0, i_max, i_max, 1 },
{ -1, -1, -2, 1 },
{ i_min, 0, i_min, 1 },
{ i_min + 1, -1, i_min, 1 },
{ i_min, -1, i_min, 0 },
{ 1, -1, 0, 1 },
{ -1, 1, 0, 1 },
{ half, half + 1, i_max, 1 },
{ half + 1, half + 1, i_max, 0 }
#undef half
#undef i_min
#undef i_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUM_SIGNED_CLIP(sword64, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUM_SIGNED(sword64, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
static wc_test_ret_t safe_sub_sword64_test(void) {
sword64 out;
int ret;
int i;
static const struct {
sword64 a;
sword64 b;
sword64 e;
int t;
} cases[] = {
#define i_max SW64LIT(9223372036854775807)
#define i_min (-i_max-1)
{ 0, 0, 0, 1 },
{ 5, 3, 2, 1 },
{ 1, -1, 2, 1 },
{ i_max, 0, i_max, 1 },
{ i_max, -1, i_max, 0 },
{ -5, -3, -2, 1 },
{ 0, 1, -1, 1 },
{ i_min, 0, i_min, 1 },
{ i_min + 1, 1, i_min, 1 },
{ i_min, 1, i_min, 0 },
{ 1, 2, -1, 1 },
{ -1, -2, 1, 1 },
{ -1, i_min, i_max, 1 },
{ i_min, -1, i_min + 1, 1 },
{ 2, -3, 5, 1 }
#undef i_min
#undef i_max
};
for (i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); ++i) {
ret = WC_SAFE_SUB_SIGNED_CLIP(sword64, cases[i].a, cases[i].b, out);
if (out != cases[i].e || ret != cases[i].t)
return WC_TEST_RET_ENC_I(i);
out = 10;
ret = WC_SAFE_SUB_SIGNED(sword64, cases[i].a, cases[i].b, out);
if ((ret != cases[i].t) || (ret && (out != cases[i].e)))
return WC_TEST_RET_ENC_I(i);
}
return 0;
}
#endif /* WORD64_AVAILABLE */
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t macro_test(void)
{
wc_test_ret_t ret;
ret = safe_sum_word32_test();
if (ret == 0)
ret = safe_sub_word32_test();
if (ret == 0)
ret = safe_sum_sword32_test();
if (ret == 0)
ret = safe_sub_sword32_test();
#ifdef WORD64_AVAILABLE
if (ret == 0)
ret = safe_sum_word64_test();
if (ret == 0)
ret = safe_sub_word64_test();
if (ret == 0)
ret = safe_sum_sword64_test();
if (ret == 0)
ret = safe_sub_sword64_test();
#endif /* WORD64_AVAILABLE */
return ret;
}
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t error_test(void)
{
const char* errStr;
@@ -34550,9 +34914,9 @@ static const byte p521PubKey[] = {
/* perform verify of signature and hash using public key */
/* key is public Qx + public Qy */
/* sig is r + s */
static wc_test_ret_t crypto_ecc_verify(const byte *key, uint32_t keySz,
const byte *hash, uint32_t hashSz, const byte *sig, uint32_t sigSz,
uint32_t curveSz, int curveId)
static wc_test_ret_t crypto_ecc_verify(const byte *key, word32 keySz,
const byte *hash, word32 hashSz, const byte *sig, word32 sigSz,
word32 curveSz, int curveId)
{
wc_test_ret_t ret;
int verify_res = 0, count = 0;
@@ -34652,9 +35016,9 @@ static wc_test_ret_t crypto_ecc_verify(const byte *key, uint32_t keySz,
}
/* perform signature operation against hash using private key */
static wc_test_ret_t crypto_ecc_sign(const byte *key, uint32_t keySz,
const byte *hash, uint32_t hashSz, byte *sig, uint32_t* sigSz,
uint32_t curveSz, int curveId, WC_RNG* rng)
static wc_test_ret_t crypto_ecc_sign(const byte *key, word32 keySz,
const byte *hash, word32 hashSz, byte *sig, word32* sigSz,
word32 curveSz, int curveId, WC_RNG* rng)
{
wc_test_ret_t ret;
int count = 0;

View File

@@ -35,7 +35,7 @@
struct XmssKey {
unsigned char pk[XMSS_SHA256_PUBLEN];
uint32_t oid;
word32 oid;
int is_xmssmt;
xmss_params params;
#ifndef WOLFSSL_XMSS_VERIFY_ONLY

View File

@@ -470,67 +470,143 @@ enum {
#ifdef WORD64_AVAILABLE
#define WC_MAX_UINT_OF(x) \
((((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - \
(word64)1)) - (word64)1) \
| \
((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - (word64)1)))
((x)((((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - \
(word64)1)) - (word64)1) \
| \
((word64)1 << \
((sizeof(x) * (word64)CHAR_BIT) - (word64)1))))
#define WC_MAX_SINT_OF(x) \
((sword64)((((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - \
(word64)2)) - (word64)1) \
| \
((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - \
(word64)2))))
#define WC_MIN_SINT_OF(x) \
((sword64)((word64)1 << ((sizeof(x) * (word64)CHAR_BIT) - \
(word64)1)))
((x)((sword64)((((word64)1 << \
((sizeof(x) * (word64)CHAR_BIT) - \
(word64)2)) - (word64)1) \
| \
((word64)1 << \
((sizeof(x) * (word64)CHAR_BIT) - \
(word64)2)))))
#else
#define WC_MAX_UINT_OF(x) \
((((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - \
(word32)1)) - (word32)1) \
| \
((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - (word32)1)))
((x)((((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - \
(word32)1)) - (word32)1) \
| \
((word32)1 << \
((sizeof(x) * (word32)CHAR_BIT) - (word32)1))))
#define WC_MAX_SINT_OF(x) \
((sword32)((((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - \
(word32)2)) - (word32)1) \
| \
((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - \
(word32)2))))
#define WC_MIN_SINT_OF(x) \
((sword32)((word32)1 << ((sizeof(x) * (word32)CHAR_BIT) - \
(word32)1)))
((x)((sword32)((((word32)1 << \
((sizeof(x) * (word32)CHAR_BIT) - \
(word32)2)) - (word32)1) \
| \
((word32)1 << \
((sizeof(x) * (word32)CHAR_BIT) - \
(word32)2)))))
#endif
#define WC_MIN_SINT_OF(x) (-WC_MAX_SINT_OF(x) - 1)
#define WC_SAFE_SUM_UNSIGNED_NO_WUR(type, in1, in2, out) \
/* The _CLIP variants of the safe arithmetic macros always store a value to out,
* but if the result is too large to represent in the type, out is set to the
* largest representable value with same sign as the actual result ("clipped").
*
* The non-_CLIP variants do not store a value if the result can't be accurately
* represented, and their return values must be checked.
*
* Both _CLIP and non-_CLIP macros return 1 if the result could be represented
* by the type, and 0 if not.
*/
#define WC_SAFE_SUM_UNSIGNED_CLIP(type, in1, in2, out) \
((in2) <= (WC_MAX_UINT_OF(type) - (in1)) ? \
((out) = (in1) + (in2), 1) : \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
((out) = WC_MAX_UINT_OF(type), 0))
#define WC_SAFE_SUM_UNSIGNED(type, in1, in2, out) \
WC_WUR_INT(WC_SAFE_SUM_UNSIGNED_NO_WUR(type, in1, in2, out))
#define WC_SAFE_SUB_UNSIGNED_CLIP(type, in1, in2, out) \
((in2) <= (in1) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_UNDERFLOW] */ 1) : \
((out) = 0, 0))
#define WC_SAFE_SUM_UNSIGNED(type, in1, in2, out) WC_WUR_INT( \
((in2) <= (WC_MAX_UINT_OF(type) - (in1)) ? \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
0))
#define WC_SAFE_SUB_UNSIGNED(type, in1, in2, out) WC_WUR_INT( \
((in2) <= (in1) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_UNDERFLOW] */ 1) : \
0))
#if defined(HAVE_SELFTEST) || (defined(HAVE_FIPS) && FIPS_VERSION3_LE(6,0,0))
#define WC_SAFE_SUM_WORD32(in1, in2, out) \
WC_SAFE_SUM_UNSIGNED_NO_WUR(word32, in1, in2, out)
WC_SAFE_SUM_UNSIGNED_CLIP(word32, in1, in2, out)
#else
#define WC_SAFE_SUM_WORD32(in1, in2, out) \
WC_SAFE_SUM_UNSIGNED(word32, in1, in2, out)
#endif
#define WC_SAFE_SUM_SIGNED_NO_WUR(type, in1, in2, out) \
#define WC_SAFE_SUM_SIGNED_CLIP(type, in1, in2, out) \
((((in1) > 0) && ((in2) > 0)) ? \
((in2) <= WC_MAX_SINT_OF(type) - (in1) ? \
((out) = (in1) + (in2), 1) : \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
((out) = (type)WC_MAX_SINT_OF(type), 0)) \
: \
((((in1) < 0) && ((in2) < 0)) ? \
((in2) >= WC_MIN_SINT_OF(type) - (in1) ? \
((out) = (in1) + (in2), 1) : \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
((out) = (type)WC_MIN_SINT_OF(type), 0)) \
: \
((out) = (in1) + (in2), 1)))
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1)))
#define WC_SAFE_SUM_SIGNED(type, in1, in2, out) \
WC_WUR_INT(WC_SAFE_SUM_SIGNED_NO_WUR(type, in1, in2, out))
#define WC_SAFE_SUB_SIGNED_CLIP(type, in1, in2, out) \
((((in1) > 0) && ((in2) < 0)) ? \
((in2) >= (in1) - WC_MAX_SINT_OF(type) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
((out) = (type)WC_MAX_SINT_OF(type), 0)) \
: \
((((in1) < 0) && ((in2) > 0)) ? \
((in2) <= (in1) - WC_MIN_SINT_OF(type) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
((out) = (type)WC_MIN_SINT_OF(type), 0)) \
: \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1)))
#define WC_SAFE_SUM_SIGNED(type, in1, in2, out) WC_WUR_INT( \
((((in1) > 0) && ((in2) > 0)) ? \
((in2) <= WC_MAX_SINT_OF(type) - (in1) ? \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
0) \
: \
((((in1) < 0) && ((in2) < 0)) ? \
((in2) >= WC_MIN_SINT_OF(type) - (in1) ? \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
0) \
: \
((out) = (in1) + (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1))))
#define WC_SAFE_SUB_SIGNED(type, in1, in2, out) WC_WUR_INT( \
((((in1) > 0) && ((in2) < 0)) ? \
((in2) >= (in1) - WC_MAX_SINT_OF(type) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
0) \
: \
((((in1) < 0) && ((in2) > 0)) ? \
((in2) <= (in1) - WC_MIN_SINT_OF(type) ? \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1) : \
0) \
: \
((out) = (in1) - (in2), \
/* coverity[INTEGER_OVERFLOW] */ 1))))
#if defined(HAVE_IO_POOL)
WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type);