Submitted by: Alexei Khlebnikov <alexei.khlebnikov@opera.com>
Reviewed by: steve

OOM checking. Leak in OOM fix. Fall-through comment. Duplicate code
elimination.
This commit is contained in:
Dr. Stephen Henson 2011-05-20 14:56:29 +00:00
parent 101e6e19f2
commit f37f20ffd3
6 changed files with 130 additions and 8 deletions

View File

@ -4,6 +4,9 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add TLS v1.2 server support for client authentication.
[Steve Henson]
*) Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers
and enable MD5.
[Steve Henson]

View File

@ -569,12 +569,12 @@ void ssl3_free_digest_list(SSL *s)
OPENSSL_free(s->s3->handshake_dgst);
s->s3->handshake_dgst=NULL;
}
void ssl3_finish_mac(SSL *s, const unsigned char *buf, int len)
{
if (s->s3->handshake_buffer)
if (s->s3->handshake_buffer && !(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE))
{
BIO_write (s->s3->handshake_buffer,(void *)buf,len);
}
@ -629,9 +629,12 @@ int ssl3_digest_cached_records(SSL *s)
s->s3->handshake_dgst[i]=NULL;
}
}
/* Free handshake_buffer BIO */
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
if (!(s->s3->flags & TLS1_FLAGS_KEEP_HANDSHAKE))
{
/* Free handshake_buffer BIO */
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
}
return 1;
}

View File

@ -516,6 +516,9 @@ int ssl3_accept(SSL *s)
skip=1;
s->s3->tmp.cert_request=0;
s->state=SSL3_ST_SW_SRVR_DONE_A;
if (s->s3->handshake_buffer)
if (!ssl3_digest_cached_records(s))
return -1;
}
else
{
@ -608,6 +611,24 @@ int ssl3_accept(SSL *s)
#endif
s->init_num = 0;
}
else if (s->version >= TLS1_2_VERSION)
{
s->state=SSL3_ST_SR_CERT_VRFY_A;
s->init_num=0;
if (!s->session->peer)
break;
/* For TLS v1.2 freeze the handshake buffer
* at this point and digest cached records.
*/
if (!s->s3->handshake_buffer)
{
SSLerr(SSL_F_SSL3_ACCEPT,ERR_R_INTERNAL_ERROR);
return -1;
}
s->s3->flags |= TLS1_FLAGS_KEEP_HANDSHAKE;
if (!ssl3_digest_cached_records(s))
return -1;
}
else
{
int offset=0;
@ -1359,8 +1380,11 @@ int ssl3_get_client_hello(SSL *s)
s->s3->tmp.new_cipher=s->session->cipher;
}
if (!ssl3_digest_cached_records(s))
goto f_err;
if (s->version < TLS1_2_VERSION || !(s->verify_mode & SSL_VERIFY_PEER))
{
if (!ssl3_digest_cached_records(s))
goto f_err;
}
/* we now have the following setup.
* client_random
@ -2007,6 +2031,14 @@ int ssl3_send_certificate_request(SSL *s)
p+=n;
n++;
if (s->version >= TLS1_2_VERSION)
{
nl = tls12_get_req_sig_algs(s, p + 2);
s2n(nl, p);
p += nl + 2;
n += nl + 2;
}
off=n;
p+=2;
n+=2;
@ -2861,6 +2893,9 @@ int ssl3_get_cert_verify(SSL *s)
long n;
int type=0,i,j;
X509 *peer;
const EVP_MD *md = NULL;
EVP_MD_CTX mctx;
EVP_MD_CTX_init(&mctx);
n=s->method->ssl_get_message(s,
SSL3_ST_SR_CERT_VRFY_A,
@ -2929,6 +2964,36 @@ int ssl3_get_cert_verify(SSL *s)
}
else
{
if (s->version >= TLS1_2_VERSION)
{
int sigalg = tls12_get_sigid(pkey);
/* Should never happen */
if (sigalg == -1)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,ERR_R_INTERNAL_ERROR);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
/* Check key type is consistent with signature */
if (sigalg != (int)p[1])
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_WRONG_SIGNATURE_TYPE);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
md = tls12_get_hash(p[0]);
if (md == NULL)
{
SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_UNKNOWN_DIGEST);
al=SSL_AD_DECODE_ERROR;
goto f_err;
}
#ifdef SSL_DEBUG
fprintf(stderr, "USING TLSv1.2 HASH %s\n", EVP_MD_name(md));
#endif
p += 2;
n -= 2;
}
n2s(p,i);
n-=2;
if (i > n)
@ -2946,6 +3011,37 @@ int ssl3_get_cert_verify(SSL *s)
goto f_err;
}
if (s->version >= TLS1_2_VERSION)
{
long hdatalen = 0;
void *hdata;
hdatalen = BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (hdatalen <= 0)
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_INTERNAL_ERROR);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
#ifdef SSL_DEBUG
fprintf(stderr, "Using TLS 1.2 with client verify alg %s\n",
EVP_MD_name(md));
#endif
if (!EVP_VerifyInit_ex(&mctx, md, NULL)
|| !EVP_VerifyUpdate(&mctx, hdata, hdatalen))
{
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY, ERR_R_EVP_LIB);
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
if (EVP_VerifyFinal(&mctx, p , i, pkey) <= 0)
{
al=SSL_AD_DECRYPT_ERROR;
SSLerr(SSL_F_SSL3_GET_CERT_VERIFY,SSL_R_BAD_SIGNATURE);
goto f_err;
}
}
else
#ifndef OPENSSL_NO_RSA
if (pkey->type == EVP_PKEY_RSA)
{
@ -3036,6 +3132,13 @@ f_err:
ssl3_send_alert(s,SSL3_AL_FATAL,al);
}
end:
if (s->s3->handshake_buffer)
{
BIO_free(s->s3->handshake_buffer);
s->s3->handshake_buffer = NULL;
s->s3->flags &= ~TLS1_FLAGS_KEEP_HANDSHAKE;
}
EVP_MD_CTX_cleanup(&mctx);
EVP_PKEY_free(pkey);
return(ret);
}
@ -3148,6 +3251,12 @@ int ssl3_get_client_certificate(SSL *s)
al=SSL_AD_HANDSHAKE_FAILURE;
goto f_err;
}
/* No client certificate so digest cached records */
if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s))
{
al=SSL_AD_INTERNAL_ERROR;
goto f_err;
}
}
else
{

View File

@ -383,6 +383,7 @@ typedef struct ssl3_buffer_st
#define SSL3_FLAGS_POP_BUFFER 0x0004
#define TLS1_FLAGS_TLS_PADDING_BUG 0x0008
#define TLS1_FLAGS_SKIP_CERT_VERIFY 0x0010
#define TLS1_FLAGS_KEEP_HANDSHAKE 0x0020
#ifndef OPENSSL_NO_SSL_INTERN

View File

@ -1096,4 +1096,5 @@ int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
int *al);
long ssl_get_algorithm2(SSL *s);
int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize);
int tls12_get_req_sig_algs(SSL *s, unsigned char *p);
#endif

View File

@ -315,7 +315,12 @@ static unsigned char tls12_sigalgs[] = {
#endif
};
int tls12_get_req_sig_algs(SSL *s, unsigned char *p)
{
if (p)
memcpy(p, tls12_sigalgs, sizeof(tls12_sigalgs));
return (int)sizeof(tls12_sigalgs);
}
unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned char *limit)
{