blob: f6471a22f8157482e5f2a0f1fbb557fe12713a88 [file] [log] [blame]
diff --git a/sdk/runtime/bin/secure_socket_boringssl.cc b/sdk/runtime/bin/secure_socket_boringssl.cc
index def3aae..e881815 100644
--- a/sdk/runtime/bin/secure_socket_boringssl.cc
+++ b/sdk/runtime/bin/secure_socket_boringssl.cc
@@ -94,11 +94,14 @@ static void ThrowIOException(int status,
const char* message) {
char error_string[SSL_ERROR_MESSAGE_BUFFER_SIZE];
FetchErrorString(error_string, SSL_ERROR_MESSAGE_BUFFER_SIZE);
- OSError os_error_struct(status, error_string, OSError::kBoringSSL);
- Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
- Dart_Handle exception =
- DartUtils::NewDartIOException(exception_type, message, os_error);
- ASSERT(!Dart_IsError(exception));
+ Dart_Handle exception;
+ {
+ OSError os_error_struct(status, error_string, OSError::kBoringSSL);
+ Dart_Handle os_error = DartUtils::NewDartOSError(&os_error_struct);
+ exception =
+ DartUtils::NewDartIOException(exception_type, message, os_error);
+ ASSERT(!Dart_IsError(exception));
+ }
Dart_ThrowException(exception);
UNREACHABLE();
}
@@ -143,8 +146,8 @@ static Dart_Handle SetFilter(Dart_NativeArguments args, SSLFilter* filter) {
}
-static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) {
- SSL_CTX* context;
+static SSLContext* GetSecurityContext(Dart_NativeArguments args) {
+ SSLContext* context;
Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
ASSERT(Dart_IsInstance(dart_this));
ThrowIfError(Dart_GetNativeInstanceField(
@@ -155,17 +158,17 @@ static SSL_CTX* GetSecurityContext(Dart_NativeArguments args) {
}
-static void FreeSecurityContext(
+static void DeleteSecurityContext(
void* isolate_data,
Dart_WeakPersistentHandle handle,
void* context_pointer) {
- SSL_CTX* context = static_cast<SSL_CTX*>(context_pointer);
- SSL_CTX_free(context);
+ SSLContext* context = static_cast<SSLContext*>(context_pointer);
+ delete context;
}
static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
- SSL_CTX* context) {
+ SSLContext* context) {
const int approximate_size_of_context = 1500;
Dart_Handle dart_this = Dart_GetNativeArgument(args, 0);
RETURN_IF_ERROR(dart_this);
@@ -178,7 +181,7 @@ static Dart_Handle SetSecurityContext(Dart_NativeArguments args,
Dart_NewWeakPersistentHandle(dart_this,
context,
approximate_size_of_context,
- FreeSecurityContext);
+ DeleteSecurityContext);
return Dart_Null();
}
@@ -198,7 +201,7 @@ static X509* GetX509Certificate(Dart_NativeArguments args) {
// Forward declaration.
static void SetAlpnProtocolList(Dart_Handle protocols_handle,
SSL* ssl,
- SSL_CTX* context,
+ SSLContext* context,
bool is_server);
@@ -235,7 +238,7 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
// TODO(whesse): Is truncating a Dart string containing \0 what we want?
ThrowIfError(Dart_StringToCString(host_name_object, &host_name));
- SSL_CTX* context = NULL;
+ SSLContext* context = NULL;
if (!Dart_IsNull(context_object)) {
ThrowIfError(Dart_GetNativeInstanceField(
context_object,
@@ -248,7 +251,7 @@ void FUNCTION_NAME(SecureSocket_Connect)(Dart_NativeArguments args) {
ASSERT(!Dart_IsNull(protocols_handle));
GetFilter(args)->Connect(host_name,
- context,
+ context->context(),
is_server,
request_client_certificate,
require_client_certificate,
@@ -426,14 +429,15 @@ int CertificateCallback(int preverify_ok, X509_STORE_CTX* store_ctx) {
void FUNCTION_NAME(SecurityContext_Allocate)(Dart_NativeArguments args) {
SSLFilter::InitializeLibrary();
- SSL_CTX* context = SSL_CTX_new(TLS_method());
- SSL_CTX_set_verify(context, SSL_VERIFY_PEER, CertificateCallback);
- SSL_CTX_set_min_version(context, TLS1_VERSION);
- SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM");
- SSL_CTX_set_cipher_list_tls11(context, "HIGH:MEDIUM");
+ SSL_CTX* ctx = SSL_CTX_new(TLS_method());
+ SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, CertificateCallback);
+ SSL_CTX_set_min_version(ctx, TLS1_VERSION);
+ SSL_CTX_set_cipher_list(ctx, "HIGH:MEDIUM");
+ SSL_CTX_set_cipher_list_tls11(ctx, "HIGH:MEDIUM");
+ SSLContext* context = new SSLContext(ctx);
Dart_Handle err = SetSecurityContext(args, context);
if (Dart_IsError(err)) {
- SSL_CTX_free(context);
+ delete context;
Dart_PropagateError(err);
}
}
@@ -663,14 +667,17 @@ static const char* GetPasswordArgument(Dart_NativeArguments args,
void FUNCTION_NAME(SecurityContext_UsePrivateKeyBytes)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
const char* password = GetPasswordArgument(args, 2);
int status;
{
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
EVP_PKEY *key = GetPrivateKey(bio.bio(), password);
- status = SSL_CTX_use_PrivateKey(context, key);
+ status = SSL_CTX_use_PrivateKey(context->context(), key);
+ // SSL_CTX_use_PrivateKey increments the reference count of key on success,
+ // so we have to call EVP_PKEY_free on both success and failure.
+ EVP_PKEY_free(key);
}
// TODO(24184): Handle different expected errors here - file missing,
@@ -699,16 +706,18 @@ static int SetTrustedCertificatesBytesPKCS12(SSL_CTX* context,
ScopedX509Stack cert_stack(ca_certs);
X509_STORE* store = SSL_CTX_get_cert_store(context);
status = X509_STORE_add_cert(store, cert);
+ // X509_STORE_add_cert increments the reference count of cert on success.
+ X509_free(cert);
if (status == 0) {
- X509_free(cert);
return status;
}
X509* ca;
while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
status = X509_STORE_add_cert(store, ca);
+ // X509_STORE_add_cert increments the reference count of cert on success.
+ X509_free(ca);
if (status == 0) {
- X509_free(ca);
return status;
}
}
@@ -724,8 +733,9 @@ static int SetTrustedCertificatesBytesPEM(SSL_CTX* context, BIO* bio) {
X509* cert = NULL;
while ((cert = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
status = X509_STORE_add_cert(store, cert);
+ // X509_STORE_add_cert increments the reference count of cert on success.
+ X509_free(cert);
if (status == 0) {
- X509_free(cert);
return status;
}
}
@@ -759,12 +769,13 @@ static int SetTrustedCertificatesBytes(SSL_CTX* context,
void FUNCTION_NAME(SecurityContext_SetTrustedCertificatesBytes)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
const char* password = GetPasswordArgument(args, 2);
int status;
{
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
- status = SetTrustedCertificatesBytes(context, bio.bio(), password);
+ status = SetTrustedCertificatesBytes(
+ context->context(), bio.bio(), password);
}
CheckStatus(status,
"TlsException",
@@ -779,7 +790,7 @@ void FUNCTION_NAME(SecurityContext_AlpnSupported)(Dart_NativeArguments args) {
void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
#if defined(TARGET_OS_ANDROID)
// On Android, we don't compile in the trusted root certificates. Insead,
// we use the directory of trusted certificates already present on the device.
@@ -789,10 +800,11 @@ void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
// the Dart thread so that Dart code can be invoked from the "bad certificate"
// callback called by SSL_do_handshake.
const char* android_cacerts = "/system/etc/security/cacerts";
- int status = SSL_CTX_load_verify_locations(context, NULL, android_cacerts);
+ int status = SSL_CTX_load_verify_locations(
+ context->context(), NULL, android_cacerts);
CheckStatus(status, "TlsException", "Failure trusting builtint roots");
#else
- X509_STORE* store = SSL_CTX_get_cert_store(context);
+ X509_STORE* store = SSL_CTX_get_cert_store(context->context());
BIO* roots_bio =
BIO_new_mem_buf(const_cast<unsigned char*>(root_certificates_pem),
root_certificates_pem_length);
@@ -801,7 +813,12 @@ void FUNCTION_NAME(SecurityContext_TrustBuiltinRoots)(
// backed by a memory buffer), and returns X509 objects, one by one.
// When the end of the bio is reached, it returns null.
while ((root_cert = PEM_read_bio_X509(roots_bio, NULL, NULL, NULL)) != NULL) {
- X509_STORE_add_cert(store, root_cert);
+ int status = X509_STORE_add_cert(store, root_cert);
+ // X509_STORE_add_cert increments the reference count of cert on success.
+ X509_free(root_cert);
+ if (status == 0) {
+ break;
+ }
}
BIO_free(roots_bio);
// If there is an error here, it must be the error indicating that we are done
@@ -844,6 +861,8 @@ static int UseChainBytesPKCS12(SSL_CTX* context,
X509* ca;
while ((ca = sk_X509_shift(certs.get())) != NULL) {
status = SSL_CTX_add0_chain_cert(context, ca);
+ // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
+ // call fails.
if (status == 0) {
X509_free(ca);
return status;
@@ -875,6 +894,8 @@ static int UseChainBytesPEM(SSL_CTX* context, BIO* bio) {
X509* ca;
while ((ca = PEM_read_bio_X509(bio, NULL, NULL, NULL)) != NULL) {
status = SSL_CTX_add0_chain_cert(context, ca);
+ // SSL_CTX_add0_chain_cert does not inc ref count, so don't free unless the
+ // call fails.
if (status == 0) {
X509_free(ca);
return status;
@@ -906,12 +927,12 @@ static int UseChainBytes(SSL_CTX* context, BIO* bio, const char* password) {
void FUNCTION_NAME(SecurityContext_UseCertificateChainBytes)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
const char* password = GetPasswordArgument(args, 2);
int status;
{
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
- status = UseChainBytes(context, bio.bio(), password);
+ status = UseChainBytes(context->context(), bio.bio(), password);
}
CheckStatus(status,
"TlsException",
@@ -937,14 +958,16 @@ static int SetClientAuthoritiesPKCS12(SSL_CTX* context,
ScopedX509Stack cert_stack(ca_certs);
status = SSL_CTX_add_client_CA(context, cert);
+ // SSL_CTX_add_client_CA increments the reference count of cert on success.
+ X509_free(cert);
if (status == 0) {
- X509_free(cert);
return status;
}
X509* ca;
while ((ca = sk_X509_shift(cert_stack.get())) != NULL) {
status = SSL_CTX_add_client_CA(context, ca);
+ // SSL_CTX_add_client_CA increments the reference count of ca on success.
X509_free(ca); // The name has been extracted.
if (status == 0) {
return status;
@@ -989,13 +1012,13 @@ static int SetClientAuthorities(SSL_CTX* context,
void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
const char* password = GetPasswordArgument(args, 2);
int status;
{
ScopedMemBIO bio(ThrowIfError(Dart_GetNativeArgument(args, 1)));
- status = SetClientAuthorities(context, bio.bio(), password);
+ status = SetClientAuthorities(context->context(), bio.bio(), password);
}
CheckStatus(status,
@@ -1006,7 +1029,7 @@ void FUNCTION_NAME(SecurityContext_SetClientAuthoritiesBytes)(
void FUNCTION_NAME(SecurityContext_SetAlpnProtocols)(
Dart_NativeArguments args) {
- SSL_CTX* context = GetSecurityContext(args);
+ SSLContext* context = GetSecurityContext(args);
Dart_Handle protocols_handle =
ThrowIfError(Dart_GetNativeArgument(args, 1));
Dart_Handle is_server_handle =
@@ -1363,7 +1386,7 @@ int AlpnCallback(SSL *ssl,
// Sets the protocol list for ALPN on a SSL object or a context.
static void SetAlpnProtocolList(Dart_Handle protocols_handle,
SSL* ssl,
- SSL_CTX* context,
+ SSLContext* context,
bool is_server) {
// Enable ALPN (application layer protocol negotiation) if the caller provides
// a valid list of supported protocols.
@@ -1400,13 +1423,9 @@ static void SetAlpnProtocolList(Dart_Handle protocols_handle,
static_cast<uint8_t*>(malloc(protocol_string_len + 1));
memmove(protocol_string_copy, protocol_string, protocol_string_len);
protocol_string_copy[protocol_string_len] = '\0';
- SSL_CTX_set_alpn_select_cb(context, AlpnCallback, protocol_string_copy);
- // TODO(whesse): If this function is called again, free the previous
- // protocol_string_copy. It may be better to keep this as a native
- // field on the Dart object, since fetching it from the structure is
- // not in the public api.
- // Also free protocol_string_copy when the context is destroyed,
- // in FreeSecurityContext()
+ SSL_CTX_set_alpn_select_cb(
+ context->context(), AlpnCallback, protocol_string_copy);
+ context->set_alpn_protocol_string(protocol_string_copy);
} else {
// The function makes a local copy of protocol_string, which it owns.
if (ssl != NULL) {
@@ -1416,7 +1435,7 @@ static void SetAlpnProtocolList(Dart_Handle protocols_handle,
ASSERT(context != NULL);
ASSERT(ssl == NULL);
status = SSL_CTX_set_alpn_protos(
- context, protocol_string, protocol_string_len);
+ context->context(), protocol_string, protocol_string_len);
}
ASSERT(status == 0); // The function returns a non-standard status.
}
diff --git a/sdk/runtime/bin/secure_socket_boringssl.h b/sdk/runtime/bin/secure_socket_boringssl.h
index d5449a4..788b257 100644
--- a/sdk/runtime/bin/secure_socket_boringssl.h
+++ b/sdk/runtime/bin/secure_socket_boringssl.h
@@ -33,8 +33,39 @@ namespace bin {
extern const unsigned char* root_certificates_pem;
extern unsigned int root_certificates_pem_length;
+class SSLContext {
+ public:
+ explicit SSLContext(SSL_CTX* context) :
+ context_(context),
+ alpn_protocol_string_(NULL) {
+ }
+
+ ~SSLContext() {
+ SSL_CTX_free(context_);
+ if (alpn_protocol_string_ != NULL) {
+ free(alpn_protocol_string_);
+ }
+ }
+
+ SSL_CTX* context() const { return context_; }
+
+ uint8_t* alpn_protocol_string() const { return alpn_protocol_string_; }
+ void set_alpn_protocol_string(uint8_t* protocol_string) {
+ if (alpn_protocol_string_ != NULL) {
+ free(alpn_protocol_string_);
+ }
+ alpn_protocol_string_ = protocol_string;
+ }
+
+ private:
+ SSL_CTX* context_;
+ uint8_t* alpn_protocol_string_;
+
+ DISALLOW_COPY_AND_ASSIGN(SSLContext);
+};
+
/*
- * SSLFilter encapsulates the NSS SSL(TLS) code in a filter, that communicates
+ * SSLFilter encapsulates the SSL(TLS) code in a filter, that communicates
* with the containing _SecureFilterImpl Dart object through four shared
* ExternalByteArray buffers, for reading and writing plaintext, and
* reading and writing encrypted text. The filter handles handshaking