[openssl-commits] [openssl] master update

Emilia Kasper emilia at openssl.org
Wed Aug 26 12:28:12 UTC 2015


The branch master has been updated
       via  ec30e8566e43d888ab1d7cf01749a979896bb3d9 (commit)
       via  9cc3e8f1f2b9e9c36a2f61e914bc9711c35568b6 (commit)
       via  2aa815c343357524aa5a3775994d694de65544f8 (commit)
      from  b48357d9953decc43333979ca11ebc1500040f4e (commit)


- Log -----------------------------------------------------------------
commit ec30e8566e43d888ab1d7cf01749a979896bb3d9
Author: Emilia Kasper <emilia at openssl.org>
Date:   Tue Aug 18 12:29:36 2015 +0200

    PACKET: add methods for reading length-prefixed TLS vectors.
    
    Rewrite ssl3_get_client_hello to use the new methods.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 9cc3e8f1f2b9e9c36a2f61e914bc9711c35568b6
Author: Emilia Kasper <emilia at openssl.org>
Date:   Tue Aug 18 19:01:51 2015 +0200

    Fix SSLv2-compatible ClientHello processing.
    
    If the client challenge is less than 32 bytes, it is padded with leading - not trailing - zero bytes.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

commit 2aa815c343357524aa5a3775994d694de65544f8
Author: Emilia Kasper <emilia at openssl.org>
Date:   Tue Aug 18 14:55:53 2015 +0200

    PACKET: constify where possible
    
    The PACKET should hold a 'const unsigned char*' underneath as well
    but the legacy code passes the record buffer around as 'unsigned char*'
    (to callbacks, too) so that's a bigger refactor.
    
    Reviewed-by: Matt Caswell <matt at openssl.org>

-----------------------------------------------------------------------

Summary of changes:
 ssl/packet_locl.h | 110 +++++++++++++++++++++++++++++++++++++++++++++++-------
 ssl/s3_srvr.c     | 105 +++++++++++++++++++++++++--------------------------
 test/packettest.c |  84 ++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 231 insertions(+), 68 deletions(-)

