Tests api.c: rework for malloc failure testing

Modified number of tests to not crash on failure and cleanup allocations
on failure.
Added memory fail count option to set which memory allocation to start
failing on.
Fix issues found from testing.

bio.c:
BIO_new() move ref count up so that calls to wolfSSL_BIO_free()
work.
internal.c:
ImportCipherSpecState wasn't checking SetKeySide for failure. Crash
when pointer is NULL and accessed directly.
ocsp.c:
wolfSSL_OCSP_response_get1_basic() doesn't need to free vs->source
as it is freed in WOLFSSL_OCSP_RESPONSE_free().
ssl.c:
ProcessBuffer() Don't strip PKCS#8 header if failed to create DER.
Crasged as directly accessing 'der' which was NULL.
ssl_asn.c:
wolfssl_asn1_integer_require_len was checking wrong variable to see
if allocation failed.
x509,c:
wolfSSL_X509_ALGOR_set0 needs to set aobj only when no failure
possible.
wolfSSL_X509_chain_up_ref needs to call cleanup to ensure everything
is freed.
This commit is contained in:
Sean Parkinson
2023-05-26 15:49:14 +10:00
parent 37c03e3f11
commit 541ea51ad5
14 changed files with 3888 additions and 3252 deletions

View File

@ -2481,6 +2481,23 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
bio->shutdown = BIO_CLOSE; /* default to close things */
bio->num = WOLFSSL_BIO_ERROR;
bio->init = 1;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
{
int ret;
wolfSSL_RefInit(&bio->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret != 0) {
wolfSSL_BIO_free(bio);
WOLFSSL_MSG("wc_InitMutex failed for WOLFSSL_BIO");
return NULL;
}
#else
(void)ret;
#endif
}
#endif
if (method->type == WOLFSSL_BIO_MEMORY)
bio->eof = WOLFSSL_BIO_ERROR; /* Return value for empty buffer */
if (method->type == WOLFSSL_BIO_MEMORY ||
@ -2507,22 +2524,6 @@ int wolfSSL_BIO_flush(WOLFSSL_BIO* bio)
method->createCb(bio);
}
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
{
int ret;
wolfSSL_RefInit(&bio->ref, &ret);
#ifdef WOLFSSL_REFCNT_ERROR_RETURN
if (ret != 0) {
wolfSSL_BIO_free(bio);
WOLFSSL_MSG("wc_InitMutex failed for WOLFSSL_BIO");
return NULL;
}
#else
(void)ret;
#endif
}
#endif
}
return bio;
}

View File

@ -913,6 +913,7 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len,
word32 tmp_seq_peer_hi;
word32 tmp_seq_lo;
word32 tmp_seq_hi;
int ret;
WOLFSSL_ENTER("ImportCipherSpecState");
@ -951,7 +952,9 @@ static int ImportCipherSpecState(WOLFSSL* ssl, const byte* exp, word32 len,
tmp_seq_lo = ssl->keys.sequence_number_lo;
tmp_seq_hi = ssl->keys.sequence_number_hi;
SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) < 0) {
return ret;
}
/* reset sequence numbers after setting keys */
ssl->keys.peer_sequence_number_lo = tmp_seq_peer_lo;

View File

@ -938,8 +938,10 @@ WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response)
DYNAMIC_TYPE_OCSP_ENTRY);
bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (bs->single == NULL || bs->source == NULL) {
if (bs->single) XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (bs->single) {
XFREE(bs->single, NULL, DYNAMIC_TYPE_OCSP_ENTRY);
bs->single = NULL;
}
wolfSSL_OCSP_RESPONSE_free(bs);
bs = NULL;
}

View File

@ -7365,7 +7365,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
#ifdef HAVE_PKCS8
/* if private key try and remove PKCS8 header */
if (type == PRIVATEKEY_TYPE) {
if (ret == 0 && type == PRIVATEKEY_TYPE) {
if ((ret = ToTraditional_ex(der->buffer, der->length,
&algId)) > 0) {
/* Found PKCS8 header */
@ -8013,7 +8013,10 @@ static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff,
ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl,
&consumed, 0, verify);
if (ret < 0) {
if (ret == MEMORY_E) {
return ret;
}
else if (ret < 0) {
#if defined(WOLFSSL_WPAS) && defined(HAVE_CRL)
DerBuffer* der = NULL;
EncryptedInfo info;
@ -38466,7 +38469,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY);
}
if (certData != NULL) {
XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
}
/* Free up WC_DerCertList and move on */
while (current != NULL) {
@ -38580,6 +38583,7 @@ int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
wolfSSL_sk_X509_pop_free(*ca, NULL); *ca = NULL;
}
wolfSSL_X509_free(*cert); *cert = NULL;
XFREE(certData, heap, DYNAMIC_TYPE_PKCS);
ret = WOLFSSL_FAILURE;
goto out;
}

View File

@ -623,7 +623,7 @@ static int wolfssl_asn1_integer_require_len(WOLFSSL_ASN1_INTEGER* a, int len,
if ((!a->isDynamic) && (len > (int)a->dataMax)) {
/* Create a new buffer to hold large integer value. */
data = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL);
if (a->data == NULL) {
if (data == NULL) {
ret = 0;
}
else {

View File

@ -9007,9 +9007,6 @@ int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj
if (!algor) {
return WOLFSSL_FAILURE;
}
if (aobj) {
algor->algorithm = aobj;
}
if (!algor->parameter) {
algor->parameter = wolfSSL_ASN1_TYPE_new();
@ -9018,6 +9015,9 @@ int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj
}
}
if (aobj) {
algor->algorithm = aobj;
}
wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval);
return WOLFSSL_SUCCESS;
@ -9991,8 +9991,8 @@ WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_chain_up_ref(
{
ret = wc_InitRng(&rng);
if (ret != 0) {
XFREE(cert, NULL, DYNAMIC_TYPE_CERT);
return WOLFSSL_FAILURE;
ret = WOLFSSL_FAILURE;
goto cleanup;
}
ret = wc_MakeCert_ex(cert, der, *derSz, type, key, &rng);

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,7 @@
int allTesting = 1;
int apiTesting = 1;
int myoptind = 0;
char* myoptarg = NULL;
int unit_test(int argc, char** argv);
@ -185,21 +186,26 @@ int unit_test(int argc, char** argv)
goto exit;
}
else if (XSTRCMP(argv[1], "--api") == 0) {
allTesting = 0;
}
else if (XSTRCMP(argv[1], "--no-api") == 0) {
apiTesting = 0;
}
else if (argv[1][1] >= '0' && argv[1][1] <= '9') {
ret = ApiTest_RunIdx(atoi(argv[1] + 1));
if (ret != 0) {
goto exit;
}
allTesting = 0;
}
else {
ret = ApiTest_RunName(argv[1] + 1);
if (ret != 0) {
goto exit;
}
allTesting = 0;
}
allTesting = 0;
argc--;
argv++;
}
@ -208,7 +214,11 @@ int unit_test(int argc, char** argv)
if (argc == 1)
#endif
{
ApiTest();
if (apiTesting) {
ret = ApiTest();
if (ret != 0)
goto exit;
}
if (!allTesting) {
goto exit;

View File

@ -122,10 +122,111 @@
#define AssertPtrLE(x, y) AssertPtr(x, y, <=, >)
#define EXPECT_DECLS \
int _ret = 0
#define EXPECT_RESULT() \
((_ret == 0) ? TEST_SUCCESS : TEST_FAIL)
#define EXPECT_SUCCESS() \
(_ret == 0)
#define EXPECT_FAIL() \
(_ret != 0)
#define ExpFail(description, result) do { \
printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \
fputs("\n expected: ", stdout); printf description; \
fputs("\n result: ", stdout); printf result; fputs("\n\n", stdout); \
fflush(stdout); \
_ret = -1; \
} while (0)
#define Expect(test, description, result) \
if ((_ret == 0) && (!(test))) ExpFail(description, result)
#define ExpectTrue(x) Expect( (x), ("%s is true", #x), (#x " => FALSE"))
#define ExpectFalse(x) Expect(!(x), ("%s is false", #x), (#x " => TRUE"))
#define ExpectNotNull(x) Expect( (x), ("%s is not null", #x), (#x " => NULL"))
#define ExpectNull(x) do { \
if (_ret == 0) { \
PEDANTIC_EXTENSION void* _x = (void*)(x); \
Expect(!_x, ("%s is null", #x), (#x " => %p", _x)); \
} \
} while(0)
#define ExpectInt(x, y, op, er) do { \
if (_ret == 0) { \
int _x = (int)(x); \
int _y = (int)(y); \
Expect(_x op _y, ("%s " #op " %s", #x, #y), ("%d " #er " %d", _x, _y));\
} \
} while(0)
#define ExpectIntEQ(x, y) ExpectInt(x, y, ==, !=)
#define ExpectIntNE(x, y) ExpectInt(x, y, !=, ==)
#define ExpectIntGT(x, y) ExpectInt(x, y, >, <=)
#define ExpectIntLT(x, y) ExpectInt(x, y, <, >=)
#define ExpectIntGE(x, y) ExpectInt(x, y, >=, <)
#define ExpectIntLE(x, y) ExpectInt(x, y, <=, >)
#define ExpectStr(x, y, op, er) do { \
if (_ret == 0) { \
const char* _x = (const char*)(x); \
const char* _y = (const char*)(y); \
int _z = (_x && _y) ? strcmp(_x, _y) : -1; \
Expect(_z op 0, ("%s " #op " %s", #x, #y), \
("\"%s\" " #er " \"%s\"", _x, _y));\
} \
} while(0)
#define ExpectStrEQ(x, y) ExpectStr(x, y, ==, !=)
#define ExpectStrNE(x, y) ExpectStr(x, y, !=, ==)
#define ExpectStrGT(x, y) ExpectStr(x, y, >, <=)
#define ExpectStrLT(x, y) ExpectStr(x, y, <, >=)
#define ExpectStrGE(x, y) ExpectStr(x, y, >=, <)
#define ExpectStrLE(x, y) ExpectStr(x, y, <=, >)
#define ExpectPtr(x, y, op, er) do { \
if (_ret == 0) { \
PRAGMA_GCC_DIAG_PUSH; \
/* remarkably, without this inhibition, */ \
/* the _Pragma()s make the declarations warn. */ \
PRAGMA_GCC("GCC diagnostic ignored \"-Wdeclaration-after-statement\"");\
/* inhibit "ISO C forbids conversion of function pointer */ \
/* to object pointer type [-Werror=pedantic]" */ \
PRAGMA_GCC("GCC diagnostic ignored \"-Wpedantic\""); \
void* _x = (void*)(x); \
void* _y = (void*)(y); \
Expect(_x op _y, ("%s " #op " %s", #x, #y), ("%p " #er " %p", _x, _y));\
PRAGMA_GCC_DIAG_POP; \
} \
} while(0)
#define ExpectPtrEq(x, y) ExpectPtr(x, y, ==, !=)
#define ExpectPtrNE(x, y) ExpectPtr(x, y, !=, ==)
#define ExpectPtrGT(x, y) ExpectPtr(x, y, >, <=)
#define ExpectPtrLT(x, y) ExpectPtr(x, y, <, >=)
#define ExpectPtrGE(x, y) ExpectPtr(x, y, >=, <)
#define ExpectPtrLE(x, y) ExpectPtr(x, y, <=, >)
#define ExpectBuf(x, y, z, op, er) do { \
if (_ret == 0) { \
const byte* _x = (const byte*)(x); \
const byte* _y = (const byte*)(y); \
int _z = (int)(z); \
int _w = ((_x) && (_y)) ? XMEMCMP(_x, _y, _z) : -1; \
Expect(_w op 0, ("%s " #op " %s for %s", #x, #y, #z), \
("\"%p\" " #er " \"%p\" for \"%d\"", _x, _y, _z));\
} \
} while(0)
#define ExpectBufEQ(x, y, z) ExpectBuf(x, y, z, ==, !=)
#define ExpectBufNE(x, y, z) ExpectBuf(x, y, z, !=, ==)
void ApiTest_PrintTestCases(void);
int ApiTest_RunIdx(int idx);
int ApiTest_RunName(char* name);
void ApiTest(void);
int ApiTest(void);
int SuiteTest(int argc, char** argv);
int HashTest(void);

View File

@ -15390,15 +15390,18 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey),
sigCtx->heap, DYNAMIC_TYPE_RSA);
sigCtx->sigCpy = (byte*)XMALLOC(sigSz, sigCtx->heap,
DYNAMIC_TYPE_SIGNATURE);
if (sigCtx->key.rsa == NULL || sigCtx->sigCpy == NULL) {
if (sigCtx->key.rsa == NULL) {
ERROR_OUT(MEMORY_E, exit_cs);
}
if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap,
sigCtx->devId)) != 0) {
goto exit_cs;
}
sigCtx->sigCpy = (byte*)XMALLOC(sigSz, sigCtx->heap,
DYNAMIC_TYPE_SIGNATURE);
if (sigCtx->sigCpy == NULL) {
ERROR_OUT(MEMORY_E, exit_cs);
}
if (sigSz > MAX_ENCODED_SIG_SZ) {
WOLFSSL_MSG("Verify Signature is too big");
ERROR_OUT(BUFFER_E, exit_cs);

View File

@ -24,10 +24,6 @@
#include <config.h>
#endif
#ifdef WOLFSSL_LINUXKM
#define WOLFSSL_NEED_LINUX_CURRENT
#endif
#include <wolfssl/wolfcrypt/settings.h>
/* check old macros @wc_fips */
@ -55,6 +51,8 @@ Possible memory options:
* WOLFSSL_MALLOC_CHECK: Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN
* WOLFSSL_FORCE_MALLOC_FAIL_TEST: Used for internal testing to induce random malloc failures.
* WOLFSSL_HEAP_TEST: Used for internal testing of heap hint
* WOLFSSL_MEM_FAIL_COUNT: Fail memory allocation at a count from
* environment variable: MEM_FAIL_CNT.
*/
#ifdef WOLFSSL_ZEPHYR
@ -264,6 +262,50 @@ void wc_MemZero_Check(void* addr, size_t len)
}
#endif /* WOLFSSL_CHECK_MEM_ZERO */
#ifdef WOLFSSL_MEM_FAIL_COUNT
static wolfSSL_Mutex memFailMutex;
int mem_fail_allocs = 0;
int mem_fail_frees = 0;
int mem_fail_cnt = 0;
void wc_MemFailCount_Init()
{
wc_InitMutex(&memFailMutex);
char* cnt = getenv("MEM_FAIL_CNT");
if (cnt != NULL) {
fprintf(stderr, "MemFailCount At: %d\n", mem_fail_cnt);
mem_fail_cnt = atoi(cnt);
}
}
static int wc_MemFailCount_AllocMem(void)
{
int ret = 1;
wc_LockMutex(&memFailMutex);
if ((mem_fail_cnt > 0) && (mem_fail_cnt <= mem_fail_allocs + 1)) {
ret = 0;
}
else {
mem_fail_allocs++;
}
wc_UnLockMutex(&memFailMutex);
return ret;
}
static void wc_MemFailCount_FreeMem(void)
{
wc_LockMutex(&memFailMutex);
mem_fail_frees++;
wc_UnLockMutex(&memFailMutex);
}
void wc_MemFailCount_Free()
{
wc_FreeMutex(&memFailMutex);
fprintf(stderr, "MemFailCount Total: %d\n", mem_fail_allocs);
fprintf(stderr, "MemFailCount Frees: %d\n", mem_fail_frees);
}
#endif
#ifdef WOLFSSL_DEBUG_MEMORY
void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line)
#else
@ -272,6 +314,13 @@ void* wolfSSL_Malloc(size_t size)
{
void* res = 0;
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (!wc_MemFailCount_AllocMem()) {
WOLFSSL_MSG("MemFailCnt: Fail malloc");
return NULL;
}
#endif
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Space for requested size. */
size += MEM_ALIGN;
@ -365,6 +414,9 @@ void wolfSSL_Free(void *ptr)
/* Check that the pointer is zero where required. */
wc_MemZero_Check(((unsigned char*)ptr) + MEM_ALIGN, *(size_t*)ptr);
#endif
#ifdef WOLFSSL_MEM_FAIL_COUNT
wc_MemFailCount_FreeMem();
#endif
if (free_function) {
#ifdef WOLFSSL_DEBUG_MEMORY
@ -417,6 +469,13 @@ void* wolfSSL_Realloc(void *ptr, size_t size)
#else
void* res = 0;
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (!wc_MemFailCount_AllocMem()) {
WOLFSSL_MSG("MemFailCnt: Fail realloc");
return NULL;
}
#endif
if (realloc_function) {
#ifdef WOLFSSL_DEBUG_MEMORY
res = realloc_function(ptr, size, func, line);
@ -432,6 +491,12 @@ void* wolfSSL_Realloc(void *ptr, size_t size)
#endif
}
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (ptr != NULL) {
wc_MemFailCount_FreeMem();
}
#endif
return res;
#endif
}
@ -1245,6 +1310,13 @@ void *xmalloc(size_t n, void* heap, int type, const char* func,
void* p = NULL;
word32* p32;
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (!wc_MemFailCount_AllocMem()) {
WOLFSSL_MSG("MemFailCnt: Fail malloc");
return NULL;
}
#endif
if (malloc_function)
p32 = malloc_function(n + sizeof(word32) * 4);
else
@ -1270,6 +1342,13 @@ void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
word32* oldp32 = NULL;
word32 oldLen;
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (!wc_MemFailCount_AllocMem()) {
WOLFSSL_MSG("MemFailCnt: Fail malloc");
return NULL;
}
#endif
if (p != NULL) {
oldp32 = (word32*)p;
oldp32 -= 4;
@ -1293,6 +1372,12 @@ void *xrealloc(void *p, size_t n, void* heap, int type, const char* func,
type, func, file, line);
}
#ifdef WOLFSSL_MEM_FAIL_COUNT
if (p != NULL) {
wc_MemFailCount_FreeMem();
}
#endif
(void)heap;
return newp;
@ -1303,6 +1388,9 @@ void xfree(void *p, void* heap, int type, const char* func, const char* file,
word32* p32 = (word32*)p;
if (p != NULL) {
#ifdef WOLFSSL_MEM_FAIL_COUNT
wc_MemFailCount_FreeMem();
#endif
p32 -= 4;
fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%u\n", p, p32[0], type,

View File

@ -144,6 +144,9 @@ int wolfCrypt_Init(void)
* must be freed. */
wc_MemZero_Init();
#endif
#ifdef WOLFSSL_MEM_FAIL_COUNT
wc_MemFailCount_Init();
#endif
#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST
{
@ -474,6 +477,9 @@ int wolfCrypt_Cleanup(void)
Entropy_Final();
#endif
#ifdef WOLFSSL_MEM_FAIL_COUNT
wc_MemFailCount_Free();
#endif
#ifdef WOLFSSL_CHECK_MEM_ZERO
/* Free the mutex for access to the list of memory locations that
* must be freed. */

View File

@ -2930,12 +2930,13 @@ static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store)
wolfSSL_X509_get_subject_name(peer), 0, 0);
printf("\tPeer's cert info:\n issuer : %s\n subject: %s\n", issuer,
subject);
#if defined(OPENSSL_ALL) || defined(WOLFSSL_QT)
/* preverify needs to be self-signer error for Qt compat.
* Should be ASN_SELF_SIGNED_E */
if (XSTRCMP(issuer, subject) == 0 && preverify == ASN_NO_SIGNER_E)
return 0;
if (issuer != NULL && subject != NULL) {
/* preverify needs to be self-signer error for Qt compat.
* Should be ASN_SELF_SIGNED_E */
if (XSTRCMP(issuer, subject) == 0 && preverify == ASN_NO_SIGNER_E)
return 0;
}
#endif
XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL);

View File

@ -238,6 +238,11 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf,
__cyg_profile_func_exit(void *func, void *caller);
#endif /* WOLFSSL_STACK_LOG */
#ifdef WOLFSSL_MEM_FAIL_COUNT
WOLFSSL_LOCAL void wc_MemFailCount_Init(void);
WOLFSSL_LOCAL void wc_MemFailCount_Free(void);
#endif
#ifdef WOLFSSL_CHECK_MEM_ZERO
WOLFSSL_LOCAL void wc_MemZero_Init(void);
WOLFSSL_LOCAL void wc_MemZero_Free(void);