1 /* $OpenBSD: bs_cbs.c,v 1.20 2021/05/16 10:58:27 jsing Exp $ */ 2 /* 3 * Copyright (c) 2014, Google Inc. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 12 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 14 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 #include <string.h> 20 21 #include "bytestring.h" 22 23 void 24 CBS_init(CBS *cbs, const uint8_t *data, size_t len) 25 { 26 cbs->data = data; 27 cbs->initial_len = len; 28 cbs->len = len; 29 } 30 31 void 32 CBS_dup(const CBS *cbs, CBS *out) 33 { 34 CBS_init(out, CBS_data(cbs), CBS_len(cbs)); 35 out->initial_len = cbs->initial_len; 36 } 37 38 static int 39 cbs_get(CBS *cbs, const uint8_t **p, size_t n) 40 { 41 if (cbs->len < n) 42 return 0; 43 44 *p = cbs->data; 45 cbs->data += n; 46 cbs->len -= n; 47 return 1; 48 } 49 50 size_t 51 CBS_offset(const CBS *cbs) 52 { 53 return cbs->initial_len - cbs->len; 54 } 55 56 int 57 CBS_skip(CBS *cbs, size_t len) 58 { 59 const uint8_t *dummy; 60 return cbs_get(cbs, &dummy, len); 61 } 62 63 const uint8_t * 64 CBS_data(const CBS *cbs) 65 { 66 return cbs->data; 67 } 68 69 size_t 70 CBS_len(const CBS *cbs) 71 { 72 return cbs->len; 73 } 74 75 int 76 CBS_stow(const CBS *cbs, uint8_t **out_ptr, size_t *out_len) 77 { 78 free(*out_ptr); 79 *out_ptr = NULL; 80 *out_len = 0; 81 82 if (cbs->len == 0) 83 return 1; 84 85 if ((*out_ptr = malloc(cbs->len)) == NULL) 86 return 0; 87 88 memcpy(*out_ptr, cbs->data, cbs->len); 89 90 *out_len = cbs->len; 91 return 1; 92 } 93 94 int 95 CBS_strdup(const CBS *cbs, char **out_ptr) 96 { 97 free(*out_ptr); 98 *out_ptr = strndup((const char *)cbs->data, cbs->len); 99 return (*out_ptr != NULL); 100 } 101 102 int 103 CBS_write_bytes(const CBS *cbs, uint8_t *dst, size_t dst_len, size_t *copied) 104 { 105 if (dst_len < cbs->len) 106 return 0; 107 108 memmove(dst, cbs->data, cbs->len); 109 110 if (copied != NULL) 111 *copied = cbs->len; 112 113 return 1; 114 } 115 116 int 117 CBS_contains_zero_byte(const CBS *cbs) 118 { 119 return memchr(cbs->data, 0, cbs->len) != NULL; 120 } 121 122 int 123 CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) 124 { 125 if (len != cbs->len) 126 return 0; 127 128 return timingsafe_memcmp(cbs->data, data, len) == 0; 129 } 130 131 static int 132 cbs_get_u(CBS *cbs, uint32_t *out, size_t len) 133 { 134 uint32_t result = 0; 135 size_t i; 136 const uint8_t *data; 137 138 if (len < 1 || len > 4) 139 return 0; 140 141 if (!cbs_get(cbs, &data, len)) 142 return 0; 143 144 for (i = 0; i < len; i++) { 145 result <<= 8; 146 result |= data[i]; 147 } 148 *out = result; 149 return 1; 150 } 151 152 int 153 CBS_get_u8(CBS *cbs, uint8_t *out) 154 { 155 const uint8_t *v; 156 157 if (!cbs_get(cbs, &v, 1)) 158 return 0; 159 160 *out = *v; 161 return 1; 162 } 163 164 int 165 CBS_get_u16(CBS *cbs, uint16_t *out) 166 { 167 uint32_t v; 168 169 if (!cbs_get_u(cbs, &v, 2)) 170 return 0; 171 172 *out = v; 173 return 1; 174 } 175 176 int 177 CBS_get_u24(CBS *cbs, uint32_t *out) 178 { 179 return cbs_get_u(cbs, out, 3); 180 } 181 182 int 183 CBS_get_u32(CBS *cbs, uint32_t *out) 184 { 185 return cbs_get_u(cbs, out, 4); 186 } 187 188 int 189 CBS_get_bytes(CBS *cbs, CBS *out, size_t len) 190 { 191 const uint8_t *v; 192 193 if (!cbs_get(cbs, &v, len)) 194 return 0; 195 196 CBS_init(out, v, len); 197 return 1; 198 } 199 200 static int 201 cbs_get_length_prefixed(CBS *cbs, CBS *out, size_t len_len) 202 { 203 uint32_t len; 204 205 if (!cbs_get_u(cbs, &len, len_len)) 206 return 0; 207 208 return CBS_get_bytes(cbs, out, len); 209 } 210 211 int 212 CBS_get_u8_length_prefixed(CBS *cbs, CBS *out) 213 { 214 return cbs_get_length_prefixed(cbs, out, 1); 215 } 216 217 int 218 CBS_get_u16_length_prefixed(CBS *cbs, CBS *out) 219 { 220 return cbs_get_length_prefixed(cbs, out, 2); 221 } 222 223 int 224 CBS_get_u24_length_prefixed(CBS *cbs, CBS *out) 225 { 226 return cbs_get_length_prefixed(cbs, out, 3); 227 } 228 229 int 230 CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned int *out_tag, 231 size_t *out_header_len) 232 { 233 return cbs_get_any_asn1_element_internal(cbs, out, out_tag, 234 out_header_len, 1); 235 } 236 237 /* 238 * Review X.690 for details on ASN.1 DER encoding. 239 * 240 * If non-strict mode is enabled, then DER rules are relaxed 241 * for indefinite constructs (violates DER but a little closer to BER). 242 * Non-strict mode should only be used by bs_ber.c 243 * 244 * Sections 8, 10 and 11 for DER encoding 245 */ 246 int 247 cbs_get_any_asn1_element_internal(CBS *cbs, CBS *out, unsigned int *out_tag, 248 size_t *out_header_len, int strict) 249 { 250 uint8_t tag, length_byte; 251 CBS header = *cbs; 252 CBS throwaway; 253 size_t len; 254 255 if (out == NULL) 256 out = &throwaway; 257 258 /* 259 * Get identifier octet and length octet. Only 1 octet for each 260 * is a CBS limitation. 261 */ 262 if (!CBS_get_u8(&header, &tag) || !CBS_get_u8(&header, &length_byte)) 263 return 0; 264 265 /* CBS limitation: long form tags are not supported. */ 266 if ((tag & 0x1f) == 0x1f) 267 return 0; 268 269 if (out_tag != NULL) 270 *out_tag = tag; 271 272 if ((length_byte & 0x80) == 0) { 273 /* Short form length. */ 274 len = ((size_t) length_byte) + 2; 275 if (out_header_len != NULL) 276 *out_header_len = 2; 277 278 } else { 279 /* Long form length. */ 280 const size_t num_bytes = length_byte & 0x7f; 281 uint32_t len32; 282 283 /* ASN.1 reserved value for future extensions */ 284 if (num_bytes == 0x7f) 285 return 0; 286 287 /* Handle indefinite form length */ 288 if (num_bytes == 0) { 289 /* DER encoding doesn't allow for indefinite form. */ 290 if (strict) 291 return 0; 292 293 /* Primitive cannot use indefinite in BER or DER. */ 294 if ((tag & CBS_ASN1_CONSTRUCTED) == 0) 295 return 0; 296 297 /* Constructed, indefinite length allowed in BER. */ 298 if (out_header_len != NULL) 299 *out_header_len = 2; 300 return CBS_get_bytes(cbs, out, 2); 301 } 302 303 /* CBS limitation. */ 304 if (num_bytes > 4) 305 return 0; 306 307 if (!cbs_get_u(&header, &len32, num_bytes)) 308 return 0; 309 310 /* DER has a minimum length octet requirement. */ 311 if (len32 < 128) 312 /* Should have used short form instead */ 313 return 0; 314 315 if ((len32 >> ((num_bytes - 1) * 8)) == 0) 316 /* Length should have been at least one byte shorter. */ 317 return 0; 318 319 len = len32; 320 if (len + 2 + num_bytes < len) 321 /* Overflow. */ 322 return 0; 323 324 len += 2 + num_bytes; 325 if (out_header_len != NULL) 326 *out_header_len = 2 + num_bytes; 327 } 328 329 return CBS_get_bytes(cbs, out, len); 330 } 331 332 static int 333 cbs_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value, int skip_header) 334 { 335 size_t header_len; 336 unsigned int tag; 337 CBS throwaway; 338 339 if (out == NULL) 340 out = &throwaway; 341 342 if (!CBS_get_any_asn1_element(cbs, out, &tag, &header_len) || 343 tag != tag_value) 344 return 0; 345 346 if (skip_header && !CBS_skip(out, header_len)) 347 return 0; 348 349 return 1; 350 } 351 352 int 353 CBS_get_asn1(CBS *cbs, CBS *out, unsigned int tag_value) 354 { 355 return cbs_get_asn1(cbs, out, tag_value, 1 /* skip header */); 356 } 357 358 int 359 CBS_get_asn1_element(CBS *cbs, CBS *out, unsigned int tag_value) 360 { 361 return cbs_get_asn1(cbs, out, tag_value, 0 /* include header */); 362 } 363 364 int 365 CBS_peek_asn1_tag(const CBS *cbs, unsigned int tag_value) 366 { 367 if (CBS_len(cbs) < 1) 368 return 0; 369 370 /* 371 * Tag number 31 indicates the start of a long form number. 372 * This is valid in ASN.1, but CBS only supports short form. 373 */ 374 if ((tag_value & 0x1f) == 0x1f) 375 return 0; 376 377 return CBS_data(cbs)[0] == tag_value; 378 } 379 380 /* Encoding details are in ASN.1: X.690 section 8.3 */ 381 int 382 CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) 383 { 384 CBS bytes; 385 const uint8_t *data; 386 size_t i, len; 387 388 if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) 389 return 0; 390 391 *out = 0; 392 data = CBS_data(&bytes); 393 len = CBS_len(&bytes); 394 395 if (len == 0) 396 /* An INTEGER is encoded with at least one content octet. */ 397 return 0; 398 399 if ((data[0] & 0x80) != 0) 400 /* Negative number. */ 401 return 0; 402 403 if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) 404 /* Violates smallest encoding rule: excessive leading zeros. */ 405 return 0; 406 407 for (i = 0; i < len; i++) { 408 if ((*out >> 56) != 0) 409 /* Too large to represent as a uint64_t. */ 410 return 0; 411 412 *out <<= 8; 413 *out |= data[i]; 414 } 415 416 return 1; 417 } 418 419 int 420 CBS_get_optional_asn1(CBS *cbs, CBS *out, int *out_present, unsigned int tag) 421 { 422 if (CBS_peek_asn1_tag(cbs, tag)) { 423 if (!CBS_get_asn1(cbs, out, tag)) 424 return 0; 425 426 *out_present = 1; 427 } else { 428 *out_present = 0; 429 } 430 return 1; 431 } 432 433 int 434 CBS_get_optional_asn1_octet_string(CBS *cbs, CBS *out, int *out_present, 435 unsigned int tag) 436 { 437 CBS child; 438 int present; 439 440 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 441 return 0; 442 443 if (present) { 444 if (!CBS_get_asn1(&child, out, CBS_ASN1_OCTETSTRING) || 445 CBS_len(&child) != 0) 446 return 0; 447 } else { 448 CBS_init(out, NULL, 0); 449 } 450 if (out_present) 451 *out_present = present; 452 453 return 1; 454 } 455 456 int 457 CBS_get_optional_asn1_uint64(CBS *cbs, uint64_t *out, unsigned int tag, 458 uint64_t default_value) 459 { 460 CBS child; 461 int present; 462 463 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 464 return 0; 465 466 if (present) { 467 if (!CBS_get_asn1_uint64(&child, out) || 468 CBS_len(&child) != 0) 469 return 0; 470 } else { 471 *out = default_value; 472 } 473 return 1; 474 } 475 476 int 477 CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned int tag, 478 int default_value) 479 { 480 CBS child, child2; 481 int present; 482 483 if (!CBS_get_optional_asn1(cbs, &child, &present, tag)) 484 return 0; 485 486 if (present) { 487 uint8_t boolean; 488 489 if (!CBS_get_asn1(&child, &child2, CBS_ASN1_BOOLEAN) || 490 CBS_len(&child2) != 1 || CBS_len(&child) != 0) 491 return 0; 492 493 boolean = CBS_data(&child2)[0]; 494 if (boolean == 0) 495 *out = 0; 496 else if (boolean == 0xff) 497 *out = 1; 498 else 499 return 0; 500 501 } else { 502 *out = default_value; 503 } 504 return 1; 505 } 506