PR: 2259
Submitted By: Artem Chuprina <ran@cryptocom.ru> Check return values of HMAC in tls_P_hash and tls1_generate_key_block. Although the previous version could in theory crash that would only happen if a digest call failed. The standard software methods can never fail and only one ENGINE currently uses digests and it is not compiled in by default.
This commit is contained in:
parent
acf635b9b2
commit
7837c7ec45
129
ssl/t1_enc.c
129
ssl/t1_enc.c
@ -149,7 +149,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* seed1 through seed5 are virtually concatenated */
|
/* seed1 through seed5 are virtually concatenated */
|
||||||
static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
|
static int tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
|
||||||
int sec_len,
|
int sec_len,
|
||||||
const void *seed1, int seed1_len,
|
const void *seed1, int seed1_len,
|
||||||
const void *seed2, int seed2_len,
|
const void *seed2, int seed2_len,
|
||||||
@ -164,55 +164,79 @@ static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec,
|
|||||||
HMAC_CTX ctx_tmp;
|
HMAC_CTX ctx_tmp;
|
||||||
unsigned char A1[EVP_MAX_MD_SIZE];
|
unsigned char A1[EVP_MAX_MD_SIZE];
|
||||||
unsigned int A1_len;
|
unsigned int A1_len;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
chunk=EVP_MD_size(md);
|
chunk=EVP_MD_size(md);
|
||||||
OPENSSL_assert(chunk >= 0);
|
OPENSSL_assert(chunk >= 0);
|
||||||
|
|
||||||
HMAC_CTX_init(&ctx);
|
HMAC_CTX_init(&ctx);
|
||||||
HMAC_CTX_init(&ctx_tmp);
|
HMAC_CTX_init(&ctx_tmp);
|
||||||
HMAC_Init_ex(&ctx,sec,sec_len,md, NULL);
|
if (!HMAC_Init_ex(&ctx,sec,sec_len,md, NULL))
|
||||||
HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL);
|
goto err;
|
||||||
if (seed1 != NULL) HMAC_Update(&ctx,seed1,seed1_len);
|
if (!HMAC_Init_ex(&ctx_tmp,sec,sec_len,md, NULL))
|
||||||
if (seed2 != NULL) HMAC_Update(&ctx,seed2,seed2_len);
|
goto err;
|
||||||
if (seed3 != NULL) HMAC_Update(&ctx,seed3,seed3_len);
|
if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
|
||||||
if (seed4 != NULL) HMAC_Update(&ctx,seed4,seed4_len);
|
goto err;
|
||||||
if (seed5 != NULL) HMAC_Update(&ctx,seed5,seed5_len);
|
if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
|
||||||
HMAC_Final(&ctx,A1,&A1_len);
|
goto err;
|
||||||
|
if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
|
||||||
|
goto err;
|
||||||
|
if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
|
||||||
|
goto err;
|
||||||
|
if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
|
||||||
|
goto err;
|
||||||
|
if (!HMAC_Final(&ctx,A1,&A1_len))
|
||||||
|
goto err;
|
||||||
|
|
||||||
n=0;
|
n=0;
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
HMAC_Init_ex(&ctx,NULL,0,NULL,NULL); /* re-init */
|
if (!HMAC_Init_ex(&ctx,NULL,0,NULL,NULL)) /* re-init */
|
||||||
HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL); /* re-init */
|
goto err;
|
||||||
HMAC_Update(&ctx,A1,A1_len);
|
if (!HMAC_Init_ex(&ctx_tmp,NULL,0,NULL,NULL)) /* re-init */
|
||||||
HMAC_Update(&ctx_tmp,A1,A1_len);
|
goto err;
|
||||||
if (seed1 != NULL) HMAC_Update(&ctx,seed1,seed1_len);
|
if (!HMAC_Update(&ctx,A1,A1_len))
|
||||||
if (seed2 != NULL) HMAC_Update(&ctx,seed2,seed2_len);
|
goto err;
|
||||||
if (seed3 != NULL) HMAC_Update(&ctx,seed3,seed3_len);
|
if (!HMAC_Update(&ctx_tmp,A1,A1_len))
|
||||||
if (seed4 != NULL) HMAC_Update(&ctx,seed4,seed4_len);
|
goto err;
|
||||||
if (seed5 != NULL) HMAC_Update(&ctx,seed5,seed5_len);
|
if (seed1 != NULL && !HMAC_Update(&ctx,seed1,seed1_len))
|
||||||
|
goto err;
|
||||||
|
if (seed2 != NULL && !HMAC_Update(&ctx,seed2,seed2_len))
|
||||||
|
goto err;
|
||||||
|
if (seed3 != NULL && !HMAC_Update(&ctx,seed3,seed3_len))
|
||||||
|
goto err;
|
||||||
|
if (seed4 != NULL && !HMAC_Update(&ctx,seed4,seed4_len))
|
||||||
|
goto err;
|
||||||
|
if (seed5 != NULL && !HMAC_Update(&ctx,seed5,seed5_len))
|
||||||
|
goto err;
|
||||||
|
|
||||||
if (olen > chunk)
|
if (olen > chunk)
|
||||||
{
|
{
|
||||||
HMAC_Final(&ctx,out,&j);
|
if (!HMAC_Final(&ctx,out,&j))
|
||||||
|
goto err;
|
||||||
out+=j;
|
out+=j;
|
||||||
olen-=j;
|
olen-=j;
|
||||||
HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */
|
if (!HMAC_Final(&ctx_tmp,A1,&A1_len)) /* calc the next A1 value */
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
else /* last one */
|
else /* last one */
|
||||||
{
|
{
|
||||||
HMAC_Final(&ctx,A1,&A1_len);
|
if (!HMAC_Final(&ctx,A1,&A1_len))
|
||||||
|
goto err;
|
||||||
memcpy(out,A1,olen);
|
memcpy(out,A1,olen);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = 1;
|
||||||
|
err:
|
||||||
HMAC_CTX_cleanup(&ctx);
|
HMAC_CTX_cleanup(&ctx);
|
||||||
HMAC_CTX_cleanup(&ctx_tmp);
|
HMAC_CTX_cleanup(&ctx_tmp);
|
||||||
OPENSSL_cleanse(A1,sizeof(A1));
|
OPENSSL_cleanse(A1,sizeof(A1));
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* seed1 through seed5 are virtually concatenated */
|
/* seed1 through seed5 are virtually concatenated */
|
||||||
static void tls1_PRF(long digest_mask,
|
static int tls1_PRF(long digest_mask,
|
||||||
const void *seed1, int seed1_len,
|
const void *seed1, int seed1_len,
|
||||||
const void *seed2, int seed2_len,
|
const void *seed2, int seed2_len,
|
||||||
const void *seed3, int seed3_len,
|
const void *seed3, int seed3_len,
|
||||||
@ -226,6 +250,7 @@ static void tls1_PRF(long digest_mask,
|
|||||||
const unsigned char *S1;
|
const unsigned char *S1;
|
||||||
long m;
|
long m;
|
||||||
const EVP_MD *md;
|
const EVP_MD *md;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
/* Count number of digests and partition sec evenly */
|
/* Count number of digests and partition sec evenly */
|
||||||
count=0;
|
count=0;
|
||||||
@ -240,11 +265,12 @@ static void tls1_PRF(long digest_mask,
|
|||||||
if (!md) {
|
if (!md) {
|
||||||
SSLerr(SSL_F_TLS1_PRF,
|
SSLerr(SSL_F_TLS1_PRF,
|
||||||
SSL_R_UNSUPPORTED_DIGEST_TYPE);
|
SSL_R_UNSUPPORTED_DIGEST_TYPE);
|
||||||
return;
|
goto err;
|
||||||
}
|
}
|
||||||
tls1_P_hash(md ,S1,len+(slen&1),
|
if (!tls1_P_hash(md ,S1,len+(slen&1),
|
||||||
seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len,
|
seed1,seed1_len,seed2,seed2_len,seed3,seed3_len,seed4,seed4_len,seed5,seed5_len,
|
||||||
out2,olen);
|
out2,olen))
|
||||||
|
goto err;
|
||||||
S1+=len;
|
S1+=len;
|
||||||
for (i=0; i<olen; i++)
|
for (i=0; i<olen; i++)
|
||||||
{
|
{
|
||||||
@ -252,12 +278,15 @@ static void tls1_PRF(long digest_mask,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = 1;
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
static void tls1_generate_key_block(SSL *s, unsigned char *km,
|
static int tls1_generate_key_block(SSL *s, unsigned char *km,
|
||||||
unsigned char *tmp, int num)
|
unsigned char *tmp, int num)
|
||||||
{
|
{
|
||||||
tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
int ret;
|
||||||
|
ret = tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
||||||
TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
|
TLS_MD_KEY_EXPANSION_CONST,TLS_MD_KEY_EXPANSION_CONST_SIZE,
|
||||||
s->s3->server_random,SSL3_RANDOM_SIZE,
|
s->s3->server_random,SSL3_RANDOM_SIZE,
|
||||||
s->s3->client_random,SSL3_RANDOM_SIZE,
|
s->s3->client_random,SSL3_RANDOM_SIZE,
|
||||||
@ -275,6 +304,7 @@ static void tls1_generate_key_block(SSL *s, unsigned char *km,
|
|||||||
}
|
}
|
||||||
printf("\n"); }
|
printf("\n"); }
|
||||||
#endif /* KSSL_DEBUG */
|
#endif /* KSSL_DEBUG */
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tls1_change_cipher_state(SSL *s, int which)
|
int tls1_change_cipher_state(SSL *s, int which)
|
||||||
@ -462,22 +492,24 @@ printf("which = %04X\nmac key=",which);
|
|||||||
/* In here I set both the read and write key/iv to the
|
/* In here I set both the read and write key/iv to the
|
||||||
* same value since only the correct one will be used :-).
|
* same value since only the correct one will be used :-).
|
||||||
*/
|
*/
|
||||||
tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
||||||
exp_label,exp_label_len,
|
exp_label,exp_label_len,
|
||||||
s->s3->client_random,SSL3_RANDOM_SIZE,
|
s->s3->client_random,SSL3_RANDOM_SIZE,
|
||||||
s->s3->server_random,SSL3_RANDOM_SIZE,
|
s->s3->server_random,SSL3_RANDOM_SIZE,
|
||||||
NULL,0,NULL,0,
|
NULL,0,NULL,0,
|
||||||
key,j,tmp1,tmp2,EVP_CIPHER_key_length(c));
|
key,j,tmp1,tmp2,EVP_CIPHER_key_length(c)))
|
||||||
|
goto err2;
|
||||||
key=tmp1;
|
key=tmp1;
|
||||||
|
|
||||||
if (k > 0)
|
if (k > 0)
|
||||||
{
|
{
|
||||||
tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
||||||
TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
|
TLS_MD_IV_BLOCK_CONST,TLS_MD_IV_BLOCK_CONST_SIZE,
|
||||||
s->s3->client_random,SSL3_RANDOM_SIZE,
|
s->s3->client_random,SSL3_RANDOM_SIZE,
|
||||||
s->s3->server_random,SSL3_RANDOM_SIZE,
|
s->s3->server_random,SSL3_RANDOM_SIZE,
|
||||||
NULL,0,NULL,0,
|
NULL,0,NULL,0,
|
||||||
empty,0,iv1,iv2,k*2);
|
empty,0,iv1,iv2,k*2))
|
||||||
|
goto err2;
|
||||||
if (client_write)
|
if (client_write)
|
||||||
iv=iv1;
|
iv=iv1;
|
||||||
else
|
else
|
||||||
@ -519,12 +551,13 @@ err2:
|
|||||||
|
|
||||||
int tls1_setup_key_block(SSL *s)
|
int tls1_setup_key_block(SSL *s)
|
||||||
{
|
{
|
||||||
unsigned char *p1,*p2;
|
unsigned char *p1,*p2=NULL;
|
||||||
const EVP_CIPHER *c;
|
const EVP_CIPHER *c;
|
||||||
const EVP_MD *hash;
|
const EVP_MD *hash;
|
||||||
int num;
|
int num;
|
||||||
SSL_COMP *comp;
|
SSL_COMP *comp;
|
||||||
int mac_type= NID_undef,mac_secret_size=0;
|
int mac_type= NID_undef,mac_secret_size=0;
|
||||||
|
int ret=0;
|
||||||
|
|
||||||
#ifdef KSSL_DEBUG
|
#ifdef KSSL_DEBUG
|
||||||
printf ("tls1_setup_key_block()\n");
|
printf ("tls1_setup_key_block()\n");
|
||||||
@ -549,13 +582,19 @@ int tls1_setup_key_block(SSL *s)
|
|||||||
ssl3_cleanup_key_block(s);
|
ssl3_cleanup_key_block(s);
|
||||||
|
|
||||||
if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
|
if ((p1=(unsigned char *)OPENSSL_malloc(num)) == NULL)
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
|
||||||
goto err;
|
goto err;
|
||||||
if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
|
}
|
||||||
goto err;
|
|
||||||
|
|
||||||
s->s3->tmp.key_block_length=num;
|
s->s3->tmp.key_block_length=num;
|
||||||
s->s3->tmp.key_block=p1;
|
s->s3->tmp.key_block=p1;
|
||||||
|
|
||||||
|
if ((p2=(unsigned char *)OPENSSL_malloc(num)) == NULL)
|
||||||
|
{
|
||||||
|
SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef TLS_DEBUG
|
#ifdef TLS_DEBUG
|
||||||
printf("client random\n");
|
printf("client random\n");
|
||||||
@ -565,9 +604,8 @@ printf("server random\n");
|
|||||||
printf("pre-master\n");
|
printf("pre-master\n");
|
||||||
{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
|
{ int z; for (z=0; z<s->session->master_key_length; z++) printf("%02X%c",s->session->master_key[z],((z+1)%16)?' ':'\n'); }
|
||||||
#endif
|
#endif
|
||||||
tls1_generate_key_block(s,p1,p2,num);
|
if (!tls1_generate_key_block(s,p1,p2,num))
|
||||||
OPENSSL_cleanse(p2,num);
|
goto err;
|
||||||
OPENSSL_free(p2);
|
|
||||||
#ifdef TLS_DEBUG
|
#ifdef TLS_DEBUG
|
||||||
printf("\nkey block\n");
|
printf("\nkey block\n");
|
||||||
{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
|
{ int z; for (z=0; z<num; z++) printf("%02X%c",p1[z],((z+1)%16)?' ':'\n'); }
|
||||||
@ -592,10 +630,14 @@ printf("\nkey block\n");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(1);
|
ret = 1;
|
||||||
err:
|
err:
|
||||||
SSLerr(SSL_F_TLS1_SETUP_KEY_BLOCK,ERR_R_MALLOC_FAILURE);
|
if (p2)
|
||||||
return(0);
|
{
|
||||||
|
OPENSSL_cleanse(p2,num);
|
||||||
|
OPENSSL_free(p2);
|
||||||
|
}
|
||||||
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int tls1_enc(SSL *s, int send)
|
int tls1_enc(SSL *s, int send)
|
||||||
@ -849,10 +891,11 @@ int tls1_final_finish_mac(SSL *s,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
if (!tls1_PRF(s->s3->tmp.new_cipher->algorithm2,
|
||||||
str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
|
str,slen, buf,(int)(q-buf), NULL,0, NULL,0, NULL,0,
|
||||||
s->session->master_key,s->session->master_key_length,
|
s->session->master_key,s->session->master_key_length,
|
||||||
out,buf2,sizeof buf2);
|
out,buf2,sizeof buf2))
|
||||||
|
err = 1;
|
||||||
EVP_MD_CTX_cleanup(&ctx);
|
EVP_MD_CTX_cleanup(&ctx);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user