PACKETise ClientHello processing
authorMatt Caswell <matt@openssl.org>
Thu, 16 Apr 2015 09:06:25 +0000 (10:06 +0100)
committerMatt Caswell <matt@openssl.org>
Mon, 3 Aug 2015 10:01:42 +0000 (11:01 +0100)
Uses the new PACKET code to process the incoming ClientHello including all
extensions etc.

Reviewed-by: Tim Hudson <tjh@openssl.org>
ssl/d1_srtp.c
ssl/s3_srvr.c
ssl/ssl_locl.h
ssl/ssl_sess.c
ssl/t1_lib.c
ssl/t1_reneg.c

index 19cf6ff..4384eda 100644 (file)
@@ -266,38 +266,18 @@ int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
     return 0;
 }
 
-int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
-                                       int *al)
+int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al)
 {
     SRTP_PROTECTION_PROFILE *sprof;
     STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
-    int ct;
-    int mki_len;
+    unsigned int ct, mki_len, id;
     int i, srtp_pref;
-    unsigned int id;
-
-    /* Length value + the MKI length */
-    if (len < 3) {
-        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
-               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-        *al = SSL_AD_DECODE_ERROR;
-        return 1;
-    }
-
-    /* Pull off the length of the cipher suite list */
-    n2s(d, ct);
-    len -= 2;
+    PACKET subpkt;
 
-    /* Check that it is even */
-    if (ct % 2) {
-        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
-               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
-        *al = SSL_AD_DECODE_ERROR;
-        return 1;
-    }
-
-    /* Check that lengths are consistent */
-    if (len < (ct + 1)) {
+    /* Pull off the length of the cipher suite list  and check it is even */
+    if (!PACKET_get_net_2(pkt, &ct)
+            || (ct & 1) != 0
+            || !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
         SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
                SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
         *al = SSL_AD_DECODE_ERROR;
@@ -309,10 +289,13 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
     /* Search all profiles for a match initially */
     srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
 
-    while (ct) {
-        n2s(d, id);
-        ct -= 2;
-        len -= 2;
+    while (PACKET_remaining(&subpkt)) {
+        if (!PACKET_get_net_2(&subpkt, &id)) {
+            SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+                   SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+            *al = SSL_AD_DECODE_ERROR;
+            return 1;
+        }
 
         /*
          * Only look for match in profiles of higher preference than
@@ -333,11 +316,15 @@ int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
     /*
      * Now extract the MKI value as a sanity check, but discard it for now
      */
-    mki_len = *d;
-    d++;
-    len--;
+    if (!PACKET_get_1(pkt, &mki_len)) {
+        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
+               SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
+        *al = SSL_AD_DECODE_ERROR;
+        return 1;
+    }
 
-    if (mki_len != len) {
+    if (!PACKET_forward(pkt, mki_len)
+            || PACKET_remaining(pkt)) {
         SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_USE_SRTP_EXT,
                SSL_R_BAD_SRTP_MKI_VALUE);
         *al = SSL_AD_DECODE_ERROR;
index 718ca2c..bc7f84f 100644 (file)
@@ -862,11 +862,11 @@ int ssl3_send_hello_request(SSL *s)
 
 int ssl3_get_client_hello(SSL *s)
 {
-    int i, complen, j, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
-    unsigned int cookie_len;
+    int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
+    unsigned int j, cipherlen, complen;
+    unsigned int cookie_len = 0;
     long n;
     unsigned long id;
-    unsigned char *p, *d;
     SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
     unsigned char *q = NULL;
@@ -874,6 +874,8 @@ int ssl3_get_client_hello(SSL *s)
 #endif
     STACK_OF(SSL_CIPHER) *ciphers = NULL;
     int protverr = 1;
+    PACKET pkt;
+    unsigned char *sess, *cdata;
 
     if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
         goto retry_cert;
@@ -897,10 +899,12 @@ int ssl3_get_client_hello(SSL *s)
     if (!ok)
         return ((int)n);
     s->first_packet = 0;
-    d = p = (unsigned char *)s->init_msg;
+    PACKET_buf_init(&pkt, s->init_msg, n);
 
     /* First lets get s->client_version set correctly */
     if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) {
+        unsigned int version;
+        unsigned int mt;
         /*-
          * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
          * header is sent directly on the wire, not wrapped as a TLS
@@ -916,7 +920,8 @@ int ssl3_get_client_hello(SSL *s)
          * ...   ...
          */
 
-        if (p[0] != SSL2_MT_CLIENT_HELLO) {
+        if (!PACKET_get_1(&pkt, &mt)
+                || mt != SSL2_MT_CLIENT_HELLO) {
             /*
              * Should never happen. We should have tested this in the record
              * layer in order to have determined that this is a SSLv2 record
@@ -926,13 +931,18 @@ int ssl3_get_client_hello(SSL *s)
             goto err;
         }
 
-        if ((p[1] == 0x00) && (p[2] == 0x02)) {
+        if (!PACKET_get_net_2(&pkt, &version)) {
+            /* No protocol version supplied! */
+            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
+            goto err;
+        }
+        if (version == 0x0002) {
             /* This is real SSLv2. We don't support it. */
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
             goto err;
-        } else if (p[1] == SSL3_VERSION_MAJOR) {
+        } else if ((version & 0xff00) == (SSL3_VERSION_MAJOR << 8)) {
             /* SSLv3/TLS */
-            s->client_version = (((int)p[1]) << 8) | (int)p[2];
+            s->client_version = version;
         } else {
             /* No idea what protocol this is */
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL);
@@ -940,20 +950,14 @@ int ssl3_get_client_hello(SSL *s)
         }
     } else {
         /*
-         * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte
-         * for session id length
+         * use version from inside client hello, not from record header (may
+         * differ: see RFC 2246, Appendix E, second paragraph)
          */
-        if (n < 2 + SSL3_RANDOM_SIZE + 1) {
+        if(!PACKET_get_net_2(&pkt, (unsigned int *)&s->client_version)) {
             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)
-         */
-        s->client_version = (((int)p[0]) << 8) | (int)p[1];
     }
 
     /* Do SSL/TLS version negotiation if applicable */
@@ -1032,15 +1036,9 @@ int ssl3_get_client_hello(SSL *s)
          */
         unsigned int csl, sil, cl;
 
-        p += 3;
-        n2s(p, csl);
-        n2s(p, sil);
-        n2s(p, cl);
-
-        if (csl + sil + cl + MIN_SSL2_RECORD_LEN != (unsigned int) n) {
-            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
-            al = SSL_AD_DECODE_ERROR;
-            goto f_err;
+        if (!PACKET_get_net_2(&pkt, &csl)
+                || !PACKET_get_net_2(&pkt, &sil)
+                || !PACKET_get_net_2(&pkt, &cl)) {
         }
 
         if (csl == 0) {
@@ -1050,7 +1048,13 @@ int ssl3_get_client_hello(SSL *s)
             goto f_err;
         }
 
-        if (ssl_bytes_to_cipher_list(s, p, csl, &(ciphers), 1) == NULL) {
+        if (!PACKET_get_bytes(&pkt, &cdata, csl)) {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+            al = SSL_AD_DECODE_ERROR;
+            goto f_err;
+        }
+
+        if (ssl_bytes_to_cipher_list(s, cdata, csl, &(ciphers), 1) == NULL) {
             goto err;
         }
 
@@ -1058,6 +1062,11 @@ int ssl3_get_client_hello(SSL *s)
          * Ignore any session id. We don't allow resumption in a backwards
          * compatible ClientHello
          */
+        if (!PACKET_forward(&pkt, sil)) {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+            al = SSL_AD_DECODE_ERROR;
+            goto f_err;
+        }
         s->hit = 0;
 
         if (!ssl_get_new_session(s, 1))
@@ -1066,17 +1075,27 @@ int ssl3_get_client_hello(SSL *s)
         /* Load the client random */
         i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
         memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
-        memcpy(s->s3->client_random, &(p[csl + sil]), i);
-
-        /* Set p to end of packet to ensure we don't look for extensions */
-        p = d + n;
+        if (!PACKET_peek_copy_bytes(&pkt, s->s3->client_random, i)
+                || !PACKET_forward(&pkt, cl)
+                || !PACKET_remaining(&pkt) == 0) {
+            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
+            al = SSL_AD_DECODE_ERROR;
+            goto f_err;
+        }
 
         /* No compression, so set complen to 0 */
         complen = 0;
     } else {
         /* If we get here we've got SSLv3+ in an SSLv3+ record */
 
-        p += 2;
+        /* load the client random and get the session-id */
+        if (!PACKET_copy_bytes(&pkt, s->s3->client_random, SSL3_RANDOM_SIZE)
+                || !PACKET_get_1(&pkt, &j)
+                || !PACKET_get_bytes(&pkt, &sess, j)) {
+            al = SSL_AD_DECODE_ERROR;
+            SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+            goto f_err;
+        }
 
         /*
          * If we require cookies and this ClientHello doesn't contain one, just
@@ -1084,34 +1103,17 @@ int ssl3_get_client_hello(SSL *s)
          * cookie length...
          */
         if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
-            unsigned int session_length, cookie_length;
 
-            session_length = *(p + SSL3_RANDOM_SIZE);
-
-            if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) {
+            if (!PACKET_peek_1(&pkt, &cookie_len)) {
                 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)
+            if (cookie_len == 0)
                 return 1;
         }
 
-        /* load the client random */
-        memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE);
-        p += SSL3_RANDOM_SIZE;
-
-        /* 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
@@ -1131,7 +1133,7 @@ int ssl3_get_client_hello(SSL *s)
             if (!ssl_get_new_session(s, 1))
                 goto err;
         } else {
-            i = ssl_get_prev_session(s, p, j, d + n);
+            i = ssl_get_prev_session(s, &pkt, sess, j);
             /*
              * Only resume if the session's version matches the negotiated
              * version.
@@ -1153,23 +1155,12 @@ int ssl3_get_client_hello(SSL *s)
             }
         }
 
-        p += j;
-
         if (SSL_IS_DTLS(s)) {
-            /* cookie stuff */
-            if (p + 1 > d + n) {
+            if (!PACKET_get_1(&pkt, &cookie_len)) {
                 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
@@ -1185,7 +1176,13 @@ int ssl3_get_client_hello(SSL *s)
             /* verify the cookie if appropriate option is set. */
             if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
                     && cookie_len > 0) {
-                memcpy(s->d1->rcvd_cookie, p, cookie_len);
+                /* Get cookie */
+                if (!PACKET_copy_bytes(&pkt, s->d1->rcvd_cookie,
+                                              cookie_len)) {
+                    al = SSL_AD_DECODE_ERROR;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+                    goto f_err;
+                }
 
                 if (s->ctx->app_verify_cookie_cb != NULL) {
                     if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
@@ -1206,9 +1203,15 @@ int ssl3_get_client_hello(SSL *s)
                 }
                 /* Set to -2 so if successful we return 2 */
                 ret = -2;
+            } else {
+                /* Skip over cookie */
+                if (!PACKET_forward(&pkt, cookie_len)) {
+                    al = SSL_AD_DECODE_ERROR;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
+                    goto f_err;
+                }
             }
 
-            p += cookie_len;
             if (s->method->version == DTLS_ANY_VERSION) {
                 /* Select version to use */
                 if (s->client_version <= DTLS1_2_VERSION &&
@@ -1236,30 +1239,28 @@ int ssl3_get_client_hello(SSL *s)
             }
         }
 
-        if (p + 2 > d + n) {
+        if (!PACKET_get_net_2(&pkt, &cipherlen)) {
             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) {
+        if (cipherlen == 0) {
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
             goto f_err;
         }
 
-        /* i bytes of cipher data + 1 byte for compression length later */
-        if ((p + i + 1) > (d + n)) {
+        if (!PACKET_get_bytes(&pkt, &cdata, cipherlen)) {
             /* not enough data */
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
-        if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers), 0) == NULL) {
+
+        if (ssl_bytes_to_cipher_list(s, cdata, cipherlen, &(ciphers), 0) == NULL) {
             goto err;
         }
-        p += i;
 
         /* If it is a hit, check that the cipher is in the list */
         if (s->hit) {
@@ -1316,22 +1317,22 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         /* compression */
-        complen = *(p++);
-        if ((p + complen) > (d + n)) {
+        if (!PACKET_get_1(&pkt, &complen)
+            || !PACKET_get_bytes(&pkt, &cdata, complen)) {
             /* not enough data */
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
+
 #ifndef OPENSSL_NO_COMP
-        q = p;
+        q = cdata;
 #endif
         for (j = 0; j < complen; j++) {
-            if (p[j] == 0)
+            if (cdata[j] == 0)
                 break;
         }
 
-        p += complen;
         if (j >= complen) {
             /* no compress */
             al = SSL_AD_DECODE_ERROR;
@@ -1342,7 +1343,7 @@ int ssl3_get_client_hello(SSL *s)
 
     /* TLS extensions */
     if (s->version >= SSL3_VERSION) {
-        if (!ssl_parse_clienthello_tlsext(s, &p, d, n)) {
+        if (!ssl_parse_clienthello_tlsext(s, &pkt)) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_PARSE_TLSEXT);
             goto err;
         }
@@ -1407,6 +1408,7 @@ int ssl3_get_client_hello(SSL *s)
     /* This only happens if we have a cache hit */
     if (s->session->compress_meth != 0) {
         int m, comp_id = s->session->compress_meth;
+        unsigned int k;
         /* Perform sanity checks on resumed compression algorithm */
         /* Can't disable compression */
         if (!ssl_allow_compression(s)) {
@@ -1428,11 +1430,11 @@ int ssl3_get_client_hello(SSL *s)
             goto f_err;
         }
         /* Look for resumed method in compression list */
-        for (m = 0; m < complen; m++) {
-            if (q[m] == comp_id)
+        for (k = 0; k < complen; k++) {
+            if (q[k] == comp_id)
                 break;
         }
-        if (m >= complen) {
+        if (k >= complen) {
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,
                    SSL_R_REQUIRED_COMPRESSSION_ALGORITHM_MISSING);
@@ -1442,7 +1444,8 @@ int ssl3_get_client_hello(SSL *s)
         comp = NULL;
     else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
         /* See if we have a match */
-        int m, nn, o, v, done = 0;
+        int m, nn, v, done = 0;
+        unsigned int o;
 
         nn = sk_SSL_COMP_num(s->ctx->comp_methods);
         for (m = 0; m < nn; m++) {
index 579b09b..0997566 100644 (file)
@@ -1854,8 +1854,8 @@ __owur CERT *ssl_cert_dup(CERT *cert);
 void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
 __owur int ssl_get_new_session(SSL *s, int session);
-__owur int ssl_get_prev_session(SSL *s, unsigned char *session, int len,
-                         const unsigned char *limit);
+__owur int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session,
+                                int len);
 __owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
 __owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
 DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
@@ -2088,8 +2088,7 @@ __owur unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf,
                                           unsigned char *limit, int *al);
 __owur unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
                                           unsigned char *limit, int *al);
-__owur int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **data,
-                                 unsigned char *d, int n);
+__owur int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt);
 __owur int tls1_set_server_sigalgs(SSL *s);
 __owur int ssl_check_clienthello_tlsext_late(SSL *s);
 __owur int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **data,
@@ -2104,8 +2103,8 @@ __owur int tls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length)
 __owur int dtls1_process_heartbeat(SSL *s, unsigned char *p, unsigned int length);
 #  endif
 
-__owur int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
-                        const unsigned char *limit, SSL_SESSION **ret);
+__owur int tls1_process_ticket(SSL *s, PACKET *pkt,  unsigned char *session_id,
+                        int len, SSL_SESSION **ret);
 
 __owur int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk,
                          const EVP_MD *md);
@@ -2134,8 +2133,7 @@ __owur int ssl_parse_serverhello_renegotiate_ext(SSL *s, unsigned char *d, int l
                                           int *al);
 __owur int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
                                         int maxlen);
-__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
-                                          int *al);
+__owur int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al);
 __owur long ssl_get_algorithm2(SSL *s);
 __owur size_t tls12_copy_sigalgs(SSL *s, unsigned char *out,
                           const unsigned char *psig, size_t psiglen);
@@ -2149,8 +2147,7 @@ __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);
 
 __owur int ssl_add_clienthello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
                                      int maxlen);
-__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, unsigned char *d, int len,
-                                       int *al);
+__owur int ssl_parse_clienthello_use_srtp_ext(SSL *s, PACKET *pkt, int *al);
 __owur int ssl_add_serverhello_use_srtp_ext(SSL *s, unsigned char *p, int *len,
                                      int maxlen);
 __owur int ssl_parse_serverhello_use_srtp_ext(SSL *s, unsigned char *d, int len,
index 9063bca..26a3c43 100644 (file)
@@ -547,8 +547,8 @@ int ssl_get_new_session(SSL *s, int session)
  *   - Both for new and resumed sessions, s->tlsext_ticket_expected is set to 1
  *     if the server should issue a new session ticket (to 0 otherwise).
  */
-int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
-                         const unsigned char *limit)
+int ssl_get_prev_session(SSL *s, PACKET *pkt, unsigned char *session_id,
+                         int len)
 {
     /* This is used only by servers. */
 
@@ -560,16 +560,11 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
     if (len < 0 || len > SSL_MAX_SSL_SESSION_ID_LENGTH)
         goto err;
 
-    if (session_id + len > limit) {
-        fatal = 1;
-        goto err;
-    }
-
     if (len == 0)
         try_session_cache = 0;
 
     /* sets s->tlsext_ticket_expected */
-    r = tls1_process_ticket(s, session_id, len, limit, &ret);
+    r = tls1_process_ticket(s, pkt, session_id, len, &ret);
     switch (r) {
     case -1:                   /* Error during processing */
         fatal = 1;
index 47abf2b..c0dd35f 100644 (file)
@@ -1756,46 +1756,33 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf,
  * alert value to send in the event of a non-zero return.  returns: 0 on
  * success.
  */
-static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
-                                         unsigned data_len, int *al)
+static int tls1_alpn_handle_client_hello(SSL *s, PACKET *pkt, int *al)
 {
-    unsigned i;
-    unsigned proto_len;
+    unsigned int data_len;
+    unsigned int proto_len;
     const unsigned char *selected;
+    unsigned char *data;
     unsigned char selected_len;
     int r;
 
     if (s->ctx->alpn_select_cb == NULL)
         return 0;
 
-    if (data_len < 2)
-        goto parse_error;
-
     /*
      * data should contain a uint16 length followed by a series of 8-bit,
      * length-prefixed strings.
      */
-    i = ((unsigned)data[0]) << 8 | ((unsigned)data[1]);
-    data_len -= 2;
-    data += 2;
-    if (data_len != i)
-        goto parse_error;
-
-    if (data_len < 2)
+    if (!PACKET_get_net_2(pkt, &data_len)
+            || PACKET_remaining(pkt) != data_len
+            || !PACKET_peek_bytes(pkt, &data, data_len))
         goto parse_error;
 
-    for (i = 0; i < data_len;) {
-        proto_len = data[i];
-        i++;
-
-        if (proto_len == 0)
-            goto parse_error;
-
-        if (i + proto_len < i || i + proto_len > data_len)
+    do {
+        if (!PACKET_get_1(pkt, &proto_len)
+                || proto_len == 0
+                || !PACKET_forward(pkt, proto_len))
             goto parse_error;
-
-        i += proto_len;
-    }
+    } while (PACKET_remaining(pkt));
 
     r = s->ctx->alpn_select_cb(s, &selected, &selected_len, data, data_len,
                                s->ctx->alpn_select_cb_arg);
@@ -1830,10 +1817,11 @@ static int tls1_alpn_handle_client_hello(SSL *s, const unsigned char *data,
  * Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
  * 10.8..10.8.3 (which don't work).
  */
-static void ssl_check_for_safari(SSL *s, const unsigned char *data,
-                                 const unsigned char *d, int n)
+static void ssl_check_for_safari(SSL *s, PACKET *pkt)
 {
-    unsigned short type, size;
+    unsigned int type, size;
+    unsigned char *eblock1, *eblock2;
+
     static const unsigned char kSafariExtensionsBlock[] = {
         0x00, 0x0a,             /* elliptic_curves extension */
         0x00, 0x08,             /* 8 bytes */
@@ -1860,38 +1848,34 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
         0x02, 0x03,             /* SHA-1/ECDSA */
     };
 
-    if (data >= (d + n - 2))
+    if (!PACKET_forward(pkt, 2)
+            || !PACKET_get_net_2(pkt, &type)
+            || !PACKET_get_net_2(pkt, &size)
+            || !PACKET_forward(pkt, size))
         return;
-    data += 2;
-
-    if (data > (d + n - 4))
-        return;
-    n2s(data, type);
-    n2s(data, size);
 
     if (type != TLSEXT_TYPE_server_name)
         return;
 
-    if (data + size > d + n)
-        return;
-    data += size;
-
     if (TLS1_get_client_version(s) >= TLS1_2_VERSION) {
         const size_t len1 = sizeof(kSafariExtensionsBlock);
         const size_t len2 = sizeof(kSafariTLS12ExtensionsBlock);
 
-        if (data + len1 + len2 != d + n)
+        if (!PACKET_get_bytes(pkt, &eblock1, len1)
+                || !PACKET_get_bytes(pkt, &eblock2, len2)
+                || PACKET_remaining(pkt))
             return;
-        if (memcmp(data, kSafariExtensionsBlock, len1) != 0)
+        if (memcmp(eblock1, kSafariExtensionsBlock, len1) != 0)
             return;
-        if (memcmp(data + len1, kSafariTLS12ExtensionsBlock, len2) != 0)
+        if (memcmp(eblock2, kSafariTLS12ExtensionsBlock, len2) != 0)
             return;
     } else {
         const size_t len = sizeof(kSafariExtensionsBlock);
 
-        if (data + len != d + n)
+        if (!PACKET_get_bytes(pkt, &eblock1, len)
+                || PACKET_remaining(pkt))
             return;
-        if (memcmp(data, kSafariExtensionsBlock, len) != 0)
+        if (memcmp(eblock1, kSafariExtensionsBlock, len) != 0)
             return;
     }
 
@@ -1899,13 +1883,12 @@ static void ssl_check_for_safari(SSL *s, const unsigned char *data,
 }
 #endif                         /* !OPENSSL_NO_EC */
 
-static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
-                                       unsigned char *d, int n, int *al)
+static int ssl_scan_clienthello_tlsext(SSL *s, PACKET *pkt, int *al)
 {
-    unsigned short type;
-    unsigned short size;
-    unsigned short len;
-    unsigned char *data = *p;
+    unsigned int type;
+    unsigned int size;
+    unsigned int len;
+    unsigned char *data;
     int renegotiate_seen = 0;
 
     s->servername_done = 0;
@@ -1923,8 +1906,8 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 
 #ifndef OPENSSL_NO_EC
     if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
-        ssl_check_for_safari(s, data, d, n);
-#endif                         /* !OPENSSL_NO_EC */
+        ssl_check_for_safari(s, pkt);
+# endif /* !OPENSSL_NO_EC */
 
     /* Clear any signature algorithms extension received */
     OPENSSL_free(s->s3->tmp.peer_sigalgs);
@@ -1940,27 +1923,26 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 
     s->srtp_profile = NULL;
 
-    if (data == d + n)
+    if (PACKET_remaining(pkt) == 0)
         goto ri_check;
 
-    if (data > (d + n - 2))
-        goto err;
-
-    n2s(data, len);
-
-    if (data > (d + n - len))
+    if (!PACKET_get_net_2(pkt, &len))
         goto err;
 
-    while (data <= (d + n - 4)) {
-        n2s(data, type);
-        n2s(data, size);
+    while (PACKET_get_net_2(pkt, &type) && PACKET_get_net_2(pkt, &size)) {
+        PACKET subpkt;
 
-        if (data + size > (d + n))
+        if (!PACKET_peek_bytes(pkt, &data, size))
             goto err;
+
         if (s->tlsext_debug_cb)
             s->tlsext_debug_cb(s, 0, type, data, size, s->tlsext_debug_arg);
+
+        if (!PACKET_get_sub_packet(pkt, &subpkt, size))
+            goto err;
+
         if (type == TLSEXT_TYPE_renegotiate) {
-            if (!ssl_parse_clienthello_renegotiate_ext(s, data, size, al))
+            if (!ssl_parse_clienthello_renegotiate_ext(s, &subpkt, al))
                 return 0;
             renegotiate_seen = 1;
         } else if (s->version == SSL3_VERSION) {
@@ -1992,23 +1974,18 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 
         else if (type == TLSEXT_TYPE_server_name) {
             unsigned char *sdata;
-            int servname_type;
-            int dsize;
+            unsigned int servname_type;
+            unsigned int dsize;
+            PACKET ssubpkt;
 
-            if (size < 2)
+            if (!PACKET_get_net_2(&subpkt, &dsize)
+                    || !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
                 goto err;
-            n2s(data, dsize);
-            size -= 2;
-            if (dsize > size)
-                goto err;
-
-            sdata = data;
-            while (dsize > 3) {
-                servname_type = *(sdata++);
-                n2s(sdata, len);
-                dsize -= 3;
 
-                if (len > dsize)
+            while (PACKET_remaining(&ssubpkt) > 3) {
+                if (!PACKET_get_1(&ssubpkt, &servname_type)
+                        || !PACKET_get_net_2(&ssubpkt, &len)
+                        || PACKET_remaining(&ssubpkt) < len)
                     goto err;
 
                 if (s->servername_done == 0)
@@ -2027,7 +2004,13 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
                                 *al = TLS1_AD_INTERNAL_ERROR;
                                 return 0;
                             }
-                            memcpy(s->session->tlsext_hostname, sdata, len);
+                            if (!PACKET_copy_bytes(&ssubpkt,
+                                    (unsigned char *)s->session
+                                        ->tlsext_hostname,
+                                    len)) {
+                                *al = SSL_AD_DECODE_ERROR;
+                                return 0;
+                            }
                             s->session->tlsext_hostname[len] = '\0';
                             if (strlen(s->session->tlsext_hostname) != len) {
                                 OPENSSL_free(s->session->tlsext_hostname);
@@ -2037,48 +2020,55 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
                             }
                             s->servername_done = 1;
 
-                        } else
+                        } else {
+                            if (!PACKET_get_bytes(&ssubpkt, &sdata, len)) {
+                                *al = SSL_AD_DECODE_ERROR;
+                                return 0;
+                            }
                             s->servername_done = s->session->tlsext_hostname
                                 && strlen(s->session->tlsext_hostname) == len
                                 && strncmp(s->session->tlsext_hostname,
                                            (char *)sdata, len) == 0;
+                        }
 
                         break;
 
                     default:
                         break;
                     }
-
-                dsize -= len;
             }
-            if (dsize != 0)
+            /* We shouldn't have any bytes left */
+            if (PACKET_remaining(&ssubpkt))
                 goto err;
 
         }
 #ifndef OPENSSL_NO_SRP
         else if (type == TLSEXT_TYPE_srp) {
-            if (size == 0 || ((len = data[0])) != (size - 1))
-                goto err;
-            if (s->srp_ctx.login != NULL)
+            if (!PACKET_get_1(&subpkt, &len)
+                    || s->srp_ctx.login != NULL)
                 goto err;
+
             if ((s->srp_ctx.login = OPENSSL_malloc(len + 1)) == NULL)
                 return -1;
-            memcpy(s->srp_ctx.login, &data[1], len);
+            if (!PACKET_copy_bytes(&subpkt, (unsigned char *)s->srp_ctx.login,
+                                   len))
+                goto err;
             s->srp_ctx.login[len] = '\0';
 
-            if (strlen(s->srp_ctx.login) != len)
+            if (strlen(s->srp_ctx.login) != len
+                    || PACKET_remaining(&subpkt))
                 goto err;
         }
 #endif
 
 #ifndef OPENSSL_NO_EC
         else if (type == TLSEXT_TYPE_ec_point_formats) {
-            unsigned char *sdata = data;
-            int ecpointformatlist_length = *(sdata++);
+            unsigned int ecpointformatlist_length;
 
-            if (ecpointformatlist_length != size - 1 ||
-                ecpointformatlist_length < 1)
+            if (!PACKET_get_1(&subpkt, &ecpointformatlist_length)
+                    || ecpointformatlist_length == 0)
                 goto err;
+
             if (!s->hit) {
                 OPENSSL_free(s->session->tlsext_ecpointformatlist);
                 s->session->tlsext_ecpointformatlist = NULL;
@@ -2090,19 +2080,26 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
                 }
                 s->session->tlsext_ecpointformatlist_length =
                     ecpointformatlist_length;
-                memcpy(s->session->tlsext_ecpointformatlist, sdata,
-                       ecpointformatlist_length);
+                if (!PACKET_copy_bytes(&subpkt,
+                        s->session->tlsext_ecpointformatlist,
+                        ecpointformatlist_length))
+                    goto err;
+            } else if (!PACKET_forward(&subpkt, ecpointformatlist_length)) {
+                goto err;
+            }
+            /* We should have consumed all the bytes by now */
+            if (PACKET_remaining(&subpkt)) {
+                *al = TLS1_AD_DECODE_ERROR;
+                return 0;
             }
         } else if (type == TLSEXT_TYPE_elliptic_curves) {
-            unsigned char *sdata = data;
-            int ellipticcurvelist_length = (*(sdata++) << 8);
-            ellipticcurvelist_length += (*(sdata++));
+            unsigned int ellipticcurvelist_length;
 
-            if (ellipticcurvelist_length != size - 2 ||
-                ellipticcurvelist_length < 1 ||
-                /* Each NamedCurve is 2 bytes. */
-                ellipticcurvelist_length & 1)
-                    goto err;
+            /* Each NamedCurve is 2 bytes and we must have at least 1 */
+            if (!PACKET_get_net_2(&subpkt, &ellipticcurvelist_length)
+                    || ellipticcurvelist_length == 0
+                    || (ellipticcurvelist_length & 1) != 0)
+                goto err;
 
             if (!s->hit) {
                 if (s->session->tlsext_ellipticcurvelist)
@@ -2116,54 +2113,63 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
                 }
                 s->session->tlsext_ellipticcurvelist_length =
                     ellipticcurvelist_length;
-                memcpy(s->session->tlsext_ellipticcurvelist, sdata,
-                       ellipticcurvelist_length);
+                if (!PACKET_copy_bytes(&subpkt,
+                        s->session->tlsext_ellipticcurvelist,
+                        ellipticcurvelist_length))
+                    goto err;
+            } else if (!PACKET_forward(&subpkt, ellipticcurvelist_length)) {
+                goto err;
+            }
+            /* We should have consumed all the bytes by now */
+            if (PACKET_remaining(&subpkt)) {
+                goto err;
             }
         }
 #endif                         /* OPENSSL_NO_EC */
         else if (type == TLSEXT_TYPE_session_ticket) {
-            if (s->tls_session_ticket_ext_cb &&
-                !s->tls_session_ticket_ext_cb(s, data, size,
-                                              s->tls_session_ticket_ext_cb_arg))
-            {
+            if (!PACKET_forward(&subpkt, size)
+                || (s->tls_session_ticket_ext_cb &&
+                    !s->tls_session_ticket_ext_cb(s, data, size,
+                                        s->tls_session_ticket_ext_cb_arg))) {
                 *al = TLS1_AD_INTERNAL_ERROR;
                 return 0;
             }
         } else if (type == TLSEXT_TYPE_signature_algorithms) {
-            int dsize;
-            if (s->s3->tmp.peer_sigalgs || size < 2)
-                goto err;
-            n2s(data, dsize);
-            size -= 2;
-            if (dsize != size || dsize & 1 || !dsize)
-                goto err;
-            if (!tls1_save_sigalgs(s, data, dsize))
+            unsigned int dsize;
+
+            if (s->s3->tmp.peer_sigalgs
+                    || !PACKET_get_net_2(&subpkt, &dsize)
+                    || (dsize & 1) != 0
+                    || (dsize == 0)
+                    || !PACKET_get_bytes(&subpkt, &data, dsize)
+                    || PACKET_remaining(&subpkt)
+                    || !tls1_save_sigalgs(s, data, dsize)) {
                 goto err;
+            }
         } else if (type == TLSEXT_TYPE_status_request) {
+            PACKET ssubpkt;
 
-            if (size < 5)
+            if (!PACKET_get_1(&subpkt,
+                              (unsigned int *)&s->tlsext_status_type))
                 goto err;
 
-            s->tlsext_status_type = *data++;
-            size--;
             if (s->tlsext_status_type == TLSEXT_STATUSTYPE_ocsp) {
                 const unsigned char *sdata;
-                int dsize;
+                unsigned int dsize;
                 /* Read in responder_id_list */
-                n2s(data, dsize);
-                size -= 2;
-                if (dsize > size)
+                if (!PACKET_get_net_2(&subpkt, &dsize)
+                        || !PACKET_get_sub_packet(&subpkt, &ssubpkt, dsize))
                     goto err;
-                while (dsize > 0) {
+
+                while (PACKET_remaining(&ssubpkt)) {
                     OCSP_RESPID *id;
-                    int idsize;
-                    if (dsize < 4)
-                        goto err;
-                    n2s(data, idsize);
-                    dsize -= 2 + idsize;
-                    size -= 2 + idsize;
-                    if (dsize < 0)
+                    unsigned int idsize;
+
+                    if (PACKET_remaining(&ssubpkt) < 4
+                            || !PACKET_get_net_2(&ssubpkt, &idsize)
+                            || !PACKET_get_bytes(&ssubpkt, &data, idsize)) {
                         goto err;
+                    }
                     sdata = data;
                     data += idsize;
                     id = d2i_OCSP_RESPID(NULL, &sdata, idsize);
@@ -2188,12 +2194,11 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
                 }
 
                 /* Read in request_extensions */
-                if (size < 2)
-                    goto err;
-                n2s(data, dsize);
-                size -= 2;
-                if (dsize != size)
+                if (!PACKET_get_net_2(&subpkt, &dsize)
+                        || !PACKET_get_bytes(&subpkt, &data, dsize)
+                        || PACKET_remaining(&subpkt)) {
                     goto err;
+                }
                 sdata = data;
                 if (dsize > 0) {
                     sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
@@ -2212,7 +2217,14 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
         }
 #ifndef OPENSSL_NO_HEARTBEATS
         else if (type == TLSEXT_TYPE_heartbeat) {
-            switch (data[0]) {
+            unsigned int hbtype;
+
+            if (!PACKET_get_1(&subpkt, &hbtype)
+                    || PACKET_remaining(&subpkt)) {
+                *al = SSL_AD_DECODE_ERROR;
+                return 0;
+            }
+            switch (hbtype) {
             case 0x01:         /* Client allows us to send HB requests */
                 s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
                 break;
@@ -2253,7 +2265,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 
         else if (type == TLSEXT_TYPE_application_layer_protocol_negotiation &&
                  s->ctx->alpn_select_cb && s->s3->tmp.finish_md_len == 0) {
-            if (tls1_alpn_handle_client_hello(s, data, size, al) != 0)
+            if (tls1_alpn_handle_client_hello(s, &subpkt, al) != 0)
                 return 0;
 #ifndef OPENSSL_NO_NEXTPROTONEG
             /* ALPN takes precedence over NPN. */
@@ -2265,7 +2277,7 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
 #ifndef OPENSSL_NO_SRTP
         else if (SSL_IS_DTLS(s) && SSL_get_srtp_profiles(s)
                  && type == TLSEXT_TYPE_use_srtp) {
-            if (ssl_parse_clienthello_use_srtp_ext(s, data, size, al))
+            if (ssl_parse_clienthello_use_srtp_ext(s, &subpkt, al))
                 return 0;
         }
 #endif
@@ -2288,16 +2300,12 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p,
             if (custom_ext_parse(s, 1, type, data, size, al) <= 0)
                 return 0;
         }
-
-        data += size;
     }
 
     /* Spurious data on the end */
-    if (data != d + n)
+    if (PACKET_remaining(pkt) != 0)
         goto err;
 
-    *p = data;
-
  ri_check:
 
     /* Need RI if renegotiating */
@@ -2316,12 +2324,11 @@ err:
     return 0;
 }
 
-int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
-                                 int n)
+int ssl_parse_clienthello_tlsext(SSL *s, PACKET *pkt)
 {
     int al = -1;
     custom_ext_init(&s->cert->srv_ext);
-    if (ssl_scan_clienthello_tlsext(s, p, d, n, &al) <= 0) {
+    if (ssl_scan_clienthello_tlsext(s, pkt, &al) <= 0) {
         ssl3_send_alert(s, SSL3_AL_FATAL, al);
         return 0;
     }
@@ -2934,12 +2941,12 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d,
  *   s->ctx->tlsext_ticket_key_cb asked to renew the client's ticket.
  *   Otherwise, s->tlsext_ticket_expected is set to 0.
  */
-int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
-                        const unsigned char *limit, SSL_SESSION **ret)
+int tls1_process_ticket(SSL *s, PACKET *pkt,  unsigned char *session_id,
+                        int len, SSL_SESSION **ret)
 {
-    /* Point after session ID in client hello */
-    const unsigned char *p = session_id + len;
-    unsigned short i;
+    unsigned int i;
+    size_t bookmark = 0;
+    int retv = -1;
 
     *ret = NULL;
     s->tlsext_ticket_expected = 0;
@@ -2950,46 +2957,60 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
      */
     if (!tls_use_ticket(s))
         return 0;
-    if ((s->version <= SSL3_VERSION) || !limit)
+    if ((s->version <= SSL3_VERSION))
         return 0;
-    if (p >= limit)
+
+    if (!PACKET_get_bookmark(pkt, &bookmark)) {
         return -1;
+    }
+
     /* Skip past DTLS cookie */
     if (SSL_IS_DTLS(s)) {
-        i = *(p++);
-        p += i;
-        if (p >= limit)
-            return -1;
+        if (!PACKET_get_1(pkt, &i)
+                || !PACKET_forward(pkt, i)) {
+            retv = -1;
+            goto end;
+        }
     }
-    /* Skip past cipher list */
-    n2s(p, i);
-    p += i;
-    if (p >= limit)
-        return -1;
-    /* Skip past compression algorithm list */
-    i = *(p++);
-    p += i;
-    if (p > limit)
-        return -1;
+    /* Skip past cipher list and compression algorithm list */
+    if (!PACKET_get_net_2(pkt, &i)
+            || !PACKET_forward(pkt, i)
+            || !PACKET_get_1(pkt, &i)
+            || !PACKET_forward(pkt, i)) {
+        retv = -1;
+        goto end;
+    }
+
     /* Now at start of extensions */
-    if ((p + 2) >= limit)
-        return 0;
-    n2s(p, i);
-    while ((p + 4) <= limit) {
-        unsigned short type, size;
-        n2s(p, type);
-        n2s(p, size);
-        if (p + size > limit)
-            return 0;
+    if (!PACKET_get_net_2(pkt, &i)) {
+        retv = 0;
+        goto end;
+    }
+    while (PACKET_remaining (pkt) >= 4) {
+        unsigned int type, size;
+
+        if (!PACKET_get_net_2(pkt, &type)
+                || !PACKET_get_net_2(pkt, &size)) {
+            /* Shouldn't ever happen */
+            retv = -1;
+            goto end;
+        }
+        if (PACKET_remaining(pkt) < size) {
+            retv = 0;
+            goto end;
+        }
         if (type == TLSEXT_TYPE_session_ticket) {
             int r;
+            unsigned char *etick;
+
             if (size == 0) {
                 /*
                  * The client will accept a ticket but doesn't currently have
                  * one.
                  */
                 s->tlsext_ticket_expected = 1;
-                return 1;
+                retv = 1;
+                goto end;
             }
             if (s->tls_session_secret_cb) {
                 /*
@@ -2998,25 +3019,39 @@ int tls1_process_ticket(SSL *s, unsigned char *session_id, int len,
                  * abbreviated handshake based on external mechanism to
                  * calculate the master secret later.
                  */
-                return 2;
+                retv = 2;
+                goto end;
             }
-            r = tls_decrypt_ticket(s, p, size, session_id, len, ret);
+            if (!PACKET_get_bytes(pkt, &etick, size)) {
+                /* Shouldn't ever happen */
+                retv = -1;
+                goto end;
+            }
+            r = tls_decrypt_ticket(s, etick, size, session_id, len, ret);
             switch (r) {
             case 2:            /* ticket couldn't be decrypted */
                 s->tlsext_ticket_expected = 1;
-                return 2;
+                retv = 2;
+                break;
             case 3:            /* ticket was decrypted */
-                return r;
+                retv = r;
+                break;
             case 4:            /* ticket decrypted but need to renew */
                 s->tlsext_ticket_expected = 1;
-                return 3;
+                retv = 3;
+                break;
             default:           /* fatal error */
-                return -1;
+                retv = -1;
+                break;
             }
+            goto end;
         }
-        p += size;
     }
-    return 0;
+    retv = 0;
+end:
+    if (!PACKET_goto_bookmark(pkt, bookmark))
+        return -1;
+    return retv;
 }
 
 /*-
index b9a35c7..22a71fe 100644 (file)
@@ -143,23 +143,14 @@ int ssl_add_clienthello_renegotiate_ext(SSL *s, unsigned char *p, int *len,
 /*
  * Parse the client's renegotiation binding and abort if it's not right
  */
-int ssl_parse_clienthello_renegotiate_ext(SSL *s, unsigned char *d, int len,
-                                          int *al)
+int ssl_parse_clienthello_renegotiate_ext(SSL *s, PACKET *pkt, int *al)
 {
-    int ilen;
+    unsigned int ilen;
+    unsigned char *d;
 
     /* Parse the length byte */
-    if (len < 1) {
-        SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
-               SSL_R_RENEGOTIATION_ENCODING_ERR);
-        *al = SSL_AD_ILLEGAL_PARAMETER;
-        return 0;
-    }
-    ilen = *d;
-    d++;
-
-    /* Consistency check */
-    if ((ilen + 1) != len) {
+    if (!PACKET_get_1(pkt, &ilen)
+            || !PACKET_get_bytes(pkt, &d, ilen)) {
         SSLerr(SSL_F_SSL_PARSE_CLIENTHELLO_RENEGOTIATE_EXT,
                SSL_R_RENEGOTIATION_ENCODING_ERR);
         *al = SSL_AD_ILLEGAL_PARAMETER;