aboutsummaryrefslogtreecommitdiff
path: root/openssl/trunk/crypto/x509v3/v3_asid.c
diff options
context:
space:
mode:
authorRob Austein <sra@hactrn.net>2006-07-26 19:10:06 +0000
committerRob Austein <sra@hactrn.net>2006-07-26 19:10:06 +0000
commitf2f336920034a365e9bca1ad16405f098dd04b38 (patch)
tree29108c34af08056edcf13e4f5c575e95ef035c20 /openssl/trunk/crypto/x509v3/v3_asid.c
parent9da658b4e7e0f61ec2e325c9c30e344050c25ba4 (diff)
Rewrite asid_canonize() to merge ranges properly.
svn path=/openssl/trunk/crypto/x509v3/v3_asid.c; revision=91
Diffstat (limited to 'openssl/trunk/crypto/x509v3/v3_asid.c')
-rw-r--r--openssl/trunk/crypto/x509v3/v3_asid.c131
1 files changed, 87 insertions, 44 deletions
diff --git a/openssl/trunk/crypto/x509v3/v3_asid.c b/openssl/trunk/crypto/x509v3/v3_asid.c
index 1473e16b..4c1ace75 100644
--- a/openssl/trunk/crypto/x509v3/v3_asid.c
+++ b/openssl/trunk/crypto/x509v3/v3_asid.c
@@ -30,6 +30,7 @@
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/x509v3.h>
+#include <openssl/bn.h>
ASN1_SEQUENCE(ASRange) = {
ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
@@ -90,7 +91,7 @@ static int i2r_ASIdentifierChoice(BIO *out,
return 0;
BIO_puts(out, s);
OPENSSL_free(s);
- BIO_puts(out, " - ");
+ BIO_puts(out, "-");
if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
return 0;
BIO_puts(out, s);
@@ -215,15 +216,17 @@ static int asid_add_id_or_range(ASIdentifierChoice **choice,
/*
* Whack an ASIdentifierChoice into canonical form.
*/
-static void asid_canonize(ASIdentifierChoice *choice)
+static int asid_canonize(ASIdentifierChoice *choice)
{
- int i;
+ 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;
+ return 1;
/*
* We have a list. Sort it.
@@ -237,68 +240,108 @@ static void asid_canonize(ASIdentifierChoice *choice)
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, *a_max, *b_min, *b_max;
+
+ switch (a->type) {
+ case ASIdOrRange_id:
+ a_min = a_max = a->u.id;
+ break;
+ case ASIdOrRange_range:
+ a_min = a->u.range->min;
+ a_max = a->u.range->max;
+ break;
+ }
- /*
- * Comparing ID a with ID b, remove a if they're equal.
- */
- if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) {
- if (ASN1_INTEGER_cmp(a->u.id, b->u.id) == 0) {
- sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i);
- ASIdOrRange_free(a);
- i--;
- }
- continue;
+ switch (b->type) {
+ case ASIdOrRange_id:
+ b_min = b_max = b->u.id;
+ break;
+ case ASIdOrRange_range:
+ b_min = b->u.range->min;
+ b_max = b->u.range->max;
+ break;
}
/*
- * Comparing ID a with range b, remove a if contained in b.
+ * Make sure we're properly sorted (paranoia).
*/
- if (a->type == ASIdOrRange_id) {
- if (ASN1_INTEGER_cmp(a->u.id, b->u.range->min) >= 0 &&
- ASN1_INTEGER_cmp(a->u.id, b->u.range->max) <= 0) {
- sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i);
- ASIdOrRange_free(a);
- i--;
- }
- continue;
- }
+ assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0);
/*
- * Comparing range a with ID b, remove b if contained in a.
+ * If a contains b, remove b.
*/
- if (b->type == ASIdOrRange_id) {
- if (ASN1_INTEGER_cmp(b->u.id, a->u.range->min) >= 0 &&
- ASN1_INTEGER_cmp(b->u.id, a->u.range->max) <= 0) {
- sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
+ if (ASN1_INTEGER_cmp(a_max, b_max) >= 0) {
+ sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
ASIdOrRange_free(b);
- i--;
- }
- continue;
+ --i;
+ continue;
}
/*
- * Comparing range a with range b, remove b if contained in a.
+ * If b contains a, remove a.
*/
- if (ASN1_INTEGER_cmp(a->u.range->max, b->u.range->max) >= 0) {
- sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
- ASIdOrRange_free(b);
- i--;
- continue;
+ if (ASN1_INTEGER_cmp(a_min, b_min) == 0 &&
+ ASN1_INTEGER_cmp(a_max, b_max) <= 0) {
+ sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i);
+ ASIdOrRange_free(a);
+ --i;
+ continue;
}
/*
- * Comparing range a with range b, merge if they overlap.
+ * Calculate a_max + 1 to check for adjacency.
*/
- if (ASN1_INTEGER_cmp(a->u.range->max, b->u.range->min) >= 0) {
- ASN1_INTEGER *tmp = b->u.range->min;
- b->u.range->min = a->u.range->min;
- a->u.range->min = tmp;
- sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i);
+ 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)
+ goto err;
+
+ /*
+ * If a and b are adjacent or overlap, merge them.
+ */
+ if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) {
+ ASIdOrRange *aor = ASIdOrRange_new();
+ if (aor == NULL)
+ goto err;
+ aor->type = ASIdOrRange_range;
+ if ((aor->u.range = ASRange_new()) == NULL) {
+ ASIdOrRange_free(aor);
+ goto err;
+ }
+ aor->u.range->min = a_min;
+ aor->u.range->max = b_max;
+ sk_ASIdOrRange_set(choice->u.asIdsOrRanges, i, aor);
+ sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
+ switch (a->type) {
+ case ASIdOrRange_id:
+ a->u.id = NULL;
+ break;
+ case ASIdOrRange_range:
+ a->u.range->min = NULL;
+ break;
+ }
ASIdOrRange_free(a);
+ switch (b->type) {
+ case ASIdOrRange_id:
+ b->u.id = NULL;
+ break;
+ case ASIdOrRange_range:
+ b->u.range->max = NULL;
+ break;
+ }
+ ASIdOrRange_free(b);
i--;
continue;
}
}
+
+ ret = 1;
+
+ err:
+ ASN1_INTEGER_free(a_max_plus_one);
+ BN_free(bn);
+ return ret;
}
/*