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 
     23 void CBB_zero(CBB *cbb) {
     24   memset(cbb, 0, sizeof(CBB));
     25 }
     26 
     27 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
     28   /* This assumes that |cbb| has already been zeroed. */
     29   struct cbb_buffer_st *base;
     30 
     31   base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
     32   if (base == NULL) {
     33     return 0;
     34   }
     35 
     36   base->buf = buf;
     37   base->len = 0;
     38   base->cap = cap;
     39   base->can_resize = 1;
     40 
     41   cbb->base = base;
     42   cbb->is_top_level = 1;
     43   return 1;
     44 }
     45 
     46 int CBB_init(CBB *cbb, size_t initial_capacity) {
     47   CBB_zero(cbb);
     48 
     49   uint8_t *buf = OPENSSL_malloc(initial_capacity);
     50   if (initial_capacity > 0 && buf == NULL) {
     51     return 0;
     52   }
     53 
     54   if (!cbb_init(cbb, buf, initial_capacity)) {
     55     OPENSSL_free(buf);
     56     return 0;
     57   }
     58 
     59   return 1;
     60 }
     61 
     62 int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
     63   CBB_zero(cbb);
     64 
     65   if (!cbb_init(cbb, buf, len)) {
     66     return 0;
     67   }
     68 
     69   cbb->base->can_resize = 0;
     70   return 1;
     71 }
     72 
     73 void CBB_cleanup(CBB *cbb) {
     74   if (cbb->base) {
     75     /* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
     76      * are implicitly discarded when the parent is flushed or cleaned up. */
     77     assert(cbb->is_top_level);
     78 
     79     if (cbb->base->can_resize) {
     80       OPENSSL_free(cbb->base->buf);
     81     }
     82     OPENSSL_free(cbb->base);
     83   }
     84   cbb->base = NULL;
     85 }
     86 
     87 static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
     88                               size_t len) {
     89   size_t newlen;
     90 
     91   if (base == NULL) {
     92     return 0;
     93   }
     94 
     95   newlen = base->len + len;
     96   if (newlen < base->len) {
     97     /* Overflow */
     98     return 0;
     99   }
    100 
    101   if (newlen > base->cap) {
    102     size_t newcap = base->cap * 2;
    103     uint8_t *newbuf;
    104 
    105     if (!base->can_resize) {
    106       return 0;
    107     }
    108 
    109     if (newcap < base->cap || newcap < newlen) {
    110       newcap = newlen;
    111     }
    112     newbuf = OPENSSL_realloc(base->buf, newcap);
    113     if (newbuf == NULL) {
    114       return 0;
    115     }
    116 
    117     base->buf = newbuf;
    118     base->cap = newcap;
    119   }
    120 
    121   if (out) {
    122     *out = base->buf + base->len;
    123   }
    124 
    125   return 1;
    126 }
    127 
    128 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
    129                           size_t len) {
    130   if (!cbb_buffer_reserve(base, out, len)) {
    131     return 0;
    132   }
    133   /* This will not overflow or |cbb_buffer_reserve| would have failed. */
    134   base->len += len;
    135   return 1;
    136 }
    137 
    138 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
    139                             size_t len_len) {
    140   uint8_t *buf;
    141   size_t i;
    142 
    143   if (len_len == 0) {
    144     return 1;
    145   }
    146   if (!cbb_buffer_add(base, &buf, len_len)) {
    147     return 0;
    148   }
    149 
    150   for (i = len_len - 1; i < len_len; i--) {
    151     buf[i] = v;
    152     v >>= 8;
    153   }
    154   return 1;
    155 }
    156 
    157 int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
    158   if (!cbb->is_top_level) {
    159     return 0;
    160   }
    161 
    162   if (!CBB_flush(cbb)) {
    163     return 0;
    164   }
    165 
    166   if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
    167     /* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
    168     return 0;
    169   }
    170 
    171   if (out_data != NULL) {
    172     *out_data = cbb->base->buf;
    173   }
    174   if (out_len != NULL) {
    175     *out_len = cbb->base->len;
    176   }
    177   cbb->base->buf = NULL;
    178   CBB_cleanup(cbb);
    179   return 1;
    180 }
    181 
    182 /* CBB_flush recurses and then writes out any pending length prefix. The
    183  * current length of the underlying base is taken to be the length of the
    184  * length-prefixed data. */
    185 int CBB_flush(CBB *cbb) {
    186   size_t child_start, i, len;
    187 
    188   if (cbb->base == NULL) {
    189     return 0;
    190   }
    191 
    192   if (cbb->child == NULL || cbb->child->pending_len_len == 0) {
    193     return 1;
    194   }
    195 
    196   child_start = cbb->child->offset + cbb->child->pending_len_len;
    197 
    198   if (!CBB_flush(cbb->child) ||
    199       child_start < cbb->child->offset ||
    200       cbb->base->len < child_start) {
    201     return 0;
    202   }
    203 
    204   len = cbb->base->len - child_start;
    205 
    206   if (cbb->child->pending_is_asn1) {
    207     /* For ASN.1 we assume that we'll only need a single byte for the length.
    208      * If that turned out to be incorrect, we have to move the contents along
    209      * in order to make space. */
    210     size_t len_len;
    211     uint8_t initial_length_byte;
    212 
    213     assert (cbb->child->pending_len_len == 1);
    214 
    215     if (len > 0xfffffffe) {
    216       /* Too large. */
    217       return 0;
    218     } else if (len > 0xffffff) {
    219       len_len = 5;
    220       initial_length_byte = 0x80 | 4;
    221     } else if (len > 0xffff) {
    222       len_len = 4;
    223       initial_length_byte = 0x80 | 3;
    224     } else if (len > 0xff) {
    225       len_len = 3;
    226       initial_length_byte = 0x80 | 2;
    227     } else if (len > 0x7f) {
    228       len_len = 2;
    229       initial_length_byte = 0x80 | 1;
    230     } else {
    231       len_len = 1;
    232       initial_length_byte = len;
    233       len = 0;
    234     }
    235 
    236     if (len_len != 1) {
    237       /* We need to move the contents along in order to make space. */
    238       size_t extra_bytes = len_len - 1;
    239       if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
    240         return 0;
    241       }
    242       memmove(cbb->base->buf + child_start + extra_bytes,
    243               cbb->base->buf + child_start, len);
    244     }
    245     cbb->base->buf[cbb->child->offset++] = initial_length_byte;
    246     cbb->child->pending_len_len = len_len - 1;
    247   }
    248 
    249   for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
    250        i--) {
    251     cbb->base->buf[cbb->child->offset + i] = len;
    252     len >>= 8;
    253   }
    254   if (len != 0) {
    255     return 0;
    256   }
    257 
    258   cbb->child->base = NULL;
    259   cbb->child = NULL;
    260 
    261   return 1;
    262 }
    263 
    264 const uint8_t *CBB_data(const CBB *cbb) {
    265   assert(cbb->child == NULL);
    266   return cbb->base->buf + cbb->offset + cbb->pending_len_len;
    267 }
    268 
    269 size_t CBB_len(const CBB *cbb) {
    270   assert(cbb->child == NULL);
    271   assert(cbb->offset + cbb->pending_len_len <= cbb->base->len);
    272 
    273   return cbb->base->len - cbb->offset - cbb->pending_len_len;
    274 }
    275 
    276 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
    277                                    size_t len_len) {
    278   uint8_t *prefix_bytes;
    279 
    280   if (!CBB_flush(cbb)) {
    281     return 0;
    282   }
    283 
    284   size_t offset = cbb->base->len;
    285   if (!cbb_buffer_add(cbb->base, &prefix_bytes, len_len)) {
    286     return 0;
    287   }
    288 
    289   memset(prefix_bytes, 0, len_len);
    290   memset(out_contents, 0, sizeof(CBB));
    291   out_contents->base = cbb->base;
    292   cbb->child = out_contents;
    293   cbb->child->offset = offset;
    294   cbb->child->pending_len_len = len_len;
    295   cbb->child->pending_is_asn1 = 0;
    296 
    297   return 1;
    298 }
    299 
    300 int CBB_add_u8_length_prefixed(CBB *cbb, CBB *out_contents) {
    301   return cbb_add_length_prefixed(cbb, out_contents, 1);
    302 }
    303 
    304 int CBB_add_u16_length_prefixed(CBB *cbb, CBB *out_contents) {
    305   return cbb_add_length_prefixed(cbb, out_contents, 2);
    306 }
    307 
    308 int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
    309   return cbb_add_length_prefixed(cbb, out_contents, 3);
    310 }
    311 
    312 int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
    313   if ((tag & 0x1f) == 0x1f) {
    314     /* Long form identifier octets are not supported. */
    315     return 0;
    316   }
    317 
    318   if (!CBB_flush(cbb) ||
    319       !CBB_add_u8(cbb, tag)) {
    320     return 0;
    321   }
    322 
    323   size_t offset = cbb->base->len;
    324   if (!CBB_add_u8(cbb, 0)) {
    325     return 0;
    326   }
    327 
    328   memset(out_contents, 0, sizeof(CBB));
    329   out_contents->base = cbb->base;
    330   cbb->child = out_contents;
    331   cbb->child->offset = offset;
    332   cbb->child->pending_len_len = 1;
    333   cbb->child->pending_is_asn1 = 1;
    334 
    335   return 1;
    336 }
    337 
    338 int CBB_add_bytes(CBB *cbb, const uint8_t *data, size_t len) {
    339   uint8_t *dest;
    340 
    341   if (!CBB_flush(cbb) ||
    342       !cbb_buffer_add(cbb->base, &dest, len)) {
    343     return 0;
    344   }
    345   memcpy(dest, data, len);
    346   return 1;
    347 }
    348 
    349 int CBB_add_space(CBB *cbb, uint8_t **out_data, size_t len) {
    350   if (!CBB_flush(cbb) ||
    351       !cbb_buffer_add(cbb->base, out_data, len)) {
    352     return 0;
    353   }
    354   return 1;
    355 }
    356 
    357 int CBB_reserve(CBB *cbb, uint8_t **out_data, size_t len) {
    358   if (!CBB_flush(cbb) ||
    359       !cbb_buffer_reserve(cbb->base, out_data, len)) {
    360     return 0;
    361   }
    362   return 1;
    363 }
    364 
    365 int CBB_did_write(CBB *cbb, size_t len) {
    366   size_t newlen = cbb->base->len + len;
    367   if (cbb->child != NULL ||
    368       newlen < cbb->base->len ||
    369       newlen > cbb->base->cap) {
    370     return 0;
    371   }
    372   cbb->base->len = newlen;
    373   return 1;
    374 }
    375 
    376 int CBB_add_u8(CBB *cbb, uint8_t value) {
    377   if (!CBB_flush(cbb)) {
    378     return 0;
    379   }
    380 
    381   return cbb_buffer_add_u(cbb->base, value, 1);
    382 }
    383 
    384 int CBB_add_u16(CBB *cbb, uint16_t value) {
    385   if (!CBB_flush(cbb)) {
    386     return 0;
    387   }
    388 
    389   return cbb_buffer_add_u(cbb->base, value, 2);
    390 }
    391 
    392 int CBB_add_u24(CBB *cbb, uint32_t value) {
    393   if (!CBB_flush(cbb)) {
    394     return 0;
    395   }
    396 
    397   return cbb_buffer_add_u(cbb->base, value, 3);
    398 }
    399 
    400 void CBB_discard_child(CBB *cbb) {
    401   if (cbb->child == NULL) {
    402     return;
    403   }
    404 
    405   cbb->base->len = cbb->child->offset;
    406 
    407   cbb->child->base = NULL;
    408   cbb->child = NULL;
    409 }
    410 
    411 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
    412   CBB child;
    413   size_t i;
    414   int started = 0;
    415 
    416   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
    417     return 0;
    418   }
    419 
    420   for (i = 0; i < 8; i++) {
    421     uint8_t byte = (value >> 8*(7-i)) & 0xff;
    422     if (!started) {
    423       if (byte == 0) {
    424         /* Don't encode leading zeros. */
    425         continue;
    426       }
    427       /* If the high bit is set, add a padding byte to make it
    428        * unsigned. */
    429       if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
    430         return 0;
    431       }
    432       started = 1;
    433     }
    434     if (!CBB_add_u8(&child, byte)) {
    435       return 0;
    436     }
    437   }
    438 
    439   /* 0 is encoded as a single 0, not the empty string. */
    440   if (!started && !CBB_add_u8(&child, 0)) {
    441     return 0;
    442   }
    443 
    444   return CBB_flush(cbb);
    445 }
    446