Home | History | Annotate | Download | only in bytestring
      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 
     25 void CBB_zero(CBB *cbb) {
     26   OPENSSL_memset(cbb, 0, sizeof(CBB));
     27 }
     28 
     29 static 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 
     49 int 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 
     65 int 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 
     76 void 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 
     90 static 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 
    130 err:
    131   base->error = 1;
    132   return 0;
    133 }
    134 
    135 static 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 
    145 static 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 
    169 int 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. */
    197 int 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 
    278 err:
    279   cbb->base->error = 1;
    280   return 0;
    281 }
    282 
    283 const 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 
    288 size_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 
    295 static 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 
    319 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
    320   return cbb_add_length_prefixed(cbb, out_contents, 1);
    321 }
    322 
    323 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
    324   return cbb_add_length_prefixed(cbb, out_contents, 2);
    325 }
    326 
    327 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
    328   return cbb_add_length_prefixed(cbb, out_contents, 3);
    329 }
    330 
    331 int 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 
    361 int 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 
    372 int 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 
    380 int 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 
    388 int 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 
    399 int 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 
    407 int 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 
    415 int 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 
    423 int 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 
    431 void 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 
    442 int 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