Give WPACKET the ability to have a NULL buffer underneath it

This means the WPACKET API can be used for calculating the number of
bytes that would have been written if a non-NULL buffer had been used.
This enables us to calculate the number of length bytes required when
encoding ASN.1

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9111)
This commit is contained in:
Matt Caswell 2019-06-10 17:48:26 +01:00 committed by Pauli
parent 8ae173bb57
commit 15cb0f0958
2 changed files with 53 additions and 11 deletions

View file

@ -35,7 +35,10 @@ int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
} }
#define GETBUF(p) (((p)->staticbuf != NULL) \ #define GETBUF(p) (((p)->staticbuf != NULL) \
? (p)->staticbuf : (unsigned char *)(p)->buf->data) ? (p)->staticbuf \
: ((p)->buf != NULL \
? (unsigned char *)(p)->buf->data \
: NULL))
int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes) int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
{ {
@ -46,7 +49,7 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
if (pkt->maxsize - pkt->written < len) if (pkt->maxsize - pkt->written < len)
return 0; return 0;
if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) { if (pkt->buf != NULL && (pkt->buf->length - pkt->written < len)) {
size_t newlen; size_t newlen;
size_t reflen; size_t reflen;
@ -74,6 +77,7 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes)) if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
return 0; return 0;
if (*allocbytes != NULL)
*allocbytes += lenbytes; *allocbytes += lenbytes;
return 1; return 1;
@ -110,7 +114,7 @@ static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
pkt->subs = NULL; pkt->subs = NULL;
return 0; return 0;
} }
pkt->subs->packet_len = lenchars - GETBUF(pkt); pkt->subs->packet_len = 0;
return 1; return 1;
} }
@ -149,6 +153,15 @@ int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
return WPACKET_init_len(pkt, buf, 0); return WPACKET_init_len(pkt, buf, 0);
} }
int WPACKET_init_null(WPACKET *pkt, size_t lenbytes)
{
pkt->staticbuf = NULL;
pkt->buf = NULL;
pkt->maxsize = maxmaxsize(lenbytes);
return wpacket_intern_init_len(pkt, 0);
}
int WPACKET_set_flags(WPACKET *pkt, unsigned int flags) int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
{ {
/* Internal API, so should not fail */ /* Internal API, so should not fail */
@ -163,6 +176,9 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
/* Store the |value| of length |len| at location |data| */ /* Store the |value| of length |len| at location |data| */
static int put_value(unsigned char *data, size_t value, size_t len) static int put_value(unsigned char *data, size_t value, size_t len)
{ {
if (data == NULL)
return 1;
for (data += len - 1; len > 0; len--) { for (data += len - 1; len > 0; len--) {
*data = (unsigned char)(value & 0xff); *data = (unsigned char)(value & 0xff);
data--; data--;
@ -209,10 +225,14 @@ static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
} }
/* Write out the WPACKET length if needed */ /* Write out the WPACKET length if needed */
if (sub->lenbytes > 0 if (sub->lenbytes > 0) {
&& !put_value(&GETBUF(pkt)[sub->packet_len], packlen, unsigned char *buf = GETBUF(pkt);
if (buf != NULL
&& !put_value(&buf[sub->packet_len], packlen,
sub->lenbytes)) sub->lenbytes))
return 0; return 0;
}
if (doclose) { if (doclose) {
pkt->subs = sub->parent; pkt->subs = sub->parent;
@ -293,10 +313,10 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
return 1; return 1;
} }
sub->packet_len = pkt->written;
if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars)) if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
return 0; return 0;
/* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
sub->packet_len = lenchars - GETBUF(pkt);
return 1; return 1;
} }
@ -354,6 +374,7 @@ int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
if (!WPACKET_allocate_bytes(pkt, len, &dest)) if (!WPACKET_allocate_bytes(pkt, len, &dest))
return 0; return 0;
if (dest != NULL)
memset(dest, ch, len); memset(dest, ch, len);
return 1; return 1;
@ -369,6 +390,7 @@ int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
if (!WPACKET_allocate_bytes(pkt, len, &dest)) if (!WPACKET_allocate_bytes(pkt, len, &dest))
return 0; return 0;
if (dest != NULL)
memcpy(dest, src, len); memcpy(dest, src, len);
return 1; return 1;
@ -409,7 +431,17 @@ int WPACKET_get_length(WPACKET *pkt, size_t *len)
unsigned char *WPACKET_get_curr(WPACKET *pkt) unsigned char *WPACKET_get_curr(WPACKET *pkt)
{ {
return GETBUF(pkt) + pkt->curr; unsigned char *buf = GETBUF(pkt);
if (buf == NULL)
return NULL;
return buf + pkt->curr;
}
int WPACKET_is_null_buf(WPACKET *pkt)
{
return pkt->buf == NULL && pkt->staticbuf == NULL;
} }
void WPACKET_cleanup(WPACKET *pkt) void WPACKET_cleanup(WPACKET *pkt)

View file

@ -669,6 +669,13 @@ int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
*/ */
int WPACKET_init(WPACKET *pkt, BUF_MEM *buf); int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);
/*
* Same as WPACKET_init_len except there is no underlying buffer. No data is
* ever actually written. We just keep track of how much data would have been
* written if a buffer was there.
*/
int WPACKET_init_null(WPACKET *pkt, size_t lenbytes);
/* /*
* Same as WPACKET_init_len except we do not use a growable BUF_MEM structure. * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
* A fixed buffer of memory |buf| of size |len| is used instead. A failure will * A fixed buffer of memory |buf| of size |len| is used instead. A failure will
@ -868,6 +875,9 @@ int WPACKET_get_length(WPACKET *pkt, size_t *len);
*/ */
unsigned char *WPACKET_get_curr(WPACKET *pkt); unsigned char *WPACKET_get_curr(WPACKET *pkt);
/* Returns true if the underlying buffer is actually NULL */
int WPACKET_is_null_buf(WPACKET *pkt);
/* Release resources in a WPACKET if a failure has occurred. */ /* Release resources in a WPACKET if a failure has occurred. */
void WPACKET_cleanup(WPACKET *pkt); void WPACKET_cleanup(WPACKET *pkt);