diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index 01e7b7553..cc5e884bf 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -1231,12 +1231,12 @@ static void set_pps_cred_home_sp_oi(struct hs20_osu_client *ctx, int id,
 		   homeoi, required);
 
 	if (required) {
-		if (set_cred(ctx->ifname, id, "required_roaming_consortium",
+		if (set_cred(ctx->ifname, id, "required_home_ois",
 			     homeoi) < 0)
-			wpa_printf(MSG_INFO, "Failed to set cred required_roaming_consortium");
+			wpa_printf(MSG_INFO, "Failed to set cred required_home_ois");
 	} else {
-		if (set_cred(ctx->ifname, id, "roaming_consortium", homeoi) < 0)
-			wpa_printf(MSG_INFO, "Failed to set cred roaming_consortium");
+		if (set_cred(ctx->ifname, id, "home_ois", homeoi) < 0)
+			wpa_printf(MSG_INFO, "Failed to set cred home_ois");
 	}
 
 	xml_node_get_text_free(ctx->xml, homeoi);
diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py
index c981b3547..f90745021 100644
--- a/tests/hwsim/test_ap_hs20.py
+++ b/tests/hwsim/test_ap_hs20.py
@@ -1092,7 +1092,7 @@ def test_ap_hs20_roaming_consortium(dev, apdev):
                                      'password': "password",
                                      'domain': "example.com",
                                      'ca_cert': "auth_serv/ca.pem",
-                                     'roaming_consortium': consortium,
+                                     'home_ois': [consortium],
                                      'eap': "PEAP"})
         interworking_select(dev[0], bssid, "home", freq="2412")
         interworking_connect(dev[0], bssid, "PEAP")
@@ -1161,7 +1161,7 @@ def test_ap_hs20_roaming_consortium_invalid(dev, apdev):
                                  'password': "password",
                                  'domain': "example.com",
                                  'ca_cert': "auth_serv/ca.pem",
-                                 'roaming_consortium': "fedcba",
+                                 'home_ois': ["fedcba"],
                                  'eap': "PEAP"})
     interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
 
@@ -1180,7 +1180,7 @@ def test_ap_hs20_roaming_consortium_element(dev, apdev):
                                  'password': "password",
                                  'domain': "example.com",
                                  'ca_cert': "auth_serv/ca.pem",
-                                 'roaming_consortium': "112233",
+                                 'home_ois': ["112233"],
                                  'eap': "PEAP"})
     interworking_select(dev[0], bssid, freq="2412", no_match=True)
 
@@ -1205,10 +1205,10 @@ def test_ap_hs20_roaming_consortium_constraints(dev, apdev):
             'password': "password",
             'domain': "example.com",
             'ca_cert': "auth_serv/ca.pem",
-            'roaming_consortium': "fedcba",
+            'home_ois': ["fedcba"],
             'eap': "TTLS"}
     vals2 = vals.copy()
-    vals2['required_roaming_consortium'] = "223344"
+    vals2['required_home_ois'] = ["223344"]
     id = dev[0].add_cred_values(vals2)
     interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
     dev[0].remove_cred(id)
@@ -1249,16 +1249,16 @@ def test_ap_hs20_roaming_consortium_constraints(dev, apdev):
     dev[0].remove_cred(id)
 
     values = default_cred()
-    values['roaming_consortium'] = "fedcba"
+    values['home_ois'] = ["fedcba"]
     id3 = dev[0].add_cred_values(values)
 
     vals2 = vals.copy()
-    vals2['roaming_consortium'] = "fedcba"
+    vals2['home_ois'] = ["fedcba"]
     vals2['priority'] = "2"
     id = dev[0].add_cred_values(vals2)
 
     values = default_cred()
-    values['roaming_consortium'] = "fedcba"
+    values['home_ois'] = ["fedcba"]
     id2 = dev[0].add_cred_values(values)
 
     dev[0].request("INTERWORKING_SELECT freq=2412")
@@ -1285,7 +1285,7 @@ def test_ap_hs20_3gpp_constraints(dev, apdev):
             'eap': "SIM",
             'milenage': "5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123"}
     vals2 = vals.copy()
-    vals2['required_roaming_consortium'] = "223344"
+    vals2['required_home_ois'] = ["223344"]
     id = dev[0].add_cred_values(vals2)
     interworking_select(dev[0], bssid, "home", freq="2412", no_match=True)
     dev[0].remove_cred(id)
@@ -1313,16 +1313,16 @@ def test_ap_hs20_3gpp_constraints(dev, apdev):
     dev[0].remove_cred(id)
 
     values = default_cred()
-    values['roaming_consortium'] = "fedcba"
+    values['home_ois'] = ["fedcba"]
     id3 = dev[0].add_cred_values(values)
 
     vals2 = vals.copy()
-    vals2['roaming_consortium'] = "fedcba"
+    vals2['home_ois'] = ["fedcba"]
     vals2['priority'] = "2"
     id = dev[0].add_cred_values(vals2)
 
     values = default_cred()
