summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authortb <>2023-11-11 09:35:21 +0000
committertb <>2023-11-11 09:35:21 +0000
commit04a4b9d9b4067f424283f0e5c80bcd9ea6aff6c0 (patch)
tree6220c6b10ffd4dcbf53f7871348f8e717039ce94 /src/lib
parent34a76fe207a0f8a739b7c8501991143e58861fbf (diff)
downloadopenbsd-04a4b9d9b4067f424283f0e5c80bcd9ea6aff6c0.tar.gz
openbsd-04a4b9d9b4067f424283f0e5c80bcd9ea6aff6c0.tar.bz2
openbsd-04a4b9d9b4067f424283f0e5c80bcd9ea6aff6c0.zip
Fix a few bugs in X509v3_asid_add*()
These 'builder' functions, usually used together, can result in corrupt ASIdentifiers on failure. In general, no caller should ever try to recover from OpenSSL API failure. There are simply too many traps. We can still make an effort to leave the objects in unmodified state on failure. This is tricky because ownership transfer happens. Unfortunately a really clean version of this seems impossible, maybe a future iteration will bring improvements... The nasty bit here is that the caller of X509v3_asid_add_id_or_range() can't know from the return value whether ownership of min and max was transferred or not. An inspection of (*choice)->u.range is required. If a caller frees min and max after sk_ASIdOrRange_push() failed, there is a double free. All these complications could have been avoided if the API interface had simply used uint32_t instead of ASN1_INTEGERs. The entire RFC 3779 API was clearly written without proper review. I don't know if there ever was an actual consumer before rpki-client. If it existed, nobody with the requisite skill set looked at it in depth. ok beck for the general direction with a lot of input and ok jsing
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/x509/x509_asid.c134
1 files changed, 96 insertions, 38 deletions
diff --git a/src/lib/libcrypto/x509/x509_asid.c b/src/lib/libcrypto/x509/x509_asid.c
index 95b1acb1e4..ecd35b1f1d 100644
--- a/src/lib/libcrypto/x509/x509_asid.c
+++ b/src/lib/libcrypto/x509/x509_asid.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_asid.c,v 1.40 2023/04/19 12:30:09 jsg Exp $ */ 1/* $OpenBSD: x509_asid.c,v 1.41 2023/11/11 09:35:21 tb Exp $ */
2/* 2/*
3 * Contributed to the OpenSSL Project by the American Registry for 3 * Contributed to the OpenSSL Project by the American Registry for
4 * Internet Numbers ("ARIN"). 4 * Internet Numbers ("ARIN").
@@ -406,8 +406,12 @@ int
406X509v3_asid_add_inherit(ASIdentifiers *asid, int which) 406X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
407{ 407{
408 ASIdentifierChoice **choice; 408 ASIdentifierChoice **choice;
409 ASIdentifierChoice *aic = NULL;
410 int ret = 0;
411
409 if (asid == NULL) 412 if (asid == NULL)
410 return 0; 413 goto err;
414
411 switch (which) { 415 switch (which) {
412 case V3_ASID_ASNUM: 416 case V3_ASID_ASNUM:
413 choice = &asid->asnum; 417 choice = &asid->asnum;
@@ -416,19 +420,76 @@ X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
416 choice = &asid->rdi; 420 choice = &asid->rdi;
417 break; 421 break;
418 default: 422 default:
419 return 0; 423 goto err;
420 } 424 }
421 if (*choice == NULL) { 425
422 if ((*choice = ASIdentifierChoice_new()) == NULL) 426 if (*choice != NULL) {
423 return 0; 427 if ((*choice)->type != ASIdentifierChoice_inherit)
424 if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL) 428 goto err;
425 return 0; 429 } else {
426 (*choice)->type = ASIdentifierChoice_inherit; 430 if ((aic = ASIdentifierChoice_new()) == NULL)
431 goto err;
432 if ((aic->u.inherit = ASN1_NULL_new()) == NULL)
433 goto err;
434 aic->type = ASIdentifierChoice_inherit;
435
436 *choice = aic;
437 aic = NULL;
427 } 438 }
428 return (*choice)->type == ASIdentifierChoice_inherit; 439
440 ret = 1;
441
442 err:
443 ASIdentifierChoice_free(aic);
444
445 return ret;
429} 446}
430LCRYPTO_ALIAS(X509v3_asid_add_inherit); 447LCRYPTO_ALIAS(X509v3_asid_add_inherit);
431 448
449static int
450ASIdOrRanges_add_id_or_range(ASIdOrRanges *aors, ASN1_INTEGER *min,
451 ASN1_INTEGER *max)
452{
453 ASIdOrRange *aor = NULL;
454 ASRange *asr = NULL;
455 int ret = 0;
456
457 /* Preallocate since we must not fail after sk_ASIdOrRange_push(). */
458 if (max != NULL) {
459 if ((asr = ASRange_new()) == NULL)
460 goto err;
461 }
462
463 if ((aor = ASIdOrRange_new()) == NULL)
464 goto err;
465 if (sk_ASIdOrRange_push(aors, aor) <= 0)
466 goto err;
467
468 if (max == NULL) {
469 aor->type = ASIdOrRange_id;
470 aor->u.id = min;
471 } else {
472 ASN1_INTEGER_free(asr->min);
473 asr->min = min;
474 ASN1_INTEGER_free(asr->max);
475 asr->max = max;
476
477 aor->type = ASIdOrRange_range;
478 aor->u.range = asr;
479 asr = NULL;
480 }
481
482 aor = NULL;
483
484 ret = 1;
485
486 err:
487 ASIdOrRange_free(aor);
488 ASRange_free(asr);
489
490 return ret;
491}
492
432/* 493/*
433 * Add an ID or range to an ASIdentifierChoice. 494 * Add an ID or range to an ASIdentifierChoice.
434 */ 495 */
@@ -437,9 +498,12 @@ X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min,
437 ASN1_INTEGER *max) 498 ASN1_INTEGER *max)
438{ 499{
439 ASIdentifierChoice **choice; 500 ASIdentifierChoice **choice;
440 ASIdOrRange *aor; 501 ASIdentifierChoice *aic = NULL, *new_aic = NULL;
502 int ret = 0;
503
441 if (asid == NULL) 504 if (asid == NULL)
442 return 0; 505 goto err;
506
443 switch (which) { 507 switch (which) {
444 case V3_ASID_ASNUM: 508 case V3_ASID_ASNUM:
445 choice = &asid->asnum; 509 choice = &asid->asnum;
@@ -448,39 +512,33 @@ X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min,
448 choice = &asid->rdi; 512 choice = &asid->rdi;
449 break; 513 break;
450 default: 514 default:
451 return 0; 515 goto err;
452 }
453 if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
454 return 0;
455 if (*choice == NULL) {
456 if ((*choice = ASIdentifierChoice_new()) == NULL)
457 return 0;
458 (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
459 if ((*choice)->u.asIdsOrRanges == NULL)
460 return 0;
461 (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
462 } 516 }
463 if ((aor = ASIdOrRange_new()) == NULL) 517
464 return 0; 518 if ((aic = *choice) != NULL) {
465 if (max == NULL) { 519 if (aic->type != ASIdentifierChoice_asIdsOrRanges)
466 aor->type = ASIdOrRange_id; 520 goto err;
467 aor->u.id = min;
468 } else { 521 } else {
469 aor->type = ASIdOrRange_range; 522 if ((aic = new_aic = ASIdentifierChoice_new()) == NULL)
470 if ((aor->u.range = ASRange_new()) == NULL) 523 goto err;
524 aic->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
525 if (aic->u.asIdsOrRanges == NULL)
471 goto err; 526 goto err;
472 ASN1_INTEGER_free(aor->u.range->min); 527 aic->type = ASIdentifierChoice_asIdsOrRanges;
473 aor->u.range->min = min;
474 ASN1_INTEGER_free(aor->u.range->max);
475 aor->u.range->max = max;
476 } 528 }
477 if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) 529
530 if (!ASIdOrRanges_add_id_or_range(aic->u.asIdsOrRanges, min, max))
478 goto err; 531 goto err;
479 return 1; 532
533 *choice = aic;
534 aic = new_aic = NULL;
535
536 ret = 1;
480 537
481 err: 538 err:
482 ASIdOrRange_free(aor); 539 ASIdentifierChoice_free(new_aic);
483 return 0; 540
541 return ret;
484} 542}
485LCRYPTO_ALIAS(X509v3_asid_add_id_or_range); 543LCRYPTO_ALIAS(X509v3_asid_add_id_or_range);
486 544