1/* Copyright (c) 2014, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
15#include <openssl/bytestring.h>
16
17#include <assert.h>
18#include <string.h>
19
20#include <openssl/mem.h>
21
22#include "../internal.h"
23
24
25void CBB_zero(CBB *cbb) {
26  OPENSSL_memset(cbb, 0, sizeof(CBB));
27}
28
29static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
30  /* This assumes that |cbb| has already been zeroed. */
31  struct cbb_buffer_st *base;
32
33  base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
34  if (base == NULL) {
35    return 0;
36  }
37
38  base->buf = buf;
39  base->len = 0;
40  base->cap = cap;
41  base->can_resize = 1;
42  base->error = 0;
43
44  cbb->base = base;
45  cbb->is_top_level = 1;
46  return 1;
47}
48
49int CBB_init(CBB *cbb, size_t initial_capacity) {
50  CBB_zero(cbb);
51
52  uint8_t *buf = OPENSSL_malloc(initial_capacity);
53  if (initial_capacity > 0 && buf == NULL) {
54    return 0;
55  }
56
57  if (!cbb_init(cbb, buf, initial_capacity)) {
58    OPENSSL_free(buf);
59    return 0;
60  }
61
62  return 1;
63}
64
65int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
66  CBB_zero(cbb);
67
68  if (!cbb_init(cbb, buf, len)) {
69    return 0;
70  }
71
72  cbb->base->can_resize = 0;
73  return 1;
74}
75
76void CBB_cleanup(CBB *cbb) {
77  if (cbb->base) {
78    /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
79     * are implicitly discarded when the parent is flushed or cleaned up. */
80    assert(cbb->is_top_level);
81
82    if (cbb->base->can_resize) {
83      OPENSSL_free(cbb->base->buf);
84    }
85    OPENSSL_free(cbb->base);
86  }
87  cbb->base = NULL;
88}
89
90static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
91                              size_t len) {
92  size_t newlen;
93
94  if (base == NULL) {
95    return 0;
96  }
97
98  newlen = base->len + len;
99  if (newlen < base->len) {
100    /* Overflow */
101    goto err;
102  }
103
104  if (newlen > base->cap) {
105    size_t newcap = base->cap * 2;
106    uint8_t *newbuf;
107
108    if (!base->can_resize) {
109      goto err;
110    }
111
112    if (newcap < base->cap || newcap < newlen) {
113      newcap = newlen;
114    }
115    newbuf = OPENSSL_realloc(base->buf, newcap);
116    if (newbuf == NULL) {
117      goto err;
118    }
119
120    base->buf = newbuf;
121    base->cap = newcap;
122  }
123
124  if (out) {
125    *out = base->buf + base->len;
126  }
127
128  return 1;
129
130err:
131  base->error = 1;
132  return 0;
133}
134
135static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
136                          size_t len) {
137  if (!cbb_buffer_reserve(base, out, len)) {
138    return 0;
139  }
140  /* This will not overflow or |cbb_buffer_reserve| would have failed. */
141  base->len += len;
142  return 1;
143}
144
145static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
146                            size_t len_len) {
147  if (len_len == 0) {
148    return 1;
149  }
150
151  uint8_t *buf;
152  if (!cbb_buffer_add(base, &buf, len_len)) {
153    return 0;
154  }
155
156  for (size_t i = len_len - 1; i < len_len; i--) {
157    buf[i] = v;
158    v >>= 8;
159  }
160
161  if (v != 0) {
162    base->error = 1;
163    return 0;
164  }
165
166  return 1;
167}
168
169int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
170  if (!cbb->is_top_level) {
171    return 0;
172  }
173
174  if (!CBB_flush(cbb)) {
175    return 0;
176  }
177
178  if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
179    /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
180    return 0;
181  }
182
183  if (out_data != NULL) {
184    *out_data = cbb->base->buf;
185  }
186  if (out_len != NULL) {
187    *out_len = cbb->base->len;
188  }
189  cbb->base->buf = NULL;
190  CBB_cleanup(cbb);
191  return 1;
192}
193
194/* CBB_flush recurses and then writes out any pending length prefix. The
195 * current length of the underlying base is taken to be the length of the
196 * length-prefixed data. */
197int CBB_flush(CBB *cbb) {
198  size_t child_start, i, len;
199
200  /* If |cbb->base| has hit an error, the buffer is in an undefined state, so
201   * fail all following calls. In particular, |cbb->child| may point to invalid
202   * memory. */
203  if (cbb->base == NULL || cbb->base->error) {
204    return 0;
205  }
206
207  if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
208    return 1;
209  }
210
211  child_start = cbb->child->offset + cbb->child->pending_len_len;
212
213  if (!CBB_flush(cbb->child) ||
214      child_start < cbb->child->offset ||
215      cbb->base->len < child_start) {
216    goto err;
217  }
218
219  len = cbb->base->len - child_start;
220
221  if (cbb->child->pending_is_asn1) {
222    /* For ASN.1 we assume that we'll only need a single byte for the length.
223     * If that turned out to be incorrect, we have to move the contents along
224     * in order to make space. */
225    uint8_t len_len;
226    uint8_t initial_length_byte;
227
228    assert (cbb->child->pending_len_len == 1);
229
230    if (len > 0xfffffffe) {
231      /* Too large. */
232      goto err;
233    } else if (len > 0xffffff) {
234      len_len = 5;
235      initial_length_byte = 0x80 | 4;
236    } else if (len > 0xffff) {
237      len_len = 4;
238      initial_length_byte = 0x80 | 3;
239    } else if (len > 0xff) {
240      len_len = 3;
241      initial_length_byte = 0x80 | 2;
242    } else if (len > 0x7f) {
243      len_len = 2;
244      initial_length_byte = 0x80 | 1;
245    } else {
246      len_len = 1;
247      initial_length_byte = (uint8_t)len;
248      len = 0;
249    }
250
251    if (len_len != 1) {
252      /* We need to move the contents along in order to make space. */
253      size_t extra_bytes = len_len - 1;
254      if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
255        goto err;
256      }
257      OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
258                      cbb->base->buf + child_start, len);
259    }
260    cbb->base->buf[cbb->child->offset++] = initial_length_byte;
261    cbb->child->pending_len_len = len_len - 1;
262  }
263
264  for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
265       i--) {
266    cbb->base->buf[cbb->child->offset + i] = (uint8_t)len;
267    len >>= 8;
268  }
269  if (len != 0) {
270    goto err;
271  }
272
273  cbb->child->base = NULL;
274  cbb->child = NULL;
275
276  return 1;
277
278err:
279  cbb->base->error = 1;
280  return 0;
281}
282
283const uint8_t *CBB_data(const CBB *cbb) {
284  assert(cbb->child == NULL);
285  return cbb->base->buf + cbb->offset + cbb->pending_len_len;
286}
287
288size_t CBB_len(const CBB *cbb) {
289  assert(cbb->child == NULL);
290  assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
291
292  return cbb->base->len - cbb->offset - cbb->pending_len_len;
293}
294
295static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
296                                   uint8_t len_len) {
297  uint8_t *prefix_bytes;
298
299  if (!CBB_flush(cbb)) {
300    return 0;
301  }
302
303  size_t offset = cbb->base->len;
304  if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
305    return 0;
306  }
307
308  OPENSSL_memset(prefix_bytes, 0, len_len);
309  OPENSSL_memset(out_contents, 0, sizeof(CBB));
310  out_contents->base = cbb->base;
311  cbb->child = out_contents;
312  cbb->child->offset = offset;
313  cbb->child->pending_len_len = len_len;
314  cbb->child->pending_is_asn1 = 0;
315
316  return 1;
317}
318
319int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
320  return cbb_add_length_prefixed(cbb, out_contents, 1);
321}
322
323int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
324  return cbb_add_length_prefixed(cbb, out_contents, 2);
325}
326
327int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
328  return cbb_add_length_prefixed(cbb, out_contents, 3);
329}
330
331int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
332  if (tag > 0xff ||
333      (tag & 0x1f) == 0x1f) {
334    /* Long form identifier octets are not supported. Further, all current valid
335     * tag serializations are 8 bits. */
336    cbb->base->error = 1;
337    return 0;
338  }
339
340  if (!CBB_flush(cbb) ||
341      /* |tag|'s representation matches the DER encoding. */
342      !CBB_add_u8(cbb, (uint8_t)tag)) {
343    return 0;
344  }
345
346  size_t offset = cbb->base->len;
347  if (!CBB_add_u8(cbb, 0)) {
348    return 0;
349  }
350
351  OPENSSL_memset(out_contents, 0, sizeof(CBB));
352  out_contents->base = cbb->base;
353  cbb->child = out_contents;
354  cbb->child->offset = offset;
355  cbb->child->pending_len_len = 1;
356  cbb->child->pending_is_asn1 = 1;
357
358  return 1;
359}
360
361int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
362  uint8_t *dest;
363
364  if (!CBB_flush(cbb) ||
365      !cbb_buffer_add(cbb->base, &dest, len)) {
366    return 0;
367  }
368  OPENSSL_memcpy(dest, data, len);
369  return 1;
370}
371
372int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
373  if (!CBB_flush(cbb) ||
374      !cbb_buffer_add(cbb->base, out_data, len)) {
375    return 0;
376  }
377  return 1;
378}
379
380int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
381  if (!CBB_flush(cbb) ||
382      !cbb_buffer_reserve(cbb->base, out_data, len)) {
383    return 0;
384  }
385  return 1;
386}
387
388int CBB_did_write(CBB *cbb, size_t len) {
389  size_t newlen = cbb->base->len + len;
390  if (cbb->child != NULL ||
391      newlen < cbb->base->len ||
392      newlen > cbb->base->cap) {
393    return 0;
394  }
395  cbb->base->len = newlen;
396  return 1;
397}
398
399int CBB_add_u8(CBB *cbb, uint8_t value) {
400  if (!CBB_flush(cbb)) {
401    return 0;
402  }
403
404  return cbb_buffer_add_u(cbb->base, value, 1);
405}
406
407int CBB_add_u16(CBB *cbb, uint16_t value) {
408  if (!CBB_flush(cbb)) {
409    return 0;
410  }
411
412  return cbb_buffer_add_u(cbb->base, value, 2);
413}
414
415int CBB_add_u24(CBB *cbb, uint32_t value) {
416  if (!CBB_flush(cbb)) {
417    return 0;
418  }
419
420  return cbb_buffer_add_u(cbb->base, value, 3);
421}
422
423int CBB_add_u32(CBB *cbb, uint32_t value) {
424  if (!CBB_flush(cbb)) {
425    return 0;
426  }
427
428  return cbb_buffer_add_u(cbb->base, value, 4);
429}
430
431void CBB_discard_child(CBB *cbb) {
432  if (cbb->child == NULL) {
433    return;
434  }
435
436  cbb->base->len = cbb->child->offset;
437
438  cbb->child->base = NULL;
439  cbb->child = NULL;
440}
441
442int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
443  CBB child;
444  int started = 0;
445
446  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
447    return 0;
448  }
449
450  for (size_t i = 0; i < 8; i++) {
451    uint8_t byte = (value >> 8*(7-i)) & 0xff;
452    if (!started) {
453      if (byte == 0) {
454        /* Don't encode leading zeros. */
455        continue;
456      }
457      /* If the high bit is set, add a padding byte to make it
458       * unsigned. */
459      if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
460        return 0;
461      }
462      started = 1;
463    }
464    if (!CBB_add_u8(&child, byte)) {
465      return 0;
466    }
467  }
468
469  /* 0 is encoded as a single 0, not the empty string. */
470  if (!started && !CBB_add_u8(&child, 0)) {
471    return 0;
472  }
473
474  return CBB_flush(cbb);
475}
476