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);
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
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)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service port
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
#define RETURN_IF_ERROR(handle)