summaryrefslogtreecommitdiffstats
path: root/comm/third_party/botan/src/lib/ffi/ffi_cert.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/botan/src/lib/ffi/ffi_cert.cpp')
-rw-r--r--comm/third_party/botan/src/lib/ffi/ffi_cert.cpp503
1 files changed, 503 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/lib/ffi/ffi_cert.cpp b/comm/third_party/botan/src/lib/ffi/ffi_cert.cpp
new file mode 100644
index 0000000000..1baaa18d6b
--- /dev/null
+++ b/comm/third_party/botan/src/lib/ffi/ffi_cert.cpp
@@ -0,0 +1,503 @@
+/*
+* (C) 2015,2017,2018 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/ffi.h>
+#include <botan/internal/ffi_util.h>
+#include <botan/internal/ffi_pkey.h>
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ #include <botan/x509cert.h>
+ #include <botan/x509path.h>
+ #include <botan/x509_crl.h>
+ #include <botan/data_src.h>
+#endif
+
+extern "C" {
+
+using namespace Botan_FFI;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+
+BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937);
+
+#endif
+
+int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path)
+ {
+ if(!cert_obj || !cert_path)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ std::unique_ptr<Botan::X509_Certificate> c(new Botan::X509_Certificate(cert_path));
+ *cert_obj = new botan_x509_cert_struct(c.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_dup(botan_x509_cert_t* cert_obj, botan_x509_cert_t cert)
+ {
+ if(!cert_obj)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ std::unique_ptr<Botan::X509_Certificate> c(new Botan::X509_Certificate(safe_get(cert)));
+ *cert_obj = new botan_x509_cert_struct(c.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+
+#else
+ BOTAN_UNUSED(cert);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len)
+ {
+ if(!cert_obj || !cert_bits)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
+ std::unique_ptr<Botan::X509_Certificate> c(new Botan::X509_Certificate(bits));
+ *cert_obj = new botan_x509_cert_struct(c.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+#else
+ BOTAN_UNUSED(cert_bits_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key)
+ {
+ if(key == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ *key = nullptr;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ std::unique_ptr<Botan::Public_Key> publicKey = safe_get(cert).load_subject_public_key();
+ *key = new botan_pubkey_struct(publicKey.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+#else
+ BOTAN_UNUSED(cert);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_issuer_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.issuer_info(key).at(index)); });
+#else
+ BOTAN_UNUSED(cert, key, index, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.subject_info(key).at(index)); });
+#else
+ BOTAN_UNUSED(cert, key, index, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.to_string()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_RETURNING(Botan::X509_Certificate, cert, c, {
+ const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
+ if(c.allowed_usage(k))
+ return BOTAN_FFI_SUCCESS;
+ return 1;
+ });
+#else
+ BOTAN_UNUSED(cert, key_usage);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_destroy(botan_x509_cert_t cert)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_CHECKED_DELETE(cert);
+#else
+ BOTAN_UNUSED(cert);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.not_before().to_string()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.not_after().to_string()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_not_before(botan_x509_cert_t cert, uint64_t* time_since_epoch)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, {
+ *time_since_epoch = c.not_before().time_since_epoch();
+ });
+#else
+ BOTAN_UNUSED(cert, time_since_epoch);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_not_after(botan_x509_cert_t cert, uint64_t* time_since_epoch)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, {
+ *time_since_epoch = c.not_after().time_since_epoch();
+ });
+#else
+ BOTAN_UNUSED(cert, time_since_epoch);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_vec_output(out, out_len, c.serial_number()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_str_output(out, out_len, c.fingerprint(hash)); });
+#else
+ BOTAN_UNUSED(cert, hash, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_vec_output(out, out_len, c.authority_key_id()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_vec_output(out, out_len, c.subject_key_id()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c, { return write_vec_output(out, out_len, c.subject_public_key_bits()); });
+#else
+ BOTAN_UNUSED(cert, out, out_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_hostname_match(botan_x509_cert_t cert, const char* hostname)
+ {
+ if(hostname == nullptr)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, c,
+ { return c.matches_dns_name(hostname) ? 0 : -1; });
+#else
+ BOTAN_UNUSED(cert);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_verify(int* result_code,
+ botan_x509_cert_t cert,
+ const botan_x509_cert_t* intermediates,
+ size_t intermediates_len,
+ const botan_x509_cert_t* trusted,
+ size_t trusted_len,
+ const char* trusted_path,
+ size_t required_strength,
+ const char* hostname_cstr,
+ uint64_t reference_time)
+ {
+ if(required_strength == 0)
+ required_strength = 110;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
+ const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
+ const auto validation_time = reference_time == 0 ?
+ std::chrono::system_clock::now() :
+ std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
+
+ std::vector<Botan::X509_Certificate> end_certs;
+ end_certs.push_back(safe_get(cert));
+ for(size_t i = 0; i != intermediates_len; ++i)
+ end_certs.push_back(safe_get(intermediates[i]));
+
+ std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
+ std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
+ std::vector<Botan::Certificate_Store*> trusted_roots;
+
+ if(trusted_path && *trusted_path)
+ {
+ trusted_from_path.reset(new Botan::Certificate_Store_In_Memory(trusted_path));
+ trusted_roots.push_back(trusted_from_path.get());
+ }
+
+ if(trusted_len > 0)
+ {
+ trusted_extra.reset(new Botan::Certificate_Store_In_Memory);
+ for(size_t i = 0; i != trusted_len; ++i)
+ {
+ trusted_extra->add_certificate(safe_get(trusted[i]));
+ }
+ trusted_roots.push_back(trusted_extra.get());
+ }
+
+ Botan::Path_Validation_Restrictions restrictions(false, required_strength);
+
+ auto validation_result = Botan::x509_path_validate(end_certs,
+ restrictions,
+ trusted_roots,
+ hostname,
+ usage,
+ validation_time);
+
+ if(result_code)
+ *result_code = static_cast<int>(validation_result.result());
+
+ if(validation_result.successful_validation())
+ return 0;
+ else
+ return 1;
+ });
+#else
+ BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
+ BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+const char* botan_x509_cert_validation_status(int code)
+ {
+ if(code < 0)
+ return nullptr;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ Botan::Certificate_Status_Code sc = static_cast<Botan::Certificate_Status_Code>(code);
+ return Botan::to_string(sc);
+#else
+ return nullptr;
+#endif
+ }
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+
+BOTAN_FFI_DECLARE_STRUCT(botan_x509_crl_struct, Botan::X509_CRL, 0x2C628910);
+
+#endif
+
+int botan_x509_crl_load_file(botan_x509_crl_t* crl_obj, const char* crl_path)
+ {
+ if(!crl_obj || !crl_path)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES) && defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
+
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ std::unique_ptr<Botan::X509_CRL> c(new Botan::X509_CRL(crl_path));
+ *crl_obj = new botan_x509_crl_struct(c.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_crl_load(botan_x509_crl_t* crl_obj, const uint8_t crl_bits[], size_t crl_bits_len)
+ {
+ if(!crl_obj || !crl_bits)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ Botan::DataSource_Memory bits(crl_bits, crl_bits_len);
+ std::unique_ptr<Botan::X509_CRL> c(new Botan::X509_CRL(bits));
+ *crl_obj = new botan_x509_crl_struct(c.release());
+ return BOTAN_FFI_SUCCESS;
+ });
+#else
+ BOTAN_UNUSED(crl_bits_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_crl_destroy(botan_x509_crl_t crl)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_CHECKED_DELETE(crl);
+#else
+ BOTAN_UNUSED(crl);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_is_revoked(botan_x509_crl_t crl, botan_x509_cert_t cert)
+ {
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return BOTAN_FFI_RETURNING(Botan::X509_CRL, crl, c, {
+ return c.is_revoked(safe_get(cert)) ? 0 : -1;
+ });
+#else
+ BOTAN_UNUSED(cert);
+ BOTAN_UNUSED(crl);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+int botan_x509_cert_verify_with_crl(
+ int* result_code,
+ botan_x509_cert_t cert,
+ const botan_x509_cert_t* intermediates,
+ size_t intermediates_len,
+ const botan_x509_cert_t* trusted,
+ size_t trusted_len,
+ const botan_x509_crl_t* crls,
+ size_t crls_len,
+ const char* trusted_path,
+ size_t required_strength,
+ const char* hostname_cstr,
+ uint64_t reference_time)
+ {
+ if(required_strength == 0)
+ required_strength = 110;
+
+#if defined(BOTAN_HAS_X509_CERTIFICATES)
+ return ffi_guard_thunk(__func__, [=]() -> int {
+ const std::string hostname((hostname_cstr == nullptr) ? "" : hostname_cstr);
+ const Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED;
+ const auto validation_time = reference_time == 0 ?
+ std::chrono::system_clock::now() :
+ std::chrono::system_clock::from_time_t(static_cast<time_t>(reference_time));
+
+ std::vector<Botan::X509_Certificate> end_certs;
+ end_certs.push_back(safe_get(cert));
+ for(size_t i = 0; i != intermediates_len; ++i)
+ end_certs.push_back(safe_get(intermediates[i]));
+
+ std::unique_ptr<Botan::Certificate_Store> trusted_from_path;
+ std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_extra;
+ std::unique_ptr<Botan::Certificate_Store_In_Memory> trusted_crls;
+ std::vector<Botan::Certificate_Store*> trusted_roots;
+
+ if(trusted_path && *trusted_path)
+ {
+ trusted_from_path.reset(new Botan::Certificate_Store_In_Memory(trusted_path));
+ trusted_roots.push_back(trusted_from_path.get());
+ }
+
+ if(trusted_len > 0)
+ {
+ trusted_extra.reset(new Botan::Certificate_Store_In_Memory);
+ for(size_t i = 0; i != trusted_len; ++i)
+ {
+ trusted_extra->add_certificate(safe_get(trusted[i]));
+ }
+ trusted_roots.push_back(trusted_extra.get());
+ }
+
+ if(crls_len > 0)
+ {
+ trusted_crls.reset(new Botan::Certificate_Store_In_Memory);
+ for(size_t i = 0; i != crls_len; ++i)
+ {
+ trusted_crls->add_crl(safe_get(crls[i]));
+ }
+ trusted_roots.push_back(trusted_crls.get());
+ }
+
+ Botan::Path_Validation_Restrictions restrictions(false, required_strength);
+
+ auto validation_result = Botan::x509_path_validate(end_certs,
+ restrictions,
+ trusted_roots,
+ hostname,
+ usage,
+ validation_time);
+
+ if(result_code)
+ *result_code = static_cast<int>(validation_result.result());
+
+ if(validation_result.successful_validation())
+ return 0;
+ else
+ return 1;
+ });
+#else
+ BOTAN_UNUSED(result_code, cert, intermediates, intermediates_len, trusted);
+ BOTAN_UNUSED(trusted_len, trusted_path, hostname_cstr, reference_time, crls, crls_len);
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+
+}