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/buf.h>
     16 #include <openssl/mem.h>
     17 #include <openssl/bytestring.h>
     18 
     19 #include <assert.h>
     20 #include <string.h>
     21 
     22 #include "internal.h"
     23 #include "../internal.h"
     24 
     25 
     26 void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
     27   cbs->data = data;
     28   cbs->len = len;
     29 }
     30 
     31 static int cbs_get(CBS *cbs, const uint8_t **p, size_t n) {
     32   if (cbs->len < n) {
     33     return 0;
     34   }
     35 
     36   *p = cbs->data;
     37   cbs->data += n;
     38   cbs->len -= n;
     39   return 1;
     40 }
     41 
     42 int CBS_skip(CBS *cbs, size_t len) {
     43   const uint8_t *dummy;
     44   return cbs_get(cbs, &dummy, len);
     45 }
     46 
     47 const uint8_t *CBS_data(const CBS *cbs) {
     48   return cbs->data;
     49 }
     50 
     51 size_t CBS_len(const CBS *cbs) {
     52   return cbs->len;
     53 }
     54 
     55 int CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) {
     56   OPENSSL_free(*out_ptr);
     57   *out_ptr = NULL;
     58   *out_len = 0;
     59 
     60   if (cbs->len == 0) {
     61     return 1;
     62   }
     63   *out_ptr = BUF_memdup(cbs->data, cbs->len);
     64   if (*out_ptr == NULL) {
     65     return 0;
     66   }
     67   *out_len = cbs->len;
     68   return 1;
     69 }
     70 
     71 int CBS_strdup(const CBS *cbs, char **out_ptr) {
     72   if (*out_ptr != NULL) {
     73     OPENSSL_free(*out_ptr);
     74   }
     75   *out_ptr = BUF_strndup((const char*)cbs->data, cbs->len);
     76   return (*out_ptr != NULL);
     77 }
     78 
     79 int CBS_contains_zero_byte(const CBS *cbs) {
     80   return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
     81 }
     82 
     83 int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
     84   if (len != cbs->len) {
     85     return 0;
     86   }
     87   return CRYPTO_memcmp(cbs->data, data, len) == 0;
     88 }
     89 
     90 static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
     91   uint32_t result = 0;
     92   const uint8_t *data;
     93 
     94   if (!cbs_get(cbs, &data, len)) {
     95     return 0;
     96   }
     97   for (size_t i = 0; i < len; i++) {
     98     result <<= 8;
     99     result |= data[i];
    100   }
    101   *out = result;
    102   return 1;
    103 }
    104 
    105 int CBS_get_u8(CBS *cbs, uint8_t *out) {
    106   const uint8_t *v;
    107   if (!cbs_get(cbs, &v, 1)) {
    108     return 0;
    109   }
    110   *out = *v;
    111   return 1;
    112 }
    113 
    114 int CBS_get_u16(CBS *cbs, uint16_t *out) {
    115   uint32_t v;
    116   if (!cbs_get_u(cbs, &v, 2)) {
    117     return 0;
    118   }
    119   *out = v;
    120   return 1;
    121 }
    122 
    123 int CBS_get_u24(CBS *cbs, uint32_t *out) {
    124   return cbs_get_u(cbs, out, 3);
    125 }
    126 
    127 int CBS_get_u32(CBS *cbs, uint32_t *out) {
    128   return cbs_get_u(cbs, out, 4);
    129 }
    130 
    131 int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
    132   if (cbs->len == 0) {
    133     return 0;
    134   }
    135   *out = cbs->data[cbs->len - 1];
    136   cbs->len--;
    137   return 1;
    138 }
    139 
    140 int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
    141   const uint8_t *v;
    142   if (!cbs_get(cbs, &v, len)) {
    143     return 0;
    144   }
    145   CBS_init(out, v, len);
    146   return 1;
    147 }
    148 
    149 int CBS_copy_bytes(CBS *cbs, uint8_t *out, size_t len) {
    150   const uint8_t *v;
    151   if (!cbs_get(cbs, &v, len)) {
    152     return 0;
    153   }
    154   OPENSSL_memcpy(out, v, len);
    155   return 1;
    156 }
    157 
    158 static int cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) {
    159   uint32_t len;
    160   if (!cbs_get_u(cbs, &len, len_len)) {
    161     return 0;
    162   }
    163   return CBS_get_bytes(cbs, out, len);
    164 }
    165 
    166 int CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) {
    167   return cbs_get_length_prefixed(cbs, out, 1);
    168 }
    169 
    170 int CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) {
    171   return cbs_get_length_prefixed(cbs, out, 2);
    172 }
    173 
    174 int CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) {
    175   return cbs_get_length_prefixed(cbs, out, 3);
    176 }
    177 
    178 static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
    179                                     size_t *out_header_len, int ber_ok) {
    180   uint8_t tag, length_byte;
    181   CBS header = *cbs;
    182   CBS throwaway;
    183 
    184   if (out == NULL) {
    185     out = &throwaway;
    186   }
    187 
    188   if (!CBS_get_u8(&header, &tag) ||
    189       !CBS_get_u8(&header, &length_byte)) {
    190     return 0;
    191   }
    192 
    193   /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
    194    * number no greater than 30.
    195    *
    196    * If the number portion is 31 (0x1f, the largest value that fits in the
    197    * allotted bits), then the tag is more than one byte long and the
    198    * continuation bytes contain the tag number. This parser only supports tag
    199    * numbers less than 31 (and thus single-byte tags). */
    200   if ((tag & 0x1f) == 0x1f) {
    201     return 0;
    202   }
    203 
    204   if (out_tag != NULL) {
    205     *out_tag = tag;
    206   }
    207 
    208   size_t len;
    209   /* The format for the length encoding is specified in ITU-T X.690 section
    210    * 8.1.3. */
    211   if ((length_byte & 0x80) == 0) {
    212     /* Short form length. */
    213     len = ((size_t) length_byte) + 2;
    214     if (out_header_len != NULL) {
    215       *out_header_len = 2;
    216     }
    217   } else {
    218     /* The high bit indicate that this is the long form, while the next 7 bits
    219      * encode the number of subsequent octets used to encode the length (ITU-T
    220      * X.690 clause 8.1.3.5.b). */
    221     const size_t num_bytes = length_byte & 0x7f;
    222     uint32_t len32;
    223 
    224     if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
    225       /* indefinite length */
    226       if (out_header_len != NULL) {
    227         *out_header_len = 2;
    228       }
    229       return CBS_get_bytes(cbs, out, 2);
    230     }
    231 
    232     /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
    233      * used as the first byte of the length. If this parser encounters that
    234      * value, num_bytes will be parsed as 127, which will fail the check below.
    235      */
    236     if (num_bytes == 0 || num_bytes > 4) {
    237       return 0;
    238     }
    239     if (!cbs_get_u(&header, &len32, num_bytes)) {
    240       return 0;
    241     }
    242     /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
    243      * with the minimum number of octets. */
    244     if (len32 < 128) {
    245       /* Length should have used short-form encoding. */
    246       return 0;
    247     }
    248     if ((len32 >> ((num_bytes-1)*8)) == 0) {
    249       /* Length should have been at least one byte shorter. */
    250       return 0;
    251     }
    252     len = len32;
    253     if (len + 2 + num_bytes < len) {
    254       /* Overflow. */
    255       return 0;
    256     }
    257     len += 2 + num_bytes;
    258     if (out_header_len != NULL) {
    259       *out_header_len = 2 + num_bytes;
    260     }
    261   }
    262 
    263   return CBS_get_bytes(cbs, out, len);
    264 }
    265 
    266 int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag) {
    267   size_t header_len;
    268   if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
    269     return 0;
    270   }
    271 
    272   if (!CBS_skip(out, header_len)) {
    273     assert(0);
    274     return 0;
    275   }
    276 
    277   return 1;
    278 }
    279 
    280 int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
    281                                     size_t *out_header_len) {
    282   return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
    283                                   0 /* DER only */);
    284 }
    285 
    286 int CBS_get_any_ber_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
    287                                  size_t *out_header_len) {
    288   return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
    289                                   1 /* BER allowed */);
    290 }
    291 
    292 static int cbs_get_asn1(CBS *cbs, CBS *out, unsigned tag_value,
    293                         int skip_header) {
    294   size_t header_len;
    295   unsigned tag;
    296   CBS throwaway;
    297 
    298   if (out == NULL) {
    299     out = &throwaway;
    300   }
    301 
    302   if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) ||
    303       tag != tag_value) {
    304     return 0;
    305   }
    306 
    307   if (skip_header && !CBS_skip(out, header_len)) {
    308     assert(0);
    309     return 0;
    310   }
    311 
    312   return 1;
    313 }
    314 
    315 int CBS_get_asn1(CBS *cbs, CBS *out, unsigned tag_value) {
    316   return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */);
    317 }
    318 
    319 int CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned tag_value) {
    320   return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */);
    321 }
    322 
    323 int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
    324   if (CBS_len(cbs) < 1) {
    325     return 0;
    326   }
    327   return CBS_data(cbs)[0] == tag_value;
    328 }
    329 
    330 int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
    331   CBS bytes;
    332   const uint8_t *data;
    333   size_t i, len;
    334 
    335   if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
    336     return 0;
    337   }
    338 
    339   *out = 0;
    340   data = CBS_data(&bytes);
    341   len = CBS_len(&bytes);
    342 
    343   if (len == 0) {
    344     /* An INTEGER is encoded with at least one octet. */
    345     return 0;
    346   }
    347 
    348   if ((data[0] & 0x80) != 0) {
    349     /* Negative number. */
    350     return 0;
    351   }
    352 
    353   if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
    354     /* Extra leading zeros. */
    355     return 0;
    356   }
    357 
    358   for (i = 0; i < len; i++) {
    359     if ((*out >> 56) != 0) {
    360       /* Too large to represent as a uint64_t. */
    361       return 0;
    362     }
    363     *out <<= 8;
    364     *out |= data[i];
    365   }
    366 
    367   return 1;
    368 }
    369 
    370 int CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned tag) {
    371   int present = 0;
    372 
    373   if (CBS_peek_asn1_tag(cbs, tag)) {
    374     if (!CBS_get_asn1(cbs, out, tag)) {
    375       return 0;
    376     }
    377     present = 1;
    378   }
    379 
    380   if (out_present != NULL) {
    381     *out_present = present;
    382   }
    383 
    384   return 1;
    385 }
    386 
    387 int CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present,
    388                                        unsigned tag) {
    389   CBS child;
    390   int present;
    391   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
    392     return 0;
    393   }
    394   if (present) {
    395     if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) ||
    396         CBS_len(&child) != 0) {
    397       return 0;
    398     }
    399   } else {
    400     CBS_init(out, NULL, 0);
    401   }
    402   if (out_present) {
    403     *out_present = present;
    404   }
    405   return 1;
    406 }
    407 
    408 int CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned tag,
    409                                  uint64_t default_value) {
    410   CBS child;
    411   int present;
    412   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
    413     return 0;
    414   }
    415   if (present) {
    416     if (!CBS_get_asn1_uint64(&child, out) ||
    417         CBS_len(&child) != 0) {
    418       return 0;
    419     }
    420   } else {
    421     *out = default_value;
    422   }
    423   return 1;
    424 }
    425 
    426 int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
    427                                int default_value) {
    428   CBS child, child2;
    429   int present;
    430   if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) {
    431     return 0;
    432   }
    433   if (present) {
    434     uint8_t boolean;
    435 
    436     if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
    437         CBS_len(&child2) != 1 ||
    438         CBS_len(&child) != 0) {
    439       return 0;
    440     }
    441 
    442     boolean = CBS_data(&child2)[0];
    443     if (boolean == 0) {
    444       *out = 0;
    445     } else if (boolean == 0xff) {
    446       *out = 1;
    447     } else {
    448       return 0;
    449     }
    450   } else {
    451     *out = default_value;
    452   }
    453   return 1;
    454 }
    455 
    456 int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
    457   CBS in = *cbs;
    458   uint8_t num_unused_bits;
    459   if (!CBS_get_u8(&in, &num_unused_bits) ||
    460       num_unused_bits > 7) {
    461     return 0;
    462   }
    463 
    464   if (num_unused_bits == 0) {
    465     return 1;
    466   }
    467 
    468   /* All num_unused_bits bits must exist and be zeros. */
    469   uint8_t last;
    470   if (!CBS_get_last_u8(&in, &last) ||
    471       (last & ((1 << num_unused_bits) - 1)) != 0) {
    472     return 0;
    473   }
    474 
    475   return 1;
    476 }
    477 
    478 int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
    479   if (!CBS_is_valid_asn1_bitstring(cbs)) {
    480     return 0;
    481   }
    482 
    483   const unsigned byte_num = (bit >> 3) + 1;
    484   const unsigned bit_num = 7 - (bit & 7);
    485 
    486   /* Unused bits are zero, and this function does not distinguish between
    487    * missing and unset bits. Thus it is sufficient to do a byte-level length
    488    * check. */
    489   return byte_num < CBS_len(cbs) &&
    490          (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
    491 }
    492