-    values['roaming_consortium'] = "fedcba"
+    values['home_ois'] = ["fedcba"]
     id2 = dev[0].add_cred_values(values)
 
     dev[0].request("INTERWORKING_SELECT freq=2412")
@@ -1365,7 +1365,7 @@ def test_ap_hs20_connect_no_full_match(dev, apdev):
             'password': "password",
             'domain': "example.com",
             'ca_cert': "auth_serv/ca.pem",
-            'roaming_consortium': "fedcba",
+            'home_ois': ["fedcba"],
             'eap': "TTLS",
             'min_dl_bandwidth_home': "65500"}
     id = dev[0].add_cred_values(vals)
@@ -1779,7 +1779,7 @@ def test_ap_hs20_prefer_home(dev, apdev):
     values['domain'] = "example.org"
     policy_test(dev[0], apdev[0], values, only_one=False)
 
-def test_ap_hs20_req_roaming_consortium(dev, apdev):
+def test_ap_hs20_req_home_ois(dev, apdev):
     """Hotspot 2.0 required roaming consortium"""
     check_eap_capa(dev[0], "MSCHAPV2")
     params = hs20_ap_params()
@@ -1791,18 +1791,18 @@ def test_ap_hs20_req_roaming_consortium(dev, apdev):
     hostapd.add_ap(apdev[1], params)
 
     values = default_cred()
-    values['required_roaming_consortium'] = "223344"
+    values['required_home_ois'] = ["223344"]
     policy_test(dev[0], apdev[1], values)
-    values['required_roaming_consortium'] = "112233"
+    values['required_home_ois'] = ["112233"]
     policy_test(dev[0], apdev[0], values)
 
     id = dev[0].add_cred()
-    dev[0].set_cred(id, "required_roaming_consortium", "112233")
-    dev[0].set_cred(id, "required_roaming_consortium", "112233445566778899aabbccddeeff")
+    dev[0].set_cred_quoted(id, "required_home_ois", "112233")
+    dev[0].set_cred_quoted(id, "required_home_ois", "112233445566778899aabbccddeeff")
 
     for val in ["", "1", "11", "1122", "1122334",
                 "112233445566778899aabbccddeeff00"]:
-        if "FAIL" not in dev[0].request('SET_CRED {} required_roaming_consortium {}'.format(id, val)):
+        if "FAIL" not in dev[0].request('SET_CRED {} required_home_ois {}'.format(id, val)):
             raise Exception("Invalid roaming consortium value accepted: " + val)
 
 def test_ap_hs20_req_roaming_consortium_no_match(dev, apdev):
@@ -1818,7 +1818,7 @@ def test_ap_hs20_req_roaming_consortium_no_match(dev, apdev):
     hostapd.add_ap(apdev[1], params)
 
     values = default_cred()
-    values['required_roaming_consortium'] = "223344"
+    values['required_home_ois'] = ["223344"]
     dev[0].hs20_enable()
     id = dev[0].add_cred_values(values)
     dev[0].request("INTERWORKING_SELECT auto freq=2412")
@@ -1853,7 +1853,7 @@ def test_ap_hs20_excluded_ssid(dev, apdev):
         raise Exception("Excluded network not reported")
 
     values = default_cred()
-    values['roaming_consortium'] = "223344"
+    values['home_ois'] = ["223344"]
     values['eap'] = "TTLS"
     values['phase2'] = "auth=MSCHAPV2"
     values['excluded_ssid'] = "test-hs20"
@@ -5540,7 +5540,7 @@ def test_ap_hs20_cred_with_nai_realm(dev, apdev):
                                  'username': "test",
                                  'password': "secret",
                                  'domain': "example.com",
-                                 'roaming_consortium': "112234",
+                                 'home_ois': ["112234"],
                                  'eap': 'TTLS'})
     interworking_select(dev[0], bssid, "home", freq=2412, no_match=True)
     dev[0].remove_cred(id)
@@ -5559,7 +5559,7 @@ def test_ap_hs20_cred_and_no_roaming_consortium(dev, apdev):
                                  'username': "test",
                                  'password': "secret",
                                  'domain': "example.com",
-                                 'roaming_consortium': "112234",
+                                 'home_ois': ["112234"],
                                  'eap': 'TTLS'})
     interworking_select(dev[0], bssid, "home", freq=2412)
 
@@ -5635,7 +5635,7 @@ def test_ap_hs20_no_rsn_connect(dev, apdev):
                                  'username': "test",
                                  'password': "secret",
                                  'domain': "example.com",
-                                 'roaming_consortium': "112233",
+                                 'home_ois': ["112233"],
                                  'eap': 'TTLS'})
 
     interworking_select(dev[0], bssid, freq=2412, no_match=True)
@@ -5655,7 +5655,7 @@ def test_ap_hs20_no_match_connect(dev, apdev):
                                  'username': "test",
                                  'password': "secret",
                                  'domain': "example.org",
-                                 'roaming_consortium': "112234",
+                                 'home_ois': ["112234"],
                                  'eap': 'TTLS'})
 
     interworking_select(dev[0], bssid, freq=2412, no_match=True)
