1 /* $OpenBSD: x509_extensions_test.c,v 1.2 2024/05/28 15:42:09 tb Exp $ */ 2 3 /* 4 * Copyright (c) 2024 Theo Buehler <tb@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <err.h> 20 #include <stdio.h> 21 22 #include <openssl/asn1.h> 23 #include <openssl/err.h> 24 #include <openssl/x509.h> 25 #include <openssl/x509v3.h> 26 27 #define ASN1_BOOLEAN_TRUE 0xff 28 #define ASN1_BOOLEAN_FALSE 0x00 29 30 static BASIC_CONSTRAINTS * 31 create_basic_constraints(int ca) 32 { 33 BASIC_CONSTRAINTS *bc; 34 35 if ((bc = BASIC_CONSTRAINTS_new()) == NULL) 36 errx(1, "BASIC_CONSTRAINTS_new"); 37 38 bc->ca = ca ? ASN1_BOOLEAN_TRUE : ASN1_BOOLEAN_FALSE; 39 40 return bc; 41 } 42 43 static int 44 test_x509v3_add1_i2d_empty_stack(STACK_OF(X509_EXTENSION) **extensions) 45 { 46 unsigned long error; 47 int op, got; 48 int nid = NID_basic_constraints; 49 int failed = 1; 50 51 if (X509v3_get_ext_count(*extensions) != 0) { 52 fprintf(stderr, "%s: FAIL: need empty stack\n", __func__); 53 goto err; 54 } 55 56 ERR_clear_error(); 57 58 op = X509V3_ADD_REPLACE_EXISTING; 59 60 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { 61 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 62 "want %d, got %d.\n", __func__, 0, got); 63 goto err; 64 } 65 66 error = ERR_get_error(); 67 if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_NOT_FOUND) { 68 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 69 "pushed %d for empty stack, want %d.\n", __func__, 70 ERR_GET_REASON(error), X509V3_R_EXTENSION_NOT_FOUND); 71 goto err; 72 } 73 if ((error = ERR_get_error()) != 0) { 74 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 75 "expected exactly one error.\n", __func__); 76 goto err; 77 } 78 79 op = X509V3_ADD_REPLACE_EXISTING | X509V3_ADD_SILENT; 80 81 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { 82 fprintf(stderr, "%s: FAIL: silent X509V3_ADD_REPLACE_EXISTING " 83 "want %d, got %d.\n", __func__, 0, got); 84 goto err; 85 } 86 if ((error = ERR_get_error()) != 0) { 87 fprintf(stderr, "%s: FAIL: silent X509V3_ADD_REPLACE_EXISTING " 88 "added error %d, want %d.\n", __func__, 89 ERR_GET_REASON(error), 0); 90 goto err; 91 } 92 93 op = X509V3_ADD_DELETE; 94 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { 95 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 96 "want %d, got %d.\n", __func__, 0, got); 97 goto err; 98 } 99 100 error = ERR_get_error(); 101 if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_NOT_FOUND) { 102 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 103 "pushed %d for empty stack, want %d.\n", __func__, 104 ERR_GET_REASON(error), X509V3_R_EXTENSION_NOT_FOUND); 105 goto err; 106 } 107 108 if ((error = ERR_get_error()) != 0) { 109 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 110 "expected exactly one error.\n", __func__); 111 goto err; 112 } 113 114 failed = 0; 115 116 err: 117 118 return failed; 119 } 120 121 static int 122 test_x509v3_add1_i2d_single_nid(STACK_OF(X509_EXTENSION) **extensions) 123 { 124 BASIC_CONSTRAINTS *bc = NULL; 125 unsigned long error; 126 int crit, got, nid, op; 127 int failed = 1; 128 129 if (X509v3_get_ext_count(*extensions) != 0) { 130 fprintf(stderr, "%s: FAIL: need an empty stack.\n", __func__); 131 goto err; 132 } 133 134 /* 135 * Add basic ca constraints. 136 */ 137 138 nid = NID_basic_constraints; 139 bc = create_basic_constraints(1); 140 op = X509V3_ADD_DEFAULT; 141 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { 142 fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT failed to add " 143 "basic constraints to empty stack: want %d, got %d.\n", 144 __func__, 1, got); 145 goto err; 146 } 147 BASIC_CONSTRAINTS_free(bc); 148 bc = NULL; 149 150 if ((got = X509v3_get_ext_count(*extensions)) != 1) { 151 fprintf(stderr, "%s: FAIL: expected 1 extension, have %d.\n", 152 __func__, got); 153 goto err; 154 } 155 156 /* 157 * Can't delete or replace non-existent extension. 158 */ 159 160 nid = NID_policy_constraints; 161 op = X509V3_ADD_DELETE; 162 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { 163 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE non-existent " 164 "want %d, got %d,\n", __func__, 0, got); 165 goto err; 166 } 167 nid = NID_policy_constraints; 168 op = X509V3_ADD_REPLACE_EXISTING; 169 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 0) { 170 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING non-existent " 171 "want %d, got %d.\n", __func__, 0, got); 172 goto err; 173 } 174 175 /* 176 * X509V3_ADD_DEFAULT refuses to add second basic constraints extension. 177 */ 178 179 ERR_clear_error(); 180 181 nid = NID_basic_constraints; 182 bc = create_basic_constraints(0); 183 op = X509V3_ADD_DEFAULT; 184 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 0) { 185 fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second constraints " 186 "want %d, got %d.\n", __func__, 0, got); 187 goto err; 188 } 189 BASIC_CONSTRAINTS_free(bc); 190 bc = NULL; 191 192 error = ERR_get_error(); 193 if (ERR_GET_REASON(error) != X509V3_R_EXTENSION_EXISTS) { 194 fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second constraints " 195 " pushed %d, want %d.\n", __func__, 196 ERR_GET_REASON(error), X509V3_R_EXTENSION_EXISTS); 197 goto err; 198 } 199 200 if ((got = X509v3_get_ext_count(*extensions)) != 1) { 201 fprintf(stderr, "%s: FAIL: X509V3_ADD_DEFAULT second contraints " 202 "expected 1 extension, have %d.\n", __func__, got); 203 goto err; 204 } 205 206 /* 207 * We can replace existing basic constraints using X509V3_ADD_REPLACE. 208 */ 209 210 nid = NID_basic_constraints; 211 bc = create_basic_constraints(0); 212 op = X509V3_ADD_REPLACE; 213 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { 214 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 215 "want %d, got %d.\n", __func__, 1, got); 216 goto err; 217 } 218 BASIC_CONSTRAINTS_free(bc); 219 bc = NULL; 220 221 if ((got = X509v3_get_ext_count(*extensions)) != 1) { 222 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 223 "expected 1 extension, have %d.\n", __func__, got); 224 goto err; 225 } 226 227 /* Check that the extension was actually replaced. */ 228 nid = NID_basic_constraints; 229 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { 230 if (crit != -1) 231 errx(1, "X509V3_get_d2i"); 232 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 233 "expected basic constraints\n", __func__); 234 goto err; 235 } 236 if (bc->ca != ASN1_BOOLEAN_FALSE) { 237 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 238 "expected cA = false in basic constraints\n", __func__); 239 goto err; 240 } 241 BASIC_CONSTRAINTS_free(bc); 242 bc = NULL; 243 244 /* 245 * X509V3_ADD_KEEP_EXISTING existing does what it is supposed to do 246 * if basic constraints are already present. 247 */ 248 249 nid = NID_basic_constraints; 250 bc = create_basic_constraints(1); 251 op = X509V3_ADD_KEEP_EXISTING; 252 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { 253 fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " 254 "want %d, got %d.\n", __func__, 1, got); 255 goto err; 256 } 257 BASIC_CONSTRAINTS_free(bc); 258 bc = NULL; 259 260 /* 261 * Check we still have non-ca basic constraints. 262 */ 263 264 nid = NID_basic_constraints; 265 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { 266 if (crit != -1) 267 errx(1, "X509V3_get_d2i"); 268 fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " 269 "expected basic constraints\n", __func__); 270 goto err; 271 } 272 if (bc->ca != ASN1_BOOLEAN_FALSE) { 273 fprintf(stderr, "%s: FAIL: X509V3_ADD_KEEP_EXISTING " 274 "expected non-ca basic constraints\n", __func__); 275 goto err; 276 } 277 BASIC_CONSTRAINTS_free(bc); 278 bc = NULL; 279 280 /* 281 * X509V3_ADD_REPLACE_EXISTING also works. 282 */ 283 284 nid = NID_basic_constraints; 285 bc = create_basic_constraints(1); 286 op = X509V3_ADD_REPLACE_EXISTING; 287 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { 288 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 289 "want %d, got %d.\n", __func__, 1, got); 290 goto err; 291 } 292 BASIC_CONSTRAINTS_free(bc); 293 bc = NULL; 294 295 /* 296 * Check we again have ca basic constraints. 297 */ 298 299 nid = NID_basic_constraints; 300 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, NULL)) == NULL) { 301 if (crit != -1) 302 errx(1, "X509V3_get_d2i"); 303 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 304 "expected basic constraints\n", __func__); 305 goto err; 306 } 307 if (bc->ca != ASN1_BOOLEAN_TRUE) { 308 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE_EXISTING " 309 "expected ca basic constraints\n", __func__); 310 goto err; 311 } 312 BASIC_CONSTRAINTS_free(bc); 313 bc = NULL; 314 315 /* 316 * And X509V3_ADD_DELETE now works. 317 */ 318 319 nid = NID_basic_constraints; 320 op = X509V3_ADD_DELETE; 321 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { 322 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 323 "want %d, got %d.\n", __func__, 0, got); 324 goto err; 325 } 326 327 if ((got = X509v3_get_ext_count(*extensions)) != 0) { 328 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 329 "expected 0 extensions, have %d.\n", __func__, got); 330 goto err; 331 } 332 333 /* 334 * X509V3_ADD_REPLACE adds the extension to empty stack as it should. 335 */ 336 337 nid = NID_basic_constraints; 338 bc = create_basic_constraints(0); 339 op = X509V3_ADD_REPLACE; 340 if ((got = X509V3_add1_i2d(extensions, nid, bc, 1, op)) != 1) { 341 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE on empty stack " 342 "want %d, got %d.\n", __func__, 1, got); 343 goto err; 344 } 345 BASIC_CONSTRAINTS_free(bc); 346 bc = NULL; 347 348 if ((got = X509v3_get_ext_count(*extensions)) != 1) { 349 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 350 "expected 1 extension, have %d.\n", __func__, got); 351 goto err; 352 } 353 354 /* 355 * And X509V3_ADD_DELETE works again. 356 */ 357 358 nid = NID_basic_constraints; 359 op = X509V3_ADD_DELETE; 360 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { 361 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE after add replace " 362 "want %d, got %d.\n", __func__, 0, got); 363 goto err; 364 } 365 366 if ((got = X509v3_get_ext_count(*extensions)) != 0) { 367 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 368 "expected 0 extensions, have %d.\n", __func__, got); 369 goto err; 370 } 371 372 failed = 0; 373 374 err: 375 BASIC_CONSTRAINTS_free(bc); 376 377 return failed; 378 } 379 380 static int 381 test_x509v3_add1_i2d_add_append(STACK_OF(X509_EXTENSION) **extensions) 382 { 383 BASIC_CONSTRAINTS *bc = NULL; 384 int crit, got, idx, nid, op; 385 int failed = 1; 386 387 if (X509v3_get_ext_count(*extensions) != 0) { 388 fprintf(stderr, "%s: FAIL: need empty stack.\n", __func__); 389 goto err; 390 } 391 392 /* 393 * Let the toolkit add two basic constraints extensions. 394 */ 395 396 nid = NID_basic_constraints; 397 bc = create_basic_constraints(1); 398 crit = 1; 399 op = X509V3_ADD_APPEND; 400 if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { 401 fprintf(stderr, "%s: FAIL: first X509V3_ADD_APPEND " 402 "want %d, got %d.\n", __func__, 0, got); 403 goto err; 404 } 405 BASIC_CONSTRAINTS_free(bc); 406 bc = NULL; 407 408 nid = NID_basic_constraints; 409 bc = create_basic_constraints(0); 410 crit = 1; 411 op = X509V3_ADD_APPEND; 412 if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { 413 fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " 414 "want %d, got %d.\n", __func__, 0, got); 415 goto err; 416 } 417 BASIC_CONSTRAINTS_free(bc); 418 bc = NULL; 419 420 if ((got = X509v3_get_ext_count(*extensions)) != 2) { 421 fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " 422 "expected 2 extensions, have %d.\n", __func__, got); 423 goto err; 424 } 425 426 /* 427 * Inspect the extensions on the stack. First we should get the one 428 * with the ca bit set and it should be critical. 429 */ 430 431 nid = NID_basic_constraints; 432 idx = -1; 433 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { 434 fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " 435 "expected basic constraints.\n", __func__); 436 goto err; 437 } 438 if (bc->ca != ASN1_BOOLEAN_TRUE) { 439 fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " 440 "expected ca basic constraints.\n", __func__); 441 goto err; 442 } 443 if (crit != 1) { 444 fprintf(stderr, "%s: FAIL: X509V3_ADD_APPEND " 445 "expected critical basic constraints.\n", __func__); 446 goto err; 447 } 448 BASIC_CONSTRAINTS_free(bc); 449 bc = NULL; 450 451 /* Redo the exercise and get the basic constraints with ca bit unset. */ 452 nid = NID_basic_constraints; 453 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { 454 fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " 455 "expected basic constraints.\n", __func__); 456 goto err; 457 } 458 if (bc->ca != ASN1_BOOLEAN_FALSE) { 459 fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " 460 "expected basic constraints to be non-ca.\n", __func__); 461 goto err; 462 } 463 if (crit != 1) { 464 fprintf(stderr, "%s: FAIL: second X509V3_ADD_APPEND " 465 "expected critical basic constraints.\n", __func__); 466 goto err; 467 } 468 BASIC_CONSTRAINTS_free(bc); 469 bc = NULL; 470 471 /* 472 * Now X509V3_ADD_REPLACE non-critical ca constraints. They should 473 * replace the critical ca constraints we added before. 474 */ 475 476 nid = NID_basic_constraints; 477 bc = create_basic_constraints(1); 478 crit = 0; 479 op = X509V3_ADD_REPLACE; 480 if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != 1) { 481 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 482 "want %d, got %d\n", __func__, 1, got); 483 goto err; 484 } 485 BASIC_CONSTRAINTS_free(bc); 486 bc = NULL; 487 488 /* 489 * If we get basic constraints now, we get the non-critical one with the 490 * ca bit set. 491 */ 492 493 nid = NID_basic_constraints; 494 idx = -1; 495 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { 496 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 497 "expected basic constraints.\n", __func__); 498 goto err; 499 } 500 if (bc->ca != ASN1_BOOLEAN_TRUE) { 501 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 502 "expected ca basic constraints.\n", __func__); 503 goto err; 504 } 505 if (crit != 0) { 506 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 507 "expected non-critical basic constraints.\n", __func__); 508 goto err; 509 } 510 BASIC_CONSTRAINTS_free(bc); 511 bc = NULL; 512 513 if ((got = X509v3_get_ext_count(*extensions)) != 2) { 514 fprintf(stderr, "%s: FAIL: X509V3_ADD_REPLACE " 515 "expected 2 extensions, got %d.\n", __func__, got); 516 goto err; 517 } 518 519 nid = NID_basic_constraints; 520 op = X509V3_ADD_DELETE; 521 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { 522 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 523 "want %d, got %d\n", __func__, 1, got); 524 goto err; 525 } 526 527 if ((got = X509v3_get_ext_count(*extensions)) != 1) { 528 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 529 "expected 1 extension, got %d.\n", __func__, got); 530 goto err; 531 } 532 533 /* The last deletion will have left the critical non-ca constraints. */ 534 nid = NID_basic_constraints; 535 idx = -1; 536 if ((bc = X509V3_get_d2i(*extensions, nid, &crit, &idx)) == NULL) { 537 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 538 "expected basic constraints.\n", __func__); 539 goto err; 540 } 541 if (bc->ca != ASN1_BOOLEAN_FALSE) { 542 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 543 "expected ca basic constraints.\n", __func__); 544 goto err; 545 } 546 if (crit != 1) { 547 fprintf(stderr, "%s: FAIL: X509V3_ADD_DELETE " 548 "expected critical basic constraints.\n", __func__); 549 goto err; 550 } 551 BASIC_CONSTRAINTS_free(bc); 552 bc = NULL; 553 554 /* Now delete the last extension. */ 555 nid = NID_basic_constraints; 556 op = X509V3_ADD_DELETE; 557 if ((got = X509V3_add1_i2d(extensions, nid, NULL, 0, op)) != 1) { 558 fprintf(stderr, "%s: FAIL: second X509V3_ADD_DELETE " 559 "want %d, got %d\n", __func__, 1, got); 560 goto err; 561 } 562 563 if ((got = X509v3_get_ext_count(*extensions)) != 0) { 564 fprintf(stderr, "%s: FAIL: second X509V3_ADD_DELETE " 565 "expected 0 extensions, got %d.\n", __func__, got); 566 goto err; 567 } 568 569 failed = 0; 570 571 err: 572 BASIC_CONSTRAINTS_free(bc); 573 574 return failed; 575 } 576 577 static int 578 test_x509v3_add1_i2d_invalid_operations(STACK_OF(X509_EXTENSION) **extensions) 579 { 580 BASIC_CONSTRAINTS *bc = NULL; 581 long error; 582 int crit, got, nid, op; 583 int failed = 1; 584 585 if (X509v3_get_ext_count(*extensions) != 0) { 586 fprintf(stderr, "%s: FAIL: need empty stack.\n", __func__); 587 goto err; 588 } 589 590 /* 591 * Attempt to add a basic constraint extension with invalid operations 592 */ 593 594 nid = NID_basic_constraints; 595 bc = create_basic_constraints(1); 596 crit = 1; 597 for (op = X509V3_ADD_DELETE + 1; op <= X509V3_ADD_OP_MASK; op++) { 598 if ((got = X509V3_add1_i2d(extensions, nid, bc, crit, op)) != -1) { 599 fprintf(stderr, "%s: FAIL: operation %d " 600 "want %d, got %d.\n", __func__, op, -1, got); 601 goto err; 602 } 603 error = ERR_get_error(); 604 if (ERR_GET_REASON(error) != X509V3_R_UNSUPPORTED_OPTION) { 605 fprintf(stderr, "%s: FAIL: invalid operation %d " 606 " pushed %d, want %d.\n", __func__, op, 607 ERR_GET_REASON(error), X509V3_R_EXTENSION_EXISTS); 608 goto err; 609 } 610 } 611 BASIC_CONSTRAINTS_free(bc); 612 bc = NULL; 613 614 if ((got = X509v3_get_ext_count(*extensions)) != 0) { 615 fprintf(stderr, "%s: FAIL: expected 0 extensions, have %d.\n", 616 __func__, got); 617 goto err; 618 } 619 620 failed = 0; 621 622 err: 623 BASIC_CONSTRAINTS_free(bc); 624 625 return failed; 626 } 627 628 static int 629 test_x509v3_add1_i2d(void) 630 { 631 STACK_OF(X509_EXTENSION) *extensions; 632 int failed = 0; 633 634 if ((extensions = sk_X509_EXTENSION_new_null()) == NULL) 635 errx(1, "sk_X509_EXTENSION_new_null"); 636 637 failed |= test_x509v3_add1_i2d_empty_stack(&extensions); 638 failed |= test_x509v3_add1_i2d_single_nid(&extensions); 639 failed |= test_x509v3_add1_i2d_add_append(&extensions); 640 failed |= test_x509v3_add1_i2d_invalid_operations(&extensions); 641 642 sk_X509_EXTENSION_pop_free(extensions, X509_EXTENSION_free); 643 644 return failed; 645 } 646 647 int 648 main(void) 649 { 650 int failed = 0; 651 652 failed |= test_x509v3_add1_i2d(); 653 654 return failed; 655 } 656