/* * Add an ID or range to an ASIdentifierChoice. */ int v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min, ASN1_INTEGER *max) { ASIdentifierChoice **choice; ASIdOrRange *aor; if (asid == NULL) return 0; switch (which) { case V3_ASID_ASNUM: choice = &asid->asnum; break; case V3_ASID_RDI: choice = &asid->rdi; break; default: return 0; } if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit) return 0; if (*choice == NULL) { if ((*choice = ASIdentifierChoice_new()) == NULL) return 0; assert((*choice)->u.asIdsOrRanges == NULL); (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); if ((*choice)->u.asIdsOrRanges == NULL) return 0; (*choice)->type = ASIdentifierChoice_asIdsOrRanges; } if ((aor = ASIdOrRange_new()) == NULL) return 0; if (max == NULL) { aor->type = ASIdOrRange_id; aor->u.id = min; } else { aor->type = ASIdOrRange_range; if ((aor->u.range = ASRange_new()) == NULL) goto err; ASN1_INTEGER_free(aor->u.range->min); aor->u.range->min = min; ASN1_INTEGER_free(aor->u.range->max); aor->u.range->max = max; } if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor))) goto err; return 1; err: ASIdOrRange_free(aor); return 0; }
/* * Whack an ASIdentifierChoice into canonical form. */ static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice) { ASN1_INTEGER *a_max_plus_one = NULL; BIGNUM *bn = NULL; int i, ret = 0; /* * Nothing to do for empty element or inheritance. */ if (choice == NULL || choice->type == ASIdentifierChoice_inherit) return 1; /* * If not a list, or if empty list, it's broken. */ if (choice->type != ASIdentifierChoice_asIdsOrRanges || sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); return 0; } /* * We have a non-empty list. Sort it. */ sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); /* * Now check for errors and suboptimal encoding, rejecting the * former and fixing the latter. */ for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; if (!extract_min_max(a, &a_min, &a_max) || !extract_min_max(b, &b_min, &b_max)) goto done; /* * Make sure we're properly sorted (paranoia). */ if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0)) goto done; /* * Punt inverted ranges. */ if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || ASN1_INTEGER_cmp(b_min, b_max) > 0) goto done; /* * Check for overlaps. */ if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, X509V3_R_EXTENSION_VALUE_ERROR); goto done; } /* * Calculate a_max + 1 to check for adjacency. */ if ((bn == NULL && (bn = BN_new()) == NULL) || ASN1_INTEGER_to_BN(a_max, bn) == NULL || !BN_add_word(bn, 1) || (a_max_plus_one = BN_to_ASN1_INTEGER(bn, a_max_plus_one)) == NULL) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE); goto done; } /* * If a and b are adjacent, merge them. */ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { ASRange *r; switch (a->type) { case ASIdOrRange_id: if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) { X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE, ERR_R_MALLOC_FAILURE); goto done; } r->min = a_min; r->max = b_max; a->type = ASIdOrRange_range; a->u.range = r; break; case ASIdOrRange_range: ASN1_INTEGER_free(a->u.range->max); a->u.range->max = b_max; break; } switch (b->type) { case ASIdOrRange_id: b->u.id = NULL; break; case ASIdOrRange_range: b->u.range->max = NULL; break; } ASIdOrRange_free(b); (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1); i--; continue; } } /* * Check for final inverted range. */ i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; { ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); ASN1_INTEGER *a_min, *a_max; if (a != NULL && a->type == ASIdOrRange_range) { if (!extract_min_max(a, &a_min, &a_max) || ASN1_INTEGER_cmp(a_min, a_max) > 0) goto done; } } /* Paranoia */ if (!ossl_assert(ASIdentifierChoice_is_canonical(choice))) goto done; ret = 1; done: ASN1_INTEGER_free(a_max_plus_one); BN_free(bn); return ret; }