From eaaf0a7c28db36b4a4ef3c74889f6cb9d15041e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mois=C3=A9s=20Guimar=C3=A3es?= Date: Mon, 21 Apr 2014 14:45:07 -0300 Subject: [PATCH] pwdbased: PBKDF2 refactory to reduce stack usage: (up to 64 bytes - pointer size) moved to the heap. --- buffer variable moved to the heap; (up to 64 bytes) --- returns changed to breaks pwdbased: PKCS12_PBKDF refactory to reduce stack usage: (up to 1023 + 128 bytes - pointer sizes) moved to the heap. --- staticBuffer variable changed to have size = 1 byte (1023 bytes saved) --- Ai variable moved to the heap; (up to 64 bytes) --- B variable moved to the heap; (up to 64 bytes) hmac: HKDF refactory to restore previous behavior inside while loop. --- ctaocrypt/src/hmac.c | 36 +++++++++++---- ctaocrypt/src/pwdbased.c | 99 +++++++++++++++++++++++++++++++--------- 2 files changed, 105 insertions(+), 30 deletions(-) diff --git a/ctaocrypt/src/hmac.c b/ctaocrypt/src/hmac.c index 009864d16..6f4b32c2a 100644 --- a/ctaocrypt/src/hmac.c +++ b/ctaocrypt/src/hmac.c @@ -767,19 +767,36 @@ int HKDF(int type, const byte* inKey, word32 inKeySz, saltSz = hashSz; } - if ((ret = HmacSetKey(&myHmac, type, localSalt, saltSz)) == 0) - if ((ret = HmacUpdate(&myHmac, inKey, inKeySz)) == 0) - ret = HmacFinal(&myHmac, prk); + do { + ret = HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret != 0) + break; + ret = HmacUpdate(&myHmac, inKey, inKeySz); + if (ret != 0) + break; + ret = HmacFinal(&myHmac, prk); + } while (0); - while (ret == 0 && outIdx < outSz) { + if (ret == 0) { + while (outIdx < outSz) { int tmpSz = (n == 1) ? 0 : hashSz; word32 left = outSz - outIdx; - if ((ret = HmacSetKey(&myHmac, type, prk, hashSz)) == 0) - if ((ret = HmacUpdate(&myHmac, tmp, tmpSz)) == 0) - if ((ret = HmacUpdate(&myHmac, info, infoSz)) == 0) - if ((ret = HmacUpdate(&myHmac, &n, 1)) == 0) - ret = HmacFinal(&myHmac, tmp); + ret = HmacSetKey(&myHmac, type, prk, hashSz); + if (ret != 0) + break; + ret = HmacUpdate(&myHmac, tmp, tmpSz); + if (ret != 0) + break; + ret = HmacUpdate(&myHmac, info, infoSz); + if (ret != 0) + break; + ret = HmacUpdate(&myHmac, &n, 1); + if (ret != 0) + break; + ret = HmacFinal(&myHmac, tmp); + if (ret != 0) + break; left = min(left, (word32)hashSz); XMEMCPY(out+outIdx, tmp, left); @@ -787,6 +804,7 @@ int HKDF(int type, const byte* inKey, word32 inKeySz, outIdx += hashSz; n++; } + } #ifdef CYASSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/ctaocrypt/src/pwdbased.c b/ctaocrypt/src/pwdbased.c index b9d3ba2a7..9ae31e22d 100644 --- a/ctaocrypt/src/pwdbased.c +++ b/ctaocrypt/src/pwdbased.c @@ -124,7 +124,11 @@ int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, int hLen; int j, ret; Hmac hmac; +#ifdef CYASSL_SMALL_STACK + byte* buffer; +#else byte buffer[MAX_DIGEST_SIZE]; +#endif if (hashType == MD5) { hLen = MD5_DIGEST_SIZE; @@ -145,16 +149,21 @@ int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, else return BAD_FUNC_ARG; - ret = HmacSetKey(&hmac, hashType, passwd, pLen); - if (ret != 0) - return ret; +#ifdef CYASSL_SMALL_STACK + buffer = (byte*)XMALLOC(MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; +#endif + ret = HmacSetKey(&hmac, hashType, passwd, pLen); + + if (ret == 0) { while (kLen) { int currentLen; ret = HmacUpdate(&hmac, salt, sLen); if (ret != 0) - return ret; + break; /* encode i */ for (j = 0; j < 4; j++) { @@ -162,12 +171,16 @@ int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, ret = HmacUpdate(&hmac, &b, 1); if (ret != 0) - return ret; + break; } + /* check ret from inside for loop */ + if (ret != 0) + break; + ret = HmacFinal(&hmac, buffer); if (ret != 0) - return ret; + break; currentLen = min(kLen, hLen); XMEMCPY(output, buffer, currentLen); @@ -175,21 +188,37 @@ int PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, for (j = 1; j < iterations; j++) { ret = HmacUpdate(&hmac, buffer, hLen); if (ret != 0) - return ret; + break; ret = HmacFinal(&hmac, buffer); if (ret != 0) - return ret; + break; xorbuf(output, buffer, currentLen); } + /* check ret from inside for loop */ + if (ret != 0) + break; + output += currentLen; kLen -= currentLen; i++; } + } - return 0; +#ifdef CYASSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; } +#ifdef CYASSL_SHA512 +#define PBKDF_DIGEST_SIZE SHA512_BLOCK_SIZE +#elif !defined(NO_SHA256) +#define PBKDF_DIGEST_SIZE SHA256_BLOCK_SIZE +#else +#define PBKDF_DIGEST_SIZE SHA_DIGEST_SIZE +#endif int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, int saltLen, int iterations, int kLen, int hashType, int id) @@ -200,17 +229,19 @@ int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, int ret = 0; int i; byte *D, *S, *P, *I; - byte staticBuffer[1024]; - byte* buffer = staticBuffer; -#ifdef CYASSL_SHA512 - byte Ai[SHA512_DIGEST_SIZE]; - byte B[SHA512_BLOCK_SIZE]; -#elif !defined(NO_SHA256) - byte Ai[SHA256_DIGEST_SIZE]; - byte B[SHA256_BLOCK_SIZE]; +#ifdef CYASSL_SMALL_STACK + byte staticBuffer[1]; /* force dynamic usage */ #else - byte Ai[SHA_DIGEST_SIZE]; - byte B[SHA_BLOCK_SIZE]; + byte staticBuffer[1024]; +#endif + byte* buffer = staticBuffer; + +#ifdef CYASSL_SMALL_STACK + byte* Ai; + byte* B; +#else + byte Ai[PBKDF_DIGEST_SIZE]; + byte B[PBKDF_DIGEST_SIZE]; #endif if (!iterations) @@ -237,7 +268,19 @@ int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, } #endif else - return BAD_FUNC_ARG; + return BAD_FUNC_ARG; + +#ifdef CYASSL_SMALL_STACK + Ai = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (Ai == NULL) + return MEMORY_E; + + B = (byte*)XMALLOC(PBKDF_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (B == NULL) { + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif dLen = v; sLen = v * ((saltLen + v - 1) / v); @@ -251,7 +294,13 @@ int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, if (totalLen > sizeof(staticBuffer)) { buffer = (byte*)XMALLOC(totalLen, 0, DYNAMIC_TYPE_KEY); - if (buffer == NULL) return MEMORY_E; + if (buffer == NULL) { +#ifdef CYASSL_SMALL_STACK + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } dynamic = 1; } @@ -410,8 +459,16 @@ int PKCS12_PBKDF(byte* output, const byte* passwd, int passLen,const byte* salt, } if (dynamic) XFREE(buffer, 0, DYNAMIC_TYPE_KEY); + +#ifdef CYASSL_SMALL_STACK + XFREE(Ai, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; } +#undef PBKDF_DIGEST_SIZE + #endif /* NO_PWDBASED */