5#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
9#include <openssl/bio.h>
10#include <openssl/err.h>
11#include <openssl/pkcs12.h>
12#include <openssl/ssl.h>
13#include <openssl/x509.h>
24#define RETURN_IF_ERROR(handle) \
26 Dart_Handle __handle = handle; \
27 if (Dart_IsError((__handle))) { \
35const char* SSLCertContext::root_certs_file_ =
nullptr;
36const char* SSLCertContext::root_certs_cache_ =
nullptr;
37bool SSLCertContext::long_ssl_cert_evaluation_ =
false;
38bool SSLCertContext::bypass_trusting_system_roots_ =
false;
41 X509_STORE_CTX* store_ctx) {
42 if (preverify_ok == 1) {
46 if (isolate ==
nullptr) {
47 FATAL(
"CertificateCallback called with no current isolate\n");
49 X509* certificate = X509_STORE_CTX_get_current_cert(store_ctx);
50 int ssl_index = SSL_get_ex_data_X509_STORE_CTX_idx();
52 static_cast<SSL*
>(X509_STORE_CTX_get_ex_data(store_ctx, ssl_index));
61 if (certificate !=
nullptr) {
62 X509_up_ref(certificate);
74 "BadCertificateCallback returned a value that was not a boolean",
101 reinterpret_cast<intptr_t*
>(&
context)));
121 reinterpret_cast<intptr_t
>(context));
130 X509* cert =
reinterpret_cast<X509*
>(context_pointer);
135 intptr_t
length = i2d_X509(certificate,
nullptr);
147 if (certificate ==
nullptr) {
153 X509_free(certificate);
160 X509_free(certificate);
166 reinterpret_cast<intptr_t
>(certificate));
168 X509_free(certificate);
171 const intptr_t approximate_size_of_certificate =
173 ASSERT(approximate_size_of_certificate > 0);
175 approximate_size_of_certificate,
182 const char* password) {
186 EVP_PKEY*
key =
nullptr;
188 int status = PKCS12_get_key_and_certs(&
key, cert_stack.
get(), &cbs, password);
193 X509_STORE*
store = SSL_CTX_get_cert_store(context);
195 while ((ca = sk_X509_shift(cert_stack.
get())) !=
nullptr) {
196 status = X509_STORE_add_cert(
store, ca);
208 X509_STORE*
store = SSL_CTX_get_cert_store(context);
211 X509* cert =
nullptr;
212 while ((cert = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr)) !=
214 status = X509_STORE_add_cert(
store, cert);
231 const char* password) {
239 BIO_reset(bio.
bio());
248 "Failure trusting builtin roots");
253 const char* password) {
257 EVP_PKEY*
key =
nullptr;
259 int status = PKCS12_get_key_and_certs(&
key, cert_stack.
get(), &cbs, password);
265 while ((ca = sk_X509_shift(cert_stack.
get())) !=
nullptr) {
266 status = SSL_CTX_add_client_CA(context, ca);
279 X509* cert =
nullptr;
280 while ((cert = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr)) !=
282 status = SSL_CTX_add_client_CA(context, cert);
293 const char* password) {
298 BIO_reset(bio->
bio());
310 const char* password) {
318 "Failure in setClientAuthoritiesBytes");
321void SSLCertContext::LoadRootCertFile(
const char* file) {
327 -1,
"TlsException",
"Failed to find root cert file",
nullptr);
329 int status = SSL_CTX_load_verify_locations(
context(), file,
nullptr);
331 "Failure trusting builtin roots");
337void SSLCertContext::AddCompiledInCerts() {
352 while ((root_cert = PEM_read_bio_X509(roots_bio,
nullptr,
nullptr,
353 nullptr)) !=
nullptr) {
354 int status = X509_STORE_add_cert(
store, root_cert);
356 X509_free(root_cert);
368void SSLCertContext::LoadRootCertCache(
const char* cache) {
374 -1,
"TlsException",
"Failed to find root cert cache",
nullptr);
376 int status = SSL_CTX_load_verify_locations(
context(),
nullptr, cache);
378 "Failure trusting builtin roots");
385 char* password =
static_cast<char*
>(userdata);
386 ASSERT(size == PEM_BUFSIZE);
387 strncpy(buf, password, size);
388 return strlen(password);
393 if (p12.
get() ==
nullptr) {
397 EVP_PKEY*
key =
nullptr;
398 X509* cert =
nullptr;
399 STACK_OF(X509)* ca_certs =
nullptr;
400 int status = PKCS12_parse(p12.
get(), password, &
key, &cert, &ca_certs);
413 const_cast<char*
>(password));
414 if (
key ==
nullptr) {
435 const char* password =
nullptr;
438 if (strlen(password) > PEM_BUFSIZE - 1) {
440 "Password length is greater than 1023 (PEM_BUFSIZE)"));
459 uint8_t* server_list =
static_cast<uint8_t*
>(arg);
460 while (*server_list != 0) {
461 uint8_t protocol_length = *server_list++;
462 const uint8_t* client_list = in;
463 while (client_list < in + inlen) {
464 uint8_t client_protocol_length = *client_list++;
465 if (client_protocol_length == protocol_length) {
466 if (0 == memcmp(server_list, client_list, protocol_length)) {
468 *outlen = client_protocol_length;
469 return SSL_TLSEXT_ERR_OK;
472 client_list += client_protocol_length;
474 server_list += protocol_length;
477 return SSL_TLSEXT_ERR_NOACK;
488 uint8_t* protocol_string =
nullptr;
489 uint8_t* protocol_string_copy =
nullptr;
490 intptr_t protocol_string_len = 0;
494 protocols_handle, &protocols_type,
495 reinterpret_cast<void**
>(&protocol_string), &protocol_string_len);
503 "Unexpected type for protocols (expected valid Uint8List)."));
506 if (protocol_string_len > 0) {
514 protocol_string_copy =
515 static_cast<uint8_t*
>(
malloc(protocol_string_len + 1));
516 memmove(protocol_string_copy, protocol_string, protocol_string_len);
517 protocol_string_copy[protocol_string_len] =
'\0';
519 protocol_string_copy);
520 context->set_alpn_protocol_string(protocol_string_copy);
523 if (ssl !=
nullptr) {
525 status = SSL_set_alpn_protos(ssl, protocol_string, protocol_string_len);
529 status = SSL_CTX_set_alpn_protos(
context->context(), protocol_string,
530 protocol_string_len);
540 const char* password) {
544 EVP_PKEY*
key =
nullptr;
546 int status = PKCS12_get_key_and_certs(&
key, certs.
get(), &cbs, password);
551 X509* ca = sk_X509_shift(certs.
get());
552 status = SSL_CTX_use_certificate(context, ca);
553 if (ERR_peek_error() != 0) {
562 SSL_CTX_clear_chain_certs(context);
564 while ((ca = sk_X509_shift(certs.
get())) !=
nullptr) {
565 status = SSL_CTX_add0_chain_cert(context, ca);
579 ScopedX509 x509(PEM_read_bio_X509_AUX(bio,
nullptr,
nullptr,
nullptr));
580 if (x509.
get() ==
nullptr) {
584 status = SSL_CTX_use_certificate(context, x509.
get());
585 if (ERR_peek_error() != 0) {
593 SSL_CTX_clear_chain_certs(context);
596 while ((ca = PEM_read_bio_X509(bio,
nullptr,
nullptr,
nullptr)) !=
nullptr) {
597 status = SSL_CTX_add0_chain_cert(context, ca);
614 const char* password) {
619 BIO_reset(bio->
bio());
630 const char* password) {
636 X509* certificate =
nullptr;
641 reinterpret_cast<intptr_t*
>(&certificate)));
642 if (certificate ==
nullptr) {
653 intptr_t
length = i2d_X509(certificate,
nullptr);
659 void* dart_cert_bytes =
nullptr;
669 unsigned char* tmp =
static_cast<unsigned char*
>(dart_cert_bytes);
670 const intptr_t written_length = i2d_X509(certificate, &tmp);
672 if (written_length < 0) {
675 -1,
"TlsException",
"Failed to get certificate bytes",
nullptr);
688 BIO* cert_bio = BIO_new(BIO_s_mem());
689 intptr_t status = PEM_write_bio_X509(cert_bio, certificate);
693 -1,
"TlsException",
"Failed to write certificate to PEM",
nullptr);
697 BUF_MEM* mem =
nullptr;
698 BIO_get_mem_ptr(cert_bio, &mem);
700 reinterpret_cast<const uint8_t*
>(mem->data), mem->length);
710 unsigned char sha1_bytes[EVP_MAX_MD_SIZE];
712 const EVP_MD* hash_type = EVP_sha1();
714 unsigned int sha1_size;
715 intptr_t status = X509_digest(certificate, hash_type, sha1_bytes, &sha1_size);
718 -1,
"TlsException",
"Failed to compute certificate's sha1",
nullptr);
728 void* dart_sha1_bytes;
736 memmove(dart_sha1_bytes, sha1_bytes,
length);
747 X509_NAME* subject = X509_get_subject_name(certificate);
748 char* subject_string = X509_NAME_oneline(subject,
nullptr, 0);
749 if (subject_string ==
nullptr) {
751 "X509.subject failed to find subject's common name."));
754 OPENSSL_free(subject_string);
755 return subject_handle;
760 X509_NAME* issuer = X509_get_issuer_name(certificate);
761 char* issuer_string = X509_NAME_oneline(issuer,
nullptr, 0);
762 if (issuer_string ==
nullptr) {
764 "X509.issuer failed to find issuer's common name."));
767 OPENSSL_free(issuer_string);
768 return issuer_handle;
772 ASN1_UTCTIME* epoch_start = ASN1_UTCTIME_new();
773 ASN1_UTCTIME_set_string(epoch_start,
"700101000000Z");
776 int result = ASN1_TIME_diff(&days, &seconds, epoch_start, aTime);
777 ASN1_UTCTIME_free(epoch_start);
787 ASN1_TIME* not_before = X509_get_notBefore(certificate);
793 ASN1_TIME* not_after = X509_get_notAfter(certificate);
808 if (
key ==
nullptr) {
810 "Expected private key, but none was found"));
812 status = SSL_CTX_use_PrivateKey(context->
context(),
key);
822 "Failure in usePrivateKeyBytes");
827 SSL_CTX* ctx = SSL_CTX_new(TLS_method());
830 SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
831 SSL_CTX_set_cipher_list(ctx,
"HIGH:MEDIUM");
846 ASSERT(context !=
nullptr);
847 ASSERT(password !=
nullptr);
858 ASSERT(context !=
nullptr);
859 ASSERT(password !=
nullptr);
870 ASSERT(context !=
nullptr);
871 ASSERT(password !=
nullptr);
876 "Failure in useCertificateChainBytes");
883 ASSERT(context !=
nullptr);
893 ASSERT(context !=
nullptr);
894 ASSERT(allow_tls_handle !=
nullptr);
898 "Non-boolean argument passed to SetAllowTlsRenegotiation"));
943 "Non-boolean is_server argument passed to SetAlpnProtocols"));
#define FUNCTION_NAME(name)
static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static void Print(const char *format,...) PRINTF_ATTRIBUTE(1
static constexpr const char * kIOLibURL
static bool GetBooleanValue(Dart_Handle bool_obj)
static Dart_Handle NewDartIOException(const char *exception_name, const char *message, Dart_Handle os_error)
static bool PostString(Dart_Port port_id, const char *value)
static Dart_Handle NewString(const char *str)
static Dart_Handle NewDartArgumentError(const char *message)
static Dart_Handle NewInternalError(const char *message)
static Dart_Handle GetDartType(const char *library_url, const char *class_name)
static ExistsResult Exists(Namespace *namespc, const char *path)
static bool Exists(Namespace *namespc, const char *path)
static void KeyLogCallback(const SSL *ssl, const char *line)
static SSLCertContext * GetSecurityContext(Dart_NativeArguments args)
SSL_CTX * context() const
static constexpr int kX509NativeFieldIndex
void SetClientAuthoritiesBytes(Dart_Handle client_authorities_bytes, const char *password)
static int CertificateCallback(int preverify_ok, X509_STORE_CTX *store_ctx)
static const char * GetPasswordArgument(Dart_NativeArguments args, intptr_t index)
static const intptr_t kApproximateSize
void set_allow_tls_renegotiation(bool allow)
int UseCertificateChainBytes(Dart_Handle cert_chain_bytes, const char *password)
static void SetAlpnProtocolList(Dart_Handle protocols_handle, SSL *ssl, SSLCertContext *context, bool is_server)
void SetTrustedCertificatesBytes(Dart_Handle cert_bytes, const char *password)
static constexpr int kSecurityContextNativeFieldIndex
static void InitializeLibrary()
Dart_Handle bad_certificate_callback()
Dart_Handle callback_error
static int filter_ssl_index
static void ThrowIOException(int status, const char *exception_type, const char *message, const SSL *ssl)
static bool NoPEMStartLine()
static void CheckStatus(int status, const char *type, const char *message)
static Dart_Handle GetSha1(Dart_NativeArguments args)
static Dart_Handle GetDer(Dart_NativeArguments args)
static Dart_Handle GetStartValidity(Dart_NativeArguments args)
static Dart_Handle WrappedX509Certificate(X509 *certificate)
static Dart_Handle GetIssuer(Dart_NativeArguments args)
static Dart_Handle GetPem(Dart_NativeArguments args)
static Dart_Handle GetEndValidity(Dart_NativeArguments args)
static Dart_Handle GetSubject(Dart_NativeArguments args)
struct _Dart_Handle * Dart_Handle
struct _Dart_Isolate * Dart_Isolate
struct _Dart_NativeArguments * Dart_NativeArguments
#define RETURN_IF_ERROR(handle)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
static int UseChainBytesPEM(SSL_CTX *context, BIO *bio)
static intptr_t EstimateX509Size(X509 *certificate)
void FUNCTION_NAME() SecurityContext_SetTrustedCertificatesBytes(Dart_NativeArguments args)
const bool SSL_LOG_STATUS
static Dart_Handle ThrowIfError(Dart_Handle handle)
void FUNCTION_NAME() X509_Issuer(Dart_NativeArguments args)
void FUNCTION_NAME() SecurityContext_TrustBuiltinRoots(Dart_NativeArguments args)
static int SetTrustedCertificatesBytesPEM(SSL_CTX *context, BIO *bio)
static int UseChainBytes(SSL_CTX *context, ScopedMemBIO *bio, const char *password)
void FUNCTION_NAME() X509_EndValidity(Dart_NativeArguments args)
void FUNCTION_NAME() SecurityContext_UseCertificateChainBytes(Dart_NativeArguments args)
static EVP_PKEY * GetPrivateKeyPKCS12(BIO *bio, const char *password)
int PasswordCallback(char *buf, int size, int rwflag, void *userdata)
void FUNCTION_NAME() SecurityContext_Allocate(Dart_NativeArguments args)
static Dart_Handle ASN1TimeToMilliseconds(ASN1_TIME *aTime)
static Dart_Handle SetSecurityContext(Dart_NativeArguments args, SSLCertContext *context)
static void ReleaseCertificate(void *isolate_data, void *context_pointer)
static int SetClientAuthorities(SSL_CTX *context, ScopedMemBIO *bio, const char *password)
void FUNCTION_NAME() SecurityContext_UsePrivateKeyBytes(Dart_NativeArguments args)
void FUNCTION_NAME() X509_Der(Dart_NativeArguments args)
const unsigned char * root_certificates_pem
static void DeleteSecurityContext(void *isolate_data, void *context_pointer)
static X509 * GetX509Certificate(Dart_NativeArguments args)
void FUNCTION_NAME() X509_Subject(Dart_NativeArguments args)
void FUNCTION_NAME() SecurityContext_SetAlpnProtocols(Dart_NativeArguments args)
unsigned int root_certificates_pem_length
static EVP_PKEY * GetPrivateKey(BIO *bio, const char *password)
static int SetClientAuthoritiesPEM(SSL_CTX *context, BIO *bio)
void FUNCTION_NAME() X509_Pem(Dart_NativeArguments args)
static int UseChainBytesPKCS12(SSL_CTX *context, ScopedMemBIO *bio, const char *password)
void FUNCTION_NAME() SecurityContext_SetAllowTlsRenegotiation(Dart_NativeArguments args)
void FUNCTION_NAME() X509_StartValidity(Dart_NativeArguments args)
static int SetClientAuthoritiesPKCS12(SSL_CTX *context, ScopedMemBIO *bio, const char *password)
void FUNCTION_NAME() SecurityContext_SetClientAuthoritiesBytes(Dart_NativeArguments args)
static int SetTrustedCertificatesBytesPKCS12(SSL_CTX *context, ScopedMemBIO *bio, const char *password)
int AlpnCallback(SSL *ssl, const uint8_t **out, uint8_t *outlen, const uint8_t *in, unsigned int inlen, void *arg)
void FUNCTION_NAME() X509_Sha1(Dart_NativeArguments args)
DART_EXPORT bool Dart_IsInstance(Dart_Handle object)
DART_EXPORT bool Dart_IsBoolean(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
void * malloc(size_t size)
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t *utf8_array, intptr_t length)
DART_EXPORT void Dart_PropagateError(Dart_Handle handle)
DART_EXPORT Dart_FinalizableHandle Dart_NewFinalizableHandle(Dart_Handle object, void *peer, intptr_t external_allocation_size, Dart_HandleFinalizer callback)
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, intptr_t length)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_TypedDataAcquireData(Dart_Handle object, Dart_TypedData_Type *type, void **data, intptr_t *len)
DART_EXPORT Dart_Isolate Dart_CurrentIsolate()
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_NewApiError(const char *error)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_Null()
DART_EXPORT bool Dart_IsString(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_New(Dart_Handle type, Dart_Handle constructor_name, int number_of_arguments, Dart_Handle *arguments)
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object, const char **cstr)
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char *str)