diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 413cccddc..59be04c25 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -367,15 +367,21 @@ int __must_check tls_connection_get_random(void *tls_ctx,
  * @tls_ctx: TLS context data from tls_init()
  * @conn: Connection context data from tls_connection_init()
  * @label: Label (e.g., description of the key) for PRF
+ * @context: optional extra upper-layer context (max len 2^16)
+ * @context_len: the length of the context value
  * @out: Buffer for output data from TLS-PRF
  * @out_len: Length of the output buffer
  * Returns: 0 on success, -1 on failure
  *
  * Exports keying material using the mechanism described in RFC 5705.
+ *
+ * Note: to provide the RFC5705 context, the context variable must be non-null.
  */
 int __must_check tls_connection_export_key(void *tls_ctx,
 					   struct tls_connection *conn,
 					   const char *label,
+					   const unsigned char *context,
+					   size_t context_len,
 					   u8 *out, size_t out_len);
 
 /**
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 527d01ecf..0a4ac5995 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -895,14 +895,14 @@ int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
 
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
-			      const char *label, u8 *out, size_t out_len)
+			      const char *label, const unsigned char *context,
+			      size_t context_len, u8 *out, size_t out_len)
 {
 	if (conn == NULL || conn->session == NULL)
 		return -1;
 
-	return gnutls_prf(conn->session, os_strlen(label), label,
-			  0 /* client_random first */, 0, NULL, out_len,
-			  (char *) out);
+	return gnutls_prf_rfc5705(conn->session, os_strlen(label), label,
+				  context_len, context, out_len, (char *) out);
 }
 
 
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index 57b3e632d..a0eea83f8 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -449,8 +449,11 @@ static int tls_connection_prf(void *tls_ctx, struct tls_connection *conn,
 
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
-			      const char *label, u8 *out, size_t out_len)
+			      const char *label, const unsigned char *context,
+			      size_t context_len, u8 *out, size_t out_len)
 {
+	if (context != NULL)
+		return -1; // Not implemented yet
 	return tls_connection_prf(tls_ctx, conn, label, 0, 0, out, out_len);
 }
 
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index 108e9aa2e..d55431e02 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -94,7 +94,8 @@ int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
 
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
-			      const char *label, u8 *out, size_t out_len)
+			      const char *label, const unsigned char *context,
+			      size_t context_len, u8 *out, size_t out_len)
 {
 	return -1;
 }
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 18d76737e..4393abf71 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -3669,11 +3669,13 @@ static int openssl_get_keyblock_size(SSL *ssl)
 
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
-			      const char *label, u8 *out, size_t out_len)
+			      const char *label, const unsigned char *context,
+			      size_t context_len, u8 *out, size_t out_len)
 {
 	if (!conn ||
 	    SSL_export_keying_material(conn->ssl, out, out_len, label,
-				       os_strlen(label), NULL, 0, 0) != 1)
+				       os_strlen(label), context, context_len,
+                                       (context != NULL)) != 1)
 		return -1;
 	return 0;
 }
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c
index b59622e5e..9aa3840e2 100644
--- a/src/crypto/tls_wolfssl.c
+++ b/src/crypto/tls_wolfssl.c
@@ -1970,8 +1970,11 @@ int tls_connection_get_random(void *ssl_ctx, struct tls_connection *conn,
 
 
 int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
-			      const char *label, u8 *out, size_t out_len)
+			      const char *label, const unsigned char *context,
+			      size_t context_len, u8 *out, size_t out_len)
 {
+	if (context != NULL)
+		return -1; // Not implemented in WolfSSL yet
 	if (!conn || wolfSSL_make_eap_keys(conn->ssl, out, out_len, label) != 0)
 		return -1;
 	return 0;
diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c
index 650bea6ad..8dcf7cc29 100644
--- a/src/eap_peer/eap_peap.c
+++ b/src/eap_peer/eap_peap.c
@@ -1084,6 +1084,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
 				   "key derivation", label);
 			data->key_data =
 				eap_peer_tls_derive_key(sm, &data->ssl, label,
+							NULL, 0,
 							EAP_TLS_KEY_LEN +
 							EAP_EMSK_LEN);
 			if (data->key_data) {
diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c
index cb747026c..ffea9d213 100644
--- a/src/eap_peer/eap_tls.c
+++ b/src/eap_peer/eap_tls.c
@@ -198,6 +198,7 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
 
 	eap_tls_free_key(data);
 	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label,
+						 NULL, 0,
 						 EAP_TLS_KEY_LEN +
 						 EAP_EMSK_LEN);
 	if (data->key_data) {
diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c
index 7dbd364a5..99893c5f5 100644
--- a/src/eap_peer/eap_tls_common.c
+++ b/src/eap_peer/eap_tls_common.c
@@ -347,6 +347,8 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
  * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
  * @data: Data for TLS processing
  * @label: Label string for deriving the keys, e.g., "client EAP encryption"
+ * @context: optional extra upper-layer context (max len 2^16)
+ * @context_len: the length of the context value
  * @len: Length of the key material to generate (usually 64 for MSK)
  * Returns: Pointer to allocated key on success or %NULL on failure
  *
@@ -355,9 +357,12 @@ void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
  * different label to bind the key usage into the generated material.
  *
  * The caller is responsible for freeing the returned buffer.
+ * 
+ * Note: to provide the RFC5705 context, the context variable must be non-null.
  */
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			     const char *label, size_t len)
+			     const char *label, const unsigned char *context,
+			     size_t context_len, size_t len)
 {
 	u8 *out;
 
@@ -365,8 +370,8 @@ u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 	if (out == NULL)
 		return NULL;
 
-	if (tls_connection_export_key(data->ssl_ctx, data->conn, label, out,
-				      len)) {
+	if (tls_connection_export_key(data->ssl_ctx, data->conn, label,
+                                      context, context_len, out, len)) {
 		os_free(out);
 		return NULL;
 	}
@@ -407,7 +412,7 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
 		if (!id)
 			return NULL;
 		method_id = eap_peer_tls_derive_key(
-			sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+			sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
 		if (!method_id) {
 			os_free(id);
 			return NULL;
diff --git a/src/eap_peer/eap_tls_common.h b/src/eap_peer/eap_tls_common.h
index 306e6a98b..cd2f629d9 100644
--- a/src/eap_peer/eap_tls_common.h
+++ b/src/eap_peer/eap_tls_common.h
@@ -99,7 +99,8 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			  struct eap_peer_config *config, u8 eap_type);
 void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			     const char *label, size_t len);
+			     const char *label, const unsigned char *context,
+                	     size_t context_len, size_t len);
 u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
 				    struct eap_ssl_data *data, u8 eap_type,
 				    size_t *len);
diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c
index 5d267010e..687c4b089 100644
--- a/src/eap_peer/eap_ttls.c
+++ b/src/eap_peer/eap_ttls.c
@@ -271,6 +271,7 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
 	eap_ttls_free_key(data);
 	data->key_data = eap_peer_tls_derive_key(sm, &data->ssl,
 						 "ttls keying material",
+						 NULL, 0,
 						 EAP_TLS_KEY_LEN +
 						 EAP_EMSK_LEN);
 	if (!data->key_data) {
@@ -303,7 +304,8 @@ static int eap_ttls_v0_derive_key(struct eap_sm *sm,
 static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
 					struct eap_ttls_data *data, size_t len)
 {
-	return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", len);
+	return eap_peer_tls_derive_key(sm, &data->ssl, "ttls challenge", 
+				       NULL, 0, len);
 }
 #endif /* CONFIG_FIPS */
 
diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c
index 3d334a0db..92c0e5ec9 100644
--- a/src/eap_server/eap_server_peap.c
+++ b/src/eap_server/eap_server_peap.c
@@ -331,7 +331,7 @@ static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
 	 * phase 1 of PEAP (based on TLS).
 	 */
 	tk = eap_server_tls_derive_key(sm, &data->ssl, "client EAP encryption",
-				       EAP_TLS_KEY_LEN);
+				       NULL, 0, EAP_TLS_KEY_LEN);
 	if (tk == NULL)
 		return -1;
 	wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
