/src/Botan-3.4.0/src/lib/ffi/ffi_cert.cpp
Line | Count | Source |
1 | | /* |
2 | | * (C) 2015,2017,2018 Jack Lloyd |
3 | | * |
4 | | * Botan is released under the Simplified BSD License (see license.txt) |
5 | | */ |
6 | | |
7 | | #include <botan/ffi.h> |
8 | | |
9 | | #include <botan/internal/ffi_pkey.h> |
10 | | #include <botan/internal/ffi_util.h> |
11 | | #include <memory> |
12 | | |
13 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
14 | | #include <botan/data_src.h> |
15 | | #include <botan/x509_crl.h> |
16 | | #include <botan/x509cert.h> |
17 | | #include <botan/x509path.h> |
18 | | #endif |
19 | | |
20 | | extern "C" { |
21 | | |
22 | | using namespace Botan_FFI; |
23 | | |
24 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
25 | | |
26 | | BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937); |
27 | | |
28 | | #endif |
29 | | |
30 | 0 | int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path) { |
31 | 0 | if(!cert_obj || !cert_path) { |
32 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
33 | 0 | } |
34 | | |
35 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) |
36 | | |
37 | | return ffi_guard_thunk(__func__, [=]() -> int { |
38 | | auto c = std::make_unique<Botan::X509_Certificate>(cert_path); |
39 | | *cert_obj = new botan_x509_cert_struct(std::move(c)); |
40 | | return BOTAN_FFI_SUCCESS; |
41 | | }); |
42 | | |
43 | | #else |
44 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
45 | 0 | #endif |
46 | 0 | } |
47 | | |
48 | 0 | int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert) { |
49 | 0 | if(!cert_obj) { |
50 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
51 | 0 | } |
52 | | |
53 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) |
54 | | |
55 | | return ffi_guard_thunk(__func__, [=]() -> int { |
56 | | auto c = std::make_unique<Botan::X509_Certificate>(safe_get(cert)); |
57 | | *cert_obj = new botan_x509_cert_struct(std::move(c)); |
58 | | return BOTAN_FFI_SUCCESS; |
59 | | }); |
60 | | |
61 | | #else |
62 | 0 | BOTAN_UNUSED(cert); |
63 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
64 | 0 | #endif |
65 | 0 | } |
66 | | |
67 | 0 | int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len) { |
68 | 0 | if(!cert_obj || !cert_bits) { |
69 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
70 | 0 | } |
71 | | |
72 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
73 | | return ffi_guard_thunk(__func__, [=]() -> int { |
74 | | Botan::DataSource_Memory bits(cert_bits, cert_bits_len); |
75 | | auto c = std::make_unique<Botan::X509_Certificate>(bits); |
76 | | *cert_obj = new botan_x509_cert_struct(std::move(c)); |
77 | | return BOTAN_FFI_SUCCESS; |
78 | | }); |
79 | | #else |
80 | 0 | BOTAN_UNUSED(cert_bits_len); |
81 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
82 | 0 | #endif |
83 | 0 | } |
84 | | |
85 | 0 | int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key) { |
86 | 0 | if(key == nullptr) { |
87 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
88 | 0 | } |
89 | | |
90 | 0 | *key = nullptr; |
91 | |
|
92 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
93 | | return ffi_guard_thunk(__func__, [=]() -> int { |
94 | | auto public_key = safe_get(cert).subject_public_key(); |
95 | | *key = new botan_pubkey_struct(std::move(public_key)); |
96 | | return BOTAN_FFI_SUCCESS; |
97 | | }); |
98 | | #else |
99 | 0 | BOTAN_UNUSED(cert); |
100 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
101 | 0 | #endif |
102 | 0 | } |
103 | | |
104 | | int botan_x509_cert_get_issuer_dn( |
105 | 0 | botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) { |
106 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
107 | | return BOTAN_FFI_VISIT(cert, |
108 | | [=](const auto& c) { return write_str_output(out, out_len, c.issuer_info(key).at(index)); }); |
109 | | #else |
110 | 0 | BOTAN_UNUSED(cert, key, index, out, out_len); |
111 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
112 | 0 | #endif |
113 | 0 | } |
114 | | |
115 | | int botan_x509_cert_get_subject_dn( |
116 | 0 | botan_x509_cert_t cert, const char* key, size_t index, uint8_t out[], size_t* out_len) { |
117 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
118 | | return BOTAN_FFI_VISIT(cert, |
119 | | [=](const auto& c) { return write_str_output(out, out_len, c.subject_info(key).at(index)); }); |
120 | | #else |
121 | 0 | BOTAN_UNUSED(cert, key, index, out, out_len); |
122 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
123 | 0 | #endif |
124 | 0 | } |
125 | | |
126 | 0 | int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len) { |
127 | 0 | return copy_view_str(reinterpret_cast<uint8_t*>(out), out_len, botan_x509_cert_view_as_string, cert); |
128 | 0 | } |
129 | | |
130 | 0 | int botan_x509_cert_view_as_string(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_str_fn view) { |
131 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
132 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return invoke_view_callback(view, ctx, c.to_string()); }); |
133 | | #else |
134 | 0 | BOTAN_UNUSED(cert, ctx, view); |
135 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
136 | 0 | #endif |
137 | 0 | } |
138 | | |
139 | 0 | int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage) { |
140 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
141 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) -> int { |
142 | | const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage); |
143 | | if(c.allowed_usage(k)) |
144 | | return BOTAN_FFI_SUCCESS; |
145 | | return 1; |
146 | | }); |
147 | | #else |
148 | 0 | BOTAN_UNUSED(cert, key_usage); |
149 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
150 | 0 | #endif |
151 | 0 | } |
152 | | |
153 | 0 | int botan_x509_cert_destroy(botan_x509_cert_t cert) { |
154 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
155 | | return BOTAN_FFI_CHECKED_DELETE(cert); |
156 | | #else |
157 | 0 | BOTAN_UNUSED(cert); |
158 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
159 | 0 | #endif |
160 | 0 | } |
161 | | |
162 | 0 | int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len) { |
163 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
164 | | return BOTAN_FFI_VISIT(cert, |
165 | | [=](const auto& c) { return write_str_output(out, out_len, c.not_before().to_string()); }); |
166 | | #else |
167 | 0 | BOTAN_UNUSED(cert, out, out_len); |
168 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
169 | 0 | #endif |
170 | 0 | } |
171 | | |
172 | 0 | int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len) { |
173 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
174 | | return BOTAN_FFI_VISIT(cert, |
175 | | [=](const auto& c) { return write_str_output(out, out_len, c.not_after().to_string()); }); |
176 | | #else |
177 | 0 | BOTAN_UNUSED(cert, out, out_len); |
178 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
179 | 0 | #endif |
180 | 0 | } |
181 | | |
182 | 0 | int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch) { |
183 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
184 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_before().time_since_epoch(); }); |
185 | | #else |
186 | 0 | BOTAN_UNUSED(cert, time_since_epoch); |
187 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
188 | 0 | #endif |
189 | 0 | } |
190 | | |
191 | 0 | int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch) { |
192 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
193 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { *time_since_epoch = c.not_after().time_since_epoch(); }); |
194 | | #else |
195 | 0 | BOTAN_UNUSED(cert, time_since_epoch); |
196 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
197 | 0 | #endif |
198 | 0 | } |
199 | | |
200 | 0 | int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) { |
201 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
202 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.serial_number()); }); |
203 | | #else |
204 | 0 | BOTAN_UNUSED(cert, out, out_len); |
205 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
206 | 0 | #endif |
207 | 0 | } |
208 | | |
209 | 0 | int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len) { |
210 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
211 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_str_output(out, out_len, c.fingerprint(hash)); }); |
212 | | #else |
213 | 0 | BOTAN_UNUSED(cert, hash, out, out_len); |
214 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
215 | 0 | #endif |
216 | 0 | } |
217 | | |
218 | 0 | int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) { |
219 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
220 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.authority_key_id()); }); |
221 | | #else |
222 | 0 | BOTAN_UNUSED(cert, out, out_len); |
223 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
224 | 0 | #endif |
225 | 0 | } |
226 | | |
227 | 0 | int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) { |
228 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
229 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return write_vec_output(out, out_len, c.subject_key_id()); }); |
230 | | #else |
231 | 0 | BOTAN_UNUSED(cert, out, out_len); |
232 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
233 | 0 | #endif |
234 | 0 | } |
235 | | |
236 | 0 | int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len) { |
237 | 0 | return copy_view_bin(out, out_len, botan_x509_cert_view_public_key_bits, cert); |
238 | 0 | } |
239 | | |
240 | 0 | int botan_x509_cert_view_public_key_bits(botan_x509_cert_t cert, botan_view_ctx ctx, botan_view_bin_fn view) { |
241 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
242 | | return BOTAN_FFI_VISIT(cert, |
243 | | [=](const auto& c) { return invoke_view_callback(view, ctx, c.subject_public_key_bits()); }); |
244 | | #else |
245 | 0 | BOTAN_UNUSED(cert, ctx, view); |
246 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
247 | 0 | #endif |
248 | 0 | } |
249 | | |
250 | 0 | int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname) { |
251 | 0 | if(hostname == nullptr) { |
252 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
253 | 0 | } |
254 | | |
255 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
256 | | return BOTAN_FFI_VISIT(cert, [=](const auto& c) { return c.matches_dns_name(hostname) ? 0 : -1; }); |
257 | | #else |
258 | 0 | BOTAN_UNUSED(cert); |
259 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
260 | 0 | #endif |
261 | 0 | } |
262 | | |
263 | | int botan_x509_cert_verify(int* result_code, |
264 | | botan_x509_cert_t cert, |
265 | | const botan_x509_cert_t* intermediates, |
266 | | size_t intermediates_len, |
267 | | const botan_x509_cert_t* trusted, |
268 | | size_t trusted_len, |
269 | | const char* trusted_path, |
270 | | size_t required_strength, |
271 | | const char* hostname_cstr, |
272 | 0 | uint64_t reference_time) { |
273 | 0 | if(required_strength == 0) { |
274 | 0 | required_strength = 110; |
275 | 0 | } |
276 | |
|
277 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
278 | | return ffi_guard_thunk(__func__, [=]() -> int { |
279 | | const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr); |
280 | | const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED; |
281 | | const auto validation_time = reference_time == 0 |
282 | | ? std::chrono::system_clock::now() |
283 | | : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time)); |
284 | | |
285 | | std::vector<Botan::X509_Certificate> end_certs; |
286 | | end_certs.push_back(safe_get(cert)); |
287 | | for(size_t i = 0; i != intermediates_len; ++i) { |
288 | | end_certs.push_back(safe_get(intermediates[i])); |
289 | | } |
290 | | |
291 | | std::unique_ptr<Botan::Certificate_Store> trusted_from_path; |
292 | | std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra; |
293 | | std::vector<Botan::Certificate_Store*> trusted_roots; |
294 | | |
295 | | if(trusted_path && *trusted_path) { |
296 | | trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path); |
297 | | trusted_roots.push_back(trusted_from_path.get()); |
298 | | } |
299 | | |
300 | | if(trusted_len > 0) { |
301 | | trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>(); |
302 | | for(size_t i = 0; i != trusted_len; ++i) { |
303 | | trusted_extra->add_certificate(safe_get(trusted[i])); |
304 | | } |
305 | | trusted_roots.push_back(trusted_extra.get()); |
306 | | } |
307 | | |
308 | | Botan::Path_Validation_Restrictions restrictions(false, required_strength); |
309 | | |
310 | | auto validation_result = |
311 | | Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time); |
312 | | |
313 | | if(result_code) { |
314 | | *result_code = static_cast<int>(validation_result.result()); |
315 | | } |
316 | | |
317 | | if(validation_result.successful_validation()) { |
318 | | return 0; |
319 | | } else { |
320 | | return 1; |
321 | | } |
322 | | }); |
323 | | #else |
324 | 0 | BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted); |
325 | 0 | BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time); |
326 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
327 | 0 | #endif |
328 | 0 | } |
329 | | |
330 | 0 | const char* botan_x509_cert_validation_status(int code) { |
331 | 0 | if(code < 0) { |
332 | 0 | return nullptr; |
333 | 0 | } |
334 | | |
335 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
336 | | Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code); |
337 | | return Botan::to_string(sc); |
338 | | #else |
339 | 0 | return nullptr; |
340 | 0 | #endif |
341 | 0 | } |
342 | | |
343 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
344 | | |
345 | | BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910); |
346 | | |
347 | | #endif |
348 | | |
349 | 0 | int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path) { |
350 | 0 | if(!crl_obj || !crl_path) { |
351 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
352 | 0 | } |
353 | | |
354 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM) |
355 | | |
356 | | return ffi_guard_thunk(__func__, [=]() -> int { |
357 | | auto c = std::make_unique<Botan::X509_CRL>(crl_path); |
358 | | *crl_obj = new botan_x509_crl_struct(std::move(c)); |
359 | | return BOTAN_FFI_SUCCESS; |
360 | | }); |
361 | | |
362 | | #else |
363 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
364 | 0 | #endif |
365 | 0 | } |
366 | | |
367 | 0 | int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len) { |
368 | 0 | if(!crl_obj || !crl_bits) { |
369 | 0 | return BOTAN_FFI_ERROR_NULL_POINTER; |
370 | 0 | } |
371 | | |
372 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
373 | | return ffi_guard_thunk(__func__, [=]() -> int { |
374 | | Botan::DataSource_Memory bits(crl_bits, crl_bits_len); |
375 | | auto c = std::make_unique<Botan::X509_CRL>(bits); |
376 | | *crl_obj = new botan_x509_crl_struct(std::move(c)); |
377 | | return BOTAN_FFI_SUCCESS; |
378 | | }); |
379 | | #else |
380 | 0 | BOTAN_UNUSED(crl_bits_len); |
381 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
382 | 0 | #endif |
383 | 0 | } |
384 | | |
385 | 0 | int botan_x509_crl_destroy(botan_x509_crl_t crl) { |
386 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
387 | | return BOTAN_FFI_CHECKED_DELETE(crl); |
388 | | #else |
389 | 0 | BOTAN_UNUSED(crl); |
390 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
391 | 0 | #endif |
392 | 0 | } |
393 | | |
394 | 0 | int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert) { |
395 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
396 | | return BOTAN_FFI_VISIT(crl, [=](const auto& c) { return c.is_revoked(safe_get(cert)) ? 0 : -1; }); |
397 | | #else |
398 | 0 | BOTAN_UNUSED(cert); |
399 | 0 | BOTAN_UNUSED(crl); |
400 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
401 | 0 | #endif |
402 | 0 | } |
403 | | |
404 | | int botan_x509_cert_verify_with_crl(int* result_code, |
405 | | botan_x509_cert_t cert, |
406 | | const botan_x509_cert_t* intermediates, |
407 | | size_t intermediates_len, |
408 | | const botan_x509_cert_t* trusted, |
409 | | size_t trusted_len, |
410 | | const botan_x509_crl_t* crls, |
411 | | size_t crls_len, |
412 | | const char* trusted_path, |
413 | | size_t required_strength, |
414 | | const char* hostname_cstr, |
415 | 0 | uint64_t reference_time) { |
416 | 0 | if(required_strength == 0) { |
417 | 0 | required_strength = 110; |
418 | 0 | } |
419 | |
|
420 | | #if defined(BOTAN_HAS_X509_CERTIFICATES) |
421 | | return ffi_guard_thunk(__func__, [=]() -> int { |
422 | | const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr); |
423 | | const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED; |
424 | | const auto validation_time = reference_time == 0 |
425 | | ? std::chrono::system_clock::now() |
426 | | : std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time)); |
427 | | |
428 | | std::vector<Botan::X509_Certificate> end_certs; |
429 | | end_certs.push_back(safe_get(cert)); |
430 | | for(size_t i = 0; i != intermediates_len; ++i) { |
431 | | end_certs.push_back(safe_get(intermediates[i])); |
432 | | } |
433 | | |
434 | | std::unique_ptr<Botan::Certificate_Store> trusted_from_path; |
435 | | std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra; |
436 | | std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls; |
437 | | std::vector<Botan::Certificate_Store*> trusted_roots; |
438 | | |
439 | | if(trusted_path && *trusted_path) { |
440 | | trusted_from_path = std::make_unique<Botan::Certificate_Store_In_Memory>(trusted_path); |
441 | | trusted_roots.push_back(trusted_from_path.get()); |
442 | | } |
443 | | |
444 | | if(trusted_len > 0) { |
445 | | trusted_extra = std::make_unique<Botan::Certificate_Store_In_Memory>(); |
446 | | for(size_t i = 0; i != trusted_len; ++i) { |
447 | | trusted_extra->add_certificate(safe_get(trusted[i])); |
448 | | } |
449 | | trusted_roots.push_back(trusted_extra.get()); |
450 | | } |
451 | | |
452 | | if(crls_len > 0) { |
453 | | trusted_crls = std::make_unique<Botan::Certificate_Store_In_Memory>(); |
454 | | for(size_t i = 0; i != crls_len; ++i) { |
455 | | trusted_crls->add_crl(safe_get(crls[i])); |
456 | | } |
457 | | trusted_roots.push_back(trusted_crls.get()); |
458 | | } |
459 | | |
460 | | Botan::Path_Validation_Restrictions restrictions(false, required_strength); |
461 | | |
462 | | auto validation_result = |
463 | | Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage, validation_time); |
464 | | |
465 | | if(result_code) { |
466 | | *result_code = static_cast<int>(validation_result.result()); |
467 | | } |
468 | | |
469 | | if(validation_result.successful_validation()) { |
470 | | return 0; |
471 | | } else { |
472 | | return 1; |
473 | | } |
474 | | }); |
475 | | #else |
476 | 0 | BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted); |
477 | 0 | BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len); |
478 | 0 | return BOTAN_FFI_ERROR_NOT_IMPLEMENTED; |
479 | 0 | #endif |
480 | 0 | } |
481 | | } |