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