Botan 3.13.0
Crypto and TLS for C&
ffi_cert_ext.cpp
Go to the documentation of this file.
1/*
2* (C) 2026 Jack Lloyd
3* (C) 2026 Dominik Schricker
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ffi.h>
9
10#include <botan/assert.h>
11#include <botan/internal/ffi_cert.h>
12#include <botan/internal/ffi_util.h>
13
14#if defined(BOTAN_HAS_X509_CERTIFICATES)
15 #include <botan/x509_ext.h>
16#endif
17
18namespace {
19#if defined(BOTAN_HAS_X509_CERTIFICATES)
20
21template <Botan::Cert_Extension::IPAddressBlocks::Version V>
22int ip_addr_blocks_get_family(const Botan::Cert_Extension::IPAddressBlocks::IPAddressFamily& family,
23 int* present,
24 size_t* count) {
25 if(!std::holds_alternative<Botan::Cert_Extension::IPAddressBlocks::IPAddressChoice<V>>(family.addr_choice())) {
27 }
28 const auto& choice = std::get<Botan::Cert_Extension::IPAddressBlocks::IPAddressChoice<V>>(family.addr_choice());
29
30 if(!choice.ranges().has_value()) {
31 *present = 0;
32 } else {
33 *present = 1;
34 *count = choice.ranges().value().size();
35 }
36 return BOTAN_FFI_SUCCESS;
37}
38
39template <Botan::Cert_Extension::IPAddressBlocks::Version V>
40int ip_addr_blocks_get_address(const Botan::Cert_Extension::IPAddressBlocks::IPAddressFamily::AddrChoice& addr_choice,
41 size_t entry,
42 uint8_t min_out[],
43 uint8_t max_out[],
44 size_t* out_len) {
45 if(!std::holds_alternative<Botan::Cert_Extension::IPAddressBlocks::IPAddressChoice<V>>(addr_choice)) {
47 }
48 const auto& choice = std::get<Botan::Cert_Extension::IPAddressBlocks::IPAddressChoice<V>>(addr_choice);
49
50 if(!choice.ranges().has_value()) {
52 }
53 if(entry >= choice.ranges().value().size()) {
55 }
56
57 const auto& entry_ = choice.ranges().value().at(entry);
58
59 const int ret = Botan_FFI::write_vec_output(min_out, out_len, entry_.min().value());
60 if(ret != BOTAN_FFI_SUCCESS) {
61 return ret;
62 }
63 return Botan_FFI::write_vec_output(max_out, out_len, entry_.max().value());
64}
65#endif
66} // namespace
67
68extern "C" {
69
70using namespace Botan_FFI;
71
72// ip addr blocks ext
73int botan_x509_ext_ip_addr_blocks_get_counts(botan_x509_cert_t cert, size_t* v4_count, size_t* v6_count) {
74 if(Botan::any_null_pointers(v4_count, v6_count)) {
76 }
77#if defined(BOTAN_HAS_X509_CERTIFICATES)
78 return ffi_guard_thunk(__func__, [=]() -> int {
79 const auto& ext =
80 safe_get(cert).v3_extensions().get_extension_object_as<Botan::Cert_Extension::IPAddressBlocks>();
83 }
84
85 *v4_count = ext->v4_count();
86 *v6_count = ext->v6_count();
87
88 return BOTAN_FFI_SUCCESS;
89 });
90#else
91 BOTAN_UNUSED(cert);
93#endif
94}
95
97 botan_x509_cert_t cert, int ipv6, size_t i, int* has_safi, uint8_t* safi, int* present, size_t* count) {
98 if(Botan::any_null_pointers(has_safi, safi, present, count)) {
100 }
101#if defined(BOTAN_HAS_X509_CERTIFICATES)
102 return ffi_guard_thunk(__func__, [=]() -> int {
103 if(ipv6 != 0 && ipv6 != 1) {
105 }
106
107 const auto& ext =
108 safe_get(cert).v3_extensions().get_extension_object_as<Botan::Cert_Extension::IPAddressBlocks>();
109 if(Botan::any_null_pointers(ext)) {
111 }
112
113 const size_t limit = ipv6 == 0 ? ext->v4_count() : ext->v6_count();
114 if(i >= limit) {
116 }
117
118 const size_t index = ipv6 == 0 ? i : ext->v4_count() + i;
119 const auto& addr_blocks = ext->addr_blocks();
120 const auto& family = addr_blocks.at(index);
121 if(family.safi().has_value()) {
122 *has_safi = 1;
123 *safi = family.safi().value();
124 } else {
125 *has_safi = 0;
126 }
127
128 if(ipv6 == 0) {
129 return ip_addr_blocks_get_family<Botan::Cert_Extension::IPAddressBlocks::Version::IPv4>(
130 family, present, count);
131 } else {
132 return ip_addr_blocks_get_family<Botan::Cert_Extension::IPAddressBlocks::Version::IPv6>(
133 family, present, count);
134 }
135 });
136#else
137 BOTAN_UNUSED(cert, ipv6, i);
139#endif
140}
141
143 botan_x509_cert_t cert, int ipv6, size_t i, size_t entry, uint8_t min_out[], uint8_t max_out[], size_t* out_len) {
144 if(out_len == nullptr) {
146 }
147#if defined(BOTAN_HAS_X509_CERTIFICATES)
148 return ffi_guard_thunk(__func__, [=]() -> int {
149 if(ipv6 != 0 && ipv6 != 1) {
151 }
152
153 const auto& ext =
154 safe_get(cert).v3_extensions().get_extension_object_as<Botan::Cert_Extension::IPAddressBlocks>();
155 if(Botan::any_null_pointers(ext)) {
157 }
158
159 const size_t limit = ipv6 == 0 ? ext->v4_count() : ext->v6_count();
160 if(i >= limit) {
162 }
163
164 const size_t index = ipv6 == 0 ? i : ext->v4_count() + i;
165 const auto& addr_blocks = ext->addr_blocks();
166 const auto& addr_choice = addr_blocks.at(index).addr_choice();
167
168 if(ipv6 == 0) {
169 return ip_addr_blocks_get_address<Botan::Cert_Extension::IPAddressBlocks::Version::IPv4>(
170 addr_choice, entry, min_out, max_out, out_len);
171 } else {
172 return ip_addr_blocks_get_address<Botan::Cert_Extension::IPAddressBlocks::Version::IPv6>(
173 addr_choice, entry, min_out, max_out, out_len);
174 }
175 });
176#else
177 BOTAN_UNUSED(cert, ipv6, i, entry, min_out, max_out);
179#endif
180}
181
182// as blocks ext
183int botan_x509_ext_as_blocks_get_info(botan_x509_cert_t cert, int asnum, int* present, size_t* count) {
184 if(Botan::any_null_pointers(present, count)) {
186 }
187#if defined(BOTAN_HAS_X509_CERTIFICATES)
188 return ffi_guard_thunk(__func__, [=]() -> int {
189 if(asnum != 0 && asnum != 1) {
191 }
192
193 const auto& ext = safe_get(cert).v3_extensions().get_extension_object_as<Botan::Cert_Extension::ASBlocks>();
194 if(Botan::any_null_pointers(ext)) {
196 }
197
198 const auto& asnum_or_rdi = asnum == 1 ? ext->as_identifiers().asnum() : ext->as_identifiers().rdi();
199
200 if(!asnum_or_rdi.has_value()) {
202 }
203
204 const auto& ranges = asnum_or_rdi.value().ranges();
205
206 if(!ranges.has_value()) {
207 *present = 0;
208 return BOTAN_FFI_SUCCESS;
209 }
210
211 *present = 1;
212 *count = ranges.value().size();
213
214 return BOTAN_FFI_SUCCESS;
215 });
216#else
217 BOTAN_UNUSED(cert, asnum);
219#endif
220}
221
222int botan_x509_ext_as_blocks_get_entry_at(botan_x509_cert_t cert, int asnum, size_t i, uint32_t* min, uint32_t* max) {
223 if(Botan::any_null_pointers(min, max)) {
225 }
226#if defined(BOTAN_HAS_X509_CERTIFICATES)
227 return ffi_guard_thunk(__func__, [=]() -> int {
228 if(asnum != 0 && asnum != 1) {
230 }
231
232 const auto& ext = safe_get(cert).v3_extensions().get_extension_object_as<Botan::Cert_Extension::ASBlocks>();
233 if(Botan::any_null_pointers(ext)) {
235 }
236
237 const auto& asnum_or_rdi = asnum == 1 ? ext->as_identifiers().asnum() : ext->as_identifiers().rdi();
238 if(!asnum_or_rdi.has_value() || !asnum_or_rdi.value().ranges().has_value()) {
240 }
241
242 const auto& range = asnum_or_rdi.value().ranges().value();
243 if(i >= range.size()) {
245 }
246
247 *min = range.at(i).min();
248 *max = range.at(i).max();
249 return BOTAN_FFI_SUCCESS;
250 });
251#else
252 BOTAN_UNUSED(cert, asnum, i);
254#endif
255}
256}
#define BOTAN_UNUSED
Definition assert.h:144
const std::optional< ASIdentifierChoice > & asnum() const
Definition x509_ext.h:1195
const ASIdentifiers & as_identifiers() const
Definition x509_ext.h:1257
std::variant< IPAddressChoice< Version::IPv4 >, IPAddressChoice< Version::IPv6 > > AddrChoice
Definition x509_ext.h:1028
size_t v4_count() const
The number of IPv4 families contained in the extension.
Definition x509_ext.h:1109
struct botan_x509_cert_struct * botan_x509_cert_t
Definition ffi.h:3483
@ BOTAN_FFI_ERROR_NOT_IMPLEMENTED
Definition ffi.h:138
@ BOTAN_FFI_ERROR_OUT_OF_RANGE
Definition ffi.h:136
@ BOTAN_FFI_ERROR_NULL_POINTER
Definition ffi.h:131
@ BOTAN_FFI_SUCCESS
Definition ffi.h:114
@ BOTAN_FFI_ERROR_NO_VALUE
Definition ffi.h:120
@ BOTAN_FFI_ERROR_BAD_PARAMETER
Definition ffi.h:132
int botan_x509_ext_ip_addr_blocks_get_address(botan_x509_cert_t cert, int ipv6, size_t i, size_t entry, uint8_t min_out[], uint8_t max_out[], size_t *out_len)
int botan_x509_ext_as_blocks_get_info(botan_x509_cert_t cert, int asnum, int *present, size_t *count)
int botan_x509_ext_as_blocks_get_entry_at(botan_x509_cert_t cert, int asnum, size_t i, uint32_t *min, uint32_t *max)
int botan_x509_ext_ip_addr_blocks_get_counts(botan_x509_cert_t cert, size_t *v4_count, size_t *v6_count)
int botan_x509_ext_ip_addr_blocks_get_family(botan_x509_cert_t cert, int ipv6, size_t i, int *has_safi, uint8_t *safi, int *present, size_t *count)
T & safe_get(botan_struct< T, M > *p)
Definition ffi_util.h:79
int ffi_guard_thunk(const char *func_name, T thunk)
Definition ffi_util.h:95
int write_vec_output(uint8_t out[], size_t *out_len, std::span< const uint8_t > buf)
Definition ffi_util.h:267
bool any_null_pointers(Ptrs... ptr)
Definition mem_utils.h:54