1 /* 2 * ASN.1 DER parsing 3 * Copyright (c) 2006-2014, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "utils/wpabuf.h" 13 #include "asn1.h" 14 15 const struct asn1_oid asn1_sha1_oid = { 16 .oid = { 1, 3, 14, 3, 2, 26 }, 17 .len = 6 18 }; 19 20 const struct asn1_oid asn1_sha256_oid = { 21 .oid = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }, 22 .len = 9 23 }; 24 25 const struct asn1_oid asn1_ec_public_key_oid = { 26 .oid = { 1, 2, 840, 10045, 2, 1 }, 27 .len = 6 28 }; 29 30 const struct asn1_oid asn1_prime256v1_oid = { 31 .oid = { 1, 2, 840, 10045, 3, 1, 7 }, 32 .len = 7 33 }; 34 35 const struct asn1_oid asn1_secp384r1_oid = { 36 .oid = { 1, 3, 132, 0, 34 }, 37 .len = 5 38 }; 39 40 const struct asn1_oid asn1_secp521r1_oid = { 41 .oid = { 1, 3, 132, 0, 35 }, 42 .len = 5 43 }; 44 45 const struct asn1_oid asn1_brainpoolP256r1_oid = { 46 .oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 7 }, 47 .len = 10 48 }; 49 50 const struct asn1_oid asn1_brainpoolP384r1_oid = { 51 .oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 11 }, 52 .len = 10 53 }; 54 55 const struct asn1_oid asn1_brainpoolP512r1_oid = { 56 .oid = { 1, 3, 36, 3, 3, 2, 8, 1, 1, 13 }, 57 .len = 10 58 }; 59 60 const struct asn1_oid asn1_aes_siv_cmac_aead_256_oid = { 61 .oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 22 }, 62 .len = 9 63 }; 64 65 const struct asn1_oid asn1_aes_siv_cmac_aead_384_oid = { 66 .oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 23 }, 67 .len = 9 68 }; 69 70 const struct asn1_oid asn1_aes_siv_cmac_aead_512_oid = { 71 .oid = { 1, 2, 840, 113549, 1, 9, 16, 3, 24 }, 72 .len = 9 73 }; 74 75 const struct asn1_oid asn1_pbkdf2_oid = { 76 .oid = { 1, 2, 840, 113549, 1, 5, 12 }, 77 .len = 7 78 }; 79 80 const struct asn1_oid asn1_pbkdf2_hmac_sha256_oid = { 81 .oid = { 1, 2, 840, 113549, 2, 9 }, 82 .len = 6 83 }; 84 85 const struct asn1_oid asn1_pbkdf2_hmac_sha384_oid = { 86 .oid = { 1, 2, 840, 113549, 2, 10 }, 87 .len = 6 88 }; 89 90 const struct asn1_oid asn1_pbkdf2_hmac_sha512_oid = { 91 .oid = { 1, 2, 840, 113549, 2, 11 }, 92 .len = 6 93 }; 94 95 const struct asn1_oid asn1_dpp_config_params_oid = { 96 .oid = { 1, 3, 6, 1, 4, 1, 40808, 1, 2, 1 }, 97 .len = 10 98 }; 99 100 const struct asn1_oid asn1_dpp_asymmetric_key_package_oid = { 101 .oid = { 1, 3, 6, 1, 4, 1, 40808, 1, 2, 2 }, 102 .len = 10 103 }; 104 105 106 static int asn1_valid_der_boolean(struct asn1_hdr *hdr) 107 { 108 /* Enforce DER requirements for a single way of encoding a BOOLEAN */ 109 if (hdr->length != 1) { 110 wpa_printf(MSG_DEBUG, "ASN.1: Unexpected BOOLEAN length (%u)", 111 hdr->length); 112 return 0; 113 } 114 115 if (hdr->payload[0] != 0 && hdr->payload[0] != 0xff) { 116 wpa_printf(MSG_DEBUG, 117 "ASN.1: Invalid BOOLEAN value 0x%x (DER requires 0 or 0xff)", 118 hdr->payload[0]); 119 return 0; 120 } 121 122 return 1; 123 } 124 125 126 static int asn1_valid_der(struct asn1_hdr *hdr) 127 { 128 if (hdr->class != ASN1_CLASS_UNIVERSAL) 129 return 1; 130 if (hdr->tag == ASN1_TAG_BOOLEAN && !asn1_valid_der_boolean(hdr)) 131 return 0; 132 if (hdr->tag == ASN1_TAG_NULL && hdr->length != 0) 133 return 0; 134 135 /* Check for allowed primitive/constructed values */ 136 if (hdr->constructed && 137 (hdr->tag == ASN1_TAG_BOOLEAN || 138 hdr->tag == ASN1_TAG_INTEGER || 139 hdr->tag == ASN1_TAG_NULL || 140 hdr->tag == ASN1_TAG_OID || 141 hdr->tag == ANS1_TAG_RELATIVE_OID || 142 hdr->tag == ASN1_TAG_REAL || 143 hdr->tag == ASN1_TAG_ENUMERATED || 144 hdr->tag == ASN1_TAG_BITSTRING || 145 hdr->tag == ASN1_TAG_OCTETSTRING || 146 hdr->tag == ASN1_TAG_NUMERICSTRING || 147 hdr->tag == ASN1_TAG_PRINTABLESTRING || 148 hdr->tag == ASN1_TAG_T61STRING || 149 hdr->tag == ASN1_TAG_VIDEOTEXSTRING || 150 hdr->tag == ASN1_TAG_VISIBLESTRING || 151 hdr->tag == ASN1_TAG_IA5STRING || 152 hdr->tag == ASN1_TAG_GRAPHICSTRING || 153 hdr->tag == ASN1_TAG_GENERALSTRING || 154 hdr->tag == ASN1_TAG_UNIVERSALSTRING || 155 hdr->tag == ASN1_TAG_UTF8STRING || 156 hdr->tag == ASN1_TAG_BMPSTRING || 157 hdr->tag == ASN1_TAG_CHARACTERSTRING || 158 hdr->tag == ASN1_TAG_UTCTIME || 159 hdr->tag == ASN1_TAG_GENERALIZEDTIME || 160 hdr->tag == ASN1_TAG_TIME)) 161 return 0; 162 if (!hdr->constructed && 163 (hdr->tag == ASN1_TAG_SEQUENCE || 164 hdr->tag == ASN1_TAG_SET)) 165 return 0; 166 167 return 1; 168 } 169 170 171 int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) 172 { 173 const u8 *pos, *end; 174 u8 tmp; 175 176 os_memset(hdr, 0, sizeof(*hdr)); 177 pos = buf; 178 end = buf + len; 179 180 if (pos >= end) { 181 wpa_printf(MSG_DEBUG, "ASN.1: No room for Identifier"); 182 return -1; 183 } 184 hdr->identifier = *pos++; 185 hdr->class = hdr->identifier >> 6; 186 hdr->constructed = !!(hdr->identifier & (1 << 5)); 187 188 if ((hdr->identifier & 0x1f) == 0x1f) { 189 size_t ext_len = 0; 190 191 hdr->tag = 0; 192 if (pos == end || (*pos & 0x7f) == 0) { 193 wpa_printf(MSG_DEBUG, 194 "ASN.1: Invalid extended tag (first octet has to be included with at least one nonzero bit for the tag value)"); 195 return -1; 196 } 197 do { 198 if (pos >= end) { 199 wpa_printf(MSG_DEBUG, "ASN.1: Identifier " 200 "underflow"); 201 return -1; 202 } 203 ext_len++; 204 tmp = *pos++; 205 wpa_printf(MSG_MSGDUMP, "ASN.1: Extended tag data: " 206 "0x%02x", tmp); 207 hdr->tag = (hdr->tag << 7) | (tmp & 0x7f); 208 } while (tmp & 0x80); 209 wpa_printf(MSG_MSGDUMP, "ASN.1: Extended Tag: 0x%x (len=%zu)", 210 hdr->tag, ext_len); 211 if ((hdr->class != ASN1_CLASS_PRIVATE && hdr->tag < 31) || 212 ext_len * 7 > sizeof(hdr->tag) * 8) { 213 wpa_printf(MSG_DEBUG, 214 "ASN.1: Invalid or unsupported (too large) extended Tag: 0x%x (len=%zu)", 215 hdr->tag, ext_len); 216 return -1; 217 } 218 } else 219 hdr->tag = hdr->identifier & 0x1f; 220 221 if (pos >= end) { 222 wpa_printf(MSG_DEBUG, "ASN.1: No room for Length"); 223 return -1; 224 } 225 tmp = *pos++; 226 if (tmp & 0x80) { 227 if (tmp == 0xff) { 228 wpa_printf(MSG_DEBUG, "ASN.1: Reserved length " 229 "value 0xff used"); 230 return -1; 231 } 232 tmp &= 0x7f; /* number of subsequent octets */ 233 hdr->length = 0; 234 if (tmp == 0 || pos == end || *pos == 0) { 235 wpa_printf(MSG_DEBUG, 236 "ASN.1: Definite long form of the length does not start with a nonzero value"); 237 return -1; 238 } 239 if (tmp > 4) { 240 wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); 241 return -1; 242 } 243 while (tmp--) { 244 if (pos >= end) { 245 wpa_printf(MSG_DEBUG, "ASN.1: Length " 246 "underflow"); 247 return -1; 248 } 249 hdr->length = (hdr->length << 8) | *pos++; 250 } 251 if (hdr->length < 128) { 252 wpa_printf(MSG_DEBUG, 253 "ASN.1: Definite long form of the length used with too short length"); 254 return -1; 255 } 256 } else { 257 /* Short form - length 0..127 in one octet */ 258 hdr->length = tmp; 259 } 260 261 if (end < pos || hdr->length > (unsigned int) (end - pos)) { 262 wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); 263 return -1; 264 } 265 266 hdr->payload = pos; 267 268 if (!asn1_valid_der(hdr)) { 269 asn1_print_hdr(hdr, "ASN.1: Invalid DER encoding: "); 270 return -1; 271 } 272 return 0; 273 } 274 275 276 void asn1_print_hdr(const struct asn1_hdr *hdr, const char *title) 277 { 278 wpa_printf(MSG_DEBUG, "%sclass %d constructed %d tag 0x%x", 279 title, hdr->class, hdr->constructed, hdr->tag); 280 } 281 282 283 void asn1_unexpected(const struct asn1_hdr *hdr, const char *title) 284 { 285 wpa_printf(MSG_DEBUG, "%s - found class %d constructed %d tag 0x%x", 286 title, hdr->class, hdr->constructed, hdr->tag); 287 } 288 289 290 int asn1_parse_oid(const u8 *buf, size_t len, struct asn1_oid *oid) 291 { 292 const u8 *pos, *end; 293 unsigned long val; 294 u8 tmp; 295 296 os_memset(oid, 0, sizeof(*oid)); 297 298 pos = buf; 299 end = buf + len; 300 301 while (pos < end) { 302 val = 0; 303 304 do { 305 if (pos >= end) 306 return -1; 307 tmp = *pos++; 308 val = (val << 7) | (tmp & 0x7f); 309 } while (tmp & 0x80); 310 311 if (oid->len >= ASN1_MAX_OID_LEN) { 312 wpa_printf(MSG_DEBUG, "ASN.1: Too long OID value"); 313 return -1; 314 } 315 if (oid->len == 0) { 316 /* 317 * The first octet encodes the first two object 318 * identifier components in (X*40) + Y formula. 319 * X = 0..2. 320 */ 321 oid->oid[0] = val / 40; 322 if (oid->oid[0] > 2) 323 oid->oid[0] = 2; 324 oid->oid[1] = val - oid->oid[0] * 40; 325 oid->len = 2; 326 } else 327 oid->oid[oid->len++] = val; 328 } 329 330 return 0; 331 } 332 333 334 int asn1_get_oid(const u8 *buf, size_t len, struct asn1_oid *oid, 335 const u8 **next) 336 { 337 struct asn1_hdr hdr; 338 339 if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 || 340 !asn1_is_oid(&hdr)) { 341 asn1_unexpected(&hdr, "ASN.1: Expected OID"); 342 return -1; 343 } 344 345 *next = hdr.payload + hdr.length; 346 347 return asn1_parse_oid(hdr.payload, hdr.length, oid); 348 } 349 350 351 void asn1_oid_to_str(const struct asn1_oid *oid, char *buf, size_t len) 352 { 353 char *pos = buf; 354 size_t i; 355 int ret; 356 357 if (len == 0) 358 return; 359 360 buf[0] = '\0'; 361 362 for (i = 0; i < oid->len; i++) { 363 ret = os_snprintf(pos, buf + len - pos, 364 "%s%lu", 365 i == 0 ? "" : ".", oid->oid[i]); 366 if (os_snprintf_error(buf + len - pos, ret)) 367 break; 368 pos += ret; 369 } 370 buf[len - 1] = '\0'; 371 } 372 373 374 static u8 rotate_bits(u8 octet) 375 { 376 int i; 377 u8 res; 378 379 res = 0; 380 for (i = 0; i < 8; i++) { 381 res <<= 1; 382 if (octet & 1) 383 res |= 1; 384 octet >>= 1; 385 } 386 387 return res; 388 } 389 390 391 unsigned long asn1_bit_string_to_long(const u8 *buf, size_t len) 392 { 393 unsigned long val = 0; 394 const u8 *pos = buf; 395 396 /* BER requires that unused bits are zero, so we can ignore the number 397 * of unused bits */ 398 pos++; 399 400 if (len >= 2) 401 val |= rotate_bits(*pos++); 402 if (len >= 3) 403 val |= ((unsigned long) rotate_bits(*pos++)) << 8; 404 if (len >= 4) 405 val |= ((unsigned long) rotate_bits(*pos++)) << 16; 406 if (len >= 5) 407 val |= ((unsigned long) rotate_bits(*pos++)) << 24; 408 if (len >= 6) 409 wpa_printf(MSG_DEBUG, "X509: %s - some bits ignored " 410 "(BIT STRING length %lu)", 411 __func__, (unsigned long) len); 412 413 return val; 414 } 415 416 417 int asn1_oid_equal(const struct asn1_oid *a, const struct asn1_oid *b) 418 { 419 size_t i; 420 421 if (a->len != b->len) 422 return 0; 423 424 for (i = 0; i < a->len; i++) { 425 if (a->oid[i] != b->oid[i]) 426 return 0; 427 } 428 429 return 1; 430 } 431 432 433 int asn1_get_integer(const u8 *buf, size_t len, int *integer, const u8 **next) 434 { 435 struct asn1_hdr hdr; 436 size_t left; 437 const u8 *pos; 438 int value; 439 440 if (asn1_get_next(buf, len, &hdr) < 0 || hdr.length == 0 || 441 !asn1_is_integer(&hdr)) { 442 asn1_unexpected(&hdr, "ASN.1: Expected INTEGER"); 443 return -1; 444 } 445 446 *next = hdr.payload + hdr.length; 447 pos = hdr.payload; 448 left = hdr.length; 449 if (left > sizeof(value)) { 450 wpa_printf(MSG_DEBUG, "ASN.1: Too large INTEGER (len %u)", 451 hdr.length); 452 return -1; 453 } 454 value = 0; 455 while (left) { 456 value <<= 8; 457 value |= *pos++; 458 left--; 459 } 460 461 *integer = value; 462 return 0; 463 } 464 465 466 int asn1_get_sequence(const u8 *buf, size_t len, struct asn1_hdr *hdr, 467 const u8 **next) 468 { 469 if (asn1_get_next(buf, len, hdr) < 0 || !asn1_is_sequence(hdr)) { 470 asn1_unexpected(hdr, "ASN.1: Expected SEQUENCE"); 471 return -1; 472 } 473 474 if (next) 475 *next = hdr->payload + hdr->length; 476 return 0; 477 } 478 479 480 int asn1_get_alg_id(const u8 *buf, size_t len, struct asn1_oid *oid, 481 const u8 **params, size_t *params_len, const u8 **next) 482 { 483 const u8 *pos = buf, *end = buf + len; 484 struct asn1_hdr hdr; 485 486 /* 487 * AlgorithmIdentifier ::= SEQUENCE { 488 * algorithm OBJECT IDENTIFIER, 489 * parameters ANY DEFINED BY algorithm OPTIONAL} 490 */ 491 if (asn1_get_sequence(pos, end - pos, &hdr, next) < 0 || 492 asn1_get_oid(hdr.payload, hdr.length, oid, &pos) < 0) 493 return -1; 494 495 if (params && params_len) { 496 *params = pos; 497 *params_len = hdr.payload + hdr.length - pos; 498 } 499 500 return 0; 501 } 502 503 504 void asn1_put_integer(struct wpabuf *buf, int val) 505 { 506 u8 bin[4]; 507 int zeros; 508 509 WPA_PUT_BE32(bin, val); 510 zeros = 0; 511 while (zeros < 3 && bin[zeros] == 0) 512 zeros++; 513 wpabuf_put_u8(buf, ASN1_TAG_INTEGER); 514 wpabuf_put_u8(buf, 4 - zeros); 515 wpabuf_put_data(buf, &bin[zeros], 4 - zeros); 516 } 517 518 519 static void asn1_put_len(struct wpabuf *buf, size_t len) 520 { 521 if (len <= 0x7f) { 522 wpabuf_put_u8(buf, len); 523 } else if (len <= 0xff) { 524 wpabuf_put_u8(buf, 0x80 | 1); 525 wpabuf_put_u8(buf, len); 526 } else if (len <= 0xffff) { 527 wpabuf_put_u8(buf, 0x80 | 2); 528 wpabuf_put_be16(buf, len); 529 } else if (len <= 0xffffff) { 530 wpabuf_put_u8(buf, 0x80 | 3); 531 wpabuf_put_be24(buf, len); 532 } else { 533 wpabuf_put_u8(buf, 0x80 | 4); 534 wpabuf_put_be32(buf, len); 535 } 536 } 537 538 539 void asn1_put_octet_string(struct wpabuf *buf, const struct wpabuf *val) 540 { 541 wpabuf_put_u8(buf, ASN1_TAG_OCTETSTRING); 542 asn1_put_len(buf, wpabuf_len(val)); 543 wpabuf_put_buf(buf, val); 544 } 545 546 547 void asn1_put_oid(struct wpabuf *buf, const struct asn1_oid *oid) 548 { 549 u8 *len; 550 size_t i; 551 552 if (oid->len < 2) 553 return; 554 wpabuf_put_u8(buf, ASN1_TAG_OID); 555 len = wpabuf_put(buf, 1); 556 wpabuf_put_u8(buf, 40 * oid->oid[0] + oid->oid[1]); 557 for (i = 2; i < oid->len; i++) { 558 unsigned long val = oid->oid[i]; 559 u8 bytes[8]; 560 int idx = 0; 561 562 while (val) { 563 bytes[idx] = (idx ? 0x80 : 0x00) | (val & 0x7f); 564 idx++; 565 val >>= 7; 566 } 567 if (idx == 0) { 568 bytes[idx] = 0; 569 idx = 1; 570 } 571 while (idx > 0) { 572 idx--; 573 wpabuf_put_u8(buf, bytes[idx]); 574 } 575 } 576 *len = (u8 *) wpabuf_put(buf, 0) - len - 1; 577 } 578 579 580 void asn1_put_hdr(struct wpabuf *buf, u8 class, int constructed, u8 tag, 581 size_t len) 582 { 583 wpabuf_put_u8(buf, class << 6 | (constructed ? 0x20 : 0x00) | tag); 584 asn1_put_len(buf, len); 585 } 586 587 588 void asn1_put_sequence(struct wpabuf *buf, const struct wpabuf *payload) 589 { 590 asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 1, ASN1_TAG_SEQUENCE, 591 wpabuf_len(payload)); 592 wpabuf_put_buf(buf, payload); 593 } 594 595 596 void asn1_put_set(struct wpabuf *buf, const struct wpabuf *payload) 597 { 598 asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 1, ASN1_TAG_SET, 599 wpabuf_len(payload)); 600 wpabuf_put_buf(buf, payload); 601 } 602 603 604 void asn1_put_utf8string(struct wpabuf *buf, const char *val) 605 { 606 asn1_put_hdr(buf, ASN1_CLASS_UNIVERSAL, 0, ASN1_TAG_UTF8STRING, 607 os_strlen(val)); 608 wpabuf_put_str(buf, val); 609 } 610 611 612 struct wpabuf * asn1_build_alg_id(const struct asn1_oid *oid, 613 const struct wpabuf *params) 614 { 615 struct wpabuf *buf; 616 size_t len; 617 618 /* 619 * AlgorithmIdentifier ::= SEQUENCE { 620 * algorithm OBJECT IDENTIFIER, 621 * parameters ANY DEFINED BY algorithm OPTIONAL} 622 */ 623 624 len = 100; 625 if (params) 626 len += wpabuf_len(params); 627 buf = wpabuf_alloc(len); 628 if (!buf) 629 return NULL; 630 asn1_put_oid(buf, oid); 631 if (params) 632 wpabuf_put_buf(buf, params); 633 return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); 634 } 635 636 637 struct wpabuf * asn1_encaps(struct wpabuf *buf, u8 class, u8 tag) 638 { 639 struct wpabuf *res; 640 641 if (!buf) 642 return NULL; 643 res = wpabuf_alloc(10 + wpabuf_len(buf)); 644 if (res) { 645 asn1_put_hdr(res, class, 1, tag, wpabuf_len(buf)); 646 wpabuf_put_buf(res, buf); 647 } 648 wpabuf_clear_free(buf); 649 return res; 650 } 651