summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509/x509_asid.c
diff options
context:
space:
mode:
authorjob <>2021-09-02 12:41:44 +0000
committerjob <>2021-09-02 12:41:44 +0000
commita9cb954f2cf630ab74009f5641622ac0d175bc58 (patch)
tree68881b07659cc9e2b17902a5156f430f2154ecf8 /src/lib/libcrypto/x509/x509_asid.c
parente7198b4ee0ece23326da3c1f771171a6ca285eca (diff)
downloadopenbsd-a9cb954f2cf630ab74009f5641622ac0d175bc58.tar.gz
openbsd-a9cb954f2cf630ab74009f5641622ac0d175bc58.tar.bz2
openbsd-a9cb954f2cf630ab74009f5641622ac0d175bc58.zip
Lay groundwork to support X.509 v3 extensions for IP Addresses and AS Identifiers
These extensions are defined in RFC 3779 and used in the RPKI (RFC 6482, RFC 8360). Imported from OpenSSL 1.1.1j (aaf2fcb575cdf6491b98ab4829abf78a3dec8402b8b81efc8f23c00d443981bf) This changeset is a no-op, as there are 10+ issues and at least 2 security issues. Work will continue in-tree. OK tb@, discussed with beck@
Diffstat (limited to 'src/lib/libcrypto/x509/x509_asid.c')
-rw-r--r--src/lib/libcrypto/x509/x509_asid.c894
1 files changed, 894 insertions, 0 deletions
diff --git a/src/lib/libcrypto/x509/x509_asid.c b/src/lib/libcrypto/x509/x509_asid.c
new file mode 100644
index 0000000000..ac68572672
--- /dev/null
+++ b/src/lib/libcrypto/x509/x509_asid.c
@@ -0,0 +1,894 @@
1/*
2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10/*
11 * Implementation of RFC 3779 section 3.2.
12 */
13
14#include <assert.h>
15#include <stdio.h>
16#include <string.h>
17#include "internal/cryptlib.h"
18#include <openssl/conf.h>
19#include <openssl/asn1.h>
20#include <openssl/asn1t.h>
21#include <openssl/x509v3.h>
22#include <openssl/x509.h>
23#include "crypto/x509.h"
24#include <openssl/bn.h>
25#include "ext_dat.h"
26
27#ifndef OPENSSL_NO_RFC3779
28
29/*
30 * OpenSSL ASN.1 template translation of RFC 3779 3.2.3.
31 */
32
33ASN1_SEQUENCE(ASRange) = {
34 ASN1_SIMPLE(ASRange, min, ASN1_INTEGER),
35 ASN1_SIMPLE(ASRange, max, ASN1_INTEGER)
36} ASN1_SEQUENCE_END(ASRange)
37
38ASN1_CHOICE(ASIdOrRange) = {
39 ASN1_SIMPLE(ASIdOrRange, u.id, ASN1_INTEGER),
40 ASN1_SIMPLE(ASIdOrRange, u.range, ASRange)
41} ASN1_CHOICE_END(ASIdOrRange)
42
43ASN1_CHOICE(ASIdentifierChoice) = {
44 ASN1_SIMPLE(ASIdentifierChoice, u.inherit, ASN1_NULL),
45 ASN1_SEQUENCE_OF(ASIdentifierChoice, u.asIdsOrRanges, ASIdOrRange)
46} ASN1_CHOICE_END(ASIdentifierChoice)
47
48ASN1_SEQUENCE(ASIdentifiers) = {
49 ASN1_EXP_OPT(ASIdentifiers, asnum, ASIdentifierChoice, 0),
50 ASN1_EXP_OPT(ASIdentifiers, rdi, ASIdentifierChoice, 1)
51} ASN1_SEQUENCE_END(ASIdentifiers)
52
53IMPLEMENT_ASN1_FUNCTIONS(ASRange)
54IMPLEMENT_ASN1_FUNCTIONS(ASIdOrRange)
55IMPLEMENT_ASN1_FUNCTIONS(ASIdentifierChoice)
56IMPLEMENT_ASN1_FUNCTIONS(ASIdentifiers)
57
58/*
59 * i2r method for an ASIdentifierChoice.
60 */
61static int i2r_ASIdentifierChoice(BIO *out,
62 ASIdentifierChoice *choice,
63 int indent, const char *msg)
64{
65 int i;
66 char *s;
67 if (choice == NULL)
68 return 1;
69 BIO_printf(out, "%*s%s:\n", indent, "", msg);
70 switch (choice->type) {
71 case ASIdentifierChoice_inherit:
72 BIO_printf(out, "%*sinherit\n", indent + 2, "");
73 break;
74 case ASIdentifierChoice_asIdsOrRanges:
75 for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); i++) {
76 ASIdOrRange *aor =
77 sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
78 switch (aor->type) {
79 case ASIdOrRange_id:
80 if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == NULL)
81 return 0;
82 BIO_printf(out, "%*s%s\n", indent + 2, "", s);
83 OPENSSL_free(s);
84 break;
85 case ASIdOrRange_range:
86 if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->min)) == NULL)
87 return 0;
88 BIO_printf(out, "%*s%s-", indent + 2, "", s);
89 OPENSSL_free(s);
90 if ((s = i2s_ASN1_INTEGER(NULL, aor->u.range->max)) == NULL)
91 return 0;
92 BIO_printf(out, "%s\n", s);
93 OPENSSL_free(s);
94 break;
95 default:
96 return 0;
97 }
98 }
99 break;
100 default:
101 return 0;
102 }
103 return 1;
104}
105
106/*
107 * i2r method for an ASIdentifier extension.
108 */
109static int i2r_ASIdentifiers(const X509V3_EXT_METHOD *method,
110 void *ext, BIO *out, int indent)
111{
112 ASIdentifiers *asid = ext;
113 return (i2r_ASIdentifierChoice(out, asid->asnum, indent,
114 "Autonomous System Numbers") &&
115 i2r_ASIdentifierChoice(out, asid->rdi, indent,
116 "Routing Domain Identifiers"));
117}
118
119/*
120 * Sort comparison function for a sequence of ASIdOrRange elements.
121 */
122static int ASIdOrRange_cmp(const ASIdOrRange *const *a_,
123 const ASIdOrRange *const *b_)
124{
125 const ASIdOrRange *a = *a_, *b = *b_;
126
127 assert((a->type == ASIdOrRange_id && a->u.id != NULL) ||
128 (a->type == ASIdOrRange_range && a->u.range != NULL &&
129 a->u.range->min != NULL && a->u.range->max != NULL));
130
131 assert((b->type == ASIdOrRange_id && b->u.id != NULL) ||
132 (b->type == ASIdOrRange_range && b->u.range != NULL &&
133 b->u.range->min != NULL && b->u.range->max != NULL));
134
135 if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id)
136 return ASN1_INTEGER_cmp(a->u.id, b->u.id);
137
138 if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) {
139 int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min);
140 return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max,
141 b->u.range->max);
142 }
143
144 if (a->type == ASIdOrRange_id)
145 return ASN1_INTEGER_cmp(a->u.id, b->u.range->min);
146 else
147 return ASN1_INTEGER_cmp(a->u.range->min, b->u.id);
148}
149
150/*
151 * Add an inherit element.
152 */
153int X509v3_asid_add_inherit(ASIdentifiers *asid, int which)
154{
155 ASIdentifierChoice **choice;
156 if (asid == NULL)
157 return 0;
158 switch (which) {
159 case V3_ASID_ASNUM:
160 choice = &asid->asnum;
161 break;
162 case V3_ASID_RDI:
163 choice = &asid->rdi;
164 break;
165 default:
166 return 0;
167 }
168 if (*choice == NULL) {
169 if ((*choice = ASIdentifierChoice_new()) == NULL)
170 return 0;
171 if (((*choice)->u.inherit = ASN1_NULL_new()) == NULL)
172 return 0;
173 (*choice)->type = ASIdentifierChoice_inherit;
174 }
175 return (*choice)->type == ASIdentifierChoice_inherit;
176}
177
178/*
179 * Add an ID or range to an ASIdentifierChoice.
180 */
181int X509v3_asid_add_id_or_range(ASIdentifiers *asid,
182 int which, ASN1_INTEGER *min, ASN1_INTEGER *max)
183{
184 ASIdentifierChoice **choice;
185 ASIdOrRange *aor;
186 if (asid == NULL)
187 return 0;
188 switch (which) {
189 case V3_ASID_ASNUM:
190 choice = &asid->asnum;
191 break;
192 case V3_ASID_RDI:
193 choice = &asid->rdi;
194 break;
195 default:
196 return 0;
197 }
198 if (*choice != NULL && (*choice)->type == ASIdentifierChoice_inherit)
199 return 0;
200 if (*choice == NULL) {
201 if ((*choice = ASIdentifierChoice_new()) == NULL)
202 return 0;
203 (*choice)->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp);
204 if ((*choice)->u.asIdsOrRanges == NULL)
205 return 0;
206 (*choice)->type = ASIdentifierChoice_asIdsOrRanges;
207 }
208 if ((aor = ASIdOrRange_new()) == NULL)
209 return 0;
210 if (max == NULL) {
211 aor->type = ASIdOrRange_id;
212 aor->u.id = min;
213 } else {
214 aor->type = ASIdOrRange_range;
215 if ((aor->u.range = ASRange_new()) == NULL)
216 goto err;
217 ASN1_INTEGER_free(aor->u.range->min);
218 aor->u.range->min = min;
219 ASN1_INTEGER_free(aor->u.range->max);
220 aor->u.range->max = max;
221 }
222 if (!(sk_ASIdOrRange_push((*choice)->u.asIdsOrRanges, aor)))
223 goto err;
224 return 1;
225
226 err:
227 ASIdOrRange_free(aor);
228 return 0;
229}
230
231/*
232 * Extract min and max values from an ASIdOrRange.
233 */
234static int extract_min_max(ASIdOrRange *aor,
235 ASN1_INTEGER **min, ASN1_INTEGER **max)
236{
237 if (!ossl_assert(aor != NULL))
238 return 0;
239 switch (aor->type) {
240 case ASIdOrRange_id:
241 *min = aor->u.id;
242 *max = aor->u.id;
243 return 1;
244 case ASIdOrRange_range:
245 *min = aor->u.range->min;
246 *max = aor->u.range->max;
247 return 1;
248 }
249
250 return 0;
251}
252
253/*
254 * Check whether an ASIdentifierChoice is in canonical form.
255 */
256static int ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice)
257{
258 ASN1_INTEGER *a_max_plus_one = NULL;
259 ASN1_INTEGER *orig;
260 BIGNUM *bn = NULL;
261 int i, ret = 0;
262
263 /*
264 * Empty element or inheritance is canonical.
265 */
266 if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
267 return 1;
268
269 /*
270 * If not a list, or if empty list, it's broken.
271 */
272 if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
273 sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0)
274 return 0;
275
276 /*
277 * It's a list, check it.
278 */
279 for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
280 ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
281 ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
282 ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
283 NULL;
284
285 if (!extract_min_max(a, &a_min, &a_max)
286 || !extract_min_max(b, &b_min, &b_max))
287 goto done;
288
289 /*
290 * Punt misordered list, overlapping start, or inverted range.
291 */
292 if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 ||
293 ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
294 ASN1_INTEGER_cmp(b_min, b_max) > 0)
295 goto done;
296
297 /*
298 * Calculate a_max + 1 to check for adjacency.
299 */
300 if ((bn == NULL && (bn = BN_new()) == NULL) ||
301 ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
302 !BN_add_word(bn, 1)) {
303 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL,
304 ERR_R_MALLOC_FAILURE);
305 goto done;
306 }
307
308 if ((a_max_plus_one =
309 BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
310 a_max_plus_one = orig;
311 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_IS_CANONICAL,
312 ERR_R_MALLOC_FAILURE);
313 goto done;
314 }
315
316 /*
317 * Punt if adjacent or overlapping.
318 */
319 if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0)
320 goto done;
321 }
322
323 /*
324 * Check for inverted range.
325 */
326 i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
327 {
328 ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
329 ASN1_INTEGER *a_min, *a_max;
330 if (a != NULL && a->type == ASIdOrRange_range) {
331 if (!extract_min_max(a, &a_min, &a_max)
332 || ASN1_INTEGER_cmp(a_min, a_max) > 0)
333 goto done;
334 }
335 }
336
337 ret = 1;
338
339 done:
340 ASN1_INTEGER_free(a_max_plus_one);
341 BN_free(bn);
342 return ret;
343}
344
345/*
346 * Check whether an ASIdentifier extension is in canonical form.
347 */
348int X509v3_asid_is_canonical(ASIdentifiers *asid)
349{
350 return (asid == NULL ||
351 (ASIdentifierChoice_is_canonical(asid->asnum) &&
352 ASIdentifierChoice_is_canonical(asid->rdi)));
353}
354
355/*
356 * Whack an ASIdentifierChoice into canonical form.
357 */
358static int ASIdentifierChoice_canonize(ASIdentifierChoice *choice)
359{
360 ASN1_INTEGER *a_max_plus_one = NULL;
361 ASN1_INTEGER *orig;
362 BIGNUM *bn = NULL;
363 int i, ret = 0;
364
365 /*
366 * Nothing to do for empty element or inheritance.
367 */
368 if (choice == NULL || choice->type == ASIdentifierChoice_inherit)
369 return 1;
370
371 /*
372 * If not a list, or if empty list, it's broken.
373 */
374 if (choice->type != ASIdentifierChoice_asIdsOrRanges ||
375 sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) {
376 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
377 X509V3_R_EXTENSION_VALUE_ERROR);
378 return 0;
379 }
380
381 /*
382 * We have a non-empty list. Sort it.
383 */
384 sk_ASIdOrRange_sort(choice->u.asIdsOrRanges);
385
386 /*
387 * Now check for errors and suboptimal encoding, rejecting the
388 * former and fixing the latter.
389 */
390 for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) {
391 ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
392 ASIdOrRange *b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1);
393 ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max =
394 NULL;
395
396 if (!extract_min_max(a, &a_min, &a_max)
397 || !extract_min_max(b, &b_min, &b_max))
398 goto done;
399
400 /*
401 * Make sure we're properly sorted (paranoia).
402 */
403 if (!ossl_assert(ASN1_INTEGER_cmp(a_min, b_min) <= 0))
404 goto done;
405
406 /*
407 * Punt inverted ranges.
408 */
409 if (ASN1_INTEGER_cmp(a_min, a_max) > 0 ||
410 ASN1_INTEGER_cmp(b_min, b_max) > 0)
411 goto done;
412
413 /*
414 * Check for overlaps.
415 */
416 if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) {
417 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
418 X509V3_R_EXTENSION_VALUE_ERROR);
419 goto done;
420 }
421
422 /*
423 * Calculate a_max + 1 to check for adjacency.
424 */
425 if ((bn == NULL && (bn = BN_new()) == NULL) ||
426 ASN1_INTEGER_to_BN(a_max, bn) == NULL ||
427 !BN_add_word(bn, 1)) {
428 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
429 ERR_R_MALLOC_FAILURE);
430 goto done;
431 }
432
433 if ((a_max_plus_one =
434 BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) {
435 a_max_plus_one = orig;
436 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
437 ERR_R_MALLOC_FAILURE);
438 goto done;
439 }
440
441 /*
442 * If a and b are adjacent, merge them.
443 */
444 if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) {
445 ASRange *r;
446 switch (a->type) {
447 case ASIdOrRange_id:
448 if ((r = OPENSSL_malloc(sizeof(*r))) == NULL) {
449 X509V3err(X509V3_F_ASIDENTIFIERCHOICE_CANONIZE,
450 ERR_R_MALLOC_FAILURE);
451 goto done;
452 }
453 r->min = a_min;
454 r->max = b_max;
455 a->type = ASIdOrRange_range;
456 a->u.range = r;
457 break;
458 case ASIdOrRange_range:
459 ASN1_INTEGER_free(a->u.range->max);
460 a->u.range->max = b_max;
461 break;
462 }
463 switch (b->type) {
464 case ASIdOrRange_id:
465 b->u.id = NULL;
466 break;
467 case ASIdOrRange_range:
468 b->u.range->max = NULL;
469 break;
470 }
471 ASIdOrRange_free(b);
472 (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, i + 1);
473 i--;
474 continue;
475 }
476 }
477
478 /*
479 * Check for final inverted range.
480 */
481 i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1;
482 {
483 ASIdOrRange *a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i);
484 ASN1_INTEGER *a_min, *a_max;
485 if (a != NULL && a->type == ASIdOrRange_range) {
486 if (!extract_min_max(a, &a_min, &a_max)
487 || ASN1_INTEGER_cmp(a_min, a_max) > 0)
488 goto done;
489 }
490 }
491
492 /* Paranoia */
493 if (!ossl_assert(ASIdentifierChoice_is_canonical(choice)))
494 goto done;
495
496 ret = 1;
497
498 done:
499 ASN1_INTEGER_free(a_max_plus_one);
500 BN_free(bn);
501 return ret;
502}
503
504/*
505 * Whack an ASIdentifier extension into canonical form.
506 */
507int X509v3_asid_canonize(ASIdentifiers *asid)
508{
509 return (asid == NULL ||
510 (ASIdentifierChoice_canonize(asid->asnum) &&
511 ASIdentifierChoice_canonize(asid->rdi)));
512}
513
514/*
515 * v2i method for an ASIdentifier extension.
516 */
517static void *v2i_ASIdentifiers(const struct v3_ext_method *method,
518 struct v3_ext_ctx *ctx,
519 STACK_OF(CONF_VALUE) *values)
520{
521 ASN1_INTEGER *min = NULL, *max = NULL;
522 ASIdentifiers *asid = NULL;
523 int i;
524
525 if ((asid = ASIdentifiers_new()) == NULL) {
526 X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
527 return NULL;
528 }
529
530 for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
531 CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
532 int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0;
533
534 /*
535 * Figure out whether this is an AS or an RDI.
536 */
537 if (!name_cmp(val->name, "AS")) {
538 which = V3_ASID_ASNUM;
539 } else if (!name_cmp(val->name, "RDI")) {
540 which = V3_ASID_RDI;
541 } else {
542 X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
543 X509V3_R_EXTENSION_NAME_ERROR);
544 X509V3_conf_err(val);
545 goto err;
546 }
547
548 /*
549 * Handle inheritance.
550 */
551 if (strcmp(val->value, "inherit") == 0) {
552 if (X509v3_asid_add_inherit(asid, which))
553 continue;
554 X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
555 X509V3_R_INVALID_INHERITANCE);
556 X509V3_conf_err(val);
557 goto err;
558 }
559
560 /*
561 * Number, range, or mistake, pick it apart and figure out which.
562 */
563 i1 = strspn(val->value, "0123456789");
564 if (val->value[i1] == '\0') {
565 is_range = 0;
566 } else {
567 is_range = 1;
568 i2 = i1 + strspn(val->value + i1, " \t");
569 if (val->value[i2] != '-') {
570 X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
571 X509V3_R_INVALID_ASNUMBER);
572 X509V3_conf_err(val);
573 goto err;
574 }
575 i2++;
576 i2 = i2 + strspn(val->value + i2, " \t");
577 i3 = i2 + strspn(val->value + i2, "0123456789");
578 if (val->value[i3] != '\0') {
579 X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
580 X509V3_R_INVALID_ASRANGE);
581 X509V3_conf_err(val);
582 goto err;
583 }
584 }
585
586 /*
587 * Syntax is ok, read and add it.
588 */
589 if (!is_range) {
590 if (!X509V3_get_value_int(val, &min)) {
591 X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
592 goto err;
593 }
594 } else {
595 char *s = OPENSSL_strdup(val->value);
596 if (s == NULL) {
597 X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
598 goto err;
599 }
600 s[i1] = '\0';
601 min = s2i_ASN1_INTEGER(NULL, s);
602 max = s2i_ASN1_INTEGER(NULL, s + i2);
603 OPENSSL_free(s);
604 if (min == NULL || max == NULL) {
605 X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
606 goto err;
607 }
608 if (ASN1_INTEGER_cmp(min, max) > 0) {
609 X509V3err(X509V3_F_V2I_ASIDENTIFIERS,
610 X509V3_R_EXTENSION_VALUE_ERROR);
611 goto err;
612 }
613 }
614 if (!X509v3_asid_add_id_or_range(asid, which, min, max)) {
615 X509V3err(X509V3_F_V2I_ASIDENTIFIERS, ERR_R_MALLOC_FAILURE);
616 goto err;
617 }
618 min = max = NULL;
619 }
620
621 /*
622 * Canonize the result, then we're done.
623 */
624 if (!X509v3_asid_canonize(asid))
625 goto err;
626 return asid;
627
628 err:
629 ASIdentifiers_free(asid);
630 ASN1_INTEGER_free(min);
631 ASN1_INTEGER_free(max);
632 return NULL;
633}
634
635/*
636 * OpenSSL dispatch.
637 */
638const X509V3_EXT_METHOD v3_asid = {
639 NID_sbgp_autonomousSysNum, /* nid */
640 0, /* flags */
641 ASN1_ITEM_ref(ASIdentifiers), /* template */
642 0, 0, 0, 0, /* old functions, ignored */
643 0, /* i2s */
644 0, /* s2i */
645 0, /* i2v */
646 v2i_ASIdentifiers, /* v2i */
647 i2r_ASIdentifiers, /* i2r */
648 0, /* r2i */
649 NULL /* extension-specific data */
650};
651
652/*
653 * Figure out whether extension uses inheritance.
654 */
655int X509v3_asid_inherits(ASIdentifiers *asid)
656{
657 return (asid != NULL &&
658 ((asid->asnum != NULL &&
659 asid->asnum->type == ASIdentifierChoice_inherit) ||
660 (asid->rdi != NULL &&
661 asid->rdi->type == ASIdentifierChoice_inherit)));
662}
663
664/*
665 * Figure out whether parent contains child.
666 */
667static int asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child)
668{
669 ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL;
670 int p, c;
671
672 if (child == NULL || parent == child)
673 return 1;
674 if (parent == NULL)
675 return 0;
676
677 p = 0;
678 for (c = 0; c < sk_ASIdOrRange_num(child); c++) {
679 if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, &c_max))
680 return 0;
681 for (;; p++) {
682 if (p >= sk_ASIdOrRange_num(parent))
683 return 0;
684 if (!extract_min_max(sk_ASIdOrRange_value(parent, p), &p_min,
685 &p_max))
686 return 0;
687 if (ASN1_INTEGER_cmp(p_max, c_max) < 0)
688 continue;
689 if (ASN1_INTEGER_cmp(p_min, c_min) > 0)
690 return 0;
691 break;
692 }
693 }
694
695 return 1;
696}
697
698/*
699 * Test whether a is a subset of b.
700 */
701int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b)
702{
703 return (a == NULL ||
704 a == b ||
705 (b != NULL &&
706 !X509v3_asid_inherits(a) &&
707 !X509v3_asid_inherits(b) &&
708 asid_contains(b->asnum->u.asIdsOrRanges,
709 a->asnum->u.asIdsOrRanges) &&
710 asid_contains(b->rdi->u.asIdsOrRanges,
711 a->rdi->u.asIdsOrRanges)));
712}
713
714/*
715 * Validation error handling via callback.
716 */
717#define validation_err(_err_) \
718 do { \
719 if (ctx != NULL) { \
720 ctx->error = _err_; \
721 ctx->error_depth = i; \
722 ctx->current_cert = x; \
723 ret = ctx->verify_cb(0, ctx); \
724 } else { \
725 ret = 0; \
726 } \
727 if (!ret) \
728 goto done; \
729 } while (0)
730
731/*
732 * Core code for RFC 3779 3.3 path validation.
733 */
734static int asid_validate_path_internal(X509_STORE_CTX *ctx,
735 STACK_OF(X509) *chain,
736 ASIdentifiers *ext)
737{
738 ASIdOrRanges *child_as = NULL, *child_rdi = NULL;
739 int i, ret = 1, inherit_as = 0, inherit_rdi = 0;
740 X509 *x;
741
742 if (!ossl_assert(chain != NULL && sk_X509_num(chain) > 0)
743 || !ossl_assert(ctx != NULL || ext != NULL)
744 || !ossl_assert(ctx == NULL || ctx->verify_cb != NULL)) {
745 if (ctx != NULL)
746 ctx->error = X509_V_ERR_UNSPECIFIED;
747 return 0;
748 }
749
750
751 /*
752 * Figure out where to start. If we don't have an extension to
753 * check, we're done. Otherwise, check canonical form and
754 * set up for walking up the chain.
755 */
756 if (ext != NULL) {
757 i = -1;
758 x = NULL;
759 } else {
760 i = 0;
761 x = sk_X509_value(chain, i);
762 if ((ext = x->rfc3779_asid) == NULL)
763 goto done;
764 }
765 if (!X509v3_asid_is_canonical(ext))
766 validation_err(X509_V_ERR_INVALID_EXTENSION);
767 if (ext->asnum != NULL) {
768 switch (ext->asnum->type) {
769 case ASIdentifierChoice_inherit:
770 inherit_as = 1;
771 break;
772 case ASIdentifierChoice_asIdsOrRanges:
773 child_as = ext->asnum->u.asIdsOrRanges;
774 break;
775 }
776 }
777 if (ext->rdi != NULL) {
778 switch (ext->rdi->type) {
779 case ASIdentifierChoice_inherit:
780 inherit_rdi = 1;
781 break;
782 case ASIdentifierChoice_asIdsOrRanges:
783 child_rdi = ext->rdi->u.asIdsOrRanges;
784 break;
785 }
786 }
787
788 /*
789 * Now walk up the chain. Extensions must be in canonical form, no
790 * cert may list resources that its parent doesn't list.
791 */
792 for (i++; i < sk_X509_num(chain); i++) {
793 x = sk_X509_value(chain, i);
794 if (!ossl_assert(x != NULL)) {
795 if (ctx != NULL)
796 ctx->error = X509_V_ERR_UNSPECIFIED;
797 return 0;
798 }
799 if (x->rfc3779_asid == NULL) {
800 if (child_as != NULL || child_rdi != NULL)
801 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
802 continue;
803 }
804 if (!X509v3_asid_is_canonical(x->rfc3779_asid))
805 validation_err(X509_V_ERR_INVALID_EXTENSION);
806 if (x->rfc3779_asid->asnum == NULL && child_as != NULL) {
807 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
808 child_as = NULL;
809 inherit_as = 0;
810 }
811 if (x->rfc3779_asid->asnum != NULL &&
812 x->rfc3779_asid->asnum->type ==
813 ASIdentifierChoice_asIdsOrRanges) {
814 if (inherit_as
815 || asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges,
816 child_as)) {
817 child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges;
818 inherit_as = 0;
819 } else {
820 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
821 }
822 }
823 if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) {
824 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
825 child_rdi = NULL;
826 inherit_rdi = 0;
827 }
828 if (x->rfc3779_asid->rdi != NULL &&
829 x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) {
830 if (inherit_rdi ||
831 asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges,
832 child_rdi)) {
833 child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges;
834 inherit_rdi = 0;
835 } else {
836 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
837 }
838 }
839 }
840
841 /*
842 * Trust anchor can't inherit.
843 */
844 if (!ossl_assert(x != NULL)) {
845 if (ctx != NULL)
846 ctx->error = X509_V_ERR_UNSPECIFIED;
847 return 0;
848 }
849 if (x->rfc3779_asid != NULL) {
850 if (x->rfc3779_asid->asnum != NULL &&
851 x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit)
852 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
853 if (x->rfc3779_asid->rdi != NULL &&
854 x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit)
855 validation_err(X509_V_ERR_UNNESTED_RESOURCE);
856 }
857
858 done:
859 return ret;
860}
861
862#undef validation_err
863
864/*
865 * RFC 3779 3.3 path validation -- called from X509_verify_cert().
866 */
867int X509v3_asid_validate_path(X509_STORE_CTX *ctx)
868{
869 if (ctx->chain == NULL
870 || sk_X509_num(ctx->chain) == 0
871 || ctx->verify_cb == NULL) {
872 ctx->error = X509_V_ERR_UNSPECIFIED;
873 return 0;
874 }
875 return asid_validate_path_internal(ctx, ctx->chain, NULL);
876}
877
878/*
879 * RFC 3779 3.3 path validation of an extension.
880 * Test whether chain covers extension.
881 */
882int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
883 ASIdentifiers *ext, int allow_inheritance)
884{
885 if (ext == NULL)
886 return 1;
887 if (chain == NULL || sk_X509_num(chain) == 0)
888 return 0;
889 if (!allow_inheritance && X509v3_asid_inherits(ext))
890 return 0;
891 return asid_validate_path_internal(NULL, chain, ext);
892}
893
894#endif /* OPENSSL_NO_RFC3779 */