tls: refactoring p_hash to reduce stack usage:

--- variable previous moved to the heap (up to 48 bytes saved)
--- variable current moved to the heap (up to 48 bytes saved)
--- variable hmac moved to the heap (sizeof(Hmac) bytes saved)
This commit is contained in:
Moisés Guimarães
2014-07-29 12:40:01 -03:00
parent 9429f07a8a
commit e3db86753c

174
src/tls.c
View File

@ -46,109 +46,131 @@
#ifdef CYASSL_SHA384 #ifdef CYASSL_SHA384
#define PHASH_MAX_DIGEST_SIZE SHA384_DIGEST_SIZE #define P_HASH_MAX_SIZE SHA384_DIGEST_SIZE
#else #else
#define PHASH_MAX_DIGEST_SIZE SHA256_DIGEST_SIZE #define P_HASH_MAX_SIZE SHA256_DIGEST_SIZE
#endif #endif
/* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */ /* compute p_hash for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1 PRF */
static int p_hash(byte* result, word32 resLen, const byte* secret, static int p_hash(byte* result, word32 resLen, const byte* secret,
word32 secLen, const byte* seed, word32 seedLen, int hash) word32 secLen, const byte* seed, word32 seedLen, int hash)
{ {
word32 len = PHASH_MAX_DIGEST_SIZE; word32 len = P_HASH_MAX_SIZE;
word32 times; word32 times;
word32 lastLen; word32 lastLen;
word32 lastTime; word32 lastTime;
word32 i; word32 i;
word32 idx = 0; word32 idx = 0;
int ret; int ret = 0;
byte previous[PHASH_MAX_DIGEST_SIZE]; /* max size */ #ifdef CYASSL_SMALL_STACK
byte current[PHASH_MAX_DIGEST_SIZE]; /* max size */ byte* previous;
byte* current;
Hmac* hmac;
#else
byte previous[P_HASH_MAX_SIZE]; /* max size */
byte current[P_HASH_MAX_SIZE]; /* max size */
Hmac hmac[1];
#endif
Hmac hmac; #ifdef CYASSL_SMALL_STACK
previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
current = (byte*)XMALLOC(P_HASH_MAX_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (previous == NULL || current == NULL || hmac == NULL) {
if (previous) XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (current) XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (hmac) XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
switch (hash) { switch (hash) {
#ifndef NO_MD5 #ifndef NO_MD5
case md5_mac: case md5_mac:
{ hash = MD5;
len = MD5_DIGEST_SIZE; len = MD5_DIGEST_SIZE;
hash = MD5; break;
}
break;
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
case sha256_mac: case sha256_mac:
{ hash = SHA256;
len = SHA256_DIGEST_SIZE; len = SHA256_DIGEST_SIZE;
hash = SHA256; break;
}
break;
#endif #endif
#ifdef CYASSL_SHA384 #ifdef CYASSL_SHA384
case sha384_mac: case sha384_mac:
{ hash = SHA384;
len = SHA384_DIGEST_SIZE; len = SHA384_DIGEST_SIZE;
hash = SHA384; break;
} #endif
break;
#ifndef NO_SHA
case sha_mac:
default:
hash = SHA;
len = SHA_DIGEST_SIZE;
break;
#endif #endif
#ifndef NO_SHA
case sha_mac:
default:
{
len = SHA_DIGEST_SIZE;
hash = SHA;
}
break;
#endif
} }
times = resLen / len; times = resLen / len;
lastLen = resLen % len; lastLen = resLen % len;
if (lastLen) times += 1;
if (lastLen)
times += 1;
lastTime = times - 1; lastTime = times - 1;
ret = HmacSetKey(&hmac, hash, secret, secLen); if ((ret = HmacSetKey(hmac, hash, secret, secLen)) == 0) {
if (ret != 0) if ((ret = HmacUpdate(hmac, seed, seedLen)) == 0) { /* A0 = seed */
return ret; if ((ret = HmacFinal(hmac, previous)) == 0) { /* A1 */
ret = HmacUpdate(&hmac, seed, seedLen); /* A0 = seed */ for (i = 0; i < times; i++) {
if (ret != 0) ret = HmacUpdate(hmac, previous, len);
return ret; if (ret != 0)
ret = HmacFinal(&hmac, previous); /* A1 */ break;
if (ret != 0) ret = HmacUpdate(hmac, seed, seedLen);
return ret; if (ret != 0)
break;
ret = HmacFinal(hmac, current);
if (ret != 0)
break;
for (i = 0; i < times; i++) { if ((i == lastTime) && lastLen)
ret = HmacUpdate(&hmac, previous, len); XMEMCPY(&result[idx], current,
if (ret != 0) min(lastLen, P_HASH_MAX_SIZE));
return ret; else {
ret = HmacUpdate(&hmac, seed, seedLen); XMEMCPY(&result[idx], current, len);
if (ret != 0) idx += len;
return ret; ret = HmacUpdate(hmac, previous, len);
ret = HmacFinal(&hmac, current); if (ret != 0)
if (ret != 0) break;
return ret; ret = HmacFinal(hmac, previous);
if (ret != 0)
if ( (i == lastTime) && lastLen) break;
XMEMCPY(&result[idx], current, min(lastLen, sizeof(current))); }
else { }
XMEMCPY(&result[idx], current, len); }
idx += len;
ret = HmacUpdate(&hmac, previous, len);
if (ret != 0)
return ret;
ret = HmacFinal(&hmac, previous);
if (ret != 0)
return ret;
} }
} }
XMEMSET(previous, 0, sizeof previous);
XMEMSET(current, 0, sizeof current);
XMEMSET(&hmac, 0, sizeof hmac);
return 0; XMEMSET(previous, 0, P_HASH_MAX_SIZE);
XMEMSET(current, 0, P_HASH_MAX_SIZE);
XMEMSET(hmac, 0, sizeof(Hmac));
#ifdef CYASSL_SMALL_STACK
XFREE(previous, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(current, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hmac, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
} }
#undef P_HASH_MAX_SIZE
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS