diff options
Diffstat (limited to 'src/lib/libcrypto/x509/x509_asid.c')
-rw-r--r-- | src/lib/libcrypto/x509/x509_asid.c | 1255 |
1 files changed, 0 insertions, 1255 deletions
diff --git a/src/lib/libcrypto/x509/x509_asid.c b/src/lib/libcrypto/x509/x509_asid.c deleted file mode 100644 index 40ee201a9f..0000000000 --- a/src/lib/libcrypto/x509/x509_asid.c +++ /dev/null | |||
@@ -1,1255 +0,0 @@ | |||
1 | /* $OpenBSD: x509_asid.c,v 1.45 2024/07/13 15:08:58 tb Exp $ */ | ||
2 | /* | ||
3 | * Contributed to the OpenSSL Project by the American Registry for | ||
4 | * Internet Numbers ("ARIN"). | ||
5 | */ | ||
6 | /* ==================================================================== | ||
7 | * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved. | ||
8 | * | ||
9 | * Redistribution and use in source and binary forms, with or without | ||
10 | * modification, are permitted provided that the following conditions | ||
11 | * are met: | ||
12 | * | ||
13 | * 1. Redistributions of source code must retain the above copyright | ||
14 | * notice, this list of conditions and the following disclaimer. | ||
15 | * | ||
16 | * 2. Redistributions in binary form must reproduce the above copyright | ||
17 | * notice, this list of conditions and the following disclaimer in | ||
18 | * the documentation and/or other materials provided with the | ||
19 | * distribution. | ||
20 | * | ||
21 | * 3. All advertising materials mentioning features or use of this | ||
22 | * software must display the following acknowledgment: | ||
23 | * "This product includes software developed by the OpenSSL Project | ||
24 | * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" | ||
25 | * | ||
26 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | ||
27 | * endorse or promote products derived from this software without | ||
28 | * prior written permission. For written permission, please contact | ||
29 | * licensing@OpenSSL.org. | ||
30 | * | ||
31 | * 5. Products derived from this software may not be called "OpenSSL" | ||
32 | * nor may "OpenSSL" appear in their names without prior written | ||
33 | * permission of the OpenSSL Project. | ||
34 | * | ||
35 | * 6. Redistributions of any form whatsoever must retain the following | ||
36 | * acknowledgment: | ||
37 | * "This product includes software developed by the OpenSSL Project | ||
38 | * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" | ||
39 | * | ||
40 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | ||
41 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
43 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | ||
44 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
45 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
46 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
47 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
48 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
49 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
50 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | ||
51 | * OF THE POSSIBILITY OF SUCH DAMAGE. | ||
52 | * ==================================================================== | ||
53 | * | ||
54 | * This product includes cryptographic software written by Eric Young | ||
55 | * (eay@cryptsoft.com). This product includes software written by Tim | ||
56 | * Hudson (tjh@cryptsoft.com). | ||
57 | */ | ||
58 | |||
59 | /* | ||
60 | * Implementation of RFC 3779 section 3.2. | ||
61 | */ | ||
62 | |||
63 | #include <stdio.h> | ||
64 | #include <stdlib.h> | ||
65 | #include <string.h> | ||
66 | |||
67 | #include <openssl/asn1.h> | ||
68 | #include <openssl/asn1t.h> | ||
69 | #include <openssl/bn.h> | ||
70 | #include <openssl/conf.h> | ||
71 | #include <openssl/err.h> | ||
72 | #include <openssl/x509.h> | ||
73 | #include <openssl/x509v3.h> | ||
74 | |||
75 | #include "x509_local.h" | ||
76 | |||
77 | #ifndef OPENSSL_NO_RFC3779 | ||
78 | |||
79 | static const ASN1_TEMPLATE ASRange_seq_tt[] = { | ||
80 | { | ||
81 | .flags = 0, | ||
82 | .tag = 0, | ||
83 | .offset = offsetof(ASRange, min), | ||
84 | .field_name = "min", | ||
85 | .item = &ASN1_INTEGER_it, | ||
86 | }, | ||
87 | { | ||
88 | .flags = 0, | ||
89 | .tag = 0, | ||
90 | .offset = offsetof(ASRange, max), | ||
91 | .field_name = "max", | ||
92 | .item = &ASN1_INTEGER_it, | ||
93 | }, | ||
94 | }; | ||
95 | |||
96 | const ASN1_ITEM ASRange_it = { | ||
97 | .itype = ASN1_ITYPE_SEQUENCE, | ||
98 | .utype = V_ASN1_SEQUENCE, | ||
99 | .templates = ASRange_seq_tt, | ||
100 | .tcount = sizeof(ASRange_seq_tt) / sizeof(ASN1_TEMPLATE), | ||
101 | .funcs = NULL, | ||
102 | .size = sizeof(ASRange), | ||
103 | .sname = "ASRange", | ||
104 | }; | ||
105 | LCRYPTO_ALIAS(ASRange_it); | ||
106 | |||
107 | static const ASN1_TEMPLATE ASIdOrRange_ch_tt[] = { | ||
108 | { | ||
109 | .flags = 0, | ||
110 | .tag = 0, | ||
111 | .offset = offsetof(ASIdOrRange, u.id), | ||
112 | .field_name = "u.id", | ||
113 | .item = &ASN1_INTEGER_it, | ||
114 | }, | ||
115 | { | ||
116 | .flags = 0, | ||
117 | .tag = 0, | ||
118 | .offset = offsetof(ASIdOrRange, u.range), | ||
119 | .field_name = "u.range", | ||
120 | .item = &ASRange_it, | ||
121 | }, | ||
122 | }; | ||
123 | |||
124 | const ASN1_ITEM ASIdOrRange_it = { | ||
125 | .itype = ASN1_ITYPE_CHOICE, | ||
126 | .utype = offsetof(ASIdOrRange, type), | ||
127 | .templates = ASIdOrRange_ch_tt, | ||
128 | .tcount = sizeof(ASIdOrRange_ch_tt) / sizeof(ASN1_TEMPLATE), | ||
129 | .funcs = NULL, | ||
130 | .size = sizeof(ASIdOrRange), | ||
131 | .sname = "ASIdOrRange", | ||
132 | }; | ||
133 | LCRYPTO_ALIAS(ASIdOrRange_it); | ||
134 | |||
135 | static const ASN1_TEMPLATE ASIdentifierChoice_ch_tt[] = { | ||
136 | { | ||
137 | .flags = 0, | ||
138 | .tag = 0, | ||
139 | .offset = offsetof(ASIdentifierChoice, u.inherit), | ||
140 | .field_name = "u.inherit", | ||
141 | .item = &ASN1_NULL_it, | ||
142 | }, | ||
143 | { | ||
144 | .flags = ASN1_TFLG_SEQUENCE_OF, | ||
145 | .tag = 0, | ||
146 | .offset = offsetof(ASIdentifierChoice, u.asIdsOrRanges), | ||
147 | .field_name = "u.asIdsOrRanges", | ||
148 | .item = &ASIdOrRange_it, | ||
149 | }, | ||
150 | }; | ||
151 | |||
152 | const ASN1_ITEM ASIdentifierChoice_it = { | ||
153 | .itype = ASN1_ITYPE_CHOICE, | ||
154 | .utype = offsetof(ASIdentifierChoice, type), | ||
155 | .templates = ASIdentifierChoice_ch_tt, | ||
156 | .tcount = sizeof(ASIdentifierChoice_ch_tt) / sizeof(ASN1_TEMPLATE), | ||
157 | .funcs = NULL, | ||
158 | .size = sizeof(ASIdentifierChoice), | ||
159 | .sname = "ASIdentifierChoice", | ||
160 | }; | ||
161 | LCRYPTO_ALIAS(ASIdentifierChoice_it); | ||
162 | |||
163 | static const ASN1_TEMPLATE ASIdentifiers_seq_tt[] = { | ||
164 | { | ||
165 | .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, | ||
166 | .tag = 0, | ||
167 | .offset = offsetof(ASIdentifiers, asnum), | ||
168 | .field_name = "asnum", | ||
169 | .item = &ASIdentifierChoice_it, | ||
170 | }, | ||
171 | { | ||
172 | .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL, | ||
173 | .tag = 1, | ||
174 | .offset = offsetof(ASIdentifiers, rdi), | ||
175 | .field_name = "rdi", | ||
176 | .item = &ASIdentifierChoice_it, | ||
177 | }, | ||
178 | }; | ||
179 | |||
180 | const ASN1_ITEM ASIdentifiers_it = { | ||
181 | .itype = ASN1_ITYPE_SEQUENCE, | ||
182 | .utype = V_ASN1_SEQUENCE, | ||
183 | .templates = ASIdentifiers_seq_tt, | ||
184 | .tcount = sizeof(ASIdentifiers_seq_tt) / sizeof(ASN1_TEMPLATE), | ||
185 | .funcs = NULL, | ||
186 | .size = sizeof(ASIdentifiers), | ||
187 | .sname = "ASIdentifiers", | ||
188 | }; | ||
189 | LCRYPTO_ALIAS(ASIdentifiers_it); | ||
190 | |||
191 | ASRange * | ||
192 | d2i_ASRange(ASRange **a, const unsigned char **in, long len) | ||
193 | { | ||
194 | return (ASRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
195 | &ASRange_it); | ||
196 | } | ||
197 | LCRYPTO_ALIAS(d2i_ASRange); | ||
198 | |||
199 | int | ||
200 | i2d_ASRange(ASRange *a, unsigned char **out) | ||
201 | { | ||
202 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASRange_it); | ||
203 | } | ||
204 | LCRYPTO_ALIAS(i2d_ASRange); | ||
205 | |||
206 | ASRange * | ||
207 | ASRange_new(void) | ||
208 | { | ||
209 | return (ASRange *)ASN1_item_new(&ASRange_it); | ||
210 | } | ||
211 | LCRYPTO_ALIAS(ASRange_new); | ||
212 | |||
213 | void | ||
214 | ASRange_free(ASRange *a) | ||
215 | { | ||
216 | ASN1_item_free((ASN1_VALUE *)a, &ASRange_it); | ||
217 | } | ||
218 | LCRYPTO_ALIAS(ASRange_free); | ||
219 | |||
220 | ASIdOrRange * | ||
221 | d2i_ASIdOrRange(ASIdOrRange **a, const unsigned char **in, long len) | ||
222 | { | ||
223 | return (ASIdOrRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
224 | &ASIdOrRange_it); | ||
225 | } | ||
226 | LCRYPTO_ALIAS(d2i_ASIdOrRange); | ||
227 | |||
228 | int | ||
229 | i2d_ASIdOrRange(ASIdOrRange *a, unsigned char **out) | ||
230 | { | ||
231 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdOrRange_it); | ||
232 | } | ||
233 | LCRYPTO_ALIAS(i2d_ASIdOrRange); | ||
234 | |||
235 | ASIdOrRange * | ||
236 | ASIdOrRange_new(void) | ||
237 | { | ||
238 | return (ASIdOrRange *)ASN1_item_new(&ASIdOrRange_it); | ||
239 | } | ||
240 | LCRYPTO_ALIAS(ASIdOrRange_new); | ||
241 | |||
242 | void | ||
243 | ASIdOrRange_free(ASIdOrRange *a) | ||
244 | { | ||
245 | ASN1_item_free((ASN1_VALUE *)a, &ASIdOrRange_it); | ||
246 | } | ||
247 | LCRYPTO_ALIAS(ASIdOrRange_free); | ||
248 | |||
249 | ASIdentifierChoice * | ||
250 | d2i_ASIdentifierChoice(ASIdentifierChoice **a, const unsigned char **in, | ||
251 | long len) | ||
252 | { | ||
253 | return (ASIdentifierChoice *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
254 | &ASIdentifierChoice_it); | ||
255 | } | ||
256 | LCRYPTO_ALIAS(d2i_ASIdentifierChoice); | ||
257 | |||
258 | int | ||
259 | i2d_ASIdentifierChoice(ASIdentifierChoice *a, unsigned char **out) | ||
260 | { | ||
261 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdentifierChoice_it); | ||
262 | } | ||
263 | LCRYPTO_ALIAS(i2d_ASIdentifierChoice); | ||
264 | |||
265 | ASIdentifierChoice * | ||
266 | ASIdentifierChoice_new(void) | ||
267 | { | ||
268 | return (ASIdentifierChoice *)ASN1_item_new(&ASIdentifierChoice_it); | ||
269 | } | ||
270 | LCRYPTO_ALIAS(ASIdentifierChoice_new); | ||
271 | |||
272 | void | ||
273 | ASIdentifierChoice_free(ASIdentifierChoice *a) | ||
274 | { | ||
275 | ASN1_item_free((ASN1_VALUE *)a, &ASIdentifierChoice_it); | ||
276 | } | ||
277 | LCRYPTO_ALIAS(ASIdentifierChoice_free); | ||
278 | |||
279 | ASIdentifiers * | ||
280 | d2i_ASIdentifiers(ASIdentifiers **a, const unsigned char **in, long len) | ||
281 | { | ||
282 | return (ASIdentifiers *)ASN1_item_d2i((ASN1_VALUE **)a, in, len, | ||
283 | &ASIdentifiers_it); | ||
284 | } | ||
285 | LCRYPTO_ALIAS(d2i_ASIdentifiers); | ||
286 | |||
287 | int | ||
288 | i2d_ASIdentifiers(ASIdentifiers *a, unsigned char **out) | ||
289 | { | ||
290 | return ASN1_item_i2d((ASN1_VALUE *)a, out, &ASIdentifiers_it); | ||
291 | } | ||
292 | LCRYPTO_ALIAS(i2d_ASIdentifiers); | ||
293 | |||
294 | ASIdentifiers * | ||
295 | ASIdentifiers_new(void) | ||
296 | { | ||
297 | return (ASIdentifiers *)ASN1_item_new(&ASIdentifiers_it); | ||
298 | } | ||
299 | LCRYPTO_ALIAS(ASIdentifiers_new); | ||
300 | |||
301 | void | ||
302 | ASIdentifiers_free(ASIdentifiers *a) | ||
303 | { | ||
304 | ASN1_item_free((ASN1_VALUE *)a, &ASIdentifiers_it); | ||
305 | } | ||
306 | LCRYPTO_ALIAS(ASIdentifiers_free); | ||
307 | |||
308 | /* | ||
309 | * i2r method for an ASIdentifierChoice. | ||
310 | */ | ||
311 | static int | ||
312 | i2r_ASIdentifierChoice(BIO *out, ASIdentifierChoice *choice, int indent, | ||
313 | const char *msg) | ||
314 | { | ||
315 | int i; | ||
316 | char *s; | ||
317 | if (choice == NULL) | ||
318 | return 1; | ||
319 | BIO_printf(out, "%*s%s:\n", indent, "", msg); | ||
320 | switch (choice->type) { | ||
321 | case ASIdentifierChoice_inherit: | ||
322 | BIO_printf(out, "%*sinherit\n", indent + 2, ""); | ||
323 | break; | ||
324 | case ASIdentifierChoice_asIdsOrRanges: | ||
325 | for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges); | ||
326 | i++) { | ||
327 | ASIdOrRange *aor = | ||
328 | sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); | ||
329 | switch (aor->type) { | ||
330 | case ASIdOrRange_id: | ||
331 | if ((s = i2s_ASN1_INTEGER(NULL, aor->u.id)) == | ||
332 | NULL) | ||
333 | return 0; | ||
334 | BIO_printf(out, "%*s%s\n", indent + 2, "", s); | ||
335 | free(s); | ||
336 | break; | ||
337 | case ASIdOrRange_range: | ||
338 | if ((s = i2s_ASN1_INTEGER(NULL, | ||
339 | aor->u.range->min)) == NULL) | ||
340 | return 0; | ||
341 | BIO_printf(out, "%*s%s-", indent + 2, "", s); | ||
342 | free(s); | ||
343 | if ((s = i2s_ASN1_INTEGER(NULL, | ||
344 | aor->u.range->max)) == NULL) | ||
345 | return 0; | ||
346 | BIO_printf(out, "%s\n", s); | ||
347 | free(s); | ||
348 | break; | ||
349 | default: | ||
350 | return 0; | ||
351 | } | ||
352 | } | ||
353 | break; | ||
354 | default: | ||
355 | return 0; | ||
356 | } | ||
357 | return 1; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * i2r method for an ASIdentifier extension. | ||
362 | */ | ||
363 | static int | ||
364 | i2r_ASIdentifiers(const X509V3_EXT_METHOD *method, void *ext, BIO *out, | ||
365 | int indent) | ||
366 | { | ||
367 | ASIdentifiers *asid = ext; | ||
368 | return (i2r_ASIdentifierChoice(out, asid->asnum, indent, | ||
369 | "Autonomous System Numbers") && | ||
370 | i2r_ASIdentifierChoice(out, asid->rdi, indent, | ||
371 | "Routing Domain Identifiers")); | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * Sort comparison function for a sequence of ASIdOrRange elements. | ||
376 | */ | ||
377 | static int | ||
378 | ASIdOrRange_cmp(const ASIdOrRange *const *a_, const ASIdOrRange *const *b_) | ||
379 | { | ||
380 | const ASIdOrRange *a = *a_, *b = *b_; | ||
381 | |||
382 | /* XXX: these asserts need to be replaced */ | ||
383 | OPENSSL_assert((a->type == ASIdOrRange_id && a->u.id != NULL) || | ||
384 | (a->type == ASIdOrRange_range && a->u.range != NULL && | ||
385 | a->u.range->min != NULL && a->u.range->max != NULL)); | ||
386 | |||
387 | OPENSSL_assert((b->type == ASIdOrRange_id && b->u.id != NULL) || | ||
388 | (b->type == ASIdOrRange_range && b->u.range != NULL && | ||
389 | b->u.range->min != NULL && b->u.range->max != NULL)); | ||
390 | |||
391 | if (a->type == ASIdOrRange_id && b->type == ASIdOrRange_id) | ||
392 | return ASN1_INTEGER_cmp(a->u.id, b->u.id); | ||
393 | |||
394 | if (a->type == ASIdOrRange_range && b->type == ASIdOrRange_range) { | ||
395 | int r = ASN1_INTEGER_cmp(a->u.range->min, b->u.range->min); | ||
396 | return r != 0 ? r : ASN1_INTEGER_cmp(a->u.range->max, | ||
397 | b->u.range->max); | ||
398 | } | ||
399 | |||
400 | if (a->type == ASIdOrRange_id) | ||
401 | return ASN1_INTEGER_cmp(a->u.id, b->u.range->min); | ||
402 | else | ||
403 | return ASN1_INTEGER_cmp(a->u.range->min, b->u.id); | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Add an inherit element. | ||
408 | */ | ||
409 | int | ||
410 | X509v3_asid_add_inherit(ASIdentifiers *asid, int which) | ||
411 | { | ||
412 | ASIdentifierChoice **choice; | ||
413 | ASIdentifierChoice *aic = NULL; | ||
414 | int ret = 0; | ||
415 | |||
416 | if (asid == NULL) | ||
417 | goto err; | ||
418 | |||
419 | switch (which) { | ||
420 | case V3_ASID_ASNUM: | ||
421 | choice = &asid->asnum; | ||
422 | break; | ||
423 | case V3_ASID_RDI: | ||
424 | choice = &asid->rdi; | ||
425 | break; | ||
426 | default: | ||
427 | goto err; | ||
428 | } | ||
429 | |||
430 | if (*choice != NULL) { | ||
431 | if ((*choice)->type != ASIdentifierChoice_inherit) | ||
432 | goto err; | ||
433 | } else { | ||
434 | if ((aic = ASIdentifierChoice_new()) == NULL) | ||
435 | goto err; | ||
436 | if ((aic->u.inherit = ASN1_NULL_new()) == NULL) | ||
437 | goto err; | ||
438 | aic->type = ASIdentifierChoice_inherit; | ||
439 | |||
440 | *choice = aic; | ||
441 | aic = NULL; | ||
442 | } | ||
443 | |||
444 | ret = 1; | ||
445 | |||
446 | err: | ||
447 | ASIdentifierChoice_free(aic); | ||
448 | |||
449 | return ret; | ||
450 | } | ||
451 | LCRYPTO_ALIAS(X509v3_asid_add_inherit); | ||
452 | |||
453 | static int | ||
454 | ASIdOrRanges_add_id_or_range(ASIdOrRanges *aors, ASN1_INTEGER *min, | ||
455 | ASN1_INTEGER *max) | ||
456 | { | ||
457 | ASIdOrRange *aor = NULL; | ||
458 | ASRange *asr = NULL; | ||
459 | int ret = 0; | ||
460 | |||
461 | /* Preallocate since we must not fail after sk_ASIdOrRange_push(). */ | ||
462 | if (max != NULL) { | ||
463 | if ((asr = ASRange_new()) == NULL) | ||
464 | goto err; | ||
465 | } | ||
466 | |||
467 | if ((aor = ASIdOrRange_new()) == NULL) | ||
468 | goto err; | ||
469 | if (sk_ASIdOrRange_push(aors, aor) <= 0) | ||
470 | goto err; | ||
471 | |||
472 | if (max == NULL) { | ||
473 | aor->type = ASIdOrRange_id; | ||
474 | aor->u.id = min; | ||
475 | } else { | ||
476 | ASN1_INTEGER_free(asr->min); | ||
477 | asr->min = min; | ||
478 | ASN1_INTEGER_free(asr->max); | ||
479 | asr->max = max; | ||
480 | |||
481 | aor->type = ASIdOrRange_range; | ||
482 | aor->u.range = asr; | ||
483 | asr = NULL; | ||
484 | } | ||
485 | |||
486 | aor = NULL; | ||
487 | |||
488 | ret = 1; | ||
489 | |||
490 | err: | ||
491 | ASIdOrRange_free(aor); | ||
492 | ASRange_free(asr); | ||
493 | |||
494 | return ret; | ||
495 | } | ||
496 | |||
497 | /* | ||
498 | * Add an ID or range to an ASIdentifierChoice. | ||
499 | */ | ||
500 | int | ||
501 | X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which, ASN1_INTEGER *min, | ||
502 | ASN1_INTEGER *max) | ||
503 | { | ||
504 | ASIdentifierChoice **choice; | ||
505 | ASIdentifierChoice *aic = NULL, *new_aic = NULL; | ||
506 | int ret = 0; | ||
507 | |||
508 | if (asid == NULL) | ||
509 | goto err; | ||
510 | |||
511 | switch (which) { | ||
512 | case V3_ASID_ASNUM: | ||
513 | choice = &asid->asnum; | ||
514 | break; | ||
515 | case V3_ASID_RDI: | ||
516 | choice = &asid->rdi; | ||
517 | break; | ||
518 | default: | ||
519 | goto err; | ||
520 | } | ||
521 | |||
522 | if ((aic = *choice) != NULL) { | ||
523 | if (aic->type != ASIdentifierChoice_asIdsOrRanges) | ||
524 | goto err; | ||
525 | } else { | ||
526 | if ((aic = new_aic = ASIdentifierChoice_new()) == NULL) | ||
527 | goto err; | ||
528 | aic->u.asIdsOrRanges = sk_ASIdOrRange_new(ASIdOrRange_cmp); | ||
529 | if (aic->u.asIdsOrRanges == NULL) | ||
530 | goto err; | ||
531 | aic->type = ASIdentifierChoice_asIdsOrRanges; | ||
532 | } | ||
533 | |||
534 | if (!ASIdOrRanges_add_id_or_range(aic->u.asIdsOrRanges, min, max)) | ||
535 | goto err; | ||
536 | |||
537 | *choice = aic; | ||
538 | aic = new_aic = NULL; | ||
539 | |||
540 | ret = 1; | ||
541 | |||
542 | err: | ||
543 | ASIdentifierChoice_free(new_aic); | ||
544 | |||
545 | return ret; | ||
546 | } | ||
547 | LCRYPTO_ALIAS(X509v3_asid_add_id_or_range); | ||
548 | |||
549 | /* | ||
550 | * Extract min and max values from an ASIdOrRange. | ||
551 | */ | ||
552 | static int | ||
553 | extract_min_max(ASIdOrRange *aor, ASN1_INTEGER **min, ASN1_INTEGER **max) | ||
554 | { | ||
555 | switch (aor->type) { | ||
556 | case ASIdOrRange_id: | ||
557 | *min = aor->u.id; | ||
558 | *max = aor->u.id; | ||
559 | return 1; | ||
560 | case ASIdOrRange_range: | ||
561 | *min = aor->u.range->min; | ||
562 | *max = aor->u.range->max; | ||
563 | return 1; | ||
564 | } | ||
565 | *min = NULL; | ||
566 | *max = NULL; | ||
567 | |||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * Check whether an ASIdentifierChoice is in canonical form. | ||
573 | */ | ||
574 | static int | ||
575 | ASIdentifierChoice_is_canonical(ASIdentifierChoice *choice) | ||
576 | { | ||
577 | ASIdOrRange *a, *b; | ||
578 | ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; | ||
579 | ASN1_INTEGER *a_max_plus_one = NULL; | ||
580 | ASN1_INTEGER *orig; | ||
581 | BIGNUM *bn = NULL; | ||
582 | int i, ret = 0; | ||
583 | |||
584 | /* | ||
585 | * Empty element or inheritance is canonical. | ||
586 | */ | ||
587 | if (choice == NULL || choice->type == ASIdentifierChoice_inherit) | ||
588 | return 1; | ||
589 | |||
590 | /* | ||
591 | * If not a list, or if empty list, it's broken. | ||
592 | */ | ||
593 | if (choice->type != ASIdentifierChoice_asIdsOrRanges || | ||
594 | sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) | ||
595 | return 0; | ||
596 | |||
597 | /* | ||
598 | * It's a list, check it. | ||
599 | */ | ||
600 | for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { | ||
601 | a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); | ||
602 | b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); | ||
603 | |||
604 | if (!extract_min_max(a, &a_min, &a_max) || | ||
605 | !extract_min_max(b, &b_min, &b_max)) | ||
606 | goto done; | ||
607 | |||
608 | /* | ||
609 | * Punt misordered list, overlapping start, or inverted range. | ||
610 | */ | ||
611 | if (ASN1_INTEGER_cmp(a_min, b_min) >= 0 || | ||
612 | ASN1_INTEGER_cmp(a_min, a_max) > 0 || | ||
613 | ASN1_INTEGER_cmp(b_min, b_max) > 0) | ||
614 | goto done; | ||
615 | |||
616 | /* | ||
617 | * Calculate a_max + 1 to check for adjacency. | ||
618 | */ | ||
619 | if ((bn == NULL && (bn = BN_new()) == NULL) || | ||
620 | ASN1_INTEGER_to_BN(a_max, bn) == NULL || | ||
621 | !BN_add_word(bn, 1)) { | ||
622 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
623 | goto done; | ||
624 | } | ||
625 | |||
626 | if ((a_max_plus_one = | ||
627 | BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) { | ||
628 | a_max_plus_one = orig; | ||
629 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
630 | goto done; | ||
631 | } | ||
632 | |||
633 | /* | ||
634 | * Punt if adjacent or overlapping. | ||
635 | */ | ||
636 | if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) >= 0) | ||
637 | goto done; | ||
638 | } | ||
639 | |||
640 | /* | ||
641 | * Check for inverted range. | ||
642 | */ | ||
643 | i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; | ||
644 | a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); | ||
645 | if (a != NULL && a->type == ASIdOrRange_range) { | ||
646 | if (!extract_min_max(a, &a_min, &a_max) || | ||
647 | ASN1_INTEGER_cmp(a_min, a_max) > 0) | ||
648 | goto done; | ||
649 | } | ||
650 | |||
651 | ret = 1; | ||
652 | |||
653 | done: | ||
654 | ASN1_INTEGER_free(a_max_plus_one); | ||
655 | BN_free(bn); | ||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | /* | ||
660 | * Check whether an ASIdentifier extension is in canonical form. | ||
661 | */ | ||
662 | int | ||
663 | X509v3_asid_is_canonical(ASIdentifiers *asid) | ||
664 | { | ||
665 | return (asid == NULL || | ||
666 | (ASIdentifierChoice_is_canonical(asid->asnum) && | ||
667 | ASIdentifierChoice_is_canonical(asid->rdi))); | ||
668 | } | ||
669 | LCRYPTO_ALIAS(X509v3_asid_is_canonical); | ||
670 | |||
671 | /* | ||
672 | * Whack an ASIdentifierChoice into canonical form. | ||
673 | */ | ||
674 | static int | ||
675 | ASIdentifierChoice_canonize(ASIdentifierChoice *choice) | ||
676 | { | ||
677 | ASIdOrRange *a, *b; | ||
678 | ASN1_INTEGER *a_min = NULL, *a_max = NULL, *b_min = NULL, *b_max = NULL; | ||
679 | ASN1_INTEGER *a_max_plus_one = NULL; | ||
680 | ASN1_INTEGER *orig; | ||
681 | BIGNUM *bn = NULL; | ||
682 | int i, ret = 0; | ||
683 | |||
684 | /* | ||
685 | * Nothing to do for empty element or inheritance. | ||
686 | */ | ||
687 | if (choice == NULL || choice->type == ASIdentifierChoice_inherit) | ||
688 | return 1; | ||
689 | |||
690 | /* | ||
691 | * If not a list, or if empty list, it's broken. | ||
692 | */ | ||
693 | if (choice->type != ASIdentifierChoice_asIdsOrRanges || | ||
694 | sk_ASIdOrRange_num(choice->u.asIdsOrRanges) == 0) { | ||
695 | X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * We have a non-empty list. Sort it. | ||
701 | */ | ||
702 | sk_ASIdOrRange_sort(choice->u.asIdsOrRanges); | ||
703 | |||
704 | /* | ||
705 | * Now check for errors and suboptimal encoding, rejecting the | ||
706 | * former and fixing the latter. | ||
707 | */ | ||
708 | for (i = 0; i < sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; i++) { | ||
709 | a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); | ||
710 | b = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i + 1); | ||
711 | |||
712 | if (!extract_min_max(a, &a_min, &a_max) || | ||
713 | !extract_min_max(b, &b_min, &b_max)) | ||
714 | goto done; | ||
715 | |||
716 | /* | ||
717 | * Make sure we're properly sorted (paranoia). | ||
718 | */ | ||
719 | if (ASN1_INTEGER_cmp(a_min, b_min) > 0) | ||
720 | goto done; | ||
721 | |||
722 | /* | ||
723 | * Punt inverted ranges. | ||
724 | */ | ||
725 | if (ASN1_INTEGER_cmp(a_min, a_max) > 0 || | ||
726 | ASN1_INTEGER_cmp(b_min, b_max) > 0) | ||
727 | goto done; | ||
728 | |||
729 | /* | ||
730 | * Check for overlaps. | ||
731 | */ | ||
732 | if (ASN1_INTEGER_cmp(a_max, b_min) >= 0) { | ||
733 | X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); | ||
734 | goto done; | ||
735 | } | ||
736 | |||
737 | /* | ||
738 | * Calculate a_max + 1 to check for adjacency. | ||
739 | */ | ||
740 | if ((bn == NULL && (bn = BN_new()) == NULL) || | ||
741 | ASN1_INTEGER_to_BN(a_max, bn) == NULL || | ||
742 | !BN_add_word(bn, 1)) { | ||
743 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
744 | goto done; | ||
745 | } | ||
746 | |||
747 | if ((a_max_plus_one = | ||
748 | BN_to_ASN1_INTEGER(bn, orig = a_max_plus_one)) == NULL) { | ||
749 | a_max_plus_one = orig; | ||
750 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
751 | goto done; | ||
752 | } | ||
753 | |||
754 | /* | ||
755 | * If a and b are adjacent, merge them. | ||
756 | */ | ||
757 | if (ASN1_INTEGER_cmp(a_max_plus_one, b_min) == 0) { | ||
758 | ASRange *r; | ||
759 | switch (a->type) { | ||
760 | case ASIdOrRange_id: | ||
761 | if ((r = calloc(1, sizeof(*r))) == NULL) { | ||
762 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
763 | goto done; | ||
764 | } | ||
765 | r->min = a_min; | ||
766 | r->max = b_max; | ||
767 | a->type = ASIdOrRange_range; | ||
768 | a->u.range = r; | ||
769 | break; | ||
770 | case ASIdOrRange_range: | ||
771 | ASN1_INTEGER_free(a->u.range->max); | ||
772 | a->u.range->max = b_max; | ||
773 | break; | ||
774 | } | ||
775 | switch (b->type) { | ||
776 | case ASIdOrRange_id: | ||
777 | b->u.id = NULL; | ||
778 | break; | ||
779 | case ASIdOrRange_range: | ||
780 | b->u.range->max = NULL; | ||
781 | break; | ||
782 | } | ||
783 | ASIdOrRange_free(b); | ||
784 | (void)sk_ASIdOrRange_delete(choice->u.asIdsOrRanges, | ||
785 | i + 1); | ||
786 | i--; | ||
787 | continue; | ||
788 | } | ||
789 | } | ||
790 | |||
791 | /* | ||
792 | * Check for final inverted range. | ||
793 | */ | ||
794 | i = sk_ASIdOrRange_num(choice->u.asIdsOrRanges) - 1; | ||
795 | a = sk_ASIdOrRange_value(choice->u.asIdsOrRanges, i); | ||
796 | if (a != NULL && a->type == ASIdOrRange_range) { | ||
797 | if (!extract_min_max(a, &a_min, &a_max) || | ||
798 | ASN1_INTEGER_cmp(a_min, a_max) > 0) | ||
799 | goto done; | ||
800 | } | ||
801 | |||
802 | /* Paranoia */ | ||
803 | if (!ASIdentifierChoice_is_canonical(choice)) | ||
804 | goto done; | ||
805 | |||
806 | ret = 1; | ||
807 | |||
808 | done: | ||
809 | ASN1_INTEGER_free(a_max_plus_one); | ||
810 | BN_free(bn); | ||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | /* | ||
815 | * Whack an ASIdentifier extension into canonical form. | ||
816 | */ | ||
817 | int | ||
818 | X509v3_asid_canonize(ASIdentifiers *asid) | ||
819 | { | ||
820 | if (asid == NULL) | ||
821 | return 1; | ||
822 | |||
823 | if (!ASIdentifierChoice_canonize(asid->asnum)) | ||
824 | return 0; | ||
825 | |||
826 | return ASIdentifierChoice_canonize(asid->rdi); | ||
827 | } | ||
828 | LCRYPTO_ALIAS(X509v3_asid_canonize); | ||
829 | |||
830 | /* | ||
831 | * v2i method for an ASIdentifier extension. | ||
832 | */ | ||
833 | static void * | ||
834 | v2i_ASIdentifiers(const struct v3_ext_method *method, struct v3_ext_ctx *ctx, | ||
835 | STACK_OF(CONF_VALUE)*values) | ||
836 | { | ||
837 | ASN1_INTEGER *min = NULL, *max = NULL; | ||
838 | ASIdentifiers *asid = NULL; | ||
839 | int i; | ||
840 | |||
841 | if ((asid = ASIdentifiers_new()) == NULL) { | ||
842 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
843 | return NULL; | ||
844 | } | ||
845 | |||
846 | for (i = 0; i < sk_CONF_VALUE_num(values); i++) { | ||
847 | CONF_VALUE *val = sk_CONF_VALUE_value(values, i); | ||
848 | int i1 = 0, i2 = 0, i3 = 0, is_range = 0, which = 0; | ||
849 | |||
850 | /* | ||
851 | * Figure out whether this is an AS or an RDI. | ||
852 | */ | ||
853 | if (!name_cmp(val->name, "AS")) { | ||
854 | which = V3_ASID_ASNUM; | ||
855 | } else if (!name_cmp(val->name, "RDI")) { | ||
856 | which = V3_ASID_RDI; | ||
857 | } else { | ||
858 | X509V3error(X509V3_R_EXTENSION_NAME_ERROR); | ||
859 | X509V3_conf_err(val); | ||
860 | goto err; | ||
861 | } | ||
862 | |||
863 | /* | ||
864 | * Handle inheritance. | ||
865 | */ | ||
866 | if (strcmp(val->value, "inherit") == 0) { | ||
867 | if (X509v3_asid_add_inherit(asid, which)) | ||
868 | continue; | ||
869 | X509V3error(X509V3_R_INVALID_INHERITANCE); | ||
870 | X509V3_conf_err(val); | ||
871 | goto err; | ||
872 | } | ||
873 | |||
874 | /* | ||
875 | * Number, range, or mistake, pick it apart and figure out which | ||
876 | */ | ||
877 | i1 = strspn(val->value, "0123456789"); | ||
878 | if (val->value[i1] == '\0') { | ||
879 | is_range = 0; | ||
880 | } else { | ||
881 | is_range = 1; | ||
882 | i2 = i1 + strspn(val->value + i1, " \t"); | ||
883 | if (val->value[i2] != '-') { | ||
884 | X509V3error(X509V3_R_INVALID_ASNUMBER); | ||
885 | X509V3_conf_err(val); | ||
886 | goto err; | ||
887 | } | ||
888 | i2++; | ||
889 | i2 = i2 + strspn(val->value + i2, " \t"); | ||
890 | i3 = i2 + strspn(val->value + i2, "0123456789"); | ||
891 | if (val->value[i3] != '\0') { | ||
892 | X509V3error(X509V3_R_INVALID_ASRANGE); | ||
893 | X509V3_conf_err(val); | ||
894 | goto err; | ||
895 | } | ||
896 | } | ||
897 | |||
898 | /* | ||
899 | * Syntax is ok, read and add it. | ||
900 | */ | ||
901 | if (!is_range) { | ||
902 | if (!X509V3_get_value_int(val, &min)) { | ||
903 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
904 | goto err; | ||
905 | } | ||
906 | } else { | ||
907 | char *s = strdup(val->value); | ||
908 | if (s == NULL) { | ||
909 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
910 | goto err; | ||
911 | } | ||
912 | s[i1] = '\0'; | ||
913 | min = s2i_ASN1_INTEGER(NULL, s); | ||
914 | max = s2i_ASN1_INTEGER(NULL, s + i2); | ||
915 | free(s); | ||
916 | if (min == NULL || max == NULL) { | ||
917 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
918 | goto err; | ||
919 | } | ||
920 | if (ASN1_INTEGER_cmp(min, max) > 0) { | ||
921 | X509V3error(X509V3_R_EXTENSION_VALUE_ERROR); | ||
922 | goto err; | ||
923 | } | ||
924 | } | ||
925 | if (!X509v3_asid_add_id_or_range(asid, which, min, max)) { | ||
926 | X509V3error(ERR_R_MALLOC_FAILURE); | ||
927 | goto err; | ||
928 | } | ||
929 | min = max = NULL; | ||
930 | } | ||
931 | |||
932 | /* | ||
933 | * Canonize the result, then we're done. | ||
934 | */ | ||
935 | if (!X509v3_asid_canonize(asid)) | ||
936 | goto err; | ||
937 | return asid; | ||
938 | |||
939 | err: | ||
940 | ASIdentifiers_free(asid); | ||
941 | ASN1_INTEGER_free(min); | ||
942 | ASN1_INTEGER_free(max); | ||
943 | return NULL; | ||
944 | } | ||
945 | |||
946 | /* | ||
947 | * OpenSSL dispatch. | ||
948 | */ | ||
949 | static const X509V3_EXT_METHOD x509v3_ext_sbgp_autonomousSysNum = { | ||
950 | .ext_nid = NID_sbgp_autonomousSysNum, | ||
951 | .ext_flags = 0, | ||
952 | .it = &ASIdentifiers_it, | ||
953 | .ext_new = NULL, | ||
954 | .ext_free = NULL, | ||
955 | .d2i = NULL, | ||
956 | .i2d = NULL, | ||
957 | .i2s = NULL, | ||
958 | .s2i = NULL, | ||
959 | .i2v = NULL, | ||
960 | .v2i = v2i_ASIdentifiers, | ||
961 | .i2r = i2r_ASIdentifiers, | ||
962 | .r2i = NULL, | ||
963 | .usr_data = NULL, | ||
964 | }; | ||
965 | |||
966 | const X509V3_EXT_METHOD * | ||
967 | x509v3_ext_method_sbgp_autonomousSysNum(void) | ||
968 | { | ||
969 | return &x509v3_ext_sbgp_autonomousSysNum; | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * Figure out whether extension uses inheritance. | ||
974 | */ | ||
975 | int | ||
976 | X509v3_asid_inherits(ASIdentifiers *asid) | ||
977 | { | ||
978 | if (asid == NULL) | ||
979 | return 0; | ||
980 | |||
981 | if (asid->asnum != NULL) { | ||
982 | if (asid->asnum->type == ASIdentifierChoice_inherit) | ||
983 | return 1; | ||
984 | } | ||
985 | |||
986 | if (asid->rdi != NULL) { | ||
987 | if (asid->rdi->type == ASIdentifierChoice_inherit) | ||
988 | return 1; | ||
989 | } | ||
990 | |||
991 | return 0; | ||
992 | } | ||
993 | LCRYPTO_ALIAS(X509v3_asid_inherits); | ||
994 | |||
995 | /* | ||
996 | * Figure out whether parent contains child. | ||
997 | */ | ||
998 | static int | ||
999 | asid_contains(ASIdOrRanges *parent, ASIdOrRanges *child) | ||
1000 | { | ||
1001 | ASN1_INTEGER *p_min = NULL, *p_max = NULL, *c_min = NULL, *c_max = NULL; | ||
1002 | int p, c; | ||
1003 | |||
1004 | if (child == NULL || parent == child) | ||
1005 | return 1; | ||
1006 | |||
1007 | if (parent == NULL) | ||
1008 | return 0; | ||
1009 | |||
1010 | p = 0; | ||
1011 | for (c = 0; c < sk_ASIdOrRange_num(child); c++) { | ||
1012 | if (!extract_min_max(sk_ASIdOrRange_value(child, c), &c_min, | ||
1013 | &c_max)) | ||
1014 | return 0; | ||
1015 | for (;; p++) { | ||
1016 | if (p >= sk_ASIdOrRange_num(parent)) | ||
1017 | return 0; | ||
1018 | if (!extract_min_max(sk_ASIdOrRange_value(parent, p), | ||
1019 | &p_min, &p_max)) | ||
1020 | return 0; | ||
1021 | if (ASN1_INTEGER_cmp(p_max, c_max) < 0) | ||
1022 | continue; | ||
1023 | if (ASN1_INTEGER_cmp(p_min, c_min) > 0) | ||
1024 | return 0; | ||
1025 | break; | ||
1026 | } | ||
1027 | } | ||
1028 | |||
1029 | return 1; | ||
1030 | } | ||
1031 | |||
1032 | /* | ||
1033 | * Test whether child is a subset of parent. | ||
1034 | */ | ||
1035 | int | ||
1036 | X509v3_asid_subset(ASIdentifiers *child, ASIdentifiers *parent) | ||
1037 | { | ||
1038 | if (child == NULL || child == parent) | ||
1039 | return 1; | ||
1040 | |||
1041 | if (parent == NULL) | ||
1042 | return 0; | ||
1043 | |||
1044 | if (X509v3_asid_inherits(child) || X509v3_asid_inherits(parent)) | ||
1045 | return 0; | ||
1046 | |||
1047 | if (child->asnum != NULL) { | ||
1048 | if (parent->asnum == NULL) | ||
1049 | return 0; | ||
1050 | |||
1051 | if (!asid_contains(parent->asnum->u.asIdsOrRanges, | ||
1052 | child->asnum->u.asIdsOrRanges)) | ||
1053 | return 0; | ||
1054 | } | ||
1055 | |||
1056 | if (child->rdi != NULL) { | ||
1057 | if (parent->rdi == NULL) | ||
1058 | return 0; | ||
1059 | |||
1060 | if (!asid_contains(parent->rdi->u.asIdsOrRanges, | ||
1061 | child->rdi->u.asIdsOrRanges)) | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | return 1; | ||
1066 | } | ||
1067 | LCRYPTO_ALIAS(X509v3_asid_subset); | ||
1068 | |||
1069 | /* | ||
1070 | * Validation error handling via callback. | ||
1071 | */ | ||
1072 | #define validation_err(_err_) \ | ||
1073 | do { \ | ||
1074 | if (ctx != NULL) { \ | ||
1075 | ctx->error = _err_; \ | ||
1076 | ctx->error_depth = i; \ | ||
1077 | ctx->current_cert = x; \ | ||
1078 | ret = ctx->verify_cb(0, ctx); \ | ||
1079 | } else { \ | ||
1080 | ret = 0; \ | ||
1081 | } \ | ||
1082 | if (!ret) \ | ||
1083 | goto done; \ | ||
1084 | } while (0) | ||
1085 | |||
1086 | /* | ||
1087 | * Core code for RFC 3779 3.3 path validation. | ||
1088 | */ | ||
1089 | static int | ||
1090 | asid_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain, | ||
1091 | ASIdentifiers *ext) | ||
1092 | { | ||
1093 | ASIdOrRanges *child_as = NULL, *child_rdi = NULL; | ||
1094 | int i, ret = 1, inherit_as = 0, inherit_rdi = 0; | ||
1095 | X509 *x; | ||
1096 | |||
1097 | /* We need a non-empty chain to test against. */ | ||
1098 | if (sk_X509_num(chain) <= 0) | ||
1099 | goto err; | ||
1100 | /* We need either a store ctx or an extension to work with. */ | ||
1101 | if (ctx == NULL && ext == NULL) | ||
1102 | goto err; | ||
1103 | /* If there is a store ctx, it needs a verify_cb. */ | ||
1104 | if (ctx != NULL && ctx->verify_cb == NULL) | ||
1105 | goto err; | ||
1106 | |||
1107 | /* | ||
1108 | * Figure out where to start. If we don't have an extension to check, | ||
1109 | * (either extracted from the leaf or passed by the caller), we're done. | ||
1110 | * Otherwise, check canonical form and set up for walking up the chain. | ||
1111 | */ | ||
1112 | if (ext != NULL) { | ||
1113 | i = -1; | ||
1114 | x = NULL; | ||
1115 | if (!X509v3_asid_is_canonical(ext)) | ||
1116 | validation_err(X509_V_ERR_INVALID_EXTENSION); | ||
1117 | } else { | ||
1118 | i = 0; | ||
1119 | x = sk_X509_value(chain, i); | ||
1120 | if ((X509_get_extension_flags(x) & EXFLAG_INVALID) != 0) | ||
1121 | goto done; | ||
1122 | if ((ext = x->rfc3779_asid) == NULL) | ||
1123 | goto done; | ||
1124 | } | ||
1125 | if (ext->asnum != NULL) { | ||
1126 | switch (ext->asnum->type) { | ||
1127 | case ASIdentifierChoice_inherit: | ||
1128 | inherit_as = 1; | ||
1129 | break; | ||
1130 | case ASIdentifierChoice_asIdsOrRanges: | ||
1131 | child_as = ext->asnum->u.asIdsOrRanges; | ||
1132 | break; | ||
1133 | } | ||
1134 | } | ||
1135 | if (ext->rdi != NULL) { | ||
1136 | switch (ext->rdi->type) { | ||
1137 | case ASIdentifierChoice_inherit: | ||
1138 | inherit_rdi = 1; | ||
1139 | break; | ||
1140 | case ASIdentifierChoice_asIdsOrRanges: | ||
1141 | child_rdi = ext->rdi->u.asIdsOrRanges; | ||
1142 | break; | ||
1143 | } | ||
1144 | } | ||
1145 | |||
1146 | /* | ||
1147 | * Now walk up the chain. Extensions must be in canonical form, no | ||
1148 | * cert may list resources that its parent doesn't list. | ||
1149 | */ | ||
1150 | for (i++; i < sk_X509_num(chain); i++) { | ||
1151 | x = sk_X509_value(chain, i); | ||
1152 | |||
1153 | if ((X509_get_extension_flags(x) & EXFLAG_INVALID) != 0) | ||
1154 | validation_err(X509_V_ERR_INVALID_EXTENSION); | ||
1155 | if (x->rfc3779_asid == NULL) { | ||
1156 | if (child_as != NULL || child_rdi != NULL) | ||
1157 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1158 | continue; | ||
1159 | } | ||
1160 | if (x->rfc3779_asid->asnum == NULL && child_as != NULL) { | ||
1161 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1162 | child_as = NULL; | ||
1163 | inherit_as = 0; | ||
1164 | } | ||
1165 | if (x->rfc3779_asid->asnum != NULL && | ||
1166 | x->rfc3779_asid->asnum->type == | ||
1167 | ASIdentifierChoice_asIdsOrRanges) { | ||
1168 | if (inherit_as || | ||
1169 | asid_contains(x->rfc3779_asid->asnum->u.asIdsOrRanges, | ||
1170 | child_as)) { | ||
1171 | child_as = x->rfc3779_asid->asnum->u.asIdsOrRanges; | ||
1172 | inherit_as = 0; | ||
1173 | } else { | ||
1174 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1175 | } | ||
1176 | } | ||
1177 | if (x->rfc3779_asid->rdi == NULL && child_rdi != NULL) { | ||
1178 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1179 | child_rdi = NULL; | ||
1180 | inherit_rdi = 0; | ||
1181 | } | ||
1182 | if (x->rfc3779_asid->rdi != NULL && | ||
1183 | x->rfc3779_asid->rdi->type == ASIdentifierChoice_asIdsOrRanges) { | ||
1184 | if (inherit_rdi || | ||
1185 | asid_contains(x->rfc3779_asid->rdi->u.asIdsOrRanges, | ||
1186 | child_rdi)) { | ||
1187 | child_rdi = x->rfc3779_asid->rdi->u.asIdsOrRanges; | ||
1188 | inherit_rdi = 0; | ||
1189 | } else { | ||
1190 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1191 | } | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | /* | ||
1196 | * Trust anchor can't inherit. | ||
1197 | */ | ||
1198 | |||
1199 | if (x == NULL) | ||
1200 | goto err; | ||
1201 | |||
1202 | if (x->rfc3779_asid != NULL) { | ||
1203 | if (x->rfc3779_asid->asnum != NULL && | ||
1204 | x->rfc3779_asid->asnum->type == ASIdentifierChoice_inherit) | ||
1205 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1206 | if (x->rfc3779_asid->rdi != NULL && | ||
1207 | x->rfc3779_asid->rdi->type == ASIdentifierChoice_inherit) | ||
1208 | validation_err(X509_V_ERR_UNNESTED_RESOURCE); | ||
1209 | } | ||
1210 | |||
1211 | done: | ||
1212 | return ret; | ||
1213 | |||
1214 | err: | ||
1215 | if (ctx != NULL) | ||
1216 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | #undef validation_err | ||
1222 | |||
1223 | /* | ||
1224 | * RFC 3779 3.3 path validation -- called from X509_verify_cert(). | ||
1225 | */ | ||
1226 | int | ||
1227 | X509v3_asid_validate_path(X509_STORE_CTX *ctx) | ||
1228 | { | ||
1229 | if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) { | ||
1230 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1231 | return 0; | ||
1232 | } | ||
1233 | return asid_validate_path_internal(ctx, ctx->chain, NULL); | ||
1234 | } | ||
1235 | LCRYPTO_ALIAS(X509v3_asid_validate_path); | ||
1236 | |||
1237 | /* | ||
1238 | * RFC 3779 3.3 path validation of an extension. | ||
1239 | * Test whether chain covers extension. | ||
1240 | */ | ||
1241 | int | ||
1242 | X509v3_asid_validate_resource_set(STACK_OF(X509) *chain, ASIdentifiers *ext, | ||
1243 | int allow_inheritance) | ||
1244 | { | ||
1245 | if (ext == NULL) | ||
1246 | return 1; | ||
1247 | if (sk_X509_num(chain) <= 0) | ||
1248 | return 0; | ||
1249 | if (!allow_inheritance && X509v3_asid_inherits(ext)) | ||
1250 | return 0; | ||
1251 | return asid_validate_path_internal(NULL, chain, ext); | ||
1252 | } | ||
1253 | LCRYPTO_ALIAS(X509v3_asid_validate_resource_set); | ||
1254 | |||
1255 | #endif /* OPENSSL_NO_RFC3779 */ | ||