internal.c: refactoring DoServerKeyExchange to reduce stack usage:

--- using goto to centralize resources deallocation.
This commit is contained in:
Moisés Guimarães 2014-10-21 12:39:02 -03:00
parent 5056ebe829
commit a60332d9a3

View File

@ -9457,6 +9457,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
word16 length = 0; word16 length = 0;
word32 begin = *inOutIdx; word32 begin = *inOutIdx;
int ret = 0; int ret = 0;
#define ERROR_OUT(err, exit) do { ret = err; goto exit; } while(0)
(void)length; /* shut up compiler warnings */ (void)length; /* shut up compiler warnings */
(void)begin; (void)begin;
@ -9691,8 +9692,8 @@ static void PickHashSigAlgo(CYASSL* ssl,
Md5* md5 = NULL; Md5* md5 = NULL;
Sha* sha = NULL; Sha* sha = NULL;
#else #else
Md5 md5[0]; Md5 md5[1];
Sha sha[0]; Sha sha[1];
#endif #endif
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
@ -9700,7 +9701,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
Sha256* sha256 = NULL; Sha256* sha256 = NULL;
byte* hash256 = NULL; byte* hash256 = NULL;
#else #else
Sha256 sha256[0]; Sha256 sha256[1];
byte hash256[SHA256_DIGEST_SIZE]; byte hash256[SHA256_DIGEST_SIZE];
#endif #endif
#endif #endif
@ -9709,7 +9710,7 @@ static void PickHashSigAlgo(CYASSL* ssl,
Sha384* sha384 = NULL; Sha384* sha384 = NULL;
byte* hash384 = NULL; byte* hash384 = NULL;
#else #else
Sha384 sha384[0]; Sha384 sha384[1];
byte hash384[SHA384_DIGEST_SIZE]; byte hash384[SHA384_DIGEST_SIZE];
#endif #endif
#endif #endif
@ -9726,102 +9727,70 @@ static void PickHashSigAlgo(CYASSL* ssl,
/* save message for hash verify */ /* save message for hash verify */
if (verifySz > MAX_DH_SZ) if (verifySz > MAX_DH_SZ)
return BUFFER_ERROR; ERROR_OUT(BUFFER_ERROR, done);
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL, messageVerify = (byte*)XMALLOC(MAX_DH_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
if (messageVerify == NULL) if (messageVerify == NULL)
return MEMORY_E; ERROR_OUT(MEMORY_E, done);
#endif #endif
XMEMCPY(messageVerify, input + begin, verifySz); XMEMCPY(messageVerify, input + begin, verifySz);
if (IsAtLeastTLSv1_2(ssl)) { if (IsAtLeastTLSv1_2(ssl)) {
if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size) { if ((*inOutIdx - begin) + ENUM_LEN + ENUM_LEN > size)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(BUFFER_ERROR, done);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BUFFER_ERROR;
}
hashAlgo = input[(*inOutIdx)++]; hashAlgo = input[(*inOutIdx)++];
sigAlgo = input[(*inOutIdx)++]; sigAlgo = input[(*inOutIdx)++];
} }
/* signature */ /* signature */
if ((*inOutIdx - begin) + OPAQUE16_LEN > size) { if ((*inOutIdx - begin) + OPAQUE16_LEN > size)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(BUFFER_ERROR, done);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BUFFER_ERROR;
}
ato16(input + *inOutIdx, &length); ato16(input + *inOutIdx, &length);
*inOutIdx += OPAQUE16_LEN; *inOutIdx += OPAQUE16_LEN;
if ((*inOutIdx - begin) + length > size) { if ((*inOutIdx - begin) + length > size)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(BUFFER_ERROR, done);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BUFFER_ERROR;
}
/* inOutIdx updated at the end of the function */ /* inOutIdx updated at the end of the function */
/* verify signature */ /* verify signature */
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); hash = (byte*)XMALLOC(FINISHED_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (hash == NULL) { if (hash == NULL)
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER); ERROR_OUT(MEMORY_E, done);
return MEMORY_E;
}
#endif #endif
#ifndef NO_OLD_TLS #ifndef NO_OLD_TLS
/* md5 */ /* md5 */
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); md5 = (Md5*)XMALLOC(sizeof(Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (md5 == NULL) { if (md5 == NULL)
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); ERROR_OUT(MEMORY_E, done);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif #endif
InitMd5(md5); InitMd5(md5);
Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN); Md5Update(md5, ssl->arrays->clientRandom, RAN_LEN);
Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN); Md5Update(md5, ssl->arrays->serverRandom, RAN_LEN);
Md5Update(md5, messageVerify, verifySz); Md5Update(md5, messageVerify, verifySz);
Md5Final(md5, hash); Md5Final(md5, hash);
#ifdef CYASSL_SMALL_STACK
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
/* sha */ /* sha */
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); sha = (Sha*)XMALLOC(sizeof(Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (sha == NULL) { if (sha == NULL)
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER); ERROR_OUT(MEMORY_E, done);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif #endif
ret = InitSha(sha); ret = InitSha(sha);
if (ret != 0) { if (ret != 0)
#ifdef CYASSL_SMALL_STACK goto done;
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN); ShaUpdate(sha, ssl->arrays->clientRandom, RAN_LEN);
ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN); ShaUpdate(sha, ssl->arrays->serverRandom, RAN_LEN);
ShaUpdate(sha, messageVerify, verifySz); ShaUpdate(sha, messageVerify, verifySz);
ShaFinal(sha, hash + MD5_DIGEST_SIZE); ShaFinal(sha, hash + MD5_DIGEST_SIZE);
#ifdef CYASSL_SMALL_STACK
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#endif #endif
#ifndef NO_SHA256 #ifndef NO_SHA256
@ -9830,30 +9799,16 @@ static void PickHashSigAlgo(CYASSL* ssl,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL, hash256 = (byte*)XMALLOC(SHA256_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
if (sha256 == NULL || hash256 == NULL) { if (sha256 == NULL || hash256 == NULL)
XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); ERROR_OUT(MEMORY_E, done);
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif #endif
if (!(ret = InitSha256(sha256)) if (!(ret = InitSha256(sha256))
&& !(ret = Sha256Update(sha256, ssl->arrays->clientRandom, RAN_LEN)) && !(ret = Sha256Update(sha256, ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = Sha256Update(sha256, ssl->arrays->serverRandom, RAN_LEN)) && !(ret = Sha256Update(sha256, ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = Sha256Update(sha256, messageVerify, verifySz))) && !(ret = Sha256Update(sha256, messageVerify, verifySz)))
ret = Sha256Final(sha256, hash256); ret = Sha256Final(sha256, hash256);
#ifdef CYASSL_SMALL_STACK if (ret != 0)
XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); goto done;
#endif
if (ret != 0) {
#ifdef CYASSL_SMALL_STACK
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
#endif #endif
#ifdef CYASSL_SHA384 #ifdef CYASSL_SHA384
@ -9862,80 +9817,47 @@ static void PickHashSigAlgo(CYASSL* ssl,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL, hash384 = (byte*)XMALLOC(SHA384_DIGEST_SIZE, NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
if (sha384 == NULL || hash384 == NULL) { if (sha384 == NULL || hash384 == NULL)
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); ERROR_OUT(MEMORY_E, done);
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif #endif
if (!(ret = InitSha384(sha384)) if (!(ret = InitSha384(sha384))
&& !(ret = Sha384Update(sha384, ssl->arrays->clientRandom, RAN_LEN)) && !(ret = Sha384Update(sha384, ssl->arrays->clientRandom, RAN_LEN))
&& !(ret = Sha384Update(sha384, ssl->arrays->serverRandom, RAN_LEN)) && !(ret = Sha384Update(sha384, ssl->arrays->serverRandom, RAN_LEN))
&& !(ret = Sha384Update(sha384, messageVerify, verifySz))) && !(ret = Sha384Update(sha384, messageVerify, verifySz)))
ret = Sha384Final(sha384, hash384); ret = Sha384Final(sha384, hash384);
#ifdef CYASSL_SMALL_STACK if (ret != 0)
XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); goto done;
#endif
if (ret != 0) {
#ifdef CYASSL_SMALL_STACK
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret;
}
#endif #endif
#ifdef CYASSL_SMALL_STACK
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifndef NO_RSA #ifndef NO_RSA
/* rsa */ /* rsa */
if (sigAlgo == rsa_sa_algo) if (sigAlgo == rsa_sa_algo)
{ {
byte* out = NULL; byte* out = NULL;
byte doUserRsa = 0; byte doUserRsa = 0;
word32 verifiedSz = 0;
#ifdef HAVE_PK_CALLBACKS #ifdef HAVE_PK_CALLBACKS
if (ssl->ctx->RsaVerifyCb) if (ssl->ctx->RsaVerifyCb)
doUserRsa = 1; doUserRsa = 1;
#endif /*HAVE_PK_CALLBACKS */ #endif /*HAVE_PK_CALLBACKS */
if (!ssl->peerRsaKeyPresent) { if (!ssl->peerRsaKeyPresent)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(NO_PEER_KEY, done);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NO_PEER_KEY;
}
if (doUserRsa) { if (doUserRsa) {
#ifdef HAVE_PK_CALLBACKS #ifdef HAVE_PK_CALLBACKS
ret = ssl->ctx->RsaVerifyCb(ssl, (byte *) input + *inOutIdx, verifiedSz = ssl->ctx->RsaVerifyCb(ssl,
length, &out, (byte *)input + *inOutIdx,
ssl->buffers.peerRsaKey.buffer, length, &out,
ssl->buffers.peerRsaKey.length, ssl->buffers.peerRsaKey.buffer,
ssl->RsaVerifyCtx); ssl->buffers.peerRsaKey.length,
ssl->RsaVerifyCtx);
#endif /*HAVE_PK_CALLBACKS */ #endif /*HAVE_PK_CALLBACKS */
} }
else { else
ret = RsaSSL_VerifyInline((byte *) input + *inOutIdx, length, verifiedSz = RsaSSL_VerifyInline((byte *)input + *inOutIdx,
&out, ssl->peerRsaKey); length, &out, ssl->peerRsaKey);
}
if (IsAtLeastTLSv1_2(ssl)) { if (IsAtLeastTLSv1_2(ssl)) {
word32 encSigSz; word32 encSigSz;
@ -9979,55 +9901,25 @@ static void PickHashSigAlgo(CYASSL* ssl,
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER); DYNAMIC_TYPE_TMP_BUFFER);
if (encodedSig == NULL) { if (encodedSig == NULL)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(MEMORY_E, done);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return MEMORY_E;
}
#endif #endif
encSigSz = EncodeSignature(encodedSig, digest, digestSz, typeH); encSigSz = EncodeSignature(encodedSig, digest, digestSz, typeH);
if (encSigSz != (word32)ret || !out || XMEMCMP(out, encodedSig, if (encSigSz != verifiedSz || !out || XMEMCMP(out, encodedSig,
min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0)
#ifdef CYASSL_SMALL_STACK ret = VERIFY_SIGN_ERROR;
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return VERIFY_SIGN_ERROR;
}
#ifdef CYASSL_SMALL_STACK #ifdef CYASSL_SMALL_STACK
XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(encodedSig, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif #endif
if (ret != 0)
goto done;
} }
else { else if (verifiedSz != FINISHED_SZ || !out || XMEMCMP(out,
if (ret != FINISHED_SZ || !out || XMEMCMP(out, hash, FINISHED_SZ) != 0)
hash, FINISHED_SZ) != 0) { ERROR_OUT(VERIFY_SIGN_ERROR, done);
#ifdef CYASSL_SMALL_STACK
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return VERIFY_SIGN_ERROR;
}
}
} else } else
#endif #endif
#ifdef HAVE_ECC #ifdef HAVE_ECC
@ -10048,18 +9940,8 @@ static void PickHashSigAlgo(CYASSL* ssl,
doUserEcc = 1; doUserEcc = 1;
#endif #endif
if (!ssl->peerEccDsaKeyPresent) { if (!ssl->peerEccDsaKeyPresent)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(NO_PEER_KEY, done);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return NO_PEER_KEY;
}
if (IsAtLeastTLSv1_2(ssl)) { if (IsAtLeastTLSv1_2(ssl)) {
if (hashAlgo == sha_mac) { if (hashAlgo == sha_mac) {
@ -10094,47 +9976,37 @@ static void PickHashSigAlgo(CYASSL* ssl,
ret = ecc_verify_hash(input + *inOutIdx, length, ret = ecc_verify_hash(input + *inOutIdx, length,
digest, digestSz, &verify, ssl->peerEccDsaKey); digest, digestSz, &verify, ssl->peerEccDsaKey);
} }
if (ret != 0 || verify == 0) { if (ret != 0 || verify == 0)
#ifdef CYASSL_SMALL_STACK ERROR_OUT(VERIFY_SIGN_ERROR, done);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return VERIFY_SIGN_ERROR;
}
} }
else { else
#endif /* HAVE_ECC */ #endif /* HAVE_ECC */
#ifdef CYASSL_SMALL_STACK ERROR_OUT(ALGO_ID_E, done);
#ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ALGO_ID_E;
}
/* signature length */ /* signature length */
*inOutIdx += length; *inOutIdx += length;
ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE;
#ifdef CYASSL_SMALL_STACK done:
#ifdef CYASSL_SMALL_STACK
#ifndef NO_OLD_TLS
XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
#ifndef NO_SHA256 #ifndef NO_SHA256
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif #endif
#ifdef CYASSL_SHA384 #ifdef CYASSL_SHA384
XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif XFREE(hash384, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif #endif
XFREE(hash, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(messageVerify, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
if (ret != 0)
return ret;
} }
if (ssl->keys.encryptionOn) { if (ssl->keys.encryptionOn) {