From f9506dc05a351a84f3b8d035c9e1cba46768e234 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 30 Sep 2022 13:53:10 -0700 Subject: [PATCH 1/3] Add small stack to DoClientHello Suites (360 bytes). Add small stack for DRBG health test. Refactor of the small stack into its own header, to allow easier use in other files. Minor build fixes. --- src/internal.c | 56 +- tests/api.c | 6 +- wolfcrypt/benchmark/benchmark.c | 58 +- wolfcrypt/src/asn.c | 17 +- wolfcrypt/src/integer.c | 4 +- wolfcrypt/src/logging.c | 7 + wolfcrypt/src/random.c | 177 ++++-- wolfcrypt/test/test.c | 14 +- wolfssl/test.h | 407 +----------- wolfssl/wolfcrypt/mem_track.h | 1020 +++++++++++++++++++++---------- wolfssl/wolfcrypt/random.h | 2 +- wolfssl/wolfcrypt/types.h | 51 ++ 12 files changed, 960 insertions(+), 859 deletions(-) diff --git a/src/internal.c b/src/internal.c index 7cce86cf6..aef649c80 100644 --- a/src/internal.c +++ b/src/internal.c @@ -32701,7 +32701,11 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, byte b; byte bogusID = 0; /* flag for a bogus session id */ ProtocolVersion pv; - Suites clSuites; +#ifdef WOLFSSL_SMALL_STACK + Suites* clSuites = NULL; +#else + Suites clSuites[1]; +#endif word32 i = *inOutIdx; word32 begin = i; int ret = 0; @@ -33019,31 +33023,40 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto out; } - ato16(&input[i], &clSuites.suiteSz); +#ifdef WOLFSSL_SMALL_STACK + clSuites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (clSuites == NULL) { + ret = MEMORY_E; + goto out; + } +#endif + XMEMSET(clSuites, 0, sizeof(Suites)); + ato16(&input[i], &clSuites->suiteSz); i += OPAQUE16_LEN; /* Cipher suite lists are always multiples of two in length. */ - if (clSuites.suiteSz % 2 != 0) { + if (clSuites->suiteSz % 2 != 0) { ret = BUFFER_ERROR; goto out; } /* suites and compression length check */ - if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) { + if ((i - begin) + clSuites->suiteSz + OPAQUE8_LEN > helloSz) { ret = BUFFER_ERROR; goto out; } - if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) { + if (clSuites->suiteSz > WOLFSSL_MAX_SUITE_SZ) { ret = BUFFER_ERROR; goto out; } - XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + XMEMCPY(clSuites->suites, input + i, clSuites->suiteSz); #ifdef HAVE_SERVER_RENEGOTIATION_INFO /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ - if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) { + if (FindSuite(clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) { TLSX* extension; /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ @@ -33061,7 +33074,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #endif /* HAVE_SERVER_RENEGOTIATION_INFO */ #if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL) /* check for TLS_FALLBACK_SCSV suite */ - if (FindSuite(&clSuites, TLS_FALLBACK_SCSV, 0) >= 0) { + if (FindSuite(clSuites, TLS_FALLBACK_SCSV, 0) >= 0) { WOLFSSL_MSG("Found Fallback SCSV"); if (ssl->ctx->method->version.minor > pv.minor) { WOLFSSL_MSG("Client trying to connect with lesser version"); @@ -33076,12 +33089,12 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (IsDtlsNotSctpMode(ssl) && IsDtlsNotSrtpMode(ssl) && !IsSCR(ssl)) { ret = wc_HmacUpdate(&cookieHmac, input + i - OPAQUE16_LEN, - clSuites.suiteSz + OPAQUE16_LEN); + clSuites->suiteSz + OPAQUE16_LEN); if (ret != 0) goto out; } #endif /* WOLFSSL_DTLS */ - i += clSuites.suiteSz; - clSuites.hashSigAlgoSz = 0; + i += clSuites->suiteSz; + clSuites->hashSigAlgoSz = 0; /* compression length */ b = input[i++]; @@ -33200,7 +33213,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef HAVE_TLS_EXTENSIONS /* tls extensions */ if ((ret = TLSX_Parse(ssl, input + i, totalExtSz, client_hello, - &clSuites))) + clSuites))) goto out; #ifdef WOLFSSL_TLS13 if (TLSX_Find(ssl->extensions, @@ -33252,15 +33265,15 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, goto out; } - clSuites.hashSigAlgoSz = hashSigAlgoSz; - if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + clSuites->hashSigAlgoSz = hashSigAlgoSz; + if (clSuites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, " "truncating"); - clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + clSuites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; } - XMEMCPY(clSuites.hashSigAlgo, &input[i], - clSuites.hashSigAlgoSz); + XMEMCPY(clSuites->hashSigAlgo, &input[i], + clSuites->hashSigAlgoSz); i += hashSigAlgoSz; } @@ -33290,7 +33303,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, /* ProcessOld uses same resume code */ if (ssl->options.resuming) { - ret = HandleTlsResumption(ssl, bogusID, &clSuites); + ret = HandleTlsResumption(ssl, bogusID, clSuites); if (ret != 0) goto out; @@ -33345,7 +33358,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, ret = CertSetupCbWrapper(ssl); #endif if (ret == 0) - ret = MatchSuite(ssl, &clSuites); + ret = MatchSuite(ssl, clSuites); #ifdef WOLFSSL_EXTRA_ALERTS if (ret == BUFFER_ERROR) @@ -33373,7 +33386,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, #ifdef WOLFSSL_DTLS wc_HmacFree(&cookieHmac); #endif - +#ifdef WOLFSSL_SMALL_STACK + if (clSuites != NULL) + XFREE(clSuites, ssl->heap, DYNAMIC_TYPE_SUITES); +#endif WOLFSSL_LEAVE("DoClientHello", ret); WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); diff --git a/tests/api.c b/tests/api.c index 7e13a379f..07f6d0ef4 100644 --- a/tests/api.c +++ b/tests/api.c @@ -50514,7 +50514,7 @@ static int test_tls13_apis(void) #ifndef NO_WOLFSSL_SERVER WOLFSSL_CTX* serverCtx; WOLFSSL* serverSsl; -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM) const char* ourCert = svrCertFile; const char* ourKey = svrKeyFile; #endif @@ -50575,7 +50575,7 @@ static int test_tls13_apis(void) #endif #ifndef NO_WOLFSSL_SERVER serverTls12Ctx = wolfSSL_CTX_new(wolfTLSv1_2_server_method()); -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM) wolfSSL_CTX_use_certificate_chain_file(serverTls12Ctx, ourCert); wolfSSL_CTX_use_PrivateKey_file(serverTls12Ctx, ourKey, WOLFSSL_FILETYPE_PEM); #endif @@ -50589,7 +50589,7 @@ static int test_tls13_apis(void) #endif #ifndef NO_WOLFSSL_SERVER serverCtx = wolfSSL_CTX_new(wolfTLSv1_3_server_method()); -#ifndef NO_CERTS +#if !defined(NO_CERTS) && !defined(NO_FILESYSTEM) wolfSSL_CTX_use_certificate_chain_file(serverCtx, ourCert); wolfSSL_CTX_use_PrivateKey_file(serverCtx, ourKey, WOLFSSL_FILETYPE_PEM); #endif diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index ed91473f0..1ff29d5ea 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -52,60 +52,13 @@ /* Macro to disable benchmark */ #ifndef NO_CRYPT_BENCHMARK -/* only for stack size check */ -#ifdef HAVE_STACK_SIZE - #include - #include +#include -#elif defined(WOLFSSL_ASYNC_CRYPT) +/* only for stack size check */ +#if defined(WOLFSSL_ASYNC_CRYPT) #ifndef WC_NO_ASYNC_THREADING #define WC_ENABLE_BENCH_THREADING #endif - -/* benchmark multi-threading - disable for FIPS self test */ -#elif !defined(SINGLE_THREADED) && !defined(WC_NO_BENCH_THREADING) && \ - defined(HAVE_PTHREAD) && !defined(HAVE_RENESAS_SYNC) - - #define WC_ENABLE_BENCH_THREADING - #if defined(_POSIX_THREADS) - typedef void* THREAD_RETURN; - typedef pthread_t THREAD_TYPE; - #define WOLFSSL_THREAD - #if !defined(__MINGW32__) - #define INFINITE (-1) - #define WAIT_OBJECT_0 0L - #endif - #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) || defined(FREESCALE_MQX) - typedef unsigned int THREAD_RETURN; - typedef int THREAD_TYPE; - #define WOLFSSL_THREAD - #elif defined(WOLFSSL_TIRTOS) - typedef void THREAD_RETURN; - typedef Task_Handle THREAD_TYPE; - #ifdef HAVE_STACK_SIZE - #undef EXIT_TEST - #define EXIT_TEST(ret) - #endif - #define WOLFSSL_THREAD - #elif defined(WOLFSSL_ZEPHYR) - typedef void THREAD_RETURN; - typedef struct k_thread THREAD_TYPE; - #ifdef HAVE_STACK_SIZE - #undef EXIT_TEST - #define EXIT_TEST(ret) - #endif - #define WOLFSSL_THREAD - #elif defined(NETOS) - typedef UINT THREAD_RETURN; - typedef TX_THREAD THREAD_TYPE; - #define WOLFSSL_THREAD - #define INFINITE TX_WAIT_FOREVER - #define WAIT_OBJECT_0 TX_NO_WAIT - #else - typedef unsigned int THREAD_RETURN; - typedef intptr_t THREAD_TYPE; - #define WOLFSSL_THREAD __stdcall - #endif #endif #ifdef USE_FLAT_BENCHMARK_H @@ -1079,10 +1032,9 @@ static const char* bench_desc_words[][15] = { #pragma warning(disable: 4996) #endif - #ifdef WOLFSSL_CURRTIME_REMAP #define current_time WOLFSSL_CURRTIME_REMAP -#elif !defined(HAVE_STACK_SIZE) +#else double current_time(int reset); #endif @@ -8100,7 +8052,6 @@ void bench_sphincsKeySign(byte level, byte optim) #endif /* HAVE_SPHINCS */ #endif /* HAVE_PQC */ -#ifndef HAVE_STACK_SIZE #if defined(_WIN32) && !defined(INTIME_RTOS) #define WIN32_LEAN_AND_MEAN @@ -8315,7 +8266,6 @@ void bench_sphincsKeySign(byte level, byte optim) } #endif /* _WIN32 */ -#endif /* !HAVE_STACK_SIZE */ #if defined(HAVE_GET_CYCLES) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index d16da0882..53c540e49 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -13587,7 +13587,7 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) word32 localIdx; byte tag; - WOLFSSL_MSG("Getting Cert Name"); + WOLFSSL_MSG("Getting Name"); if (nameType == ISSUER) { full = cert->issuer; @@ -13634,7 +13634,7 @@ int GetName(DecodedCert* cert, int nameType, int maxIdx) char* full; byte* hash; - WOLFSSL_MSG("Getting Cert Name"); + WOLFSSL_MSG("Getting Name"); XMEMSET(dataASN, 0, sizeof(dataASN)); /* Initialize for data and don't check optional prefix OID. */ @@ -14008,9 +14008,9 @@ int wc_ValidateDate(const byte* date, byte format, int dateType) struct tm* localTime; struct tm* tmpTime; int i = 0; - int timeDiff = 0 ; - int diffHH = 0 ; int diffMM = 0 ; - int diffSign = 0 ; + int timeDiff = 0; + int diffHH = 0, diffMM = 0; + int diffSign = 0; #if defined(NEED_TMP_TIME) struct tm tmpTimeStorage; @@ -15345,6 +15345,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx, byte* rsaKeyIdx) { int ret = 0; +#if defined(WOLFSSL_RENESAS_TSIP_TLS) || defined(WOLFSSL_RENESAS_SCEPROTECT) + CertAttribute* certatt = NULL; +#endif if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || keySz == 0 || sig == NULL || sigSz == 0) { @@ -15363,12 +15366,10 @@ static int ConfirmSignature(SignatureCtx* sigCtx, #if !defined(WOLFSSL_RENESAS_TSIP_TLS) && !defined(WOLFSSL_RENESAS_SCEPROTECT) (void)rsaKeyIdx; #else - CertAttribute* certatt = NULL; - #if !defined(NO_RSA) || defined(HAVE_ECC) certatt = (CertAttribute*)&sigCtx->CertAtt; #endif - if(certatt) { + if (certatt) { certatt->keyIndex = rsaKeyIdx; certatt->cert = buf; certatt->certSz = bufSz; diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index f54d16da1..cb05fa4bf 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4667,7 +4667,7 @@ int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) #endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */ -#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) +#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA)) || !defined(NO_DH) || !defined(NO_DSA) const FLASH_QUALIFIER mp_digit ltm_prime_tab[PRIME_SIZE] = { 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, @@ -5018,7 +5018,7 @@ LBL_B:mp_clear (&b); return err; } -#endif /* WOLFSSL_KEY_GEN NO_DH NO_DSA NO_RSA */ +#endif /* (WOLFSSL_KEY_GEN && !NO_RSA) || !NO_DH || !NO_DSA */ #ifdef WOLFSSL_KEY_GEN diff --git a/wolfcrypt/src/logging.c b/wolfcrypt/src/logging.c index b002323c2..e5247b8f1 100644 --- a/wolfcrypt/src/logging.c +++ b/wolfcrypt/src/logging.c @@ -318,6 +318,10 @@ void WOLFSSL_TIME(int count) int dc_log_printf(char*, ...); #endif +#ifdef HAVE_STACK_SIZE_VERBOSE +#include +#endif + static void wolfssl_log(const int logLevel, const char *const logMessage) { if (log_function) @@ -359,6 +363,9 @@ static void wolfssl_log(const int logLevel, const char *const logMessage) printk("%s\n", logMessage); #elif defined(WOLFSSL_RENESAS_RA6M4) myprintf("%s\n", logMessage); +#elif defined(STACK_SIZE_CHECKPOINT_MSG) && \ + defined(HAVE_STACK_SIZE_VERBOSE) && defined(HAVE_STACK_SIZE_VERBOSE_LOG) + STACK_SIZE_CHECKPOINT_MSG(logMessage); #else fprintf(stderr, "%s\n", logMessage); #endif diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 26e830c52..fdb6de0f4 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -363,16 +363,19 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, #else wc_Sha256 sha[1]; #endif -#ifdef WC_ASYNC_ENABLE_SHA256 - WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); - if (digest == NULL) - return MEMORY_E; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; #else byte digest[WC_SHA256_DIGEST_SIZE]; #endif - (void)drbg; -#ifdef WC_ASYNC_ENABLE_SHA256 + if (drbg == NULL) { + return DRBG_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); if (digest == NULL) return DRBG_FAILURE; #endif @@ -431,8 +434,8 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, ForceZero(digest, WC_SHA256_DIGEST_SIZE); -#ifdef WC_ASYNC_ENABLE_SHA256 - WC_FREE_VAR(digest, drbg->heap); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); #endif return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; @@ -441,31 +444,44 @@ static int Hash_df(DRBG_internal* drbg, byte* out, word32 outSz, byte type, /* Returns: DRBG_SUCCESS or DRBG_FAILURE */ static int Hash_DRBG_Reseed(DRBG_internal* drbg, const byte* seed, word32 seedSz) { + int ret; +#ifdef WOLFSSL_SMALL_STACK + byte* newV; +#else byte newV[DRBG_SEED_LEN]; +#endif if (drbg == NULL) { return DRBG_FAILURE; } +#ifdef WOLFSSL_SMALL_STACK + newV = (byte*)XMALLOC(DRBG_SEED_LEN, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (newV == NULL) { + return MEMORY_E; + } +#endif XMEMSET(newV, 0, DRBG_SEED_LEN); - if (Hash_df(drbg, newV, sizeof(newV), drbgReseed, - drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) { - return DRBG_FAILURE; + ret = Hash_df(drbg, newV, DRBG_SEED_LEN, drbgReseed, + drbg->V, sizeof(drbg->V), seed, seedSz); + if (ret == DRBG_SUCCESS) { + XMEMCPY(drbg->V, newV, sizeof(drbg->V)); + ForceZero(newV, DRBG_SEED_LEN); + + ret = Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0); + } + if (ret == DRBG_SUCCESS) { + drbg->reseedCtr = 1; + drbg->lastBlock = 0; + drbg->matchCount = 0; } - XMEMCPY(drbg->V, newV, sizeof(drbg->V)); - ForceZero(newV, sizeof(newV)); - - if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, - sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) { - return DRBG_FAILURE; - } - - drbg->reseedCtr = 1; - drbg->lastBlock = 0; - drbg->matchCount = 0; - return DRBG_SUCCESS; +#ifdef WOLFSSL_SMALL_STACK + XFREE(newV, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } /* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */ @@ -491,9 +507,7 @@ int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) static WC_INLINE void array_add_one(byte* data, word32 dataSz) { int i; - - for (i = dataSz - 1; i >= 0; i--) - { + for (i = dataSz - 1; i >= 0; i--) { data[i]++; if (data[i] != 0) break; } @@ -503,7 +517,13 @@ static WC_INLINE void array_add_one(byte* data, word32 dataSz) static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) { int ret = DRBG_FAILURE; +#ifdef WOLFSSL_SMALL_STACK + byte* data; + byte* digest; +#else byte data[DRBG_SEED_LEN]; + byte digest[WC_SHA256_DIGEST_SIZE]; +#endif int i; int len; word32 checkBlock; @@ -512,22 +532,32 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) #else wc_Sha256 sha[1]; #endif -#ifdef WC_ASYNC_ENABLE_SHA256 - WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); - if (digest == NULL) - return MEMORY_E; -#else - byte digest[WC_SHA256_DIGEST_SIZE]; + + if (drbg == NULL) { + return DRBG_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + data = (byte*)XMALLOC(DRBG_SEED_LEN, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); + digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (data == NULL || digest == NULL) { + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); + return DRBG_FAILURE; + } #endif /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for * the continuous test. */ - if (outSz == 0) outSz = 1; + if (outSz == 0) { + outSz = 1; + } len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); - XMEMCPY(data, V, sizeof(data)); + XMEMCPY(data, V, DRBG_SEED_LEN); for (i = 0; i < len; i++) { #ifndef WOLFSSL_SMALL_STACK_CACHE #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) @@ -537,7 +567,7 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) #endif if (ret == 0) #endif - ret = wc_Sha256Update(sha, data, sizeof(data)); + ret = wc_Sha256Update(sha, data, DRBG_SEED_LEN); if (ret == 0) ret = wc_Sha256Final(sha, digest); #ifndef WOLFSSL_SMALL_STACK_CACHE @@ -580,10 +610,11 @@ static int Hash_gen(DRBG_internal* drbg, byte* out, word32 outSz, const byte* V) break; } } - ForceZero(data, sizeof(data)); + ForceZero(data, DRBG_SEED_LEN); -#ifdef WC_ASYNC_ENABLE_SHA256 - WC_FREE_VAR(digest, drbg->heap); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); + XFREE(data, drbg->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; @@ -630,14 +661,17 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) if (drbg->reseedCtr == RESEED_INTERVAL) { return DRBG_NEED_RESEED; - } else { - #ifdef WC_ASYNC_ENABLE_SHA256 - WC_DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); - if (digest == NULL) - return MEMORY_E; - #else + } + else { + #ifndef WOLFSSL_SMALL_STACK byte digest[WC_SHA256_DIGEST_SIZE]; + #else + byte* digest = (byte*)XMALLOC(WC_SHA256_DIGEST_SIZE, drbg->heap, + DYNAMIC_TYPE_DIGEST); + if (digest == NULL) + return DRBG_FAILURE; #endif + type = drbgGenerateH; reseedCtr = drbg->reseedCtr; @@ -674,8 +708,8 @@ static int Hash_DRBG_Generate(DRBG_internal* drbg, byte* out, word32 outSz) drbg->reseedCtr++; } ForceZero(digest, WC_SHA256_DIGEST_SIZE); - #ifdef WC_ASYNC_ENABLE_SHA256 - WC_FREE_VAR(digest, drbg->heap); + #ifdef WOLFSSL_SMALL_STACK + XFREE(digest, drbg->heap, DYNAMIC_TYPE_DIGEST); #endif } @@ -690,11 +724,10 @@ static int Hash_DRBG_Instantiate(DRBG_internal* drbg, const byte* seed, word32 s int ret = DRBG_FAILURE; XMEMSET(drbg, 0, sizeof(DRBG_internal)); -#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) drbg->heap = heap; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) drbg->devId = devId; #else - (void)heap; (void)devId; #endif @@ -735,8 +768,9 @@ static int Hash_DRBG_Uninstantiate(DRBG_internal* drbg) ForceZero(drbg, sizeof(DRBG_internal)); - for (i = 0; i < sizeof(DRBG_internal); i++) + for (i = 0; i < sizeof(DRBG_internal); i++) { compareSum |= compareDrbg[i] ^ 0; + } return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; } @@ -838,12 +872,13 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, seedSz = MAX_SEED_SZ; if (wc_RNG_HealthTestLocal(0) == 0) { - #ifdef WC_ASYNC_ENABLE_SHA256 - WC_DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap); + #ifndef WOLFSSL_SMALL_STACK + byte seed[MAX_SEED_SZ]; + #else + byte* seed = (byte*)XMALLOC(MAX_SEED_SZ, rng->heap, + DYNAMIC_TYPE_SEED); if (seed == NULL) return MEMORY_E; - #else - byte seed[MAX_SEED_SZ]; #endif #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) @@ -892,12 +927,13 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, } ForceZero(seed, seedSz); - #ifdef WC_ASYNC_ENABLE_SHA256 - WC_FREE_VAR(seed, rng->heap); + #ifdef WOLFSSL_SMALL_STACK + XFREE(seed, rng->heap, DYNAMIC_TYPE_SEED); #endif } - else + else { ret = DRBG_CONT_FAILURE; + } if (ret == DRBG_SUCCESS) { #ifdef WOLFSSL_CHECK_MEM_ZERO @@ -1044,13 +1080,21 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); if (ret == DRBG_NEED_RESEED) { if (wc_RNG_HealthTestLocal(1) == 0) { + #ifndef WOLFSSL_SMALL_STACK byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; - - ret = wc_GenerateSeed(&rng->seed, newSeed, + ret = DRBG_SUCCESS; + #else + byte* newSeed = (byte*)XMALLOC(SEED_SZ + SEED_BLOCK_SZ, rng->heap, + DYNAMIC_TYPE_SEED); + ret = (newSeed == NULL) ? MEMORY_E : DRBG_SUCCESS; + #endif + if (ret == DRBG_SUCCESS) { + ret = wc_GenerateSeed(&rng->seed, newSeed, SEED_SZ + SEED_BLOCK_SZ); - if (ret != 0) - ret = DRBG_FAILURE; - else + if (ret != 0) + ret = DRBG_FAILURE; + } + if (ret == DRBG_SUCCESS) ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ); if (ret == DRBG_SUCCESS) @@ -1060,9 +1104,13 @@ int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) ret = Hash_DRBG_Generate((DRBG_internal *)rng->drbg, output, sz); ForceZero(newSeed, sizeof(newSeed)); + #ifdef WOLFSSL_SMALL_STACK + XFREE(newSeed, rng->heap, DYNAMIC_TYPE_SEED); + #endif } - else + else { ret = DRBG_CONT_FAILURE; + } } if (ret == DRBG_SUCCESS) { @@ -1167,7 +1215,8 @@ int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz, } #ifdef WOLFSSL_SMALL_STACK - drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), NULL, DYNAMIC_TYPE_RNG); + drbg = (DRBG_internal*)XMALLOC(sizeof(DRBG_internal), heap, + DYNAMIC_TYPE_RNG); if (drbg == NULL) { return MEMORY_E; } @@ -1210,7 +1259,7 @@ exit_rng_ht: } #ifdef WOLFSSL_SMALL_STACK - XFREE(drbg, NULL, DYNAMIC_TYPE_RNG); + XFREE(drbg, heap, DYNAMIC_TYPE_RNG); #endif return ret; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 12642bc65..92accfff9 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -27,14 +27,13 @@ #include #endif #include -#include -#include #ifndef NO_CRYPT_TEST -#if defined(HAVE_STACK_SIZE) && !defined(HAVE_WOLFCRYPT_TEST_OPTIONS) - #define HAVE_WOLFCRYPT_TEST_OPTIONS -#endif +#include +#include +#include +#include #if defined(HAVE_WOLFCRYPT_TEST_OPTIONS) #include @@ -48,15 +47,12 @@ #include #endif -#if defined(HAVE_STACK_SIZE_VERBOSE) +#ifdef HAVE_STACK_SIZE_VERBOSE #ifdef WOLFSSL_TEST_MAX_RELATIVE_STACK_BYTES static ssize_t max_relative_stack = WOLFSSL_TEST_MAX_RELATIVE_STACK_BYTES; #else static ssize_t max_relative_stack = -1; #endif -#else - #define STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max, ...) (__VA_ARGS__, 0) - #define STACK_SIZE_INIT() #endif #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE diff --git a/wolfssl/test.h b/wolfssl/test.h index f282cb38a..a6647cfbf 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -1,4 +1,29 @@ -/* test.h */ +/* test.h + * + * Copyright (C) 2006-2022 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 2 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 + */ +/*! + \file ../wolfssl/test.h + \brief Header file containing test inline functions +*/ + +/* Testing functions */ #ifndef wolfSSL_TEST_H #define wolfSSL_TEST_H @@ -252,57 +277,6 @@ #endif #endif - - -#ifdef SINGLE_THREADED - #if defined(WC_32BIT_CPU) - typedef void* THREAD_RETURN; - #else - typedef unsigned int THREAD_RETURN; - #endif - typedef void* THREAD_TYPE; - #define WOLFSSL_THREAD -#else - #if defined(_POSIX_THREADS) && !defined(__MINGW32__) - typedef void* THREAD_RETURN; - typedef pthread_t THREAD_TYPE; - #define WOLFSSL_THREAD - #define INFINITE (-1) - #define WAIT_OBJECT_0 0L - #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) || defined(FREESCALE_MQX) - typedef unsigned int THREAD_RETURN; - typedef int THREAD_TYPE; - #define WOLFSSL_THREAD - #elif defined(WOLFSSL_TIRTOS) - typedef void THREAD_RETURN; - typedef Task_Handle THREAD_TYPE; - #ifdef HAVE_STACK_SIZE - #undef EXIT_TEST - #define EXIT_TEST(ret) - #endif - #define WOLFSSL_THREAD - #elif defined(WOLFSSL_ZEPHYR) - typedef void THREAD_RETURN; - typedef struct k_thread THREAD_TYPE; - #ifdef HAVE_STACK_SIZE - #undef EXIT_TEST - #define EXIT_TEST(ret) - #endif - #define WOLFSSL_THREAD - #elif defined(NETOS) - typedef UINT THREAD_RETURN; - typedef TX_THREAD THREAD_TYPE; - #define WOLFSSL_THREAD - #define INFINITE TX_WAIT_FOREVER - #define WAIT_OBJECT_0 TX_NO_WAIT - #else - typedef unsigned int THREAD_RETURN; - typedef intptr_t THREAD_TYPE; - #define WOLFSSL_THREAD __stdcall - #endif -#endif - - #ifndef MY_EX_USAGE #define MY_EX_USAGE 2 #endif @@ -3004,335 +2978,6 @@ static WC_INLINE void CaCb(unsigned char* der, int sz, int type) } #endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) */ -#ifdef HAVE_STACK_SIZE - -typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); -#define STACK_CHECK_VAL 0x01 - -struct stack_size_debug_context { - unsigned char *myStack; - size_t stackSize; -#ifdef HAVE_STACK_SIZE_VERBOSE - size_t *stackSizeHWM_ptr; - thread_func fn; - void *args; -#endif -}; - -#ifdef HAVE_STACK_SIZE_VERBOSE - -/* per-subtest stack high water mark tracking. - * - * enable with - * - * ./configure --enable-stacksize=verbose [...] - */ - -static THREAD_RETURN debug_stack_size_verbose_shim(struct stack_size_debug_context *shim_args) { - StackSizeCheck_myStack = shim_args->myStack; - StackSizeCheck_stackSize = shim_args->stackSize; - StackSizeCheck_stackSizeHWM_ptr = shim_args->stackSizeHWM_ptr; - return shim_args->fn(shim_args->args); -} - -static WC_INLINE int StackSizeSetOffset(const char *funcname, void *p) -{ - if (StackSizeCheck_myStack == NULL) - return -BAD_FUNC_ARG; - - StackSizeCheck_stackOffsetPointer = p; - - printf("setting stack relative offset reference mark in %s to +%lu\n", - funcname, (unsigned long)((char*)(StackSizeCheck_myStack + - StackSizeCheck_stackSize) - (char *)p)); - - return 0; -} - -static WC_INLINE ssize_t StackSizeHWM(void) -{ - size_t i; - ssize_t used; - - if (StackSizeCheck_myStack == NULL) - return -BAD_FUNC_ARG; - - for (i = 0; i < StackSizeCheck_stackSize; i++) { - if (StackSizeCheck_myStack[i] != STACK_CHECK_VAL) { - break; - } - } - - used = StackSizeCheck_stackSize - i; - if ((ssize_t)*StackSizeCheck_stackSizeHWM_ptr < used) - *StackSizeCheck_stackSizeHWM_ptr = used; - - return used; -} - -static WC_INLINE ssize_t StackSizeHWM_OffsetCorrected(void) -{ - ssize_t used = StackSizeHWM(); - if (used < 0) - return used; - if (StackSizeCheck_stackOffsetPointer) - used -= (ssize_t)(((char *)StackSizeCheck_myStack + StackSizeCheck_stackSize) - (char *)StackSizeCheck_stackOffsetPointer); - return used; -} - -static -#ifdef __GNUC__ -__attribute__((unused)) __attribute__((noinline)) -#endif -int StackSizeHWMReset(void) -{ - volatile ssize_t i; - - if (StackSizeCheck_myStack == NULL) - return -BAD_FUNC_ARG; - - for (i = (ssize_t)((char *)&i - (char *)StackSizeCheck_myStack) - (ssize_t)sizeof i - 1; i >= 0; --i) - { - StackSizeCheck_myStack[i] = STACK_CHECK_VAL; - } - - return 0; -} - -#define STACK_SIZE_CHECKPOINT(...) ({ \ - ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ - __VA_ARGS__; \ - printf(" relative stack peak usage = %ld bytes\n", (long int)HWM); \ - StackSizeHWMReset(); \ - }) - -#define STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max, ...) ({ \ - ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ - int _ret; \ - __VA_ARGS__; \ - printf(" relative stack peak usage = %ld bytes\n", (long int)HWM); \ - _ret = StackSizeHWMReset(); \ - if ((max >= 0) && (HWM > (ssize_t)(max))) { \ - fprintf(stderr, \ - " relative stack usage at %s L%d exceeds designated max %ld bytes.\n", \ - __FILE__, __LINE__, (long int)(max)); \ - _ret = -1; \ - } \ - _ret; \ - }) - - -#ifdef __GNUC__ -#define STACK_SIZE_INIT() (void)StackSizeSetOffset(__FUNCTION__, __builtin_frame_address(0)) -#endif - -#endif /* HAVE_STACK_SIZE_VERBOSE */ - -static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) -{ - size_t i; - int ret; - void* status; - unsigned char* myStack = NULL; - size_t stackSize = 1024*1024*2; - pthread_attr_t myAttr; - pthread_t threadId; -#ifdef HAVE_STACK_SIZE_VERBOSE - struct stack_size_debug_context shim_args; -#endif - -#ifdef PTHREAD_STACK_MIN - if (stackSize < PTHREAD_STACK_MIN) - stackSize = PTHREAD_STACK_MIN; -#endif - - ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); - if (ret != 0 || myStack == NULL) { - err_sys_with_errno("posix_memalign failed\n"); - return -1; - } - - XMEMSET(myStack, STACK_CHECK_VAL, stackSize); - - ret = pthread_attr_init(&myAttr); - if (ret != 0) - err_sys("attr_init failed"); - - ret = pthread_attr_setstack(&myAttr, myStack, stackSize); - if (ret != 0) - err_sys("attr_setstackaddr failed"); - -#ifdef HAVE_STACK_SIZE_VERBOSE - StackSizeCheck_stackSizeHWM = 0; - shim_args.myStack = myStack; - shim_args.stackSize = stackSize; - shim_args.stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; - shim_args.fn = tf; - shim_args.args = args; - ret = pthread_create(&threadId, &myAttr, (thread_func)debug_stack_size_verbose_shim, (void *)&shim_args); -#else - ret = pthread_create(&threadId, &myAttr, tf, args); -#endif - if (ret != 0) { - printf("ret = %d\n", ret); - perror("pthread_create failed"); - exit(EXIT_FAILURE); - } - - ret = pthread_join(threadId, &status); - if (ret != 0) - err_sys("pthread_join failed"); - - for (i = 0; i < stackSize; i++) { - if (myStack[i] != STACK_CHECK_VAL) { - break; - } - } - - free(myStack); -#ifdef HAVE_STACK_SIZE_VERBOSE - printf("stack used = %lu\n", StackSizeCheck_stackSizeHWM > (stackSize - i) - ? (unsigned long)StackSizeCheck_stackSizeHWM - : (unsigned long)(stackSize - i)); -#else - { - size_t used = stackSize - i; - printf("stack used = %lu\n", (unsigned long)used); - } -#endif - - return (int)((size_t)status); -} - -static WC_INLINE int StackSizeCheck_launch(func_args* args, thread_func tf, pthread_t *threadId, void **stack_context) -{ - int ret; - unsigned char* myStack = NULL; - size_t stackSize = 1024*1024*2; - pthread_attr_t myAttr; - -#ifdef PTHREAD_STACK_MIN - if (stackSize < PTHREAD_STACK_MIN) - stackSize = PTHREAD_STACK_MIN; -#endif - - struct stack_size_debug_context *shim_args = (struct stack_size_debug_context *)malloc(sizeof *shim_args); - if (! shim_args) { - perror("malloc"); - exit(EXIT_FAILURE); - } - - ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); - if (ret != 0 || myStack == NULL) { - err_sys_with_errno("posix_memalign failed\n"); - free(shim_args); - return -1; - } - - XMEMSET(myStack, STACK_CHECK_VAL, stackSize); - - ret = pthread_attr_init(&myAttr); - if (ret != 0) - err_sys("attr_init failed"); - - ret = pthread_attr_setstack(&myAttr, myStack, stackSize); - if (ret != 0) - err_sys("attr_setstackaddr failed"); - - shim_args->myStack = myStack; - shim_args->stackSize = stackSize; -#ifdef HAVE_STACK_SIZE_VERBOSE - shim_args->stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; - shim_args->fn = tf; - shim_args->args = args; - ret = pthread_create(threadId, &myAttr, (thread_func)debug_stack_size_verbose_shim, (void *)shim_args); -#else - ret = pthread_create(threadId, &myAttr, tf, args); -#endif - if (ret != 0) { - fprintf(stderr,"pthread_create failed: %s",strerror(ret)); - exit(EXIT_FAILURE); - } - - *stack_context = (void *)shim_args; - - return 0; -} - -static WC_INLINE int StackSizeCheck_reap(pthread_t threadId, void *stack_context) -{ - struct stack_size_debug_context *shim_args = (struct stack_size_debug_context *)stack_context; - size_t i; - void *status; - int ret = pthread_join(threadId, &status); - if (ret != 0) - err_sys("pthread_join failed"); - - for (i = 0; i < shim_args->stackSize; i++) { - if (shim_args->myStack[i] != STACK_CHECK_VAL) { - break; - } - } - - free(shim_args->myStack); -#ifdef HAVE_STACK_SIZE_VERBOSE - printf("stack used = %lu\n", - *shim_args->stackSizeHWM_ptr > (shim_args->stackSize - i) - ? (unsigned long)*shim_args->stackSizeHWM_ptr - : (unsigned long)(shim_args->stackSize - i)); -#else - { - size_t used = shim_args->stackSize - i; - printf("stack used = %lu\n", (unsigned long)used); - } -#endif - free(shim_args); - - return (int)((size_t)status); -} - - -#endif /* HAVE_STACK_SIZE */ - -#ifndef STACK_SIZE_CHECKPOINT -#define STACK_SIZE_CHECKPOINT(...) (__VA_ARGS__) -#endif -#ifndef STACK_SIZE_INIT -#define STACK_SIZE_INIT() -#endif - -#ifdef STACK_TRAP - -/* good settings - --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP" - -*/ - -#ifdef HAVE_STACK_SIZE - /* client only for now, setrlimit will fail if pthread_create() called */ - /* STACK_SIZE does pthread_create() on client */ - #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail" -#endif /* HAVE_STACK_SIZE */ - -static WC_INLINE void StackTrap(void) -{ - struct rlimit rl; - if (getrlimit(RLIMIT_STACK, &rl) != 0) - err_sys_with_errno("getrlimit failed"); - printf("rlim_cur = %llu\n", rl.rlim_cur); - rl.rlim_cur = 1024*21; /* adjust trap size here */ - if (setrlimit(RLIMIT_STACK, &rl) != 0) - err_sys_with_errno("setrlimit failed"); -} - -#else /* STACK_TRAP */ - -static WC_INLINE void StackTrap(void) -{ -} - -#endif /* STACK_TRAP */ - #if defined(ATOMIC_USER) && !defined(WOLFSSL_AEAD_ONLY) diff --git a/wolfssl/wolfcrypt/mem_track.h b/wolfssl/wolfcrypt/mem_track.h index cba10ffc4..ceea2416d 100644 --- a/wolfssl/wolfcrypt/mem_track.h +++ b/wolfssl/wolfcrypt/mem_track.h @@ -19,6 +19,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* Memory and stack use tracking */ + +#ifndef WOLFSSL_MEM_TRACK_H +#define WOLFSSL_MEM_TRACK_H + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) /* The memory tracker overrides the wolfSSL memory callback system and uses a * static to track the total, peak and currently allocated bytes. @@ -55,377 +61,757 @@ */ -#ifndef WOLFSSL_MEM_TRACK_H -#define WOLFSSL_MEM_TRACK_H +#include +#include "wolfssl/wolfcrypt/logging.h" -#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) - - #include "wolfssl/wolfcrypt/logging.h" - - #if defined(WOLFSSL_TRACK_MEMORY) - #define DO_MEM_STATS - #if defined(__linux__) || defined(__MACH__) - #define DO_MEM_LIST - #endif +#if defined(WOLFSSL_TRACK_MEMORY) + #define DO_MEM_STATS + #if defined(__linux__) || defined(__MACH__) + #define DO_MEM_LIST #endif - - - typedef struct memoryStats { - long totalAllocs; /* number of allocations */ - long totalDeallocs; /* number of deallocations */ - long totalBytes; /* total number of bytes allocated */ - long peakBytes; /* concurrent max bytes */ - long currentBytes; /* total current bytes in use */ -#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - long peakAllocsTripOdometer; /* peak number of concurrent allocations, - * subject to reset by - * wolfCrypt_heap_peak_checkpoint() - */ - long peakBytesTripOdometer; /* peak concurrent bytes, subject to reset - * by wolfCrypt_heap_peak_checkpoint() - */ #endif - } memoryStats; - typedef struct memHint { - size_t thisSize; /* size of this memory */ - #ifdef DO_MEM_LIST - struct memHint* next; - struct memHint* prev; - #ifdef WOLFSSL_DEBUG_MEMORY - const char* func; - unsigned int line; - #endif - #endif - void* thisMemory; /* actual memory for user */ - } memHint; +typedef struct memoryStats { + long totalAllocs; /* number of allocations */ + long totalDeallocs; /* number of deallocations */ + long totalBytes; /* total number of bytes allocated */ + long peakBytes; /* concurrent max bytes */ + long currentBytes; /* total current bytes in use */ +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + long peakAllocsTripOdometer; /* peak number of concurrent allocations, + * subject to reset by + * wolfCrypt_heap_peak_checkpoint() + */ + long peakBytesTripOdometer; /* peak concurrent bytes, subject to reset + * by wolfCrypt_heap_peak_checkpoint() + */ +#endif +} memoryStats; - typedef struct memoryTrack { - union { - memHint hint; - byte alignit[sizeof(memHint) + ((16-1) & ~(16-1))]; /* make sure we have strong alignment */ - } u; - } memoryTrack; +typedef struct memHint { + size_t thisSize; /* size of this memory */ #ifdef DO_MEM_LIST - /* track allocations and report at end */ - typedef struct memoryList { - memHint* head; - memHint* tail; - word32 count; - } memoryList; + struct memHint* next; + struct memHint* prev; + #ifdef WOLFSSL_DEBUG_MEMORY + const char* func; + unsigned int line; + #endif +#endif + void* thisMemory; /* actual memory for user */ +} memHint; + +typedef struct memoryTrack { + union { + memHint hint; + byte alignit[sizeof(memHint) + ((16-1) & ~(16-1))]; /* make sure we have strong alignment */ + } u; +} memoryTrack; + +#ifdef DO_MEM_LIST +/* track allocations and report at end */ +typedef struct memoryList { + memHint* head; + memHint* tail; + word32 count; +} memoryList; #endif #if defined(WOLFSSL_TRACK_MEMORY) - static memoryStats ourMemStats; +static memoryStats ourMemStats; - #ifdef DO_MEM_LIST - #include - static memoryList ourMemList; - static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER; - #endif +#ifdef DO_MEM_LIST + #include + static memoryList ourMemList; + static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER; +#endif #endif - /* if defined to not using inline then declare function prototypes */ - #ifdef NO_INLINE - #define WC_STATIC - #ifdef WOLFSSL_DEBUG_MEMORY - WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line); - WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line); - WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line); - #else - WOLFSSL_LOCAL void* TrackMalloc(size_t sz); - WOLFSSL_LOCAL void TrackFree(void* ptr); - WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz); - #endif - WOLFSSL_LOCAL int InitMemoryTracker(void); - WOLFSSL_LOCAL void ShowMemoryTracker(void); - #else - #define WC_STATIC static - #endif - -#ifdef WOLFSSL_DEBUG_MEMORY - WC_STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line) -#else - WC_STATIC WC_INLINE void* TrackMalloc(size_t sz) -#endif - { - memoryTrack* mt; - memHint* header; - - if (sz == 0) - return NULL; - - #ifdef FREERTOS - mt = (memoryTrack*)pvPortMalloc(sizeof(memoryTrack) + sz); - #else - mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz); - #endif - if (mt == NULL) - return NULL; - - header = &mt->u.hint; - header->thisSize = sz; - header->thisMemory = (byte*)mt + sizeof(memoryTrack); - +/* if defined to not using inline then declare function prototypes */ +#ifdef NO_INLINE + #define WC_STATIC #ifdef WOLFSSL_DEBUG_MEMORY - #ifdef WOLFSSL_DEBUG_MEMORY_PRINT - fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", header->thisMemory, (word32)sz, func, line); + WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line); + WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line); #else - (void)func; - (void)line; + WOLFSSL_LOCAL void* TrackMalloc(size_t sz); + WOLFSSL_LOCAL void TrackFree(void* ptr); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz); #endif - #endif - - #ifdef DO_MEM_STATS - ourMemStats.totalAllocs++; - ourMemStats.totalBytes += sz; - ourMemStats.currentBytes += sz; - #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - ourMemStats.totalDeallocs) - ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - ourMemStats.totalDeallocs; - if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) { - ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; - #endif - if (ourMemStats.currentBytes > ourMemStats.peakBytes) - ourMemStats.peakBytes = ourMemStats.currentBytes; - #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - } - #endif - #endif - #ifdef DO_MEM_LIST - if (pthread_mutex_lock(&memLock) == 0) { - #ifdef WOLFSSL_DEBUG_MEMORY - header->func = func; - header->line = line; - #endif - - /* Setup event */ - header->next = NULL; - if (ourMemList.tail == NULL) { - ourMemList.head = header; - header->prev = NULL; - } - else { - ourMemList.tail->next = header; - header->prev = ourMemList.tail; - } - ourMemList.tail = header; /* add to the end either way */ - ourMemList.count++; - - pthread_mutex_unlock(&memLock); - } - #endif - - return header->thisMemory; - } - + WOLFSSL_LOCAL int InitMemoryTracker(void); + WOLFSSL_LOCAL void ShowMemoryTracker(void); +#else + #define WC_STATIC static +#endif #ifdef WOLFSSL_DEBUG_MEMORY - WC_STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line) +WC_STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line) #else - WC_STATIC WC_INLINE void TrackFree(void* ptr) +WC_STATIC WC_INLINE void* TrackMalloc(size_t sz) #endif - { - memoryTrack* mt; - memHint* header; - size_t sz; +{ + memoryTrack* mt; + memHint* header; - if (ptr == NULL) { - return; - } + if (sz == 0) + return NULL; - mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); - header = &mt->u.hint; - sz = header->thisSize; +#ifdef FREERTOS + mt = (memoryTrack*)pvPortMalloc(sizeof(memoryTrack) + sz); +#else + mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz); +#endif + if (mt == NULL) + return NULL; - #ifdef DO_MEM_LIST - if (pthread_mutex_lock(&memLock) == 0) - { - #endif - - #ifdef DO_MEM_STATS - ourMemStats.currentBytes -= header->thisSize; - ourMemStats.totalDeallocs++; - #endif - - #ifdef DO_MEM_LIST - if (header == ourMemList.head && header == ourMemList.tail) { - ourMemList.head = NULL; - ourMemList.tail = NULL; - } - else if (header == ourMemList.head) { - ourMemList.head = header->next; - ourMemList.head->prev = NULL; - } - else if (header == ourMemList.tail) { - ourMemList.tail = header->prev; - ourMemList.tail->next = NULL; - } - else { - memHint* next = header->next; - memHint* prev = header->prev; - if (next) - next->prev = prev; - if (prev) - prev->next = next; - } - ourMemList.count--; - - pthread_mutex_unlock(&memLock); - } - #endif + header = &mt->u.hint; + header->thisSize = sz; + header->thisMemory = (byte*)mt + sizeof(memoryTrack); #ifdef WOLFSSL_DEBUG_MEMORY #ifdef WOLFSSL_DEBUG_MEMORY_PRINT - fprintf(stderr, "Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line); + fprintf(stderr, "Alloc: %p -> %u at %s:%d\n", header->thisMemory, (word32)sz, func, line); #else - (void)func; - (void)line; + (void)func; + (void)line; #endif #endif - (void)sz; - #ifdef FREERTOS - vPortFree(mt); - #else - free(mt); +#ifdef DO_MEM_STATS + ourMemStats.totalAllocs++; + ourMemStats.totalBytes += sz; + ourMemStats.currentBytes += sz; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + if (ourMemStats.peakAllocsTripOdometer < ourMemStats.totalAllocs - ourMemStats.totalDeallocs) + ourMemStats.peakAllocsTripOdometer = ourMemStats.totalAllocs - ourMemStats.totalDeallocs; + if (ourMemStats.peakBytesTripOdometer < ourMemStats.currentBytes) { + ourMemStats.peakBytesTripOdometer = ourMemStats.currentBytes; #endif + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + #ifdef WOLFSSL_TRACK_MEMORY_VERBOSE } + #endif +#endif +#ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) { + #ifdef WOLFSSL_DEBUG_MEMORY + header->func = func; + header->line = line; + #endif + + /* Setup event */ + header->next = NULL; + if (ourMemList.tail == NULL) { + ourMemList.head = header; + header->prev = NULL; + } + else { + ourMemList.tail->next = header; + header->prev = ourMemList.tail; + } + ourMemList.tail = header; /* add to the end either way */ + ourMemList.count++; + + pthread_mutex_unlock(&memLock); + } +#endif + + return header->thisMemory; +} #ifdef WOLFSSL_DEBUG_MEMORY - WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line) +WC_STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line) #else - WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz) +WC_STATIC WC_INLINE void TrackFree(void* ptr) #endif - { - #ifdef WOLFSSL_DEBUG_MEMORY - void* ret = TrackMalloc(sz, func, line); - #else - void* ret = TrackMalloc(sz); - #endif +{ + memoryTrack* mt; + memHint* header; + size_t sz; - if (ptr) { - /* if realloc is bigger, don't overread old ptr */ - memoryTrack* mt; - memHint* header; - - mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); - header = &mt->u.hint; - - if (header->thisSize < sz) - sz = header->thisSize; - } - - if (ret && ptr) - XMEMCPY(ret, ptr, sz); - - if (ret) { - #ifdef WOLFSSL_DEBUG_MEMORY - TrackFree(ptr, func, line); - #else - TrackFree(ptr); - #endif - } - - return ret; + if (ptr == NULL) { + return; } + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + sz = header->thisSize; + +#ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { +#endif + +#ifdef DO_MEM_STATS + ourMemStats.currentBytes -= header->thisSize; + ourMemStats.totalDeallocs++; +#endif + +#ifdef DO_MEM_LIST + if (header == ourMemList.head && header == ourMemList.tail) { + ourMemList.head = NULL; + ourMemList.tail = NULL; + } + else if (header == ourMemList.head) { + ourMemList.head = header->next; + ourMemList.head->prev = NULL; + } + else if (header == ourMemList.tail) { + ourMemList.tail = header->prev; + ourMemList.tail->next = NULL; + } + else { + memHint* next = header->next; + memHint* prev = header->prev; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + } + ourMemList.count--; + + pthread_mutex_unlock(&memLock); + } +#endif + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + fprintf(stderr, "Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line); +#else + (void)func; + (void)line; +#endif +#endif + (void)sz; + +#ifdef FREERTOS + vPortFree(mt); +#else + free(mt); +#endif +} + + +#ifdef WOLFSSL_DEBUG_MEMORY +WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line) +#else +WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz) +#endif +{ +#ifdef WOLFSSL_DEBUG_MEMORY + void* ret = TrackMalloc(sz, func, line); +#else + void* ret = TrackMalloc(sz); +#endif + + if (ptr) { + /* if realloc is bigger, don't overread old ptr */ + memoryTrack* mt; + memHint* header; + + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + + if (header->thisSize < sz) + sz = header->thisSize; + } + + if (ret && ptr) + XMEMCPY(ret, ptr, sz); + + if (ret) { + #ifdef WOLFSSL_DEBUG_MEMORY + TrackFree(ptr, func, line); + #else + TrackFree(ptr); + #endif + } + + return ret; +} + #ifdef WOLFSSL_TRACK_MEMORY - static wolfSSL_Malloc_cb mfDefault = NULL; - static wolfSSL_Free_cb ffDefault = NULL; - static wolfSSL_Realloc_cb rfDefault = NULL; +static wolfSSL_Malloc_cb mfDefault = NULL; +static wolfSSL_Free_cb ffDefault = NULL; +static wolfSSL_Realloc_cb rfDefault = NULL; - WC_STATIC WC_INLINE int InitMemoryTracker(void) - { - int ret; - - ret = wolfSSL_GetAllocators(&mfDefault, &ffDefault, &rfDefault); - if (ret < 0) { - fprintf(stderr, "wolfSSL GetAllocators failed to get the defaults\n"); - } - ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); - if (ret < 0) { - fprintf(stderr, "wolfSSL SetAllocators failed for track memory\n"); - return ret; - } - - #ifdef DO_MEM_LIST - if (pthread_mutex_lock(&memLock) == 0) - { - #endif - - #ifdef DO_MEM_STATS - ourMemStats.totalAllocs = 0; - ourMemStats.totalDeallocs = 0; - ourMemStats.totalBytes = 0; - ourMemStats.peakBytes = 0; - ourMemStats.currentBytes = 0; -#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE - ourMemStats.peakAllocsTripOdometer = 0; - ourMemStats.peakBytesTripOdometer = 0; -#endif - #endif - - #ifdef DO_MEM_LIST - XMEMSET(&ourMemList, 0, sizeof(ourMemList)); - - pthread_mutex_unlock(&memLock); - } - #endif +WC_STATIC WC_INLINE int InitMemoryTracker(void) +{ + int ret; + ret = wolfSSL_GetAllocators(&mfDefault, &ffDefault, &rfDefault); + if (ret < 0) { + fprintf(stderr, "wolfSSL GetAllocators failed to get the defaults\n"); + } + ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); + if (ret < 0) { + fprintf(stderr, "wolfSSL SetAllocators failed for track memory\n"); return ret; } - WC_STATIC WC_INLINE void ShowMemoryTracker(void) +#ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) { - #ifdef DO_MEM_LIST - if (pthread_mutex_lock(&memLock) == 0) - { - #endif +#endif - #ifdef DO_MEM_STATS - fprintf(stderr, "total Allocs = %9ld\n", ourMemStats.totalAllocs); - fprintf(stderr, "total Deallocs = %9ld\n", ourMemStats.totalDeallocs); - fprintf(stderr, "total Bytes = %9ld\n", ourMemStats.totalBytes); - fprintf(stderr, "peak Bytes = %9ld\n", ourMemStats.peakBytes); - fprintf(stderr, "current Bytes = %9ld\n", ourMemStats.currentBytes); - #endif +#ifdef DO_MEM_STATS + ourMemStats.totalAllocs = 0; + ourMemStats.totalDeallocs = 0; + ourMemStats.totalBytes = 0; + ourMemStats.peakBytes = 0; + ourMemStats.currentBytes = 0; +#ifdef WOLFSSL_TRACK_MEMORY_VERBOSE + ourMemStats.peakAllocsTripOdometer = 0; + ourMemStats.peakBytesTripOdometer = 0; +#endif +#endif - #ifdef DO_MEM_LIST - if (ourMemList.count > 0) { - /* print list of allocations */ - memHint* header; - for (header = ourMemList.head; header != NULL; header = header->next) { - fprintf(stderr, "Leak: Ptr %p, Size %u" - #ifdef WOLFSSL_DEBUG_MEMORY - ", Func %s, Line %d" - #endif - "\n", - (byte*)header + sizeof(memHint), (unsigned int)header->thisSize - #ifdef WOLFSSL_DEBUG_MEMORY - , header->func, header->line - #endif - ); - } - } +#ifdef DO_MEM_LIST + XMEMSET(&ourMemList, 0, sizeof(ourMemList)); - pthread_mutex_unlock(&memLock); - } - #endif - } - - WC_STATIC WC_INLINE int CleanupMemoryTracker(void) - { - /* restore default allocators */ - return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault); + pthread_mutex_unlock(&memLock); } #endif -#endif /* USE_WOLFSSL_MEMORY */ + return ret; +} + +WC_STATIC WC_INLINE void ShowMemoryTracker(void) +{ +#ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { +#endif + +#ifdef DO_MEM_STATS + fprintf(stderr, "total Allocs = %9ld\n", ourMemStats.totalAllocs); + fprintf(stderr, "total Deallocs = %9ld\n", ourMemStats.totalDeallocs); + fprintf(stderr, "total Bytes = %9ld\n", ourMemStats.totalBytes); + fprintf(stderr, "peak Bytes = %9ld\n", ourMemStats.peakBytes); + fprintf(stderr, "current Bytes = %9ld\n", ourMemStats.currentBytes); +#endif + +#ifdef DO_MEM_LIST + if (ourMemList.count > 0) { + /* print list of allocations */ + memHint* header; + for (header = ourMemList.head; header != NULL; header = header->next) { + fprintf(stderr, "Leak: Ptr %p, Size %u" + #ifdef WOLFSSL_DEBUG_MEMORY + ", Func %s, Line %d" + #endif + "\n", + (byte*)header + sizeof(memHint), (unsigned int)header->thisSize + #ifdef WOLFSSL_DEBUG_MEMORY + , header->func, header->line + #endif + ); + } + } + + pthread_mutex_unlock(&memLock); + } +#endif +} + +WC_STATIC WC_INLINE int CleanupMemoryTracker(void) +{ + /* restore default allocators */ + return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault); +} +#endif /* WOLFSSL_TRACK_MEMORY */ + +#endif /* USE_WOLFSSL_MEMORY && !WOLFSSL_STATIC_MEMORY */ + + +#ifdef HAVE_STACK_SIZE + +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef void* (*thread_func)(void* args); +#define STACK_CHECK_VAL 0x01 + +struct stack_size_debug_context { + unsigned char *myStack; + size_t stackSize; +#ifdef HAVE_STACK_SIZE_VERBOSE + size_t *stackSizeHWM_ptr; + thread_func fn; + void *args; +#endif +}; + +struct func_args; /* forward declaration */ + +#ifdef HAVE_STACK_SIZE_VERBOSE + +/* per-subtest stack high water mark tracking. + * + * enable with + * + * ./configure --enable-stacksize=verbose [...] + */ + +static void* debug_stack_size_verbose_shim( + struct stack_size_debug_context *shim_args) +{ + StackSizeCheck_myStack = shim_args->myStack; + StackSizeCheck_stackSize = shim_args->stackSize; + StackSizeCheck_stackSizeHWM_ptr = shim_args->stackSizeHWM_ptr; + return shim_args->fn(shim_args->args); +} + +static WC_INLINE int StackSizeSetOffset(const char *funcname, void *p) +{ + if (StackSizeCheck_myStack == NULL) + return -BAD_FUNC_ARG; + + StackSizeCheck_stackOffsetPointer = p; + + printf("setting stack relative offset reference mark in %s to +%lu\n", + funcname, (unsigned long)((char*)(StackSizeCheck_myStack + + StackSizeCheck_stackSize) - (char *)p)); + + return 0; +} + +static WC_INLINE ssize_t StackSizeHWM(void) +{ + size_t i; + ssize_t used; + + if (StackSizeCheck_myStack == NULL) + return -BAD_FUNC_ARG; + + for (i = 0; i < StackSizeCheck_stackSize; i++) { + if (StackSizeCheck_myStack[i] != STACK_CHECK_VAL) { + break; + } + } + + used = StackSizeCheck_stackSize - i; + if ((ssize_t)*StackSizeCheck_stackSizeHWM_ptr < used) + *StackSizeCheck_stackSizeHWM_ptr = used; + + return used; +} + +static WC_INLINE ssize_t StackSizeHWM_OffsetCorrected(void) +{ + ssize_t used = StackSizeHWM(); + if (used < 0) + return used; + if (StackSizeCheck_stackOffsetPointer) { + used -= (ssize_t)(((char *)StackSizeCheck_myStack + + StackSizeCheck_stackSize) - + (char *)StackSizeCheck_stackOffsetPointer); + } + return used; +} + +static +#ifdef __GNUC__ +__attribute__((unused)) __attribute__((noinline)) +#endif +int StackSizeHWMReset(void) +{ + volatile ssize_t i; + + if (StackSizeCheck_myStack == NULL) + return -BAD_FUNC_ARG; + + for (i = (ssize_t)((char *)&i - (char *)StackSizeCheck_myStack) - + (ssize_t)sizeof(i) - 1; i >= 0; --i) { + StackSizeCheck_myStack[i] = STACK_CHECK_VAL; + } + + return 0; +} + +#define STACK_SIZE_CHECKPOINT(...) ({ \ + ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ + __VA_ARGS__; \ + printf(" relative stack peak usage = %ld bytes\n", (long int)HWM); \ + StackSizeHWMReset(); \ + }) + +#define STACK_SIZE_CHECKPOINT_MSG(msg) ({ \ + ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ + fprintf(stderr, "%ld\t%s\n", (long int)HWM, msg); \ + StackSizeHWMReset(); \ + }) + \ + + +#define STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max, ...) ({ \ + ssize_t HWM = StackSizeHWM_OffsetCorrected(); \ + int _ret; \ + __VA_ARGS__; \ + printf(" relative stack peak usage = %ld bytes\n", (long int)HWM); \ + _ret = StackSizeHWMReset(); \ + if ((max >= 0) && (HWM > (ssize_t)(max))) { \ + fprintf(stderr, \ + " relative stack usage at %s L%d exceeds designated max %ld bytes.\n", \ + __FILE__, __LINE__, (long int)(max)); \ + _ret = -1; \ + } \ + _ret; \ + }) + + +#if defined(__GNUC__) || defined(__clang__) +#define STACK_SIZE_INIT() \ + (void)StackSizeSetOffset(__FUNCTION__, __builtin_frame_address(0)) +#endif + +#endif /* HAVE_STACK_SIZE_VERBOSE */ + +static WC_INLINE int StackSizeCheck(struct func_args* args, thread_func tf) +{ + size_t i; + int ret; + void* status; + unsigned char* myStack = NULL; + size_t stackSize = 1024*1024*2; + pthread_attr_t myAttr; + pthread_t threadId; +#ifdef HAVE_STACK_SIZE_VERBOSE + struct stack_size_debug_context shim_args; +#endif + +#ifdef PTHREAD_STACK_MIN + if (stackSize < PTHREAD_STACK_MIN) + stackSize = PTHREAD_STACK_MIN; +#endif + + ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); + if (ret != 0 || myStack == NULL) { + fprintf(stderr, "posix_memalign failed\n"); + return -1; + } + + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); + + ret = pthread_attr_init(&myAttr); + if (ret != 0) { + fprintf(stderr, "attr_init failed\n"); + return ret; + } + + ret = pthread_attr_setstack(&myAttr, myStack, stackSize); + if (ret != 0) { + fprintf(stderr, "attr_setstackaddr failed\n"); + return ret; + } + +#ifdef HAVE_STACK_SIZE_VERBOSE + StackSizeCheck_stackSizeHWM = 0; + shim_args.myStack = myStack; + shim_args.stackSize = stackSize; + shim_args.stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; + shim_args.fn = tf; + shim_args.args = args; + ret = pthread_create(&threadId, &myAttr, + (thread_func)debug_stack_size_verbose_shim, (void *)&shim_args); +#else + ret = pthread_create(&threadId, &myAttr, tf, args); +#endif + if (ret != 0) { + printf("ret = %d\n", ret); + perror("pthread_create failed"); + exit(EXIT_FAILURE); + } + + ret = pthread_join(threadId, &status); + if (ret != 0) { + fprintf(stderr, "pthread_join failed\n"); + return ret; + } + + for (i = 0; i < stackSize; i++) { + if (myStack[i] != STACK_CHECK_VAL) { + break; + } + } + + free(myStack); +#ifdef HAVE_STACK_SIZE_VERBOSE + printf("stack used = %lu\n", StackSizeCheck_stackSizeHWM > (stackSize - i) + ? (unsigned long)StackSizeCheck_stackSizeHWM + : (unsigned long)(stackSize - i)); + StackSizeCheck_myStack = NULL; + StackSizeCheck_stackOffsetPointer = NULL; +#else + { + size_t used = stackSize - i; + printf("stack used = %lu\n", (unsigned long)used); + } +#endif + + return (int)((size_t)status); +} + +static WC_INLINE int StackSizeCheck_launch(struct func_args* args, + thread_func tf, pthread_t *threadId, void **stack_context) +{ + int ret; + unsigned char* myStack = NULL; + size_t stackSize = 1024*1024*2; + pthread_attr_t myAttr; + +#ifdef PTHREAD_STACK_MIN + if (stackSize < PTHREAD_STACK_MIN) + stackSize = PTHREAD_STACK_MIN; +#endif + + struct stack_size_debug_context *shim_args = + (struct stack_size_debug_context *)malloc(sizeof *shim_args); + if (! shim_args) { + perror("malloc"); + exit(EXIT_FAILURE); + } + + ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); + if (ret != 0 || myStack == NULL) { + fprintf(stderr, "posix_memalign failed\n"); + free(shim_args); + return -1; + } + + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); + + ret = pthread_attr_init(&myAttr); + if (ret != 0) { + fprintf(stderr, "attr_init failed\n"); + return ret; + } + + ret = pthread_attr_setstack(&myAttr, myStack, stackSize); + if (ret != 0) { + fprintf(stderr, "attr_setstackaddr failed\n"); + } + + shim_args->myStack = myStack; + shim_args->stackSize = stackSize; +#ifdef HAVE_STACK_SIZE_VERBOSE + shim_args->stackSizeHWM_ptr = &StackSizeCheck_stackSizeHWM; + shim_args->fn = tf; + shim_args->args = args; + ret = pthread_create(threadId, &myAttr, + (thread_func)debug_stack_size_verbose_shim, (void *)shim_args); +#else + ret = pthread_create(threadId, &myAttr, tf, args); +#endif + if (ret != 0) { + fprintf(stderr,"pthread_create failed: %s",strerror(ret)); + exit(EXIT_FAILURE); + } + + *stack_context = (void *)shim_args; + + return 0; +} + +static WC_INLINE int StackSizeCheck_reap(pthread_t threadId, void *stack_context) +{ + struct stack_size_debug_context *shim_args = + (struct stack_size_debug_context *)stack_context; + size_t i; + void *status; + int ret = pthread_join(threadId, &status); + if (ret != 0) { + fprintf(stderr, "pthread_join failed\n"); + return ret; + } + + for (i = 0; i < shim_args->stackSize; i++) { + if (shim_args->myStack[i] != STACK_CHECK_VAL) { + break; + } + } + + free(shim_args->myStack); +#ifdef HAVE_STACK_SIZE_VERBOSE + printf("stack used = %lu\n", + *shim_args->stackSizeHWM_ptr > (shim_args->stackSize - i) + ? (unsigned long)*shim_args->stackSizeHWM_ptr + : (unsigned long)(shim_args->stackSize - i)); +#else + { + size_t used = shim_args->stackSize - i; + printf("stack used = %lu\n", (unsigned long)used); + } +#endif + free(shim_args); + + return (int)((size_t)status); +} + + +#endif /* HAVE_STACK_SIZE */ + + +#ifdef STACK_TRAP + +/* good settings + ./configure --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME \ + -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP" + +*/ + +#ifdef HAVE_STACK_SIZE + /* client only for now, setrlimit will fail if pthread_create() called */ + /* STACK_SIZE does pthread_create() on client */ + #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail" +#endif /* HAVE_STACK_SIZE */ + +static WC_INLINE void StackTrap(void) +{ + struct rlimit rl; + if (getrlimit(RLIMIT_STACK, &rl) != 0) { + fprintf(stderr, "getrlimit failed\n"); + } + printf("rlim_cur = %llu\n", rl.rlim_cur); + rl.rlim_cur = 1024*21; /* adjust trap size here */ + if (setrlimit(RLIMIT_STACK, &rl) != 0) { + fprintf(stderr, "setrlimit failed\n"); + } +} + +#else /* STACK_TRAP */ + +static WC_INLINE void StackTrap(void) +{ +} + +#endif /* STACK_TRAP */ + +/* Stubs when not used */ +#ifndef STACK_SIZE_CHECKPOINT +#define STACK_SIZE_CHECKPOINT(...) (__VA_ARGS__) +#endif +#ifndef STACK_SIZE_CHECKPOINT_MSG +#define STACK_SIZE_CHECKPOINT_MSG(msg) +#endif +#ifndef STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK +#define STACK_SIZE_CHECKPOINT_WITH_MAX_CHECK(max, ...) (0) +#endif +#ifndef STACK_SIZE_INIT +#define STACK_SIZE_INIT() +#endif #endif /* WOLFSSL_MEM_TRACK_H */ - diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 28ac8f640..5deea40a0 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -162,8 +162,8 @@ struct DRBG_internal { word32 lastBlock; byte V[DRBG_SEED_LEN]; byte C[DRBG_SEED_LEN]; -#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) void* heap; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) int devId; #endif byte matchCount; diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 026e8487e..6822f6b34 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -1234,6 +1234,57 @@ typedef struct w64wrapper { #define FALSE 0 #endif + #ifdef SINGLE_THREADED + #if defined(WC_32BIT_CPU) + typedef void* THREAD_RETURN; + #else + typedef unsigned int THREAD_RETURN; + #endif + typedef void* THREAD_TYPE; + #define WOLFSSL_THREAD + #elif (defined(_POSIX_THREADS) || defined(HAVE_PTHREAD)) && \ + !defined(__MINGW32__) + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define WOLFSSL_THREAD + #define INFINITE (-1) + #define WAIT_OBJECT_0 0L + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) || \ + defined(FREESCALE_MQX) + typedef unsigned int THREAD_RETURN; + typedef int THREAD_TYPE; + #define WOLFSSL_THREAD + #elif defined(WOLFSSL_TIRTOS) + typedef void THREAD_RETURN; + typedef Task_Handle THREAD_TYPE; + #ifdef HAVE_STACK_SIZE + #undef EXIT_TEST + #define EXIT_TEST(ret) + #endif + #define WOLFSSL_THREAD + #elif defined(WOLFSSL_ZEPHYR) + typedef void THREAD_RETURN; + typedef struct k_thread THREAD_TYPE; + #ifdef HAVE_STACK_SIZE + #undef EXIT_TEST + #define EXIT_TEST(ret) + #endif + #define WOLFSSL_THREAD + #elif defined(NETOS) + typedef UINT THREAD_RETURN; + typedef TX_THREAD THREAD_TYPE; + #define WOLFSSL_THREAD + #define INFINITE TX_WAIT_FOREVER + #define WAIT_OBJECT_0 TX_NO_WAIT + #elif defined(WOLFSSL_LINUXKM) + typedef unsigned int THREAD_RETURN; + typedef size_t THREAD_TYPE; + #define WOLFSSL_THREAD + #else + typedef unsigned int THREAD_RETURN; + typedef size_t THREAD_TYPE; + #define WOLFSSL_THREAD __stdcall + #endif #if defined(HAVE_STACK_SIZE) #define EXIT_TEST(ret) return (THREAD_RETURN)((size_t)(ret)) From 09f4a94b240ab71f23dc60786ae4e6a119e5ceb1 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 3 Oct 2022 12:52:11 -0700 Subject: [PATCH 2/3] Fixes for small stack in TLS v1.3, HKDF and SHA2. Add new `WC_ASN_HASH_SHA256` build option to allow forcing SHA2-256 for the internal certificate calculations. Fixes for integer.c with small stack (allocate only the size needed, not the max). --- src/tls13.c | 35 +++++++++---- wolfcrypt/src/asn.c | 10 +++- wolfcrypt/src/hmac.c | 71 ++++++++++++++++++------- wolfcrypt/src/integer.c | 26 +++------- wolfcrypt/src/kdf.c | 17 +++++- wolfcrypt/src/sha256.c | 75 ++++++++++++++++++--------- wolfcrypt/src/sha512.c | 94 ++++++++++++++++++++++++---------- wolfssl/wolfcrypt/asn.h | 4 +- wolfssl/wolfcrypt/asn_public.h | 8 +-- wolfssl/wolfcrypt/settings.h | 3 -- 10 files changed, 233 insertions(+), 110 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index 24578d2c9..6a6bd4042 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1106,7 +1106,11 @@ int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, byte* secret) static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, word32* pHashSz) { - Hmac verifyHmac; +#ifdef WOLFSSL_SMALL_STACK + Hmac* verifyHmac; +#else + Hmac verifyHmac[1]; +#endif int hashType = WC_SHA256; int hashSz = WC_SHA256_DIGEST_SIZE; int ret = BAD_FUNC_ARG; @@ -1151,16 +1155,27 @@ static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, WOLFSSL_BUFFER(hash, hashSz); #endif - /* Calculate the verify data. */ - ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId); - if (ret == 0) { - ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size); - if (ret == 0) - ret = wc_HmacUpdate(&verifyHmac, hash, hashSz); - if (ret == 0) - ret = wc_HmacFinal(&verifyHmac, hash); - wc_HmacFree(&verifyHmac); +#ifdef WOLFSSL_SMALL_STACK + verifyHmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC); + if (verifyHmac == NULL) { + return MEMORY_E; } +#endif + + /* Calculate the verify data. */ + ret = wc_HmacInit(verifyHmac, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_HmacSetKey(verifyHmac, hashType, key, ssl->specs.hash_size); + if (ret == 0) + ret = wc_HmacUpdate(verifyHmac, hash, hashSz); + if (ret == 0) + ret = wc_HmacFinal(verifyHmac, hash); + wc_HmacFree(verifyHmac); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(verifyHmac, NULL, DYNAMIC_TYPE_HMAC); +#endif #ifdef WOLFSSL_DEBUG_TLS WOLFSSL_MSG(" Hash"); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 53c540e49..169510a9f 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -87,6 +87,7 @@ ASN Options: * WOLFSSL_CERT_NAME_ALL: Adds more certificate name capability at the cost of taking up more memory. Adds initials, givenname, dnQualifer for example. + * WC_ASN_HASH_SHA256: Force use of SHA2-256 for the internal hash ID calcs. */ #ifndef NO_ASN @@ -12014,7 +12015,7 @@ int CalcHashId(const byte* data, word32 len, byte* hash) { int ret; -#if defined(NO_SHA) && !defined(NO_SHA256) +#if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256)) ret = wc_Sha256Hash(data, len, hash); #elif !defined(NO_SHA) ret = wc_ShaHash(data, len, hash); @@ -23530,7 +23531,7 @@ int wc_PemToDer(const unsigned char* buff, long longSz, int type, return ret; } - +#ifdef WOLFSSL_ENCRYPTED_KEYS /* our KeyPemToDer password callback, password in userData */ static int KeyPemToDerPassCb(char* passwd, int sz, int rw, void* userdata) { @@ -23542,6 +23543,7 @@ static int KeyPemToDerPassCb(char* passwd, int sz, int rw, void* userdata) XSTRNCPY(passwd, (char*)userdata, sz); return min((word32)sz, (word32)XSTRLEN((char*)userdata)); } +#endif /* Return bytes written to buff or < 0 for error */ int wc_KeyPemToDer(const unsigned char* pem, int pemSz, @@ -23570,8 +23572,12 @@ int wc_KeyPemToDer(const unsigned char* pem, int pemSz, #endif XMEMSET(info, 0, sizeof(EncryptedInfo)); +#ifdef WOLFSSL_ENCRYPTED_KEYS info->passwd_cb = KeyPemToDerPassCb; info->passwd_userdata = (void*)pass; +#else + (void)pass; +#endif ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, NULL); diff --git a/wolfcrypt/src/hmac.c b/wolfcrypt/src/hmac.c index 2fb143a06..8f26aadc6 100644 --- a/wolfcrypt/src/hmac.c +++ b/wolfcrypt/src/hmac.c @@ -1184,14 +1184,26 @@ int wolfSSL_GetHmacMaxSize(void) const byte* inKey, word32 inKeySz, byte* out) { byte tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */ - Hmac myHmac; + #ifdef WOLFSSL_SMALL_STACK + Hmac* myHmac; + #else + Hmac myHmac[1]; + #endif int ret; const byte* localSalt; /* either points to user input or tmp */ int hashSz; ret = wc_HmacSizeByType(type); - if (ret < 0) + if (ret < 0) { return ret; + } + + #ifdef WOLFSSL_SMALL_STACK + myHmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC); + if (myHmac == NULL) { + return MEMORY_E; + } + #endif hashSz = ret; localSalt = salt; @@ -1201,15 +1213,18 @@ int wolfSSL_GetHmacMaxSize(void) saltSz = hashSz; } - ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); + ret = wc_HmacInit(myHmac, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + ret = wc_HmacSetKey(myHmac, type, localSalt, saltSz); if (ret == 0) - ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + ret = wc_HmacUpdate(myHmac, inKey, inKeySz); if (ret == 0) - ret = wc_HmacFinal(&myHmac, out); - wc_HmacFree(&myHmac); + ret = wc_HmacFinal(myHmac, out); + wc_HmacFree(myHmac); } + #ifdef WOLFSSL_SMALL_STACK + XFREE(myHmac, NULL, DYNAMIC_TYPE_HMAC); + #endif return ret; } @@ -1229,40 +1244,55 @@ int wolfSSL_GetHmacMaxSize(void) const byte* info, word32 infoSz, byte* out, word32 outSz) { byte tmp[WC_MAX_DIGEST_SIZE]; - Hmac myHmac; + #ifdef WOLFSSL_SMALL_STACK + Hmac* myHmac; + #else + Hmac myHmac[1]; + #endif int ret = 0; word32 outIdx = 0; word32 hashSz = wc_HmacSizeByType(type); byte n = 0x1; /* RFC 5869 states that the length of output keying material in - octets must be L <= 255*HashLen or N = ceil(L/HashLen) */ + * octets must be L <= 255*HashLen or N = ceil(L/HashLen) */ - if (out == NULL || ((outSz/hashSz) + ((outSz % hashSz) != 0)) > 255) + if (out == NULL || ((outSz/hashSz) + ((outSz % hashSz) != 0)) > 255) { return BAD_FUNC_ARG; + } - ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); - if (ret != 0) + #ifdef WOLFSSL_SMALL_STACK + myHmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC); + if (myHmac == NULL) { + return MEMORY_E; + } + #endif + + ret = wc_HmacInit(myHmac, NULL, INVALID_DEVID); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(myHmac, NULL, DYNAMIC_TYPE_HMAC); + #endif return ret; - + } while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; - ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); + ret = wc_HmacSetKey(myHmac, type, inKey, inKeySz); if (ret != 0) break; - ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); + ret = wc_HmacUpdate(myHmac, tmp, tmpSz); if (ret != 0) break; - ret = wc_HmacUpdate(&myHmac, info, infoSz); + ret = wc_HmacUpdate(myHmac, info, infoSz); if (ret != 0) break; - ret = wc_HmacUpdate(&myHmac, &n, 1); + ret = wc_HmacUpdate(myHmac, &n, 1); if (ret != 0) break; - ret = wc_HmacFinal(&myHmac, tmp); + ret = wc_HmacFinal(myHmac, tmp); if (ret != 0) break; @@ -1273,7 +1303,10 @@ int wolfSSL_GetHmacMaxSize(void) n++; } - wc_HmacFree(&myHmac); + wc_HmacFree(myHmac); + #ifdef WOLFSSL_SMALL_STACK + XFREE(myHmac, NULL, DYNAMIC_TYPE_HMAC); + #endif return ret; } diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index cb05fa4bf..d6780e6ba 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -2306,11 +2306,7 @@ int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) { mp_digit buf, mp; int err = MP_OKAY, bitbuf, bitcpy, bitcnt, digidx, x, y; -#ifdef WOLFSSL_SMALL_STACK - mp_int *res = NULL; -#else mp_int res[1]; -#endif int (*redux)(mp_int*,mp_int*,mp_digit) = NULL; /* automatically pick the comba one if available (saves quite a few @@ -2332,13 +2328,6 @@ int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) return MP_VAL; } -#ifdef WOLFSSL_SMALL_STACK - res = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (res == NULL) { - return MP_MEM; - } -#endif - /* now setup montgomery */ if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) { goto LBL_M; @@ -2449,9 +2438,6 @@ int mp_exptmod_base_2(mp_int * X, mp_int * P, mp_int * Y) LBL_RES:mp_clear (res); LBL_M: -#ifdef WOLFSSL_SMALL_STACK - XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif return err; } @@ -2526,12 +2512,13 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) } #ifdef WOLFSSL_SMALL_STACK - W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + W = (mp_word*)XMALLOC(sizeof(mp_word) * (n->used * 2 + 1), NULL, + DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif - XMEMSET(W, 0, (n->used * 2 + 1) * sizeof(mp_word)); + XMEMSET(W, 0, sizeof(mp_word) * (n->used * 2 + 1)); /* first we have to get the digits of the input into * an array of double precision words W[...] @@ -3349,7 +3336,7 @@ int fast_s_mp_sqr (mp_int * a, mp_int * b) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * pa, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -3468,7 +3455,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * pa, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif @@ -4203,13 +4190,12 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) return MP_RANGE; /* TAO range check */ #ifdef WOLFSSL_SMALL_STACK - W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * pa, NULL, DYNAMIC_TYPE_BIGINT); if (W == NULL) return MP_MEM; #endif /* number of output digits to produce */ - pa = a->used + b->used; _W = 0; for (ix = digs; ix < pa; ix++) { /* JRB, have a->dp check at top of function*/ int tx, ty, iy; diff --git a/wolfcrypt/src/kdf.c b/wolfcrypt/src/kdf.c index 7c144ab89..c7f6e0f95 100644 --- a/wolfcrypt/src/kdf.c +++ b/wolfcrypt/src/kdf.c @@ -435,13 +435,25 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, { int ret = 0; int idx = 0; + #ifdef WOLFSSL_SMALL_STACK + byte* data; + #else byte data[MAX_TLS13_HKDF_LABEL_SZ]; + #endif /* okmLen (2) + protocol|label len (1) + info len(1) + protocollen + * labellen + infolen */ idx = 4 + protocolLen + labelLen + infoLen; - if (idx > MAX_TLS13_HKDF_LABEL_SZ) + if (idx > MAX_TLS13_HKDF_LABEL_SZ) { return BUFFER_E; + } + + #ifdef WOLFSSL_SMALL_STACK + data = (byte*)XMALLOC(idx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) { + return MEMORY_E; + } + #endif idx = 0; /* Output length. */ @@ -484,6 +496,9 @@ int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, #ifdef WOLFSSL_CHECK_MEM_ZERO wc_MemZero_Check(data, MAX_TLS13_HKDF_LABEL_SZ); + #endif + #ifdef WOLFSSL_SMALL_STACK + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif return ret; } diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index fda36af7b..3be80672b 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -1793,19 +1793,36 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash) { int ret; - wc_Sha224 tmpSha224; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha224* tmpSha224; + #else + wc_Sha224 tmpSha224[1]; + #endif - wc_InitSha224(&tmpSha224); - if (sha224 == NULL || hash == NULL) + if (sha224 == NULL || hash == NULL) { return BAD_FUNC_ARG; - - ret = wc_Sha224Copy(sha224, &tmpSha224); - if (ret == 0) { - ret = wc_Sha224Final(&tmpSha224, hash); - wc_Sha224Free(&tmpSha224); } + + #ifdef WOLFSSL_SMALL_STACK + tmpSha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpSha224 == NULL) { + return MEMORY_E; + } + #endif + + ret = wc_Sha224Copy(sha224, tmpSha224); + if (ret == 0) { + ret = wc_Sha224Final(tmpSha224, hash); + wc_Sha224Free(tmpSha224); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmpSha224, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } + int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) { int ret = 0; @@ -1894,44 +1911,54 @@ int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz) int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) { int ret; - wc_Sha256 tmpSha256; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha256* tmpSha256; +#else + wc_Sha256 tmpSha256[1]; +#endif - if (sha256 == NULL || hash == NULL) + if (sha256 == NULL || hash == NULL) { return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpSha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpSha256 == NULL) { + return MEMORY_E; + } +#endif #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW) - /* ESP32 hardware can only handle only 1 active hardware hashing * at a time. If the mutex lock is acquired the first time then * that Sha256 instance has exclusive access to hardware. The * final or free needs to release the mutex. Operations that * do not get the lock fallback to software based Sha256 */ - if(sha256->ctx.mode == ESP32_SHA_INIT){ + if (sha256->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha256->ctx); } - if(sha256->ctx.mode == ESP32_SHA_HW) - { + if (sha256->ctx.mode == ESP32_SHA_HW) { esp_sha256_digest_process(sha256, 0); } #endif - ret = wc_Sha256Copy(sha256, &tmpSha256); + + ret = wc_Sha256Copy(sha256, tmpSha256); if (ret == 0) { - ret = wc_Sha256Final(&tmpSha256, hash); + ret = wc_Sha256Final(tmpSha256, hash); -#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW) - { + #if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW) sha256->ctx.mode = ESP32_SHA_SW; - } -#endif + #endif - wc_Sha256Free(&tmpSha256); + wc_Sha256Free(tmpSha256); } -#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW) - /* TODO: Make sure the ESP32 crypto mutex is released (in case final is not - * called */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpSha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif + return ret; } int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index a0cf26e28..d42806976 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -1502,29 +1502,49 @@ static int Sha512_Family_GetHash(wc_Sha512* sha512, byte* hash, int (*finalfp)(wc_Sha512*, byte*)) { int ret; - wc_Sha512 tmpSha512; - - if (sha512 == NULL || hash == NULL) - return BAD_FUNC_ARG; - -#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ - !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) - if(sha512->ctx.mode == ESP32_SHA_INIT) { - esp_sha_try_hw_lock(&sha512->ctx); - } - if(sha512->ctx.mode != ESP32_SHA_SW) - esp_sha512_digest_process(sha512, 0); +#ifdef WOLFSSL_SMALL_STACK + wc_Sha512* tmpSha512; +#else + wc_Sha512 tmpSha512[1]; #endif - ret = wc_Sha512Copy(sha512, &tmpSha512); + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpSha512 = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpSha512 == NULL) { + return MEMORY_E; + } +#endif + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if (sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + if (sha512->ctx.mode != ESP32_SHA_SW) { + esp_sha512_digest_process(sha512, 0); + } +#endif + + ret = wc_Sha512Copy(sha512, tmpSha512); if (ret == 0) { - ret = finalfp(&tmpSha512, hash); -#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + ret = finalfp(tmpSha512, hash); + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) sha512->ctx.mode = ESP32_SHA_SW;; #endif - wc_Sha512Free(&tmpSha512); + wc_Sha512Free(tmpSha512); } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpSha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } @@ -1735,36 +1755,58 @@ int wc_Sha512_256Transform(wc_Sha512* sha, const unsigned char* data) int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) { int ret; - wc_Sha384 tmpSha384; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha384* tmpSha384; +#else + wc_Sha384 tmpSha384[1]; +#endif - if (sha384 == NULL || hash == NULL) + if (sha384 == NULL || hash == NULL) { return BAD_FUNC_ARG; -#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + } + +#ifdef WOLFSSL_SMALL_STACK + tmpSha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpSha384 == NULL) { + return MEMORY_E; + } +#endif + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) - if(sha384->ctx.mode == ESP32_SHA_INIT) { + if (sha384->ctx.mode == ESP32_SHA_INIT) { esp_sha_try_hw_lock(&sha384->ctx); } - if(sha384->ctx.mode != ESP32_SHA_SW) { + if (sha384->ctx.mode != ESP32_SHA_SW) { esp_sha512_digest_process(sha384, 0); } #endif - ret = wc_Sha384Copy(sha384, &tmpSha384); + ret = wc_Sha384Copy(sha384, tmpSha384); if (ret == 0) { - ret = wc_Sha384Final(&tmpSha384, hash); -#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + ret = wc_Sha384Final(tmpSha384, hash); + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) sha384->ctx.mode = ESP32_SHA_SW; #endif - wc_Sha384Free(&tmpSha384); + wc_Sha384Free(tmpSha384); } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpSha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } + int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) { int ret = 0; - if (src == NULL || dst == NULL) + if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; + } XMEMCPY(dst, src, sizeof(wc_Sha384)); #ifdef WOLFSSL_SMALL_STACK_CACHE diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a2cce5529..5f23f89a1 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -872,7 +872,7 @@ enum Misc_ASN { ASN_BOOL_SIZE = 2, /* including type */ ASN_ECC_HEADER_SZ = 2, /* String type + 1 byte len */ ASN_ECC_CONTEXT_SZ = 2, /* Content specific type + 1 byte len */ -#ifdef NO_SHA +#if defined(NO_SHA) || (!defined(NO_SHA256) && defined(WC_ASN_HASH_SHA256)) KEYID_SIZE = WC_SHA256_DIGEST_SIZE, #else KEYID_SIZE = WC_SHA_DIGEST_SIZE, @@ -1591,7 +1591,7 @@ struct DecodedCert { byte issuerHash[KEYID_SIZE]; /* hash of all Names */ #ifdef HAVE_OCSP byte subjectKeyHash[KEYID_SIZE]; /* hash of the public Key */ - byte issuerKeyHash[KEYID_SIZE]; /* hash of the public Key */ + byte issuerKeyHash[KEYID_SIZE]; /* hash of the public Key */ #endif /* HAVE_OCSP */ const byte* signature; /* not owned, points into raw cert */ char* subjectCN; /* CommonName */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 0f212b5fd..b46b16e0b 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -285,11 +285,12 @@ typedef int (wc_pem_password_cb)(char* passwd, int sz, int rw, void* userdata); #endif typedef struct EncryptedInfo { - wc_pem_password_cb* passwd_cb; - void* passwd_userdata; - long consumed; /* tracks PEM bytes consumed */ +#ifdef WOLFSSL_ENCRYPTED_KEYS + wc_pem_password_cb* passwd_cb; + void* passwd_userdata; + int cipherType; word32 keySz; word32 ivSz; /* salt or encrypted IV size */ @@ -298,6 +299,7 @@ typedef struct EncryptedInfo { byte iv[IV_SZ]; /* salt or encrypted IV */ word16 set:1; /* if encryption set */ +#endif } EncryptedInfo; diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index 1f2537187..dbf000605 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -2377,9 +2377,6 @@ extern void uITRON4_free(void *p) ; #ifndef USE_WOLF_STRTOK #define USE_WOLF_STRTOK #endif - #ifndef WOLFSSL_SP_DIV_WORD_HALF - #define WOLFSSL_SP_DIV_WORD_HALF - #endif #ifndef WOLFSSL_OLD_PRIME_CHECK #define WOLFSSL_OLD_PRIME_CHECK #endif From 0006d1f91c48730fd3733b44ce1522277e728b5f Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 4 Oct 2022 08:39:42 -0700 Subject: [PATCH 3/3] Fix benchmark with small stack and `WOLFSSL_RSA_VERIFY_ONLY`. --- wolfcrypt/benchmark/benchmark.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 1ff29d5ea..c39736322 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -5645,13 +5645,14 @@ static void bench_rsa_helper(int useDeviceID, RsaKey rsaKey[BENCH_MAX_PENDING], ret = MEMORY_E; goto exit; } -#ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC + +#ifndef WOLFSSL_RSA_VERIFY_ONLY + #ifdef WC_DECLARE_VAR_IS_HEAP_ALLOC if (message == NULL) { ret = MEMORY_E; goto exit; } -#endif -#ifndef WOLFSSL_RSA_VERIFY_ONLY + #endif XMEMCPY(message, messageStr, len); #endif @@ -5807,7 +5808,9 @@ exit: #if !defined(WOLFSSL_RSA_VERIFY_INLINE) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) WC_FREE_ARRAY_DYNAMIC(out, BENCH_MAX_PENDING, HEAP_HINT); #endif +#ifndef WOLFSSL_RSA_VERIFY_ONLY WC_FREE_VAR(message, HEAP_HINT); +#endif } void bench_rsa(int useDeviceID)