Add the WPACKET_reserve_bytes() function
authorMatt Caswell <matt@openssl.org>
Thu, 29 Sep 2016 10:43:37 +0000 (11:43 +0100)
committerMatt Caswell <matt@openssl.org>
Thu, 29 Sep 2016 14:09:02 +0000 (15:09 +0100)
WPACKET_allocate_bytes() requires you to know the size of the data you
are allocating for, before you create it. Sometimes this isn't the case,
for example we know the maximum size that a signature will be before we
create it, but not the actual size. WPACKET_reserve_bytes() enables us to
reserve bytes in the WPACKET, but not count them as written yet. We then
subsequently need to acall WPACKET_allocate_bytes to actually count them as
written.

Reviewed-by: Rich Salz <rsalz@openssl.org>
ssl/packet.c
ssl/packet_locl.h

index 4077de5..7c240a4 100644 (file)
 #define DEFAULT_BUF_SIZE    256
 
 int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
+{
+    if (!WPACKET_reserve_bytes(pkt, len, allocbytes))
+        return 0;
+    pkt->written += len;
+    pkt->curr += len;
+
+    return 1;
+}
+
+int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
+                                 unsigned char **allocbytes, size_t lenbytes)
+{
+    if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
+            || !WPACKET_allocate_bytes(pkt, len, allocbytes)
+            || !WPACKET_close(pkt))
+        return 0;
+
+    return 1;
+}
+
+int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
 {
     /* Internal API, so should not fail */
     assert(pkt->subs != NULL && len != 0);
@@ -39,20 +60,18 @@ int WPACKET_allocate_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
             return 0;
     }
     *allocbytes = (unsigned char *)pkt->buf->data + pkt->curr;
-    pkt->written += len;
-    pkt->curr += len;
 
     return 1;
 }
 
-int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
-                                 unsigned char **allocbytes, size_t lenbytes)
+int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
+                                unsigned char **allocbytes, size_t lenbytes)
 {
-    if (!WPACKET_start_sub_packet_len__(pkt, lenbytes)
-            || !WPACKET_allocate_bytes(pkt, len, allocbytes)
-            || !WPACKET_close(pkt))
+    if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
         return 0;
 
+    *allocbytes += lenbytes;
+
     return 1;
 }
 
index 44a8f82..0e50c7d 100644 (file)
@@ -675,7 +675,7 @@ int WPACKET_start_sub_packet(WPACKET *pkt);
  * WPACKET_* calls. If not then the underlying buffer may be realloc'd and
  * change its location.
  */
-int WPACKET_allocate_bytes(WPACKET *pkt, size_t bytes,
+int WPACKET_allocate_bytes(WPACKET *pkt, size_t len,
                            unsigned char **allocbytes);
 
 /*
@@ -700,6 +700,34 @@ int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
 #define WPACKET_sub_allocate_bytes_u32(pkt, len, bytes) \
     WPACKET_sub_allocate_bytes__((pkt), (len), (bytes), 4)
 
+/*
+ * The same as WPACKET_allocate_bytes() except the reserved bytes are not
+ * actually counted as written. Typically this will be for when we don't know
+ * how big arbitrary data is going to be up front, but we do know what the
+ * maximum size will be. If this function is used, then it should be immediately
+ * followed by a WPACKET_allocate_bytes() call before any other WPACKET
+ * functions are called (unless the write to the allocated bytes is abandoned).
+ */
+int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes);
+
+/*
+ * The "reserve_bytes" equivalent of WPACKET_sub_allocate_bytes__()
+ */
+int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
+                                 unsigned char **allocbytes, size_t lenbytes);
+
+/*
+ * Convenience macros for  WPACKET_sub_reserve_bytes with different lengths
+ */
+#define WPACKET_sub_reserve_bytes_u8(pkt, len, bytes) \
+    WPACKET_reserve_bytes__((pkt), (len), (bytes), 1)
+#define WPACKET_sub_reserve_bytes_u16(pkt, len, bytes) \
+    WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 2)
+#define WPACKET_sub_reserve_bytes_u24(pkt, len, bytes) \
+    WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 3)
+#define WPACKET_sub_reserve_bytes_u32(pkt, len, bytes) \
+    WPACKET_sub_reserve_bytes__((pkt), (len), (bytes), 4)
+
 /*
  * Write the value stored in |val| into the WPACKET. The value will consume
  * |bytes| amount of storage. An error will occur if |val| cannot be