@@ -5712,7 +5712,7 @@ def test_ap_hs20_anqp_invalid_gas_response(dev, apdev):
                                  'username': "test",
                                  'password': "secret",
                                  'domain': "example.com",
-                                 'roaming_consortium': "112234",
+                                 'home_ois': ["112234"],
                                  'eap': 'TTLS'})
     dev[0].request("INTERWORKING_SELECT freq=2412")
 
@@ -5885,7 +5885,7 @@ def test_ap_hs20_set_profile_failures(dev, apdev):
         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
     dev[0].remove_cred(id)
 
-    id = dev[0].add_cred_values({'roaming_consortium': "112233",
+    id = dev[0].add_cred_values({'home_ois': ["112233"],
                                  'domain': "example.com",
                                  'username': "hs20-test",
                                  'password': "password",
@@ -5907,7 +5907,7 @@ def test_ap_hs20_set_profile_failures(dev, apdev):
     dev[0].remove_cred(id)
     dev[0].wait_disconnected()
 
-    id = dev[0].add_cred_values({'roaming_consortium': "112233",
+    id = dev[0].add_cred_values({'home_ois': ["112233"],
                                  'domain': "example.com",
                                  'realm': "example.com",
                                  'username': "user",
@@ -5925,7 +5925,7 @@ def test_ap_hs20_set_profile_failures(dev, apdev):
         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
     dev[0].remove_cred(id)
 
-    id = dev[0].add_cred_values({'roaming_consortium': "112233",
+    id = dev[0].add_cred_values({'home_ois': ["112233"],
                                  'domain': "example.com",
                                  'realm': "example.com",
                                  'username': "user",
@@ -5949,7 +5949,7 @@ def test_ap_hs20_set_profile_failures(dev, apdev):
         wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
     dev[0].remove_cred(id)
 
-    id = dev[0].add_cred_values({'roaming_consortium': "112233",
+    id = dev[0].add_cred_values({'home_ois': ["112233"],
                                  'domain': "example.com",
                                  'realm': "example.com",
                                  'username': "user",
@@ -6023,7 +6023,7 @@ def test_ap_hs20_set_profile_failures(dev, apdev):
             wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
     dev[0].remove_cred(id)
 
-    id = dev[0].add_cred_values({'roaming_consortium': "112233",
+    id = dev[0].add_cred_values({'home_ois': ["112233"],
                                  'eap': 'TTLS',
                                  'username': "user@example.com",
                                  'password': "password"})
diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py
index fe59e1856..03968b33f 100644
--- a/tests/hwsim/test_dbus.py
+++ b/tests/hwsim/test_dbus.py
@@ -6104,8 +6104,8 @@ def test_dbus_creds(dev, apdev):
 
     args = {'domain': 'server.w1.fi',
             'realm': 'server.w1.fi',
-            'roaming_consortium': '50a9bf',
-            'required_roaming_consortium': '23bf50',
+            'home_ois': ['50a9bf'],
+            'required_home_ois': ['23bf50'],
             'eap': 'TTLS',
             'phase2': 'auth=MSCHAPV2',
             'username': 'user',
diff --git a/tests/hwsim/test_wpas_config.py b/tests/hwsim/test_wpas_config.py
index 3cd7dfcf3..860e80a05 100644
--- a/tests/hwsim/test_wpas_config.py
+++ b/tests/hwsim/test_wpas_config.py
@@ -223,8 +223,8 @@ def test_wpas_config_file(dev, apdev, params):
         wpas.set_cred_quoted(id, "provisioning_sp", "example.com")
         wpas.set_cred_quoted(id, "domain", "example.com")
         wpas.set_cred_quoted(id, "domain_suffix_match", "example.com")
-        wpas.set_cred(id, "roaming_consortium", "112233")
-        wpas.set_cred(id, "required_roaming_consortium", "112233")
+        wpas.set_cred_quoted(id, "home_ois", "112233,445566")
+        wpas.set_cred_quoted(id, "required_home_ois", "112233")
         wpas.set_cred_quoted(id, "roaming_consortiums",
                              "112233,aabbccddee,445566")
         wpas.set_cred_quoted(id, "roaming_partner",
diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py
index 898e8bdea..ea560a89a 100644
--- a/tests/hwsim/test_wpas_ctrl.py
+++ b/tests/hwsim/test_wpas_ctrl.py
@@ -465,8 +465,12 @@ def test_wpas_ctrl_cred(dev):
         raise Exception("Unexpected success on invalid string")
 
     for i in ("11", "1122", "112233445566778899aabbccddeeff00"):
-        if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " roaming_consortium " + i):
-            raise Exception("Unexpected success on invalid roaming_consortium")
+        if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " home_ois " + i):
+            raise Exception("Unexpected success on invalid home_ois")
+
+    for i in ("11", "1122", "112233445566778899aabbccddeeff00"):
+        if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " required_home_ois " + i):
+            raise Exception("Unexpected success on invalid required_home_ois")
 
     dev[0].set_cred(id, "excluded_ssid", "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff")
     if "FAIL" not in dev[0].request("SET_CRED " + str(id) + " excluded_ssid 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00"):
diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py
index fe1892785..adc7e02e7 100644
--- a/tests/hwsim/wpasupplicant.py
+++ b/tests/hwsim/wpasupplicant.py
@@ -460,15 +460,19 @@ class WpaSupplicant:
             if field in params:
                 self.set_cred_quoted(id, field, params[field])
 
-        not_quoted = ["eap", "roaming_consortium", "priority",
-                      "required_roaming_consortium", "sp_priority",
-                      "max_bss_load", "update_identifier", "req_conn_capab",
+        not_quoted = ["eap", "priority", "sp_priority", "max_bss_load",
+                      "update_identifier", "req_conn_capab",
                       "min_dl_bandwidth_home", "min_ul_bandwidth_home",
                       "min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming"]
         for field in not_quoted:
             if field in params:
                 self.set_cred(id, field, params[field])
 
+        as_list = ["home_ois", "required_home_ois"]
+        for field in as_list:
+            if field in params:
+                self.set_cred_quoted(id, field, ','.join(params[field]))
+
         return id
 
     def select_network(self, id, freq=None):
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a91c689d0..c1dd66bcf 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3531,53 +3531,61 @@ static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred,
 }
 
 
-static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred,
-						   const char *value)
-{
-	u8 roaming_consortiums[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
-	size_t roaming_consortiums_len[MAX_ROAMING_CONS];
-	unsigned int num_roaming_consortiums = 0;
+static int wpa_config_set_cred_ois(u8 cred_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN],
+				   size_t cred_ois_len[MAX_ROAMING_CONS],
+				   unsigned int *cred_num_ois,
+				   const char *value)
+{
+	u8 ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+	size_t ois_len[MAX_ROAMING_CONS];
+	unsigned int num_ois = 0;
 	const char *pos, *end;
 	size_t len;
 
-	os_memset(roaming_consortiums, 0, sizeof(roaming_consortiums));
-	os_memset(roaming_consortiums_len, 0, sizeof(roaming_consortiums_len));
+	len = os_strlen(value);
+	if (len / 2 < 3) {
+		wpa_printf(MSG_ERROR,
+			   "Invalid organisation identifier (OI) list: %s",
+			   value);
+		return -1;
+	}
+
+	os_memset(ois, 0, sizeof(ois));
+	os_memset(ois_len, 0, sizeof(ois_len));
 
 	for (pos = value;;) {
 		end = os_strchr(pos, ',');
 		len = end ? (size_t) (end - pos) : os_strlen(pos);
 		if (!end && len == 0)
 			break;
-		if (len == 0 || (len & 1) != 0 ||
+		if (len / 2 < 3 || (len & 1) != 0 ||
 		    len / 2 > MAX_ROAMING_CONS_OI_LEN ||
 		    hexstr2bin(pos,
-			       roaming_consortiums[num_roaming_consortiums],
+			       ois[num_ois],
 			       len / 2) < 0) {
-			wpa_printf(MSG_INFO,
-				   "Invalid roaming_consortiums entry: %s",
+			wpa_printf(MSG_ERROR,
+				   "Invalid organisation identifier (OI) entry: %s",
 				   pos);
 			return -1;
 		}
-		roaming_consortiums_len[num_roaming_consortiums] = len / 2;
-		num_roaming_consortiums++;
+		ois_len[num_ois] = len / 2;
+		num_ois++;
 
 		if (!end)
 			break;
 
-		if (num_roaming_consortiums >= MAX_ROAMING_CONS) {
+		if (num_ois >= MAX_ROAMING_CONS) {
 			wpa_printf(MSG_INFO,
-				   "Too many roaming_consortiums OIs");
+				   "Too many OIs");
 			return -1;
 		}
 
 		pos = end + 1;
 	}
 
-	os_memcpy(cred->roaming_consortiums, roaming_consortiums,
-		  sizeof(roaming_consortiums));
-	os_memcpy(cred->roaming_consortiums_len, roaming_consortiums_len,
-		  sizeof(roaming_consortiums_len));
-	cred->num_roaming_consortiums = num_roaming_consortiums;
+	os_memcpy(cred_ois, ois, sizeof(ois));
+	os_memcpy(cred_ois_len, ois_len, sizeof(ois_len));
+	*cred_num_ois = num_ois;
 
 	return 0;
 }
@@ -3812,21 +3820,25 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 	}
 
 	if (os_strcmp(var, "roaming_consortium") == 0) {
-		if (len < 3 || len > sizeof(cred->roaming_consortium)) {
+		if (len < 3 || len > sizeof(cred->home_ois[0])) {
 			wpa_printf(MSG_ERROR, "Line %d: invalid "
 				   "roaming_consortium length %d (3..15 "
 				   "expected)", line, (int) len);
 			os_free(val);
 			return -1;
 		}
-		os_memcpy(cred->roaming_consortium, val, len);
-		cred->roaming_consortium_len = len;
+		wpa_printf(MSG_WARNING, "Line %d: option roaming_consortium is "
+			   "deprecated and will be removed in the future",
+			   line);
+		os_memcpy(cred->home_ois[0], val, len);
+		cred->home_ois_len[0] = len;
+		cred->num_home_ois = 1;
 		os_free(val);
 		return 0;
 	}
 
 	if (os_strcmp(var, "required_roaming_consortium") == 0) {
-		if (len < 3 || len > sizeof(cred->required_roaming_consortium))
+		if (len < 3 || len > sizeof(cred->required_home_ois[0]))
 		{
 			wpa_printf(MSG_ERROR, "Line %d: invalid "
 				   "required_roaming_consortium length %d "
@@ -3834,14 +3846,48 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 			os_free(val);
 			return -1;
 		}
-		os_memcpy(cred->required_roaming_consortium, val, len);
-		cred->required_roaming_consortium_len = len;
+		wpa_printf(MSG_WARNING,
+			   "Line %d: option required_roaming_consortium is "
+			   "deprecated and will be removed in the future",
+			   line);
+		os_memcpy(cred->required_home_ois[0], val, len);
+		cred->required_home_ois_len[0] = len;
+		cred->num_required_home_ois = 1;
 		os_free(val);
 		return 0;
 	}
 
+	if (os_strcmp(var, "home_ois") == 0) {
+		res = wpa_config_set_cred_ois(cred->home_ois,
+					      cred->home_ois_len,
+					      &cred->num_home_ois,
+					      val);
+		if (res < 0)
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid home_ois",
+				   line);
+		os_free(val);
+		return res;
+	}
+
+	if (os_strcmp(var, "required_home_ois") == 0) {
+		res = wpa_config_set_cred_ois(cred->required_home_ois,
+					      cred->required_home_ois_len,
+					      &cred->num_required_home_ois,
+					      val);
+		if (res < 0)
+			wpa_printf(MSG_ERROR,
+				   "Line %d: invalid required_home_ois",
+				   line);
+		os_free(val);
+		return res;
+	}
+
 	if (os_strcmp(var, "roaming_consortiums") == 0) {
-		res = wpa_config_set_cred_roaming_consortiums(cred, val);
+		res = wpa_config_set_cred_ois(cred->roaming_consortiums,
+					      cred->roaming_consortiums_len,
+					      &cred->num_roaming_consortiums,
+					      val);
 		if (res < 0)
 			wpa_printf(MSG_ERROR,
 				   "Line %d: invalid roaming_consortiums",
@@ -4153,14 +4199,14 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
 		size_t buflen;
 		char *buf;
 
-		if (!cred->roaming_consortium_len)
+		if (!cred->num_home_ois || !cred->home_ois_len[0])
 			return NULL;
-		buflen = cred->roaming_consortium_len * 2 + 1;
+		buflen = cred->home_ois_len[0] * 2 + 1;
 		buf = os_malloc(buflen);
 		if (buf == NULL)
 			return NULL;
-		wpa_snprintf_hex(buf, buflen, cred->roaming_consortium,
-				 cred->roaming_consortium_len);
+		wpa_snprintf_hex(buf, buflen, cred->home_ois[0],
+				 cred->home_ois_len[0]);
 		return buf;
 	}
 
@@ -4168,14 +4214,65 @@ char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var)
 		size_t buflen;
 		char *buf;
 
-		if (!cred->required_roaming_consortium_len)
+		if (!cred->num_required_home_ois ||
+                    !cred->required_home_ois_len[0])
 			return NULL;
-		buflen = cred->required_roaming_consortium_len * 2 + 1;
+		buflen = cred->required_home_ois_len[0] * 2 + 1;
 		buf = os_malloc(buflen);
 		if (buf == NULL)
 			return NULL;
-		wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium,
-				 cred->required_roaming_consortium_len);
+		wpa_snprintf_hex(buf, buflen, cred->required_home_ois[0],
+				 cred->required_home_ois_len[0]);
+		return buf;
+	}
+
+	if (os_strcmp(var, "home_ois") == 0) {
+		size_t buflen;
+		char *buf, *pos;
+		size_t i;
+
+		if (!cred->num_home_ois)
+			return NULL;
+		buflen = cred->num_home_ois *
+			MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+		buf = os_malloc(buflen);
+		if (!buf)
+			return NULL;
+		pos = buf;
+		for (i = 0; i < cred->num_home_ois; i++) {
+			if (i > 0)
+				*pos++ = ',';
+			pos += wpa_snprintf_hex(
+				pos, buf + buflen - pos,
+				cred->home_ois[i],
+				cred->home_ois_len[i]);
+		}
+		*pos = '\0';
+		return buf;
+	}
+
+	if (os_strcmp(var, "required_home_ois") == 0) {
+		size_t buflen;
+		char *buf, *pos;
+		size_t i;
+
+		if (!cred->num_required_home_ois)
+			return NULL;
+		buflen = cred->num_required_home_ois *
+			MAX_ROAMING_CONS_OI_LEN * 2 + 1;
+		buf = os_malloc(buflen);
+		if (!buf)
+			return NULL;
+		pos = buf;
+		for (i = 0; i < cred->num_required_home_ois; i++) {
+			if (i > 0)
+				*pos++ = ',';
+			pos += wpa_snprintf_hex(
+				pos, buf + buflen - pos,
+				cred->required_home_ois[i],
+				cred->required_home_ois_len[i]);
+		}
+		*pos = '\0';
 		return buf;
 	}
 
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 8b8be2a45..d509074be 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -259,36 +259,50 @@ struct wpa_cred {
 	size_t num_domain;
 
 	/**
-	 * roaming_consortium - Roaming Consortium OI
+	 * home_ois - Home OIs
 	 *
-	 * If roaming_consortium_len is non-zero, this field contains the
-	 * Roaming Consortium OI that can be used to determine which access
-	 * points support authentication with this credential. This is an
-	 * alternative to the use of the realm parameter. When using Roaming
-	 * Consortium to match the network, the EAP parameters need to be
-	 * pre-configured with the credential since the NAI Realm information
-	 * may not be available or fetched.
+	 * If num_home_ois is non-zero, this field contains the set of Home OIs
+	 * that can be use to determine which access points support
+	 * authentication with this credential. There are an alternative to the
+	 * use of the realm parameter. When using Home OIs to match the network,
+	 * the EAP parameters need to be pre-configured with the credentials
+	 * since the NAI Realm information may not be available or fetched.
+	 * A successful authentication with the access point is possible as soon
+	 * as at least one Home OI from the list matches an OI in the Roaming
+	 * Consortium advertised by the access point.
+	 * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOI)
 	 */
-	u8 roaming_consortium[15];
+	u8 home_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
 
 	/**
-	 * roaming_consortium_len - Length of roaming_consortium
+	 * home_ois_len - Length of home_ois[i]
 	 */
-	size_t roaming_consortium_len;
+	size_t home_ois_len[MAX_ROAMING_CONS];
 
 	/**
-	 * required_roaming_consortium - Required Roaming Consortium OI
+	 * num_home_ois - Number of entries in home_ois
+	 */
+	unsigned int num_home_ois;
+
+	/**
+	 * required_home_ois - Required Home OI(s)
 	 *
-	 * If required_roaming_consortium_len is non-zero, this field contains
-	 * the Roaming Consortium OI that is required to be advertised by the AP
-	 * for the credential to be considered matching.
+	 * If required_home_ois_len is non-zero, this field contains the set of
+	 * Home OI(s) that are required to be advertised by the AP for the
+	 * credential to be considered matching.
+	 * (Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOIRequired)
+	 */
+	u8 required_home_ois[MAX_ROAMING_CONS][MAX_ROAMING_CONS_OI_LEN];
+
+	/**
+	 * required_home_ois_len - Length of required_home_ois
 	 */
-	u8 required_roaming_consortium[15];
+	size_t required_home_ois_len[MAX_ROAMING_CONS];
 
 	/**
-	 * required_roaming_consortium_len - Length of required_roaming_consortium
+	 * num_required_home_ois - Number of entries in required_home_ois
 	 */
-	size_t required_roaming_consortium_len;
+	unsigned int num_required_home_ois;
 
 	/**
 	 * roaming_consortiums - Roaming Consortium OI(s) memberships
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index b637dbfbc..51b8d05f8 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -921,12 +921,6 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
 	if (cred->domain_suffix_match)
 		fprintf(f, "\tdomain_suffix_match=\"%s\"\n",
 			cred->domain_suffix_match);
-	if (cred->roaming_consortium_len) {
-		fprintf(f, "\troaming_consortium=");
-		for (i = 0; i < cred->roaming_consortium_len; i++)
-			fprintf(f, "%02x", cred->roaming_consortium[i]);
-		fprintf(f, "\n");
-	}
 	if (cred->eap_method) {
 		const char *name;
 		name = eap_get_name(cred->eap_method[0].vendor,
@@ -1002,12 +996,32 @@ static void wpa_config_write_cred(FILE *f, struct wpa_cred *cred)
 		}
 	}
 
-	if (cred->required_roaming_consortium_len) {
-		fprintf(f, "\trequired_roaming_consortium=");
-		for (i = 0; i < cred->required_roaming_consortium_len; i++)
-			fprintf(f, "%02x",
-				cred->required_roaming_consortium[i]);
-		fprintf(f, "\n");
+	if (cred->num_home_ois) {
+		size_t j;
+
+		fprintf(f, "\thome_ois=\"");
+		for (i = 0; i < cred->num_home_ois; i++) {
+			if (i > 0)
+				fprintf(f, ",");
+			for (j = 0; j < cred->home_ois_len[i]; j++)
+				fprintf(f, "%02x",
+					cred->home_ois[i][j]);
+		}
+		fprintf(f, "\"\n");
+	}
+
+	if (cred->num_required_home_ois) {
+		size_t j;
+
+		fprintf(f, "\trequired_home_ois=\"");
+		for (i = 0; i < cred->num_required_home_ois; i++) {
+			if (i > 0)
+				fprintf(f, ",");
+			for (j = 0; j < cred->required_home_ois_len[i]; j++)
+				fprintf(f, "%02x",
+					cred->required_home_ois[i][j]);
+		}
+		fprintf(f, "\"\n");
 	}
 
 	if (cred->num_roaming_consortiums) {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index bc81728ad..ff4c54aea 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -144,9 +144,9 @@ static int cred_with_roaming_consortium(struct wpa_supplicant *wpa_s)
 	struct wpa_cred *cred;
 
 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-		if (cred->roaming_consortium_len)
+		if (cred->num_home_ois)
 			return 1;
-		if (cred->required_roaming_consortium_len)
+		if (cred->num_required_home_ois)
 			return 1;
 		if (cred->num_roaming_consortiums)
 			return 1;
@@ -1092,8 +1092,7 @@ fail:
 }
 
 
-static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
-					    size_t rc_len)
+static int oi_element_match(const u8 *ie, const u8 *oi, size_t oi_len)
 {
 	const u8 *pos, *end;
 	u8 lens;
@@ -1118,24 +1117,24 @@ static int roaming_consortium_element_match(const u8 *ie, const u8 *rc_id,
 	if ((lens & 0x0f) + (lens >> 4) > end - pos)
 		return 0;
 
-	if ((lens & 0x0f) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+	if ((lens & 0x0f) == oi_len && os_memcmp(pos, oi, oi_len) == 0)
 		return 1;
 	pos += lens & 0x0f;
 
-	if ((lens >> 4) == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+	if ((lens >> 4) == oi_len && os_memcmp(pos, oi, oi_len) == 0)
 		return 1;
 	pos += lens >> 4;
 
-	if (pos < end && (size_t) (end - pos) == rc_len &&
-	    os_memcmp(pos, rc_id, rc_len) == 0)
+	if (pos < end && (size_t) (end - pos) == oi_len &&
+	    os_memcmp(pos, oi, oi_len) == 0)
 		return 1;
 
 	return 0;
 }
 
 
-static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
-					 const u8 *rc_id, size_t rc_len)
+static int oi_anqp_match(const struct wpabuf *anqp, const u8 *oi,
+			 size_t oi_len)
 {
 	const u8 *pos, *end;
 	u8 len;
@@ -1151,7 +1150,7 @@ static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
 		len = *pos++;
 		if (len > end - pos)
 			break;
-		if (len == rc_len && os_memcmp(pos, rc_id, rc_len) == 0)
+		if (len == oi_len && os_memcmp(pos, oi, oi_len) == 0)
 			return 1;
 		pos += len;
 	}
@@ -1160,13 +1159,26 @@ static int roaming_consortium_anqp_match(const struct wpabuf *anqp,
 }
 
 
-static int roaming_consortium_match(const u8 *ie, const struct wpabuf *anqp,
-				    const u8 *rc_id, size_t rc_len)
+static int oi_match(const u8 *ie, const struct wpabuf *anqp,
+		    const u8 *oi, size_t oi_len)
 {
-	return roaming_consortium_element_match(ie, rc_id, rc_len) ||
-		roaming_consortium_anqp_match(anqp, rc_id, rc_len);
+	return oi_element_match(ie, oi, oi_len) ||
+		oi_anqp_match(anqp, oi, oi_len);
 }
 
+static int cred_home_ois_match(const u8 *ie, const struct wpabuf *anqp,
+			       const struct wpa_cred *cred) {
+	unsigned int i;
+
+	// There's a match if at least one of the home OI matches.
+	for (i = 0; i < cred->num_home_ois; i++) {
+		if (oi_match(ie, anqp, cred->home_ois[i],
+			     cred->home_ois_len[i]))
+			return 1;
+	}
+
+	return 0;
+}
 
 static int cred_roaming_consortiums_match(const u8 *ie,
 					  const struct wpabuf *anqp,
@@ -1175,9 +1187,8 @@ static int cred_roaming_consortiums_match(const u8 *ie,
 	unsigned int i;
 
 	for (i = 0; i < cred->num_roaming_consortiums; i++) {
-		if (roaming_consortium_match(ie, anqp,
-					     cred->roaming_consortiums[i],
-					     cred->roaming_consortiums_len[i]))
+		if (oi_match(ie, anqp, cred->roaming_consortiums[i],
+			     cred->roaming_consortiums_len[i]))
 			return 1;
 	}
 
@@ -1188,8 +1199,9 @@ static int cred_roaming_consortiums_match(const u8 *ie,
 static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
 {
 	const u8 *ie;
+	unsigned int i;
 
-	if (cred->required_roaming_consortium_len == 0)
+	if (cred->num_required_home_ois == 0)
 		return 0;
 
 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
@@ -1198,11 +1210,16 @@ static int cred_no_required_oi_match(struct wpa_cred *cred, struct wpa_bss *bss)
 	    (bss->anqp == NULL || bss->anqp->roaming_consortium == NULL))
 		return 1;
 
-	return !roaming_consortium_match(ie,
-					 bss->anqp ?
-					 bss->anqp->roaming_consortium : NULL,
-					 cred->required_roaming_consortium,
-					 cred->required_roaming_consortium_len);
+	// According to Passpoint specification, there must be a match for
+	// each required home OI provided.
+	for (i = 0; i < cred->num_required_home_ois; i++) {
+		if (!oi_match(ie, bss->anqp ?
+			      bss->anqp->roaming_consortium : NULL,
+			      cred->required_home_ois[i],
+			      cred->required_home_ois_len[i]))
+			return 1;
+	}
+	return 0;
 }
 
 
@@ -1402,26 +1419,24 @@ static struct wpa_cred * interworking_credentials_available_roaming_consortium(
 		return NULL;
 
 	for (cred = wpa_s->conf->cred; cred; cred = cred->next) {
-		if (cred->roaming_consortium_len == 0 &&
+		if (cred->num_home_ois == 0 &&
+		    cred->num_required_home_ois == 0 &&
 		    cred->num_roaming_consortiums == 0)
 			continue;
 
 		if (!cred->eap_method)
 			continue;
 
-		if ((cred->roaming_consortium_len == 0 ||
-		     !roaming_consortium_match(ie, anqp,
-					       cred->roaming_consortium,
-					       cred->roaming_consortium_len)) &&
-		    !cred_roaming_consortiums_match(ie, anqp, cred) &&
-		    (cred->required_roaming_consortium_len == 0 ||
-		     !roaming_consortium_match(
-			     ie, anqp, cred->required_roaming_consortium,
-			     cred->required_roaming_consortium_len)))
+		// If there's required home OIs, there must be a match for each
+		// required OI (see Passpoint v3.2 - 9.1.2 - RequiredHomeOI).
+		if (cred->num_required_home_ois > 0 &&
+		    cred_no_required_oi_match(cred, bss))
 			continue;
 
-		if (cred_no_required_oi_match(cred, bss))
+		if (!cred_home_ois_match(ie, anqp, cred) &&
+		    !cred_roaming_consortiums_match(ie, anqp, cred))
 			continue;
+
 		if (!ignore_bw && cred_below_min_backhaul(wpa_s, cred, bss))
 			continue;
 		if (!ignore_bw && cred_over_max_bss_load(wpa_s, cred, bss))
@@ -1636,9 +1651,8 @@ static int interworking_connect_roaming_consortium(
 	ie = wpa_bss_get_ie(bss, WLAN_EID_ROAMING_CONSORTIUM);
 	anqp = bss->anqp ? bss->anqp->roaming_consortium : NULL;
 	for (i = 0; (ie || anqp) && i < cred->num_roaming_consortiums; i++) {
-		if (!roaming_consortium_match(
-			    ie, anqp, cred->roaming_consortiums[i],
-			    cred->roaming_consortiums_len[i]))
+		if (!oi_match(ie, anqp, cred->roaming_consortiums[i],
+			      cred->roaming_consortiums_len[i]))
 			continue;
 
 		ssid->roaming_consortium_selection =
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 90061ba67..d0c28c025 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -655,7 +655,26 @@ fast_reauth=1
 #	be used to configure alternative FQDNs that will be considered home
 #	networks.
 #
+# home_ois: Home OI(s)
+#	This string field contains one or more comma delimited OIs (hexdump)
+#	identifying the access the access points that support authentication
+#	with this credential. There are an alternative to the use of the realm
+#	parameter. When using Home OIs to match the network, the EAP parameters
+#	need to be pre-configured with the credentials since the NAI Realm
+#	information may not be available or fetched.
+#	A successful authentication with the access point is possible as soon
+#	as at least one Home OI from the list matches an OI in the Roaming
+#	Consortium advertised by the access point.
+#	(Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOI)
+#
+# required_home_ois: Required Home OI(s)
+#	This string field contains the set of Home OI(s) (hexdump) that are
+#	required to be advertised by the AP for the credential to be considered
+#	matching.
+#	(Hotspot 2.0 PerProviderSubscription/<X+>/HomeSP/HomeOIList/<X+>/HomeOIRequired)
+#
 # roaming_consortium: Roaming Consortium OI
+#	Deprecated: use home_ois instead.
 #	If roaming_consortium_len is non-zero, this field contains the
 #	Roaming Consortium OI that can be used to determine which access
 #	points support authentication with this credential. This is an
@@ -665,6 +684,7 @@ fast_reauth=1
 #	may not be available or fetched.
 #
 # required_roaming_consortium: Required Roaming Consortium OI
+#	Deprecated: use required_home_ois instead.
 #	If required_roaming_consortium_len is non-zero, this field contains the
 #	Roaming Consortium OI that is required to be advertised by the AP for
 #	the credential to be considered matching.
