From 7f4c1d4300a7402d04bff720997e94228cd1df04 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 27 Feb 2008 17:57:19 -0800 Subject: [PATCH] EAP-FAST: Moved common peer/server functionality into a shared file --- src/eap_common/eap_fast_common.c | 261 ++++++++++++++++++++++++++++++ src/eap_common/eap_fast_common.h | 22 +++ src/eap_peer/eap_fast.c | 204 +----------------------- src/eap_server/eap_fast.c | 262 +------------------------------ 4 files changed, 298 insertions(+), 451 deletions(-) diff --git a/src/eap_common/eap_fast_common.c b/src/eap_common/eap_fast_common.c index 039c40eea..7b9207f9a 100644 --- a/src/eap_common/eap_fast_common.c +++ b/src/eap_common/eap_fast_common.c @@ -15,6 +15,10 @@ #include "includes.h" #include "common.h" +#include "sha1.h" +#include "tls.h" +#include "eap_defs.h" +#include "eap_tlv_common.h" #include "eap_fast_common.h" @@ -41,3 +45,260 @@ void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data)); wpabuf_put_buf(buf, data); } + + +struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf) +{ + struct wpabuf *e; + + if (buf == NULL) + return NULL; + + /* Encapsulate EAP packet in EAP-Payload TLV */ + wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV"); + e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf)); + if (e == NULL) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " + "for TLV encapsulation"); + wpabuf_free(buf); + return NULL; + } + eap_fast_put_tlv_buf(e, + EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV, + buf); + wpabuf_free(buf); + return e; +} + + +void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, + const u8 *client_random, u8 *master_secret) +{ +#define TLS_RANDOM_LEN 32 +#define TLS_MASTER_SECRET_LEN 48 + u8 seed[2 * TLS_RANDOM_LEN]; + + wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", + client_random, TLS_RANDOM_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", + server_random, TLS_RANDOM_LEN); + + /* + * RFC 4851, Section 5.1: + * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", + * server_random + client_random, 48) + */ + os_memcpy(seed, server_random, TLS_RANDOM_LEN); + os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN); + sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN, + "PAC to master secret label hash", + seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN); + + wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret", + master_secret, TLS_MASTER_SECRET_LEN); +} + + +u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, + const char *label, size_t len) +{ + struct tls_keys keys; + u8 *rnd = NULL, *out; + int block_size; + + block_size = tls_connection_get_keyblock_size(ssl_ctx, conn); + if (block_size < 0) + return NULL; + + out = os_malloc(block_size + len); + if (out == NULL) + return NULL; + + if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len) + == 0) { + os_memmove(out, out + block_size, len); + return out; + } + + if (tls_connection_get_keys(ssl_ctx, conn, &keys)) + goto fail; + + rnd = os_malloc(keys.client_random_len + keys.server_random_len); + if (rnd == NULL) + goto fail; + + os_memcpy(rnd, keys.server_random, keys.server_random_len); + os_memcpy(rnd + keys.server_random_len, keys.client_random, + keys.client_random_len); + + wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " + "expansion", keys.master_key, keys.master_key_len); + if (tls_prf(keys.master_key, keys.master_key_len, + label, rnd, keys.client_random_len + + keys.server_random_len, out, block_size + len)) + goto fail; + os_free(rnd); + os_memmove(out, out + block_size, len); + return out; + +fail: + os_free(rnd); + os_free(out); + return NULL; +} + + +void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk) +{ + /* + * RFC 4851, Section 5.4: EAP Master Session Key Generation + * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64) + */ + + sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, + "Session Key Generating Function", (u8 *) "", 0, + msk, EAP_FAST_KEY_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", + msk, EAP_FAST_KEY_LEN); +} + + +void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk) +{ + /* + * RFC 4851, Section 5.4: EAP Master Session Key Genreration + * EMSK = T-PRF(S-IMCK[j], + * "Extended Session Key Generating Function", 64) + */ + + sha1_t_prf(simck, EAP_FAST_SIMCK_LEN, + "Extended Session Key Generating Function", (u8 *) "", 0, + emsk, EAP_EMSK_LEN); + wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", + emsk, EAP_EMSK_LEN); +} + + +int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, + int tlv_type, u8 *pos, int len) +{ + switch (tlv_type) { + case EAP_TLV_EAP_PAYLOAD_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV", + pos, len); + if (tlv->eap_payload_tlv) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "EAP-Payload TLV in the message"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + tlv->eap_payload_tlv = pos; + tlv->eap_payload_tlv_len = len; + break; + case EAP_TLV_RESULT_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len); + if (tlv->result) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "Result TLV in the message"); + tlv->result = EAP_TLV_RESULT_FAILURE; + return -2; + } + if (len < 2) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " + "Result TLV"); + tlv->result = EAP_TLV_RESULT_FAILURE; + break; + } + tlv->result = WPA_GET_BE16(pos); + if (tlv->result != EAP_TLV_RESULT_SUCCESS && + tlv->result != EAP_TLV_RESULT_FAILURE) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d", + tlv->result); + tlv->result = EAP_TLV_RESULT_FAILURE; + } + wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", + tlv->result == EAP_TLV_RESULT_SUCCESS ? + "Success" : "Failure"); + break; + case EAP_TLV_INTERMEDIATE_RESULT_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV", + pos, len); + if (len < 2) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " + "Intermediate-Result TLV"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + break; + } + if (tlv->iresult) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "Intermediate-Result TLV in the message"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + tlv->iresult = WPA_GET_BE16(pos); + if (tlv->iresult != EAP_TLV_RESULT_SUCCESS && + tlv->iresult != EAP_TLV_RESULT_FAILURE) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate " + "Result %d", tlv->iresult); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + } + wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s", + tlv->iresult == EAP_TLV_RESULT_SUCCESS ? + "Success" : "Failure"); + break; + case EAP_TLV_CRYPTO_BINDING_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV", + pos, len); + if (tlv->crypto_binding) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "Crypto-Binding TLV in the message"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; + if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " + "Crypto-Binding TLV"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + tlv->crypto_binding = (struct eap_tlv_crypto_binding__tlv *) + (pos - sizeof(struct eap_tlv_hdr)); + break; + case EAP_TLV_REQUEST_ACTION_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV", + pos, len); + if (tlv->request_action) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "Request-Action TLV in the message"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + if (len < 2) { + wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " + "Request-Action TLV"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + break; + } + tlv->request_action = WPA_GET_BE16(pos); + wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d", + tlv->request_action); + break; + case EAP_TLV_PAC_TLV: + wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len); + if (tlv->pac) { + wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " + "PAC TLV in the message"); + tlv->iresult = EAP_TLV_RESULT_FAILURE; + return -2; + } + tlv->pac = pos; + tlv->pac_len = len; + break; + default: + /* Unknown TLV */ + return -1; + } + + return 0; +} diff --git a/src/eap_common/eap_fast_common.h b/src/eap_common/eap_fast_common.h index e69b7a0f3..8bb767b8a 100644 --- a/src/eap_common/eap_fast_common.h +++ b/src/eap_common/eap_fast_common.h @@ -84,11 +84,33 @@ struct eap_fast_key_block_provisioning { struct wpabuf; +struct tls_connection; + +struct eap_fast_tlv_parse { + u8 *eap_payload_tlv; + size_t eap_payload_tlv_len; + struct eap_tlv_crypto_binding__tlv *crypto_binding; + size_t crypto_binding_len; + int iresult; + int result; + int request_action; + u8 *pac; + size_t pac_len; +}; void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len); void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data, u16 len); void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type, const struct wpabuf *data); +struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf); +void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random, + const u8 *client_random, u8 *master_secret); +u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn, + const char *label, size_t len); +void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk); +void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk); +int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, + int tlv_type, u8 *pos, int len); #endif /* EAP_FAST_H */ diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 0d2e28cd6..a8d089e89 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -80,9 +80,6 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, u8 *master_secret) { struct eap_fast_data *data = ctx; -#define TLS_RANDOM_LEN 32 -#define TLS_MASTER_SECRET_LEN 48 - u8 seed[2 * TLS_RANDOM_LEN]; wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); @@ -101,10 +98,6 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, } wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket", ticket, len); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - client_random, TLS_RANDOM_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, TLS_RANDOM_LEN); if (data->current_pac == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: No PAC-Key available for " @@ -113,19 +106,9 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, return 0; } - /* - * RFC 4851, Section 5.1: - * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) - */ - os_memcpy(seed, server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN); - sha1_t_prf(data->current_pac->pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret", - master_secret, TLS_MASTER_SECRET_LEN); + eap_fast_derive_master_secret(data->current_pac->pac_key, + server_random, client_random, + master_secret); data->session_ticket_used = 1; @@ -268,74 +251,13 @@ static void eap_fast_deinit(struct eap_sm *sm, void *priv) static int eap_fast_derive_msk(struct eap_fast_data *data) { - /* Derive EAP Master Session Keys (section 5.4) */ - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Session Key Generating Function", (u8 *) "", 0, - data->key_data, EAP_FAST_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - data->key_data, EAP_FAST_KEY_LEN); - - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Extended Session Key Generating Function", - (u8 *) "", 0, data->emsk, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", - data->emsk, EAP_EMSK_LEN); - + eap_fast_derive_eap_msk(data->simck, data->key_data); + eap_fast_derive_eap_emsk(data->simck, data->emsk); data->success = 1; - return 0; } -static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - int block_size; - - block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn); - if (block_size < 0) - return NULL; - - out = os_malloc(block_size + len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out, - block_size + len) == 0) { - os_memmove(out, out + block_size, len); - return out; - } - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " - "expansion", keys.master_key, keys.master_key_len); - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, block_size + len)) - goto fail; - os_free(rnd); - os_memmove(out, out + block_size, len); - return out; - -fail: - os_free(rnd); - os_free(out); - return NULL; -} - - static void eap_fast_derive_key_auth(struct eap_sm *sm, struct eap_fast_data *data) { @@ -345,7 +267,7 @@ static void eap_fast_derive_key_auth(struct eap_sm *sm, * Extra key material after TLS key_block: session_key_seed[40] */ - sks = eap_fast_derive_key(sm, &data->ssl, "key expansion", + sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", EAP_FAST_SKS_LEN); if (sks == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " @@ -371,7 +293,8 @@ static void eap_fast_derive_key_provisioning(struct eap_sm *sm, { os_free(data->key_block_p); data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm, &data->ssl, "key expansion", + eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, + "key expansion", sizeof(*data->key_block_p)); if (data->key_block_p == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); @@ -596,29 +519,6 @@ static struct wpabuf * eap_fast_tlv_pac_ack(void) } -static struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *msg; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP Payload TLV */ - msg = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf)); - if (msg == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - eap_fast_put_tlv_buf(msg, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV, - buf); - wpabuf_free(buf); - return msg; -} - - static struct wpabuf * eap_fast_process_eap_payload_tlv( struct eap_sm *sm, struct eap_fast_data *data, struct eap_method_ret *ret, const struct eap_hdr *req, @@ -1166,94 +1066,6 @@ static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm, } -struct eap_fast_tlv_parse { - u8 *eap_payload_tlv; - size_t eap_payload_tlv_len; - u8 *pac; - size_t pac_len; - struct eap_tlv_crypto_binding__tlv *crypto_binding; - size_t crypto_binding_len; - int iresult; - int result; -}; - - -static int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len) -{ - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP Payload TLV", - pos, len); - tlv->eap_payload_tlv = pos; - tlv->eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - tlv->result = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->result = WPA_GET_BE16(pos); - if (tlv->result != EAP_TLV_RESULT_SUCCESS && - tlv->result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d", - tlv->result); - tlv->result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - tlv->result == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_INTERMEDIATE_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Intermediate Result TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->iresult = WPA_GET_BE16(pos); - if (tlv->iresult != EAP_TLV_RESULT_SUCCESS && - tlv->iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate " - "Result %d", tlv->iresult); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s", - tlv->iresult == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV", - pos, len); - tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding = (struct eap_tlv_crypto_binding__tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len); - tlv->pac = pos; - tlv->pac_len = len; - break; - default: - /* Unknown TLV */ - return -1; - } - - return 0; -} - - static int eap_fast_parse_decrypted(struct wpabuf *decrypted, struct eap_fast_tlv_parse *tlv, struct wpabuf **resp) diff --git a/src/eap_server/eap_fast.c b/src/eap_server/eap_fast.c index 7fd41f9ae..c877bba6f 100644 --- a/src/eap_server/eap_fast.c +++ b/src/eap_server/eap_fast.c @@ -128,9 +128,6 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, u8 *master_secret) { struct eap_fast_data *data = ctx; -#define TLS_RANDOM_LEN 32 -#define TLS_MASTER_SECRET_LEN 48 - u8 seed[2 * TLS_RANDOM_LEN]; const u8 *pac_opaque; size_t pac_opaque_len; u8 *buf, *pos, *end, *pac_key = NULL; @@ -142,10 +139,6 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, wpa_printf(MSG_DEBUG, "EAP-FAST: SessionTicket callback"); wpa_hexdump(MSG_DEBUG, "EAP-FAST: SessionTicket (PAC-Opaque)", ticket, len); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random", - client_random, TLS_RANDOM_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random", - server_random, TLS_RANDOM_LEN); if (len < 4 || WPA_GET_BE16(ticket) != PAC_TYPE_PAC_OPAQUE) { wpa_printf(MSG_DEBUG, "EAP-FAST: Ignore invalid " @@ -259,19 +252,8 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, if (lifetime - now.sec < PAC_KEY_REFRESH_TIME) data->send_new_pac = 1; - /* - * RFC 4851, Section 5.1: - * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", - * server_random + client_random, 48) - */ - os_memcpy(seed, server_random, TLS_RANDOM_LEN); - os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN); - sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN, - "PAC to master secret label hash", - seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN); - - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret", - master_secret, TLS_MASTER_SECRET_LEN); + eap_fast_derive_master_secret(pac_key, server_random, client_random, + master_secret); os_free(buf); @@ -279,55 +261,6 @@ static int eap_fast_session_ticket_cb(void *ctx, const u8 *ticket, size_t len, } -static u8 * eap_fast_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, - char *label, size_t len) -{ - struct tls_keys keys; - u8 *rnd = NULL, *out; - int block_size; - - block_size = tls_connection_get_keyblock_size(sm->ssl_ctx, data->conn); - if (block_size < 0) - return NULL; - - out = os_malloc(block_size + len); - if (out == NULL) - return NULL; - - if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 1, out, - block_size + len) == 0) { - os_memmove(out, out + block_size, len); - return out; - } - - if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) - goto fail; - - rnd = os_malloc(keys.client_random_len + keys.server_random_len); - if (rnd == NULL) - goto fail; - - os_memcpy(rnd, keys.server_random, keys.server_random_len); - os_memcpy(rnd + keys.server_random_len, keys.client_random, - keys.client_random_len); - - wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key " - "expansion", keys.master_key, keys.master_key_len); - if (tls_prf(keys.master_key, keys.master_key_len, - label, rnd, keys.client_random_len + - keys.server_random_len, out, block_size + len)) - goto fail; - os_free(rnd); - os_memmove(out, out + block_size, len); - return out; - -fail: - os_free(rnd); - os_free(out); - return NULL; -} - - static void eap_fast_derive_key_auth(struct eap_sm *sm, struct eap_fast_data *data) { @@ -337,7 +270,7 @@ static void eap_fast_derive_key_auth(struct eap_sm *sm, * Extra key material after TLS key_block: session_key_seed[40] */ - sks = eap_fast_derive_key(sm, &data->ssl, "key expansion", + sks = eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, "key expansion", EAP_FAST_SKS_LEN); if (sks == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive " @@ -363,7 +296,8 @@ static void eap_fast_derive_key_provisioning(struct eap_sm *sm, { os_free(data->key_block_p); data->key_block_p = (struct eap_fast_key_block_provisioning *) - eap_fast_derive_key(sm, &data->ssl, "key expansion", + eap_fast_derive_key(sm->ssl_ctx, data->ssl.conn, + "key expansion", sizeof(*data->key_block_p)); if (data->key_block_p == NULL) { wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to derive key block"); @@ -653,30 +587,6 @@ static struct wpabuf * eap_fast_encrypt(struct eap_sm *sm, } -static struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf) -{ - struct wpabuf *e; - - if (buf == NULL) - return NULL; - - /* Encapsulate EAP packet in EAP-Payload TLV */ - wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV"); - e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf)); - if (e == NULL) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory " - "for TLV encapsulation"); - wpabuf_free(buf); - return NULL; - } - eap_fast_put_tlv_buf(e, - EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV, - buf); - wpabuf_free(buf); - return e; -} - - static struct wpabuf * eap_fast_build_phase2_req(struct eap_sm *sm, struct eap_fast_data *data, u8 id) @@ -1121,144 +1031,6 @@ static void eap_fast_process_phase2_eap(struct eap_sm *sm, } -struct eap_fast_tlv_parse { - u8 *eap_payload_tlv; - size_t eap_payload_tlv_len; - struct eap_tlv_crypto_binding__tlv *crypto_binding; - size_t crypto_binding_len; - int iresult; - int result; - int request_action; - u8 *pac; - size_t pac_len; -}; - - -static int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv, - int tlv_type, u8 *pos, int len) -{ - switch (tlv_type) { - case EAP_TLV_EAP_PAYLOAD_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV", - pos, len); - if (tlv->eap_payload_tlv) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "EAP-Payload TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->eap_payload_tlv = pos; - tlv->eap_payload_tlv_len = len; - break; - case EAP_TLV_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len); - if (tlv->result) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Result TLV in the message"); - tlv->result = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Result TLV"); - tlv->result = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->result = WPA_GET_BE16(pos); - if (tlv->result != EAP_TLV_RESULT_SUCCESS && - tlv->result != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d", - tlv->result); - tlv->result = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s", - tlv->result == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_INTERMEDIATE_RESULT_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV", - pos, len); - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Intermediate-Result TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - if (tlv->iresult) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Intermediate-Result TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->iresult = WPA_GET_BE16(pos); - if (tlv->iresult != EAP_TLV_RESULT_SUCCESS && - tlv->iresult != EAP_TLV_RESULT_FAILURE) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate " - "Result %d", tlv->iresult); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - } - wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s", - tlv->iresult == EAP_TLV_RESULT_SUCCESS ? - "Success" : "Failure"); - break; - case EAP_TLV_CRYPTO_BINDING_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV", - pos, len); - if (tlv->crypto_binding) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Crypto-Binding TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len; - if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Crypto-Binding TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->crypto_binding = (struct eap_tlv_crypto_binding__tlv *) - (pos - sizeof(struct eap_tlv_hdr)); - break; - case EAP_TLV_REQUEST_ACTION_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV", - pos, len); - if (tlv->request_action) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "Request-Action TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - if (len < 2) { - wpa_printf(MSG_DEBUG, "EAP-FAST: Too short " - "Request-Action TLV"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - break; - } - tlv->request_action = WPA_GET_BE16(pos); - wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d", - tlv->request_action); - break; - case EAP_TLV_PAC_TLV: - wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len); - if (tlv->pac) { - wpa_printf(MSG_DEBUG, "EAP-FAST: More than one " - "PAC TLV in the message"); - tlv->iresult = EAP_TLV_RESULT_FAILURE; - return -2; - } - tlv->pac = pos; - tlv->pac_len = len; - break; - default: - /* Unknown TLV */ - return -1; - } - - return 0; -} - - static int eap_fast_parse_tlvs(u8 *data, size_t data_len, struct eap_fast_tlv_parse *tlv) { @@ -1696,20 +1468,11 @@ static u8 * eap_fast_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->state != SUCCESS) return NULL; - /* - * RFC 4851, Section 5.4: EAP Master Session Key Genreration - * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64) - */ - eapKeyData = os_malloc(EAP_FAST_KEY_LEN); if (eapKeyData == NULL) return NULL; - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Session Key Generating Function", (u8 *) "", 0, - eapKeyData, EAP_FAST_KEY_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)", - eapKeyData, EAP_FAST_KEY_LEN); + eap_fast_derive_eap_msk(data->simck, eapKeyData); *len = EAP_FAST_KEY_LEN; return eapKeyData; @@ -1724,22 +1487,11 @@ static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) if (data->state != SUCCESS) return NULL; - /* - * RFC 4851, Section 5.4: EAP Master Session Key Genreration - * EMSK = T-PRF(S-IMCK[j], - * "Extended Session Key Generating Function", 64) - */ - eapKeyData = os_malloc(EAP_EMSK_LEN); if (eapKeyData == NULL) return NULL; - sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN, - "Extended Session Key Generating Function", - (u8 *) "", 0, eapKeyData, EAP_EMSK_LEN); - wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)", - eapKeyData, EAP_EMSK_LEN); - + eap_fast_derive_eap_emsk(data->simck, eapKeyData); *len = EAP_EMSK_LEN; return eapKeyData;