@@ -367,6 +367,9 @@ 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)
+ * @contextlen: the length of the context value (MAY be zero)
+ * @use_context: 0 if context is not used (no context != 0-length context)
* @out: Buffer for output data from TLS-PRF
* @out_len: Length of the output buffer
* Returns: 0 on success, -1 on failure
@@ -378,6 +381,13 @@ int __must_check tls_connection_export_key(void *tls_ctx,
const char *label,
u8 *out, size_t out_len);
+int __must_check tls_connection_export_key2(void *tls_ctx,
+ struct tls_connection *conn,
+ const char *label,
+ const unsigned char *context,
+ size_t contextlen, int use_context,
+ u8 *out, size_t out_len);
+
/**
* tls_connection_get_eap_fast_key - Derive key material for EAP-FAST
* @tls_ctx: TLS context data from tls_init()
@@ -896,13 +896,23 @@ 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)
+{
+ return tls_connection_export_key2(tls_ctx, conn, label, NULL, 0, 0 out,
+ out_len);
+}
+
+
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, 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);
+ 0 /* client_random first */, contextlen, context,
+ out_len, (char *) out);
}
@@ -455,6 +455,15 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
}
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, u8 *out,
+ size_t out_len)
+{
+ return -1;
+}
+
+
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
u8 *out, size_t out_len)
{
@@ -100,6 +100,15 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
}
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, u8 *out,
+ size_t out_len)
+{
+ return -1;
+}
+
+
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
u8 *out, size_t out_len)
{
@@ -3670,10 +3670,21 @@ 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)
+{
+ return tls_connection_export_key2(tls_ctx, conn, label, NULL, 0, 0, out,
+ out_len);
+}
+
+
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, 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, contextlen,
+ use_context) != 1)
return -1;
return 0;
}
@@ -1978,6 +1978,15 @@ int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
}
+int tls_connection_export_key2(void *tls_ctx, struct tls_connection *conn,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, u8 *out,
+ size_t out_len)
+{
+ return -1;
+}
+
+
#define SEED_LEN (RAN_LEN + RAN_LEN)
int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
@@ -174,6 +174,9 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
struct eap_method_ret *ret)
{
const char *label;
+ const unsigned char context[] = {EAP_TYPE_TLS};
+ size_t contextlen = 0;
+ int use_context = 0;
wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
@@ -184,6 +187,8 @@ static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data,
if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
+ contextlen = 1;
+ use_context = 1;
/* A possible NewSessionTicket may be received before
* EAP-Success, so need to allow it to be received. */
@@ -197,9 +202,11 @@ 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,
- EAP_TLS_KEY_LEN +
- EAP_EMSK_LEN);
+ data->key_data = eap_peer_tls_derive_key2(sm, &data->ssl, label,
+ context, contextlen,
+ use_context,
+ EAP_TLS_KEY_LEN +
+ EAP_EMSK_LEN);
if (data->key_data) {
wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key",
data->key_data, EAP_TLS_KEY_LEN);
@@ -347,6 +347,9 @@ 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)
+ * @contextlen: the length of the context value (MAY be zero)
+ * @use_context: 0 if context is not used (no context != 0-length context)
* @len: Length of the key material to generate (usually 64 for MSK)
* Returns: Pointer to allocated key on success or %NULL on failure
*
@@ -358,6 +361,14 @@ 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)
+{
+ return eap_peer_tls_derive_key2(sm, data, label, NULL, 0, 0, len);
+}
+
+
+u8 * eap_peer_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, size_t len)
{
u8 *out;
@@ -365,8 +376,9 @@ 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_key2(data->ssl_ctx, data->conn, label,
+ context, contextlen, use_context, out,
+ len)) {
os_free(out);
return NULL;
}
@@ -400,14 +412,16 @@ u8 * eap_peer_tls_derive_session_id(struct eap_sm *sm,
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
- * "", 64)
+ * Type-Code, 64)
*/
*len = 1 + 64;
id = os_malloc(*len);
if (!id)
return NULL;
- method_id = eap_peer_tls_derive_key(
- sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+ const unsigned char context[] = {EAP_TYPE_TLS};
+ method_id = eap_peer_tls_derive_key2(
+ sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 1,
+ 64);
if (!method_id) {
os_free(id);
return NULL;
@@ -100,6 +100,9 @@ int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
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);
+u8 * eap_peer_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, 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);
@@ -322,16 +322,23 @@ static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
struct eap_tls_data *data = priv;
u8 *eapKeyData;
const char *label;
+ const unsigned char context[] = {EAP_TYPE_TLS};
+ size_t contextlen = 0;
+ int use_context = 0;
if (data->state != SUCCESS)
return NULL;
- if (data->ssl.tls_v13)
+ if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
- else
+ contextlen = 1;
+ use_context = 1;
+ } else {
label = "client EAP encryption";
- eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
- EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+ }
+ eapKeyData = eap_server_tls_derive_key2(sm, &data->ssl, label,
+ context, contextlen, use_context,
+ EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
*len = EAP_TLS_KEY_LEN;
wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
@@ -350,16 +357,23 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
struct eap_tls_data *data = priv;
u8 *eapKeyData, *emsk;
const char *label;
+ const unsigned char context[] = {EAP_TYPE_TLS};
+ size_t contextlen = 0;
+ int use_context = 0;
if (data->state != SUCCESS)
return NULL;
- if (data->ssl.tls_v13)
+ if (data->ssl.tls_v13) {
label = "EXPORTER_EAP_TLS_Key_Material";
- else
+ contextlen = 1;
+ use_context = 1;
+ } else {
label = "client EAP encryption";
- eapKeyData = eap_server_tls_derive_key(sm, &data->ssl, label,
- EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
+ }
+ eapKeyData = eap_server_tls_derive_key2(sm, &data->ssl, label,
+ context, contextlen, use_context,
+ EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
if (eapKeyData) {
emsk = os_malloc(EAP_EMSK_LEN);
if (emsk)
@@ -108,6 +108,14 @@ 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)
+{
+ return eap_server_tls_derive_key2(sm, data, label, NULL, 0, 0, len);
+}
+
+
+u8 * eap_server_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, size_t len)
{
u8 *out;
@@ -115,8 +123,9 @@ 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_key2(sm->ssl_ctx, data->conn, label,
+ context, contextlen, use_context, out,
+ len)) {
os_free(out);
return NULL;
}
@@ -150,14 +159,16 @@ u8 * eap_server_tls_derive_session_id(struct eap_sm *sm,
/* Session-Id = <EAP-Type> || Method-Id
* Method-Id = TLS-Exporter("EXPORTER_EAP_TLS_Method-Id",
- * "", 64)
+ * Type-Code, 64)
*/
*len = 1 + 64;
id = os_malloc(*len);
if (!id)
return NULL;
- method_id = eap_server_tls_derive_key(
- sm, data, "EXPORTER_EAP_TLS_Method-Id", 64);
+ const unsigned char context[] = {EAP_TYPE_TLS};
+ method_id = eap_server_tls_derive_key2(
+ sm, data, "EXPORTER_EAP_TLS_Method-Id", context, 1, 1,
+ 64);
if (!method_id) {
os_free(id);
return NULL;
@@ -79,6 +79,9 @@ int eap_server_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data,
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);
+u8 * eap_server_tls_derive_key2(struct eap_sm *sm, struct eap_ssl_data *data,
+ const char *label, const unsigned char *context,
+ size_t contextlen, int use_context, 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);
According to the proposed standard change in https://emu-wg.github.io/draft-ietf-emu-eap-tls13/draft-ietf-emu-eap-tls13.html#rfc.section.2.3 Internal SSL library nor the WolfSSL library seem to support an additional context value as specified in rfc5705#section-4. Therefore, this breaks EAP_TLS 1.3 with those. (However, TLS 1.3 remains disabled by default.) Signed-off-by: Ervin Oro <ervin.oro@aalto.fi> --- src/crypto/tls.h | 10 +++++++++ src/crypto/tls_gnutls.c | 14 ++++++++++-- src/crypto/tls_internal.c | 9 ++++++++ src/crypto/tls_none.c | 9 ++++++++ src/crypto/tls_openssl.c | 13 ++++++++++- src/crypto/tls_wolfssl.c | 9 ++++++++ src/eap_peer/eap_tls.c | 13 ++++++++--- src/eap_peer/eap_tls_common.c | 24 ++++++++++++++++----- src/eap_peer/eap_tls_common.h | 3 +++ src/eap_server/eap_server_tls.c | 30 +++++++++++++++++++------- src/eap_server/eap_server_tls_common.c | 21 +++++++++++++----- src/eap_server/eap_tls_common.h | 3 +++ 12 files changed, 134 insertions(+), 24 deletions(-)