diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index bf97de698..c5f1a126b 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2855,6 +2855,10 @@ void wpa_config_free_cred(struct wpa_cred *cred)
 	os_free(cred->client_cert);
 	os_free(cred->private_key);
 	str_clear_free(cred->private_key_passwd);
+	os_free(cred->engine_id);
+	os_free(cred->ca_cert_id);
+	os_free(cred->cert_id);
+	os_free(cred->key_id);
 	os_free(cred->imsi);
 	str_clear_free(cred->milenage);
 	for (i = 0; i < cred->num_domain; i++)
@@ -3618,6 +3622,11 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 		return 0;
 	}
 
+	if (os_strcmp(var, "engine") == 0) {
+		cred->engine = atoi(value);
+		return 0;
+	}
+
 	val = wpa_config_parse_string(value, &len);
 	if (val == NULL ||
 	    (os_strcmp(var, "excluded_ssid") != 0 &&
@@ -3673,6 +3682,30 @@ int wpa_config_set_cred(struct wpa_cred *cred, const char *var,
 		return 0;
 	}
 
+	if (os_strcmp(var, "engine_id") == 0) {
+		os_free(cred->engine_id);
+		cred->engine_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "ca_cert_id") == 0) {
+		os_free(cred->ca_cert_id);
+		cred->ca_cert_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "cert_id") == 0) {
+		os_free(cred->cert_id);
+		cred->cert_id = val;
+		return 0;
+	}
+
+	if (os_strcmp(var, "key_id") == 0) {
+		os_free(cred->key_id);
+		cred->key_id = val;
+		return 0;
+	}
+
 	if (os_strcmp(var, "imsi") == 0) {
 		os_free(cred->imsi);
 		cred->imsi = val;
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 0320d9eeb..c7a55202b 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -179,6 +179,31 @@ struct wpa_cred {
 	 */
 	char *milenage;
 
+	/**
+	 * engine - Use an engine for private key operations.
+	 */
+	int engine;
+
+	/**
+	 * engine_id - String identifying the engine to use.
+	 */
+	char *engine_id;
+
+	/**
+	 * ca_cert_id - The CA certificate identifier when using an engine.
+	 */
+	char *ca_cert_id;
+
+	/**
+	 * cert_id - The certificate identifier when using an engine.
+	 */
+	char *cert_id;
+
+	/**
+	 * key_id - The private key identifier when using an engine.
+	 */
+	char *key_id;
+
 	/**
 	 * domain_suffix_match - Constraint for server domain name
 	 *
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 1c82d2117..066e344a0 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -702,12 +702,15 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
 	    ((cred->password == NULL ||
 	      cred->password[0] == '\0') &&
 	     (cred->private_key == NULL ||
-	      cred->private_key[0] == '\0'))) {
+	      cred->private_key[0] == '\0') &&
+	     (cred->key_id == NULL ||
+	      cred->key_id[0] == '\0'))) {
 		wpa_msg(wpa_s, MSG_DEBUG,
-			"nai-realm-find-eap: incomplete cred info: username: %s  password: %s private_key: %s",
+			"nai-realm-find-eap: incomplete cred info: username: %s  password: %s private_key: %s key_id: %s",
 			cred->username ? cred->username : "NULL",
 			cred->password ? cred->password : "NULL",
-			cred->private_key ? cred->private_key : "NULL");
+			cred->private_key ? cred->private_key : "NULL",
+			cred->key_id ? cred->private_key : "NULL");
 		return NULL;
 	}
 
@@ -716,7 +719,8 @@ static struct nai_realm_eap * nai_realm_find_eap(struct wpa_supplicant *wpa_s,
 		if (cred->password && cred->password[0] &&
 		    nai_realm_cred_username(wpa_s, eap))
 			return eap;
-		if (cred->private_key && cred->private_key[0] &&
+		if (((cred->private_key && cred->private_key[0]) ||
+		     (cred->key_id && cred->key_id[0])) &&
 		    nai_realm_cred_cert(wpa_s, eap))
 			return eap;
 	}
@@ -1539,6 +1543,24 @@ static int interworking_set_eap_params(struct wpa_ssid *ssid,
 				  cred->private_key_passwd) < 0)
 		return -1;
 
+	if (cred->ca_cert_id && cred->ca_cert_id[0] &&
+	    wpa_config_set_quoted(ssid, "ca_cert_id", cred->ca_cert_id) < 0)
+		return -1;
+
+	if (cred->cert_id && cred->cert_id[0] &&
+	    wpa_config_set_quoted(ssid, "cert_id", cred->cert_id) < 0)
+		return -1;
+
+	if (cred->key_id && cred->key_id[0] &&
+	    wpa_config_set_quoted(ssid, "key_id", cred->key_id) < 0)
+		return -1;
+
+	if (cred->engine_id && cred->engine_id[0] &&
+	    wpa_config_set_quoted(ssid, "engine_id", cred->engine_id) < 0)
+		return -1;
+
+	ssid->eap.cert.engine = cred->engine;
+
 	if (cred->phase1) {
 		os_free(ssid->eap.phase1);
 		ssid->eap.phase1 = os_strdup(cred->phase1);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index b72983e9c..17b14c824 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1591,6 +1591,7 @@ static const char * const cred_fields[] = {
 	"min_dl_bandwidth_roaming", "min_ul_bandwidth_roaming", "max_bss_load",
 	"req_conn_capab", "ocsp", "sim_num", "realm", "username", "password",
 	"ca_cert", "client_cert", "private_key", "private_key_passwd", "imsi",
+	"ca_cert_id", "cert_id", "key_id", "engine_id", "engine",
 	"milenage", "domain_suffix_match", "domain", "phase1", "phase2",
 	"roaming_consortium", "required_roaming_consortium", "excluded_ssid",
 	"roaming_partner", "provisioning_sp"