@@ -1333,7 +1333,7 @@ static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
 
 	/* TODO: PEAPv1 - different label in some cases */
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-					       "client EAP encryption",
+					       "client EAP encryption", NULL, 0,
 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		os_memset(eapKeyData + EAP_TLS_KEY_LEN, 0, EAP_EMSK_LEN);
@@ -1363,7 +1363,7 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 
 	/* TODO: PEAPv1 - different label in some cases */
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-					       "client EAP encryption",
+					       "client EAP encryption", NULL, 0,
 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		emsk = os_memdup(eapKeyData + EAP_TLS_KEY_LEN, EAP_EMSK_LEN);
diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c
index 13d234982..357e72a82 100644
--- a/src/eap_server/eap_server_tls.c
+++ b/src/eap_server/eap_server_tls.c
@@ -331,6 +331,7 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
 	else
 		label = "client EAP encryption";
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
+					       NULL, 0,
 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		*len = EAP_TLS_KEY_LEN;
@@ -359,6 +360,7 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 	else
 		label = "client EAP encryption";
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
+					       NULL, 0,
 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		emsk = os_malloc(EAP_EMSK_LEN);
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 4ba7c2499..4b847be7e 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -107,7 +107,8 @@ void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data)
 
 
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			       const char *label, size_t len)
+			       const char *label, const unsigned char *context,
+                               size_t context_len, size_t len)
 {
 	u8 *out;
 
@@ -115,8 +116,8 @@ u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
 	if (out == NULL)
 		return NULL;
 
-	if (tls_connection_export_key(sm->ssl_ctx, data->conn, label, out,
-				      len)) {
+	if (tls_connection_export_key(sm->ssl_ctx, data->conn, label,
+                                      context, context_len, out, len)) {
 		os_free(out);
 		return NULL;
 	}
@@ -157,7 +158,7 @@ u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
 		if (!id)
 			return NULL;
 		method_id = eap_server_tls_derive_key(
-			sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+			sm, data, "EXPORTER_EAP_TLS_Method-Id", NULL, 0, 64);
 		if (!method_id) {
 			os_free(id);
 			return NULL;
diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c
index b14996b0b..52bff8afe 100644
--- a/src/eap_server/eap_server_ttls.c
+++ b/src/eap_server/eap_server_ttls.c
@@ -332,7 +332,7 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
 					struct eap_ttls_data *data, size_t len)
 {
 	return eap_server_tls_derive_key(sm, &data->ssl, "ttls challenge",
-					 len);
+					 NULL, 0, len);
 }
 
 
@@ -1268,7 +1268,7 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len)
 		return NULL;
 
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-					       "ttls keying material",
+					       "ttls keying material", NULL, 0,
 					       EAP_TLS_KEY_LEN);
 	if (eapKeyData) {
 		*len = EAP_TLS_KEY_LEN;
@@ -1310,7 +1310,7 @@ static u8 * eap_ttls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
 		return NULL;
 
 	eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
-					       "ttls keying material",
+					       "ttls keying material", NULL, 0,
 					       EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
 	if (eapKeyData) {
 		emsk = os_malloc(EAP_EMSK_LEN);
diff --git a/src/eap_server/eap_tls_common.h b/src/eap_server/eap_tls_common.h
index 31f6e72d7..36bf1949c 100644
--- a/src/eap_server/eap_tls_common.h
+++ b/src/eap_server/eap_tls_common.h
@@ -78,7 +78,8 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
 			    int verify_peer, int eap_type);
 void eap_server_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data);
 u8 * eap_server_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data,
-			       const char *label, size_t len);
+			       const char *label, const unsigned char *context,
+                               size_t context_len, size_t len);
 u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
 				      struct eap_ssl_data *data, u8 eap_type,
 				      size_t *len);
