EAP-FAST: Moved common peer/server functionality into a shared file
authorJouni Malinen <j@w1.fi>
Thu, 28 Feb 2008 01:57:19 +0000 (17:57 -0800)
committerJouni Malinen <j@w1.fi>
Thu, 28 Feb 2008 01:57:19 +0000 (17:57 -0800)
src/eap_common/eap_fast_common.c
src/eap_common/eap_fast_common.h
src/eap_peer/eap_fast.c
src/eap_server/eap_fast.c

index 039c40e..7b9207f 100644 (file)
 #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;
+}
index e69b7a0..8bb767b 100644 (file)
@@ -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 */
index 0d2e28c..a8d089e 100644 (file)
@@ -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)
index 7fd41f9..c877bba 100644 (file)
@@ -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;