diff --git a/ssl/packet_locl.h b/ssl/packet_locl.h
index a5e4d00..3f03fa7 100644
--- a/ssl/packet_locl.h
+++ b/ssl/packet_locl.h
@@ -82,12 +82,23 @@ typedef struct {
 /*
  * Returns the number of bytes remaining to be read in the PACKET
  */
-__owur static inline size_t PACKET_remaining(PACKET *pkt)
+__owur static inline size_t PACKET_remaining(const PACKET *pkt)
 {
     return (size_t)(pkt->end - pkt->curr);
 }
 
 /*
+ * Returns a pointer to the PACKET's current position.
+ * For use in non-PACKETized APIs.
+ * TODO(openssl-team): this should return 'const unsigned char*' but can't
+ * currently because legacy code passes 'unsigned char*'s around.
+ */
+static inline unsigned char *PACKET_data(const PACKET *pkt)
+{
+    return pkt->curr;
+}
+
+/*
  * Initialise a PACKET with |len| bytes held in |buf|. This does not make a
  * copy of the data so |buf| must be present for the whole time that the PACKET
  * is being used.
@@ -113,8 +124,8 @@ static inline int PACKET_buf_init(PACKET *pkt, unsigned char *buf, size_t len)
  * Data is not copied: the |subpkt| packet will share its underlying buffer with
  * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
  */
-__owur static inline int PACKET_peek_sub_packet(PACKET *pkt, PACKET *subpkt,
-                                               size_t len)
+__owur static inline int PACKET_peek_sub_packet(const PACKET *pkt,
+                                                PACKET *subpkt, size_t len)
 {
     if (PACKET_remaining(pkt) < len)
         return 0;
@@ -143,7 +154,8 @@ __owur static inline int PACKET_get_sub_packet(PACKET *pkt, PACKET *subpkt,
 /* Peek ahead at 2 bytes in network order from |pkt| and store the value in
  * |*data|
  */
-__owur static inline int PACKET_peek_net_2(PACKET *pkt, unsigned int *data)
+__owur static inline int PACKET_peek_net_2(const PACKET *pkt,
+                                           unsigned int *data)
 {
     if (PACKET_remaining(pkt) < 2)
         return 0;
@@ -169,7 +181,8 @@ __owur static inline int PACKET_get_net_2(PACKET *pkt, unsigned int *data)
 /* Peek ahead at 3 bytes in network order from |pkt| and store the value in
  * |*data|
  */
-__owur static inline int PACKET_peek_net_3(PACKET *pkt, unsigned long *data)
+__owur static inline int PACKET_peek_net_3(const PACKET *pkt,
+                                           unsigned long *data)
 {
     if (PACKET_remaining(pkt) < 3)
         return 0;
@@ -196,7 +209,8 @@ __owur static inline int PACKET_get_net_3(PACKET *pkt, unsigned long *data)
 /* Peek ahead at 4 bytes in network order from |pkt| and store the value in
  * |*data|
  */
-__owur static inline int PACKET_peek_net_4(PACKET *pkt, unsigned long *data)
+__owur static inline int PACKET_peek_net_4(const PACKET *pkt,
+                                           unsigned long *data)
 {
     if (PACKET_remaining(pkt) < 4)
         return 0;
@@ -222,7 +236,7 @@ __owur static inline int PACKET_get_net_4(PACKET *pkt, unsigned long *data)
 }
 
 /* Peek ahead at 1 byte from |pkt| and store the value in |*data| */
-__owur static inline int PACKET_peek_1(PACKET *pkt, unsigned int *data)
+__owur static inline int PACKET_peek_1(const PACKET *pkt, unsigned int *data)
 {
     if (!PACKET_remaining(pkt))
         return 0;
@@ -247,7 +261,7 @@ __owur static inline int PACKET_get_1(PACKET *pkt, unsigned int *data)
  * Peek ahead at 4 bytes in reverse network order from |pkt| and store the value
  * in |*data|
  */
-__owur static inline int PACKET_peek_4(PACKET *pkt, unsigned long *data)
+__owur static inline int PACKET_peek_4(const PACKET *pkt, unsigned long *data)
 {
     if (PACKET_remaining(pkt) < 4)
         return 0;
@@ -281,7 +295,7 @@ __owur static inline int PACKET_get_4(PACKET *pkt, unsigned long *data)
  * caller should not free this data directly (it will be freed when the
  * underlying buffer gets freed
  */
-__owur static inline int PACKET_peek_bytes(PACKET *pkt, unsigned char **data,
+__owur static inline int PACKET_peek_bytes(const PACKET *pkt, unsigned char **data,
                                           size_t len)
 {
     if (PACKET_remaining(pkt) < len)
@@ -310,7 +324,7 @@ __owur static inline int PACKET_get_bytes(PACKET *pkt, unsigned char **data,
 }
 
 /* Peek ahead at |len| bytes from |pkt| and copy them to |data| */
-__owur static inline int PACKET_peek_copy_bytes(PACKET *pkt,
+__owur static inline int PACKET_peek_copy_bytes(const PACKET *pkt,
                                                 unsigned char *data, size_t len)
 {
     if (PACKET_remaining(pkt) < len)
@@ -356,7 +370,7 @@ __owur static inline int PACKET_forward(PACKET *pkt, size_t len)
 }
 
 /* Store a bookmark for the current reading position in |*bm| */
-__owur static inline int PACKET_get_bookmark(PACKET *pkt, size_t *bm)
+__owur static inline int PACKET_get_bookmark(const PACKET *pkt, size_t *bm)
 {
     *bm = pkt->curr - pkt->start;
 
@@ -378,16 +392,86 @@ __owur static inline int PACKET_goto_bookmark(PACKET *pkt, size_t bm)
  * Stores the total length of the packet we have in the underlying buffer in
  * |*len|
  */
-__owur static inline int PACKET_length(PACKET *pkt, size_t *len)
+__owur static inline int PACKET_length(const PACKET *pkt, size_t *len)
 {
     *len = pkt->end - pkt->start;
 
     return 1;
 }
 
+/*
+ * Reads a variable-length vector prefixed with a one-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static inline int PACKET_get_length_prefixed_1(PACKET *pkt, PACKET *subpkt)
+{
+  unsigned int length;
+  unsigned char *data;
+  PACKET tmp = *pkt;
+  if (!PACKET_get_1(&tmp, &length) ||
+      !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+      return 0;
+  }
+
+  *pkt = tmp;
+  subpkt->start = subpkt->curr = data;
+  subpkt->end = subpkt->start + length;
+
+  return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a two-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static inline int PACKET_get_length_prefixed_2(PACKET *pkt, PACKET *subpkt)
+{
+  unsigned int length;
+  unsigned char *data;
+  PACKET tmp = *pkt;
+  if (!PACKET_get_net_2(&tmp, &length) ||
+      !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+      return 0;
+  }
+
+  *pkt = tmp;
+  subpkt->start = subpkt->curr = data;
+  subpkt->end = subpkt->start + length;
+
+  return 1;
+}
+
+/*
+ * Reads a variable-length vector prefixed with a three-byte length, and stores
+ * the contents in |subpkt|. |pkt| can equal |subpkt|.
+ * Data is not copied: the |subpkt| packet will share its underlying buffer with
+ * the original |pkt|, so data wrapped by |pkt| must outlive the |subpkt|.
+ * Upon failure, the original |pkt| and |subpkt| are not modified.
+ */
+__owur static inline int PACKET_get_length_prefixed_3(PACKET *pkt, PACKET *subpkt)
+{
+  unsigned long length;
+  unsigned char *data;
+  PACKET tmp = *pkt;
+  if (!PACKET_get_net_3(&tmp, &length) ||
+      !PACKET_get_bytes(&tmp, &data, (size_t)length)) {
+      return 0;
+  }
+
+  *pkt = tmp;
+  subpkt->start = subpkt->curr = data;
+  subpkt->end = subpkt->start + length;
+
+  return 1;
+}
 # ifdef __cplusplus
 }
 # endif
 
 #endif /* HEADER_PACKET_LOCL_H */
-
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 8bdb082..74c3696 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -838,19 +838,16 @@ int ssl3_send_hello_request(SSL *s)
 int ssl3_get_client_hello(SSL *s)
 {
     int i, ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
-    unsigned int j, cipherlen, complen;
-    unsigned int cookie_len = 0;
+    unsigned int j, complen = 0;
     long n;
     unsigned long id;
     SSL_CIPHER *c;
 #ifndef OPENSSL_NO_COMP
-    unsigned char *q = NULL;
     SSL_COMP *comp = NULL;
 #endif
     STACK_OF(SSL_CIPHER) *ciphers = NULL;
     int protverr = 1;
-    PACKET pkt;
-    unsigned char *sess, *cdata;
+    PACKET pkt, cipher_suite, compression;
 
     if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet)
         goto retry_cert;
@@ -1013,30 +1010,31 @@ int ssl3_get_client_hello(SSL *s)
          * Note, this is only for SSLv3+ using the backward compatible format.
          * Real SSLv2 is not supported, and is rejected above.
          */
-        unsigned int csl, sil, cl;
+        unsigned int cipher_len, session_id_len, challenge_len;
 
-        if (!PACKET_get_net_2(&pkt, &csl)
-                || !PACKET_get_net_2(&pkt, &sil)
-                || !PACKET_get_net_2(&pkt, &cl)) {
+        if (!PACKET_get_net_2(&pkt, &cipher_len)
+                || !PACKET_get_net_2(&pkt, &session_id_len)
+                || !PACKET_get_net_2(&pkt, &challenge_len)) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
         }
 
-        if (csl == 0) {
+        if (cipher_len == 0) {
             /* we need at least one cipher */
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
             goto f_err;
         }
 
-        if (!PACKET_get_bytes(&pkt, &cdata, csl)) {
+        if (!PACKET_get_sub_packet(&pkt, &cipher_suite, cipher_len)) {
             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) {
+        if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite),
+                                     cipher_len, &(ciphers), 1) == NULL) {
             goto err;
         }
 
@@ -1044,7 +1042,7 @@ 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)) {
+        if (!PACKET_forward(&pkt, session_id_len)) {
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH);
             al = SSL_AD_DECODE_ERROR;
             goto f_err;
@@ -1055,25 +1053,24 @@ int ssl3_get_client_hello(SSL *s)
             goto err;
 
         /* Load the client random */
-        i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl;
+        i = challenge_len > SSL3_RANDOM_SIZE ? SSL3_RANDOM_SIZE : challenge_len;
         memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE);
-        if (!PACKET_peek_copy_bytes(&pkt, s->s3->client_random, i)
-                || !PACKET_forward(&pkt, cl)
+        if (!PACKET_peek_copy_bytes(&pkt,
+                                    s->s3->client_random + SSL3_RANDOM_SIZE - i,
+                                    i)
+                || !PACKET_forward(&pkt, challenge_len)
                 || 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 */
-
+        PACKET session_id;
+        unsigned int cookie_len;
         /* 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)) {
+		|| !PACKET_get_length_prefixed_1(&pkt, &session_id)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
@@ -1115,7 +1112,13 @@ int ssl3_get_client_hello(SSL *s)
             if (!ssl_get_new_session(s, 1))
                 goto err;
         } else {
-            i = ssl_get_prev_session(s, &pkt, sess, j);
+            /*
+             * TODO(openssl-team): ssl_get_prev_session passes a non-const
+             * 'unsigned char*' session id to a user callback. Grab a copy of
+             * the data?
+             */
+	    i = ssl_get_prev_session(s, &pkt, PACKET_data(&session_id),
+		                     PACKET_remaining(&session_id));
             /*
              * Only resume if the session's version matches the negotiated
              * version.
@@ -1138,11 +1141,13 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         if (SSL_IS_DTLS(s)) {
-            if (!PACKET_get_1(&pkt, &cookie_len)) {
+            PACKET cookie;
+            if (!PACKET_get_length_prefixed_1(&pkt, &cookie)) {
                 al = SSL_AD_DECODE_ERROR;
                 SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
                 goto f_err;
             }
+	    cookie_len = PACKET_remaining(&cookie);
             /*
              * The ClientHello may contain a cookie even if the
              * HelloVerify message has not been sent--make sure that it
@@ -1159,10 +1164,13 @@ int ssl3_get_client_hello(SSL *s)
             if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)
                     && cookie_len > 0) {
                 /* 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);
+                /*
+                 * TODO(openssl-team): rcvd_cookie appears unused outside this
+                 * function. Remove the field?
+                 */
+                if (!PACKET_copy_bytes(&cookie, s->d1->rcvd_cookie, cookie_len)) {
+                    al = SSL_AD_INTERNAL_ERROR;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
                     goto f_err;
                 }
 
@@ -1185,15 +1193,7 @@ 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;
-                }
             }
-
             if (s->method->version == DTLS_ANY_VERSION) {
                 /* Select version to use */
                 if (s->client_version <= DTLS1_2_VERSION &&
@@ -1221,26 +1221,21 @@ int ssl3_get_client_hello(SSL *s)
             }
         }
 
-        if (!PACKET_get_net_2(&pkt, &cipherlen)) {
+        if (!PACKET_get_length_prefixed_2(&pkt, &cipher_suite)) {
             al = SSL_AD_DECODE_ERROR;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT);
             goto f_err;
         }
 
-        if (cipherlen == 0) {
+        if (PACKET_remaining(&cipher_suite) == 0) {
             al = SSL_AD_ILLEGAL_PARAMETER;
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED);
             goto f_err;
         }
 
-        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, cdata, cipherlen, &(ciphers), 0) == NULL) {
+        if (ssl_bytes_to_cipher_list(s, PACKET_data(&cipher_suite),
+                                     PACKET_remaining(&cipher_suite),
+                                     &(ciphers), 0) == NULL) {
             goto err;
         }
 
@@ -1299,19 +1294,21 @@ int ssl3_get_client_hello(SSL *s)
         }
 
         /* compression */
-        if (!PACKET_get_1(&pkt, &complen)
-            || !PACKET_get_bytes(&pkt, &cdata, complen)) {
+        if (!PACKET_get_length_prefixed_1(&pkt, &compression)) {
             /* not enough data */
             al = SSL_AD_DECODE_ERROR;
+            /*
+             * TODO(openssl-team):
+             * SSL_R_LENGTH_TOO_SHORT and SSL_R_LENGTH_MISMATCH are used
+             * interchangeably. Pick one.
+             */
             SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
             goto f_err;
         }
 
-#ifndef OPENSSL_NO_COMP
-        q = cdata;
-#endif
+        complen = PACKET_remaining(&compression);
         for (j = 0; j < complen; j++) {
-            if (cdata[j] == 0)
+            if (PACKET_data(&compression)[j] == 0)
                 break;
         }
 
@@ -1413,7 +1410,7 @@ int ssl3_get_client_hello(SSL *s)
         }
         /* Look for resumed method in compression list */
         for (k = 0; k < complen; k++) {
-            if (q[k] == comp_id)
+            if (PACKET_data(&compression)[k] == comp_id)
                 break;
         }
         if (k >= complen) {
@@ -1434,7 +1431,7 @@ int ssl3_get_client_hello(SSL *s)
             comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
             v = comp->id;
             for (o = 0; o < complen; o++) {
-                if (v == q[o]) {
+                if (v == PACKET_data(&compression)[o]) {
                     done = 1;
                     break;
                 }
diff --git a/test/packettest.c b/test/packettest.c
index c3ac53b..b3f7bbb 100644
--- a/test/packettest.c
+++ b/test/packettest.c
@@ -281,6 +281,85 @@ static int test_PACKET_buf_init()
     return 1;
 }
 
+static int test_PACKET_get_length_prefixed_1()
+{
+    unsigned char buf[BUF_LEN];
+    const size_t len = 16;
+    unsigned int i;
+    PACKET pkt, short_pkt, subpkt;
+
+    buf[0] = len;
+    for (i = 1; i < BUF_LEN; i++) {
+        buf[i] = (i * 2) & 0xff;
+    }
+
+    if (       !PACKET_buf_init(&pkt, buf, BUF_LEN)
+            || !PACKET_buf_init(&short_pkt, buf, len)
+            || !PACKET_get_length_prefixed_1(&pkt, &subpkt)
+            ||  PACKET_remaining(&subpkt) != len
+            || !PACKET_get_net_2(&subpkt, &i)
+            ||  i != 0x0204
+            ||  PACKET_get_length_prefixed_1(&short_pkt, &subpkt)
+            ||  PACKET_remaining(&short_pkt) != len) {
+        fprintf(stderr, "test_PACKET_get_length_prefixed_1() failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+static int test_PACKET_get_length_prefixed_2()
+{
+    unsigned char buf[1024];
+    const size_t len = 516;  /* 0x0204 */
+    unsigned int i;
+    PACKET pkt, short_pkt, subpkt;
+
+    for (i = 1; i <= 1024; i++) {
+        buf[i-1] = (i * 2) & 0xff;
+    }
+
+    if (       !PACKET_buf_init(&pkt, buf, 1024)
+            || !PACKET_buf_init(&short_pkt, buf, len)
+            || !PACKET_get_length_prefixed_2(&pkt, &subpkt)
+            ||  PACKET_remaining(&subpkt) != len
+            || !PACKET_get_net_2(&subpkt, &i)
+            ||  i != 0x0608
+            ||  PACKET_get_length_prefixed_2(&short_pkt, &subpkt)
+            ||  PACKET_remaining(&short_pkt) != len) {
+        fprintf(stderr, "test_PACKET_get_length_prefixed_2() failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+static int test_PACKET_get_length_prefixed_3()
+{
+    unsigned char buf[1024];
+    const size_t len = 516;  /* 0x000204 */
+    unsigned int i;
+    PACKET pkt, short_pkt, subpkt;
+
+    for (i = 0; i < 1024; i++) {
+        buf[i] = (i * 2) & 0xff;
+    }
+
+    if (       !PACKET_buf_init(&pkt, buf, 1024)
+            || !PACKET_buf_init(&short_pkt, buf, len)
+            || !PACKET_get_length_prefixed_3(&pkt, &subpkt)
+            ||  PACKET_remaining(&subpkt) != len
+            || !PACKET_get_net_2(&subpkt, &i)
+            ||  i != 0x0608
+            ||  PACKET_get_length_prefixed_3(&short_pkt, &subpkt)
+            ||  PACKET_remaining(&short_pkt) != len) {
+        fprintf(stderr, "test_PACKET_get_length_prefixed_3() failed\n");
+        return 0;
+    }
+
+    return 1;
+}
+
 int main(int argc, char **argv)
 {
     unsigned char buf[BUF_LEN];
@@ -309,7 +388,10 @@ int main(int argc, char **argv)
             || !test_PACKET_get_sub_packet(&pkt, start)
             || !test_PACKET_get_bytes(&pkt, start)
             || !test_PACKET_copy_bytes(&pkt, start)
-            || !test_PACKET_move_funcs(&pkt, start)) {
+            || !test_PACKET_move_funcs(&pkt, start)
+            || !test_PACKET_get_length_prefixed_1()
+            || !test_PACKET_get_length_prefixed_2()
+            || !test_PACKET_get_length_prefixed_3()) {
         return 1;
     }
     printf("PASS\n");


More information about the openssl-commits mailing list