summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/man/X509v3_addr_add_inherit.3
diff options
context:
space:
mode:
authortb <>2023-09-25 01:14:34 +0000
committertb <>2023-09-25 01:14:34 +0000
commitde805f6a027c108e7292c0c5f4bd5be74fd6fde4 (patch)
tree0c90055b8753a2c2f45f1f0092fece234da5592c /src/lib/libcrypto/man/X509v3_addr_add_inherit.3
parent3ea71d1778f511b776dc81cb998189a896bda759 (diff)
downloadopenbsd-de805f6a027c108e7292c0c5f4bd5be74fd6fde4.tar.gz
openbsd-de805f6a027c108e7292c0c5f4bd5be74fd6fde4.tar.bz2
openbsd-de805f6a027c108e7292c0c5f4bd5be74fd6fde4.zip
Add initial documentation for the RFC 3779 API
This documents the part of the API that allows building the two extensions. It is all very complicated and the bug density is quite high. Surely there's lots of room for improvement, but I've been sitting way too long on versions of these. I'll never finish. Let's fix and improve in tree.
Diffstat (limited to 'src/lib/libcrypto/man/X509v3_addr_add_inherit.3')
-rw-r--r--src/lib/libcrypto/man/X509v3_addr_add_inherit.3455
1 files changed, 455 insertions, 0 deletions
diff --git a/src/lib/libcrypto/man/X509v3_addr_add_inherit.3 b/src/lib/libcrypto/man/X509v3_addr_add_inherit.3
new file mode 100644
index 0000000000..e5730c881e
--- /dev/null
+++ b/src/lib/libcrypto/man/X509v3_addr_add_inherit.3
@@ -0,0 +1,455 @@
1.\" $OpenBSD: X509v3_addr_add_inherit.3,v 1.1 2023/09/25 01:14:34 tb Exp $
2.\"
3.\" Copyright (c) 2023 Theo Buehler <tb@openbsd.org>
4.\"
5.\" Permission to use, copy, modify, and distribute this software for any
6.\" purpose with or without fee is hereby granted, provided that the above
7.\" copyright notice and this permission notice appear in all copies.
8.\"
9.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16.\"
17.Dd $Mdocdate: September 25 2023 $
18.Dt X509V3_ADDR_ADD_INHERIT 3
19.Os
20.Sh NAME
21.Nm X509v3_addr_add_inherit ,
22.Nm X509v3_addr_add_prefix ,
23.Nm X509v3_addr_add_range ,
24.Nm X509v3_addr_canonize ,
25.Nm X509v3_addr_is_canonical
26.Nd construct X509v3 IP address blocks extensions and
27bring them into canonical form
28.Sh SYNOPSIS
29.In openssl/x509v3.h
30.Ft int
31.Fo X509v3_addr_add_inherit
32.Fa "IPAddrBlocks *addrblocks"
33.Fa "const unsigned afi"
34.Fa "const unsigned *safi"
35.Fc
36.Ft int
37.Fo X509v3_addr_add_prefix
38.Fa "IPAddrBlocks *addrblocks"
39.Fa "const unsigned afi"
40.Fa "const unsigned *safi"
41.Fa "unsigned char *prefix"
42.Fa "const int prefixlen"
43.Fc
44.Ft int
45.Fo X509v3_addr_add_range
46.Fa "IPAddrBlocks *addrblocks"
47.Fa "const unsigned afi"
48.Fa "const unsigned *safi"
49.Fa "unsigned char *min"
50.Fa "unsigned char *max"
51.Fc
52.Ft int
53.Fo X509v3_addr_canonize
54.Fa "IPAddrBlocks *addrblocks"
55.Fc
56.Ft int
57.Fo X509v3_addr_is_canonical
58.Fa "IPAddrBlocks *addrblocks"
59.Fc
60.Sh DESCRIPTION
61An
62.Vt IPAddrBlocks
63object represents the content of
64an X509v3 IP address blocks delegation extension
65as defined in RFC 3779, section 2.2.3.1.
66It can hold lists of delegated IP address prefixes and
67IP address ranges.
68Each list is uniquely identified by
69an address family identifier (AFI) and
70an optional subsequent address family identifier (SAFI).
71Each list can be absent or it can contain a single
72.Dq inherit
73marker to indicate that the resources are to be inherited
74from the corresponding list of the issuer certificate.
75.Pp
76Per specification, an AFI is an unsigned 16-bit integer and
77a SAFI is an unsigned 8-bit integer.
78For IPv4 and IPv6 there are the predefined constants
79.Dv IANA_AFI_IPV4
80and
81.Dv IANA_AFI_IPV6 ,
82which should be the only values used for
83.Fa afi
84in this API.
85In practice,
86.Fa safi
87is always NULL.
88.Fa afi
89is generally silently truncated to its lowest 16 bits and, if
90.Fa safi
91is non-NULL,
92only the lowest 8 bits of the value pointed at are used.
93.Pp
94.Fn X509v3_addr_add_inherit
95adds a list with an
96.Dq inherit
97marker to
98.Fa addrblocks .
99If a list corresponding to
100.Fa afi
101and
102.Fa safi
103already exists, no action occurs if it is marked
104.Dq inherit ,
105otherwise the call fails.
106.Pp
107.Fn X509v3_addr_add_prefix
108adds a newly allocated internal representation of the
109.Fa prefix
110of length
111.Fa prefixlen
112to the list corresponding to
113.Fa afi
114and the optional
115.Fa safi
116in
117.Fa addrblocks .
118If no such list exists, it is created first.
119If the list exists and is marked
120.Dq inherit ,
121the call fails.
122.Fa prefix
123is expected to be a byte array in network byte order.
124It should point at enough memory to accommodate
125.Fa prefixlen
126bits and it is recommended that all the bits not covered by
127the prefixlen be set to 0.
128It is the caller's responsibility to ensure that the prefix
129has no address in common with any of
130the prefixes or ranges already in the list.
131If
132.Fa afi
133is
134.Dv IANA_AFI_IPV4 ,
135.Fa prefixlen
136should be between 0 and 32 (inclusive) and if
137.Fa afi
138is
139.Dv IANA_AFI_IPV6 ,
140.Fa prefixlen
141should be between 0 and 128 (inclusive).
142.Pp
143.Fn X509v3_addr_add_range
144is similar to
145.Fn X509v3_addr_add_prefix
146for the closed interval of IP addresses between
147.Fa min
148and
149.Fa max
150in network presentation.
151If
152.Fa afi
153is
154.Dv IANA_AFI_IPV4 ,
155.Fa min
156and
157.Fa max
158should point at 4 bytes of memory
159and if
160.Fa afi
161is
162.Dv IANA_AFI_IPV6 ,
163.Fa min
164and
165.Fa max
166should point at 16 bytes of memory.
167In case the range of IP addresses between
168.Fa min
169and
170.Fa max
171is a prefix, a prefix will be added.
172It is the caller's responsibility to ensure that
173.Fa min
174is less than or equal to
175.Fa max
176and that it does not contain any address already present
177in the list.
178Failure to do so will result in a subsequent failure of
179.Fn X509v3_addr_canonize .
180.Pp
181.Fn X509v3_addr_canonize
182attempts to bring the
183.Pf non- Dv NULL
184.Fa addrblocks
185into canonical form.
186An
187.Vt IPAddrBlocks
188object is said to be in canonical form if it conforms
189to the ordering specified in RFC 3779:
190section 2.2.3.3 requires that the lists be sorted first by increasing
191.Fa afi
192and then by increasing
193.Fa safi ,
194where NULL is the minimal SAFI;
195section 2.2.3.6 requires that each list be in minimal form and sorted.
196The minimality requirement is that all adjacent prefixes
197and ranges must be merged into a single range and that each
198range must be expressed as a prefix, if possible.
199In particular, any given address can be in at most one list entry.
200The order is by increasing minimal IP address in network byte order.
201.Pp
202.Fn X509v3_addr_is_canonical
203indicates whether
204.Fa addrblocks
205is in canonical form.
206.Sh RETURN VALUES
207All these functions return 1 on success and 0 on failure.
208Memory allocation failure is one possible reason for all of them.
209Sometimes an error code can be obtained by
210.Xr ERR_get_error 3 .
211.Pp
212.Fn X509v3_addr_add_inherit
213fails if the list corresponding to
214.Fa afi
215and the optional
216.Fa safi
217already exists and is not marked
218.Dq inherit .
219.Pp
220.Fn X509v3_addr_add_prefix
221and
222.Fn X509v3_addr_add_range
223fail if a list corresponding to
224.Fa afi
225and the optional
226.Fa safi
227already exists and is marked
228.Dq inherit ,
229or if
230.Fa prefixlen
231is outside the interval [0,32] for IPv4 addresses
232or [0,128] for IPv6 addresses.
233.Pp
234.Fn X509v3_addr_canonize
235fails if one of the lists in
236.Fa addrblocks
237is malformed,
238in particular if it contains corrupt, overlapping,
239or duplicate entries.
240Corruption includes ranges where
241.Fa max
242is strictly smaller than
243.Fa min .
244The error conditions are generally indistinguishable.
245.Pp
246.Fn X509v3_addr_is_canonical
247returns 1 if
248.Fa addrblocks
249is in canonical form.
250A return value of 0 can indicate non-canonical form or corrupted list.
251.Sh EXAMPLES
252Construct the first extension from RFC 3779, Appendix B.
253.Bd -literal
254#include <sys/socket.h>
255#include <arpa/inet.h>
256
257#include <err.h>
258#include <stdio.h>
259#include <unistd.h>
260
261#include <openssl/asn1.h>
262#include <openssl/objects.h>
263#include <openssl/x509.h>
264#include <openssl/x509v3.h>
265
266const char *prefixes[6] = {
267 "10.0.32/20", "10.0.64/24", "10.1/16",
268 "10.2.48/20", "10.2.64/24", "10.3/16",
269};
270#define N_PREFIXES (sizeof(prefixes) / sizeof(prefixes[0]))
271
272static void
273hexdump(const unsigned char *buf, size_t len)
274{
275 size_t i;
276
277 for (i = 1; i <= len; i++)
278 printf(" 0x%02x,%s", buf[i - 1], i % 8 ? "" : "\en");
279 if (len % 8)
280 printf("\en");
281}
282
283int
284main(void)
285{
286 IPAddrBlocks *addrblocks;
287 X509_EXTENSION *ext;
288 unsigned char *der;
289 int der_len;
290 size_t i;
291
292 if (pledge("stdio", NULL) == -1)
293 err(1, "pledge");
294
295 /*
296 * Somebody forgot to implement IPAddrBlocks_new(). IPAddrBlocks
297 * is the same as STACK_OF(IPAddressFamily). As such, it should
298 * have IPAddressFamily_cmp() as its comparison function. It is
299 * not possible to call sk_new(3) because IPAddressFamily_cmp()
300 * is not part of the public API. The correct comparison function
301 * can be installed as a side-effect of X509v3_addr_canonize(3).
302 */
303 if ((addrblocks = sk_IPAddressFamily_new_null()) == NULL)
304 err(1, "sk_IPAddressFamily_new_null");
305 if (!X509v3_addr_canonize(addrblocks))
306 errx(1, "X509v3_addr_canonize");
307
308 /* Add the prefixes as IPv4 unicast. */
309 for (i = 0; i < N_PREFIXES; i++) {
310 unsigned char addr[16] = {0};
311 int len;
312 int unicast = 1; /* SAFI for unicast forwarding. */
313
314 len = inet_net_pton(AF_INET, prefixes[i], addr,
315 sizeof(addr));
316 if (len == -1)
317 errx(1, "inet_net_pton(%s)", prefixes[i]);
318 if (!X509v3_addr_add_prefix(addrblocks, IANA_AFI_IPV4,
319 &unicast, addr, len))
320 errx(1, "X509v3_addr_add_prefix(%s)", prefixes[i]);
321 }
322 if (!X509v3_addr_add_inherit(addrblocks, IANA_AFI_IPV6, NULL))
323 errx(1, "X509v3_addr_add_inherit");
324
325 /*
326 * Ensure the extension is in canonical form. Otherwise the two
327 * adjacent prefixes 10.2.48/20 and 10.2.64/24 are not merged into
328 * the range 10.2.48.0--10.2.64.255. This results in invalid DER
329 * encoding from X509V3_EXT_i2d(3) and i2d_X509_EXTENSION(3).
330 */
331 if (!X509v3_addr_canonize(addrblocks))
332 errx(1, "X509v3_addr_canonize");
333
334 /* Create the extension. The 1 indicates that it is critical. */
335 ext = X509V3_EXT_i2d(NID_sbgp_ipAddrBlock, 1, addrblocks);
336 if (ext == NULL)
337 errx(1, "X509V3_EXT_i2d");
338
339 der = NULL;
340 if ((der_len = i2d_X509_EXTENSION(ext, &der)) <= 0)
341 errx(1, "i2d_X509_EXTENSION");
342
343 hexdump(der, der_len);
344
345 /* One way of implementing IPAddrBlocks_free(). */
346 sk_IPAddressFamily_pop_free(addrblocks, IPAddressFamily_free);
347 X509_EXTENSION_free(ext);
348 free(der);
349
350 return 0;
351}
352.Ed
353.Pp
354Implement the missing public API
355.Fn d2i_IPAddrBlocks
356and
357.Fn i2d_IPAddrBlocks
358using
359.Xr ASN1_item_d2i 3 :
360.Bd -literal
361IPAddrBlocks *
362d2i_IPAddrBlocks(IPAddrBlocks **addrblocks, const unsigned char **in,
363 long len)
364{
365 const X509V3_EXT_METHOD *v3_addr;
366
367 if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL)
368 return NULL;
369 return (IPAddrBlocks *)ASN1_item_d2i((ASN1_VALUE **)addrblocks,
370 in, len, ASN1_ITEM_ptr(v3_addr->it));
371}
372
373int
374i2d_IPAddrBlocks(IPAddrBlocks *addrblocks, unsigned char **out)
375{
376 const X509V3_EXT_METHOD *v3_addr;
377
378 if ((v3_addr = X509V3_EXT_get_nid(NID_sbgp_ipAddrBlock)) == NULL)
379 return -1;
380 return ASN1_item_i2d((ASN1_VALUE *)addrblocks, out,
381 ASN1_ITEM_ptr(v3_addr->it));
382}
383.Ed
384.Pp
385the use of the undocumented macro
386.Dv ASN1_ITEM_ptr()
387is necessary if compatibility with modern versions of other implementations
388is desired.
389.Sh SEE ALSO
390.Xr ASIdentifiers_new 3 ,
391.Xr crypto 3 ,
392.Xr inet_net_ntop 3 ,
393.Xr inet_ntop 3 ,
394.Xr X509_new 3 ,
395.Xr X509v3_asid_add_id_or_range 3
396.Sh STANDARDS
397RFC 3779: X.509 Extensions for IP Addresses and AS Identifiers:
398.Bl -dash -compact
399.It
400section 2: IP Address delegation extension
401.El
402.Pp
403RFC 7020: The Internet Numbers Registry System
404.Pp
405RFC 7249: Internet Number Registries
406.Pp
407.Rs
408.%T Address Family Numbers
409.%U https://www.iana.org/assignments/address-family-numbers
410.Re
411.Pp
412.Rs
413.%T Subsequent Address Family Identifiers (SAFI) Parameters
414.%U https://www.iana.org/assignments/safi-namespace
415.Re
416.Sh HISTORY
417These functions first appeared in OpenSSL 0.9.8e
418and have been available since
419.Ox 7.1 .
420.Sh BUGS
421.Fn IPAddrBlocks_new ,
422.Fn IPAddrBlocks_free ,
423.Fn d2i_IPAddrBlocks ,
424and
425.Fn i2d_IPAddrBlocks
426do not exist and
427.Fa IPAddrBlocks_it
428is not public.
429The above examples show how to implement the four missing functions
430with public API.
431.Pp
432.Fn X509v3_asid_add_range
433should check for inverted range bounds and overlaps
434on insertion and fail instead of creating a nonsensical
435.Fa asid
436that fails to be canonized by
437.Fn X509v3_asid_canonize .
438.Pp
439If
440.Dv NULL
441is passed to
442.Xr X509v3_asid_canonize 3 ,
443it succeeds.
444.Fn X509v3_addr_is_canonical
445considers
446.Dv NULL
447to be a canonical
448.Vt IPAddrBlocks .
449In contrast,
450.Fn X509v3_addr_canonize
451crashes with a
452.Dv NULL
453dereference.
454.Pp
455The only supported AFIs are IPv4 and IPv6, but this is not enforced.