mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 10:47:28 +02:00
Fix for SRP leaks with WOLFSSL_SMALL_STACK_CACHE
This commit is contained in:
39
src/ssl.c
39
src/ssl.c
@ -403,7 +403,7 @@ WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap)
|
|||||||
#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
|
#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
|
||||||
&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
|
&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
|
||||||
else {
|
else {
|
||||||
ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
|
ctx->srp = (Srp*)XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP);
|
||||||
if (ctx->srp == NULL){
|
if (ctx->srp == NULL){
|
||||||
WOLFSSL_MSG("Init CTX failed");
|
WOLFSSL_MSG("Init CTX failed");
|
||||||
wolfSSL_CTX_free(ctx);
|
wolfSSL_CTX_free(ctx);
|
||||||
@ -451,7 +451,7 @@ void wolfSSL_CTX_free(WOLFSSL_CTX* ctx)
|
|||||||
if (ctx) {
|
if (ctx) {
|
||||||
#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
|
#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \
|
||||||
&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
|
&& !defined(NO_SHA256) && !defined(WC_NO_RNG)
|
||||||
if (ctx->srp != NULL){
|
if (ctx->srp != NULL) {
|
||||||
if (ctx->srp_password != NULL){
|
if (ctx->srp_password != NULL){
|
||||||
XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
|
XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
|
||||||
ctx->srp_password = NULL;
|
ctx->srp_password = NULL;
|
||||||
@ -14677,10 +14677,10 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){
|
if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0) {
|
||||||
WOLFSSL_MSG("Init CTX failed");
|
WOLFSSL_MSG("Init SRP CTX failed");
|
||||||
XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
|
XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP);
|
||||||
wolfSSL_CTX_free(ctx);
|
ctx->srp = NULL;
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
|
r = wc_SrpSetUsername(ctx->srp, (const byte*)username,
|
||||||
@ -14692,23 +14692,24 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
|
|
||||||
/* if wolfSSL_CTX_set_srp_password has already been called, */
|
/* if wolfSSL_CTX_set_srp_password has already been called, */
|
||||||
/* execute wc_SrpSetPassword here */
|
/* execute wc_SrpSetPassword here */
|
||||||
if (ctx->srp_password != NULL){
|
if (ctx->srp_password != NULL) {
|
||||||
|
WC_RNG rng;
|
||||||
if (wc_InitRng(&rng) < 0){
|
if (wc_InitRng(&rng) < 0){
|
||||||
WOLFSSL_MSG("wc_InitRng failed");
|
WOLFSSL_MSG("wc_InitRng failed");
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
|
XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
|
||||||
if (wc_RNG_GenerateBlock(&rng, salt,
|
r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0]));
|
||||||
sizeof(salt)/sizeof(salt[0])) < 0){
|
wc_FreeRng(&rng);
|
||||||
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
|
if (r < 0) {
|
||||||
wc_FreeRng(&rng);
|
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
|
if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
|
||||||
srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
|
srp_g, sizeof(srp_g)/sizeof(srp_g[0]),
|
||||||
salt, sizeof(salt)/sizeof(salt[0])) < 0){
|
salt, sizeof(salt)/sizeof(salt[0])) < 0) {
|
||||||
WOLFSSL_MSG("wc_SrpSetParam failed");
|
WOLFSSL_MSG("wc_SrpSetParam failed");
|
||||||
wc_FreeRng(&rng);
|
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
r = wc_SrpSetPassword(ctx->srp,
|
r = wc_SrpSetPassword(ctx->srp,
|
||||||
@ -14718,7 +14719,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
WOLFSSL_MSG("fail to set srp password.");
|
WOLFSSL_MSG("fail to set srp password.");
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
wc_FreeRng(&rng);
|
|
||||||
XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
|
XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP);
|
||||||
ctx->srp_password = NULL;
|
ctx->srp_password = NULL;
|
||||||
}
|
}
|
||||||
@ -14729,23 +14730,23 @@ int wolfSSL_set_compression(WOLFSSL* ssl)
|
|||||||
int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
|
int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
WC_RNG rng;
|
|
||||||
byte salt[SRP_SALT_SIZE];
|
byte salt[SRP_SALT_SIZE];
|
||||||
|
|
||||||
WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
|
WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password");
|
||||||
if (ctx == NULL || ctx->srp == NULL || password == NULL)
|
if (ctx == NULL || ctx->srp == NULL || password == NULL)
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
|
|
||||||
if (ctx->srp->user != NULL){
|
if (ctx->srp->user != NULL) {
|
||||||
if (wc_InitRng(&rng) < 0){
|
WC_RNG rng;
|
||||||
|
if (wc_InitRng(&rng) < 0) {
|
||||||
WOLFSSL_MSG("wc_InitRng failed");
|
WOLFSSL_MSG("wc_InitRng failed");
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
|
XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0]));
|
||||||
if (wc_RNG_GenerateBlock(&rng, salt,
|
r = wc_RNG_GenerateBlock(&rng, salt, sizeof(salt)/sizeof(salt[0]));
|
||||||
sizeof(salt)/sizeof(salt[0])) < 0){
|
wc_FreeRng(&rng);
|
||||||
|
if (r < 0) {
|
||||||
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
|
WOLFSSL_MSG("wc_RNG_GenerateBlock failed");
|
||||||
wc_FreeRng(&rng);
|
|
||||||
return SSL_FAILURE;
|
return SSL_FAILURE;
|
||||||
}
|
}
|
||||||
if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
|
if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]),
|
||||||
|
@ -449,6 +449,7 @@ static int sha512_key_gen(Srp* srp, byte* secret, word32 size)
|
|||||||
r = wc_InitSha512(&hash);
|
r = wc_InitSha512(&hash);
|
||||||
if (!r) r = wc_Sha512Update(&hash, secret, size);
|
if (!r) r = wc_Sha512Update(&hash, secret, size);
|
||||||
if (!r) r = wc_Sha512Final(&hash, srp->key);
|
if (!r) r = wc_Sha512Final(&hash, srp->key);
|
||||||
|
wc_Sha512Free(&hash);
|
||||||
|
|
||||||
XMEMSET(&hash, 0, sizeof(wc_Sha512));
|
XMEMSET(&hash, 0, sizeof(wc_Sha512));
|
||||||
|
|
||||||
|
@ -188,6 +188,35 @@ static word32 SrpHashSize(SrpType type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SrpHashFree(SrpHash* hash)
|
||||||
|
{
|
||||||
|
switch (hash->type) {
|
||||||
|
case SRP_TYPE_SHA:
|
||||||
|
#ifndef NO_SHA
|
||||||
|
wc_ShaFree(&hash->data.sha);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SRP_TYPE_SHA256:
|
||||||
|
#ifndef NO_SHA256
|
||||||
|
wc_Sha256Free(&hash->data.sha256);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SRP_TYPE_SHA384:
|
||||||
|
#ifdef WOLFSSL_SHA384
|
||||||
|
wc_Sha384Free(&hash->data.sha384);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case SRP_TYPE_SHA512:
|
||||||
|
#ifdef WOLFSSL_SHA512
|
||||||
|
wc_Sha512Free(&hash->data.sha512);
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int wc_SrpInit(Srp* srp, SrpType type, SrpSide side)
|
int wc_SrpInit(Srp* srp, SrpType type, SrpSide side)
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
@ -234,18 +263,21 @@ int wc_SrpInit(Srp* srp, SrpType type, SrpSide side)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* initializing variables */
|
/* initializing variables */
|
||||||
|
|
||||||
XMEMSET(srp, 0, sizeof(Srp));
|
XMEMSET(srp, 0, sizeof(Srp));
|
||||||
|
|
||||||
if ((r = SrpHashInit(&srp->client_proof, type)) != 0)
|
if ((r = SrpHashInit(&srp->client_proof, type)) != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if ((r = SrpHashInit(&srp->server_proof, type)) != 0)
|
if ((r = SrpHashInit(&srp->server_proof, type)) != 0) {
|
||||||
|
SrpHashFree(&srp->client_proof);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth,
|
if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth,
|
||||||
&srp->priv, 0, 0)) != 0)
|
&srp->priv, 0, 0)) != 0) {
|
||||||
|
SrpHashFree(&srp->client_proof);
|
||||||
|
SrpHashFree(&srp->server_proof);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
srp->side = side; srp->type = type;
|
srp->side = side; srp->type = type;
|
||||||
srp->salt = NULL; srp->saltSz = 0;
|
srp->salt = NULL; srp->saltSz = 0;
|
||||||
@ -282,6 +314,8 @@ void wc_SrpTerm(Srp* srp)
|
|||||||
XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP);
|
XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SrpHashFree(&srp->client_proof);
|
||||||
|
SrpHashFree(&srp->server_proof);
|
||||||
ForceZero(srp, sizeof(Srp));
|
ForceZero(srp, sizeof(Srp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -353,6 +387,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
|
|||||||
}
|
}
|
||||||
if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
|
if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
|
||||||
if (!r) r = SrpHashFinal(&hash, srp->k);
|
if (!r) r = SrpHashFinal(&hash, srp->k);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* update client proof */
|
/* update client proof */
|
||||||
|
|
||||||
@ -360,11 +395,13 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
|
|||||||
if (!r) r = SrpHashInit(&hash, srp->type);
|
if (!r) r = SrpHashInit(&hash, srp->type);
|
||||||
if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz);
|
if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz);
|
||||||
if (!r) r = SrpHashFinal(&hash, digest1);
|
if (!r) r = SrpHashFinal(&hash, digest1);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* digest2 = H(g) */
|
/* digest2 = H(g) */
|
||||||
if (!r) r = SrpHashInit(&hash, srp->type);
|
if (!r) r = SrpHashInit(&hash, srp->type);
|
||||||
if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
|
if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz);
|
||||||
if (!r) r = SrpHashFinal(&hash, digest2);
|
if (!r) r = SrpHashFinal(&hash, digest2);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* digest1 = H(N) ^ H(g) */
|
/* digest1 = H(N) ^ H(g) */
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
@ -376,6 +413,7 @@ int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz,
|
|||||||
if (!r) r = SrpHashInit(&hash, srp->type);
|
if (!r) r = SrpHashInit(&hash, srp->type);
|
||||||
if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
|
if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz);
|
||||||
if (!r) r = SrpHashFinal(&hash, digest2);
|
if (!r) r = SrpHashFinal(&hash, digest2);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* client proof = H( H(N) ^ H(g) | H(user) | salt) */
|
/* client proof = H( H(N) ^ H(g) | H(user) | salt) */
|
||||||
if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j);
|
if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j);
|
||||||
@ -406,12 +444,14 @@ int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size)
|
|||||||
if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1);
|
if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1);
|
||||||
if (!r) r = SrpHashUpdate(&hash, password, size);
|
if (!r) r = SrpHashUpdate(&hash, password, size);
|
||||||
if (!r) r = SrpHashFinal(&hash, digest);
|
if (!r) r = SrpHashFinal(&hash, digest);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* digest = H(salt | H(username | ':' | password)) */
|
/* digest = H(salt | H(username | ':' | password)) */
|
||||||
if (!r) r = SrpHashInit(&hash, srp->type);
|
if (!r) r = SrpHashInit(&hash, srp->type);
|
||||||
if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz);
|
if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz);
|
||||||
if (!r) r = SrpHashUpdate(&hash, digest, digestSz);
|
if (!r) r = SrpHashUpdate(&hash, digest, digestSz);
|
||||||
if (!r) r = SrpHashFinal(&hash, digest);
|
if (!r) r = SrpHashFinal(&hash, digest);
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* Set x (private key) */
|
/* Set x (private key) */
|
||||||
if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz);
|
if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz);
|
||||||
@ -579,6 +619,7 @@ static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size)
|
|||||||
if (!r) r = SrpHashFinal(&hash, srp->key + j);
|
if (!r) r = SrpHashFinal(&hash, srp->key + j);
|
||||||
j += digestSz;
|
j += digestSz;
|
||||||
}
|
}
|
||||||
|
SrpHashFree(&hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
ForceZero(digest, sizeof(digest));
|
ForceZero(digest, sizeof(digest));
|
||||||
@ -641,6 +682,7 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz,
|
|||||||
/* set u */
|
/* set u */
|
||||||
if (!r) r = SrpHashFinal(&hash, digest);
|
if (!r) r = SrpHashFinal(&hash, digest);
|
||||||
if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type));
|
if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type));
|
||||||
|
SrpHashFree(&hash);
|
||||||
|
|
||||||
/* building s (secret) */
|
/* building s (secret) */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user