Hi,

I verified that regression test
src/regress/lib/libssl/unit/tls_ext_alpn.c fails on these cases;

 - proto_invalid_len5, 7, 8
 - proto_invalid_missing1 - 5
 - proto_invalid_missing8, 9

To correct these failures, ssl_parse_clienthello_tlsext() and
ssl_parse_serverhello_tlsext() in ssl/t1_lib.c should be fixed.

I attached the patch and it resolves the issues above.

BTW, ssl_parse_serverhello_tlsext() and ssl_parse_clienthello_tlsext()
of OpenSSL codebase seems to have issues below, I believe.

- fixes in ssl_parse_clienthello_tlsext() is NOT reflected to
  ssl_parse_serverhello_tlsext() (ex. limit, parsing logic, etc.)

- ssl_parse_serverhello_tlsext() always `goto ri_check`
  if data structure is invalid.

If I'm wrong, please let me know.

Thanks.

diff --git src/lib/libssl/src/ssl/t1_lib.c src/lib/libssl/src/ssl/t1_lib.c
index b225bb3..01c341f 100644
--- src/lib/libssl/src/ssl/t1_lib.c
+++ src/lib/libssl/src/ssl/t1_lib.c
@@ -1214,20 +1214,25 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, 
unsigned char *d,
        s->s3->next_proto_neg_seen = 0;
        free(s->s3->alpn_selected);
        s->s3->alpn_selected = NULL;
+       s->srtp_profile = NULL;
 
-       if (data >= (d + n - 2))
+       if (data == (d + n))
                goto ri_check;
-       n2s(data, len);
 
-       if (data > (d + n - len))
-               goto ri_check;
+       if ((d + n) - data < 2)
+               goto err;
+
+       n2s(data, len);
+       if ((d + n) - data != len)
+               goto err;
 
-       while (data <= (d + n - 4)) {
+       while ((d + n) - data >= 4) {
                n2s(data, type);
                n2s(data, size);
 
-               if (data + size > (d + n))
-                       goto ri_check;
+               if ((d + n) - data < size)
+                       goto err;
+
                if (s->tlsext_debug_cb)
                        s->tlsext_debug_cb(s, 0, type, data, size,
                            s->tlsext_debug_arg);
@@ -1560,6 +1565,10 @@ ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, 
unsigned char *d,
                data += size;
        }
 
+       /* Spurious data on the end */
+       if (data != (d + n))
+               goto err;
+
        *p = data;
 
 ri_check:
@@ -1574,6 +1583,10 @@ ri_check:
        }
 
        return 1;
+
+err:
+       *al = SSL_AD_DECODE_ERROR;
+       return 0;
 }
 
 /*
@@ -1599,9 +1612,9 @@ int
 ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
     int n, int *al)
 {
-       unsigned short length;
        unsigned short type;
        unsigned short size;
+       unsigned short len;
        unsigned char *data = *p;
        int tlsext_servername = 0;
        int renegotiate_seen = 0;
@@ -1610,21 +1623,22 @@ ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, 
unsigned char *d,
        free(s->s3->alpn_selected);
        s->s3->alpn_selected = NULL;
 
-       if (data >= (d + n - 2))
+       if (data == (d + n))
                goto ri_check;
 
-       n2s(data, length);
-       if (data + length != d + n) {
-               *al = SSL_AD_DECODE_ERROR;
-               return 0;
-       }
+       if ((d + n) - data < 2)
+               goto err;
+
+       n2s(data, len);
+       if ((d + n) - data != len)
+               goto err;
 
-       while (data <= (d + n - 4)) {
+       while ((d + n) - data >= 4) {
                n2s(data, type);
                n2s(data, size);
 
-               if (data + size > (d + n))
-                       goto ri_check;
+               if ((d + n) - data < size)
+                       goto err;
 
                if (s->tlsext_debug_cb)
                        s->tlsext_debug_cb(s, 1, type, data, size,
@@ -1818,6 +1832,10 @@ ri_check:
        }
 
        return 1;
+
+err:
+       *al = SSL_AD_DECODE_ERROR;
+       return 0;
 }
 
 int

Reply via email to