diff --git a/include/gsystem-local-alloc.h b/include/gsystem-local-alloc.h
index 68b1227..9a46cc9 100644
--- a/include/gsystem-local-alloc.h
+++ b/include/gsystem-local-alloc.h
@@ -178,6 +178,13 @@ GS_DEFINE_CLEANUP_FUNCTION(void*, gs_local_free, g_free)
  */
 #define gs_free_error __attribute__ ((cleanup(gs_local_free_error)))
 
+/**
+ * gs_unref_key_file:
+ *
+ * Call g_key_file_unref() on a variable location when it goes out of scope.
+ */
+#define gs_unref_key_file __attribute__ ((cleanup(gs_local_keyfile_unref)))
+
 G_END_DECLS
 
 #endif
diff --git a/include/nm-test-utils.h b/include/nm-test-utils.h
index 187a0f1..9f20be3 100644
--- a/include/nm-test-utils.h
+++ b/include/nm-test-utils.h
@@ -1066,24 +1066,14 @@ nmtst_assert_hwaddr_equals (gconstpointer hwaddr1, gssize hwaddr1_len, const cha
 inline static NMConnection *
 nmtst_create_connection_from_keyfile (const char *keyfile_str, const char *keyfile_name, const char *base_dir)
 {
-	GKeyFile *keyfile;
 	GError *error = NULL;
-	gboolean success;
 	NMConnection *con;
 
 	g_assert (keyfile_str);
-
-	keyfile =  g_key_file_new ();
-	success = g_key_file_load_from_data (keyfile, keyfile_str, strlen (keyfile_str), G_KEY_FILE_NONE, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	con = nm_keyfile_read (keyfile, keyfile_name, base_dir, NULL, NULL, &error);
+	con = nm_keyfile_read (keyfile_str, keyfile_name, base_dir, NULL, NULL, &error);
 	g_assert_no_error (error);
 	g_assert (NM_IS_CONNECTION (con));
 
-	g_key_file_unref (keyfile);
-
 	nmtst_connection_normalize (con);
 
 	return con;
diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h
index 90af562..9ecd930 100644
--- a/libnm-core/nm-keyfile-internal.h
+++ b/libnm-core/nm-keyfile-internal.h
@@ -89,7 +89,7 @@ typedef struct {
 } NMKeyfileReadTypeDataWarn;
 
 
-NMConnection *nm_keyfile_read (GKeyFile *keyfile,
+NMConnection *nm_keyfile_read (const char *keyfile_data,
                                const char *keyfile_name,
                                const char *base_dir,
                                NMKeyfileReadHandler handler,
diff --git a/libnm-core/nm-keyfile-reader.c b/libnm-core/nm-keyfile-reader.c
index 87c1e14..8402fb1 100644
--- a/libnm-core/nm-keyfile-reader.c
+++ b/libnm-core/nm-keyfile-reader.c
@@ -1513,7 +1513,7 @@ read_vpn_secrets (KeyfileReaderInfo *info, NMSettingVpn *s_vpn)
 
 /**
  * nm_keyfile_read:
- * @keyfile: the keyfile from which to create the connection
+ * @keyfile_data: a string conforming to the Desktop Entry Specification
  * @keyfile_name: keyfile allows missing connection id and uuid
  *   and NetworkManager will create those when reading a connection
  *   from file. By providing a filename you can reproduce that behavior,
@@ -1535,7 +1535,7 @@ read_vpn_secrets (KeyfileReaderInfo *info, NMSettingVpn *s_vpn)
  * Returns: (transfer full): on success, returns the created connection.
  */
 NMConnection *
-nm_keyfile_read (GKeyFile *keyfile,
+nm_keyfile_read (const char *keyfile_data,
                  const char *keyfile_name,
                  const char *base_dir,
                  NMKeyfileReadHandler handler,
@@ -1551,8 +1551,9 @@ nm_keyfile_read (GKeyFile *keyfile,
 	gboolean vpn_secrets = FALSE;
 	KeyfileReaderInfo info = { 0 };
 	gs_free char *base_dir_free = NULL;
+	gs_unref_key_file GKeyFile *keyfile = NULL;
 
-	g_return_val_if_fail (keyfile, NULL);
+	g_return_val_if_fail (keyfile_data, NULL);
 	g_return_val_if_fail (!error || !*error, NULL);
 
 	if (!base_dir) {
@@ -1569,8 +1570,12 @@ nm_keyfile_read (GKeyFile *keyfile,
 
 	connection = nm_simple_connection_new ();
 
+	keyfile = g_key_file_new ();
+	if (!g_key_file_load_from_data (keyfile, keyfile_data, -1, G_KEY_FILE_NONE, error))
+		goto out_error;
+
 	info.connection = connection;
-	info.keyfile = (GKeyFile *) keyfile;
+	info.keyfile = keyfile;
 	info.base_dir = base_dir;
 	info.handler = handler;
 	info.user_data = user_data;
diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c
index 6855a5c..167029c 100644
--- a/libnm-core/tests/test-keyfile.c
+++ b/libnm-core/tests/test-keyfile.c
@@ -39,15 +39,6 @@
 
 /******************************************************************************/
 
-#define CLEAR(con, keyfile) \
-	G_STMT_START { \
-		NMConnection **_con = (con); \
-		GKeyFile **_keyfile = (keyfile); \
-		\
-		g_clear_object (_con); \
-		g_clear_pointer (_keyfile, g_key_file_unref); \
-	} G_STMT_END
-
 static void
 _assert_gbytes (GBytes *bytes, gconstpointer data, gssize len)
 {
@@ -64,21 +55,10 @@ _assert_gbytes (GBytes *bytes, gconstpointer data, gssize len)
 	}
 }
 
-static GKeyFile *
-_keyfile_load_from_data (const char *str)
+static inline const char *
+_keyfile_load_from_data (const char *data)
 {
-	GError *error = NULL;
-	gboolean success;
-	GKeyFile *keyfile;
-
-	g_assert (str);
-
-	keyfile =  g_key_file_new ();
-	success = g_key_file_load_from_data (keyfile, str, strlen (str), G_KEY_FILE_NONE, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	return keyfile;
+	return data;
 }
 
 static gboolean
@@ -116,7 +96,8 @@ _keyfile_equals (GKeyFile *kf_a, GKeyFile *kf_b)
 
 static void
 _keyfile_convert (NMConnection **con,
-                  GKeyFile **keyfile,
+                  const char *keyfile_data,
+                  GKeyFile **out_keyfile,
                   const char *keyfile_name,
                   const char *base_dir,
                   NMKeyfileReadHandler read_handler,
@@ -129,23 +110,36 @@ _keyfile_convert (NMConnection **con,
 	GKeyFile *k, *k2;
 	GError *error = NULL;
 	NMSetting8021x *s1, *s2;
+	gs_free char *keyfile_data2 = NULL;
+	gboolean success;
 
 	/* convert from @con to @keyfile and check that we can make
 	 * full round trips and obtaining the same result. */
 
 	g_assert (con);
-	g_assert (keyfile);
-	g_assert (*con || *keyfile);
+	g_assert (*con || keyfile_data);
+	g_assert (!out_keyfile || !*out_keyfile);
 
-	if (!*keyfile) {
+	/* Generate keyfile from data or connection */
+	if (keyfile_data) {
+		k = g_key_file_new ();
+		g_assert (k);
+		success = g_key_file_load_from_data (k, keyfile_data, -1, G_KEY_FILE_NONE, &error);
+		g_assert_no_error (error);
+		g_assert (success);
+	} else {
 		k = nm_keyfile_write (*con, write_handler, read_data, &error);
 		g_assert_no_error (error);
 		g_assert (k);
-		*keyfile = k;
-	} else
-		k = *keyfile;
-	if (!*con) {
-		c = nm_keyfile_read (*keyfile, keyfile_name, base_dir, read_handler, read_data, &error);
+	}
+	if (out_keyfile)
+		*out_keyfile = g_key_file_ref (k);
+
+	/* Generate connection from given connection or keyfile data */
+	if (*con) {
+		c = *con;
+	} else if (keyfile_data) {
+		c = nm_keyfile_read (keyfile_data, keyfile_name, base_dir, read_handler, read_data, &error);
 		g_assert_no_error (error);
 		g_assert (c);
 		if (needs_normalization)
@@ -154,16 +148,16 @@ _keyfile_convert (NMConnection **con,
 			nmtst_assert_connection_verifies_without_normalization (c);
 		*con = c;
 	} else
-		c = *con;
-
-	nmtst_assert_connection_equals (c, FALSE, *con, FALSE);
-	_keyfile_equals (k, *keyfile);
+		g_assert_not_reached ();
 
 	k2 = nm_keyfile_write (c, write_handler, read_data, &error);
 	g_assert_no_error (error);
 	g_assert (k2);
 
-	c2 = nm_keyfile_read (k, keyfile_name, base_dir, read_handler, read_data, &error);
+	keyfile_data2 = g_key_file_to_data (k, NULL, NULL);
+	g_assert (keyfile_data2);
+
+	c2 = nm_keyfile_read (keyfile_data2, keyfile_name, base_dir, read_handler, read_data, &error);
 	g_assert_no_error (error);
 	g_assert (c2);
 	if (needs_normalization)
@@ -194,9 +188,10 @@ _keyfile_convert (NMConnection **con,
 	}
 
 	nmtst_assert_connection_equals (c2, FALSE, *con, FALSE);
-	_keyfile_equals (k2, *keyfile);
+	_keyfile_equals (k2, k);
 
 	g_object_unref (c2);
+	g_key_file_unref (k);
 	g_key_file_unref (k2);
 }
 
@@ -212,7 +207,7 @@ _test_8021x_cert_check (NMConnection *con,
 	NMSetting8021x *s_8021x;
 	gs_free char *kval = NULL;
 
-	_keyfile_convert (&con, &keyfile, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
+	_keyfile_convert (&con, NULL, &keyfile, NULL, NULL, NULL, NULL, NULL, NULL, FALSE);
 
 	s_8021x = nm_connection_get_setting_802_1x (con);
 
@@ -344,7 +339,7 @@ test_8021x_cert (void)
 static void
 test_8021x_cert_read (void)
 {
-	GKeyFile *keyfile = NULL;
+	const char *keyfile = NULL;
 	gs_unref_object NMConnection *con = NULL;
 	NMSetting8021x *s_8021x;
 
@@ -352,15 +347,15 @@ test_8021x_cert_read (void)
 	      "[connection]\n"
 	      "type=ethernet",
 	      "/test_8021x_cert_read/test0", NULL);
-	CLEAR (&con, &keyfile);
-
+	g_clear_object (&con);
 
 	keyfile = _keyfile_load_from_data (
 	          "[connection]\n"
 	          "type=ethernet"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, NULL, TRUE);
-	CLEAR (&con, &keyfile);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, NULL, TRUE);
+	g_clear_object (&con);
+
 
 	keyfile = _keyfile_load_from_data (
 	          "[connection]\n"
@@ -374,8 +369,8 @@ test_8021x_cert_read (void)
 	          "private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;109;0;\n"
 	          "private-key-password=12345testing\n"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
-	CLEAR (&con, &keyfile);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
+	g_clear_object (&con);
 
 
 	keyfile = _keyfile_load_from_data (
@@ -404,7 +399,7 @@ test_8021x_cert_read (void)
 	                      "/33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333111111\n"
 	          "private-key-password=12345testing\n"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
 	s_8021x = nm_connection_get_setting_802_1x (con);
 
 	g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
@@ -418,7 +413,7 @@ test_8021x_cert_read (void)
 	g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
 	g_assert (g_str_has_prefix (nm_setting_802_1x_get_private_key_path (s_8021x), "/333333333"));
 	g_assert_cmpint (strlen (nm_setting_802_1x_get_private_key_path (s_8021x)), ==, 505);
-	CLEAR (&con, &keyfile);
+	g_clear_object (&con);
 
 
 	keyfile = _keyfile_load_from_data (
@@ -433,7 +428,7 @@ test_8021x_cert_read (void)
 	          "private-key=data:;base64,aGFsbG8=\n" // hallo
 	          "private-key-password=12345testing\n"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
 	s_8021x = nm_connection_get_setting_802_1x (con);
 
 	g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
@@ -444,7 +439,7 @@ test_8021x_cert_read (void)
 
 	g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
 	_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "hallo", -1);
-	CLEAR (&con, &keyfile);
+	g_clear_object (&con);
 
 
 	keyfile = _keyfile_load_from_data (
@@ -459,7 +454,7 @@ test_8021x_cert_read (void)
 	          "private-key=abc.deR\n"
 	          "private-key-password=12345testing\n"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
 	s_8021x = nm_connection_get_setting_802_1x (con);
 
 	g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH);
@@ -470,7 +465,7 @@ test_8021x_cert_read (void)
 
 	g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
 	_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "abc.deR\0", 8);
-	CLEAR (&con, &keyfile);
+	g_clear_object (&con);
 
 
 	keyfile = _keyfile_load_from_data (
@@ -485,7 +480,7 @@ test_8021x_cert_read (void)
 	          "private-key=hallo\n"
 	          "private-key-password=12345testing\n"
 	          );
-	_keyfile_convert (&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
+	_keyfile_convert (&con, keyfile, NULL, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, NULL, TRUE);
 	s_8021x = nm_connection_get_setting_802_1x (con);
 
 	g_assert (nm_setting_802_1x_get_ca_cert_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
@@ -496,7 +491,7 @@ test_8021x_cert_read (void)
 
 	g_assert (nm_setting_802_1x_get_private_key_scheme (s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB);
 	_assert_gbytes (nm_setting_802_1x_get_private_key_blob (s_8021x), "hallo\0", 6);
-	CLEAR (&con, &keyfile);
+	g_clear_object (&con);
 }
 
 /******************************************************************************/
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index a149e06..baeed2f 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -88,11 +88,11 @@ _handler_read (GKeyFile *keyfile,
 NMConnection *
 nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 {
-	GKeyFile *key_file;
 	struct stat statbuf;
 	gboolean bad_permissions;
 	NMConnection *connection = NULL;
 	GError *verify_error = NULL;
+	char *contents = NULL;
 
 	if (stat (filename, &statbuf) != 0 || !S_ISREG (statbuf.st_mode)) {
 		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
@@ -109,11 +109,10 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 		return NULL;
 	}
 
-	key_file = g_key_file_new ();
-	if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
+	if (!g_file_get_contents (filename, &contents, NULL, error))
 		goto out;
 
-	connection = nm_keyfile_read (key_file, filename, NULL, _handler_read, NULL, error);
+	connection = nm_keyfile_read (contents, filename, NULL, _handler_read, NULL, error);
 	if (!connection)
 		goto out;
 
@@ -128,7 +127,7 @@ nm_keyfile_plugin_connection_from_file (const char *filename, GError **error)
 	}
 
 out:
-	g_key_file_free (key_file);
+	g_free (contents);
 	return connection;
 }
 
