eap_fast_common.c

Go to the documentation of this file.
00001 
00016 #include "includes.h"
00017 
00018 #include "common.h"
00019 #include "sha1.h"
00020 #include "tls.h"
00021 #include "eap_defs.h"
00022 #include "eap_tlv_common.h"
00023 #include "eap_fast_common.h"
00024 
00025 
00026 void eap_fast_put_tlv_hdr(struct wpabuf *buf, u16 type, u16 len)
00027 {
00028         struct pac_tlv_hdr hdr;
00029         hdr.type = host_to_be16(type);
00030         hdr.len = host_to_be16(len);
00031         wpabuf_put_data(buf, &hdr, sizeof(hdr));
00032 }
00033 
00034 
00035 void eap_fast_put_tlv(struct wpabuf *buf, u16 type, const void *data,
00036                              u16 len)
00037 {
00038         eap_fast_put_tlv_hdr(buf, type, len);
00039         wpabuf_put_data(buf, data, len);
00040 }
00041 
00042 
00043 void eap_fast_put_tlv_buf(struct wpabuf *buf, u16 type,
00044                                  const struct wpabuf *data)
00045 {
00046         eap_fast_put_tlv_hdr(buf, type, wpabuf_len(data));
00047         wpabuf_put_buf(buf, data);
00048 }
00049 
00050 
00051 struct wpabuf * eap_fast_tlv_eap_payload(struct wpabuf *buf)
00052 {
00053         struct wpabuf *e;
00054 
00055         if (buf == NULL)
00056                 return NULL;
00057 
00058         /* Encapsulate EAP packet in EAP-Payload TLV */
00059         wpa_printf(MSG_DEBUG, "EAP-FAST: Add EAP-Payload TLV");
00060         e = wpabuf_alloc(sizeof(struct pac_tlv_hdr) + wpabuf_len(buf));
00061         if (e == NULL) {
00062                 wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to allocate memory "
00063                            "for TLV encapsulation");
00064                 wpabuf_free(buf);
00065                 return NULL;
00066         }
00067         eap_fast_put_tlv_buf(e,
00068                              EAP_TLV_TYPE_MANDATORY | EAP_TLV_EAP_PAYLOAD_TLV,
00069                              buf);
00070         wpabuf_free(buf);
00071         return e;
00072 }
00073 
00074 
00075 void eap_fast_derive_master_secret(const u8 *pac_key, const u8 *server_random,
00076                                    const u8 *client_random, u8 *master_secret)
00077 {
00078 #define TLS_RANDOM_LEN 32
00079 #define TLS_MASTER_SECRET_LEN 48
00080         u8 seed[2 * TLS_RANDOM_LEN];
00081 
00082         wpa_hexdump(MSG_DEBUG, "EAP-FAST: client_random",
00083                     client_random, TLS_RANDOM_LEN);
00084         wpa_hexdump(MSG_DEBUG, "EAP-FAST: server_random",
00085                     server_random, TLS_RANDOM_LEN);
00086 
00087         /*
00088          * RFC 4851, Section 5.1:
00089          * master_secret = T-PRF(PAC-Key, "PAC to master secret label hash", 
00090          *                       server_random + client_random, 48)
00091          */
00092         os_memcpy(seed, server_random, TLS_RANDOM_LEN);
00093         os_memcpy(seed + TLS_RANDOM_LEN, client_random, TLS_RANDOM_LEN);
00094         sha1_t_prf(pac_key, EAP_FAST_PAC_KEY_LEN,
00095                    "PAC to master secret label hash",
00096                    seed, sizeof(seed), master_secret, TLS_MASTER_SECRET_LEN);
00097 
00098         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: master_secret",
00099                         master_secret, TLS_MASTER_SECRET_LEN);
00100 }
00101 
00102 
00103 u8 * eap_fast_derive_key(void *ssl_ctx, struct tls_connection *conn,
00104                          const char *label, size_t len)
00105 {
00106         struct tls_keys keys;
00107         u8 *rnd = NULL, *out;
00108         int block_size;
00109 
00110         block_size = tls_connection_get_keyblock_size(ssl_ctx, conn);
00111         if (block_size < 0)
00112                 return NULL;
00113 
00114         out = os_malloc(block_size + len);
00115         if (out == NULL)
00116                 return NULL;
00117 
00118         if (tls_connection_prf(ssl_ctx, conn, label, 1, out, block_size + len)
00119             == 0) {
00120                 os_memmove(out, out + block_size, len);
00121                 return out;
00122         }
00123 
00124         if (tls_connection_get_keys(ssl_ctx, conn, &keys))
00125                 goto fail;
00126 
00127         rnd = os_malloc(keys.client_random_len + keys.server_random_len);
00128         if (rnd == NULL)
00129                 goto fail;
00130 
00131         os_memcpy(rnd, keys.server_random, keys.server_random_len);
00132         os_memcpy(rnd + keys.server_random_len, keys.client_random,
00133                   keys.client_random_len);
00134 
00135         wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: master_secret for key "
00136                         "expansion", keys.master_key, keys.master_key_len);
00137         if (tls_prf(keys.master_key, keys.master_key_len,
00138                     label, rnd, keys.client_random_len +
00139                     keys.server_random_len, out, block_size + len))
00140                 goto fail;
00141         os_free(rnd);
00142         os_memmove(out, out + block_size, len);
00143         return out;
00144 
00145 fail:
00146         os_free(rnd);
00147         os_free(out);
00148         return NULL;
00149 }
00150 
00151 
00152 void eap_fast_derive_eap_msk(const u8 *simck, u8 *msk)
00153 {
00154         /*
00155          * RFC 4851, Section 5.4: EAP Master Session Key Generation
00156          * MSK = T-PRF(S-IMCK[j], "Session Key Generating Function", 64)
00157          */
00158 
00159         sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
00160                    "Session Key Generating Function", (u8 *) "", 0,
00161                    msk, EAP_FAST_KEY_LEN);
00162         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (MSK)",
00163                         msk, EAP_FAST_KEY_LEN);
00164 }
00165 
00166 
00167 void eap_fast_derive_eap_emsk(const u8 *simck, u8 *emsk)
00168 {
00169         /*
00170          * RFC 4851, Section 5.4: EAP Master Session Key Genreration
00171          * EMSK = T-PRF(S-IMCK[j],
00172          *        "Extended Session Key Generating Function", 64)
00173          */
00174 
00175         sha1_t_prf(simck, EAP_FAST_SIMCK_LEN,
00176                    "Extended Session Key Generating Function", (u8 *) "", 0,
00177                    emsk, EAP_EMSK_LEN);
00178         wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: Derived key (EMSK)",
00179                         emsk, EAP_EMSK_LEN);
00180 }
00181 
00182 
00183 int eap_fast_parse_tlv(struct eap_fast_tlv_parse *tlv,
00184                        int tlv_type, u8 *pos, int len)
00185 {
00186         switch (tlv_type) {
00187         case EAP_TLV_EAP_PAYLOAD_TLV:
00188                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: EAP-Payload TLV",
00189                             pos, len);
00190                 if (tlv->eap_payload_tlv) {
00191                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00192                                    "EAP-Payload TLV in the message");
00193                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00194                         return -2;
00195                 }
00196                 tlv->eap_payload_tlv = pos;
00197                 tlv->eap_payload_tlv_len = len;
00198                 break;
00199         case EAP_TLV_RESULT_TLV:
00200                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Result TLV", pos, len);
00201                 if (tlv->result) {
00202                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00203                                    "Result TLV in the message");
00204                         tlv->result = EAP_TLV_RESULT_FAILURE;
00205                         return -2;
00206                 }
00207                 if (len < 2) {
00208                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
00209                                    "Result TLV");
00210                         tlv->result = EAP_TLV_RESULT_FAILURE;
00211                         break;
00212                 }
00213                 tlv->result = WPA_GET_BE16(pos);
00214                 if (tlv->result != EAP_TLV_RESULT_SUCCESS &&
00215                     tlv->result != EAP_TLV_RESULT_FAILURE) {
00216                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Result %d",
00217                                    tlv->result);
00218                         tlv->result = EAP_TLV_RESULT_FAILURE;
00219                 }
00220                 wpa_printf(MSG_DEBUG, "EAP-FAST: Result: %s",
00221                            tlv->result == EAP_TLV_RESULT_SUCCESS ?
00222                            "Success" : "Failure");
00223                 break;
00224         case EAP_TLV_INTERMEDIATE_RESULT_TLV:
00225                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Intermediate Result TLV",
00226                             pos, len);
00227                 if (len < 2) {
00228                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
00229                                    "Intermediate-Result TLV");
00230                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00231                         break;
00232                 }
00233                 if (tlv->iresult) {
00234                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00235                                    "Intermediate-Result TLV in the message");
00236                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00237                         return -2;
00238                 }
00239                 tlv->iresult = WPA_GET_BE16(pos);
00240                 if (tlv->iresult != EAP_TLV_RESULT_SUCCESS &&
00241                     tlv->iresult != EAP_TLV_RESULT_FAILURE) {
00242                         wpa_printf(MSG_DEBUG, "EAP-FAST: Unknown Intermediate "
00243                                    "Result %d", tlv->iresult);
00244                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00245                 }
00246                 wpa_printf(MSG_DEBUG, "EAP-FAST: Intermediate Result: %s",
00247                            tlv->iresult == EAP_TLV_RESULT_SUCCESS ?
00248                            "Success" : "Failure");
00249                 break;
00250         case EAP_TLV_CRYPTO_BINDING_TLV:
00251                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV",
00252                             pos, len);
00253                 if (tlv->crypto_binding) {
00254                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00255                                    "Crypto-Binding TLV in the message");
00256                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00257                         return -2;
00258                 }
00259                 tlv->crypto_binding_len = sizeof(struct eap_tlv_hdr) + len;
00260                 if (tlv->crypto_binding_len < sizeof(*tlv->crypto_binding)) {
00261                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
00262                                    "Crypto-Binding TLV");
00263                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00264                         return -2;
00265                 }
00266                 tlv->crypto_binding = (struct eap_tlv_crypto_binding_tlv *)
00267                         (pos - sizeof(struct eap_tlv_hdr));
00268                 break;
00269         case EAP_TLV_REQUEST_ACTION_TLV:
00270                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Request-Action TLV",
00271                             pos, len);
00272                 if (tlv->request_action) {
00273                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00274                                    "Request-Action TLV in the message");
00275                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00276                         return -2;
00277                 }
00278                 if (len < 2) {
00279                         wpa_printf(MSG_DEBUG, "EAP-FAST: Too short "
00280                                    "Request-Action TLV");
00281                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00282                         break;
00283                 }
00284                 tlv->request_action = WPA_GET_BE16(pos);
00285                 wpa_printf(MSG_DEBUG, "EAP-FAST: Request-Action: %d",
00286                            tlv->request_action);
00287                 break;
00288         case EAP_TLV_PAC_TLV:
00289                 wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: PAC TLV", pos, len);
00290                 if (tlv->pac) {
00291                         wpa_printf(MSG_DEBUG, "EAP-FAST: More than one "
00292                                    "PAC TLV in the message");
00293                         tlv->iresult = EAP_TLV_RESULT_FAILURE;
00294                         return -2;
00295                 }
00296                 tlv->pac = pos;
00297                 tlv->pac_len = len;
00298                 break;
00299         default:
00300                 /* Unknown TLV */
00301                 return -1;
00302         }
00303 
00304         return 0;
00305 }
00306 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines

Generated on Sat Nov 21 23:16:51 2009 for hostapd by  doxygen 1.6.1