Home | History | Annotate | Download | only in src
      1 // Copyright 2015 The Weave Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/macaroon_encoding.h"
      6 
      7 #include <string.h>
      8 
      9 #define MAJOR_TYPE_MASK 0xE0       // 0b11100000
     10 #define ADDITIONAL_DATA_MASK 0x1F  // 0b00011111
     11 
     12 #define FLAG_1BYTE_UINT 24
     13 #define FLAG_2BYTE_UINT 25
     14 #define FLAG_4BYTE_UINT 26
     15 // #define FLAG_8BYTE_UINT 27  // Do not support 8-byte
     16 
     17 typedef enum {
     18   kCborMajorTypeUint = 0,          // type 0 -- unsigned integers
     19   kCborMajorTypeByteStr = 2 << 5,  // type 2 -- byte strings
     20   kCborMajorTypeTextStr = 3 << 5,  // type 3 -- text strings
     21   kCborMajorTypeArray = 4 << 5,    // type 4 -- arrays
     22 } CborMajorType;
     23 
     24 static inline CborMajorType get_type_(const uint8_t* cbor);
     25 static inline uint8_t get_addtl_data_(const uint8_t* cbor);
     26 static inline void set_type_(CborMajorType type, uint8_t* cbor);
     27 static inline void set_addtl_data_(uint8_t addtl_data, uint8_t* cbor);
     28 
     29 /** Computes the minimum number of bytes to store the unsigned integer. */
     30 static inline size_t uint_min_len_(uint32_t unsigned_int);
     31 
     32 /** Encoding or decoding without checking types */
     33 static bool blindly_encode_uint_(uint32_t unsigned_int,
     34                                  uint8_t* buffer,
     35                                  size_t buffer_size,
     36                                  size_t* result_len);
     37 static bool blindly_encode_str_(const uint8_t* str,
     38                                 size_t str_len,
     39                                 uint8_t* buffer,
     40                                 size_t buffer_size,
     41                                 size_t* result_len);
     42 static bool blindly_decode_uint_(const uint8_t* cbor,
     43                                  size_t cbor_len,
     44                                  uint32_t* unsigned_int);
     45 static bool blindly_decode_str_(const uint8_t* cbor,
     46                                 size_t cbor_len,
     47                                 const uint8_t** out_str,
     48                                 size_t* out_str_len);
     49 
     50 bool uw_macaroon_encoding_get_item_len_(const uint8_t* cbor,
     51                                         size_t cbor_len,
     52                                         size_t* first_item_len) {
     53   if (cbor == NULL || cbor_len == 0 || first_item_len == NULL) {
     54     return false;
     55   }
     56 
     57   CborMajorType type = get_type_(cbor);
     58   if (type != kCborMajorTypeUint && type != kCborMajorTypeByteStr &&
     59       type != kCborMajorTypeTextStr && type != kCborMajorTypeArray) {
     60     // Other types are not supported
     61     return false;
     62   }
     63 
     64   uint32_t unsigned_int;
     65   if (!blindly_decode_uint_(cbor, cbor_len, &unsigned_int)) {
     66     return false;
     67   }
     68 
     69   *first_item_len = uint_min_len_(unsigned_int) + 1;
     70 
     71   // For arrays, it returns only the length of the array length portion, not the
     72   // length of the whole array
     73   if (type == kCborMajorTypeByteStr || type == kCborMajorTypeTextStr) {
     74     *first_item_len += (size_t)unsigned_int;
     75   }
     76 
     77   if (*first_item_len > cbor_len) {
     78     // Something is wrong. The CBOR string isn't long enough.
     79     return false;
     80   }
     81   return true;
     82 }
     83 
     84 bool uw_macaroon_encoding_encode_uint_(const uint32_t unsigned_int,
     85                                        uint8_t* buffer,
     86                                        size_t buffer_size,
     87                                        size_t* resulting_cbor_len) {
     88   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
     89     return false;
     90   }
     91 
     92   set_type_(kCborMajorTypeUint, buffer);
     93   return blindly_encode_uint_(unsigned_int, buffer, buffer_size,
     94                               resulting_cbor_len);
     95 }
     96 
     97 bool uw_macaroon_encoding_encode_array_len_(const uint32_t array_len,
     98                                             uint8_t* buffer,
     99                                             size_t buffer_size,
    100                                             size_t* resulting_cbor_len) {
    101   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
    102     return false;
    103   }
    104 
    105   set_type_(kCborMajorTypeArray, buffer);
    106   return blindly_encode_uint_(array_len, buffer, buffer_size,
    107                               resulting_cbor_len);
    108 }
    109 
    110 bool uw_macaroon_encoding_encode_byte_str_(const uint8_t* str,
    111                                            size_t str_len,
    112                                            uint8_t* buffer,
    113                                            size_t buffer_size,
    114                                            size_t* resulting_cbor_len) {
    115   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
    116     return false;
    117   }
    118 
    119   set_type_(kCborMajorTypeByteStr, buffer);
    120   return blindly_encode_str_(str, str_len, buffer, buffer_size,
    121                              resulting_cbor_len);
    122 }
    123 
    124 bool uw_macaroon_encoding_encode_text_str_(const uint8_t* str,
    125                                            size_t str_len,
    126                                            uint8_t* buffer,
    127                                            size_t buffer_size,
    128                                            size_t* resulting_cbor_len) {
    129   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
    130     return false;
    131   }
    132 
    133   set_type_(kCborMajorTypeTextStr, buffer);
    134   return blindly_encode_str_(str, str_len, buffer, buffer_size,
    135                              resulting_cbor_len);
    136 }
    137 
    138 bool uw_macaroon_encoding_encode_byte_str_len_(size_t str_len,
    139                                                uint8_t* buffer,
    140                                                size_t buffer_size,
    141                                                size_t* resulting_cbor_len) {
    142   if (buffer == NULL || buffer_size == 0 || resulting_cbor_len == NULL) {
    143     return false;
    144   }
    145   set_type_(kCborMajorTypeByteStr, buffer);
    146   return blindly_encode_uint_(str_len, buffer, buffer_size, resulting_cbor_len);
    147 }
    148 
    149 bool uw_macaroon_encoding_decode_uint_(const uint8_t* cbor,
    150                                        size_t cbor_len,
    151                                        uint32_t* unsigned_int) {
    152   if (cbor == NULL || cbor_len == 0 || unsigned_int == NULL ||
    153       get_type_(cbor) != kCborMajorTypeUint) {
    154     return false;
    155   }
    156 
    157   return blindly_decode_uint_(cbor, cbor_len, unsigned_int);
    158 }
    159 
    160 bool uw_macaroon_encoding_decode_array_len_(const uint8_t* cbor,
    161                                             size_t cbor_len,
    162                                             uint32_t* array_len) {
    163   if (cbor == NULL || cbor_len == 0 || array_len == NULL ||
    164       get_type_(cbor) != kCborMajorTypeArray) {
    165     return false;
    166   }
    167 
    168   return blindly_decode_uint_(cbor, cbor_len, array_len);
    169 }
    170 
    171 bool uw_macaroon_encoding_decode_byte_str_(const uint8_t* cbor,
    172                                            size_t cbor_len,
    173                                            const uint8_t** out_str,
    174                                            size_t* out_str_len) {
    175   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str_len == NULL ||
    176       get_type_(cbor) != kCborMajorTypeByteStr) {
    177     return false;
    178   }
    179 
    180   return blindly_decode_str_(cbor, cbor_len, out_str, out_str_len);
    181 }
    182 
    183 bool uw_macaroon_encoding_decode_text_str_(const uint8_t* cbor,
    184                                            size_t cbor_len,
    185                                            const uint8_t** out_str,
    186                                            size_t* out_str_len) {
    187   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str_len == NULL ||
    188       get_type_(cbor) != kCborMajorTypeTextStr) {
    189     return false;
    190   }
    191 
    192   return blindly_decode_str_(cbor, cbor_len, out_str, out_str_len);
    193 }
    194 
    195 static inline CborMajorType get_type_(const uint8_t* cbor) {
    196   return (CborMajorType)((*cbor) & MAJOR_TYPE_MASK);
    197 }
    198 
    199 static inline uint8_t get_addtl_data_(const uint8_t* cbor) {
    200   return (*cbor) & ADDITIONAL_DATA_MASK;
    201 }
    202 
    203 static inline void set_type_(CborMajorType type, uint8_t* cbor) {
    204   *cbor = ((uint8_t)type) | ((*cbor) & ADDITIONAL_DATA_MASK);
    205 }
    206 
    207 static inline void set_addtl_data_(uint8_t addtl_data, uint8_t* cbor) {
    208   *cbor = ((*cbor) & MAJOR_TYPE_MASK) | (addtl_data & ADDITIONAL_DATA_MASK);
    209 }
    210 
    211 static inline size_t uint_min_len_(uint32_t unsigned_int) {
    212   if (unsigned_int < FLAG_1BYTE_UINT) {
    213     return 0;  // Should be stored in the 5-bit additional data part
    214   } else if (unsigned_int <= 0xFF) {
    215     return 1;
    216   } else if (unsigned_int <= 0xFFFF) {
    217     return 2;
    218   }
    219   return 4;
    220 }
    221 
    222 /**
    223  * Writes the unsigned int in the big-endian fashion by using the minimum number
    224  * of bytes in CBOR
    225  */
    226 static inline bool write_uint_big_endian_(uint32_t unsigned_int,
    227                                           uint8_t* buff,
    228                                           size_t buff_len) {
    229   if (buff == NULL || buff_len == 0) {
    230     return false;
    231   }
    232 
    233   size_t num_bytes = uint_min_len_(unsigned_int);
    234   if (num_bytes > buff_len) {
    235     // Not enough memory
    236     return false;
    237   }
    238 
    239   switch (num_bytes) {
    240     // Falling through intentionally
    241     case 4:
    242       *(buff++) = (uint8_t)(0xFF & (unsigned_int >> 24));
    243       *(buff++) = (uint8_t)(0xFF & (unsigned_int >> 16));
    244     case 2:
    245       *(buff++) = (uint8_t)(0xFF & (unsigned_int >> 8));
    246     case 1:
    247       *(buff++) = (uint8_t)(0xFF & (unsigned_int));
    248       break;
    249 
    250     default:
    251       return false;
    252   }
    253 
    254   return true;
    255 }
    256 
    257 /** Reads the unsigned int written in big-endian. */
    258 static inline bool read_uint_big_endian_(const uint8_t* bytes,
    259                                          size_t num_bytes,
    260                                          uint32_t* unsigned_int) {
    261   if (bytes == NULL || num_bytes == 0 || num_bytes > 4 ||
    262       unsigned_int == NULL) {
    263     return false;
    264   }
    265 
    266   *unsigned_int = 0;
    267   switch (num_bytes) {
    268     // Falling through intentionally
    269     case 4:
    270       *unsigned_int |= ((uint32_t)(*(bytes++))) << 24;
    271       *unsigned_int |= ((uint32_t)(*(bytes++))) << 16;
    272     case 2:
    273       *unsigned_int |= ((uint32_t)(*(bytes++))) << 8;
    274     case 1:
    275       *unsigned_int |= ((uint32_t)(*(bytes++)));
    276       break;
    277 
    278     default:
    279       return false;
    280   }
    281 
    282   return true;
    283 }
    284 
    285 static bool blindly_encode_uint_(uint32_t unsigned_int,
    286                                  uint8_t* buffer,
    287                                  size_t buffer_size,
    288                                  size_t* result_len) {
    289   if (buffer == NULL || buffer_size == 0 || result_len == NULL) {
    290     return false;
    291   }
    292 
    293   // Don't need to set the data type in this function
    294 
    295   *result_len = uint_min_len_(unsigned_int) + 1;
    296 
    297   if (*result_len > buffer_size) {
    298     // Not enough memory
    299     return false;
    300   }
    301 
    302   switch (*result_len) {
    303     case 1:
    304       set_addtl_data_(unsigned_int, buffer);
    305       return true;
    306     case 2:  // 1 + 1
    307       set_addtl_data_(FLAG_1BYTE_UINT, buffer);
    308       break;
    309     case 3:  // 1 + 2
    310       set_addtl_data_(FLAG_2BYTE_UINT, buffer);
    311       break;
    312     case 5:  // 1 + 4
    313       set_addtl_data_(FLAG_4BYTE_UINT, buffer);
    314       break;
    315     default:
    316       // Wrong length
    317       return false;
    318   }
    319 
    320   return write_uint_big_endian_(unsigned_int, buffer + 1, buffer_size - 1);
    321 }
    322 
    323 static bool blindly_encode_str_(const uint8_t* str,
    324                                 size_t str_len,
    325                                 uint8_t* buffer,
    326                                 size_t buffer_size,
    327                                 size_t* result_len) {
    328   if (buffer == NULL || buffer_size == 0) {
    329     return false;
    330   }
    331   if (str == NULL && str_len != 0) {
    332     // str_len should be 0 for empty strings
    333     return false;
    334   }
    335 
    336   // Don't need to set the data type in this function
    337 
    338   if (!blindly_encode_uint_((uint32_t)str_len, buffer, buffer_size,
    339                             result_len)) {
    340     return false;
    341   }
    342 
    343   if (str_len == 0) {
    344     return true;
    345   }
    346 
    347   if (str_len + (*result_len) > buffer_size) {
    348     // Not enough memory
    349     return false;
    350   }
    351 
    352   memcpy(buffer + (*result_len), str, str_len);
    353   *result_len += str_len;
    354   return true;
    355 }
    356 
    357 static bool blindly_decode_uint_(const uint8_t* cbor,
    358                                  size_t cbor_len,
    359                                  uint32_t* unsigned_int) {
    360   if (cbor == NULL || cbor_len == 0 || unsigned_int == NULL) {
    361     return false;
    362   }
    363 
    364   uint8_t addtl_data = get_addtl_data_(cbor);
    365   if (addtl_data < FLAG_1BYTE_UINT) {
    366     *unsigned_int = (uint32_t)addtl_data;
    367     return true;
    368   }
    369   if (addtl_data > FLAG_4BYTE_UINT) {
    370     return false;
    371   }
    372 
    373   size_t uint_num_bytes = 1 << (addtl_data - (uint8_t)FLAG_1BYTE_UINT);
    374   if (uint_num_bytes + 1 > cbor_len) {
    375     // The CBOR string isn't long enough.
    376     return false;
    377   }
    378 
    379   return read_uint_big_endian_(cbor + 1, uint_num_bytes, unsigned_int);
    380 }
    381 
    382 static bool blindly_decode_str_(const uint8_t* cbor,
    383                                 size_t cbor_len,
    384                                 const uint8_t** out_str,
    385                                 size_t* out_str_len) {
    386   if (cbor == NULL || cbor_len == 0 || out_str == NULL || out_str == NULL) {
    387     return false;
    388   }
    389 
    390   uint32_t unsigned_int;
    391   if (!blindly_decode_uint_(cbor, cbor_len, &unsigned_int)) {
    392     return false;
    393   }
    394 
    395   size_t offset = 1 + uint_min_len_(unsigned_int);
    396   if (unsigned_int > (uint32_t)(cbor_len - offset)) {
    397     // The CBOR string isn't long enough
    398     return false;
    399   }
    400 
    401   *out_str = cbor + offset;
    402   *out_str_len = unsigned_int;
    403   return true;
    404 }
    405