1 /* $OpenBSD: asn1basic.c,v 1.7 2022/06/25 13:57:17 jsing Exp $ */ 2 /* 3 * Copyright (c) 2017, 2021 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and 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 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <openssl/asn1.h> 19 20 #include <err.h> 21 #include <stdio.h> 22 #include <string.h> 23 24 #include "asn1_locl.h" 25 26 static void 27 hexdump(const unsigned char *buf, size_t len) 28 { 29 size_t i; 30 31 for (i = 1; i <= len; i++) 32 fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n"); 33 34 fprintf(stderr, "\n"); 35 } 36 37 static int 38 asn1_compare_bytes(const char *label, const unsigned char *d1, int len1, 39 const unsigned char *d2, int len2) 40 { 41 if (len1 != len2) { 42 fprintf(stderr, "FAIL: %s - byte lengths differ " 43 "(%i != %i)\n", label, len1, len2); 44 fprintf(stderr, "Got:\n"); 45 hexdump(d1, len1); 46 fprintf(stderr, "Want:\n"); 47 hexdump(d2, len2); 48 return 0; 49 } 50 if (memcmp(d1, d2, len1) != 0) { 51 fprintf(stderr, "FAIL: %s - bytes differ\n", label); 52 fprintf(stderr, "Got:\n"); 53 hexdump(d1, len1); 54 fprintf(stderr, "Want:\n"); 55 hexdump(d2, len2); 56 return 0; 57 } 58 return 1; 59 } 60 61 const uint8_t asn1_bit_string_primitive[] = { 62 0x03, 0x07, 63 0x04, 0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0, 64 }; 65 66 static int 67 asn1_bit_string_test(void) 68 { 69 uint8_t bs[] = {0x0a, 0x3b, 0x5f, 0x29, 0x1c, 0xd0}; 70 ASN1_BIT_STRING *abs; 71 uint8_t *p = NULL, *pp; 72 const uint8_t *q; 73 int bit, i, len; 74 int failed = 1; 75 76 if ((abs = ASN1_BIT_STRING_new()) == NULL) { 77 fprintf(stderr, "FAIL: ASN1_BIT_STRING_new() == NULL\n"); 78 goto failed; 79 } 80 if (!ASN1_BIT_STRING_set(abs, bs, sizeof(bs))) { 81 fprintf(stderr, "FAIL: failed to set bit string\n"); 82 goto failed; 83 } 84 85 if ((len = i2d_ASN1_BIT_STRING(abs, NULL)) < 0) { 86 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING with NULL\n"); 87 goto failed; 88 } 89 if ((p = malloc(len)) == NULL) 90 errx(1, "malloc"); 91 memset(p, 0xbd, len); 92 pp = p; 93 if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { 94 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 95 goto failed; 96 } 97 98 if (!asn1_compare_bytes("BIT_STRING", p, len, asn1_bit_string_primitive, 99 sizeof(asn1_bit_string_primitive))) 100 goto failed; 101 102 /* Test primitive decoding. */ 103 q = p; 104 if (d2i_ASN1_BIT_STRING(&abs, &q, len) == NULL) { 105 fprintf(stderr, "FAIL: d2i_ASN1_BIT_STRING primitive\n"); 106 goto failed; 107 } 108 if (!asn1_compare_bytes("BIT_STRING primitive data", abs->data, abs->length, 109 bs, sizeof(bs))) 110 goto failed; 111 112 /* Test ASN1_BIT_STRING_get_bit(). */ 113 for (i = 0; i < ((int)sizeof(bs) * 8); i++) { 114 bit = (bs[i / 8] >> (7 - i % 8)) & 1; 115 116 if (ASN1_BIT_STRING_get_bit(abs, i) != bit) { 117 fprintf(stderr, "FAIL: ASN1_BIT_STRING_get_bit(_, %d) " 118 "= %d, want %d\n", i, 119 ASN1_BIT_STRING_get_bit(abs, i), bit); 120 goto failed; 121 } 122 } 123 124 /* Test ASN1_BIT_STRING_set_bit(). */ 125 for (i = 0; i < ((int)sizeof(bs) * 8); i++) { 126 if (!ASN1_BIT_STRING_set_bit(abs, i, 1)) { 127 fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit 1\n"); 128 goto failed; 129 } 130 } 131 for (i = ((int)sizeof(bs) * 8) - 1; i >= 0; i--) { 132 bit = (bs[i / 8] >> (7 - i % 8)) & 1; 133 if (bit == 1) 134 continue; 135 if (!ASN1_BIT_STRING_set_bit(abs, i, 0)) { 136 fprintf(stderr, "FAIL: ASN1_BIT_STRING_set_bit\n"); 137 goto failed; 138 } 139 } 140 141 if ((i2d_ASN1_BIT_STRING(abs, NULL)) != len) { 142 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 143 goto failed; 144 } 145 146 memset(p, 0xbd, len); 147 pp = p; 148 if ((i2d_ASN1_BIT_STRING(abs, &pp)) != len) { 149 fprintf(stderr, "FAIL: i2d_ASN1_BIT_STRING\n"); 150 goto failed; 151 } 152 153 if (!asn1_compare_bytes("BIT_STRING set", p, len, asn1_bit_string_primitive, 154 sizeof(asn1_bit_string_primitive))) 155 goto failed; 156 157 failed = 0; 158 159 failed: 160 ASN1_BIT_STRING_free(abs); 161 free(p); 162 163 return failed; 164 } 165 166 const uint8_t asn1_boolean_false[] = { 167 0x01, 0x01, 0x00, 168 }; 169 const uint8_t asn1_boolean_true[] = { 170 0x01, 0x01, 0x01, 171 }; 172 173 static int 174 asn1_boolean_test(void) 175 { 176 uint8_t *p = NULL, *pp; 177 const uint8_t *q; 178 int len; 179 int failed = 1; 180 181 if ((len = i2d_ASN1_BOOLEAN(0, NULL)) < 0) { 182 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false with NULL\n"); 183 goto failed; 184 } 185 if ((p = malloc(len)) == NULL) 186 errx(1, "calloc"); 187 memset(p, 0xbd, len); 188 pp = p; 189 if ((i2d_ASN1_BOOLEAN(0, &pp)) != len) { 190 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN false\n"); 191 goto failed; 192 } 193 194 if (!asn1_compare_bytes("BOOLEAN false", p, len, asn1_boolean_false, 195 sizeof(asn1_boolean_false))) 196 goto failed; 197 198 q = p; 199 if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 0) { 200 fprintf(stderr, "FAIL: BOOLEAN false did not decode to 0\n"); 201 goto failed; 202 } 203 204 free(p); 205 p = NULL; 206 207 if ((len = i2d_ASN1_BOOLEAN(1, NULL)) < 0) { 208 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true with NULL\n"); 209 goto failed; 210 } 211 if ((p = calloc(1, len)) == NULL) 212 errx(1, "calloc"); 213 pp = p; 214 if ((i2d_ASN1_BOOLEAN(1, &pp)) != len) { 215 fprintf(stderr, "FAIL: i2d_ASN1_BOOLEAN true\n"); 216 goto failed; 217 } 218 219 if (!asn1_compare_bytes("BOOLEAN true", p, len, asn1_boolean_true, 220 sizeof(asn1_boolean_true))) 221 goto failed; 222 223 q = p; 224 if (d2i_ASN1_BOOLEAN(NULL, &q, len) != 1) { 225 fprintf(stderr, "FAIL: BOOLEAN true did not decode to 1\n"); 226 goto failed; 227 } 228 229 failed = 0; 230 231 failed: 232 free(p); 233 234 return failed; 235 } 236 237 struct asn1_integer_test { 238 long value; 239 uint8_t content[64]; 240 size_t content_len; 241 int content_neg; 242 uint8_t der[64]; 243 size_t der_len; 244 int want_error; 245 }; 246 247 struct asn1_integer_test asn1_integer_tests[] = { 248 { 249 .value = 0, 250 .content = {0x00}, 251 .content_len = 1, 252 .der = {0x02, 0x01, 0x00}, 253 .der_len = 3, 254 }, 255 { 256 .value = 1, 257 .content = {0x01}, 258 .content_len = 1, 259 .der = {0x02, 0x01, 0x01}, 260 .der_len = 3, 261 }, 262 { 263 .value = -1, 264 .content = {0x01}, 265 .content_len = 1, 266 .content_neg = 1, 267 .der = {0x02, 0x01, 0xff}, 268 .der_len = 3, 269 }, 270 { 271 .value = 127, 272 .content = {0x7f}, 273 .content_len = 1, 274 .der = {0x02, 0x01, 0x7f}, 275 .der_len = 3, 276 }, 277 { 278 .value = -127, 279 .content = {0x7f}, 280 .content_len = 1, 281 .content_neg = 1, 282 .der = {0x02, 0x01, 0x81}, 283 .der_len = 3, 284 }, 285 { 286 .value = 128, 287 .content = {0x80}, 288 .content_len = 1, 289 .der = {0x02, 0x02, 0x00, 0x80}, 290 .der_len = 4, 291 }, 292 { 293 .value = -128, 294 .content = {0x80}, 295 .content_len = 1, 296 .content_neg = 1, 297 .der = {0x02, 0x01, 0x80}, 298 .der_len = 3, 299 }, 300 { 301 /* 2^64 */ 302 .content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 303 .content_len = 9, 304 .der = {0x02, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 305 .der_len = 11, 306 }, 307 { 308 /* -2^64 */ 309 .content = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 310 .content_len = 9, 311 .content_neg = 1, 312 .der = {0x02, 0x09, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 313 .der_len = 11, 314 }, 315 { 316 /* Invalid length. */ 317 .der = {0x02, 0x00}, 318 .der_len = 2, 319 .want_error = 1, 320 }, 321 { 322 /* Invalid padding. */ 323 .der = {0x02, 0x09, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 324 .der_len = 11, 325 .want_error = 1, 326 }, 327 { 328 /* Invalid padding. */ 329 .der = {0x02, 0x09, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 330 .der_len = 11, 331 .want_error = 1, 332 }, 333 }; 334 335 #define N_ASN1_INTEGER_TESTS \ 336 (sizeof(asn1_integer_tests) / sizeof(*asn1_integer_tests)) 337 338 static int 339 asn1_integer_set_test(struct asn1_integer_test *ait) 340 { 341 ASN1_INTEGER *aint = NULL; 342 uint8_t *p = NULL, *pp; 343 int len; 344 int failed = 1; 345 346 if ((aint = ASN1_INTEGER_new()) == NULL) { 347 fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); 348 goto failed; 349 } 350 if (!ASN1_INTEGER_set(aint, ait->value)) { 351 fprintf(stderr, "FAIL: ASN1_INTEGER_(%ld) failed\n", 352 ait->value); 353 goto failed; 354 } 355 if (ait->value != 0 && 356 !asn1_compare_bytes("INTEGER set", aint->data, aint->length, 357 ait->content, ait->content_len)) 358 goto failed; 359 if (ait->content_neg && aint->type != V_ASN1_NEG_INTEGER) { 360 fprintf(stderr, "FAIL: Not V_ASN1_NEG_INTEGER\n"); 361 goto failed; 362 } 363 if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) { 364 fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); 365 goto failed; 366 } 367 if ((p = malloc(len)) == NULL) 368 errx(1, "malloc"); 369 memset(p, 0xbd, len); 370 pp = p; 371 if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) { 372 fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); 373 goto failed; 374 } 375 if (!asn1_compare_bytes("INTEGER set", p, len, ait->der, 376 ait->der_len)) 377 goto failed; 378 379 failed = 0; 380 381 failed: 382 ASN1_INTEGER_free(aint); 383 free(p); 384 385 return failed; 386 } 387 388 static int 389 asn1_integer_content_test(struct asn1_integer_test *ait) 390 { 391 ASN1_INTEGER *aint = NULL; 392 uint8_t *p = NULL, *pp; 393 int len; 394 int failed = 1; 395 396 if ((aint = ASN1_INTEGER_new()) == NULL) { 397 fprintf(stderr, "FAIL: ASN1_INTEGER_new() == NULL\n"); 398 goto failed; 399 } 400 if ((aint->data = malloc(ait->content_len)) == NULL) 401 errx(1, "malloc"); 402 memcpy(aint->data, ait->content, ait->content_len); 403 aint->length = ait->content_len; 404 if (ait->content_neg) 405 aint->type = V_ASN1_NEG_INTEGER; 406 407 if ((len = i2d_ASN1_INTEGER(aint, NULL)) < 0) { 408 fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); 409 goto failed; 410 } 411 if ((p = malloc(len)) == NULL) 412 errx(1, "malloc"); 413 memset(p, 0xbd, len); 414 pp = p; 415 if ((len = i2d_ASN1_INTEGER(aint, &pp)) < 0) { 416 fprintf(stderr, "FAIL: i2d_ASN1_INTEGER() failed\n"); 417 goto failed; 418 } 419 if (!asn1_compare_bytes("INTEGER content", p, len, ait->der, 420 ait->der_len)) 421 goto failed; 422 423 failed = 0; 424 425 failed: 426 ASN1_INTEGER_free(aint); 427 free(p); 428 429 return failed; 430 } 431 432 static int 433 asn1_integer_decode_test(struct asn1_integer_test *ait) 434 { 435 ASN1_INTEGER *aint = NULL; 436 const uint8_t *q; 437 int failed = 1; 438 439 q = ait->der; 440 if (d2i_ASN1_INTEGER(&aint, &q, ait->der_len) != NULL) { 441 if (ait->want_error != 0) { 442 fprintf(stderr, "FAIL: INTEGER decoded when it should " 443 "have failed\n"); 444 goto failed; 445 } 446 if (!asn1_compare_bytes("INTEGER content", aint->data, 447 aint->length, ait->content, ait->content_len)) 448 goto failed; 449 } else if (ait->want_error == 0) { 450 fprintf(stderr, "FAIL: INTEGER failed to decode\n"); 451 goto failed; 452 } 453 454 failed = 0; 455 456 failed: 457 ASN1_INTEGER_free(aint); 458 459 return failed; 460 } 461 462 static int 463 asn1_integer_cmp_test(void) 464 { 465 ASN1_INTEGER *a = NULL, *b = NULL; 466 int failed = 1; 467 468 if ((a = ASN1_INTEGER_new()) == NULL) 469 goto failed; 470 if ((b = ASN1_INTEGER_new()) == NULL) 471 goto failed; 472 473 if (ASN1_INTEGER_cmp(a, b) != 0) { 474 fprintf(stderr, "FAIL: INTEGER 0 == 0"); 475 goto failed; 476 } 477 478 if (!ASN1_INTEGER_set(b, 1)) { 479 fprintf(stderr, "FAIL: failed to set INTEGER"); 480 goto failed; 481 } 482 if (ASN1_INTEGER_cmp(a, b) >= 0) { 483 fprintf(stderr, "FAIL: INTEGER 0 < 1"); 484 goto failed; 485 } 486 if (ASN1_INTEGER_cmp(b, a) <= 0) { 487 fprintf(stderr, "FAIL: INTEGER 1 > 0"); 488 goto failed; 489 } 490 491 if (!ASN1_INTEGER_set(b, -1)) { 492 fprintf(stderr, "FAIL: failed to set INTEGER"); 493 goto failed; 494 } 495 if (ASN1_INTEGER_cmp(a, b) <= 0) { 496 fprintf(stderr, "FAIL: INTEGER 0 > -1"); 497 goto failed; 498 } 499 if (ASN1_INTEGER_cmp(b, a) >= 0) { 500 fprintf(stderr, "FAIL: INTEGER -1 < 0"); 501 goto failed; 502 } 503 504 if (!ASN1_INTEGER_set(a, 1)) { 505 fprintf(stderr, "FAIL: failed to set INTEGER"); 506 goto failed; 507 } 508 if (ASN1_INTEGER_cmp(a, b) <= 0) { 509 fprintf(stderr, "FAIL: INTEGER 1 > -1"); 510 goto failed; 511 } 512 if (ASN1_INTEGER_cmp(b, a) >= 0) { 513 fprintf(stderr, "FAIL: INTEGER -1 < 1"); 514 goto failed; 515 } 516 517 if (!ASN1_INTEGER_set(b, 1)) { 518 fprintf(stderr, "FAIL: failed to set INTEGER"); 519 goto failed; 520 } 521 if (ASN1_INTEGER_cmp(a, b) != 0) { 522 fprintf(stderr, "FAIL: INTEGER 1 == 1"); 523 goto failed; 524 } 525 526 failed = 0; 527 528 failed: 529 ASN1_INTEGER_free(a); 530 ASN1_INTEGER_free(b); 531 532 return failed; 533 } 534 535 static int 536 asn1_integer_test(void) 537 { 538 struct asn1_integer_test *ait; 539 int failed = 0; 540 size_t i; 541 542 for (i = 0; i < N_ASN1_INTEGER_TESTS; i++) { 543 ait = &asn1_integer_tests[i]; 544 if (ait->content_len > 0 && ait->content_len <= 4) 545 failed |= asn1_integer_set_test(ait); 546 if (ait->content_len > 0) 547 failed |= asn1_integer_content_test(ait); 548 failed |= asn1_integer_decode_test(ait); 549 } 550 551 failed |= asn1_integer_cmp_test(); 552 553 return failed; 554 } 555 556 int 557 main(int argc, char **argv) 558 { 559 int failed = 0; 560 561 failed |= asn1_bit_string_test(); 562 failed |= asn1_boolean_test(); 563 failed |= asn1_integer_test(); 564 565 return (failed); 566 } 567