aboutsummaryrefslogtreecommitdiffstats
path: root/ssl
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2015-04-10 17:25:27 +0100
committerMatt Caswell <matt@openssl.org>2015-04-14 14:58:25 +0100
commit5e9f0eebcfa25a55177d9a7025713262367bec14 (patch)
tree219ab4ba523c8247cd1a44c2b7e34bce66fcb9a6 /ssl
parente0e920b1a063f14f36418f8795c96f2c649400e1 (diff)
downloadopenssl-5e9f0eebcfa25a55177d9a7025713262367bec14.tar.gz
Check for ClientHello message overruns
The ClientHello processing is insufficiently rigorous in its checks to make sure that we don't read past the end of the message. This does not have security implications due to the size of the underlying buffer - but still needs to be fixed. With thanks to Qinghao Tang for reporting this issue. Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'ssl')
-rw-r--r--ssl/s3_srvr.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 5b17e52450..7376fe61ec 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -932,6 +932,16 @@ int ssl3_get_client_hello(SSL *s)
d = p = (unsigned char *)s->init_msg;
/*
+ * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
+ * for session id length
+ */
+ if (n < 2 + SSL3_RANDOM_SIZE + 1) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
+ /*
* use version from inside client hello, not from record header (may
* differ: see RFC 2246, Appendix E, second paragraph)
*/
@@ -963,6 +973,12 @@ int ssl3_get_client_hello(SSL *s)
unsigned int session_length, cookie_length;
session_length = *(p + SSL3_RANDOM_SIZE);
+
+ if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1);
if (cookie_length == 0)
@@ -976,6 +992,12 @@ int ssl3_get_client_hello(SSL *s)
/* get the session-id */
j = *(p++);
+ if (p + j > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
s->hit = 0;
/*
* Versions before 0.9.7 always allow clients to resume sessions in
@@ -1020,8 +1042,19 @@ int ssl3_get_client_hello(SSL *s)
if (SSL_IS_DTLS(s)) {
/* cookie stuff */
+ if (p + 1 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
cookie_len = *(p++);
+ if (p + cookie_len > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
+
/*
* The ClientHello may contain a cookie even if the
* HelloVerify message has not been sent--make sure that it
@@ -1087,6 +1120,11 @@ int ssl3_get_client_hello(SSL *s)
}
}
+ if (p + 2 > d + n) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+ goto f_err;
+ }
n2s(p, i);
if ((i == 0) && (j != 0)) {
/* we need a cipher if we are not resuming a session */
@@ -1094,7 +1132,9 @@ int ssl3_get_client_hello(SSL *s)
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
goto f_err;
}
- if ((p + i) >= (d + n)) {
+
+ /* i bytes of cipher data + 1 byte for compression length later */
+ if ((p + i + 1) > (d + n)) {
/* not enough data */
al = SSL_AD_DECODE_ERROR;
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);