1*8b5faa71Stb /* $OpenBSD: x509_addr.c,v 1.93 2024/07/13 15:08:58 tb Exp $ */
20b5aa37fSjob /*
3f49a1506Stb * Contributed to the OpenSSL Project by the American Registry for
4f49a1506Stb * Internet Numbers ("ARIN").
5f49a1506Stb */
6f49a1506Stb /* ====================================================================
7f49a1506Stb * Copyright (c) 2006-2016 The OpenSSL Project. All rights reserved.
80b5aa37fSjob *
9f49a1506Stb * Redistribution and use in source and binary forms, with or without
10f49a1506Stb * modification, are permitted provided that the following conditions
11f49a1506Stb * are met:
12f49a1506Stb *
13f49a1506Stb * 1. Redistributions of source code must retain the above copyright
14f49a1506Stb * notice, this list of conditions and the following disclaimer.
15f49a1506Stb *
16f49a1506Stb * 2. Redistributions in binary form must reproduce the above copyright
17f49a1506Stb * notice, this list of conditions and the following disclaimer in
18f49a1506Stb * the documentation and/or other materials provided with the
19f49a1506Stb * distribution.
20f49a1506Stb *
21f49a1506Stb * 3. All advertising materials mentioning features or use of this
22f49a1506Stb * software must display the following acknowledgment:
23f49a1506Stb * "This product includes software developed by the OpenSSL Project
24f49a1506Stb * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25f49a1506Stb *
26f49a1506Stb * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27f49a1506Stb * endorse or promote products derived from this software without
28f49a1506Stb * prior written permission. For written permission, please contact
29f49a1506Stb * licensing@OpenSSL.org.
30f49a1506Stb *
31f49a1506Stb * 5. Products derived from this software may not be called "OpenSSL"
32f49a1506Stb * nor may "OpenSSL" appear in their names without prior written
33f49a1506Stb * permission of the OpenSSL Project.
34f49a1506Stb *
35f49a1506Stb * 6. Redistributions of any form whatsoever must retain the following
36f49a1506Stb * acknowledgment:
37f49a1506Stb * "This product includes software developed by the OpenSSL Project
38f49a1506Stb * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39f49a1506Stb *
40f49a1506Stb * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41f49a1506Stb * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42f49a1506Stb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43f49a1506Stb * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44f49a1506Stb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45f49a1506Stb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46f49a1506Stb * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47f49a1506Stb * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48f49a1506Stb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49f49a1506Stb * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50f49a1506Stb * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51f49a1506Stb * OF THE POSSIBILITY OF SUCH DAMAGE.
52f49a1506Stb * ====================================================================
53f49a1506Stb *
54f49a1506Stb * This product includes cryptographic software written by Eric Young
55f49a1506Stb * (eay@cryptsoft.com). This product includes software written by Tim
56f49a1506Stb * Hudson (tjh@cryptsoft.com).
570b5aa37fSjob */
580b5aa37fSjob
590b5aa37fSjob /*
600b5aa37fSjob * Implementation of RFC 3779 section 2.2.
610b5aa37fSjob */
620b5aa37fSjob
635420e9ccStb #include <limits.h>
640b5aa37fSjob #include <stdio.h>
650b5aa37fSjob #include <stdlib.h>
665f135508Sjob #include <string.h>
670b5aa37fSjob
680b5aa37fSjob #include <openssl/asn1.h>
690b5aa37fSjob #include <openssl/asn1t.h>
700b5aa37fSjob #include <openssl/buffer.h>
71bb6956c3Sjob #include <openssl/conf.h>
721ec75446Sjob #include <openssl/err.h>
73bb6956c3Sjob #include <openssl/x509.h>
740b5aa37fSjob #include <openssl/x509v3.h>
75bb6956c3Sjob
76c9675a23Stb #include "asn1_local.h"
77efb484e8Stb #include "bytestring.h"
78c9675a23Stb #include "x509_local.h"
79838f0b6dStb
800b5aa37fSjob #ifndef OPENSSL_NO_RFC3779
810b5aa37fSjob
820b5aa37fSjob /*
830b5aa37fSjob * OpenSSL ASN.1 template translation of RFC 3779 2.2.3.
840b5aa37fSjob */
850b5aa37fSjob
864dab7425Sjob static const ASN1_TEMPLATE IPAddressRange_seq_tt[] = {
874dab7425Sjob {
884dab7425Sjob .flags = 0,
894dab7425Sjob .tag = 0,
904dab7425Sjob .offset = offsetof(IPAddressRange, min),
914dab7425Sjob .field_name = "min",
924dab7425Sjob .item = &ASN1_BIT_STRING_it,
934dab7425Sjob },
944dab7425Sjob {
954dab7425Sjob .flags = 0,
964dab7425Sjob .tag = 0,
974dab7425Sjob .offset = offsetof(IPAddressRange, max),
984dab7425Sjob .field_name = "max",
994dab7425Sjob .item = &ASN1_BIT_STRING_it,
1004dab7425Sjob },
1014dab7425Sjob };
1020b5aa37fSjob
1034dab7425Sjob const ASN1_ITEM IPAddressRange_it = {
1044dab7425Sjob .itype = ASN1_ITYPE_SEQUENCE,
1054dab7425Sjob .utype = V_ASN1_SEQUENCE,
1064dab7425Sjob .templates = IPAddressRange_seq_tt,
1074dab7425Sjob .tcount = sizeof(IPAddressRange_seq_tt) / sizeof(ASN1_TEMPLATE),
1084dab7425Sjob .funcs = NULL,
1094dab7425Sjob .size = sizeof(IPAddressRange),
1104dab7425Sjob .sname = "IPAddressRange",
1114dab7425Sjob };
112c0ebdaf2Sbeck LCRYPTO_ALIAS(IPAddressRange_it);
1130b5aa37fSjob
1144dab7425Sjob static const ASN1_TEMPLATE IPAddressOrRange_ch_tt[] = {
1154dab7425Sjob {
1164dab7425Sjob .flags = 0,
1174dab7425Sjob .tag = 0,
1184dab7425Sjob .offset = offsetof(IPAddressOrRange, u.addressPrefix),
1194dab7425Sjob .field_name = "u.addressPrefix",
1204dab7425Sjob .item = &ASN1_BIT_STRING_it,
1214dab7425Sjob },
1224dab7425Sjob {
1234dab7425Sjob .flags = 0,
1244dab7425Sjob .tag = 0,
1254dab7425Sjob .offset = offsetof(IPAddressOrRange, u.addressRange),
1264dab7425Sjob .field_name = "u.addressRange",
1274dab7425Sjob .item = &IPAddressRange_it,
1284dab7425Sjob },
1294dab7425Sjob };
1300b5aa37fSjob
1314dab7425Sjob const ASN1_ITEM IPAddressOrRange_it = {
1324dab7425Sjob .itype = ASN1_ITYPE_CHOICE,
1334dab7425Sjob .utype = offsetof(IPAddressOrRange, type),
1344dab7425Sjob .templates = IPAddressOrRange_ch_tt,
1354dab7425Sjob .tcount = sizeof(IPAddressOrRange_ch_tt) / sizeof(ASN1_TEMPLATE),
1364dab7425Sjob .funcs = NULL,
1374dab7425Sjob .size = sizeof(IPAddressOrRange),
1384dab7425Sjob .sname = "IPAddressOrRange",
1394dab7425Sjob };
140c0ebdaf2Sbeck LCRYPTO_ALIAS(IPAddressOrRange_it);
1410b5aa37fSjob
1424dab7425Sjob static const ASN1_TEMPLATE IPAddressChoice_ch_tt[] = {
1434dab7425Sjob {
1444dab7425Sjob .flags = 0,
1454dab7425Sjob .tag = 0,
1464dab7425Sjob .offset = offsetof(IPAddressChoice, u.inherit),
1474dab7425Sjob .field_name = "u.inherit",
1484dab7425Sjob .item = &ASN1_NULL_it,
1494dab7425Sjob },
1504dab7425Sjob {
1514dab7425Sjob .flags = ASN1_TFLG_SEQUENCE_OF,
1524dab7425Sjob .tag = 0,
1534dab7425Sjob .offset = offsetof(IPAddressChoice, u.addressesOrRanges),
1544dab7425Sjob .field_name = "u.addressesOrRanges",
1554dab7425Sjob .item = &IPAddressOrRange_it,
1564dab7425Sjob },
1574dab7425Sjob };
1584dab7425Sjob
1594dab7425Sjob const ASN1_ITEM IPAddressChoice_it = {
1604dab7425Sjob .itype = ASN1_ITYPE_CHOICE,
1614dab7425Sjob .utype = offsetof(IPAddressChoice, type),
1624dab7425Sjob .templates = IPAddressChoice_ch_tt,
1634dab7425Sjob .tcount = sizeof(IPAddressChoice_ch_tt) / sizeof(ASN1_TEMPLATE),
1644dab7425Sjob .funcs = NULL,
1654dab7425Sjob .size = sizeof(IPAddressChoice),
1664dab7425Sjob .sname = "IPAddressChoice",
1674dab7425Sjob };
168c0ebdaf2Sbeck LCRYPTO_ALIAS(IPAddressChoice_it);
1694dab7425Sjob
1704dab7425Sjob static const ASN1_TEMPLATE IPAddressFamily_seq_tt[] = {
1714dab7425Sjob {
1724dab7425Sjob .flags = 0,
1734dab7425Sjob .tag = 0,
1744dab7425Sjob .offset = offsetof(IPAddressFamily, addressFamily),
1754dab7425Sjob .field_name = "addressFamily",
1764dab7425Sjob .item = &ASN1_OCTET_STRING_it,
1774dab7425Sjob },
1784dab7425Sjob {
1794dab7425Sjob .flags = 0,
1804dab7425Sjob .tag = 0,
1814dab7425Sjob .offset = offsetof(IPAddressFamily, ipAddressChoice),
1824dab7425Sjob .field_name = "ipAddressChoice",
1834dab7425Sjob .item = &IPAddressChoice_it,
1844dab7425Sjob },
1854dab7425Sjob };
1864dab7425Sjob
1874dab7425Sjob const ASN1_ITEM IPAddressFamily_it = {
1884dab7425Sjob .itype = ASN1_ITYPE_SEQUENCE,
1894dab7425Sjob .utype = V_ASN1_SEQUENCE,
1904dab7425Sjob .templates = IPAddressFamily_seq_tt,
1914dab7425Sjob .tcount = sizeof(IPAddressFamily_seq_tt) / sizeof(ASN1_TEMPLATE),
1924dab7425Sjob .funcs = NULL,
1934dab7425Sjob .size = sizeof(IPAddressFamily),
1944dab7425Sjob .sname = "IPAddressFamily",
1954dab7425Sjob };
196c0ebdaf2Sbeck LCRYPTO_ALIAS(IPAddressFamily_it);
1974dab7425Sjob
198e42fe416Sjob static const ASN1_TEMPLATE IPAddrBlocks_item_tt = {
199e42fe416Sjob .flags = ASN1_TFLG_SEQUENCE_OF,
200e42fe416Sjob .tag = 0,
201e42fe416Sjob .offset = 0,
202e42fe416Sjob .field_name = "IPAddrBlocks",
203e42fe416Sjob .item = &IPAddressFamily_it,
204e42fe416Sjob };
2050b5aa37fSjob
20646b061f5Sjob static const ASN1_ITEM IPAddrBlocks_it = {
20746b061f5Sjob .itype = ASN1_ITYPE_PRIMITIVE,
20846b061f5Sjob .utype = -1,
20946b061f5Sjob .templates = &IPAddrBlocks_item_tt,
21046b061f5Sjob .tcount = 0,
21146b061f5Sjob .funcs = NULL,
21246b061f5Sjob .size = 0,
21346b061f5Sjob .sname = "IPAddrBlocks",
21446b061f5Sjob };
21546b061f5Sjob
216306ab8c3Sjob IPAddressRange *
d2i_IPAddressRange(IPAddressRange ** a,const unsigned char ** in,long len)217306ab8c3Sjob d2i_IPAddressRange(IPAddressRange **a, const unsigned char **in, long len)
218306ab8c3Sjob {
219306ab8c3Sjob return (IPAddressRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
2201993757bSjob &IPAddressRange_it);
221306ab8c3Sjob }
222cedac418Stb LCRYPTO_ALIAS(d2i_IPAddressRange);
223306ab8c3Sjob
224306ab8c3Sjob int
i2d_IPAddressRange(IPAddressRange * a,unsigned char ** out)225306ab8c3Sjob i2d_IPAddressRange(IPAddressRange *a, unsigned char **out)
226306ab8c3Sjob {
2271993757bSjob return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressRange_it);
228306ab8c3Sjob }
229cedac418Stb LCRYPTO_ALIAS(i2d_IPAddressRange);
230306ab8c3Sjob
231306ab8c3Sjob IPAddressRange *
IPAddressRange_new(void)232306ab8c3Sjob IPAddressRange_new(void)
233306ab8c3Sjob {
2341993757bSjob return (IPAddressRange *)ASN1_item_new(&IPAddressRange_it);
235306ab8c3Sjob }
236cedac418Stb LCRYPTO_ALIAS(IPAddressRange_new);
237306ab8c3Sjob
238306ab8c3Sjob void
IPAddressRange_free(IPAddressRange * a)239306ab8c3Sjob IPAddressRange_free(IPAddressRange *a)
240306ab8c3Sjob {
2411993757bSjob ASN1_item_free((ASN1_VALUE *)a, &IPAddressRange_it);
242306ab8c3Sjob }
243cedac418Stb LCRYPTO_ALIAS(IPAddressRange_free);
244306ab8c3Sjob
245306ab8c3Sjob IPAddressOrRange *
d2i_IPAddressOrRange(IPAddressOrRange ** a,const unsigned char ** in,long len)246306ab8c3Sjob d2i_IPAddressOrRange(IPAddressOrRange **a, const unsigned char **in, long len)
247306ab8c3Sjob {
248306ab8c3Sjob return (IPAddressOrRange *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
2491993757bSjob &IPAddressOrRange_it);
250306ab8c3Sjob }
251cedac418Stb LCRYPTO_ALIAS(d2i_IPAddressOrRange);
252306ab8c3Sjob
253306ab8c3Sjob int
i2d_IPAddressOrRange(IPAddressOrRange * a,unsigned char ** out)254306ab8c3Sjob i2d_IPAddressOrRange(IPAddressOrRange *a, unsigned char **out)
255306ab8c3Sjob {
2561993757bSjob return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressOrRange_it);
257306ab8c3Sjob }
258cedac418Stb LCRYPTO_ALIAS(i2d_IPAddressOrRange);
259306ab8c3Sjob
260306ab8c3Sjob IPAddressOrRange *
IPAddressOrRange_new(void)261306ab8c3Sjob IPAddressOrRange_new(void)
262306ab8c3Sjob {
2631993757bSjob return (IPAddressOrRange *)ASN1_item_new(&IPAddressOrRange_it);
264306ab8c3Sjob }
265cedac418Stb LCRYPTO_ALIAS(IPAddressOrRange_new);
266306ab8c3Sjob
267306ab8c3Sjob void
IPAddressOrRange_free(IPAddressOrRange * a)2681a94ae9bSjob IPAddressOrRange_free(IPAddressOrRange *a)
2691a94ae9bSjob {
2701993757bSjob ASN1_item_free((ASN1_VALUE *)a, &IPAddressOrRange_it);
271306ab8c3Sjob }
272cedac418Stb LCRYPTO_ALIAS(IPAddressOrRange_free);
273306ab8c3Sjob
274306ab8c3Sjob IPAddressChoice *
d2i_IPAddressChoice(IPAddressChoice ** a,const unsigned char ** in,long len)275306ab8c3Sjob d2i_IPAddressChoice(IPAddressChoice **a, const unsigned char **in, long len)
276306ab8c3Sjob {
277306ab8c3Sjob return (IPAddressChoice *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
2781993757bSjob &IPAddressChoice_it);
279306ab8c3Sjob }
280cedac418Stb LCRYPTO_ALIAS(d2i_IPAddressChoice);
281306ab8c3Sjob
282306ab8c3Sjob int
i2d_IPAddressChoice(IPAddressChoice * a,unsigned char ** out)283306ab8c3Sjob i2d_IPAddressChoice(IPAddressChoice *a, unsigned char **out)
284306ab8c3Sjob {
2851993757bSjob return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressChoice_it);
286306ab8c3Sjob }
287cedac418Stb LCRYPTO_ALIAS(i2d_IPAddressChoice);
288306ab8c3Sjob
289306ab8c3Sjob IPAddressChoice *
IPAddressChoice_new(void)290306ab8c3Sjob IPAddressChoice_new(void)
291306ab8c3Sjob {
2921993757bSjob return (IPAddressChoice *)ASN1_item_new(&IPAddressChoice_it);
293306ab8c3Sjob }
294cedac418Stb LCRYPTO_ALIAS(IPAddressChoice_new);
295306ab8c3Sjob
296306ab8c3Sjob void
IPAddressChoice_free(IPAddressChoice * a)297306ab8c3Sjob IPAddressChoice_free(IPAddressChoice *a)
298306ab8c3Sjob {
2991993757bSjob ASN1_item_free((ASN1_VALUE *)a, &IPAddressChoice_it);
300306ab8c3Sjob }
301cedac418Stb LCRYPTO_ALIAS(IPAddressChoice_free);
302306ab8c3Sjob
303306ab8c3Sjob IPAddressFamily *
d2i_IPAddressFamily(IPAddressFamily ** a,const unsigned char ** in,long len)304306ab8c3Sjob d2i_IPAddressFamily(IPAddressFamily **a, const unsigned char **in, long len)
305306ab8c3Sjob {
306306ab8c3Sjob return (IPAddressFamily *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
3071993757bSjob &IPAddressFamily_it);
308306ab8c3Sjob }
309cedac418Stb LCRYPTO_ALIAS(d2i_IPAddressFamily);
310306ab8c3Sjob
311306ab8c3Sjob int
i2d_IPAddressFamily(IPAddressFamily * a,unsigned char ** out)312306ab8c3Sjob i2d_IPAddressFamily(IPAddressFamily *a, unsigned char **out)
313306ab8c3Sjob {
3141993757bSjob return ASN1_item_i2d((ASN1_VALUE *)a, out, &IPAddressFamily_it);
315306ab8c3Sjob }
316cedac418Stb LCRYPTO_ALIAS(i2d_IPAddressFamily);
317306ab8c3Sjob
318306ab8c3Sjob IPAddressFamily *
IPAddressFamily_new(void)319306ab8c3Sjob IPAddressFamily_new(void)
320306ab8c3Sjob {
3211993757bSjob return (IPAddressFamily *)ASN1_item_new(&IPAddressFamily_it);
322306ab8c3Sjob }
323cedac418Stb LCRYPTO_ALIAS(IPAddressFamily_new);
324306ab8c3Sjob
325306ab8c3Sjob void
IPAddressFamily_free(IPAddressFamily * a)326306ab8c3Sjob IPAddressFamily_free(IPAddressFamily *a)
327306ab8c3Sjob {
3281993757bSjob ASN1_item_free((ASN1_VALUE *)a, &IPAddressFamily_it);
329306ab8c3Sjob }
330cedac418Stb LCRYPTO_ALIAS(IPAddressFamily_free);
3310b5aa37fSjob
3320b5aa37fSjob /*
333ddc1bf0aStb * Convenience accessors for IPAddressFamily.
334ddc1bf0aStb */
335ddc1bf0aStb
336ddc1bf0aStb static int
IPAddressFamily_type(IPAddressFamily * af)33770818e4aStb IPAddressFamily_type(IPAddressFamily *af)
338ddc1bf0aStb {
33970818e4aStb /* XXX - can af->ipAddressChoice == NULL actually happen? */
34070818e4aStb if (af == NULL || af->ipAddressChoice == NULL)
341ddc1bf0aStb return -1;
342ddc1bf0aStb
34370818e4aStb switch (af->ipAddressChoice->type) {
344ddc1bf0aStb case IPAddressChoice_inherit:
345ddc1bf0aStb case IPAddressChoice_addressesOrRanges:
34670818e4aStb return af->ipAddressChoice->type;
347ddc1bf0aStb default:
348ddc1bf0aStb return -1;
349ddc1bf0aStb }
350ddc1bf0aStb }
351ddc1bf0aStb
352ddc1bf0aStb static IPAddressOrRanges *
IPAddressFamily_addressesOrRanges(IPAddressFamily * af)35370818e4aStb IPAddressFamily_addressesOrRanges(IPAddressFamily *af)
354ddc1bf0aStb {
35570818e4aStb if (IPAddressFamily_type(af) == IPAddressChoice_addressesOrRanges)
35670818e4aStb return af->ipAddressChoice->u.addressesOrRanges;
357ddc1bf0aStb
358ddc1bf0aStb return NULL;
359ddc1bf0aStb }
360ddc1bf0aStb
361ddc1bf0aStb static ASN1_NULL *
IPAddressFamily_inheritance(IPAddressFamily * af)36270818e4aStb IPAddressFamily_inheritance(IPAddressFamily *af)
363ddc1bf0aStb {
36470818e4aStb if (IPAddressFamily_type(af) == IPAddressChoice_inherit)
36570818e4aStb return af->ipAddressChoice->u.inherit;
366ddc1bf0aStb
367ddc1bf0aStb return NULL;
368ddc1bf0aStb }
369ddc1bf0aStb
370ddc1bf0aStb static int
IPAddressFamily_set_inheritance(IPAddressFamily * af)37170818e4aStb IPAddressFamily_set_inheritance(IPAddressFamily *af)
372ddc1bf0aStb {
37370818e4aStb if (IPAddressFamily_addressesOrRanges(af) != NULL)
374ddc1bf0aStb return 0;
375ddc1bf0aStb
37670818e4aStb if (IPAddressFamily_inheritance(af) != NULL)
377ddc1bf0aStb return 1;
378ddc1bf0aStb
37970818e4aStb if ((af->ipAddressChoice->u.inherit = ASN1_NULL_new()) == NULL)
380ddc1bf0aStb return 0;
38170818e4aStb af->ipAddressChoice->type = IPAddressChoice_inherit;
382ddc1bf0aStb
383ddc1bf0aStb return 1;
384ddc1bf0aStb }
385ddc1bf0aStb
386ddc1bf0aStb /*
3870b5aa37fSjob * How much buffer space do we need for a raw address?
3880b5aa37fSjob */
3890b5aa37fSjob #define ADDR_RAW_BUF_LEN 16
3900b5aa37fSjob
3910b5aa37fSjob /*
3920b5aa37fSjob * What's the address length associated with this AFI?
3930b5aa37fSjob */
3941a94ae9bSjob static int
length_from_afi(const unsigned afi,int * length)3952b4f9a55Stb length_from_afi(const unsigned afi, int *length)
3960b5aa37fSjob {
3970b5aa37fSjob switch (afi) {
3980b5aa37fSjob case IANA_AFI_IPV4:
3992b4f9a55Stb *length = 4;
4002b4f9a55Stb return 1;
4010b5aa37fSjob case IANA_AFI_IPV6:
4022b4f9a55Stb *length = 16;
4032b4f9a55Stb return 1;
4040b5aa37fSjob default:
4052b4f9a55Stb *length = 0;
4060b5aa37fSjob return 0;
4070b5aa37fSjob }
4080b5aa37fSjob }
4090b5aa37fSjob
4100b5aa37fSjob /*
411a4b2db38Stb * Get AFI and optional SAFI from an IPAddressFamily. All three out arguments
412a4b2db38Stb * are optional; if |out_safi| is non-NULL, |safi_is_set| must be non-NULL.
413a4b2db38Stb */
414a4b2db38Stb static int
IPAddressFamily_afi_safi(const IPAddressFamily * af,uint16_t * out_afi,uint8_t * out_safi,int * safi_is_set)41570818e4aStb IPAddressFamily_afi_safi(const IPAddressFamily *af, uint16_t *out_afi,
416a4b2db38Stb uint8_t *out_safi, int *safi_is_set)
417a4b2db38Stb {
418a4b2db38Stb CBS cbs;
419a4b2db38Stb uint16_t afi;
420a4b2db38Stb uint8_t safi = 0;
421a4b2db38Stb int got_safi = 0;
422a4b2db38Stb
423d1c8496fStb if (out_afi != NULL)
424d1c8496fStb *out_afi = 0;
425d1c8496fStb if (out_safi != NULL) {
426d1c8496fStb *out_safi = 0;
427d1c8496fStb *safi_is_set = 0;
428d1c8496fStb }
429d1c8496fStb
43070818e4aStb CBS_init(&cbs, af->addressFamily->data, af->addressFamily->length);
431a4b2db38Stb
432a4b2db38Stb if (!CBS_get_u16(&cbs, &afi))
433a4b2db38Stb return 0;
434a4b2db38Stb
4352b4f9a55Stb if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6)
4362b4f9a55Stb return 0;
4372b4f9a55Stb
438a4b2db38Stb /* Fetch the optional SAFI. */
439a4b2db38Stb if (CBS_len(&cbs) != 0) {
440a4b2db38Stb if (!CBS_get_u8(&cbs, &safi))
441a4b2db38Stb return 0;
442a4b2db38Stb got_safi = 1;
443a4b2db38Stb }
444a4b2db38Stb
445a4b2db38Stb /* If there's anything left, it's garbage. */
446a4b2db38Stb if (CBS_len(&cbs) != 0)
447a4b2db38Stb return 0;
448a4b2db38Stb
449a4b2db38Stb /* XXX - error on reserved AFI/SAFI? */
450a4b2db38Stb
451a4b2db38Stb if (out_afi != NULL)
452a4b2db38Stb *out_afi = afi;
453a4b2db38Stb
454a4b2db38Stb if (out_safi != NULL) {
455a4b2db38Stb *out_safi = safi;
456a4b2db38Stb *safi_is_set = got_safi;
457a4b2db38Stb }
458a4b2db38Stb
459a4b2db38Stb return 1;
460a4b2db38Stb }
461a4b2db38Stb
462a4b2db38Stb static int
IPAddressFamily_afi(const IPAddressFamily * af,uint16_t * out_afi)46370818e4aStb IPAddressFamily_afi(const IPAddressFamily *af, uint16_t *out_afi)
464a4b2db38Stb {
46570818e4aStb return IPAddressFamily_afi_safi(af, out_afi, NULL, NULL);
466a4b2db38Stb }
467a4b2db38Stb
468a4b2db38Stb static int
IPAddressFamily_afi_is_valid(const IPAddressFamily * af)46970818e4aStb IPAddressFamily_afi_is_valid(const IPAddressFamily *af)
470a4b2db38Stb {
47170818e4aStb return IPAddressFamily_afi_safi(af, NULL, NULL, NULL);
472a4b2db38Stb }
473a4b2db38Stb
474a4b2db38Stb static int
IPAddressFamily_afi_length(const IPAddressFamily * af,int * out_length)47570818e4aStb IPAddressFamily_afi_length(const IPAddressFamily *af, int *out_length)
476a4b2db38Stb {
477a4b2db38Stb uint16_t afi;
478a4b2db38Stb
479a4b2db38Stb *out_length = 0;
480a4b2db38Stb
48170818e4aStb if (!IPAddressFamily_afi(af, &afi))
482a4b2db38Stb return 0;
483a4b2db38Stb
4842b4f9a55Stb return length_from_afi(afi, out_length);
485a4b2db38Stb }
486a4b2db38Stb
487063160b2Stb #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
488063160b2Stb
489063160b2Stb /*
490063160b2Stb * Sort comparison function for a sequence of IPAddressFamily.
491063160b2Stb *
492063160b2Stb * The last paragraph of RFC 3779 2.2.3.3 is slightly ambiguous about
493063160b2Stb * the ordering: I can read it as meaning that IPv6 without a SAFI
494063160b2Stb * comes before IPv4 with a SAFI, which seems pretty weird. The
495063160b2Stb * examples in appendix B suggest that the author intended the
496063160b2Stb * null-SAFI rule to apply only within a single AFI, which is what I
497063160b2Stb * would have expected and is what the following code implements.
498063160b2Stb */
499063160b2Stb static int
IPAddressFamily_cmp(const IPAddressFamily * const * a_,const IPAddressFamily * const * b_)500063160b2Stb IPAddressFamily_cmp(const IPAddressFamily *const *a_,
501063160b2Stb const IPAddressFamily *const *b_)
502063160b2Stb {
503063160b2Stb const ASN1_OCTET_STRING *a = (*a_)->addressFamily;
504063160b2Stb const ASN1_OCTET_STRING *b = (*b_)->addressFamily;
505063160b2Stb int len, cmp;
506063160b2Stb
507063160b2Stb len = MINIMUM(a->length, b->length);
508063160b2Stb
509063160b2Stb if ((cmp = memcmp(a->data, b->data, len)) != 0)
510063160b2Stb return cmp;
511063160b2Stb
512063160b2Stb return a->length - b->length;
513063160b2Stb }
514063160b2Stb
5152ad22f62Stb static IPAddressFamily *
IPAddressFamily_find_in_parent(IPAddrBlocks * parent,IPAddressFamily * child_af)5162ad22f62Stb IPAddressFamily_find_in_parent(IPAddrBlocks *parent, IPAddressFamily *child_af)
5172ad22f62Stb {
5182ad22f62Stb int index;
5192ad22f62Stb
520f978902fStb (void)sk_IPAddressFamily_set_cmp_func(parent, IPAddressFamily_cmp);
5212ad22f62Stb
5222ad22f62Stb if ((index = sk_IPAddressFamily_find(parent, child_af)) < 0)
5232ad22f62Stb return NULL;
5242ad22f62Stb
5252ad22f62Stb return sk_IPAddressFamily_value(parent, index);
5262ad22f62Stb }
5272ad22f62Stb
528a4b2db38Stb /*
5290b5aa37fSjob * Extract the AFI from an IPAddressFamily.
530efb484e8Stb *
531efb484e8Stb * This is public API. It uses the reserved AFI 0 as an in-band error
532efb484e8Stb * while it doesn't care about the reserved AFI 65535...
5330b5aa37fSjob */
5341a94ae9bSjob unsigned int
X509v3_addr_get_afi(const IPAddressFamily * af)53570818e4aStb X509v3_addr_get_afi(const IPAddressFamily *af)
5360b5aa37fSjob {
537efb484e8Stb uint16_t afi;
538efb484e8Stb
539efb484e8Stb /*
54070818e4aStb * XXX are these NULL checks really sensible? If af is non-NULL, it
541efb484e8Stb * should have both addressFamily and ipAddressChoice...
542efb484e8Stb */
54370818e4aStb if (af == NULL || af->addressFamily == NULL ||
54470818e4aStb af->addressFamily->data == NULL)
5450b5aa37fSjob return 0;
546efb484e8Stb
54770818e4aStb if (!IPAddressFamily_afi(af, &afi))
54882c2bbddStb return 0;
54982c2bbddStb
550efb484e8Stb return afi;
5510b5aa37fSjob }
552cedac418Stb LCRYPTO_ALIAS(X509v3_addr_get_afi);
5530b5aa37fSjob
5540b5aa37fSjob /*
55591fd884cStb * Expand the bitstring form (RFC 3779, section 2.1.2) of an address into
55691fd884cStb * a raw byte array. At the moment this is coded for simplicity, not speed.
55791fd884cStb *
55891fd884cStb * Unused bits in the last octet of |bs| and all bits in subsequent bytes
55991fd884cStb * of |addr| are set to 0 or 1 depending on whether |fill| is 0 or not.
5600b5aa37fSjob */
5611a94ae9bSjob static int
addr_expand(unsigned char * addr,const ASN1_BIT_STRING * bs,const int length,uint8_t fill)5621a94ae9bSjob addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length,
56391fd884cStb uint8_t fill)
5640b5aa37fSjob {
5650b5aa37fSjob if (bs->length < 0 || bs->length > length)
5660b5aa37fSjob return 0;
56791fd884cStb
56891fd884cStb if (fill != 0)
56917c51bc6Stb fill = 0xff;
57091fd884cStb
5710b5aa37fSjob if (bs->length > 0) {
57291fd884cStb /* XXX - shouldn't this check ASN1_STRING_FLAG_BITS_LEFT? */
57391fd884cStb uint8_t unused_bits = bs->flags & 7;
57491fd884cStb uint8_t mask = (1 << unused_bits) - 1;
57591fd884cStb
5760b5aa37fSjob memcpy(addr, bs->data, bs->length);
57791fd884cStb
5780b5aa37fSjob if (fill == 0)
5790b5aa37fSjob addr[bs->length - 1] &= ~mask;
5800b5aa37fSjob else
5810b5aa37fSjob addr[bs->length - 1] |= mask;
5820b5aa37fSjob }
58391fd884cStb
5840b5aa37fSjob memset(addr + bs->length, fill, length - bs->length);
58591fd884cStb
5860b5aa37fSjob return 1;
5870b5aa37fSjob }
5880b5aa37fSjob
5890b5aa37fSjob /*
59091fd884cStb * Extract the prefix length from a bitstring: 8 * length - unused bits.
5910b5aa37fSjob */
59202fbd552Stb #define addr_prefix_len(bs) ((int) ((bs)->length * 8 - ((bs)->flags & 7)))
5930b5aa37fSjob
5940b5aa37fSjob /*
5950b5aa37fSjob * i2r handler for one address bitstring.
5960b5aa37fSjob */
5971a94ae9bSjob static int
i2r_address(BIO * out,const unsigned afi,const unsigned char fill,const ASN1_BIT_STRING * bs)5981a94ae9bSjob i2r_address(BIO *out, const unsigned afi, const unsigned char fill,
5991a94ae9bSjob const ASN1_BIT_STRING *bs)
6000b5aa37fSjob {
6010b5aa37fSjob unsigned char addr[ADDR_RAW_BUF_LEN];
6020b5aa37fSjob int i, n;
6030b5aa37fSjob
6040b5aa37fSjob if (bs->length < 0)
6050b5aa37fSjob return 0;
6060b5aa37fSjob switch (afi) {
6070b5aa37fSjob case IANA_AFI_IPV4:
6080b5aa37fSjob if (!addr_expand(addr, bs, 4, fill))
6090b5aa37fSjob return 0;
6101a94ae9bSjob BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2],
6111a94ae9bSjob addr[3]);
6120b5aa37fSjob break;
6130b5aa37fSjob case IANA_AFI_IPV6:
6140b5aa37fSjob if (!addr_expand(addr, bs, 16, fill))
6150b5aa37fSjob return 0;
6161a94ae9bSjob for (n = 16;
6171a94ae9bSjob n > 1 && addr[n - 1] == 0x00 && addr[n - 2] == 0x00; n -= 2)
618ff7f58ebSjob continue;
6190b5aa37fSjob for (i = 0; i < n; i += 2)
6200b5aa37fSjob BIO_printf(out, "%x%s", (addr[i] << 8) | addr[i + 1],
6210b5aa37fSjob (i < 14 ? ":" : ""));
6220b5aa37fSjob if (i < 16)
6230b5aa37fSjob BIO_puts(out, ":");
6240b5aa37fSjob if (i == 0)
6250b5aa37fSjob BIO_puts(out, ":");
6260b5aa37fSjob break;
6270b5aa37fSjob default:
6280b5aa37fSjob for (i = 0; i < bs->length; i++)
6291a94ae9bSjob BIO_printf(out, "%s%02x", (i > 0 ? ":" : ""),
6301a94ae9bSjob bs->data[i]);
6310b5aa37fSjob BIO_printf(out, "[%d]", (int)(bs->flags & 7));
6320b5aa37fSjob break;
6330b5aa37fSjob }
6340b5aa37fSjob return 1;
6350b5aa37fSjob }
6360b5aa37fSjob
6370b5aa37fSjob /*
6380b5aa37fSjob * i2r handler for a sequence of addresses and ranges.
6390b5aa37fSjob */
6401a94ae9bSjob static int
i2r_IPAddressOrRanges(BIO * out,const int indent,const IPAddressOrRanges * aors,const unsigned afi)6411a94ae9bSjob i2r_IPAddressOrRanges(BIO *out, const int indent,
6421a94ae9bSjob const IPAddressOrRanges *aors, const unsigned afi)
6430b5aa37fSjob {
644f4f4cc81Stb const IPAddressOrRange *aor;
645f4f4cc81Stb const ASN1_BIT_STRING *prefix;
646f4f4cc81Stb const IPAddressRange *range;
6470b5aa37fSjob int i;
648f4f4cc81Stb
6490b5aa37fSjob for (i = 0; i < sk_IPAddressOrRange_num(aors); i++) {
650f4f4cc81Stb aor = sk_IPAddressOrRange_value(aors, i);
651f4f4cc81Stb
6520b5aa37fSjob BIO_printf(out, "%*s", indent, "");
653f4f4cc81Stb
6540b5aa37fSjob switch (aor->type) {
6550b5aa37fSjob case IPAddressOrRange_addressPrefix:
656f4f4cc81Stb prefix = aor->u.addressPrefix;
657f4f4cc81Stb
658f4f4cc81Stb if (!i2r_address(out, afi, 0x00, prefix))
6590b5aa37fSjob return 0;
660f4f4cc81Stb BIO_printf(out, "/%d\n", addr_prefix_len(prefix));
6610b5aa37fSjob continue;
6620b5aa37fSjob case IPAddressOrRange_addressRange:
663f4f4cc81Stb range = aor->u.addressRange;
664f4f4cc81Stb
665f4f4cc81Stb if (!i2r_address(out, afi, 0x00, range->min))
6660b5aa37fSjob return 0;
6670b5aa37fSjob BIO_puts(out, "-");
668f4f4cc81Stb if (!i2r_address(out, afi, 0xff, range->max))
6690b5aa37fSjob return 0;
6700b5aa37fSjob BIO_puts(out, "\n");
6710b5aa37fSjob continue;
6720b5aa37fSjob }
6730b5aa37fSjob }
674f4f4cc81Stb
6750b5aa37fSjob return 1;
6760b5aa37fSjob }
6770b5aa37fSjob
6780b5aa37fSjob /*
6790b5aa37fSjob * i2r handler for an IPAddrBlocks extension.
6800b5aa37fSjob */
6811a94ae9bSjob static int
i2r_IPAddrBlocks(const X509V3_EXT_METHOD * method,void * ext,BIO * out,int indent)6821a94ae9bSjob i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, void *ext, BIO *out,
6831a94ae9bSjob int indent)
6840b5aa37fSjob {
6850b5aa37fSjob const IPAddrBlocks *addr = ext;
68670818e4aStb IPAddressFamily *af;
687b1088c0cSjob uint16_t afi;
688b1088c0cSjob uint8_t safi;
689b1088c0cSjob int i, safi_is_set;
690a4b2db38Stb
6910b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
69270818e4aStb af = sk_IPAddressFamily_value(addr, i);
693a4b2db38Stb
69470818e4aStb if (!IPAddressFamily_afi_safi(af, &afi, &safi, &safi_is_set))
695a4b2db38Stb goto print_addresses;
696a4b2db38Stb
6970b5aa37fSjob switch (afi) {
6980b5aa37fSjob case IANA_AFI_IPV4:
6990b5aa37fSjob BIO_printf(out, "%*sIPv4", indent, "");
7000b5aa37fSjob break;
7010b5aa37fSjob case IANA_AFI_IPV6:
7020b5aa37fSjob BIO_printf(out, "%*sIPv6", indent, "");
7030b5aa37fSjob break;
7040b5aa37fSjob default:
7050b5aa37fSjob BIO_printf(out, "%*sUnknown AFI %u", indent, "", afi);
7060b5aa37fSjob break;
7070b5aa37fSjob }
708a4b2db38Stb if (safi_is_set) {
709a4b2db38Stb switch (safi) {
7100b5aa37fSjob case 1:
7110b5aa37fSjob BIO_puts(out, " (Unicast)");
7120b5aa37fSjob break;
7130b5aa37fSjob case 2:
7140b5aa37fSjob BIO_puts(out, " (Multicast)");
7150b5aa37fSjob break;
7160b5aa37fSjob case 3:
7170b5aa37fSjob BIO_puts(out, " (Unicast/Multicast)");
7180b5aa37fSjob break;
7190b5aa37fSjob case 4:
7200b5aa37fSjob BIO_puts(out, " (MPLS)");
7210b5aa37fSjob break;
7220b5aa37fSjob case 64:
7230b5aa37fSjob BIO_puts(out, " (Tunnel)");
7240b5aa37fSjob break;
7250b5aa37fSjob case 65:
7260b5aa37fSjob BIO_puts(out, " (VPLS)");
7270b5aa37fSjob break;
7280b5aa37fSjob case 66:
7290b5aa37fSjob BIO_puts(out, " (BGP MDT)");
7300b5aa37fSjob break;
7310b5aa37fSjob case 128:
7320b5aa37fSjob BIO_puts(out, " (MPLS-labeled VPN)");
7330b5aa37fSjob break;
7340b5aa37fSjob default:
735a4b2db38Stb BIO_printf(out, " (Unknown SAFI %u)", safi);
7360b5aa37fSjob break;
7370b5aa37fSjob }
7380b5aa37fSjob }
739a4b2db38Stb
740a4b2db38Stb print_addresses:
74170818e4aStb switch (IPAddressFamily_type(af)) {
7420b5aa37fSjob case IPAddressChoice_inherit:
7430b5aa37fSjob BIO_puts(out, ": inherit\n");
7440b5aa37fSjob break;
7450b5aa37fSjob case IPAddressChoice_addressesOrRanges:
7460b5aa37fSjob BIO_puts(out, ":\n");
747cb7bf5bdStb if (!i2r_IPAddressOrRanges(out, indent + 2,
74870818e4aStb IPAddressFamily_addressesOrRanges(af), afi))
7490b5aa37fSjob return 0;
7500b5aa37fSjob break;
7515df401b8Stb /* XXX - how should we handle -1 here? */
7520b5aa37fSjob }
7530b5aa37fSjob }
7540b5aa37fSjob return 1;
7550b5aa37fSjob }
7560b5aa37fSjob
7570b5aa37fSjob /*
7580b5aa37fSjob * Sort comparison function for a sequence of IPAddressOrRange
7590b5aa37fSjob * elements.
7600b5aa37fSjob *
7610b5aa37fSjob * There's no sane answer we can give if addr_expand() fails, and an
7620b5aa37fSjob * assertion failure on externally supplied data is seriously uncool,
7630b5aa37fSjob * so we just arbitrarily declare that if given invalid inputs this
7640b5aa37fSjob * function returns -1. If this messes up your preferred sort order
7650b5aa37fSjob * for garbage input, tough noogies.
7660b5aa37fSjob */
7671a94ae9bSjob static int
IPAddressOrRange_cmp(const IPAddressOrRange * a,const IPAddressOrRange * b,const int length)7681a94ae9bSjob IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b,
7691a94ae9bSjob const int length)
7700b5aa37fSjob {
7710b5aa37fSjob unsigned char addr_a[ADDR_RAW_BUF_LEN], addr_b[ADDR_RAW_BUF_LEN];
77202fbd552Stb int prefix_len_a = 0, prefix_len_b = 0;
7730b5aa37fSjob int r;
7740b5aa37fSjob
7750b5aa37fSjob switch (a->type) {
7760b5aa37fSjob case IPAddressOrRange_addressPrefix:
7770b5aa37fSjob if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00))
7780b5aa37fSjob return -1;
77902fbd552Stb prefix_len_a = addr_prefix_len(a->u.addressPrefix);
7800b5aa37fSjob break;
7810b5aa37fSjob case IPAddressOrRange_addressRange:
7820b5aa37fSjob if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00))
7830b5aa37fSjob return -1;
78402fbd552Stb prefix_len_a = length * 8;
7850b5aa37fSjob break;
7860b5aa37fSjob }
7870b5aa37fSjob
7880b5aa37fSjob switch (b->type) {
7890b5aa37fSjob case IPAddressOrRange_addressPrefix:
7900b5aa37fSjob if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00))
7910b5aa37fSjob return -1;
79202fbd552Stb prefix_len_b = addr_prefix_len(b->u.addressPrefix);
7930b5aa37fSjob break;
7940b5aa37fSjob case IPAddressOrRange_addressRange:
7950b5aa37fSjob if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00))
7960b5aa37fSjob return -1;
79702fbd552Stb prefix_len_b = length * 8;
7980b5aa37fSjob break;
7990b5aa37fSjob }
8000b5aa37fSjob
8010b5aa37fSjob if ((r = memcmp(addr_a, addr_b, length)) != 0)
8020b5aa37fSjob return r;
8030b5aa37fSjob else
80402fbd552Stb return prefix_len_a - prefix_len_b;
8050b5aa37fSjob }
8060b5aa37fSjob
8070b5aa37fSjob /*
8080b5aa37fSjob * IPv4-specific closure over IPAddressOrRange_cmp, since sk_sort()
8090b5aa37fSjob * comparison routines are only allowed two arguments.
8100b5aa37fSjob */
8111a94ae9bSjob static int
v4IPAddressOrRange_cmp(const IPAddressOrRange * const * a,const IPAddressOrRange * const * b)8121a94ae9bSjob v4IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
8130b5aa37fSjob const IPAddressOrRange *const *b)
8140b5aa37fSjob {
8150b5aa37fSjob return IPAddressOrRange_cmp(*a, *b, 4);
8160b5aa37fSjob }
8170b5aa37fSjob
8180b5aa37fSjob /*
8190b5aa37fSjob * IPv6-specific closure over IPAddressOrRange_cmp, since sk_sort()
8200b5aa37fSjob * comparison routines are only allowed two arguments.
8210b5aa37fSjob */
8221a94ae9bSjob static int
v6IPAddressOrRange_cmp(const IPAddressOrRange * const * a,const IPAddressOrRange * const * b)8231a94ae9bSjob v6IPAddressOrRange_cmp(const IPAddressOrRange *const *a,
8240b5aa37fSjob const IPAddressOrRange *const *b)
8250b5aa37fSjob {
8260b5aa37fSjob return IPAddressOrRange_cmp(*a, *b, 16);
8270b5aa37fSjob }
8280b5aa37fSjob
8290b5aa37fSjob /*
8300b5aa37fSjob * Calculate whether a range collapses to a prefix.
8310b5aa37fSjob * See last paragraph of RFC 3779 2.2.3.7.
8320135a380Stb *
8330135a380Stb * It's the caller's responsibility to ensure that min <= max.
8340b5aa37fSjob */
8351a94ae9bSjob static int
range_should_be_prefix(const unsigned char * min,const unsigned char * max,const int length)8361a94ae9bSjob range_should_be_prefix(const unsigned char *min, const unsigned char *max,
8371a94ae9bSjob const int length)
8380b5aa37fSjob {
8390b5aa37fSjob unsigned char mask;
8400b5aa37fSjob int i, j;
8410b5aa37fSjob
8421a94ae9bSjob for (i = 0; i < length && min[i] == max[i]; i++)
843ff7f58ebSjob continue;
84417c51bc6Stb for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xff; j--)
845ff7f58ebSjob continue;
8460b5aa37fSjob if (i < j)
8470b5aa37fSjob return -1;
8480b5aa37fSjob if (i > j)
8490b5aa37fSjob return i * 8;
8500b5aa37fSjob mask = min[i] ^ max[i];
8510b5aa37fSjob switch (mask) {
8520b5aa37fSjob case 0x01:
8530b5aa37fSjob j = 7;
8540b5aa37fSjob break;
8550b5aa37fSjob case 0x03:
8560b5aa37fSjob j = 6;
8570b5aa37fSjob break;
8580b5aa37fSjob case 0x07:
8590b5aa37fSjob j = 5;
8600b5aa37fSjob break;
86117c51bc6Stb case 0x0f:
8620b5aa37fSjob j = 4;
8630b5aa37fSjob break;
86417c51bc6Stb case 0x1f:
8650b5aa37fSjob j = 3;
8660b5aa37fSjob break;
86717c51bc6Stb case 0x3f:
8680b5aa37fSjob j = 2;
8690b5aa37fSjob break;
87017c51bc6Stb case 0x7f:
8710b5aa37fSjob j = 1;
8720b5aa37fSjob break;
8730b5aa37fSjob default:
8740b5aa37fSjob return -1;
8750b5aa37fSjob }
8760b5aa37fSjob if ((min[i] & mask) != 0 || (max[i] & mask) != mask)
8770b5aa37fSjob return -1;
8780b5aa37fSjob else
8790b5aa37fSjob return i * 8 + j;
8800b5aa37fSjob }
8810b5aa37fSjob
8820b5aa37fSjob /*
8835a0c623bStb * Fill IPAddressOrRange with bit string encoding of a prefix - RFC 3779, 2.1.1.
8840b5aa37fSjob */
8851a94ae9bSjob static int
make_addressPrefix(IPAddressOrRange ** out_aor,uint8_t * addr,uint32_t afi,int prefix_len)8865a0c623bStb make_addressPrefix(IPAddressOrRange **out_aor, uint8_t *addr, uint32_t afi,
8875a0c623bStb int prefix_len)
8880b5aa37fSjob {
8895a0c623bStb IPAddressOrRange *aor = NULL;
8902b4f9a55Stb int afi_len, num_bits, num_octets;
8915a0c623bStb uint8_t unused_bits;
8920b5aa37fSjob
89302fbd552Stb if (prefix_len < 0)
8945a0c623bStb goto err;
895761d8685Stb
8962b4f9a55Stb if (!length_from_afi(afi, &afi_len))
8972b4f9a55Stb goto err;
8982b4f9a55Stb if (prefix_len > 8 * afi_len)
8995a0c623bStb goto err;
900761d8685Stb
9015a0c623bStb num_octets = (prefix_len + 7) / 8;
9025a0c623bStb num_bits = prefix_len % 8;
9035a0c623bStb
9045a0c623bStb unused_bits = 0;
9055a0c623bStb if (num_bits > 0)
9065a0c623bStb unused_bits = 8 - num_bits;
907761d8685Stb
908761d8685Stb if ((aor = IPAddressOrRange_new()) == NULL)
9095a0c623bStb goto err;
9105a0c623bStb
9110b5aa37fSjob aor->type = IPAddressOrRange_addressPrefix;
9125a0c623bStb
9138af78584Stb if ((aor->u.addressPrefix = ASN1_BIT_STRING_new()) == NULL)
9140b5aa37fSjob goto err;
9155a0c623bStb if (!ASN1_BIT_STRING_set(aor->u.addressPrefix, addr, num_octets))
9165a0c623bStb goto err;
9175a0c623bStb if (!asn1_abs_set_unused_bits(aor->u.addressPrefix, unused_bits))
9180b5aa37fSjob goto err;
919761d8685Stb
9205a0c623bStb *out_aor = aor;
9210b5aa37fSjob return 1;
9220b5aa37fSjob
9230b5aa37fSjob err:
9240b5aa37fSjob IPAddressOrRange_free(aor);
9250b5aa37fSjob return 0;
9260b5aa37fSjob }
9270b5aa37fSjob
92884b681d4Stb static uint8_t
count_trailing_zeroes(uint8_t octet)92984b681d4Stb count_trailing_zeroes(uint8_t octet)
93084b681d4Stb {
93184b681d4Stb uint8_t count = 0;
93284b681d4Stb
93384b681d4Stb if (octet == 0)
93484b681d4Stb return 8;
93584b681d4Stb
93684b681d4Stb while ((octet & (1 << count)) == 0)
93784b681d4Stb count++;
93884b681d4Stb
93984b681d4Stb return count;
94084b681d4Stb }
94184b681d4Stb
94284b681d4Stb static int
trim_end_u8(CBS * cbs,uint8_t trim)94384b681d4Stb trim_end_u8(CBS *cbs, uint8_t trim)
94484b681d4Stb {
94584b681d4Stb uint8_t octet;
94684b681d4Stb
94784b681d4Stb while (CBS_len(cbs) > 0) {
94884b681d4Stb if (!CBS_peek_last_u8(cbs, &octet))
94984b681d4Stb return 0;
95084b681d4Stb if (octet != trim)
95184b681d4Stb return 1;
95284b681d4Stb if (!CBS_get_last_u8(cbs, &octet))
95384b681d4Stb return 0;
95484b681d4Stb }
95584b681d4Stb
95684b681d4Stb return 1;
95784b681d4Stb }
95884b681d4Stb
9590b5aa37fSjob /*
96084b681d4Stb * Populate IPAddressOrRange with bit string encoding of a range, see
96184b681d4Stb * RFC 3779, 2.1.2.
9620b5aa37fSjob */
9631a94ae9bSjob static int
make_addressRange(IPAddressOrRange ** out_aor,uint8_t * min,uint8_t * max,uint32_t afi,int length)96484b681d4Stb make_addressRange(IPAddressOrRange **out_aor, uint8_t *min, uint8_t *max,
96584b681d4Stb uint32_t afi, int length)
9660b5aa37fSjob {
96784b681d4Stb IPAddressOrRange *aor = NULL;
96884b681d4Stb IPAddressRange *range;
96984b681d4Stb int prefix_len;
97084b681d4Stb CBS cbs;
97184b681d4Stb size_t max_len, min_len;
97284b681d4Stb uint8_t unused_bits_min, unused_bits_max;
97384b681d4Stb uint8_t octet;
9740b5aa37fSjob
9750135a380Stb if (memcmp(min, max, length) > 0)
97684b681d4Stb goto err;
97784b681d4Stb
97884b681d4Stb /*
97984b681d4Stb * RFC 3779, 2.2.3.6 - a range that can be expressed as a prefix
98084b681d4Stb * must be encoded as a prefix.
98184b681d4Stb */
9820135a380Stb
98302fbd552Stb if ((prefix_len = range_should_be_prefix(min, max, length)) >= 0)
98484b681d4Stb return make_addressPrefix(out_aor, min, afi, prefix_len);
98584b681d4Stb
98684b681d4Stb /*
98784b681d4Stb * The bit string representing min is formed by removing all its
98884b681d4Stb * trailing zero bits, so remove all trailing zero octets and count
98984b681d4Stb * the trailing zero bits of the last octet.
99084b681d4Stb */
99184b681d4Stb
99284b681d4Stb CBS_init(&cbs, min, length);
99384b681d4Stb
99484b681d4Stb if (!trim_end_u8(&cbs, 0x00))
99584b681d4Stb goto err;
99684b681d4Stb
99784b681d4Stb unused_bits_min = 0;
99884b681d4Stb if ((min_len = CBS_len(&cbs)) > 0) {
99984b681d4Stb if (!CBS_peek_last_u8(&cbs, &octet))
100084b681d4Stb goto err;
100184b681d4Stb
100284b681d4Stb unused_bits_min = count_trailing_zeroes(octet);
100384b681d4Stb }
100484b681d4Stb
100584b681d4Stb /*
100684b681d4Stb * The bit string representing max is formed by removing all its
100784b681d4Stb * trailing one bits, so remove all trailing 0xff octets and count
100884b681d4Stb * the trailing ones of the last octet.
100984b681d4Stb */
101084b681d4Stb
101184b681d4Stb CBS_init(&cbs, max, length);
101284b681d4Stb
101384b681d4Stb if (!trim_end_u8(&cbs, 0xff))
101484b681d4Stb goto err;
101584b681d4Stb
101684b681d4Stb unused_bits_max = 0;
101784b681d4Stb if ((max_len = CBS_len(&cbs)) > 0) {
101884b681d4Stb if (!CBS_peek_last_u8(&cbs, &octet))
101984b681d4Stb goto err;
102084b681d4Stb
102184b681d4Stb unused_bits_max = count_trailing_zeroes(octet + 1);
102284b681d4Stb }
102384b681d4Stb
102484b681d4Stb /*
102584b681d4Stb * Populate IPAddressOrRange.
102684b681d4Stb */
10270b5aa37fSjob
10280b5aa37fSjob if ((aor = IPAddressOrRange_new()) == NULL)
102984b681d4Stb goto err;
103084b681d4Stb
10310b5aa37fSjob aor->type = IPAddressOrRange_addressRange;
103284b681d4Stb
103384b681d4Stb if ((range = aor->u.addressRange = IPAddressRange_new()) == NULL)
10340b5aa37fSjob goto err;
10350b5aa37fSjob
103684b681d4Stb if (!ASN1_BIT_STRING_set(range->min, min, min_len))
10370b5aa37fSjob goto err;
103884b681d4Stb if (!asn1_abs_set_unused_bits(range->min, unused_bits_min))
10390b5aa37fSjob goto err;
10400b5aa37fSjob
104184b681d4Stb if (!ASN1_BIT_STRING_set(range->max, max, max_len))
104284b681d4Stb goto err;
104384b681d4Stb if (!asn1_abs_set_unused_bits(range->max, unused_bits_max))
104484b681d4Stb goto err;
104584b681d4Stb
104684b681d4Stb *out_aor = aor;
104784b681d4Stb
10480b5aa37fSjob return 1;
10490b5aa37fSjob
10500b5aa37fSjob err:
10510b5aa37fSjob IPAddressOrRange_free(aor);
10520b5aa37fSjob return 0;
10530b5aa37fSjob }
10540b5aa37fSjob
10550b5aa37fSjob /*
10560b5aa37fSjob * Construct a new address family or find an existing one.
10570b5aa37fSjob */
10581a94ae9bSjob static IPAddressFamily *
make_IPAddressFamily(IPAddrBlocks * addr,const unsigned afi,const unsigned * safi)10591a94ae9bSjob make_IPAddressFamily(IPAddrBlocks *addr, const unsigned afi,
10600b5aa37fSjob const unsigned *safi)
10610b5aa37fSjob {
106270818e4aStb IPAddressFamily *af = NULL;
1063a51f55edStb CBB cbb;
1064a51f55edStb CBS cbs;
1065a51f55edStb uint8_t *key = NULL;
1066a51f55edStb size_t keylen;
10670b5aa37fSjob int i;
10680b5aa37fSjob
1069a51f55edStb if (!CBB_init(&cbb, 0))
1070a51f55edStb goto err;
1071a51f55edStb
10722b4f9a55Stb if (afi != IANA_AFI_IPV4 && afi != IANA_AFI_IPV6)
10732b4f9a55Stb goto err;
1074a51f55edStb if (!CBB_add_u16(&cbb, afi))
1075a51f55edStb goto err;
10762b4f9a55Stb
10770b5aa37fSjob if (safi != NULL) {
10782b4f9a55Stb if (*safi > 255)
10792b4f9a55Stb goto err;
1080a51f55edStb if (!CBB_add_u8(&cbb, *safi))
1081a51f55edStb goto err;
10820b5aa37fSjob }
10830b5aa37fSjob
1084a51f55edStb if (!CBB_finish(&cbb, &key, &keylen))
1085a51f55edStb goto err;
1086a51f55edStb
10870b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
108870818e4aStb af = sk_IPAddressFamily_value(addr, i);
1089a51f55edStb
109070818e4aStb CBS_init(&cbs, af->addressFamily->data,
109170818e4aStb af->addressFamily->length);
1092a51f55edStb if (CBS_mem_equal(&cbs, key, keylen))
1093a51f55edStb goto done;
10940b5aa37fSjob }
10950b5aa37fSjob
109670818e4aStb if ((af = IPAddressFamily_new()) == NULL)
10970b5aa37fSjob goto err;
109870818e4aStb if (!ASN1_OCTET_STRING_set(af->addressFamily, key, keylen))
10990b5aa37fSjob goto err;
110070818e4aStb if (!sk_IPAddressFamily_push(addr, af))
11010b5aa37fSjob goto err;
11020b5aa37fSjob
1103a51f55edStb done:
1104a51f55edStb free(key);
1105a51f55edStb
110670818e4aStb return af;
11070b5aa37fSjob
11080b5aa37fSjob err:
1109a51f55edStb CBB_cleanup(&cbb);
1110a51f55edStb free(key);
111170818e4aStb IPAddressFamily_free(af);
1112a51f55edStb
11130b5aa37fSjob return NULL;
11140b5aa37fSjob }
11150b5aa37fSjob
11160b5aa37fSjob /*
11170b5aa37fSjob * Add an inheritance element.
11180b5aa37fSjob */
11191a94ae9bSjob int
X509v3_addr_add_inherit(IPAddrBlocks * addr,const unsigned afi,const unsigned * safi)11201a94ae9bSjob X509v3_addr_add_inherit(IPAddrBlocks *addr, const unsigned afi,
11211a94ae9bSjob const unsigned *safi)
11220b5aa37fSjob {
112370818e4aStb IPAddressFamily *af;
1124ddc1bf0aStb
112570818e4aStb if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL)
11260b5aa37fSjob return 0;
1127ddc1bf0aStb
112870818e4aStb return IPAddressFamily_set_inheritance(af);
11290b5aa37fSjob }
1130cedac418Stb LCRYPTO_ALIAS(X509v3_addr_add_inherit);
11310b5aa37fSjob
11320b5aa37fSjob /*
11330b5aa37fSjob * Construct an IPAddressOrRange sequence, or return an existing one.
11340b5aa37fSjob */
11351a94ae9bSjob static IPAddressOrRanges *
make_prefix_or_range(IPAddrBlocks * addr,const unsigned afi,const unsigned * safi)11361a94ae9bSjob make_prefix_or_range(IPAddrBlocks *addr, const unsigned afi,
11370b5aa37fSjob const unsigned *safi)
11380b5aa37fSjob {
113970818e4aStb IPAddressFamily *af;
11400b5aa37fSjob IPAddressOrRanges *aors = NULL;
11410b5aa37fSjob
114270818e4aStb if ((af = make_IPAddressFamily(addr, afi, safi)) == NULL)
11430b5aa37fSjob return NULL;
1144ddc1bf0aStb
114570818e4aStb if (IPAddressFamily_inheritance(af) != NULL)
1146ddc1bf0aStb return NULL;
1147ddc1bf0aStb
114870818e4aStb if ((aors = IPAddressFamily_addressesOrRanges(af)) != NULL)
11490b5aa37fSjob return aors;
1150ddc1bf0aStb
11510b5aa37fSjob if ((aors = sk_IPAddressOrRange_new_null()) == NULL)
11520b5aa37fSjob return NULL;
1153ddc1bf0aStb
11540b5aa37fSjob switch (afi) {
11550b5aa37fSjob case IANA_AFI_IPV4:
1156f978902fStb (void)sk_IPAddressOrRange_set_cmp_func(aors,
1157f978902fStb v4IPAddressOrRange_cmp);
11580b5aa37fSjob break;
11590b5aa37fSjob case IANA_AFI_IPV6:
1160f978902fStb (void)sk_IPAddressOrRange_set_cmp_func(aors,
1161f978902fStb v6IPAddressOrRange_cmp);
11620b5aa37fSjob break;
11630b5aa37fSjob }
1164ddc1bf0aStb
116570818e4aStb af->ipAddressChoice->type = IPAddressChoice_addressesOrRanges;
116670818e4aStb af->ipAddressChoice->u.addressesOrRanges = aors;
1167ddc1bf0aStb
11680b5aa37fSjob return aors;
11690b5aa37fSjob }
11700b5aa37fSjob
11710b5aa37fSjob /*
11720b5aa37fSjob * Add a prefix.
11730b5aa37fSjob */
11741a94ae9bSjob int
X509v3_addr_add_prefix(IPAddrBlocks * addr,const unsigned afi,const unsigned * safi,unsigned char * a,const int prefix_len)11751a94ae9bSjob X509v3_addr_add_prefix(IPAddrBlocks *addr, const unsigned afi,
117602fbd552Stb const unsigned *safi, unsigned char *a, const int prefix_len)
11770b5aa37fSjob {
11786e49db69Stb IPAddressOrRanges *aors;
11790b5aa37fSjob IPAddressOrRange *aor;
11806e49db69Stb
11816e49db69Stb if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL)
11820b5aa37fSjob return 0;
11836e49db69Stb
118402fbd552Stb if (!make_addressPrefix(&aor, a, afi, prefix_len))
11856e49db69Stb return 0;
11866e49db69Stb
11876e49db69Stb if (sk_IPAddressOrRange_push(aors, aor) <= 0) {
11880b5aa37fSjob IPAddressOrRange_free(aor);
11890b5aa37fSjob return 0;
11900b5aa37fSjob }
11910b5aa37fSjob
11926e49db69Stb return 1;
11936e49db69Stb }
1194cedac418Stb LCRYPTO_ALIAS(X509v3_addr_add_prefix);
11956e49db69Stb
11960b5aa37fSjob /*
11970b5aa37fSjob * Add a range.
11980b5aa37fSjob */
11991a94ae9bSjob int
X509v3_addr_add_range(IPAddrBlocks * addr,const unsigned afi,const unsigned * safi,unsigned char * min,unsigned char * max)12001a94ae9bSjob X509v3_addr_add_range(IPAddrBlocks *addr, const unsigned afi,
12011a94ae9bSjob const unsigned *safi, unsigned char *min, unsigned char *max)
12020b5aa37fSjob {
12035e62140aStb IPAddressOrRanges *aors;
12040b5aa37fSjob IPAddressOrRange *aor;
12055e62140aStb int length;
12065e62140aStb
12075e62140aStb if ((aors = make_prefix_or_range(addr, afi, safi)) == NULL)
12080b5aa37fSjob return 0;
12095e62140aStb
12102b4f9a55Stb if (!length_from_afi(afi, &length))
12112b4f9a55Stb return 0;
12125e62140aStb
1213761d8685Stb if (!make_addressRange(&aor, min, max, afi, length))
12140b5aa37fSjob return 0;
12155e62140aStb
12165e62140aStb if (sk_IPAddressOrRange_push(aors, aor) <= 0) {
12170b5aa37fSjob IPAddressOrRange_free(aor);
12180b5aa37fSjob return 0;
12190b5aa37fSjob }
12200b5aa37fSjob
12215e62140aStb return 1;
12225e62140aStb }
1223cedac418Stb LCRYPTO_ALIAS(X509v3_addr_add_range);
12245e62140aStb
1225406a7a7bStb static int
extract_min_max_bitstr(IPAddressOrRange * aor,ASN1_BIT_STRING ** out_min,ASN1_BIT_STRING ** out_max)1226406a7a7bStb extract_min_max_bitstr(IPAddressOrRange *aor, ASN1_BIT_STRING **out_min,
1227406a7a7bStb ASN1_BIT_STRING **out_max)
1228406a7a7bStb {
1229406a7a7bStb switch (aor->type) {
1230406a7a7bStb case IPAddressOrRange_addressPrefix:
1231406a7a7bStb *out_min = *out_max = aor->u.addressPrefix;
1232406a7a7bStb return 1;
1233406a7a7bStb case IPAddressOrRange_addressRange:
1234406a7a7bStb *out_min = aor->u.addressRange->min;
1235406a7a7bStb *out_max = aor->u.addressRange->max;
1236406a7a7bStb return 1;
1237406a7a7bStb default:
1238406a7a7bStb return 0;
1239406a7a7bStb }
1240406a7a7bStb }
1241406a7a7bStb
12420b5aa37fSjob /*
12430b5aa37fSjob * Extract min and max values from an IPAddressOrRange.
12440b5aa37fSjob */
12451a94ae9bSjob static int
extract_min_max(IPAddressOrRange * aor,unsigned char * min,unsigned char * max,int length)12461a94ae9bSjob extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max,
12471a94ae9bSjob int length)
12480b5aa37fSjob {
1249406a7a7bStb ASN1_BIT_STRING *min_bitstr, *max_bitstr;
1250406a7a7bStb
12510b5aa37fSjob if (aor == NULL || min == NULL || max == NULL)
12520b5aa37fSjob return 0;
1253406a7a7bStb
1254406a7a7bStb if (!extract_min_max_bitstr(aor, &min_bitstr, &max_bitstr))
12550b5aa37fSjob return 0;
1256406a7a7bStb
1257406a7a7bStb if (!addr_expand(min, min_bitstr, length, 0))
1258406a7a7bStb return 0;
1259406a7a7bStb
1260406a7a7bStb return addr_expand(max, max_bitstr, length, 1);
12610b5aa37fSjob }
12620b5aa37fSjob
12630b5aa37fSjob /*
12640b5aa37fSjob * Public wrapper for extract_min_max().
12650b5aa37fSjob */
12661a94ae9bSjob int
X509v3_addr_get_range(IPAddressOrRange * aor,const unsigned afi,unsigned char * min,unsigned char * max,const int length)12671a94ae9bSjob X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
12681a94ae9bSjob unsigned char *min, unsigned char *max, const int length)
12690b5aa37fSjob {
127002fbd552Stb int afi_len;
127137f392f9Stb
12722b4f9a55Stb if (!length_from_afi(afi, &afi_len))
127337f392f9Stb return 0;
127437f392f9Stb
127502fbd552Stb if (length < afi_len)
127637f392f9Stb return 0;
127737f392f9Stb
127802fbd552Stb if (!extract_min_max(aor, min, max, afi_len))
12790b5aa37fSjob return 0;
12800b5aa37fSjob
128102fbd552Stb return afi_len;
12820b5aa37fSjob }
1283cedac418Stb LCRYPTO_ALIAS(X509v3_addr_get_range);
12840b5aa37fSjob
12850b5aa37fSjob /*
12860b5aa37fSjob * Check whether an IPAddrBLocks is in canonical form.
12870b5aa37fSjob */
12881a94ae9bSjob int
X509v3_addr_is_canonical(IPAddrBlocks * addr)12891a94ae9bSjob X509v3_addr_is_canonical(IPAddrBlocks *addr)
12900b5aa37fSjob {
12910b5aa37fSjob unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
12920b5aa37fSjob unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
129370818e4aStb IPAddressFamily *af;
12940b5aa37fSjob IPAddressOrRanges *aors;
1295b5341c5bStb IPAddressOrRange *aor, *aor_a, *aor_b;
1296b5341c5bStb int i, j, k, length;
12970b5aa37fSjob
12980b5aa37fSjob /*
12990b5aa37fSjob * Empty extension is canonical.
13000b5aa37fSjob */
13010b5aa37fSjob if (addr == NULL)
13020b5aa37fSjob return 1;
13030b5aa37fSjob
13040b5aa37fSjob /*
13050b5aa37fSjob * Check whether the top-level list is in order.
13060b5aa37fSjob */
13070b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr) - 1; i++) {
13080b5aa37fSjob const IPAddressFamily *a = sk_IPAddressFamily_value(addr, i);
13090b5aa37fSjob const IPAddressFamily *b = sk_IPAddressFamily_value(addr, i + 1);
1310f8fec339Stb
1311f8fec339Stb /* Check that both have valid AFIs before comparing them. */
1312a4b2db38Stb if (!IPAddressFamily_afi_is_valid(a))
1313f8fec339Stb return 0;
1314a4b2db38Stb if (!IPAddressFamily_afi_is_valid(b))
1315f8fec339Stb return 0;
1316f8fec339Stb
13170b5aa37fSjob if (IPAddressFamily_cmp(&a, &b) >= 0)
13180b5aa37fSjob return 0;
13190b5aa37fSjob }
13200b5aa37fSjob
13210b5aa37fSjob /*
13220b5aa37fSjob * Top level's ok, now check each address family.
13230b5aa37fSjob */
13240b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
132570818e4aStb af = sk_IPAddressFamily_value(addr, i);
1326ddc1bf0aStb
132770818e4aStb if (!IPAddressFamily_afi_length(af, &length))
1328ddc1bf0aStb return 0;
13290b5aa37fSjob
13300b5aa37fSjob /*
1331b5341c5bStb * If this family has an inheritance element, it is canonical.
13320b5aa37fSjob */
133370818e4aStb if (IPAddressFamily_inheritance(af) != NULL)
13340b5aa37fSjob continue;
13350b5aa37fSjob
13360b5aa37fSjob /*
1337b5341c5bStb * If this family has neither an inheritance element nor an
1338b5341c5bStb * addressesOrRanges, we don't know what this is.
13390b5aa37fSjob */
134070818e4aStb if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL)
1341b5341c5bStb return 0;
1342b5341c5bStb
13430b5aa37fSjob if (sk_IPAddressOrRange_num(aors) == 0)
13440b5aa37fSjob return 0;
13450b5aa37fSjob
1346b5341c5bStb for (j = 0; j < sk_IPAddressOrRange_num(aors) - 1; j++) {
1347b5341c5bStb aor_a = sk_IPAddressOrRange_value(aors, j);
1348b5341c5bStb aor_b = sk_IPAddressOrRange_value(aors, j + 1);
1349b5341c5bStb
1350b5341c5bStb if (!extract_min_max(aor_a, a_min, a_max, length) ||
1351b5341c5bStb !extract_min_max(aor_b, b_min, b_max, length))
13520b5aa37fSjob return 0;
13530b5aa37fSjob
13540b5aa37fSjob /*
13553c1c1242Sjob * Punt misordered list, overlapping start, or inverted
13563c1c1242Sjob * range.
13570b5aa37fSjob */
13580b5aa37fSjob if (memcmp(a_min, b_min, length) >= 0 ||
13590b5aa37fSjob memcmp(a_min, a_max, length) > 0 ||
13600b5aa37fSjob memcmp(b_min, b_max, length) > 0)
13610b5aa37fSjob return 0;
13620b5aa37fSjob
13630b5aa37fSjob /*
1364b5341c5bStb * Punt if adjacent or overlapping. Check for adjacency
1365b5341c5bStb * by subtracting one from b_min first.
13660b5aa37fSjob */
13671a94ae9bSjob for (k = length - 1; k >= 0 && b_min[k]-- == 0x00; k--)
1368ff7f58ebSjob continue;
13690b5aa37fSjob if (memcmp(a_max, b_min, length) >= 0)
13700b5aa37fSjob return 0;
13710b5aa37fSjob
13720b5aa37fSjob /*
13730b5aa37fSjob * Check for range that should be expressed as a prefix.
13740b5aa37fSjob */
1375b5341c5bStb if (aor_a->type == IPAddressOrRange_addressPrefix)
1376b5341c5bStb continue;
1377b5341c5bStb
1378b5341c5bStb if (range_should_be_prefix(a_min, a_max, length) >= 0)
13790b5aa37fSjob return 0;
13800b5aa37fSjob }
13810b5aa37fSjob
13820b5aa37fSjob /*
1383b5341c5bStb * Check final range to see if it's inverted or should be a
13840b5aa37fSjob * prefix.
13850b5aa37fSjob */
1386b5341c5bStb aor = sk_IPAddressOrRange_value(aors, j);
1387b5341c5bStb if (aor->type == IPAddressOrRange_addressRange) {
1388b5341c5bStb if (!extract_min_max(aor, a_min, a_max, length))
13890b5aa37fSjob return 0;
1390b5341c5bStb if (memcmp(a_min, a_max, length) > 0)
13910b5aa37fSjob return 0;
1392b5341c5bStb if (range_should_be_prefix(a_min, a_max, length) >= 0)
1393b5341c5bStb return 0;
13940b5aa37fSjob }
13950b5aa37fSjob }
13960b5aa37fSjob
13970b5aa37fSjob /*
13980b5aa37fSjob * If we made it through all that, we're happy.
13990b5aa37fSjob */
14000b5aa37fSjob return 1;
14010b5aa37fSjob }
1402cedac418Stb LCRYPTO_ALIAS(X509v3_addr_is_canonical);
14030b5aa37fSjob
14040b5aa37fSjob /*
14050b5aa37fSjob * Whack an IPAddressOrRanges into canonical form.
14060b5aa37fSjob */
14071a94ae9bSjob static int
IPAddressOrRanges_canonize(IPAddressOrRanges * aors,const unsigned afi)14081a94ae9bSjob IPAddressOrRanges_canonize(IPAddressOrRanges *aors, const unsigned afi)
14090b5aa37fSjob {
141097ab7993Stb IPAddressOrRange *a, *b, *merged;
141197ab7993Stb unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN];
141297ab7993Stb unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN];
141397ab7993Stb int i, j, length;
141497ab7993Stb
14152b4f9a55Stb if (!length_from_afi(afi, &length))
14162b4f9a55Stb return 0;
14170b5aa37fSjob
14180b5aa37fSjob /*
14190b5aa37fSjob * Sort the IPAddressOrRanges sequence.
14200b5aa37fSjob */
14210b5aa37fSjob sk_IPAddressOrRange_sort(aors);
14220b5aa37fSjob
14230b5aa37fSjob /*
14240b5aa37fSjob * Clean up representation issues, punt on duplicates or overlaps.
14250b5aa37fSjob */
14260b5aa37fSjob for (i = 0; i < sk_IPAddressOrRange_num(aors) - 1; i++) {
142797ab7993Stb a = sk_IPAddressOrRange_value(aors, i);
142897ab7993Stb b = sk_IPAddressOrRange_value(aors, i + 1);
14290b5aa37fSjob
14300b5aa37fSjob if (!extract_min_max(a, a_min, a_max, length) ||
14310b5aa37fSjob !extract_min_max(b, b_min, b_max, length))
14320b5aa37fSjob return 0;
14330b5aa37fSjob
14340b5aa37fSjob /*
14350b5aa37fSjob * Punt inverted ranges.
14360b5aa37fSjob */
14370b5aa37fSjob if (memcmp(a_min, a_max, length) > 0 ||
14380b5aa37fSjob memcmp(b_min, b_max, length) > 0)
14390b5aa37fSjob return 0;
14400b5aa37fSjob
14410b5aa37fSjob /*
14420b5aa37fSjob * Punt overlaps.
14430b5aa37fSjob */
14440b5aa37fSjob if (memcmp(a_max, b_min, length) >= 0)
14450b5aa37fSjob return 0;
14460b5aa37fSjob
14470b5aa37fSjob /*
14480b5aa37fSjob * Merge if a and b are adjacent. We check for
14490b5aa37fSjob * adjacency by subtracting one from b_min first.
14500b5aa37fSjob */
14511a94ae9bSjob for (j = length - 1; j >= 0 && b_min[j]-- == 0x00; j--)
1452ff7f58ebSjob continue;
145397ab7993Stb
145497ab7993Stb if (memcmp(a_max, b_min, length) != 0)
145597ab7993Stb continue;
145697ab7993Stb
145797ab7993Stb if (!make_addressRange(&merged, a_min, b_max, afi, length))
14580b5aa37fSjob return 0;
145997ab7993Stb sk_IPAddressOrRange_set(aors, i, merged);
1460f978902fStb (void)sk_IPAddressOrRange_delete(aors, i + 1);
14610b5aa37fSjob IPAddressOrRange_free(a);
14620b5aa37fSjob IPAddressOrRange_free(b);
146397ab7993Stb i--;
14640b5aa37fSjob }
14650b5aa37fSjob
14660b5aa37fSjob /*
14670b5aa37fSjob * Check for inverted final range.
14680b5aa37fSjob */
14694579fb7dStb a = sk_IPAddressOrRange_value(aors, i);
14700b5aa37fSjob if (a != NULL && a->type == IPAddressOrRange_addressRange) {
14710b5aa37fSjob if (!extract_min_max(a, a_min, a_max, length))
14720b5aa37fSjob return 0;
14730b5aa37fSjob if (memcmp(a_min, a_max, length) > 0)
14740b5aa37fSjob return 0;
14750b5aa37fSjob }
14760b5aa37fSjob
14770b5aa37fSjob return 1;
14780b5aa37fSjob }
14790b5aa37fSjob
14800b5aa37fSjob /*
14810b5aa37fSjob * Whack an IPAddrBlocks extension into canonical form.
14820b5aa37fSjob */
14831a94ae9bSjob int
X509v3_addr_canonize(IPAddrBlocks * addr)14841a94ae9bSjob X509v3_addr_canonize(IPAddrBlocks *addr)
14850b5aa37fSjob {
148670818e4aStb IPAddressFamily *af;
14875589d264Stb IPAddressOrRanges *aors;
1488a4b2db38Stb uint16_t afi;
14890b5aa37fSjob int i;
1490aa99f8feStb
14910b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
149270818e4aStb af = sk_IPAddressFamily_value(addr, i);
1493c719c8bcStb
1494c719c8bcStb /* Check AFI/SAFI here - IPAddressFamily_cmp() can't error. */
149570818e4aStb if (!IPAddressFamily_afi(af, &afi))
1496c719c8bcStb return 0;
1497c719c8bcStb
149870818e4aStb if ((aors = IPAddressFamily_addressesOrRanges(af)) == NULL)
14995589d264Stb continue;
15005589d264Stb
15015589d264Stb if (!IPAddressOrRanges_canonize(aors, afi))
15020b5aa37fSjob return 0;
15030b5aa37fSjob }
1504aa99f8feStb
1505f978902fStb (void)sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp);
15060b5aa37fSjob sk_IPAddressFamily_sort(addr);
1507aa99f8feStb
1508aa99f8feStb return X509v3_addr_is_canonical(addr);
15090b5aa37fSjob }
1510cedac418Stb LCRYPTO_ALIAS(X509v3_addr_canonize);
15110b5aa37fSjob
15120b5aa37fSjob /*
15130b5aa37fSjob * v2i handler for the IPAddrBlocks extension.
15140b5aa37fSjob */
15151a94ae9bSjob static void *
v2i_IPAddrBlocks(const struct v3_ext_method * method,struct v3_ext_ctx * ctx,STACK_OF (CONF_VALUE)* values)15161a94ae9bSjob v2i_IPAddrBlocks(const struct v3_ext_method *method, struct v3_ext_ctx *ctx,
15170b5aa37fSjob STACK_OF(CONF_VALUE)*values)
15180b5aa37fSjob {
15190b5aa37fSjob static const char v4addr_chars[] = "0123456789.";
15200b5aa37fSjob static const char v6addr_chars[] = "0123456789.:abcdefABCDEF";
15210b5aa37fSjob IPAddrBlocks *addr = NULL;
15220b5aa37fSjob char *s = NULL, *t;
15230b5aa37fSjob int i;
15240b5aa37fSjob
15250b5aa37fSjob if ((addr = sk_IPAddressFamily_new(IPAddressFamily_cmp)) == NULL) {
1526dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
15270b5aa37fSjob return NULL;
15280b5aa37fSjob }
15290b5aa37fSjob
15300b5aa37fSjob for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
15310b5aa37fSjob CONF_VALUE *val = sk_CONF_VALUE_value(values, i);
15320b5aa37fSjob unsigned char min[ADDR_RAW_BUF_LEN], max[ADDR_RAW_BUF_LEN];
15330b5aa37fSjob unsigned afi, *safi = NULL, safi_;
15340b5aa37fSjob const char *addr_chars = NULL;
15359addd722Stb const char *errstr;
153602fbd552Stb int prefix_len, i1, i2, delim, length;
15370b5aa37fSjob
15380b5aa37fSjob if (!name_cmp(val->name, "IPv4")) {
15390b5aa37fSjob afi = IANA_AFI_IPV4;
15400b5aa37fSjob } else if (!name_cmp(val->name, "IPv6")) {
15410b5aa37fSjob afi = IANA_AFI_IPV6;
15420b5aa37fSjob } else if (!name_cmp(val->name, "IPv4-SAFI")) {
15430b5aa37fSjob afi = IANA_AFI_IPV4;
15440b5aa37fSjob safi = &safi_;
15450b5aa37fSjob } else if (!name_cmp(val->name, "IPv6-SAFI")) {
15460b5aa37fSjob afi = IANA_AFI_IPV6;
15470b5aa37fSjob safi = &safi_;
15480b5aa37fSjob } else {
1549dd120803Sjob X509V3error(X509V3_R_EXTENSION_NAME_ERROR);
15500b5aa37fSjob X509V3_conf_err(val);
15510b5aa37fSjob goto err;
15520b5aa37fSjob }
15530b5aa37fSjob
15540b5aa37fSjob switch (afi) {
15550b5aa37fSjob case IANA_AFI_IPV4:
15560b5aa37fSjob addr_chars = v4addr_chars;
15570b5aa37fSjob break;
15580b5aa37fSjob case IANA_AFI_IPV6:
15590b5aa37fSjob addr_chars = v6addr_chars;
15600b5aa37fSjob break;
15610b5aa37fSjob }
15620b5aa37fSjob
15632b4f9a55Stb if (!length_from_afi(afi, &length))
15642b4f9a55Stb goto err;
15650b5aa37fSjob
15660b5aa37fSjob /*
15675f135508Sjob * Handle SAFI, if any, and strdup() so we can null-terminate
15680b5aa37fSjob * the other input values.
15690b5aa37fSjob */
15700b5aa37fSjob if (safi != NULL) {
15715420e9ccStb unsigned long parsed_safi;
15725420e9ccStb int saved_errno = errno;
15735420e9ccStb
15745420e9ccStb errno = 0;
15755420e9ccStb parsed_safi = strtoul(val->value, &t, 0);
15765420e9ccStb
15775420e9ccStb /* Value must be present, then a tab, space or colon. */
15785420e9ccStb if (val->value[0] == '\0' ||
15795420e9ccStb (*t != '\t' && *t != ' ' && *t != ':')) {
1580dd120803Sjob X509V3error(X509V3_R_INVALID_SAFI);
15810b5aa37fSjob X509V3_conf_err(val);
15820b5aa37fSjob goto err;
15830b5aa37fSjob }
15845420e9ccStb /* Range and overflow check. */
15855420e9ccStb if ((errno == ERANGE && parsed_safi == ULONG_MAX) ||
158617c51bc6Stb parsed_safi > 0xff) {
15875420e9ccStb X509V3error(X509V3_R_INVALID_SAFI);
15885420e9ccStb X509V3_conf_err(val);
15895420e9ccStb goto err;
15905420e9ccStb }
15915420e9ccStb errno = saved_errno;
15925420e9ccStb
15935420e9ccStb *safi = parsed_safi;
15945420e9ccStb
15955420e9ccStb /* Check possible whitespace is followed by a colon. */
15960b5aa37fSjob t += strspn(t, " \t");
15975420e9ccStb if (*t != ':') {
15985420e9ccStb X509V3error(X509V3_R_INVALID_SAFI);
15995420e9ccStb X509V3_conf_err(val);
16005420e9ccStb goto err;
16015420e9ccStb }
16025420e9ccStb
16035420e9ccStb /* Skip over colon. */
16045420e9ccStb t++;
16055420e9ccStb
16065420e9ccStb /* Then over any trailing whitespace. */
16075420e9ccStb t += strspn(t, " \t");
16085420e9ccStb
16095f135508Sjob s = strdup(t);
16100b5aa37fSjob } else {
16115f135508Sjob s = strdup(val->value);
16120b5aa37fSjob }
16130b5aa37fSjob if (s == NULL) {
1614dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
16150b5aa37fSjob goto err;
16160b5aa37fSjob }
16170b5aa37fSjob
16180b5aa37fSjob /*
16190b5aa37fSjob * Check for inheritance. Not worth additional complexity to
16200b5aa37fSjob * optimize this (seldom-used) case.
16210b5aa37fSjob */
16220b5aa37fSjob if (strcmp(s, "inherit") == 0) {
16230b5aa37fSjob if (!X509v3_addr_add_inherit(addr, afi, safi)) {
1624dd120803Sjob X509V3error(X509V3_R_INVALID_INHERITANCE);
16250b5aa37fSjob X509V3_conf_err(val);
16260b5aa37fSjob goto err;
16270b5aa37fSjob }
162895e11b57Sjob free(s);
16290b5aa37fSjob s = NULL;
16300b5aa37fSjob continue;
16310b5aa37fSjob }
16320b5aa37fSjob
16330b5aa37fSjob i1 = strspn(s, addr_chars);
16340b5aa37fSjob i2 = i1 + strspn(s + i1, " \t");
16350b5aa37fSjob delim = s[i2++];
16360b5aa37fSjob s[i1] = '\0';
16370b5aa37fSjob
16380b5aa37fSjob if (a2i_ipadd(min, s) != length) {
1639dd120803Sjob X509V3error(X509V3_R_INVALID_IPADDRESS);
16400b5aa37fSjob X509V3_conf_err(val);
16410b5aa37fSjob goto err;
16420b5aa37fSjob }
16430b5aa37fSjob
16440b5aa37fSjob switch (delim) {
16450b5aa37fSjob case '/':
16469addd722Stb /* length contains the size of the address in bytes. */
16479addd722Stb if (length != 4 && length != 16)
16489addd722Stb goto err;
164902fbd552Stb prefix_len = strtonum(s + i2, 0, 8 * length, &errstr);
16509addd722Stb if (errstr != NULL) {
1651dd120803Sjob X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
16520b5aa37fSjob X509V3_conf_err(val);
16530b5aa37fSjob goto err;
16540b5aa37fSjob }
16551a94ae9bSjob if (!X509v3_addr_add_prefix(addr, afi, safi, min,
165602fbd552Stb prefix_len)) {
1657dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
16580b5aa37fSjob goto err;
16590b5aa37fSjob }
16600b5aa37fSjob break;
16610b5aa37fSjob case '-':
16620b5aa37fSjob i1 = i2 + strspn(s + i2, " \t");
16630b5aa37fSjob i2 = i1 + strspn(s + i1, addr_chars);
16640b5aa37fSjob if (i1 == i2 || s[i2] != '\0') {
1665dd120803Sjob X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
16660b5aa37fSjob X509V3_conf_err(val);
16670b5aa37fSjob goto err;
16680b5aa37fSjob }
16690b5aa37fSjob if (a2i_ipadd(max, s + i1) != length) {
1670dd120803Sjob X509V3error(X509V3_R_INVALID_IPADDRESS);
16710b5aa37fSjob X509V3_conf_err(val);
16720b5aa37fSjob goto err;
16730b5aa37fSjob }
16742b4f9a55Stb if (memcmp(min, max, length) > 0) {
1675dd120803Sjob X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
16760b5aa37fSjob X509V3_conf_err(val);
16770b5aa37fSjob goto err;
16780b5aa37fSjob }
16790b5aa37fSjob if (!X509v3_addr_add_range(addr, afi, safi, min, max)) {
1680dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
16810b5aa37fSjob goto err;
16820b5aa37fSjob }
16830b5aa37fSjob break;
16840b5aa37fSjob case '\0':
16851a94ae9bSjob if (!X509v3_addr_add_prefix(addr, afi, safi, min,
16861a94ae9bSjob length * 8)) {
1687dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
16880b5aa37fSjob goto err;
16890b5aa37fSjob }
16900b5aa37fSjob break;
16910b5aa37fSjob default:
1692dd120803Sjob X509V3error(X509V3_R_EXTENSION_VALUE_ERROR);
16930b5aa37fSjob X509V3_conf_err(val);
16940b5aa37fSjob goto err;
16950b5aa37fSjob }
16960b5aa37fSjob
169795e11b57Sjob free(s);
16980b5aa37fSjob s = NULL;
16990b5aa37fSjob }
17000b5aa37fSjob
17010b5aa37fSjob /*
17020b5aa37fSjob * Canonize the result, then we're done.
17030b5aa37fSjob */
17040b5aa37fSjob if (!X509v3_addr_canonize(addr))
17050b5aa37fSjob goto err;
17060b5aa37fSjob return addr;
17070b5aa37fSjob
17080b5aa37fSjob err:
170995e11b57Sjob free(s);
17100b5aa37fSjob sk_IPAddressFamily_pop_free(addr, IPAddressFamily_free);
17110b5aa37fSjob return NULL;
17120b5aa37fSjob }
17130b5aa37fSjob
17140b5aa37fSjob /*
17150b5aa37fSjob * OpenSSL dispatch
17160b5aa37fSjob */
1717*8b5faa71Stb static const X509V3_EXT_METHOD x509v3_ext_sbgp_ipAddrBlock = {
17181e9dee73Stb .ext_nid = NID_sbgp_ipAddrBlock,
17191e9dee73Stb .ext_flags = 0,
17201e9dee73Stb .it = &IPAddrBlocks_it,
17211e9dee73Stb .ext_new = NULL,
17221e9dee73Stb .ext_free = NULL,
17231e9dee73Stb .d2i = NULL,
17241e9dee73Stb .i2d = NULL,
17251e9dee73Stb .i2s = NULL,
17261e9dee73Stb .s2i = NULL,
17271e9dee73Stb .i2v = NULL,
17281e9dee73Stb .v2i = v2i_IPAddrBlocks,
17291e9dee73Stb .i2r = i2r_IPAddrBlocks,
17301e9dee73Stb .r2i = NULL,
17311e9dee73Stb .usr_data = NULL,
17320b5aa37fSjob };
17330b5aa37fSjob
1734*8b5faa71Stb const X509V3_EXT_METHOD *
x509v3_ext_method_sbgp_ipAddrBlock(void)1735*8b5faa71Stb x509v3_ext_method_sbgp_ipAddrBlock(void)
1736*8b5faa71Stb {
1737*8b5faa71Stb return &x509v3_ext_sbgp_ipAddrBlock;
1738*8b5faa71Stb }
1739*8b5faa71Stb
17400b5aa37fSjob /*
1741f2de96f0Stb * Figure out whether extension uses inheritance.
17420b5aa37fSjob */
17431a94ae9bSjob int
X509v3_addr_inherits(IPAddrBlocks * addr)17441a94ae9bSjob X509v3_addr_inherits(IPAddrBlocks *addr)
17450b5aa37fSjob {
174670818e4aStb IPAddressFamily *af;
17470b5aa37fSjob int i;
1748f2de96f0Stb
17490b5aa37fSjob if (addr == NULL)
17500b5aa37fSjob return 0;
1751f2de96f0Stb
17520b5aa37fSjob for (i = 0; i < sk_IPAddressFamily_num(addr); i++) {
175370818e4aStb af = sk_IPAddressFamily_value(addr, i);
1754f2de96f0Stb
175570818e4aStb if (IPAddressFamily_inheritance(af) != NULL)
17560b5aa37fSjob return 1;
17570b5aa37fSjob }
1758f2de96f0Stb
17590b5aa37fSjob return 0;
17600b5aa37fSjob }
1761cedac418Stb LCRYPTO_ALIAS(X509v3_addr_inherits);
17620b5aa37fSjob
17630b5aa37fSjob /*
17640b5aa37fSjob * Figure out whether parent contains child.
1765d946f2a2Stb *
1766d946f2a2Stb * This only works correctly if both parent and child are in canonical form.
17670b5aa37fSjob */
17681a94ae9bSjob static int
addr_contains(IPAddressOrRanges * parent,IPAddressOrRanges * child,int length)17691a94ae9bSjob addr_contains(IPAddressOrRanges *parent, IPAddressOrRanges *child, int length)
17700b5aa37fSjob {
17717601c9c8Stb IPAddressOrRange *child_aor, *parent_aor;
1772d0764d1bStb uint8_t parent_min[ADDR_RAW_BUF_LEN], parent_max[ADDR_RAW_BUF_LEN];
1773d0764d1bStb uint8_t child_min[ADDR_RAW_BUF_LEN], child_max[ADDR_RAW_BUF_LEN];
17740b5aa37fSjob int p, c;
17750b5aa37fSjob
17760b5aa37fSjob if (child == NULL || parent == child)
17770b5aa37fSjob return 1;
17780b5aa37fSjob if (parent == NULL)
17790b5aa37fSjob return 0;
17800b5aa37fSjob
17810b5aa37fSjob p = 0;
17820b5aa37fSjob for (c = 0; c < sk_IPAddressOrRange_num(child); c++) {
17837601c9c8Stb child_aor = sk_IPAddressOrRange_value(child, c);
1784d946f2a2Stb
1785d0764d1bStb if (!extract_min_max(child_aor, child_min, child_max, length))
1786e5e14cfcStb return 0;
1787d946f2a2Stb
17880b5aa37fSjob for (;; p++) {
17890b5aa37fSjob if (p >= sk_IPAddressOrRange_num(parent))
17900b5aa37fSjob return 0;
1791d946f2a2Stb
17927601c9c8Stb parent_aor = sk_IPAddressOrRange_value(parent, p);
1793d946f2a2Stb
1794d0764d1bStb if (!extract_min_max(parent_aor, parent_min, parent_max,
1795d0764d1bStb length))
17960b5aa37fSjob return 0;
1797d946f2a2Stb
1798d0764d1bStb if (memcmp(parent_max, child_max, length) < 0)
17990b5aa37fSjob continue;
1800d0764d1bStb if (memcmp(parent_min, child_min, length) > 0)
18010b5aa37fSjob return 0;
18020b5aa37fSjob break;
18030b5aa37fSjob }
18040b5aa37fSjob }
18050b5aa37fSjob
18060b5aa37fSjob return 1;
18070b5aa37fSjob }
18080b5aa37fSjob
18090b5aa37fSjob /*
18102aab0f11Stb * Test whether |child| is a subset of |parent|.
18110b5aa37fSjob */
18121a94ae9bSjob int
X509v3_addr_subset(IPAddrBlocks * child,IPAddrBlocks * parent)18135b11d0bbStb X509v3_addr_subset(IPAddrBlocks *child, IPAddrBlocks *parent)
18140b5aa37fSjob {
1815382c9060Stb IPAddressFamily *child_af, *parent_af;
18167601c9c8Stb IPAddressOrRanges *child_aor, *parent_aor;
18172ad22f62Stb int i, length;
18185b11d0bbStb
18195b11d0bbStb if (child == NULL || child == parent)
18200b5aa37fSjob return 1;
18215b11d0bbStb if (parent == NULL)
18220b5aa37fSjob return 0;
18235b11d0bbStb
18245b11d0bbStb if (X509v3_addr_inherits(child) || X509v3_addr_inherits(parent))
18250b5aa37fSjob return 0;
18265b11d0bbStb
18275b11d0bbStb for (i = 0; i < sk_IPAddressFamily_num(child); i++) {
1828382c9060Stb child_af = sk_IPAddressFamily_value(child, i);
18295b11d0bbStb
1830382c9060Stb parent_af = IPAddressFamily_find_in_parent(parent, child_af);
1831382c9060Stb if (parent_af == NULL)
18325b11d0bbStb return 0;
18335b11d0bbStb
1834382c9060Stb if (!IPAddressFamily_afi_length(parent_af, &length))
18355b11d0bbStb return 0;
18365b11d0bbStb
18377601c9c8Stb child_aor = IPAddressFamily_addressesOrRanges(child_af);
18387601c9c8Stb parent_aor = IPAddressFamily_addressesOrRanges(parent_af);
18395b11d0bbStb
18407601c9c8Stb if (!addr_contains(parent_aor, child_aor, length))
18410b5aa37fSjob return 0;
18420b5aa37fSjob }
18430b5aa37fSjob return 1;
18440b5aa37fSjob }
1845cedac418Stb LCRYPTO_ALIAS(X509v3_addr_subset);
18460b5aa37fSjob
184765d9c3c1Stb static int
verify_error(X509_STORE_CTX * ctx,X509 * cert,int error,int depth)184865d9c3c1Stb verify_error(X509_STORE_CTX *ctx, X509 *cert, int error, int depth)
184965d9c3c1Stb {
185065d9c3c1Stb if (ctx == NULL)
185165d9c3c1Stb return 0;
185265d9c3c1Stb
185365d9c3c1Stb ctx->current_cert = cert;
185465d9c3c1Stb ctx->error = error;
185565d9c3c1Stb ctx->error_depth = depth;
185665d9c3c1Stb
185765d9c3c1Stb return ctx->verify_cb(0, ctx);
185865d9c3c1Stb }
18590b5aa37fSjob
18600b5aa37fSjob /*
18610b5aa37fSjob * Core code for RFC 3779 2.3 path validation.
18620b5aa37fSjob *
18630b5aa37fSjob * Returns 1 for success, 0 on error.
18640b5aa37fSjob *
18650b5aa37fSjob * When returning 0, ctx->error MUST be set to an appropriate value other than
18660b5aa37fSjob * X509_V_OK.
18670b5aa37fSjob */
18681a94ae9bSjob static int
addr_validate_path_internal(X509_STORE_CTX * ctx,STACK_OF (X509)* chain,IPAddrBlocks * ext)18691a94ae9bSjob addr_validate_path_internal(X509_STORE_CTX *ctx, STACK_OF(X509) *chain,
18700b5aa37fSjob IPAddrBlocks *ext)
18710b5aa37fSjob {
1872b7d4d78fStb IPAddrBlocks *child = NULL, *parent = NULL;
1873382c9060Stb IPAddressFamily *child_af, *parent_af;
18747601c9c8Stb IPAddressOrRanges *child_aor, *parent_aor;
187523d19b24Stb X509 *cert = NULL;
18766788a3caStb int depth = -1;
18772ad22f62Stb int i;
1878b7d4d78fStb unsigned int length;
1879b7d4d78fStb int ret = 1;
18800b5aa37fSjob
1881ee334350Stb /* We need a non-empty chain to test against. */
1882ee334350Stb if (sk_X509_num(chain) <= 0)
1883ee334350Stb goto err;
1884ee334350Stb /* We need either a store ctx or an extension to work with. */
1885ee334350Stb if (ctx == NULL && ext == NULL)
1886ee334350Stb goto err;
1887ee334350Stb /* If there is a store ctx, it needs a verify_cb. */
1888ee334350Stb if (ctx != NULL && ctx->verify_cb == NULL)
1889ee334350Stb goto err;
18900b5aa37fSjob
18910b5aa37fSjob /*
18923c1c1242Sjob * Figure out where to start. If we don't have an extension to check,
1893f34e4695Stb * (either extracted from the leaf or passed by the caller), we're done.
1894f34e4695Stb * Otherwise, check canonical form and set up for walking up the chain.
18950b5aa37fSjob */
18966788a3caStb if (ext == NULL) {
18976788a3caStb depth = 0;
189823d19b24Stb cert = sk_X509_value(chain, depth);
1899c8ef2279Stb if ((X509_get_extension_flags(cert) & EXFLAG_INVALID) != 0) {
1900c8ef2279Stb if ((ret = verify_error(ctx, cert,
1901c8ef2279Stb X509_V_ERR_INVALID_EXTENSION, depth)) == 0)
19021b14589dStb goto done;
1903c8ef2279Stb }
190423d19b24Stb if ((ext = cert->rfc3779_addr) == NULL)
19050b5aa37fSjob goto done;
19061b14589dStb } else if (!X509v3_addr_is_canonical(ext)) {
190723d19b24Stb if ((ret = verify_error(ctx, cert,
19086788a3caStb X509_V_ERR_INVALID_EXTENSION, depth)) == 0)
190965d9c3c1Stb goto done;
191065d9c3c1Stb }
191165d9c3c1Stb
19120b5aa37fSjob (void)sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp);
19130b5aa37fSjob if ((child = sk_IPAddressFamily_dup(ext)) == NULL) {
1914dd120803Sjob X509V3error(ERR_R_MALLOC_FAILURE);
19150b5aa37fSjob if (ctx != NULL)
19160b5aa37fSjob ctx->error = X509_V_ERR_OUT_OF_MEM;
19170b5aa37fSjob ret = 0;
19180b5aa37fSjob goto done;
19190b5aa37fSjob }
19200b5aa37fSjob
19210b5aa37fSjob /*
19223c1c1242Sjob * Now walk up the chain. No cert may list resources that its parent
19233c1c1242Sjob * doesn't list.
19240b5aa37fSjob */
19256788a3caStb for (depth++; depth < sk_X509_num(chain); depth++) {
192623d19b24Stb cert = sk_X509_value(chain, depth);
1927b7d4d78fStb
19281b14589dStb if ((X509_get_extension_flags(cert) & EXFLAG_INVALID) != 0) {
19291b14589dStb if ((ret = verify_error(ctx, cert,
19301b14589dStb X509_V_ERR_INVALID_EXTENSION, depth)) == 0)
19311b14589dStb goto done;
19321b14589dStb }
19331b14589dStb
193423d19b24Stb if ((parent = cert->rfc3779_addr) == NULL) {
1935817223e6Stb for (i = 0; i < sk_IPAddressFamily_num(child); i++) {
1936382c9060Stb child_af = sk_IPAddressFamily_value(child, i);
1937b7d4d78fStb
1938382c9060Stb if (IPAddressFamily_inheritance(child_af) !=
1939382c9060Stb NULL)
194065d9c3c1Stb continue;
194165d9c3c1Stb
194223d19b24Stb if ((ret = verify_error(ctx, cert,
19436788a3caStb X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0)
194465d9c3c1Stb goto done;
19450b5aa37fSjob break;
19460b5aa37fSjob }
19470b5aa37fSjob continue;
19480b5aa37fSjob }
1949b7d4d78fStb
1950b7d4d78fStb /*
1951b7d4d78fStb * Check that the child's resources are covered by the parent.
1952b7d4d78fStb * Each covered resource is replaced with the parent's resource
1953b7d4d78fStb * covering it, so the next iteration will check that the
1954b7d4d78fStb * parent's resources are covered by the grandparent.
1955b7d4d78fStb */
1956817223e6Stb for (i = 0; i < sk_IPAddressFamily_num(child); i++) {
1957382c9060Stb child_af = sk_IPAddressFamily_value(child, i);
1958b7d4d78fStb
1959369b4a35Stb if ((parent_af = IPAddressFamily_find_in_parent(parent,
1960369b4a35Stb child_af)) == NULL) {
1961b7d4d78fStb /*
1962b7d4d78fStb * If we have no match in the parent and the
1963b7d4d78fStb * child inherits, that's fine.
1964b7d4d78fStb */
1965382c9060Stb if (IPAddressFamily_inheritance(child_af) !=
1966382c9060Stb NULL)
1967b7d4d78fStb continue;
1968b7d4d78fStb
1969b7d4d78fStb /* Otherwise the child isn't covered. */
197023d19b24Stb if ((ret = verify_error(ctx, cert,
19716788a3caStb X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0)
197265d9c3c1Stb goto done;
19730b5aa37fSjob break;
19740b5aa37fSjob }
1975b7d4d78fStb
1976b7d4d78fStb /* Parent inherits, nothing to do. */
1977382c9060Stb if (IPAddressFamily_inheritance(parent_af) != NULL)
1978b7d4d78fStb continue;
1979b7d4d78fStb
1980b7d4d78fStb /* Child inherits. Use parent's address family. */
1981382c9060Stb if (IPAddressFamily_inheritance(child_af) != NULL) {
1982382c9060Stb sk_IPAddressFamily_set(child, i, parent_af);
19830b5aa37fSjob continue;
19840b5aa37fSjob }
1985b7d4d78fStb
19867601c9c8Stb child_aor = IPAddressFamily_addressesOrRanges(child_af);
1987369b4a35Stb parent_aor =
1988369b4a35Stb IPAddressFamily_addressesOrRanges(parent_af);
1989b7d4d78fStb
1990b7d4d78fStb /*
1991b7d4d78fStb * Child and parent are canonical and neither inherits.
1992b7d4d78fStb * If either addressesOrRanges is NULL, something's
1993b7d4d78fStb * very wrong.
1994b7d4d78fStb */
19957601c9c8Stb if (child_aor == NULL || parent_aor == NULL)
1996b7d4d78fStb goto err;
1997b7d4d78fStb
1998382c9060Stb if (!IPAddressFamily_afi_length(child_af, &length))
1999b7d4d78fStb goto err;
2000b7d4d78fStb
2001b7d4d78fStb /* Now check containment and replace or error. */
20027601c9c8Stb if (addr_contains(parent_aor, child_aor, length)) {
2003382c9060Stb sk_IPAddressFamily_set(child, i, parent_af);
2004b7d4d78fStb continue;
20050b5aa37fSjob }
2006b7d4d78fStb
200723d19b24Stb if ((ret = verify_error(ctx, cert,
20086788a3caStb X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0)
200965d9c3c1Stb goto done;
20100b5aa37fSjob }
20110b5aa37fSjob }
20120b5aa37fSjob
20130b5aa37fSjob /*
20140b5aa37fSjob * Trust anchor can't inherit.
20150b5aa37fSjob */
201623d19b24Stb if ((parent = cert->rfc3779_addr) != NULL) {
2017817223e6Stb for (i = 0; i < sk_IPAddressFamily_num(parent); i++) {
2018382c9060Stb parent_af = sk_IPAddressFamily_value(parent, i);
2019b7d4d78fStb
2020382c9060Stb if (IPAddressFamily_inheritance(parent_af) == NULL)
2021b7d4d78fStb continue;
2022b7d4d78fStb
202323d19b24Stb if ((ret = verify_error(ctx, cert,
20246788a3caStb X509_V_ERR_UNNESTED_RESOURCE, depth)) == 0)
202565d9c3c1Stb goto done;
20260b5aa37fSjob }
20270b5aa37fSjob }
20280b5aa37fSjob
20290b5aa37fSjob done:
20300b5aa37fSjob sk_IPAddressFamily_free(child);
20310b5aa37fSjob return ret;
2032ee334350Stb
2033ee334350Stb err:
2034b7d4d78fStb sk_IPAddressFamily_free(child);
2035b7d4d78fStb
2036ee334350Stb if (ctx != NULL)
2037ee334350Stb ctx->error = X509_V_ERR_UNSPECIFIED;
2038ee334350Stb
2039ee334350Stb return 0;
20400b5aa37fSjob }
20410b5aa37fSjob
20420b5aa37fSjob /*
20430b5aa37fSjob * RFC 3779 2.3 path validation -- called from X509_verify_cert().
20440b5aa37fSjob */
20451a94ae9bSjob int
X509v3_addr_validate_path(X509_STORE_CTX * ctx)20461a94ae9bSjob X509v3_addr_validate_path(X509_STORE_CTX *ctx)
20470b5aa37fSjob {
2048ee334350Stb if (sk_X509_num(ctx->chain) <= 0 || ctx->verify_cb == NULL) {
20490b5aa37fSjob ctx->error = X509_V_ERR_UNSPECIFIED;
20500b5aa37fSjob return 0;
20510b5aa37fSjob }
20520b5aa37fSjob return addr_validate_path_internal(ctx, ctx->chain, NULL);
20530b5aa37fSjob }
2054cedac418Stb LCRYPTO_ALIAS(X509v3_addr_validate_path);
20550b5aa37fSjob
20560b5aa37fSjob /*
20570b5aa37fSjob * RFC 3779 2.3 path validation of an extension.
20580b5aa37fSjob * Test whether chain covers extension.
20590b5aa37fSjob */
20601a94ae9bSjob int
X509v3_addr_validate_resource_set(STACK_OF (X509)* chain,IPAddrBlocks * ext,int allow_inheritance)20611a94ae9bSjob X509v3_addr_validate_resource_set(STACK_OF(X509) *chain, IPAddrBlocks *ext,
20621a94ae9bSjob int allow_inheritance)
20630b5aa37fSjob {
20640b5aa37fSjob if (ext == NULL)
20650b5aa37fSjob return 1;
2066ee334350Stb if (sk_X509_num(chain) <= 0)
20670b5aa37fSjob return 0;
20680b5aa37fSjob if (!allow_inheritance && X509v3_addr_inherits(ext))
20690b5aa37fSjob return 0;
20700b5aa37fSjob return addr_validate_path_internal(NULL, chain, ext);
20710b5aa37fSjob }
2072cedac418Stb LCRYPTO_ALIAS(X509v3_addr_validate_resource_set);
20730b5aa37fSjob
20740b5aa37fSjob #endif /* OPENSSL_NO_RFC3779 */
2075