Ejemplo n.º 1
0
/*
 * 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;
}
Ejemplo n.º 2
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;
}