diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index 9aa28cb..526ac03 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3688,3 +3688,9 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line)
 	return ret;
 }
 
+int wpa_config_process_common(struct wpa_config *config, char *pos, int line)
+{
+	return wpa_config_process_fields(config, pos, line, common_fields,
+					 NUM_COMMON_FIELDS);
+}
+
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index de43970..3428f85 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1065,6 +1065,7 @@ void wpa_config_debug_dump_networks(struct wpa_config *config);
 
 /* Prototypes for common functions from config.c */
 int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
+int wpa_config_process_common(struct wpa_config *config, char *pos, int line);
 
 
 /* Prototypes for backend specific functions from the selected config_*.c */
@@ -1085,6 +1086,22 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line);
 struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp);
 
 /**
+ * wpa_config_read_common - Read and parse common configuration database
+ * @name: Name of the configuration (e.g., path and file name for the
+ * configuration file)
+ * @cfgp: Pointer to previously allocated configuration data
+ * Returns: Pointer to an updated cfgp
+ *
+ * This function reads a configuration file, updating only the common global
+ * configuration data (data that should be common to all interfaces), e.g., WPS
+ * and P2P configuration data.
+ *
+ * Each configuration backend needs to implement this function.
+ */
+struct wpa_config *wpa_config_read_common(const char *name,
+					  struct wpa_config *cfgp);
+
+/**
  * wpa_config_write - Write or update configuration data
  * @name: Name of the configuration (e.g., path and file name for the
  * configuration file)
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 4f58130..b280521 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -451,6 +451,104 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 	return config;
 }
 
+struct wpa_config *wpa_config_read_common(const char *name,
+					  struct wpa_config *cfgp)
+{
+	FILE *f;
+	char buf[512], *pos;
+	int errors = 0, line = 0;
+	struct wpa_ssid *ssid;
+	struct wpa_cred *cred;
+	struct wpa_config *config, *dummy;
+
+	if (name == NULL)
+		return NULL;
+	if (!cfgp)
+		return NULL;
+
+	config = cfgp;
+
+	/*
+	 * The dummy configuration file is used to consume configuration data
+	 * that should not be used to update the given configuration
+	 */
+	dummy = wpa_config_alloc_empty(NULL, NULL);
+	if (dummy == NULL) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to allocate config file structure");
+		return NULL;
+	}
+
+	wpa_printf(MSG_DEBUG, "Reading common configuration file '%s'", name);
+	f = fopen(name, "r");
+	if (f == NULL) {
+		wpa_printf(MSG_ERROR,
+			   "Failed to open config file '%s', error: %s",
+			   name, strerror(errno));
+		os_free(config);
+		return NULL;
+	}
+
+	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
+		if (os_strcmp(pos, "network={") == 0) {
+			ssid = wpa_config_read_network(f, &line, 0);
+			if (ssid == NULL) {
+				wpa_printf(MSG_ERROR,
+					   "Line %d: failed to parse network block.",
+					   line);
+				errors++;
+				continue;
+			}
+			wpa_config_free_ssid(ssid);
+			ssid = NULL;
+		} else if (os_strcmp(pos, "cred={") == 0) {
+			cred = wpa_config_read_cred(f, &line, 0);
+			if (cred == NULL) {
+				wpa_printf(MSG_ERROR,
+					   "Line %d: failed to parse cred block.",
+					   line);
+				errors++;
+				continue;
+			}
+			wpa_config_free_cred(cred);
+			cred = NULL;
+#ifndef CONFIG_NO_CONFIG_BLOBS
+		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
+			if (wpa_config_process_blob(dummy, f, &line,
+						    pos + 12)
+			    < 0) {
+				wpa_printf(MSG_ERROR,
+					   "Line %d: failed to process blob.",
+					   line);
+				errors++;
+				continue;
+			}
+#endif /* CONFIG_NO_CONFIG_BLOBS */
+		} else {
+			if (wpa_config_process_common(config, pos, line) < 0 &&
+			    wpa_config_process_global(dummy, pos, line) < 0) {
+				wpa_printf(MSG_ERROR,
+					   "Line %d: Invalid configuration line '%s'.",
+					   line, pos);
+				errors++;
+				continue;
+			}
+		}
+	}
+
+	fclose(f);
+
+#ifndef WPA_IGNORE_CONFIG_ERRORS
+	if (errors) {
+		wpa_config_free(config);
+		config = NULL;
+	}
+	wpa_config_free(dummy);
+
+#endif /* WPA_IGNORE_CONFIG_ERRORS */
+
+	return config;
+}
 
 #ifndef CONFIG_NO_CONFIG_WRITE
 
diff --git a/wpa_supplicant/config_none.c b/wpa_supplicant/config_none.c
index 2aac28f..0362a77 100644
--- a/wpa_supplicant/config_none.c
+++ b/wpa_supplicant/config_none.c
@@ -34,6 +34,15 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 }
 
 
+struct wpa_config *wpa_config_read_common(const char *name,
+					  struct wpa_config *cfgp)
+{
+	if (name == NULL)
+		return NULL;
+	return cfgp;
+}
+
+
 int wpa_config_write(const char *name, struct wpa_config *config)
 {
 	struct wpa_ssid *ssid;
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 00a1004..4ab3bd7 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -489,6 +489,18 @@ struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp)
 }
 
 
+struct wpa_config *wpa_config_read_common(const char *name,
+					  struct wpa_config *cfgp)
+{
+	if (name == NULL)
+		return NULL;
+
+	/* TODO: requires real implementation */
+
+	return cfgp;
+}
+
+
 static int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val,
 				      int def)
 {
