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


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Apr 24 2014 15:34:34